http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigUpgradePack.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigUpgradePack.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigUpgradePack.java new file mode 100644 index 0000000..f2e2e61 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigUpgradePack.java @@ -0,0 +1,192 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack; + +import org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Represents a pack of changes that should be applied to configs + * when upgrading from a previous stack. In other words, it's a config delta + * from prev stack. + * + * After first call of enumerateConfigChangesByID() method, instance contains + * a cache of data, so it should not be modified in runtime (otherwise + * the cache will become outdated). + */ +@XmlRootElement(name="upgrade-config-changes") +@XmlAccessorType(XmlAccessType.FIELD) +public class ConfigUpgradePack { + + /** + * Defines per-service config changes. + */ + @XmlElementWrapper(name="services") + @XmlElement(name="service") + public List<AffectedService> services; + + /** + * Contains a cached mapping of <change id, change definition>. + */ + private Map<String, ConfigUpgradeChangeDefinition> changesById; + + private static Logger LOG = LoggerFactory.getLogger(ConfigUpgradePack.class); + + /** + * no-arg default constructor for JAXB + */ + public ConfigUpgradePack() { + } + + public ConfigUpgradePack(List<AffectedService> services) { + this.services = services; + } + + /** + * @return a map of <service name, AffectedService>. + */ + public Map<String, AffectedService> getServiceMap() { + Map<String, AffectedService> result = new HashMap<>(); + for (AffectedService service : services) { + result.put(service.name, service); + } + return result; + } + + /** + * @return a map of <change id, change definition>. Map is built once and + * cached + */ + public Map<String, ConfigUpgradeChangeDefinition> enumerateConfigChangesByID() { + if (changesById == null) { + changesById = new HashMap<>(); + for(AffectedService service : services) { + for(AffectedComponent component: service.components) { + for (ConfigUpgradeChangeDefinition changeDefinition : component.changes) { + if (changeDefinition.id == null) { + LOG.warn(String.format("Config upgrade change definition for service %s," + + " component %s has no id", service.name, component.name)); + } else if (changesById.containsKey(changeDefinition.id)) { + LOG.warn("Duplicate config upgrade change definition with ID " + + changeDefinition.id); + } + changesById.put(changeDefinition.id, changeDefinition); + } + } + } + } + return changesById; + } + + /** + * Merges few config upgrade packs into one and returs result. During merge, + * a deep copy of AffectedService and AffectedComponent lists is added to resulting + * config upgrade pack. The only level that is not copied deeply is a list of + * per-component config changes. + * @param cups list of source config upgrade packs + * @return merged config upgrade pack that is a deep copy of source + * config upgrade packs + */ + public static ConfigUpgradePack merge(ArrayList<ConfigUpgradePack> cups) { + // Map <service_name, <component_name, component_changes>> + Map<String, Map<String, AffectedComponent>> mergedServiceMap = new HashMap<>(); + + for (ConfigUpgradePack configUpgradePack : cups) { + for (AffectedService service : configUpgradePack.services) { + if (! mergedServiceMap.containsKey(service.name)) { + mergedServiceMap.put(service.name, new HashMap<String, AffectedComponent>()); + } + Map<String, AffectedComponent> mergedComponentMap = mergedServiceMap.get(service.name); + + for (AffectedComponent component : service.components) { + if (! mergedComponentMap.containsKey(component.name)) { + AffectedComponent mergedComponent = new AffectedComponent(); + mergedComponent.name = component.name; + mergedComponent.changes = new ArrayList<>(); + mergedComponentMap.put(component.name, mergedComponent); + } + AffectedComponent mergedComponent = mergedComponentMap.get(component.name); + mergedComponent.changes.addAll(component.changes); + } + + } + } + // Convert merged maps into new ConfigUpgradePack + ArrayList<AffectedService> mergedServices = new ArrayList<>(); + for (String serviceName : mergedServiceMap.keySet()) { + AffectedService mergedService = new AffectedService(); + Map<String, AffectedComponent> mergedComponentMap = mergedServiceMap.get(serviceName); + mergedService.name = serviceName; + mergedService.components = new ArrayList<>(mergedComponentMap.values()); + mergedServices.add(mergedService); + } + + return new ConfigUpgradePack(mergedServices); + } + + /** + * A service definition in the 'services' element. + */ + public static class AffectedService { + + @XmlAttribute + public String name; + + @XmlElement(name="component") + public List<AffectedComponent> components; + + /** + * @return a map of <component name, AffectedService> + */ + public Map<String, AffectedComponent> getComponentMap() { + Map<String, AffectedComponent> result = new HashMap<>(); + for (AffectedComponent component : components) { + result.put(component.name, component); + } + return result; + } + } + + /** + * A component definition in the 'services/service' path. + */ + public static class AffectedComponent { + + @XmlAttribute + public String name; + + @XmlElementWrapper(name="changes") + @XmlElement(name="definition") + public List<ConfigUpgradeChangeDefinition> changes; + + } +}
http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java index 5b65732..33dfc0a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java @@ -22,6 +22,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -36,6 +37,7 @@ 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.ServiceCheckGrouping; import org.apache.ambari.server.state.stack.upgrade.Task; +import org.apache.ambari.server.state.stack.upgrade.UpgradeType; /** * Represents an upgrade pack. @@ -44,6 +46,11 @@ import org.apache.ambari.server.state.stack.upgrade.Task; @XmlAccessorType(XmlAccessType.FIELD) public class UpgradePack { + /** + * Name of the file without the extension, such as upgrade-2.2 + */ + private String name; + @XmlElement(name="target") private String target; @@ -54,6 +61,15 @@ public class UpgradePack { @XmlElement(name="group") private List<Grouping> groups; + @XmlElementWrapper(name="prerequisite-checks") + @XmlElement(name="check", type=String.class) + private List<String> prerequisiteChecks = new ArrayList<String>(); + + /** + * In the case of a rolling upgrade, will specify processing logic for a particular component. + * NonRolling upgrades are simpler so the "processing" is embedded into the group's "type", which is a function like + * "stop" or "start". + */ @XmlElementWrapper(name="processing") @XmlElement(name="service") private List<ProcessingService> processing; @@ -81,7 +97,20 @@ public class UpgradePack { @XmlTransient private boolean m_resolvedGroups = false; + @XmlElement(name="type", defaultValue="rolling") + private UpgradeType type; + @XmlElementWrapper(name="upgrade-path") + @XmlElement(name="intermediate-stack") + private List<IntermediateStack> intermediateStacks; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } /** * @return the target version for the upgrade pack */ @@ -90,6 +119,27 @@ public class UpgradePack { } /** + * @return the type of upgrade, e.g., "ROLLING" or "NON_ROLLING" + */ + public UpgradeType getType() { + return type; + } + + /** + * @return the preCheck name, e.g. "CheckDescription" + */ + public List<String> getPrerequisiteChecks() { + return new ArrayList<String>(prerequisiteChecks); + } + + /** + * @return a list for intermediate stacks for cross-stack upgrade, or null if no any + */ + public List<IntermediateStack> getIntermediateStacks() { + return intermediateStacks; + } + + /** * @return the target stack, or {@code null} if the upgrade is within the same stack */ public String getTargetStack() { @@ -124,7 +174,16 @@ public class UpgradePack { * @return the list of groups */ public List<Grouping> getGroups(Direction direction) { - List<Grouping> list = direction.isUpgrade() ? groups : getDowngradeGroups(); + List<Grouping> list = new ArrayList<Grouping>(); + if (direction.isUpgrade()) { + list = groups; + } else { + if (type == UpgradeType.ROLLING) { + list = getDowngradeGroupsForRolling(); + } else if (type == UpgradeType.NON_ROLLING) { + list = getDowngradeGroupsForNonrolling(); + } + } List<Grouping> checked = new ArrayList<Grouping>(); for (Grouping group : list) { @@ -137,8 +196,18 @@ public class UpgradePack { return checked; } + public boolean canBeApplied(String targetVersion){ + // check that upgrade pack can be applied to selected stack + // converting 2.2.*.* -> 2\.2(\.\d+)?(\.\d+)?(-\d+)? + + String regexPattern = getTarget().replaceAll("\\.", "\\\\."); // . -> \. + regexPattern = regexPattern.replaceAll("\\\\\\.\\*", "(\\\\\\.\\\\d+)?"); // \.* -> (\.\d+)? + regexPattern = regexPattern.concat("(-\\d+)?"); + return Pattern.matches(regexPattern, targetVersion); + } + /** - * Calculates the group orders when performing a downgrade + * Calculates the group orders when performing a rolling downgrade * <ul> * <li>ClusterGroupings must remain at the same positions (first/last).</li> * <li>When there is a ServiceCheck group, it must ALWAYS follow the same</li> @@ -169,7 +238,7 @@ public class UpgradePack { * </ol> * @return the list of groups, reversed appropriately for a downgrade. */ - private List<Grouping> getDowngradeGroups() { + private List<Grouping> getDowngradeGroupsForRolling() { List<Grouping> reverse = new ArrayList<Grouping>(); int idx = 0; @@ -199,6 +268,17 @@ public class UpgradePack { return reverse; } + private List<Grouping> getDowngradeGroupsForNonrolling() { + throw new UnsupportedOperationException("TODO AMBARI-12698"); + /* + List<Grouping> list = new ArrayList<Grouping>(); + for (Grouping g : groups) { + list.add(g); + } + return list; + */ + } + /** * Gets the tasks by which services and components should be upgraded. * @return a map of service_name -> map(component_name -> process). @@ -208,15 +288,17 @@ public class UpgradePack { if (null == m_process) { m_process = new LinkedHashMap<String, Map<String, ProcessingComponent>>(); - for (ProcessingService svc : processing) { - if (!m_process.containsKey(svc.name)) { - m_process.put(svc.name, new LinkedHashMap<String, ProcessingComponent>()); - } + if (processing != null) { + for (ProcessingService svc : processing) { + if (!m_process.containsKey(svc.name)) { + m_process.put(svc.name, new LinkedHashMap<String, ProcessingComponent>()); + } - Map<String, ProcessingComponent> componentMap = m_process.get(svc.name); + Map<String, ProcessingComponent> componentMap = m_process.get(svc.name); - for (ProcessingComponent pc : svc.components) { - componentMap.put(pc.name, pc); + for (ProcessingComponent pc : svc.components) { + componentMap.put(pc.name, pc); + } } } } @@ -248,8 +330,6 @@ public class UpgradePack { public List<ProcessingComponent> components; } - - /** * A component definition in the 'processing/service' path. */ @@ -279,4 +359,14 @@ public class UpgradePack { @XmlElement(name="task") public List<Task> postDowngradeTasks; } + + /** + * An intermediate stack definition in + * upgrade/upgrade-path/intermediate-stack path + */ + public static class IntermediateStack { + + @XmlAttribute + public String version; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java index eff1b13..ba44408 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java @@ -53,7 +53,7 @@ import com.google.gson.JsonPrimitive; public class ClusterGrouping extends Grouping { /** - * Stages against a Service and Component, or the Server + * Stages against a Service and Component, or the Server, that doesn't need a Processing Component. */ @XmlElement(name="execute-stage") public List<ExecuteStage> executionStages; @@ -166,6 +166,12 @@ public class ClusterGrouping extends Grouping { } } + /** + * Return a Stage Wrapper for a manual task that runs on the server. + * @param ctx Upgrade Context + * @param execution Execution Stage + * @return Returns a Stage Wrapper + */ private StageWrapper getManualStageWrapper(UpgradeContext ctx, ExecuteStage execution) { String service = execution.service; @@ -204,6 +210,12 @@ public class ClusterGrouping extends Grouping { new TaskWrapper(service, component, realHosts, task)); } + /** + * Return a Stage Wrapper for a task meant to execute code, typically on Ambari Server. + * @param ctx Upgrade Context + * @param execution Execution Stage + * @return Returns a Stage Wrapper, or null if a valid one could not be created. + */ private StageWrapper getExecuteStageWrapper(UpgradeContext ctx, ExecuteStage execution) { String service = execution.service; String component = execution.component; @@ -251,15 +263,18 @@ public class ClusterGrouping extends Grouping { return new StageWrapper( StageWrapper.Type.RU_TASKS, execution.title, new TaskWrapper(service, component, hostNames, et)); - } return null; } - private void fillHostDetails(ManualTask mt, Map<String, List<String>> unhealthy) { - + /** + * Populates the manual task, mt, with information about the list of hosts. + * @param mt Manual Task + * @param hostToComponents Map from host name to list of components + */ + private void fillHostDetails(ManualTask mt, Map<String, List<String>> hostToComponents) { JsonArray arr = new JsonArray(); - for (Entry<String, List<String>> entry : unhealthy.entrySet()) { + for (Entry<String, List<String>> entry : hostToComponents.entrySet()) { JsonObject hostObj = new JsonObject(); hostObj.addProperty("host", entry.getKey()); @@ -276,7 +291,5 @@ public class ClusterGrouping extends Grouping { obj.add("unhealthy", arr); mt.structuredOut = obj.toString(); - } - } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigUpgradeChangeDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigUpgradeChangeDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigUpgradeChangeDefinition.java new file mode 100644 index 0000000..780f96d --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigUpgradeChangeDefinition.java @@ -0,0 +1,420 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack.upgrade; + +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * The {@link ConfigUpgradeChangeDefinition} represents a configuration change. This change can be + * defined with conditional statements that will only set values if a condition + * passes: + * <p/> + * + * <pre> + * {@code + * <definition> + * <condition type="hive-site" key="hive.server2.transport.mode" value="binary"> + * <type>hive-site</type> + * <key>hive.server2.thrift.port</key> + * <value>10010</value> + * </condition> + * <condition type="hive-site" key="hive.server2.transport.mode" value="http"> + * <type>hive-site</type> + * <key>hive.server2.http.port</key> + * <value>10011</value> + * </condition> + * </definition> + * } + * </pre> + * + * It's also possible to simple set values directly without a precondition + * check. + * + * <pre> + * {@code + * <definition xsi:type="configure"> + * <type>hive-site</type> + * <set key="hive.server2.thrift.port" value="10010"/> + * <set key="foo" value="bar"/> + * <set key="foobar" value="baz"/> + * </definition> + * } + * </pre> + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class ConfigUpgradeChangeDefinition { + + private static Logger LOG = LoggerFactory.getLogger(ConfigUpgradeChangeDefinition.class); + + /** + * The key that represents the configuration type to change (ie hdfs-site). + */ + public static final String PARAMETER_CONFIG_TYPE = "configure-task-config-type"; + + /** + * Setting key/value pairs can be several per task, so they're passed in as a + * json-ified list of objects. + */ + public static final String PARAMETER_KEY_VALUE_PAIRS = "configure-task-key-value-pairs"; + + /** + * Transfers can be several per task, so they're passed in as a json-ified + * list of objects. + */ + public static final String PARAMETER_TRANSFERS = "configure-task-transfers"; + + /** + * Replacements can be several per task, so they're passed in as a json-ified list of + * objects. + */ + public static final String PARAMETER_REPLACEMENTS = "configure-task-replacements"; + + public static final String actionVerb = "Configuring"; + + public static final Float DEFAULT_PRIORITY = 1.0f; + + /** + * Gson + */ + private Gson m_gson = new Gson(); + + /** + * An optional brief description of config changes. + */ + @XmlAttribute(name = "summary") + public String summary; + + @XmlAttribute(name = "id", required = true) + public String id; + + @XmlElement(name="type") + private String configType; + + @XmlElement(name = "set") + private List<ConfigurationKeyValue> keyValuePairs; + + @XmlElement(name = "condition") + private List<Condition> conditions; + + @XmlElement(name = "transfer") + private List<Transfer> transfers; + + @XmlElement(name="replace") + private List<Replace> replacements; + + /** + * @return the config type + */ + public String getConfigType() { + return configType; + } + + /** + * @return the list of <set key=foo value=bar/> items + */ + public List<ConfigurationKeyValue> getKeyValuePairs() { + return keyValuePairs; + } + + /** + * @return the list of conditions + */ + public List<Condition> getConditions() { + return conditions; + } + + /** + * @return the list of transfers, checking for appropriate null fields. + */ + public List<Transfer> getTransfers() { + if (null == transfers) { + return Collections.emptyList(); + } + + List<Transfer> list = new ArrayList<>(); + for (Transfer t : transfers) { + switch (t.operation) { + case COPY: + case MOVE: + if (null != t.fromKey && null != t.toKey) { + list.add(t); + } else { + LOG.warn(String.format("Transfer %s is invalid", t)); + } + break; + case DELETE: + if (null != t.deleteKey) { + list.add(t); + } else { + LOG.warn(String.format("Transfer %s is invalid", t)); + } + + break; + } + } + + return list; + } + + /** + * @return the replacement tokens, never {@code null} + */ + public List<Replace> getReplacements() { + if (null == replacements) { + return Collections.emptyList(); + } + + List<Replace> list = new ArrayList<>(); + for (Replace r : replacements) { + if (null == r.key || null == r.find || null == r.replaceWith) { + LOG.warn(String.format("Replacement %s is invalid", r)); + continue; + } + list.add(r); + } + + return list; + } + + /** + * Used for configuration updates that should mask their values from being + * printed in plain text. + */ + @XmlAccessorType(XmlAccessType.FIELD) + public static class Masked { + @XmlAttribute(name = "mask") + public boolean mask = false; + } + + + /** + * A key/value pair to set in the type specified by {@link ConfigUpgradeChangeDefinition#configType} + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "set") + public static class ConfigurationKeyValue extends Masked { + @XmlAttribute(name = "key") + public String key; + + @XmlAttribute(name = "value") + public String value; + } + + /** + * A conditional element that will only perform the configuration if the + * condition is met. + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "condition") + public static class Condition { + @XmlAttribute(name = "type") + private String conditionConfigType; + + @XmlAttribute(name = "key") + private String conditionKey; + + @XmlAttribute(name = "value") + private String conditionValue; + + @XmlElement(name = "type") + private String configType; + + @XmlElement(name = "key") + private String key; + + @XmlElement(name = "value") + private String value; + + public String getConditionConfigType() { + return conditionConfigType; + } + + public String getConditionKey() { + return conditionKey; + } + + public String getConditionValue() { + return conditionValue; + } + + public String getConfigType() { + return configType; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + } + + /** + * A {@code transfer} element will copy, move, or delete the value of one type/key to another type/key. + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "transfer") + public static class Transfer extends Masked { + /** + * The type of operation, such as COPY or DELETE. + */ + @XmlAttribute(name = "operation") + public TransferOperation operation; + + /** + * The configuration type to copy or move from. + */ + @XmlAttribute(name = "from-type") + public String fromType; + + /** + * The key to copy or move the configuration from. + */ + @XmlAttribute(name = "from-key") + public String fromKey; + + /** + * The key to copy the configuration value to. + */ + @XmlAttribute(name = "to-key") + public String toKey; + + /** + * The configuration key to delete, or "*" for all. + */ + @XmlAttribute(name = "delete-key") + public String deleteKey; + + /** + * If {@code true}, this will ensure that any changed properties are not + * removed during a {@link TransferOperation#DELETE}. + */ + @XmlAttribute(name = "preserve-edits") + public boolean preserveEdits = false; + + /** + * A default value to use when the configurations don't contain the + * {@link #fromKey}. + */ + @XmlAttribute(name = "default-value") + public String defaultValue; + + /** + * A data type to convert the configuration value to when the action is + * {@link TransferOperation#COPY}. + */ + @XmlAttribute(name = "coerce-to") + public TransferCoercionType coerceTo; + + // if the condition is true apply the transfer action + // only supported conditional action is DELETE + // if-type/if-key == if-value + /** + * The key to read for the if condition. + */ + @XmlAttribute(name = "if-key") + public String ifKey; + + /** + * The config type to read for the if condition. + */ + @XmlAttribute(name = "if-type") + public String ifType; + + /** + * The property value to compare against for the if condition. + */ + @XmlAttribute(name = "if-value") + public String ifValue; + + /** + * The keys to keep when the action is {@link TransferOperation#DELETE}. + */ + @XmlElement(name = "keep-key") + public List<String> keepKeys = new ArrayList<String>(); + + @Override + public String toString() { + return "Transfer{" + + "operation=" + operation + + ", fromType='" + fromType + '\'' + + ", fromKey='" + fromKey + '\'' + + ", toKey='" + toKey + '\'' + + ", deleteKey='" + deleteKey + '\'' + + ", preserveEdits=" + preserveEdits + + ", defaultValue='" + defaultValue + '\'' + + ", coerceTo=" + coerceTo + + ", ifKey='" + ifKey + '\'' + + ", ifType='" + ifType + '\'' + + ", ifValue='" + ifValue + '\'' + + ", keepKeys=" + keepKeys + + '}'; + } + } + + /** + * Used to replace strings in a key with other strings. More complex + * scenarios will be possible with regex (when needed) + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "replace") + public static class Replace extends Masked { + /** + * The key name + */ + @XmlAttribute(name="key") + public String key; + + /** + * The string to find + */ + @XmlAttribute(name="find") + public String find; + + /** + * The string to replace + */ + @XmlAttribute(name="replace-with") + public String replaceWith; + + @Override + public String toString() { + return "Replace{" + + "key='" + key + '\'' + + ", find='" + find + '\'' + + ", replaceWith='" + replaceWith + '\'' + + '}'; + } + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java index 8a9e2e5..cd0f18a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java @@ -18,7 +18,6 @@ package org.apache.ambari.server.state.stack.upgrade; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -26,11 +25,10 @@ import java.util.Map; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlType; +import org.apache.ambari.server.state.stack.ConfigUpgradePack; import org.apache.commons.lang.StringUtils; import org.apache.ambari.server.serveraction.upgrades.ConfigureAction; import org.apache.ambari.server.state.Cluster; @@ -40,41 +38,21 @@ import org.apache.ambari.server.state.DesiredConfig; import com.google.gson.Gson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition.Transfer; +import static org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition.Replace; +import static org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition.Condition; +import static org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition.ConfigurationKeyValue; /** - * The {@link ConfigureTask} represents a configuration change. This task can be - * defined with conditional statements that will only set values if a condition - * passes: + * The {@link ConfigureTask} represents a configuration change. This task + * contains id of change. Change definitions are located in a separate file (config + * upgrade pack). IDs of change definitions share the same namespace within all + * stacks * <p/> * * <pre> * {@code - * <task xsi:type="configure"> - * <condition type="hive-site" key="hive.server2.transport.mode" value="binary"> - * <type>hive-site</type> - * <key>hive.server2.thrift.port</key> - * <value>10010</value> - * </condition> - * <condition type="hive-site" key="hive.server2.transport.mode" value="http"> - * <type>hive-site</type> - * <key>hive.server2.http.port</key> - * <value>10011</value> - * </condition> - * </task> - * } - * </pre> - * - * It's also possible to simple set values directly without a precondition - * check. - * - * <pre> - * {@code - * <task xsi:type="configure"> - * <type>hive-site</type> - * <set key="hive.server2.thrift.port" value="10010"/> - * <set key="foo" value="bar"/> - * <set key="foobar" value="baz"/> - * </task> + * <task xsi:type="configure" id="hdp_2_3_0_0-UpdateHiveConfig"/> * } * </pre> * @@ -109,6 +87,8 @@ public class ConfigureTask extends ServerSideActionTask { */ public static final String PARAMETER_REPLACEMENTS = "configure-task-replacements"; + public static final String actionVerb = "Configuring"; + /** * Gson */ @@ -116,29 +96,15 @@ public class ConfigureTask extends ServerSideActionTask { /** * Constructor. - * */ public ConfigureTask() { implClass = ConfigureAction.class.getName(); } - @XmlTransient private Task.Type type = Task.Type.CONFIGURE; - @XmlElement(name="type") - private String configType; - - @XmlElement(name = "set") - private List<ConfigurationKeyValue> keyValuePairs; - - @XmlElement(name = "condition") - private List<Condition> conditions; - - @XmlElement(name = "transfer") - private List<Transfer> transfers; - - @XmlElement(name="replace") - private List<Replace> replacements; + @XmlAttribute(name = "id") + public String id; /** * {@inheritDoc} @@ -148,220 +114,23 @@ public class ConfigureTask extends ServerSideActionTask { return type; } - /** - * @return the config type - */ - public String getConfigType() { - return configType; - } - - /** - * Used for configuration updates that should mask their values from being - * printed in plain text. - */ - @XmlAccessorType(XmlAccessType.FIELD) - public static class Masked { - @XmlAttribute(name = "mask") - public boolean mask = false; - } - - - /** - * A key/value pair to set in the type specified by {@link ConfigureTask#type} - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "set") - public static class ConfigurationKeyValue extends Masked { - @XmlAttribute(name = "key") - public String key; - - @XmlAttribute(name = "value") - public String value; - } - - /** - * A conditional element that will only perform the configuration if the - * condition is met. - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "condition") - public static class Condition { - @XmlAttribute(name = "type") - private String conditionConfigType; - - @XmlAttribute(name = "key") - private String conditionKey; - - @XmlAttribute(name = "value") - private String conditionValue; - - @XmlElement(name = "type") - private String configType; - - @XmlElement(name = "key") - private String key; - - @XmlElement(name = "value") - private String value; - } - - /** - * A {@code transfer} element will copy, move, or delete the value of one type/key to another type/key. - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "transfer") - public static class Transfer extends Masked { - /** - * The type of operation, such as COPY or DELETE. - */ - @XmlAttribute(name = "operation") - public TransferOperation operation; - - /** - * The configuration type to copy or move from. - */ - @XmlAttribute(name = "from-type") - public String fromType; - - /** - * The key to copy or move the configuration from. - */ - @XmlAttribute(name = "from-key") - public String fromKey; - - /** - * The key to copy the configuration value to. - */ - @XmlAttribute(name = "to-key") - public String toKey; - - /** - * The configuration key to delete, or "*" for all. - */ - @XmlAttribute(name = "delete-key") - public String deleteKey; - - /** - * If {@code true}, this will ensure that any changed properties are not - * removed during a {@link TransferOperation#DELETE}. - */ - @XmlAttribute(name = "preserve-edits") - public boolean preserveEdits = false; - - /** - * A default value to use when the configurations don't contain the - * {@link #fromKey}. - */ - @XmlAttribute(name = "default-value") - public String defaultValue; - - /** - * A data type to convert the configuration value to when the action is - * {@link TransferOperation#COPY}. - */ - @XmlAttribute(name = "coerce-to") - public TransferCoercionType coerceTo; - - // if the condition is true apply the transfer action - // only supported conditional action is DELETE - // if-type/if-key == if-value - /** - * The key to read for the if condition. - */ - @XmlAttribute(name = "if-key") - public String ifKey; - - /** - * The config type to read for the if condition. - */ - @XmlAttribute(name = "if-type") - public String ifType; - - /** - * The property value to compare against for the if condition. - */ - @XmlAttribute(name = "if-value") - public String ifValue; - - /** - * The keys to keep when the action is {@link TransferOperation#DELETE}. - */ - @XmlElement(name = "keep-key") - public List<String> keepKeys = new ArrayList<String>(); - } - - /** - * @return the list of transfers, checking for appropriate null fields. - */ - public List<Transfer> getTransfers() { - if (null == transfers) { - return Collections.<Transfer>emptyList(); - } - - List<Transfer> list = new ArrayList<Transfer>(); - for (Transfer t : transfers) { - switch (t.operation) { - case COPY: - case MOVE: - if (null != t.fromKey && null != t.toKey) { - list.add(t); - } - break; - case DELETE: - if (null != t.deleteKey) { - list.add(t); - } - - break; - } - } - - return list; + @Override + public StageWrapper.Type getStageWrapperType() { + return StageWrapper.Type.SERVER_SIDE_ACTION; } - /** - * Used to replace strings in a key with other strings. More complex - * scenarios will be possible with regex (when needed) - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "replace") - public static class Replace extends Masked { - /** - * The key name - */ - @XmlAttribute(name="key") - public String key; - - /** - * The string to find - */ - @XmlAttribute(name="find") - public String find; - - /** - * The string to replace - */ - @XmlAttribute(name="replace-with") - public String replaceWith; + @Override + public String getActionVerb() { + return actionVerb; } /** - * @return the replacement tokens, never {@code null} + * This getter is intended to be used only from tests. In production, + * getConfigurationChanges() logic should be used instead + * @return id of config upgrade change definition as defined in upgrade pack */ - public List<Replace> getReplacements() { - if (null == replacements) { - return Collections.emptyList(); - } - - List<Replace> list = new ArrayList<Replace>(); - for (Replace r : replacements) { - if (null == r.key || null == r.find || null == r.replaceWith) { - continue; - } - list.add(r); - } - - return list; + public String getId() { + return id; } /** @@ -385,21 +154,41 @@ public class ConfigureTask extends ServerSideActionTask { * handle a configuration task that is unable to set any configuration * values. */ - public Map<String, String> getConfigurationChanges(Cluster cluster) { - Map<String, String> configParameters = new HashMap<String, String>(); + public Map<String, String> getConfigurationChanges(Cluster cluster, + ConfigUpgradePack configUpgradePack) { + Map<String, String> configParameters = new HashMap<>(); + + if (this.id == null || this.id.isEmpty()) { + LOG.warn("Config task id is not defined, skipping config change"); + return configParameters; + } + + if (configUpgradePack == null) { + LOG.warn("Config upgrade pack is not defined, skipping config change"); + return configParameters; + } + + // extract config change definition, referenced by current ConfigureTask + ConfigUpgradeChangeDefinition definition = configUpgradePack.enumerateConfigChangesByID().get(this.id); + if (definition == null) { + LOG.warn(String.format("Can not resolve config change definition by id %s, " + + "skipping config change", this.id)); + return configParameters; + } // the first matched condition will win; conditions make configuration tasks singular in // the properties that can be set - when there is a condition the task will only contain // conditions + List<Condition> conditions = definition.getConditions(); if( null != conditions && !conditions.isEmpty() ){ for (Condition condition : conditions) { - String conditionConfigType = condition.conditionConfigType; - String conditionKey = condition.conditionKey; - String conditionValue = condition.conditionValue; + String conditionConfigType = condition.getConditionConfigType(); + String conditionKey = condition.getConditionKey(); + String conditionValue = condition.getConditionValue(); // always add the condition's target type just so that we have one to // return even if none of the conditions match - configParameters.put(PARAMETER_CONFIG_TYPE, condition.configType); + configParameters.put(PARAMETER_CONFIG_TYPE, condition.getConfigType()); // check the condition; if it passes, set the configuration properties // and break @@ -407,10 +196,10 @@ public class ConfigureTask extends ServerSideActionTask { conditionConfigType, conditionKey); if (conditionValue.equals(checkValue)) { - List<ConfigurationKeyValue> configurations = new ArrayList<ConfigurationKeyValue>(1); + List<ConfigurationKeyValue> configurations = new ArrayList<>(1); ConfigurationKeyValue keyValue = new ConfigurationKeyValue(); - keyValue.key = condition.key; - keyValue.value = condition.value; + keyValue.key = condition.getKey(); + keyValue.value = condition.getValue(); configurations.add(keyValue); configParameters.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, @@ -422,20 +211,21 @@ public class ConfigureTask extends ServerSideActionTask { } // this task is not a condition task, so process the other elements normally - if (null != configType) { - configParameters.put(PARAMETER_CONFIG_TYPE, configType); + if (null != definition.getConfigType()) { + configParameters.put(PARAMETER_CONFIG_TYPE, definition.getConfigType()); } // for every <set key=foo value=bar/> add it to this list - if (null != keyValuePairs && !keyValuePairs.isEmpty()) { + if (null != definition.getKeyValuePairs() && !definition.getKeyValuePairs().isEmpty()) { configParameters.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, - m_gson.toJson(keyValuePairs)); + m_gson.toJson(definition.getKeyValuePairs())); } // transfers + List<Transfer> transfers = definition.getTransfers(); if (null != transfers && !transfers.isEmpty()) { - List<Transfer> allowedTransfers = new ArrayList<Transfer>(); + List<Transfer> allowedTransfers = new ArrayList<>(); for (Transfer transfer : transfers) { if (transfer.operation == TransferOperation.DELETE) { if (StringUtils.isNotBlank(transfer.ifKey) && @@ -450,7 +240,7 @@ public class ConfigureTask extends ServerSideActionTask { if (!ifValue.toLowerCase().equals(StringUtils.lowerCase(checkValue))) { // skip adding LOG.info("Skipping property delete for {}/{} as the value {} for {}/{} is not equal to {}", - this.getConfigType(), transfer.deleteKey, checkValue, ifConfigType, ifKey, ifValue); + definition.getConfigType(), transfer.deleteKey, checkValue, ifConfigType, ifKey, ifValue); continue; } } @@ -461,6 +251,7 @@ public class ConfigureTask extends ServerSideActionTask { } // replacements + List<Replace> replacements = definition.getReplacements(); if( null != replacements && !replacements.isEmpty() ){ configParameters.put(ConfigureTask.PARAMETER_REPLACEMENTS, m_gson.toJson(replacements)); } @@ -496,4 +287,4 @@ public class ConfigureTask extends ServerSideActionTask { return config.getProperties().get(propertyKey); } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ExecuteTask.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ExecuteTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ExecuteTask.java index a0afdfb..d175a13 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ExecuteTask.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ExecuteTask.java @@ -66,8 +66,20 @@ public class ExecuteTask extends Task { @XmlElement(name="command") public String command; + public static final String actionVerb = "Executing"; + @Override public Task.Type getType() { return type; } + + @Override + public StageWrapper.Type getStageWrapperType() { + return StageWrapper.Type.RU_TASKS; + } + + @Override + public String getActionVerb() { + return actionVerb; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java index cd27722..d6db9b1 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Grouping.java @@ -36,7 +36,7 @@ import org.apache.commons.lang.StringUtils; /** * */ -@XmlSeeAlso(value = { ColocatedGrouping.class, ClusterGrouping.class, ServiceCheckGrouping.class }) +@XmlSeeAlso(value = { ColocatedGrouping.class, ClusterGrouping.class, UpdateStackGrouping.class, ServiceCheckGrouping.class, RestartGrouping.class, StartGrouping.class, StopGrouping.class }) public class Grouping { @XmlAttribute(name="name") @@ -60,7 +60,6 @@ public class Grouping { @XmlElement(name="direction") public Direction intendedDirection = null; - /** * Gets the default builder. */ @@ -68,7 +67,6 @@ public class Grouping { return new DefaultBuilder(this, performServiceCheck); } - private static class DefaultBuilder extends StageWrapperBuilder { private List<StageWrapper> m_stages = new ArrayList<StageWrapper>(); @@ -93,6 +91,7 @@ public class Grouping { boolean forUpgrade = ctx.getDirection().isUpgrade(); + // Construct the pre tasks during Upgrade/Downgrade direction. List<TaskBucket> buckets = buckets(resolveTasks(forUpgrade, true, pc)); for (TaskBucket bucket : buckets) { List<TaskWrapper> preTasks = TaskWrapperBuilder.getTaskList(service, pc.name, hostsType, bucket.tasks); @@ -107,20 +106,20 @@ public class Grouping { } } - // !!! FIXME upgrade definition have only one step, and it better be a restart + // Add the processing component if (null != pc.tasks && 1 == pc.tasks.size()) { Task t = pc.tasks.get(0); - if (RestartTask.class.isInstance(t)) { - for (String hostName : hostsType.hosts) { - StageWrapper stage = new StageWrapper( - StageWrapper.Type.RESTART, - getStageText("Restarting", ctx.getComponentDisplay(service, pc.name), Collections.singleton(hostName)), - new TaskWrapper(service, pc.name, Collections.singleton(hostName), t)); - m_stages.add(stage); - } + + for (String hostName : hostsType.hosts) { + StageWrapper stage = new StageWrapper( + t.getStageWrapperType(), + getStageText(t.getActionVerb(), ctx.getComponentDisplay(service, pc.name), Collections.singleton(hostName)), + new TaskWrapper(service, pc.name, Collections.singleton(hostName), t)); + m_stages.add(stage); } } + // Construct the post tasks during Upgrade/Downgrade direction. buckets = buckets(resolveTasks(forUpgrade, false, pc)); for (TaskBucket bucket : buckets) { List<TaskWrapper> postTasks = TaskWrapperBuilder.getTaskList(service, pc.name, hostsType, bucket.tasks); @@ -135,13 +134,16 @@ public class Grouping { } } - if (!clientOnly) { + // Potentially add a service check + if (this.m_serviceCheck && !clientOnly) { m_servicesToCheck.add(service); } } /** - * {@inheritDoc} + * Determine if service checks need to be ran after the stages. + * @param upgradeContext the upgrade context + * @return Return the stages, which may potentially be followed by service checks. */ @Override public List<StageWrapper> build(UpgradeContext upgradeContext, @@ -202,7 +204,6 @@ public class Grouping { } return holders; - } private static class TaskBucket { @@ -221,6 +222,12 @@ public class Grouping { case RESTART: type = StageWrapper.Type.RESTART; break; + case START: + type = StageWrapper.Type.START; + break; + case STOP: + type = StageWrapper.Type.STOP; + break; case SERVICE_CHECK: type = StageWrapper.Type.SERVICE_CHECK; break; http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ManualTask.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ManualTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ManualTask.java index 2b1ba56..a0a347a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ManualTask.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ManualTask.java @@ -52,4 +52,8 @@ public class ManualTask extends ServerSideActionTask { return type; } + @Override + public StageWrapper.Type getStageWrapperType() { + return StageWrapper.Type.SERVER_SIDE_ACTION; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java index 2e17cf4..6a36522 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java @@ -22,7 +22,6 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.regex.Pattern; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.api.services.AmbariMetaInfo; @@ -159,47 +158,29 @@ public class RepositoryVersionHelper { * @param stackName stack name * @param stackVersion stack version * @param repositoryVersion target repository version + * @param upgradeType if not {@code null} null, will only return upgrade packs whose type matches. * @return upgrade pack name * @throws AmbariException if no upgrade packs suit the requirements */ - public String getUpgradePackageName(String stackName, String stackVersion, String repositoryVersion) throws AmbariException { + public String getUpgradePackageName(String stackName, String stackVersion, String repositoryVersion, UpgradeType upgradeType) throws AmbariException { final Map<String, UpgradePack> upgradePacks = ambariMetaInfo.getUpgradePacks(stackName, stackVersion); - for (Entry<String, UpgradePack> upgradePackEntry : upgradePacks.entrySet()) { - final UpgradePack upgradePack = upgradePackEntry.getValue(); - final String upgradePackName = upgradePackEntry.getKey(); + for (UpgradePack upgradePack : upgradePacks.values()) { + final String upgradePackName = upgradePack.getName(); + + if (null != upgradeType && upgradePack.getType() != upgradeType) { + continue; + } + // check that upgrade pack has <target> node if (StringUtils.isBlank(upgradePack.getTarget())) { LOG.error("Upgrade pack " + upgradePackName + " is corrupted, it should contain <target> node"); continue; } - - // check that upgrade pack can be applied to selected stack - // converting 2.2.*.* -> 2\.2(\.\d+)?(\.\d+)?(-\d+)? - String regexPattern = upgradePack.getTarget(); - regexPattern = regexPattern.replaceAll("\\.", "\\\\."); // . -> \. - regexPattern = regexPattern.replaceAll("\\\\\\.\\*", "(\\\\\\.\\\\d+)?"); // \.* -> (\.\d+)? - regexPattern = regexPattern.concat("(-\\d+)?"); - if (Pattern.matches(regexPattern, repositoryVersion)) { + if (upgradePack.canBeApplied(repositoryVersion)) { return upgradePackName; } } - throw new AmbariException("There were no suitable upgrade packs for stack " + stackName + " " + stackVersion); - } - - /** - * Scans the given stack for upgrade packages which can be applied to update the cluster to given repository version. - * Returns NONE if there were no suitable packages. - * - * @param stackName stack name - * @param stackVersion stack version - * @param repositoryVersion target repository version - * @return upgrade pack name or NONE - */ - public String getUpgradePackageNameSafe(String stackName, String stackVersion, String repositoryVersion) { - try { - return getUpgradePackageName(stackName, stackVersion, repositoryVersion); - } catch (AmbariException ex) { - return "NONE"; - } + throw new AmbariException("There were no suitable upgrade packs for stack " + stackName + " " + stackVersion + + ((null != upgradeType) ? " and upgrade type " + upgradeType : "")); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RestartGrouping.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RestartGrouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RestartGrouping.java new file mode 100644 index 0000000..529cadd --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RestartGrouping.java @@ -0,0 +1,36 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack.upgrade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.annotation.XmlType; + +/** + * Used for a group that restarts services. + */ +@XmlType(name="restart") +public class RestartGrouping extends Grouping implements UpgradeFunction { + + private static Logger LOG = LoggerFactory.getLogger(RestartGrouping.class); + + @Override + public Task.Type getFunction() { + return Task.Type.RESTART; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RestartTask.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RestartTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RestartTask.java index 1b69b5b..fac0179 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RestartTask.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RestartTask.java @@ -28,14 +28,26 @@ import javax.xml.bind.annotation.XmlType; */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name="restart") +@XmlType(name="restart-task") public class RestartTask extends Task { @XmlTransient private Task.Type type = Task.Type.RESTART; + public static final String actionVerb = "Restarting"; + @Override public Task.Type getType() { return type; } + + @Override + public StageWrapper.Type getStageWrapperType() { + return StageWrapper.Type.RESTART; + } + + @Override + public String getActionVerb() { + return actionVerb; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerActionTask.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerActionTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerActionTask.java index 74144b7..5f6438c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerActionTask.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerActionTask.java @@ -39,4 +39,8 @@ public class ServerActionTask extends ServerSideActionTask { return type; } + @Override + public StageWrapper.Type getStageWrapperType() { + return StageWrapper.Type.SERVER_SIDE_ACTION; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerSideActionTask.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerSideActionTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerSideActionTask.java index 97981ae..595465d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerSideActionTask.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerSideActionTask.java @@ -27,7 +27,14 @@ public abstract class ServerSideActionTask extends Task { @XmlAttribute(name="class") protected String implClass; + public static final String actionVerb = "Executing"; + public String getImplementationClass() { return implClass; } + + @Override + public String getActionVerb() { + return actionVerb; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckGrouping.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckGrouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckGrouping.java index 6061895..fec9978 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckGrouping.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckGrouping.java @@ -50,10 +50,17 @@ public class ServiceCheckGrouping extends Grouping { private static Logger LOG = LoggerFactory.getLogger(ServiceCheckGrouping.class); + /** + * During a Rolling Upgrade, the priority services are ran first, then the remaining services in the cluster. + * During a Stop-and-Start Upgrade, only the priority services are ran. + */ @XmlElementWrapper(name="priority") @XmlElement(name="service") private Set<String> priorityServices = new LinkedHashSet<String>(); + /** + * During a Rolling Upgrade, exclude certain services. + */ @XmlElementWrapper(name="exclude") @XmlElement(name="service") private Set<String> excludeServices = new HashSet<String>(); @@ -122,29 +129,42 @@ public class ServiceCheckGrouping extends Grouping { for (String service : priorityServices) { if (checkServiceValidity(upgradeContext, service, serviceMap)) { StageWrapper wrapper = new StageWrapper( - StageWrapper.Type.SERVICE_CHECK, - "Service Check " + upgradeContext.getServiceDisplay(service), - new TaskWrapper(service, "", Collections.<String>emptySet(), - new ServiceCheckTask())); + StageWrapper.Type.SERVICE_CHECK, + "Service Check " + upgradeContext.getServiceDisplay(service), + new TaskWrapper(service, "", Collections.<String>emptySet(), + new ServiceCheckTask())); result.add(wrapper); clusterServices.remove(service); } } - // create stages for everything else, as long it is valid - for (String service : clusterServices) { - if (excludeServices.contains(service)) { - continue; - } + if (upgradeContext.getType() == UpgradeType.ROLLING) { + // During Rolling Upgrade, create stages for everything else, as long it is valid + for (String service : clusterServices) { + if (ServiceCheckGrouping.this.excludeServices.contains(service)) { + continue; + } + if (checkServiceValidity(upgradeContext, service, serviceMap)) { + StageWrapper wrapper = new StageWrapper( + StageWrapper.Type.SERVICE_CHECK, + "Service Check " + upgradeContext.getServiceDisplay(service), + new TaskWrapper(service, "", Collections.<String>emptySet(), + new ServiceCheckTask())); + result.add(wrapper); + } + if (excludeServices.contains(service)) { + continue; + } - if (checkServiceValidity(upgradeContext, service, serviceMap)) { - StageWrapper wrapper = new StageWrapper( + if (checkServiceValidity(upgradeContext, service, serviceMap)) { + StageWrapper wrapper = new StageWrapper( StageWrapper.Type.SERVICE_CHECK, "Service Check " + upgradeContext.getServiceDisplay(service), new TaskWrapper(service, "", Collections.<String>emptySet(), - new ServiceCheckTask())); - result.add(wrapper); + new ServiceCheckTask())); + result.add(wrapper); + } } } return result; http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckTask.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckTask.java index 5893edf..d6c19b8 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckTask.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServiceCheckTask.java @@ -34,8 +34,20 @@ public class ServiceCheckTask extends Task { @XmlTransient private Task.Type type = Task.Type.SERVICE_CHECK; + public static final String actionVerb = "Running"; + @Override public Task.Type getType() { return type; } + + @Override + public StageWrapper.Type getStageWrapperType() { + return StageWrapper.Type.SERVICE_CHECK; + } + + @Override + public String getActionVerb() { + return actionVerb; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapper.java index eac5ce5..92df3b5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapper.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapper.java @@ -92,7 +92,7 @@ public class StageWrapper { } /** - * @param text the new text for the stage + * @param newText the new text for the stage */ public void setText(String newText) { text = newText; @@ -113,6 +113,8 @@ public class StageWrapper { SERVER_SIDE_ACTION, RESTART, RU_TASKS, - SERVICE_CHECK + SERVICE_CHECK, + STOP, + START } } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java index 57cd41f..d4ee9a8 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java @@ -17,6 +17,7 @@ */ package org.apache.ambari.server.state.stack.upgrade; +import java.util.Collections; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -28,7 +29,7 @@ import org.apache.ambari.server.state.UpgradeContext; import org.apache.ambari.server.state.stack.UpgradePack.ProcessingComponent; /** - * Defines how to build stages. + * Defines how to build stages for an Upgrade or Downgrade. */ public abstract class StageWrapperBuilder { @@ -182,9 +183,14 @@ public abstract class StageWrapperBuilder { * @param forUpgrade {@code true} if resolving for an upgrade, {@code false} for downgrade * @param preTasks {@code true} if loading pre-upgrade or pre-downgrade * @param pc the processing component holding task definitions - * @return + * @return A collection, potentially empty, of the tasks to run, which may contain either + * pre or post tasks if they exist, and the order depends on whether it's an upgrade or downgrade. */ protected List<Task> resolveTasks(boolean forUpgrade, boolean preTasks, ProcessingComponent pc) { + if (null == pc) { + return Collections.emptyList(); + } + if (forUpgrade) { return preTasks ? pc.preTasks : pc.postTasks; } else { @@ -193,6 +199,4 @@ public abstract class StageWrapperBuilder { (null == pc.postDowngradeTasks ? pc.postTasks : pc.postDowngradeTasks); } } - - } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StartGrouping.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StartGrouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StartGrouping.java new file mode 100644 index 0000000..7237599 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StartGrouping.java @@ -0,0 +1,36 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack.upgrade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.annotation.XmlType; + +/** + * Used for a group that starts services. + */ +@XmlType(name="start") +public class StartGrouping extends Grouping implements UpgradeFunction { + + private static Logger LOG = LoggerFactory.getLogger(StartGrouping.class); + + @Override + public Task.Type getFunction() { + return Task.Type.START; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StartTask.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StartTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StartTask.java new file mode 100644 index 0000000..4d05dcb --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StartTask.java @@ -0,0 +1,53 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack.upgrade; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** + * Used to represent a start of a component. + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name="start-task") +public class StartTask extends Task { + + @XmlTransient + private Type type = Type.START; + + public static final String actionVerb = "Starting"; + + @Override + public Type getType() { + return type; + } + + @Override + public StageWrapper.Type getStageWrapperType() { + return StageWrapper.Type.START; + } + + @Override + public String getActionVerb() { + return actionVerb; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StopGrouping.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StopGrouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StopGrouping.java new file mode 100644 index 0000000..5cf1149 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StopGrouping.java @@ -0,0 +1,36 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack.upgrade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.annotation.XmlType; + +/** + * Used for a group that stops services. + */ +@XmlType(name="stop") +public class StopGrouping extends Grouping implements UpgradeFunction { + + private static Logger LOG = LoggerFactory.getLogger(StopGrouping.class); + + @Override + public Task.Type getFunction() { + return Task.Type.STOP; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StopTask.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StopTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StopTask.java new file mode 100644 index 0000000..30a557f --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StopTask.java @@ -0,0 +1,53 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack.upgrade; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** + * Used to represent a stop of a component. + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name="stop-task") +public class StopTask extends Task { + + @XmlTransient + private Type type = Type.STOP; + + public static final String actionVerb = "Stopping"; + + @Override + public Type getType() { + return type; + } + + @Override + public StageWrapper.Type getStageWrapperType() { + return StageWrapper.Type.STOP; + } + + @Override + public String getActionVerb() { + return actionVerb; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Task.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Task.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Task.java index 6416b57..f443e53 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Task.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Task.java @@ -24,7 +24,7 @@ import javax.xml.bind.annotation.XmlSeeAlso; /** * Base class to identify the items that could possibly occur during an upgrade */ -@XmlSeeAlso(value={ExecuteTask.class, ConfigureTask.class, ManualTask.class, RestartTask.class, ServerActionTask.class}) +@XmlSeeAlso(value={ExecuteTask.class, ConfigureTask.class, ManualTask.class, RestartTask.class, StartTask.class, StopTask.class, ServerActionTask.class}) public abstract class Task { /** @@ -38,6 +38,16 @@ public abstract class Task { */ public abstract Type getType(); + /** + * @return when a single Task is constructed, this is the type of stage it should belong to. + */ + public abstract StageWrapper.Type getStageWrapperType(); + + /** + * @return a verb to display that describes the type of task, e.g., "executing". + */ + public abstract String getActionVerb(); + @Override public String toString() { return getType().toString(); @@ -64,6 +74,14 @@ public abstract class Task { */ RESTART, /** + * Task that is a start command. + */ + START, + /** + * Task that is a stop command. + */ + STOP, + /** * Task that is a service check */ SERVICE_CHECK, @@ -83,7 +101,7 @@ public abstract class Task { * @return {@code true} if the task is a command type (as opposed to an action) */ public boolean isCommand() { - return this == RESTART || this == SERVICE_CHECK; + return this == RESTART || this == START || this == STOP || this == SERVICE_CHECK; } } } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpdateStackGrouping.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpdateStackGrouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpdateStackGrouping.java new file mode 100644 index 0000000..9dc9af8 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpdateStackGrouping.java @@ -0,0 +1,36 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack.upgrade; + + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Used to represent operations that update the Stack. + * This is primarily needed during a {@link UpgradeType#NON_ROLLING} upgrade. + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name="update-stack") +public class UpdateStackGrouping extends ClusterGrouping { + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpgradeFunction.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpgradeFunction.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpgradeFunction.java new file mode 100644 index 0000000..d58316d --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpgradeFunction.java @@ -0,0 +1,26 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack.upgrade; + +public interface UpgradeFunction { + + /** + * @return Return the function that the group must provide. + */ + public Task.Type getFunction(); +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpgradeType.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpgradeType.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpgradeType.java new file mode 100644 index 0000000..3acfb9f --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/UpgradeType.java @@ -0,0 +1,36 @@ +/** + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.state.stack.upgrade; + +import javax.xml.bind.annotation.XmlEnumValue; + +/** + * Indicates the type of Upgrade performed. + */ +public enum UpgradeType { + /** + * Services are up the entire time + */ + @XmlEnumValue("ROLLING") + ROLLING, + /** + * All services are stopped, then started + */ + @XmlEnumValue("NON_ROLLING") + NON_ROLLING; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java index 71d0581..c0804ff 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java @@ -1577,7 +1577,6 @@ public class ServiceComponentHostImpl implements ServiceComponentHost { stackEntity, version, stackId.getStackName() + "-" + version, - repositoryVersionHelper.getUpgradePackageNameSafe(stackId.getStackName(), stackId.getStackVersion(), version), repositoryVersionHelper.serializeOperatingSystems(stackInfo.getRepositories())); } http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql index 1511385..c82a584 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -541,7 +541,6 @@ CREATE TABLE repo_version ( stack_id BIGINT NOT NULL, version VARCHAR(255) NOT NULL, display_name VARCHAR(128) NOT NULL, - upgrade_package VARCHAR(255) NOT NULL, repositories LONGTEXT NOT NULL, PRIMARY KEY(repo_version_id) ); @@ -883,6 +882,8 @@ CREATE TABLE upgrade ( from_version VARCHAR(255) DEFAULT '' NOT NULL, to_version VARCHAR(255) DEFAULT '' NOT NULL, direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL, + upgrade_package VARCHAR(255) NOT NULL, + upgrade_type VARCHAR(32) NOT NULL, PRIMARY KEY (upgrade_id), FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id), FOREIGN KEY (request_id) REFERENCES request(request_id) http://git-wip-us.apache.org/repos/asf/ambari/blob/c58162fe/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql index a3c1625..17e5ddc 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -530,7 +530,6 @@ CREATE TABLE repo_version ( stack_id NUMBER(19) NOT NULL, version VARCHAR2(255) NOT NULL, display_name VARCHAR2(128) NOT NULL, - upgrade_package VARCHAR2(255) NOT NULL, repositories CLOB NOT NULL, PRIMARY KEY(repo_version_id) ); @@ -872,6 +871,8 @@ CREATE TABLE upgrade ( from_version VARCHAR2(255) DEFAULT '' NOT NULL, to_version VARCHAR2(255) DEFAULT '' NOT NULL, direction VARCHAR2(255) DEFAULT 'UPGRADE' NOT NULL, + upgrade_package VARCHAR2(255) NOT NULL, + upgrade_type VARCHAR2(32) NOT NULL, PRIMARY KEY (upgrade_id), FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id), FOREIGN KEY (request_id) REFERENCES request(request_id)