You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by br...@apache.org on 2018/10/30 06:03:09 UTC
[39/50] [abbrv] hadoop git commit: YARN-8569. Create an interface to
provide cluster information to application. Contributed by Eric Yang
YARN-8569. Create an interface to provide cluster information to application. Contributed by Eric Yang
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/c653a6fc
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/c653a6fc
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/c653a6fc
Branch: refs/heads/HDFS-13891
Commit: c653a6fc33c3d0147d35f15a62707f3bd7472d32
Parents: 4929be9
Author: Billie Rinaldi <bi...@apache.org>
Authored: Thu Oct 25 09:55:05 2018 -0700
Committer: Brahma Reddy Battula <br...@apache.org>
Committed: Tue Oct 30 11:31:17 2018 +0530
----------------------------------------------------------------------
.../hadoop/yarn/api/ApplicationConstants.java | 9 +-
.../hadoop/yarn/service/ServiceMaster.java | 7 +
.../hadoop/yarn/service/ServiceScheduler.java | 67 +++++++++
.../yarn/service/client/ServiceClient.java | 141 ++++++++++++++++++-
.../hadoop/yarn/service/utils/HttpUtil.java | 123 ++++++++++++++++
.../yarn/service/utils/ServiceApiUtil.java | 2 -
.../hadoop/yarn/service/TestServiceAM.java | 32 ++++-
.../server/nodemanager/ContainerExecutor.java | 12 ++
.../nodemanager/DefaultContainerExecutor.java | 7 +
.../nodemanager/LinuxContainerExecutor.java | 43 ++++++
.../linux/privileged/PrivilegedOperation.java | 6 +-
.../runtime/DockerLinuxContainerRuntime.java | 18 +++
.../linux/runtime/docker/DockerRunCommand.java | 6 +
.../nodemanager/webapp/NMWebServices.java | 27 ++++
.../impl/container-executor.c | 97 +++++++++++++
.../impl/container-executor.h | 22 ++-
.../main/native/container-executor/impl/main.c | 30 +++-
.../impl/utils/string-utils.c | 9 ++
.../impl/utils/string-utils.h | 6 +
.../test/test-container-executor.c | 61 ++++++++
.../nodemanager/TestLinuxContainerExecutor.java | 11 ++
.../TestContainersMonitorResourceChange.java | 4 +
.../src/site/markdown/DockerContainers.md | 16 +++
23 files changed, 745 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/ApplicationConstants.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/ApplicationConstants.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/ApplicationConstants.java
index 490e95e..eb03fb2 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/ApplicationConstants.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/ApplicationConstants.java
@@ -273,7 +273,14 @@ public interface ApplicationConstants {
* Final, Docker run support ENTRY_POINT.
*/
YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE(
- "YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE");
+ "YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE"),
+
+ /**
+ * $YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE
+ * Final, expose cluster information to container.
+ */
+ YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE(
+ "YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE");
private final String variable;
private Environment(String variable) {
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceMaster.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceMaster.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceMaster.java
index 0caa119..9ac1753 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceMaster.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceMaster.java
@@ -45,6 +45,7 @@ import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.hadoop.yarn.security.AMRMTokenIdentifier;
import org.apache.hadoop.yarn.security.client.ClientToAMTokenSecretManager;
+import org.apache.hadoop.yarn.service.api.records.Service;
import org.apache.hadoop.yarn.service.api.records.ServiceState;
import org.apache.hadoop.yarn.service.exceptions.BadClusterStateException;
import org.apache.hadoop.yarn.service.monitor.ServiceMonitor;
@@ -302,6 +303,12 @@ public class ServiceMaster extends CompositeService {
LOG.info("Service state changed from {} -> {}", curState,
scheduler.getApp().getState());
}
+ populateYarnSysFS(scheduler);
+ }
+
+ private static void populateYarnSysFS(ServiceScheduler scheduler) {
+ Service service = scheduler.getApp();
+ scheduler.syncSysFs(service);
}
private void printSystemEnv() {
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceScheduler.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceScheduler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceScheduler.java
index 9b9305c..249767f 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceScheduler.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/ServiceScheduler.java
@@ -21,6 +21,9 @@ package org.apache.hadoop.yarn.service;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource.Builder;
+
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
@@ -38,6 +41,7 @@ import org.apache.hadoop.registry.client.types.yarn.YarnRegistryAttributes;
import org.apache.hadoop.security.HadoopKerberosName;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.service.CompositeService;
+import org.apache.hadoop.yarn.api.ApplicationConstants;
import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId;
@@ -77,6 +81,7 @@ import org.apache.hadoop.yarn.service.provider.ProviderUtils;
import org.apache.hadoop.yarn.service.registry.YarnRegistryViewForProviders;
import org.apache.hadoop.yarn.service.timelineservice.ServiceMetricsSink;
import org.apache.hadoop.yarn.service.timelineservice.ServiceTimelinePublisher;
+import org.apache.hadoop.yarn.service.utils.HttpUtil;
import org.apache.hadoop.yarn.service.utils.ServiceApiUtil;
import org.apache.hadoop.yarn.service.utils.ServiceRegistryUtils;
import org.apache.hadoop.yarn.service.utils.ServiceUtils;
@@ -90,6 +95,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
+import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.Collection;
@@ -1027,4 +1033,65 @@ public class ServiceScheduler extends CompositeService {
public ServiceUtils.ProcessTerminationHandler getTerminationHandler() {
return terminationHandler;
}
+
+ public void syncSysFs(Service yarnApp) {
+ boolean success = true;
+ Configuration conf = getConfig();
+ String spec;
+ boolean useKerberos = UserGroupInformation.isSecurityEnabled();
+ boolean printSyncResult = false;
+ try {
+ String port = conf.get("yarn.nodemanager.webapp.address").split(":")[1];
+ spec = ServiceApiUtil.jsonSerDeser.toJson(yarnApp);
+ for (org.apache.hadoop.yarn.service.api.records.Component c :
+ yarnApp.getComponents()) {
+ Set<String> nodes = new HashSet<String>();
+ boolean update = Boolean.parseBoolean(c.getConfiguration()
+ .getEnv(ApplicationConstants.Environment
+ .YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE.name()));
+ if (!update) {
+ continue;
+ }
+ printSyncResult = true;
+ for (org.apache.hadoop.yarn.service.api.records.Container container :
+ c.getContainers()) {
+ String bareHost = container.getBareHost();
+ nodes.add(bareHost);
+ }
+ for (String bareHost : nodes) {
+ StringBuilder requestPath = new StringBuilder();
+ if (YarnConfiguration.useHttps(conf)) {
+ requestPath.append("https://");
+ } else {
+ requestPath.append("http://");
+ }
+ requestPath.append(bareHost);
+ requestPath.append(":");
+ requestPath.append(port);
+ requestPath.append("/ws/v1/node/yarn/sysfs/");
+ requestPath.append(UserGroupInformation.getCurrentUser()
+ .getShortUserName());
+ requestPath.append("/");
+ requestPath.append(yarnApp.getId());
+ if (!useKerberos) {
+ requestPath.append("?user.name=");
+ requestPath.append(UserGroupInformation.getCurrentUser()
+ .getShortUserName());
+ }
+ Builder builder = HttpUtil.connect(requestPath.toString());
+ ClientResponse response = builder.put(ClientResponse.class, spec);
+ if (response.getStatus()!=ClientResponse.Status.OK.getStatusCode()) {
+ LOG.warn("Error synchronize YARN sysfs: " +
+ response.getEntity(String.class));
+ success = false;
+ }
+ }
+ }
+ if (printSyncResult && success) {
+ LOG.info("YARN sysfs synchronized.");
+ }
+ } catch (IOException | URISyntaxException | InterruptedException e) {
+ LOG.error("Fail to sync service spec: {}", e);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java
index 42f04da..91d6367 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java
@@ -20,10 +20,14 @@ package org.apache.hadoop.yarn.service.client;
import com.google.common.annotations.VisibleForTesting;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
+import org.apache.curator.shaded.com.google.common.io.Files;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
@@ -73,6 +77,8 @@ import org.apache.hadoop.yarn.service.api.records.ComponentContainers;
import org.apache.hadoop.yarn.service.api.records.Container;
import org.apache.hadoop.yarn.service.api.records.ContainerState;
import org.apache.hadoop.yarn.service.api.records.Component;
+import org.apache.hadoop.yarn.service.api.records.ConfigFile;
+import org.apache.hadoop.yarn.service.api.records.ConfigFile.TypeEnum;
import org.apache.hadoop.yarn.service.api.records.Service;
import org.apache.hadoop.yarn.service.api.records.ServiceState;
import org.apache.hadoop.yarn.service.conf.SliderExitCodes;
@@ -97,12 +103,18 @@ import org.apache.hadoop.yarn.util.Times;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@@ -929,6 +941,8 @@ public class ServiceClient extends AppAdminClient implements SliderExitCodes,
addJarResource(serviceName, localResources);
// add keytab if in secure env
addKeytabResourceIfSecure(fs, localResources, app);
+ // add yarn sysfs to localResources
+ addYarnSysFs(appRootDir, localResources, app);
if (LOG.isDebugEnabled()) {
printLocalResources(localResources);
}
@@ -938,8 +952,8 @@ public class ServiceClient extends AppAdminClient implements SliderExitCodes,
String cmdStr = buildCommandLine(app, conf, appRootDir, hasAMLog4j);
submissionContext.setResource(Resource.newInstance(YarnServiceConf
.getLong(YarnServiceConf.AM_RESOURCE_MEM,
- YarnServiceConf.DEFAULT_KEY_AM_RESOURCE_MEM, app.getConfiguration(),
- conf), 1));
+ YarnServiceConf.DEFAULT_KEY_AM_RESOURCE_MEM,
+ app.getConfiguration(), conf), 1));
String queue = app.getQueue();
if (StringUtils.isEmpty(queue)) {
queue = conf.get(YARN_QUEUE, DEFAULT_YARN_QUEUE);
@@ -963,6 +977,128 @@ public class ServiceClient extends AppAdminClient implements SliderExitCodes,
return submissionContext.getApplicationId();
}
+ /**
+ * Compress (tar) the input files to the output file.
+ *
+ * @param files The files to compress
+ * @param output The resulting output file (should end in .tar.gz)
+ * @param bundleRoot
+ * @throws IOException
+ */
+ public static File compressFiles(Collection<File> files, File output,
+ String bundleRoot) throws IOException {
+ try (FileOutputStream fos = new FileOutputStream(output);
+ TarArchiveOutputStream taos = new TarArchiveOutputStream(
+ new BufferedOutputStream(fos))) {
+ taos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
+ for (File f : files) {
+ addFilesToCompression(taos, f, "sysfs", bundleRoot);
+ }
+ }
+ return output;
+ }
+
+ /**
+ * Compile file list for compression and going recursive for
+ * nested directories.
+ *
+ * @param taos The archive
+ * @param file The file to add to the archive
+ * @param dir The directory that should serve as
+ * the parent directory in the archive
+ * @throws IOException
+ */
+ private static void addFilesToCompression(TarArchiveOutputStream taos,
+ File file, String dir, String bundleRoot) throws IOException {
+ if (!file.isHidden()) {
+ // Create an entry for the file
+ if (!dir.equals(".")) {
+ if (File.separator.equals("\\")) {
+ dir = dir.replaceAll("\\\\", "/");
+ }
+ }
+ taos.putArchiveEntry(
+ new TarArchiveEntry(file, dir + "/" + file.getName()));
+ if (file.isFile()) {
+ // Add the file to the archive
+ try (FileInputStream input = new FileInputStream(file)) {
+ IOUtils.copy(input, taos);
+ taos.closeArchiveEntry();
+ }
+ } else if (file.isDirectory()) {
+ // close the archive entry
+ if (!dir.equals(".")) {
+ taos.closeArchiveEntry();
+ }
+ // go through all the files in the directory and using recursion, add
+ // them to the archive
+ File[] allFiles = file.listFiles();
+ if (allFiles != null) {
+ for (File childFile : allFiles) {
+ addFilesToCompression(taos, childFile,
+ file.getPath().substring(bundleRoot.length()), bundleRoot);
+ }
+ }
+ }
+ }
+ }
+
+ private void addYarnSysFs(Path path,
+ Map<String, LocalResource> localResources, Service app)
+ throws IOException {
+ List<Component> componentsWithYarnSysFS = new ArrayList<Component>();
+ for(Component c : app.getComponents()) {
+ boolean enabled = Boolean.parseBoolean(c.getConfiguration()
+ .getEnv(ApplicationConstants.Environment
+ .YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE.name()));
+ if (enabled) {
+ componentsWithYarnSysFS.add(c);
+ }
+ }
+ if(componentsWithYarnSysFS.size() == 0) {
+ return;
+ }
+ String buffer = ServiceApiUtil.jsonSerDeser.toJson(app);
+ File tmpDir = Files.createTempDir();
+ if (tmpDir.exists()) {
+ String serviceJsonPath = tmpDir.getAbsolutePath() + "/app.json";
+ File localFile = new File(serviceJsonPath);
+ if (localFile.createNewFile()) {
+ try (Writer writer = new OutputStreamWriter(
+ new FileOutputStream(localFile), StandardCharsets.UTF_8)) {
+ writer.write(buffer);
+ }
+ } else {
+ throw new IOException("Fail to write app.json to temp directory");
+ }
+ File destinationFile = new File(tmpDir.getAbsolutePath() + "/sysfs.tar");
+ if (!destinationFile.createNewFile()) {
+ throw new IOException("Fail to localize sysfs.tar.");
+ }
+ List<File> files = new ArrayList<File>();
+ files.add(localFile);
+ compressFiles(files, destinationFile, "sysfs");
+ LocalResource localResource =
+ fs.submitFile(destinationFile, path, ".", "sysfs.tar");
+ Path serviceJson = new Path(path, "sysfs.tar");
+ for (Component c : componentsWithYarnSysFS) {
+ ConfigFile e = new ConfigFile();
+ e.type(TypeEnum.ARCHIVE);
+ e.srcFile(serviceJson.toString());
+ e.destFile("/hadoop/yarn");
+ if (!c.getConfiguration().getFiles().contains(e)) {
+ c.getConfiguration().getFiles().add(e);
+ }
+ }
+ localResources.put("sysfs", localResource);
+ if (!tmpDir.delete()) {
+ LOG.warn("Failed to delete temp file: " + tmpDir.getAbsolutePath());
+ }
+ } else {
+ throw new IOException("Fail to localize sysfs resource.");
+ }
+ }
+
private void setLogAggregationContext(Service app, Configuration conf,
ApplicationSubmissionContext submissionContext) {
LogAggregationContext context = Records.newRecord(LogAggregationContext
@@ -1565,4 +1701,5 @@ public class ServiceClient extends AppAdminClient implements SliderExitCodes,
this.principalName = principalName;
}
}
+
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/HttpUtil.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/HttpUtil.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/HttpUtil.java
new file mode 100644
index 0000000..ac5c079
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/HttpUtil.java
@@ -0,0 +1,123 @@
+/*
+ * 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.hadoop.yarn.service.utils;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.security.PrivilegedExceptionAction;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.apache.hadoop.security.authentication.util.KerberosUtil;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.WebResource.Builder;
+
+/**
+ * Http connection utilities.
+ *
+ */
+public class HttpUtil {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(HttpUtil.class);
+ private static final Base64 BASE_64_CODEC = new Base64(0);
+
+ protected HttpUtil() {
+ // prevents calls from subclass
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Generate SPNEGO challenge request token.
+ *
+ * @param server - hostname to contact
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public static String generateToken(String server) throws
+ IOException, InterruptedException {
+ UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
+ LOG.debug("The user credential is {}", currentUser);
+ String challenge = currentUser
+ .doAs(new PrivilegedExceptionAction<String>() {
+ @Override
+ public String run() throws Exception {
+ try {
+ // This Oid for Kerberos GSS-API mechanism.
+ Oid mechOid = KerberosUtil.getOidInstance("GSS_KRB5_MECH_OID");
+ GSSManager manager = GSSManager.getInstance();
+ // GSS name for server
+ GSSName serverName = manager.createName("HTTP@" + server,
+ GSSName.NT_HOSTBASED_SERVICE);
+ // Create a GSSContext for authentication with the service.
+ // We're passing client credentials as null since we want them to
+ // be read from the Subject.
+ GSSContext gssContext = manager.createContext(
+ serverName.canonicalize(mechOid), mechOid, null,
+ GSSContext.DEFAULT_LIFETIME);
+ gssContext.requestMutualAuth(true);
+ gssContext.requestCredDeleg(true);
+ // Establish context
+ byte[] inToken = new byte[0];
+ byte[] outToken = gssContext.initSecContext(inToken, 0,
+ inToken.length);
+ gssContext.dispose();
+ // Base64 encoded and stringified token for server
+ LOG.debug("Got valid challenge for host {}", serverName);
+ return new String(BASE_64_CODEC.encode(outToken),
+ StandardCharsets.US_ASCII);
+ } catch (GSSException | IllegalAccessException
+ | NoSuchFieldException | ClassNotFoundException e) {
+ LOG.error("Error: {}", e);
+ throw new AuthenticationException(e);
+ }
+ }
+ });
+ return challenge;
+ }
+
+ public static Builder connect(String url) throws URISyntaxException,
+ IOException, InterruptedException {
+ boolean useKerberos = UserGroupInformation.isSecurityEnabled();
+ URI resource = new URI(url);
+ Client client = Client.create();
+ Builder builder = client
+ .resource(url).type(MediaType.APPLICATION_JSON);
+ if (useKerberos) {
+ String challenge = generateToken(resource.getHost());
+ builder.header(HttpHeaders.AUTHORIZATION, "Negotiate " +
+ challenge);
+ LOG.debug("Authorization: Negotiate {}", challenge);
+ }
+ return builder;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java
index cab7ddc..b57e632 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java
@@ -95,8 +95,6 @@ public class ServiceApiUtil {
private static final PatternValidator userNamePattern
= new PatternValidator("[a-z][a-z0-9-.]*");
-
-
@VisibleForTesting
public static void setJsonSerDeser(JsonSerDeser jsd) {
jsonSerDeser = jsd;
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestServiceAM.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestServiceAM.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestServiceAM.java
index 21e93fa..80f4910 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestServiceAM.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestServiceAM.java
@@ -18,7 +18,6 @@
package org.apache.hadoop.yarn.service;
-import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.io.FileUtils;
import org.apache.curator.test.TestingCluster;
@@ -426,4 +425,35 @@ public class TestServiceAM extends ServiceTestUtils{
am.getComponent("compa").getPendingInstances().size());
am.stop();
}
+
+ @Test(timeout = 30000)
+ public void testSyncSysFS() {
+ ApplicationId applicationId = ApplicationId.newInstance(
+ System.currentTimeMillis(), 1);
+ Service exampleApp = new Service();
+ exampleApp.setId(applicationId.toString());
+ exampleApp.setVersion("v1");
+ exampleApp.setName("tensorflow");
+
+ Component compA = createComponent("compa", 1, "pwd");
+ compA.getConfiguration().getEnv().put(
+ "YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE", "true");
+ Artifact artifact = new Artifact();
+ artifact.setType(Artifact.TypeEnum.TARBALL);
+ compA.artifact(artifact);
+ exampleApp.addComponent(compA);
+ try {
+ MockServiceAM am = new MockServiceAM(exampleApp);
+ am.init(conf);
+ am.start();
+ ServiceScheduler scheduler = am.context.scheduler;
+ scheduler.syncSysFs(exampleApp);
+ scheduler.close();
+ am.stop();
+ am.close();
+ } catch (Exception e) {
+ LOG.error("Fail to sync sysfs: {}", e);
+ Assert.fail("Fail to sync sysfs.");
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java
index b3a6df1..6024dbf 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java
@@ -259,6 +259,18 @@ public abstract class ContainerExecutor implements Configurable {
throws IOException;
/**
+ * Update cluster information inside container.
+ *
+ * @param ctx ContainerRuntimeContext
+ * @param user Owner of application
+ * @param appId YARN application ID
+ * @param spec Service Specification
+ * @throws IOException if there is a failure while writing spec to disk
+ */
+ public abstract void updateYarnSysFS(Context ctx, String user,
+ String appId, String spec) throws IOException;
+
+ /**
* Recover an already existing container. This is a blocking call and returns
* only when the container exits. Note that the container must have been
* activated prior to this call.
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DefaultContainerExecutor.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DefaultContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DefaultContainerExecutor.java
index b552c1f..a500c02 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DefaultContainerExecutor.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DefaultContainerExecutor.java
@@ -46,6 +46,7 @@ import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.UnsupportedFileSystemException;
import org.apache.hadoop.fs.permission.FsPermission;
+import org.apache.hadoop.service.ServiceStateException;
import org.apache.hadoop.util.Shell;
import org.apache.hadoop.util.Shell.CommandExecutor;
import org.apache.hadoop.util.Shell.ExitCodeException;
@@ -1038,4 +1039,10 @@ public class DefaultContainerExecutor extends ContainerExecutor {
}
return paths;
}
+
+ @Override
+ public void updateYarnSysFS(Context ctx, String user,
+ String appId, String spec) throws IOException {
+ throw new ServiceStateException("Implementation unavailable");
+ }
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
index 3946eed..0282f58 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
@@ -67,6 +67,7 @@ import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
@@ -996,4 +997,46 @@ public class LinuxContainerExecutor extends ContainerExecutor {
"containerId: {}. Exception: ", containerId, e);
}
}
+
+ @Override
+ public synchronized void updateYarnSysFS(Context ctx, String user,
+ String appId, String spec) throws IOException {
+ LocalDirsHandlerService dirsHandler = nmContext.getLocalDirsHandler();
+ Path sysFSPath = dirsHandler.getLocalPathForWrite(
+ "nmPrivate/" + appId + "/sysfs/app.json");
+ File file = new File(sysFSPath.toString());
+ List<String> localDirs = dirsHandler.getLocalDirs();
+ if (file.exists()) {
+ if (!file.delete()) {
+ LOG.warn("Unable to delete " + sysFSPath.toString());
+ }
+ }
+ if (file.createNewFile()) {
+ FileOutputStream output = new FileOutputStream(file);
+ try {
+ output.write(spec.getBytes("UTF-8"));
+ } finally {
+ output.close();
+ }
+ }
+ PrivilegedOperation privOp = new PrivilegedOperation(
+ PrivilegedOperation.OperationType.SYNC_YARN_SYSFS);
+ String runAsUser = getRunAsUser(user);
+ privOp.appendArgs(runAsUser,
+ user,
+ Integer.toString(PrivilegedOperation.RunAsUserCommand
+ .SYNC_YARN_SYSFS.getValue()),
+ appId, StringUtils.join(PrivilegedOperation
+ .LINUX_FILE_PATH_SEPARATOR, localDirs));
+ privOp.disableFailureLogging();
+ PrivilegedOperationExecutor privilegedOperationExecutor =
+ PrivilegedOperationExecutor.getInstance(nmContext.getConf());
+ try {
+ privilegedOperationExecutor.executePrivilegedOperation(null,
+ privOp, null, null, false, false);
+ } catch (PrivilegedOperationException e) {
+ throw new IOException(e);
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java
index 92a82e8..f199662 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java
@@ -56,7 +56,8 @@ public class PrivilegedOperation {
LIST_AS_USER(""), // no CLI switch supported yet.
ADD_NUMA_PARAMS(""), // no CLI switch supported yet.
REMOVE_DOCKER_CONTAINER("--remove-docker-container"),
- INSPECT_DOCKER_CONTAINER("--inspect-docker-container");
+ INSPECT_DOCKER_CONTAINER("--inspect-docker-container"),
+ SYNC_YARN_SYSFS("");
private final String option;
@@ -153,7 +154,8 @@ public class PrivilegedOperation {
SIGNAL_CONTAINER(2),
DELETE_AS_USER(3),
LAUNCH_DOCKER_CONTAINER(4),
- LIST_AS_USER(5);
+ LIST_AS_USER(5),
+ SYNC_YARN_SYSFS(6);
private int value;
RunAsUserCommand(int value) {
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java
index 436c0ad..2cfa9c5 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java
@@ -179,6 +179,12 @@ import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.r
* This feature is disabled by default. When this feature is disabled or set
* to false, the container will be removed as soon as it exits.
* </li>
+ * <li>
+ * {@code YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE} allows export yarn
+ * service json to docker container. This feature is disabled by default.
+ * when this feature is set, app.json will be available in
+ * /hadoop/yarn/sysfs/app.json.
+ * </li>
* </ul>
*/
@InterfaceAudience.Private
@@ -231,6 +237,11 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
@InterfaceAudience.Private
public static final String ENV_DOCKER_CONTAINER_DELAYED_REMOVAL =
"YARN_CONTAINER_RUNTIME_DOCKER_DELAYED_REMOVAL";
+ @InterfaceAudience.Private
+ public static final String ENV_DOCKER_CONTAINER_YARN_SYSFS =
+ "YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE";
+ public static final String YARN_SYSFS_PATH =
+ "/hadoop/yarn/sysfs";
private Configuration conf;
private Context nmContext;
private DockerClient dockerClient;
@@ -964,6 +975,12 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
addCGroupParentIfRequired(resourcesOpts, containerIdStr, runCommand);
+ if(environment.containsKey(ENV_DOCKER_CONTAINER_YARN_SYSFS) &&
+ Boolean.parseBoolean(environment
+ .get(ENV_DOCKER_CONTAINER_YARN_SYSFS))) {
+ runCommand.setYarnSysFS(true);
+ }
+
if (useEntryPoint) {
runCommand.setOverrideDisabled(true);
runCommand.addEnv(environment);
@@ -1438,4 +1455,5 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
}
}
}
+
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerRunCommand.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerRunCommand.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerRunCommand.java
index 395c1e1..aac8224 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerRunCommand.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerRunCommand.java
@@ -217,4 +217,10 @@ public class DockerRunCommand extends DockerCommand {
public final void addEnv(Map<String, String> environment) {
userEnv.putAll(environment);
}
+
+ public DockerRunCommand setYarnSysFS(boolean toggle) {
+ String value = Boolean.toString(toggle);
+ super.addCommandArguments("use-yarn-sysfs", value);
+ return this;
+ }
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
index bb0881b..ca08897 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
@@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -56,6 +57,7 @@ import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
import org.apache.hadoop.http.JettyUtils;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.service.ServiceStateException;
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ContainerId;
@@ -554,6 +556,31 @@ public class NMWebServices {
return new NMResourceInfo();
}
+ @PUT
+ @Path("/yarn/sysfs/{user}/{appId}")
+ @Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
+ MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 })
+ public Response syncYarnSysFS(@javax.ws.rs.core.Context
+ HttpServletRequest req,
+ @PathParam("user") String user,
+ @PathParam("appId") String appId,
+ String spec) {
+ if (UserGroupInformation.isSecurityEnabled()) {
+ if (!req.getRemoteUser().equals(user)) {
+ return Response.status(Status.FORBIDDEN).build();
+ }
+ }
+ try {
+ nmContext.getContainerExecutor().updateYarnSysFS(nmContext, user, appId,
+ spec);
+ } catch (IOException | ServiceStateException e) {
+ LOG.error("Fail to sync yarn sysfs for application ID: {}, reason: ",
+ appId, e);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build();
+ }
+ return Response.ok().build();
+ }
+
private long parseLongParam(String bytes) {
if (bytes == null || bytes.isEmpty()) {
return Long.MAX_VALUE;
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
index 1ca94fe..e2130ab 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
@@ -76,6 +76,7 @@ static const char* DEFAULT_BANNED_USERS[] = {"yarn", "mapred", "hdfs", "bin", 0}
static const int DEFAULT_DOCKER_SUPPORT_ENABLED = 0;
static const int DEFAULT_TC_SUPPORT_ENABLED = 0;
static const int DEFAULT_MOUNT_CGROUP_SUPPORT_ENABLED = 0;
+static const int DEFAULT_YARN_SYSFS_SUPPORT_ENABLED = 0;
static const char* PROC_PATH = "/proc";
@@ -506,6 +507,11 @@ int is_mount_cgroups_support_enabled() {
&executor_cfg);
}
+int is_yarn_sysfs_support_enabled() {
+ return is_feature_enabled(YARN_SYSFS_SUPPORT_ENABLED_KEY,
+ DEFAULT_YARN_SYSFS_SUPPORT_ENABLED, &executor_cfg);
+}
+
/**
* Utility function to concatenate argB to argA using the concat_pattern.
*/
@@ -1778,6 +1784,27 @@ int create_user_filecache_dirs(const char * user, char* const* local_dirs) {
return rc;
}
+int create_yarn_sysfs(const char* user, const char *app_id,
+ const char *container_id, const char *work_dir, char* const* local_dirs) {
+ int result = OUT_OF_MEMORY;
+ const mode_t perms = S_IRWXU | S_IXGRP;
+ char* const* local_dir_ptr;
+ for(local_dir_ptr = local_dirs; *local_dir_ptr != NULL; ++local_dir_ptr) {
+ char *container_dir = get_container_work_directory(*local_dir_ptr, user, app_id,
+ container_id);
+ if (container_dir == NULL) {
+ return OUT_OF_MEMORY;
+ }
+ char *yarn_sysfs_dir = make_string("%s/%s", container_dir, "sysfs");
+ if (mkdir(yarn_sysfs_dir, perms) == 0) {
+ result = 0;
+ }
+ free(yarn_sysfs_dir);
+ free(container_dir);
+ }
+ return result;
+}
+
int launch_docker_container_as_user(const char * user, const char *app_id,
const char *container_id, const char *work_dir,
const char *script_name, const char *cred_file,
@@ -1834,6 +1861,14 @@ int launch_docker_container_as_user(const char * user, const char *app_id,
goto cleanup;
}
+ exit_code = create_yarn_sysfs(user, app_id, container_id, work_dir, local_dirs);
+ if (exit_code != 0) {
+ fprintf(ERRORFILE, "Could not create user yarn sysfs directory");
+ fflush(ERRORFILE);
+ exit(-1);
+ goto cleanup;
+ }
+
docker_command = construct_docker_command(command_file);
docker_binary = get_docker_binary(&CFG);
@@ -2799,6 +2834,68 @@ struct configuration* get_cfg() {
return &CFG;
}
+char *locate_sysfs_path(const char *src) {
+ char *result = NULL;
+ DIR *dir;
+ struct dirent *entry;
+ if (!(dir = opendir(src))) {
+ return NULL;
+ }
+ while ((entry = readdir(dir)) != NULL) {
+ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
+ continue;
+ }
+ char *new_src = make_string("%s/%s", src, entry->d_name);
+ if (str_ends_with(new_src, "/sysfs.tar/sysfs")) {
+ result = new_src;
+ goto cleanup;
+ }
+ result = locate_sysfs_path(new_src);
+ if (result != NULL) {
+ goto cleanup;
+ }
+ }
+cleanup:
+ closedir(dir);
+ return result;
+}
+
+int sync_yarn_sysfs(char* const* local_dir, const char *running_user, const char *end_user, const char *app_id) {
+ int result = OUT_OF_MEMORY;
+ char *src = NULL;
+ char *dest = NULL;
+ char* const* local_dir_ptr;
+
+ for(local_dir_ptr = local_dir; *local_dir_ptr != NULL; ++local_dir_ptr) {
+ char *appcache_dir = make_string("%s/usercache/%s/appcache/%s", *local_dir_ptr, end_user, app_id);
+ char *sysfs_dir = locate_sysfs_path(appcache_dir);
+ char *nm_private_app_dir = make_string("%s/nmPrivate/%s/sysfs", *local_dir_ptr, app_id);
+ if (sysfs_dir == NULL) {
+ return OUT_OF_MEMORY;
+ }
+ src = make_string("%s/%s", nm_private_app_dir, "app.json");
+ dest = make_string("%s/%s", sysfs_dir, "app.json");
+ // open up the spec file
+ int spec_file = open_file_as_nm(src);
+ if (spec_file == -1) {
+ continue;
+ }
+
+ delete_path(dest, 0);
+ if (copy_file(spec_file, src, dest, S_IRWXU | S_IRGRP | S_IXGRP) == 0) {
+ result = 0;
+ }
+ // continue on to create other work directories
+ free(sysfs_dir);
+ free(src);
+ free(dest);
+ if (result == 0) {
+ break;
+ }
+ }
+ return result;
+}
+
/**
* Flatten docker launch command
*/
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h
index 3eb931a..1415830 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h
@@ -32,7 +32,8 @@ enum command {
SIGNAL_CONTAINER = 2,
DELETE_AS_USER = 3,
LAUNCH_DOCKER_CONTAINER = 4,
- LIST_AS_USER = 5
+ LIST_AS_USER = 5,
+ SYNC_YARN_SYSFS = 6
};
enum operations {
@@ -49,7 +50,8 @@ enum operations {
RUN_DOCKER = 11,
RUN_AS_USER_LIST = 12,
REMOVE_DOCKER_CONTAINER = 13,
- INSPECT_DOCKER_CONTAINER = 14
+ INSPECT_DOCKER_CONTAINER = 14,
+ RUN_AS_USER_SYNC_YARN_SYSFS = 15
};
#define NM_GROUP_KEY "yarn.nodemanager.linux-container-executor.group"
@@ -67,6 +69,7 @@ enum operations {
#define DOCKER_SUPPORT_ENABLED_KEY "feature.docker.enabled"
#define TC_SUPPORT_ENABLED_KEY "feature.tc.enabled"
#define MOUNT_CGROUP_SUPPORT_ENABLED_KEY "feature.mount-cgroup.enabled"
+#define YARN_SYSFS_SUPPORT_ENABLED_KEY "feature.yarn.sysfs.enabled"
#define TMP_DIR "tmp"
extern struct passwd *user_detail;
@@ -293,6 +296,21 @@ int run_docker_with_pty(const char *command_file);
*/
int exec_docker_command(char *docker_command, char **argv, int argc);
+/** Check if yarn sysfs is enabled in configuration. */
+int is_yarn_sysfs_support_enabled();
+
+/**
+ * Create YARN SysFS
+ */
+int create_yarn_sysfs(const char* user, const char *app_id,
+ const char *container_id, const char *work_dir, char* const* local_dirs);
+
+/**
+ * Sync YARN SysFS
+ */
+int sync_yarn_sysfs(char* const* local_dirs, const char *running_user,
+ const char *end_user, const char *app_id);
+
/*
* Compile the regex_str and determine if the input string matches.
* Return 0 on match, 1 of non-match.
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
index c269fa4..7b13e7c 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
@@ -99,11 +99,21 @@ static void display_usage(FILE *stream) {
fprintf(stream, "\n");
}
- fprintf(stream,
+ fprintf(stream,
" signal container: %2d container-pid signal\n"
" delete as user: %2d relative-path\n"
" list as user: %2d relative-path\n",
SIGNAL_CONTAINER, DELETE_AS_USER, LIST_AS_USER);
+
+ if(is_yarn_sysfs_support_enabled()) {
+ fprintf(stream,
+ " sync yarn sysfs: %2d app-id nm-local-dirs\n",
+ SYNC_YARN_SYSFS);
+ } else {
+ fprintf(stream,
+ "[DISABLED] sync yarn sysfs: %2d app-id nm-local-dirs\n",
+ SYNC_YARN_SYSFS);
+ }
}
/* Sets up log files for normal/error logging */
@@ -566,6 +576,11 @@ static int validate_run_as_user_commands(int argc, char **argv, int *operation)
cmd_input.target_dir = argv[optind++];
*operation = RUN_AS_USER_LIST;
return 0;
+ case SYNC_YARN_SYSFS:
+ cmd_input.app_id = argv[optind++];
+ cmd_input.local_dirs = argv[optind++];
+ *operation = RUN_AS_USER_SYNC_YARN_SYSFS;
+ return 0;
default:
fprintf(ERRORFILE, "Invalid command %d not supported.",command);
fflush(ERRORFILE);
@@ -723,6 +738,19 @@ int main(int argc, char **argv) {
exit_code = list_as_user(cmd_input.target_dir);
break;
+ case RUN_AS_USER_SYNC_YARN_SYSFS:
+ exit_code = set_user(cmd_input.run_as_user_name);
+ if (exit_code != 0) {
+ break;
+ }
+ if (is_yarn_sysfs_support_enabled()) {
+ exit_code = sync_yarn_sysfs(split(cmd_input.local_dirs),
+ cmd_input.run_as_user_name, cmd_input.yarn_user_name,
+ cmd_input.app_id);
+ } else {
+ exit_code = FEATURE_DISABLED;
+ }
+ break;
}
flush_and_close_log_files();
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.c
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.c
index 80511e5..68857a9 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.c
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.c
@@ -17,6 +17,9 @@
*/
#include "util.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
#include <limits.h>
#include <errno.h>
#include <strings.h>
@@ -180,3 +183,9 @@ char *make_string(const char *fmt, ...) {
}
return buf;
}
+
+int str_ends_with(const char *s, const char *suffix) {
+ size_t slen = strlen(s);
+ size_t suffix_len = strlen(suffix);
+ return suffix_len <= slen && !strcmp(s + slen - suffix_len, suffix);
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.h
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.h
index affb3c3..995cdf3 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.h
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.h
@@ -38,4 +38,10 @@ int get_numbers_split_by_comma(const char* input, int** numbers, size_t* n_numbe
* String format utility
*/
char *make_string(const char *fmt, ...);
+
+/*
+ * Compare string end with a suffix.
+ * return 1 if succeeded
+ */
+int str_ends_with(const char *s, const char *suffix);
#endif
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
index 327e441..437850d 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
@@ -105,6 +105,7 @@ int write_config_file(char *file_name, int banned) {
fprintf(file, "min.user.id=0\n");
}
fprintf(file, "allowed.system.users=allowedUser,daemon\n");
+ fprintf(file, "feature.yarn.sysfs.enabled=1\n");
fclose(file);
return 0;
}
@@ -524,6 +525,63 @@ void test_is_feature_enabled() {
free_configuration(&exec_cfg);
}
+void test_yarn_sysfs() {
+ char *app_id = "app-1";
+ char *container_id = "container-1";
+ // Test create sysfs without container.
+ int result = create_yarn_sysfs(username, app_id, container_id, "work", local_dirs);
+ if (result == 0) {
+ printf("Should not be able to create yarn sysfs without container directories.\n");
+ exit(1);
+ }
+
+ result = sync_yarn_sysfs(local_dirs, username, username, app_id);
+ if (result == 0) {
+ printf("sync_yarn_sysfs failed.\n");
+ exit(1);
+ }
+
+ // Create container directories and init app.json
+ char* const* local_dir_ptr;
+ for (local_dir_ptr = local_dirs; *local_dir_ptr != 0; ++local_dir_ptr) {
+ char *user_dir = make_string("%s/usercache/%s", *local_dir_ptr, username);
+ if (mkdirs(user_dir, 0750) != 0) {
+ printf("Can not make user directories: %s\n", user_dir);
+ exit(1);
+ }
+ free(user_dir);
+ char *app_dir = make_string("%s/usercache/%s/appcache/%s/%s", *local_dir_ptr, username, app_id);
+ if (mkdirs(app_dir, 0750) != 0) {
+ printf("Can not make app directories: %s\n", app_dir);
+ exit(1);
+ }
+ free(app_dir);
+ // Simulate distributed cache created directory structures.
+ char *cache_dir = make_string("%s/usercache/%s/appcache/%s/filecache/%s/sysfs.tar/sysfs", *local_dir_ptr, username, app_id, container_id);
+ if (mkdirs(cache_dir, 0750) != 0) {
+ printf("Can not make container directories: %s\n", cache_dir);
+ exit(1);
+ }
+ free(cache_dir);
+ char *nm_dir = make_string("%s/nmPrivate/%s/sysfs", *local_dir_ptr, app_id);
+ if (mkdirs(nm_dir, 0750) != 0) {
+ printf("Can not make nmPrivate directories: %s\n", nm_dir);
+ exit(1);
+ }
+ char *sysfs_path = make_string("%s/%s", nm_dir, "app.json");
+ FILE *file = fopen(sysfs_path, "w");
+ fprintf(file, "{}\n");
+ fclose(file);
+ free(nm_dir);
+ }
+
+ result = sync_yarn_sysfs(local_dirs, username, username, app_id);
+ if (result != 0) {
+ printf("sync_yarn_sysfs failed.\n");
+ exit(1);
+ }
+}
+
void test_delete_user() {
printf("\nTesting delete_user\n");
char* app_dir = get_app_directory(TEST_ROOT "/local-1", yarn_username, "app_3");
@@ -1551,6 +1609,9 @@ int main(int argc, char **argv) {
printf("\nTesting is_feature_enabled()\n");
test_is_feature_enabled();
+ printf("\nTesting yarn sysfs\n");
+ test_yarn_sysfs();
+
test_check_user(0);
test_cleaning_docker_cgroups();
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java
index 856d5ff..c34fb20 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java
@@ -706,6 +706,17 @@ public class TestLinuxContainerExecutor {
verify(lce, times(1)).execContainer(ctx);
}
+ @Test
+ public void testUpdateYarnSysFS() throws Exception {
+ String user = System.getProperty("user.name");
+ String appId="app-1";
+ String spec="";
+ Context ctx = mock(Context.class);
+ LinuxContainerExecutor lce = mock(LinuxContainerExecutor.class);
+ lce.updateYarnSysFS(ctx, user, appId, spec);
+ verify(lce, times(1)).updateYarnSysFS(ctx, user, appId, spec);
+ }
+
private static class TestResourceHandler implements LCEResourcesHandler {
static Set<ContainerId> postExecContainers = new HashSet<ContainerId>();
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java
index 3d535e9..d00c93b 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java
@@ -128,6 +128,10 @@ public class TestContainersMonitorResourceChange {
throws IOException {
return true;
}
+ @Override
+ public void updateYarnSysFS(Context ctx, String user, String appId,
+ String spec) throws IOException {
+ }
}
private static class MockContainerEventHandler implements
http://git-wip-us.apache.org/repos/asf/hadoop/blob/c653a6fc/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/DockerContainers.md
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/DockerContainers.md b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/DockerContainers.md
index 17a335e..2d6f867 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/DockerContainers.md
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/DockerContainers.md
@@ -287,6 +287,7 @@ The following properties are optional:
| `banned.users` | A comma-separated list of usernames who should not be allowed to launch applications. The default setting is: yarn, mapred, hdfs, and bin. |
| `allowed.system.users` | A comma-separated list of usernames who should be allowed to launch applications even if their UIDs are below the configured minimum. If a user appears in allowed.system.users and banned.users, the user will be considered banned. |
| `feature.tc.enabled` | Must be "true" or "false". "false" means traffic control commands are disabled. "true" means traffic control commands are allowed. |
+| `feature.yarn.sysfs.enabled` | Must be "true" or "false". See YARN sysfs support for detail. The default setting is disabled. |
Part of a container-executor.cfg which allows Docker containers to be launched is below:
@@ -369,6 +370,7 @@ environment variables in the application's environment:
| `YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS` | Adds additional volume mounts to the Docker container. The value of the environment variable should be a comma-separated list of mounts. All such mounts must be given as `source:dest[:mode]` and the mode must be "ro" (read-only) or "rw" (read-write) to specify the type of access being requested. If neither is specified, read-write will be assumed. The mode may include a bind propagation option. In that case, the mode should either be of the form `[option]`, `rw+[option]`, or `ro+[option]`. Valid bind propagation options are shared, rshared, slave, rslave, private, and rprivate. The requested mounts will be validated by container-executor based on the values set in container-executor.cfg for `docker.allowed.ro-mounts` and `docker.allowed.rw-mounts`. |
| `YARN_CONTAINER_RUNTIME_DOCKER_TMPFS_MOUNTS` | Adds additional tmpfs mounts to the Docker container. The value of the environment variable should be a comma-separated list of absolute mount points within the container. |
| `YARN_CONTAINER_RUNTIME_DOCKER_DELAYED_REMOVAL` | Allows a user to request delayed deletion of the Docker container on a per container basis. If true, Docker containers will not be removed until the duration defined by yarn.nodemanager.delete.debug-delay-sec has elapsed. Administrators can disable this feature through the yarn-site property yarn.nodemanager.runtime.linux.docker.delayed-removal.allowed. This feature is disabled by default. When this feature is disabled or set to false, the container will be removed as soon as it exits. |
+| `YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE` | Enable mounting of container working directory sysfs sub-directory into Docker container /hadoop/yarn/sysfs. This is useful for populating cluster information into container. |
The first two are required. The remainder can be set as needed. While
controlling the container type through environment variables is somewhat less
@@ -767,3 +769,17 @@ In yarn-env.sh, define:
```
export YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE=true
```
+
+Docker Container YARN SysFS Support
+-----------------------------------
+
+YARN SysFS is a pseudo file system provided by the YARN framework that
+exports information about clustering information to Docker container.
+Cluster information is exported to /hadoop/yarn/sysfs path. This
+API allows application developer to obtain clustering information
+without external service dependencies. Custom application master can
+populate cluster information by calling node manager REST API.
+YARN service framework automatically populates cluster information
+to /hadoop/yarn/sysfs/app.json. For more information about
+YARN service, see: [YARN Service](./yarn-service/Overview.html).
+
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org