Repository: ambari
Updated Branches:
  refs/heads/trunk 6ece2d24b -> ce77ec515


AMBARI-6673 Expose ability to cancel requests via API (Dmitro Lisnichenko via 
dsen)


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

Branch: refs/heads/trunk
Commit: ce77ec515e80f9413e0939ea1134ddd17f2a1a7e
Parents: 6ece2d2
Author: Dmytro Sen <d...@hortonworks.com>
Authored: Wed Jul 30 20:19:32 2014 +0300
Committer: Dmytro Sen <d...@hortonworks.com>
Committed: Wed Jul 30 20:19:32 2014 +0300

----------------------------------------------------------------------
 .../server/actionmanager/ActionManager.java     |   5 +
 .../ambari/server/actionmanager/Request.java    |   9 -
 .../server/api/services/RequestService.java     |  18 ++
 .../server/controller/RequestRequest.java       |  82 ++++++++
 .../internal/RequestResourceProvider.java       | 192 +++++++++++++------
 .../src/main/resources/properties.json          |   1 +
 .../internal/RequestResourceProviderTest.java   |  76 +++++++-
 7 files changed, 312 insertions(+), 71 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ce77ec51/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java
index 4bb9d1d..d51a792 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java
@@ -219,4 +219,9 @@ public class ActionManager {
   public String getRequestContext(long requestId) {
     return db.getRequestContext(requestId);
   }
+
+  public void cancelRequest(Request request) {
+    // TODO: implement (dlysnichenko)
+    // TODO : what if cluster name == null?
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ce77ec51/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
index 6e35071..74eb6c1 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
@@ -53,7 +53,6 @@ public class Request {
   private long createTime;
   private long startTime;
   private long endTime;
-  private HostRoleStatus status; // not persisted yet
   private String inputs;
   private List<RequestResourceFilter> resourceFilters;
   private RequestOperationLevel operationLevel;
@@ -160,7 +159,6 @@ public class Request {
 
     this.requestType = entity.getRequestType();
     this.commandName = entity.getCommandName();
-    this.status = entity.getStatus();
     if (entity.getRequestScheduleEntity() != null) {
       this.requestScheduleId = 
entity.getRequestScheduleEntity().getScheduleId();
     }
@@ -373,11 +371,4 @@ public class Request {
         '}';
   }
 
-  public HostRoleStatus getStatus() {
-    return status;
-  }
-
-  public void setStatus(HostRoleStatus status) {
-    this.status = status;
-  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ce77ec51/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestService.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestService.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestService.java
index 9483254..fc1b515 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestService.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestService.java
@@ -24,6 +24,7 @@ import org.apache.ambari.server.controller.spi.Resource;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -104,6 +105,23 @@ public class RequestService extends BaseService {
   }
 
   /**
+   * Handles: PUT /clusters/{clusterId}/requests/{requestId} or 
/requests/{requestId}
+   * Change state of existing requests. Usually used to cancel running requests
+   *
+   * @param body        http body
+   * @param headers     http headers
+   * @param ui          uri info
+   * @return information regarding the created services
+   */
+  @PUT
+  @Path("{requestId}")
+  @Produces("text/plain")
+  public Response updateRequests(String body, @Context HttpHeaders headers, 
@Context UriInfo ui,
+                                 @PathParam("requestId") String requestId) {
+    return handleRequest(headers, body, ui, Request.Type.PUT, 
createRequestResource(m_clusterName, requestId));
+  }
+
+  /**
    * Handles: POST /clusters/{clusterId}/requests or /requests
    * Create multiple services.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/ce77ec51/ambari-server/src/main/java/org/apache/ambari/server/controller/RequestRequest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/RequestRequest.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/RequestRequest.java
new file mode 100644
index 0000000..db9268b
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/RequestRequest.java
@@ -0,0 +1,82 @@
+/**
+ * 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.controller;
+
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+
+/**
+ * Encapsulates all data about update request that came to 
RequestResourceProvider
+ */
+public class RequestRequest {
+
+  public RequestRequest(String clusterName, long requestId) {
+    this.clusterName = clusterName;
+    this.requestId = requestId;
+  }
+
+  private String clusterName;
+
+  private long requestId;
+
+  private HostRoleStatus status;
+
+  private String abortReason;
+
+
+  public HostRoleStatus getStatus() {
+    return status;
+  }
+
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  public long getRequestId() {
+    return requestId;
+  }
+
+  public void setRequestId(int requestId) {
+    this.requestId = requestId;
+  }
+
+  public void setStatus(HostRoleStatus status) {
+    this.status = status;
+  }
+
+  public String getAbortReason() {
+    return abortReason;
+  }
+
+  public void setAbortReason(String abortReason) {
+    this.abortReason = abortReason;
+  }
+
+  @Override
+  public String toString() {
+    return "RequestRequest{" +
+            "clusterName='" + clusterName + '\'' +
+            ", requestId=" + requestId +
+            ", status=" + status +
+            ", abortReason='" + abortReason + '\'' +
+            '}';
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/ce77ec51/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
index c7eecec..838cf38 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
@@ -24,6 +24,7 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.api.services.BaseRequest;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.ExecuteActionRequest;
+import org.apache.ambari.server.controller.RequestRequest;
 import org.apache.ambari.server.controller.RequestStatusResponse;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
@@ -42,6 +43,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -56,6 +58,7 @@ public class RequestResourceProvider extends 
AbstractControllerResourceProvider
   protected static final String REQUEST_CLUSTER_NAME_PROPERTY_ID = 
"Requests/cluster_name";
   protected static final String REQUEST_ID_PROPERTY_ID = "Requests/id";
   protected static final String REQUEST_STATUS_PROPERTY_ID = 
"Requests/request_status";
+  protected static final String REQUEST_ABORT_REASON_PROPERTY_ID = 
"Requests/abort_reason";
   protected static final String REQUEST_CONTEXT_ID = 
"Requests/request_context";
   public static final String REQUEST_SOURCE_SCHEDULE = 
"Requests/request_schedule";
   public static final String REQUEST_SOURCE_SCHEDULE_ID = 
"Requests/request_schedule/schedule_id";
@@ -159,9 +162,79 @@ public class RequestResourceProvider extends 
AbstractControllerResourceProvider
   }
 
   @Override
-  public RequestStatus updateResources(Request request, Predicate predicate)
-      throws SystemException, UnsupportedPropertyException, 
NoSuchResourceException, NoSuchParentResourceException {
-    throw new UnsupportedOperationException("Not currently supported.");
+  public RequestStatus updateResources(Request requestInfo, Predicate 
predicate)
+          throws SystemException, UnsupportedPropertyException,
+          NoSuchResourceException, NoSuchParentResourceException {
+    AmbariManagementController amc = getManagementController();
+    final Set<RequestRequest> requests = new HashSet<RequestRequest>();
+
+    Iterator<Map<String,Object>> iterator = 
requestInfo.getProperties().iterator();
+    if (iterator.hasNext()) {
+      for (Map<String, Object> propertyMap : getPropertyMaps(iterator.next(), 
predicate)) {
+        requests.add(getRequest(propertyMap));
+      }
+    }
+    // Validate
+    List<org.apache.ambari.server.actionmanager.Request> targets =
+            new ArrayList<org.apache.ambari.server.actionmanager.Request>();
+    for (RequestRequest updateRequest : requests) {
+      ActionManager actionManager = amc.getActionManager();
+      List<org.apache.ambari.server.actionmanager.Request> internalRequests =
+              
actionManager.getRequests(Collections.singletonList(updateRequest.getRequestId()));
+      if (internalRequests.size() == 0) {
+        throw new IllegalArgumentException(
+                String.format("Request %s does not exist", 
updateRequest.getRequestId()));
+      }
+      // There should be only one request with this id (or no request at all)
+      org.apache.ambari.server.actionmanager.Request internalRequest = 
internalRequests.get(0);
+      // Validate update request (check constraints on state value and 
presense of abort reason)
+      if (updateRequest.getAbortReason() == null || 
updateRequest.getAbortReason().isEmpty()) {
+        throw new IllegalArgumentException("Abort reason can not be empty.");
+      }
+
+      HostRoleStatus internalRequestStatus = calculateSummaryStatus(
+              calculateRequestStatusCounters(internalRequest),
+              internalRequest.getCommands().size()
+      );
+      if (updateRequest.getStatus() != HostRoleStatus.ABORTED) {
+        throw new IllegalArgumentException(
+                String.format("%s is wrong value. The only allowed value " +
+                                "for updating request status is ABORTED",
+                        updateRequest.getStatus()));
+      }
+      if (internalRequestStatus.isCompletedState()) {
+        throw new IllegalArgumentException(
+                String.format("Can not set request that is in %s state to %s 
state.",
+                        internalRequestStatus.toString(), 
updateRequest.getStatus()));
+      }
+      // Validation passed
+      targets.add(internalRequest);
+    }
+    // Perform update
+    for (org.apache.ambari.server.actionmanager.Request target : targets) {
+      amc.getActionManager().cancelRequest(target);
+    }
+    return getRequestStatus(null);
+  }
+
+  private RequestRequest getRequest(Map<String, Object> propertyMap) {
+    // Cluster name may be empty for custom actions
+    String clusterNameStr = (String) 
propertyMap.get(REQUEST_CLUSTER_NAME_PROPERTY_ID);
+    String requestIdStr = (String) propertyMap.get(REQUEST_ID_PROPERTY_ID);
+    long requestId = Integer.valueOf(requestIdStr);
+    String requestStatusStr = (String) 
propertyMap.get(REQUEST_STATUS_PROPERTY_ID);
+    HostRoleStatus requestStatus = null;
+    if (requestStatusStr != null) {
+      // This conversion may throw IllegalArgumentException, it is OK
+      // in this case it will be mapped to HTTP 400 Bad Request
+      requestStatus = HostRoleStatus.valueOf(requestStatusStr);
+    }
+    String abortReason = (String) 
propertyMap.get(REQUEST_ABORT_REASON_PROPERTY_ID);
+    RequestRequest requestRequest = new RequestRequest(clusterNameStr, 
requestId);
+    requestRequest.setStatus(requestStatus);
+    requestRequest.setAbortReason(abortReason);
+    return requestRequest;
+
   }
 
   @Override
@@ -351,67 +424,76 @@ public class RequestResourceProvider extends 
AbstractControllerResourceProvider
     } else {
       setResourceProperty(resource, REQUEST_SOURCE_SCHEDULE, null, 
requestedPropertyIds);
     }
+    int taskCount = request.getCommands().size();
 
-    List<HostRoleCommand> commands = request.getCommands();
-
-    int taskCount = commands.size();
-    int completedTaskCount = 0;
-    int queuedTaskCount = 0;
-    int pendingTaskCount = 0;
-    int failedTaskCount = 0;
-    int abortedTaskCount = 0;
-    int timedOutTaskCount = 0;
-
-    for (HostRoleCommand hostRoleCommand : commands) {
-      HostRoleStatus status = hostRoleCommand.getStatus();
-      if (status.isCompletedState()) {
-        completedTaskCount++;
-
-        switch (status) {
-          case ABORTED:
-            abortedTaskCount++;
-            break;
-          case FAILED:
-            failedTaskCount++;
-            break;
-          case TIMEDOUT:
-            timedOutTaskCount++;
-            break;
-        }
-      } else if (status.equals(HostRoleStatus.QUEUED)) {
-        queuedTaskCount++;
-      } else if (status.equals(HostRoleStatus.PENDING)) {
-        pendingTaskCount++;
-      }
-    }
-
-    int inProgressTaskCount = taskCount - completedTaskCount - queuedTaskCount 
- pendingTaskCount;
+    Map<HostRoleStatus, Integer> hostRoleStatusCounters = 
calculateRequestStatusCounters(request);
+    HostRoleStatus requestStatus = 
calculateSummaryStatus(hostRoleStatusCounters, taskCount);
 
-    LOG.debug("taskCount={}, inProgressTaskCount={}, completedTaskCount={}, 
queuedTaskCount={}, " +
-      "pendingTaskCount={}, failedTaskCount={}, abortedTaskCount={}, 
timedOutTaskCount={}",
-      taskCount, inProgressTaskCount, completedTaskCount, queuedTaskCount, 
pendingTaskCount,
-      failedTaskCount, abortedTaskCount, timedOutTaskCount);
-
-    // determine request status
-    HostRoleStatus requestStatus = failedTaskCount > 0 ? HostRoleStatus.FAILED 
:
-        abortedTaskCount > 0 ? HostRoleStatus.ABORTED :
-            timedOutTaskCount > 0 ? HostRoleStatus.TIMEDOUT :
-                inProgressTaskCount > 0 ? HostRoleStatus.IN_PROGRESS :
-                    completedTaskCount == taskCount ? HostRoleStatus.COMPLETED 
:
-                        HostRoleStatus.PENDING;
     double progressPercent =
-        ((queuedTaskCount * 0.09 + inProgressTaskCount * 0.35 + 
completedTaskCount) / (double) taskCount) * 100.0;
+            ((hostRoleStatusCounters.get(HostRoleStatus.QUEUED) * 0.09 +
+                    hostRoleStatusCounters.get(HostRoleStatus.IN_PROGRESS) * 
0.35 +
+                    hostRoleStatusCounters.get(HostRoleStatus.COMPLETED)) / 
(double) taskCount) * 100.0;
 
     setResourceProperty(resource, REQUEST_STATUS_PROPERTY_ID, 
requestStatus.toString(), requestedPropertyIds);
     setResourceProperty(resource, REQUEST_TASK_CNT_ID, taskCount, 
requestedPropertyIds);
-    setResourceProperty(resource, REQUEST_FAILED_TASK_CNT_ID, failedTaskCount, 
requestedPropertyIds);
-    setResourceProperty(resource, REQUEST_ABORTED_TASK_CNT_ID, 
abortedTaskCount, requestedPropertyIds);
-    setResourceProperty(resource, REQUEST_TIMED_OUT_TASK_CNT_ID, 
timedOutTaskCount, requestedPropertyIds);
-    setResourceProperty(resource, REQUEST_QUEUED_TASK_CNT_ID, queuedTaskCount, 
requestedPropertyIds);
-    setResourceProperty(resource, REQUEST_COMPLETED_TASK_CNT_ID, 
completedTaskCount, requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_FAILED_TASK_CNT_ID,
+            hostRoleStatusCounters.get(HostRoleStatus.FAILED), 
requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_ABORTED_TASK_CNT_ID,
+            hostRoleStatusCounters.get(HostRoleStatus.ABORTED), 
requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_TIMED_OUT_TASK_CNT_ID,
+            hostRoleStatusCounters.get(HostRoleStatus.TIMEDOUT), 
requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_QUEUED_TASK_CNT_ID,
+            hostRoleStatusCounters.get(HostRoleStatus.QUEUED), 
requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_COMPLETED_TASK_CNT_ID,
+            hostRoleStatusCounters.get(HostRoleStatus.COMPLETED), 
requestedPropertyIds);
     setResourceProperty(resource, REQUEST_PROGRESS_PERCENT_ID, 
progressPercent, requestedPropertyIds);
 
     return resource;
   }
 
+  /**
+   * Returns counts of tasks that are in various states.
+   */
+  private Map<HostRoleStatus, Integer> 
calculateRequestStatusCounters(org.apache.ambari.server.actionmanager.Request 
request) {
+    List<HostRoleCommand> commands = request.getCommands();
+    Map<HostRoleStatus, Integer> counters = new HashMap<HostRoleStatus, 
Integer>();
+    int totalTasks = commands.size();
+    // initialize
+    for (HostRoleStatus hostRoleStatus : HostRoleStatus.values()) {
+      counters.put(hostRoleStatus, 0);
+    }
+    // calculate counts
+    for (HostRoleCommand hostRoleCommand : commands) {
+      HostRoleStatus status = hostRoleCommand.getStatus();
+      if (status.isCompletedState() &&
+            status != HostRoleStatus.COMPLETED ) { // we don't want to count 
twice
+        // Increase total number of completed tasks;
+        counters.put(HostRoleStatus.COMPLETED, 
counters.get(HostRoleStatus.COMPLETED) + 1);
+      }
+      // Increment counter for particular status
+      counters.put(status, counters.get(status) + 1);
+    }
+    // We overwrite the value to have the sum converged
+    counters.put(HostRoleStatus.IN_PROGRESS,
+            totalTasks - counters.get(HostRoleStatus.COMPLETED)-
+                    counters.get(HostRoleStatus.QUEUED)-
+                    counters.get(HostRoleStatus.PENDING));
+    return counters;
+  }
+
+  /**
+   * @param counters counts of tasks that are in various states.
+   * @param totalTasks total number of tasks in request
+   * @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 :
+            // TODO (dlysnichenko): maybe change order of FAILED and ABORTED?
+            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;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ce77ec51/ambari-server/src/main/resources/properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/properties.json 
b/ambari-server/src/main/resources/properties.json
index 170fa4b..237f646 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -123,6 +123,7 @@
         "Requests/completed_task_count",
         "Requests/queued_task_count",
         "Requests/progress_percent",
+        "Requests/abort_reason",
         "_"
     ],
     "RequestSchedule" : [

http://git-wip-us.apache.org/repos/asf/ambari/blob/ce77ec51/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
index 5c0d538..f5d8227 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
@@ -760,14 +760,33 @@ public class RequestResourceProviderTest {
   }
 
   @Test
-  public void testUpdateResources() throws Exception {
+  public void testUpdateResources_CancelRequest() throws Exception {
     Resource.Type type = Resource.Type.Request;
 
     AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
+    ActionManager actionManager = createNiceMock(ActionManager.class);
+    HostRoleCommand hostRoleCommand = createNiceMock(HostRoleCommand.class);
+    Clusters clusters = createNiceMock(Clusters.class);
+
+    List<HostRoleCommand> hostRoleCommands = new LinkedList<HostRoleCommand>();
+    hostRoleCommands.add(hostRoleCommand);
+
+    org.apache.ambari.server.actionmanager.Request requestMock =
+            
createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock.getCommands()).andReturn(hostRoleCommands).anyTimes();
+
+    Capture<Collection<Long>> requestIdsCapture = new 
Capture<Collection<Long>>();
+
+    // set expectations
+    
expect(managementController.getActionManager()).andReturn(actionManager).anyTimes();
+    expect(actionManager.getRequests(capture(requestIdsCapture))).
+            andReturn(Collections.singletonList(requestMock)).anyTimes();
+    
expect(hostRoleCommand.getStatus()).andReturn(HostRoleStatus.IN_PROGRESS).anyTimes();
+
     RequestStatusResponse response = 
createNiceMock(RequestStatusResponse.class);
 
     // replay
-    replay(managementController, response);
+    replay(managementController, actionManager, hostRoleCommand, clusters, 
requestMock, response);
 
     ResourceProvider provider = 
AbstractControllerResourceProvider.getResourceProvider(
         type,
@@ -775,22 +794,65 @@ public class RequestResourceProviderTest {
         PropertyHelper.getKeyPropertyIds(type),
         managementController);
 
+    // TEST CASE: Check update request validation (abort reason not specified)
     // add the property map to a set for the request.
     Map<String, Object> properties = new LinkedHashMap<String, Object>();
-
     // create the request
     Request request = PropertyHelper.getUpdateRequest(properties, null);
-
     Predicate predicate = new 
PredicateBuilder().property(RequestResourceProvider.REQUEST_ID_PROPERTY_ID).
-        equals("Request100").toPredicate();
+        equals("100").toPredicate();
 
     try {
       provider.updateResources(request, predicate);
-      Assert.fail("Expected an UnsupportedOperationException");
-    } catch (UnsupportedOperationException e) {
+      Assert.fail("Expected an java.lang.IllegalArgumentException: Abort 
reason can not be empty.");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+
+    // Add abort reason to previous request
+    properties.put(RequestResourceProvider.REQUEST_ABORT_REASON_PROPERTY_ID, 
"Some reason");
+
+    // TEST CASE: Check update request validation (new state is not specified)
+    request = PropertyHelper.getUpdateRequest(properties, null);
+    try {
+      provider.updateResources(request, predicate);
+      Assert.fail("Expected an java.lang.IllegalArgumentException: null is 
wrong value.");
+    } catch (IllegalArgumentException e) {
       // expected
     }
 
+    // TEST CASE: Check update request validation (new state is wrong)
+    properties.put(RequestResourceProvider.REQUEST_STATUS_PROPERTY_ID, 
"COMPLETED");
+    request = PropertyHelper.getUpdateRequest(properties, null);
+    try {
+      provider.updateResources(request, predicate);
+      Assert.fail("Expected an java.lang.IllegalArgumentException: COMPLETED 
is wrong value. " +
+              "The only allowed value for updating request status is ABORTED");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+
+    // TEST CASE: Check update request validation (request is in wrong state)
+    // Put valid request status
+    properties.put(RequestResourceProvider.REQUEST_STATUS_PROPERTY_ID, 
"ABORTED");
+    for (HostRoleStatus status : HostRoleStatus.values()) {
+      reset(hostRoleCommand);
+      expect(hostRoleCommand.getStatus()).andReturn(status).anyTimes();
+      replay(hostRoleCommand);
+      request = PropertyHelper.getUpdateRequest(properties, null);
+      if (status == HostRoleStatus.IN_PROGRESS ||
+              status == HostRoleStatus.PENDING ||
+              status == HostRoleStatus.QUEUED) { // the only valid cases
+        provider.updateResources(request, predicate);
+      } else {  // In other cases, should error out
+        try {
+          provider.updateResources(request, predicate);
+          Assert.fail("Expected an java.lang.IllegalArgumentException: null is 
wrong value.");
+        } catch (IllegalArgumentException e) {
+          // expected
+        }
+      }
+    }
     // verify
     verify(managementController, response);
   }

Reply via email to