Repository: ambari Updated Branches: refs/heads/branch-feature-AMBARI-21348 408212f58 -> 00cc41b94
AMBARI-21391 - Use the Correct Effective Stack ID for Commands During an Express Upgrade (jonathanhurley) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/00cc41b9 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/00cc41b9 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/00cc41b9 Branch: refs/heads/branch-feature-AMBARI-21348 Commit: 00cc41b948dd69f0d7a0431960706a0b1618cbf3 Parents: 408212f Author: Jonathan Hurley <[email protected]> Authored: Mon Jul 3 00:15:16 2017 -0400 Committer: Jonathan Hurley <[email protected]> Committed: Tue Jul 4 09:29:36 2017 -0400 ---------------------------------------------------------------------- .../internal/UpgradeResourceProvider.java | 139 +++++++++++++------ .../upgrades/FinalizeUpgradeAction.java | 46 +++--- .../upgrades/UpdateDesiredStackAction.java | 27 ++-- .../ambari/server/state/UpgradeContext.java | 35 ++--- .../server/state/cluster/ClusterImpl.java | 50 ++++--- .../state/stack/upgrade/HostOrderGrouping.java | 2 +- .../internal/UpgradeResourceProviderTest.java | 11 +- .../upgrades/UpgradeActionTest.java | 34 +---- .../ambari/server/state/UpgradeHelperTest.java | 1 - .../cluster/ClusterEffectiveVersionTest.java | 47 ++++--- 10 files changed, 217 insertions(+), 175 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java index 25e8cab..795e8d1 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java @@ -114,6 +114,7 @@ import org.apache.ambari.server.state.stack.upgrade.ServerSideActionTask; import org.apache.ambari.server.state.stack.upgrade.StageWrapper; import org.apache.ambari.server.state.stack.upgrade.Task; import org.apache.ambari.server.state.stack.upgrade.TaskWrapper; +import org.apache.ambari.server.state.stack.upgrade.UpdateStackGrouping; import org.apache.ambari.server.state.stack.upgrade.UpgradeScope; import org.apache.ambari.server.state.stack.upgrade.UpgradeType; import org.apache.ambari.server.state.svccomphost.ServiceComponentHostServerActionEvent; @@ -868,17 +869,29 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider } // !!! determine which stack to check for component isAdvertised - StackId componentStack = upgradeContext.getDirection() == Direction.UPGRADE ? - upgradeContext.getTargetStackId() : upgradeContext.getOriginalStackId(); + StackId componentStack = upgradeContext.getTargetStackId(); s_upgradeHelper.putComponentsToUpgradingState(repositoryVersion.getStackId(), repositoryVersion.getVersion(), targetComponents, componentStack); + // keep track of which stack to use when building commands - an express + // upgrade switches the stack half way through while other types move it in + // the beginning + StackId effectiveStackId = upgradeContext.getTargetStackId(); + if(upgradeContext.getType() == UpgradeType.NON_ROLLING ) { + effectiveStackId = upgradeContext.getSourceStackId(); + } + for (UpgradeGroupHolder group : groups) { boolean skippable = group.skippable; boolean supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure; boolean allowRetry = group.allowRetry; + if (upgradeContext.getType() == UpgradeType.NON_ROLLING + && UpdateStackGrouping.class.equals(group.groupClass)) { + effectiveStackId = upgradeContext.getTargetStackId(); + } + List<UpgradeItemEntity> itemEntities = new ArrayList<>(); for (StageWrapper wrapper : group.items) { if (wrapper.getType() == StageWrapper.Type.SERVER_SIDE_ACTION) { @@ -900,8 +913,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider itemEntities.add(itemEntity); injectVariables(configHelper, cluster, itemEntity); - makeServerSideStage(upgradeContext, req, itemEntity, (ServerSideActionTask) task, - skippable, supportsAutoSkipOnFailure, allowRetry, pack, configUpgradePack); + makeServerSideStage(upgradeContext, req, effectiveStackId, itemEntity, + (ServerSideActionTask) task, skippable, supportsAutoSkipOnFailure, allowRetry, + pack, configUpgradePack); } } } else { @@ -914,7 +928,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider injectVariables(configHelper, cluster, itemEntity); // upgrade items match a stage - createStage(upgradeContext, req, itemEntity, wrapper, skippable, + createStage(upgradeContext, req, effectiveStackId, itemEntity, wrapper, skippable, supportsAutoSkipOnFailure, allowRetry); } } @@ -1248,25 +1262,49 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider return requestStages; } + /** + * Builds a stage's commands. + * + * @param context + * the upgrade context (not {@code null}). + * @param request + * the request to add the new stage to (not {@code null}). + * @param effectiveStackId + * the stack ID to use when building the command. This will determine + * things like stack tools and version information added to the + * command (not {@code null}). + * @param entity + * the upgrade entity to add the new items to (not {@code null}). + * @param wrapper + * the encapsulation of a stage (not {@code null}). + * @param skippable + * {@code true} if the stage is skippable. + * @param supportsAutoSkipOnFailure + * {@code true} if a failure will skip the stage automatically. + * @param allowRetry + * {@code true} if the stage can be retried on failure. + * @throws AmbariException + */ private void createStage(UpgradeContext context, RequestStageContainer request, - UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, - boolean supportsAutoSkipOnFailure, boolean allowRetry) - throws AmbariException { + StackId effectiveStackId, UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, + boolean supportsAutoSkipOnFailure, boolean allowRetry) throws AmbariException { switch (wrapper.getType()) { case CONFIGURE: case START: case STOP: case RESTART: - makeCommandStage(context, request, entity, wrapper, skippable, supportsAutoSkipOnFailure, + makeCommandStage(context, request, effectiveStackId, entity, wrapper, skippable, + supportsAutoSkipOnFailure, allowRetry); break; case RU_TASKS: - makeActionStage(context, request, entity, wrapper, skippable, supportsAutoSkipOnFailure, + makeActionStage(context, request, effectiveStackId, entity, wrapper, skippable, + supportsAutoSkipOnFailure, allowRetry); break; case SERVICE_CHECK: - makeServiceCheckStage(context, request, entity, wrapper, skippable, + makeServiceCheckStage(context, request, effectiveStackId, entity, wrapper, skippable, supportsAutoSkipOnFailure, allowRetry); break; default: @@ -1290,9 +1328,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider } private void makeActionStage(UpgradeContext context, RequestStageContainer request, - UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, - boolean supportsAutoSkipOnFailure, boolean allowRetry) - throws AmbariException { + StackId effectiveStackId, UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, + boolean supportsAutoSkipOnFailure, boolean allowRetry) throws AmbariException { if (0 == wrapper.getHosts().size()) { throw new AmbariException( @@ -1343,7 +1380,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped()); ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext, - cluster, context.getEffectiveStackId()); + cluster, effectiveStackId); Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari", cluster.getClusterName(), cluster.getClusterId(), entity.getText(), jsons.getCommandParamsForStage(), @@ -1374,18 +1411,28 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider /** * Used to create a stage for restart, start, or stop. - * @param context Upgrade Context - * @param request Container for stage - * @param entity Upgrade Item - * @param wrapper Stage - * @param skippable Whether the item can be skipped - * @param allowRetry Whether the item is allowed to be retried + * + * @param context + * Upgrade Context + * @param request + * Container for stage + * @param effectiveStackId + * the stack ID to use when building the command. This will determine + * things like stack tools and version information added to the + * command (not {@code null}). + * @param entity + * Upgrade Item + * @param wrapper + * Stage + * @param skippable + * Whether the item can be skipped + * @param allowRetry + * Whether the item is allowed to be retried * @throws AmbariException */ private void makeCommandStage(UpgradeContext context, RequestStageContainer request, - UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, - boolean supportsAutoSkipOnFailure, boolean allowRetry) - throws AmbariException { + StackId effectiveStackId, UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, + boolean supportsAutoSkipOnFailure, boolean allowRetry) throws AmbariException { Cluster cluster = context.getCluster(); @@ -1425,7 +1472,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider actionContext.setMaintenanceModeHostExcluded(true); ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext, - cluster, context.getEffectiveStackId()); + cluster, effectiveStackId); Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari", cluster.getClusterName(), cluster.getClusterId(), entity.getText(), jsons.getCommandParamsForStage(), @@ -1457,9 +1504,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider } private void makeServiceCheckStage(UpgradeContext context, RequestStageContainer request, - UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, - boolean supportsAutoSkipOnFailure, boolean allowRetry) - throws AmbariException { + StackId effectiveStackId, UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable, + boolean supportsAutoSkipOnFailure, boolean allowRetry) throws AmbariException { List<RequestResourceFilter> filters = new ArrayList<>(); @@ -1486,7 +1532,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider actionContext.setMaintenanceModeHostExcluded(true); ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext, - cluster, context.getEffectiveStackId()); + cluster, effectiveStackId); Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari", cluster.getClusterName(), cluster.getClusterId(), entity.getText(), jsons.getCommandParamsForStage(), @@ -1511,20 +1557,31 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider /** * Creates a stage consisting of server side actions - * @param context upgrade context - * @param request upgrade request - * @param entity a single of upgrade - * @param task server-side task (if any) - * @param skippable if user can skip stage on failure - * @param allowRetry if user can retry running stage on failure - * @param configUpgradePack a runtime-generated config upgrade pack that - * contains all config change definitions from all stacks involved into - * upgrade + * + * @param context + * upgrade context + * @param request + * upgrade request + * @param effectiveStackId + * the stack ID to use when building the command. This will determine + * things like stack tools and version information added to the + * command (not {@code null}). + * @param entity + * a single of upgrade + * @param task + * server-side task (if any) + * @param skippable + * if user can skip stage on failure + * @param allowRetry + * if user can retry running stage on failure + * @param configUpgradePack + * a runtime-generated config upgrade pack that contains all config + * change definitions from all stacks involved into upgrade * @throws AmbariException */ private void makeServerSideStage(UpgradeContext context, RequestStageContainer request, - UpgradeItemEntity entity, ServerSideActionTask task, boolean skippable, - boolean supportsAutoSkipOnFailure, boolean allowRetry, + StackId effectiveStackId, UpgradeItemEntity entity, ServerSideActionTask task, + boolean skippable, boolean supportsAutoSkipOnFailure, boolean allowRetry, UpgradePack upgradePack, ConfigUpgradePack configUpgradePack) throws AmbariException { @@ -1616,7 +1673,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider actionContext.setMaintenanceModeHostExcluded(true); ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext, - cluster, context.getEffectiveStackId()); + cluster, effectiveStackId); Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari", cluster.getClusterName(), cluster.getClusterId(), stageText, jsons.getCommandParamsForStage(), http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java index 2fc492b..8a54679 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java @@ -346,7 +346,7 @@ public class FinalizeUpgradeAction extends AbstractServerAction { String clusterName = cluster.getClusterName(); StackId currentClusterStackId = cluster.getCurrentStackVersion(); - StackId originalStackId = context.getOriginalStackId(); + StackId sourceStackId = context.getSourceStackId(); StackId targetStackId = context.getTargetStackId(); RepositoryVersionEntity targetRepositoryVersion = context.getTargetRepositoryVersion(); @@ -356,43 +356,38 @@ public class FinalizeUpgradeAction extends AbstractServerAction { ClusterVersionEntity currentClusterVersion = cluster.getCurrentClusterVersion(); RepositoryVersionEntity currentRepoVersion = currentClusterVersion.getRepositoryVersion(); StackId currentRepoStackId = currentRepoVersion.getStackId(); - if (!currentRepoStackId.equals(originalStackId)) { + if (!currentRepoStackId.equals(targetStackId)) { String msg = String.format( - "The stack of cluster %s's CURRENT repo version is %s, yet the original stack id from the Stack Upgrade has a different value of %s. %s", - clusterName, currentRepoStackId.getStackId(), originalStackId.getStackId(), PREVIOUS_UPGRADE_NOT_COMPLETED_MSG); + "The stack of %s's CURRENT repository version is %s, yet the target stack for this downgrade is %s. %s", + clusterName, currentRepoStackId.getStackId(), targetStackId.getStackId(), + PREVIOUS_UPGRADE_NOT_COMPLETED_MSG); out.append(msg); err.append(msg); - throw new AmbariException("The source target stack doesn't match the cluster's CURRENT repo version's stack."); + throw new AmbariException( + "The target stack of this downgrade doesn't match the cluster's current stack."); } // This was a cross-stack upgrade, meaning that configurations were created that now need to be removed. - if (!originalStackId.equals(targetStackId)) { - out.append(String.format("Will remove configs since the original stack %s differs from the target stack %s " + - "that Ambari just downgraded from.", originalStackId.getStackId(), targetStackId.getStackId())); - cluster.removeConfigurations(targetStackId); - } + if (!sourceStackId.equals(targetStackId)) { + out.append(String.format( + "Configurations created for stack %s will be removed since this downgrade is to stack %s.", + sourceStackId.getStackId(), targetStackId.getStackId())); - // !!! find and make sure the cluster_version EXCEPT current are set back - out.append(String.format("Searching for current version for %s\n", - clusterName)); + out.append(System.lineSeparator()); + cluster.removeConfigurations(sourceStackId); + } ClusterVersionEntity clusterVersion = clusterVersionDAO.findByClusterAndStateCurrent(clusterName); if (null == clusterVersion) { throw new AmbariException("Could not find current cluster version"); } - out.append(String.format( - "Comparing downgrade version %s %s to current cluster version %s %s\n", targetStackId, - targetRepositoryVersion.getVersion(), clusterVersion.getRepositoryVersion().getStackId(), + "Comparing downgrade target version %s-%s to current cluster version %s-%s\n", + targetStackId.getStackName(), targetRepositoryVersion.getVersion(), + clusterVersion.getRepositoryVersion().getStackId().getStackName(), clusterVersion.getRepositoryVersion().getVersion())); - if (!targetStackId.equals(clusterVersion.getRepositoryVersion().getStackId())) { - throw new AmbariException( - String.format("Downgrade stack %s is not the current cluster stack of %s", - targetStackId, clusterVersion.getRepositoryVersion().getStackId())); - } - if (!StringUtils.equals(targetRepositoryVersion.getVersion(), clusterVersion.getRepositoryVersion().getVersion())) { throw new AmbariException( @@ -430,7 +425,7 @@ public class FinalizeUpgradeAction extends AbstractServerAction { Set<String> badHosts = new HashSet<>(); for (String badVersion : badVersions) { List<HostVersionEntity> hostVersions = hostVersionDAO.findByClusterStackAndVersion( - clusterName, targetStackId, badVersion); + clusterName, sourceStackId, badVersion); for (HostVersionEntity hostVersion : hostVersions) { badHosts.add(hostVersion.getHostName()); @@ -439,8 +434,8 @@ public class FinalizeUpgradeAction extends AbstractServerAction { } } - out.append(String.format("Found %d hosts not matching downgrade version: %s %s\n", - badHosts.size(), targetStackId, targetRepositoryVersion.getVersion())); + out.append(String.format("Found %d hosts not matching downgrade version: %s-%s\n", + badHosts.size(), targetStackId.getStackName(), targetRepositoryVersion.getVersion())); for (String badHost : badHosts) { List<HostComponentStateEntity> hostComponentStates = hostComponentStateDAO.findByHost(badHost); @@ -454,6 +449,7 @@ public class FinalizeUpgradeAction extends AbstractServerAction { // original value cluster.setDesiredStackVersion(currentClusterStackId); versionEventPublisher.publish(new StackUpgradeFinishEvent(cluster)); + // Reset upgrade state cluster.setUpgradeEntity(null); http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java index cca87bc..b071914 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java @@ -107,20 +107,18 @@ public class UpdateDesiredStackAction extends AbstractServerAction { StringBuilder err = new StringBuilder(); try { + StackId clusterDesiredStackId = cluster.getDesiredStackVersion(); StackId currentClusterStackId = cluster.getCurrentStackVersion(); + StackId targetStackId = toRepositoryVersion.getStackId(); + out.append(String.format("%s %s from %s-%s to %s-%s\n", direction.getVerb(true), clusterName, fromRepositoryVersion.getStackId().getStackName(), fromRepositoryVersion.getVersion(), - toRepositoryVersion.getStackId().getStackName(), + targetStackId.getStackName(), toRepositoryVersion.getVersion())); - out.append(String.format( - "Checking if can update the desired stack to %s. The cluster's current stack is %s\n", - toRepositoryVersion.getStackId(), currentClusterStackId.getStackId())); - // Ensure that the target stack id exist - StackId targetStackId = toRepositoryVersion.getStackId(); StackInfo desiredClusterStackInfo = ambariMetaInfo.getStack(targetStackId.getStackName(), targetStackId.getStackVersion()); if (null == desiredClusterStackInfo) { String message = String.format("Invalid target stack of \n", targetStackId.getStackId()); @@ -130,11 +128,10 @@ public class UpdateDesiredStackAction extends AbstractServerAction { } // Ensure that the current Stack Id coincides with the parameter that the user passed in. - StackId originalStackId = context.getOriginalStackId(); - if (!currentClusterStackId.equals(originalStackId)) { + if (direction == Direction.DOWNGRADE && !currentClusterStackId.equals(targetStackId)) { String message = String.format( - "The current cluster stack of %s doesn't match the original upgrade stack of %s", - currentClusterStackId, originalStackId); + "The cluster's current stack of %s doesn't match %s which is target stack of this downgrade", + currentClusterStackId, targetStackId); err.append(message); out.append(message); @@ -142,8 +139,10 @@ public class UpdateDesiredStackAction extends AbstractServerAction { } // Check for a no-op - if (currentClusterStackId.equals(targetStackId)) { - String message = String.format("Success! The cluster's desired stack was already set to %s\n", targetStackId.getStackId()); + if (clusterDesiredStackId.equals(targetStackId)) { + String message = String.format("The cluster's desired stack is already set to %s\n", + targetStackId.getStackId()); + out.append(message); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", out.toString(), err.toString()); } @@ -152,7 +151,9 @@ public class UpdateDesiredStackAction extends AbstractServerAction { // Also updates the desired stack version. UpgradeResourceProvider upgradeResourceProvider = new UpgradeResourceProvider(AmbariServer.getController()); upgradeResourceProvider.applyStackAndProcessConfigurations(context); - String message = String.format("Success! Set cluster's %s desired stack to %s.\n", clusterName, targetStackId.getStackId()); + String message = String.format("The cluster's desired stack was set to %s.\n", + targetStackId.getStackId()); + out.append(message); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", out.toString(), err.toString()); http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java index 1bb3d77..b97dc80 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java @@ -210,8 +210,15 @@ public class UpgradeContext { m_toRepositoryVersion = upgradeEntity.getToRepositoryVersion(); String upgradePackage = upgradeEntity.getUpgradePackage(); - StackId stackId = getOriginalStackId(); - Map<String, UpgradePack> packs = m_metaInfo.getUpgradePacks(stackId.getStackName(), stackId.getStackVersion()); + + StackId originalStackId = m_fromRepositoryVersion.getStackId(); + if (m_direction == Direction.DOWNGRADE) { + originalStackId = m_toRepositoryVersion.getStackId(); + } + + Map<String, UpgradePack> packs = m_metaInfo.getUpgradePacks(originalStackId.getStackName(), + originalStackId.getStackVersion()); + m_upgradePack = packs.get(upgradePackage); // since this constructor is initialized from an entity, then this map is @@ -344,25 +351,19 @@ public class UpgradeContext { } /** - * @return the originalStackId + * Gets the original stack ID that the cluster was on. For an upgrade, this + * returns the source stack ID. For a downgrade, this will return the target + * stack ID. + * + * @return the original stack ID. */ public StackId getOriginalStackId() { - if (m_direction == Direction.UPGRADE) { - return m_fromRepositoryVersion.getStackId(); - } else { - return m_toRepositoryVersion.getStackId(); + StackId originalStackId = getSourceStackId(); + if (m_direction == Direction.DOWNGRADE) { + originalStackId = getTargetStackId(); } - } - /** - * @return the effectiveStackId that is currently in use. - */ - public StackId getEffectiveStackId() { - if (m_type == UpgradeType.NON_ROLLING && m_direction == Direction.UPGRADE) { - return m_fromRepositoryVersion.getStackId(); - } - - return m_toRepositoryVersion.getStackId(); + return originalStackId; } /** http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java index c4f28b2..db67807 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java @@ -337,11 +337,11 @@ public class ClusterImpl implements Cluster { private Map<String, String> m_clusterPropertyCache = new ConcurrentHashMap<>(); /** - * A simple cache of the effective cluster version during an upgrade. Since - * calculation of this during an upgrade is not very quick or clean, it's good - * to cache it. + * A simple cache of the effective cluster version. This is mainly used during + * upgrades to prevent calculating the value repeatedly. calculation of this + * during an upgrade is not very quick or clean, it's good to cache it. */ - private final Map<Long, String> upgradeEffectiveVersionCache = new ConcurrentHashMap<>(); + private final Map<Long, Long> upgradeEffectiveVersionCache = new ConcurrentHashMap<>(); @Inject public ClusterImpl(@Assisted ClusterEntity clusterEntity, Injector injector, @@ -1018,7 +1018,6 @@ public class ClusterImpl implements Cluster { Collection<ClusterVersionEntity> clusterVersionEntities = getClusterEntity().getClusterVersionEntities(); for (ClusterVersionEntity clusterVersionEntity : clusterVersionEntities) { if (clusterVersionEntity.getState() == RepositoryVersionState.CURRENT) { - // TODO assuming there's only 1 current version, return 1st found, exception was expected in previous implementation return clusterVersionEntity; } } @@ -1037,39 +1036,44 @@ public class ClusterImpl implements Cluster { // see if this is in the cache first, and only walk the upgrade if it's not Long upgradeId = upgradeEntity.getId(); - String effectiveVersion = upgradeEffectiveVersionCache.get(upgradeId); - if (null == effectiveVersion) { - if(upgradeEntity.getUpgradeType() != UpgradeType.ROLLING){ - effectiveVersion = upgradeEntity.getToRepositoryVersion().getVersion(); + Long effectiveClusterVersionId = upgradeEffectiveVersionCache.get(upgradeId); + if (null == effectiveClusterVersionId) { + final ClusterVersionEntity effectiveClusterVersion; + + if (upgradeEntity.getUpgradeType() != UpgradeType.NON_ROLLING) { + RepositoryVersionEntity repositoryVersion = upgradeEntity.getToRepositoryVersion(); + effectiveClusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion( + clusterName, repositoryVersion.getStackId(), repositoryVersion.getVersion()); } else { if (upgradeEntity.getDirection() == Direction.UPGRADE) { boolean pastChangingStack = isNonRollingUpgradePastUpgradingStack(upgradeEntity); - effectiveVersion = pastChangingStack ? upgradeEntity.getToRepositoryVersion().getVersion() - : upgradeEntity.getFromRepositoryVersion().getVersion(); + RepositoryVersionEntity repositoryVersion = pastChangingStack + ? upgradeEntity.getToRepositoryVersion() : upgradeEntity.getFromRepositoryVersion(); + + effectiveClusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(clusterName, + repositoryVersion.getStackId(), repositoryVersion.getVersion()); } else { // Should be the lower value during a Downgrade. - effectiveVersion = upgradeEntity.getToRepositoryVersion().getVersion(); + RepositoryVersionEntity repositoryVersion = upgradeEntity.getToRepositoryVersion(); + effectiveClusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(clusterName, + repositoryVersion.getStackId(), repositoryVersion.getVersion()); } } // cache for later use - upgradeEffectiveVersionCache.put(upgradeId, effectiveVersion); + if (null != effectiveClusterVersion) { + effectiveClusterVersionId = effectiveClusterVersion.getId(); + upgradeEffectiveVersionCache.put(upgradeId, effectiveClusterVersionId); + } } - if (effectiveVersion == null) { + if (effectiveClusterVersionId == null) { throw new AmbariException( "Unable to determine which version to use during Stack Upgrade, effectiveVersion is null."); } - // Find the first cluster version whose repo matches the expected version. - Collection<ClusterVersionEntity> clusterVersionEntities = getClusterEntity().getClusterVersionEntities(); - for (ClusterVersionEntity clusterVersionEntity : clusterVersionEntities) { - if (clusterVersionEntity.getRepositoryVersion().getVersion().equals(effectiveVersion)) { - return clusterVersionEntity; - } - } - - return null; + // return cluster version which is "effective" given the upgrade state + return clusterVersionDAO.findByPK(effectiveClusterVersionId); } /** http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/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 9ca0d4e..b55d185 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 @@ -226,7 +226,7 @@ public class HostOrderGrouping extends Grouping { // create task wrappers List<TaskWrapper> taskWrappers = new ArrayList<>(); for (HostRoleCommand command : stageCommandsForHost) { - StackId stackId = upgradeContext.getEffectiveStackId(); + StackId stackId = upgradeContext.getTargetStackId(); String componentName = command.getRole().name(); String serviceName = null; http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java index 3a26164..b2c6b9f 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java @@ -1676,17 +1676,12 @@ public class UpgradeResourceProviderTest { public void testTimeouts() throws Exception { Cluster cluster = clusters.getCluster("c1"); - StackEntity stackEntity = stackDAO.find("HDP", "2.1.1"); - RepositoryVersionEntity repoVersionEntity = new RepositoryVersionEntity(); - repoVersionEntity.setDisplayName("My New Version 3"); - repoVersionEntity.setOperatingSystems(""); - repoVersionEntity.setStack(stackEntity); - repoVersionEntity.setVersion("2.2.2.3"); - repoVersionDao.create(repoVersionEntity); + cluster.createClusterVersion(repoVersionEntity2111.getStackId(), + repoVersionEntity2111.getVersion(), "admin", RepositoryVersionState.INSTALLED); Map<String, Object> requestProps = new HashMap<>(); requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1"); - requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION, "2.2.2.3"); + requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION, repoVersionEntity2111.getVersion()); requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test"); requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true"); requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name()); http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java index 46949ea..a303167 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java @@ -88,10 +88,6 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; @@ -112,8 +108,6 @@ public class UpgradeActionTest { private static final StackId HDP_21_STACK = new StackId("HDP-2.1.1"); private static final StackId HDP_22_STACK = new StackId("HDP-2.2.0"); - private static final String HDP_211_CENTOS6_REPO_URL = "http://s3.amazonaws.com/dev.hortonworks.com/HDP/centos6/2.x/BUILDS/2.1.1.0-118"; - private Injector m_injector; private AmbariManagementController amc; @@ -475,19 +469,15 @@ public class UpgradeActionTest { StackId targetStack = HDP_21_STACK; String sourceRepo = HDP_2_1_1_0; String targetRepo = HDP_2_1_1_1; - RepositoryVersionEntity sourceRepositoryVersion = repositoryVersion2110; - RepositoryVersionEntity targetRepositoryVersion = repositoryVersion2111; + RepositoryVersionEntity sourceRepositoryVersion = repositoryVersion2111; + RepositoryVersionEntity targetRepositoryVersion = repositoryVersion2110; makeDowngradeCluster(sourceStack, sourceRepo, targetStack, targetRepo); Cluster cluster = clusters.getCluster(clusterName); - createUpgrade(cluster, sourceRepositoryVersion, targetRepositoryVersion); + createUpgrade(cluster, "", Direction.DOWNGRADE, sourceRepositoryVersion, + targetRepositoryVersion); Map<String, String> commandParams = new HashMap<>(); - commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "downgrade"); - commandParams.put(FinalizeUpgradeAction.VERSION_KEY, sourceRepo); - commandParams.put(FinalizeUpgradeAction.ORIGINAL_STACK_KEY, sourceStack.getStackId()); - commandParams.put(FinalizeUpgradeAction.TARGET_STACK_KEY, targetStack.getStackId()); - ExecutionCommand executionCommand = new ExecutionCommand(); executionCommand.setCommandParams(commandParams); executionCommand.setClusterName(clusterName); @@ -601,9 +591,6 @@ public class UpgradeActionTest { CommandReport report = finalizeUpgradeAction.execute(null); assertNotNull(report); assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus()); - - // Verify the metainfo url - verifyBaseRepoURL(helper, cluster, host, "http://foo1"); } /** @@ -665,19 +652,6 @@ public class UpgradeActionTest { assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus()); } - private void verifyBaseRepoURL(AmbariCustomCommandExecutionHelper helper, Cluster cluster, Host host, String expectedRepoBaseURL) throws AmbariException { - String repoInfo = helper.getRepoInfo(cluster, host); - Gson gson = new Gson(); - JsonElement element = gson.fromJson(repoInfo, JsonElement.class); - assertTrue(element.isJsonArray()); - JsonArray list = JsonArray.class.cast(element); - assertEquals(1, list.size()); - - JsonObject o = list.get(0).getAsJsonObject(); - assertTrue(o.has("baseUrl")); - assertEquals(expectedRepoBaseURL, o.get("baseUrl").getAsString()); - } - @Test public void testFinalizeUpgradeAcrossStacks() throws Exception { StackId sourceStack = HDP_21_STACK; http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/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 8b1f4ef..6e27cba 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 @@ -2274,7 +2274,6 @@ public class UpgradeHelperTest { expect(context.getDirection()).andReturn(direction).anyTimes(); expect(context.getSourceRepositoryVersion()).andReturn(sourceRepositoryVersion).anyTimes(); expect(context.getTargetRepositoryVersion()).andReturn(repositoryVersion).anyTimes(); - expect(context.getEffectiveStackId()).andReturn(repositoryVersion.getStackId()).anyTimes(); expect(context.getTargetStackId()).andReturn(repositoryVersion.getStackId()).anyTimes(); expect(context.getAmbariMetaInfo()).andReturn(ambariMetaInfo).anyTimes(); expect(context.getHostRoleCommandFactory()).andStubReturn(injector.getInstance(HostRoleCommandFactory.class)); http://git-wip-us.apache.org/repos/asf/ambari/blob/00cc41b9/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterEffectiveVersionTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterEffectiveVersionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterEffectiveVersionTest.java index 9bb9b45..05f31d4 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterEffectiveVersionTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterEffectiveVersionTest.java @@ -19,7 +19,6 @@ package org.apache.ambari.server.state.cluster; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import javax.persistence.EntityManager; @@ -38,6 +37,7 @@ import org.apache.ambari.server.metadata.CachedRoleCommandOrderProvider; import org.apache.ambari.server.metadata.RoleCommandOrderProvider; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.dao.ClusterDAO; +import org.apache.ambari.server.orm.dao.ClusterVersionDAO; import org.apache.ambari.server.orm.dao.HostRoleCommandDAO; import org.apache.ambari.server.orm.entities.ClusterConfigEntity; import org.apache.ambari.server.orm.entities.ClusterEntity; @@ -59,6 +59,7 @@ import org.apache.ambari.server.state.ServiceComponentFactory; import org.apache.ambari.server.state.ServiceComponentHostFactory; import org.apache.ambari.server.state.ServiceFactory; import org.apache.ambari.server.state.ServiceInfo; +import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.state.UpgradeContextFactory; import org.apache.ambari.server.state.configgroup.ConfigGroupFactory; import org.apache.ambari.server.state.scheduler.RequestExecutionFactory; @@ -76,7 +77,6 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.springframework.security.crypto.password.PasswordEncoder; -import com.google.common.collect.Lists; import com.google.inject.Binder; import com.google.inject.Guice; import com.google.inject.Injector; @@ -92,6 +92,8 @@ import junit.framework.Assert; @PrepareForTest({ ClusterImpl.class }) public class ClusterEffectiveVersionTest extends EasyMockSupport { + private static final String CLUSTER_NAME = "c1"; + private Injector m_injector; private ClusterEntity m_clusterEntity; private Cluster m_cluster; @@ -145,8 +147,13 @@ public class ClusterEffectiveVersionTest extends EasyMockSupport { RepositoryVersionEntity repoVersion2300 = createNiceMock(RepositoryVersionEntity.class); RepositoryVersionEntity repoVersion2400 = createNiceMock(RepositoryVersionEntity.class); + StackId stackId23 = new StackId("HDP", "2.3"); + StackId stackId24 = new StackId("HDP", "2.4"); + EasyMock.expect(repoVersion2300.getVersion()).andReturn("2.3.0.0-1234").anyTimes(); + EasyMock.expect(repoVersion2300.getStackId()).andReturn(stackId23).anyTimes(); EasyMock.expect(repoVersion2400.getVersion()).andReturn("2.4.0.0-1234").anyTimes(); + EasyMock.expect(repoVersion2400.getStackId()).andReturn(stackId24).anyTimes(); UpgradeEntity upgradeEntity = createNiceMock(UpgradeEntity.class); EasyMock.expect(upgradeEntity.getId()).andReturn(1L).atLeastOnce(); @@ -155,11 +162,13 @@ public class ClusterEffectiveVersionTest extends EasyMockSupport { EasyMock.expect(upgradeEntity.getToRepositoryVersion()).andReturn(repoVersion2400).atLeastOnce(); ClusterVersionEntity clusterVersionUpgradingTo = createNiceMock(ClusterVersionEntity.class); - EasyMock.expect(clusterVersionUpgradingTo.getRepositoryVersion()).andReturn( - repoVersion2400).atLeastOnce(); + EasyMock.expect(clusterVersionUpgradingTo.getId()).andReturn(1L).atLeastOnce(); - List<ClusterVersionEntity> clusterVersionEntities = Lists.newArrayList(clusterVersionUpgradingTo); - EasyMock.expect(m_clusterEntity.getClusterVersionEntities()).andReturn(clusterVersionEntities).atLeastOnce(); + ClusterVersionDAO clusterVersionDAO = m_injector.getInstance(ClusterVersionDAO.class); + EasyMock.expect(clusterVersionDAO.findByClusterAndStackAndVersion(CLUSTER_NAME, stackId24, + "2.4.0.0-1234")).andReturn(clusterVersionUpgradingTo).once(); + + EasyMock.expect(clusterVersionDAO.findByPK(1L)).andReturn(clusterVersionUpgradingTo).once(); replayAll(); @@ -189,24 +198,29 @@ public class ClusterEffectiveVersionTest extends EasyMockSupport { RepositoryVersionEntity repoVersion2300 = createNiceMock(RepositoryVersionEntity.class); RepositoryVersionEntity repoVersion2400 = createNiceMock(RepositoryVersionEntity.class); + StackId stackId23 = new StackId("HDP", "2.3"); + StackId stackId24 = new StackId("HDP", "2.4"); + EasyMock.expect(repoVersion2300.getVersion()).andReturn("2.3.0.0-1234").anyTimes(); + EasyMock.expect(repoVersion2300.getStackId()).andReturn(stackId23).anyTimes(); EasyMock.expect(repoVersion2400.getVersion()).andReturn("2.4.0.0-1234").anyTimes(); + EasyMock.expect(repoVersion2400.getStackId()).andReturn(stackId24).anyTimes(); - // from/to are switched on downgrade UpgradeEntity upgradeEntity = createNiceMock(UpgradeEntity.class); EasyMock.expect(upgradeEntity.getId()).andReturn(1L).atLeastOnce(); EasyMock.expect(upgradeEntity.getUpgradeType()).andReturn(UpgradeType.NON_ROLLING).atLeastOnce(); - + EasyMock.expect(upgradeEntity.getDirection()).andReturn(Direction.DOWNGRADE).atLeastOnce(); EasyMock.expect(upgradeEntity.getFromRepositoryVersion()).andReturn(repoVersion2400).anyTimes(); EasyMock.expect(upgradeEntity.getToRepositoryVersion()).andReturn(repoVersion2300).atLeastOnce(); - EasyMock.expect(upgradeEntity.getDirection()).andReturn(Direction.DOWNGRADE).anyTimes(); - ClusterVersionEntity clusterVersionUpgradingTo = createNiceMock(ClusterVersionEntity.class); - EasyMock.expect(clusterVersionUpgradingTo.getRepositoryVersion()).andReturn( - repoVersion2300).atLeastOnce(); + ClusterVersionEntity clusterVersionDowngradingTo = createNiceMock(ClusterVersionEntity.class); + EasyMock.expect(clusterVersionDowngradingTo.getId()).andReturn(1L).atLeastOnce(); - List<ClusterVersionEntity> clusterVersionEntities = Lists.newArrayList(clusterVersionUpgradingTo); - EasyMock.expect(m_clusterEntity.getClusterVersionEntities()).andReturn(clusterVersionEntities).atLeastOnce(); + ClusterVersionDAO clusterVersionDAO = m_injector.getInstance(ClusterVersionDAO.class); + EasyMock.expect(clusterVersionDAO.findByClusterAndStackAndVersion(CLUSTER_NAME, stackId23, + "2.3.0.0-1234")).andReturn(clusterVersionDowngradingTo).once(); + + EasyMock.expect(clusterVersionDAO.findByPK(1L)).andReturn(clusterVersionDowngradingTo).once(); replayAll(); @@ -217,7 +231,7 @@ public class ClusterEffectiveVersionTest extends EasyMockSupport { Mockito.doReturn(currentClusterVersion).when(clusterSpy).getCurrentClusterVersion(); ClusterVersionEntity effectiveVersion = clusterSpy.getEffectiveClusterVersion(); - Assert.assertEquals(clusterVersionUpgradingTo, effectiveVersion); + Assert.assertEquals(clusterVersionDowngradingTo, effectiveVersion); verifyAll(); } @@ -236,7 +250,7 @@ public class ClusterEffectiveVersionTest extends EasyMockSupport { EasyMock.expect(stackEntity.getStackVersion()).andReturn("2.3").anyTimes(); EasyMock.expect(m_clusterEntity.getClusterId()).andReturn(1L).anyTimes(); - EasyMock.expect(m_clusterEntity.getClusterName()).andReturn("c1").anyTimes(); + EasyMock.expect(m_clusterEntity.getClusterName()).andReturn(CLUSTER_NAME).anyTimes(); EasyMock.expect(m_clusterEntity.getDesiredStack()).andReturn(stackEntity).anyTimes(); EasyMock.expect(m_clusterEntity.getClusterServiceEntities()).andReturn( new ArrayList<ClusterServiceEntity>()).anyTimes(); @@ -306,6 +320,7 @@ public class ClusterEffectiveVersionTest extends EasyMockSupport { } binder.bind(ClusterDAO.class).toInstance(createNiceMock(ClusterDAO.class)); + binder.bind(ClusterVersionDAO.class).toInstance(createNiceMock(ClusterVersionDAO.class)); } } }
