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 2017/01/12 16:35:41 UTC

ambari git commit: AMBARI-19473 - Add Downgrade request validation to avoid accidental double-upgrades (jonathanhurley)

Repository: ambari
Updated Branches:
  refs/heads/trunk fdbe0939e -> 50cb77bb0


AMBARI-19473 - Add Downgrade request validation to avoid accidental double-upgrades (jonathanhurley)


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

Branch: refs/heads/trunk
Commit: 50cb77bb0b0e4b782107601497b083095fbd5221
Parents: fdbe093
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Wed Jan 11 16:26:39 2017 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Thu Jan 12 11:34:31 2017 -0500

----------------------------------------------------------------------
 .../resources/UpgradeResourceDefinition.java    |  4 +-
 .../internal/UpgradeResourceProvider.java       | 52 ++++++-------
 .../server/state/cluster/ClusterImpl.java       |  8 +-
 .../UpgradeResourceDefinitionTest.java          |  7 +-
 .../UpgradeResourceProviderHDP22Test.java       |  2 +
 .../internal/UpgradeResourceProviderTest.java   | 78 +++++++++++++++++---
 ambari-web/app/utils/ajax/ajax.js               | 15 +---
 7 files changed, 105 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/50cb77bb/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
index 64d8ee1..c44754a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
@@ -28,7 +28,6 @@ import org.apache.ambari.server.controller.spi.Resource;
  */
 public class UpgradeResourceDefinition extends SimpleResourceDefinition {
 
-  public static String DOWNGRADE_DIRECTIVE           = "downgrade";
   public static String SKIP_SERVICE_CHECKS_DIRECTIVE = "skip_service_checks";
 
   /**
@@ -39,6 +38,7 @@ public class UpgradeResourceDefinition extends SimpleResourceDefinition {
         "upgrade",
         "upgrades",
         Collections.singleton(Resource.Type.UpgradeGroup),
-        Collections.singletonMap(DirectiveType.CREATE, Arrays.asList(DOWNGRADE_DIRECTIVE, SKIP_SERVICE_CHECKS_DIRECTIVE)));
+        Collections.singletonMap(DirectiveType.CREATE,
+            Arrays.asList(SKIP_SERVICE_CHECKS_DIRECTIVE)));
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/50cb77bb/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 4c01964..6f8ebb7 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
@@ -48,7 +48,6 @@ import org.apache.ambari.server.actionmanager.RequestFactory;
 import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.actionmanager.StageFactory;
 import org.apache.ambari.server.agent.ExecutionCommand.KeyNames;
-import org.apache.ambari.server.api.resources.UpgradeResourceDefinition;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.ActionExecutionContext;
@@ -372,16 +371,17 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
           "manage upgrade and downgrade");
     }
 
-    final Map<String, String> requestInfoProps = request.getRequestInfoProperties();
-    final String forceDowngrade = requestInfoProps.get(UpgradeResourceDefinition.DOWNGRADE_DIRECTIVE);
-
-    final Direction direction = Boolean.parseBoolean(forceDowngrade) ? Direction.DOWNGRADE
-        : Direction.UPGRADE;
-
     UpgradeEntity entity = createResources(new Command<UpgradeEntity>() {
       @Override
       public UpgradeEntity invoke() throws AmbariException, AuthorizationException {
 
+        final String directionProperty = (String) requestMap.get(UPGRADE_DIRECTION);
+        if (StringUtils.isEmpty(directionProperty)) {
+          throw new AmbariException(String.format("%s is required", UPGRADE_DIRECTION));
+        }
+
+        final Direction direction = Direction.valueOf(directionProperty);
+
         // Default to ROLLING upgrade, but attempt to read from properties.
         UpgradeType upgradeType = UpgradeType.ROLLING;
         if (requestMap.containsKey(UPGRADE_TYPE)) {
@@ -1760,9 +1760,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         // Remove relevant upgrade entity
         try {
           Cluster cluster = clusters.get().getClusterById(clusterId);
-          UpgradeEntity lastUpgradeItemForCluster = s_upgradeDAO.findLastUpgradeOrDowngradeForCluster(cluster.getClusterId());
-          lastUpgradeItemForCluster.setSuspended(true);
-          s_upgradeDAO.merge(lastUpgradeItemForCluster);
+          UpgradeEntity upgradeEntity = s_upgradeDAO.findUpgradeByRequestId(requestId);
+          upgradeEntity.setSuspended(true);
+          s_upgradeDAO.merge(upgradeEntity);
 
           cluster.setUpgradeEntity(null);
         } catch (AmbariException e) {
@@ -2002,14 +2002,19 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
       String clusterName = (String) requestMap.get(UPGRADE_CLUSTER_NAME);
       String version = (String) requestMap.get(UPGRADE_VERSION);
+      String direction = (String) requestMap.get(UPGRADE_DIRECTION);
 
-      if (null == clusterName) {
+      if (StringUtils.isBlank(clusterName)) {
         throw new AmbariException(String.format("%s is required", UPGRADE_CLUSTER_NAME));
       }
 
-      if (null == version) {
+      if (StringUtils.isBlank(version)) {
         throw new AmbariException(String.format("%s is required", UPGRADE_VERSION));
       }
+
+      if (StringUtils.isBlank(direction)) {
+        throw new AmbariException(String.format("%s is required", UPGRADE_DIRECTION));
+      }
     }
   }
 
@@ -2033,22 +2038,13 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
       boolean failOnCheckWarnings = Boolean.parseBoolean((String) requestMap.get(UPGRADE_FAIL_ON_CHECK_WARNINGS));
       String preferredUpgradePack = requestMap.containsKey(UPGRADE_PACK) ? (String) requestMap.get(UPGRADE_PACK) : null;
 
-      // Validate there isn't an direction == upgrade/downgrade already in progress.
-      List<UpgradeEntity> upgrades = s_upgradeDAO.findUpgrades(cluster.getClusterId());
-      for (UpgradeEntity entity : upgrades) {
-        if (entity.getDirection() == direction) {
-          Map<Long, HostRoleCommandStatusSummaryDTO> summary = s_hostRoleCommandDAO.findAggregateCounts(
-              entity.getRequestId());
-          CalculatedStatus calc = CalculatedStatus.statusFromStageSummary(summary, summary.keySet());
-          HostRoleStatus status = calc.getStatus();
-          if (!HostRoleStatus.getCompletedStates().contains(status)) {
-            throw new AmbariException(
-                String.format("Unable to perform %s as another %s is in progress. %s request %d is in %s",
-                    direction.getText(false), direction.getText(false), direction.getText(true),
-                    entity.getRequestId().longValue(), status)
-            );
-          }
-        }
+      // verify that there is not an upgrade or downgrade that is in progress or suspended
+      UpgradeEntity existingUpgrade = cluster.getUpgradeInProgress();
+      if( null != existingUpgrade ){
+        throw new AmbariException(
+            String.format("Unable to perform %s as another %s (request ID %s) is in progress.",
+                direction.getText(false), direction.getText(false),
+                existingUpgrade.getRequestId().longValue()));
       }
 
       // skip this check if it's a downgrade or we are instructed to skip it

http://git-wip-us.apache.org/repos/asf/ambari/blob/50cb77bb/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index 6455d6e..7b0b696 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -1023,12 +1023,10 @@ public class ClusterImpl implements Cluster {
         return mostRecentUpgrade;
       }
 
-      List<HostRoleStatus> UNFINISHED_STATUSES = new ArrayList<>();
-      UNFINISHED_STATUSES.add(HostRoleStatus.PENDING);
-      UNFINISHED_STATUSES.add(HostRoleStatus.ABORTED);
-
+      // look for any item from the prior upgrade which is still in progress
+      // (not failed, completed, or aborted)
       List<HostRoleCommandEntity> commands = hostRoleCommandDAO.findByRequestIdAndStatuses(
-          mostRecentUpgrade.getRequestId(), UNFINISHED_STATUSES);
+          mostRecentUpgrade.getRequestId(), HostRoleStatus.IN_PROGRESS_STATUSES);
 
       if (!commands.isEmpty()) {
         return mostRecentUpgrade;

http://git-wip-us.apache.org/repos/asf/ambari/blob/50cb77bb/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinitionTest.java
index 6a42115..f3e475c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinitionTest.java
@@ -20,11 +20,11 @@ package org.apache.ambari.server.api.resources;
 
 import static org.junit.Assert.assertEquals;
 
-import java.util.HashSet;
-
 import org.apache.ambari.server.controller.spi.Resource;
 import org.junit.Test;
 
+import com.google.common.collect.Sets;
+
 /**
  * UpgradeResourceDefinition tests.
  */
@@ -52,8 +52,7 @@ public class UpgradeResourceDefinitionTest {
   public void testGetCreateDirectives() {
     ResourceDefinition resourceDefinition = new UpgradeResourceDefinition();
 
-    assertEquals(
-        new HashSet<String>() {{add(UpgradeResourceDefinition.DOWNGRADE_DIRECTIVE); add(UpgradeResourceDefinition.SKIP_SERVICE_CHECKS_DIRECTIVE);}},
+    assertEquals(Sets.newHashSet(UpgradeResourceDefinition.SKIP_SERVICE_CHECKS_DIRECTIVE),
         resourceDefinition.getCreateDirectives());
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/50cb77bb/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderHDP22Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderHDP22Test.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderHDP22Test.java
index 1747b28..e803529 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderHDP22Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderHDP22Test.java
@@ -74,6 +74,7 @@ import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.topology.TopologyManager;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.ambari.server.view.ViewRegistry;
@@ -242,6 +243,7 @@ public class UpgradeResourceProviderHDP22Test {
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
     requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.4.2");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/50cb77bb/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 92e4a49..a702e6f 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
@@ -46,16 +46,17 @@ import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.actionmanager.HostRoleCommand;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.actionmanager.Stage;
-import org.apache.ambari.server.api.resources.UpgradeResourceDefinition;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.audit.AuditLogger;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.AmbariServer;
+import org.apache.ambari.server.controller.ResourceProviderFactory;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.controller.spi.RequestStatus;
 import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Resource.Type;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.utilities.PredicateBuilder;
@@ -145,6 +146,7 @@ public class UpgradeResourceProviderTest {
   private AmbariMetaInfo ambariMetaInfo;
   private TopologyManager topologyManager;
   private ConfigFactory configFactory;
+  private HostRoleCommandDAO hrcDAO;
 
   @Before
   public void before() throws Exception {
@@ -185,6 +187,7 @@ public class UpgradeResourceProviderTest {
     upgradeDao = injector.getInstance(UpgradeDAO.class);
     requestDao = injector.getInstance(RequestDAO.class);
     repoVersionDao = injector.getInstance(RepositoryVersionDAO.class);
+    hrcDAO = injector.getInstance(HostRoleCommandDAO.class);
 
     AmbariEventPublisher publisher = createNiceMock(AmbariEventPublisher.class);
     replay(publisher);
@@ -297,6 +300,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_SC_FAILURES, Boolean.TRUE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_MANUAL_VERIFICATION, Boolean.FALSE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, Boolean.TRUE.toString());
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
     Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
@@ -357,6 +361,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, UpgradeType.ROLLING.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_MANUAL_VERIFICATION, Boolean.TRUE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, Boolean.TRUE.toString());
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
     Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
@@ -402,6 +407,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_SC_FAILURES, Boolean.TRUE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_MANUAL_VERIFICATION, Boolean.TRUE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, Boolean.TRUE.toString());
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
     Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
@@ -554,6 +560,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.1");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     // tests skipping SC failure options
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_FAILURES, "true");
@@ -637,9 +644,9 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.1");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.DOWNGRADE.name());
 
     Map<String, String> requestInfoProperties = new HashMap<String, String>();
-    requestInfoProperties.put(UpgradeResourceDefinition.DOWNGRADE_DIRECTIVE, "true");
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
 
@@ -671,6 +678,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.1");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
 
@@ -680,6 +688,12 @@ public class UpgradeResourceProviderTest {
     List<UpgradeEntity> upgrades = upgradeDao.findUpgrades(cluster.getClusterId());
     assertEquals(1, upgrades.size());
 
+    UpgradeEntity upgrade = upgrades.get(0);
+
+    // now abort the upgrade so another can be created
+    abortUpgrade(upgrade.getRequestId());
+
+    // create another upgrade which should fail
     requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
     requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2");
@@ -693,14 +707,15 @@ public class UpgradeResourceProviderTest {
       // !!! expected
     }
 
+    // fix the properties and try again
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
     requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_FROM_VERSION, "2.1.1.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.DOWNGRADE.name());
 
     Map<String, String> requestInfoProperties = new HashMap<>();
-    requestInfoProperties.put(UpgradeResourceDefinition.DOWNGRADE_DIRECTIVE, "true");
 
     request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), requestInfoProperties);
     RequestStatus status = upgradeResourceProvider.createResources(request);
@@ -750,6 +765,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_nonrolling_new_stack");
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, "NON_ROLLING");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
 
@@ -760,7 +776,8 @@ public class UpgradeResourceProviderTest {
     List<UpgradeEntity> upgrades = upgradeDao.findUpgrades(cluster.getClusterId());
     assertEquals(1, upgrades.size());
 
-    List<UpgradeGroupEntity> groups = upgrades.get(0).getUpgradeGroups();
+    UpgradeEntity upgrade = upgrades.get(0);
+    List<UpgradeGroupEntity> groups = upgrade.getUpgradeGroups();
     boolean isHiveGroupFound = false;
     boolean isZKGroupFound = false;
 
@@ -780,6 +797,9 @@ public class UpgradeResourceProviderTest {
     isZKGroupFound = false;
     sch.setVersion("2.2.0.0");
 
+    // now abort the upgrade so another can be created
+    abortUpgrade(upgrade.getRequestId());
+
     // create downgrade with one upgraded service
     StackId stackId = new StackId("HDP", "2.2.0");
     cluster.setDesiredStackVersion(stackId, true);
@@ -789,9 +809,9 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_nonrolling_new_stack");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_FROM_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.DOWNGRADE.name());
 
     Map<String, String> requestInfoProperties = new HashMap<>();
-    requestInfoProperties.put(UpgradeResourceDefinition.DOWNGRADE_DIRECTIVE, "true");
 
     request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), requestInfoProperties);
     RequestStatus status = upgradeResourceProvider.createResources(request);
@@ -929,6 +949,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.2.3");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_direction");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
 
@@ -949,6 +970,8 @@ public class UpgradeResourceProviderTest {
       Assert.assertFalse(item.getText().toLowerCase().contains("downgrade"));
     }
 
+    // now abort the upgrade so another can be created
+    abortUpgrade(upgrade.getRequestId());
 
     requestProps.clear();
     // Now perform a downgrade
@@ -957,11 +980,9 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_direction");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_FROM_VERSION, "2.2.2.3");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.DOWNGRADE.name());
 
-    Map<String, String> requestInfoProps = new HashMap<String, String>();
-    requestInfoProps.put("downgrade", "true");
-
-    request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), requestInfoProps);
+    request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
     upgradeResourceProvider.createResources(request);
 
     upgrades = upgradeDao.findUpgrades(cluster.getClusterId());
@@ -1056,6 +1077,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
 
@@ -1209,7 +1231,13 @@ public class UpgradeResourceProviderTest {
    * @return the provider
    */
   private UpgradeResourceProvider createProvider(AmbariManagementController amc) {
-    return new UpgradeResourceProvider(amc);
+    ResourceProviderFactory factory = injector.getInstance(ResourceProviderFactory.class);
+    AbstractControllerResourceProvider.init(factory);
+
+    Resource.Type type = Type.Upgrade;
+    return (UpgradeResourceProvider) AbstractControllerResourceProvider.getResourceProvider(type,
+        PropertyHelper.getPropertyIds(type), PropertyHelper.getKeyPropertyIds(type),
+        amc);
   }
 
   private RequestStatus testCreateResources() throws Exception {
@@ -1224,6 +1252,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.1");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
 
@@ -1405,11 +1434,12 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, UpgradeType.ROLLING.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_MANUAL_VERIFICATION, Boolean.FALSE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, Boolean.TRUE.toString());
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     // this will cause a NPE when creating the upgrade, allowing us to test
     // rollback
     UpgradeResourceProvider upgradeResourceProvider = createProvider(amc);
-    upgradeResourceProvider.s_upgradeDAO = null;
+    UpgradeResourceProvider.s_upgradeDAO = null;
 
     try {
       Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
@@ -1442,6 +1472,7 @@ public class UpgradeResourceProviderTest {
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test_host_ordered");
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, UpgradeType.HOST_ORDERED.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, Boolean.TRUE.toString());
+    requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     ResourceProvider upgradeResourceProvider = createProvider(amc);
     Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
@@ -1488,6 +1519,31 @@ public class UpgradeResourceProviderTest {
   }
 
   /**
+   * Aborts and upgrade.
+   *
+   * @param requestId
+   * @throws Exception
+   */
+  private void abortUpgrade(long requestId) throws Exception {
+    // now abort the upgrade so another can be created
+    Map<String, Object> requestProps = new HashMap<>();
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REQUEST_ID, String.valueOf(requestId));
+    requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REQUEST_STATUS, "ABORTED");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_SUSPENDED, "false");
+    Request request = PropertyHelper.getUpdateRequest(requestProps, null);
+
+    ResourceProvider upgradeResourceProvider = createProvider(amc);
+    upgradeResourceProvider.updateResources(request, null);
+
+    // !!! this is required since the ActionManager/ActionScheduler isn't
+    // running and can't remove queued PENDING - it's a cheap way of ensuring
+    // that the upgrade commands do get aborted
+    hrcDAO.updateStatusByRequestId(requestId, HostRoleStatus.ABORTED,
+        HostRoleStatus.IN_PROGRESS_STATUSES);
+  }
+
+  /**
    *
    */
   private class MockModule implements Module {

http://git-wip-us.apache.org/repos/asf/ambari/blob/50cb77bb/ambari-web/app/utils/ajax/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js
index d4b1474..e344128 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -1722,7 +1722,8 @@ var urls = {
             "repository_version": data.value,
             "upgrade_type": data.type,
             "skip_failures": data.skipComponentFailures,
-            "skip_service_check_failures": data.skipSCFailures
+            "skip_service_check_failures": data.skipSCFailures,
+            "direction": "UPGRADE"
           }
         })
       }
@@ -1735,13 +1736,11 @@ var urls = {
     'format': function (data) {
       return {
         data: JSON.stringify({
-          "RequestInfo": {
-            "downgrade": "true"
-          },
           "Upgrade": {
             "from_version": data.from,
             "repository_version": data.value,
-            "upgrade_type": data.upgradeType
+            "upgrade_type": data.upgradeType,
+            "direction": "DOWNGRADE"
           }
         })
       }
@@ -1754,9 +1753,6 @@ var urls = {
     'format': function (data) {
       return {
         data: JSON.stringify({
-          "RequestInfo": {
-            "downgrade": data.isDowngrade
-          },
           "Upgrade": {
             "request_status": "ABORTED",
             "suspended": "false"
@@ -1772,9 +1768,6 @@ var urls = {
     'format': function (data) {
       return {
         data: JSON.stringify({
-          "RequestInfo": {
-            "downgrade": data.isDowngrade
-          },
           "Upgrade": {
             "request_status": "ABORTED",
             "suspended": "true"