You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2015/08/25 15:03:52 UTC

ambari git commit: AMBARI-12867 - Do Not Automatically Abort Stack Repository Installation When A Host Timed Out (jonathanhurley

Repository: ambari
Updated Branches:
  refs/heads/trunk 5b0acfbdc -> bba679959


AMBARI-12867 - Do Not Automatically Abort Stack Repository Installation When A Host Timed Out (jonathanhurley


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/bba67995
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/bba67995
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/bba67995

Branch: refs/heads/trunk
Commit: bba679959b3edc16db507faeacd84d33167bbcf4
Parents: 5b0acfb
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Mon Aug 24 19:28:03 2015 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Tue Aug 25 09:03:24 2015 -0400

----------------------------------------------------------------------
 .../java/org/apache/ambari/server/Role.java     |   1 +
 .../ClusterStackVersionResourceProvider.java    | 112 +++++++++++--------
 ...ClusterStackVersionResourceProviderTest.java |  17 +--
 3 files changed, 76 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/bba67995/ambari-server/src/main/java/org/apache/ambari/server/Role.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/Role.java b/ambari-server/src/main/java/org/apache/ambari/server/Role.java
index 636df3f..c684981 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/Role.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/Role.java
@@ -113,6 +113,7 @@ public class Role {
   public static final Role METRICS_MONITOR = valueOf("METRICS_MONITOR");
   public static final Role AMS_SERVICE_CHECK = valueOf("AMBARI_METRICS_SERVICE_CHECK");
   public static final Role ACCUMULO_CLIENT = valueOf("ACCUMULO_CLIENT");
+  public static final Role INSTALL_PACKAGES = valueOf("install_packages");
 
   private String name = null;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/bba67995/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
index 6133885..2f3e959 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
@@ -58,11 +58,9 @@ import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.events.ActionFinalReportReceivedEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
-import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
 import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
-import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
 import org.apache.ambari.server.orm.entities.HostVersionEntity;
 import org.apache.ambari.server.orm.entities.OperatingSystemEntity;
@@ -79,6 +77,7 @@ import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.ServiceOsSpecific;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.utils.StageUtils;
+import org.apache.commons.lang.StringUtils;
 
 import com.google.gson.Gson;
 import com.google.inject.Inject;
@@ -93,17 +92,30 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
 
   // ----- Property ID constants ---------------------------------------------
 
-  protected static final String CLUSTER_STACK_VERSION_ID_PROPERTY_ID                   = PropertyHelper.getPropertyId("ClusterStackVersions", "id");
-  protected static final String CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID         = PropertyHelper.getPropertyId("ClusterStackVersions", "cluster_name");
-  protected static final String CLUSTER_STACK_VERSION_STACK_PROPERTY_ID                = PropertyHelper.getPropertyId("ClusterStackVersions", "stack");
-  protected static final String CLUSTER_STACK_VERSION_VERSION_PROPERTY_ID              = PropertyHelper.getPropertyId("ClusterStackVersions", "version");
-  protected static final String CLUSTER_STACK_VERSION_STATE_PROPERTY_ID                = PropertyHelper.getPropertyId("ClusterStackVersions", "state");
-  protected static final String CLUSTER_STACK_VERSION_HOST_STATES_PROPERTY_ID          = PropertyHelper.getPropertyId("ClusterStackVersions", "host_states");
-  protected static final String CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID   = PropertyHelper.getPropertyId("ClusterStackVersions", "repository_version");
+  protected static final String CLUSTER_STACK_VERSION_ID_PROPERTY_ID = PropertyHelper.getPropertyId("ClusterStackVersions", "id");
+  protected static final String CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("ClusterStackVersions", "cluster_name");
+  protected static final String CLUSTER_STACK_VERSION_STACK_PROPERTY_ID = PropertyHelper.getPropertyId("ClusterStackVersions", "stack");
+  protected static final String CLUSTER_STACK_VERSION_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("ClusterStackVersions", "version");
+  protected static final String CLUSTER_STACK_VERSION_STATE_PROPERTY_ID = PropertyHelper.getPropertyId("ClusterStackVersions", "state");
+  protected static final String CLUSTER_STACK_VERSION_HOST_STATES_PROPERTY_ID = PropertyHelper.getPropertyId("ClusterStackVersions", "host_states");
+  protected static final String CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID  = PropertyHelper.getPropertyId("ClusterStackVersions", "repository_version");
+  protected static final String CLUSTER_STACK_VERSION_STAGE_SUCCESS_FACTOR  = PropertyHelper.getPropertyId("ClusterStackVersions", "success_factor");
 
   protected static final String INSTALL_PACKAGES_ACTION = "install_packages";
   protected static final String INSTALL_PACKAGES_FULL_NAME = "Install version";
 
+  /**
+   * The default success factor that will be used when determining if a stage's
+   * failure should cause other stages to abort. Consider a scenario with 1000
+   * hosts, broken up into 10 stages. Each stage would have 100 hosts. If the
+   * success factor was 100%, then any failure in stage 1 woudl cause all 9
+   * other stages to abort. If set to 90%, then 10 hosts would need to fail for
+   * the other stages to abort. This is necessary to prevent the abortion of
+   * stages based on 1 or 2 errant hosts failing in a large cluster's stack
+   * distribution.
+   */
+  private static final float INSTALL_PACKAGES_SUCCESS_FACTOR = 0.85f;
+
   @SuppressWarnings("serial")
   private static Set<String> pkPropertyIds = new HashSet<String>() {
     {
@@ -126,6 +138,7 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
       add(CLUSTER_STACK_VERSION_HOST_STATES_PROPERTY_ID);
       add(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID);
       add(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID);
+      add(CLUSTER_STACK_VERSION_STAGE_SUCCESS_FACTOR);
     }
   };
 
@@ -147,9 +160,6 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
   private static HostVersionDAO hostVersionDAO;
 
   @Inject
-  private static StackDAO stackDAO;
-
-  @Inject
   private static RepositoryVersionDAO repositoryVersionDAO;
 
   @Inject
@@ -164,9 +174,6 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
   private static StageFactory stageFactory;
 
   @Inject
-  private static ClusterDAO clusterDAO;
-
-  @Inject
   private static RequestFactory requestFactory;
 
   @Inject
@@ -272,14 +279,14 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
     if (request.getProperties().size() != 1) {
       throw new UnsupportedOperationException("Multiple requests cannot be executed at the same time.");
     }
+
     Map<String, Object> propertyMap = iterator.next();
 
-    Set<String> requiredProperties = new HashSet<String>(){{
-      add(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID);
-      add(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID);
-      add(CLUSTER_STACK_VERSION_STACK_PROPERTY_ID);
-      add(CLUSTER_STACK_VERSION_VERSION_PROPERTY_ID);
-    }};
+    Set<String> requiredProperties = new HashSet<String>();
+    requiredProperties.add(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID);
+    requiredProperties.add(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID);
+    requiredProperties.add(CLUSTER_STACK_VERSION_STACK_PROPERTY_ID);
+    requiredProperties.add(CLUSTER_STACK_VERSION_VERSION_PROPERTY_ID);
 
     for (String requiredProperty : requiredProperties) {
       if (! propertyMap.containsKey(requiredProperty)) {
@@ -319,13 +326,22 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
       stackId = currentStackVersion;
     }
 
+    // why does the JSON body parser convert JSON primitives into strings!?
+    Float successFactor = INSTALL_PACKAGES_SUCCESS_FACTOR;
+    String successFactorProperty = (String) propertyMap.get(CLUSTER_STACK_VERSION_STAGE_SUCCESS_FACTOR);
+    if (StringUtils.isNotBlank(successFactorProperty)) {
+      successFactor = Float.valueOf(successFactorProperty);
+    }
+
     RepositoryVersionEntity repoVersionEnt = repositoryVersionDAO.findByStackAndVersion(
         stackId, desiredRepoVersion);
+
     if (repoVersionEnt == null) {
       throw new IllegalArgumentException(String.format(
               "Repo version %s is not available for stack %s",
               desiredRepoVersion, stackId));
     }
+
     List<OperatingSystemEntity> operatingSystems = repoVersionEnt.getOperatingSystems();
     Map<String, List<RepositoryEntity>> perOsRepos = new HashMap<String, List<RepositoryEntity>>();
     for (OperatingSystemEntity operatingSystem : operatingSystems) {
@@ -351,27 +367,32 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
     }
 
     ArrayList<Stage> stages = new ArrayList<Stage>(batchCount);
-    for (int batchId = 1; batchId <= batchCount ; batchId++) {
+    for (int batchId = 1; batchId <= batchCount; batchId++) {
       // Create next stage
       String stageName;
       if (batchCount > 1) {
         stageName = INSTALL_PACKAGES_FULL_NAME;
       } else {
-        stageName = String.format(INSTALL_PACKAGES_FULL_NAME +
-                ". Batch %d of %d", batchId, batchCount);
+        stageName = String.format(INSTALL_PACKAGES_FULL_NAME + ". Batch %d of %d", batchId,
+            batchCount);
       }
-      Stage stage = stageFactory.createNew(req.getId(),
-              "/tmp/ambari",
-              cluster.getClusterName(),
-              cluster.getClusterId(),
-              stageName,
-              "{}",
-              "{}",
-              hostParamsJson
-      );
+
+      Stage stage = stageFactory.createNew(req.getId(), "/tmp/ambari", cluster.getClusterName(),
+          cluster.getClusterId(), stageName, "{}", "{}", hostParamsJson);
+
+      // if you have 1000 hosts (10 stages with 100 installs), we want to ensure
+      // that a single failure doesn't cause all other stages to abort; set the
+      // success factor ratio in order to tolerate some failures in a single
+      // stage
+      stage.getSuccessFactors().put(Role.INSTALL_PACKAGES, successFactor);
+
+      // set and increment stage ID
       stage.setStageId(stageId);
-      stages.add(stage);
       stageId++;
+
+      // add the stage that was just created
+      stages.add(stage);
+
       // Populate with commands for host
       for (int i = 0; i < maxTasks && hostsForClusterIter.hasNext(); i++) {
         Host host = hostsForClusterIter.next();
@@ -389,6 +410,7 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
     try {
       ClusterVersionEntity existingCSVer = clusterVersionDAO.findByClusterAndStackAndVersion(
           clName, stackId, desiredRepoVersion);
+
       if (existingCSVer == null) {
         try {
           // Create/persist new cluster stack version
@@ -467,12 +489,11 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
     final String packageList = gson.toJson(packages);
     final String repoList = gson.toJson(repoInfo);
 
-    Map<String, String> params = new HashMap<String, String>() {{
-      put("stack_id", stackId.getStackId());
-      put("repository_version", desiredRepoVersion);
-      put("base_urls", repoList);
-      put("package_list", packageList);
-    }};
+    Map<String, String> params = new HashMap<String, String>();
+    params.put("stack_id", stackId.getStackId());
+    params.put("repository_version", desiredRepoVersion);
+    params.put("base_urls", repoList);
+    params.put("package_list", packageList);
 
     // add host to this stage
     RequestResourceFilter filter = new RequestResourceFilter(null, null,
@@ -571,11 +592,10 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
       }
       Map<String, Object> propertyMap = iterator.next();
 
-      Set<String> requiredProperties = new HashSet<String>() {{
-        add(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID);
-        add(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID);
-        add(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID);
-      }};
+      Set<String> requiredProperties = new HashSet<String>();
+      requiredProperties.add(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID);
+      requiredProperties.add(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID);
+      requiredProperties.add(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID);
 
       for (String requiredProperty : requiredProperties) {
         if (!propertyMap.containsKey(requiredProperty)) {
@@ -634,7 +654,7 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
       command.setCommandParams(args);
       command.setClusterName(clName);
       finalizeUpgradeAction.setExecutionCommand(command);
-      
+
       HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(defaultHostName,
               Role.AMBARI_SERVER_ACTION, null, null);
       finalizeUpgradeAction.setHostRoleCommand(hostRoleCommand);

http://git-wip-us.apache.org/repos/asf/ambari/blob/bba67995/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
index a56823b..5b24edc 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
@@ -31,7 +31,6 @@ import static org.easymock.EasyMock.verify;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -41,6 +40,7 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
+import org.apache.ambari.server.Role;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.actionmanager.ExecutionCommandWrapper;
 import org.apache.ambari.server.actionmanager.HostRoleCommand;
@@ -61,7 +61,6 @@ import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
-import org.apache.ambari.server.orm.PersistenceType;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
 import org.apache.ambari.server.orm.dao.HostDAO;
@@ -70,7 +69,6 @@ import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
 import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
-import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
@@ -266,6 +264,9 @@ public class ClusterStackVersionResourceProviderTest {
     expect(stage.getExecutionCommandWrapper(anyObject(String.class), anyObject(String.class))).
             andReturn(executionCommandWrapper).anyTimes();
 
+    Map<Role, Float> successFactors = new HashMap<>();
+    expect(stage.getSuccessFactors()).andReturn(successFactors).atLeastOnce();
+
     // Check that we create proper stage count
     expect(stageFactory.createNew(anyLong(), anyObject(String.class),
             anyObject(String.class), anyLong(),
@@ -314,18 +315,18 @@ public class ClusterStackVersionResourceProviderTest {
 
     propertySet.add(properties);
 
-
-
-
-
     // create the request
     Request request = PropertyHelper.getCreateRequest(propertySet, null);
 
     RequestStatus status = provider.createResources(request);
+    Assert.assertNotNull(status);
 
     // verify
-    verify(managementController, response, clusters, stageFactory);
+    verify(managementController, response, clusters, stageFactory, stage);
 
+    // check that the success factor was populated in the stage
+    Float successFactor = successFactors.get(Role.INSTALL_PACKAGES);
+    Assert.assertEquals(Float.valueOf(0.85f), successFactor);
   }