@Test
  public void testHostGroupingOrchestration() throws Exception {
    Clusters clusters = injector.getInstance(Clusters.class);
    ServiceFactory serviceFactory = injector.getInstance(ServiceFactory.class);

    String clusterName = "c1";

    String version = "2.1.1.0-1234";
    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);

    RepositoryVersionEntity repoVersion211 = helper.getOrCreateRepositoryVersion(stackId, version);

    RepositoryVersionEntity repoVersion220 = helper.getOrCreateRepositoryVersion(stackId2, "2.2.0");

    // create 2 hosts
    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<>();
      hostAttributes.put("os_family", "redhat");
      hostAttributes.put("os_release_version", "6");

      host.setHostAttributes(hostAttributes);

      clusters.mapHostToCluster(hostName, clusterName);
    }

    // add ZK Server to both hosts, and then Nimbus to only 1 - this will test
    // how the HOU breaks out dependencies into stages
    c.addService(serviceFactory.createNew(c, "ZOOKEEPER", repoVersion211));
    c.addService(serviceFactory.createNew(c, "HBASE", repoVersion211));
    Service zookeeper = c.getService("ZOOKEEPER");
    Service hbase = c.getService("HBASE");
    ServiceComponent zookeeperServer = zookeeper.addServiceComponent("ZOOKEEPER_SERVER");
    ServiceComponentHost zookeeperServer1 = zookeeperServer.addServiceComponentHost("h1");
    ServiceComponentHost zookeeperServer2 = zookeeperServer.addServiceComponentHost("h2");
    ServiceComponent hbaseMaster = hbase.addServiceComponent("HBASE_MASTER");
    ServiceComponentHost hbaseMaster1 = hbaseMaster.addServiceComponentHost("h1");

    // !!! make a custom grouping
    HostOrderItem hostItem = new HostOrderItem(HostOrderActionType.HOST_UPGRADE,
        Lists.newArrayList("h1", "h2"));

    HostOrderItem checkItem = new HostOrderItem(HostOrderActionType.SERVICE_CHECK,
        Lists.newArrayList("ZOOKEEPER", "HBASE"));

    Grouping g = new HostOrderGrouping();
    ((HostOrderGrouping) g).setHostOrderItems(Lists.newArrayList(hostItem, checkItem));
    g.title = "Some Title";

    UpgradePack upgradePack = new UpgradePack();

    // !!! set the groups directly; allow the logic in getGroups(Direction) to happen
    Field field = UpgradePack.class.getDeclaredField("groups");
    field.setAccessible(true);
    field.set(upgradePack, Lists.newArrayList(g));

    field = UpgradePack.class.getDeclaredField("type" );
    field.setAccessible(true);
    field.set(upgradePack, UpgradeType.HOST_ORDERED);

    UpgradeContext context = getMockUpgradeContextNoReplay(c, Direction.UPGRADE,
        UpgradeType.HOST_ORDERED, repoVersion220);

    MasterHostResolver resolver = new MasterHostResolver(c, m_configHelper, context);
    expect(context.getResolver()).andReturn(resolver).anyTimes();
    replay(context);


    List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgradePack, context);

    assertEquals(1, groups.size());

    UpgradeGroupHolder holder = groups.get(0);
    assertEquals(9, holder.items.size());

    for (int i = 0; i < 7; i++) {
      StageWrapper w = holder.items.get(i);
      if (i == 0 || i == 4) {
        assertEquals(StageWrapper.Type.STOP, w.getType());
      } else if (i == 1 || i == 5) {
        assertEquals(StageWrapper.Type.SERVER_SIDE_ACTION, w.getType());
        assertEquals(1, w.getTasks().size());
        assertEquals(1, w.getTasks().get(0).getTasks().size());
        Task t = w.getTasks().get(0).getTasks().get(0);
        assertEquals(ManualTask.class, t.getClass());
        ManualTask mt = (ManualTask) t;
        assertNotNull(mt.structuredOut);
        assertTrue(mt.structuredOut.contains("type"));
        assertTrue(mt.structuredOut.contains(HostOrderItem.HostOrderActionType.HOST_UPGRADE.toString()));
        assertTrue(mt.structuredOut.contains("host"));
        assertTrue(mt.structuredOut.contains(i == 1 ? "h1" : "h2"));
      } else {
        assertEquals(StageWrapper.Type.RESTART, w.getType());
      }
    }

    assertEquals(StageWrapper.Type.SERVICE_CHECK, holder.items.get(7).getType());
    assertEquals(StageWrapper.Type.SERVICE_CHECK, holder.items.get(8).getType());

    // !!! test downgrade when all host components have failed
    zookeeperServer1.setVersion(repoVersion211.getVersion());
    zookeeperServer2.setVersion(repoVersion211.getVersion());
    hbaseMaster1.setVersion(repoVersion211.getVersion());

    context = getMockUpgradeContextNoReplay(c, Direction.DOWNGRADE, UpgradeType.HOST_ORDERED,
        repoVersion211);

    resolver = new MasterHostResolver(c, m_configHelper, context);
    expect(context.getResolver()).andReturn(resolver).anyTimes();
    replay(context);

    groups = m_upgradeHelper.createSequence(upgradePack, context);

    assertEquals(1, groups.size());
    assertEquals(2, groups.get(0).items.size());

    // !!! test downgrade when one of the hosts had failed
    zookeeperServer1.setVersion(repoVersion211.getVersion());
    zookeeperServer2.setVersion(repoVersion220.getVersion());
    hbaseMaster1.setVersion(repoVersion211.getVersion());

    context = getMockUpgradeContextNoReplay(c, Direction.DOWNGRADE, UpgradeType.HOST_ORDERED,
        repoVersion211);

    resolver = new MasterHostResolver(c, m_configHelper, context);
    expect(context.getResolver()).andReturn(resolver).anyTimes();
    replay(context);

    groups = m_upgradeHelper.createSequence(upgradePack, context);

    assertEquals(1, groups.size());
    assertEquals(5, groups.get(0).items.size());
  }
Tests {@link UpgradeType#HOST_ORDERED}, specifically that the orchestration
can properly expand the single {@link HostOrderGrouping} and create the
correct stages based on the dependencies of the components.

@throws Exception
ambari-server/src/test/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeHelperTest.java