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<>();