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/provider/docker/DockerProviderService.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/provider/docker/DockerProviderService.java index 7844621b4ae..3397e5c8e84 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/provider/docker/DockerProviderService.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/provider/docker/DockerProviderService.java @@ -54,18 +54,20 @@ public void processArtifact(AbstractLauncher launcher, * Check if system is default to disable docker override or * user requested a Docker container with ENTRY_POINT support. * - * @param component - YARN Service component + * @param compLaunchContext - launch context for the component. * @return true if Docker launch command override is disabled */ - private boolean checkUseEntryPoint(Component component) { + private boolean checkUseEntryPoint( + ContainerLaunchService.ComponentLaunchContext compLaunchContext) { boolean overrideDisable = false; String overrideDisableKey = Environment. YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE. name(); - String overrideDisableValue = (component - .getConfiguration().getEnv(overrideDisableKey) != null) ? - component.getConfiguration().getEnv(overrideDisableKey) : - System.getenv(overrideDisableKey); + String overrideDisableValue = ( + compLaunchContext.getConfiguration().getEnv(overrideDisableKey) + != null) ? + compLaunchContext.getConfiguration().getEnv( + overrideDisableKey) : System.getenv(overrideDisableKey); overrideDisable = Boolean.parseBoolean(overrideDisableValue); return overrideDisable; } @@ -77,10 +79,9 @@ public void buildContainerLaunchCommand(AbstractLauncher launcher, ContainerLaunchService.ComponentLaunchContext compLaunchContext, Map tokensForSubstitution) throws IOException, SliderException { - Component component = instance.getComponent().getComponentSpec(); - boolean useEntryPoint = checkUseEntryPoint(component); + boolean useEntryPoint = checkUseEntryPoint(compLaunchContext); if (useEntryPoint) { - String launchCommand = component.getLaunchCommand(); + String launchCommand = compLaunchContext.getLaunchCommand(); if (!StringUtils.isEmpty(launchCommand)) { launcher.addCommand(launchCommand); } 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/provider/TestAbstractProviderService.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/provider/TestAbstractProviderService.java new file mode 100644 index 00000000000..310d6fa7728 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/provider/TestAbstractProviderService.java @@ -0,0 +1,85 @@ +/* + * 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.provider; + +import com.google.common.collect.Lists; +import org.apache.hadoop.yarn.api.records.Container; +import org.apache.hadoop.yarn.service.MockRunningServiceContext; +import org.apache.hadoop.yarn.service.ServiceTestUtils; +import org.apache.hadoop.yarn.service.TestServiceManager; +import org.apache.hadoop.yarn.service.api.records.Artifact; +import org.apache.hadoop.yarn.service.api.records.Service; +import org.apache.hadoop.yarn.service.component.Component; +import org.apache.hadoop.yarn.service.component.instance.ComponentInstance; +import org.apache.hadoop.yarn.service.containerlaunch.AbstractLauncher; +import org.apache.hadoop.yarn.service.containerlaunch.ContainerLaunchService; +import org.apache.hadoop.yarn.service.provider.docker.DockerProviderService; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link AbstractProviderService} + */ +public class TestAbstractProviderService { + + @Rule + public ServiceTestUtils.ServiceFSWatcher rule = + new ServiceTestUtils.ServiceFSWatcher(); + + @Test + public void testBuildContainerLaunchCommand() throws Exception { + AbstractProviderService providerService = new DockerProviderService(); + Service service = TestServiceManager.createBaseDef("testLaunchCommand"); + MockRunningServiceContext sc = new MockRunningServiceContext(rule, service); + + Component component = sc.scheduler.getAllComponents().entrySet() + .iterator().next().getValue(); + //preparing component launch context + String launchCmd = "sleep,9000"; + Artifact artifact = new Artifact(); + artifact.setType(Artifact.TypeEnum.DOCKER); + artifact.setId("example"); + Map env = new HashMap<>(); + env.put("YARN_CONTAINER_RUNTIME_DOCKER_DELAYED_REMOVAL", "true"); + env.put("YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE", "true"); + component.getComponentSpec().getConfiguration().setEnv(env); + + ContainerLaunchService.ComponentLaunchContext clc = new + ContainerLaunchService.ComponentLaunchContext(component.getName(), + service.getVersion()) + .setArtifact(artifact) + .setConfiguration(component.getComponentSpec().getConfiguration()) + .setLaunchCommand(launchCmd); + + AbstractLauncher launcher = new AbstractLauncher(sc); + ComponentInstance instance = component.getAllComponentInstances().iterator() + .next(); + Container container = mock(Container.class); + providerService.buildContainerLaunchCommand(launcher, service, instance, + rule.getFs(), sc.scheduler.getConfig(), container, clc, null); + + Assert.assertEquals(Lists.newArrayList(launchCmd), launcher.getCommands()); + } +} 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/launcher/ContainerLaunch.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java index 04295e13678..ae6f427b606 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java @@ -43,6 +43,8 @@ import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; @@ -136,6 +138,8 @@ protected final LocalDirsHandlerService dirsHandler; + private final Lock containerExecLock = new ReentrantLock(); + public ContainerLaunch(Context context, Configuration configuration, Dispatcher dispatcher, ContainerExecutor exec, Application app, Container container, LocalDirsHandlerService dirsHandler, @@ -486,7 +490,12 @@ protected int launchContainer(ContainerStartContext ctx) throws IOException, ConfigurationException { int launchPrep = prepareForLaunch(ctx); if (launchPrep == 0) { - return exec.launchContainer(ctx); + containerExecLock.lock(); + try { + return exec.launchContainer(ctx); + } finally { + containerExecLock.unlock(); + } } return launchPrep; } @@ -495,7 +504,12 @@ protected int relaunchContainer(ContainerStartContext ctx) throws IOException, ConfigurationException { int launchPrep = prepareForLaunch(ctx); if (launchPrep == 0) { - return exec.relaunchContainer(ctx); + containerExecLock.lock(); + try { + return exec.relaunchContainer(ctx); + } finally { + containerExecLock.unlock(); + } } return launchPrep; } @@ -807,18 +821,22 @@ public void cleanupContainer() throws IOException { lfs.delete(pidFilePath.suffix(EXIT_CODE_FILE_SUFFIX), false); } } - - // Reap the container - boolean result = exec.reapContainer( - new ContainerReapContext.Builder() - .setContainer(container) - .setUser(container.getUser()) - .build()); - if (!result) { - throw new IOException("Reap container failed for container " - + containerIdStr); + containerExecLock.lock(); + try { + // Reap the container + boolean result = exec.reapContainer( + new ContainerReapContext.Builder() + .setContainer(container) + .setUser(container.getUser()) + .build()); + if (!result) { + throw new IOException("Reap container failed for container " + + containerIdStr); + } + cleanupContainerFiles(getContainerWorkDir()); + } finally { + containerExecLock.unlock(); } - cleanupContainerFiles(getContainerWorkDir()); } /**