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.apache.hadoop.hbase.backup.BackupRestoreConstants.LONG_OPTION_ENABLE_CONTINUOUS_BACKUP;
021import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.LONG_OPTION_FORCE_DELETE;
022import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_BACKUP_LIST_DESC;
023import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_BANDWIDTH;
024import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_BANDWIDTH_DESC;
025import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_DEBUG;
026import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_DEBUG_DESC;
027import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_ENABLE_CONTINUOUS_BACKUP;
028import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_ENABLE_CONTINUOUS_BACKUP_DESC;
029import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_FORCE_DELETE;
030import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_FORCE_DELETE_DESC;
031import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_IGNORECHECKSUM;
032import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_IGNORECHECKSUM_DESC;
033import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_KEEP;
034import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_KEEP_DESC;
035import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_LIST;
036import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_PATH;
037import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_PATH_DESC;
038import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_RECORD_NUMBER;
039import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_RECORD_NUMBER_DESC;
040import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_SET;
041import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_SET_DESC;
042import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_TABLE;
043import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_TABLE_DESC;
044import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_WORKERS;
045import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_WORKERS_DESC;
046import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_YARN_QUEUE_NAME;
047import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_YARN_QUEUE_NAME_DESC;
048
049import java.io.IOException;
050import java.net.URI;
051import java.util.Objects;
052import org.apache.hadoop.conf.Configuration;
053import org.apache.hadoop.fs.Path;
054import org.apache.hadoop.hbase.HBaseConfiguration;
055import org.apache.hadoop.hbase.backup.BackupRestoreConstants.BackupCommand;
056import org.apache.hadoop.hbase.backup.impl.BackupCommands;
057import org.apache.hadoop.hbase.backup.impl.BackupManager;
058import org.apache.hadoop.hbase.logging.Log4jUtils;
059import org.apache.hadoop.hbase.util.AbstractHBaseTool;
060import org.apache.hadoop.hbase.util.CommonFSUtils;
061import org.apache.hadoop.util.ToolRunner;
062import org.apache.yetus.audience.InterfaceAudience;
063import org.slf4j.Logger;
064import org.slf4j.LoggerFactory;
065
066import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;
067
068/**
069 * Command-line entry point for backup operation
070 */
071@InterfaceAudience.Private
072public class BackupDriver extends AbstractHBaseTool {
073
074  private static final Logger LOG = LoggerFactory.getLogger(BackupDriver.class);
075  private CommandLine cmd;
076
077  public BackupDriver() throws IOException {
078    init();
079  }
080
081  protected void init() throws IOException {
082    // disable irrelevant loggers to avoid it mess up command output
083    Log4jUtils.disableZkAndClientLoggers();
084  }
085
086  private int parseAndRun(String[] args) throws IOException {
087
088    // Check if backup is enabled
089    if (!BackupManager.isBackupEnabled(getConf())) {
090      System.err.println(BackupRestoreConstants.ENABLE_BACKUP);
091      return -1;
092    }
093
094    String cmd = null;
095    String[] remainArgs = null;
096    if (args == null || args.length == 0) {
097      printToolUsage();
098      return -1;
099    } else {
100      cmd = args[0];
101      remainArgs = new String[args.length - 1];
102      if (args.length > 1) {
103        System.arraycopy(args, 1, remainArgs, 0, args.length - 1);
104      }
105    }
106
107    BackupCommand type = BackupCommand.HELP;
108    if (BackupCommand.CREATE.name().equalsIgnoreCase(cmd)) {
109      type = BackupCommand.CREATE;
110    } else if (BackupCommand.HELP.name().equalsIgnoreCase(cmd)) {
111      type = BackupCommand.HELP;
112    } else if (BackupCommand.DELETE.name().equalsIgnoreCase(cmd)) {
113      type = BackupCommand.DELETE;
114    } else if (BackupCommand.DESCRIBE.name().equalsIgnoreCase(cmd)) {
115      type = BackupCommand.DESCRIBE;
116    } else if (BackupCommand.HISTORY.name().equalsIgnoreCase(cmd)) {
117      type = BackupCommand.HISTORY;
118    } else if (BackupCommand.PROGRESS.name().equalsIgnoreCase(cmd)) {
119      type = BackupCommand.PROGRESS;
120    } else if (BackupCommand.SET.name().equalsIgnoreCase(cmd)) {
121      type = BackupCommand.SET;
122    } else if (BackupCommand.REPAIR.name().equalsIgnoreCase(cmd)) {
123      type = BackupCommand.REPAIR;
124    } else if (BackupCommand.MERGE.name().equalsIgnoreCase(cmd)) {
125      type = BackupCommand.MERGE;
126    } else {
127      System.out.println("Unsupported command for backup: " + cmd);
128      printToolUsage();
129      return -1;
130    }
131
132    // enable debug logging
133    if (this.cmd.hasOption(OPTION_DEBUG)) {
134      Log4jUtils.setLogLevel("org.apache.hadoop.hbase.backup", "DEBUG");
135    }
136
137    BackupCommands.Command command = BackupCommands.createCommand(getConf(), type, this.cmd);
138    if (type == BackupCommand.CREATE && conf != null) {
139      ((BackupCommands.CreateCommand) command).setConf(conf);
140    }
141    try {
142      command.execute();
143    } catch (IOException e) {
144      if (e.getMessage().equals(BackupCommands.INCORRECT_USAGE)) {
145        return -1;
146      }
147      throw e;
148    } finally {
149      command.finish();
150    }
151    return 0;
152  }
153
154  @Override
155  protected void addOptions() {
156    // define supported options
157    addOptNoArg(OPTION_DEBUG, OPTION_DEBUG_DESC);
158    addOptWithArg(OPTION_TABLE, OPTION_TABLE_DESC);
159    addOptWithArg(OPTION_BANDWIDTH, OPTION_BANDWIDTH_DESC);
160    addOptWithArg(OPTION_LIST, OPTION_BACKUP_LIST_DESC);
161    addOptWithArg(OPTION_WORKERS, OPTION_WORKERS_DESC);
162    addOptNoArg(OPTION_IGNORECHECKSUM, OPTION_IGNORECHECKSUM_DESC);
163    addOptWithArg(OPTION_RECORD_NUMBER, OPTION_RECORD_NUMBER_DESC);
164    addOptWithArg(OPTION_SET, OPTION_SET_DESC);
165    addOptWithArg(OPTION_PATH, OPTION_PATH_DESC);
166    addOptWithArg(OPTION_KEEP, OPTION_KEEP_DESC);
167    addOptWithArg(OPTION_YARN_QUEUE_NAME, OPTION_YARN_QUEUE_NAME_DESC);
168    addOptNoArg(OPTION_ENABLE_CONTINUOUS_BACKUP, LONG_OPTION_ENABLE_CONTINUOUS_BACKUP,
169      OPTION_ENABLE_CONTINUOUS_BACKUP_DESC);
170    addOptNoArg(OPTION_FORCE_DELETE, LONG_OPTION_FORCE_DELETE, OPTION_FORCE_DELETE_DESC);
171  }
172
173  @Override
174  protected void processOptions(CommandLine cmd) {
175    this.cmd = cmd;
176  }
177
178  @Override
179  protected int doWork() throws Exception {
180    return parseAndRun(cmd.getArgs());
181  }
182
183  public static void main(String[] args) throws Exception {
184    Configuration conf = HBaseConfiguration.create();
185    Path hbasedir = CommonFSUtils.getRootDir(conf);
186    URI defaultFs = hbasedir.getFileSystem(conf).getUri();
187    CommonFSUtils.setFsDefault(conf, new Path(defaultFs));
188    int ret = ToolRunner.run(conf, new BackupDriver(), args);
189    System.exit(ret);
190  }
191
192  @Override
193  public int run(String[] args) throws IOException {
194    Objects.requireNonNull(conf, "Tool configuration is not initialized");
195
196    CommandLine cmd;
197    try {
198      // parse the command line arguments
199      cmd = parseArgs(args);
200      cmdLineArgs = args;
201    } catch (Exception e) {
202      System.err.println("Error when parsing command-line arguments: " + e.getMessage());
203      printToolUsage();
204      return EXIT_FAILURE;
205    }
206    processOptions(cmd);
207
208    int ret = EXIT_FAILURE;
209    try {
210      ret = doWork();
211    } catch (Exception e) {
212      LOG.error("Error running command-line tool", e);
213      return EXIT_FAILURE;
214    }
215    return ret;
216  }
217
218  protected void printToolUsage() throws IOException {
219    System.out.println(BackupCommands.USAGE);
220    System.out.println(BackupRestoreConstants.VERIFY_BACKUP);
221  }
222}