/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ambari.server.topology;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.powermock.api.easymock.PowerMock.mockStatic;
import java.util.Collection;
import java.util.Collections;
import javax.annotation.Nullable;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.AmbariServer;
import org.apache.ambari.server.controller.internal.ProvisionAction;
import org.apache.ambari.server.orm.entities.TopologyHostGroupEntity;
import org.apache.ambari.server.orm.entities.TopologyHostInfoEntity;
import org.apache.ambari.server.orm.entities.TopologyHostRequestEntity;
import org.apache.ambari.server.orm.entities.TopologyHostTaskEntity;
import org.apache.ambari.server.orm.entities.TopologyLogicalRequestEntity;
import org.apache.ambari.server.orm.entities.TopologyRequestEntity;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
import org.easymock.EasyMockRule;
import org.easymock.EasyMockSupport;
import org.easymock.Mock;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@RunWith(PowerMockRunner.class)
@PrepareForTest(AmbariServer.class)
public class LogicalRequestTest extends EasyMockSupport {
@Rule
public EasyMockRule mocks = new EasyMockRule(this);
@Mock
private TopologyRequest replayedTopologyRequest;
@Mock
private ClusterTopology clusterTopology;
@Mock
private TopologyLogicalRequestEntity logicalRequestEntity;
@Mock
private AmbariManagementController controller;
@Mock
private AmbariContext ambariContext;
private final long clusterId = 2L;
private final String clusterName = "myCluster";
@Mock
private Clusters clusters;
@Mock
private Cluster cluster;
@Mock
private Blueprint blueprint;
@Mock
private HostGroup hostGroup1;
@Mock
private HostGroup hostGroup2;
@Before
public void setup() throws Exception {
resetAll();
expect(controller.getClusters()).andReturn(clusters).anyTimes();
expect(clusters.getClusterById(clusterId)).andReturn(cluster).anyTimes();
expect(cluster.getClusterName()).andReturn(clusterName).anyTimes();
String topologyReqestDescription = "Provision cluster";
expect(replayedTopologyRequest.getDescription()).andReturn(topologyReqestDescription).anyTimes();
expect(clusterTopology.getAmbariContext()).andReturn(ambariContext).anyTimes();
expect(clusterTopology.getClusterId()).andReturn(clusterId).anyTimes();
expect(clusterTopology.getProvisionAction()).andReturn(ProvisionAction.INSTALL_ONLY).anyTimes();
expect(clusterTopology.getBlueprint()).andReturn(blueprint).anyTimes();
expect(blueprint.getName()).andReturn("blueprintDef").anyTimes();
expect(blueprint.shouldSkipFailure()).andReturn(true).anyTimes();
PowerMock.reset(AmbariServer.class);
mockStatic(AmbariServer.class);
expect(AmbariServer.getController()).andReturn(controller).anyTimes();
PowerMock.replay(AmbariServer.class);
}
@Test
public void testPersistedRequestsWithReservedHosts() throws Exception {
// Given
Long requestId = 1L;
TopologyHostInfoEntity host1 = new TopologyHostInfoEntity();
host1.setId(100L);
host1.setFqdn("host1");
TopologyHostInfoEntity host2 = new TopologyHostInfoEntity();
host2.setId(101L);
host2.setFqdn("host2");
TopologyHostInfoEntity host3 = new TopologyHostInfoEntity();
host3.setId(103L);
host3.setFqdn("host3");
TopologyHostInfoEntity host4 = new TopologyHostInfoEntity();
host4.setId(104L);
host4.setFqdn("host4");
TopologyHostGroupEntity hostGroupEntity1 = new TopologyHostGroupEntity();
hostGroupEntity1.setTopologyHostInfoEntities(ImmutableSet.of(host1, host2, host3, host4));
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 hostRequestEntityHost4NotMatched = new TopologyHostRequestEntity();
hostRequestEntityHost4NotMatched.setId(4L);
hostRequestEntityHost4NotMatched.setTopologyHostGroupEntity(hostGroupEntity1);
hostRequestEntityHost4NotMatched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet());
expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq(host4.getFqdn()))).andReturn(false).anyTimes();
Collection<TopologyHostRequestEntity> reservedHostRequestEntities = ImmutableSet.of(
hostRequestEntityHost1Matched,
hostRequestEntityHost2Matched,
hostRequestEntityHost3NotMatched,
hostRequestEntityHost4NotMatched);
hostGroupEntity1.setTopologyHostRequestEntities(reservedHostRequestEntities);
TopologyRequestEntity topologyRequestEntity = new TopologyRequestEntity();
topologyRequestEntity.setTopologyHostGroupEntities(Collections.singleton(hostGroupEntity1));
expect(logicalRequestEntity.getTopologyHostRequestEntities()).andReturn(reservedHostRequestEntities).atLeastOnce();
expect(logicalRequestEntity.getTopologyRequestEntity()).andReturn(topologyRequestEntity).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);
// Then
verifyAll();
// reserved hosts names are the ones that have no
// matching hosts among the registered hosts
Collection<String> actualReservedHosts = req.getReservedHosts();
Collection<String> expectedReservedHosts = ImmutableSet.of(host3.getFqdn(), host4.getFqdn());
assertEquals(expectedReservedHosts, actualReservedHosts);
Collection<HostRequest> actualCompletedHostReqs = req.getCompletedHostRequests();
assertEquals(2, actualCompletedHostReqs.size());
Optional<HostRequest> completedHostReq1 = Iterables.tryFind(actualCompletedHostReqs, new Predicate<HostRequest>() {
@Override
public boolean apply(@Nullable HostRequest input) {
return "host1".equals(input.getHostName());
}
});
Optional<HostRequest> completedHostReq2 = Iterables.tryFind(actualCompletedHostReqs, new Predicate<HostRequest>() {
@Override
public boolean apply(@Nullable HostRequest input) {
return "host2".equals(input.getHostName());
}
});
assertTrue(completedHostReq1.isPresent() && completedHostReq2.isPresent());
}
@Test
public void testPersistedRequestsWithHostPredicate() throws Exception {
// Given
Long requestId = 1L;
TopologyHostInfoEntity host = new TopologyHostInfoEntity();
host.setId(800L);
host.setPredicate("Hosts/host_name.in(host[1-4])");
TopologyHostGroupEntity hostGroupEntity2 = new TopologyHostGroupEntity();
hostGroupEntity2.setTopologyHostInfoEntities(ImmutableSet.of(host));
hostGroupEntity2.setName("host_group_2");
// host request matched to a registered host
TopologyHostRequestEntity hostRequestEntityHost1Matched = new TopologyHostRequestEntity();
hostRequestEntityHost1Matched.setId(1L);
hostRequestEntityHost1Matched.setHostName("host1"); //host request matched host1
hostRequestEntityHost1Matched.setTopologyHostGroupEntity(hostGroupEntity2);
hostRequestEntityHost1Matched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet());
expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq("host1"))).andReturn(true).anyTimes();
TopologyHostRequestEntity hostRequestEntityHost2Matched = new TopologyHostRequestEntity();
hostRequestEntityHost2Matched.setId(2L);
hostRequestEntityHost2Matched.setHostName("host2"); // host request matched host2
hostRequestEntityHost2Matched.setTopologyHostGroupEntity(hostGroupEntity2);
hostRequestEntityHost2Matched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet());
expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq("host2"))).andReturn(true).anyTimes();
// host request that hasn't been matched to any registered host yet
TopologyHostRequestEntity hostRequestEntityHost3NotMatched = new TopologyHostRequestEntity();
hostRequestEntityHost3NotMatched.setId(3L);
hostRequestEntityHost3NotMatched.setTopologyHostGroupEntity(hostGroupEntity2);
hostRequestEntityHost3NotMatched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet());
expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq("host3"))).andReturn(false).anyTimes();
TopologyHostRequestEntity hostRequestEntityHost4NotMatched = new TopologyHostRequestEntity();
hostRequestEntityHost4NotMatched.setId(4L);
hostRequestEntityHost4NotMatched.setTopologyHostGroupEntity(hostGroupEntity2);
hostRequestEntityHost4NotMatched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet());
expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq("host4"))).andReturn(false).anyTimes();
Collection<TopologyHostRequestEntity> reservedHostRequestEntities = ImmutableSet.of(
hostRequestEntityHost1Matched,
hostRequestEntityHost2Matched,
hostRequestEntityHost3NotMatched,
hostRequestEntityHost4NotMatched);
hostGroupEntity2.setTopologyHostRequestEntities(reservedHostRequestEntities);
TopologyRequestEntity topologyRequestEntity = new TopologyRequestEntity();
topologyRequestEntity.setTopologyHostGroupEntities(Collections.singleton(hostGroupEntity2));
expect(logicalRequestEntity.getTopologyHostRequestEntities()).andReturn(reservedHostRequestEntities).atLeastOnce();
expect(logicalRequestEntity.getTopologyRequestEntity()).andReturn(topologyRequestEntity).atLeastOnce();
expect(blueprint.getHostGroup(eq("host_group_2"))).andReturn(hostGroup2).atLeastOnce();
expect(hostGroup2.containsMasterComponent()).andReturn(false).atLeastOnce();
replayAll();
// When
LogicalRequest req = new LogicalRequest(requestId, replayedTopologyRequest, clusterTopology, logicalRequestEntity);
// Then
verifyAll();
// there should be no reserved hosts when host predicates are used
Collection<String> actualReservedHosts = req.getReservedHosts();
Collection<String> expectedReservedHosts = Collections.emptySet();
assertEquals(expectedReservedHosts, actualReservedHosts);
Collection<HostRequest> actualCompletedHostReqs = req.getCompletedHostRequests();
assertEquals(2, actualCompletedHostReqs.size());
Optional<HostRequest> completedHostReq1 = Iterables.tryFind(actualCompletedHostReqs, new Predicate<HostRequest>() {
@Override
public boolean apply(@Nullable HostRequest input) {
return "host1".equals(input.getHostName());
}
});
Optional<HostRequest> completedHostReq2 = Iterables.tryFind(actualCompletedHostReqs, new Predicate<HostRequest>() {
@Override
public boolean apply(@Nullable HostRequest input) {
return "host2".equals(input.getHostName());
}
});
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());
}
@Test
public void testRemovePendingHostRequests() throws Exception {
// Given
Long requestId = 1L;
final TopologyHostInfoEntity host1 = new TopologyHostInfoEntity();
host1.setId(100L);
host1.setFqdn("host1");
final TopologyHostInfoEntity host2 = new TopologyHostInfoEntity();
host2.setId(102L);
host2.setFqdn("host2");
TopologyHostGroupEntity hostGroupEntity1 = new TopologyHostGroupEntity();
hostGroupEntity1.setTopologyHostInfoEntities(ImmutableSet.of(host1, host2));
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();
// host request that hasn't been matched to any registered host yet
TopologyHostRequestEntity hostRequestEntityHost2NotMatched = new TopologyHostRequestEntity();
hostRequestEntityHost2NotMatched.setId(2L);
hostRequestEntityHost2NotMatched.setTopologyHostGroupEntity(hostGroupEntity1);
hostRequestEntityHost2NotMatched.setTopologyHostTaskEntities(Collections.<TopologyHostTaskEntity>emptySet());
expect(ambariContext.isHostRegisteredWithCluster(eq(clusterId), eq(host2.getFqdn()))).andReturn(false).anyTimes();
Collection<TopologyHostRequestEntity> reservedHostRequestEntities = ImmutableSet.of(
hostRequestEntityHost1Matched,
hostRequestEntityHost2NotMatched);
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.removePendingHostRequests(null);
// Then
verifyAll();
Collection<HostRequest> hostRequests = req.getHostRequests();
assertEquals(1, hostRequests.size());
}
}