Repository: ambari
Updated Branches:
  refs/heads/trunk dc85e67d7 -> e6983857b


AMBARI-21575. Ambari REST API to support setting rack info during add host. 
(stoader)


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

Branch: refs/heads/trunk
Commit: e6983857be6fe1fdfd4c393fec27b08aa3e2ce45
Parents: dc85e67
Author: Toader, Sebastian <stoa...@hortonworks.com>
Authored: Thu Jul 27 17:31:13 2017 +0200
Committer: Toader, Sebastian <stoa...@hortonworks.com>
Committed: Thu Jul 27 17:31:13 2017 +0200

----------------------------------------------------------------------
 .../internal/HostResourceProvider.java          | 82 +++++++++++++++++---
 .../ambari/server/topology/AmbariContext.java   |  2 +-
 .../AmbariManagementControllerTest.java         |  6 +-
 .../internal/HostResourceProviderTest.java      | 27 ++++++-
 4 files changed, 100 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/e6983857/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 8ef42ba..01e0aac 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
@@ -193,7 +193,7 @@ public class HostResourceProvider extends 
AbstractControllerResourceProvider {
     } else {
       createResources(new Command<Void>() {
         @Override
-        public Void invoke() throws AmbariException {
+        public Void invoke() throws AmbariException, AuthorizationException {
           createHosts(request);
           return null;
         }
@@ -428,7 +428,7 @@ public class HostResourceProvider extends 
AbstractControllerResourceProvider {
    * @param request Request that must contain registered hosts, and optionally 
a cluster.
    */
   public synchronized void createHosts(Request request)
-      throws AmbariException {
+      throws AmbariException, AuthorizationException {
 
     Set<Map<String, Object>> propertySet = request.getProperties();
     if (propertySet == null || propertySet.isEmpty()) {
@@ -501,6 +501,74 @@ public class HostResourceProvider extends 
AbstractControllerResourceProvider {
     }
     clusters.updateHostWithClusterAndAttributes(hostClustersMap, 
hostAttributes);
 
+    updateHostRackInfoIfChanged(clusters, hostRequests);
+
+  }
+
+  /**
+   * Iterates through the provided host request and checks if there is rack 
info provided.
+   * If the rack info differs from the rack info of the host than updates it 
with the value from
+   * the host request.
+   * @param clusters
+   * @param hostRequests 
+   * @throws AmbariException
+   * @throws AuthorizationException
+   */
+  private void updateHostRackInfoIfChanged(Clusters clusters, Set<HostRequest> 
hostRequests)
+    throws AmbariException, AuthorizationException {
+
+    HashSet<String> rackChangeAffectedClusters = new HashSet<>();
+
+    for (HostRequest hostRequest : hostRequests) {
+      String clusterName = hostRequest.getClusterName();
+
+      if (StringUtils.isNotBlank(clusterName)) {
+        Cluster cluster = clusters.getCluster(clusterName);
+        Host host = clusters.getHost(hostRequest.getHostname());
+
+        if (updateHostRackInfoIfChanged(cluster, host, hostRequest))
+          rackChangeAffectedClusters.add(clusterName);
+      }
+    }
+
+    for (String clusterName: rackChangeAffectedClusters) {
+      getManagementController().registerRackChange(clusterName);
+    }
+  }
+
+
+
+  /**
+   * If the rack info provided in the request differs from the rack info of 
the host
+   * update the rack info of the host with the value from the host request
+   *
+   * @param cluster The cluster to check user privileges against. User is 
required
+   *                to have {@link RoleAuthorization#HOST_ADD_DELETE_HOSTS} 
rights on the cluster.
+   * @param host The host of which rack information is to be updated
+   * @param hostRequest
+   * @return true is host was updated otherwise false
+   * @throws AmbariException
+   * @throws AuthorizationException
+   */
+  private boolean updateHostRackInfoIfChanged(Cluster cluster, Host host, 
HostRequest hostRequest)
+    throws AmbariException, AuthorizationException {
+
+    Long resourceId = cluster.getResourceId();
+
+    String hostRackInfo = host.getRackInfo();
+    String requestRackInfo = hostRequest.getRackInfo();
+
+    boolean rackChange = requestRackInfo != null && 
!requestRackInfo.equals(hostRackInfo);
+
+    if (rackChange) {
+      if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, resourceId, 
RoleAuthorization.HOST_ADD_DELETE_HOSTS)) {
+        throw new AuthorizationException("The authenticated user is not 
authorized to update host rack information");
+      }
+
+      host.setRackInfo(requestRackInfo);
+    }
+
+    return rackChange;
   }
 
   private void createHostResource(Clusters clusters, Set<String> duplicates,
@@ -705,16 +773,8 @@ public class HostResourceProvider extends 
AbstractControllerResourceProvider {
         // do nothing
       }
 
-      String  rackInfo        = host.getRackInfo();
-      String  requestRackInfo = request.getRackInfo();
-      boolean rackChange      = requestRackInfo != null && 
!requestRackInfo.equals(rackInfo);
+      boolean rackChange = updateHostRackInfoIfChanged(cluster, host, request);
 
-      if (rackChange) {
-        if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, resourceId, 
RoleAuthorization.HOST_ADD_DELETE_HOSTS)) {
-          throw new AuthorizationException("The authenticated user is not 
authorized to update host rack information");
-        }
-        host.setRackInfo(requestRackInfo);
-      }
 
       if (null != request.getPublicHostName()) {
         if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, resourceId, 
RoleAuthorization.HOST_ADD_DELETE_HOSTS)) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/e6983857/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
index fe56760..662f9aa 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
@@ -304,7 +304,7 @@ public class AmbariContext {
 
     try {
       getHostResourceProvider().createHosts(new RequestImpl(null, 
Collections.singleton(properties), null, null));
-    } catch (AmbariException e) {
+    } catch (AmbariException | AuthorizationException e) {
       LOG.error("Unable to create host component resource for host {}", 
hostName, e);
       throw new RuntimeException(String.format("Unable to create host resource 
for host '%s': %s",
           hostName, e.toString()), e);

http://git-wip-us.apache.org/repos/asf/ambari/blob/e6983857/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
index fc42ff9..efb150f 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
@@ -1797,7 +1797,7 @@ public class AmbariManagementControllerTest {
   }
 
   @Test
-  public void testCreateHostSimple() throws AmbariException {
+  public void testCreateHostSimple() throws AmbariException, 
AuthorizationException {
     String cluster1 = getUniqueName();
     String host1 = getUniqueName();
     String host2 = getUniqueName();
@@ -1826,7 +1826,7 @@ public class AmbariManagementControllerTest {
     try {
       HostResourceProviderTest.createHosts(controller, requests);
       fail("Create host should fail for invalid clusters");
-    } catch (Exception e) {
+    } catch (AmbariException e) {
       // Expected
     }
 
@@ -1850,7 +1850,7 @@ public class AmbariManagementControllerTest {
   }
 
   @Test
-  public void testCreateHostMultiple() throws AmbariException {
+  public void testCreateHostMultiple() throws AmbariException, 
AuthorizationException {
     String host1 = getUniqueName();
     String host2 = getUniqueName();
     String host3 = getUniqueName();

http://git-wip-us.apache.org/repos/asf/ambari/blob/e6983857/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
index a4cc6fc..c6fdd28 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.server.controller.internal;
 
 import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
@@ -80,6 +81,7 @@ import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.stack.OsFamily;
 import org.apache.ambari.server.topology.LogicalRequest;
 import org.apache.ambari.server.topology.TopologyManager;
+import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.easymock.EasyMockSupport;
 import org.junit.After;
@@ -124,26 +126,40 @@ public class HostResourceProviderTest extends 
EasyMockSupport {
     Injector injector = createInjector();
 
     AmbariManagementController managementController = 
injector.getInstance(AmbariManagementController.class);
+    Capture<String> rackChangeAffectedClusterName = EasyMock.newCapture();
+    
managementController.registerRackChange(capture(rackChangeAffectedClusterName));
+    EasyMock.expectLastCall().once();
+
+
     Clusters clusters = injector.getInstance(Clusters.class);
     Cluster cluster = createMock(Cluster.class);
+    Host host = createMock(Host.class);
     ResourceProviderFactory resourceProviderFactory = 
createNiceMock(ResourceProviderFactory.class);
     ResourceProvider hostResourceProvider = getHostProvider(injector);
 
     AbstractControllerResourceProvider.init(resourceProviderFactory);
 
     expect(cluster.getClusterId()).andReturn(2L).anyTimes();
+    expect(cluster.getResourceId()).andReturn(4L).anyTimes();
     expect(cluster.getDesiredConfigs()).andReturn(new HashMap<String, 
DesiredConfig>()).anyTimes();
 
     expect(clusters.getCluster("Cluster100")).andReturn(cluster).atLeastOnce();
-    expect(clusters.getHost("Host100")).andReturn(null).atLeastOnce();
+    expect(clusters.getHost("Host100")).andReturn(host).atLeastOnce();
     clusters.updateHostWithClusterAndAttributes(EasyMock.<Map<String, 
Set<String>>>anyObject(), EasyMock.<Map<String, Map<String, 
String>>>anyObject());
     EasyMock.expectLastCall().once();
 
+
+    expect(host.getRackInfo()).andReturn("/default-rack").anyTimes();
+    Capture<String> newRack = EasyMock.newCapture();
+    host.setRackInfo(capture(newRack));
+    EasyMock.expectLastCall().once();
+
     
expect(managementController.getClusters()).andReturn(clusters).atLeastOnce();
 
     
expect(resourceProviderFactory.getHostResourceProvider(EasyMock.<Set<String>>anyObject(),
         EasyMock.<Map<Resource.Type, String>>anyObject(),
         eq(managementController))).andReturn(hostResourceProvider).anyTimes();
+
     // replay
     replayAll();
 
@@ -163,6 +179,7 @@ public class HostResourceProviderTest extends 
EasyMockSupport {
     // add properties to the request map
     properties.put(HostResourceProvider.HOST_CLUSTER_NAME_PROPERTY_ID, 
"Cluster100");
     properties.put(HostResourceProvider.HOST_HOST_NAME_PROPERTY_ID, "Host100");
+    properties.put(HostResourceProvider.HOST_RACK_INFO_PROPERTY_ID, 
"/test-rack");
 
     propertySet.add(properties);
 
@@ -173,6 +190,12 @@ public class HostResourceProviderTest extends 
EasyMockSupport {
 
     // verify
     verifyAll();
+
+    // the registerRackChange should be called on AmbariManagementController 
for Cluster100 cluster
+    assertEquals("Cluster100", rackChangeAffectedClusterName.getValue());
+
+    // new rack info of the host should be /test-rack
+    assertEquals("/test-rack", newRack.getValue());
   }
 
   @Test
@@ -1294,7 +1317,7 @@ public class HostResourceProviderTest extends 
EasyMockSupport {
     verifyAll();
   }
 
-  public static void createHosts(AmbariManagementController controller, 
Set<HostRequest> requests) throws AmbariException {
+  public static void createHosts(AmbariManagementController controller, 
Set<HostRequest> requests) throws AmbariException, AuthorizationException {
     HostResourceProvider provider = getHostProvider(controller);
     Set<Map<String, Object>> properties = new HashSet<>();
 

Reply via email to