/* * Copyright © 2016 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.master.startup; import co.cask.cdap.common.conf.CConfiguration; import co.cask.cdap.common.conf.Constants; import co.cask.cdap.common.guice.ConfigModule; import co.cask.cdap.common.guice.DiscoveryRuntimeModule; import co.cask.cdap.common.guice.IOModule; import co.cask.cdap.common.guice.KafkaClientModule; import co.cask.cdap.common.guice.LocationRuntimeModule; import co.cask.cdap.common.guice.ZKClientModule; import co.cask.cdap.common.kerberos.SecurityUtil; import co.cask.cdap.common.startup.CheckRunner; import co.cask.cdap.common.startup.ConfigurationLogger; import co.cask.cdap.data.runtime.main.ClientVersions; import co.cask.cdap.explore.service.ExploreServiceUtils; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.base.Throwables; import com.google.inject.Guice; import com.google.inject.Injector; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.List; /** * Runs some sanity checks that indicate whether the CDAP master will be able to start right away. */ public class MasterStartupTool { private static final Logger LOG = LoggerFactory.getLogger(MasterStartupTool.class); private final CheckRunner checkRunner; public static void main(String[] args) { CConfiguration cConf = CConfiguration.create(); ConfigurationLogger.logImportantConfig(cConf); LOG.info("Hadoop subsystem versions:"); LOG.info(" Hadoop version: {}", ClientVersions.getHadoopVersion()); LOG.info(" HBase version: {}", ClientVersions.getHBaseVersion()); LOG.info(" ZooKeeper version: {}", ClientVersions.getZooKeeperVersion()); LOG.info(" Kafka version: {}", ClientVersions.getKafkaVersion()); if (cConf.getBoolean(Constants.Explore.EXPLORE_ENABLED)) { LOG.info(" Hive version: {}", ExploreServiceUtils.getHiveVersion()); } LOG.info("CDAP version: {}", ClientVersions.getCdapVersion()); LOG.info("CDAP HBase compat version: {}", ClientVersions.getCdapHBaseCompatVersion()); LOG.info("Tephra HBase compat version: {}", ClientVersions.getTephraHBaseCompatVersion()); if (!cConf.getBoolean(Constants.Startup.CHECKS_ENABLED)) { return; } try { SecurityUtil.loginForMasterService(cConf); } catch (Exception e) { LOG.error("Failed to login as CDAP user", e); throw Throwables.propagate(e); } Configuration hConf = HBaseConfiguration.create(); MasterStartupTool masterStartupTool = new MasterStartupTool(createInjector(cConf, hConf)); if (!masterStartupTool.canStartMaster()) { System.exit(1); } } public MasterStartupTool(Injector injector) { this.checkRunner = createCheckRunner(injector); } public boolean canStartMaster() { List<CheckRunner.Failure> failures = checkRunner.runChecks(); if (!failures.isEmpty()) { for (CheckRunner.Failure failure : failures) { LOG.error("{} failed: {}", failure.getName(), failure.getException().getMessage()); if (failure.getException().getCause() != null) { LOG.error(" Root cause: {}", ExceptionUtils.getRootCauseMessage(failure.getException().getCause())); } } LOG.error("Errors detected while starting up master. " + "Please check the logs, address all errors, then try again."); return false; } return true; } private CheckRunner createCheckRunner(Injector injector) { CheckRunner.Builder checkRunnerBuilder = CheckRunner.builder(injector); CConfiguration cConf = injector.getInstance(CConfiguration.class); // add all checks in the configured packages String startupCheckPackages = cConf.get(Constants.Startup.CHECK_PACKAGES); if (!Strings.isNullOrEmpty(startupCheckPackages)) { for (String checkPackage : Splitter.on(',').trimResults().split(startupCheckPackages)) { LOG.debug("Adding startup checks from package {}", checkPackage); try { checkRunnerBuilder.addChecksInPackage(checkPackage); } catch (IOException e) { // not expected unless something is weird with the local filesystem LOG.error("Unable to examine classpath to look for startup checks in package {}.", checkPackage, e); throw new RuntimeException(e); } } } // add all checks specified directly by name String startupCheckClassnames = cConf.get(Constants.Startup.CHECK_CLASSES); if (!Strings.isNullOrEmpty(startupCheckClassnames)) { for (String className : Splitter.on(',').trimResults().split(startupCheckClassnames)) { LOG.debug("Adding startup check {}.", className); try { checkRunnerBuilder.addClass(className); } catch (ClassNotFoundException e) { LOG.error("Startup check {} not found. " + "Please check for typos and ensure the class is available on the classpath.", className); throw new RuntimeException(e); } } } return checkRunnerBuilder.build(); } private static Injector createInjector(CConfiguration cConf, Configuration hConf) { return Guice.createInjector( new ConfigModule(cConf, hConf), new ZKClientModule(), new LocationRuntimeModule().getDistributedModules(), new IOModule(), new KafkaClientModule(), new DiscoveryRuntimeModule().getDistributedModules() ); } }