Repository: ambari Updated Branches: refs/heads/branch-2.1 4e54ac7fd -> b3ca260b1
AMBARI-11901. Installed Version Getting out of sync (dlysnichenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b3ca260b Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b3ca260b Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b3ca260b Branch: refs/heads/branch-2.1 Commit: b3ca260b15e31dba5f5c12bdaea25fcf3ba9dd0f Parents: 4e54ac7 Author: Lisnichenko Dmitro <[email protected]> Authored: Mon Jun 15 12:05:07 2015 +0300 Committer: Lisnichenko Dmitro <[email protected]> Committed: Mon Jun 15 12:05:49 2015 +0300 ---------------------------------------------------------------------- .../upgrade/HostVersionOutOfSyncListener.java | 48 ++++++++++++++++++-- .../HostVersionOutOfSyncListenerTest.java | 42 +++++++++++++++++ 2 files changed, 86 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/b3ca260b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListener.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListener.java index 1acb54b..b850774 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListener.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListener.java @@ -17,7 +17,9 @@ */ package org.apache.ambari.server.events.listeners.upgrade; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -25,6 +27,7 @@ import java.util.Set; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.EagerSingleton; +import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.events.HostAddedEvent; import org.apache.ambari.server.events.ServiceComponentInstalledEvent; import org.apache.ambari.server.events.ServiceInstalledEvent; @@ -37,6 +40,7 @@ import org.apache.ambari.server.orm.entities.HostVersionEntity; import org.apache.ambari.server.orm.entities.StackEntity; 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.RepositoryVersionState; import org.apache.ambari.server.state.ServiceComponent; import org.apache.ambari.server.state.StackId; @@ -75,6 +79,9 @@ public class HostVersionOutOfSyncListener { private Provider<Clusters> clusters; @Inject + private Provider<AmbariMetaInfo> ami; + + @Inject public HostVersionOutOfSyncListener(AmbariEventPublisher ambariEventPublisher) { ambariEventPublisher.register(this); } @@ -92,10 +99,22 @@ public class HostVersionOutOfSyncListener { hostVersionDAO.get().findByClusterAndHost(cluster.getClusterName(), event.getHostName()); StackId currentStackId = cluster.getCurrentStackVersion(); + for (HostVersionEntity hostVersionEntity : hostVersionEntities) { StackEntity hostStackEntity = hostVersionEntity.getRepositoryVersion().getStack(); StackId hostStackId = new StackId(hostStackEntity.getStackName(), hostStackEntity.getStackVersion()); + // If added components do not advertise version, it makes no sense to mark version OUT_OF_SYNC + // We perform check per-stack version, because component may be not versionAdvertised in current + // stack, but become versionAdvertised in some future (installed, but not yet upgraded to) stack + String serviceName = event.getServiceName(); + String componentName = event.getComponentName(); + ComponentInfo component = ami.get().getComponent(hostStackId.getStackName(), + hostStackId.getStackVersion(), serviceName, componentName); + if (!component.isVersionAdvertised()) { + continue; + } + if (currentStackId.equals(hostStackId) && hostVersionEntity.getState().equals(RepositoryVersionState.INSTALLED)) { hostVersionEntity.setState(RepositoryVersionState.OUT_OF_SYNC); @@ -122,19 +141,40 @@ public class HostVersionOutOfSyncListener { StackId currentStackId = cluster.getCurrentStackVersion(); Map<String, ServiceComponent> serviceComponents = cluster.getService(event.getServiceName()).getServiceComponents(); // Determine hosts that become OUT_OF_SYNC when adding components for new service - Set<String> affectedHosts = new HashSet<String>(); + Map<String, List<ServiceComponent>> affectedHosts = + new HashMap<String, List<ServiceComponent>>(); for (ServiceComponent component : serviceComponents.values()) { for (String hostname : component.getServiceComponentHosts().keySet()) { - affectedHosts.add(hostname); + if (! affectedHosts.containsKey(hostname)) { + affectedHosts.put(hostname, new ArrayList<ServiceComponent>()); + } + affectedHosts.get(hostname).add(component); } } - for (String hostName : affectedHosts) { + for (String hostName : affectedHosts.keySet()) { List<HostVersionEntity> hostVersionEntities = hostVersionDAO.get().findByClusterAndHost(cluster.getClusterName(), hostName); for (HostVersionEntity hostVersionEntity : hostVersionEntities) { StackEntity hostStackEntity = hostVersionEntity.getRepositoryVersion().getStack(); StackId hostStackId = new StackId(hostStackEntity.getStackName(), hostStackEntity.getStackVersion()); - + + // If added components do not advertise version, it makes no sense to mark version OUT_OF_SYNC + // We perform check per-stack version, because component may be not versionAdvertised in current + // stack, but become versionAdvertised in some future (installed, but not yet upgraded to) stack + boolean hasChangedComponentsWithVersions = false; + String serviceName = event.getServiceName(); + for (ServiceComponent comp : affectedHosts.get(hostName)) { + String componentName = comp.getName(); + ComponentInfo component = ami.get().getComponent(hostStackId.getStackName(), + hostStackId.getStackVersion(), serviceName, componentName); + if (component.isVersionAdvertised()) { + hasChangedComponentsWithVersions = true; + } + } + if (! hasChangedComponentsWithVersions) { + continue; + } + if (currentStackId.equals(hostStackId) && hostVersionEntity.getState().equals(RepositoryVersionState.INSTALLED)) { hostVersionEntity.setState(RepositoryVersionState.OUT_OF_SYNC); http://git-wip-us.apache.org/repos/asf/ambari/blob/b3ca260b/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListenerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListenerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListenerTest.java index 078d4c7..90e0b53 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListenerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListenerTest.java @@ -19,6 +19,7 @@ package org.apache.ambari.server.events.listeners.upgrade; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.ArrayList; @@ -224,6 +225,47 @@ public class HostVersionOutOfSyncListenerTest { assertTrue(atLeastOneOutOfSync); } + + /** + * When a service with components that don't advertise their versions + * is added to a cluster, all non-CURRENT host versions on + * all affected hosts (where host new components are installed) + * should NOT transition to OUT_OF_SYNC state + */ + @Test + public void testOnServiceEvent_component_does_not_advertise_version() throws AmbariException { + String INSTALLED_VERSION = "1.0-1000"; + StackId stackId = new StackId(this.stackId); + + createClusterAndHosts(INSTALLED_VERSION, stackId); + + //Add Ganglia service + List<String> hostList = new ArrayList<String>(); + hostList.add("h1"); + hostList.add("h2"); + hostList.add("h3"); + Map<String, List<Integer>> hdfsTopology = new HashMap<String, List<Integer>>(); + hdfsTopology.put("GANGLIA_SERVER", Collections.singletonList(0)); + List<Integer> monitorHosts = Arrays.asList(0, 1); + hdfsTopology.put("GANGLIA_MONITOR", new ArrayList<Integer>(monitorHosts)); + addService(c1, hostList, hdfsTopology, "GANGLIA"); + + // Check result + Set<String> changedHosts = new HashSet<String>(); + changedHosts.add("h1"); + changedHosts.add("h2"); + + List<HostVersionEntity> hostVersions = hostVersionDAO.findAll(); + + // Host version should not transition to OUT_OF_SYNC state + checkStackVersionState(stackId.getStackId(), INSTALLED_VERSION, RepositoryVersionState.INSTALLED); + for (HostVersionEntity hostVersionEntity : hostVersions) { + if (hostVersionEntity.getRepositoryVersion().getVersion().equals(INSTALLED_VERSION)) { + assertEquals(hostVersionEntity.getState(), RepositoryVersionState.INSTALLED); + } + } + } + /** * When a new service is added to a cluster with components, all INSTALLED host versions on * all affected hosts (where host new components are installed)
