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 dfcc6acafb1..e5c65393840 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 @@ -113,6 +113,7 @@ private boolean containerLimitUsers; private ResourceHandler resourceHandlerChain; private LinuxContainerRuntime linuxContainerRuntime; + private Context nmContext; /** * The container exit code. @@ -286,6 +287,7 @@ protected PrivilegedOperationExecutor getPrivilegedOperationExecutor() { @Override public void init(Context nmContext) throws IOException { Configuration conf = super.getConf(); + this.nmContext = nmContext; // Send command to executor which will just start up, // verify configuration/permissions and exit @@ -956,11 +958,11 @@ public void removeDockerContainer(String containerId) { PrivilegedOperationExecutor.getInstance(super.getConf()); if (DockerCommandExecutor.isRemovable( DockerCommandExecutor.getContainerStatus(containerId, - super.getConf(), privOpExecutor))) { + super.getConf(), privOpExecutor, nmContext))) { LOG.info("Removing Docker container : " + containerId); DockerRmCommand dockerRmCommand = new DockerRmCommand(containerId); DockerCommandExecutor.executeDockerCommand(dockerRmCommand, containerId, - null, super.getConf(), privOpExecutor, false); + null, super.getConf(), privOpExecutor, false, nmContext); } } catch (ContainerExecutionException e) { LOG.warn("Unable to remove docker container: " + containerId); 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 7106aad2fe9..999b343628a 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 @@ -383,7 +383,7 @@ private String runDockerVolumeCommand(DockerVolumeCommand dockerVolumeCommand, Container container) throws ContainerExecutionException { try { String commandFile = dockerClient.writeCommandToTempFile( - dockerVolumeCommand, container.getContainerId().toString()); + dockerVolumeCommand, container, nmContext); PrivilegedOperation privOp = new PrivilegedOperation( PrivilegedOperation.OperationType.RUN_DOCKER_CMD); privOp.appendArgs(commandFile); @@ -902,7 +902,7 @@ public void launchContainer(ContainerRuntimeContext ctx) } String commandFile = dockerClient.writeCommandToTempFile(runCommand, - containerIdStr); + container, nmContext); PrivilegedOperation launchOp = buildLaunchOp(ctx, commandFile, runCommand); @@ -926,12 +926,12 @@ public void relaunchContainer(ContainerRuntimeContext ctx) // Check to see if the container already exists for relaunch DockerCommandExecutor.DockerContainerStatus containerStatus = DockerCommandExecutor.getContainerStatus(containerIdStr, conf, - privilegedOperationExecutor); + privilegedOperationExecutor, nmContext); if (containerStatus != null && DockerCommandExecutor.isStartable(containerStatus)) { DockerStartCommand startCommand = new DockerStartCommand(containerIdStr); String commandFile = dockerClient.writeCommandToTempFile(startCommand, - containerIdStr); + container, nmContext); PrivilegedOperation launchOp = buildLaunchOp(ctx, commandFile, startCommand); @@ -1041,7 +1041,7 @@ public void reapContainer(ContainerRuntimeContext ctx) new DockerInspectCommand(containerId).getIpAndHost(); try { String commandFile = dockerClient.writeCommandToTempFile(inspectCommand, - containerId); + container, nmContext); PrivilegedOperation privOp = new PrivilegedOperation( PrivilegedOperation.OperationType.RUN_DOCKER_CMD); privOp.appendArgs(commandFile); @@ -1183,12 +1183,12 @@ private void handleContainerStop(String containerId, Map env) throws ContainerExecutionException { DockerCommandExecutor.DockerContainerStatus containerStatus = DockerCommandExecutor.getContainerStatus(containerId, conf, - privilegedOperationExecutor); + privilegedOperationExecutor, nmContext); if (DockerCommandExecutor.isStoppable(containerStatus)) { DockerStopCommand dockerStopCommand = new DockerStopCommand( containerId).setGracePeriod(dockerStopGracePeriod); DockerCommandExecutor.executeDockerCommand(dockerStopCommand, containerId, - env, conf, privilegedOperationExecutor, false); + env, conf, privilegedOperationExecutor, false, nmContext); } else { if (LOG.isDebugEnabled()) { LOG.debug( @@ -1202,12 +1202,12 @@ private void handleContainerKill(String containerId, Map env, ContainerExecutor.Signal signal) throws ContainerExecutionException { DockerCommandExecutor.DockerContainerStatus containerStatus = DockerCommandExecutor.getContainerStatus(containerId, conf, - privilegedOperationExecutor); + privilegedOperationExecutor, nmContext); if (DockerCommandExecutor.isKillable(containerStatus)) { DockerKillCommand dockerKillCommand = new DockerKillCommand(containerId).setSignal(signal.name()); DockerCommandExecutor.executeDockerCommand(dockerKillCommand, containerId, - env, conf, privilegedOperationExecutor, false); + env, conf, privilegedOperationExecutor, false, nmContext); } else { if (LOG.isDebugEnabled()) { LOG.debug( @@ -1227,11 +1227,11 @@ private void handleContainerRemove(String containerId, } else { DockerCommandExecutor.DockerContainerStatus containerStatus = DockerCommandExecutor.getContainerStatus(containerId, conf, - privilegedOperationExecutor); + privilegedOperationExecutor, nmContext); if (DockerCommandExecutor.isRemovable(containerStatus)) { DockerRmCommand dockerRmCommand = new DockerRmCommand(containerId); DockerCommandExecutor.executeDockerCommand(dockerRmCommand, containerId, - env, conf, privilegedOperationExecutor, false); + env, conf, privilegedOperationExecutor, false, nmContext); } } } 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/DockerClient.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/DockerClient.java index 77c53a86970..c55b83b16f7 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/DockerClient.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/DockerClient.java @@ -23,7 +23,13 @@ import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; import org.apache.hadoop.util.StringUtils; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.server.nodemanager.Context; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.ResourceLocalizationService; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -97,4 +103,54 @@ public String writeCommandToTempFile(DockerCommand cmd, String filePrefix) throw new ContainerExecutionException(e); } } + + public String writeCommandToTempFile(DockerCommand cmd, Container container, + Context nmContext) throws ContainerExecutionException { + ContainerId containerId = container.getContainerId(); + String filePrefix = containerId.toString(); + ApplicationId appId = containerId.getApplicationAttemptId() + .getApplicationId(); + File dockerCommandFile; + String cmdDir = null; + + if(nmContext == null || nmContext.getLocalDirsHandler() == null) { + throw new ContainerExecutionException( + "Unable to write temporary docker command"); + } + + try { + cmdDir = nmContext.getLocalDirsHandler().getLocalPathForWrite( + ResourceLocalizationService.NM_PRIVATE_DIR + Path.SEPARATOR + + appId + Path.SEPARATOR + filePrefix + Path.SEPARATOR).toString(); + + dockerCommandFile = File.createTempFile(TMP_FILE_PREFIX + filePrefix, + TMP_FILE_SUFFIX, new File(cmdDir)); + + Writer writer = new OutputStreamWriter( + new FileOutputStream(dockerCommandFile.toString()), "UTF-8"); + PrintWriter printWriter = new PrintWriter(writer); + printWriter.println("[docker-command-execution]"); + for (Map.Entry> entry : + cmd.getDockerCommandWithArguments().entrySet()) { + if (entry.getKey().contains("=")) { + throw new ContainerExecutionException( + "'=' found in entry for docker command file, key = " + entry + .getKey() + "; value = " + entry.getValue()); + } + if (entry.getValue().contains("\n")) { + throw new ContainerExecutionException( + "'\\n' found in entry for docker command file, key = " + entry + .getKey() + "; value = " + entry.getValue()); + } + printWriter.println(" " + entry.getKey() + "=" + StringUtils + .join(",", entry.getValue())); + } + printWriter.close(); + + return dockerCommandFile.toString(); + } catch (IOException e) { + LOG.warn("Unable to write docker command to " + cmdDir); + throw new ContainerExecutionException(e); + } + } } 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/DockerCommandExecutor.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/DockerCommandExecutor.java index f11f4605b3a..6d9f4f446d7 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/DockerCommandExecutor.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/DockerCommandExecutor.java @@ -17,6 +17,8 @@ package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.server.nodemanager.Context; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationException; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationExecutor; @@ -76,11 +78,13 @@ private DockerCommandExecutor() { public static String executeDockerCommand(DockerCommand dockerCommand, String containerId, Map env, Configuration conf, PrivilegedOperationExecutor privilegedOperationExecutor, - boolean disableFailureLogging) + boolean disableFailureLogging, Context nmContext) throws ContainerExecutionException { DockerClient dockerClient = new DockerClient(conf); String commandFile = - dockerClient.writeCommandToTempFile(dockerCommand, containerId); + dockerClient.writeCommandToTempFile(dockerCommand, + nmContext.getContainers().get(ContainerId.fromString(containerId)) + , nmContext); PrivilegedOperation dockerOp = new PrivilegedOperation( PrivilegedOperation.OperationType.RUN_DOCKER_CMD); dockerOp.appendArgs(commandFile); @@ -116,11 +120,13 @@ public static String executeDockerCommand(DockerCommand dockerCommand, */ public static DockerContainerStatus getContainerStatus(String containerId, Configuration conf, - PrivilegedOperationExecutor privilegedOperationExecutor) { + PrivilegedOperationExecutor privilegedOperationExecutor, + Context nmContext) { try { DockerContainerStatus dockerContainerStatus; String currentContainerStatus = - executeStatusCommand(containerId, conf, privilegedOperationExecutor); + executeStatusCommand(containerId, conf, + privilegedOperationExecutor, nmContext); if (currentContainerStatus == null) { dockerContainerStatus = DockerContainerStatus.UNKNOWN; } else if (currentContainerStatus @@ -177,13 +183,15 @@ public static DockerContainerStatus getContainerStatus(String containerId, */ private static String executeStatusCommand(String containerId, Configuration conf, - PrivilegedOperationExecutor privilegedOperationExecutor) + PrivilegedOperationExecutor privilegedOperationExecutor, + Context nmContext) throws ContainerExecutionException { DockerInspectCommand dockerInspectCommand = new DockerInspectCommand(containerId).getContainerStatus(); try { return DockerCommandExecutor.executeDockerCommand(dockerInspectCommand, - containerId, null, conf, privilegedOperationExecutor, true); + containerId, null, conf, privilegedOperationExecutor, true, + nmContext); } catch (ContainerExecutionException e) { throw new ContainerExecutionException(e); } 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/linux/runtime/TestDockerContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java index 8fbfbe2db43..c468a25f6bd 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java @@ -30,8 +30,10 @@ import org.apache.hadoop.security.Credentials; import org.apache.hadoop.util.Shell; import org.apache.hadoop.util.StringUtils; +import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; +import org.apache.hadoop.yarn.server.nodemanager.LocalDirsHandlerService; import org.apache.hadoop.yarn.util.DockerClientConfigHandler; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.security.TestDockerClientConfigHandler; @@ -84,6 +86,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.concurrent.ConcurrentMap; import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.LinuxContainerRuntimeConstants.APPID; import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.LinuxContainerRuntimeConstants.APPLICATION_LOCAL_DIRS; @@ -104,6 +107,7 @@ import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.LinuxContainerRuntimeConstants.TC_COMMAND_FILE; import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.LinuxContainerRuntimeConstants.USER; import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.LinuxContainerRuntimeConstants.USER_FILECACHE_DIRS; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyList; @@ -123,7 +127,9 @@ private String containerId; private Container container; private ContainerId cId; + private ApplicationAttemptId appAttemptId; private ContainerLaunchContext context; + private Context nmContext; private HashMap env; private String image; private String uidGidPair; @@ -162,13 +168,15 @@ public void setup() { mockExecutor = Mockito .mock(PrivilegedOperationExecutor.class); mockCGroupsHandler = Mockito.mock(CGroupsHandler.class); - containerId = "container_id"; + containerId = "container_e11_1518975676334_14532816_01_000001"; container = mock(Container.class); cId = mock(ContainerId.class); + appAttemptId = mock(ApplicationAttemptId.class); context = mock(ContainerLaunchContext.class); env = new HashMap(); env.put("FROM_CLIENT", "1"); image = "busybox:latest"; + nmContext = createMockNMContext(); dockerStopGracePeriod = conf.getInt( YarnConfiguration.NM_DOCKER_STOP_GRACE_PERIOD, @@ -177,6 +185,7 @@ public void setup() { env.put(DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_IMAGE, image); when(container.getContainerId()).thenReturn(cId); when(cId.toString()).thenReturn(containerId); + when(cId.getApplicationAttemptId()).thenReturn(appAttemptId); when(container.getLaunchContext()).thenReturn(context); when(context.getEnvironment()).thenReturn(env); when(container.getUser()).thenReturn(submittingUser); @@ -265,6 +274,34 @@ public void setup() { .setExecutionAttribute(RESOURCES_OPTIONS, resourcesOptions); } + public Context createMockNMContext() { + Context mockNMContext = mock(Context.class); + LocalDirsHandlerService localDirsHandler = + mock(LocalDirsHandlerService.class); + ResourcePluginManager resourcePluginManager = + mock(ResourcePluginManager.class); + + String tmpPath = new StringBuffer(System.getProperty("test.build.data")) + .append('/').append("hadoop.tmp.dir").toString(); + + ConcurrentMap containerMap = + mock(ConcurrentMap.class); + + when(mockNMContext.getLocalDirsHandler()).thenReturn(localDirsHandler); + when(mockNMContext.getResourcePluginManager()) + .thenReturn(resourcePluginManager); + when(mockNMContext.getContainers()).thenReturn(containerMap); + when(containerMap.get(any())).thenReturn(container); + + try { + when(localDirsHandler.getLocalPathForWrite(anyString())) + .thenReturn(new Path(tmpPath)); + } catch (IOException ioe) { + LOG.info("LocalDirsHandler failed" + ioe); + } + return mockNMContext; + } + @Test public void testSelectDockerContainerType() { Map envDockerType = new HashMap<>(); @@ -341,7 +378,7 @@ public void testDockerContainerLaunch() IOException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); runtime.launchContainer(builder.build()); PrivilegedOperation op = capturePrivilegedOperationAndVerifyArgs(); @@ -368,7 +405,7 @@ public void testDockerContainerLaunch() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," + "/test_user_filecache_dir:/test_user_filecache_dir", @@ -390,7 +427,7 @@ public void testContainerLaunchWithUserRemapping() true); DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); runtime.launchContainer(builder.build()); PrivilegedOperation op = capturePrivilegedOperationAndVerifyArgs(); @@ -416,7 +453,7 @@ public void testContainerLaunchWithUserRemapping() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert .assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," @@ -439,7 +476,7 @@ public void testAllowedNetworksConfiguration() throws DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); //invalid default network configuration - sdn2 is included in allowed // networks @@ -455,7 +492,7 @@ public void testAllowedNetworksConfiguration() throws try { runtime = new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); Assert.fail("Invalid default network configuration should did not " + "trigger initialization failure."); } catch (ContainerExecutionException e) { @@ -471,7 +508,7 @@ public void testAllowedNetworksConfiguration() throws validDefaultNetwork); runtime = new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); } @Test @@ -481,7 +518,7 @@ public void testContainerLaunchWithNetworkingDefaults() PrivilegedOperationException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); Random randEngine = new Random(); String disallowedNetwork = "sdn" + Integer.toString(randEngine.nextInt()); @@ -532,7 +569,7 @@ public void testContainerLaunchWithNetworkingDefaults() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert .assertEquals(" net=" + allowedNetwork, dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," @@ -557,7 +594,7 @@ public void testContainerLaunchWithHostDnsNetwork() conf.setBoolean(RegistryConstants.KEY_DNS_ENABLED, true); DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); String expectedHostname = "test.hostname"; env.put(DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_HOSTNAME, @@ -590,7 +627,7 @@ public void testContainerLaunchWithHostDnsNetwork() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert .assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," @@ -628,7 +665,7 @@ public void testContainerLaunchWithCustomNetworks() customNetwork1); //this should cause no failures. - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); runtime.launchContainer(builder.build()); PrivilegedOperation op = capturePrivilegedOperationAndVerifyArgs(); List args = op.getArguments(); @@ -651,13 +688,13 @@ public void testContainerLaunchWithCustomNetworks() Assert.assertEquals(" docker-command=run", dockerCommands.get(counter++)); Assert.assertEquals(" group-add=" + String.join(",", groups), dockerCommands.get(counter++)); - Assert.assertEquals(" hostname=ctr-id", dockerCommands.get(counter++)); + Assert.assertEquals(" hostname=ctr-e11-1518975676334-14532816-01-000001", dockerCommands.get(counter++)); Assert .assertEquals(" image=busybox:latest", dockerCommands.get(counter++)); Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=sdn1", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," + "/test_user_filecache_dir:/test_user_filecache_dir", @@ -696,14 +733,14 @@ public void testContainerLaunchWithCustomNetworks() Assert.assertEquals(" docker-command=run", dockerCommands.get(counter++)); Assert.assertEquals(" group-add=" + String.join(",", groups), dockerCommands.get(counter++)); - Assert.assertEquals(" hostname=ctr-id", dockerCommands.get(counter++)); + Assert.assertEquals(" hostname=ctr-e11-1518975676334-14532816-01-000001", dockerCommands.get(counter++)); Assert .assertEquals(" image=busybox:latest", dockerCommands.get(counter++)); Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=sdn2", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," + "/test_user_filecache_dir:/test_user_filecache_dir", @@ -736,7 +773,7 @@ public void testLaunchPidNamespaceContainersInvalidEnvVar() IOException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put(DockerLinuxContainerRuntime .ENV_DOCKER_CONTAINER_PID_NAMESPACE, "invalid-value"); @@ -764,7 +801,7 @@ public void testLaunchPidNamespaceContainersWithDisabledSetting() throws ContainerExecutionException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put(DockerLinuxContainerRuntime .ENV_DOCKER_CONTAINER_PID_NAMESPACE, "host"); @@ -787,7 +824,7 @@ public void testLaunchPidNamespaceContainersEnabled() DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put(DockerLinuxContainerRuntime .ENV_DOCKER_CONTAINER_PID_NAMESPACE, "host"); @@ -817,7 +854,7 @@ public void testLaunchPidNamespaceContainersEnabled() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals(" pid=host", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," @@ -838,7 +875,7 @@ public void testLaunchPrivilegedContainersInvalidEnvVar() IOException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put(DockerLinuxContainerRuntime .ENV_DOCKER_CONTAINER_RUN_PRIVILEGED_CONTAINER, "invalid-value"); @@ -866,7 +903,7 @@ public void testLaunchPrivilegedContainersWithDisabledSetting() throws ContainerExecutionException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put(DockerLinuxContainerRuntime .ENV_DOCKER_CONTAINER_RUN_PRIVILEGED_CONTAINER, "true"); @@ -888,7 +925,7 @@ public void testLaunchPrivilegedContainersWithEnabledSettingAndDefaultACL() DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put(DockerLinuxContainerRuntime .ENV_DOCKER_CONTAINER_RUN_PRIVILEGED_CONTAINER, "true"); @@ -917,7 +954,7 @@ public void testLaunchPrivilegedContainersWithEnabledSettingAndDefaultACL() DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put(DockerLinuxContainerRuntime .ENV_DOCKER_CONTAINER_RUN_PRIVILEGED_CONTAINER, "true"); @@ -944,7 +981,7 @@ public void testLaunchPrivilegedContainersWithEnabledSettingAndDefaultACL() DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put(DockerLinuxContainerRuntime .ENV_DOCKER_CONTAINER_RUN_PRIVILEGED_CONTAINER, "true"); @@ -972,7 +1009,7 @@ public void testLaunchPrivilegedContainersWithEnabledSettingAndDefaultACL() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals(" privileged=true", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," @@ -996,7 +1033,7 @@ public void testCGroupParent() throws ContainerExecutionException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime (mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); String resourceOptionsNone = "cgroups=none"; DockerRunCommand command = Mockito.mock(DockerRunCommand.class); @@ -1023,7 +1060,7 @@ public void testCGroupParent() throws ContainerExecutionException { runtime = new DockerLinuxContainerRuntime (mockExecutor, null); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); runtime.addCGroupParentIfRequired(resourceOptionsNone, containerIdStr, command); @@ -1038,7 +1075,7 @@ public void testCGroupParent() throws ContainerExecutionException { public void testMountSourceOnly() throws ContainerExecutionException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put( DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_LOCAL_RESOURCE_MOUNTS, @@ -1058,7 +1095,7 @@ public void testMountSourceTarget() IOException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put( DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_LOCAL_RESOURCE_MOUNTS, @@ -1089,7 +1126,7 @@ public void testMountSourceTarget() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals( " ro-mounts=/test_filecache_dir:/test_filecache_dir,/" @@ -1109,7 +1146,7 @@ public void testMountSourceTarget() public void testMountInvalid() throws ContainerExecutionException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put( DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_LOCAL_RESOURCE_MOUNTS, @@ -1129,7 +1166,7 @@ public void testMountMultiple() IOException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put( DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_LOCAL_RESOURCE_MOUNTS, @@ -1161,7 +1198,7 @@ public void testMountMultiple() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals( " ro-mounts=/test_filecache_dir:/test_filecache_dir," @@ -1184,7 +1221,7 @@ public void testUserMounts() IOException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put( DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_MOUNTS, @@ -1215,7 +1252,7 @@ public void testUserMounts() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," + "/test_user_filecache_dir:/test_user_filecache_dir," @@ -1235,7 +1272,7 @@ public void testUserMounts() public void testUserMountInvalid() throws ContainerExecutionException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put( DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_MOUNTS, @@ -1253,7 +1290,7 @@ public void testUserMountInvalid() throws ContainerExecutionException { public void testUserMountModeInvalid() throws ContainerExecutionException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put( DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_MOUNTS, @@ -1271,7 +1308,7 @@ public void testUserMountModeInvalid() throws ContainerExecutionException { public void testUserMountModeNulInvalid() throws ContainerExecutionException { DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); env.put( DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_MOUNTS, @@ -1318,7 +1355,7 @@ public void testDockerStopOnTermSignalWhenRunning() Assert.assertEquals(4, dockerCommands.size()); Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0)); Assert.assertEquals(" docker-command=stop", dockerCommands.get(1)); - Assert.assertEquals(" name=container_id", dockerCommands.get(2)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(2)); Assert.assertEquals(" time=10", dockerCommands.get(3)); } @@ -1332,7 +1369,7 @@ public void testDockerStopOnKillSignalWhenRunning() Assert.assertEquals(4, dockerCommands.size()); Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0)); Assert.assertEquals(" docker-command=stop", dockerCommands.get(1)); - Assert.assertEquals(" name=container_id", dockerCommands.get(2)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(2)); Assert.assertEquals(" time=10", dockerCommands.get(3)); } @@ -1344,7 +1381,7 @@ public void testDockerKillOnQuitSignalWhenRunning() throws Exception { Assert.assertEquals(4, dockerCommands.size()); Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0)); Assert.assertEquals(" docker-command=kill", dockerCommands.get(1)); - Assert.assertEquals(" name=container_id", dockerCommands.get(2)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(2)); Assert.assertEquals(" signal=QUIT", dockerCommands.get(3)); } @@ -1563,7 +1600,7 @@ private void testDockerCommandPluginWithVolumesOutput( any(File.class), anyMap(), anyBoolean(), anyBoolean())).thenReturn( dockerVolumeListOutput); - Context nmContext = mock(Context.class); + Context mockNMContext = createMockNMContext(); ResourcePluginManager rpm = mock(ResourcePluginManager.class); Map pluginsMap = new HashMap<>(); ResourcePlugin plugin1 = mock(ResourcePlugin.class); @@ -1580,9 +1617,9 @@ private void testDockerCommandPluginWithVolumesOutput( when(rpm.getNameToPlugins()).thenReturn(pluginsMap); - when(nmContext.getResourcePluginManager()).thenReturn(rpm); + when(mockNMContext.getResourcePluginManager()).thenReturn(rpm); - runtime.initialize(conf, nmContext); + runtime.initialize(conf, mockNMContext); ContainerRuntimeContext containerRuntimeContext = builder.build(); @@ -1660,7 +1697,7 @@ public void testDockerCommandPlugin() throws Exception { any(File.class), anyMap(), anyBoolean(), anyBoolean())).thenReturn( "volume1,local"); - Context nmContext = mock(Context.class); + Context mockNMContext = createMockNMContext(); ResourcePluginManager rpm = mock(ResourcePluginManager.class); Map pluginsMap = new HashMap<>(); ResourcePlugin plugin1 = mock(ResourcePlugin.class); @@ -1677,9 +1714,9 @@ public void testDockerCommandPlugin() throws Exception { when(rpm.getNameToPlugins()).thenReturn(pluginsMap); - when(nmContext.getResourcePluginManager()).thenReturn(rpm); + when(mockNMContext.getResourcePluginManager()).thenReturn(rpm); - runtime.initialize(conf, nmContext); + runtime.initialize(conf, mockNMContext); ContainerRuntimeContext containerRuntimeContext = builder.build(); @@ -1711,7 +1748,7 @@ public void testDockerCommandPlugin() throws Exception { Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," + "/test_user_filecache_dir:/test_user_filecache_dir," @@ -1737,7 +1774,7 @@ public void testDockerCapabilities() throws ContainerExecutionException { try { conf.setStrings(YarnConfiguration.NM_DOCKER_CONTAINER_CAPABILITIES, "none", "CHOWN", "DAC_OVERRIDE"); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); Assert.fail("Initialize didn't fail with invalid capabilities " + "'none', 'CHOWN', 'DAC_OVERRIDE'"); } catch (ContainerExecutionException e) { @@ -1746,7 +1783,7 @@ public void testDockerCapabilities() throws ContainerExecutionException { try { conf.setStrings(YarnConfiguration.NM_DOCKER_CONTAINER_CAPABILITIES, "CHOWN", "DAC_OVERRIDE", "NONE"); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); Assert.fail("Initialize didn't fail with invalid capabilities " + "'CHOWN', 'DAC_OVERRIDE', 'NONE'"); } catch (ContainerExecutionException e) { @@ -1754,17 +1791,17 @@ public void testDockerCapabilities() throws ContainerExecutionException { conf.setStrings(YarnConfiguration.NM_DOCKER_CONTAINER_CAPABILITIES, "NONE"); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); Assert.assertEquals(0, runtime.getCapabilities().size()); conf.setStrings(YarnConfiguration.NM_DOCKER_CONTAINER_CAPABILITIES, "none"); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); Assert.assertEquals(0, runtime.getCapabilities().size()); conf.setStrings(YarnConfiguration.NM_DOCKER_CONTAINER_CAPABILITIES, "CHOWN", "DAC_OVERRIDE"); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); Iterator it = runtime.getCapabilities().iterator(); Assert.assertEquals("CHOWN", it.next()); Assert.assertEquals("DAC_OVERRIDE", it.next()); @@ -1792,7 +1829,7 @@ public void testLaunchContainerWithDockerTokens() when(context.getTokens()).thenReturn(tokens); DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler); - runtime.initialize(conf, null); + runtime.initialize(conf, nmContext); Set perms = PosixFilePermissions.fromString("rwxr-xr--"); @@ -1852,7 +1889,7 @@ public void testLaunchContainerWithDockerTokens() Assert.assertEquals( " launch-command=bash,/test_container_work_dir/launch_container.sh", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter++)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter++)); Assert.assertEquals(" net=host", dockerCommands.get(counter++)); Assert.assertEquals(" ro-mounts=/test_filecache_dir:/test_filecache_dir," + "/test_user_filecache_dir:/test_user_filecache_dir", @@ -1889,7 +1926,7 @@ public void testDockerContainerRelaunch() dockerCommands.get(counter++)); Assert.assertEquals(" docker-command=start", dockerCommands.get(counter++)); - Assert.assertEquals(" name=container_id", dockerCommands.get(counter)); + Assert.assertEquals(" name=container_e11_1518975676334_14532816_01_000001", dockerCommands.get(counter)); } class MockRuntime extends DockerLinuxContainerRuntime { @@ -1922,7 +1959,8 @@ public void signalContainer(ContainerRuntimeContext ctx) new DockerStopCommand(containerName) .setGracePeriod(dockerStopGracePeriod); DockerCommandExecutor.executeDockerCommand(dockerStopCommand, - containerName, environment, conf, mockExecutor, false); + containerName, environment, conf, mockExecutor, false, + nmContext); } } else { if (DockerCommandExecutor.isKillable(containerStatus)) { @@ -1930,7 +1968,8 @@ public void signalContainer(ContainerRuntimeContext ctx) new DockerKillCommand(containerName); dockerKillCommand.setSignal(signal.name()); DockerCommandExecutor.executeDockerCommand(dockerKillCommand, - containerName, environment, conf, mockExecutor, false); + containerName, environment, conf, mockExecutor, false, + nmContext); } } } catch (ContainerExecutionException e) { @@ -1953,7 +1992,7 @@ public void reapContainer(ContainerRuntimeContext ctx) DockerRmCommand dockerRmCommand = new DockerRmCommand(containerId); DockerCommandExecutor .executeDockerCommand(dockerRmCommand, containerId, env, conf, - privilegedOperationExecutor, false); + privilegedOperationExecutor, false, nmContext); } } } 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/linux/runtime/docker/TestDockerCommandExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/TestDockerCommandExecutor.java index 94da90ba19b..11fdc940c32 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/TestDockerCommandExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/TestDockerCommandExecutor.java @@ -17,9 +17,13 @@ package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; import org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor; +import org.apache.hadoop.yarn.server.nodemanager.Context; +import org.apache.hadoop.yarn.server.nodemanager.LocalDirsHandlerService; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.MockPrivilegedOperationCaptor; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation; @@ -39,13 +43,16 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.concurrent.ConcurrentMap; import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.LinuxContainerRuntimeConstants.CONTAINER_ID_STR; import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerCommandExecutor.DockerContainerStatus; +import static org.eclipse.jetty.server.handler.gzip.GzipHttpOutputInterceptor.LOG; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -55,7 +62,7 @@ */ public class TestDockerCommandExecutor { - private static final String MOCK_CONTAINER_ID = "container_id"; + private static final String MOCK_CONTAINER_ID = "container_e11_1861047502093_13763105_01_000001"; private static final String MOCK_LOCAL_IMAGE_NAME = "local_image_name"; private static final String MOCK_IMAGE_NAME = "image_name"; @@ -68,21 +75,29 @@ private ContainerId cId; private ContainerLaunchContext context; private HashMap env; + private Context nmContext; + private ApplicationAttemptId appAttemptId; @Before public void setUp() throws Exception { mockExecutor = mock(PrivilegedOperationExecutor.class); mockCGroupsHandler = mock(CGroupsHandler.class); configuration = new Configuration(); + String tmpPath = new StringBuffer(System.getProperty("test.build.data")) + .append('/').append("hadoop.tmp.dir").toString(); + configuration.set("hadoop.tmp.dir", tmpPath); runtime = new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler); container = mock(Container.class); cId = mock(ContainerId.class); context = mock(ContainerLaunchContext.class); env = new HashMap<>(); builder = new ContainerRuntimeContext.Builder(container); + nmContext = createMockNMContext(); + appAttemptId = mock(ApplicationAttemptId.class); when(container.getContainerId()).thenReturn(cId); when(cId.toString()).thenReturn(MOCK_CONTAINER_ID); + when(cId.getApplicationAttemptId()).thenReturn(appAttemptId); when(container.getLaunchContext()).thenReturn(context); when(context.getEnvironment()).thenReturn(env); @@ -92,12 +107,37 @@ public void setUp() throws Exception { null); } + + public Context createMockNMContext() { + Context mockNMContext = mock(Context.class); + LocalDirsHandlerService localDirsHandler = + mock(LocalDirsHandlerService.class); + + String tmpPath = new StringBuffer(System.getProperty("test.build.data")) + .append('/').append("hadoop.tmp.dir").toString(); + + ConcurrentMap containerMap = + mock(ConcurrentMap.class); + + when(mockNMContext.getLocalDirsHandler()).thenReturn(localDirsHandler); + when(mockNMContext.getContainers()).thenReturn(containerMap); + when(containerMap.get(any())).thenReturn(container); + + try { + when(localDirsHandler.getLocalPathForWrite(anyString())) + .thenReturn(new Path(tmpPath)); + } catch (IOException ioe) { + LOG.info("LocalDirsHandler failed" + ioe); + } + return mockNMContext; + } + @Test public void testExecuteDockerCommand() throws Exception { DockerStopCommand dockerStopCommand = new DockerStopCommand(MOCK_CONTAINER_ID); DockerCommandExecutor.executeDockerCommand(dockerStopCommand, - cId.toString(), env, configuration, mockExecutor, false); + cId.toString(), env, configuration, mockExecutor, false, nmContext); List ops = MockPrivilegedOperationCaptor .capturePrivilegedOperations(mockExecutor, 1, true); assertEquals(1, ops.size()); @@ -109,7 +149,7 @@ public void testExecuteDockerCommand() throws Exception { public void testExecuteDockerRm() throws Exception { DockerRmCommand dockerCommand = new DockerRmCommand(MOCK_CONTAINER_ID); DockerCommandExecutor.executeDockerCommand(dockerCommand, MOCK_CONTAINER_ID, - env, configuration, mockExecutor, false); + env, configuration, mockExecutor, false, nmContext); List ops = MockPrivilegedOperationCaptor .capturePrivilegedOperations(mockExecutor, 1, true); List dockerCommands = getValidatedDockerCommands(ops); @@ -126,7 +166,7 @@ public void testExecuteDockerRm() throws Exception { public void testExecuteDockerStop() throws Exception { DockerStopCommand dockerCommand = new DockerStopCommand(MOCK_CONTAINER_ID); DockerCommandExecutor.executeDockerCommand(dockerCommand, MOCK_CONTAINER_ID, - env, configuration, mockExecutor, false); + env, configuration, mockExecutor, false, nmContext); List ops = MockPrivilegedOperationCaptor .capturePrivilegedOperations(mockExecutor, 1, true); List dockerCommands = getValidatedDockerCommands(ops); @@ -144,7 +184,7 @@ public void testExecuteDockerInspectStatus() throws Exception { DockerInspectCommand dockerCommand = new DockerInspectCommand(MOCK_CONTAINER_ID).getContainerStatus(); DockerCommandExecutor.executeDockerCommand(dockerCommand, MOCK_CONTAINER_ID, - env, configuration, mockExecutor, false); + env, configuration, mockExecutor, false, nmContext); List ops = MockPrivilegedOperationCaptor .capturePrivilegedOperations(mockExecutor, 1, true); List dockerCommands = getValidatedDockerCommands(ops); @@ -164,7 +204,7 @@ public void testExecuteDockerPull() throws Exception { DockerPullCommand dockerCommand = new DockerPullCommand(MOCK_IMAGE_NAME); DockerCommandExecutor.executeDockerCommand(dockerCommand, MOCK_CONTAINER_ID, - env, configuration, mockExecutor, false); + env, configuration, mockExecutor, false, nmContext); List ops = MockPrivilegedOperationCaptor .capturePrivilegedOperations(mockExecutor, 1, true); List dockerCommands = getValidatedDockerCommands(ops); @@ -182,7 +222,7 @@ public void testExecuteDockerLoad() throws Exception { DockerLoadCommand dockerCommand = new DockerLoadCommand(MOCK_LOCAL_IMAGE_NAME); DockerCommandExecutor.executeDockerCommand(dockerCommand, MOCK_CONTAINER_ID, - env, configuration, mockExecutor, false); + env, configuration, mockExecutor, false, nmContext); List ops = MockPrivilegedOperationCaptor .capturePrivilegedOperations(mockExecutor, 1, true); List dockerCommands = getValidatedDockerCommands(ops); @@ -204,7 +244,7 @@ public void testGetContainerStatus() throws Exception { any(PrivilegedOperation.class), eq(null), any(), eq(true), eq(false))) .thenReturn(status.getName()); assertEquals(status, DockerCommandExecutor.getContainerStatus( - MOCK_CONTAINER_ID, configuration, mockExecutor)); + MOCK_CONTAINER_ID, configuration, mockExecutor, nmContext)); } } @@ -214,7 +254,7 @@ public void testExecuteDockerKillSIGQUIT() throws Exception { new DockerKillCommand(MOCK_CONTAINER_ID) .setSignal(ContainerExecutor.Signal.QUIT.name()); DockerCommandExecutor.executeDockerCommand(dockerKillCommand, - MOCK_CONTAINER_ID, env, configuration, mockExecutor, false); + MOCK_CONTAINER_ID, env, configuration, mockExecutor, false, nmContext); List ops = MockPrivilegedOperationCaptor .capturePrivilegedOperations(mockExecutor, 1, true); List dockerCommands = getValidatedDockerCommands(ops); @@ -235,7 +275,7 @@ public void testExecuteDockerKillSIGKILL() throws Exception { new DockerKillCommand(MOCK_CONTAINER_ID) .setSignal(ContainerExecutor.Signal.KILL.name()); DockerCommandExecutor.executeDockerCommand(dockerKillCommand, - MOCK_CONTAINER_ID, env, configuration, mockExecutor, false); + MOCK_CONTAINER_ID, env, configuration, mockExecutor, false, nmContext); List ops = MockPrivilegedOperationCaptor .capturePrivilegedOperations(mockExecutor, 1, true); List dockerCommands = getValidatedDockerCommands(ops); @@ -256,7 +296,7 @@ public void testExecuteDockerKillSIGTERM() throws Exception { new DockerKillCommand(MOCK_CONTAINER_ID) .setSignal(ContainerExecutor.Signal.TERM.name()); DockerCommandExecutor.executeDockerCommand(dockerKillCommand, - MOCK_CONTAINER_ID, env, configuration, mockExecutor, false); + MOCK_CONTAINER_ID, env, configuration, mockExecutor, false, nmContext); List ops = MockPrivilegedOperationCaptor .capturePrivilegedOperations(mockExecutor, 1, true); List dockerCommands = getValidatedDockerCommands(ops);