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.OPTION_CHECK; 021import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_CHECK_DESC; 022import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_DEBUG; 023import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_DEBUG_DESC; 024import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_OVERWRITE; 025import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_OVERWRITE_DESC; 026import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_SET; 027import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_SET_RESTORE_DESC; 028import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_TABLE; 029import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_TABLE_LIST_DESC; 030import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_TABLE_MAPPING; 031import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_TABLE_MAPPING_DESC; 032import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_YARN_QUEUE_NAME; 033import static org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_YARN_QUEUE_NAME_RESTORE_DESC; 034 035import java.io.IOException; 036import java.util.List; 037import java.util.Objects; 038import org.apache.commons.lang3.StringUtils; 039import org.apache.hadoop.hbase.TableName; 040import org.apache.hadoop.hbase.backup.impl.BackupManager; 041import org.apache.hadoop.hbase.backup.impl.BackupSystemTable; 042import org.apache.hadoop.hbase.backup.util.BackupUtils; 043import org.apache.hadoop.hbase.client.Connection; 044import org.apache.hadoop.hbase.client.ConnectionFactory; 045import org.apache.hadoop.hbase.logging.Log4jUtils; 046import org.apache.hadoop.hbase.util.AbstractHBaseTool; 047import org.apache.yetus.audience.InterfaceAudience; 048import org.slf4j.Logger; 049import org.slf4j.LoggerFactory; 050 051import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine; 052import org.apache.hbase.thirdparty.org.apache.commons.cli.HelpFormatter; 053 054@InterfaceAudience.Private 055public abstract class AbstractRestoreDriver extends AbstractHBaseTool { 056 protected static final Logger LOG = LoggerFactory.getLogger(AbstractRestoreDriver.class); 057 protected CommandLine cmd; 058 059 protected static final String USAGE_FOOTER = ""; 060 061 protected AbstractRestoreDriver() { 062 init(); 063 } 064 065 protected void init() { 066 Log4jUtils.disableZkAndClientLoggers(); 067 } 068 069 protected abstract int executeRestore(boolean check, TableName[] fromTables, TableName[] toTables, 070 boolean isOverwrite); 071 072 private int parseAndRun() throws IOException { 073 if (!BackupManager.isBackupEnabled(getConf())) { 074 System.err.println(BackupRestoreConstants.ENABLE_BACKUP); 075 return -1; 076 } 077 078 if (cmd.hasOption(OPTION_DEBUG)) { 079 Log4jUtils.setLogLevel("org.apache.hadoop.hbase.backup", "DEBUG"); 080 } 081 082 boolean overwrite = cmd.hasOption(OPTION_OVERWRITE); 083 if (overwrite) { 084 LOG.debug("Found overwrite option (-{}) in restore command, " 085 + "will overwrite to existing table if any in the restore target", OPTION_OVERWRITE); 086 } 087 088 boolean check = cmd.hasOption(OPTION_CHECK); 089 if (check) { 090 LOG.debug( 091 "Found check option (-{}) in restore command, will check and verify the dependencies", 092 OPTION_CHECK); 093 } 094 095 if (cmd.hasOption(OPTION_SET) && cmd.hasOption(OPTION_TABLE)) { 096 System.err.printf( 097 "Set name (-%s) and table list (-%s) are mutually exclusive, you can not specify both " 098 + "of them.%n", 099 OPTION_SET, OPTION_TABLE); 100 printToolUsage(); 101 return -1; 102 } 103 104 if (!cmd.hasOption(OPTION_SET) && !cmd.hasOption(OPTION_TABLE)) { 105 System.err.printf( 106 "You have to specify either set name (-%s) or table list (-%s) to " + "restore%n", 107 OPTION_SET, OPTION_TABLE); 108 printToolUsage(); 109 return -1; 110 } 111 112 if (cmd.hasOption(OPTION_YARN_QUEUE_NAME)) { 113 String queueName = cmd.getOptionValue(OPTION_YARN_QUEUE_NAME); 114 // Set MR job queuename to configuration 115 getConf().set("mapreduce.job.queuename", queueName); 116 } 117 118 String tables; 119 TableName[] sTableArray; 120 TableName[] tTableArray; 121 122 String tableMapping = cmd.getOptionValue(OPTION_TABLE_MAPPING); 123 124 try (final Connection conn = ConnectionFactory.createConnection(conf)) { 125 // Check backup set 126 if (cmd.hasOption(OPTION_SET)) { 127 String setName = cmd.getOptionValue(OPTION_SET); 128 try { 129 tables = getTablesForSet(conn, setName); 130 } catch (IOException e) { 131 System.out.println("ERROR: " + e.getMessage() + " for setName=" + setName); 132 printToolUsage(); 133 return -2; 134 } 135 if (tables == null) { 136 System.out 137 .println("ERROR: Backup set '" + setName + "' is either empty or does not exist"); 138 printToolUsage(); 139 return -3; 140 } 141 } else { 142 tables = cmd.getOptionValue(OPTION_TABLE); 143 } 144 145 sTableArray = BackupUtils.parseTableNames(tables); 146 tTableArray = BackupUtils.parseTableNames(tableMapping); 147 148 if ( 149 sTableArray != null && tTableArray != null && (sTableArray.length != tTableArray.length) 150 ) { 151 System.out.println("ERROR: table mapping mismatch: " + tables + " : " + tableMapping); 152 printToolUsage(); 153 return -4; 154 } 155 } 156 157 return executeRestore(check, sTableArray, tTableArray, overwrite); 158 } 159 160 @Override 161 protected void addOptions() { 162 addOptNoArg(OPTION_OVERWRITE, OPTION_OVERWRITE_DESC); 163 addOptNoArg(OPTION_CHECK, OPTION_CHECK_DESC); 164 addOptNoArg(OPTION_DEBUG, OPTION_DEBUG_DESC); 165 addOptWithArg(OPTION_SET, OPTION_SET_RESTORE_DESC); 166 addOptWithArg(OPTION_TABLE, OPTION_TABLE_LIST_DESC); 167 addOptWithArg(OPTION_TABLE_MAPPING, OPTION_TABLE_MAPPING_DESC); 168 addOptWithArg(OPTION_YARN_QUEUE_NAME, OPTION_YARN_QUEUE_NAME_RESTORE_DESC); 169 } 170 171 @Override 172 protected void processOptions(CommandLine cmd) { 173 this.cmd = cmd; 174 } 175 176 @Override 177 protected int doWork() throws Exception { 178 return parseAndRun(); 179 } 180 181 @Override 182 public int run(String[] args) { 183 Objects.requireNonNull(conf, "Tool configuration is not initialized"); 184 185 try { 186 cmd = parseArgs(args); 187 } catch (Exception e) { 188 System.out.println("Error parsing command-line arguments: " + e.getMessage()); 189 printToolUsage(); 190 return EXIT_FAILURE; 191 } 192 193 if (cmd.hasOption(SHORT_HELP_OPTION) || cmd.hasOption(LONG_HELP_OPTION)) { 194 printToolUsage(); 195 return EXIT_FAILURE; 196 } 197 198 processOptions(cmd); 199 200 try { 201 return doWork(); 202 } catch (Exception e) { 203 LOG.error("Error running restore tool", e); 204 return EXIT_FAILURE; 205 } 206 } 207 208 protected void printToolUsage() { 209 System.out.println(getUsageString()); 210 HelpFormatter helpFormatter = new HelpFormatter(); 211 helpFormatter.setLeftPadding(2); 212 helpFormatter.setDescPadding(8); 213 helpFormatter.setWidth(100); 214 helpFormatter.setSyntaxPrefix("Options:"); 215 helpFormatter.printHelp(" ", null, options, USAGE_FOOTER); 216 System.out.println(BackupRestoreConstants.VERIFY_BACKUP); 217 } 218 219 protected abstract String getUsageString(); 220 221 private String getTablesForSet(Connection conn, String name) throws IOException { 222 try (final BackupSystemTable table = new BackupSystemTable(conn)) { 223 List<TableName> tables = table.describeBackupSet(name); 224 225 if (tables == null) { 226 return null; 227 } 228 229 return StringUtils.join(tables, BackupRestoreConstants.TABLENAME_DELIMITER_IN_COMMAND); 230 } 231 } 232}