View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.backup;
19  
20  import java.io.IOException;
21  import java.util.List;
22  
23  import org.apache.commons.cli.CommandLine;
24  import org.apache.commons.lang.StringUtils;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.HBaseConfiguration;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.backup.impl.BackupRestoreConstants;
31  import org.apache.hadoop.hbase.backup.impl.BackupSystemTable;
32  import org.apache.hadoop.hbase.backup.util.BackupServerUtil;
33  import org.apache.hadoop.hbase.client.Connection;
34  import org.apache.hadoop.hbase.client.ConnectionFactory;
35  import org.apache.hadoop.hbase.util.AbstractHBaseTool;
36  import org.apache.hadoop.hbase.util.LogUtils;
37  import org.apache.hadoop.util.ToolRunner;
38  import org.apache.log4j.Level;
39  import org.apache.log4j.Logger;
40  
41  public class RestoreDriver extends AbstractHBaseTool {
42  
43    private static final Log LOG = LogFactory.getLog(RestoreDriver.class);
44    private CommandLine cmd;
45  
46    private static final String OPTION_OVERWRITE = "overwrite";
47    private static final String OPTION_CHECK = "check";
48    private static final String OPTION_AUTOMATIC = "automatic";
49    private static final String OPTION_SET = "set";
50    private static final String OPTION_DEBUG = "debug";
51  
52  
53    private static final String USAGE =
54        "Usage: hbase restore [-set set_name] <backup_root_path> <backup_id> <tables> [tableMapping] \n"
55            + "       [-overwrite] [-check] [-automatic]\n"
56            + " backup_root_path  The parent location where the backup images are stored\n"
57            + " backup_id         The id identifying the backup image\n"
58            + " table(s)          Table(s) from the backup image to be restored.\n"
59            + "                   Tables are separated by comma.\n"
60            + " Options:\n"
61            + "   tableMapping    A comma separated list of target tables.\n"
62            + "                   If specified, each table in <tables> must have a mapping.\n"
63            + "   -overwrite      With this option, restore overwrites to the existing table "
64            + "if there's any in\n"
65            + "                   restore target. The existing table must be online before restore.\n"
66            + "   -check          With this option, restore sequence and dependencies are checked\n"
67            + "                   and verified without executing the restore\n"
68            + "   -set set_name   Backup set to restore, mutually exclusive with table list <tables>.";
69  
70      
71    protected RestoreDriver() throws IOException
72    {
73      init();
74    }
75    
76    protected void init() throws IOException {
77      // define supported options
78      addOptNoArg(OPTION_OVERWRITE,
79          "Overwrite the data if any of the restore target tables exists");
80      addOptNoArg(OPTION_CHECK, "Check restore sequence and dependencies");
81      addOptNoArg(OPTION_AUTOMATIC, "Restore all dependencies");
82      addOptNoArg(OPTION_DEBUG,  "Enable debug logging");
83      addOptWithArg(OPTION_SET, "Backup set name");
84  
85      // disable irrelevant loggers to avoid it mess up command output
86      LogUtils.disableUselessLoggers(LOG);
87    }
88  
89    private int parseAndRun(String[] args) {
90  
91      // enable debug logging
92      Logger backupClientLogger = Logger.getLogger("org.apache.hadoop.hbase.backup");
93      if (cmd.hasOption(OPTION_DEBUG)) {
94        backupClientLogger.setLevel(Level.DEBUG);
95      }
96  
97      // whether to overwrite to existing table if any, false by default
98      boolean isOverwrite = cmd.hasOption(OPTION_OVERWRITE);
99      if (isOverwrite) {
100       LOG.debug("Found -overwrite option in restore command, "
101           + "will overwrite to existing table if any in the restore target");
102     }
103 
104     // whether to only check the dependencies, false by default
105     boolean check = cmd.hasOption(OPTION_CHECK);
106     if (check) {
107       LOG.debug("Found -check option in restore command, "
108           + "will check and verify the dependencies");
109     }
110 
111     LOG.debug("Will automatically restore all the dependencies");
112 
113     // parse main restore command options
114     String[] remainArgs = cmd.getArgs();
115     if (remainArgs.length < 3 && !cmd.hasOption(OPTION_SET) ||
116         (cmd.hasOption(OPTION_SET) && remainArgs.length < 2)) {
117       System.out.println("ERROR: remain args length="+ remainArgs.length);
118       System.out.println(USAGE);
119       return -1;
120     } 
121 
122     String backupRootDir = remainArgs[0];
123     String backupId = remainArgs[1];
124     String tables = null;
125     String tableMapping = null;
126     // Check backup set
127     if (cmd.hasOption(OPTION_SET)) {
128       String setName = cmd.getOptionValue(OPTION_SET);
129       try{
130         tables = getTablesForSet(setName, conf);       
131       } catch(IOException e){
132         System.out.println("ERROR: "+ e.getMessage()+" for setName="+setName);
133         return -2;
134       }
135       if (tables == null) {
136         System.out.println("ERROR: Backup set '" + setName
137         + "' is either empty or does not exist");
138         return -3;
139       }
140       tableMapping = (remainArgs.length > 2) ? remainArgs[2] : null;
141     } else {
142       tables = remainArgs[2];    
143       tableMapping = (remainArgs.length > 3) ? remainArgs[3] : null;
144     }    
145 
146     TableName[] sTableArray = BackupServerUtil.parseTableNames(tables);
147     TableName[] tTableArray = BackupServerUtil.parseTableNames(tableMapping);
148 
149     if (sTableArray != null && tTableArray != null && (sTableArray.length != tTableArray.length)) {
150       System.out.println("ERROR: table mapping mismatch: " + tables + " : " + tableMapping);
151       System.out.println(USAGE);
152       return -4;
153     }
154 
155     
156     RestoreClient client = BackupRestoreClientFactory.getRestoreClient(getConf());
157     try{
158       client.restore(backupRootDir, backupId, check, sTableArray,
159         tTableArray, isOverwrite);
160     } catch (Exception e){
161       e.printStackTrace();
162       return -5;
163     }
164     return 0;
165   }
166 
167   private String getTablesForSet(String name, Configuration conf) throws IOException {
168     try (final Connection conn = ConnectionFactory.createConnection(conf);
169         final BackupSystemTable table = new BackupSystemTable(conn)) {
170       List<TableName> tables = table.describeBackupSet(name);
171       if (tables == null) return null;
172       return StringUtils.join(tables, BackupRestoreConstants.TABLENAME_DELIMITER_IN_COMMAND);
173     }
174   }
175   
176   @Override
177   protected void addOptions() {
178   }
179 
180   @Override
181   protected void processOptions(CommandLine cmd) {
182     this.cmd = cmd;
183   }
184 
185   @Override
186   protected int doWork() throws Exception {
187     return parseAndRun(cmd.getArgs());
188   }
189 
190   public static void main(String[] args) throws Exception {
191     Configuration conf = HBaseConfiguration.create();
192     int ret = ToolRunner.run(conf, new RestoreDriver(), args);
193     System.exit(ret);
194   }
195 }