/* * Copyright © 2014 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.runtime.main; import co.cask.cdap.common.conf.CConfiguration; import co.cask.cdap.common.conf.Constants; import co.cask.cdap.common.twill.AbortOnTimeoutEventHandler; import co.cask.cdap.common.utils.DirUtils; import co.cask.cdap.explore.service.ExploreServiceUtils; import co.cask.cdap.logging.run.LogSaverTwillRunnable; import co.cask.cdap.metrics.runtime.MetricsProcessorTwillRunnable; import co.cask.cdap.metrics.runtime.MetricsTwillRunnable; import com.google.common.base.Preconditions; import org.apache.twill.api.ResourceSpecification; import org.apache.twill.api.TwillApplication; import org.apache.twill.api.TwillSpecification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.Map; import java.util.Set; /** * TwillApplication wrapper for Master Services running in YARN. */ public class MasterTwillApplication implements TwillApplication { private static final Logger LOG = LoggerFactory.getLogger(MasterTwillApplication.class); private static final String NAME = Constants.Service.MASTER_SERVICES; private final CConfiguration cConf; private final File cConfFile; private final File hConfFile; private final boolean runHiveService; private final Map<String, Integer> instanceCountMap; public MasterTwillApplication(CConfiguration cConf, File cConfFile, File hConfFile, Map<String, Integer> instanceCountMap) { this.cConf = cConf; this.cConfFile = cConfFile; this.hConfFile = hConfFile; this.runHiveService = cConf.getBoolean(Constants.Explore.EXPLORE_ENABLED); this.instanceCountMap = instanceCountMap; } @Override public TwillSpecification configure() { // It is always present in cdap-default.xml final long noContainerTimeout = cConf.getLong(Constants.CFG_TWILL_NO_CONTAINER_TIMEOUT, Long.MAX_VALUE); TwillSpecification.Builder.RunnableSetter runnableSetter = addDatasetOpExecutor( addLogSaverService( addStreamService( addTransactionService( addMetricsProcessor ( addMetricsService( TwillSpecification.Builder.with().setName(NAME).withRunnable())))))); if (runHiveService) { LOG.info("Adding explore runnable."); runnableSetter = addExploreService(runnableSetter); } else { LOG.info("Explore module disabled - will not launch explore runnable."); } return runnableSetter .withPlacementPolicy() .add(TwillSpecification.PlacementPolicy.Type.DISTRIBUTED, Constants.Service.STREAMS) .anyOrder() .withEventHandler(new AbortOnTimeoutEventHandler(noContainerTimeout)) .build(); } private TwillSpecification.Builder.RunnableSetter addLogSaverService(TwillSpecification.Builder.MoreRunnable builder) { int numInstances = instanceCountMap.get(Constants.Service.LOGSAVER); Preconditions.checkArgument(numInstances > 0, "log saver num instances should be at least 1, got %s", numInstances); int memory = cConf.getInt(Constants.LogSaver.MEMORY_MB); Preconditions.checkArgument(memory > 0, "Got invalid memory value for log saver %s", memory); int cores = cConf.getInt(Constants.LogSaver.NUM_CORES); Preconditions.checkArgument(cores > 0, "Got invalid num cores value for log saver %s", cores); ResourceSpecification spec = ResourceSpecification.Builder .with() .setVirtualCores(cores) .setMemory(memory, ResourceSpecification.SizeUnit.MEGA) .setInstances(numInstances) .build(); return builder.add(new LogSaverTwillRunnable(Constants.Service.LOGSAVER, "hConf.xml", "cConf.xml"), spec) .withLocalFiles() .add("hConf.xml", hConfFile.toURI()) .add("cConf.xml", cConfFile.toURI()) .apply(); } private TwillSpecification.Builder.RunnableSetter addMetricsProcessor(TwillSpecification.Builder.MoreRunnable builder) { int numCores = cConf.getInt(Constants.MetricsProcessor.NUM_CORES); int memoryMB = cConf.getInt(Constants.MetricsProcessor.MEMORY_MB); int instances = instanceCountMap.get(Constants.Service.METRICS_PROCESSOR); ResourceSpecification metricsProcessorSpec = ResourceSpecification.Builder .with() .setVirtualCores(numCores) .setMemory(memoryMB, ResourceSpecification.SizeUnit.MEGA) .setInstances(instances) .build(); return builder.add(new MetricsProcessorTwillRunnable(Constants.Service.METRICS_PROCESSOR, "cConf.xml", "hConf.xml"), metricsProcessorSpec) .withLocalFiles() .add("cConf.xml", cConfFile.toURI()) .add("hConf.xml", hConfFile.toURI()) .apply(); } private TwillSpecification.Builder.RunnableSetter addMetricsService(TwillSpecification.Builder.MoreRunnable builder) { int metricsNumCores = cConf.getInt(Constants.Metrics.NUM_CORES); int metricsMemoryMb = cConf.getInt(Constants.Metrics.MEMORY_MB); int metricsInstances = instanceCountMap.get(Constants.Service.METRICS); ResourceSpecification metricsSpec = ResourceSpecification.Builder .with() .setVirtualCores(metricsNumCores) .setMemory(metricsMemoryMb, ResourceSpecification.SizeUnit.MEGA) .setInstances(metricsInstances) .build(); return builder.add(new MetricsTwillRunnable(Constants.Service.METRICS, "cConf.xml", "hConf.xml"), metricsSpec) .withLocalFiles() .add("cConf.xml", cConfFile.toURI()) .add("hConf.xml", hConfFile.toURI()) .apply(); } private TwillSpecification.Builder.RunnableSetter addTransactionService(TwillSpecification.Builder.MoreRunnable builder) { int txNumCores = cConf.getInt(Constants.Transaction.Container.NUM_CORES); int txMemoryMb = cConf.getInt(Constants.Transaction.Container.MEMORY_MB); int txInstances = instanceCountMap.get(Constants.Service.TRANSACTION); ResourceSpecification transactionSpec = ResourceSpecification.Builder .with() .setVirtualCores(txNumCores) .setMemory(txMemoryMb, ResourceSpecification.SizeUnit.MEGA) .setInstances(txInstances) .build(); return builder.add(new TransactionServiceTwillRunnable(Constants.Service.TRANSACTION, "cConf.xml", "hConf.xml"), transactionSpec) .withLocalFiles() .add("cConf.xml", cConfFile.toURI()) .add("hConf.xml", hConfFile.toURI()) .apply(); } private TwillSpecification.Builder.RunnableSetter addStreamService(TwillSpecification.Builder.MoreRunnable builder) { int instances = instanceCountMap.get(Constants.Service.STREAMS); ResourceSpecification resourceSpec = ResourceSpecification.Builder.with() .setVirtualCores(cConf.getInt(Constants.Stream.CONTAINER_VIRTUAL_CORES)) .setMemory(cConf.getInt(Constants.Stream.CONTAINER_MEMORY_MB), ResourceSpecification.SizeUnit.MEGA) .setInstances(instances) .build(); return builder.add(new StreamHandlerRunnable(Constants.Service.STREAMS, "cConf.xml", "hConf.xml"), resourceSpec) .withLocalFiles() .add("cConf.xml", cConfFile.toURI()) .add("hConf.xml", hConfFile.toURI()) .apply(); } private TwillSpecification.Builder.RunnableSetter addDatasetOpExecutor( TwillSpecification.Builder.MoreRunnable builder) { int instances = instanceCountMap.get(Constants.Service.DATASET_EXECUTOR); ResourceSpecification resourceSpec = ResourceSpecification.Builder.with() .setVirtualCores(cConf.getInt(Constants.Dataset.Executor.CONTAINER_VIRTUAL_CORES)) .setMemory(cConf.getInt(Constants.Dataset.Executor.CONTAINER_MEMORY_MB), ResourceSpecification.SizeUnit.MEGA) .setInstances(instances) .build(); return builder.add( new DatasetOpExecutorServerTwillRunnable(Constants.Service.DATASET_EXECUTOR, "cConf.xml", "hConf.xml"), resourceSpec) .withLocalFiles() .add("cConf.xml", cConfFile.toURI()) .add("hConf.xml", hConfFile.toURI()) .apply(); } private TwillSpecification.Builder.RunnableSetter addExploreService(TwillSpecification.Builder.MoreRunnable builder) { int instances = instanceCountMap.get(Constants.Service.EXPLORE_HTTP_USER_SERVICE); ResourceSpecification resourceSpec = ResourceSpecification.Builder.with() .setVirtualCores(cConf.getInt(Constants.Explore.CONTAINER_VIRTUAL_CORES)) .setMemory(cConf.getInt(Constants.Explore.CONTAINER_MEMORY_MB), ResourceSpecification.SizeUnit.MEGA) .setInstances(instances) .build(); TwillSpecification.Builder.MoreFile twillSpecs = builder.add( new ExploreCustomClassLoaderTwillRunnable( new ExploreServiceTwillRunnable(Constants.Service.EXPLORE_HTTP_USER_SERVICE, "cConf.xml", "hConf.xml") .configure()), resourceSpec) .withLocalFiles() .add("cConf.xml", cConfFile.toURI()) .add("hConf.xml", hConfFile.toURI()); try { // Ship jars needed by Hive to the container File tempDir = DirUtils.createTempDir(new File(cConf.get(Constants.CFG_LOCAL_DATA_DIR), cConf.get(Constants.AppFabric.TEMP_DIR)).getAbsoluteFile()); Set<File> jars = ExploreServiceUtils.traceExploreDependencies(tempDir); for (File jarFile : jars) { LOG.debug("Adding jar {} for explore.service", jarFile.getAbsolutePath()); twillSpecs = twillSpecs.add(jarFile.getName(), jarFile); } } catch (Exception e) { throw new RuntimeException("Unable to trace Explore dependencies", e); } return twillSpecs.apply(); } }