You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2017/07/13 19:14:44 UTC
[26/37] ambari git commit: AMBARI-21450. Initial cherry-picking for
feature branch (ncole)
http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/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 b97dc80..d2c0ea2 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
@@ -1,4 +1,4 @@
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -17,31 +17,70 @@
*/
package org.apache.ambari.server.state;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.VERSION;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_DIRECTION;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_FAIL_ON_CHECK_WARNINGS;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_HOST_ORDERED_HOSTS;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_PACK;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_REVERT_UPGRADE_ID;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_SKIP_FAILURES;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_SKIP_MANUAL_VERIFICATION;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_SKIP_SC_FAILURES;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_TYPE;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.ambari.annotations.Experimental;
import org.apache.ambari.annotations.ExperimentalFeature;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ServiceNotFoundException;
import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
import org.apache.ambari.server.agent.ExecutionCommand.KeyNames;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.controller.internal.AbstractControllerResourceProvider;
+import org.apache.ambari.server.controller.internal.PreUpgradeCheckResourceProvider;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
+import org.apache.ambari.server.orm.dao.UpgradeDAO;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
import org.apache.ambari.server.orm.entities.UpgradeEntity;
+import org.apache.ambari.server.orm.entities.UpgradeHistoryEntity;
import org.apache.ambari.server.stack.MasterHostResolver;
import org.apache.ambari.server.stageplanner.RoleGraphFactory;
+import org.apache.ambari.server.state.repository.VersionDefinitionXml;
+import org.apache.ambari.server.state.stack.PrereqCheckStatus;
import org.apache.ambari.server.state.stack.UpgradePack;
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.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.UpgradeScope;
import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.common.base.Objects;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.inject.Inject;
@@ -49,11 +88,14 @@ import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
/**
- * Used to hold various helper objects required to process an upgrade pack.
+ * The {@link UpgradeContext} is used to hold all information pertaining to an
+ * upgrade. It is initialized directly from an existing {@link UpgradeEntity} or
+ * from a request to create an upgrade/downgrade.
*/
public class UpgradeContext {
- public static final String COMMAND_PARAM_VERSION = VERSION;
+ private static final Logger LOG = LoggerFactory.getLogger(UpgradeContext.class);
+
public static final String COMMAND_PARAM_CLUSTER_NAME = "clusterName";
public static final String COMMAND_PARAM_DIRECTION = "upgrade_direction";
public static final String COMMAND_PARAM_UPGRADE_PACK = "upgrade_pack";
@@ -62,21 +104,6 @@ public class UpgradeContext {
public static final String COMMAND_PARAM_UPGRADE_TYPE = "upgrade_type";
public static final String COMMAND_PARAM_TASKS = "tasks";
public static final String COMMAND_PARAM_STRUCT_OUT = "structured_out";
- public static final String COMMAND_DOWNGRADE_FROM_VERSION = "downgrade_from_version";
-
- /**
- * The original "current" stack of the cluster before the upgrade started.
- * This is the same regardless of whether the current direction is
- * {@link Direction#UPGRADE} or {@link Direction#DOWNGRADE}.
- */
- public static final String COMMAND_PARAM_ORIGINAL_STACK = "original_stack";
-
- /**
- * The target upgrade stack before the upgrade started. This is the same
- * regardless of whether the current direction is {@link Direction#UPGRADE} or
- * {@link Direction#DOWNGRADE}.
- */
- public static final String COMMAND_PARAM_TARGET_STACK = "target_stack";
/**
* The cluster that the upgrade is for.
@@ -94,31 +121,42 @@ public class UpgradeContext {
final private UpgradeType m_type;
/**
- * The request parameters from the REST API for creating this upgrade.
+ * The upgrade pack for this upgrade.
*/
- final private Map<String, Object> m_upgradeRequestMap;
+ private UpgradePack m_upgradePack;
/**
- * The upgrade pack for this upgrade.
+ * Upgrades will always have a single version being upgraded to and downgrades
+ * will have a single version being downgraded from. This repository
+ * represents that version.
+ * <p/>
+ * When the direction is {@link Direction#UPGRADE}, this represents the target
+ * repository. <br/>
+ * When the direction is {@link Direction#DOWNGRADE}, this represents the
+ * repository being downgraded from.
*/
- private UpgradePack m_upgradePack;
+ private final RepositoryVersionEntity m_repositoryVersion;
/**
- * The source of the upgrade/downgrade.
+ * Resolves master components on hosts.
*/
- private final RepositoryVersionEntity m_fromRepositoryVersion;
+ private final MasterHostResolver m_resolver;
/**
- * The target of the upgrade/downgrade.
+ * A collection of hosts in the cluster which are unhealthy and will not
+ * participate in the upgrade.
*/
- private final RepositoryVersionEntity m_toRepositoryVersion;
+ private final List<ServiceComponentHost> m_unhealthy = new ArrayList<>();
+ /**
+ * Mapping of service name to display name.
+ */
+ private final Map<String, String> m_serviceNames = new HashMap<>();
- private MasterHostResolver m_resolver;
- private AmbariMetaInfo m_metaInfo;
- private List<ServiceComponentHost> m_unhealthy = new ArrayList<>();
- private Map<String, String> m_serviceNames = new HashMap<>();
- private Map<String, String> m_componentNames = new HashMap<>();
+ /**
+ * Mapping of component name to display name.
+ */
+ private final Map<String, String> m_componentNames = new HashMap<>();
/**
* {@code true} if slave/client component failures should be automatically
@@ -139,9 +177,27 @@ public class UpgradeContext {
*/
private boolean m_autoSkipManualVerification = false;
- private Set<String> m_supported = new HashSet<>();
+ /**
+ * A set of services which are included in this upgrade. If this is empty,
+ * then all cluster services are included.
+ */
+ private Set<String> m_services = new HashSet<>();
- private UpgradeScope m_scope = UpgradeScope.ANY;
+ /**
+ * A mapping of service to target repository. On an upgrade, this will be the
+ * same for all services. On a downgrade, this may be different for each
+ * service depending on which repository the service was on before the failed
+ * upgrade.
+ */
+ private final Map<String, RepositoryVersionEntity> m_targetRepositoryMap = new HashMap<>();
+
+ /**
+ * A mapping of service to source (from) repository. On an upgrade, this will
+ * be the current desired repository of every service. When downgrading, this
+ * will be the same for all components and will represent the value returned
+ * from {@link #getRepositoryVersion()}.
+ */
+ private final Map<String, RepositoryVersionEntity> m_sourceRepositoryMap = new HashMap<>();
/**
* Used by some {@link Grouping}s to generate commands. It is exposed here
@@ -164,29 +220,249 @@ public class UpgradeContext {
private Gson m_gson;
/**
- * Constructor.
- *
- * @param cluster
- * the cluster that the upgrade is for
- * @param type
- * the type of upgrade, either rolling or non_rolling
- * @param direction
- * the direction for the upgrade
- * @param upgradeRequestMap
- * the original map of paramters used to create the upgrade
+ * Used for looking up information about components and services.
+ */
+ @Inject
+ private AmbariMetaInfo m_metaInfo;
+
+ /**
+ * Used to suggest upgrade packs during creation of an upgrade context.
+ */
+ @Inject
+ private UpgradeHelper m_upgradeHelper;
+
+ /**
+ * Used to lookup the repository version from an ID.
+ */
+ @Inject
+ private RepositoryVersionDAO m_repoVersionDAO;
+
+ /**
+ * Used to lookup a prior upgrade by ID.
*/
+ @Inject
+ private UpgradeDAO m_upgradeDAO;
+
+ /**
+ * Used as a quick way to tell if the upgrade is to revert a patch.
+ */
+ private boolean m_isRevert = false;
+
+ /**
+ * Defines orchestration type. This is not the repository type when reverting a patch.
+ */
+ private RepositoryType m_orchestration = RepositoryType.STANDARD;
+
@AssistedInject
- public UpgradeContext(@Assisted Cluster cluster, @Assisted UpgradeType type,
- @Assisted Direction direction,
- @Assisted("fromRepositoryVersion") RepositoryVersionEntity fromRepositoryVersion,
- @Assisted("toRepositoryVersion") RepositoryVersionEntity toRepositoryVersion,
- @Assisted Map<String, Object> upgradeRequestMap) {
+ public UpgradeContext(@Assisted Cluster cluster,
+ @Assisted Map<String, Object> upgradeRequestMap, Gson gson, UpgradeHelper upgradeHelper,
+ UpgradeDAO upgradeDAO, RepositoryVersionDAO repoVersionDAO, ConfigHelper configHelper)
+ throws AmbariException {
+ // injected constructor dependencies
+ m_gson = gson;
+ m_upgradeHelper = upgradeHelper;
+ m_upgradeDAO = upgradeDAO;
+ m_repoVersionDAO = repoVersionDAO;
+
m_cluster = cluster;
- m_type = type;
- m_direction = direction;
- m_fromRepositoryVersion = fromRepositoryVersion;
- m_toRepositoryVersion = toRepositoryVersion;
- m_upgradeRequestMap = upgradeRequestMap;
+
+ // determine upgrade type (default is ROLLING)
+ String upgradeTypeProperty = (String) upgradeRequestMap.get(UPGRADE_TYPE);
+ if (StringUtils.isNotBlank(upgradeTypeProperty)) {
+ try {
+ m_type = UpgradeType.valueOf(upgradeRequestMap.get(UPGRADE_TYPE).toString());
+ } catch (Exception e) {
+ throw new AmbariException(String.format("Property %s has an incorrect value of %s.",
+ UPGRADE_TYPE, upgradeTypeProperty));
+ }
+ } else {
+ // default type
+ m_type= UpgradeType.ROLLING;
+ }
+
+ m_isRevert = upgradeRequestMap.containsKey(UPGRADE_REVERT_UPGRADE_ID);
+
+ if (m_isRevert) {
+ Long revertUpgradeId = Long.valueOf(upgradeRequestMap.get(UPGRADE_REVERT_UPGRADE_ID).toString());
+ UpgradeEntity revertUpgrade = m_upgradeDAO.findUpgrade(revertUpgradeId);
+
+ if (null == revertUpgrade) {
+ throw new AmbariException(String.format("Could not find Upgrade with id %s to revert.", revertUpgradeId));
+ }
+
+ if (revertUpgrade.getOrchestration() != RepositoryType.PATCH) {
+ throw new AmbariException("Can only revert upgrades that have been done as a patch.");
+ }
+
+ if (revertUpgrade.getDirection() != Direction.UPGRADE) {
+ throw new AmbariException("Can only revert successful upgrades, not downgrades.");
+ }
+
+ Set<RepositoryVersionEntity> priors = new HashSet<>();
+ for (UpgradeHistoryEntity history : revertUpgrade.getHistory()) {
+ priors.add(history.getFromReposistoryVersion());
+
+ // !!! build all service-specific
+ m_services.add(history.getServiceName());
+ m_sourceRepositoryMap.put(history.getServiceName(), history.getTargetRepositoryVersion());
+ m_targetRepositoryMap.put(history.getServiceName(), history.getFromReposistoryVersion());
+ }
+
+ if (priors.size() != 1) {
+ String message = String.format("Upgrade from %s could not be reverted as there is no single "
+ + " repository across services.", revertUpgrade.getRepositoryVersion().getVersion());
+
+ throw new AmbariException(message);
+ }
+
+ m_repositoryVersion = priors.iterator().next();
+
+ // !!! the version is used later in validators
+ upgradeRequestMap.put(UPGRADE_REPO_VERSION_ID, m_repositoryVersion.getId().toString());
+ // !!! use the same upgrade pack that was used in the upgrade being reverted
+ upgradeRequestMap.put(UPGRADE_PACK, revertUpgrade.getUpgradePackage());
+
+ // !!! direction can ONLY be an downgrade on revert
+ m_direction = Direction.DOWNGRADE;
+ m_orchestration = RepositoryType.PATCH;
+ } else {
+
+ // determine direction
+ String directionProperty = (String) upgradeRequestMap.get(UPGRADE_DIRECTION);
+ if (StringUtils.isEmpty(directionProperty)) {
+ throw new AmbariException(String.format("%s is required", UPGRADE_DIRECTION));
+ }
+
+ m_direction = Direction.valueOf(directionProperty);
+
+ // depending on the direction, we must either have a target repository or an upgrade we are downgrading from
+ switch(m_direction){
+ case UPGRADE:{
+ String repositoryVersionId = (String) upgradeRequestMap.get(UPGRADE_REPO_VERSION_ID);
+ if (null == repositoryVersionId) {
+ throw new AmbariException(
+ String.format("The property %s is required when the upgrade direction is %s",
+ UPGRADE_REPO_VERSION_ID, m_direction));
+ }
+
+ // depending on the repository, add services
+ m_repositoryVersion = m_repoVersionDAO.findByPK(Long.valueOf(repositoryVersionId));
+ m_orchestration = m_repositoryVersion.getType();
+
+ if (m_orchestration == RepositoryType.STANDARD) {
+ m_services.addAll(cluster.getServices().keySet());
+ } else {
+ try {
+ VersionDefinitionXml vdf = m_repositoryVersion.getRepositoryXml();
+ m_services.addAll(vdf.getAvailableServiceNames());
+
+ // if this is every true, then just stop the upgrade attempt and
+ // throw an exception
+ if (m_services.isEmpty()) {
+ String message = String.format(
+ "When using a VDF of type %s, the available services must be defined in the VDF",
+ m_repositoryVersion.getType());
+
+ throw new AmbariException(message);
+ }
+
+ } catch (Exception e) {
+ String msg = String.format(
+ "Could not parse version definition for %s. Upgrade will not proceed.",
+ m_repositoryVersion.getVersion());
+
+ throw new AmbariException(msg);
+ }
+ }
+
+ Set<String> installedServices = new HashSet<>();
+ // populate the target repository map for all services in the upgrade
+ for (String serviceName : m_services) {
+ try {
+ Service service = cluster.getService(serviceName);
+ m_sourceRepositoryMap.put(serviceName, service.getDesiredRepositoryVersion());
+ m_targetRepositoryMap.put(serviceName, m_repositoryVersion);
+ installedServices.add(serviceName);
+ } catch (ServiceNotFoundException e) {
+ LOG.warn("Skipping orchestraction for service {}, as it was defined to upgrade, but is not installed in cluster {}",
+ serviceName, cluster.getClusterName());
+ }
+ }
+
+ m_services = installedServices;
+
+ break;
+ }
+ case DOWNGRADE:{
+ UpgradeEntity upgrade = m_upgradeDAO.findLastUpgradeForCluster(
+ cluster.getClusterId(), Direction.UPGRADE);
+
+ m_repositoryVersion = upgrade.getRepositoryVersion();
+
+ // populate the repository maps for all services in the upgrade
+ for (UpgradeHistoryEntity history : upgrade.getHistory()) {
+ m_services.add(history.getServiceName());
+ m_sourceRepositoryMap.put(history.getServiceName(), m_repositoryVersion);
+ m_targetRepositoryMap.put(history.getServiceName(), history.getFromReposistoryVersion());
+ }
+
+ break;
+ }
+ default:
+ m_repositoryVersion = null;
+ break;
+ }
+ }
+
+
+ /**
+ * For the unit tests tests, there are multiple upgrade packs for the same
+ * type, so allow picking one of them. In prod, this is empty.
+ */
+ String preferredUpgradePackName = (String) upgradeRequestMap.get(UPGRADE_PACK);
+
+ @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES, comment="This is wrong")
+ String upgradePackFromVersion = cluster.getService(
+ m_services.iterator().next()).getDesiredRepositoryVersion().getVersion();
+
+ m_upgradePack = m_upgradeHelper.suggestUpgradePack(m_cluster.getClusterName(),
+ upgradePackFromVersion, m_repositoryVersion.getVersion(), m_direction, m_type,
+ preferredUpgradePackName);
+
+ // the validator will throw an exception if the upgrade request is not valid
+ UpgradeRequestValidator upgradeRequestValidator = buildValidator(m_type);
+ upgradeRequestValidator.validate(cluster, m_direction, m_type, m_upgradePack,
+ upgradeRequestMap);
+
+ // optionally skip failures - this can be supplied on either the request or
+ // in the upgrade pack explicitely, however the request will always override
+ // the upgrade pack if explicitely specified
+ boolean skipComponentFailures = m_upgradePack.isComponentFailureAutoSkipped();
+ boolean skipServiceCheckFailures = m_upgradePack.isServiceCheckFailureAutoSkipped();
+
+ // only override the upgrade pack if set on the request
+ if (upgradeRequestMap.containsKey(UPGRADE_SKIP_FAILURES)) {
+ skipComponentFailures = Boolean.parseBoolean(
+ (String) upgradeRequestMap.get(UPGRADE_SKIP_FAILURES));
+ }
+
+ // only override the upgrade pack if set on the request
+ if (upgradeRequestMap.containsKey(UPGRADE_SKIP_SC_FAILURES)) {
+ skipServiceCheckFailures = Boolean.parseBoolean(
+ (String) upgradeRequestMap.get(UPGRADE_SKIP_SC_FAILURES));
+ }
+
+ boolean skipManualVerification = false;
+ if (upgradeRequestMap.containsKey(UPGRADE_SKIP_MANUAL_VERIFICATION)) {
+ skipManualVerification = Boolean.parseBoolean(
+ (String) upgradeRequestMap.get(UPGRADE_SKIP_MANUAL_VERIFICATION));
+ }
+
+ m_autoSkipComponentFailures = skipComponentFailures;
+ m_autoSkipServiceCheckFailures = skipServiceCheckFailures;
+ m_autoSkipManualVerification = skipManualVerification;
+
+ m_resolver = new MasterHostResolver(m_cluster, configHelper, this);
}
/**
@@ -199,42 +475,38 @@ public class UpgradeContext {
*/
@AssistedInject
public UpgradeContext(@Assisted Cluster cluster, @Assisted UpgradeEntity upgradeEntity,
- AmbariMetaInfo ambariMetaInfo) {
-
+ AmbariMetaInfo ambariMetaInfo, ConfigHelper configHelper) {
m_metaInfo = ambariMetaInfo;
+
m_cluster = cluster;
m_type = upgradeEntity.getUpgradeType();
m_direction = upgradeEntity.getDirection();
-
- m_fromRepositoryVersion = upgradeEntity.getFromRepositoryVersion();
- m_toRepositoryVersion = upgradeEntity.getToRepositoryVersion();
-
- String upgradePackage = upgradeEntity.getUpgradePackage();
-
- StackId originalStackId = m_fromRepositoryVersion.getStackId();
- if (m_direction == Direction.DOWNGRADE) {
- originalStackId = m_toRepositoryVersion.getStackId();
+ m_repositoryVersion = upgradeEntity.getRepositoryVersion();
+
+ m_autoSkipComponentFailures = upgradeEntity.isComponentFailureAutoSkipped();
+ m_autoSkipServiceCheckFailures = upgradeEntity.isServiceCheckFailureAutoSkipped();
+
+ List<UpgradeHistoryEntity> allHistory = upgradeEntity.getHistory();
+ for (UpgradeHistoryEntity history : allHistory) {
+ String serviceName = history.getServiceName();
+ RepositoryVersionEntity sourceRepositoryVersion = history.getFromReposistoryVersion();
+ RepositoryVersionEntity targetRepositoryVersion = history.getTargetRepositoryVersion();
+ m_sourceRepositoryMap.put(serviceName, sourceRepositoryVersion);
+ m_targetRepositoryMap.put(serviceName, targetRepositoryVersion);
+ m_services.add(serviceName);
}
- Map<String, UpgradePack> packs = m_metaInfo.getUpgradePacks(originalStackId.getStackName(),
- originalStackId.getStackVersion());
-
+ @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES, comment = "This is wrong")
+ String upgradePackage = upgradeEntity.getUpgradePackage();
+ StackId stackId = m_repositoryVersion.getStackId();
+ Map<String, UpgradePack> packs = m_metaInfo.getUpgradePacks(stackId.getStackName(), stackId.getStackVersion());
m_upgradePack = packs.get(upgradePackage);
- // since this constructor is initialized from an entity, then this map is
- // not present
- m_upgradeRequestMap = Collections.emptyMap();
- }
+ m_resolver = new MasterHostResolver(m_cluster, configHelper, this);
+ m_orchestration = upgradeEntity.getOrchestration();
- /**
- * Gets the original mapping of key/value pairs from the request which created
- * the upgrade.
- *
- * @return the original mapping of key/value pairs from the request which
- * created the upgrade.
- */
- public Map<String, Object> getUpgradeRequest() {
- return m_upgradeRequestMap;
+ m_isRevert = upgradeEntity.getOrchestration() == RepositoryType.PATCH &&
+ upgradeEntity.getDirection() == Direction.DOWNGRADE;
}
/**
@@ -266,104 +538,146 @@ public class UpgradeContext {
}
/**
- * @return the target version for the upgrade
+ * Gets the version that components are being considered to be "coming from".
+ * <p/>
+ * With a {@link Direction#UPGRADE}, this value represent the services'
+ * desired repository. However, {@link Direction#DOWNGRADE} will use the same
+ * value for all services which is the version that the downgrade is coming
+ * from.
+ *
+ * @return the source version for the upgrade
*/
- public RepositoryVersionEntity getTargetRepositoryVersion() {
- return m_toRepositoryVersion;
+ public Map<String, RepositoryVersionEntity> getSourceVersions() {
+ return new HashMap<>(m_sourceRepositoryMap);
}
/**
- * @return the source version for the upgrade
+ * Gets the version that service is being considered to be "coming from".
+ * <p/>
+ * With a {@link Direction#UPGRADE}, this value represent the services'
+ * desired repository. However, {@link Direction#DOWNGRADE} will use the same
+ * value for all services which is the version that the downgrade is coming
+ * from.
+ *
+ * @return the source repository for the upgrade
*/
- public RepositoryVersionEntity getSourceRepositoryVersion() {
- return m_fromRepositoryVersion;
+ public RepositoryVersionEntity getSourceRepositoryVersion(String serviceName) {
+ return m_sourceRepositoryMap.get(serviceName);
}
/**
- * @return the direction of the upgrade
+ * Gets the version that service is being considered to be "coming from".
+ * <p/>
+ * With a {@link Direction#UPGRADE}, this value represent the services'
+ * desired repository. However, {@link Direction#DOWNGRADE} will use the same
+ * value for all services which is the version that the downgrade is coming
+ * from.
+ *
+ * @return the source repository for the upgrade
+ * @see #getSourceRepositoryVersion(String)
*/
- public Direction getDirection() {
- return m_direction;
+ public String getSourceVersion(String serviceName) {
+ RepositoryVersionEntity serviceSourceVersion = m_sourceRepositoryMap.get(serviceName);
+ return serviceSourceVersion.getVersion();
}
/**
- * @return the type of upgrade.
+ * Gets the version being upgraded to or downgraded to for all services
+ * participating. This is the version that the service will be on if the
+ * upgrade or downgrade succeeds.
+ * <p/>
+ * With a {@link Direction#UPGRADE}, all services should be targetting the
+ * same repository version. However, {@link Direction#DOWNGRADE} will target
+ * the original repository that the service was on.
+ *
+ * @return the target version for the upgrade
*/
- public UpgradeType getType() {
- return m_type;
+ public Map<String, RepositoryVersionEntity> getTargetVersions() {
+ return new HashMap<>(m_targetRepositoryMap);
}
/**
- * Sets the host resolver.
+ * Gets the repository being upgraded to or downgraded to for the given
+ * service. This is the version that the service will be on if the upgrade or
+ * downgrade succeeds.
+ * <p/>
+ * With a {@link Direction#UPGRADE}, all services should be targeting the
+ * same repository version. However, {@link Direction#DOWNGRADE} will target
+ * the original repository that the service was on.
*
- * @param resolver
- * the resolver that also references the required cluster
+ * @return the target repository for the upgrade
*/
- public void setResolver(MasterHostResolver resolver) {
- m_resolver = resolver;
+ public RepositoryVersionEntity getTargetRepositoryVersion(String serviceName) {
+ return m_targetRepositoryMap.get(serviceName);
}
/**
- * @return the resolver
+ * Gets the version being upgraded to or downgraded to for the given service.
+ * This is the version that the service will be on if the upgrade or downgrade
+ * succeeds.
+ * <p/>
+ * With a {@link Direction#UPGRADE}, all services should be targetting the
+ * same repository version. However, {@link Direction#DOWNGRADE} will target
+ * the original repository that the service was on.
+ *
+ * @return the target version for the upgrade
+ * @see #getTargetRepositoryVersion(String)
*/
- public MasterHostResolver getResolver() {
- return m_resolver;
+ public String getTargetVersion(String serviceName) {
+ RepositoryVersionEntity serviceTargetVersion = m_targetRepositoryMap.get(serviceName);
+ return serviceTargetVersion.getVersion();
}
/**
- * @return the metainfo for access to service definitions
+ * @return the direction of the upgrade
*/
- public AmbariMetaInfo getAmbariMetaInfo() {
- return m_metaInfo;
+ public Direction getDirection() {
+ return m_direction;
}
/**
- * @param metaInfo the metainfo for access to service definitions
+ * @return the type of upgrade.
*/
- public void setAmbariMetaInfo(AmbariMetaInfo metaInfo) {
- m_metaInfo = metaInfo;
+ public UpgradeType getType() {
+ return m_type;
}
/**
- * @param unhealthy a list of unhealthy host components
+ * @return the resolver
*/
- public void addUnhealthy(List<ServiceComponentHost> unhealthy) {
- m_unhealthy.addAll(unhealthy);
+ public MasterHostResolver getResolver() {
+ return m_resolver;
}
/**
- * Gets the target stack of the upgrade based on the target repository which
- * finalization will set.
- *
- * @return the target stack (never {@code null}).
+ * @return the metainfo for access to service definitions
*/
- public StackId getTargetStackId() {
- return m_toRepositoryVersion.getStackId();
+ public AmbariMetaInfo getAmbariMetaInfo() {
+ return m_metaInfo;
}
/**
- * Gets the current stack of the components participating in the upgrade.
- *
- * @return the source stack (never {@code null}).
+ * @param unhealthy a list of unhealthy host components
*/
- public StackId getSourceStackId() {
- return m_fromRepositoryVersion.getStackId();
+ public void addUnhealthy(List<ServiceComponentHost> unhealthy) {
+ m_unhealthy.addAll(unhealthy);
}
/**
- * 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.
+ * Gets the single repository version for the upgrade depending on the
+ * direction.
+ * <p/>
+ * If the direction is {@link Direction#UPGRADE} then this will return the
+ * target repository which every service will be on if the upgrade is
+ * finalized. <br/>
+ * If the direction is {@link Direction#DOWNGRADE} then this will return the
+ * repository from which the downgrade is coming from.
*
- * @return the original stack ID.
+ * @return the target repository version for this upgrade (never
+ * {@code null}).
*/
- public StackId getOriginalStackId() {
- StackId originalStackId = getSourceStackId();
- if (m_direction == Direction.DOWNGRADE) {
- originalStackId = getTargetStackId();
- }
-
- return originalStackId;
+ public RepositoryVersionEntity getRepositoryVersion() {
+ return m_repositoryVersion;
}
/**
@@ -417,17 +731,6 @@ public class UpgradeContext {
}
/**
- * Sets whether skippable components that failed are automatically skipped.
- *
- * @param autoSkipComponentFailures
- * {@code true} to automatically skip component failures which are
- * marked as skippable.
- */
- public void setAutoSkipComponentFailures(boolean autoSkipComponentFailures) {
- m_autoSkipComponentFailures = autoSkipComponentFailures;
- }
-
- /**
* Gets whether skippable service checks that failed are automatically
* skipped.
*
@@ -438,18 +741,6 @@ public class UpgradeContext {
}
/**
- * Sets whether skippable service checks that failed are automatically
- * skipped.
- *
- * @param autoSkipServiceCheckFailures
- * {@code true} to automatically skip service check failures which
- * are marked as being skippable.
- */
- public void setAutoSkipServiceCheckFailures(boolean autoSkipServiceCheckFailures) {
- m_autoSkipServiceCheckFailures = autoSkipServiceCheckFailures;
- }
-
- /**
* Gets whether manual verification tasks can be automatically skipped.
*
* @return the skipManualVerification
@@ -459,49 +750,43 @@ public class UpgradeContext {
}
/**
- * Sets whether manual verification checks are automatically skipped.
+ * Gets the services participating in the upgrade.
*
- * @param autoSkipManualVerification
- * {@code true} to automatically skip manual verification tasks.
- */
- public void setAutoSkipManualVerification(boolean autoSkipManualVerification) {
- m_autoSkipManualVerification = autoSkipManualVerification;
- }
-
- /**
- * Sets the service names that are supported by an upgrade. This is used for
- * {@link RepositoryType#PATCH} and {@link RepositoryType#SERVICE}.
- *
- * @param services the set of specific services
+ * @return the set of supported services. This collection should never be
+ * empty.
*/
@Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
- public void setSupportedServices(Set<String> services) {
- m_supported = services;
+ public Set<String> getSupportedServices() {
+ return Collections.unmodifiableSet(m_services);
}
/**
- * Gets if a service is supported. If there are no services marked for the context,
- * then ALL services are supported
- * @param serviceName the service name to check.
+ * Gets if a service is supported.
+ *
+ * @param serviceName
+ * the service name to check.
* @return {@code true} when the service is supported
*/
@Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
public boolean isServiceSupported(String serviceName) {
- if (m_supported.isEmpty() || m_supported.contains(serviceName)) {
+ return m_services.contains(serviceName);
+ }
+
+ @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES)
+ public boolean isScoped(UpgradeScope scope) {
+ if (scope == UpgradeScope.ANY) {
return true;
}
- return false;
- }
-
- @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
- public void setScope(UpgradeScope scope) {
- m_scope = scope;
- }
+ switch (m_orchestration) {
+ case PATCH:
+ case SERVICE:
+ return scope == UpgradeScope.PARTIAL;
+ case STANDARD:
+ return scope == UpgradeScope.COMPLETE;
+ }
- @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
- public boolean isScoped(UpgradeScope scope) {
- return m_scope.isScoped(scope);
+ return false;
}
/**
@@ -523,6 +808,18 @@ public class UpgradeContext {
}
/**
+ * Gets the repository type to determine if this upgrade is a complete upgrade
+ * or a service/patch. This value is not always the same as the repository version. In
+ * the case of a revert of a patch, the target repository may be of type STANDARD, but orchestration
+ * must be "like a patch".
+ *
+ * @return the orchestration type.
+ */
+ public RepositoryType getOrchestrationType() {
+ return m_orchestration;
+ }
+
+ /**
* Gets a map initialized with parameters required for upgrades to work. The
* following properties are already set:
* <ul>
@@ -557,4 +854,350 @@ public class UpgradeContext {
parameters.put(KeyNames.REFRESH_CONFIG_TAGS_BEFORE_EXECUTION, "true");
return parameters;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("direction", m_direction)
+ .add("type", m_type)
+ .add("target", m_repositoryVersion).toString();
+ }
+
+ /**
+ * Gets whether a downgrade is allowed for this upgrade. If the direction is
+ * {@link Direction#DOWNGRADE}, then this method always returns false.
+ * Otherwise it will consule {@link UpgradePack#isDowngradeAllowed()}.
+ *
+ * @return {@code true} of a downgrade is allowed for this upgrade,
+ * {@code false} otherwise.
+ */
+ public boolean isDowngradeAllowed() {
+ if (m_direction == Direction.DOWNGRADE) {
+ return false;
+ }
+
+ return m_upgradePack.isDowngradeAllowed();
+ }
+
+ /**
+ * @return
+ */
+ public boolean isPatchRevert() {
+ return m_isRevert;
+ }
+
+ /**
+ * Builds a chain of {@link UpgradeRequestValidator}s to ensure that the
+ * incoming request to create a new upgrade is valid.
+ *
+ * @param upgradeType
+ * the type of upgrade to build the validator for.
+ * @return the validator which can check to ensure that the properties are
+ * valid.
+ */
+ private UpgradeRequestValidator buildValidator(UpgradeType upgradeType){
+ UpgradeRequestValidator validator = new BasicUpgradePropertiesValidator();
+ UpgradeRequestValidator preReqValidator = new PreReqCheckValidator();
+ validator.setNextValidator(preReqValidator);
+
+ final UpgradeRequestValidator upgradeTypeValidator;
+ switch (upgradeType) {
+ case HOST_ORDERED:
+ upgradeTypeValidator = new HostOrderedUpgradeValidator();
+ break;
+ case NON_ROLLING:
+ case ROLLING:
+ default:
+ upgradeTypeValidator = null;
+ break;
+ }
+
+ preReqValidator.setNextValidator(upgradeTypeValidator);
+ return validator;
+ }
+
+ /**
+ * The {@link UpgradeRequestValidator} contains the logic to check for correct
+ * upgrade request properties and then pass the responsibility onto the next
+ * validator in the chain.
+ */
+ private abstract class UpgradeRequestValidator {
+ /**
+ * The next validator.
+ */
+ UpgradeRequestValidator m_nextValidator;
+
+ /**
+ * Sets the next validator in the chain.
+ *
+ * @param nextValidator
+ * the next validator to run, or {@code null} for none.
+ */
+ void setNextValidator(UpgradeRequestValidator nextValidator) {
+ m_nextValidator = nextValidator;
+ }
+
+ /**
+ * Validates the upgrade request from this point in the chain.
+ *
+ * @param cluster
+ * @param direction
+ * @param type
+ * @param upgradePack
+ * @param requestMap
+ * @throws AmbariException
+ */
+ final void validate(Cluster cluster, Direction direction, UpgradeType type,
+ UpgradePack upgradePack, Map<String, Object> requestMap) throws AmbariException {
+
+ // run this instance's check
+ check(cluster, direction, type, upgradePack, requestMap);
+
+ // pass along to the next
+ if (null != m_nextValidator) {
+ m_nextValidator.validate(cluster, direction, type, upgradePack, requestMap);
+ }
+ }
+
+ /**
+ * Checks to ensure that upgrade request is valid given the specific
+ * arguments.
+ *
+ * @param cluster
+ * @param direction
+ * @param type
+ * @param upgradePack
+ * @param requestMap
+ * @throws AmbariException
+ */
+ abstract void check(Cluster cluster, Direction direction, UpgradeType type,
+ UpgradePack upgradePack, Map<String, Object> requestMap) throws AmbariException;
+ }
+
+ /**
+ * The {@link BasicUpgradePropertiesValidator} ensures that the basic required
+ * properties are present on the upgrade request.
+ */
+ private final class BasicUpgradePropertiesValidator extends UpgradeRequestValidator {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void check(Cluster cluster, Direction direction, UpgradeType type,
+ UpgradePack upgradePack, Map<String, Object> requestMap) throws AmbariException {
+
+ if (direction == Direction.UPGRADE) {
+ String repositoryVersionId = (String) requestMap.get(UPGRADE_REPO_VERSION_ID);
+ if (StringUtils.isBlank(repositoryVersionId)) {
+ throw new AmbariException(
+ String.format("%s is required for upgrades", UPGRADE_REPO_VERSION_ID));
+ }
+ }
+ }
+ }
+
+ /**
+ * The {@link PreReqCheckValidator} ensures that the upgrade pre-requisite
+ * checks have passed.
+ */
+ private final class PreReqCheckValidator extends UpgradeRequestValidator {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ void check(Cluster cluster, Direction direction, UpgradeType type, UpgradePack upgradePack,
+ Map<String, Object> requestMap) throws AmbariException {
+
+ String repositoryVersionId = (String) requestMap.get(UPGRADE_REPO_VERSION_ID);
+ boolean skipPrereqChecks = Boolean.parseBoolean((String) requestMap.get(UPGRADE_SKIP_PREREQUISITE_CHECKS));
+ boolean failOnCheckWarnings = Boolean.parseBoolean((String) requestMap.get(UPGRADE_FAIL_ON_CHECK_WARNINGS));
+ String preferredUpgradePack = requestMap.containsKey(UPGRADE_PACK) ? (String) requestMap.get(UPGRADE_PACK) : null;
+
+ // verify that there is not an upgrade or downgrade that is in progress or suspended
+ UpgradeEntity existingUpgrade = cluster.getUpgradeInProgress();
+ if (null != existingUpgrade) {
+ throw new AmbariException(
+ String.format("Unable to perform %s as another %s (request ID %s) is in progress.",
+ direction.getText(false), existingUpgrade.getDirection().getText(false),
+ existingUpgrade.getRequestId()));
+ }
+
+ // skip this check if it's a downgrade or we are instructed to skip it
+ if (direction.isDowngrade() || skipPrereqChecks) {
+ return;
+ }
+
+ RepositoryVersionEntity repositoryVersion = m_repoVersionDAO.findByPK(
+ Long.valueOf(repositoryVersionId));
+
+ // Validate pre-req checks pass
+ PreUpgradeCheckResourceProvider provider = (PreUpgradeCheckResourceProvider) AbstractControllerResourceProvider.getResourceProvider(
+ Resource.Type.PreUpgradeCheck);
+
+ Predicate preUpgradeCheckPredicate = new PredicateBuilder().property(
+ PreUpgradeCheckResourceProvider.UPGRADE_CHECK_CLUSTER_NAME_PROPERTY_ID).equals(cluster.getClusterName()).and().property(
+ PreUpgradeCheckResourceProvider.UPGRADE_CHECK_REPOSITORY_VERSION_PROPERTY_ID).equals(repositoryVersion.getVersion()).and().property(
+ PreUpgradeCheckResourceProvider.UPGRADE_CHECK_FOR_REVERT_PROPERTY_ID).equals(m_isRevert).and().property(
+ PreUpgradeCheckResourceProvider.UPGRADE_CHECK_UPGRADE_TYPE_PROPERTY_ID).equals(type).and().property(
+ PreUpgradeCheckResourceProvider.UPGRADE_CHECK_UPGRADE_PACK_PROPERTY_ID).equals(preferredUpgradePack).toPredicate();
+
+ Request preUpgradeCheckRequest = PropertyHelper.getReadRequest();
+
+ Set<Resource> preUpgradeCheckResources;
+ try {
+ preUpgradeCheckResources = provider.getResources(
+ preUpgradeCheckRequest, preUpgradeCheckPredicate);
+ } catch (NoSuchResourceException|SystemException|UnsupportedPropertyException|NoSuchParentResourceException e) {
+ throw new AmbariException(
+ String.format("Unable to perform %s. Prerequisite checks could not be run",
+ direction.getText(false), e));
+ }
+
+ List<Resource> failedResources = new LinkedList<>();
+ if (preUpgradeCheckResources != null) {
+ for (Resource res : preUpgradeCheckResources) {
+ PrereqCheckStatus prereqCheckStatus = (PrereqCheckStatus) res.getPropertyValue(
+ PreUpgradeCheckResourceProvider.UPGRADE_CHECK_STATUS_PROPERTY_ID);
+
+ if (prereqCheckStatus == PrereqCheckStatus.FAIL
+ || (failOnCheckWarnings && prereqCheckStatus == PrereqCheckStatus.WARNING)) {
+ failedResources.add(res);
+ }
+ }
+ }
+
+ if (!failedResources.isEmpty()) {
+ throw new AmbariException(
+ String.format("Unable to perform %s. Prerequisite checks failed %s",
+ direction.getText(false), m_gson.toJson(failedResources)));
+ }
+ }
+ }
+
+ /**
+ * Ensures that for {@link UpgradeType#HOST_ORDERED}, the properties supplied
+ * are valid.
+ */
+ @SuppressWarnings("unchecked")
+ private final class HostOrderedUpgradeValidator extends UpgradeRequestValidator {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ void check(Cluster cluster, Direction direction, UpgradeType type, UpgradePack upgradePack,
+ Map<String, Object> requestMap) throws AmbariException {
+
+ String skipFailuresRequestProperty = (String) requestMap.get(UPGRADE_SKIP_FAILURES);
+ if (Boolean.parseBoolean(skipFailuresRequestProperty)) {
+ throw new AmbariException(
+ String.format("The %s property is not valid when creating a %s upgrade.",
+ UPGRADE_SKIP_FAILURES, UpgradeType.HOST_ORDERED));
+ }
+
+ String skipManualVerification = (String) requestMap.get(UPGRADE_SKIP_MANUAL_VERIFICATION);
+ if (Boolean.parseBoolean(skipManualVerification)) {
+ throw new AmbariException(
+ String.format("The %s property is not valid when creating a %s upgrade.",
+ UPGRADE_SKIP_MANUAL_VERIFICATION, UpgradeType.HOST_ORDERED));
+ }
+
+ if (!requestMap.containsKey(UPGRADE_HOST_ORDERED_HOSTS)) {
+ throw new AmbariException(
+ String.format("The %s property is required when creating a %s upgrade.",
+ UPGRADE_HOST_ORDERED_HOSTS, UpgradeType.HOST_ORDERED));
+ }
+
+ List<HostOrderItem> hostOrderItems = extractHostOrderItemsFromRequest(requestMap);
+ List<String> hostsFromRequest = new ArrayList<>(hostOrderItems.size());
+ for (HostOrderItem hostOrderItem : hostOrderItems) {
+ if (hostOrderItem.getType() == HostOrderActionType.HOST_UPGRADE) {
+ hostsFromRequest.addAll(hostOrderItem.getActionItems());
+ }
+ }
+
+ // ensure that all hosts for this cluster are accounted for
+ Collection<Host> hosts = cluster.getHosts();
+ Set<String> clusterHostNames = new HashSet<>(hosts.size());
+ for (Host host : hosts) {
+ clusterHostNames.add(host.getHostName());
+ }
+
+ Collection<String> disjunction = CollectionUtils.disjunction(hostsFromRequest,
+ clusterHostNames);
+
+ if (CollectionUtils.isNotEmpty(disjunction)) {
+ throw new AmbariException(String.format(
+ "The supplied list of hosts must match the cluster hosts in an upgrade of type %s. The following hosts are either missing or invalid: %s",
+ UpgradeType.HOST_ORDERED, StringUtils.join(disjunction, ", ")));
+ }
+
+ // verify that the upgradepack has the required grouping and set the
+ // action items on it
+ HostOrderGrouping hostOrderGrouping = null;
+ List<Grouping> groupings = upgradePack.getGroups(direction);
+ for (Grouping grouping : groupings) {
+ if (grouping instanceof HostOrderGrouping) {
+ hostOrderGrouping = (HostOrderGrouping) grouping;
+ hostOrderGrouping.setHostOrderItems(hostOrderItems);
+ }
+ }
+ }
+
+ /**
+ * Builds the list of {@link HostOrderItem}s from the upgrade request. If
+ * the upgrade request does not contain the hosts
+ *
+ * @param requestMap
+ * the map of properties from the request (not {@code null}).
+ * @return the ordered list of actions to orchestrate for the
+ * {@link UpgradeType#HOST_ORDERED} upgrade.
+ * @throws AmbariException
+ * if the request properties are not valid.
+ */
+ private List<HostOrderItem> extractHostOrderItemsFromRequest(Map<String, Object> requestMap)
+ throws AmbariException {
+ // ewwww
+ Set<Map<String, List<String>>> hostsOrder = (Set<Map<String, List<String>>>) requestMap.get(
+ UPGRADE_HOST_ORDERED_HOSTS);
+
+ if (CollectionUtils.isEmpty(hostsOrder)) {
+ throw new AmbariException(
+ String.format("The %s property must be specified when using a %s upgrade type.",
+ UPGRADE_HOST_ORDERED_HOSTS, UpgradeType.HOST_ORDERED));
+ }
+
+ List<HostOrderItem> hostOrderItems = new ArrayList<>();
+
+ // extract all of the hosts so that we can ensure they are all accounted
+ // for
+ Iterator<Map<String, List<String>>> iterator = hostsOrder.iterator();
+ while (iterator.hasNext()) {
+ Map<String, List<String>> grouping = iterator.next();
+ List<String> hosts = grouping.get("hosts");
+ List<String> serviceChecks = grouping.get("service_checks");
+
+ if (CollectionUtils.isEmpty(hosts) && CollectionUtils.isEmpty(serviceChecks)) {
+ throw new AmbariException(String.format(
+ "The %s property must contain at least one object with either a %s or %s key",
+ UPGRADE_HOST_ORDERED_HOSTS, "hosts", "service_checks"));
+ }
+
+ if (CollectionUtils.isNotEmpty(hosts)) {
+ hostOrderItems.add(new HostOrderItem(HostOrderActionType.HOST_UPGRADE, hosts));
+ }
+
+ if (CollectionUtils.isNotEmpty(serviceChecks)) {
+ hostOrderItems.add(new HostOrderItem(HostOrderActionType.SERVICE_CHECK, serviceChecks));
+ }
+ }
+
+ return hostOrderItems;
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java
index d482b8a..833c0b5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java
@@ -1,4 +1,4 @@
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -19,12 +19,8 @@ package org.apache.ambari.server.state;
import java.util.Map;
-import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.orm.entities.UpgradeEntity;
-import org.apache.ambari.server.state.stack.upgrade.Direction;
-import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
-
-import com.google.inject.assistedinject.Assisted;
/**
* The {@link UpgradeContextFactory} is used to create dependency-injected
@@ -37,27 +33,14 @@ public interface UpgradeContextFactory {
*
* @param cluster
* the cluster that the upgrade is for (not {@code null}).
- * @param type
- * the type of upgrade, either rolling or non_rolling (not
- * {@code null}).
- * @param direction
- * the direction for the upgrade
- * @param fromRepositoryVersion
- * the repository where any existing services are coming from
- * {@code null}).
- * @param toRepositoryVersion
- * the repository which is the target of the finalized
- * upgrade/downgrade {@code null}).
* @param upgradeRequestMap
* the original map of parameters used to create the upgrade (not
* {@code null}).
*
* @return an initialized {@link UpgradeContext}.
*/
- UpgradeContext create(Cluster cluster, UpgradeType type, Direction direction,
- @Assisted("fromRepositoryVersion") RepositoryVersionEntity fromRepositoryVersion,
- @Assisted("toRepositoryVersion") RepositoryVersionEntity toRepositoryVersion,
- Map<String, Object> upgradeRequestMap);
+ UpgradeContext create(Cluster cluster, Map<String, Object> upgradeRequestMap)
+ throws AmbariException;
/**
* Creates an {@link UpgradeContext} which is injected with dependencies.
http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/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 fe6532d..5fdcd66 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
@@ -1,4 +1,4 @@
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -19,8 +19,10 @@ package org.apache.ambari.server.state;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -28,8 +30,11 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.ambari.annotations.Experimental;
+import org.apache.ambari.annotations.ExperimentalFeature;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.internal.TaskResourceProvider;
import org.apache.ambari.server.controller.predicate.AndPredicate;
import org.apache.ambari.server.controller.spi.ClusterController;
@@ -46,7 +51,10 @@ import org.apache.ambari.server.controller.utilities.PredicateBuilder;
import org.apache.ambari.server.controller.utilities.PropertyHelper;
import org.apache.ambari.server.events.listeners.upgrade.StackVersionListener;
import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
+import org.apache.ambari.server.orm.dao.ServiceConfigDAO;
+import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
import org.apache.ambari.server.stack.HostsType;
import org.apache.ambari.server.stack.MasterHostResolver;
import org.apache.ambari.server.state.stack.UpgradePack;
@@ -98,7 +106,7 @@ public class UpgradeHelper {
/**
* Enum used to define placeholder text for replacement
*/
- private static enum Placeholder {
+ private enum Placeholder {
/**
* No placeholder defined
*/
@@ -154,7 +162,7 @@ public class UpgradeHelper {
DIRECTION_VERB_PROPER("direction.verb.proper");
private String pattern;
- private Placeholder(String key) {
+ Placeholder(String key) {
pattern = "{{" + key + "}}";
}
@@ -174,35 +182,55 @@ public class UpgradeHelper {
* {@link StageWrapperBuilder} has finished building out all of the stages.
*/
@Inject
- private Provider<ConfigHelper> m_configHelper;
+ Provider<ConfigHelper> m_configHelperProvider;
+
+ @Inject
+ private Provider<AmbariMetaInfo> m_ambariMetaInfoProvider;
+
+ @Inject
+ private Provider<Clusters> m_clusters;
@Inject
- private Provider<AmbariMetaInfo> m_ambariMetaInfo;
+ private Provider<RepositoryVersionDAO> m_repoVersionProvider;
+ /**
+ * Used to update the configuration properties.
+ */
@Inject
- private Provider<Clusters> clusters;
+ private Provider<AmbariManagementController> m_controllerProvider;
+ /**
+ * Used to get configurations by service name.
+ */
@Inject
- private Provider<RepositoryVersionDAO> s_repoVersionDAO;
+ ServiceConfigDAO m_serviceConfigDAO;
/**
- * Get right Upgrade Pack, depends on stack, direction and upgrade type information
- * @param clusterName The name of the cluster
- * @param upgradeFromVersion Current stack version
- * @param upgradeToVersion Target stack version
- * @param direction {@code Direction} of the upgrade
- * @param upgradeType The {@code UpgradeType}
- * @param targetStackName The destination target stack name.
- * @param preferredUpgradePackName For unit test, need to prefer an upgrade pack since multiple matches can be found.
+ * Get right Upgrade Pack, depends on stack, direction and upgrade type
+ * information
+ *
+ * @param clusterName
+ * The name of the cluster
+ * @param upgradeFromVersion
+ * Current stack version
+ * @param upgradeToVersion
+ * Target stack version
+ * @param direction
+ * {@code Direction} of the upgrade
+ * @param upgradeType
+ * The {@code UpgradeType}
+ * @param preferredUpgradePackName
+ * For unit test, need to prefer an upgrade pack since multiple
+ * matches can be found.
* @return {@code UpgradeType} object
* @throws AmbariException
*/
public UpgradePack suggestUpgradePack(String clusterName, String upgradeFromVersion, String upgradeToVersion,
- Direction direction, UpgradeType upgradeType, String targetStackName, String preferredUpgradePackName) throws AmbariException {
+ Direction direction, UpgradeType upgradeType, String preferredUpgradePackName) throws AmbariException {
// Find upgrade packs based on current stack. This is where to upgrade from
- Cluster cluster = clusters.get().getCluster(clusterName);
- StackId currentStack = cluster.getCurrentStackVersion();
+ Cluster cluster = m_clusters.get().getCluster(clusterName);
+ StackId stack = cluster.getCurrentStackVersion();
String repoVersion = upgradeToVersion;
@@ -211,25 +239,19 @@ public class UpgradeHelper {
repoVersion = upgradeFromVersion;
}
- Map<String, UpgradePack> packs = m_ambariMetaInfo.get().getUpgradePacks(currentStack.getStackName(), currentStack.getStackVersion());
- UpgradePack pack = null;
-
- if (StringUtils.isNotEmpty(preferredUpgradePackName) && packs.containsKey(preferredUpgradePackName)) {
- pack = packs.get(preferredUpgradePackName);
- }
-
- RepositoryVersionEntity versionEntity = s_repoVersionDAO.get().findByStackNameAndVersion(targetStackName, repoVersion);
- if (null == versionEntity) {
- versionEntity = s_repoVersionDAO.get().findByVersion(repoVersion);
- }
+ RepositoryVersionEntity versionEntity = m_repoVersionProvider.get().findByStackNameAndVersion(
+ stack.getStackName(), repoVersion);
if (versionEntity == null) {
- throw new AmbariException(String.format("Repository version %s was not found for target stack %s", repoVersion, targetStackName));
+ throw new AmbariException(String.format("Repository version %s was not found", repoVersion));
}
- // Best-attempt at picking an upgrade pack assuming within the same stack whose target stack version matches.
- // If multiple candidates are found, raise an exception.
- if (null == pack) {
+ Map<String, UpgradePack> packs = m_ambariMetaInfoProvider.get().getUpgradePacks(stack.getStackName(), stack.getStackVersion());
+ UpgradePack pack = null;
+
+ if (StringUtils.isNotEmpty(preferredUpgradePackName) && packs.containsKey(preferredUpgradePackName)) {
+ pack = packs.get(preferredUpgradePackName);
+ } else {
String repoStackId = versionEntity.getStackId().getStackId();
for (UpgradePack upgradePack : packs.values()) {
if (null != upgradePack.getTargetStack() && upgradePack.getTargetStack().equals(repoStackId) &&
@@ -247,8 +269,8 @@ public class UpgradeHelper {
}
if (null == pack) {
- throw new AmbariException(String.format("Unable to perform %s. Could not locate %s upgrade pack for stack %s and version %s",
- direction.getText(false), upgradeType.toString(), targetStackName, repoVersion));
+ throw new AmbariException(String.format("Unable to perform %s. Could not locate %s upgrade pack for version %s",
+ direction.getText(false), upgradeType.toString(), repoVersion));
}
return pack;
@@ -268,7 +290,6 @@ public class UpgradeHelper {
public List<UpgradeGroupHolder> createSequence(UpgradePack upgradePack,
UpgradeContext context) throws AmbariException {
- context.setAmbariMetaInfo(m_ambariMetaInfo.get());
Cluster cluster = context.getCluster();
MasterHostResolver mhr = context.getResolver();
@@ -546,7 +567,6 @@ public class UpgradeHelper {
private String tokenReplace(UpgradeContext ctx, String source, String service, String component) {
Cluster cluster = ctx.getCluster();
MasterHostResolver mhr = ctx.getResolver();
- String version = ctx.getTargetRepositoryVersion().getVersion();
String result = source;
@@ -583,7 +603,7 @@ public class UpgradeHelper {
break;
}
case VERSION:
- value = version;
+ value = ctx.getRepositoryVersion().getVersion();
break;
case DIRECTION_VERB:
case DIRECTION_VERB_PROPER:
@@ -602,7 +622,7 @@ public class UpgradeHelper {
value = ctx.getDirection().getText(p == Placeholder.DIRECTION_TEXT_PROPER);
break;
default:
- value = m_configHelper.get().getPlaceholderValueFromDesiredConfigurations(
+ value = m_configHelperProvider.get().getPlaceholderValueFromDesiredConfigurations(
cluster, token);
break;
}
@@ -708,7 +728,7 @@ public class UpgradeHelper {
private void setDisplayNames(UpgradeContext context, String service, String component) {
StackId stackId = context.getCluster().getDesiredStackVersion();
try {
- ServiceInfo serviceInfo = m_ambariMetaInfo.get().getService(stackId.getStackName(),
+ ServiceInfo serviceInfo = m_ambariMetaInfoProvider.get().getService(stackId.getStackName(),
stackId.getStackVersion(), service);
context.setServiceDisplay(service, serviceInfo.getDisplayName());
@@ -721,6 +741,32 @@ public class UpgradeHelper {
}
/**
+ * Updates the various repositories and configurations for services
+ * participating in the upgrade or downgrade. The following actions are
+ * performed in order:
+ * <ul>
+ * <li>The desired repository for every service and component is changed<
+ * <li>The {@link UpgradeState} of every component host is moved to either
+ * {@link UpgradeState#IN_PROGRESS} or {@link UpgradeState#NONE}.
+ * <li>In the case of an upgrade, new configurations and service
+ * configurations are created if necessary. In the case of a downgrade, any
+ * configurations created by the upgrade are reverted.
+ * </ul>
+ *
+ * @param upgradeContext
+ * the upgrade context holding all relevent upgrade information (not
+ * {@code null}).
+ * @throws AmbariException
+ */
+ @Transactional
+ @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES)
+ public void updateDesiredRepositoriesAndConfigs(UpgradeContext upgradeContext)
+ throws AmbariException {
+ setDesiredRepositories(upgradeContext);
+ processConfigurationsIfRequired(upgradeContext);
+ }
+
+ /**
* Transitions all affected components to {@link UpgradeState#IN_PROGRESS}.
* Transition is performed only for components that advertise their version.
* Additionally sets the service component desired version to the specified
@@ -730,27 +776,25 @@ public class UpgradeHelper {
* the upgrade state individually, we wrap this method inside of a transaction
* to prevent 1000's of transactions from being opened and committed.
*
- * @param stackId
- * the desired stack ID for the upgrade
- * @param version
- * desired version (like 2.2.1.0-1234) for upgrade
- * @param targetServices
- * targets for upgrade
- * @param targetStack
- * the target stack for the components. Express and Rolling upgrades
- * determine the "correct" stack differently, so the component's
- * desired stack id is not a reliable indicator.
+ * @param upgradeContext
+ * the upgrade context (not {@code null}).
*/
- @Transactional
- public void putComponentsToUpgradingState(StackId stackId, String version,
- Map<Service, Set<ServiceComponent>> targetServices, StackId targetStack) throws AmbariException {
-
- for (Map.Entry<Service, Set<ServiceComponent>> entry: targetServices.entrySet()) {
- for (ServiceComponent serviceComponent: entry.getValue()) {
-
+ @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES)
+ private void setDesiredRepositories(UpgradeContext upgradeContext) throws AmbariException {
+ Cluster cluster = upgradeContext.getCluster();
+ Set<String> services = upgradeContext.getSupportedServices();
+
+ for (String serviceName : services) {
+ Service service = cluster.getService(serviceName);
+ RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion(serviceName);
+ StackId targetStack = targetRepositoryVersion.getStackId();
+ service.setDesiredRepositoryVersion(targetRepositoryVersion);
+
+ Collection<ServiceComponent> components = service.getServiceComponents().values();
+ for (ServiceComponent serviceComponent : components) {
boolean versionAdvertised = false;
try {
- ComponentInfo ci = m_ambariMetaInfo.get().getComponent(targetStack.getStackName(),
+ ComponentInfo ci = m_ambariMetaInfoProvider.get().getComponent(targetStack.getStackName(),
targetStack.getStackVersion(), serviceComponent.getServiceName(),
serviceComponent.getName());
@@ -761,27 +805,224 @@ public class UpgradeHelper {
StackVersionListener.UNKNOWN_VERSION);
}
- UpgradeState upgradeState = UpgradeState.IN_PROGRESS;
- String desiredVersion = version;
-
+ UpgradeState upgradeStateToSet = UpgradeState.IN_PROGRESS;
if (!versionAdvertised) {
- upgradeState = UpgradeState.NONE;
- desiredVersion = StackVersionListener.UNKNOWN_VERSION;
+ upgradeStateToSet = UpgradeState.NONE;
}
- for (ServiceComponentHost serviceComponentHost: serviceComponent.getServiceComponentHosts().values()) {
- serviceComponentHost.setUpgradeState(upgradeState);
+ for (ServiceComponentHost serviceComponentHost : serviceComponent.getServiceComponentHosts().values()) {
+ if (serviceComponentHost.getUpgradeState() != upgradeStateToSet) {
+ serviceComponentHost.setUpgradeState(upgradeStateToSet);
+ }
- // !!! if we aren't version advertised, but there IS a version, set it.
- if (!versionAdvertised &&
- !serviceComponentHost.getVersion().equals(StackVersionListener.UNKNOWN_VERSION)) {
+ // !!! if we aren't version advertised, but there IS a version, set
+ // it.
+ if (!versionAdvertised && !StringUtils.equals(StackVersionListener.UNKNOWN_VERSION,
+ serviceComponentHost.getVersion())) {
serviceComponentHost.setVersion(StackVersionListener.UNKNOWN_VERSION);
}
}
- serviceComponent.setDesiredStackVersion(stackId);
- serviceComponent.setDesiredVersion(desiredVersion);
+ // set component desired repo
+ serviceComponent.setDesiredRepositoryVersion(targetRepositoryVersion);
+ }
+ }
+ }
+
+ /**
+ * Handles the creation or resetting of configurations based on whether an
+ * upgrade or downgrade is occurring. This method will not do anything when
+ * the service is not crossing major stack versions, since, by definition, no
+ * new configurations are automatically created when upgrading with the same
+ * stack (ie HDP 2.2.0.0 -> HDP 2.2.1.0).
+ * <p/>
+ * When upgrading or downgrade between stacks (HDP 2.2.0.0 -> HDP 2.3.0.0)
+ * then this will perform the following:
+ * <ul>
+ * <li>Upgrade: Create new configurations that are a merge between the source
+ * stack and the target stack. If a value has changed between stacks, then the
+ * target stack value should be taken unless the cluster's value differs from
+ * the old stack. This can occur if a property has been customized after
+ * installation.</li>
+ * <li>Downgrade: Reset the latest configurations from the service's original
+ * stack. The new configurations that were created on upgrade must be left
+ * intact until all components have been reverted, otherwise heartbeats will
+ * fail due to missing configurations.</li>
+ * </ul>
+ *
+ * @param upgradeContext
+ * the upgrade context (not {@code null}).
+ * @throws AmbariException
+ */
+ private void processConfigurationsIfRequired(UpgradeContext upgradeContext)
+ throws AmbariException {
+
+ AmbariManagementController controller = m_controllerProvider.get();
+
+ Cluster cluster = upgradeContext.getCluster();
+ Direction direction = upgradeContext.getDirection();
+ String userName = controller.getAuthName();
+ Set<String> servicesInUpgrade = upgradeContext.getSupportedServices();
+
+ // merge or revert configurations for any service that needs it
+ for( String serviceName : servicesInUpgrade ){
+ RepositoryVersionEntity sourceRepositoryVersion = upgradeContext.getSourceRepositoryVersion(serviceName);
+ RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion(serviceName);
+ StackId sourceStackId = sourceRepositoryVersion.getStackId();
+ StackId targetStackId = targetRepositoryVersion.getStackId();
+
+ // only work with configurations when crossing stacks
+ if (sourceStackId.equals(targetStackId)) {
+ RepositoryVersionEntity associatedRepositoryVersion = upgradeContext.getRepositoryVersion();
+ LOG.info(
+ "The {} {} {} will not change stack configurations for {} since the source and target are both {}",
+ direction.getText(false), direction.getPreposition(),
+ associatedRepositoryVersion.getVersion(), serviceName, targetStackId);
+
+ continue;
+ }
+
+ ConfigHelper configHelper = m_configHelperProvider.get();
+
+ // downgrade is easy - just remove the new and make the old current
+ if (direction == Direction.DOWNGRADE) {
+ cluster.applyLatestConfigurations(targetStackId, serviceName);
+ return;
+ }
+
+ // upgrade is a bit harder - we have to merge new stack configurations in
+
+ // populate a map of default configurations for the service on the old
+ // stack (this is used when determining if a property has been
+ // customized and should be overriden with the new stack value)
+ Map<String, Map<String, String>> oldServiceDefaultConfigsByType = configHelper.getDefaultProperties(
+ sourceStackId, serviceName);
+
+ // populate a map with default configurations from the new stack
+ Map<String, Map<String, String>> newServiceDefaultConfigsByType = configHelper.getDefaultProperties(
+ targetStackId, serviceName);
+
+ // find the current, existing configurations for the service
+ List<Config> existingServiceConfigs = new ArrayList<>();
+ List<ServiceConfigEntity> latestServiceConfigs = m_serviceConfigDAO.getLastServiceConfigsForService(
+ cluster.getClusterId(), serviceName);
+
+ for (ServiceConfigEntity serviceConfig : latestServiceConfigs) {
+ List<ClusterConfigEntity> existingConfigurations = serviceConfig.getClusterConfigEntities();
+ for (ClusterConfigEntity currentServiceConfig : existingConfigurations) {
+ String configurationType = currentServiceConfig.getType();
+ Config currentClusterConfigForService = cluster.getDesiredConfigByType(configurationType);
+ existingServiceConfigs.add(currentClusterConfigForService);
+ }
+ }
+
+ // now that we have found, old, new, and existing confgs, overlay the
+ // existing on top of the new
+ for (Config existingServiceConfig : existingServiceConfigs) {
+ String configurationType = existingServiceConfig.getType();
+
+ // get current stack default configurations on install
+ Map<String, String> oldServiceDefaultConfigs = oldServiceDefaultConfigsByType.get(
+ configurationType);
+
+ // NPE sanity for current stack defaults
+ if (null == oldServiceDefaultConfigs) {
+ oldServiceDefaultConfigs = Collections.emptyMap();
+ }
+
+ // get the existing configurations
+ Map<String, String> existingConfigurations = existingServiceConfig.getProperties();
+
+ // get the new configurations
+ Map<String, String> newDefaultConfigurations = newServiceDefaultConfigsByType.get(
+ configurationType);
+
+ // if the new stack configurations don't have the type, then simply add
+ // all of the existing in
+ if (null == newDefaultConfigurations) {
+ newServiceDefaultConfigsByType.put(configurationType, existingConfigurations);
+ continue;
+ } else {
+ // Remove any configs in the new stack whose value is NULL, unless
+ // they currently exist and the value is not NULL.
+ Iterator<Map.Entry<String, String>> iter = newDefaultConfigurations.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry<String, String> entry = iter.next();
+ if (entry.getValue() == null) {
+ iter.remove();
+ }
+ }
+ }
+
+ // process every existing configuration property for this configuration
+ // type
+ for (Map.Entry<String, String> existingConfigurationEntry : existingConfigurations.entrySet()) {
+ String existingConfigurationKey = existingConfigurationEntry.getKey();
+ String existingConfigurationValue = existingConfigurationEntry.getValue();
+
+ // if there is already an entry, we now have to try to determine if
+ // the value was customized after stack installation
+ if (newDefaultConfigurations.containsKey(existingConfigurationKey)) {
+ String newDefaultConfigurationValue = newDefaultConfigurations.get(
+ existingConfigurationKey);
+
+ if (!StringUtils.equals(existingConfigurationValue, newDefaultConfigurationValue)) {
+ // the new default is different from the existing cluster value;
+ // only override the default value if the existing value differs
+ // from the original stack
+ String oldDefaultValue = oldServiceDefaultConfigs.get(existingConfigurationKey);
+
+ if (!StringUtils.equals(existingConfigurationValue, oldDefaultValue)) {
+ // at this point, we've determined that there is a
+ // difference
+ // between default values between stacks, but the value was
+ // also customized, so keep the customized value
+ newDefaultConfigurations.put(existingConfigurationKey, existingConfigurationValue);
+ }
+ }
+ } else {
+ // there is no entry in the map, so add the existing key/value
+ // pair
+ newDefaultConfigurations.put(existingConfigurationKey, existingConfigurationValue);
+ }
+ }
+
+ /*
+ for every new configuration which does not exist in the existing
+ configurations, see if it was present in the current stack
+
+ stack 2.x has foo-site/property (on-ambari-upgrade is false)
+ stack 2.y has foo-site/property
+ the current cluster (on 2.x) does not have it
+
+ In this case, we should NOT add it back as clearly stack advisor has removed it
+ */
+ Iterator<Map.Entry<String, String>> newDefaultConfigurationsIterator = newDefaultConfigurations.entrySet().iterator();
+ while (newDefaultConfigurationsIterator.hasNext()) {
+ Map.Entry<String, String> newConfigurationEntry = newDefaultConfigurationsIterator.next();
+ String newConfigurationPropertyName = newConfigurationEntry.getKey();
+ if (oldServiceDefaultConfigs.containsKey(newConfigurationPropertyName)
+ && !existingConfigurations.containsKey(newConfigurationPropertyName)) {
+ LOG.info(
+ "The property {}/{} exists in both {} and {} but is not part of the current set of configurations and will therefore not be included in the configuration merge",
+ configurationType, newConfigurationPropertyName, sourceStackId, targetStackId);
+
+ // remove the property so it doesn't get merged in
+ newDefaultConfigurationsIterator.remove();
+ }
+ }
+ }
+
+ if (null != newServiceDefaultConfigsByType) {
+ Set<String> configTypes = newServiceDefaultConfigsByType.keySet();
+ LOG.info("The upgrade will create the following configurations for stack {}: {}",
+ targetStackId, StringUtils.join(configTypes, ','));
+
+ String serviceVersionNote = String.format("%s %s %s", direction.getText(true),
+ direction.getPreposition(), upgradeContext.getRepositoryVersion().getVersion());
+ configHelper.createConfigTypes(cluster, targetStackId, controller,
+ newServiceDefaultConfigsByType, userName, serviceVersionNote);
}
}
}