Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 5181E200B13 for ; Wed, 15 Jun 2016 14:16:26 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 5044C160A4D; Wed, 15 Jun 2016 12:16:26 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 4D935160A4C for ; Wed, 15 Jun 2016 14:16:25 +0200 (CEST) Received: (qmail 24442 invoked by uid 500); 15 Jun 2016 12:16:24 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 24433 invoked by uid 99); 15 Jun 2016 12:16:24 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 15 Jun 2016 12:16:24 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 52F54DFBA8; Wed, 15 Jun 2016 12:16:24 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: stoader@apache.org To: commits@ambari.apache.org Message-Id: <2cd27c27f7214927843c04947004027d@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: ambari git commit: AMBARI-17219. Removing and re-adding hosts makes database inconsitent. (Daniel Gergely via stoader) Date: Wed, 15 Jun 2016 12:16:24 +0000 (UTC) archived-at: Wed, 15 Jun 2016 12:16:26 -0000 Repository: ambari Updated Branches: refs/heads/trunk afb4b6dc9 -> 4fe413e95 AMBARI-17219. Removing and re-adding hosts makes database inconsitent. (Daniel Gergely via stoader) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4fe413e9 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4fe413e9 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4fe413e9 Branch: refs/heads/trunk Commit: 4fe413e95063405b5d40a010b83b7559dc4eb0f1 Parents: afb4b6d Author: Daniel Gergely Authored: Wed Jun 15 14:14:17 2016 +0200 Committer: Toader, Sebastian Committed: Wed Jun 15 14:16:10 2016 +0200 ---------------------------------------------------------------------- .../ambari/server/topology/TopologyManager.java | 16 ++++ .../server/topology/TopologyManagerTest.java | 96 +++++++++++++------- 2 files changed, 77 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/4fe413e9/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyManager.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyManager.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyManager.java index e3f5b49..4a1e29e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyManager.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyManager.java @@ -27,6 +27,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -300,6 +301,8 @@ public class TopologyManager { "blueprint can be scaled with this API. If the cluster was originally created " + "via the API as described above, please file a Jira for this matter."); } + + hostNameCheck(request, topology); request.setClusterId(clusterId); PersistedTopologyRequest persistedRequest = persistedState.persistTopologyRequest(request); // this registers/updates all request host groups @@ -308,6 +311,19 @@ public class TopologyManager { ambariContext.getNextRequestId()).getRequestId()); } + private void hostNameCheck(ScaleClusterRequest request, ClusterTopology topology) throws InvalidTopologyException { + Set hostNames = new HashSet<>(); + for(Map.Entry entry : request.getHostGroupInfo().entrySet()) { + hostNames.addAll(entry.getValue().getHostNames()); + } + for(String hostName : hostNames) { + // check if host exists already + if(topology.getHostGroupForHost(hostName) != null) { + throw new InvalidTopologyException("Host " + hostName + " cannot be added, because it is already in the cluster"); + } + } + } + public void onHostRegistered(HostImpl host, boolean associatedWithCluster) { ensureInitialized(); LOG.info("TopologyManager.onHostRegistered: Entering"); http://git-wip-us.apache.org/repos/asf/ambari/blob/4fe413e9/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java index fd8653c..017eab5 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java @@ -18,40 +18,23 @@ package org.apache.ambari.server.topology; -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; -import static org.easymock.EasyMock.isA; -import static org.easymock.EasyMock.isNull; -import static org.easymock.EasyMock.newCapture; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.reset; -import static org.easymock.EasyMock.verify; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; - +import junit.framework.Assert; +import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.controller.ClusterRequest; import org.apache.ambari.server.controller.ConfigurationRequest; import org.apache.ambari.server.controller.RequestStatusResponse; +import org.apache.ambari.server.controller.internal.HostResourceProvider; import org.apache.ambari.server.controller.internal.ProvisionClusterRequest; +import org.apache.ambari.server.controller.internal.ScaleClusterRequest; import org.apache.ambari.server.controller.internal.Stack; import org.apache.ambari.server.controller.spi.ClusterController; import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.ResourceProvider; import org.apache.ambari.server.security.encryption.CredentialStoreService; +import org.apache.ambari.server.stack.NoSuchStackException; import org.apache.ambari.server.state.SecurityType; import org.easymock.Capture; +import org.easymock.EasyMock; import org.easymock.EasyMockRule; import org.easymock.EasyMockSupport; import org.easymock.Mock; @@ -62,6 +45,31 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +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; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.isNull; +import static org.easymock.EasyMock.newCapture; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reset; +import static org.easymock.EasyMock.verify; + /** * TopologyManager unit tests */ @@ -244,7 +252,7 @@ public class TopologyManagerTest { expect(request.getHostGroupInfo()).andReturn(groupInfoMap).anyTimes(); expect(request.getTopologyValidators()).andReturn(topologyValidators).anyTimes(); - expect(request.getConfigRecommendationStrategy()).andReturn(ConfigRecommendationStrategy.NEVER_APPLY); + expect(request.getConfigRecommendationStrategy()).andReturn(ConfigRecommendationStrategy.NEVER_APPLY).anyTimes(); expect(request.getSecurityConfiguration()).andReturn(null).anyTimes(); @@ -276,40 +284,41 @@ public class TopologyManagerTest { andReturn(logicalRequest).anyTimes(); expect(logicalRequest.getRequestId()).andReturn(1L).anyTimes(); expect(logicalRequest.getReservedHosts()).andReturn(Collections.singleton("host1")).anyTimes(); - expect(logicalRequest.getRequestStatus()).andReturn(requestStatusResponse).once(); + expect(logicalRequest.getRequestStatus()).andReturn(requestStatusResponse).anyTimes(); expect(ambariContext.getPersistedTopologyState()).andReturn(persistedState).anyTimes(); //todo: don't ignore param ambariContext.createAmbariResources(isA(ClusterTopology.class), eq(CLUSTER_NAME), (SecurityType) isNull(), (String) isNull()); - expectLastCall().once(); - expect(ambariContext.getNextRequestId()).andReturn(1L).once(); + expectLastCall().anyTimes(); + expect(ambariContext.getNextRequestId()).andReturn(1L).anyTimes(); expect(ambariContext.isClusterKerberosEnabled(CLUSTER_ID)).andReturn(false).anyTimes(); expect(ambariContext.getClusterId(CLUSTER_NAME)).andReturn(CLUSTER_ID).anyTimes(); expect(ambariContext.getClusterName(CLUSTER_ID)).andReturn(CLUSTER_NAME).anyTimes(); // cluster configuration task run() isn't executed by mock executor // so only INITIAL config expect(ambariContext.createConfigurationRequests(capture(configRequestPropertiesCapture))). - andReturn(Collections.singletonList(configurationRequest)); + andReturn(Collections.singletonList(configurationRequest)).anyTimes(); expect(ambariContext.createConfigurationRequests(capture(configRequestPropertiesCapture2))). - andReturn(Collections.singletonList(configurationRequest2)).once(); + andReturn(Collections.singletonList(configurationRequest2)).anyTimes(); expect(ambariContext.createConfigurationRequests(capture(configRequestPropertiesCapture3))). - andReturn(Collections.singletonList(configurationRequest3)).once(); + andReturn(Collections.singletonList(configurationRequest3)).anyTimes(); ambariContext.setConfigurationOnCluster(capture(updateClusterConfigRequestCapture)); - expectLastCall().times(3); + expectLastCall().anyTimes(); ambariContext.persistInstallStateForUI(CLUSTER_NAME, STACK_NAME, STACK_VERSION); - expectLastCall().once(); + expectLastCall().anyTimes(); expect(clusterController.ensureResourceProvider(anyObject(Resource.Type.class))).andReturn(resourceProvider); expect(executor.submit(anyObject(AsyncCallableService.class))).andReturn(mockFuture); - expectLastCall().times(1); + expectLastCall().anyTimes(); expect(persistedState.getAllRequests()).andReturn(Collections.>emptyMap()).once(); - expect(persistedState.persistTopologyRequest(request)).andReturn(persistedTopologyRequest).once(); + List>emptyMap()).anyTimes(); + expect(persistedState.persistTopologyRequest(request)).andReturn(persistedTopologyRequest).anyTimes(); persistedState.persistLogicalRequest(logicalRequest, 1); + expectLastCall().anyTimes(); replay(blueprint, stack, request, group1, group2, ambariContext, logicalRequestFactory, logicalRequest, configurationRequest, configurationRequest2, configurationRequest3, requestStatusResponse, executor, @@ -343,4 +352,21 @@ public class TopologyManagerTest { //todo: assertions } + @Test(expected = InvalidTopologyException.class) + public void testScaleHosts__alreadyExistingHost() throws InvalidTopologyTemplateException, InvalidTopologyException, AmbariException, NoSuchStackException { + HashSet> propertySet = new HashSet<>(); + Map properties = new TreeMap<>(); + properties.put(HostResourceProvider.HOST_NAME_PROPERTY_ID, "host1"); + properties.put(HostResourceProvider.HOSTGROUP_PROPERTY_ID, "group1"); + properties.put(HostResourceProvider.HOST_CLUSTER_NAME_PROPERTY_ID, CLUSTER_NAME); + properties.put(HostResourceProvider.BLUEPRINT_PROPERTY_ID, BLUEPRINT_NAME); + propertySet.add(properties); + BlueprintFactory bpfMock = EasyMock.createNiceMock(BlueprintFactory.class); + EasyMock.expect(bpfMock.getBlueprint(BLUEPRINT_NAME)).andReturn(blueprint).anyTimes(); + ScaleClusterRequest.init(bpfMock); + EasyMock.replay(bpfMock); + topologyManager.provisionCluster(request); + topologyManager.scaleHosts(new ScaleClusterRequest(propertySet)); + Assert.fail("InvalidTopologyException should have been thrown"); + } }