Repository: ambari Updated Branches: refs/heads/branch-dev-patch-upgrade efcfced54 -> 1f8b527f9
AMBARI-18937. Allow generic Service Upgrade Packs for all targets (ncole) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7d07b71d Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7d07b71d Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7d07b71d Branch: refs/heads/branch-dev-patch-upgrade Commit: 7d07b71de7019efaaa04fe8c09548cdc604cea60 Parents: ef91365 Author: Nate Cole <[email protected]> Authored: Mon Nov 21 15:24:59 2016 -0500 Committer: Nate Cole <[email protected]> Committed: Mon Nov 21 16:11:21 2016 -0500 ---------------------------------------------------------------------- .../apache/ambari/server/stack/StackModule.java | 101 +++++++++++++++++-- .../ambari/server/state/stack/UpgradePack.java | 12 ++- .../stacks/HDP/2.3/upgrades/upgrade-2.5.xml | 4 +- .../stacks/HDP/2.3/upgrades/upgrade-2.6.xml | 4 +- .../stacks/HDP/2.4/upgrades/upgrade-2.5.xml | 4 +- .../stacks/HDP/2.4/upgrades/upgrade-2.6.xml | 4 +- .../src/main/resources/upgrade-pack.xsd | 10 +- .../server/state/stack/UpgradePackTest.java | 22 ++++ .../GANGLIA/upgrades/HDP/rolling-upgrade.xml | 27 +++++ 9 files changed, 168 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/7d07b71d/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java index d9eaf27..ce606de 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java @@ -46,16 +46,19 @@ import org.apache.ambari.server.state.stack.ServiceMetainfoXml; import org.apache.ambari.server.state.stack.StackMetainfoXml; import org.apache.ambari.server.state.stack.UpgradePack; import org.apache.ambari.server.state.stack.upgrade.Grouping; +import org.apache.ambari.server.state.stack.upgrade.UpgradeType; +import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Function; -import com.google.common.collect.ListMultimap; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimaps; + /** * Stack module which provides all functionality related to parsing and fully * resolving stacks from the stack definition. @@ -834,6 +837,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V if (configPack == null) { return; } + for (ServiceModule module : serviceModules.values()) { File upgradesFolder = module.getModuleInfo().getServiceUpgradesFolder(); if (upgradesFolder != null) { @@ -869,12 +873,17 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V private UpgradePack getServiceUpgradePack(UpgradePack pack, File upgradesFolder) throws AmbariException { File stackFolder = new File(upgradesFolder, stackInfo.getName()); File versionFolder = new File(stackFolder, stackInfo.getVersion()); + // !!! relies on the service upgrade pack filename being named the exact same File servicePackFile = new File(versionFolder, pack.getName() + ".xml"); + LOG.info("Service folder: " + servicePackFile.getAbsolutePath()); - if (!servicePackFile.exists()) { - return null; + if (servicePackFile.exists()) { + return parseServiceUpgradePack(pack, servicePackFile); + } else { + UpgradePack child = findServiceUpgradePack(pack, stackFolder); + + return null == child ? null : parseServiceUpgradePack(pack, child); } - return parseServiceUpgradePack(pack, servicePackFile); } /** @@ -882,6 +891,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V * for any service which specifies its own upgrade. */ private void mergeUpgradePack(UpgradePack pack, List<UpgradePack> servicePacks) throws AmbariException { + List<Grouping> originalGroups = pack.getAllGroups(); Map<String, List<Grouping>> allGroupMap = new HashMap<>(); for (Grouping group : originalGroups) { @@ -889,8 +899,21 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V list.add(group); allGroupMap.put(group.name, list); } + for (UpgradePack servicePack : servicePacks) { for (Grouping group : servicePack.getAllGroups()) { + + /* + !!! special case where the service pack is targeted for any version. When + a service UP targets to run after another group, check to make sure that the + base UP contains the group. + */ + if (servicePack.isAllTarget() && !allGroupMap.keySet().contains(group.addAfterGroup)) { + LOG.warn("Service Upgrade Pack specified after-group of {}, but that is not found in {}", + group.addAfterGroup, StringUtils.join(allGroupMap.keySet(), ',')); + continue; + } + if (allGroupMap.containsKey(group.name)) { List<Grouping> list = allGroupMap.get(group.name); Grouping first = list.get(0); @@ -906,8 +929,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V else { list.add(group); } - } - else { + } else { List<Grouping> list = new ArrayList<>(); list.add(group); allGroupMap.put(group.name, list); @@ -934,15 +956,17 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V */ private void orderGroups(List<Grouping> groups, Map<String, Grouping> mergedGroupMap) throws AmbariException { Map<String, List<Grouping>> skippedGroups = new HashMap<>(); + for (Map.Entry<String, Grouping> entry : mergedGroupMap.entrySet()) { - String key = entry.getKey(); Grouping group = entry.getValue(); + if (!groups.contains(group)) { boolean added = addGrouping(groups, group); if (added) { addSkippedGroup(groups, skippedGroups, group); } else { List<Grouping> tmp = null; + // store the group until later if (skippedGroups.containsKey(group.addAfterGroup)) { tmp = skippedGroups.get(group.addAfterGroup); @@ -954,6 +978,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V } } } + if (!skippedGroups.isEmpty()) { throw new AmbariException("Missing groups: " + skippedGroups.keySet()); } @@ -999,6 +1024,50 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V } /** + * Finds an upgrade pack that: + * <ul> + * <li>Is found in the $SERVICENAME/upgrades/$STACKNAME folder</li> + * <li>Matches the same {@link UpgradeType#getType()}as the {@code base} upgrade pack</li> + * <li>Has the {@link UpgradePack#getTarget()} value equals to "*"</li> + * <li>Has the {@link UpgradePack#getTargetStack()} value equals to "*"</li> + * </ul> + * This method will not attempt to resolve the "most correct" upgrade pack. For this + * feature to work, there should be only one upgrade pack per type. If more specificity + * is required, then follow the convention of $SERVICENAME/upgrades/$STACKNAME/$STACKVERSION/$BASE_FILE_NAME.xml + * + * @param base the base upgrade pack for a stack + * @param upgradeStackDirectory service directory that contains stack upgrade files. + * @return an upgrade pack that matches {@code base} + */ + private UpgradePack findServiceUpgradePack(UpgradePack base, File upgradeStackDirectory) { + if (!upgradeStackDirectory.exists() || !upgradeStackDirectory.isDirectory()) { + return null; + } + + File[] upgradeFiles = upgradeStackDirectory.listFiles(StackDirectory.XML_FILENAME_FILTER); + if (0 == upgradeFiles.length) { + return null; + } + + for (File f : upgradeFiles) { + try { + UpgradePack upgradePack = unmarshaller.unmarshal(UpgradePack.class, f); + + // !!! if the type is the same and the target is "*", then it's good to merge + if (upgradePack.isAllTarget() && upgradePack.getType() == base.getType()) { + return upgradePack; + } + + } catch (Exception e) { + LOG.warn("File {} does not appear to be an upgrade pack and will be skipped ({})", + f.getAbsolutePath(), e.getMessage()); + } + } + + return null; + } + + /** * Parses the service specific upgrade file and merges the none order elements * (prerequisite check and processing sections). */ @@ -1011,12 +1080,24 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V throw new AmbariException("Unable to parse service upgrade file at location: " + serviceFile.getAbsolutePath(), e); } - parent.mergePrerequisiteChecks(pack); - parent.mergeProcessing(pack); + return parseServiceUpgradePack(parent, pack); + } - return pack; + /** + * Places prerequisite checks and processing objects onto the parent upgrade pack. + * + * @param parent the parent upgrade pack + * @param child the parsed child upgrade pack + * @return the child upgrade pack + */ + private UpgradePack parseServiceUpgradePack(UpgradePack parent, UpgradePack child) { + parent.mergePrerequisiteChecks(child); + parent.mergeProcessing(child); + + return child; } + /** * Process repositories associated with the stack. * @throws AmbariException if unable to fully process the stack repositories http://git-wip-us.apache.org/repos/asf/ambari/blob/7d07b71d/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 edf5c89..aa97fa3 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 @@ -52,6 +52,8 @@ import org.slf4j.LoggerFactory; @XmlAccessorType(XmlAccessType.FIELD) public class UpgradePack { + private static final String ALL_VERSIONS = "*"; + private static Logger LOG = LoggerFactory.getLogger(UpgradePack.class); /** @@ -315,7 +317,6 @@ public class UpgradePack { 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+)?"); @@ -453,6 +454,15 @@ public class UpgradePack { } /** + * @return {@code true} if the upgrade targets any version or stack. Both + * {@link #target} and {@link #targetStack} must equal "*" + */ + public boolean isAllTarget() { + return ALL_VERSIONS.equals(target) && ALL_VERSIONS.equals(targetStack); + } + + + /** * A service definition that holds a list of components in the 'order' element. */ public static class OrderService { http://git-wip-us.apache.org/repos/asf/ambari/blob/7d07b71d/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml index a838fc7..e675633 100644 --- a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml +++ b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml @@ -421,7 +421,7 @@ </execute-stage> </group> - <group xsi:type="stop" name="STOP_STORM" title="Stop Storm Services"> + <group xsi:type="stop" name="STOP_STORM_UPGRADE" title="Stop Storm Services"> <direction>UPGRADE</direction> <service-check>false</service-check> <skippable>true</skippable> @@ -443,7 +443,7 @@ </service> </group> - <group xsi:type="stop" name="STOP_STORM" title="Stop Storm Services"> + <group xsi:type="stop" name="STOP_STORM_DOWNGRADE" title="Stop Storm Services"> <direction>DOWNGRADE</direction> <service-check>false</service-check> <skippable>true</skippable> http://git-wip-us.apache.org/repos/asf/ambari/blob/7d07b71d/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.6.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.6.xml b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.6.xml index a01996a..7d4cfc9 100644 --- a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.6.xml +++ b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.6.xml @@ -422,7 +422,7 @@ </execute-stage> </group> - <group xsi:type="stop" name="STOP_STORM" title="Stop Storm Services"> + <group xsi:type="stop" name="STOP_STORM_UPGRADE" title="Stop Storm Services"> <direction>UPGRADE</direction> <service-check>false</service-check> <skippable>true</skippable> @@ -444,7 +444,7 @@ </service> </group> - <group xsi:type="stop" name="STOP_STORM" title="Stop Storm Services"> + <group xsi:type="stop" name="STOP_STORM_DOWNGRADE" title="Stop Storm Services"> <direction>DOWNGRADE</direction> <service-check>false</service-check> <skippable>true</skippable> http://git-wip-us.apache.org/repos/asf/ambari/blob/7d07b71d/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml b/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml index 17be4a8..effdda2 100644 --- a/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml +++ b/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml @@ -406,7 +406,7 @@ </execute-stage> </group> - <group xsi:type="stop" name="STOP_STORM" title="Stop Storm Services"> + <group xsi:type="stop" name="STOP_STORM_UPGRADE" title="Stop Storm Services"> <direction>UPGRADE</direction> <service-check>false</service-check> <skippable>true</skippable> @@ -428,7 +428,7 @@ </service> </group> - <group xsi:type="stop" name="STOP_STORM" title="Stop Storm Services"> + <group xsi:type="stop" name="STOP_STORM_DOWNGRADE" title="Stop Storm Services"> <direction>DOWNGRADE</direction> <service-check>false</service-check> <skippable>true</skippable> http://git-wip-us.apache.org/repos/asf/ambari/blob/7d07b71d/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.6.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.6.xml b/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.6.xml index f520faf..31e72a1 100644 --- a/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.6.xml +++ b/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.6.xml @@ -411,7 +411,7 @@ </execute-stage> </group> - <group xsi:type="stop" name="STOP_STORM" title="Stop Storm Services"> + <group xsi:type="stop" name="STOP_STORM_UPGRADE" title="Stop Storm Services"> <direction>UPGRADE</direction> <service-check>false</service-check> <skippable>true</skippable> @@ -433,7 +433,7 @@ </service> </group> - <group xsi:type="stop" name="STOP_STORM" title="Stop Storm Services"> + <group xsi:type="stop" name="STOP_STORM_DOWNGRADE" title="Stop Storm Services"> <direction>DOWNGRADE</direction> <service-check>false</service-check> <skippable>true</skippable> http://git-wip-us.apache.org/repos/asf/ambari/blob/7d07b71d/ambari-server/src/main/resources/upgrade-pack.xsd ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/upgrade-pack.xsd b/ambari-server/src/main/resources/upgrade-pack.xsd index 2871f05..45cf5fa 100644 --- a/ambari-server/src/main/resources/upgrade-pack.xsd +++ b/ambari-server/src/main/resources/upgrade-pack.xsd @@ -392,7 +392,15 @@ <xs:element name="type" type="upgrade-kind-type" /> <xs:element name="prerequisite-checks" type="prerequisite-check-type" minOccurs="0" /> <xs:element name="upgrade-path" type="upgrade-path-type" minOccurs="0" /> - <xs:element name="order" type="order-type" /> + <xs:element name="order" type="order-type"> + <xs:unique name="unique-by-group"> + <xs:annotation> + <xs:documentation>Ensures that the element "processing" does not have duplicate services</xs:documentation> + </xs:annotation> + <xs:selector xpath="group" /> + <xs:field xpath="@name" /> + </xs:unique> + </xs:element> <xs:element name="processing" type="processing-type"> <xs:unique name="unique-by-service"> <xs:annotation> http://git-wip-us.apache.org/repos/asf/ambari/blob/7d07b71d/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java index dde7ffa..8f9f791 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java @@ -18,6 +18,7 @@ package org.apache.ambari.server.state.stack; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -570,6 +571,27 @@ public class UpgradePackTest { Map<String, Map<String, ProcessingComponent>> tasks = upgradePack.getTasks(); assertTrue(tasks.containsKey("HBASE")); + + // !!! generalized upgrade pack shouldn't be in this + boolean found = false; + for (Grouping grouping : upgradePack.getAllGroups()) { + if (grouping.name.equals("GANGLIA_UPGRADE")) { + found = true; + break; + } + } + assertFalse(found); + + // !!! test merge of a generalized upgrade pack + upgradePack = upgrades.get("upgrade_test_conditions"); + assertNotNull(upgradePack); + for (Grouping grouping : upgradePack.getAllGroups()) { + if (grouping.name.equals("GANGLIA_UPGRADE")) { + found = true; + break; + } + } + assertTrue(found); } http://git-wip-us.apache.org/repos/asf/ambari/blob/7d07b71d/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/GANGLIA/upgrades/HDP/rolling-upgrade.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/GANGLIA/upgrades/HDP/rolling-upgrade.xml b/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/GANGLIA/upgrades/HDP/rolling-upgrade.xml new file mode 100644 index 0000000..c2224dd --- /dev/null +++ b/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/GANGLIA/upgrades/HDP/rolling-upgrade.xml @@ -0,0 +1,27 @@ +<?xml version="1.0"?> + +<upgrade xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="upgrade-pack.xsd"> + <target>*</target> + <target-stack>*</target-stack> + <type>ROLLING</type> + <order> + <group name="GANGLIA_UPGRADE" title="Ganglia"> + <add-after-group>ZOOKEEPER_CONFIG_CONDITION_TEST</add-after-group> + <skippable>true</skippable> + <allow-retry>true</allow-retry> + <service name="GANGLIA"> + <component>HST_SERVER</component> + </service> + </group> + </order> + + <processing> + <service name="GANGLIA"> + <component name="GANGLIA_SERVER"> + <upgrade> + <task xsi:type="restart-task" /> + </upgrade> + </component> + </service> + </processing> +</upgrade> \ No newline at end of file
