ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jonathanhur...@apache.org
Subject ambari git commit: AMBARI-13816 - Save Cluster State Should Not Be Automatically Skipped During Upgrade (jonathanhurley)
Date Tue, 10 Nov 2015 21:13:41 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-2.1 aac2e715c -> 3765894ad


AMBARI-13816 - Save Cluster State Should Not Be Automatically Skipped During Upgrade (jonathanhurley)


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

Branch: refs/heads/branch-2.1
Commit: 3765894ad954d565ce109cc13c1cdaaea7c7c21a
Parents: aac2e71
Author: Jonathan Hurley <jhurley@hortonworks.com>
Authored: Tue Nov 10 11:12:28 2015 -0500
Committer: Jonathan Hurley <jhurley@hortonworks.com>
Committed: Tue Nov 10 16:13:08 2015 -0500

----------------------------------------------------------------------
 .../ambari/server/actionmanager/Stage.java      |  55 +++++++++-
 .../internal/UpgradeResourceProvider.java       |  34 +++++--
 .../server/orm/dao/HostRoleCommandDAO.java      |  36 +++++--
 .../ambari/server/orm/entities/StageEntity.java |  26 +++++
 .../upgrades/AutoSkipFailedSummaryAction.java   |  16 +--
 .../ambari/server/state/UpgradeHelper.java      |  14 ++-
 .../server/state/stack/upgrade/Grouping.java    |   5 +-
 .../stack/upgrade/StageWrapperBuilder.java      |   2 +-
 .../ambari/server/topology/LogicalRequest.java  |   1 +
 .../server/upgrade/UpgradeCatalog213.java       |  59 +++++++----
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   1 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   1 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   1 +
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |   1 +
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |   3 +-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   1 +
 .../HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml |   9 +-
 .../HDP/2.2/upgrades/nonrolling-upgrade-2.2.xml |  16 ++-
 .../HDP/2.2/upgrades/nonrolling-upgrade-2.3.xml |  11 +-
 .../stacks/HDP/2.2/upgrades/upgrade-2.2.xml     |   6 ++
 .../stacks/HDP/2.2/upgrades/upgrade-2.3.xml     |   4 +
 .../HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml |  11 +-
 .../stacks/HDP/2.3/upgrades/upgrade-2.3.xml     |   4 +
 .../internal/UpgradeResourceProviderTest.java   |  40 +++++---
 .../server/orm/dao/HostRoleCommandDAOTest.java  |  87 +++++++++++++++-
 .../server/state/stack/UpgradePackTest.java     |  26 ++++-
 .../stack/upgrade/StageWrapperBuilderTest.java  |   1 -
 .../server/upgrade/UpgradeCatalog213Test.java   | 101 ++++++++++++-------
 .../upgrades/upgrade_test_skip_failures.xml     |  13 ++-
 29 files changed, 464 insertions(+), 121 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
index ef50963..d0cc843 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
@@ -77,6 +77,7 @@ public class Stage {
   private String hostParamsStage;
 
   private boolean skippable;
+  private boolean supportsAutoSkipOnFailure;
 
   private int stageTimeout = -1;
 
@@ -113,7 +114,10 @@ public class Stage {
     this.clusterHostInfo = clusterHostInfo;
     this.commandParamsStage = commandParamsStage;
     this.hostParamsStage = hostParamsStage;
+
     skippable = false;
+    supportsAutoSkipOnFailure = false;
+
     this.hostRoleCommandFactory = hostRoleCommandFactory;
   }
 
@@ -125,6 +129,7 @@ public class Stage {
     requestId = stageEntity.getRequestId();
     stageId = stageEntity.getStageId();
     skippable = stageEntity.isSkippable();
+    supportsAutoSkipOnFailure = stageEntity.isAutoSkipOnFailureSupported();
     logDir = stageEntity.getLogInfo();
 
     long clusterId = stageEntity.getClusterId().longValue();
@@ -173,6 +178,7 @@ public class Stage {
     stageEntity.setStageId(getStageId());
     stageEntity.setLogInfo(logDir);
     stageEntity.setSkippable(skippable);
+    stageEntity.setAutoSkipFailureSupported(supportsAutoSkipOnFailure);
     stageEntity.setRequestContext(requestContext);
     stageEntity.setHostRoleCommands(new ArrayList<HostRoleCommandEntity>());
     stageEntity.setRoleSuccessCriterias(new ArrayList<RoleSuccessCriteriaEntity>());
@@ -274,9 +280,12 @@ public class Stage {
       String hostName, Role role, RoleCommand command, ServiceComponentHostEvent event,
       boolean retryAllowed, boolean autoSkipFailure) {
 
+    boolean isHostRoleCommandAutoSkippable = autoSkipFailure && supportsAutoSkipOnFailure
+        && skippable;
+
     // used on stage creation only, no need to check if wrappers loaded
     HostRoleCommand hrc = hostRoleCommandFactory.create(hostName, role, event, command,
-        retryAllowed, autoSkipFailure);
+        retryAllowed, isHostRoleCommandAutoSkippable);
 
     return addGenericExecutionCommand(clusterName, hostName, role, command, event, hrc);
   }
@@ -284,8 +293,12 @@ public class Stage {
   private ExecutionCommandWrapper addGenericExecutionCommand(Cluster cluster, Host host, Role role,
       RoleCommand command, ServiceComponentHostEvent event, boolean retryAllowed,
       boolean autoSkipFailure) {
+
+    boolean isHostRoleCommandAutoSkippable = autoSkipFailure && supportsAutoSkipOnFailure
+        && skippable;
+
     HostRoleCommand hrc = hostRoleCommandFactory.create(host, role, event, command, retryAllowed,
-        autoSkipFailure);
+        isHostRoleCommandAutoSkippable);
 
     return addGenericExecutionCommand(cluster.getClusterName(), host.getHostName(), role, command,
         event, hrc);
@@ -340,8 +353,11 @@ public class Stage {
       ServiceComponentHostEvent event, String clusterName, String serviceName, boolean retryAllowed,
       boolean autoSkipFailure) {
 
+    boolean isHostRoleCommandAutoSkippable = autoSkipFailure && supportsAutoSkipOnFailure
+        && skippable;
+
     ExecutionCommandWrapper commandWrapper = addGenericExecutionCommand(clusterName, host, role,
-        command, event, retryAllowed, autoSkipFailure);
+        command, event, retryAllowed, isHostRoleCommandAutoSkippable);
 
     commandWrapper.getExecutionCommand().setServiceName(serviceName);
   }
@@ -355,8 +371,11 @@ public class Stage {
       ServiceComponentHostEvent event, Cluster cluster, String serviceName, boolean retryAllowed,
       boolean autoSkipFailure) {
 
+    boolean isHostRoleCommandAutoSkippable = autoSkipFailure && supportsAutoSkipOnFailure
+        && skippable;
+
     ExecutionCommandWrapper commandWrapper = addGenericExecutionCommand(cluster, host, role,
-        command, event, retryAllowed, autoSkipFailure);
+        command, event, retryAllowed, isHostRoleCommandAutoSkippable);
 
     commandWrapper.getExecutionCommand().setServiceName(serviceName);
   }
@@ -405,8 +424,11 @@ public class Stage {
       @Nullable String commandDetail, @Nullable Map<String, Map<String, String>> configTags,
       @Nullable Integer timeout, boolean retryAllowed, boolean autoSkipFailure) {
 
+    boolean isHostRoleCommandAutoSkippable = autoSkipFailure && supportsAutoSkipOnFailure
+        && skippable;
+
     ExecutionCommandWrapper commandWrapper = addGenericExecutionCommand(clusterName,
-        INTERNAL_HOSTNAME, role, command, event, retryAllowed, autoSkipFailure);
+        INTERNAL_HOSTNAME, role, command, event, retryAllowed, isHostRoleCommandAutoSkippable);
 
     ExecutionCommand cmd = commandWrapper.getExecutionCommand();
 
@@ -799,6 +821,29 @@ public class Stage {
     this.skippable = skippable;
   }
 
+  /**
+   * Determine whether this stage supports automatically skipping failures of
+   * its commands.
+   *
+   * @return {@code true} if this stage supports automatically skipping failures
+   *         of its commands.
+   */
+  public boolean isAutoSkipOnFailureSupported() {
+    return supportsAutoSkipOnFailure;
+  }
+
+  /**
+   * Sets whether this stage supports automatically skipping failures of its
+   * commands.
+   *
+   * @param supportsAutoSkipOnFailure
+   *          {@code true} if this stage supports automatically skipping
+   *          failures of its commands.
+   */
+  public void setAutoSkipFailureSupported(boolean supportsAutoSkipOnFailure) {
+    this.supportsAutoSkipOnFailure = supportsAutoSkipOnFailure;
+  }
+
   @Override //Object
   public synchronized String toString() {
     StringBuilder builder = new StringBuilder();

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
index 8d53808..715a089 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
@@ -789,6 +789,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
     for (UpgradeGroupHolder group : groups) {
       boolean skippable = group.skippable;
+      boolean supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
       boolean allowRetry = group.allowRetry;
 
       List<UpgradeItemEntity> itemEntities = new ArrayList<UpgradeItemEntity>();
@@ -821,7 +822,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
               injectVariables(configHelper, cluster, itemEntity);
               makeServerSideStage(ctx, req, itemEntity, (ServerSideActionTask) task, skippable,
-                  allowRetry, pack, configUpgradePack);
+                  supportsAutoSkipOnFailure, allowRetry, pack, configUpgradePack);
             }
           }
         } else {
@@ -834,7 +835,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
           injectVariables(configHelper, cluster, itemEntity);
 
           // upgrade items match a stage
-          createStage(ctx, req, itemEntity, wrapper, skippable, allowRetry);
+          createStage(ctx, req, itemEntity, wrapper, skippable, supportsAutoSkipOnFailure,
+              allowRetry);
         }
       }
 
@@ -1088,20 +1090,24 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   }
 
   private void createStage(UpgradeContext context, RequestStageContainer request,
-      UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, boolean allowRetry)
+      UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable,
+      boolean supportsAutoSkipOnFailure, boolean allowRetry)
           throws AmbariException {
 
     switch (wrapper.getType()) {
       case START:
       case STOP:
       case RESTART:
-        makeCommandStage(context, request, entity, wrapper, skippable, allowRetry);
+        makeCommandStage(context, request, entity, wrapper, skippable, supportsAutoSkipOnFailure,
+            allowRetry);
         break;
       case RU_TASKS:
-        makeActionStage(context, request, entity, wrapper, skippable, allowRetry);
+        makeActionStage(context, request, entity, wrapper, skippable, supportsAutoSkipOnFailure,
+            allowRetry);
         break;
       case SERVICE_CHECK:
-        makeServiceCheckStage(context, request, entity, wrapper, skippable, allowRetry);
+        makeServiceCheckStage(context, request, entity, wrapper, skippable,
+            supportsAutoSkipOnFailure, allowRetry);
         break;
       default:
         break;
@@ -1126,7 +1132,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   }
 
   private void makeActionStage(UpgradeContext context, RequestStageContainer request,
-      UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, boolean allowRetry)
+      UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable,
+      boolean supportsAutoSkipOnFailure, boolean allowRetry)
           throws AmbariException {
 
     if (0 == wrapper.getHosts().size()) {
@@ -1186,6 +1193,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         jsons.getHostParamsForStage());
 
     stage.setSkippable(skippable);
+    stage.setAutoSkipFailureSupported(supportsAutoSkipOnFailure);
 
     long stageId = request.getLastStageId() + 1;
     if (0L == stageId) {
@@ -1218,7 +1226,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
    * @throws AmbariException
    */
   private void makeCommandStage(UpgradeContext context, RequestStageContainer request,
-      UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, boolean allowRetry)
+      UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable,
+      boolean supportsAutoSkipOnFailure, boolean allowRetry)
           throws AmbariException {
 
     Cluster cluster = context.getCluster();
@@ -1278,6 +1287,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         jsons.getHostParamsForStage());
 
     stage.setSkippable(skippable);
+    stage.setAutoSkipFailureSupported(supportsAutoSkipOnFailure);
 
     long stageId = request.getLastStageId() + 1;
     if (0L == stageId) {
@@ -1296,7 +1306,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   }
 
   private void makeServiceCheckStage(UpgradeContext context, RequestStageContainer request,
-      UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, boolean allowRetry)
+      UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable,
+      boolean supportsAutoSkipOnFailure, boolean allowRetry)
           throws AmbariException {
 
     List<RequestResourceFilter> filters = new ArrayList<RequestResourceFilter>();
@@ -1334,6 +1345,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         jsons.getHostParamsForStage());
 
     stage.setSkippable(skippable);
+    stage.setAutoSkipFailureSupported(supportsAutoSkipOnFailure);
 
     long stageId = request.getLastStageId() + 1;
     if (0L == stageId) {
@@ -1363,7 +1375,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
    * @throws AmbariException
    */
   private void makeServerSideStage(UpgradeContext context, RequestStageContainer request,
-      UpgradeItemEntity entity, ServerSideActionTask task, boolean skippable, boolean allowRetry,
+      UpgradeItemEntity entity, ServerSideActionTask task, boolean skippable,
+      boolean supportsAutoSkipOnFailure, boolean allowRetry,
       UpgradePack upgradePack, ConfigUpgradePack configUpgradePack)
           throws AmbariException {
 
@@ -1446,6 +1459,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         jsons.getCommandParamsForStage(), jsons.getHostParamsForStage());
 
     stage.setSkippable(skippable);
+    stage.setAutoSkipFailureSupported(supportsAutoSkipOnFailure);
 
     long stageId = request.getLastStageId() + 1;
     if (0L == stageId) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
index bf1f5d5..f9e7b08 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
@@ -478,10 +478,14 @@ public class HostRoleCommandDAO {
 
   /**
    * Updates the {@link HostRoleCommandEntity#isFailureAutoSkipped()} flag for
-   * all commands for the given request
+   * all commands for the given request.
    * <p/>
-   * This will update each entity to ensure that the cache is maintained in a correct
-   * state.  A batch update doesn't always reflect in JPA-managed entities
+   * This will update each entity to ensure that the cache is maintained in a
+   * correct state. A batch update doesn't always reflect in JPA-managed
+   * entities.
+   * <p/>
+   * Stages which do not support automatically skipped commands will be updated
+   * with a value of {@code false}.
    *
    * @param requestId
    *          the request ID of the commands to update
@@ -490,6 +494,8 @@ public class HostRoleCommandDAO {
    *          otherwise.
    * @param skipOnServiceCheckFailure
    *          {@code true} to skip service check failures
+   *
+   * @see StageEntity#isAutoSkipOnFailureSupported()
    */
   @Transactional
   public void updateAutomaticSkipOnFailure(long requestId,
@@ -497,14 +503,26 @@ public class HostRoleCommandDAO {
 
     List<HostRoleCommandEntity> tasks = findByRequest(requestId);
     for (HostRoleCommandEntity task : tasks) {
-      if (task.getRoleCommand() == RoleCommand.SERVICE_CHECK ) {
-        task.setAutoSkipOnFailure(skipOnServiceCheckFailure);
-        merge(task);
+      // if the stage does not support automatically skipping its commands, then
+      // do nothing
+      StageEntity stage = task.getStage();
+
+      boolean isStageSkippable = stage.isSkippable();
+      boolean isAutoSkipSupportedOnStage = stage.isAutoSkipOnFailureSupported();
+
+      // if the stage is not skippable or it does not support auto skip
+      if (!isStageSkippable || !isAutoSkipSupportedOnStage) {
+        task.setAutoSkipOnFailure(false);
       } else {
-        task.setAutoSkipOnFailure(skipOnFailure);
-        merge(task);
+        if (task.getRoleCommand() == RoleCommand.SERVICE_CHECK) {
+          task.setAutoSkipOnFailure(skipOnServiceCheckFailure);
+        } else {
+          task.setAutoSkipOnFailure(skipOnFailure);
+        }
       }
+
+      // save changes
+      merge(task);
     }
   }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java
index e801233..12ab568 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java
@@ -57,6 +57,9 @@ public class StageEntity {
   @Column(name = "skippable", nullable = false)
   private Integer skippable = Integer.valueOf(0);
 
+  @Column(name = "supports_auto_skip_failure", nullable = false)
+  private Integer supportsAutoSkipOnFailure = Integer.valueOf(0);
+
   @Column(name = "log_info")
   @Basic
   private String logInfo = "";
@@ -245,4 +248,27 @@ public class StageEntity {
   public void setSkippable(boolean skippable) {
     this.skippable = skippable ? 1 : 0;
   }
+
+  /**
+   * Determine whether this stage supports automatically skipping failures of
+   * its commands.
+   *
+   * @return {@code true} if this stage supports automatically skipping failures
+   *         of its commands.
+   */
+  public boolean isAutoSkipOnFailureSupported() {
+    return supportsAutoSkipOnFailure != 0;
+  }
+
+  /**
+   * Sets whether this stage supports automatically skipping failures of its
+   * commands.
+   *
+   * @param supportsAutoSkipOnFailure
+   *          {@code true} if this stage supports automatically skipping
+   *          failures of its commands.
+   */
+  public void setAutoSkipFailureSupported(boolean supportsAutoSkipOnFailure) {
+    this.supportsAutoSkipOnFailure = supportsAutoSkipOnFailure ? 1 : 0;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java
index 80c1611..7a99f09 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java
@@ -18,7 +18,13 @@
 package org.apache.ambari.server.serveraction.upgrades;
 
 import java.text.MessageFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
 import java.util.concurrent.ConcurrentMap;
 
 import org.apache.ambari.server.AmbariException;
@@ -65,11 +71,6 @@ public class AutoSkipFailedSummaryAction extends AbstractServerAction {
    */
   private static final String FAILURE_STD_OUT_TEMPLATE = "There were {0} skipped failure(s) that must be addressed before you can proceed. Please resolve each failure before continuing with the upgrade.";
 
-  /**
-   * ...
-   */
-  private static final String MIDDLE_ELLIPSIZE_MARKER = "\n\u2026\n";
-
   private static final String SKIPPED_SERVICE_CHECK = "service_check";
   private static final String SKIPPED_HOST_COMPONENT = "host_component";
   private static final String SKIPPED = "skipped";
@@ -191,6 +192,7 @@ public class AutoSkipFailedSummaryAction extends AbstractServerAction {
 
               publishedHostComponents.put(hostName, new HashSet<Role>());
             }
+
             Set<Role> publishedHostComponentsOnHost = publishedHostComponents.get(hostName);
             Role role = skippedTask.getRole();
             if (! publishedHostComponentsOnHost.contains(role)) {
@@ -203,9 +205,11 @@ public class AutoSkipFailedSummaryAction extends AbstractServerAction {
               failures.add(details);
             }
           }
+
           skippedFailures.put(SKIPPED_HOST_COMPONENT, hostComponents);
           m_structuredFailures.put(FAILURES, skippedFailures);
         }
+
         skippedCategories.add(skippedCategory);
 
         ServiceComponentHostEventWrapper eventWrapper = new ServiceComponentHostEventWrapper(

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
index 1b59b94..2b41f62 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
@@ -51,7 +51,6 @@ import org.apache.ambari.server.stack.MasterHostResolver;
 import org.apache.ambari.server.state.stack.UpgradePack;
 import org.apache.ambari.server.state.stack.UpgradePack.ProcessingComponent;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
-import org.apache.ambari.server.state.stack.upgrade.ExecuteTask;
 import org.apache.ambari.server.state.stack.upgrade.Grouping;
 import org.apache.ambari.server.state.stack.upgrade.ManualTask;
 import org.apache.ambari.server.state.stack.upgrade.RestartGrouping;
@@ -280,6 +279,7 @@ public class UpgradeHelper {
       groupHolder.title = group.title;
       groupHolder.groupClass = group.getClass();
       groupHolder.skippable = group.skippable;
+      groupHolder.supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
       groupHolder.allowRetry = group.allowRetry;
 
       // !!! all downgrades are skippable
@@ -334,7 +334,7 @@ public class UpgradeHelper {
 
           // NonRolling Upgrade has several tasks for the same component, since it must first call Stop, perform several
           // other tasks, and then Start on that Component.
-          
+
           HostsType hostsType = mhr.getMasterAndHosts(service.serviceName, component);
           if (null == hostsType) {
             continue;
@@ -624,6 +624,16 @@ public class UpgradeHelper {
     public boolean skippable = false;
 
     /**
+     * {@code true} if the upgrade group's tasks can be automatically skipped if
+     * they fail. This is used in conjunction with
+     * {@link UpgradePack#isComponentFailureAutoSkipped()}. If the upgrade pack
+     * (or the upgrade request) does support auto skipping failures, then this
+     * setting has no effect. It's used mainly as a way to ensure that some
+     * groupings never have their failed tasks automatically skipped.
+     */
+    public boolean supportsAutoSkipOnFailure = true;
+
+    /**
      * List of stages for the group
      */
     public List<StageWrapper> items = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java
index 6d927ac..4a94dc1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java
@@ -50,6 +50,9 @@ public class Grouping {
   @XmlElement(name="skippable", defaultValue="false")
   public boolean skippable = false;
 
+  @XmlElement(name = "supports-auto-skip-failure", defaultValue = "true")
+  public boolean supportsAutoSkipOnFailure = true;
+
   @XmlElement(name="allow-retry", defaultValue="true")
   public boolean allowRetry = true;
 
@@ -159,7 +162,7 @@ public class Grouping {
       }
 
       // Potentially add a service check
-      if (this.m_serviceCheck && !clientOnly) {
+      if (m_serviceCheck && !clientOnly) {
         m_servicesToCheck.add(service);
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
index e2f4171..7efe608 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
@@ -141,7 +141,7 @@ public abstract class StageWrapperBuilder {
       autoSkipFailures = upgradeContext.isComponentFailureAutoSkipped();
     }
 
-    if (m_grouping.skippable && autoSkipFailures) {
+    if (m_grouping.supportsAutoSkipOnFailure && m_grouping.skippable && autoSkipFailures) {
       ServerActionTask skippedFailedCheck = new ServerActionTask();
       skippedFailedCheck.implClass = AutoSkipFailedSummaryAction.class.getName();
       skippedFailedCheck.summary = AUTO_SKIPPED_TASK_SUMMARY;

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java
index f29e0f4..fb6b774 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java
@@ -206,6 +206,7 @@ public class LogicalRequest extends Request {
       //stage.setClusterHostInfo();
       stage.setClusterId(getClusterId());
       stage.setSkippable(false);
+      stage.setAutoSkipFailureSupported(false);
       // getTaskEntities() sync's state with physical tasks
       stage.setHostRoleCommands(hostRequest.getTaskEntities());
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java
index 3211b36..d8ddb3d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java
@@ -18,11 +18,20 @@
 
 package org.apache.ambari.server.upgrade;
 
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.persist.Transactional;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
@@ -60,19 +69,11 @@ import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.Transactional;
 
 /**
  * Upgrade catalog for version 2.1.3.
@@ -128,6 +129,8 @@ public class UpgradeCatalog213 extends AbstractUpgradeCatalog {
   private static final String SECURITY_TYPE_COLUMN = "security_type";
   private static final String SECURITY_DESCRIPTOR_REF_COLUMN = "security_descriptor_reference";
 
+  private static final String STAGE_TABLE = "stage";
+
   /**
    * Logger.
    */
@@ -187,6 +190,7 @@ public class UpgradeCatalog213 extends AbstractUpgradeCatalog {
 
     addKerberosDescriptorTable();
     executeBlueprintDDLUpdates();
+    executeStageDDLUpdates();
   }
 
   protected void executeUpgradeDDLUpdates() throws AmbariException, SQLException {
@@ -209,9 +213,22 @@ public class UpgradeCatalog213 extends AbstractUpgradeCatalog {
         String.class, null, null, true));
   }
 
-    /**
-     * {@inheritDoc}
-     */
+  /**
+   * Updates the {@code stage} table by:
+   * <ul>
+   * <li>Adding the {@code supports_auto_skip_failure} column</li>
+   * </ul>
+   *
+   * @throws SQLException
+   */
+  protected void executeStageDDLUpdates() throws SQLException {
+    dbAccessor.addColumn(STAGE_TABLE,
+        new DBAccessor.DBColumnInfo("supports_auto_skip_failure", Integer.class, 1, 0, false));
+  }
+
+  /**
+   * {@inheritDoc}
+   */
   @Override
   protected void executePreDMLUpdates() throws AmbariException, SQLException {
     // execute DDL updates

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 62d8054..c00e46f 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -257,6 +257,7 @@ CREATE TABLE stage (
   request_id BIGINT NOT NULL,
   cluster_id BIGINT,
   skippable SMALLINT DEFAULT 0 NOT NULL,
+  supports_auto_skip_failure SMALLINT DEFAULT 0 NOT NULL,
   log_info VARCHAR(255) NOT NULL,
   request_context VARCHAR(255),
   cluster_host_info LONGBLOB,

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index fe024ce..3cac618 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -247,6 +247,7 @@ CREATE TABLE stage (
   request_id NUMBER(19) NOT NULL,
   cluster_id NUMBER(19) NULL,
   skippable NUMBER(1) DEFAULT 0 NOT NULL,
+  supports_auto_skip_failure NUMBER(1) DEFAULT 0 NOT NULL,  
   log_info VARCHAR2(255) NULL,
   request_context VARCHAR2(255) NULL,
   cluster_host_info BLOB NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 3ae65ee..2bcfb9a 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -259,6 +259,7 @@ CREATE TABLE stage (
   request_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
   skippable SMALLINT DEFAULT 0 NOT NULL,
+  supports_auto_skip_failure SMALLINT DEFAULT 0 NOT NULL,  
   log_info VARCHAR(255) NOT NULL,
   request_context VARCHAR(255),
   cluster_host_info BYTEA NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index c014443..56dff9b 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -292,6 +292,7 @@ CREATE TABLE ambari.stage (
   request_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
   skippable SMALLINT DEFAULT 0 NOT NULL,
+  supports_auto_skip_failure SMALLINT DEFAULT 0 NOT NULL,
   log_info VARCHAR(255) NOT NULL,
   request_context VARCHAR(255),
   cluster_host_info BYTEA NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index bba17a5..1cc83ed 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -246,6 +246,7 @@ CREATE TABLE stage (
   request_id NUMERIC(19) NOT NULL,
   cluster_id NUMERIC(19),
   skippable SMALLINT DEFAULT 0 NOT NULL,
+  supports_auto_skip_failure SMALLINT DEFAULT 0 NOT NULL,
   log_info VARCHAR(255) NOT NULL,
   request_context VARCHAR(255),
   cluster_host_info IMAGE,
@@ -882,7 +883,7 @@ CREATE TABLE upgrade (
   to_version VARCHAR(255) DEFAULT '' NOT NULL,
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   skip_failures BIT NOT NULL DEFAULT 0,
-  skip_sc_failures BIT NOT NULL DEFAULT 0,  
+  skip_sc_failures BIT NOT NULL DEFAULT 0,
   downgrade_allowed BIT NOT NULL DEFAULT 1,
   PRIMARY KEY (upgrade_id),
   FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id),

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index 60938c3..4b4b0d4 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -282,6 +282,7 @@ CREATE TABLE stage (
   request_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
   skippable SMALLINT DEFAULT 0 NOT NULL,
+  supports_auto_skip_failure SMALLINT DEFAULT 0 NOT NULL,
   log_info VARCHAR(255) NOT NULL,
   request_context VARCHAR(255),
   cluster_host_info VARBINARY(MAX) NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml b/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml
index 11324d4..0a6461d 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml
@@ -33,8 +33,11 @@
 
   <order>
     <group xsi:type="cluster" name="PRE_CLUSTER" title="Prepare Upgrade">
-      <skippable>true</skippable>
       <direction>UPGRADE</direction>
+
+      <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="YARN" component="RESOURCEMANAGER" title="Stop YARN Queues">
         <task xsi:type="manual">
           <message>Before continuing, please stop all YARN queues. If yarn-site's yarn.resourcemanager.work-preserving-recovery.enabled is set to true, then you can skip this step since the clients will retry on their own.</message>
@@ -101,6 +104,8 @@
     <group xsi:type="cluster" name="Backups" title="Perform Backups">
       <direction>UPGRADE</direction>
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="OOZIE" component="OOZIE_SERVER" title="Backup Oozie Database">
         <task xsi:type="manual">
           <message>Before continuing, please backup the Oozie Server database on {{hosts.all}}.</message>
@@ -493,6 +498,8 @@
 
     <group xsi:type="cluster" name="POST_CLUSTER" title="Finalize {{direction.text.proper}}">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage title="Check Unhealthy Hosts" id="unhealthy-hosts">
         <task xsi:type="manual">
           <message>The following hosts were unhealthy and should be resolved before finalizing can be completed: {{hosts.unhealthy}}</message>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.2.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.2.xml b/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.2.xml
index 0614e12..98e7b64 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.2.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.2.xml
@@ -25,8 +25,11 @@
   </prechecks>
   <order>
     <group xsi:type="cluster" name="PRE_CLUSTER" title="Prepare Upgrade">
-      <skippable>true</skippable>
       <direction>UPGRADE</direction>
+
+      <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="YARN" component="RESOURCEMANAGER" title="Stop YARN Queues">
         <task xsi:type="manual">
           <message>Before continuing, please stop all YARN queues. If yarn-site's yarn.resourcemanager.work-preserving-recovery.enabled is set to true, then you can skip this step since the clients will retry on their own.</message>
@@ -110,6 +113,8 @@
     <group xsi:type="cluster" name="Backups" title="Perform Backups">
       <direction>UPGRADE</direction>
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="OOZIE" component="OOZIE_SERVER" title="Backup Oozie Database">
         <task xsi:type="manual">
           <message>Before continuing, please backup the Oozie Server database on {{oozie-env/oozie_hostname}}.</message>
@@ -152,6 +157,7 @@
     <group xsi:type="stop" name="STOP_LOW_LEVEL_SERVICE_COMPONENTS" title="Stop Components for Core Services">
       <direction>UPGRADE</direction>
       <skippable>true</skippable>
+
       <parallel-scheduler></parallel-scheduler>
       <service-check>false</service-check>
 
@@ -451,6 +457,8 @@
     -->
     <group xsi:type="cluster" name="ALL_HOST_OPS" title="Set Version On All Hosts">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage title="Update stack to {{version}}">
         <task xsi:type="execute">
           <script>scripts/ru_set_all.py</script>
@@ -462,7 +470,7 @@
     <group xsi:type="cluster" name="FINALIZE_PRE_CHECK" title="Finalize {{direction.text.proper}} Pre-Check">
       <skippable>false</skippable>
       <direction>UPGRADE</direction>
-      
+
       <execute-stage title="Check Component Versions">
         <task xsi:type="server_action" class="org.apache.ambari.server.serveraction.upgrades.ComponentVersionCheckAction" />
       </execute-stage>
@@ -470,6 +478,8 @@
 
     <group xsi:type="cluster" name="POST_CLUSTER" title="Finalize {{direction.text.proper}}">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage title="Check Unhealthy Hosts" id="unhealthy-hosts">
         <task xsi:type="manual">
           <message>The following hosts were unhealthy and should be resolved before finalizing can be completed: {{hosts.unhealthy}}</message>
@@ -786,4 +796,4 @@
       </component>
     </service>
   </processing>
-</upgrade>
\ No newline at end of file
+</upgrade>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.3.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.3.xml b/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.3.xml
index b9ad6fe..b8bf32a 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.3.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.3.xml
@@ -25,8 +25,11 @@
   </prerequisite-checks>
   <order>
     <group xsi:type="cluster" name="PRE_CLUSTER" title="Prepare Upgrade">
-      <skippable>true</skippable>
       <direction>UPGRADE</direction>
+
+      <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="YARN" component="RESOURCEMANAGER" title="Stop YARN Queues">
         <task xsi:type="manual">
           <message>Before continuing, please stop all YARN queues. If yarn-site's yarn.resourcemanager.work-preserving-recovery.enabled is set to true, then you can skip this step since the clients will retry on their own.</message>
@@ -140,6 +143,8 @@
     <group xsi:type="cluster" name="Backups" title="Perform Backups">
       <direction>UPGRADE</direction>
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="OOZIE" component="OOZIE_SERVER" title="Backup Oozie Database">
         <task xsi:type="manual">
           <message>Before continuing, please backup the Oozie Server database on {{hosts.all}}.</message>
@@ -724,6 +729,8 @@
     -->
     <group xsi:type="cluster" name="ALL_HOST_OPS" title="Set Version On All Hosts">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage title="Update stack to {{version}}">
         <task xsi:type="execute">
           <script>scripts/ru_set_all.py</script>
@@ -743,6 +750,8 @@
 
     <group xsi:type="cluster" name="POST_CLUSTER" title="Finalize {{direction.text.proper}}">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage title="Check Unhealthy Hosts" id="unhealthy-hosts">
         <task xsi:type="manual">
           <message>The following hosts were unhealthy and should be resolved before finalizing can be completed: {{hosts.unhealthy}}</message>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.2.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.2.xml b/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.2.xml
index f210930..02ad006 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.2.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.2.xml
@@ -39,6 +39,8 @@
   <order>
     <group xsi:type="cluster" name="PRE_CLUSTER" title="Prepare Upgrade">
       <direction>UPGRADE</direction>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="HDFS" component="NAMENODE" title="Pre Upgrade HDFS">
         <task xsi:type="execute" hosts="master">
           <script>scripts/namenode.py</script>
@@ -50,6 +52,8 @@
     <group xsi:type="cluster" name="PREPARE_BACKUPS" title="Prepare Backups">
       <direction>UPGRADE</direction>
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="HBASE" component="HBASE_MASTER" title="Pre Upgrade HBase Backup">
         <task xsi:type="execute" hosts="master">
           <script>scripts/hbase_upgrade.py</script>
@@ -308,6 +312,8 @@
 
     <group xsi:type="cluster" name="POST_CLUSTER" title="Finalize {{direction.text.proper}}">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage title="Check Unhealthy Hosts" id="unhealthy-hosts">
         <task xsi:type="manual">
           <message>The following hosts were unhealthy and should be resolved before finalizing can be completed: {{hosts.unhealthy}}</message>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.3.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.3.xml b/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.3.xml
index 9f4dfef..e94ddb1 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.3.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/upgrade-2.3.xml
@@ -39,6 +39,7 @@
   <order>
     <group xsi:type="cluster" name="PRE_CLUSTER" title="Prepare Upgrade">
       <direction>UPGRADE</direction>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
 
       <execute-stage service="HDFS" component="NAMENODE" title="Pre Upgrade HDFS">
         <task xsi:type="execute" hosts="master">
@@ -58,6 +59,8 @@
     <group xsi:type="cluster" name="PREPARE_BACKUPS" title="Prepare Backups">
       <direction>UPGRADE</direction>
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="HBASE" component="HBASE_MASTER" title="Pre Upgrade HBase Backup">
         <task xsi:type="execute" hosts="master">
           <script>scripts/hbase_upgrade.py</script>
@@ -351,6 +354,7 @@
 
     <group xsi:type="cluster" name="POST_CLUSTER" title="Finalize {{direction.text.proper}}">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
       <execute-stage title="Check Unhealthy Hosts" id="unhealthy-hosts">
         <task xsi:type="manual">
           <message>The following hosts were unhealthy and should be resolved before finalizing can be completed: {{hosts.unhealthy}}</message>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml
index b6c8498..ae5747a 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml
@@ -25,8 +25,11 @@
   </prerequisite-checks>
   <order>
     <group xsi:type="cluster" name="PRE_CLUSTER" title="Prepare Upgrade">
-      <skippable>true</skippable>
       <direction>UPGRADE</direction>
+
+      <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="YARN" component="RESOURCEMANAGER" title="Stop YARN Queues">
         <task xsi:type="manual">
           <message>Before continuing, please stop all YARN queues. If yarn-site's yarn.resourcemanager.work-preserving-recovery.enabled is set to true, then you can skip this step since the clients will retry on their own.</message>
@@ -122,6 +125,8 @@
     <group xsi:type="cluster" name="Backups" title="Perform Backups">
       <direction>UPGRADE</direction>
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="OOZIE" component="OOZIE_SERVER" title="Backup Oozie Database">
         <task xsi:type="manual">
           <message>Before continuing, please backup the Oozie Server database on {{hosts.all}}.</message>
@@ -519,6 +524,8 @@
     -->
     <group xsi:type="cluster" name="ALL_HOST_OPS" title="Set Version On All Hosts">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage title="Update stack to {{version}}">
         <task xsi:type="execute">
           <script>scripts/ru_set_all.py</script>
@@ -538,6 +545,8 @@
 
     <group xsi:type="cluster" name="POST_CLUSTER" title="Finalize {{direction.text.proper}}">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage title="Check Unhealthy Hosts" id="unhealthy-hosts">
         <task xsi:type="manual">
           <message>The following hosts were unhealthy and should be resolved before finalizing can be completed: {{hosts.unhealthy}}</message>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml
index b0bd7d9..566fe9e 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml
@@ -64,6 +64,8 @@
     <group xsi:type="cluster" name="PREPARE_BACKUPS" title="Prepare Backups">
       <direction>UPGRADE</direction>
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage service="HBASE" component="HBASE_MASTER" title="Pre Upgrade HBase Backup">
         <task xsi:type="execute" hosts="master">
           <script>scripts/hbase_upgrade.py</script>
@@ -353,6 +355,8 @@
 
     <group xsi:type="cluster" name="POST_CLUSTER" title="Finalize {{direction.text.proper}}">
       <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+
       <execute-stage title="Check Unhealthy Hosts" id="unhealthy-hosts">
         <task xsi:type="manual">
           <message>The following hosts were unhealthy and should be resolved before finalizing can be completed: {{hosts.unhealthy}}</message>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
index 4a203f2..50c2dfa 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
@@ -106,6 +106,7 @@ import com.google.inject.util.Modules;
 /**
  * UpgradeResourceDefinition tests.
  */
+@SuppressWarnings("unchecked")
 public class UpgradeResourceProviderTest {
 
   private UpgradeDAO upgradeDao = null;
@@ -528,8 +529,9 @@ public class UpgradeResourceProviderTest {
     assertEquals(true, resource.getPropertyValue(UpgradeResourceProvider.UPGRADE_SKIP_SC_FAILURES));
   }
 
-  @Ignore
+
   @Test
+  @Ignore
   public void testCreatePartialDowngrade() throws Exception {
     clusters.addHost("h2");
     Host host = clusters.getHost("h2");
@@ -597,9 +599,9 @@ public class UpgradeResourceProviderTest {
 
   }
 
-  @Ignore
-  @SuppressWarnings("unchecked")
+
   @Test
+  @Ignore
   public void testDowngradeToBase() throws Exception {
     Cluster cluster = clusters.getCluster("c1");
 
@@ -662,7 +664,7 @@ public class UpgradeResourceProviderTest {
 
   }
 
-  @Ignore
+
   @Test
   public void testAbort() throws Exception {
     RequestStatus status = testCreateResources();
@@ -685,7 +687,7 @@ public class UpgradeResourceProviderTest {
     urp.updateResources(req, null);
   }
 
-  @Ignore
+
   @Test
   public void testRetry() throws Exception {
     RequestStatus status = testCreateResources();
@@ -804,7 +806,7 @@ public class UpgradeResourceProviderTest {
   }
 
 
-  @Ignore
+
   @Test
   public void testPercents() throws Exception {
     RequestStatus status = testCreateResources();
@@ -853,8 +855,9 @@ public class UpgradeResourceProviderTest {
     assertEquals(100d, calc.getPercent(), 0.01d);
   }
 
-  @Ignore
+
   @Test
+  @Ignore
   public void testCreateCrossStackUpgrade() throws Exception {
     Cluster cluster = clusters.getCluster("c1");
     StackId oldStack = cluster.getDesiredStackVersion();
@@ -1144,7 +1147,12 @@ public class UpgradeResourceProviderTest {
 
     List<HostRoleCommandEntity> tasks = dao.findByRequest(entity.getRequestId());
     for (HostRoleCommandEntity task : tasks) {
-      assertTrue(task.isFailureAutoSkipped());
+      StageEntity stage = task.getStage();
+      if (stage.isSkippable() && stage.isAutoSkipOnFailureSupported()) {
+        assertTrue(task.isFailureAutoSkipped());
+      } else {
+        assertFalse(task.isFailureAutoSkipped());
+      }
     }
 
     Map<String, Object> requestProps = new HashMap<String, Object>();
@@ -1163,7 +1171,12 @@ public class UpgradeResourceProviderTest {
       if (task.getRoleCommand() == RoleCommand.SERVICE_CHECK) {
         assertFalse(task.isFailureAutoSkipped());
       } else {
-        assertTrue(task.isFailureAutoSkipped());
+        StageEntity stage = task.getStage();
+        if (stage.isSkippable() && stage.isAutoSkipOnFailureSupported()) {
+          assertTrue(task.isFailureAutoSkipped());
+        } else {
+          assertFalse(task.isFailureAutoSkipped());
+        }
       }
     }
 
@@ -1180,7 +1193,12 @@ public class UpgradeResourceProviderTest {
     tasks = dao.findByRequest(entity.getRequestId());
     for (HostRoleCommandEntity task : tasks) {
       if (task.getRoleCommand() == RoleCommand.SERVICE_CHECK) {
-        assertTrue(task.isFailureAutoSkipped());
+        StageEntity stage = task.getStage();
+        if (stage.isSkippable() && stage.isAutoSkipOnFailureSupported()) {
+          assertTrue(task.isFailureAutoSkipped());
+        } else {
+          assertFalse(task.isFailureAutoSkipped());
+        }
       } else {
         assertFalse(task.isFailureAutoSkipped());
       }
@@ -1200,8 +1218,6 @@ public class UpgradeResourceProviderTest {
     for (HostRoleCommandEntity task : tasks) {
       assertFalse(task.isFailureAutoSkipped());
     }
-
-
   }
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAOTest.java
index 167e49c..ba96353 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAOTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAOTest.java
@@ -95,9 +95,9 @@ public class HostRoleCommandDAOTest {
     HostEntity host = m_hostDAO.findByName("test_host1");
     host.setHostRoleCommandEntities(new ArrayList<HostRoleCommandEntity>());
 
-    createStage(stageId.getAndIncrement(), 3, host, requestEntity, HostRoleStatus.COMPLETED, false);
-    createStage(stageId.getAndIncrement(), 2, host, requestEntity, HostRoleStatus.SKIPPED_FAILED, false);
-    createStage(stageId.getAndIncrement(), 1, host, requestEntity, HostRoleStatus.ABORTED, false);
+    createStage(stageId.getAndIncrement(), 3, host, requestEntity, HostRoleStatus.COMPLETED);
+    createStage(stageId.getAndIncrement(), 2, host, requestEntity, HostRoleStatus.SKIPPED_FAILED);
+    createStage(stageId.getAndIncrement(), 1, host, requestEntity, HostRoleStatus.ABORTED);
 
     List<HostRoleCommandEntity> tasks = m_hostRoleCommandDAO.findByStatusBetweenStages(requestId,
         HostRoleStatus.SKIPPED_FAILED, 1, 3);
@@ -108,6 +108,61 @@ public class HostRoleCommandDAOTest {
     Assert.assertEquals(0, tasks.size());
   }
 
+  /**
+   * Tests that setting the auto-skip feature of a {@link HostRoleCommandEntity}
+   * is somewhat dependenant on the {@link StageEntity}'s support for it.
+   */
+  @Test
+  public void testAutoSkipSupport() {
+    OrmTestHelper helper = m_injector.getInstance(OrmTestHelper.class);
+    helper.createDefaultData();
+
+    Long requestId = Long.valueOf(100L);
+    ClusterEntity clusterEntity = m_clusterDAO.findByName("test_cluster1");
+
+    RequestEntity requestEntity = new RequestEntity();
+    requestEntity.setRequestId(requestId);
+    requestEntity.setClusterId(clusterEntity.getClusterId());
+    requestEntity.setStages(new ArrayList<StageEntity>());
+    m_requestDAO.create(requestEntity);
+
+    AtomicLong stageId = new AtomicLong(1);
+    HostEntity host = m_hostDAO.findByName("test_host1");
+    host.setHostRoleCommandEntities(new ArrayList<HostRoleCommandEntity>());
+
+    // start out with a stage that is skippable, supports auto skip, and has
+    // auto skip tasks
+    long stageIdAutoSkipAll = stageId.getAndIncrement();
+    createStage(stageIdAutoSkipAll, 3, host, requestEntity, HostRoleStatus.PENDING, true,
+        true, true);
+
+    List<HostRoleCommandEntity> tasks = m_hostRoleCommandDAO.findByRequest(requestId);
+    for (HostRoleCommandEntity task : tasks) {
+      Assert.assertTrue(task.isFailureAutoSkipped());
+    }
+
+    // let's try a skippable stage that doesn't support auto skip
+    long stageIdSkippableButNoAutoSkip = stageId.getAndIncrement();
+    createStage(stageIdSkippableButNoAutoSkip, 3, host, requestEntity, HostRoleStatus.PENDING, true,
+        false, true);
+
+    tasks = m_hostRoleCommandDAO.findByRequest(requestId);
+    for (HostRoleCommandEntity task : tasks) {
+      StageEntity stage = task.getStage();
+      if( stage.getStageId() == stageIdAutoSkipAll ){
+        Assert.assertTrue(task.isFailureAutoSkipped());
+      } else if( stage.getStageId() == stageIdSkippableButNoAutoSkip ){
+        Assert.assertFalse(task.isFailureAutoSkipped());
+      }
+    }
+
+    // ok, now unset them all
+    m_hostRoleCommandDAO.updateAutomaticSkipOnFailure(requestId, false, false);
+    tasks = m_hostRoleCommandDAO.findByRequest(requestId);
+    for (HostRoleCommandEntity task : tasks) {
+      Assert.assertFalse(task.isFailureAutoSkipped());
+    }
+  }
 
   /**
    * Creates a single stage with the specified number of commands.
@@ -118,10 +173,29 @@ public class HostRoleCommandDAOTest {
    * @param requestEntity
    * @param status
    * @param skipStage
+   * @param supportsAutoSkipOnFailure
    * @return
    */
   private void createStage(long startStageId, int count, HostEntity hostEntity,
-      RequestEntity requestEntity, HostRoleStatus status, boolean skipStage) {
+      RequestEntity requestEntity, HostRoleStatus status) {
+    createStage(startStageId, count, hostEntity, requestEntity, status, false, false, false);
+  }
+
+  /**
+   * Creates a single stage with the specified number of commands.
+   *
+   * @param startStageId
+   * @param count
+   * @param hostEntity
+   * @param requestEntity
+   * @param status
+   * @param skipStage
+   * @param supportsAutoSkipOnFailure
+   * @return
+   */
+  private void createStage(long startStageId, int count, HostEntity hostEntity,
+      RequestEntity requestEntity, HostRoleStatus status, boolean skipStage,
+      boolean supportsAutoSkipOnFailure, boolean autoSkipFailedCommandsInStage) {
     long stageId = startStageId;
 
     ClusterEntity clusterEntity = m_clusterDAO.findByName("test_cluster1");
@@ -132,6 +206,8 @@ public class HostRoleCommandDAOTest {
     stageEntity.setStageId(stageId);
     stageEntity.setHostRoleCommands(new ArrayList<HostRoleCommandEntity>());
     stageEntity.setSkippable(skipStage);
+    stageEntity.setAutoSkipFailureSupported(supportsAutoSkipOnFailure);
+
     m_stageDAO.create(stageEntity);
     requestEntity.getStages().add(stageEntity);
 
@@ -144,6 +220,9 @@ public class HostRoleCommandDAOTest {
       commandEntity.setRole(Role.DATANODE);
       commandEntity.setHostEntity(hostEntity);
       commandEntity.setStage(stageEntity);
+      commandEntity.setAutoSkipOnFailure(
+          autoSkipFailedCommandsInStage && skipStage && supportsAutoSkipOnFailure);
+
       m_hostRoleCommandDAO.create(commandEntity);
 
       hostEntity.getHostRoleCommandEntities().add(commandEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java
index 9f0ec54..a97d8db 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java
@@ -37,16 +37,14 @@ import org.apache.ambari.server.state.stack.UpgradePack.ProcessingComponent;
 import org.apache.ambari.server.state.stack.upgrade.ClusterGrouping;
 import org.apache.ambari.server.state.stack.upgrade.ClusterGrouping.ExecuteStage;
 import org.apache.ambari.server.state.stack.upgrade.ConfigureTask;
-import org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition.Transfer;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.Grouping;
 import org.apache.ambari.server.state.stack.upgrade.ParallelScheduler;
 import org.apache.ambari.server.state.stack.upgrade.RestartGrouping;
 import org.apache.ambari.server.state.stack.upgrade.RestartTask;
-import org.apache.ambari.server.state.stack.upgrade.StopGrouping;
 import org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping;
+import org.apache.ambari.server.state.stack.upgrade.StopGrouping;
 import org.apache.ambari.server.state.stack.upgrade.Task;
-import org.apache.ambari.server.state.stack.upgrade.TransferOperation;
 import org.apache.ambari.server.state.stack.upgrade.UpdateStackGrouping;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 import org.junit.After;
@@ -317,7 +315,27 @@ public class UpgradePackTest {
     Assert.assertTrue(upgradePack.isComponentFailureAutoSkipped());
     Assert.assertTrue(upgradePack.isServiceCheckFailureAutoSkipped());
   }
-  
+
+  /**
+   * Tests that the XML for not auto skipping skippable failures works.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testNoAutoSkipFailure() throws Exception {
+    Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("HDP", "2.2.0");
+    UpgradePack upgradePack = upgrades.get("upgrade_test_skip_failures");
+
+    List<Grouping> groups = upgradePack.getGroups(Direction.UPGRADE);
+    for (Grouping grouping : groups) {
+      if (grouping.name.equals("SKIPPABLE_BUT_NOT_AUTO_SKIPPABLE")) {
+        Assert.assertFalse(grouping.supportsAutoSkipOnFailure);
+      } else {
+        Assert.assertTrue(grouping.supportsAutoSkipOnFailure);
+      }
+    }
+  }
+
   @Test
   public void testDirectionForNonRolling() throws Exception {
     Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("HDP", "2.1.1");

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java
index 94a5336..267932c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java
@@ -88,7 +88,6 @@ public class StageWrapperBuilderTest {
 
     ServerActionTask task = (ServerActionTask)(skipSummaryWrapper.getTasks().get(0).getTasks().get(0));
     Assert.assertEquals(AutoSkipFailedSummaryAction.class.getName(), task.implClass);
-
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog213Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog213Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog213Test.java
index 521dede..16d38eb 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog213Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog213Test.java
@@ -18,15 +18,33 @@
 
 package org.apache.ambari.server.upgrade;
 
-import com.google.common.collect.Maps;
-import com.google.gson.Gson;
-import com.google.inject.AbstractModule;
-import com.google.inject.Binder;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.google.inject.Module;
-import com.google.inject.Provider;
-import com.google.inject.persist.PersistService;
+import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
@@ -74,33 +92,15 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-import javax.persistence.EntityManager;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.easymock.EasyMock.anyLong;
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.createMockBuilder;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.createStrictMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import com.google.common.collect.Maps;
+import com.google.gson.Gson;
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.persist.PersistService;
 
 /**
  * {@link org.apache.ambari.server.upgrade.UpgradeCatalog213} unit tests.
@@ -190,6 +190,29 @@ public class UpgradeCatalog213Test {
   }
 
   @Test
+  public void testExecuteStageDDLUpdates() throws Exception {
+    final DBAccessor dbAccessor = createNiceMock(DBAccessor.class);
+
+    dbAccessor.addColumn(eq("stage"), anyObject(DBAccessor.DBColumnInfo.class));
+    expectLastCall().times(1);
+
+    replay(dbAccessor);
+    Module module = new Module() {
+      @Override
+      public void configure(Binder binder) {
+        binder.bind(DBAccessor.class).toInstance(dbAccessor);
+        binder.bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
+        binder.bind(EntityManager.class).toInstance(entityManager);
+      }
+    };
+
+    Injector injector = Guice.createInjector(module);
+    UpgradeCatalog213 upgradeCatalog213 = injector.getInstance(UpgradeCatalog213.class);
+    upgradeCatalog213.executeStageDDLUpdates();
+    verify(dbAccessor);
+  }
+
+  @Test
   public void testExecuteDMLUpdates() throws Exception {
     // TODO AMBARI-13001, readd unit test section.
     /*
@@ -1056,6 +1079,7 @@ public class UpgradeCatalog213Test {
     Capture<DBAccessor.DBColumnInfo> capturedNewBlueprintColumn1 = EasyMock.newCapture();
     Capture<DBAccessor.DBColumnInfo> capturedNewBlueprintColumn2 = EasyMock.newCapture();
 
+    Capture<DBAccessor.DBColumnInfo> stageSkipColumnCapture = EasyMock.newCapture();
 
     EasyMock.expect(mockedInjector.getInstance(DaoUtils.class)).andReturn(mockedDaoUtils);
     mockedInjector.injectMembers(anyObject(UpgradeCatalog.class));
@@ -1079,6 +1103,8 @@ public class UpgradeCatalog213Test {
     mockedDbAccessor.addColumn(capture(capturedBlueprintTableName), capture(capturedNewBlueprintColumn1));
     mockedDbAccessor.addColumn(capture(capturedBlueprintTableName), capture(capturedNewBlueprintColumn2));
 
+    mockedDbAccessor.addColumn(eq("stage"), capture(stageSkipColumnCapture));
+
     mocksControl.replay();
 
     UpgradeCatalog213 testSubject = new UpgradeCatalog213(mockedInjector);
@@ -1103,7 +1129,8 @@ public class UpgradeCatalog213Test {
     Assert.assertEquals("The column name is wrong!", "security_descriptor_reference", capturedNewBlueprintColumn2
       .getValue().getName());
 
-
+    Assert.assertEquals("The column name is wrong!", "supports_auto_skip_failure",
+        stageSkipColumnCapture.getValue().getName());
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/ambari/blob/3765894a/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_skip_failures.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_skip_failures.xml b/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_skip_failures.xml
index 467e63a..8fa23c3 100644
--- a/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_skip_failures.xml
+++ b/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_skip_failures.xml
@@ -29,7 +29,18 @@
         <component>ZOOKEEPER_CLIENT</component>
       </service>
     </group>
-  </order>  
+    
+    <group name="SKIPPABLE_BUT_NOT_AUTO_SKIPPABLE" title="Skippable But Not Auto Skippable">
+      <skippable>true</skippable>
+      <supports-auto-skip-failure>false</supports-auto-skip-failure>
+      
+      <allow-retry>false</allow-retry>
+      <service name="ZOOKEEPER">
+        <component>ZOOKEEPER_SERVER</component>
+        <component>ZOOKEEPER_CLIENT</component>
+      </service>
+    </group>    
+  </order>
 
   <processing>
     <service name="ZOOKEEPER">


Mime
View raw message