YARN-6160. Create an agent-less docker-less provider in the native services framework. Contributed by Billie Rinaldi

This commit is contained in:
Jian He 2017-05-17 09:58:32 -07:00
parent a22256bd40
commit 9085cd5c6e
28 changed files with 664 additions and 538 deletions

View File

@ -133,7 +133,6 @@
import org.apache.slider.core.zk.ZKIntegration; import org.apache.slider.core.zk.ZKIntegration;
import org.apache.slider.providers.AbstractClientProvider; import org.apache.slider.providers.AbstractClientProvider;
import org.apache.slider.providers.ProviderUtils; import org.apache.slider.providers.ProviderUtils;
import org.apache.slider.providers.SliderProviderFactory;
import org.apache.slider.server.appmaster.SliderAppMaster; import org.apache.slider.server.appmaster.SliderAppMaster;
import org.apache.slider.server.appmaster.rpc.RpcBinder; import org.apache.slider.server.appmaster.rpc.RpcBinder;
import org.apache.slider.server.services.utility.AbstractSliderLaunchedService; import org.apache.slider.server.services.utility.AbstractSliderLaunchedService;
@ -257,8 +256,6 @@ public Configuration bindArgs(Configuration config, String... args) throws Excep
config = super.bindArgs(config, args); config = super.bindArgs(config, args);
serviceArgs = new ClientArgs(args); serviceArgs = new ClientArgs(args);
serviceArgs.parse(); serviceArgs.parse();
// add the slider XML config
ConfigHelper.injectSliderXMLResource();
// yarn-ify // yarn-ify
YarnConfiguration yarnConfiguration = new YarnConfiguration(config); YarnConfiguration yarnConfiguration = new YarnConfiguration(config);
return patchConfiguration(yarnConfiguration); return patchConfiguration(yarnConfiguration);
@ -622,14 +619,6 @@ public int actionAmSuicide(String clustername,
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@Override
public AbstractClientProvider createClientProvider(String provider)
throws SliderException {
SliderProviderFactory factory =
SliderProviderFactory.createSliderProviderFactory(provider);
return factory.createClientProvider();
}
private Application getApplicationFromArgs(String clusterName, private Application getApplicationFromArgs(String clusterName,
AbstractClusterBuildingActionArgs args) throws IOException { AbstractClusterBuildingActionArgs args) throws IOException {
File file = args.getAppDef(); File file = args.getAppDef();
@ -893,7 +882,7 @@ private Path checkAppNotExistOnHdfs(Application application)
private void persistApp(Path appDir, Application application) private void persistApp(Path appDir, Application application)
throws IOException, SliderException { throws IOException, SliderException {
FsPermission appDirPermission = new FsPermission("777"); FsPermission appDirPermission = new FsPermission("750");
sliderFileSystem.createWithPermissions(appDir, appDirPermission); sliderFileSystem.createWithPermissions(appDir, appDirPermission);
Path appJson = new Path(appDir, application.getName() + ".json"); Path appJson = new Path(appDir, application.getName() + ".json");
jsonSerDeser jsonSerDeser
@ -1190,17 +1179,18 @@ private int doClientInstall(ActionClientArgs clientInfo)
} }
} }
// TODO handle client install
// Only INSTALL is supported // Only INSTALL is supported
AbstractClientProvider // ClientProvider
provider = createClientProvider(SliderProviderFactory.DEFAULT_CLUSTER_TYPE); // provider = createClientProvider(SliderProviderFactory.DEFAULT_CLUSTER_TYPE);
provider.processClientOperation(sliderFileSystem, // provider.processClientOperation(sliderFileSystem,
getRegistryOperations(), // getRegistryOperations(),
getConfig(), // getConfig(),
"INSTALL", // "INSTALL",
clientInfo.installLocation, // clientInfo.installLocation,
pkgFile, // pkgFile,
config, // config,
clientInfo.name); // clientInfo.name);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -42,7 +42,6 @@
import org.apache.slider.common.params.ActionUpgradeArgs; import org.apache.slider.common.params.ActionUpgradeArgs;
import org.apache.slider.core.exceptions.BadCommandArgumentsException; import org.apache.slider.core.exceptions.BadCommandArgumentsException;
import org.apache.slider.core.exceptions.SliderException; import org.apache.slider.core.exceptions.SliderException;
import org.apache.slider.providers.AbstractClientProvider;
import java.io.IOException; import java.io.IOException;
@ -62,15 +61,6 @@ public interface SliderClientAPI extends Service {
int actionAmSuicide(String clustername, int actionAmSuicide(String clustername,
ActionAMSuicideArgs args) throws YarnException, IOException; ActionAMSuicideArgs args) throws YarnException, IOException;
/**
* Get the provider for this cluster
* @param provider the name of the provider
* @return the provider instance
* @throws SliderException problems building the provider
*/
AbstractClientProvider createClientProvider(String provider)
throws SliderException;
/** /**
* Manage keytabs leveraged by slider * Manage keytabs leveraged by slider
* *

View File

@ -18,8 +18,6 @@
package org.apache.slider.common; package org.apache.slider.common;
import org.apache.hadoop.yarn.api.ApplicationConstants;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -158,12 +156,7 @@ public interface SliderKeys extends SliderXmlConfKeys {
*/ */
String HISTORY_FILENAME_GLOB_PATTERN = HISTORY_FILENAME_PREFIX +"*."+ String HISTORY_FILENAME_GLOB_PATTERN = HISTORY_FILENAME_PREFIX +"*."+
HISTORY_FILENAME_SUFFIX; HISTORY_FILENAME_SUFFIX;
/**
* XML resource listing the standard Slider providers
* {@value}
*/
String SLIDER_XML = "org/apache/slider/slider.xml";
String CLUSTER_DIRECTORY = "cluster"; String CLUSTER_DIRECTORY = "cluster";
String PACKAGE_DIRECTORY = "package"; String PACKAGE_DIRECTORY = "package";
@ -311,5 +304,12 @@ public interface SliderKeys extends SliderXmlConfKeys {
String APP_RESOURCES = "application.resources"; String APP_RESOURCES = "application.resources";
String APP_RESOURCES_DIR = "app/resources"; String APP_RESOURCES_DIR = "app/resources";
String APP_PACKAGES_DIR = "app/packages"; String APP_INSTALL_DIR = "app/install";
String OUT_FILE = "stdout.txt";
String ERR_FILE = "stderr.txt";
String QUICK_LINKS = "quicklinks";
String KEY_CONTAINER_LAUNCH_DELAY = "container.launch.delay.sec";
} }

View File

@ -50,7 +50,6 @@
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* Methods to aid in config, both in the Configuration class and * Methods to aid in config, both in the Configuration class and
@ -62,11 +61,6 @@
public class ConfigHelper { public class ConfigHelper {
private static final Logger log = LoggerFactory.getLogger(ConfigHelper.class); private static final Logger log = LoggerFactory.getLogger(ConfigHelper.class);
private static AtomicBoolean sliderResourceInjected =
new AtomicBoolean(false);
private static AtomicBoolean sliderResourceInjectionAttempted =
new AtomicBoolean(false);
/** /**
* Dump the (sorted) configuration * Dump the (sorted) configuration
* @param conf config * @param conf config
@ -614,37 +608,4 @@ public static Configuration resolveConfiguration(
public static void registerDeprecatedConfigItems() { public static void registerDeprecatedConfigItems() {
} }
/**
* Load a configuration with the {@link SliderKeys#SLIDER_XML} resource
* included
* @return a configuration instance
*/
public static Configuration loadSliderConfiguration() {
Configuration conf = new Configuration();
conf.addResource(SliderKeys.SLIDER_XML);
return conf;
}
/**
* Inject the {@link SliderKeys#SLIDER_XML} resource
* into the configuration resources <i>of all configurations</i>.
* <p>
* This operation is idempotent.
* <p>
* If the resource is not on the classpath, downgrades, rather than
* fails.
* @return true if the resource was found and loaded.
*/
public static synchronized boolean injectSliderXMLResource() {
if (sliderResourceInjectionAttempted.getAndSet(true)) {
return sliderResourceInjected.get();
}
URL resourceUrl = getResourceUrl(SliderKeys.SLIDER_XML);
if (resourceUrl != null) {
Configuration.addDefaultResource(SliderKeys.SLIDER_XML);
sliderResourceInjected.set(true);
}
return sliderResourceInjected.get();
}
} }

View File

@ -19,32 +19,26 @@
package org.apache.slider.providers; package org.apache.slider.providers;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured; import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.registry.client.api.RegistryOperations; import org.apache.hadoop.registry.client.api.RegistryOperations;
import org.apache.slider.api.resource.Artifact;
import org.apache.slider.api.resource.ConfigFile;
import org.apache.slider.common.tools.SliderFileSystem; import org.apache.slider.common.tools.SliderFileSystem;
import org.apache.slider.common.tools.SliderUtils; import org.apache.slider.common.tools.SliderUtils;
import org.apache.slider.core.exceptions.SliderException; import org.apache.slider.core.exceptions.SliderException;
import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
public abstract class AbstractClientProvider extends Configured { public abstract class AbstractClientProvider {
private static final Logger log =
LoggerFactory.getLogger(AbstractClientProvider.class);
public AbstractClientProvider(Configuration conf) { public AbstractClientProvider() {
super(conf);
} }
public abstract String getName();
public abstract List<ProviderRole> getRoles();
/** /**
* Generates a fixed format of application tags given one or more of * Generates a fixed format of application tags given one or more of
* application name, version and description. This allows subsequent query for * application name, version and description. This allows subsequent query for
@ -70,7 +64,29 @@ public static final Set<String> createApplicationTags(String appName,
} }
/** /**
* Process client operations for applications such as install, configure * Validate the artifact.
* @param artifact
*/
public abstract void validateArtifact(Artifact artifact, FileSystem
fileSystem) throws IOException;
protected abstract void validateConfigFile(ConfigFile configFile, FileSystem
fileSystem) throws IOException;
/**
* Validate the config files.
* @param configFiles config file list
* @param fileSystem file system
*/
public void validateConfigFiles(List<ConfigFile> configFiles, FileSystem
fileSystem) throws IOException {
for (ConfigFile configFile : configFiles) {
validateConfigFile(configFile, fileSystem);
}
}
/**
* Process client operations for applications such as install, configure.
* @param fileSystem * @param fileSystem
* @param registryOperations * @param registryOperations
* @param configuration * @param configuration

View File

@ -0,0 +1,169 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.slider.providers;
import org.apache.hadoop.service.AbstractService;
import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.yarn.api.ApplicationConstants;
import org.apache.hadoop.yarn.api.records.Container;
import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ContainerStatus;
import org.apache.slider.api.resource.Application;
import org.apache.slider.api.resource.Component;
import org.apache.slider.api.resource.ContainerState;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.common.tools.SliderFileSystem;
import org.apache.slider.common.tools.SliderUtils;
import org.apache.slider.core.exceptions.SliderException;
import org.apache.slider.core.launch.CommandLineBuilder;
import org.apache.slider.core.launch.ContainerLauncher;
import org.apache.slider.core.registry.docstore.PublishedConfiguration;
import org.apache.slider.server.appmaster.state.RoleInstance;
import org.apache.slider.server.appmaster.state.StateAccessForProviders;
import org.apache.slider.server.appmaster.timelineservice.ServiceTimelinePublisher;
import org.apache.slider.server.services.yarnregistry.YarnRegistryViewForProviders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import static org.apache.slider.util.ServiceApiUtil.$;
public abstract class AbstractProviderService extends AbstractService
implements ProviderService, SliderKeys {
protected static final Logger log =
LoggerFactory.getLogger(AbstractProviderService.class);
private static final ProviderUtils providerUtils = new ProviderUtils(log);
protected StateAccessForProviders amState;
protected YarnRegistryViewForProviders yarnRegistry;
private ServiceTimelinePublisher serviceTimelinePublisher;
protected AbstractProviderService(String name) {
super(name);
}
public abstract void processArtifact(ContainerLauncher launcher, Component
component, SliderFileSystem fileSystem) throws IOException;
@Override
public void setAMState(StateAccessForProviders stateAccessor) {
this.amState = stateAccessor;
}
@Override
public void bindToYarnRegistry(YarnRegistryViewForProviders yarnRegistry) {
this.yarnRegistry = yarnRegistry;
}
public void buildContainerLaunchContext(ContainerLauncher launcher,
Application application, Container container, ProviderRole providerRole,
SliderFileSystem fileSystem, RoleInstance roleInstance)
throws IOException, SliderException {
Component component = providerRole.component;
processArtifact(launcher, component, fileSystem);
// Generate tokens (key-value pair) for config substitution.
// Get pre-defined tokens
Map<String, String> globalTokens = amState.getGlobalSubstitutionTokens();
Map<String, String> tokensForSubstitution = providerUtils
.initCompTokensForSubstitute(roleInstance);
tokensForSubstitution.putAll(globalTokens);
// Set the environment variables in launcher
launcher.putEnv(SliderUtils
.buildEnvMap(component.getConfiguration(), tokensForSubstitution));
launcher.setEnv("WORK_DIR", ApplicationConstants.Environment.PWD.$());
launcher.setEnv("LOG_DIR", ApplicationConstants.LOG_DIR_EXPANSION_VAR);
if (System.getenv(HADOOP_USER_NAME) != null) {
launcher.setEnv(HADOOP_USER_NAME, System.getenv(HADOOP_USER_NAME));
}
launcher.setEnv("LANG", "en_US.UTF-8");
launcher.setEnv("LC_ALL", "en_US.UTF-8");
launcher.setEnv("LANGUAGE", "en_US.UTF-8");
for (Entry<String, String> entry : launcher.getEnv().entrySet()) {
tokensForSubstitution.put($(entry.getKey()), entry.getValue());
}
providerUtils.addComponentHostTokens(tokensForSubstitution, amState);
// create config file on hdfs and add local resource
providerUtils.createConfigFileAndAddLocalResource(launcher, fileSystem,
component, tokensForSubstitution, roleInstance, amState);
// substitute launch command
String launchCommand = ProviderUtils
.substituteStrWithTokens(component.getLaunchCommand(),
tokensForSubstitution);
CommandLineBuilder operation = new CommandLineBuilder();
operation.add(launchCommand);
operation.addOutAndErrFiles(OUT_FILE, ERR_FILE);
launcher.addCommand(operation.build());
// publish exports
providerUtils
.substituteMapWithTokens(application.getQuicklinks(), tokensForSubstitution);
PublishedConfiguration pubconf = new PublishedConfiguration(QUICK_LINKS,
application.getQuicklinks().entrySet());
amState.getPublishedSliderConfigurations().put(QUICK_LINKS, pubconf);
if (serviceTimelinePublisher != null) {
serviceTimelinePublisher.serviceAttemptUpdated(application);
}
}
public boolean processContainerStatus(ContainerId containerId,
ContainerStatus status) {
log.debug("Handling container status: {}", status);
if (SliderUtils.isEmpty(status.getIPs()) ||
SliderUtils.isUnset(status.getHost())) {
return true;
}
RoleInstance instance = amState.getOwnedContainer(containerId);
if (instance == null) {
// container is completed?
return false;
}
try {
providerUtils.updateServiceRecord(amState, yarnRegistry,
containerId.toString(), instance.role, status.getIPs(), status.getHost());
} catch (IOException e) {
// could not write service record to ZK, log and retry
log.warn("Error updating container {} service record in registry, " +
"retrying", containerId, e);
return true;
}
// TODO publish ip and host
org.apache.slider.api.resource.Container container =
instance.providerRole.component.getContainer(containerId.toString());
if (container != null) {
container.setIp(StringUtils.join(",", status.getIPs()));
container.setHostname(status.getHost());
container.setState(ContainerState.READY);
} else {
log.warn(containerId + " not found in Application!");
}
return false;
}
@Override
public void setServiceTimelinePublisher(ServiceTimelinePublisher publisher) {
this.serviceTimelinePublisher = publisher;
}
}

View File

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.slider.providers;
import org.apache.hadoop.fs.FileSystem;
import org.apache.slider.api.resource.Artifact;
import org.apache.slider.api.resource.ConfigFile;
import java.io.IOException;
import java.nio.file.Paths;
public class DefaultClientProvider extends AbstractClientProvider {
public DefaultClientProvider() {
}
@Override
public void validateArtifact(Artifact artifact, FileSystem fileSystem) {
}
@Override
protected void validateConfigFile(ConfigFile configFile, FileSystem
fileSystem) throws IOException {
// validate dest_file is not absolute
if (Paths.get(configFile.getDestFile()).isAbsolute()) {
throw new IllegalArgumentException(
"Dest_file must not be absolute path: " + configFile.getDestFile());
}
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.slider.providers;
public final class DefaultProviderFactory extends SliderProviderFactory {
private static final SliderProviderFactory FACTORY = new
DefaultProviderFactory();
private DefaultProviderFactory() {}
private static class Client {
static final AbstractClientProvider PROVIDER = new DefaultClientProvider();
}
private static class Server {
static final ProviderService PROVIDER = new DefaultProviderService();
}
@Override
public AbstractClientProvider createClientProvider() {
return Client.PROVIDER;
}
@Override
public ProviderService createServerProvider() {
return Server.PROVIDER;
}
public static SliderProviderFactory getInstance() {
return FACTORY;
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.slider.providers;
import org.apache.slider.api.resource.Component;
import org.apache.slider.common.tools.SliderFileSystem;
import org.apache.slider.core.launch.ContainerLauncher;
import org.apache.slider.providers.AbstractProviderService;
import java.io.IOException;
public class DefaultProviderService extends AbstractProviderService {
protected DefaultProviderService() {
super(DefaultProviderService.class.getSimpleName());
}
@Override
public void processArtifact(ContainerLauncher launcher, Component
component, SliderFileSystem fileSystem) throws IOException {
}
}

View File

@ -18,93 +18,60 @@
package org.apache.slider.providers; package org.apache.slider.providers;
import org.apache.hadoop.conf.Configuration; import org.apache.slider.api.resource.Artifact;
import org.apache.hadoop.conf.Configured;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.common.SliderXmlConfKeys;
import org.apache.slider.core.exceptions.BadClusterStateException;
import org.apache.slider.core.exceptions.SliderException; import org.apache.slider.core.exceptions.SliderException;
import org.apache.slider.providers.agent.AgentKeys; import org.apache.slider.providers.docker.DockerProviderFactory;
import org.apache.slider.providers.tarball.TarballProviderFactory;
import org.apache.slider.util.RestApiErrorMessages;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* Base class for factories * Base class for factories.
*/ */
public abstract class SliderProviderFactory extends Configured { public abstract class SliderProviderFactory {
public static final String DEFAULT_CLUSTER_TYPE = AgentKeys.PROVIDER_AGENT;
protected static final Logger log = protected static final Logger log =
LoggerFactory.getLogger(SliderProviderFactory.class); LoggerFactory.getLogger(SliderProviderFactory.class);
public static final String PROVIDER_NOT_FOUND =
"Unable to find provider of application type %s";
public SliderProviderFactory(Configuration conf) { protected SliderProviderFactory() {}
super(conf);
}
protected SliderProviderFactory() {
}
public abstract AbstractClientProvider createClientProvider(); public abstract AbstractClientProvider createClientProvider();
public abstract ProviderService createServerProvider(); public abstract ProviderService createServerProvider();
public static synchronized ProviderService getProviderService(Artifact
artifact) {
return createSliderProviderFactory(artifact).createServerProvider();
}
public static synchronized AbstractClientProvider getClientProvider(Artifact
artifact) {
return createSliderProviderFactory(artifact).createClientProvider();
}
/** /**
* Create a provider for a specific application * Create a provider for a specific application
* @param application app * @param artifact artifact
* @return app instance * @return provider factory
* @throws SliderException on any instantiation problem * @throws SliderException on any instantiation problem
*/ */
public static SliderProviderFactory createSliderProviderFactory(String application) throws public static synchronized SliderProviderFactory createSliderProviderFactory(
SliderException { Artifact artifact) {
Configuration conf = loadSliderConfiguration(); if (artifact == null || artifact.getType() == null) {
if (application == null) { log.info("Loading service provider type default");
application = DEFAULT_CLUSTER_TYPE; return DefaultProviderFactory.getInstance();
} }
String providerKey = log.info("Loading service provider type {}", artifact.getType());
String.format(SliderXmlConfKeys.KEY_PROVIDER, application); switch (artifact.getType()) {
if (application.contains(".")) { // TODO add handling for custom types?
log.debug("Treating {} as a classname", application); // TODO handle application
String name = "classname.key"; case DOCKER:
conf.set(name, application); return DockerProviderFactory.getInstance();
providerKey = name; case TARBALL:
return TarballProviderFactory.getInstance();
default:
throw new IllegalArgumentException(
RestApiErrorMessages.ERROR_ARTIFACT_INVALID);
} }
Class<? extends SliderProviderFactory> providerClass;
try {
providerClass = conf.getClass(providerKey, null, SliderProviderFactory.class);
} catch (RuntimeException e) {
throw new BadClusterStateException(e, "Failed to load provider %s: %s", application, e);
}
if (providerClass == null) {
throw new BadClusterStateException(PROVIDER_NOT_FOUND, application);
}
Exception ex;
try {
SliderProviderFactory providerFactory = providerClass.newInstance();
providerFactory.setConf(conf);
return providerFactory;
} catch (Exception e) {
ex = e;
}
//by here the operation failed and ex is set to the value
throw new BadClusterStateException(ex,
"Failed to create an instance of %s : %s",
providerClass,
ex);
}
/**
* Load a configuration with the {@link SliderKeys#SLIDER_XML} resource
* included
* @return a configuration instance
*/
public static Configuration loadSliderConfiguration() {
Configuration conf = new Configuration();
conf.addResource(SliderKeys.SLIDER_XML);
return conf;
} }
} }

View File

@ -1,102 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.slider.providers.agent;
/*
*/
public interface AgentKeys {
String AGENT_TAR = "slider-agent.tar.gz";
String PROVIDER_AGENT = "agent";
String ROLE_NODE = "echo";
/**
* Template stored in the slider classpath -to use if there is
* no site-specific template
* {@value}
*/
String CONF_RESOURCE = "org/apache/slider/providers/agent/conf/";
/* URL to talk back to Agent Controller*/
String CONTROLLER_URL = "agent.controller.url";
/**
* The location of pre-installed agent path.
* This can be also be dynamically computed based on Yarn installation of agent.
*/
String PACKAGE_PATH = "agent.package.root";
/**
* The location of the script implementing the command.
*/
String SCRIPT_PATH = "agent.script";
/**
* Execution home for the agent.
*/
String APP_HOME = "app.home";
String APP_ROOT = "site.global.app_root";
String APP_CLIENT_ROOT = "client_root";
/**
* Runas user of the application
*/
String RUNAS_USER = "site.global.app_user";
/**
* Name of the service.
*/
String SERVICE_NAME = "app.name";
String ARG_LABEL = "--label";
String ARG_HOST = "--host";
String ARG_PORT = "--port";
String ARG_SECURED_PORT = "--secured_port";
String ARG_ZOOKEEPER_QUORUM = "--zk-quorum";
String ARG_ZOOKEEPER_REGISTRY_PATH = "--zk-reg-path";
String ARG_DEBUG = "--debug";
String AGENT_MAIN_SCRIPT_ROOT = "./infra/agent/slider-agent/";
String AGENT_JINJA2_ROOT = "./infra/agent/slider-agent/jinja2";
String AGENT_MAIN_SCRIPT = "agent/main.py";
String APP_DEF = "application.def";
String APP_DEF_ORIGINAL = "application.def.original";
String ADDON_PREFIX = "application.addon.";
String ADDONS = "application.addons";
String AGENT_VERSION = "agent.version";
String AGENT_CONF = "agent.conf";
String ADDON_FOR_ALL_COMPONENTS = "ALL";
String AGENT_INSTALL_DIR = "infra/agent";
String APP_DEFINITION_DIR = "app/definition";
String ADDON_DEFINITION_DIR = "addon/definition";
String AGENT_CONFIG_FILE = "infra/conf/agent.ini";
String AGENT_VERSION_FILE = "infra/version";
String PACKAGE_LIST = "package_list";
String WAIT_HEARTBEAT = "wait.heartbeat";
String PYTHON_EXE = "python";
String CREATE_DEF_ZK_NODE = "create.default.zookeeper.node";
String HEARTBEAT_MONITOR_INTERVAL = "heartbeat.monitor.interval";
String AGENT_INSTANCE_DEBUG_DATA = "agent.instance.debug.data";
String AGENT_OUT_FILE = "slider-agent.out";
String KEY_AGENT_TWO_WAY_SSL_ENABLED = "ssl.server.client.auth";
String INFRA_RUN_SECURITY_DIR = "infra/run/security/";
String CERT_FILE_LOCALIZATION_PATH = INFRA_RUN_SECURITY_DIR + "ca.crt";
String KEY_CONTAINER_LAUNCH_DELAY = "container.launch.delay.sec";
String TEST_RELAX_VERIFICATION = "test.relax.validation";
String DEFAULT_METAINFO_MAP_KEY = "DEFAULT_KEY";
}

View File

@ -17,37 +17,37 @@
*/ */
package org.apache.slider.providers.docker; package org.apache.slider.providers.docker;
import org.apache.hadoop.conf.Configuration; import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.fs.FileSystem;
import org.apache.slider.api.resource.Artifact;
import org.apache.slider.api.resource.ConfigFile;
import org.apache.slider.common.SliderKeys; import org.apache.slider.common.SliderKeys;
import org.apache.slider.providers.AbstractClientProvider; import org.apache.slider.providers.AbstractClientProvider;
import org.apache.slider.providers.ProviderRole; import org.apache.slider.util.RestApiErrorMessages;
import org.apache.slider.providers.ProviderUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections; import java.io.IOException;
import java.util.List;
public class DockerClientProvider extends AbstractClientProvider public class DockerClientProvider extends AbstractClientProvider
implements SliderKeys { implements SliderKeys {
protected static final Logger log = public DockerClientProvider() {
LoggerFactory.getLogger(DockerClientProvider.class); super();
private static final ProviderUtils providerUtils = new ProviderUtils(log);
protected static final String NAME = "docker";
public DockerClientProvider(Configuration conf) {
super(conf);
} }
@Override @Override
public String getName() { public void validateArtifact(Artifact artifact, FileSystem fileSystem) {
return NAME; if (artifact == null) {
throw new IllegalArgumentException(
RestApiErrorMessages.ERROR_ARTIFACT_INVALID);
}
if (StringUtils.isEmpty(artifact.getId())) {
throw new IllegalArgumentException(
RestApiErrorMessages.ERROR_ARTIFACT_ID_INVALID);
}
} }
@Override @Override
public List<ProviderRole> getRoles() { protected void validateConfigFile(ConfigFile configFile, FileSystem
return Collections.emptyList(); fileSystem) throws IOException {
} }
} }

View File

@ -27,7 +27,4 @@ public interface DockerKeys {
String DEFAULT_DOCKER_NETWORK = "bridge"; String DEFAULT_DOCKER_NETWORK = "bridge";
Boolean DEFAULT_DOCKER_USE_PRIVILEGED = false; Boolean DEFAULT_DOCKER_USE_PRIVILEGED = false;
String OUT_FILE = "stdout.txt";
String ERR_FILE = "stderr.txt";
} }

View File

@ -17,27 +17,36 @@
*/ */
package org.apache.slider.providers.docker; package org.apache.slider.providers.docker;
import org.apache.hadoop.conf.Configuration;
import org.apache.slider.providers.AbstractClientProvider; import org.apache.slider.providers.AbstractClientProvider;
import org.apache.slider.providers.ProviderService; import org.apache.slider.providers.ProviderService;
import org.apache.slider.providers.SliderProviderFactory; import org.apache.slider.providers.SliderProviderFactory;
public class DockerProviderFactory extends SliderProviderFactory { public class DockerProviderFactory extends SliderProviderFactory {
private static final SliderProviderFactory FACTORY = new
DockerProviderFactory();
public DockerProviderFactory() { private DockerProviderFactory() {
} }
public DockerProviderFactory(Configuration conf) { private static class Client {
super(conf); static final AbstractClientProvider PROVIDER = new DockerClientProvider();
}
private static class Server {
static final ProviderService PROVIDER = new DockerProviderService();
} }
@Override @Override
public AbstractClientProvider createClientProvider() { public AbstractClientProvider createClientProvider() {
return new DockerClientProvider(getConf()); return Client.PROVIDER;
} }
@Override @Override
public ProviderService createServerProvider() { public ProviderService createServerProvider() {
return new DockerProviderService(); return Server.PROVIDER;
}
public static SliderProviderFactory getInstance() {
return FACTORY;
} }
} }

View File

@ -17,159 +17,31 @@
*/ */
package org.apache.slider.providers.docker; package org.apache.slider.providers.docker;
import org.apache.hadoop.service.AbstractService;
import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.yarn.api.ApplicationConstants;
import org.apache.hadoop.yarn.api.records.Container;
import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ContainerStatus;
import org.apache.slider.api.resource.Application;
import org.apache.slider.api.resource.Component; import org.apache.slider.api.resource.Component;
import org.apache.slider.api.resource.ContainerState;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.common.tools.SliderFileSystem; import org.apache.slider.common.tools.SliderFileSystem;
import org.apache.slider.common.tools.SliderUtils;
import org.apache.slider.core.exceptions.SliderException;
import org.apache.slider.core.launch.CommandLineBuilder;
import org.apache.slider.core.launch.ContainerLauncher; import org.apache.slider.core.launch.ContainerLauncher;
import org.apache.slider.core.registry.docstore.PublishedConfiguration; import org.apache.slider.providers.AbstractProviderService;
import org.apache.slider.providers.ProviderRole;
import org.apache.slider.providers.ProviderService;
import org.apache.slider.providers.ProviderUtils;
import org.apache.slider.server.appmaster.state.RoleInstance;
import org.apache.slider.server.appmaster.state.StateAccessForProviders;
import org.apache.slider.server.appmaster.timelineservice.ServiceTimelinePublisher;
import org.apache.slider.server.services.yarnregistry.YarnRegistryViewForProviders;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import static org.apache.slider.util.ServiceApiUtil.$; public class DockerProviderService extends AbstractProviderService
implements DockerKeys {
public class DockerProviderService extends AbstractService
implements ProviderService, DockerKeys, SliderKeys {
protected static final Logger log = protected static final Logger log =
LoggerFactory.getLogger(DockerProviderService.class); LoggerFactory.getLogger(DockerProviderService.class);
private static final ProviderUtils providerUtils = new ProviderUtils(log);
private static final String QUICK_LINKS = "quicklinks";
protected StateAccessForProviders amState;
protected YarnRegistryViewForProviders yarnRegistry;
private ServiceTimelinePublisher serviceTimelinePublisher;
protected DockerProviderService() { protected DockerProviderService() {
super("DockerProviderService"); super(DockerProviderService.class.getSimpleName());
} }
@Override public void processArtifact(ContainerLauncher launcher, Component
public void setAMState(StateAccessForProviders stateAccessor) { component, SliderFileSystem fileSystem) throws IOException {
this.amState = stateAccessor;
}
@Override
public void bindToYarnRegistry(YarnRegistryViewForProviders yarnRegistry) {
this.yarnRegistry = yarnRegistry;
}
public void buildContainerLaunchContext(ContainerLauncher launcher,
Application application, Container container, ProviderRole providerRole,
SliderFileSystem fileSystem, RoleInstance roleInstance)
throws IOException, SliderException {
Component component = providerRole.component;
launcher.setYarnDockerMode(true); launcher.setYarnDockerMode(true);
launcher.setDockerImage(component.getArtifact().getId()); launcher.setDockerImage(component.getArtifact().getId());
launcher.setDockerNetwork(component.getConfiguration() launcher.setDockerNetwork(component.getConfiguration()
.getProperty(DOCKER_NETWORK, DEFAULT_DOCKER_NETWORK)); .getProperty(DOCKER_NETWORK, DEFAULT_DOCKER_NETWORK));
launcher.setRunPrivilegedContainer(component.getRunPrivilegedContainer()); launcher.setRunPrivilegedContainer(component.getRunPrivilegedContainer());
// Generate tokens (key-value pair) for config substitution.
// Get pre-defined tokens
Map<String, String> globalTokens = amState.getGlobalSubstitutionTokens();
Map<String, String> tokensForSubstitution = providerUtils
.initCompTokensForSubstitute(roleInstance);
tokensForSubstitution.putAll(globalTokens);
// Set the environment variables in launcher
launcher.putEnv(SliderUtils
.buildEnvMap(component.getConfiguration(), tokensForSubstitution));
launcher.setEnv("WORK_DIR", ApplicationConstants.Environment.PWD.$());
launcher.setEnv("LOG_DIR", ApplicationConstants.LOG_DIR_EXPANSION_VAR);
if (System.getenv(HADOOP_USER_NAME) != null) {
launcher.setEnv(HADOOP_USER_NAME, System.getenv(HADOOP_USER_NAME));
}
launcher.setEnv("LANG", "en_US.UTF-8");
launcher.setEnv("LC_ALL", "en_US.UTF-8");
launcher.setEnv("LANGUAGE", "en_US.UTF-8");
for (Entry<String, String> entry : launcher.getEnv().entrySet()) {
tokensForSubstitution.put($(entry.getKey()), entry.getValue());
}
providerUtils.addComponentHostTokens(tokensForSubstitution, amState);
// create config file on hdfs and add local resource
providerUtils.createConfigFileAndAddLocalResource(launcher, fileSystem,
component, tokensForSubstitution, roleInstance, amState);
// substitute launch command
String launchCommand = ProviderUtils
.substituteStrWithTokens(component.getLaunchCommand(),
tokensForSubstitution);
CommandLineBuilder operation = new CommandLineBuilder();
operation.add(launchCommand);
operation.addOutAndErrFiles(OUT_FILE, ERR_FILE);
launcher.addCommand(operation.build());
// publish exports
providerUtils
.substituteMapWithTokens(application.getQuicklinks(), tokensForSubstitution);
PublishedConfiguration pubconf = new PublishedConfiguration(QUICK_LINKS,
application.getQuicklinks().entrySet());
amState.getPublishedSliderConfigurations().put(QUICK_LINKS, pubconf);
if (serviceTimelinePublisher != null) {
serviceTimelinePublisher.serviceAttemptUpdated(application);
}
}
public boolean processContainerStatus(ContainerId containerId,
ContainerStatus status) {
log.debug("Handling container status: {}", status);
if (SliderUtils.isEmpty(status.getIPs()) ||
SliderUtils.isUnset(status.getHost())) {
return true;
}
RoleInstance instance = amState.getOwnedContainer(containerId);
if (instance == null) {
// container is completed?
return false;
}
try {
providerUtils.updateServiceRecord(amState, yarnRegistry,
containerId.toString(), instance.role, status.getIPs(), status.getHost());
} catch (IOException e) {
// could not write service record to ZK, log and retry
log.warn("Error updating container {} service record in registry, " +
"retrying", containerId, e);
return true;
}
// TODO publish ip and host
org.apache.slider.api.resource.Container container =
instance.providerRole.component.getContainer(containerId.toString());
if (container != null) {
container.setIp(StringUtils.join(",", status.getIPs()));
container.setHostname(status.getHost());
container.setState(ContainerState.READY);
} else {
log.warn(containerId + " not found in Application!");
}
return false;
}
@Override
public void setServiceTimelinePublisher(ServiceTimelinePublisher publisher) {
this.serviceTimelinePublisher = publisher;
} }
} }

View File

@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.slider.providers.tarball;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.slider.api.resource.Artifact;
import org.apache.slider.api.resource.ConfigFile;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.providers.AbstractClientProvider;
import org.apache.slider.util.RestApiErrorMessages;
import java.io.IOException;
import java.nio.file.Paths;
public class TarballClientProvider extends AbstractClientProvider
implements SliderKeys {
public TarballClientProvider() {
}
@Override
public void validateArtifact(Artifact artifact, FileSystem fs)
throws IOException {
if (artifact == null) {
throw new IllegalArgumentException(
RestApiErrorMessages.ERROR_ARTIFACT_INVALID);
}
if (StringUtils.isEmpty(artifact.getId())) {
throw new IllegalArgumentException(
RestApiErrorMessages.ERROR_ARTIFACT_ID_INVALID);
}
Path p = new Path(artifact.getId());
if (!fs.exists(p)) {
throw new IllegalArgumentException( "Artifact tarball does not exist "
+ artifact.getId());
}
}
@Override
protected void validateConfigFile(ConfigFile configFile, FileSystem
fileSystem) throws IOException {
// validate dest_file is not absolute
if (Paths.get(configFile.getDestFile()).isAbsolute()) {
throw new IllegalArgumentException(
"Dest_file must not be absolute path: " + configFile.getDestFile());
}
}
}

View File

@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.slider.providers.tarball;
import org.apache.slider.providers.AbstractClientProvider;
import org.apache.slider.providers.ProviderService;
import org.apache.slider.providers.SliderProviderFactory;
public class TarballProviderFactory extends SliderProviderFactory {
private static final SliderProviderFactory FACTORY = new
TarballProviderFactory();
private TarballProviderFactory() {
}
private static class Client {
static final AbstractClientProvider PROVIDER = new TarballClientProvider();
}
private static class Server {
static final ProviderService PROVIDER = new TarballProviderService();
}
@Override
public AbstractClientProvider createClientProvider() {
return Client.PROVIDER;
}
@Override
public ProviderService createServerProvider() {
return Server.PROVIDER;
}
public static SliderProviderFactory getInstance() {
return FACTORY;
}
}

View File

@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.slider.providers.tarball;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.yarn.api.records.LocalResource;
import org.apache.hadoop.yarn.api.records.LocalResourceType;
import org.apache.slider.api.resource.Component;
import org.apache.slider.common.tools.SliderFileSystem;
import org.apache.slider.core.launch.ContainerLauncher;
import org.apache.slider.providers.AbstractProviderService;
import java.io.IOException;
public class TarballProviderService extends AbstractProviderService {
protected TarballProviderService() {
super(TarballProviderService.class.getSimpleName());
}
@Override
public void processArtifact(ContainerLauncher launcher, Component
component, SliderFileSystem fileSystem) throws IOException {
Path artifact = new Path(component.getArtifact().getId());
if (!fileSystem.isFile(artifact)) {
throw new IOException("Package doesn't exist as a resource: " +
artifact.toString());
}
log.info("Adding resource {}", artifact.toString());
LocalResourceType type = LocalResourceType.ARCHIVE;
LocalResource packageResource = fileSystem.createAmResource(
artifact, type);
launcher.addLocalResource(APP_INSTALL_DIR, packageResource);
}
}

View File

@ -27,7 +27,7 @@
import org.apache.slider.core.launch.ContainerLauncher; import org.apache.slider.core.launch.ContainerLauncher;
import org.apache.slider.providers.ProviderRole; import org.apache.slider.providers.ProviderRole;
import org.apache.slider.providers.ProviderService; import org.apache.slider.providers.ProviderService;
import org.apache.slider.providers.agent.AgentKeys; import org.apache.slider.providers.SliderProviderFactory;
import org.apache.slider.server.appmaster.actions.ActionStartContainer; import org.apache.slider.server.appmaster.actions.ActionStartContainer;
import org.apache.slider.server.appmaster.actions.QueueAccess; import org.apache.slider.server.appmaster.actions.QueueAccess;
import org.apache.slider.server.appmaster.state.ContainerAssignment; import org.apache.slider.server.appmaster.state.ContainerAssignment;
@ -43,6 +43,8 @@
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static org.apache.slider.common.SliderKeys.KEY_CONTAINER_LAUNCH_DELAY;
/** /**
* A service for launching containers * A service for launching containers
*/ */
@ -59,11 +61,6 @@ public class RoleLaunchService
*/ */
private final QueueAccess actionQueue; private final QueueAccess actionQueue;
/**
* Provider building up the command
*/
private final ProviderService provider;
/** /**
* Filesystem to use for the launch * Filesystem to use for the launch
*/ */
@ -75,16 +72,14 @@ public class RoleLaunchService
/** /**
* Construct an instance of the launcher * Construct an instance of the launcher
* @param queueAccess * @param queueAccess
* @param provider the provider
* @param fs filesystem * @param fs filesystem
* @param envVars environment variables * @param envVars environment variables
*/ */
public RoleLaunchService(QueueAccess queueAccess, ProviderService provider, public RoleLaunchService(QueueAccess queueAccess, SliderFileSystem fs,
SliderFileSystem fs, Map<String, String> envVars) { Map<String, String> envVars) {
super(ROLE_LAUNCH_SERVICE); super(ROLE_LAUNCH_SERVICE);
this.actionQueue = queueAccess; this.actionQueue = queueAccess;
this.fs = fs; this.fs = fs;
this.provider = provider;
this.envVars = envVars; this.envVars = envVars;
} }
@ -167,11 +162,13 @@ public void run() {
instance.roleId = role.id; instance.roleId = role.id;
instance.environment = envDescription; instance.environment = envDescription;
ProviderService provider = SliderProviderFactory.getProviderService(
role.component.getArtifact());
provider.buildContainerLaunchContext(containerLauncher, application, provider.buildContainerLaunchContext(containerLauncher, application,
container, role, fs, instance); container, role, fs, instance);
long delay = role.component.getConfiguration() long delay = role.component.getConfiguration()
.getPropertyLong(AgentKeys.KEY_CONTAINER_LAUNCH_DELAY, 0); .getPropertyLong(KEY_CONTAINER_LAUNCH_DELAY, 0);
long maxDelay = getConfig() long maxDelay = getConfig()
.getLong(YarnConfiguration.RM_CONTAINER_ALLOC_EXPIRY_INTERVAL_MS, .getLong(YarnConfiguration.RM_CONTAINER_ALLOC_EXPIRY_INTERVAL_MS,
YarnConfiguration.DEFAULT_RM_CONTAINER_ALLOC_EXPIRY_INTERVAL_MS); YarnConfiguration.DEFAULT_RM_CONTAINER_ALLOC_EXPIRY_INTERVAL_MS);

View File

@ -64,7 +64,6 @@
import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.client.api.AMRMClient; import org.apache.hadoop.yarn.client.api.AMRMClient;
import org.apache.hadoop.yarn.client.api.TimelineClient;
import org.apache.hadoop.yarn.client.api.TimelineV2Client; import org.apache.hadoop.yarn.client.api.TimelineV2Client;
import org.apache.hadoop.yarn.client.api.YarnClient; import org.apache.hadoop.yarn.client.api.YarnClient;
import org.apache.hadoop.yarn.client.api.async.AMRMClientAsync; import org.apache.hadoop.yarn.client.api.async.AMRMClientAsync;
@ -342,7 +341,7 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
* ProviderService of this cluster * ProviderService of this cluster
*/ */
@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
private ProviderService providerService; private List<ProviderService> providers = new ArrayList<>();
/** /**
* The YARN registry service * The YARN registry service
@ -523,8 +522,6 @@ private void startQueueProcessing() {
public Configuration bindArgs(Configuration config, String... args) throws Exception { public Configuration bindArgs(Configuration config, String... args) throws Exception {
// let the superclass process it // let the superclass process it
Configuration superConf = super.bindArgs(config, args); Configuration superConf = super.bindArgs(config, args);
// add the slider XML config
ConfigHelper.injectSliderXMLResource();
//yarn-ify //yarn-ify
YarnConfiguration yarnConfiguration = new YarnConfiguration( YarnConfiguration yarnConfiguration = new YarnConfiguration(
@ -603,12 +600,15 @@ private int createAndRunCluster(String appName) throws Throwable {
// obtain security state // obtain security state
// set the global security flag for the instance definition // set the global security flag for the instance definition
//get our provider // initialize our providers
SliderProviderFactory factory = for (Component component : application.getComponents()) {
SliderProviderFactory.createSliderProviderFactory("docker"); SliderProviderFactory factory = SliderProviderFactory
providerService = factory.createServerProvider(); .createSliderProviderFactory(component.getArtifact());
// init the provider BUT DO NOT START IT YET ProviderService providerService = factory.createServerProvider();
initAndAddService(providerService); // init the provider BUT DO NOT START IT YET
initAndAddService(providerService);
providers.add(providerService);
}
InetSocketAddress rmSchedulerAddress = SliderUtils.getRmSchedulerAddress(serviceConf); InetSocketAddress rmSchedulerAddress = SliderUtils.getRmSchedulerAddress(serviceConf);
log.info("RM is at {}", rmSchedulerAddress); log.info("RM is at {}", rmSchedulerAddress);
@ -667,7 +667,9 @@ private int createAndRunCluster(String appName) throws Throwable {
serviceTimelinePublisher.init(getConfig()); serviceTimelinePublisher.init(getConfig());
serviceTimelinePublisher.start(); serviceTimelinePublisher.start();
providerService.setServiceTimelinePublisher(serviceTimelinePublisher); for (ProviderService providerService : providers) {
providerService.setServiceTimelinePublisher(serviceTimelinePublisher);
}
appState.setServiceTimelinePublisher(serviceTimelinePublisher); appState.setServiceTimelinePublisher(serviceTimelinePublisher);
log.info("ServiceTimelinePublisher started."); log.info("ServiceTimelinePublisher started.");
} }
@ -707,7 +709,7 @@ private int createAndRunCluster(String appName) throws Throwable {
WebAppApiImpl webAppApi = WebAppApiImpl webAppApi =
new WebAppApiImpl( new WebAppApiImpl(
stateForProviders, stateForProviders,
providerService, registryOperations, registryOperations,
metricsAndMonitoring, metricsAndMonitoring,
actionQueues); actionQueues);
initAMFilterOptions(serviceConf); initAMFilterOptions(serviceConf);
@ -843,13 +845,14 @@ private int createAndRunCluster(String appName) throws Throwable {
//launcher service //launcher service
launchService = new RoleLaunchService(actionQueues, launchService = new RoleLaunchService(actionQueues,
providerService,
fs, envVars); fs, envVars);
deployChildService(launchService); deployChildService(launchService);
//Give the provider access to the state, and AM //Give the provider access to the state, and AM
providerService.setAMState(stateForProviders); for (ProviderService providerService : providers) {
providerService.setAMState(stateForProviders);
}
// chaos monkey // chaos monkey
maybeStartMonkey(); maybeStartMonkey();
@ -1119,7 +1122,9 @@ public void registerServiceInstance(String instanceName,
SliderKeys.APP_TYPE, SliderKeys.APP_TYPE,
instanceName, instanceName,
appAttemptID); appAttemptID);
providerService.bindToYarnRegistry(yarnRegistryOperations); for (ProviderService providerService : providers) {
providerService.bindToYarnRegistry(yarnRegistryOperations);
}
// Yarn registry // Yarn registry
ServiceRecord serviceRecord = new ServiceRecord(); ServiceRecord serviceRecord = new ServiceRecord();
@ -1859,7 +1864,9 @@ public void updateBlacklist(List<String> blacklistAdditions,
protected synchronized void launchProviderService() protected synchronized void launchProviderService()
throws IOException, SliderException { throws IOException, SliderException {
// didn't start, so don't register // didn't start, so don't register
providerService.start(); for (ProviderService providerService : providers) {
providerService.start();
}
// and send the started event ourselves // and send the started event ourselves
eventCallbackEvent(null); eventCallbackEvent(null);
} }
@ -1959,19 +1966,23 @@ public void onContainerStatusReceived(ContainerId containerId,
ContainerStatus containerStatus) { ContainerStatus containerStatus) {
LOG_YARN.debug("Container Status: id={}, status={}", containerId, LOG_YARN.debug("Container Status: id={}, status={}", containerId,
containerStatus); containerStatus);
RoleInstance cinfo = appState.getOwnedContainer(containerId);
if (cinfo == null) {
LOG_YARN.error("Owned container not found for {}", containerId);
return;
}
ProviderService providerService = SliderProviderFactory
.getProviderService(cinfo.providerRole.component.getArtifact());
if (providerService.processContainerStatus(containerId, containerStatus)) { if (providerService.processContainerStatus(containerId, containerStatus)) {
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
} }
RoleInstance cinfo = appState.getOwnedContainer(containerId); LOG_YARN.info("Re-requesting status for role {}, {}",
if (cinfo != null) { cinfo.role, containerId);
LOG_YARN.info("Re-requesting status for role {}, {}", //trigger another async container status
cinfo.role, containerId); nmClientAsync.getContainerStatusAsync(containerId,
//trigger another async container status cinfo.container.getNodeId());
nmClientAsync.getContainerStatusAsync(containerId,
cinfo.container.getNodeId());
}
} else if (timelineServiceEnabled) { } else if (timelineServiceEnabled) {
RoleInstance instance = appState.getOwnedContainer(containerId); RoleInstance instance = appState.getOwnedContainer(containerId);
if (instance != null) { if (instance != null) {
@ -1997,11 +2008,6 @@ public void onStopContainerError(ContainerId containerId, Throwable t) {
LOG_YARN.warn("Failed to stop Container {}", containerId); LOG_YARN.warn("Failed to stop Container {}", containerId);
} }
public ProviderService getProviderService() {
return providerService;
}
/** /**
* Queue an action for immediate execution in the executor thread * Queue an action for immediate execution in the executor thread
* @param action action to execute * @param action action to execute

View File

@ -17,7 +17,6 @@
package org.apache.slider.server.appmaster.web; package org.apache.slider.server.appmaster.web;
import org.apache.hadoop.registry.client.api.RegistryOperations; import org.apache.hadoop.registry.client.api.RegistryOperations;
import org.apache.slider.providers.ProviderService;
import org.apache.slider.server.appmaster.actions.QueueAccess; import org.apache.slider.server.appmaster.actions.QueueAccess;
import org.apache.slider.server.appmaster.management.MetricsAndMonitoring; import org.apache.slider.server.appmaster.management.MetricsAndMonitoring;
import org.apache.slider.server.appmaster.state.AppState; import org.apache.slider.server.appmaster.state.AppState;
@ -33,11 +32,6 @@ public interface WebAppApi {
*/ */
StateAccessForProviders getAppState(); StateAccessForProviders getAppState();
/**
* The {@link ProviderService} for the current cluster
*/
ProviderService getProviderService();
/** /**
* Registry operations accessor * Registry operations accessor
* @return registry access * @return registry access

View File

@ -17,7 +17,6 @@
package org.apache.slider.server.appmaster.web; package org.apache.slider.server.appmaster.web;
import org.apache.hadoop.registry.client.api.RegistryOperations; import org.apache.hadoop.registry.client.api.RegistryOperations;
import org.apache.slider.providers.ProviderService;
import org.apache.slider.server.appmaster.actions.QueueAccess; import org.apache.slider.server.appmaster.actions.QueueAccess;
import org.apache.slider.server.appmaster.management.MetricsAndMonitoring; import org.apache.slider.server.appmaster.management.MetricsAndMonitoring;
import org.apache.slider.server.appmaster.state.StateAccessForProviders; import org.apache.slider.server.appmaster.state.StateAccessForProviders;
@ -33,21 +32,18 @@ public class WebAppApiImpl implements WebAppApi {
private static final Logger log = LoggerFactory.getLogger(WebAppApiImpl.class); private static final Logger log = LoggerFactory.getLogger(WebAppApiImpl.class);
protected final StateAccessForProviders appState; protected final StateAccessForProviders appState;
protected final ProviderService provider;
private final RegistryOperations registryOperations; private final RegistryOperations registryOperations;
private final MetricsAndMonitoring metricsAndMonitoring; private final MetricsAndMonitoring metricsAndMonitoring;
private final QueueAccess queues; private final QueueAccess queues;
public WebAppApiImpl(StateAccessForProviders appState, public WebAppApiImpl(StateAccessForProviders appState,
ProviderService provider, RegistryOperations registryOperations, RegistryOperations registryOperations,
MetricsAndMonitoring metricsAndMonitoring, QueueAccess queues) { MetricsAndMonitoring metricsAndMonitoring, QueueAccess queues) {
checkNotNull(appState); checkNotNull(appState);
checkNotNull(provider);
this.queues = queues; this.queues = queues;
this.registryOperations = registryOperations; this.registryOperations = registryOperations;
this.appState = appState; this.appState = appState;
this.provider = provider;
this.metricsAndMonitoring = metricsAndMonitoring; this.metricsAndMonitoring = metricsAndMonitoring;
} }
@ -56,11 +52,6 @@ public StateAccessForProviders getAppState() {
return appState; return appState;
} }
@Override
public ProviderService getProviderService() {
return provider;
}
@Override @Override
public RegistryOperations getRegistryOperations() { public RegistryOperations getRegistryOperations() {
return registryOperations; return registryOperations;

View File

@ -19,7 +19,6 @@
package org.apache.slider.server.appmaster.web.view; package org.apache.slider.server.appmaster.web.view;
import org.apache.hadoop.yarn.webapp.view.HtmlBlock; import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
import org.apache.slider.providers.ProviderService;
import org.apache.slider.server.appmaster.state.StateAccessForProviders; import org.apache.slider.server.appmaster.state.StateAccessForProviders;
import org.apache.slider.server.appmaster.web.WebAppApi; import org.apache.slider.server.appmaster.web.WebAppApi;
import org.apache.slider.server.appmaster.web.rest.RestPaths; import org.apache.slider.server.appmaster.web.rest.RestPaths;
@ -33,12 +32,10 @@
public abstract class SliderHamletBlock extends HtmlBlock { public abstract class SliderHamletBlock extends HtmlBlock {
protected final StateAccessForProviders appState; protected final StateAccessForProviders appState;
protected final ProviderService providerService;
protected final RestPaths restPaths = new RestPaths(); protected final RestPaths restPaths = new RestPaths();
public SliderHamletBlock(WebAppApi slider) { public SliderHamletBlock(WebAppApi slider) {
this.appState = slider.getAppState(); this.appState = slider.getAppState();
this.providerService = slider.getProviderService();
} }
protected String rootPath(String absolutePath) { protected String rootPath(String absolutePath) {

View File

@ -1,30 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you 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.
-->
<configuration>
<property>
<name>slider.config.loaded</name>
<value>true</value>
</property>
<property>
<name>slider.provider.docker</name>
<value>org.apache.slider.providers.docker.DockerProviderFactory</value>
</property>
</configuration>

View File

@ -18,11 +18,16 @@
package org.apache.slider.providers; package org.apache.slider.providers;
import org.apache.slider.providers.docker.DockerKeys; import org.apache.slider.api.resource.Artifact;
import org.apache.slider.api.resource.Artifact.TypeEnum;
import org.apache.slider.providers.docker.DockerClientProvider;
import org.apache.slider.providers.docker.DockerProviderFactory; import org.apache.slider.providers.docker.DockerProviderFactory;
import org.apache.slider.providers.docker.DockerProviderService;
import org.apache.slider.providers.tarball.TarballClientProvider;
import org.apache.slider.providers.tarball.TarballProviderFactory;
import org.apache.slider.providers.tarball.TarballProviderService;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/** /**
@ -30,25 +35,38 @@
*/ */
public class TestProviderFactory { public class TestProviderFactory {
@Test @Test
public void testLoadAgentProvider() throws Throwable { public void testDockerFactory() throws Throwable {
SliderProviderFactory factory = SliderProviderFactory SliderProviderFactory factory = SliderProviderFactory
.createSliderProviderFactory(DockerKeys.PROVIDER_DOCKER); .createSliderProviderFactory(new Artifact().type(TypeEnum.DOCKER));
assertTrue(factory instanceof DockerProviderFactory); assertTrue(factory instanceof DockerProviderFactory);
assertTrue(factory.createClientProvider() instanceof DockerClientProvider);
assertTrue(factory.createServerProvider() instanceof DockerProviderService);
assertTrue(SliderProviderFactory.getProviderService(new Artifact()
.type(TypeEnum.DOCKER)) instanceof DockerProviderService);
} }
@Test @Test
public void testCreateClientProvider() throws Throwable { public void testTarballFactory() throws Throwable {
SliderProviderFactory factory = SliderProviderFactory SliderProviderFactory factory = SliderProviderFactory
.createSliderProviderFactory(DockerKeys.PROVIDER_DOCKER); .createSliderProviderFactory(new Artifact().type(TypeEnum.TARBALL));
assertNotNull(factory.createClientProvider()); assertTrue(factory instanceof TarballProviderFactory);
assertTrue(factory.createClientProvider() instanceof TarballClientProvider);
assertTrue(factory.createServerProvider() instanceof
TarballProviderService);
assertTrue(SliderProviderFactory.getProviderService(new Artifact()
.type(TypeEnum.TARBALL)) instanceof TarballProviderService);
} }
@Test @Test
public void testCreateProviderByClassname() throws Throwable { public void testDefaultFactory() throws Throwable {
SliderProviderFactory factory = SliderProviderFactory SliderProviderFactory factory = SliderProviderFactory
.createSliderProviderFactory(DockerKeys.PROVIDER_DOCKER); .createSliderProviderFactory(null);
assertNotNull(factory.createServerProvider()); assertTrue(factory instanceof DefaultProviderFactory);
assertTrue(factory instanceof DockerProviderFactory); assertTrue(factory.createClientProvider() instanceof DefaultClientProvider);
assertTrue(factory.createServerProvider() instanceof
DefaultProviderService);
assertTrue(SliderProviderFactory.getProviderService(null) instanceof
DefaultProviderService);
} }
} }

View File

@ -20,9 +20,7 @@
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
import org.apache.slider.providers.ProviderService;
import org.apache.slider.server.appmaster.model.mock.BaseMockAppStateTest; import org.apache.slider.server.appmaster.model.mock.BaseMockAppStateTest;
import org.apache.slider.server.appmaster.model.mock.MockProviderService;
import org.apache.slider.server.appmaster.state.ProviderAppState; import org.apache.slider.server.appmaster.state.ProviderAppState;
import org.apache.slider.server.appmaster.web.WebAppApi; import org.apache.slider.server.appmaster.web.WebAppApi;
import org.apache.slider.server.appmaster.web.WebAppApiImpl; import org.apache.slider.server.appmaster.web.WebAppApiImpl;
@ -45,11 +43,9 @@ public void setup() throws Exception {
ProviderAppState providerAppState = new ProviderAppState( ProviderAppState providerAppState = new ProviderAppState(
"undefined", "undefined",
appState); appState);
ProviderService providerService = new MockProviderService();
WebAppApiImpl inst = new WebAppApiImpl( WebAppApiImpl inst = new WebAppApiImpl(
providerAppState, providerAppState,
providerService,
null, null,
null, null); null, null);

View File

@ -27,12 +27,10 @@
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TR; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TR;
import org.apache.hadoop.yarn.webapp.hamlet.HamletImpl.EImp; import org.apache.hadoop.yarn.webapp.hamlet.HamletImpl.EImp;
import org.apache.slider.api.ClusterNode; import org.apache.slider.api.ClusterNode;
import org.apache.slider.providers.ProviderService;
import org.apache.slider.server.appmaster.model.mock.BaseMockAppStateTest; import org.apache.slider.server.appmaster.model.mock.BaseMockAppStateTest;
import org.apache.slider.server.appmaster.model.mock.MockContainer; import org.apache.slider.server.appmaster.model.mock.MockContainer;
import org.apache.slider.server.appmaster.model.mock.MockContainerId; import org.apache.slider.server.appmaster.model.mock.MockContainerId;
import org.apache.slider.server.appmaster.model.mock.MockNodeId; import org.apache.slider.server.appmaster.model.mock.MockNodeId;
import org.apache.slider.server.appmaster.model.mock.MockProviderService;
import org.apache.slider.server.appmaster.model.mock.MockResource; import org.apache.slider.server.appmaster.model.mock.MockResource;
import org.apache.slider.server.appmaster.state.ProviderAppState; import org.apache.slider.server.appmaster.state.ProviderAppState;
import org.apache.slider.server.appmaster.state.RoleInstance; import org.apache.slider.server.appmaster.state.RoleInstance;
@ -65,14 +63,12 @@ public class TestContainerStatsBlock extends BaseMockAppStateTest {
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
super.setup(); super.setup();
ProviderService providerService = new MockProviderService();
ProviderAppState providerAppState = new ProviderAppState( ProviderAppState providerAppState = new ProviderAppState(
"undefined", "undefined",
appState); appState);
WebAppApiImpl inst = new WebAppApiImpl( WebAppApiImpl inst = new WebAppApiImpl(
providerAppState, providerAppState,
providerService,
null, null,
METRICS, null); METRICS, null);

View File

@ -22,12 +22,10 @@
import org.apache.hadoop.yarn.api.records.Container; import org.apache.hadoop.yarn.api.records.Container;
import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
import org.apache.slider.providers.ProviderService;
import org.apache.slider.server.appmaster.model.appstate.BaseMockAppStateAATest; import org.apache.slider.server.appmaster.model.appstate.BaseMockAppStateAATest;
import org.apache.slider.server.appmaster.model.mock.MockContainer; import org.apache.slider.server.appmaster.model.mock.MockContainer;
import org.apache.slider.server.appmaster.model.mock.MockContainerId; import org.apache.slider.server.appmaster.model.mock.MockContainerId;
import org.apache.slider.server.appmaster.model.mock.MockNodeId; import org.apache.slider.server.appmaster.model.mock.MockNodeId;
import org.apache.slider.server.appmaster.model.mock.MockProviderService;
import org.apache.slider.server.appmaster.model.mock.MockResource; import org.apache.slider.server.appmaster.model.mock.MockResource;
import org.apache.slider.server.appmaster.state.ContainerOutcome; import org.apache.slider.server.appmaster.state.ContainerOutcome;
import org.apache.slider.server.appmaster.state.OutstandingRequest; import org.apache.slider.server.appmaster.state.OutstandingRequest;
@ -58,14 +56,12 @@ public class TestIndexBlock extends BaseMockAppStateAATest {
public void setup() throws Exception { public void setup() throws Exception {
super.setup(); super.setup();
assertNotNull(appState); assertNotNull(appState);
ProviderService providerService = new MockProviderService();
ProviderAppState providerAppState = new ProviderAppState( ProviderAppState providerAppState = new ProviderAppState(
"undefined", "undefined",
appState); appState);
WebAppApiImpl inst = new WebAppApiImpl( WebAppApiImpl inst = new WebAppApiImpl(
providerAppState, providerAppState,
providerService,
null, null,
METRICS, null); METRICS, null);