You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by aj...@apache.org on 2016/04/21 01:01:32 UTC

ambari git commit: AMBARI-15847. add bulk host delete api

Repository: ambari
Updated Branches:
  refs/heads/trunk 5af48693e -> cc10ec0b4


AMBARI-15847. add bulk host delete api


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

Branch: refs/heads/trunk
Commit: cc10ec0b4acdfb522ff193fc66f777aa82b9f6be
Parents: 5af4869
Author: Ajit Kumar <aj...@apache.org>
Authored: Wed Apr 20 16:01:24 2016 -0700
Committer: Ajit Kumar <aj...@apache.org>
Committed: Wed Apr 20 16:01:24 2016 -0700

----------------------------------------------------------------------
 .../ambari/server/api/services/HostService.java |  8 ++
 .../internal/HostResourceProvider.java          | 82 +++++++++++++-------
 .../server/api/handlers/UpdateHandlerTest.java  | 60 +-------------
 .../creator/AuditEventCreatorTestHelper.java    | 11 +++
 4 files changed, 77 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/cc10ec0b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
index c54d30f..0ce29ae 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
@@ -195,6 +195,14 @@ public class HostService extends BaseService {
         createHostResource(m_clusterName, hostName, ui));
   }
 
+  @DELETE
+  @Produces("text/plain")
+  public Response deleteHosts(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, body, ui, Request.Type.DELETE,
+            createHostResource(m_clusterName, null, ui));
+  }
+
   /**
    * Get the host_components sub-resource.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/cc10ec0b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
index 2bd1664..4dc47be 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
@@ -333,22 +333,21 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
   protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate)
       throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
 
-    final Set<HostRequest> requests = new HashSet<HostRequest>();
+    final Set<HostRequest> requests = new HashSet<>();
     for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
       requests.add(getRequest(propertyMap));
     }
 
-    modifyResources(new Command<Void>() {
+    DeleteStatusMetaData deleteStatusMetaData = modifyResources(new Command<DeleteStatusMetaData>() {
       @Override
-      public Void invoke() throws AmbariException {
-        deleteHosts(requests);
-        return null;
+      public DeleteStatusMetaData invoke() throws AmbariException {
+        return deleteHosts(requests);
       }
     });
 
     notifyDelete(Resource.Type.Host, predicate);
 
-    return getRequestStatus(null);
+    return getRequestStatus(null, null, deleteStatusMetaData);
   }
 
   @Override
@@ -828,13 +827,14 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
   }
 
   @Transactional
-  protected void deleteHosts(Set<HostRequest> requests)
+  protected DeleteStatusMetaData deleteHosts(Set<HostRequest> requests)
       throws AmbariException {
 
     AmbariManagementController controller = getManagementController();
     Clusters                   clusters   = controller.getClusters();
+    DeleteStatusMetaData deleteStatusMetaData = new DeleteStatusMetaData();
 
-    List<HostRequest> okToRemove = new ArrayList<HostRequest>();
+    List<HostRequest> okToRemove = new ArrayList<>();
 
     for (HostRequest hostRequest : requests) {
       String hostName = hostRequest.getHostname();
@@ -842,7 +842,54 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
         continue;
       }
 
-      Set<String> clusterNamesForHost = new HashSet<String>();
+      try {
+        validateHostInDeleteFriendlyState(hostRequest, clusters);
+        okToRemove.add(hostRequest);
+      } catch (Exception ex) {
+        deleteStatusMetaData.addException(hostName, ex);
+      }
+    }
+
+    for (HostRequest hostRequest : okToRemove) {
+      // Assume the user also wants to delete it entirely, including all clusters.
+      String hostname = hostRequest.getHostname();
+      try {
+        clusters.deleteHost(hostname);
+        deleteStatusMetaData.addDeletedKey(hostname);
+      } catch (Exception ex) {
+        deleteStatusMetaData.addException(hostname, ex);
+      }
+      for (LogicalRequest logicalRequest: topologyManager.getRequests(Collections.<Long>emptyList())) {
+        logicalRequest.removeHostRequestByHostName(hostname);
+      }
+
+      if (null != hostRequest.getClusterName()) {
+        clusters.getCluster(hostRequest.getClusterName()).recalculateAllClusterVersionStates();
+      }
+    }
+
+    //Do not break behavior for existing clients where delete request contains only 1 host.
+    //Response for these requests will have empty body with appropriate error code.
+    if (deleteStatusMetaData.getDeletedKeys().size() + deleteStatusMetaData.getExceptionForKeys().size() == 1) {
+      if (deleteStatusMetaData.getDeletedKeys().size() == 1) {
+        return null;
+      }
+      for (Map.Entry<String, Exception> entry : deleteStatusMetaData.getExceptionForKeys().entrySet()) {
+        Exception ex =  entry.getValue();
+        if (ex instanceof AmbariException) {
+          throw (AmbariException)ex;
+        } else {
+          throw new AmbariException(ex.getMessage(), ex);
+        }
+      }
+    }
+
+    return deleteStatusMetaData;
+  }
+
+  private void validateHostInDeleteFriendlyState(HostRequest hostRequest, Clusters clusters ) throws AmbariException {
+    Set<String> clusterNamesForHost = new HashSet<>();
+    String hostName = hostRequest.getHostname();
       if (null != hostRequest.getClusterName()) {
         clusterNamesForHost.add(hostRequest.getClusterName());
       } else {
@@ -885,23 +932,6 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
           }
         }
       }
-      okToRemove.add(hostRequest);
-    }
-
-    for (HostRequest hostRequest : okToRemove) {
-      // Assume the user also wants to delete it entirely, including all clusters.
-      clusters.deleteHost(hostRequest.getHostname());
-
-      removeHostFromClusterTopology(clusters, hostRequest);
-
-      for (LogicalRequest logicalRequest: topologyManager.getRequests(Collections.<Long>emptyList())) {
-        logicalRequest.removeHostRequestByHostName(hostRequest.getHostname());
-      }
-
-      if (null != hostRequest.getClusterName()) {
-        clusters.getCluster(hostRequest.getClusterName()).recalculateAllClusterVersionStates();
-      }
-    }
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/cc10ec0b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java
index 85eea31..797ba65 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/handlers/UpdateHandlerTest.java
@@ -51,64 +51,6 @@ public class UpdateHandlerTest {
     ViewRegistry.initInstance(new ViewRegistry(publisher));
   }
 
-  @Test
-  public void testHandleRequest__Synchronous_NoPropsInBody() throws Exception {
-    Request request = createMock(Request.class);
-    RequestBody body = createNiceMock(RequestBody.class);
-    ResourceInstance resource = createMock(ResourceInstance.class);
-    PersistenceManager pm = createStrictMock(PersistenceManager.class);
-    RequestStatus status = createMock(RequestStatus.class);
-    Resource resource1 = createMock(Resource.class);
-    Resource resource2 = createMock(Resource.class);
-    Predicate userPredicate = createNiceMock(Predicate.class);
-    Query query = createNiceMock(Query.class);
-    Renderer renderer = new DefaultRenderer();
-
-    Set<Resource> setResources = new HashSet<Resource>();
-    setResources.add(resource1);
-    setResources.add(resource2);
-
-    // expectations
-    expect(request.getResource()).andReturn(resource).anyTimes();
-    expect(request.getBody()).andReturn(body).anyTimes();
-    expect(request.getQueryPredicate()).andReturn(userPredicate).atLeastOnce();
-    expect(request.getRenderer()).andReturn(renderer);
-
-    expect(resource.getQuery()).andReturn(query).atLeastOnce();
-    query.setRenderer(renderer);
-    query.setUserPredicate(userPredicate);
-
-    expect(pm.update(resource, body)).andReturn(status);
-    expect(status.getStatus()).andReturn(RequestStatus.Status.Complete);
-    expect(status.getAssociatedResources()).andReturn(setResources);
-    expect(resource1.getType()).andReturn(Resource.Type.Cluster).anyTimes();
-    expect(resource2.getType()).andReturn(Resource.Type.Cluster).anyTimes();
-
-    replay(request, body, resource, pm, status, resource1, resource2, userPredicate, query);
-
-    Result result = new TestUpdateHandler(pm).handleRequest(request);
-
-    assertNotNull(result);
-    TreeNode<Resource> tree = result.getResultTree();
-    assertEquals(1, tree.getChildren().size());
-    TreeNode<Resource> resourcesNode = tree.getChild("resources");
-    assertEquals(2, resourcesNode.getChildren().size());
-    boolean foundResource1 = false;
-    boolean foundResource2 = false;
-    for(TreeNode<Resource> child : resourcesNode.getChildren()) {
-      Resource r = child.getObject();
-      if (r == resource1 && ! foundResource1) {
-        foundResource1 = true;
-      } else if (r == resource2 && ! foundResource2) {
-        foundResource2 = true;
-      } else {
-        fail();
-      }
-    }
-
-    assertEquals(ResultStatus.STATUS.OK, result.getStatus().getStatus());
-    verify(request, body, resource, pm, status, resource1, resource2, userPredicate, query);
-  }
 
   @Test
   public void testHandleRequest__Synchronous() throws Exception {
@@ -139,6 +81,7 @@ public class UpdateHandlerTest {
 
     expect(pm.update(resource, body)).andReturn(status);
     expect(status.getStatus()).andReturn(RequestStatus.Status.Complete);
+    expect(status.getStatusMetadata()).andReturn(null);
     expect(status.getAssociatedResources()).andReturn(setResources);
     expect(resource1.getType()).andReturn(Resource.Type.Cluster).anyTimes();
     expect(resource2.getType()).andReturn(Resource.Type.Cluster).anyTimes();
@@ -199,6 +142,7 @@ public class UpdateHandlerTest {
 
     expect(pm.update(resource, body)).andReturn(status);
     expect(status.getStatus()).andReturn(RequestStatus.Status.Accepted);
+    expect(status.getStatusMetadata()).andReturn(null);
     expect(status.getAssociatedResources()).andReturn(setResources);
     expect(resource1.getType()).andReturn(Resource.Type.Cluster).anyTimes();
     expect(resource2.getType()).andReturn(Resource.Type.Cluster).anyTimes();

http://git-wip-us.apache.org/repos/asf/ambari/blob/cc10ec0b/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java b/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java
index 86c1ebb..29bd8e9 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/AuditEventCreatorTestHelper.java
@@ -33,6 +33,7 @@ import org.apache.ambari.server.api.services.NamedPropertySet;
 import org.apache.ambari.server.api.services.Request;
 import org.apache.ambari.server.api.services.RequestBody;
 import org.apache.ambari.server.api.services.Result;
+import org.apache.ambari.server.api.services.ResultMetadata;
 import org.apache.ambari.server.api.services.ResultStatus;
 import org.apache.ambari.server.api.util.TreeNode;
 import org.apache.ambari.server.audit.AuditLogger;
@@ -248,6 +249,16 @@ public class AuditEventCreatorTestHelper {
       public void setResultStatus(ResultStatus status) {
 
       }
+
+      @Override
+      public void setResultMetadata(ResultMetadata resultMetadata) {
+
+      }
+
+      @Override
+      public ResultMetadata getResultMetadata() {
+        return null;
+      }
     };
   }
 }