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