blob: 4427e12b838f59afcc1b299c9fc66dd4fb7d0458 [file] [log] [blame]
/**
* 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.state.cluster;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.RollbackException;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.agent.AgentEnv;
import org.apache.ambari.server.agent.AgentEnv.Directory;
import org.apache.ambari.server.agent.DiskInfo;
import org.apache.ambari.server.agent.HostInfo;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.controller.ClusterResponse;
import org.apache.ambari.server.controller.ConfigurationResponse;
import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
import org.apache.ambari.server.orm.OrmTestHelper;
import org.apache.ambari.server.orm.dao.ClusterDAO;
import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
import org.apache.ambari.server.orm.dao.HostComponentStateDAO;
import org.apache.ambari.server.orm.dao.HostDAO;
import org.apache.ambari.server.orm.dao.HostVersionDAO;
import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
import org.apache.ambari.server.orm.dao.StackDAO;
import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
import org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity;
import org.apache.ambari.server.orm.entities.ClusterEntity;
import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
import org.apache.ambari.server.orm.entities.ClusterStateEntity;
import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
import org.apache.ambari.server.orm.entities.HostEntity;
import org.apache.ambari.server.orm.entities.HostStateEntity;
import org.apache.ambari.server.orm.entities.HostVersionEntity;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
import org.apache.ambari.server.orm.entities.ResourceEntity;
import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity;
import org.apache.ambari.server.orm.entities.StackEntity;
import org.apache.ambari.server.state.AgentVersion;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.state.ComponentInfo;
import org.apache.ambari.server.state.Config;
import org.apache.ambari.server.state.ConfigFactory;
import org.apache.ambari.server.state.ConfigImpl;
import org.apache.ambari.server.state.DesiredConfig;
import org.apache.ambari.server.state.Host;
import org.apache.ambari.server.state.HostHealthStatus;
import org.apache.ambari.server.state.HostState;
import org.apache.ambari.server.state.MaintenanceState;
import org.apache.ambari.server.state.RepositoryVersionState;
import org.apache.ambari.server.state.Service;
import org.apache.ambari.server.state.ServiceComponent;
import org.apache.ambari.server.state.ServiceComponentFactory;
import org.apache.ambari.server.state.ServiceComponentHost;
import org.apache.ambari.server.state.ServiceComponentHostFactory;
import org.apache.ambari.server.state.ServiceFactory;
import org.apache.ambari.server.state.StackId;
import org.apache.ambari.server.state.State;
import org.apache.ambari.server.state.configgroup.ConfigGroup;
import org.apache.ambari.server.state.configgroup.ConfigGroupFactory;
import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
import org.apache.ambari.server.state.host.HostHealthyHeartbeatEvent;
import org.apache.ambari.server.state.host.HostRegistrationRequestEvent;
import org.apache.commons.lang.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.persist.PersistService;
import com.google.inject.persist.Transactional;
import com.google.inject.persist.UnitOfWork;
import com.google.inject.util.Modules;
import junit.framework.Assert;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ClusterTest {
private Clusters clusters;
private Cluster c1;
private Injector injector;
private ServiceFactory serviceFactory;
private ServiceComponentFactory serviceComponentFactory;
private ServiceComponentHostFactory serviceComponentHostFactory;
private AmbariMetaInfo metaInfo;
private ConfigFactory configFactory;
private ConfigGroupFactory configGroupFactory;
private OrmTestHelper helper;
private StackDAO stackDAO;
private ResourceTypeDAO resourceTypeDAO;
private ClusterDAO clusterDAO;
private HostDAO hostDAO;
private ClusterVersionDAO clusterVersionDAO;
private HostVersionDAO hostVersionDAO;
private HostComponentStateDAO hostComponentStateDAO;
private RepositoryVersionDAO repositoryVersionDAO;
private Gson gson;
@Singleton
static class ClusterVersionDAOMock extends ClusterVersionDAO {
static boolean failOnCurrentVersionState;
static List<ClusterVersionEntity> mockedClusterVersions;
@Override
@Transactional
public ClusterVersionEntity merge(ClusterVersionEntity entity) {
if (!failOnCurrentVersionState || entity.getState() != RepositoryVersionState.CURRENT) {
return super.merge(entity);
} else {
throw new RollbackException();
}
}
@Override
@Transactional
public List<ClusterVersionEntity> findByCluster(String clusterName) {
if (mockedClusterVersions == null) {
return super.findByCluster(clusterName);
} else {
return mockedClusterVersions;
}
}
}
private static class MockModule extends AbstractModule {
@Override
protected void configure() {
bind(ClusterVersionDAO.class).to(ClusterVersionDAOMock.class);
}
}
@Before
public void setup() throws Exception {
injector = Guice.createInjector(Modules.override(new InMemoryDefaultTestModule()).with(new MockModule()));
injector.getInstance(GuiceJpaInitializer.class);
clusters = injector.getInstance(Clusters.class);
serviceFactory = injector.getInstance(ServiceFactory.class);
configGroupFactory = injector.getInstance(ConfigGroupFactory.class);
serviceComponentFactory = injector.getInstance(
ServiceComponentFactory.class);
serviceComponentHostFactory = injector.getInstance(
ServiceComponentHostFactory.class);
configFactory = injector.getInstance(ConfigFactory.class);
metaInfo = injector.getInstance(AmbariMetaInfo.class);
helper = injector.getInstance(OrmTestHelper.class);
stackDAO = injector.getInstance(StackDAO.class);
resourceTypeDAO = injector.getInstance(ResourceTypeDAO.class);
clusterDAO = injector.getInstance(ClusterDAO.class);
hostDAO = injector.getInstance(HostDAO.class);
clusterVersionDAO = injector.getInstance(ClusterVersionDAO.class);
hostVersionDAO = injector.getInstance(HostVersionDAO.class);
hostComponentStateDAO = injector.getInstance(HostComponentStateDAO.class);
repositoryVersionDAO = injector.getInstance(RepositoryVersionDAO.class);
gson = injector.getInstance(Gson.class);
injector.getInstance(UnitOfWork.class).begin();
}
@After
public void teardown() {
injector.getInstance(UnitOfWork.class).end();
injector.getInstance(PersistService.class).stop();
}
private void createDefaultCluster() throws Exception {
// TODO, use common function
StackId stackId = new StackId("HDP", "0.1");
StackEntity stackEntity = stackDAO.find(stackId.getStackName(), stackId.getStackVersion());
org.junit.Assert.assertNotNull(stackEntity);
String clusterName = "c1";
ResourceTypeEntity resourceTypeEntity = resourceTypeDAO.findById(ResourceTypeEntity.CLUSTER_RESOURCE_TYPE);
if (resourceTypeEntity == null) {
resourceTypeEntity = new ResourceTypeEntity();
resourceTypeEntity.setId(ResourceTypeEntity.CLUSTER_RESOURCE_TYPE);
resourceTypeEntity.setName(ResourceTypeEntity.CLUSTER_RESOURCE_TYPE_NAME);
resourceTypeEntity = resourceTypeDAO.merge(resourceTypeEntity);
}
ResourceEntity resourceEntity = new ResourceEntity();
resourceEntity.setResourceType(resourceTypeEntity);
ClusterEntity clusterEntity = new ClusterEntity();
clusterEntity.setClusterName(clusterName);
clusterEntity.setResource(resourceEntity);
clusterEntity.setDesiredStack(stackEntity);
clusterDAO.create(clusterEntity);
Map<String, String> hostAttributes = new HashMap<String, String>();
hostAttributes.put("os_family", "redhat");
hostAttributes.put("os_release_version", "5.9");
List<HostEntity> hostEntities = new ArrayList<HostEntity>();
Set<String> hostNames = new HashSet<String>() {{ add("h1"); add("h2"); }};
for (String hostName : hostNames) {
HostEntity hostEntity = new HostEntity();
hostEntity.setHostName(hostName);
hostEntity.setIpv4("ipv4");
hostEntity.setIpv6("ipv6");
hostEntity.setHostAttributes(gson.toJson(hostAttributes));
hostEntity.setClusterEntities(Arrays.asList(clusterEntity));
hostEntities.add(hostEntity);
hostDAO.create(hostEntity);
}
clusterEntity.setHostEntities(hostEntities);
clusterDAO.merge(clusterEntity);
c1 = clusters.getCluster(clusterName);
helper.getOrCreateRepositoryVersion(stackId, stackId.getStackVersion());
c1.createClusterVersion(stackId, stackId.getStackVersion(), "admin",
RepositoryVersionState.UPGRADING);
c1.transitionClusterVersion(stackId, stackId.getStackVersion(),
RepositoryVersionState.CURRENT);
ClusterVersionDAOMock.failOnCurrentVersionState = false;
}
public ClusterEntity createDummyData() {
StackEntity stackEntity = new StackEntity();
stackEntity.setStackName("HDP");
stackEntity.setStackVersion("0.1");
ClusterEntity clusterEntity = new ClusterEntity();
clusterEntity.setClusterId(1L);
clusterEntity.setClusterName("test_cluster1");
clusterEntity.setClusterInfo("test_cluster_info1");
clusterEntity.setDesiredStack(stackEntity);
HostEntity host1 = new HostEntity();
HostEntity host2 = new HostEntity();
HostEntity host3 = new HostEntity();
host1.setHostName("test_host1");
host2.setHostName("test_host2");
host3.setHostName("test_host3");
host1.setIpv4("192.168.0.1");
host2.setIpv4("192.168.0.2");
host3.setIpv4("192.168.0.3");
List<HostEntity> hostEntities = new ArrayList<HostEntity>();
hostEntities.add(host1);
hostEntities.add(host2);
clusterEntity.setHostEntities(hostEntities);
clusterEntity.setClusterConfigEntities(Collections.EMPTY_LIST);
//both sides of relation should be set when modifying in runtime
host1.setClusterEntities(Arrays.asList(clusterEntity));
host2.setClusterEntities(Arrays.asList(clusterEntity));
HostStateEntity hostStateEntity1 = new HostStateEntity();
hostStateEntity1.setCurrentState(HostState.HEARTBEAT_LOST);
hostStateEntity1.setHostEntity(host1);
HostStateEntity hostStateEntity2 = new HostStateEntity();
hostStateEntity2.setCurrentState(HostState.HEALTHY);
hostStateEntity2.setHostEntity(host2);
host1.setHostStateEntity(hostStateEntity1);
host2.setHostStateEntity(hostStateEntity2);
ClusterServiceEntity clusterServiceEntity = new ClusterServiceEntity();
clusterServiceEntity.setServiceName("HDFS");
clusterServiceEntity.setClusterEntity(clusterEntity);
clusterServiceEntity.setServiceComponentDesiredStateEntities(
Collections.EMPTY_LIST);
ServiceDesiredStateEntity stateEntity = mock(ServiceDesiredStateEntity.class);
when(stateEntity.getDesiredStack()).thenReturn(stackEntity);
clusterServiceEntity.setServiceDesiredStateEntity(stateEntity);
List<ClusterServiceEntity> clusterServiceEntities = new ArrayList<ClusterServiceEntity>();
clusterServiceEntities.add(clusterServiceEntity);
clusterEntity.setClusterServiceEntities(clusterServiceEntities);
return clusterEntity;
}
private void checkStackVersionState(StackId stackId, String version, RepositoryVersionState state) {
Collection<ClusterVersionEntity> allClusterVersions = c1.getAllClusterVersions();
for (ClusterVersionEntity entity : allClusterVersions) {
StackId repoVersionStackId = new StackId(entity.getRepositoryVersion().getStack());
if (repoVersionStackId.equals(stackId)
&& repoVersionStackId.getStackVersion().equals(version)) {
assertEquals(state, entity.getState());
}
}
}
private void assertStateException(StackId stackId, String version,
RepositoryVersionState transitionState,
RepositoryVersionState stateAfter) {
try {
c1.transitionClusterVersion(stackId, version, transitionState);
Assert.fail();
} catch (AmbariException e) {}
checkStackVersionState(stackId, version, stateAfter);
assertNotNull(c1.getCurrentClusterVersion());
}
/**
* For Rolling Upgrades, create a cluster with the following components
* HDFS: NameNode, DataNode, HDFS Client
* ZK: Zookeeper Server, Zookeeper Monitor
* Ganglia: Ganglia Server, Ganglia Monitor
*
* Further, 3 hosts will be added.
* Finally, verify that only the Ganglia components do not need to advertise a version.
* @param clusterName Cluster Name
* @param stackId Stack to set for the cluster
* @param hostAttributes Host attributes to use for 3 hosts (h-1, h-2, h-3)
* @throws Exception
* @return Cluster that was created
*/
private Cluster createClusterForRU(String clusterName, StackId stackId, Map<String, String> hostAttributes) throws Exception {
clusters.addCluster(clusterName, stackId);
Cluster cluster = clusters.getCluster(clusterName);
Assert.assertEquals(clusterName, cluster.getClusterName());
Assert.assertEquals(1, cluster.getClusterId());
// Add Hosts
List<String> hostNames = new ArrayList<String>() {{ add("h-1"); add("h-2"); add("h-3"); }};
for(String hostName : hostNames) {
addHost(hostName, hostAttributes);
}
// Add stack and map Hosts to cluster
cluster.setDesiredStackVersion(stackId);
cluster.setCurrentStackVersion(stackId);
for(String hostName : hostNames) {
clusters.mapHostToCluster(hostName, clusterName);
}
// Transition all hosts to HEALTHY state
for (Host host : cluster.getHosts()) {
host.setState(HostState.HEALTHY);
}
// Add Services
Service s1 = serviceFactory.createNew(cluster, "HDFS");
Service s2 = serviceFactory.createNew(cluster, "ZOOKEEPER");
Service s3 = serviceFactory.createNew(cluster, "GANGLIA");
cluster.addService(s1);
cluster.addService(s2);
cluster.addService(s3);
s1.persist();
s2.persist();
s3.persist();
// Add HDFS components
ServiceComponent sc1CompA = serviceComponentFactory.createNew(s1, "NAMENODE");
ServiceComponent sc1CompB = serviceComponentFactory.createNew(s1, "DATANODE");
ServiceComponent sc1CompC = serviceComponentFactory.createNew(s1, "HDFS_CLIENT");
s1.addServiceComponent(sc1CompA);
s1.addServiceComponent(sc1CompB);
s1.addServiceComponent(sc1CompC);
sc1CompA.persist();
sc1CompB.persist();
sc1CompC.persist();
// Add ZK
ServiceComponent sc2CompA = serviceComponentFactory.createNew(s2, "ZOOKEEPER_SERVER");
ServiceComponent sc2CompB = serviceComponentFactory.createNew(s2, "ZOOKEEPER_CLIENT");
s2.addServiceComponent(sc2CompA);
s2.addServiceComponent(sc2CompB);
sc2CompA.persist();
sc2CompB.persist();
// Add Ganglia
ServiceComponent sc3CompA = serviceComponentFactory.createNew(s3, "GANGLIA_SERVER");
ServiceComponent sc3CompB = serviceComponentFactory.createNew(s3, "GANGLIA_MONITOR");
s3.addServiceComponent(sc3CompA);
s3.addServiceComponent(sc3CompB);
sc3CompA.persist();
sc3CompB.persist();
// Host 1 will have all components
ServiceComponentHost schHost1Serv1CompA = serviceComponentHostFactory.createNew(sc1CompA, "h-1");
ServiceComponentHost schHost1Serv1CompB = serviceComponentHostFactory.createNew(sc1CompB, "h-1");
ServiceComponentHost schHost1Serv1CompC = serviceComponentHostFactory.createNew(sc1CompC, "h-1");
ServiceComponentHost schHost1Serv2CompA = serviceComponentHostFactory.createNew(sc2CompA, "h-1");
ServiceComponentHost schHost1Serv2CompB = serviceComponentHostFactory.createNew(sc2CompB, "h-1");
ServiceComponentHost schHost1Serv3CompA = serviceComponentHostFactory.createNew(sc3CompA, "h-1");
ServiceComponentHost schHost1Serv3CompB = serviceComponentHostFactory.createNew(sc3CompB, "h-1");
sc1CompA.addServiceComponentHost(schHost1Serv1CompA);
sc1CompB.addServiceComponentHost(schHost1Serv1CompB);
sc1CompC.addServiceComponentHost(schHost1Serv1CompC);
sc2CompA.addServiceComponentHost(schHost1Serv2CompA);
sc2CompB.addServiceComponentHost(schHost1Serv2CompB);
sc3CompA.addServiceComponentHost(schHost1Serv3CompA);
sc3CompB.addServiceComponentHost(schHost1Serv3CompB);
schHost1Serv1CompA.persist();
schHost1Serv1CompB.persist();
schHost1Serv1CompC.persist();
schHost1Serv2CompA.persist();
schHost1Serv2CompB.persist();
schHost1Serv3CompA.persist();
schHost1Serv3CompB.persist();
// Host 2 will have ZK_CLIENT and GANGLIA_MONITOR
ServiceComponentHost schHost2Serv2CompB = serviceComponentHostFactory.createNew(sc2CompB, "h-2");
ServiceComponentHost schHost2Serv3CompB = serviceComponentHostFactory.createNew(sc3CompB, "h-2");
sc2CompB.addServiceComponentHost(schHost2Serv2CompB);
sc3CompB.addServiceComponentHost(schHost2Serv3CompB);
schHost2Serv2CompB.persist();
schHost2Serv3CompB.persist();
// Host 3 will have GANGLIA_MONITOR
ServiceComponentHost schHost3Serv3CompB = serviceComponentHostFactory.createNew(sc3CompB, "h-3");
sc3CompB.addServiceComponentHost(schHost3Serv3CompB);
schHost3Serv3CompB.persist();
// Verify count of components
List<ServiceComponentHost> scHost1 = cluster.getServiceComponentHosts("h-1");
Assert.assertEquals(7, scHost1.size());
List<ServiceComponentHost> scHost2 = cluster.getServiceComponentHosts("h-2");
Assert.assertEquals(2, scHost2.size());
List<ServiceComponentHost> scHost3 = cluster.getServiceComponentHosts("h-3");
Assert.assertEquals(1, scHost3.size());
//<editor-fold desc="Validate Version Advertised">
/*
For some reason this still uses the metainfo.xml files for these services
from HDP-2.0.5 stack instead of the provided Stack Id
*/
HashMap<String, Set<String>> componentsThatAdvertiseVersion = new HashMap<String, Set<String>>();
HashMap<String, Set<String>> componentsThatDontAdvertiseVersion = new HashMap<String, Set<String>>();
Set<String> hdfsComponents = new HashSet<String>() {{ add("NAMENODE"); add("DATANODE"); add("HDFS_CLIENT"); }};
Set<String> zkComponents = new HashSet<String>() {{ add("ZOOKEEPER_SERVER"); add("ZOOKEEPER_CLIENT"); }};
Set<String> gangliaComponents = new HashSet<String>() {{ add("GANGLIA_SERVER"); add("GANGLIA_MONITOR"); }};
componentsThatAdvertiseVersion.put("HDFS", hdfsComponents);
componentsThatAdvertiseVersion.put("ZOOKEEPER", zkComponents);
componentsThatDontAdvertiseVersion.put("GANGLIA", gangliaComponents);
for(String service : componentsThatAdvertiseVersion.keySet()) {
Set<String> components = componentsThatAdvertiseVersion.get(service);
for(String componentName : components) {
ComponentInfo component = metaInfo.getComponent(stackId.getStackName(), stackId.getStackVersion(), service, componentName);
Assert.assertTrue(component.isVersionAdvertised());
}
}
for(String service : componentsThatDontAdvertiseVersion.keySet()) {
Set<String> components = componentsThatDontAdvertiseVersion.get(service);
for(String componentName : components) {
ComponentInfo component = metaInfo.getComponent(stackId.getStackName(), stackId.getStackVersion(), service, componentName);
Assert.assertFalse(component.isVersionAdvertised());
}
}
//</editor-fold>
return cluster;
}
/**
* Add a host to the system with the provided attributes.
* @param hostName Host Name
* @param hostAttributes Host Attributes
* @throws Exception
*/
private void addHost(String hostName, Map<String, String> hostAttributes) throws Exception {
clusters.addHost(hostName);
Host host = clusters.getHost(hostName);
host.setIPv4("ipv4");
host.setIPv6("ipv6");
host.setHostAttributes(hostAttributes);
host.persist();
}
/**
* For the provided collection of HostComponentStates, set the version to {@paramref version} if the Component
* can advertise a version. Then, simulate the {@link org.apache.ambari.server.events.listeners.upgrade.StackVersionListener}
* by calling methods to transition the HostVersion, and recalculate the ClusterVersion.
* @param stackId Stack ID to retrieve the ComponentInfo
* @param version Version to set
* @param cluster Cluster to retrieve services from
* @param hostComponentStates Collection to set the version for
* @throws Exception
*/
private void simulateStackVersionListener(StackId stackId, String version, Cluster cluster, List<HostComponentStateEntity> hostComponentStates) throws Exception {
for(int i = 0; i < hostComponentStates.size(); i++) {
HostComponentStateEntity hce = hostComponentStates.get(i);
ComponentInfo compInfo = metaInfo.getComponent(
stackId.getStackName(), stackId.getStackVersion(),
hce.getServiceName(),
hce.getComponentName());
if (compInfo.isVersionAdvertised()) {
hce.setVersion(version);
hostComponentStateDAO.merge(hce);
}
RepositoryVersionEntity rv = helper.getOrCreateRepositoryVersion(stackId, version);
// Simulate the StackVersionListener during the installation
Service svc = cluster.getService(hce.getServiceName());
ServiceComponent svcComp = svc.getServiceComponent(hce.getComponentName());
ServiceComponentHost scHost = svcComp.getServiceComponentHost(hce.getHostName());
scHost.recalculateHostVersionState();
cluster.recalculateClusterVersionState(rv);
}
}
@Test
public void testAddHost() throws Exception {
createDefaultCluster();
clusters.addHost("h3");
try {
clusters.addHost("h3");
fail("Duplicate add should fail");
}
catch (AmbariException e) {
// Expected
}
}
@Test
public void testGetHostState() throws Exception {
createDefaultCluster();
Assert.assertEquals(HostState.INIT, clusters.getHost("h1").getState());
}
@Test
public void testSetHostState() throws Exception {
createDefaultCluster();
clusters.getHost("h1").setState(HostState.HEARTBEAT_LOST);
Assert.assertEquals(HostState.HEARTBEAT_LOST,
clusters.getHost("h1").getState());
}
@Test
public void testHostEvent() throws Exception,
InvalidStateTransitionException {
createDefaultCluster();
HostInfo hostInfo = new HostInfo();
hostInfo.setHostName("h1");
hostInfo.setInterfaces("fip_4");
hostInfo.setArchitecture("os_arch");
hostInfo.setOS("os_type");
hostInfo.setMemoryTotal(10);
hostInfo.setMemorySize(100);
hostInfo.setProcessorCount(10);
List<DiskInfo> mounts = new ArrayList<DiskInfo>();
mounts.add(new DiskInfo("/dev/sda", "/mnt/disk1",
"5000000", "4000000", "10%", "size", "fstype"));
hostInfo.setMounts(mounts);
AgentEnv agentEnv = new AgentEnv();
Directory dir1 = new Directory();
dir1.setName("/etc/hadoop");
dir1.setType("not_exist");
Directory dir2 = new Directory();
dir2.setName("/var/log/hadoop");
dir2.setType("not_exist");
agentEnv.setStackFoldersAndFiles(new Directory[] { dir1, dir2 });
AgentVersion agentVersion = new AgentVersion("0.0.x");
long currentTime = 1001;
clusters.getHost("h1").handleEvent(new HostRegistrationRequestEvent(
"h1", agentVersion, currentTime, hostInfo, agentEnv));
Assert.assertEquals(HostState.WAITING_FOR_HOST_STATUS_UPDATES,
clusters.getHost("h1").getState());
clusters.getHost("h1").setState(HostState.HEARTBEAT_LOST);
try {
clusters.getHost("h1").handleEvent(
new HostHealthyHeartbeatEvent("h1", currentTime, null, null));
fail("Exception should be thrown on invalid event");
}
catch (InvalidStateTransitionException e) {
// Expected
}
}
@Test
public void testBasicClusterSetup() throws Exception {
StackId stackVersion = new StackId("HDP-1.2.0");
createDefaultCluster();
String clusterName = "c2";
try {
clusters.getCluster(clusterName);
fail("Exception expected for invalid cluster");
} catch (Exception e) {
// Expected
}
clusters.addCluster(clusterName, stackVersion);
Cluster c2 = clusters.getCluster(clusterName);
Assert.assertNotNull(c2);
Assert.assertEquals(clusterName, c2.getClusterName());
c2.setClusterName("foo2");
Assert.assertEquals("foo2", c2.getClusterName());
Assert.assertNotNull(c2.getDesiredStackVersion());
Assert.assertEquals("HDP-1.2.0", c2.getDesiredStackVersion().getStackId());
}
@Test
public void testAddAndGetServices() throws Exception {
createDefaultCluster();
// TODO write unit tests for
// public void addService(Service service) throws AmbariException;
// public Service getService(String serviceName) throws AmbariException;
// public Map<String, Service> getServices();
Service s1 = serviceFactory.createNew(c1, "HDFS");
Service s2 = serviceFactory.createNew(c1, "MAPREDUCE");
c1.addService(s1);
c1.addService(s2);
s1.persist();
s2.persist();
Service s3 = serviceFactory.createNew(c1, "MAPREDUCE");
try {
c1.addService(s3);
fail("Expected error on adding dup service");
} catch (Exception e) {
// Expected
}
Service s = c1.getService("HDFS");
Assert.assertNotNull(s);
Assert.assertEquals("HDFS", s.getName());
Assert.assertEquals(c1.getClusterId(), s.getClusterId());
try {
c1.getService("HBASE");
fail("Expected error for unknown service");
} catch (Exception e) {
// Expected
}
Map<String, Service> services = c1.getServices();
Assert.assertEquals(2, services.size());
Assert.assertTrue(services.containsKey("HDFS"));
Assert.assertTrue(services.containsKey("MAPREDUCE"));
}
@Test
public void testGetServiceComponentHosts() throws Exception {
createDefaultCluster();
// TODO write unit tests
// public List<ServiceComponentHost> getServiceComponentHosts(String hostname);
Service s = serviceFactory.createNew(c1, "HDFS");
c1.addService(s);
s.persist();
ServiceComponent sc = serviceComponentFactory.createNew(s, "NAMENODE");
s.addServiceComponent(sc);
sc.persist();
ServiceComponentHost sch =
serviceComponentHostFactory.createNew(sc, "h1");
sc.addServiceComponentHost(sch);
sch.persist();
List<ServiceComponentHost> scHosts = c1.getServiceComponentHosts("h1");
Assert.assertEquals(1, scHosts.size());
Iterator<ServiceComponentHost> iterator = scHosts.iterator();
//Try to iterate on sch and modify it in loop
try {
while (iterator.hasNext()) {
iterator.next();
Service s1 = serviceFactory.createNew(c1, "PIG");
c1.addService(s1);
s1.persist();
ServiceComponent sc1 = serviceComponentFactory.createNew(s1, "PIG");
s1.addServiceComponent(sc1);
sc1.persist();
ServiceComponentHost sch1 = serviceComponentHostFactory.createNew(sc1, "h1");
sc1.addServiceComponentHost(sch1);
sch1.persist();
}
} catch (ConcurrentModificationException e ) {
Assert.assertTrue("Failed to work concurrently with sch", false);
}
scHosts = c1.getServiceComponentHosts("h1");
Assert.assertEquals(2, scHosts.size());
}
@Test
public void testGetServiceComponentHosts_ForService() throws Exception {
createDefaultCluster();
Service s = serviceFactory.createNew(c1, "HDFS");
c1.addService(s);
s.persist();
ServiceComponent scNN = serviceComponentFactory.createNew(s, "NAMENODE");
s.addServiceComponent(scNN);
scNN.persist();
ServiceComponentHost schNNH1 = serviceComponentHostFactory.createNew(scNN, "h1");
scNN.addServiceComponentHost(schNNH1);
schNNH1.persist();
ServiceComponent scDN = serviceComponentFactory.createNew(s, "DATANODE");
s.addServiceComponent(scDN);
scDN.persist();
ServiceComponentHost scDNH1 = serviceComponentHostFactory.createNew(scDN, "h1");
scDN.addServiceComponentHost(scDNH1);
scDNH1.persist();
ServiceComponentHost scDNH2 = serviceComponentHostFactory.createNew(scDN, "h2");
scDN.addServiceComponentHost(scDNH2);
scDNH2.persist();
List<ServiceComponentHost> scHosts;
scHosts = c1.getServiceComponentHosts("HDFS", null);
Assert.assertEquals(3, scHosts.size());
scHosts = c1.getServiceComponentHosts("UNKNOWN SERVICE", null);
Assert.assertEquals(0, scHosts.size());
}
@Test
public void testGetServiceComponentHosts_ForServiceComponent() throws Exception {
createDefaultCluster();
Service s = serviceFactory.createNew(c1, "HDFS");
c1.addService(s);
s.persist();
ServiceComponent scNN = serviceComponentFactory.createNew(s, "NAMENODE");
s.addServiceComponent(scNN);
scNN.persist();
ServiceComponentHost schNNH1 = serviceComponentHostFactory.createNew(scNN, "h1");
scNN.addServiceComponentHost(schNNH1);
schNNH1.persist();
ServiceComponent scDN = serviceComponentFactory.createNew(s, "DATANODE");
s.addServiceComponent(scDN);
scDN.persist();
ServiceComponentHost scDNH1 = serviceComponentHostFactory.createNew(scDN, "h1");
scDN.addServiceComponentHost(scDNH1);
scDNH1.persist();
ServiceComponentHost scDNH2 = serviceComponentHostFactory.createNew(scDN, "h2");
scDN.addServiceComponentHost(scDNH2);
scDNH2.persist();
List<ServiceComponentHost> scHosts;
scHosts = c1.getServiceComponentHosts("HDFS", "DATANODE");
Assert.assertEquals(2, scHosts.size());
scHosts = c1.getServiceComponentHosts("HDFS", "UNKNOWN COMPONENT");
Assert.assertEquals(0, scHosts.size());
scHosts = c1.getServiceComponentHosts("UNKNOWN SERVICE", "DATANODE");
Assert.assertEquals(0, scHosts.size());
scHosts = c1.getServiceComponentHosts("UNKNOWN SERVICE", "UNKNOWN COMPONENT");
Assert.assertEquals(0, scHosts.size());
}
@Test
public void testGetServiceComponentHostMap() throws Exception {
createDefaultCluster();
Service s = serviceFactory.createNew(c1, "HDFS");
c1.addService(s);
s.persist();
ServiceComponent scNN = serviceComponentFactory.createNew(s, "NAMENODE");
s.addServiceComponent(scNN);
scNN.persist();
ServiceComponentHost schNNH1 = serviceComponentHostFactory.createNew(scNN, "h1");
scNN.addServiceComponentHost(schNNH1);
schNNH1.persist();
ServiceComponent scDN = serviceComponentFactory.createNew(s, "DATANODE");
s.addServiceComponent(scDN);
scDN.persist();
ServiceComponentHost scDNH1 = serviceComponentHostFactory.createNew(scDN, "h1");
scDN.addServiceComponentHost(scDNH1);
scDNH1.persist();
ServiceComponentHost scDNH2 = serviceComponentHostFactory.createNew(scDN, "h2");
scDN.addServiceComponentHost(scDNH2);
scDNH2.persist();
Map<String, Set<String>> componentHostMap;
componentHostMap = c1.getServiceComponentHostMap(null, null);
Assert.assertEquals(2, componentHostMap.size());
Assert.assertEquals(1, componentHostMap.get("NAMENODE").size());
Assert.assertTrue(componentHostMap.get("NAMENODE").contains("h1"));
Assert.assertEquals(2, componentHostMap.get("DATANODE").size());
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h1"));
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h2"));
}
@Test
public void testGetServiceComponentHostMap_ForService() throws Exception {
createDefaultCluster();
Service sfHDFS = serviceFactory.createNew(c1, "HDFS");
c1.addService(sfHDFS);
sfHDFS.persist();
Service sfMR = serviceFactory.createNew(c1, "MAPREDUCE");
c1.addService(sfMR);
sfMR.persist();
ServiceComponent scNN = serviceComponentFactory.createNew(sfHDFS, "NAMENODE");
sfHDFS.addServiceComponent(scNN);
scNN.persist();
ServiceComponentHost schNNH1 = serviceComponentHostFactory.createNew(scNN, "h1");
scNN.addServiceComponentHost(schNNH1);
schNNH1.persist();
ServiceComponent scDN = serviceComponentFactory.createNew(sfHDFS, "DATANODE");
sfHDFS.addServiceComponent(scDN);
scDN.persist();
ServiceComponentHost scDNH1 = serviceComponentHostFactory.createNew(scDN, "h1");
scDN.addServiceComponentHost(scDNH1);
scDNH1.persist();
ServiceComponentHost scDNH2 = serviceComponentHostFactory.createNew(scDN, "h2");
scDN.addServiceComponentHost(scDNH2);
scDNH2.persist();
ServiceComponent scJT = serviceComponentFactory.createNew(sfMR, "JOBTRACKER");
sfMR.addServiceComponent(scJT);
scJT.persist();
ServiceComponentHost schJTH1 = serviceComponentHostFactory.createNew(scJT, "h1");
scJT.addServiceComponentHost(schJTH1);
schJTH1.persist();
Map<String, Set<String>> componentHostMap;
componentHostMap = c1.getServiceComponentHostMap(null, Collections.singleton("HDFS"));
Assert.assertEquals(2, componentHostMap.size());
Assert.assertEquals(1, componentHostMap.get("NAMENODE").size());
Assert.assertTrue(componentHostMap.get("NAMENODE").contains("h1"));
Assert.assertEquals(2, componentHostMap.get("DATANODE").size());
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h1"));
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h2"));
componentHostMap = c1.getServiceComponentHostMap(null, Collections.singleton("MAPREDUCE"));
Assert.assertEquals(1, componentHostMap.size());
Assert.assertEquals(1, componentHostMap.get("JOBTRACKER").size());
Assert.assertTrue(componentHostMap.get("JOBTRACKER").contains("h1"));
componentHostMap = c1.getServiceComponentHostMap(null, new HashSet<String>(Arrays.asList("HDFS", "MAPREDUCE")));
Assert.assertEquals(3, componentHostMap.size());
Assert.assertEquals(1, componentHostMap.get("NAMENODE").size());
Assert.assertTrue(componentHostMap.get("NAMENODE").contains("h1"));
Assert.assertEquals(2, componentHostMap.get("DATANODE").size());
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h1"));
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h2"));
Assert.assertEquals(1, componentHostMap.get("JOBTRACKER").size());
Assert.assertTrue(componentHostMap.get("JOBTRACKER").contains("h1"));
componentHostMap = c1.getServiceComponentHostMap(null, Collections.singleton("UNKNOWN"));
Assert.assertEquals(0, componentHostMap.size());
}
@Test
public void testGetServiceComponentHostMap_ForHost() throws Exception {
createDefaultCluster();
Service sfHDFS = serviceFactory.createNew(c1, "HDFS");
c1.addService(sfHDFS);
sfHDFS.persist();
Service sfMR = serviceFactory.createNew(c1, "MAPREDUCE");
c1.addService(sfMR);
sfMR.persist();
ServiceComponent scNN = serviceComponentFactory.createNew(sfHDFS, "NAMENODE");
sfHDFS.addServiceComponent(scNN);
scNN.persist();
ServiceComponentHost schNNH1 = serviceComponentHostFactory.createNew(scNN, "h1");
scNN.addServiceComponentHost(schNNH1);
schNNH1.persist();
ServiceComponent scDN = serviceComponentFactory.createNew(sfHDFS, "DATANODE");
sfHDFS.addServiceComponent(scDN);
scDN.persist();
ServiceComponentHost scDNH1 = serviceComponentHostFactory.createNew(scDN, "h1");
scDN.addServiceComponentHost(scDNH1);
scDNH1.persist();
ServiceComponentHost scDNH2 = serviceComponentHostFactory.createNew(scDN, "h2");
scDN.addServiceComponentHost(scDNH2);
scDNH2.persist();
ServiceComponent scJT = serviceComponentFactory.createNew(sfMR, "JOBTRACKER");
sfMR.addServiceComponent(scJT);
scJT.persist();
ServiceComponentHost schJTH1 = serviceComponentHostFactory.createNew(scJT, "h1");
scJT.addServiceComponentHost(schJTH1);
schJTH1.persist();
Map<String, Set<String>> componentHostMap;
componentHostMap = c1.getServiceComponentHostMap(Collections.singleton("h1"), null);
Assert.assertEquals(3, componentHostMap.size());
Assert.assertEquals(1, componentHostMap.get("NAMENODE").size());
Assert.assertTrue(componentHostMap.get("NAMENODE").contains("h1"));
Assert.assertEquals(1, componentHostMap.get("DATANODE").size());
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h1"));
Assert.assertEquals(1, componentHostMap.get("JOBTRACKER").size());
Assert.assertTrue(componentHostMap.get("JOBTRACKER").contains("h1"));
componentHostMap = c1.getServiceComponentHostMap(Collections.singleton("h2"), null);
Assert.assertEquals(1, componentHostMap.size());
Assert.assertEquals(1, componentHostMap.get("DATANODE").size());
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h2"));
componentHostMap = c1.getServiceComponentHostMap(new HashSet<String>(Arrays.asList("h1", "h2", "h3")), null);
Assert.assertEquals(3, componentHostMap.size());
Assert.assertEquals(1, componentHostMap.get("NAMENODE").size());
Assert.assertTrue(componentHostMap.get("NAMENODE").contains("h1"));
Assert.assertEquals(2, componentHostMap.get("DATANODE").size());
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h1"));
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h2"));
Assert.assertEquals(1, componentHostMap.get("JOBTRACKER").size());
Assert.assertTrue(componentHostMap.get("JOBTRACKER").contains("h1"));
componentHostMap = c1.getServiceComponentHostMap(Collections.singleton("unknown"), null);
Assert.assertEquals(0, componentHostMap.size());
}
@Test
public void testGetServiceComponentHostMap_ForHostAndService() throws Exception {
createDefaultCluster();
Service sfHDFS = serviceFactory.createNew(c1, "HDFS");
c1.addService(sfHDFS);
sfHDFS.persist();
Service sfMR = serviceFactory.createNew(c1, "MAPREDUCE");
c1.addService(sfMR);
sfMR.persist();
ServiceComponent scNN = serviceComponentFactory.createNew(sfHDFS, "NAMENODE");
sfHDFS.addServiceComponent(scNN);
scNN.persist();
ServiceComponentHost schNNH1 = serviceComponentHostFactory.createNew(scNN, "h1");
scNN.addServiceComponentHost(schNNH1);
schNNH1.persist();
ServiceComponent scDN = serviceComponentFactory.createNew(sfHDFS, "DATANODE");
sfHDFS.addServiceComponent(scDN);
scDN.persist();
ServiceComponentHost scDNH1 = serviceComponentHostFactory.createNew(scDN, "h1");
scDN.addServiceComponentHost(scDNH1);
scDNH1.persist();
ServiceComponentHost scDNH2 = serviceComponentHostFactory.createNew(scDN, "h2");
scDN.addServiceComponentHost(scDNH2);
scDNH2.persist();
ServiceComponent scJT = serviceComponentFactory.createNew(sfMR, "JOBTRACKER");
sfMR.addServiceComponent(scJT);
scJT.persist();
ServiceComponentHost schJTH1 = serviceComponentHostFactory.createNew(scJT, "h1");
scJT.addServiceComponentHost(schJTH1);
schJTH1.persist();
Map<String, Set<String>> componentHostMap;
componentHostMap = c1.getServiceComponentHostMap(Collections.singleton("h1"), Collections.singleton("HDFS"));
Assert.assertEquals(2, componentHostMap.size());
Assert.assertEquals(1, componentHostMap.get("DATANODE").size());
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h1"));
Assert.assertEquals(1, componentHostMap.get("NAMENODE").size());
Assert.assertTrue(componentHostMap.get("NAMENODE").contains("h1"));
componentHostMap = c1.getServiceComponentHostMap(Collections.singleton("h2"), Collections.singleton("HDFS"));
Assert.assertEquals(1, componentHostMap.size());
Assert.assertEquals(1, componentHostMap.get("DATANODE").size());
Assert.assertTrue(componentHostMap.get("DATANODE").contains("h2"));
componentHostMap = c1.getServiceComponentHostMap(Collections.singleton("h3"), Collections.singleton("HDFS"));
Assert.assertEquals(0, componentHostMap.size());
}
@Test
public void testGetAndSetConfigs() throws Exception {
createDefaultCluster();
Map<String, Map<String, String>> c1PropAttributes = new HashMap<String, Map<String,String>>();
c1PropAttributes.put("final", new HashMap<String, String>());
c1PropAttributes.get("final").put("a", "true");
Map<String, Map<String, String>> c2PropAttributes = new HashMap<String, Map<String,String>>();
c2PropAttributes.put("final", new HashMap<String, String>());
c2PropAttributes.get("final").put("x", "true");
Config config1 = configFactory.createNew(c1, "global",
new HashMap<String, String>() {{ put("a", "b"); }}, c1PropAttributes);
config1.setTag("version1");
Config config2 = configFactory.createNew(c1, "global",
new HashMap<String, String>() {{ put("x", "y"); }}, c2PropAttributes);
config2.setTag("version2");
Config config3 = configFactory.createNew(c1, "core-site",
new HashMap<String, String>() {{ put("x", "y"); }}, new HashMap<String, Map<String,String>>());
config3.setTag("version2");
c1.addConfig(config1);
c1.addConfig(config2);
c1.addConfig(config3);
c1.addDesiredConfig("_test", Collections.singleton(config1));
Config res = c1.getDesiredConfigByType("global");
Assert.assertNotNull("Expected non-null config", res);
Assert.assertEquals("true", res.getPropertiesAttributes().get("final").get("a"));
res = c1.getDesiredConfigByType("core-site");
Assert.assertNull("Expected null config", res);
c1.addDesiredConfig("_test", Collections.singleton(config2));
res = c1.getDesiredConfigByType("global");
Assert.assertEquals("Expected version tag to be 'version2'", "version2", res.getTag());
Assert.assertEquals("true", res.getPropertiesAttributes().get("final").get("x"));
}
@Test
public void testDesiredConfigs() throws Exception {
createDefaultCluster();
Config config1 = configFactory.createNew(c1, "global",
new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<String, Map<String,String>>());
config1.setTag("version1");
Config config2 = configFactory.createNew(c1, "global",
new HashMap<String, String>() {{ put("x", "y"); }}, new HashMap<String, Map<String,String>>());
config2.setTag("version2");
Config config3 = configFactory.createNew(c1, "core-site",
new HashMap<String, String>() {{ put("x", "y"); }}, new HashMap<String, Map<String,String>>());
config3.setTag("version2");
c1.addConfig(config1);
c1.addConfig(config2);
c1.addConfig(config3);
try {
c1.addDesiredConfig(null, Collections.singleton(config1));
fail("Cannot set a null user with config");
}
catch (Exception e) {
// test failure
}
c1.addDesiredConfig("_test1", Collections.singleton(config1));
c1.addDesiredConfig("_test3", Collections.singleton(config3));
Map<String, DesiredConfig> desiredConfigs = c1.getDesiredConfigs();
Assert.assertFalse("Expect desired config not contain 'mapred-site'", desiredConfigs.containsKey("mapred-site"));
Assert.assertTrue("Expect desired config contain " + config1.getType(), desiredConfigs.containsKey("global"));
Assert.assertTrue("Expect desired config contain " + config3.getType(), desiredConfigs.containsKey("core-site"));
Assert.assertEquals("Expect desired config for global should be " + config1.getTag(),
config1.getTag(), desiredConfigs.get(config1.getType()).getTag());
Assert.assertEquals("_test1", desiredConfigs.get(config1.getType()).getUser());
Assert.assertEquals("_test3", desiredConfigs.get(config3.getType()).getUser());
DesiredConfig dc = desiredConfigs.get(config1.getType());
Assert.assertTrue("Expect no host-level overrides",
(null == dc.getHostOverrides() || dc.getHostOverrides().size() == 0));
c1.addDesiredConfig("_test2", Collections.singleton(config2));
Assert.assertEquals("_test2", c1.getDesiredConfigs().get(config2.getType()).getUser());
c1.addDesiredConfig("_test1", Collections.singleton(config1));
// setup a host that also has a config override
Host host = clusters.getHost("h1");
host.addDesiredConfig(c1.getClusterId(), true, "_test2", config2);
desiredConfigs = c1.getDesiredConfigs();
dc = desiredConfigs.get(config1.getType());
Assert.assertNotNull("Expect host-level overrides", dc.getHostOverrides());
Assert.assertEquals("Expect one host-level override", 1, dc.getHostOverrides().size());
}
@Test
@Ignore
// Test clearly depends on a detached reference used to create
// in-memory objects. Based on the timeline this is a very old test with
// assertions that are not too meaningful.
public void testClusterRecovery() throws AmbariException {
ClusterEntity entity = createDummyData();
ClusterStateEntity clusterStateEntity = new ClusterStateEntity();
clusterStateEntity.setCurrentStack(entity.getDesiredStack());
entity.setClusterStateEntity(clusterStateEntity);
ClusterImpl cluster = new ClusterImpl(entity, injector);
Service service = cluster.getService("HDFS");
/* make sure the services are recovered */
Assert.assertEquals("HDFS", service.getName());
Map<String, Service> services = cluster.getServices();
Assert.assertNotNull(services.get("HDFS"));
}
@Test
public void testConvertToResponse() throws Exception {
createDefaultCluster();
ClusterResponse r = c1.convertToResponse();
Assert.assertEquals(c1.getClusterId(), r.getClusterId().longValue());
Assert.assertEquals(c1.getClusterName(), r.getClusterName());
Assert.assertEquals(Integer.valueOf(2), r.getTotalHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getAlertStatusHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getHealthyStatusHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getUnhealthyStatusHosts());
Assert.assertEquals(2, r.getClusterHealthReport().getUnknownStatusHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getStaleConfigsHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getMaintenanceStateHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getHealthyStateHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getHeartbeatLostStateHosts());
Assert.assertEquals(2, r.getClusterHealthReport().getInitStateHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getUnhealthyStateHosts());
clusters.addHost("h3");
Host host = clusters.getHost("h3");
host.setIPv4("ipv4");
host.setIPv6("ipv6");
Map<String, String> hostAttributes = new HashMap<String, String>();
hostAttributes.put("os_family", "redhat");
hostAttributes.put("os_release_version", "5.9");
host.setHostAttributes(hostAttributes);
host.setState(HostState.HEALTHY);
host.setHealthStatus(new HostHealthStatus(HostHealthStatus.HealthStatus.HEALTHY, ""));
host.setStatus(host.getHealthStatus().getHealthStatus().name());
host.persist();
c1.setDesiredStackVersion(new StackId("HDP-2.0.6"));
clusters.mapHostToCluster("h3", "c1");
r = c1.convertToResponse();
Assert.assertEquals(Integer.valueOf(3), r.getTotalHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getAlertStatusHosts());
Assert.assertEquals(1, r.getClusterHealthReport().getHealthyStatusHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getUnhealthyStatusHosts());
Assert.assertEquals(2, r.getClusterHealthReport().getUnknownStatusHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getStaleConfigsHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getMaintenanceStateHosts());
Assert.assertEquals(1, r.getClusterHealthReport().getHealthyStateHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getHeartbeatLostStateHosts());
Assert.assertEquals(2, r.getClusterHealthReport().getInitStateHosts());
Assert.assertEquals(0, r.getClusterHealthReport().getUnhealthyStateHosts());
// TODO write unit tests for debug dump
StringBuilder sb = new StringBuilder();
c1.debugDump(sb);
}
@Test
public void testDeleteService() throws Exception {
createDefaultCluster();
c1.addService("MAPREDUCE").persist();
Service hdfs = c1.addService("HDFS");
hdfs.persist();
ServiceComponent nameNode = hdfs.addServiceComponent("NAMENODE");
nameNode.persist();
assertEquals(2, c1.getServices().size());
assertEquals(2, injector.getProvider(EntityManager.class).get().
createQuery("SELECT service FROM ClusterServiceEntity service").getResultList().size());
c1.deleteService("HDFS");
assertEquals(1, c1.getServices().size());
assertEquals(1, injector.getProvider(EntityManager.class).get().
createQuery("SELECT service FROM ClusterServiceEntity service").getResultList().size());
}
@Test
public void testDeleteServiceWithConfigHistory() throws Exception {
createDefaultCluster();
c1.addService("HDFS").persist();
Config config1 = configFactory.createNew(c1, "hdfs-site",
new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<String, Map<String,String>>());
config1.setTag("version1");
Config config2 = configFactory.createNew(c1, "core-site",
new HashMap<String, String>() {{ put("x", "y"); }}, new HashMap<String, Map<String,String>>());
config2.setTag("version2");
config1.persist();
c1.addConfig(config1);
config2.persist();
c1.addConfig(config2);
Set<Config> configs = new HashSet<Config>();
configs.add(config1);
configs.add(config2);
c1.addDesiredConfig("admin", configs);
List<ServiceConfigVersionResponse> serviceConfigVersions = c1.getServiceConfigVersions();
Assert.assertNotNull(serviceConfigVersions);
// Single serviceConfigVersion for multiple configs
Assert.assertEquals(1, serviceConfigVersions.size());
Assert.assertEquals(Long.valueOf(1), serviceConfigVersions.get(0).getVersion());
Assert.assertEquals(2, c1.getDesiredConfigs().size());
Assert.assertEquals("version1", c1.getDesiredConfigByType("hdfs-site").getTag());
Assert.assertEquals("version2", c1.getDesiredConfigByType("core-site").getTag());
Map<String, Collection<ServiceConfigVersionResponse>> activeServiceConfigVersions =
c1.getActiveServiceConfigVersions();
Assert.assertEquals(1, activeServiceConfigVersions.size());
c1.deleteService("HDFS");
Assert.assertEquals(0, c1.getServices().size());
Assert.assertEquals(0, c1.getServiceConfigVersions().size());
EntityManager em = injector.getProvider(EntityManager.class).get();
// ServiceConfig
Assert.assertEquals(0,
em.createQuery("SELECT serviceConfig from ServiceConfigEntity serviceConfig").getResultList().size());
// ClusterConfig
Assert.assertEquals(2,
em.createQuery("SELECT config from ClusterConfigEntity config").getResultList().size());
// ClusterConfigMapping
List<ClusterConfigMappingEntity> configMappingEntities =
em.createQuery("SELECT configmapping from ClusterConfigMappingEntity configmapping",
ClusterConfigMappingEntity.class).getResultList();
Assert.assertEquals(2, configMappingEntities.size());
for (ClusterConfigMappingEntity configMappingEntity : configMappingEntities) {
if (StringUtils.equals(configMappingEntity.getType(), "core-site")) {
assertEquals("core-site is not part of HDFS in test stack, should remain mapped to cluster",
1, configMappingEntity.isSelected());
}
if (StringUtils.equals(configMappingEntity.getType(), "hdfs-site")) {
assertEquals("hdfs-site should be unmapped from cluster when HDFS service is removed",
0, configMappingEntity.isSelected());
}
}
// ServiceConfigMapping
Assert.assertEquals(0,
em.createNativeQuery("SELECT * from serviceconfigmapping").getResultList().size());
}
@Test
public void testGetHostsDesiredConfigs() throws Exception {
createDefaultCluster();
Host host1 = clusters.getHost("h1");
HostEntity hostEntity1 = hostDAO.findByName("h1");
Map<String, Map<String, String>> propAttributes = new HashMap<String, Map<String,String>>();
propAttributes.put("final", new HashMap<String, String>());
propAttributes.get("final").put("test", "true");
Config config = configFactory.createNew(c1, "hdfs-site", new HashMap<String, String>(){{
put("test", "test");
}}, propAttributes);
config.setTag("1");
host1.addDesiredConfig(c1.getClusterId(), true, "test", config);
Map<Long, Map<String, DesiredConfig>> configs = c1.getAllHostsDesiredConfigs();
assertTrue(configs.containsKey(hostEntity1.getHostId()));
assertEquals(1, configs.get(hostEntity1.getHostId()).size());
List<Long> hostIds = new ArrayList<Long>();
hostIds.add(hostEntity1.getHostId());
configs = c1.getHostsDesiredConfigs(hostIds);
assertTrue(configs.containsKey(hostEntity1.getHostId()));
assertEquals(1, configs.get(hostEntity1.getHostId()).size());
}
@Test
public void testProvisioningState() throws Exception {
createDefaultCluster();
c1.setProvisioningState(State.INIT);
Assert.assertEquals(State.INIT,
c1.getProvisioningState());
c1.setProvisioningState(State.INSTALLED);
Assert.assertEquals(State.INSTALLED,
c1.getProvisioningState());
}
@Test
public void testServiceConfigVersions() throws Exception {
createDefaultCluster();
Config config1 = configFactory.createNew(c1, "hdfs-site",
new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<String, Map<String,String>>());
config1.setTag("version1");
Config config2 = configFactory.createNew(c1, "hdfs-site",
new HashMap<String, String>() {{ put("x", "y"); }}, new HashMap<String, Map<String,String>>());
config2.setTag("version2");
c1.addConfig(config1);
c1.addConfig(config2);
c1.addDesiredConfig("admin", Collections.singleton(config1));
List<ServiceConfigVersionResponse> serviceConfigVersions =
c1.getServiceConfigVersions();
Assert.assertNotNull(serviceConfigVersions);
Assert.assertEquals(1, serviceConfigVersions.size());
Map<String, Collection<ServiceConfigVersionResponse>> activeServiceConfigVersions =
c1.getActiveServiceConfigVersions();
Assert.assertEquals(1, activeServiceConfigVersions.size());
ServiceConfigVersionResponse hdfsResponse =
activeServiceConfigVersions.get("HDFS").iterator().next();
Assert.assertEquals("HDFS", hdfsResponse.getServiceName());
Assert.assertEquals("c1", hdfsResponse.getClusterName());
Assert.assertEquals("admin", hdfsResponse.getUserName());
Assert.assertEquals("default", hdfsResponse.getGroupName());
Assert.assertEquals(Long.valueOf(-1), hdfsResponse.getGroupId());
Assert.assertEquals(Long.valueOf(1), hdfsResponse.getVersion());
c1.addDesiredConfig("admin", Collections.singleton(config2));
serviceConfigVersions = c1.getServiceConfigVersions();
Assert.assertNotNull(serviceConfigVersions);
// created new ServiceConfigVersion
Assert.assertEquals(2, serviceConfigVersions.size());
activeServiceConfigVersions = c1.getActiveServiceConfigVersions();
Assert.assertEquals(1, activeServiceConfigVersions.size());
hdfsResponse = activeServiceConfigVersions.get("HDFS").iterator().next();
Assert.assertEquals("HDFS", hdfsResponse.getServiceName());
Assert.assertEquals("c1", hdfsResponse.getClusterName());
Assert.assertEquals("admin", hdfsResponse.getUserName());
assertEquals(Long.valueOf(2), hdfsResponse.getVersion());
// Rollback , clonning version1 config, created new ServiceConfigVersion
c1.setServiceConfigVersion("HDFS", 1L, "admin", "test_note");
serviceConfigVersions = c1.getServiceConfigVersions();
Assert.assertNotNull(serviceConfigVersions);
// created new ServiceConfigVersion
Assert.assertEquals(3, serviceConfigVersions.size());
// active version still 1
activeServiceConfigVersions = c1.getActiveServiceConfigVersions();
Assert.assertEquals(1, activeServiceConfigVersions.size());
hdfsResponse = activeServiceConfigVersions.get("HDFS").iterator().next();
Assert.assertEquals("HDFS", hdfsResponse.getServiceName());
Assert.assertEquals("c1", hdfsResponse.getClusterName());
Assert.assertEquals("admin", hdfsResponse.getUserName());
assertEquals(Long.valueOf(3), hdfsResponse.getVersion());
}
@Test
public void testSingleServiceVersionForMultipleConfigs() throws Exception {
createDefaultCluster();
Config config1 = configFactory.createNew(c1, "hdfs-site",
new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<String, Map<String,String>>());
config1.setTag("version1");
Config config2 = configFactory.createNew(c1, "core-site",
new HashMap<String, String>() {{ put("x", "y"); }}, new HashMap<String, Map<String,String>>());
config2.setTag("version2");
c1.addConfig(config1);
c1.addConfig(config2);
Set<Config> configs = new HashSet<Config>();
configs.add(config1);
configs.add(config2);
c1.addDesiredConfig("admin", configs);
List<ServiceConfigVersionResponse> serviceConfigVersions =
c1.getServiceConfigVersions();
Assert.assertNotNull(serviceConfigVersions);
// Single serviceConfigVersion for multiple configs
Assert.assertEquals(1, serviceConfigVersions.size());
Assert.assertEquals(Long.valueOf(1), serviceConfigVersions.get(0).getVersion());
Assert.assertEquals(2, c1.getDesiredConfigs().size());
Assert.assertEquals("version1", c1.getDesiredConfigByType("hdfs-site").getTag());
Assert.assertEquals("version2", c1.getDesiredConfigByType("core-site").getTag());
Map<String, Collection<ServiceConfigVersionResponse>> activeServiceConfigVersions =
c1.getActiveServiceConfigVersions();
Assert.assertEquals(1, activeServiceConfigVersions.size());
}
@Test
public void testServiceConfigVersionsForGroups() throws Exception {
createDefaultCluster();
Config config1 = configFactory.createNew(c1, "hdfs-site",
new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<String, Map<String,String>>());
config1.setTag("version1");
c1.addConfig(config1);
ServiceConfigVersionResponse scvResponse =
c1.addDesiredConfig("admin", Collections.singleton(config1));
assertEquals("SCV 1 should be created", Long.valueOf(1), scvResponse.getVersion());
Map<String, Collection<ServiceConfigVersionResponse>> activeServiceConfigVersions =
c1.getActiveServiceConfigVersions();
Assert.assertEquals("Only one scv should be active", 1, activeServiceConfigVersions.get("HDFS").size());
//create config group
Config config2 = configFactory.createNew(c1, "hdfs-site",
new HashMap<String, String>() {{ put("a", "c"); }}, new HashMap<String, Map<String,String>>());
config2.setTag("version2");
ConfigGroup configGroup =
configGroupFactory.createNew(c1, "test group", "HDFS", "descr", Collections.singletonMap("hdfs-site", config2),
Collections.<Long, Host>emptyMap());
configGroup.persist();
c1.addConfigGroup(configGroup);
scvResponse = c1.createServiceConfigVersion("HDFS", "admin", "test note", configGroup);
assertEquals("SCV 2 should be created", Long.valueOf(2), scvResponse.getVersion());
//two scv active
activeServiceConfigVersions = c1.getActiveServiceConfigVersions();
Assert.assertEquals("Two service config versions should be active, for default and test groups",
2, activeServiceConfigVersions.get("HDFS").size());
Config config3 = configFactory.createNew(c1, "hdfs-site",
new HashMap<String, String>() {{ put("a", "d"); }}, new HashMap<String, Map<String,String>>());
configGroup.setConfigurations(Collections.singletonMap("hdfs-site", config3));
configGroup.persist();
scvResponse = c1.createServiceConfigVersion("HDFS", "admin", "test note", configGroup);
assertEquals("SCV 3 should be created", Long.valueOf(3), scvResponse.getVersion());
//still two scv active, 3 total
activeServiceConfigVersions = c1.getActiveServiceConfigVersions();
Assert.assertEquals("Two service config versions should be active, for default and test groups",
2, activeServiceConfigVersions.get("HDFS").size());
assertEquals(3, c1.getServiceConfigVersions().size());
//rollback group
scvResponse = c1.setServiceConfigVersion("HDFS", 2L, "admin", "group rollback");
assertEquals("SCV 4 should be created", Long.valueOf(4), scvResponse.getVersion());
configGroup = c1.getConfigGroups().get(configGroup.getId()); //refresh?
//still two scv active, 4 total
activeServiceConfigVersions = c1.getActiveServiceConfigVersions();
Assert.assertEquals("Two service config versions should be active, for default and test groups",
2, activeServiceConfigVersions.get("HDFS").size());
assertEquals(4, c1.getServiceConfigVersions().size());
//check properties rolled back
Map<String, String> configProperties = configGroup.getConfigurations().get("hdfs-site").getProperties();
assertEquals("Configurations should be rolled back to a:c ", "c", configProperties.get("a"));
//check config with empty cluster
Config config4 = new ConfigImpl("hdfs-site");
config4.setProperties(new HashMap<String, String>() {{
put("a", "b");
}});
ConfigGroup configGroup2 =
configGroupFactory.createNew(c1, "test group 2", "HDFS", "descr", Collections.singletonMap("hdfs-site", config4),
Collections.<Long, Host>emptyMap());
configGroup2.persist();
c1.addConfigGroup(configGroup2);
scvResponse = c1.createServiceConfigVersion("HDFS", "admin", "test note", configGroup2);
assertEquals("SCV 5 should be created", Long.valueOf(5), scvResponse.getVersion());
activeServiceConfigVersions = c1.getActiveServiceConfigVersions();
Assert.assertEquals("Three service config versions should be active, for default and test groups",
3, activeServiceConfigVersions.get("HDFS").size());
assertEquals("Five total scvs", 5, c1.getServiceConfigVersions().size());
}
@Test
public void testAllServiceConfigVersionsWithConfigGroups() throws Exception {
// Given
createDefaultCluster();
Config hdfsSiteConfigV1 = configFactory.createNew(c1, "hdfs-site", ImmutableMap.of("p1", "v1"), ImmutableMap.<String, Map<String,String>>of());
hdfsSiteConfigV1.setTag("version1");
hdfsSiteConfigV1.persist();
c1.addConfig(hdfsSiteConfigV1);
ServiceConfigVersionResponse hdfsSiteConfigResponseV1 = c1.addDesiredConfig("admin", Collections.singleton(hdfsSiteConfigV1));
List<ConfigurationResponse> configResponsesDefaultGroup = Collections.singletonList(
new ConfigurationResponse(c1.getClusterName(), hdfsSiteConfigV1.getStackId(),
hdfsSiteConfigV1.getType(), hdfsSiteConfigV1.getTag(), hdfsSiteConfigV1.getVersion(),
hdfsSiteConfigV1.getProperties(), hdfsSiteConfigV1.getPropertiesAttributes(), hdfsSiteConfigV1.getPropertiesTypes())
);
hdfsSiteConfigResponseV1.setConfigurations(configResponsesDefaultGroup);
Config hdfsSiteConfigV2 = configFactory.createNew(c1, "hdfs-site", ImmutableMap.of("p1", "v2"), ImmutableMap.<String, Map<String,String>>of());
hdfsSiteConfigV2.setTag("version2");
ConfigGroup configGroup = configGroupFactory.createNew(c1, "configGroup1", "version1", "test description", ImmutableMap.of(hdfsSiteConfigV2.getType(), hdfsSiteConfigV2), ImmutableMap.<Long, Host>of());
configGroup.persist();
c1.addConfigGroup(configGroup);
ServiceConfigVersionResponse hdfsSiteConfigResponseV2 = c1.createServiceConfigVersion("HDFS", "admin", "test note", configGroup);
hdfsSiteConfigResponseV2.setConfigurations(Collections.singletonList(
new ConfigurationResponse(c1.getClusterName(), hdfsSiteConfigV2.getStackId(),
hdfsSiteConfigV2.getType(), hdfsSiteConfigV2.getTag(), hdfsSiteConfigV2.getVersion(),
hdfsSiteConfigV2.getProperties(), hdfsSiteConfigV2.getPropertiesAttributes(), hdfsSiteConfigV2.getPropertiesTypes())
));
hdfsSiteConfigResponseV2.setIsCurrent(true); // this is the active config in 'configGroup1' config group as it's the solely service config
// hdfs config v3
ServiceConfigVersionResponse hdfsSiteConfigResponseV3 = c1.createServiceConfigVersion("HDFS", "admin", "new config in default group", null);
hdfsSiteConfigResponseV3.setConfigurations(configResponsesDefaultGroup);
hdfsSiteConfigResponseV3.setIsCurrent(true); // this is the active config in default config group as it's more recent than V1
// When
List<ServiceConfigVersionResponse> expectedServiceConfigResponses = ImmutableList.of(hdfsSiteConfigResponseV1, hdfsSiteConfigResponseV2, hdfsSiteConfigResponseV3);
List<ServiceConfigVersionResponse> allServiceConfigResponses = c1.getServiceConfigVersions();
Collections.sort(
allServiceConfigResponses,
new Comparator<ServiceConfigVersionResponse>() {
@Override
public int compare(ServiceConfigVersionResponse o1, ServiceConfigVersionResponse o2) {
return o1.getVersion().compareTo(o2.getVersion());
}
}
);
// Then
assertThat(
allServiceConfigResponses,
is(expectedServiceConfigResponses));
}
@Test
public void testAllServiceConfigVersionsWithDeletedConfigGroups() throws Exception {
// Given
createDefaultCluster();
Config hdfsSiteConfigV1 = configFactory.createNew(c1, "hdfs-site", ImmutableMap.of("p1", "v1"), ImmutableMap.<String, Map<String,String>>of());
hdfsSiteConfigV1.setTag("version1");
hdfsSiteConfigV1.persist();
c1.addConfig(hdfsSiteConfigV1);
ServiceConfigVersionResponse hdfsSiteConfigResponseV1 = c1.addDesiredConfig("admin", Collections.singleton(hdfsSiteConfigV1));
List<ConfigurationResponse> configResponsesDefaultGroup = Collections.singletonList(
new ConfigurationResponse(c1.getClusterName(), hdfsSiteConfigV1.getStackId(),
hdfsSiteConfigV1.getType(), hdfsSiteConfigV1.getTag(), hdfsSiteConfigV1.getVersion(),
hdfsSiteConfigV1.getProperties(), hdfsSiteConfigV1.getPropertiesAttributes(), hdfsSiteConfigV1.getPropertiesTypes())
);
hdfsSiteConfigResponseV1.setConfigurations(configResponsesDefaultGroup);
Config hdfsSiteConfigV2 = configFactory.createNew(c1, "hdfs-site", ImmutableMap.of("p1", "v2"), ImmutableMap.<String, Map<String,String>>of());
hdfsSiteConfigV2.setTag("version2");
ConfigGroup configGroup = configGroupFactory.createNew(c1, "configGroup1", "version1", "test description", ImmutableMap.of(hdfsSiteConfigV2.getType(), hdfsSiteConfigV2), ImmutableMap.<Long, Host>of());
configGroup.persist();
c1.addConfigGroup(configGroup);
ServiceConfigVersionResponse hdfsSiteConfigResponseV2 = c1.createServiceConfigVersion("HDFS", "admin", "test note", configGroup);
hdfsSiteConfigResponseV2.setConfigurations(Collections.singletonList(
new ConfigurationResponse(c1.getClusterName(), hdfsSiteConfigV2.getStackId(),
hdfsSiteConfigV2.getType(), hdfsSiteConfigV2.getTag(), hdfsSiteConfigV2.getVersion(),
hdfsSiteConfigV2.getProperties(), hdfsSiteConfigV2.getPropertiesAttributes(), hdfsSiteConfigV2.getPropertiesTypes())
));
// delete the config group
c1.deleteConfigGroup(configGroup.getId());
// hdfs config v3
ServiceConfigVersionResponse hdfsSiteConfigResponseV3 = c1.createServiceConfigVersion("HDFS", "admin", "new config in default group", null);
hdfsSiteConfigResponseV3.setConfigurations(configResponsesDefaultGroup);
hdfsSiteConfigResponseV3.setIsCurrent(true); // this is the active config in default config group as it's more recent than V1
// When
List<ServiceConfigVersionResponse> allServiceConfigResponses = c1.getServiceConfigVersions();
Collections.sort(
allServiceConfigResponses,
new Comparator<ServiceConfigVersionResponse>() {
@Override
public int compare(ServiceConfigVersionResponse o1, ServiceConfigVersionResponse o2) {
return o1.getVersion().compareTo(o2.getVersion());
}
}
);
// Then
assertEquals(3, allServiceConfigResponses.size());
// all configs that was created as member of config group 'configGroup1' should be marked as 'not current'
// as the parent config group has been deleted
// default group
assertEquals(false, allServiceConfigResponses.get(0).getIsCurrent());
assertEquals(ServiceConfigVersionResponse.DEFAULT_CONFIG_GROUP_NAME, allServiceConfigResponses.get(0).getGroupName());
assertEquals(true, allServiceConfigResponses.get(2).getIsCurrent());
assertEquals(ServiceConfigVersionResponse.DEFAULT_CONFIG_GROUP_NAME, allServiceConfigResponses.get(2).getGroupName());
// deleted group
assertEquals(false, allServiceConfigResponses.get(1).getIsCurrent());
assertEquals(ServiceConfigVersionResponse.DELETED_CONFIG_GROUP_NAME, allServiceConfigResponses.get(1).getGroupName());
}
@Test
public void testTransitionClusterVersion() throws Exception {
createDefaultCluster();
String stack = "HDP";
String version = "0.2";
StackId stackId = new StackId(stack, version);
helper.getOrCreateRepositoryVersion(stackId, version);
c1.createClusterVersion(stackId, version, "admin",
RepositoryVersionState.INSTALLING);
assertStateException(stackId, version, RepositoryVersionState.CURRENT,
RepositoryVersionState.INSTALLING);
assertStateException(stackId, version, RepositoryVersionState.UPGRADING,
RepositoryVersionState.INSTALLING);
assertStateException(stackId, version, RepositoryVersionState.UPGRADED,
RepositoryVersionState.INSTALLING);
assertStateException(stackId, version,
RepositoryVersionState.UPGRADE_FAILED,
RepositoryVersionState.INSTALLING);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.INSTALL_FAILED);
checkStackVersionState(stackId, version,
RepositoryVersionState.INSTALL_FAILED);
assertStateException(stackId, version, RepositoryVersionState.CURRENT,
RepositoryVersionState.INSTALL_FAILED);
assertStateException(stackId, version, RepositoryVersionState.INSTALLED,
RepositoryVersionState.INSTALL_FAILED);
assertStateException(stackId, version, RepositoryVersionState.UPGRADING,
RepositoryVersionState.INSTALL_FAILED);
assertStateException(stackId, version, RepositoryVersionState.UPGRADED,
RepositoryVersionState.INSTALL_FAILED);
assertStateException(stackId, version,
RepositoryVersionState.UPGRADE_FAILED,
RepositoryVersionState.INSTALL_FAILED);
assertStateException(stackId, version, RepositoryVersionState.OUT_OF_SYNC,
RepositoryVersionState.INSTALL_FAILED);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.INSTALLING);
checkStackVersionState(stackId, version, RepositoryVersionState.INSTALLING);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.INSTALLED);
checkStackVersionState(stackId, version, RepositoryVersionState.INSTALLED);
assertStateException(stackId, version, RepositoryVersionState.CURRENT,
RepositoryVersionState.INSTALLED);
assertStateException(stackId, version,
RepositoryVersionState.UPGRADE_FAILED, RepositoryVersionState.INSTALLED);
assertStateException(stackId, version,
RepositoryVersionState.INSTALL_FAILED, RepositoryVersionState.INSTALLED);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.OUT_OF_SYNC);
checkStackVersionState(stackId, version, RepositoryVersionState.OUT_OF_SYNC);
assertStateException(stackId, version, RepositoryVersionState.CURRENT,
RepositoryVersionState.OUT_OF_SYNC);
assertStateException(stackId, version, RepositoryVersionState.INSTALLED,
RepositoryVersionState.OUT_OF_SYNC);
assertStateException(stackId, version,
RepositoryVersionState.INSTALL_FAILED,
RepositoryVersionState.OUT_OF_SYNC);
assertStateException(stackId, version, RepositoryVersionState.UPGRADING,
RepositoryVersionState.OUT_OF_SYNC);
assertStateException(stackId, version, RepositoryVersionState.UPGRADED,
RepositoryVersionState.OUT_OF_SYNC);
assertStateException(stackId, version,
RepositoryVersionState.UPGRADE_FAILED,
RepositoryVersionState.OUT_OF_SYNC);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.INSTALLING);
checkStackVersionState(stackId, version, RepositoryVersionState.INSTALLING);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.INSTALLED);
checkStackVersionState(stackId, version, RepositoryVersionState.INSTALLED);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.UPGRADING);
checkStackVersionState(stackId, version, RepositoryVersionState.UPGRADING);
assertStateException(stackId, version, RepositoryVersionState.CURRENT,
RepositoryVersionState.UPGRADING);
assertStateException(stackId, version, RepositoryVersionState.INSTALLED,
RepositoryVersionState.UPGRADING);
assertStateException(stackId, version,
RepositoryVersionState.INSTALL_FAILED, RepositoryVersionState.UPGRADING);
assertStateException(stackId, version, RepositoryVersionState.OUT_OF_SYNC,
RepositoryVersionState.UPGRADING);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.UPGRADE_FAILED);
checkStackVersionState(stackId, version,
RepositoryVersionState.UPGRADE_FAILED);
assertStateException(stackId, version, RepositoryVersionState.CURRENT,
RepositoryVersionState.UPGRADE_FAILED);
assertStateException(stackId, version, RepositoryVersionState.INSTALLED,
RepositoryVersionState.UPGRADE_FAILED);
assertStateException(stackId, version,
RepositoryVersionState.INSTALL_FAILED,
RepositoryVersionState.UPGRADE_FAILED);
assertStateException(stackId, version, RepositoryVersionState.UPGRADED,
RepositoryVersionState.UPGRADE_FAILED);
assertStateException(stackId, version, RepositoryVersionState.OUT_OF_SYNC,
RepositoryVersionState.UPGRADE_FAILED);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.UPGRADING);
checkStackVersionState(stackId, version, RepositoryVersionState.UPGRADING);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.UPGRADED);
checkStackVersionState(stackId, version, RepositoryVersionState.UPGRADED);
assertStateException(stackId, version, RepositoryVersionState.INSTALLED,
RepositoryVersionState.UPGRADED);
assertStateException(stackId, version,
RepositoryVersionState.INSTALL_FAILED, RepositoryVersionState.UPGRADED);
assertStateException(stackId, version, RepositoryVersionState.UPGRADING,
RepositoryVersionState.UPGRADED);
assertStateException(stackId, version,
RepositoryVersionState.UPGRADE_FAILED, RepositoryVersionState.UPGRADED);
assertStateException(stackId, version, RepositoryVersionState.OUT_OF_SYNC,
RepositoryVersionState.UPGRADED);
c1.setDesiredStackVersion(stackId);
c1.transitionClusterVersion(stackId, version,
RepositoryVersionState.CURRENT);
checkStackVersionState(stackId, version, RepositoryVersionState.CURRENT);
checkStackVersionState(new StackId("HDP", "0.1"), "0.1",
RepositoryVersionState.INSTALLED);
// The only CURRENT state should not be changed
assertStateException(stackId, version, RepositoryVersionState.INSTALLED,
RepositoryVersionState.CURRENT);
}
@Test
public void testTransitionClusterVersionTransactionFail() throws Exception {
createDefaultCluster();
StackId stackId = new StackId("HDP", "0.2");
helper.getOrCreateRepositoryVersion(stackId, stackId.getStackVersion());
c1.createClusterVersion(stackId, "0.2", "admin",
RepositoryVersionState.INSTALLING);
c1.transitionClusterVersion(stackId, "0.2",
RepositoryVersionState.INSTALLED);
c1.transitionClusterVersion(stackId, "0.2",
RepositoryVersionState.UPGRADING);
c1.transitionClusterVersion(stackId, "0.2", RepositoryVersionState.UPGRADED);
try {
ClusterVersionDAOMock.failOnCurrentVersionState = true;
c1.transitionClusterVersion(stackId, "0.2",
RepositoryVersionState.CURRENT);
Assert.fail();
} catch (AmbariException e) {
} finally {
ClusterVersionDAOMock.failOnCurrentVersionState = false;
}
// There must be CURRENT state for cluster
assertNotNull(c1.getCurrentClusterVersion());
}
/**
* Tests that hosts can be correctly transitioned into the "INSTALLING" state.
* This method also tests that hosts in MM will not be transitioned, as per
* the contract of
* {@link Cluster#transitionHostsToInstalling(ClusterVersionEntity)}.
*
* @throws Exception
*/
@Test
public void testTransitionHostVersions() throws Exception {
createDefaultCluster();
StackId stackId = new StackId("HDP", "0.2");
helper.getOrCreateRepositoryVersion(stackId, stackId.getStackVersion());
c1.createClusterVersion(stackId, "0.2", "admin",
RepositoryVersionState.INSTALLING);
ClusterVersionEntity entityHDP2 = null;
for (ClusterVersionEntity entity : c1.getAllClusterVersions()) {
StackEntity repoVersionStackEntity = entity.getRepositoryVersion().getStack();
StackId repoVersionStackId = new StackId(repoVersionStackEntity);
if (repoVersionStackId.getStackName().equals("HDP")
&& repoVersionStackId.getStackVersion().equals("0.2")) {
entityHDP2 = entity;
break;
}
}
assertNotNull(entityHDP2);
List<HostVersionEntity> hostVersionsH1Before = hostVersionDAO.findByClusterAndHost("c1", "h1");
assertEquals(1, hostVersionsH1Before.size());
c1.transitionHostsToInstalling(entityHDP2);
List<HostVersionEntity> hostVersionsH1After = hostVersionDAO.findByClusterAndHost("c1", "h1");
assertEquals(2, hostVersionsH1After.size());
boolean checked = false;
for (HostVersionEntity entity : hostVersionsH1After) {
StackEntity repoVersionStackEntity = entity.getRepositoryVersion().getStack();
if (repoVersionStackEntity.getStackName().equals("HDP")
&& repoVersionStackEntity.getStackVersion().equals("0.2")) {
assertEquals(RepositoryVersionState.INSTALLING, entity.getState());
checked = true;
break;
}
}
assertTrue(checked);
// Test for update of existing host stack version
c1.transitionHostsToInstalling(entityHDP2);
hostVersionsH1After = hostVersionDAO.findByClusterAndHost("c1", "h1");
assertEquals(2, hostVersionsH1After.size());
checked = false;
for (HostVersionEntity entity : hostVersionsH1After) {
StackEntity repoVersionStackEntity = entity.getRepositoryVersion().getStack();
if (repoVersionStackEntity.getStackName().equals("HDP")
&& repoVersionStackEntity.getStackVersion().equals("0.2")) {
assertEquals(RepositoryVersionState.INSTALLING, entity.getState());
checked = true;
break;
}
}
assertTrue(checked);
// reset all to INSTALL_FAILED
List<HostVersionEntity> hostVersionEntities = hostVersionDAO.findAll();
for (HostVersionEntity hostVersionEntity : hostVersionEntities) {
hostVersionEntity.setState(RepositoryVersionState.INSTALL_FAILED);
hostVersionDAO.merge(hostVersionEntity);
}
// verify they have been transition to INSTALL_FAILED
hostVersionEntities = hostVersionDAO.findAll();
for (HostVersionEntity hostVersionEntity : hostVersionEntities) {
assertEquals(RepositoryVersionState.INSTALL_FAILED, hostVersionEntity.getState());
}
// put 1 host in maintenance mode
Collection<Host> hosts = c1.getHosts();
Iterator<Host> iterator = hosts.iterator();
Host hostInMaintenanceMode = iterator.next();
Host hostNotInMaintenanceMode = iterator.next();
hostInMaintenanceMode.setMaintenanceState(c1.getClusterId(), MaintenanceState.ON);
// transition host versions to INSTALLING
c1.transitionHostsToInstalling(entityHDP2);
List<HostVersionEntity> hostInMaintModeVersions = hostVersionDAO.findByClusterAndHost("c1",
hostInMaintenanceMode.getHostName());
List<HostVersionEntity> otherHostVersions = hostVersionDAO.findByClusterAndHost("c1",
hostNotInMaintenanceMode.getHostName());
// verify the MM host has moved to OUT_OF_SYNC
for (HostVersionEntity hostVersionEntity : hostInMaintModeVersions) {
StackEntity repoVersionStackEntity = hostVersionEntity.getRepositoryVersion().getStack();
if (repoVersionStackEntity.getStackName().equals("HDP")
&& repoVersionStackEntity.getStackVersion().equals("0.2")) {
assertEquals(RepositoryVersionState.OUT_OF_SYNC, hostVersionEntity.getState());
}
}
// verify the other host is in INSTALLING
for (HostVersionEntity hostVersionEntity : otherHostVersions) {
StackEntity repoVersionStackEntity = hostVersionEntity.getRepositoryVersion().getStack();
if (repoVersionStackEntity.getStackName().equals("HDP")
&& repoVersionStackEntity.getStackVersion().equals("0.2")) {
assertEquals(RepositoryVersionState.INSTALLING, hostVersionEntity.getState());
}
}
}
@Test
public void testRecalculateClusterVersionState() throws Exception {
createDefaultCluster();
Host h1 = clusters.getHost("h1");
h1.setState(HostState.HEALTHY);
Host h2 = clusters.getHost("h2");
h2.setState(HostState.HEALTHY);
// Phase 1: Install bits during distribution
StackId stackId = new StackId("HDP-0.1");
final String stackVersion = "0.1-1000";
RepositoryVersionEntity repositoryVersionEntity = helper.getOrCreateRepositoryVersion(
stackId,
stackVersion);
// Because the cluster already has a Cluster Version, an additional stack must init with INSTALLING
c1.createClusterVersion(stackId, stackVersion, "admin",
RepositoryVersionState.INSTALLING);
c1.setCurrentStackVersion(stackId);
HostVersionEntity hv1 = helper.createHostVersion("h1", repositoryVersionEntity, RepositoryVersionState.INSTALLING);
HostVersionEntity hv2 = helper.createHostVersion("h2", repositoryVersionEntity, RepositoryVersionState.INSTALLING);
c1.recalculateClusterVersionState(repositoryVersionEntity);
//Should remain in its current state
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.INSTALLING);
h2.setState(HostState.UNHEALTHY);
c1.recalculateClusterVersionState(repositoryVersionEntity);
// In order for the states to be accurately reflected, the host health status should not impact the status
// of the host_version.
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.INSTALLING);
// Retry by going back to INSTALLING
c1.transitionClusterVersion(stackId, stackVersion,
RepositoryVersionState.INSTALLING);
// Installation on one host fails (other is continuing)
hv1.setState(RepositoryVersionState.INSTALL_FAILED);
hostVersionDAO.merge(hv1);
// Check that cluster version is still in a non-final state
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.INSTALLING);
h2.setState(HostState.HEALTHY);
hv2.setState(RepositoryVersionState.INSTALLED);
hostVersionDAO.merge(hv2);
// Now both cluster versions are in a final state, so
// cluster version state changes to final state
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.INSTALL_FAILED);
// Retry by going back to INSTALLING
c1.transitionClusterVersion(stackId, stackVersion,
RepositoryVersionState.INSTALLING);
h2.setState(HostState.HEALTHY);
hv2.setState(RepositoryVersionState.INSTALLED);
hostVersionDAO.merge(hv2);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.INSTALLING);
// Make the last host fail
hv1.setState(RepositoryVersionState.INSTALL_FAILED);
hostVersionDAO.merge(hv1);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.INSTALL_FAILED);
// Retry by going back to INSTALLING
c1.transitionClusterVersion(stackId, stackVersion,
RepositoryVersionState.INSTALLING);
// Now, all hosts are in INSTALLED
hv1.setState(RepositoryVersionState.INSTALLED);
hostVersionDAO.merge(hv1);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.INSTALLED);
// Phase 2: Upgrade stack
hv1.setState(RepositoryVersionState.UPGRADING);
hostVersionDAO.merge(hv1);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.UPGRADING);
hv1.setState(RepositoryVersionState.UPGRADED);
hostVersionDAO.merge(hv1);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.UPGRADING);
// reset host1 state
hv1.setState(RepositoryVersionState.UPGRADING);
hv2.setState(RepositoryVersionState.UPGRADING);
hostVersionDAO.merge(hv2);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.UPGRADING);
hv2.setState(RepositoryVersionState.UPGRADE_FAILED);
hostVersionDAO.merge(hv2);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.UPGRADE_FAILED);
// Retry by going back to UPGRADING
c1.transitionClusterVersion(stackId, stackVersion,
RepositoryVersionState.UPGRADING);
hv2.setState(RepositoryVersionState.UPGRADED);
hostVersionDAO.merge(hv2);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.UPGRADING);
// Now both hosts are UPGRADED
hv1.setState(RepositoryVersionState.UPGRADED);
hostVersionDAO.merge(hv1);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.UPGRADED);
// Set both hosts to CURRENT
hv1.setState(RepositoryVersionState.CURRENT);
hostVersionDAO.merge(hv1);
hv2.setState(RepositoryVersionState.CURRENT);
hostVersionDAO.merge(hv2);
c1.recalculateClusterVersionState(repositoryVersionEntity);
checkStackVersionState(stackId, stackVersion,
RepositoryVersionState.CURRENT);
}
@Test
public void testRecalculateAllClusterVersionStates() throws Exception {
createDefaultCluster();
Host h1 = clusters.getHost("h1");
h1.setState(HostState.HEALTHY);
Host h2 = clusters.getHost("h2");
h2.setState(HostState.HEALTHY);
StackId stackId = new StackId("HDP-0.1");
RepositoryVersionEntity repositoryVersionEntity = helper.getOrCreateRepositoryVersion(
stackId,
"0.1-1000");
c1.createClusterVersion(stackId, "0.1-1000", "admin",
RepositoryVersionState.INSTALLING);
c1.setCurrentStackVersion(stackId);
c1.recalculateAllClusterVersionStates();
checkStackVersionState(stackId, "0.1-1000",
RepositoryVersionState.INSTALLING);
checkStackVersionState(stackId, "0.1-2086", RepositoryVersionState.CURRENT);
HostVersionEntity hv1 = helper.createHostVersion("h1", repositoryVersionEntity, RepositoryVersionState.INSTALLING);
HostVersionEntity hv2 = helper.createHostVersion("h2", repositoryVersionEntity, RepositoryVersionState.INSTALLING);
c1.recalculateAllClusterVersionStates();
checkStackVersionState(stackId, "0.1-1000",
RepositoryVersionState.INSTALLING);
checkStackVersionState(stackId, "1.0-2086", RepositoryVersionState.CURRENT);
hv1.setState(RepositoryVersionState.INSTALL_FAILED);
hostVersionDAO.merge(hv1);
c1.recalculateAllClusterVersionStates();
checkStackVersionState(stackId, "0.1-1000",
RepositoryVersionState.INSTALL_FAILED);
checkStackVersionState(stackId, "0.1-2086", RepositoryVersionState.CURRENT);
// Retry by going back to INSTALLING
c1.transitionClusterVersion(stackId, "0.1-1000",
RepositoryVersionState.INSTALLING);
hv1.setState(RepositoryVersionState.CURRENT);
hostVersionDAO.merge(hv1);
c1.recalculateAllClusterVersionStates();
checkStackVersionState(stackId, "0.1-1000",
RepositoryVersionState.OUT_OF_SYNC);
checkStackVersionState(stackId, "0.1-2086", RepositoryVersionState.CURRENT);
}
/**
* Comprehensive test for transitionHostVersion and recalculateClusterVersion.
* It creates a cluster with 3 hosts and 3 services, one of which does not advertise a version.
* It then verifies that all 3 hosts have a version of CURRENT, and so does the cluster.
* It then adds one more host with a component, so its HostVersion will initialize in CURRENT.
* Next, it distributes a repo so that it is INSTALLED on the 4 hosts.
* It then adds one more host, whose HostVersion will be OUT_OF_SYNC for the new repo.
* After redistributing bits again, it simulates an RU.
* Finally, some of the hosts will end up with a HostVersion in UPGRADED, and others still in INSTALLED.
* @throws Exception
*/
@Test
public void testTransitionHostVersionAdvanced() throws Exception {
String clusterName = "c1";
String v1 = "2.2.0-123";
StackId stackId = new StackId("HDP-2.2.0");
RepositoryVersionEntity rv1 = helper.getOrCreateRepositoryVersion(stackId, v1);
Map<String, String> hostAttributes = new HashMap<String, String>();
hostAttributes.put("os_family", "redhat");
hostAttributes.put("os_release_version", "5.9");
Cluster cluster = createClusterForRU(clusterName, stackId, hostAttributes);
// Begin install by starting to advertise versions
// Set the version for the HostComponentState objects
int versionedComponentCount = 0;
List<HostComponentStateEntity> hostComponentStates = hostComponentStateDAO.findAll();
for(int i = 0; i < hostComponentStates.size(); i++) {
HostComponentStateEntity hce = hostComponentStates.get(i);
ComponentInfo compInfo = metaInfo.getComponent(
stackId.getStackName(), stackId.getStackVersion(),
hce.getServiceName(),
hce.getComponentName());
if (compInfo.isVersionAdvertised()) {
hce.setVersion(v1);
hostComponentStateDAO.merge(hce);
versionedComponentCount++;
}
// Simulate the StackVersionListener during the installation of the first Stack Version
Service svc = cluster.getService(hce.getServiceName());
ServiceComponent svcComp = svc.getServiceComponent(hce.getComponentName());
ServiceComponentHost scHost = svcComp.getServiceComponentHost(hce.getHostName());
scHost.recalculateHostVersionState();
cluster.recalculateClusterVersionState(rv1);
Collection<ClusterVersionEntity> clusterVersions = cluster.getAllClusterVersions();
if (versionedComponentCount > 0) {
// On the first component with a version, a RepoVersion should have been created
RepositoryVersionEntity repositoryVersion = repositoryVersionDAO.findByStackAndVersion(stackId, v1);
Assert.assertNotNull(repositoryVersion);
Assert.assertTrue(clusterVersions != null && clusterVersions.size() == 1);
// First component to report a version should cause the ClusterVersion to go to UPGRADING
if (versionedComponentCount == 1 && i < (hostComponentStates.size() - 1)) {
Assert.assertEquals(clusterVersions.iterator().next().getState(), RepositoryVersionState.UPGRADING);
}
// Last component to report a version should cause the ClusterVersion to go to CURRENT
if (i == hostComponentStates.size() - 1) {
Assert.assertEquals(clusterVersions.iterator().next().getState(), RepositoryVersionState.CURRENT);
}
}
}
// Add another Host with components ZK Server, ZK Client, and Ganglia Monitor.
// This host should get a HostVersion in CURRENT, and the ClusterVersion should stay in CURRENT
addHost("h-4", hostAttributes);
clusters.mapHostToCluster("h-4", clusterName);
Service svc2 = cluster.getService("ZOOKEEPER");
Service svc3 = cluster.getService("GANGLIA");
ServiceComponent sc2CompA = svc2.getServiceComponent("ZOOKEEPER_SERVER");
ServiceComponent sc2CompB = svc2.getServiceComponent("ZOOKEEPER_CLIENT");
ServiceComponent sc3CompB = svc3.getServiceComponent("GANGLIA_MONITOR");
ServiceComponentHost schHost4Serv2CompA = serviceComponentHostFactory.createNew(sc2CompA, "h-4");
ServiceComponentHost schHost4Serv2CompB = serviceComponentHostFactory.createNew(sc2CompB, "h-4");
ServiceComponentHost schHost4Serv3CompB = serviceComponentHostFactory.createNew(sc3CompB, "h-4");
sc2CompA.addServiceComponentHost(schHost4Serv2CompA);
sc2CompB.addServiceComponentHost(schHost4Serv2CompB);
sc3CompB.addServiceComponentHost(schHost4Serv3CompB);
schHost4Serv2CompA.persist();
schHost4Serv2CompB.persist();
schHost4Serv3CompB.persist();
simulateStackVersionListener(stackId, v1, cluster, hostComponentStateDAO.findByHost("h-4"));
Collection<HostVersionEntity> hostVersions = hostVersionDAO.findAll();
Assert.assertEquals(hostVersions.size(), clusters.getHosts().size());
HostVersionEntity h4Version1 = hostVersionDAO.findByClusterStackVersionAndHost(clusterName, stackId, v1, "h-4");
Assert.assertNotNull(h4Version1);
Assert.assertEquals(h4Version1.getState(), RepositoryVersionState.CURRENT);
// Distribute bits for a new repo
String v2 = "2.2.0-456";
RepositoryVersionEntity rv2 = helper.getOrCreateRepositoryVersion(stackId, v2);
for(String hostName : clusters.getHostsForCluster(clusterName).keySet()) {
HostEntity host = hostDAO.findByName(hostName);
HostVersionEntity hve = new HostVersionEntity(host, rv2, RepositoryVersionState.INSTALLED);
hostVersionDAO.create(hve);
}
cluster.createClusterVersion(stackId, v2, "admin",
RepositoryVersionState.INSTALLING);
cluster.transitionClusterVersion(stackId, v2,
RepositoryVersionState.INSTALLED);
ClusterVersionEntity cv2 = clusterVersionDAO.findByClusterAndStackAndVersion(clusterName, stackId, v2);
Assert.assertNotNull(cv2);
Assert.assertEquals(cv2.getState(), RepositoryVersionState.INSTALLED);
// Add one more Host, with only Ganglia on it. It should have a HostVersion in OUT_OF_SYNC for v2
addHost("h-5", hostAttributes);
clusters.mapHostToCluster("h-5", clusterName);
ServiceComponentHost schHost5Serv3CompB = serviceComponentHostFactory.createNew(sc3CompB, "h-5");
sc3CompB.addServiceComponentHost(schHost5Serv3CompB);
schHost5Serv3CompB.persist();
// Host 5 will be in OUT_OF_SYNC, so redistribute bits to it so that it reaches a state of INSTALLED
HostVersionEntity h5Version2 = hostVersionDAO.findByClusterStackVersionAndHost(clusterName, stackId, v2, "h-5");
Assert.assertNotNull(h5Version2);
Assert.assertEquals(h5Version2.getState(), RepositoryVersionState.OUT_OF_SYNC);
h5Version2.setState(RepositoryVersionState.INSTALLED);
hostVersionDAO.merge(h5Version2);
// Perform an RU.
// Verify that on first component with the new version, the ClusterVersion transitions to UPGRADING.
// For hosts with only components that advertise a version, they HostVersion should be in UPGRADING.
// For the remaining hosts, the HostVersion should stay in INSTALLED.
versionedComponentCount = 0;
hostComponentStates = hostComponentStateDAO.findAll();
for(int i = 0; i < hostComponentStates.size(); i++) {
HostComponentStateEntity hce = hostComponentStates.get(i);
ComponentInfo compInfo = metaInfo.getComponent(
stackId.getStackName(), stackId.getStackVersion(),
hce.getServiceName(),
hce.getComponentName());
if (compInfo.isVersionAdvertised()) {
hce.setVersion(v2);
hostComponentStateDAO.merge(hce);
versionedComponentCount++;
}
// Simulate the StackVersionListener during the installation of the first Stack Version
Service svc = cluster.getService(hce.getServiceName());
ServiceComponent svcComp = svc.getServiceComponent(hce.getComponentName());
ServiceComponentHost scHost = svcComp.getServiceComponentHost(hce.getHostName());
scHost.recalculateHostVersionState();
cluster.recalculateClusterVersionState(rv2);
Collection<ClusterVersionEntity> clusterVersions = cluster.getAllClusterVersions();
if (versionedComponentCount > 0) {
// On the first component with a version, a RepoVersion should have been created
RepositoryVersionEntity repositoryVersion = repositoryVersionDAO.findByStackAndVersion(stackId, v2);
Assert.assertNotNull(repositoryVersion);
Assert.assertTrue(clusterVersions != null && clusterVersions.size() == 2);
// First component to report a version should cause the ClusterVersion to go to UPGRADING
if (versionedComponentCount == 1 && i < (hostComponentStates.size() - 1)) {
cv2 = clusterVersionDAO.findByClusterAndStackAndVersion(clusterName, stackId, v2);
Assert.assertEquals(cv2.getState(), RepositoryVersionState.UPGRADING);
}
}
}
// Last component to report a version should still keep the ClusterVersion in UPGRADING because
// hosts 3 and 5 only have Ganglia and the HostVersion will remain in INSTALLED
cv2 = clusterVersionDAO.findByClusterAndStackAndVersion(clusterName, stackId, v2);
Assert.assertEquals(cv2.getState(), RepositoryVersionState.UPGRADING);
Collection<HostVersionEntity> v2HostVersions = hostVersionDAO.findByClusterStackAndVersion(clusterName, stackId, v2);
Assert.assertEquals(v2HostVersions.size(), clusters.getHostsForCluster(clusterName).size());
for (HostVersionEntity hve : v2HostVersions) {
if (hve.getHostName().equals("h-3") || hve.getHostName().equals("h-5")) {
Assert.assertEquals(hve.getState(), RepositoryVersionState.INSTALLED);
} else {
Assert.assertEquals(hve.getState(), RepositoryVersionState.UPGRADED);
}
}
}
@Test
public void testBootstrapHostVersion() throws Exception {
String clusterName = "c1";
String v1 = "2.2.0-123";
StackId stackId = new StackId("HDP-2.2.0");
RepositoryVersionEntity rv1 = helper.getOrCreateRepositoryVersion(stackId, v1);
Map<String, String> hostAttributes = new HashMap<String, String>();
hostAttributes.put("os_family", "redhat");
hostAttributes.put("os_release_version", "5.9");
Cluster cluster = createClusterForRU(clusterName, stackId, hostAttributes);
// Make one host unhealthy
Host deadHost = cluster.getHosts().iterator().next();
deadHost.setState(HostState.UNHEALTHY);
// Begin bootstrap by starting to advertise versions
// Set the version for the HostComponentState objects
int versionedComponentCount = 0;
List<HostComponentStateEntity> hostComponentStates = hostComponentStateDAO.findAll();
for(int i = 0; i < hostComponentStates.size(); i++) {
HostComponentStateEntity hce = hostComponentStates.get(i);
ComponentInfo compInfo = metaInfo.getComponent(
stackId.getStackName(), stackId.getStackVersion(),
hce.getServiceName(),
hce.getComponentName());
if (hce.getHostName().equals(deadHost.getHostName())) {
continue; // Skip setting version
}
if (compInfo.isVersionAdvertised()) {
hce.setVersion(v1);
hostComponentStateDAO.merge(hce);
versionedComponentCount++;
}
// Simulate the StackVersionListener during the installation of the first Stack Version
Service svc = cluster.getService(hce.getServiceName());
ServiceComponent svcComp = svc.getServiceComponent(hce.getComponentName());
ServiceComponentHost scHost = svcComp.getServiceComponentHost(hce.getHostName());
scHost.recalculateHostVersionState();
cluster.recalculateClusterVersionState(rv1);
Collection<ClusterVersionEntity> clusterVersions = cluster.getAllClusterVersions();
if (versionedComponentCount > 0) {
// On the first component with a version, a RepoVersion should have been created
RepositoryVersionEntity repositoryVersion = repositoryVersionDAO.findByStackAndVersion(stackId, v1);
Assert.assertNotNull(repositoryVersion);
Assert.assertTrue(clusterVersions != null && clusterVersions.size() == 1);
// Since host 2 is dead, and host 3 contains only components that dont report a version,
// cluster version transitions to CURRENT after first component on host 1 reports it's version
if (versionedComponentCount == 1 && i < (hostComponentStates.size() - 1)) {
Assert.assertEquals(clusterVersions.iterator().next().getState(), RepositoryVersionState.CURRENT);
}
}
}
}
@Test
public void testTransitionNonReportableHost() throws Exception {
StackId stackId = new StackId("HDP-2.0.5");
String clusterName = "c1";
clusters.addCluster(clusterName, stackId);
Cluster c1 = clusters.getCluster(clusterName);
Assert.assertEquals(clusterName, c1.getClusterName());
Assert.assertEquals(1, c1.getClusterId());
clusters.addHost("h-1");
clusters.addHost("h-2");
clusters.addHost("h-3");
for (String hostName : new String[] { "h-1", "h-2", "h-3" }) {
Host h = clusters.getHost(hostName);
h.setIPv4("ipv4");
h.setIPv6("ipv6");
Map<String, String> hostAttributes = new HashMap<String, String>();
hostAttributes.put("os_family", "redhat");
hostAttributes.put("os_release_version", "5.9");
h.setHostAttributes(hostAttributes);
h.persist();
}
String v1 = "2.0.5-1";
String v2 = "2.0.5-2";
c1.setDesiredStackVersion(stackId);
RepositoryVersionEntity rve1 = helper.getOrCreateRepositoryVersion(stackId,
v1);
RepositoryVersionEntity rve2 = helper.getOrCreateRepositoryVersion(stackId,
v2);
c1.setCurrentStackVersion(stackId);
c1.createClusterVersion(stackId, v1, "admin",
RepositoryVersionState.UPGRADING);
c1.transitionClusterVersion(stackId, v1, RepositoryVersionState.CURRENT);
clusters.mapHostToCluster("h-1", clusterName);
clusters.mapHostToCluster("h-2", clusterName);
clusters.mapHostToCluster("h-3", clusterName);
ClusterVersionDAOMock.failOnCurrentVersionState = false;
Service service = c1.addService("ZOOKEEPER");
ServiceComponent sc = service.addServiceComponent("ZOOKEEPER_SERVER");
sc.addServiceComponentHost("h-1");
sc.addServiceComponentHost("h-2");
service = c1.addService("SQOOP");
sc = service.addServiceComponent("SQOOP");
sc.addServiceComponentHost("h-3");
List<HostVersionEntity> entities = hostVersionDAO.findByClusterAndHost(clusterName, "h-3");
assertTrue("Expected no host versions", null == entities || 0 == entities.size());
c1.createClusterVersion(stackId, v2, "admin",
RepositoryVersionState.INSTALLING);
c1.transitionClusterVersion(stackId, v2, RepositoryVersionState.INSTALLED);
c1.transitionClusterVersion(stackId, v2, RepositoryVersionState.UPGRADING);
c1.transitionClusterVersion(stackId, v2, RepositoryVersionState.UPGRADED);
c1.transitionClusterVersion(stackId, v2, RepositoryVersionState.CURRENT);
entities = hostVersionDAO.findByClusterAndHost(clusterName, "h-3");
assertEquals(1, entities.size());
}
@Test
public void testTransitionHostVersionState_OutOfSync_BlankCurrent() throws Exception {
/**
* Checks case when there are 2 cluster stack versions present (CURRENT and OUT_OF_SYNC),
* and we add a new host to cluster. On a new host, both CURRENT and OUT_OF_SYNC host
* versions should be present
*/
StackId stackId = new StackId("HDP-2.0.5");
String clusterName = "c1";
clusters.addCluster(clusterName, stackId);
final Cluster c1 = clusters.getCluster(clusterName);
Assert.assertEquals(clusterName, c1.getClusterName());
Assert.assertEquals(1, c1.getClusterId());
clusters.addHost("h-1");
clusters.addHost("h-2");
String h3 = "h-3";
clusters.addHost(h3);
for (String hostName : new String[] { "h-1", "h-2", h3}) {
Host h = clusters.getHost(hostName);
h.setIPv4("ipv4");
h.setIPv6("ipv6");
Map<String, String> hostAttributes = new HashMap<String, String>();
hostAttributes.put("os_family", "redhat");
hostAttributes.put("os_release_version", "5.9");
h.setHostAttributes(hostAttributes);
h.persist();
}
String v1 = "2.0.5-1";
String v2 = "2.0.5-2";
c1.setDesiredStackVersion(stackId);
RepositoryVersionEntity rve1 = helper.getOrCreateRepositoryVersion(stackId,
v1);
RepositoryVersionEntity rve2 = helper.getOrCreateRepositoryVersion(stackId,
v2);
c1.setCurrentStackVersion(stackId);
c1.createClusterVersion(stackId, v1, "admin",
RepositoryVersionState.UPGRADING);
c1.transitionClusterVersion(stackId, v1, RepositoryVersionState.CURRENT);
clusters.mapHostToCluster("h-1", clusterName);
clusters.mapHostToCluster("h-2", clusterName);
ClusterVersionDAOMock.failOnCurrentVersionState = false;
Service service = c1.addService("ZOOKEEPER");
ServiceComponent sc = service.addServiceComponent("ZOOKEEPER_SERVER");
sc.addServiceComponentHost("h-1");
sc.addServiceComponentHost("h-2");
c1.createClusterVersion(stackId, v2, "admin",
RepositoryVersionState.INSTALLING);
c1.transitionClusterVersion(stackId, v2, RepositoryVersionState.INSTALLED);
c1.transitionClusterVersion(stackId, v2, RepositoryVersionState.OUT_OF_SYNC);
clusters.mapHostToCluster(h3, clusterName);
// This method is usually called when we receive heartbeat from new host
HostEntity hostEntity3 = mock(HostEntity.class);
when(hostEntity3.getHostName()).thenReturn(h3);
// HACK: to workaround issue with NullPointerException at
// org.eclipse.persistence.internal.sessions.MergeManager.registerObjectForMergeCloneIntoWorkingCopy(MergeManager.java:1037)
// during hostVersionDAO.merge()
HostVersionDAO hostVersionDAOMock = mock(HostVersionDAO.class);
Field field = ClusterImpl.class.getDeclaredField("hostVersionDAO");
field.setAccessible(true);
field.set(c1, hostVersionDAOMock);
ArgumentCaptor<HostVersionEntity> hostVersionCaptor = ArgumentCaptor.forClass(HostVersionEntity.class);
ClusterVersionDAOMock.mockedClusterVersions = new ArrayList<ClusterVersionEntity>() {{
addAll(c1.getAllClusterVersions());
}};
c1.transitionHostVersionState(hostEntity3, rve1, stackId);
// Revert fields of static instance
ClusterVersionDAOMock.mockedClusterVersions = null;
verify(hostVersionDAOMock).merge(hostVersionCaptor.capture());
assertEquals(hostVersionCaptor.getValue().getState(), RepositoryVersionState.CURRENT);
}
/**
* Tests that an existing configuration can be successfully updated without
* creating a new version.
*
* @throws Exception
*/
@Test
public void testClusterConfigMergingWithoutNewVersion() throws Exception {
createDefaultCluster();
Cluster cluster = clusters.getCluster("c1");
ClusterEntity clusterEntity = clusterDAO.findByName("c1");
assertEquals(0, clusterEntity.getClusterConfigEntities().size());
final Config originalConfig = configFactory.createNew(cluster, "foo-site",
new HashMap<String, String>() {
{
put("one", "two");
}
}, new HashMap<String, Map<String, String>>());
originalConfig.setTag("version3");
originalConfig.persist();
cluster.addConfig(originalConfig);
ConfigGroup configGroup = configGroupFactory.createNew(cluster, "g1", "t1", "",
new HashMap<String, Config>() {
{
put("foo-site", originalConfig);
}
}, Collections.<Long, Host> emptyMap());
configGroup.persist();
cluster.addConfigGroup(configGroup);
clusterEntity = clusterDAO.findByName("c1");
assertEquals(1, clusterEntity.getClusterConfigEntities().size());
Map<String, Config> configsByType = cluster.getConfigsByType("foo-site");
Config config = configsByType.entrySet().iterator().next().getValue();
Map<String, String> properties = config.getProperties();
properties.put("three", "four");
config.setProperties(properties);
config.persist(false);
clusterEntity = clusterDAO.findByName("c1");
assertEquals(1, clusterEntity.getClusterConfigEntities().size());
ClusterConfigEntity clusterConfigEntity = clusterEntity.getClusterConfigEntities().iterator().next();
assertTrue(clusterConfigEntity.getData().contains("one"));
assertTrue(clusterConfigEntity.getData().contains("two"));
assertTrue(clusterConfigEntity.getData().contains("three"));
assertTrue(clusterConfigEntity.getData().contains("four"));
cluster.refresh();
clusterEntity = clusterDAO.findByName("c1");
assertEquals(1, clusterEntity.getClusterConfigEntities().size());
clusterConfigEntity = clusterEntity.getClusterConfigEntities().iterator().next();
assertTrue(clusterConfigEntity.getData().contains("one"));
assertTrue(clusterConfigEntity.getData().contains("two"));
assertTrue(clusterConfigEntity.getData().contains("three"));
assertTrue(clusterConfigEntity.getData().contains("four"));
}
/**
* Tests removing configurations and configuration mappings by stack.
*
* @throws Exception
*/
@Test
public void testRemoveConfigurations() throws Exception {
createDefaultCluster();
Cluster cluster = clusters.getCluster("c1");
ClusterEntity clusterEntity = clusterDAO.findByName("c1");
StackId stackId = cluster.getCurrentStackVersion();
StackId newStackId = new StackId("HDP-2.0.6");
StackEntity currentStack = stackDAO.find(stackId.getStackName(), stackId.getStackVersion());
StackEntity newStack = stackDAO.find(newStackId.getStackName(), newStackId.getStackVersion());
Assert.assertFalse(stackId.equals(newStackId));
String configType = "foo-type";
ClusterConfigEntity clusterConfig = new ClusterConfigEntity();
clusterConfig.setClusterEntity(clusterEntity);
clusterConfig.setConfigId(1L);
clusterConfig.setStack(currentStack);
clusterConfig.setTag("version-1");
clusterConfig.setData("{}");
clusterConfig.setType(configType);
clusterConfig.setTimestamp(1L);
clusterConfig.setVersion(1L);
clusterDAO.createConfig(clusterConfig);
clusterEntity.getClusterConfigEntities().add(clusterConfig);
clusterEntity = clusterDAO.merge(clusterEntity);
ClusterConfigEntity newClusterConfig = new ClusterConfigEntity();
newClusterConfig.setClusterEntity(clusterEntity);
newClusterConfig.setConfigId(2L);
newClusterConfig.setStack(newStack);
newClusterConfig.setTag("version-2");
newClusterConfig.setData("{}");
newClusterConfig.setType(configType);
newClusterConfig.setTimestamp(2L);
newClusterConfig.setVersion(2L);
clusterDAO.createConfig(newClusterConfig);
clusterEntity.getClusterConfigEntities().add(newClusterConfig);
clusterEntity = clusterDAO.merge(clusterEntity);
// config mapping set to 1
ClusterConfigMappingEntity configMapping = new ClusterConfigMappingEntity();
configMapping.setClusterEntity(clusterEntity);
configMapping.setCreateTimestamp(1L);
configMapping.setSelected(1);
configMapping.setTag("version-1");
configMapping.setType(configType);
configMapping.setUser("admin");
// new config mapping set to 0
ClusterConfigMappingEntity newConfigMapping = new ClusterConfigMappingEntity();
newConfigMapping.setClusterEntity(clusterEntity);
newConfigMapping.setCreateTimestamp(2L);
newConfigMapping.setSelected(0);
newConfigMapping.setTag("version-2");
newConfigMapping.setType(configType);
newConfigMapping.setUser("admin");
clusterDAO.persistConfigMapping(configMapping);
clusterDAO.persistConfigMapping(newConfigMapping);
clusterEntity.getConfigMappingEntities().add(configMapping);
clusterEntity.getConfigMappingEntities().add(newConfigMapping);
clusterEntity = clusterDAO.merge(clusterEntity);
// get back the cluster configs for the new stack
List<ClusterConfigEntity> clusterConfigs = clusterDAO.getAllConfigurations(
cluster.getClusterId(), newStackId);
Assert.assertEquals(1, clusterConfigs.size());
// remove the configs
cluster.removeConfigurations(newStackId);
clusterConfigs = clusterDAO.getAllConfigurations(cluster.getClusterId(), newStackId);
Assert.assertEquals(0, clusterConfigs.size());
}
}