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.assertEquals;
021import static org.junit.Assert.assertTrue;
022
023import java.io.ByteArrayOutputStream;
024import java.io.PrintStream;
025import java.util.List;
026import org.apache.hadoop.fs.FileSystem;
027import org.apache.hadoop.fs.Path;
028import org.apache.hadoop.hbase.HBaseClassTestRule;
029import org.apache.hadoop.hbase.TableName;
030import org.apache.hadoop.hbase.backup.impl.BackupSystemTable;
031import org.apache.hadoop.hbase.testclassification.LargeTests;
032import org.apache.hadoop.hbase.util.EnvironmentEdge;
033import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
034import org.apache.hadoop.util.ToolRunner;
035import org.junit.Assert;
036import org.junit.ClassRule;
037import org.junit.Test;
038import org.junit.experimental.categories.Category;
039import org.slf4j.Logger;
040import org.slf4j.LoggerFactory;
041
042import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
043import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
044
045@Category(LargeTests.class)
046public class TestBackupDelete extends TestBackupBase {
047
048  @ClassRule
049  public static final HBaseClassTestRule CLASS_RULE =
050    HBaseClassTestRule.forClass(TestBackupDelete.class);
051
052  private static final Logger LOG = LoggerFactory.getLogger(TestBackupDelete.class);
053
054  /**
055   * Verify that full backup is created on a single table with data correctly. Verify that history
056   * works as expected.
057   * @throws Exception if doing the backup or an operation on the tables fails
058   */
059  @Test
060  public void testBackupDelete() throws Exception {
061    LOG.info("test backup delete on a single table with data");
062    List<TableName> tableList = Lists.newArrayList(table1);
063    String backupId = fullTableBackup(tableList);
064    assertTrue(checkSucceeded(backupId));
065    LOG.info("backup complete");
066    String[] backupIds = new String[] { backupId };
067    BackupSystemTable table = new BackupSystemTable(TEST_UTIL.getConnection());
068    BackupInfo info = table.readBackupInfo(backupId);
069    Path path = new Path(info.getBackupRootDir(), backupId);
070    FileSystem fs = FileSystem.get(path.toUri(), conf1);
071    assertTrue(fs.exists(path));
072    int deleted = getBackupAdmin().deleteBackups(backupIds);
073
074    assertTrue(!fs.exists(path));
075    assertTrue(fs.exists(new Path(info.getBackupRootDir())));
076    assertTrue(1 == deleted);
077    table.close();
078    LOG.info("delete_backup");
079  }
080
081  /**
082   * Verify that full backup is created on a single table with data correctly. Verify that history
083   * works as expected.
084   * @throws Exception if doing the backup or an operation on the tables fails
085   */
086  @Test
087  public void testBackupDeleteCommand() throws Exception {
088    LOG.info("test backup delete on a single table with data: command-line");
089    List<TableName> tableList = Lists.newArrayList(table1);
090    String backupId = fullTableBackup(tableList);
091    assertTrue(checkSucceeded(backupId));
092    LOG.info("backup complete");
093    ByteArrayOutputStream baos = new ByteArrayOutputStream();
094    System.setOut(new PrintStream(baos));
095
096    String[] args = new String[] { "delete", "-l", backupId };
097    // Run backup
098
099    try {
100      int ret = ToolRunner.run(conf1, new BackupDriver(), args);
101      assertTrue(ret == 0);
102    } catch (Exception e) {
103      LOG.error("failed", e);
104    }
105    LOG.info("delete_backup");
106    String output = baos.toString();
107    LOG.info(baos.toString());
108    assertTrue(output.indexOf("Deleted 1 backups") >= 0);
109  }
110
111  @Test
112  public void testBackupPurgeOldBackupsCommand() throws Exception {
113    LOG.info("test backup delete (purge old backups) on a single table with data: command-line");
114    List<TableName> tableList = Lists.newArrayList(table1);
115    EnvironmentEdgeManager.injectEdge(new EnvironmentEdge() {
116      // time - 2 days
117      @Override
118      public long currentTime() {
119        return System.currentTimeMillis() - 2 * 24 * 3600 * 1000;
120      }
121    });
122    String backupId = fullTableBackup(tableList);
123    assertTrue(checkSucceeded(backupId));
124
125    EnvironmentEdgeManager.reset();
126
127    LOG.info("backup complete");
128    ByteArrayOutputStream baos = new ByteArrayOutputStream();
129    System.setOut(new PrintStream(baos));
130
131    // Purge all backups which are older than 3 days
132    // Must return 0 (no backups were purged)
133    String[] args = new String[] { "delete", "-k", "3" };
134    // Run backup
135
136    try {
137      int ret = ToolRunner.run(conf1, new BackupDriver(), args);
138      assertTrue(ret == 0);
139    } catch (Exception e) {
140      LOG.error("failed", e);
141      Assert.fail(e.getMessage());
142    }
143    String output = baos.toString();
144    LOG.info(baos.toString());
145    assertTrue(output.indexOf("Deleted 0 backups") >= 0);
146
147    // Purge all backups which are older than 1 days
148    // Must return 1 deleted backup
149    args = new String[] { "delete", "-k", "1" };
150    // Run backup
151    baos.reset();
152    try {
153      int ret = ToolRunner.run(conf1, new BackupDriver(), args);
154      assertTrue(ret == 0);
155    } catch (Exception e) {
156      LOG.error("failed", e);
157      Assert.fail(e.getMessage());
158    }
159    output = baos.toString();
160    LOG.info(baos.toString());
161    assertTrue(output.indexOf("Deleted 1 backups") >= 0);
162  }
163
164  /**
165   * Verify that backup deletion updates the incremental-backup-set.
166   */
167  @Test
168  public void testBackupDeleteUpdatesIncrementalBackupSet() throws Exception {
169    LOG.info("Test backup delete updates the incremental backup set");
170    BackupSystemTable backupSystemTable = new BackupSystemTable(TEST_UTIL.getConnection());
171
172    String backupId1 = fullTableBackup(Lists.newArrayList(table1, table2));
173    assertTrue(checkSucceeded(backupId1));
174    assertEquals(Sets.newHashSet(table1, table2),
175      backupSystemTable.getIncrementalBackupTableSet(BACKUP_ROOT_DIR));
176
177    String backupId2 = fullTableBackup(Lists.newArrayList(table3));
178    assertTrue(checkSucceeded(backupId2));
179    assertEquals(Sets.newHashSet(table1, table2, table3),
180      backupSystemTable.getIncrementalBackupTableSet(BACKUP_ROOT_DIR));
181
182    getBackupAdmin().deleteBackups(new String[] { backupId1 });
183    assertEquals(Sets.newHashSet(table3),
184      backupSystemTable.getIncrementalBackupTableSet(BACKUP_ROOT_DIR));
185  }
186}