瀏覽代碼

MAPREDUCE-3067. Ensure exit-code is set correctly for containers. Contributed by Hitesh Shah.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1176235 13f79535-47bb-0310-9956-ffa450edef68
Arun Murthy 13 年之前
父節點
當前提交
17da0bdb27

+ 3 - 0
hadoop-mapreduce-project/CHANGES.txt

@@ -1438,6 +1438,9 @@ Release 0.23.0 - Unreleased
     MAPREDUCE-3071. app master configuration web UI link under the Job menu 
     opens up application menu. (thomas graves  via mahadev)
 
+    MAPREDUCE-3067. Ensure exit-code is set correctly for containers. (Hitesh
+    Shah via acmurthy)
+
 Release 0.22.0 - Unreleased
 
   INCOMPATIBLE CHANGES

+ 3 - 0
hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/container/ContainerImpl.java

@@ -567,6 +567,9 @@ public class ContainerImpl implements Container {
 
     @Override
     public void transition(ContainerImpl container, ContainerEvent event) {
+      // Set exit code to 0 on success    	
+      container.exitCode = 0;
+    	
       // TODO: Add containerWorkDir to the deletion service.
 
       if (clCleanupRequired) {

+ 24 - 0
hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestContainerManagerWithLCE.java

@@ -105,7 +105,31 @@ public class TestContainerManagerWithLCE extends TestContainerManager {
     LOG.info("Running testContainerLaunchAndStop");
     super.testContainerLaunchAndStop();
   }
+  
+  @Override
+  public void testContainerLaunchAndExitSuccess() throws IOException,
+      InterruptedException {
+    // Don't run the test if the binary is not available.
+    if (!shouldRunTest()) {
+      LOG.info("LCE binary path is not passed. Not running the test");
+      return;
+    }
+    LOG.info("Running testContainerLaunchAndExitSuccess");
+    super.testContainerLaunchAndExitSuccess();
+  }
 
+  @Override
+  public void testContainerLaunchAndExitFailure() throws IOException,
+      InterruptedException {
+    // Don't run the test if the binary is not available.
+    if (!shouldRunTest()) {
+      LOG.info("LCE binary path is not passed. Not running the test");
+      return;
+    }
+    LOG.info("Running testContainerLaunchAndExitFailure");
+    super.testContainerLaunchAndExitFailure();
+  }
+  
   @Override
   public void testLocalFilesCleanup() throws InterruptedException,
       IOException {

+ 88 - 0
hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestContainerManager.java

@@ -287,7 +287,95 @@ public class TestContainerManager extends BaseContainerManagerTest {
         exec.signalContainer(user,
             pid, Signal.NULL));
   }
+  
+  private void testContainerLaunchAndExit(int exitCode) throws IOException, InterruptedException {
+
+	  File scriptFile = new File(tmpDir, "scriptFile.sh");
+	  PrintWriter fileWriter = new PrintWriter(scriptFile);
+	  File processStartFile =
+			  new File(tmpDir, "start_file.txt").getAbsoluteFile();
+	  fileWriter.write("\numask 0"); // So that start file is readable by the test
+	  fileWriter.write("\necho Hello World! > " + processStartFile);
+	  fileWriter.write("\necho $$ >> " + processStartFile); 
+
+	  // Have script throw an exit code at the end
+	  if (exitCode != 0) {
+		  fileWriter.write("\nexit "+exitCode);
+	  }
+	  
+	  fileWriter.close();
+
+	  ContainerLaunchContext containerLaunchContext = 
+			  recordFactory.newRecordInstance(ContainerLaunchContext.class);
+
+	  // ////// Construct the Container-id
+	  ContainerId cId = createContainerId();
+	  containerLaunchContext.setContainerId(cId);
+
+	  containerLaunchContext.setUser(user);
+
+	  URL resource_alpha =
+			  ConverterUtils.getYarnUrlFromPath(localFS
+					  .makeQualified(new Path(scriptFile.getAbsolutePath())));
+	  LocalResource rsrc_alpha =
+			  recordFactory.newRecordInstance(LocalResource.class);
+	  rsrc_alpha.setResource(resource_alpha);
+	  rsrc_alpha.setSize(-1);
+	  rsrc_alpha.setVisibility(LocalResourceVisibility.APPLICATION);
+	  rsrc_alpha.setType(LocalResourceType.FILE);
+	  rsrc_alpha.setTimestamp(scriptFile.lastModified());
+	  String destinationFile = "dest_file";
+	  Map<String, LocalResource> localResources = 
+			  new HashMap<String, LocalResource>();
+	  localResources.put(destinationFile, rsrc_alpha);
+	  containerLaunchContext.setLocalResources(localResources);
+	  containerLaunchContext.setUser(containerLaunchContext.getUser());
+	  List<String> commands = new ArrayList<String>();
+	  commands.add("/bin/bash");
+	  commands.add(scriptFile.getAbsolutePath());
+	  containerLaunchContext.setCommands(commands);
+	  containerLaunchContext.setResource(recordFactory
+			  .newRecordInstance(Resource.class));
+	  containerLaunchContext.getResource().setMemory(100 * 1024 * 1024);
+
+	  StartContainerRequest startRequest = recordFactory.newRecordInstance(StartContainerRequest.class);
+	  startRequest.setContainerLaunchContext(containerLaunchContext);
+	  containerManager.startContainer(startRequest);
+
+	  BaseContainerManagerTest.waitForContainerState(containerManager, cId,
+			  ContainerState.COMPLETE);
+
+	  GetContainerStatusRequest gcsRequest = 
+			  recordFactory.newRecordInstance(GetContainerStatusRequest.class);
+	  gcsRequest.setContainerId(cId);
+	  ContainerStatus containerStatus = 
+			  containerManager.getContainerStatus(gcsRequest).getStatus();
+
+	  // Verify exit status matches exit state of script
+	  Assert.assertEquals(exitCode,
+			  containerStatus.getExitStatus());	    
+  }
+  
+  @Test
+  public void testContainerLaunchAndExitSuccess() throws IOException, InterruptedException {
+	  containerManager.start();
+	  int exitCode = 0; 
+
+	  // launch context for a command that will return exit code 0 
+	  // and verify exit code returned 
+	  testContainerLaunchAndExit(exitCode);	  
+  }
+
+  @Test
+  public void testContainerLaunchAndExitFailure() throws IOException, InterruptedException {
+	  containerManager.start();
+	  int exitCode = 50; 
 
+	  // launch context for a command that will return exit code 0 
+	  // and verify exit code returned 
+	  testContainerLaunchAndExit(exitCode);	  
+  }
+  
   @Test
   public void testLocalFilesCleanup() throws InterruptedException,
       IOException {