Java tutorial
/** * 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()); } }