AMBARI-20270. NPE thrown if downscale is performed before all hosts registered with cluster. (stoader)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/aebe216d Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/aebe216d Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/aebe216d Branch: refs/heads/branch-feature-AMBARI-12556 Commit: aebe216d0dd54a1104337bbdd93495bef9a9a461 Parents: 56af574 Author: Toader, Sebastian <stoa...@hortonworks.com> Authored: Fri Mar 3 10:26:44 2017 +0100 Committer: Toader, Sebastian <stoa...@hortonworks.com> Committed: Fri Mar 3 10:26:44 2017 +0100 ---------------------------------------------------------------------- .../ambari/server/topology/LogicalRequest.java | 5 +- .../server/topology/LogicalRequestTest.java | 122 +++++++++++++++++++ 2 files changed, 125 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/aebe216d/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java index 0039e35..de4211f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/LogicalRequest.java @@ -25,6 +25,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicLong; @@ -343,7 +344,7 @@ public class LogicalRequest extends Request { Iterator<HostRequest> hostRequestIterator = outstandingHostRequests.iterator(); while (hostRequestIterator.hasNext()) { - if (hostRequestIterator.next().getHostName().equals(hostName)) { + if (Objects.equals(hostRequestIterator.next().getHostName(), hostName)) { hostRequestIterator.remove(); break; } @@ -352,7 +353,7 @@ public class LogicalRequest extends Request { //todo: synchronization Iterator<HostRequest> allHostRequesIterator = allHostRequests.iterator(); while (allHostRequesIterator.hasNext()) { - if (allHostRequesIterator.next().getHostName().equals(hostName)) { + if (Objects.equals(allHostRequesIterator.next().getHostName(), hostName)) { allHostRequesIterator.remove(); break; } http://git-wip-us.apache.org/repos/asf/ambari/blob/aebe216d/ambari-server/src/test/java/org/apache/ambari/server/topology/LogicalRequestTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/LogicalRequestTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/LogicalRequestTest.java index ef4f615..42ef020 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/topology/LogicalRequestTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/LogicalRequestTest.java @@ -339,4 +339,126 @@ public class LogicalRequestTest extends EasyMockSupport { assertTrue(completedHostReq1.isPresent() && completedHostReq2.isPresent()); } + + @Test + public void testRemoveHostRequestByHostName() throws Exception { + // Given + Long requestId = 1L; + + final TopologyHostInfoEntity host1 = new TopologyHostInfoEntity(); + host1.setId(100L); + host1.setFqdn("host1"); + + final TopologyHostInfoEntity host2 = new TopologyHostInfoEntity(); + host2.setId(101L); + host2.setFqdn("host2"); + + final TopologyHostInfoEntity host3 = new TopologyHostInfoEntity(); + host3.setId(103L); + host3.setFqdn("host3"); + + final TopologyHostInfoEntity host4 = new TopologyHostInfoEntity(); + host4.setId(104L); + host4.setFqdn("host4"); + + TopologyHostGroupEntity hostGroupEntity1 = new TopologyHostGroupEntity(); + hostGroupEntity1.setTopologyHostInfoEntities(ImmutableSet.of(host1, host2, host3)); + hostGroupEntity1.setName("host_group_1"); + + // host request matched to a registered host + TopologyHostRequestEntity hostRequestEntityHost1Matched = new TopologyHostRequestEntity(); + hostRequestEntityHost1Matched.setId(1L); + hostRequestEntityHost1Matched.setHostName(host1.getFqdn()); //host request matched host1 + hostRequestEntityHost1Matched.setTopologyHostGroupEntity(hostGroupEntity1); + hostRequestEntityHost1Matched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet()); + expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq(host1.getFqdn()))).andReturn(true).anyTimes(); + + + TopologyHostRequestEntity hostRequestEntityHost2Matched = new TopologyHostRequestEntity(); + hostRequestEntityHost2Matched.setId(2L); + hostRequestEntityHost2Matched.setHostName(host2.getFqdn()); // host request matched host2 + hostRequestEntityHost2Matched.setTopologyHostGroupEntity(hostGroupEntity1); + hostRequestEntityHost2Matched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet()); + expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq(host2.getFqdn()))).andReturn(true).anyTimes(); + + // host request that hasn't been matched to any registered host yet + TopologyHostRequestEntity hostRequestEntityHost3NotMatched = new TopologyHostRequestEntity(); + hostRequestEntityHost3NotMatched.setId(3L); + hostRequestEntityHost3NotMatched.setTopologyHostGroupEntity(hostGroupEntity1); + hostRequestEntityHost3NotMatched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet()); + expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq(host3.getFqdn()))).andReturn(false).anyTimes(); + + + TopologyHostRequestEntity hostRequestEntityHost4Matched = new TopologyHostRequestEntity(); + hostRequestEntityHost4Matched.setId(4L); + hostRequestEntityHost4Matched.setHostName(host4.getFqdn()); // host request matched host4 + hostRequestEntityHost4Matched.setTopologyHostGroupEntity(hostGroupEntity1); + hostRequestEntityHost4Matched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet()); + expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq(host4.getFqdn()))).andReturn(true).anyTimes(); + + Collection<TopologyHostRequestEntity> reservedHostRequestEntities = ImmutableSet.of( + hostRequestEntityHost1Matched, + hostRequestEntityHost2Matched, + hostRequestEntityHost3NotMatched, + hostRequestEntityHost4Matched); + + hostGroupEntity1.setTopologyHostRequestEntities(reservedHostRequestEntities); + + TopologyRequestEntity topologyRequestEntity = new TopologyRequestEntity(); + topologyRequestEntity.setTopologyHostGroupEntities(Collections.singleton(hostGroupEntity1)); + + + expect(logicalRequestEntity.getTopologyRequestEntity()).andReturn(topologyRequestEntity).atLeastOnce(); + expect(logicalRequestEntity.getTopologyHostRequestEntities()).andReturn(reservedHostRequestEntities).atLeastOnce(); + expect(blueprint.getHostGroup(eq("host_group_1"))).andReturn(hostGroup1).atLeastOnce(); + expect(hostGroup1.containsMasterComponent()).andReturn(false).atLeastOnce(); + + + replayAll(); + + // When + + LogicalRequest req = new LogicalRequest(requestId, replayedTopologyRequest, clusterTopology, logicalRequestEntity); + req.removeHostRequestByHostName(host4.getFqdn()); + + + // Then + verifyAll(); + + Collection<HostRequest> hostRequests = req.getHostRequests(); + assertEquals(3, hostRequests.size()); + + Optional<HostRequest> hostReqHost1 = Iterables.tryFind(hostRequests, new Predicate<HostRequest>() { + @Override + public boolean apply(@Nullable HostRequest input) { + return host1.getFqdn().equals(input.getHostName()); + } + }); + + Optional<HostRequest> hostReqHost2 = Iterables.tryFind(hostRequests, new Predicate<HostRequest>() { + @Override + public boolean apply(@Nullable HostRequest input) { + return host2.getFqdn().equals(input.getHostName()); + } + }); + + + Optional<HostRequest> hostReqHost3 = Iterables.tryFind(hostRequests, new Predicate<HostRequest>() { + @Override + public boolean apply(@Nullable HostRequest input) { + return input.getHostName() == null; + } + }); + + + Optional<HostRequest> hostReqHost4 = Iterables.tryFind(hostRequests, new Predicate<HostRequest>() { + @Override + public boolean apply(@Nullable HostRequest input) { + return host4.getFqdn().equals(input.getHostName()); + } + }); + + + assertTrue(hostReqHost1.isPresent() && hostReqHost2.isPresent() && hostReqHost3.isPresent() && !hostReqHost4.isPresent()); + } }