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)

Reply via email to