You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by tb...@apache.org on 2014/12/10 19:32:56 UTC

ambari git commit: AMBARI-8643 - Expose Stage and Upgrade Item update status API. - initial patch (tbeerbower)

Repository: ambari
Updated Branches:
  refs/heads/trunk a5c9225c2 -> c20ff90d8


AMBARI-8643 - Expose Stage and Upgrade Item update status API. - initial patch (tbeerbower)


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

Branch: refs/heads/trunk
Commit: c20ff90d8d5c2d2aabcec2b66a7490ab115a0e5c
Parents: a5c9225
Author: tbeerbower <tb...@hortonworks.com>
Authored: Wed Dec 10 13:32:42 2014 -0500
Committer: tbeerbower <tb...@hortonworks.com>
Committed: Wed Dec 10 13:32:42 2014 -0500

----------------------------------------------------------------------
 .../server/actionmanager/StageStatus.java       |  97 ++++++++++++++
 .../internal/StageResourceProvider.java         |  81 ++++++++++--
 .../internal/UpgradeItemResourceProvider.java   |  50 +++++--
 .../server/actionmanager/StageStatusTest.java   | 132 +++++++++++++++++++
 .../internal/StageResourceProviderTest.java     |  17 +--
 5 files changed, 347 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c20ff90d/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageStatus.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageStatus.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageStatus.java
new file mode 100644
index 0000000..eaeca3e
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageStatus.java
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.actionmanager;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Stage status enum.
+ */
+public enum StageStatus {
+
+  /**
+   * Stage contains tasks not yet queued for a host.
+   */
+  PENDING,
+
+  /**
+   * Stage contains tasks that are reported to be in progress.
+   */
+  IN_PROGRESS,
+
+  /**
+   * Stage is holding, waiting for command to proceed to next stage.
+   */
+  HOLDING,
+
+  /**
+   * All tasks for this stage have completed.
+   */
+  COMPLETED,
+
+  /**
+   * At least one task for this stage has reported a failure.
+   */
+  FAILED,
+
+  /**
+   * Stage is holding after a failure, waiting for command to proceed to next stage.
+   */
+  HOLDING_FAILED,
+
+  /**
+   * At least one task for this stage has timed out.
+   */
+  TIMEDOUT,
+
+  /**
+   * Stage is holding after a time-out, waiting for command to proceed to next stage.
+   */
+  HOLDING_TIMEDOUT,
+
+  /**
+   * Operation was abandoned.
+   */
+  ABORTED;
+
+  /**
+   * Mapping of valid status transitions that that are driven by manual input.
+   */
+  private static Map<StageStatus, EnumSet<StageStatus>> manualTransitionMap = new HashMap<StageStatus, EnumSet<StageStatus>>();
+
+  static {
+    manualTransitionMap.put(HOLDING, EnumSet.of(COMPLETED));
+    manualTransitionMap.put(HOLDING_FAILED, EnumSet.of(IN_PROGRESS, FAILED));
+    manualTransitionMap.put(HOLDING_TIMEDOUT, EnumSet.of(IN_PROGRESS, TIMEDOUT));
+  }
+
+  /**
+   * Determine whether or not it is valid to transition from this stage status to the given status.
+   *
+   * @param status  the stage status being transitioned to
+   *
+   * @return true if it is valid to transition to the given stage status
+   */
+  public boolean isValidManualTransition(StageStatus status) {
+    EnumSet<StageStatus> stageStatusSet = manualTransitionMap.get(this);
+    return stageStatusSet != null && stageStatusSet.contains(status);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c20ff90d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StageResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StageResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StageResourceProvider.java
index c25152d..3904b4b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StageResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StageResourceProvider.java
@@ -19,6 +19,7 @@ package org.apache.ambari.server.controller.internal;
 
 import org.apache.ambari.server.StaticallyInject;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.actionmanager.StageStatus;
 import org.apache.ambari.server.controller.spi.ExtendedResourceProvider;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
@@ -30,6 +31,8 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.dao.StageDAO;
 import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
 import org.apache.ambari.server.orm.entities.StageEntity;
@@ -41,6 +44,7 @@ import javax.inject.Provider;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -145,7 +149,27 @@ public class StageResourceProvider extends AbstractResourceProvider implements E
   public RequestStatus updateResources(Request request, Predicate predicate)
       throws SystemException, UnsupportedPropertyException,
       NoSuchResourceException, NoSuchParentResourceException {
-    throw new UnsupportedOperationException();
+
+    Iterator<Map<String,Object>> iterator = request.getProperties().iterator();
+    if (iterator.hasNext()) {
+
+      Map<String,Object> updateProperties = iterator.next();
+
+      ensureClusters();
+
+      List<StageEntity> entities = dao.findAll(request, predicate);
+      for (StageEntity entity : entities) {
+
+        String stageStatus = (String) updateProperties.get(STAGE_STATUS);
+        if (stageStatus != null) {
+          StageStatus desiredStatus = StageStatus.valueOf(stageStatus);
+          updateStageStatus(entity, desiredStatus);
+        }
+      }
+    }
+    notifyUpdate(Resource.Type.Stage, request, predicate);
+
+    return getRequestStatus(null);
   }
 
   @Override
@@ -185,10 +209,51 @@ public class StageResourceProvider extends AbstractResourceProvider implements E
     return new QueryResponseImpl(results, request.getSortRequest() != null, false, results.size());
   }
 
+  // ----- StageResourceProvider ---------------------------------------------
+
+  /**
+   * Update the stage identified by the given stage id with the desired status.
+   *
+   * @param stageId        the stage id
+   * @param desiredStatus  the desired stage status
+   */
+  public static void updateStageStatus(long stageId, StageStatus desiredStatus) {
+    Predicate predicate =
+        new PredicateBuilder().property(STAGE_STAGE_ID).equals(stageId).toPredicate();
+
+    List<StageEntity> entityList = dao.findAll(PropertyHelper.getReadRequest(), predicate);
+    for (StageEntity stageEntity : entityList) {
+      updateStageStatus(stageEntity, desiredStatus);
+    }
+  }
+
 
   // ----- helper methods ----------------------------------------------------
 
   /**
+   * Update the given stage entity with the desired status.
+   *
+   * @param entity         the stage entity to update
+   * @param desiredStatus  the desired stage status
+   *
+   * @throws java.lang.IllegalArgumentException if the transition to the desired status is not a
+   *         legal transition
+   */
+  private static void updateStageStatus(StageEntity entity, StageStatus desiredStatus) {
+    Collection<HostRoleCommandEntity> tasks = entity.getHostRoleCommands();
+
+    Map<HostRoleStatus, Integer> taskStatusCounts = calculateTaskStatusCounts(tasks);
+
+    StageStatus currentStatus = calculateSummaryStatus(taskStatusCounts, tasks.size());
+
+    if (!currentStatus.isValidManualTransition(desiredStatus)) {
+      throw new IllegalArgumentException("Can not transition a stage from " +
+          currentStatus + " to " + desiredStatus);
+    }
+    // TODO : call ActionScheduler to release holding state
+  }
+
+  /**
    * Converts the {@link StageEntity} to a {@link Resource}.
    *
    * @param entity        the entity to convert (not {@code null})
@@ -266,12 +331,12 @@ public class StageResourceProvider extends AbstractResourceProvider implements E
    *
    * @return summary request status based on statuses of tasks in different states.
    */
-  private HostRoleStatus calculateSummaryStatus(Map<HostRoleStatus, Integer> counters, int totalTasks) {
-    return counters.get(HostRoleStatus.FAILED) > 0 ? HostRoleStatus.FAILED :
-        counters.get(HostRoleStatus.ABORTED) > 0 ? HostRoleStatus.ABORTED :
-        counters.get(HostRoleStatus.TIMEDOUT) > 0 ? HostRoleStatus.TIMEDOUT :
-        counters.get(HostRoleStatus.IN_PROGRESS) > 0 ? HostRoleStatus.IN_PROGRESS :
-        counters.get(HostRoleStatus.COMPLETED) == totalTasks ? HostRoleStatus.COMPLETED : HostRoleStatus.PENDING;
+  private static StageStatus calculateSummaryStatus(Map<HostRoleStatus, Integer> counters, int totalTasks) {
+    return counters.get(HostRoleStatus.FAILED) > 0 ? StageStatus.FAILED :
+        counters.get(HostRoleStatus.ABORTED) > 0 ? StageStatus.ABORTED :
+        counters.get(HostRoleStatus.TIMEDOUT) > 0 ? StageStatus.TIMEDOUT :
+        counters.get(HostRoleStatus.IN_PROGRESS) > 0 ? StageStatus.IN_PROGRESS :
+        counters.get(HostRoleStatus.COMPLETED) == totalTasks ? StageStatus.COMPLETED : StageStatus.PENDING;
   }
 
   /**
@@ -281,7 +346,7 @@ public class StageResourceProvider extends AbstractResourceProvider implements E
    *
    * @return a map of counts of tasks keyed by the task status
    */
-  private Map<HostRoleStatus, Integer> calculateTaskStatusCounts(Collection<HostRoleCommandEntity> tasks) {
+  private static Map<HostRoleStatus, Integer> calculateTaskStatusCounts(Collection<HostRoleCommandEntity> tasks) {
     Map<HostRoleStatus, Integer> counters = new HashMap<HostRoleStatus, Integer>();
     // initialize
     for (HostRoleStatus hostRoleStatus : HostRoleStatus.values()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/c20ff90d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java
index 85d2c9a..9d542b3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java
@@ -21,26 +21,27 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.actionmanager.StageStatus;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 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.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
 import org.apache.ambari.server.orm.entities.UpgradeItemEntity;
-import org.apache.ambari.server.state.Cluster;
-import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.UpgradeHelper;
 
 import com.google.inject.Inject;
@@ -89,13 +90,44 @@ public class UpgradeItemResourceProvider extends ReadOnlyResourceProvider {
   /**
    * Constructor.
    *
-   * @param controller
+   * @param controller  the controller
    */
   UpgradeItemResourceProvider(AmbariManagementController controller) {
     super(PROPERTY_IDS, KEY_PROPERTY_IDS, controller);
   }
 
   @Override
+  public RequestStatus updateResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+
+    // the request should contain a single map of update properties...
+    Iterator<Map<String,Object>> iterator = request.getProperties().iterator();
+    if (iterator.hasNext()) {
+
+      Map<String,Object> updateProperties = iterator.next();
+
+      String statusPropertyId = STAGE_MAPPED_IDS.get(StageResourceProvider.STAGE_STATUS);
+      String stageStatus      = (String) updateProperties.get(statusPropertyId);
+
+      if (stageStatus != null) {
+
+        StageStatus   desiredStatus = StageStatus.valueOf(stageStatus);
+        Set<Resource> resources     = getResources(PropertyHelper.getReadRequest(), predicate);
+
+        for (Resource resource : resources) {
+          // Set the desired status on the underlying stage.
+          Long stageId = (Long) resource.getPropertyValue(UPGRADE_ITEM_STAGE_ID);
+          StageResourceProvider.updateStageStatus(stageId, desiredStatus);
+        }
+      }
+    }
+    notifyUpdate(Resource.Type.UpgradeItem, request, predicate);
+
+    return getRequestStatus(null);
+  }
+
+  @Override
   public Set<Resource> getResources(Request request, Predicate predicate)
       throws SystemException, UnsupportedPropertyException,
       NoSuchResourceException, NoSuchParentResourceException {
@@ -175,16 +207,6 @@ public class UpgradeItemResourceProvider extends ReadOnlyResourceProvider {
     return results;
   }
 
-  private Cluster getCluster(Long clusterId) throws SystemException {
-    Clusters clusters = getManagementController().getClusters();
-    try {
-      return clusters.getClusterById(clusterId.longValue());
-    } catch (AmbariException e) {
-      throw new SystemException("Cannot load cluster for upgrade items");
-    }
-  }
-
-
   @Override
   protected Set<String> getPKPropertyIds() {
     return PK_PROPERTY_IDS;

http://git-wip-us.apache.org/repos/asf/ambari/blob/c20ff90d/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/StageStatusTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/StageStatusTest.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/StageStatusTest.java
new file mode 100644
index 0000000..4ed4804
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/StageStatusTest.java
@@ -0,0 +1,132 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.actionmanager;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * StageStatus tests.
+ */
+public class StageStatusTest {
+
+  @Test
+  public void testIsValidManualTransition() throws Exception {
+
+    // PENDING
+    assertFalse(StageStatus.PENDING.isValidManualTransition(StageStatus.PENDING));
+    assertFalse(StageStatus.PENDING.isValidManualTransition(StageStatus.IN_PROGRESS));
+    assertFalse(StageStatus.PENDING.isValidManualTransition(StageStatus.HOLDING));
+    assertFalse(StageStatus.PENDING.isValidManualTransition(StageStatus.COMPLETED));
+    assertFalse(StageStatus.PENDING.isValidManualTransition(StageStatus.FAILED));
+    assertFalse(StageStatus.PENDING.isValidManualTransition(StageStatus.HOLDING_FAILED));
+    assertFalse(StageStatus.PENDING.isValidManualTransition(StageStatus.TIMEDOUT));
+    assertFalse(StageStatus.PENDING.isValidManualTransition(StageStatus.HOLDING_TIMEDOUT));
+    assertFalse(StageStatus.PENDING.isValidManualTransition(StageStatus.ABORTED));
+
+    // IN_PROGRESS
+    assertFalse(StageStatus.IN_PROGRESS.isValidManualTransition(StageStatus.PENDING));
+    assertFalse(StageStatus.IN_PROGRESS.isValidManualTransition(StageStatus.IN_PROGRESS));
+    assertFalse(StageStatus.IN_PROGRESS.isValidManualTransition(StageStatus.HOLDING));
+    assertFalse(StageStatus.IN_PROGRESS.isValidManualTransition(StageStatus.COMPLETED));
+    assertFalse(StageStatus.IN_PROGRESS.isValidManualTransition(StageStatus.FAILED));
+    assertFalse(StageStatus.IN_PROGRESS.isValidManualTransition(StageStatus.HOLDING_FAILED));
+    assertFalse(StageStatus.IN_PROGRESS.isValidManualTransition(StageStatus.TIMEDOUT));
+    assertFalse(StageStatus.IN_PROGRESS.isValidManualTransition(StageStatus.HOLDING_TIMEDOUT));
+    assertFalse(StageStatus.IN_PROGRESS.isValidManualTransition(StageStatus.ABORTED));
+
+    // HOLDING
+    assertFalse(StageStatus.HOLDING.isValidManualTransition(StageStatus.PENDING));
+    assertFalse(StageStatus.HOLDING.isValidManualTransition(StageStatus.IN_PROGRESS));
+    assertFalse(StageStatus.HOLDING.isValidManualTransition(StageStatus.HOLDING));
+    assertTrue(StageStatus.HOLDING.isValidManualTransition(StageStatus.COMPLETED));
+    assertFalse(StageStatus.HOLDING.isValidManualTransition(StageStatus.FAILED));
+    assertFalse(StageStatus.HOLDING.isValidManualTransition(StageStatus.HOLDING_FAILED));
+    assertFalse(StageStatus.HOLDING.isValidManualTransition(StageStatus.TIMEDOUT));
+    assertFalse(StageStatus.HOLDING.isValidManualTransition(StageStatus.HOLDING_TIMEDOUT));
+    assertFalse(StageStatus.HOLDING.isValidManualTransition(StageStatus.ABORTED));
+
+    // COMPLETED
+    assertFalse(StageStatus.COMPLETED.isValidManualTransition(StageStatus.PENDING));
+    assertFalse(StageStatus.COMPLETED.isValidManualTransition(StageStatus.IN_PROGRESS));
+    assertFalse(StageStatus.COMPLETED.isValidManualTransition(StageStatus.HOLDING));
+    assertFalse(StageStatus.COMPLETED.isValidManualTransition(StageStatus.COMPLETED));
+    assertFalse(StageStatus.COMPLETED.isValidManualTransition(StageStatus.FAILED));
+    assertFalse(StageStatus.COMPLETED.isValidManualTransition(StageStatus.HOLDING_FAILED));
+    assertFalse(StageStatus.COMPLETED.isValidManualTransition(StageStatus.TIMEDOUT));
+    assertFalse(StageStatus.COMPLETED.isValidManualTransition(StageStatus.HOLDING_TIMEDOUT));
+    assertFalse(StageStatus.COMPLETED.isValidManualTransition(StageStatus.ABORTED));
+
+    // FAILED
+    assertFalse(StageStatus.FAILED.isValidManualTransition(StageStatus.PENDING));
+    assertFalse(StageStatus.FAILED.isValidManualTransition(StageStatus.IN_PROGRESS));
+    assertFalse(StageStatus.FAILED.isValidManualTransition(StageStatus.HOLDING));
+    assertFalse(StageStatus.FAILED.isValidManualTransition(StageStatus.COMPLETED));
+    assertFalse(StageStatus.FAILED.isValidManualTransition(StageStatus.FAILED));
+    assertFalse(StageStatus.FAILED.isValidManualTransition(StageStatus.HOLDING_FAILED));
+    assertFalse(StageStatus.FAILED.isValidManualTransition(StageStatus.TIMEDOUT));
+    assertFalse(StageStatus.FAILED.isValidManualTransition(StageStatus.HOLDING_TIMEDOUT));
+    assertFalse(StageStatus.FAILED.isValidManualTransition(StageStatus.ABORTED));
+
+    // HOLDING_FAILED
+    assertFalse(StageStatus.HOLDING_FAILED.isValidManualTransition(StageStatus.PENDING));
+    assertTrue(StageStatus.HOLDING_FAILED.isValidManualTransition(StageStatus.IN_PROGRESS));
+    assertFalse(StageStatus.HOLDING_FAILED.isValidManualTransition(StageStatus.HOLDING));
+    assertFalse(StageStatus.HOLDING_FAILED.isValidManualTransition(StageStatus.COMPLETED));
+    assertTrue(StageStatus.HOLDING_FAILED.isValidManualTransition(StageStatus.FAILED));
+    assertFalse(StageStatus.HOLDING_FAILED.isValidManualTransition(StageStatus.HOLDING_FAILED));
+    assertFalse(StageStatus.HOLDING_FAILED.isValidManualTransition(StageStatus.TIMEDOUT));
+    assertFalse(StageStatus.HOLDING_FAILED.isValidManualTransition(StageStatus.HOLDING_TIMEDOUT));
+    assertFalse(StageStatus.HOLDING_FAILED.isValidManualTransition(StageStatus.ABORTED));
+
+    // TIMEDOUT
+    assertFalse(StageStatus.TIMEDOUT.isValidManualTransition(StageStatus.PENDING));
+    assertFalse(StageStatus.TIMEDOUT.isValidManualTransition(StageStatus.IN_PROGRESS));
+    assertFalse(StageStatus.TIMEDOUT.isValidManualTransition(StageStatus.HOLDING));
+    assertFalse(StageStatus.TIMEDOUT.isValidManualTransition(StageStatus.COMPLETED));
+    assertFalse(StageStatus.TIMEDOUT.isValidManualTransition(StageStatus.FAILED));
+    assertFalse(StageStatus.TIMEDOUT.isValidManualTransition(StageStatus.HOLDING_FAILED));
+    assertFalse(StageStatus.TIMEDOUT.isValidManualTransition(StageStatus.TIMEDOUT));
+    assertFalse(StageStatus.TIMEDOUT.isValidManualTransition(StageStatus.HOLDING_TIMEDOUT));
+    assertFalse(StageStatus.TIMEDOUT.isValidManualTransition(StageStatus.ABORTED));
+
+    // HOLDING_TIMEDOUT
+    assertFalse(StageStatus.HOLDING_TIMEDOUT.isValidManualTransition(StageStatus.PENDING));
+    assertTrue(StageStatus.HOLDING_TIMEDOUT.isValidManualTransition(StageStatus.IN_PROGRESS));
+    assertFalse(StageStatus.HOLDING_TIMEDOUT.isValidManualTransition(StageStatus.HOLDING));
+    assertFalse(StageStatus.HOLDING_TIMEDOUT.isValidManualTransition(StageStatus.COMPLETED));
+    assertFalse(StageStatus.HOLDING_TIMEDOUT.isValidManualTransition(StageStatus.FAILED));
+    assertFalse(StageStatus.HOLDING_TIMEDOUT.isValidManualTransition(StageStatus.HOLDING_FAILED));
+    assertTrue(StageStatus.HOLDING_TIMEDOUT.isValidManualTransition(StageStatus.TIMEDOUT));
+    assertFalse(StageStatus.HOLDING_TIMEDOUT.isValidManualTransition(StageStatus.HOLDING_TIMEDOUT));
+    assertFalse(StageStatus.HOLDING_TIMEDOUT.isValidManualTransition(StageStatus.ABORTED));
+
+    // ABORTED
+    assertFalse(StageStatus.ABORTED.isValidManualTransition(StageStatus.PENDING));
+    assertFalse(StageStatus.ABORTED.isValidManualTransition(StageStatus.IN_PROGRESS));
+    assertFalse(StageStatus.ABORTED.isValidManualTransition(StageStatus.HOLDING));
+    assertFalse(StageStatus.ABORTED.isValidManualTransition(StageStatus.COMPLETED));
+    assertFalse(StageStatus.ABORTED.isValidManualTransition(StageStatus.FAILED));
+    assertFalse(StageStatus.ABORTED.isValidManualTransition(StageStatus.HOLDING_FAILED));
+    assertFalse(StageStatus.ABORTED.isValidManualTransition(StageStatus.TIMEDOUT));
+    assertFalse(StageStatus.ABORTED.isValidManualTransition(StageStatus.HOLDING_TIMEDOUT));
+    assertFalse(StageStatus.ABORTED.isValidManualTransition(StageStatus.ABORTED));
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/c20ff90d/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StageResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StageResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StageResourceProviderTest.java
index e2d4d9f..5471b08 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StageResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StageResourceProviderTest.java
@@ -86,14 +86,15 @@ public class StageResourceProviderTest {
   public void testUpdateResources() throws Exception {
     StageResourceProvider provider = new StageResourceProvider();
 
-    Request request = createNiceMock(Request.class);
-    Predicate predicate = createNiceMock(Predicate.class);
-    try {
-      provider.updateResources(request, predicate);
-      fail("Expected UnsupportedOperationException");
-    } catch (UnsupportedOperationException e) {
-      // expected
-    }
+    // TODO : update test to account for stage status update
+//    Request request = createNiceMock(Request.class);
+//    Predicate predicate = createNiceMock(Predicate.class);
+//    try {
+//      provider.updateResources(request, predicate);
+//      fail("Expected UnsupportedOperationException");
+//    } catch (UnsupportedOperationException e) {
+//      // expected
+//    }
   }
 
   @Test