[04/32] ambari git commit: AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades (ncole)

2017-08-14 Thread lpuskas
AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades 
(ncole)


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

Branch: refs/heads/feature-branch-AMBARI-21307
Commit: b23464936abad71f07e632ab6b0472b60a9ab0e3
Parents: c9ced87
Author: Nate Cole 
Authored: Tue Aug 8 12:26:35 2017 -0400
Committer: Nate Cole 
Committed: Wed Aug 9 11:12:15 2017 -0400

--
 .../ambari/server/state/UpgradeHelper.java  | 68 +++-
 .../state/stack/upgrade/ClusterGrouping.java|  4 ++
 .../server/state/stack/upgrade/Grouping.java| 15 +
 .../stack/upgrade/ServiceCheckGrouping.java | 60 ++---
 .../ambari/server/state/UpgradeHelperTest.java  | 68 +++-
 .../HDP/2.1.1/upgrades/upgrade_test_checks.xml  | 15 +
 6 files changed, 217 insertions(+), 13 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/ambari/blob/b2346493/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
--
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
index 7ed70de..464cb41 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
@@ -63,6 +63,8 @@ import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.Grouping;
 import org.apache.ambari.server.state.stack.upgrade.ManualTask;
 import org.apache.ambari.server.state.stack.upgrade.RestartTask;
+import org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping;
+import 
org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping.ServiceCheckStageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapperBuilder;
 import org.apache.ambari.server.state.stack.upgrade.StartTask;
@@ -77,6 +79,7 @@ import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -299,6 +302,7 @@ public class UpgradeHelper {
 Map> allTasks = 
upgradePack.getTasks();
 List groups = new ArrayList<>();
 
+UpgradeGroupHolder previousGroupHolder = null;
 for (Grouping group : upgradePack.getGroups(context.getDirection())) {
 
   // !!! grouping is not scoped to context
@@ -320,6 +324,7 @@ public class UpgradeHelper {
   groupHolder.skippable = group.skippable;
   groupHolder.supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
   groupHolder.allowRetry = group.allowRetry;
+  groupHolder.processingGroup = group.isProcessingGroup();
 
   // !!! all downgrades are skippable
   if (context.getDirection().isDowngrade()) {
@@ -496,9 +501,22 @@ public class UpgradeHelper {
   List proxies = builder.build(context);
 
   if (CollectionUtils.isNotEmpty(proxies)) {
+
 groupHolder.items = proxies;
 postProcess(context, groupHolder);
-groups.add(groupHolder);
+
+// !!! prevent service checks from running twice.  merge the stage 
wrappers
+if (ServiceCheckGrouping.class.isInstance(group)) {
+  if (null != previousGroupHolder && 
ServiceCheckGrouping.class.equals(previousGroupHolder.groupClass)) {
+mergeServiceChecks(groupHolder, previousGroupHolder);
+  } else {
+groups.add(groupHolder);
+  }
+} else {
+  groups.add(groupHolder);
+}
+
+previousGroupHolder = groupHolder;
   }
 }
 
@@ -518,10 +536,53 @@ public class UpgradeHelper {
   }
 }
 
+// !!! strip off the first service check if nothing has been processed
+Iterator iterator = groups.iterator();
+boolean canServiceCheck = false;
+while (iterator.hasNext()) {
+  UpgradeGroupHolder holder = iterator.next();
+
+  if (ServiceCheckGrouping.class.equals(holder.groupClass) && 
!canServiceCheck) {
+iterator.remove();
+  }
+
+  canServiceCheck |= holder.processingGroup;
+}
+
 return groups;
   }
 
   /**
+   * Merges two service check groups when they have been orchestrated 
back-to-back.
+   * @param newHolder   the "new" group holder, which was orchestrated after 
the "old" one
+   * 

[43/50] [abbrv] ambari git commit: AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades (ncole)

2017-08-10 Thread jonathanhurley
AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades 
(ncole)


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

Branch: refs/heads/branch-2.6
Commit: e33a274baeee088c3f2e3412ddad74ac85e66aad
Parents: 1f95e14
Author: Nate Cole 
Authored: Tue Aug 8 10:56:45 2017 -0400
Committer: Nate Cole 
Committed: Wed Aug 9 11:10:12 2017 -0400

--
 .../ambari/server/state/UpgradeHelper.java  | 68 ++-
 .../state/stack/upgrade/ClusterGrouping.java|  4 ++
 .../server/state/stack/upgrade/Grouping.java| 15 +
 .../stack/upgrade/ServiceCheckGrouping.java | 69 
 .../ambari/server/state/UpgradeHelperTest.java  | 68 ++-
 .../HDP/2.1.1/upgrades/upgrade_test_checks.xml  | 15 +
 6 files changed, 222 insertions(+), 17 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/ambari/blob/e33a274b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
--
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
index 0701296..e6ca728 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
@@ -63,6 +63,8 @@ import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.Grouping;
 import org.apache.ambari.server.state.stack.upgrade.ManualTask;
 import org.apache.ambari.server.state.stack.upgrade.RestartTask;
+import org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping;
+import 
org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping.ServiceCheckStageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapperBuilder;
 import org.apache.ambari.server.state.stack.upgrade.StartTask;
@@ -77,6 +79,7 @@ import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -299,6 +302,7 @@ public class UpgradeHelper {
 Map> allTasks = 
upgradePack.getTasks();
 List groups = new ArrayList<>();
 
+UpgradeGroupHolder previousGroupHolder = null;
 for (Grouping group : upgradePack.getGroups(context.getDirection())) {
 
   // !!! grouping is not scoped to context
@@ -320,6 +324,7 @@ public class UpgradeHelper {
   groupHolder.skippable = group.skippable;
   groupHolder.supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
   groupHolder.allowRetry = group.allowRetry;
+  groupHolder.processingGroup = group.isProcessingGroup();
 
   // !!! all downgrades are skippable
   if (context.getDirection().isDowngrade()) {
@@ -496,9 +501,22 @@ public class UpgradeHelper {
   List proxies = builder.build(context);
 
   if (CollectionUtils.isNotEmpty(proxies)) {
+
 groupHolder.items = proxies;
 postProcess(context, groupHolder);
-groups.add(groupHolder);
+
+// !!! prevent service checks from running twice.  merge the stage 
wrappers
+if (ServiceCheckGrouping.class.isInstance(group)) {
+  if (null != previousGroupHolder && 
ServiceCheckGrouping.class.equals(previousGroupHolder.groupClass)) {
+mergeServiceChecks(groupHolder, previousGroupHolder);
+  } else {
+groups.add(groupHolder);
+  }
+} else {
+  groups.add(groupHolder);
+}
+
+previousGroupHolder = groupHolder;
   }
 }
 
@@ -518,10 +536,53 @@ public class UpgradeHelper {
   }
 }
 
+// !!! strip off the first service check if nothing has been processed
+Iterator iterator = groups.iterator();
+boolean canServiceCheck = false;
+while (iterator.hasNext()) {
+  UpgradeGroupHolder holder = iterator.next();
+
+  if (ServiceCheckGrouping.class.equals(holder.groupClass) && 
!canServiceCheck) {
+iterator.remove();
+  }
+
+  canServiceCheck |= holder.processingGroup;
+}
+
 return groups;
   }
 
   /**
+   * Merges two service check groups when they have been orchestrated 
back-to-back.
+   * @param newHolder   the "new" group holder, which was orchestrated after 
the "old" one
+   * @param 

[40/50] [abbrv] ambari git commit: AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades (ncole)

2017-08-10 Thread ababiichuk
AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades 
(ncole)


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

Branch: refs/heads/branch-feature-logsearch-ui
Commit: b23464936abad71f07e632ab6b0472b60a9ab0e3
Parents: c9ced87
Author: Nate Cole 
Authored: Tue Aug 8 12:26:35 2017 -0400
Committer: Nate Cole 
Committed: Wed Aug 9 11:12:15 2017 -0400

--
 .../ambari/server/state/UpgradeHelper.java  | 68 +++-
 .../state/stack/upgrade/ClusterGrouping.java|  4 ++
 .../server/state/stack/upgrade/Grouping.java| 15 +
 .../stack/upgrade/ServiceCheckGrouping.java | 60 ++---
 .../ambari/server/state/UpgradeHelperTest.java  | 68 +++-
 .../HDP/2.1.1/upgrades/upgrade_test_checks.xml  | 15 +
 6 files changed, 217 insertions(+), 13 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/ambari/blob/b2346493/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
--
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
index 7ed70de..464cb41 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
@@ -63,6 +63,8 @@ import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.Grouping;
 import org.apache.ambari.server.state.stack.upgrade.ManualTask;
 import org.apache.ambari.server.state.stack.upgrade.RestartTask;
+import org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping;
+import 
org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping.ServiceCheckStageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapperBuilder;
 import org.apache.ambari.server.state.stack.upgrade.StartTask;
@@ -77,6 +79,7 @@ import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -299,6 +302,7 @@ public class UpgradeHelper {
 Map> allTasks = 
upgradePack.getTasks();
 List groups = new ArrayList<>();
 
+UpgradeGroupHolder previousGroupHolder = null;
 for (Grouping group : upgradePack.getGroups(context.getDirection())) {
 
   // !!! grouping is not scoped to context
@@ -320,6 +324,7 @@ public class UpgradeHelper {
   groupHolder.skippable = group.skippable;
   groupHolder.supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
   groupHolder.allowRetry = group.allowRetry;
+  groupHolder.processingGroup = group.isProcessingGroup();
 
   // !!! all downgrades are skippable
   if (context.getDirection().isDowngrade()) {
@@ -496,9 +501,22 @@ public class UpgradeHelper {
   List proxies = builder.build(context);
 
   if (CollectionUtils.isNotEmpty(proxies)) {
+
 groupHolder.items = proxies;
 postProcess(context, groupHolder);
-groups.add(groupHolder);
+
+// !!! prevent service checks from running twice.  merge the stage 
wrappers
+if (ServiceCheckGrouping.class.isInstance(group)) {
+  if (null != previousGroupHolder && 
ServiceCheckGrouping.class.equals(previousGroupHolder.groupClass)) {
+mergeServiceChecks(groupHolder, previousGroupHolder);
+  } else {
+groups.add(groupHolder);
+  }
+} else {
+  groups.add(groupHolder);
+}
+
+previousGroupHolder = groupHolder;
   }
 }
 
@@ -518,10 +536,53 @@ public class UpgradeHelper {
   }
 }
 
+// !!! strip off the first service check if nothing has been processed
+Iterator iterator = groups.iterator();
+boolean canServiceCheck = false;
+while (iterator.hasNext()) {
+  UpgradeGroupHolder holder = iterator.next();
+
+  if (ServiceCheckGrouping.class.equals(holder.groupClass) && 
!canServiceCheck) {
+iterator.remove();
+  }
+
+  canServiceCheck |= holder.processingGroup;
+}
+
 return groups;
   }
 
   /**
+   * Merges two service check groups when they have been orchestrated 
back-to-back.
+   * @param newHolder   the "new" group holder, which was orchestrated after 
the "old" one
+   * 

[1/2] ambari git commit: AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades (ncole)

2017-08-09 Thread ncole
Repository: ambari
Updated Branches:
  refs/heads/trunk c9ced8768 -> 78778ad57


AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades 
(ncole)


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

Branch: refs/heads/trunk
Commit: b23464936abad71f07e632ab6b0472b60a9ab0e3
Parents: c9ced87
Author: Nate Cole 
Authored: Tue Aug 8 12:26:35 2017 -0400
Committer: Nate Cole 
Committed: Wed Aug 9 11:12:15 2017 -0400

--
 .../ambari/server/state/UpgradeHelper.java  | 68 +++-
 .../state/stack/upgrade/ClusterGrouping.java|  4 ++
 .../server/state/stack/upgrade/Grouping.java| 15 +
 .../stack/upgrade/ServiceCheckGrouping.java | 60 ++---
 .../ambari/server/state/UpgradeHelperTest.java  | 68 +++-
 .../HDP/2.1.1/upgrades/upgrade_test_checks.xml  | 15 +
 6 files changed, 217 insertions(+), 13 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/ambari/blob/b2346493/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
--
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
index 7ed70de..464cb41 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
@@ -63,6 +63,8 @@ import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.Grouping;
 import org.apache.ambari.server.state.stack.upgrade.ManualTask;
 import org.apache.ambari.server.state.stack.upgrade.RestartTask;
+import org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping;
+import 
org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping.ServiceCheckStageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapperBuilder;
 import org.apache.ambari.server.state.stack.upgrade.StartTask;
@@ -77,6 +79,7 @@ import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -299,6 +302,7 @@ public class UpgradeHelper {
 Map> allTasks = 
upgradePack.getTasks();
 List groups = new ArrayList<>();
 
+UpgradeGroupHolder previousGroupHolder = null;
 for (Grouping group : upgradePack.getGroups(context.getDirection())) {
 
   // !!! grouping is not scoped to context
@@ -320,6 +324,7 @@ public class UpgradeHelper {
   groupHolder.skippable = group.skippable;
   groupHolder.supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
   groupHolder.allowRetry = group.allowRetry;
+  groupHolder.processingGroup = group.isProcessingGroup();
 
   // !!! all downgrades are skippable
   if (context.getDirection().isDowngrade()) {
@@ -496,9 +501,22 @@ public class UpgradeHelper {
   List proxies = builder.build(context);
 
   if (CollectionUtils.isNotEmpty(proxies)) {
+
 groupHolder.items = proxies;
 postProcess(context, groupHolder);
-groups.add(groupHolder);
+
+// !!! prevent service checks from running twice.  merge the stage 
wrappers
+if (ServiceCheckGrouping.class.isInstance(group)) {
+  if (null != previousGroupHolder && 
ServiceCheckGrouping.class.equals(previousGroupHolder.groupClass)) {
+mergeServiceChecks(groupHolder, previousGroupHolder);
+  } else {
+groups.add(groupHolder);
+  }
+} else {
+  groups.add(groupHolder);
+}
+
+previousGroupHolder = groupHolder;
   }
 }
 
@@ -518,10 +536,53 @@ public class UpgradeHelper {
   }
 }
 
+// !!! strip off the first service check if nothing has been processed
+Iterator iterator = groups.iterator();
+boolean canServiceCheck = false;
+while (iterator.hasNext()) {
+  UpgradeGroupHolder holder = iterator.next();
+
+  if (ServiceCheckGrouping.class.equals(holder.groupClass) && 
!canServiceCheck) {
+iterator.remove();
+  }
+
+  canServiceCheck |= holder.processingGroup;
+}
+
 return groups;
   }
 
   /**
+   * Merges two service check groups when they have been orchestrated 
back-to-back.
+   * @param newHolder   the "new" 

ambari git commit: AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades (ncole)

2017-08-09 Thread ncole
Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-21450 1f95e149b -> e33a274ba


AMBARI-21679. Service Checks Will Run Multiple Times In Patch/Service Upgrades 
(ncole)


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

Branch: refs/heads/branch-feature-AMBARI-21450
Commit: e33a274baeee088c3f2e3412ddad74ac85e66aad
Parents: 1f95e14
Author: Nate Cole 
Authored: Tue Aug 8 10:56:45 2017 -0400
Committer: Nate Cole 
Committed: Wed Aug 9 11:10:12 2017 -0400

--
 .../ambari/server/state/UpgradeHelper.java  | 68 ++-
 .../state/stack/upgrade/ClusterGrouping.java|  4 ++
 .../server/state/stack/upgrade/Grouping.java| 15 +
 .../stack/upgrade/ServiceCheckGrouping.java | 69 
 .../ambari/server/state/UpgradeHelperTest.java  | 68 ++-
 .../HDP/2.1.1/upgrades/upgrade_test_checks.xml  | 15 +
 6 files changed, 222 insertions(+), 17 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/ambari/blob/e33a274b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
--
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
index 0701296..e6ca728 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
@@ -63,6 +63,8 @@ import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.Grouping;
 import org.apache.ambari.server.state.stack.upgrade.ManualTask;
 import org.apache.ambari.server.state.stack.upgrade.RestartTask;
+import org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping;
+import 
org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping.ServiceCheckStageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapperBuilder;
 import org.apache.ambari.server.state.stack.upgrade.StartTask;
@@ -77,6 +79,7 @@ import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -299,6 +302,7 @@ public class UpgradeHelper {
 Map> allTasks = 
upgradePack.getTasks();
 List groups = new ArrayList<>();
 
+UpgradeGroupHolder previousGroupHolder = null;
 for (Grouping group : upgradePack.getGroups(context.getDirection())) {
 
   // !!! grouping is not scoped to context
@@ -320,6 +324,7 @@ public class UpgradeHelper {
   groupHolder.skippable = group.skippable;
   groupHolder.supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
   groupHolder.allowRetry = group.allowRetry;
+  groupHolder.processingGroup = group.isProcessingGroup();
 
   // !!! all downgrades are skippable
   if (context.getDirection().isDowngrade()) {
@@ -496,9 +501,22 @@ public class UpgradeHelper {
   List proxies = builder.build(context);
 
   if (CollectionUtils.isNotEmpty(proxies)) {
+
 groupHolder.items = proxies;
 postProcess(context, groupHolder);
-groups.add(groupHolder);
+
+// !!! prevent service checks from running twice.  merge the stage 
wrappers
+if (ServiceCheckGrouping.class.isInstance(group)) {
+  if (null != previousGroupHolder && 
ServiceCheckGrouping.class.equals(previousGroupHolder.groupClass)) {
+mergeServiceChecks(groupHolder, previousGroupHolder);
+  } else {
+groups.add(groupHolder);
+  }
+} else {
+  groups.add(groupHolder);
+}
+
+previousGroupHolder = groupHolder;
   }
 }
 
@@ -518,10 +536,53 @@ public class UpgradeHelper {
   }
 }
 
+// !!! strip off the first service check if nothing has been processed
+Iterator iterator = groups.iterator();
+boolean canServiceCheck = false;
+while (iterator.hasNext()) {
+  UpgradeGroupHolder holder = iterator.next();
+
+  if (ServiceCheckGrouping.class.equals(holder.groupClass) && 
!canServiceCheck) {
+iterator.remove();
+  }
+
+  canServiceCheck |= holder.processingGroup;
+}
+
 return groups;
   }
 
   /**
+   * Merges two service check groups when they have been orchestrated