AMBARI-18680. Add orchestration for HOST_ORDERED upgrades (ncole)

Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/343b4d8f
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/343b4d8f
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/343b4d8f

Branch: refs/heads/branch-dev-patch-upgrade
Commit: 343b4d8fec60d678349d9f1f68403d5063724ae6
Parents: 1f4221c
Author: Nate Cole <[email protected]>
Authored: Thu Nov 3 11:22:42 2016 -0400
Committer: Nate Cole <[email protected]>
Committed: Fri Nov 4 09:32:47 2016 -0400

----------------------------------------------------------------------
 .../server/state/cluster/ClustersImpl.java      |   1 -
 .../state/stack/upgrade/HostOrderGrouping.java  | 174 ++++++++++++++++++-
 .../stack/upgrade/StageWrapperBuilder.java      |   2 +-
 .../HDP/2.5/upgrades/host-ordered-upgrade.xml   |  10 +-
 .../src/main/resources/upgrade-pack.xsd         |   4 +-
 .../ambari/server/state/UpgradeHelperTest.java  | 151 ++++++++++++++--
 .../upgrades/upgrade_test_host_ordered.xml      |   2 +-
 .../upgrades/upgrade_test_host_ordered.xml      |   2 +-
 8 files changed, 307 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/343b4d8f/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
index 706a476..8e5f37e 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
@@ -938,6 +938,5 @@ public class ClustersImpl implements Clusters {
     Cluster currentCluster = clusterFactory.create(clusterEntity);
     clusters.put(clusterEntity.getClusterName(), currentCluster);
     clustersById.put(currentCluster.getClusterId(), currentCluster);
-    clusterHostMap.put(currentCluster.getClusterName(), 
Collections.newSetFromMap(new ConcurrentHashMap<Host, Boolean>()));
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/343b4d8f/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java
index f3dca62..b999f2f 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java
@@ -17,14 +17,24 @@
  */
 package org.apache.ambari.server.state.stack.upgrade;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
 import javax.xml.bind.annotation.XmlType;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.stack.HostsType;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.UpgradeContext;
 import org.apache.ambari.server.state.stack.UpgradePack.ProcessingComponent;
+import org.apache.commons.collections.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Marker group for Host-Ordered upgrades.
@@ -32,6 +42,8 @@ import 
org.apache.ambari.server.state.stack.UpgradePack.ProcessingComponent;
 @XmlType(name="host-order")
 public class HostOrderGrouping extends Grouping {
 
+  private static Logger LOG = LoggerFactory.getLogger(HostOrderGrouping.class);
+
   /**
    * Contains the ordered actions to schedule for this grouping.
    */
@@ -61,29 +73,175 @@ public class HostOrderGrouping extends Grouping {
    * Builder for host upgrades.
    */
   private static class HostBuilder extends StageWrapperBuilder {
+    private final List<HostOrderItem> hostOrderItems;
+
     /**
      * @param grouping the grouping
      */
     protected HostBuilder(HostOrderGrouping grouping) {
       super(grouping);
+      hostOrderItems = grouping.m_hostOrderItems;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void add(UpgradeContext upgradeContext, HostsType hostsType, String 
service,
         boolean clientOnly, ProcessingComponent pc, Map<String, String> 
params) {
-
+      // !!! NOOP, this called when there are services in the group, and there
+      // are none for host-ordered.
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public List<StageWrapper> build(UpgradeContext upgradeContext,
         List<StageWrapper> stageWrappers) {
-      return null;
+
+      List<StageWrapper> wrappers = new ArrayList<>(stageWrappers);
+
+      for (HostOrderItem orderItem : hostOrderItems) {
+        switch (orderItem.getType()) {
+          case HOST_UPGRADE:
+            wrappers.addAll(buildHosts(upgradeContext, 
orderItem.getActionItems()));
+            break;
+          case SERVICE_CHECK:
+            wrappers.addAll(buildServiceChecks(upgradeContext, 
orderItem.getActionItems()));
+            break;
+        }
+      }
+
+      return wrappers;
+    }
+
+    /**
+     * @param upgradeContext  the context
+     * @param hosts           the list of hostnames
+     * @return  the wrappers for a host
+     */
+    private List<StageWrapper> buildHosts(UpgradeContext upgradeContext, 
List<String> hosts) {
+      if (CollectionUtils.isEmpty(hosts)) {
+        return Collections.emptyList();
+      }
+
+      Cluster cluster = upgradeContext.getCluster();
+      List<StageWrapper> wrappers = new ArrayList<>();
+
+      for (String hostName : hosts) {
+
+        List<TaskWrapper> stopTasks = new ArrayList<>();
+        List<TaskWrapper> upgradeTasks = new ArrayList<>();
+
+        for (ServiceComponentHost sch : 
cluster.getServiceComponentHosts(hostName)) {
+          if (!isVersionAdvertised(upgradeContext, sch)) {
+            continue;
+          }
+
+          HostsType hostsType = upgradeContext.getResolver().getMasterAndHosts(
+              sch.getServiceName(), sch.getServiceComponentName());
+
+          // !!! if the hosts do not contain the current one, that means the 
component
+          // either doesn't exist or the downgrade is to the current target 
version.
+          // hostsType better not be null either, but check anyway
+          if (null != hostsType && !hostsType.hosts.contains(hostName)) {
+            LOG.warn("Host {} could not be orchestrated. Either there are no 
components for {}/{} " +
+                "or the target version {} is already current.",
+                hostName, sch.getServiceName(), sch.getServiceComponentName(), 
upgradeContext.getVersion());
+            continue;
+          }
+
+          if (!sch.isClientComponent()) {
+            stopTasks.add(new TaskWrapper(sch.getServiceName(), 
sch.getServiceComponentName(),
+                Collections.singleton(hostName), new StopTask()));
+          }
+
+          // !!! simple restart will do
+          upgradeTasks.add(new TaskWrapper(sch.getServiceName(), 
sch.getServiceComponentName(),
+              Collections.singleton(hostName), new RestartTask()));
+        }
+
+        if (stopTasks.isEmpty() && upgradeTasks.isEmpty()) {
+          LOG.info("No tasks for {}", hostName);
+          continue;
+        }
+
+        StageWrapper stopWrapper = new StageWrapper(StageWrapper.Type.STOP, 
String.format("Stop on %s", hostName),
+            stopTasks.toArray(new TaskWrapper[stopTasks.size()]));
+
+        StageWrapper startWrapper = new 
StageWrapper(StageWrapper.Type.RESTART, String.format("Start on %s", hostName),
+            upgradeTasks.toArray(new TaskWrapper[upgradeTasks.size()]));
+
+
+        String message = String.format("Please acknowledge that host %s has 
been prepared.", hostName);
+
+        ManualTask mt = new ManualTask();
+        mt.messages.add(message);
+
+        StageWrapper manualWrapper = new 
StageWrapper(StageWrapper.Type.SERVER_SIDE_ACTION, "Manual Confirmation",
+            new TaskWrapper(null, null, Collections.<String>emptySet(), mt));
+
+        wrappers.add(stopWrapper);
+        wrappers.add(manualWrapper);
+        // !!! TODO install_packages for hdp and conf-select changes.  
Hopefully these will no-op.
+        wrappers.add(startWrapper);
+      }
+
+      return wrappers;
+    }
+
+    /**
+     * @param upgradeContext  the context
+     * @param hosts           the list of hostnames
+     * @return  the wrappers for a host
+     */
+    private List<StageWrapper> buildServiceChecks(UpgradeContext 
upgradeContext, List<String> serviceChecks) {
+      if (CollectionUtils.isEmpty(serviceChecks)) {
+        return Collections.emptyList();
+      }
+
+      List<StageWrapper> wrappers = new ArrayList<>();
+
+      Cluster cluster = upgradeContext.getCluster();
+
+      for (String serviceName : serviceChecks) {
+        boolean hasService = false;
+        try {
+          cluster.getService(serviceName);
+          hasService = true;
+        } catch (Exception e) {
+          LOG.warn("Service {} not found to orchestrate", serviceName);
+        }
+
+        if (!hasService) {
+          continue;
+        }
+
+        StageWrapper wrapper = new 
StageWrapper(StageWrapper.Type.SERVICE_CHECK,
+            String.format("Service Check %s", 
upgradeContext.getServiceDisplay(serviceName)),
+            new TaskWrapper(serviceName, "", Collections.<String>emptySet(), 
new ServiceCheckTask()));
+
+        wrappers.add(wrapper);
+      }
+
+      return wrappers;
+    }
+
+
+    /**
+     * @param upgradeContext  the context
+     * @param sch             the host component
+     * @return                {@code true} if the host component advertises 
its version
+     */
+    private boolean isVersionAdvertised(UpgradeContext upgradeContext, 
ServiceComponentHost sch) {
+      StackId targetStack = upgradeContext.getTargetStackId();
+
+      try {
+        ComponentInfo component = 
upgradeContext.getAmbariMetaInfo().getComponent(
+            targetStack.getStackName(), targetStack.getStackVersion(),
+            sch.getServiceName(), sch.getServiceComponentName());
+
+        return component.isVersionAdvertised();
+      } catch (AmbariException e) {
+       LOG.warn("Could not determine if {}/{}/{} could be upgraded; returning 
false",
+           targetStack, sch.getServiceName(), sch.getServiceComponentName(), 
e);
+       return false;
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/343b4d8f/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
index 267133b..0b9cb3d 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
@@ -197,7 +197,7 @@ public abstract class StageWrapperBuilder {
    *   <li>When performing a downgrade, but no downgrade tasks exist, reuse 
the upgrade tasks</li>
    * </ul>
    * @param context     the upgrade context
-   * @param preTasks    {@code true} if loading pre-upgrade or pre-downgrade
+   * @param preTasks    {@code true} if loading pre-(upgrade|downgrade) or 
{@code false for post-(upgrade|downgrade)
    * @param pc          the processing component holding task definitions
    * @return A collection, potentially empty, of the tasks to run, which may 
contain either
    * pre or post tasks if they exist, and the order depends on whether it's an 
upgrade or downgrade.

http://git-wip-us.apache.org/repos/asf/ambari/blob/343b4d8f/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/host-ordered-upgrade.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/host-ordered-upgrade.xml
 
b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/host-ordered-upgrade.xml
index d59be50..37b75b8 100644
--- 
a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/host-ordered-upgrade.xml
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/host-ordered-upgrade.xml
@@ -74,14 +74,14 @@
       </execute-stage>
 
     </group>
-    
+     
     <!--
     In a HOST_ORDERED upgrade, this placeholder group is expanded by the 
number of hosts passed
     when creating the upgrade.  For starters, this will include "stop" 
commands, a manual
     verification task, and the "start" commands as indicated by the processing 
element.
     If we get to the point where we need additional flexibility, it will get 
added at that time.
     -->
-    <group xsi:type="host-order" name="HOST_ORDER" />
+    <group xsi:type="host-order" name="HOST_ORDER" title="Upgrade All Hosts"/>
          
     <!--
     After processing this group, the user-specified Kerberos descriptor will 
be updated to work with
@@ -441,12 +441,6 @@
     <service name="OOZIE">
       <component name="OOZIE_SERVER">
         <pre-upgrade>
-          <task xsi:type="execute" hosts="all" sequential="true">
-            <summary>Shut down all Oozie servers</summary>
-            <script>scripts/oozie_server.py</script>
-            <function>stop</function>
-          </task>
-
           <task xsi:type="server_action" 
class="org.apache.ambari.server.serveraction.upgrades.OozieConfigCalculation">
             <summary>Adjusting Oozie properties</summary>
           </task>

http://git-wip-us.apache.org/repos/asf/ambari/blob/343b4d8f/ambari-server/src/main/resources/upgrade-pack.xsd
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/upgrade-pack.xsd 
b/ambari-server/src/main/resources/upgrade-pack.xsd
index cfccb29..2871f05 100644
--- a/ambari-server/src/main/resources/upgrade-pack.xsd
+++ b/ambari-server/src/main/resources/upgrade-pack.xsd
@@ -143,8 +143,8 @@
         </xs:complexType>
       </xs:element>
     </xs:sequence>
-    <xs:attribute name="name" type="xs:string" />
-    <xs:attribute name="title" type="xs:string" />
+    <xs:attribute name="name" type="xs:string" use="required" />
+    <xs:attribute name="title" type="xs:string" use="required" />
   </xs:complexType>
   
   <xs:complexType name="cluster">

http://git-wip-us.apache.org/repos/asf/ambari/blob/343b4d8f/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
index 52e6513..78969e4 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
@@ -58,6 +58,9 @@ import 
org.apache.ambari.server.state.stack.upgrade.ConfigureTask;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.ExecuteTask;
 import org.apache.ambari.server.state.stack.upgrade.Grouping;
+import org.apache.ambari.server.state.stack.upgrade.HostOrderGrouping;
+import org.apache.ambari.server.state.stack.upgrade.HostOrderItem;
+import 
org.apache.ambari.server.state.stack.upgrade.HostOrderItem.HostOrderActionType;
 import org.apache.ambari.server.state.stack.upgrade.ManualTask;
 import org.apache.ambari.server.state.stack.upgrade.SecurityCondition;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapper;
@@ -527,7 +530,7 @@ public class UpgradeHelperTest {
     List<ServiceComponentHost> schs = cluster.getServiceComponentHosts("h4");
     assertEquals(1, schs.size());
     assertEquals(HostState.HEARTBEAT_LOST, schs.get(0).getHostState());
-    
+
     UpgradeContext context = new UpgradeContext(cluster, UpgradeType.ROLLING, 
Direction.UPGRADE, null);
     context.setSourceAndTargetStacks(HDP_21, HDP_21);
     context.setVersion(UPGRADE_VERSION);
@@ -571,7 +574,7 @@ public class UpgradeHelperTest {
     context.setSourceAndTargetStacks(HDP_21, HDP_21);
     context.setVersion(DOWNGRADE_VERSION);
     context.setResolver(m_masterHostResolver);
-    
+
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, 
context);
 
     assertEquals(7, groups.size());
@@ -613,7 +616,7 @@ public class UpgradeHelperTest {
     context.setSourceAndTargetStacks(HDP_21, HDP_21);
     context.setVersion(UPGRADE_VERSION);
     context.setResolver(m_masterHostResolver);
-    
+
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, 
context);
 
     assertEquals(1, groups.size());
@@ -1069,8 +1072,8 @@ public class UpgradeHelperTest {
     UpgradeContext context = new UpgradeContext(c, UpgradeType.ROLLING, 
Direction.UPGRADE, null);
     context.setSourceAndTargetStacks(HDP_21, HDP_22);
     context.setVersion(UPGRADE_VERSION);
-    context.setResolver(m_masterHostResolver);    
-    
+    context.setResolver(m_masterHostResolver);
+
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, 
context);
 
     assertEquals(7, groups.size());
@@ -1116,8 +1119,8 @@ public class UpgradeHelperTest {
     UpgradeContext context = new UpgradeContext(cluster, UpgradeType.ROLLING, 
Direction.DOWNGRADE, null);
     context.setSourceAndTargetStacks(HDP_21, HDP_21);
     context.setVersion(DOWNGRADE_VERSION);
-    context.setResolver(m_masterHostResolver);    
-    
+    context.setResolver(m_masterHostResolver);
+
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, 
context);
 
     assertEquals(5, groups.size());
@@ -1401,8 +1404,8 @@ public class UpgradeHelperTest {
     UpgradeContext context = new UpgradeContext(cluster, UpgradeType.ROLLING, 
Direction.UPGRADE, null);
     context.setSourceAndTargetStacks(HDP_21, HDP_21);
     context.setVersion(UPGRADE_VERSION);
-    context.setResolver(m_masterHostResolver);    
-    
+    context.setResolver(m_masterHostResolver);
+
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, 
context);
 
     // The upgrade pack has 2 tasks for Oozie in the pre-upgrade group.
@@ -1502,8 +1505,8 @@ public class UpgradeHelperTest {
     UpgradeContext context = new UpgradeContext(c, UpgradeType.ROLLING, 
Direction.DOWNGRADE, null);
     context.setSourceAndTargetStacks(HDP_21, HDP_21);
     context.setVersion(DOWNGRADE_VERSION);
-    context.setResolver(m_masterHostResolver);    
-    
+    context.setResolver(m_masterHostResolver);
+
     Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("HDP", 
"2.1.1");
     assertTrue(upgrades.containsKey("upgrade_direction"));
     UpgradePack upgrade = upgrades.get("upgrade_direction");
@@ -1855,8 +1858,8 @@ public class UpgradeHelperTest {
     UpgradeContext context = new UpgradeContext(c, UpgradeType.NON_ROLLING, 
Direction.UPGRADE, null);
     context.setSourceAndTargetStacks(stackId, stackId2);
     context.setVersion("2.2.0");
-    context.setResolver(resolver);    
-    
+    context.setResolver(resolver);
+
     List<UpgradeGroupHolder> groups = 
m_upgradeHelper.createSequence(upgradePack, context);
 
     assertEquals(1, groups.size());
@@ -1864,17 +1867,131 @@ public class UpgradeHelperTest {
     sch1.setVersion("2.1.1");
     sch2.setVersion("2.1.1");
     resolver = new MasterHostResolver(m_configHelper, c, "2.1.1");
-    
+
     context = new UpgradeContext(c, UpgradeType.NON_ROLLING, 
Direction.DOWNGRADE, null);
     context.setSourceAndTargetStacks(stackId2, stackId);
     context.setVersion("2.1.1");
-    context.setResolver(resolver);    
-    
+    context.setResolver(resolver);
+
     groups = m_upgradeHelper.createSequence(upgradePack, context);
 
     assertTrue(groups.isEmpty());
   }
 
+  @Test
+  public void testHostGroupingOrchestration() throws Exception {
+
+    Clusters clusters = injector.getInstance(Clusters.class);
+    ServiceFactory serviceFactory = injector.getInstance(ServiceFactory.class);
+
+    String clusterName = "c1";
+
+    StackId stackId = new StackId("HDP-2.1.1");
+    StackId stackId2 = new StackId("HDP-2.2.0");
+    clusters.addCluster(clusterName, stackId);
+    Cluster c = clusters.getCluster(clusterName);
+
+    helper.getOrCreateRepositoryVersion(stackId,
+        c.getDesiredStackVersion().getStackVersion());
+    helper.getOrCreateRepositoryVersion(stackId2,"2.2.0");
+
+    c.createClusterVersion(stackId,
+        c.getDesiredStackVersion().getStackVersion(), "admin",
+        RepositoryVersionState.INSTALLING);
+
+    for (int i = 0; i < 2; i++) {
+      String hostName = "h" + (i+1);
+      clusters.addHost(hostName);
+      Host host = clusters.getHost(hostName);
+
+      Map<String, String> hostAttributes = new HashMap<String, String>();
+      hostAttributes.put("os_family", "redhat");
+      hostAttributes.put("os_release_version", "6");
+
+      host.setHostAttributes(hostAttributes);
+
+      clusters.mapHostToCluster(hostName, clusterName);
+    }
+
+    // !!! add storm
+    c.addService(serviceFactory.createNew(c, "ZOOKEEPER"));
+
+    Service s = c.getService("ZOOKEEPER");
+    ServiceComponent sc = s.addServiceComponent("ZOOKEEPER_SERVER");
+    ServiceComponentHost sch1 = sc.addServiceComponentHost("h1");
+    ServiceComponentHost sch2 = sc.addServiceComponentHost("h2");
+
+    UpgradePack upgradePack = new UpgradePack() {
+      @Override
+      public List<Grouping> getGroups(Direction direction) {
+        HostOrderItem hostItem = new 
HostOrderItem(HostOrderActionType.HOST_UPGRADE,
+            Lists.newArrayList("h1", "h2"));
+        HostOrderItem checkItem = new 
HostOrderItem(HostOrderActionType.SERVICE_CHECK,
+            Lists.newArrayList("ZOOKEEPER", "STORM"));
+
+        Grouping g = new HostOrderGrouping();
+        ((HostOrderGrouping) g).setHostOrderItems(Lists.newArrayList(hostItem, 
checkItem));
+        g.title = "Some Title";
+        return Lists.newArrayList(g);
+      }
+
+      @Override
+      public Map<String, Map<String, ProcessingComponent>> getTasks() {
+        return new HashMap<>();
+      }
+    };
+
+    MasterHostResolver resolver = new MasterHostResolver(m_configHelper, c);
+    UpgradeContext context = new UpgradeContext(c, UpgradeType.HOST_ORDERED, 
Direction.UPGRADE, new HashMap<String, Object>());
+    context.setResolver(resolver);
+    context.setSourceAndTargetStacks(stackId, stackId2);
+    context.setVersion("2.2.0");
+    List<UpgradeGroupHolder> groups = 
m_upgradeHelper.createSequence(upgradePack, context);
+
+    assertEquals(1, groups.size());
+
+    UpgradeGroupHolder holder = groups.get(0);
+    assertEquals(7, holder.items.size());
+
+    for (int i = 0; i < 6; i++) {
+      StageWrapper w = holder.items.get(i);
+      if (i == 0 || i == 3) {
+        assertEquals(StageWrapper.Type.STOP, w.getType());
+      } else if (i == 1 || i == 4) {
+        assertEquals(StageWrapper.Type.SERVER_SIDE_ACTION, w.getType());
+      } else {
+        assertEquals(StageWrapper.Type.RESTART, w.getType());
+      }
+    }
+    assertEquals(StageWrapper.Type.SERVICE_CHECK, 
holder.items.get(6).getType());
+
+    // !!! test downgrade when all host components have failed
+    sch1.setVersion("2.1.1");
+    sch2.setVersion("2.1.1");
+    resolver = new MasterHostResolver(m_configHelper, c, "2.1.1");
+    context = new UpgradeContext(c, UpgradeType.HOST_ORDERED, 
Direction.DOWNGRADE, new HashMap<String, Object>());
+    context.setResolver(resolver);
+    context.setSourceAndTargetStacks(stackId2, stackId);
+    context.setVersion("2.1.1");
+    groups = m_upgradeHelper.createSequence(upgradePack, context);
+
+    assertEquals(1, groups.size());
+    assertEquals(1, groups.get(0).items.size());
+
+    // !!! test downgrade when one of the hosts had failed
+    sch1.setVersion("2.1.1");
+    sch2.setVersion("2.2.0");
+    resolver = new MasterHostResolver(m_configHelper, c, "2.1.1");
+    context = new UpgradeContext(c, UpgradeType.HOST_ORDERED, 
Direction.DOWNGRADE, new HashMap<String, Object>());
+    context.setResolver(resolver);
+    context.setSourceAndTargetStacks(stackId2, stackId);
+    context.setVersion("2.1.1");
+    groups = m_upgradeHelper.createSequence(upgradePack, context);
+
+    assertEquals(1, groups.size());
+    assertEquals(4, groups.get(0).items.size());
+  }
+
   /**
    * Tests that the {@link SecurityCondition} element correctly restricts the 
groups in
    * an upgrade.
@@ -1893,7 +2010,7 @@ public class UpgradeHelperTest {
     UpgradeContext context = new UpgradeContext(cluster, UpgradeType.ROLLING, 
Direction.UPGRADE, null);
     context.setSourceAndTargetStacks(HDP_22, HDP_22);
     context.setVersion(UPGRADE_VERSION);
-    context.setResolver(m_masterHostResolver);    
+    context.setResolver(m_masterHostResolver);
 
     // initially, no conditions should be met
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, 
context);

http://git-wip-us.apache.org/repos/asf/ambari/blob/343b4d8f/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test_host_ordered.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test_host_ordered.xml
 
b/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test_host_ordered.xml
index b7ffb89..6238c82 100644
--- 
a/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test_host_ordered.xml
+++ 
b/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test_host_ordered.xml
@@ -21,7 +21,7 @@
   <type>HOST_ORDERED</type>
   
   <order>
-    <group xsi:type="host-order" name="HOST_GROUP" />
+    <group xsi:type="host-order" name="HOST_GROUP" title="Host Group" />
     
     <group xsi:type="cluster" name="MANUAL_TASK" title="A manual task just for 
fun">
       <execute-stage title="You need to accept this task">

http://git-wip-us.apache.org/repos/asf/ambari/blob/343b4d8f/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_host_ordered.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_host_ordered.xml
 
b/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_host_ordered.xml
index 6a49472..020a49f 100644
--- 
a/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_host_ordered.xml
+++ 
b/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_host_ordered.xml
@@ -35,7 +35,7 @@
   </prerequisite-checks>
   <order>
 
-    <group xsi:type="host-order" name="HOST_GROUP" />
+    <group xsi:type="host-order" name="HOST_GROUP" title="Host Group" />
 
     <group name="ZOOKEEPER" title="Zookeeper">
       <skippable>true</skippable>

Reply via email to