001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.backup; 019 020import static org.junit.jupiter.api.Assertions.assertFalse; 021import static org.junit.jupiter.api.Assertions.assertThrows; 022import static org.junit.jupiter.api.Assertions.assertTrue; 023 024import java.io.IOException; 025import java.util.List; 026import org.apache.commons.lang3.StringUtils; 027import org.apache.hadoop.hbase.TableName; 028import org.apache.hadoop.hbase.backup.util.BackupUtils; 029import org.apache.hadoop.hbase.client.Admin; 030import org.apache.hadoop.hbase.client.Table; 031import org.apache.hadoop.hbase.testclassification.LargeTests; 032import org.apache.hadoop.util.ToolRunner; 033import org.junit.jupiter.api.Tag; 034import org.junit.jupiter.api.Test; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 039 040@Tag(LargeTests.TAG) 041public class TestFullRestore extends TestBackupBase { 042 043 private static final Logger LOG = LoggerFactory.getLogger(TestFullRestore.class); 044 045 /** 046 * Verify that a single table is restored to a new table. 047 * @throws Exception if doing the backup, restoring it or an operation on the tables fails 048 */ 049 @Test 050 public void testFullRestoreSingle() throws Exception { 051 LOG.info("test full restore on a single table empty table"); 052 053 List<TableName> tables = Lists.newArrayList(table1); 054 String backupId = fullTableBackup(tables); 055 assertTrue(checkSucceeded(backupId)); 056 057 LOG.info("backup complete"); 058 059 TableName[] tableset = new TableName[] { table1 }; 060 TableName[] tablemap = new TableName[] { table1_restore }; 061 BackupAdmin client = getBackupAdmin(); 062 client.restore(BackupUtils.createRestoreRequest(BACKUP_ROOT_DIR, backupId, false, tableset, 063 tablemap, false)); 064 Admin hba = TEST_UTIL.getAdmin(); 065 assertTrue(hba.tableExists(table1_restore)); 066 TEST_UTIL.deleteTable(table1_restore); 067 hba.close(); 068 } 069 070 @Test 071 public void testFullRestoreSingleWithRegion() throws Exception { 072 LOG.info("test full restore on a single table empty table that has a region"); 073 074 // This test creates its own table so other tests are not affected (we adjust it in this test) 075 TableName tableName = TableName.valueOf("table-full-restore-single-region"); 076 TEST_UTIL.createTable(tableName, famName); 077 078 Admin admin = TEST_UTIL.getAdmin(); 079 080 // Add & remove data to ensure a region is active, but functionally empty 081 Table table = TEST_UTIL.getConnection().getTable(tableName); 082 loadTable(table); 083 admin.flush(tableName); 084 TEST_UTIL.deleteTableData(tableName); 085 admin.flush(tableName); 086 087 TEST_UTIL.compact(tableName, true); 088 089 List<TableName> tables = Lists.newArrayList(tableName); 090 String backupId = fullTableBackup(tables); 091 assertTrue(checkSucceeded(backupId)); 092 093 LOG.info("backup complete"); 094 095 TEST_UTIL.deleteTable(tableName); 096 097 TableName[] tableset = new TableName[] { tableName }; 098 TableName[] tablemap = new TableName[] { tableName }; 099 BackupAdmin client = getBackupAdmin(); 100 client.restore(BackupUtils.createRestoreRequest(BACKUP_ROOT_DIR, backupId, false, tableset, 101 tablemap, false)); 102 assertTrue(admin.tableExists(tableName)); 103 TEST_UTIL.deleteTable(tableName); 104 admin.close(); 105 } 106 107 @Test 108 public void testFullRestoreSingleCommand() throws Exception { 109 LOG.info("test full restore on a single table empty table: command-line"); 110 111 List<TableName> tables = Lists.newArrayList(table1); 112 String backupId = fullTableBackup(tables); 113 LOG.info("backup complete"); 114 assertTrue(checkSucceeded(backupId)); 115 // restore <backup_root_path> <backup_id> <tables> [tableMapping] 116 String[] args = new String[] { BACKUP_ROOT_DIR, backupId, "-t", table1.getNameAsString(), "-m", 117 table1_restore.getNameAsString() }; 118 // Run backup 119 int ret = ToolRunner.run(conf1, new RestoreDriver(), args); 120 121 assertTrue(ret == 0); 122 Admin hba = TEST_UTIL.getAdmin(); 123 assertTrue(hba.tableExists(table1_restore)); 124 TEST_UTIL.deleteTable(table1_restore); 125 hba.close(); 126 } 127 128 @Test 129 public void testFullRestoreCheckCommand() throws Exception { 130 LOG.info("test full restore on a single table: command-line, check only"); 131 132 List<TableName> tables = Lists.newArrayList(table1); 133 String backupId = fullTableBackup(tables); 134 LOG.info("backup complete"); 135 assertTrue(checkSucceeded(backupId)); 136 // restore <backup_root_path> <backup_id> <tables> [tableMapping] 137 String[] args = new String[] { BACKUP_ROOT_DIR, backupId, "-t", table1.getNameAsString(), "-m", 138 table1_restore.getNameAsString(), "-c" }; 139 // Run backup 140 int ret = ToolRunner.run(conf1, new RestoreDriver(), args); 141 assertTrue(ret == 0); 142 // Verify that table has not been restored 143 Admin hba = TEST_UTIL.getAdmin(); 144 assertFalse(hba.tableExists(table1_restore)); 145 } 146 147 /** 148 * Verify that multiple tables are restored to new tables. 149 * @throws Exception if doing the backup, restoring it or an operation on the tables fails 150 */ 151 @Test 152 public void testFullRestoreMultiple() throws Exception { 153 LOG.info("create full backup image on multiple tables"); 154 List<TableName> tables = Lists.newArrayList(table2, table3); 155 String backupId = fullTableBackup(tables); 156 assertTrue(checkSucceeded(backupId)); 157 158 TableName[] restore_tableset = new TableName[] { table2, table3 }; 159 TableName[] tablemap = new TableName[] { table2_restore, table3_restore }; 160 BackupAdmin client = getBackupAdmin(); 161 client.restore(BackupUtils.createRestoreRequest(BACKUP_ROOT_DIR, backupId, false, 162 restore_tableset, tablemap, false)); 163 Admin hba = TEST_UTIL.getAdmin(); 164 assertTrue(hba.tableExists(table2_restore)); 165 assertTrue(hba.tableExists(table3_restore)); 166 TEST_UTIL.deleteTable(table2_restore); 167 TEST_UTIL.deleteTable(table3_restore); 168 hba.close(); 169 } 170 171 /** 172 * Verify that multiple tables are restored to new tables. 173 * @throws Exception if doing the backup, restoring it or an operation on the tables fails 174 */ 175 @Test 176 public void testFullRestoreMultipleCommand() throws Exception { 177 LOG.info("create full backup image on multiple tables: command-line"); 178 List<TableName> tables = Lists.newArrayList(table2, table3); 179 String backupId = fullTableBackup(tables); 180 assertTrue(checkSucceeded(backupId)); 181 182 TableName[] restore_tableset = new TableName[] { table2, table3 }; 183 TableName[] tablemap = new TableName[] { table2_restore, table3_restore }; 184 185 // restore <backup_root_path> <backup_id> <tables> [tableMapping] 186 String[] args = new String[] { BACKUP_ROOT_DIR, backupId, "-t", 187 StringUtils.join(restore_tableset, ","), "-m", StringUtils.join(tablemap, ",") }; 188 // Run backup 189 int ret = ToolRunner.run(conf1, new RestoreDriver(), args); 190 191 assertTrue(ret == 0); 192 Admin hba = TEST_UTIL.getAdmin(); 193 assertTrue(hba.tableExists(table2_restore)); 194 assertTrue(hba.tableExists(table3_restore)); 195 TEST_UTIL.deleteTable(table2_restore); 196 TEST_UTIL.deleteTable(table3_restore); 197 hba.close(); 198 } 199 200 /** 201 * Verify that a single table is restored using overwrite. 202 * @throws Exception if doing the backup or restoring it fails 203 */ 204 @Test 205 public void testFullRestoreSingleOverwrite() throws Exception { 206 LOG.info("test full restore on a single table empty table"); 207 List<TableName> tables = Lists.newArrayList(table1); 208 String backupId = fullTableBackup(tables); 209 assertTrue(checkSucceeded(backupId)); 210 211 LOG.info("backup complete"); 212 213 TableName[] tableset = new TableName[] { table1 }; 214 BackupAdmin client = getBackupAdmin(); 215 client.restore( 216 BackupUtils.createRestoreRequest(BACKUP_ROOT_DIR, backupId, false, tableset, null, true)); 217 } 218 219 /** 220 * Verify that a single table is restored using overwrite. 221 * @throws Exception if doing the backup or an operation on the tables fails 222 */ 223 @Test 224 public void testFullRestoreSingleOverwriteCommand() throws Exception { 225 LOG.info("test full restore on a single table empty table: command-line"); 226 List<TableName> tables = Lists.newArrayList(table1); 227 String backupId = fullTableBackup(tables); 228 assertTrue(checkSucceeded(backupId)); 229 LOG.info("backup complete"); 230 TableName[] tableset = new TableName[] { table1 }; 231 // restore <backup_root_path> <backup_id> <tables> [tableMapping] 232 String[] args = 233 new String[] { BACKUP_ROOT_DIR, backupId, "-t", StringUtils.join(tableset, ","), "-o" }; 234 // Run restore 235 int ret = ToolRunner.run(conf1, new RestoreDriver(), args); 236 assertTrue(ret == 0); 237 238 Admin hba = TEST_UTIL.getAdmin(); 239 assertTrue(hba.tableExists(table1)); 240 hba.close(); 241 } 242 243 /** 244 * Verify that multiple tables are restored to new tables using overwrite. 245 * @throws Exception if doing the backup or restoring it fails 246 */ 247 @Test 248 public void testFullRestoreMultipleOverwrite() throws Exception { 249 LOG.info("create full backup image on multiple tables"); 250 251 List<TableName> tables = Lists.newArrayList(table2, table3); 252 String backupId = fullTableBackup(tables); 253 assertTrue(checkSucceeded(backupId)); 254 255 TableName[] restore_tableset = new TableName[] { table2, table3 }; 256 BackupAdmin client = getBackupAdmin(); 257 client.restore(BackupUtils.createRestoreRequest(BACKUP_ROOT_DIR, backupId, false, 258 restore_tableset, null, true)); 259 } 260 261 /** 262 * Verify that multiple tables are restored to new tables using overwrite. 263 * @throws Exception if doing the backup or an operation on the tables fails 264 */ 265 @Test 266 public void testFullRestoreMultipleOverwriteCommand() throws Exception { 267 LOG.info("create full backup image on multiple tables: command-line"); 268 269 List<TableName> tables = Lists.newArrayList(table2, table3); 270 String backupId = fullTableBackup(tables); 271 assertTrue(checkSucceeded(backupId)); 272 273 TableName[] restore_tableset = new TableName[] { table2, table3 }; 274 // restore <backup_root_path> <backup_id> <tables> [tableMapping] 275 String[] args = new String[] { BACKUP_ROOT_DIR, backupId, "-t", 276 StringUtils.join(restore_tableset, ","), "-o" }; 277 // Run backup 278 int ret = ToolRunner.run(conf1, new RestoreDriver(), args); 279 280 assertTrue(ret == 0); 281 Admin hba = TEST_UTIL.getAdmin(); 282 assertTrue(hba.tableExists(table2)); 283 assertTrue(hba.tableExists(table3)); 284 hba.close(); 285 } 286 287 /** 288 * Verify that restore fails on a single table that does not exist. 289 * @throws Exception if doing the backup or restoring it fails 290 */ 291 @Test 292 public void testFullRestoreSingleDNE() throws Exception { 293 assertThrows(IOException.class, () -> { 294 LOG.info("test restore fails on a single table that does not exist"); 295 List<TableName> tables = Lists.newArrayList(table1); 296 String backupId = fullTableBackup(tables); 297 assertTrue(checkSucceeded(backupId)); 298 299 LOG.info("backup complete"); 300 301 TableName[] tableset = new TableName[] { TableName.valueOf("faketable") }; 302 TableName[] tablemap = new TableName[] { table1_restore }; 303 BackupAdmin client = getBackupAdmin(); 304 client.restore(BackupUtils.createRestoreRequest(BACKUP_ROOT_DIR, backupId, false, tableset, 305 tablemap, false)); 306 }); 307 } 308 309 /** 310 * Verify that restore fails on a single table that does not exist. 311 * @throws Exception if doing the backup or restoring it fails 312 */ 313 @Test 314 public void testFullRestoreSingleDNECommand() throws Exception { 315 LOG.info("test restore fails on a single table that does not exist: command-line"); 316 List<TableName> tables = Lists.newArrayList(table1); 317 String backupId = fullTableBackup(tables); 318 assertTrue(checkSucceeded(backupId)); 319 320 LOG.info("backup complete"); 321 322 TableName[] tableset = new TableName[] { TableName.valueOf("faketable") }; 323 TableName[] tablemap = new TableName[] { table1_restore }; 324 String[] args = new String[] { BACKUP_ROOT_DIR, backupId, StringUtils.join(tableset, ","), "-m", 325 StringUtils.join(tablemap, ",") }; 326 // Run restore 327 int ret = ToolRunner.run(conf1, new RestoreDriver(), args); 328 assertTrue(ret != 0); 329 } 330 331 /** 332 * Verify that restore fails on multiple tables that do not exist. 333 * @throws Exception if doing the backup or restoring it fails 334 */ 335 @Test 336 public void testFullRestoreMultipleDNE() throws Exception { 337 assertThrows(IOException.class, () -> { 338 LOG.info("test restore fails on multiple tables that do not exist"); 339 340 List<TableName> tables = Lists.newArrayList(table2, table3); 341 String backupId = fullTableBackup(tables); 342 assertTrue(checkSucceeded(backupId)); 343 344 TableName[] restore_tableset = 345 new TableName[] { TableName.valueOf("faketable1"), TableName.valueOf("faketable2") }; 346 TableName[] tablemap = new TableName[] { table2_restore, table3_restore }; 347 BackupAdmin client = getBackupAdmin(); 348 client.restore(BackupUtils.createRestoreRequest(BACKUP_ROOT_DIR, backupId, false, 349 restore_tableset, tablemap, false)); 350 }); 351 } 352 353 /** 354 * Verify that restore fails on multiple tables that do not exist. 355 * @throws Exception if doing the backup or restoring it fails 356 */ 357 @Test 358 public void testFullRestoreMultipleDNECommand() throws Exception { 359 LOG.info("test restore fails on multiple tables that do not exist: command-line"); 360 361 List<TableName> tables = Lists.newArrayList(table2, table3); 362 String backupId = fullTableBackup(tables); 363 assertTrue(checkSucceeded(backupId)); 364 365 TableName[] restore_tableset = 366 new TableName[] { TableName.valueOf("faketable1"), TableName.valueOf("faketable2") }; 367 TableName[] tablemap = new TableName[] { table2_restore, table3_restore }; 368 String[] args = new String[] { BACKUP_ROOT_DIR, backupId, 369 StringUtils.join(restore_tableset, ","), "-m", StringUtils.join(tablemap, ",") }; 370 // Run restore 371 int ret = ToolRunner.run(conf1, new RestoreDriver(), args); 372 assertTrue(ret != 0); 373 } 374}