/* * Copyright © 2015 Cask Data, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package co.cask.cdap.data.tools; import co.cask.cdap.api.dataset.DatasetManagementException; import co.cask.cdap.api.dataset.module.DatasetDefinitionRegistry; import co.cask.cdap.common.conf.CConfiguration; import co.cask.cdap.common.guice.ConfigModule; import co.cask.cdap.common.guice.LocationRuntimeModule; import co.cask.cdap.common.utils.ProjectInfo; import co.cask.cdap.data2.dataset2.DatasetDefinitionRegistryFactory; import co.cask.cdap.data2.dataset2.DatasetFramework; import co.cask.cdap.data2.dataset2.DefaultDatasetDefinitionRegistry; import co.cask.cdap.data2.dataset2.InMemoryDatasetFramework; import co.cask.cdap.data2.dataset2.lib.file.FileSetModule; import co.cask.cdap.data2.dataset2.lib.table.CoreDatasetsModule; import co.cask.cdap.data2.dataset2.module.lib.hbase.HBaseMetricsTableModule; import co.cask.cdap.data2.dataset2.module.lib.hbase.HBaseTableModule; import co.cask.cdap.data2.util.hbase.HBaseTableUtil; import co.cask.cdap.data2.util.hbase.HBaseTableUtilFactory; import co.cask.cdap.metrics.store.DefaultMetricDatasetFactory; import co.cask.cdap.metrics.store.upgrade.DataMigrationException; import co.cask.cdap.proto.Id; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.assistedinject.FactoryModuleBuilder; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import java.io.IOException; /** * Command line tool to migrate data between different versions of CDAP. * Usually used along with upgrade tool{@link UpgradeTool} */ public class DataMigration { private static final String KEEP_OLD_METRICS_DATA = "--keep-old-metrics-data"; /** * Set of Action available in this tool. */ private enum Action { METRICS("Migrate metrics data, to preserve old table data use option " + KEEP_OLD_METRICS_DATA), HELP("Show this help."); private final String description; private Action(String description) { this.description = description; } private String getDescription() { return description; } } public void doMain(String[] args) throws Exception { System.out.println(String.format("%s - version %s.", getClass().getSimpleName(), ProjectInfo.getVersion())); System.out.println(); MigrationAction action = getAction(args); if (action == null) { return; } action.perform(getInjector()); } public Injector getInjector() { CConfiguration cConf = CConfiguration.create(); Configuration hConf = HBaseConfiguration.create(); return Guice.createInjector( new ConfigModule(cConf, hConf), new LocationRuntimeModule().getDistributedModules(), new AbstractModule() { @Override protected void configure() { bind(HBaseTableUtil.class).toProvider(HBaseTableUtilFactory.class); install(new FactoryModuleBuilder() .implement(DatasetDefinitionRegistry.class, DefaultDatasetDefinitionRegistry.class) .build(DatasetDefinitionRegistryFactory.class)); } }); } public MigrationAction getAction(String[] args) { if (args.length < 1) { printHelp(); return null; } Action action = parseAction(args[0]); if (action == null) { System.out.println(String.format("Unsupported action : %s", args[0])); printHelp(true); return null; } switch (action) { case METRICS: return getMetricsMigrationAction(args); case HELP: printHelp(); break; } return null; } private MigrationAction getMetricsMigrationAction(String[] args) { if (args.length > 2) { System.out.println("invalid number of arguments"); printHelp(true); } else if (args.length == 2) { if (args[1].equals(KEEP_OLD_METRICS_DATA)) { return new MetricsMigration(true); } else { System.out.println("invalid argument, expected argument " + KEEP_OLD_METRICS_DATA); } } else { return new MetricsMigration(false); } return null; } private void printHelp() { printHelp(false); } private void printHelp(boolean beginNewLine) { if (beginNewLine) { System.out.println(); } System.out.println("Available actions: "); System.out.println(); for (Action action : Action.values()) { System.out.println(String.format(" %s - %s", action.name().toLowerCase(), action.getDescription())); } } private Action parseAction(String action) { try { return Action.valueOf(action.toUpperCase()); } catch (IllegalArgumentException e) { return null; } } private static final class MetricsMigration implements MigrationAction { boolean keepOldMetricsData; public MetricsMigration(boolean keepOldMetricsData) { this.keepOldMetricsData = keepOldMetricsData; } @Override public void perform(Injector injector) { CConfiguration cConf = injector.getInstance(CConfiguration.class); Configuration hConf = injector.getInstance(Configuration.class); try { DatasetFramework framework = createRegisteredDatasetFramework(injector); // migrate metrics data DefaultMetricDatasetFactory.migrateData(cConf, hConf, framework, keepOldMetricsData, injector.getInstance(HBaseTableUtil.class)); } catch (DataMigrationException e) { System.out.println( String.format("Exception encountered during metrics migration : %s , Aborting metrics data migration", e.getMigrationExceptionMessage())); } catch (Exception e) { System.out.println(String.format( "Exception encountered : %s , Aborting metrics migration", e)); } } } public static void main(String[] args) throws Exception { new DataMigration().doMain(args); } private interface MigrationAction { void perform(Injector injector); } public static MigrationAction testMigrationParsing(String[] args) { return new DataMigration().getMetricsMigrationAction(args); } /** * Sets up a {@link DatasetFramework} instance for standalone usage. NOTE: should NOT be used by applications!!! */ public static DatasetFramework createRegisteredDatasetFramework(Injector injector) throws DatasetManagementException, IOException { DatasetDefinitionRegistryFactory registryFactory = injector.getInstance(DatasetDefinitionRegistryFactory.class); DatasetFramework datasetFramework = new InMemoryDatasetFramework(registryFactory, injector.getInstance(CConfiguration.class)); // TODO: this doesn't sound right. find out why its needed. datasetFramework.addModule(Id.DatasetModule.from(Id.Namespace.SYSTEM, "table"), new HBaseTableModule()); datasetFramework.addModule(Id.DatasetModule.from(Id.Namespace.SYSTEM, "metricsTable"), new HBaseMetricsTableModule()); datasetFramework.addModule(Id.DatasetModule.from(Id.Namespace.SYSTEM, "core"), new CoreDatasetsModule()); datasetFramework.addModule(Id.DatasetModule.from(Id.Namespace.SYSTEM, "fileSet"), new FileSetModule()); return datasetFramework; } }