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 9c05c593503..194158b88b4 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 @@ -25,7 +25,6 @@ import org.apache.hadoop.yarn.server.nodemanager.Context; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerCommandExecutor; -import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerKillCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerRmCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerStartCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerVolumeCommand; @@ -990,13 +989,10 @@ public void signalContainer(ContainerRuntimeContext ctx) try { if (ContainerExecutor.Signal.NULL.equals(signal)) { executeLivelinessCheck(ctx); + } else if (ContainerExecutor.Signal.TERM.equals(signal)) { + handleContainerStop(containerId, env); } else { - if (ContainerExecutor.Signal.KILL.equals(signal) - || ContainerExecutor.Signal.TERM.equals(signal)) { - handleContainerStop(containerId, env); - } else { - handleContainerKill(containerId, env, signal); - } + handleContainerKill(ctx); } } catch (ContainerExecutionException e) { LOG.warn("Signal docker container failed. Exception: ", e); @@ -1204,22 +1200,25 @@ private void handleContainerStop(String containerId, Map env) } } - private void handleContainerKill(String containerId, Map env, - ContainerExecutor.Signal signal) throws ContainerExecutionException { - DockerCommandExecutor.DockerContainerStatus containerStatus = - DockerCommandExecutor.getContainerStatus(containerId, conf, - privilegedOperationExecutor, nmContext); - if (DockerCommandExecutor.isKillable(containerStatus)) { - DockerKillCommand dockerKillCommand = - new DockerKillCommand(containerId).setSignal(signal.name()); - DockerCommandExecutor.executeDockerCommand(dockerKillCommand, containerId, - env, conf, privilegedOperationExecutor, false, nmContext); - } else { - if (LOG.isDebugEnabled()) { - LOG.debug( - "Container status is " + containerStatus.getName() - + ", skipping kill - " + containerId); - } + private void handleContainerKill(ContainerRuntimeContext ctx) + throws ContainerExecutionException { + PrivilegedOperation privOp = new PrivilegedOperation( + PrivilegedOperation.OperationType.SIGNAL_CONTAINER); + privOp.appendArgs(ctx.getExecutionAttribute(RUN_AS_USER), + ctx.getExecutionAttribute(USER), + Integer.toString(PrivilegedOperation.RunAsUserCommand + .SIGNAL_CONTAINER.getValue()), + ctx.getExecutionAttribute(PID), + Integer.toString(ctx.getExecutionAttribute(SIGNAL).getValue())); + privOp.disableFailureLogging(); + try { + privilegedOperationExecutor.executePrivilegedOperation(null, + privOp, null, null, false, false); + } catch (PrivilegedOperationException e) { + //Don't log the failure here. Some kinds of signaling failures are + // acceptable. Let the calling executor decide what to do. + throw new ContainerExecutionException("Signal container failed", e + .getExitCode(), e.getOutput(), e.getErrorOutput()); } } 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 6ad35b2a43b..a0876eebad4 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 @@ -46,7 +46,6 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.CGroupsHandler; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerClient; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerCommandExecutor; -import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerKillCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerRmCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerRunCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerStartCommand; @@ -1375,7 +1374,7 @@ public void testContainerLivelinessCheck() public void testDockerStopOnTermSignalWhenRunning() throws ContainerExecutionException, PrivilegedOperationException, IOException { - List dockerCommands = getDockerCommandsForSignal( + List dockerCommands = getDockerCommandsForDockerStop( ContainerExecutor.Signal.TERM, DockerCommandExecutor.DockerContainerStatus.RUNNING); Assert.assertEquals(4, dockerCommands.size()); @@ -1394,13 +1393,17 @@ public void testDockerStopOnKillSignalWhenRunning() List dockerCommands = getDockerCommandsForSignal( ContainerExecutor.Signal.KILL, DockerCommandExecutor.DockerContainerStatus.RUNNING); - Assert.assertEquals(4, dockerCommands.size()); - Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0)); - Assert.assertEquals(" docker-command=stop", dockerCommands.get(1)); + Assert.assertEquals(5, dockerCommands.size()); + Assert.assertEquals(runAsUser, dockerCommands.get(0)); + Assert.assertEquals(user, dockerCommands.get(1)); Assert.assertEquals( - " name=container_e11_1518975676334_14532816_01_000001", + Integer.toString(PrivilegedOperation.RunAsUserCommand + .SIGNAL_CONTAINER.getValue()), dockerCommands.get(2)); - Assert.assertEquals(" time=10", dockerCommands.get(3)); + Assert.assertEquals(signalPid, dockerCommands.get(3)); + Assert.assertEquals( + Integer.toString(ContainerExecutor.Signal.KILL.getValue()), + dockerCommands.get(4)); } @Test @@ -1408,13 +1411,17 @@ public void testDockerKillOnQuitSignalWhenRunning() throws Exception { List dockerCommands = getDockerCommandsForSignal( ContainerExecutor.Signal.QUIT, DockerCommandExecutor.DockerContainerStatus.RUNNING); - Assert.assertEquals(4, dockerCommands.size()); - Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0)); - Assert.assertEquals(" docker-command=kill", dockerCommands.get(1)); + Assert.assertEquals(5, dockerCommands.size()); + Assert.assertEquals(runAsUser, dockerCommands.get(0)); + Assert.assertEquals(user, dockerCommands.get(1)); Assert.assertEquals( - " name=container_e11_1518975676334_14532816_01_000001", + Integer.toString(PrivilegedOperation.RunAsUserCommand + .SIGNAL_CONTAINER.getValue()), dockerCommands.get(2)); - Assert.assertEquals(" signal=QUIT", dockerCommands.get(3)); + Assert.assertEquals(signalPid, dockerCommands.get(3)); + Assert.assertEquals( + Integer.toString(ContainerExecutor.Signal.QUIT.getValue()), + dockerCommands.get(4)); } @Test @@ -1450,7 +1457,7 @@ public void testNoDockerRmWhenDelayedDeletionEnabled() File.class), anyMap(), anyBoolean(), anyBoolean()); } - private List getDockerCommandsForSignal( + private List getDockerCommandsForDockerStop( ContainerExecutor.Signal signal, DockerCommandExecutor.DockerContainerStatus status) throws ContainerExecutionException, PrivilegedOperationException, @@ -1472,6 +1479,26 @@ public void testNoDockerRmWhenDelayedDeletionEnabled() Charset.forName("UTF-8")); } + private List getDockerCommandsForSignal( + ContainerExecutor.Signal signal, + DockerCommandExecutor.DockerContainerStatus status) + throws ContainerExecutionException, PrivilegedOperationException, + IOException { + + MockRuntime runtime = new MockRuntime(mockExecutor, status, false); + builder.setExecutionAttribute(RUN_AS_USER, runAsUser) + .setExecutionAttribute(USER, user) + .setExecutionAttribute(PID, signalPid) + .setExecutionAttribute(SIGNAL, signal); + runtime.initialize(enableMockContainerExecutor(conf), null); + runtime.signalContainer(builder.build()); + + PrivilegedOperation op = capturePrivilegedOperation(); + Assert.assertEquals(op.getOperationType(), + PrivilegedOperation.OperationType.SIGNAL_CONTAINER); + return op.getArguments(); + } + /** * Return a configuration object with the mock container executor binary * preconfigured. @@ -2003,8 +2030,7 @@ public void signalContainer(ContainerRuntimeContext ctx) Map environment = ctx.getContainer().getLaunchContext().getEnvironment(); try { - if (ContainerExecutor.Signal.KILL.equals(signal) - || ContainerExecutor.Signal.TERM.equals(signal)) { + if (ContainerExecutor.Signal.TERM.equals(signal)) { if (DockerCommandExecutor.isStoppable(containerStatus)) { DockerStopCommand dockerStopCommand = new DockerStopCommand(containerName) @@ -2014,13 +2040,22 @@ public void signalContainer(ContainerRuntimeContext ctx) nmContext); } } else { - if (DockerCommandExecutor.isKillable(containerStatus)) { - DockerKillCommand dockerKillCommand = - new DockerKillCommand(containerName); - dockerKillCommand.setSignal(signal.name()); - DockerCommandExecutor.executeDockerCommand(dockerKillCommand, - containerName, environment, conf, mockExecutor, false, - nmContext); + PrivilegedOperation privOp = new PrivilegedOperation( + PrivilegedOperation.OperationType.SIGNAL_CONTAINER); + privOp.appendArgs(ctx.getExecutionAttribute(RUN_AS_USER), + ctx.getExecutionAttribute(USER), + Integer.toString(PrivilegedOperation.RunAsUserCommand + .SIGNAL_CONTAINER.getValue()), + ctx.getExecutionAttribute(PID), + Integer.toString(ctx.getExecutionAttribute(SIGNAL).getValue())); + try { + mockExecutor.executePrivilegedOperation(null, + privOp, null, null, false, false); + } catch (PrivilegedOperationException e) { + //Don't log the failure here. Some kinds of signaling failures are + // acceptable. Let the calling executor decide what to do. + throw new ContainerExecutionException("Signal container failed", e + .getExitCode(), e.getOutput(), e.getErrorOutput()); } } } catch (ContainerExecutionException e) {