Browse Source

AMBARI-19527. Downgrade executes <pre-upgrade> section if <pre-downgrade> is not defined (ncole)

Nate Cole 8 years ago
parent
commit
4e1fabb3ac
43 changed files with 653 additions and 78 deletions
  1. 11 0
      ambari-server/src/main/java/org/apache/ambari/server/stack/ModuleFileUnmarshaller.java
  2. 62 5
      ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java
  3. 2 4
      ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java
  4. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml
  5. 9 0
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.4.xml
  6. 8 0
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml
  7. 9 0
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.6.xml
  8. 13 0
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml
  9. 6 0
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.4.xml
  10. 12 1
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml
  11. 11 0
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.6.xml
  12. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.4.xml
  13. 8 0
      ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml
  14. 8 0
      ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.6.xml
  15. 9 0
      ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.4.xml
  16. 9 0
      ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml
  17. 8 0
      ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.6.xml
  18. 9 0
      ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/host-upgrade-2.5.xml
  19. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml
  20. 4 0
      ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.6.xml
  21. 9 0
      ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.5.xml
  22. 10 0
      ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.6.xml
  23. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/host-upgrade-2.6.xml
  24. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/nonrolling-upgrade-2.6.xml
  25. 7 0
      ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/upgrade-2.6.xml
  26. 11 3
      ambari-server/src/main/resources/upgrade-pack.xsd
  27. 1 1
      ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
  28. 92 0
      ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackParsingTest.java
  29. 106 62
      ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java
  30. 4 0
      ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_bucket_test.xml
  31. 133 0
      ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_component_tasks_test.xml
  32. 5 0
      ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_direction.xml
  33. 6 0
      ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_nonrolling_new_stack.xml
  34. 8 0
      ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test.xml
  35. 6 0
      ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test_checks.xml
  36. 8 0
      ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test_partial.xml
  37. 8 2
      ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_to_new_stack.xml
  38. 7 0
      ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test.xml
  39. 7 0
      ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_15388.xml
  40. 6 0
      ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_checks.xml
  41. 2 0
      ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_host_ordered.xml
  42. 2 0
      ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_skip_failures.xml
  43. 7 0
      ambari-server/src/test/resources/stacks_with_upgrade_cycle/HDP/2.2.0/upgrades/upgrade_test_15388.xml

+ 11 - 0
ambari-server/src/main/java/org/apache/ambari/server/stack/ModuleFileUnmarshaller.java

@@ -45,6 +45,7 @@ import org.apache.ambari.server.state.stack.ServiceMetainfoXml;
 import org.apache.ambari.server.state.stack.StackMetainfoXml;
 import org.apache.ambari.server.state.stack.StackMetainfoXml;
 import org.apache.ambari.server.state.stack.UpgradePack;
 import org.apache.ambari.server.state.stack.UpgradePack;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXException;
@@ -133,6 +134,16 @@ public class ModuleFileUnmarshaller {
 
 
     try {
     try {
       return clz.cast(u.unmarshal(file));
       return clz.cast(u.unmarshal(file));
+    } catch (Exception unmarshalException) {
+
+      Throwable cause = ExceptionUtils.getRootCause(unmarshalException);
+
+      LOG.error("Cannot parse {}", file.getAbsolutePath());
+      if (null != cause) {
+        LOG.error(cause.getMessage(), cause);
+      }
+
+      throw unmarshalException;
     } finally {
     } finally {
       IOUtils.closeQuietly(xsdStream);
       IOUtils.closeQuietly(xsdStream);
     }
     }

+ 62 - 5
ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java

@@ -509,11 +509,11 @@ public class UpgradePack {
     @XmlElement(name="task")
     @XmlElement(name="task")
     public List<Task> preTasks;
     public List<Task> preTasks;
 
 
-    @XmlElementWrapper(name="pre-downgrade")
-    @XmlElement(name="task")
+    @XmlElement(name="pre-downgrade")
+    private DowngradeTasks preDowngradeXml;
+    @XmlTransient
     public List<Task> preDowngradeTasks;
     public List<Task> preDowngradeTasks;
 
 
-
     @XmlElementWrapper(name="upgrade")
     @XmlElementWrapper(name="upgrade")
     @XmlElement(name="task")
     @XmlElement(name="task")
     public List<Task> tasks;
     public List<Task> tasks;
@@ -522,9 +522,53 @@ public class UpgradePack {
     @XmlElement(name="task")
     @XmlElement(name="task")
     public List<Task> postTasks;
     public List<Task> postTasks;
 
 
-    @XmlElementWrapper(name="post-downgrade")
-    @XmlElement(name="task")
+
+    @XmlElement(name="post-downgrade")
+    private DowngradeTasks postDowngradeXml;
+    @XmlTransient
     public List<Task> postDowngradeTasks;
     public List<Task> postDowngradeTasks;
+
+    /**
+     * This method verifies that if {@code pre-upgrade} is defined, that there is also
+     * a sibling {@code pre-downgrade} defined.  Similarly, {@code post-upgrade} must have a
+     * sibling {@code post-downgrade}.  This is because the JDK (include 1.8) JAXB doesn't
+     * support XSD xpath assertions for siblings.
+     *
+     * @param unmarshaller  the unmarshaller
+     * @param parent        the parent
+     */
+    void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
+      if (null != preDowngradeXml) {
+        preDowngradeTasks = preDowngradeXml.copyUpgrade ? preTasks :
+          preDowngradeXml.tasks;
+      }
+
+      if (null != postDowngradeXml) {
+        postDowngradeTasks = postDowngradeXml.copyUpgrade ? postTasks :
+          postDowngradeXml.tasks;
+      }
+
+      ProcessingService service = (ProcessingService) parent;
+
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Processing component {}/{} preUpgrade={} postUpgrade={} preDowngrade={} postDowngrade={}",
+            preTasks, preDowngradeTasks, postTasks, postDowngradeTasks);
+      }
+
+      if (null != preTasks && null == preDowngradeTasks) {
+        String error = String.format("Upgrade pack must contain pre-downgrade elements if "
+            + "pre-upgrade exists for processing component %s/%s", service.name, name);
+
+        throw new RuntimeException(error);
+      }
+
+      if (null != postTasks && null == postDowngradeTasks) {
+        String error = String.format("Upgrade pack must contain post-downgrade elements if "
+            + "post-upgrade exists for processing component %s/%s", service.name, name);
+
+        throw new RuntimeException(error);
+      }
+    }
   }
   }
 
 
   /**
   /**
@@ -647,4 +691,17 @@ public class UpgradePack {
     @XmlValue
     @XmlValue
     public String value;
     public String value;
   }
   }
+
+  /**
+   * A {@code (pre|post)-downgrade} can have an attribute as well as contain {@code task} elements.
+   */
+  private static class DowngradeTasks {
+
+    @XmlAttribute(name="copy-upgrade")
+    private boolean copyUpgrade = false;
+
+    @XmlElement(name="task")
+    private List<Task> tasks = new ArrayList<>();
+  }
+
 }
 }

+ 2 - 4
ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilder.java

@@ -214,12 +214,10 @@ public abstract class StageWrapperBuilder {
     if (forUpgrade) {
     if (forUpgrade) {
       interim = preTasks ? pc.preTasks : pc.postTasks;
       interim = preTasks ? pc.preTasks : pc.postTasks;
     } else {
     } else {
-      interim = preTasks ?
-        (null == pc.preDowngradeTasks ? pc.preTasks : pc.preDowngradeTasks) :
-        (null == pc.postDowngradeTasks ? pc.postTasks : pc.postDowngradeTasks);
+      interim = preTasks ? pc.preDowngradeTasks : pc.postDowngradeTasks;
     }
     }
 
 
-    if (null == interim || interim.isEmpty()) {
+    if (CollectionUtils.isEmpty(interim)) {
       return Collections.emptyList();
       return Collections.emptyList();
     }
     }
 
 

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml

@@ -720,6 +720,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>

+ 9 - 0
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.4.xml

@@ -773,6 +773,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1124,6 +1126,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1138,6 +1142,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1148,6 +1154,9 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
+        
       </component>
       </component>
     </service>
     </service>
 
 

+ 8 - 0
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml

@@ -918,6 +918,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1273,6 +1275,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1287,6 +1291,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1297,6 +1303,8 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
 
 

+ 9 - 0
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.6.xml

@@ -918,6 +918,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1273,6 +1275,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1287,6 +1291,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1297,6 +1303,9 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
+        
       </component>
       </component>
     </service>
     </service>
 
 

+ 13 - 0
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.3.xml

@@ -449,6 +449,8 @@
             <function>stop</function>
             <function>stop</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -492,6 +494,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -590,6 +594,8 @@
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
 
 
+        <pre-downgrade copy-upgrade="true" />
+
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
         </upgrade>
         </upgrade>
@@ -628,6 +634,8 @@
           <!-- These HBASE configs changed in HDP 2.3.4.0, but Ambari can't distinguish HDP 2.3.2.0 vs HDP 2.3.4.0, so easier to always do them. -->
           <!-- These HBASE configs changed in HDP 2.3.4.0, but Ambari can't distinguish HDP 2.3.2.0 vs HDP 2.3.4.0, so easier to always do them. -->
           <task xsi:type="configure" id="hdp_2_3_4_0_hbase_remove_local_indexing"/>
           <task xsi:type="configure" id="hdp_2_3_4_0_hbase_remove_local_indexing"/>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -662,6 +670,9 @@
             <summary>Verifying LZO codec path for Tez</summary>
             <summary>Verifying LZO codec path for Tez</summary>
           </task>  
           </task>  
         </pre-upgrade>
         </pre-upgrade>
+
+        <pre-downgrade copy-upgrade="true" />
+        
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
         </upgrade>
         </upgrade>
@@ -811,6 +822,8 @@
 
 
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>

+ 6 - 0
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.4.xml

@@ -510,6 +510,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -609,6 +611,8 @@
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
 
 
+        <pre-downgrade copy-upgrade="true" />
+
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -896,6 +900,8 @@
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
         </pre-upgrade>
         </pre-upgrade>
 
 
+        <pre-downgrade />
+        
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>

+ 12 - 1
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml

@@ -612,7 +612,7 @@
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
 
 
-        <pre-downgrade/> <!--  no-op to prevent config changes on downgrade -->
+        <pre-downgrade /> <!--  no-op to prevent config changes on downgrade -->
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -713,6 +713,8 @@
             <summary>Verifying LZO codec path for mapreduce</summary>
             <summary>Verifying LZO codec path for mapreduce</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -870,6 +872,8 @@
         <pre-upgrade>
         <pre-upgrade>
           <task xsi:type="configure" id="hdp_2_5_0_0_webhcat_server_update_configuration_paths"/>
           <task xsi:type="configure" id="hdp_2_5_0_0_webhcat_server_update_configuration_paths"/>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1115,6 +1119,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1130,6 +1136,8 @@
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
 
 
+        <pre-downgrade copy-upgrade="true" />
+
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -1139,6 +1147,9 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
+        
       </component>
       </component>
     </service>
     </service>
 
 

+ 11 - 0
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.6.xml

@@ -715,6 +715,8 @@
             <summary>Verifying LZO codec path for mapreduce</summary>
             <summary>Verifying LZO codec path for mapreduce</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -872,6 +874,8 @@
         <pre-upgrade>
         <pre-upgrade>
           <task xsi:type="configure" id="hdp_2_5_0_0_webhcat_server_update_configuration_paths"/>
           <task xsi:type="configure" id="hdp_2_5_0_0_webhcat_server_update_configuration_paths"/>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1114,6 +1118,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1128,6 +1134,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1138,6 +1146,9 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
+        
       </component>
       </component>
     </service>
     </service>
 
 

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.4.xml

@@ -705,6 +705,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>

+ 8 - 0
ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml

@@ -881,6 +881,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1236,6 +1238,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1250,6 +1254,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1260,6 +1266,8 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
 
 

+ 8 - 0
ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.6.xml

@@ -872,6 +872,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1227,6 +1229,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1241,6 +1245,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -1251,6 +1257,8 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
 
 

+ 9 - 0
ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.4.xml

@@ -463,6 +463,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -569,6 +571,8 @@
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
 
 
+        <pre-downgrade copy-upgrade="true" />
+
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -636,6 +640,9 @@
             <summary>Verifying LZO codec path for Tez</summary>
             <summary>Verifying LZO codec path for Tez</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
+        
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -793,6 +800,8 @@
 
 
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />

+ 9 - 0
ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml

@@ -714,6 +714,8 @@
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
 
 
+        <pre-downgrade copy-upgrade="true" />
+
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -907,6 +909,7 @@
         <pre-upgrade>
         <pre-upgrade>
           <task xsi:type="configure" id="hdp_2_5_0_0_spark_client"/>
           <task xsi:type="configure" id="hdp_2_5_0_0_spark_client"/>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -1073,6 +1076,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1087,6 +1092,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1097,6 +1104,8 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
 
 
       </component>
       </component>
     </service>
     </service>

+ 8 - 0
ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.6.xml

@@ -719,6 +719,8 @@
             <summary>Verifying LZO codec path for mapreduce</summary>
             <summary>Verifying LZO codec path for mapreduce</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1070,6 +1072,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1084,6 +1088,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -1094,6 +1100,8 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
 
 
       </component>
       </component>
     </service>
     </service>

+ 9 - 0
ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/host-upgrade-2.5.xml

@@ -158,6 +158,8 @@
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
 
 
+        <pre-downgrade copy-upgrade="true" />
+
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -268,6 +270,8 @@
             <summary>Verifying LZO codec path for mapreduce</summary>
             <summary>Verifying LZO codec path for mapreduce</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -334,6 +338,9 @@
             <summary>Verifying LZO codec path for Tez</summary>
             <summary>Verifying LZO codec path for Tez</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+
+        <pre-downgrade copy-upgrade="true" />
+
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -504,6 +511,8 @@
 
 
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml

@@ -771,6 +771,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>

+ 4 - 0
ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.6.xml

@@ -775,6 +775,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -796,6 +798,8 @@
             <function>configure_atlas_user_for_tagsync</function>
             <function>configure_atlas_user_for_tagsync</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>

+ 9 - 0
ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.5.xml

@@ -511,6 +511,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -622,6 +624,8 @@
             <summary>Verifying LZO codec path for mapreduce</summary>
             <summary>Verifying LZO codec path for mapreduce</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -688,6 +692,9 @@
             <summary>Verifying LZO codec path for Tez</summary>
             <summary>Verifying LZO codec path for Tez</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
+        
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -864,6 +871,8 @@
 
 
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
           <task xsi:type="configure" id="increase_storm_zookeeper_timeouts"/>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />

+ 10 - 0
ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.6.xml

@@ -528,6 +528,8 @@
             <function>configure_atlas_user_for_tagsync</function>
             <function>configure_atlas_user_for_tagsync</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -626,6 +628,8 @@
             <summary>Verifying LZO codec path for mapreduce</summary>
             <summary>Verifying LZO codec path for mapreduce</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -692,6 +696,9 @@
             <summary>Verifying LZO codec path for Tez</summary>
             <summary>Verifying LZO codec path for Tez</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
+        
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -775,6 +782,9 @@
         <pre-upgrade>
         <pre-upgrade>
           <task xsi:type="configure" id="hdp_2_5_0_0_rename_spark_livy_configs" />
           <task xsi:type="configure" id="hdp_2_5_0_0_rename_spark_livy_configs" />
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade />
+        
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/host-upgrade-2.6.xml

@@ -152,6 +152,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/nonrolling-upgrade-2.6.xml

@@ -744,6 +744,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>

+ 7 - 0
ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/upgrade-2.6.xml

@@ -504,6 +504,8 @@
             <function>setup_ranger_java_patches</function>
             <function>setup_ranger_java_patches</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -615,6 +617,8 @@
             <summary>Verifying LZO codec path for mapreduce</summary>
             <summary>Verifying LZO codec path for mapreduce</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
@@ -681,6 +685,9 @@
             <summary>Verifying LZO codec path for Tez</summary>
             <summary>Verifying LZO codec path for Tez</summary>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
+        
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>

+ 11 - 3
ambari-server/src/main/resources/upgrade-pack.xsd

@@ -354,6 +354,13 @@
       <xs:element name="task" type="abstract-task-type" minOccurs="0" maxOccurs="unbounded"/>
       <xs:element name="task" type="abstract-task-type" minOccurs="0" maxOccurs="unbounded"/>
     </xs:sequence>
     </xs:sequence>
   </xs:complexType>
   </xs:complexType>
+
+  <xs:complexType name="downgrade-directive-type">
+    <xs:sequence>
+      <xs:element name="task" type="abstract-task-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="copy-upgrade" use="optional" type="xs:boolean" />
+  </xs:complexType>
   
   
   <xs:complexType name="processing-type">
   <xs:complexType name="processing-type">
     <xs:sequence>
     <xs:sequence>
@@ -364,14 +371,15 @@
               <xs:complexType>
               <xs:complexType>
                 <xs:sequence>
                 <xs:sequence>
                   <xs:element name="pre-upgrade" type="upgrade-directive-type" minOccurs="0"/>
                   <xs:element name="pre-upgrade" type="upgrade-directive-type" minOccurs="0"/>
-                  <xs:element name="pre-downgrade" type="upgrade-directive-type" minOccurs="0" />
+                  <xs:element name="pre-downgrade" type="downgrade-directive-type" minOccurs="0" />
                   <xs:element name="upgrade" type="upgrade-directive-type" minOccurs="1" />
                   <xs:element name="upgrade" type="upgrade-directive-type" minOccurs="1" />
                   <xs:element name="post-upgrade" type="upgrade-directive-type" minOccurs="0" />
                   <xs:element name="post-upgrade" type="upgrade-directive-type" minOccurs="0" />
-                  <xs:element name="post-downgrade" type="upgrade-directive-type" minOccurs="0" />
+                  <xs:element name="post-downgrade" type="downgrade-directive-type" minOccurs="0" />
                 </xs:sequence>
                 </xs:sequence>
                 <!-- 
                 <!-- 
-                Want to use <xs:assert> to make sure that a pre-downgrade is available i
+                Want to use <xs:assert> to make sure that a pre-downgrade is available if
                 pre-upgrade is set.  It appears as though that is not yet available to jaxb.
                 pre-upgrade is set.  It appears as though that is not yet available to jaxb.
+                See java implementation for the workaround for this.
                  -->
                  -->
                 <xs:attribute name="name" type="xs:NMTOKEN" />
                 <xs:attribute name="name" type="xs:NMTOKEN" />
               </xs:complexType>
               </xs:complexType>

+ 1 - 1
ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java

@@ -7282,7 +7282,7 @@ public class AmbariManagementControllerTest {
     Assert.assertEquals(1, responsesWithParams.size());
     Assert.assertEquals(1, responsesWithParams.size());
     StackVersionResponse resp = responsesWithParams.iterator().next();
     StackVersionResponse resp = responsesWithParams.iterator().next();
     assertNotNull(resp.getUpgradePacks());
     assertNotNull(resp.getUpgradePacks());
-    assertEquals(11, resp.getUpgradePacks().size());
+    assertEquals(12, resp.getUpgradePacks().size());
     assertTrue(resp.getUpgradePacks().contains("upgrade_test"));
     assertTrue(resp.getUpgradePacks().contains("upgrade_test"));
   }
   }
 
 

+ 92 - 0
ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackParsingTest.java

@@ -0,0 +1,92 @@
+/**
+ * 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 java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ambari.server.stack.ModuleFileUnmarshaller;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Tests parsing upgrade packs in the entire codebase.  This does not use Guice
+ * initialization, which will parse upgrade packs itself.
+ */
+@Category({ category.StackUpgradeTest.class})
+public class UpgradePackParsingTest {
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void findAndValidateUpgradePacks() throws Exception {
+
+    IOFileFilter filter = new IOFileFilter() {
+      @Override
+      public boolean accept(File dir, String name) {
+        return false;
+      }
+
+      @Override
+      public boolean accept(File file) {
+        // file has the folder named 'upgrades', ends with '.xml' and is NOT 'config-upgrade.xml'
+        if (file.getAbsolutePath().contains("upgrades") &&
+            file.getAbsolutePath().endsWith(".xml") &&
+            !file.getAbsolutePath().contains("config-upgrade.xml")) {
+
+          return true;
+        }
+
+        return false;
+      }
+    };
+
+    List<File> files = new ArrayList<>();
+
+    files.addAll(FileUtils.listFiles(new File("src/main/resources/stacks"), filter,
+      FileFilterUtils.directoryFileFilter()));
+
+    files.addAll(FileUtils.listFiles(new File("src/test/resources/stacks"), filter,
+        FileFilterUtils.directoryFileFilter()));
+
+    files.addAll(FileUtils.listFiles(new File("src/test/resources/stacks_with_upgrade_cycle"), filter,
+        FileFilterUtils.directoryFileFilter()));
+
+    ModuleFileUnmarshaller unmarshaller = new ModuleFileUnmarshaller();
+
+    for (File file : files) {
+      String fileContent = FileUtils.readFileToString(file, "UTF-8");
+
+      // these things must be in upgrade packs for them to work anyway
+      if (fileContent.contains("<upgrade") && fileContent.contains("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")) {
+        if (!fileContent.contains("xsi:noNamespaceSchemaLocation=\"upgrade-pack.xsd\"")) {
+          String msg = String.format("File %s appears to be an upgrade pack, but does not define 'upgrade-pack.xsd' as its schema",
+              file.getAbsolutePath());
+          Assert.fail(msg);
+        } else {
+          unmarshaller.unmarshal(UpgradePack.class, file, true);
+        }
+      }
+    }
+  }
+
+}

+ 106 - 62
ambari-server/src/test/java/org/apache/ambari/server/state/stack/UpgradePackTest.java

@@ -23,8 +23,6 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertTrue;
 
 
-import java.io.File;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashMap;
@@ -36,7 +34,6 @@ import java.util.Set;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
-import org.apache.ambari.server.stack.ModuleFileUnmarshaller;
 import org.apache.ambari.server.state.stack.UpgradePack.PrerequisiteCheckConfig;
 import org.apache.ambari.server.state.stack.UpgradePack.PrerequisiteCheckConfig;
 import org.apache.ambari.server.state.stack.UpgradePack.ProcessingComponent;
 import org.apache.ambari.server.state.stack.UpgradePack.ProcessingComponent;
 import org.apache.ambari.server.state.stack.upgrade.ClusterGrouping;
 import org.apache.ambari.server.state.stack.upgrade.ClusterGrouping;
@@ -53,9 +50,6 @@ import org.apache.ambari.server.state.stack.upgrade.StopGrouping;
 import org.apache.ambari.server.state.stack.upgrade.Task;
 import org.apache.ambari.server.state.stack.upgrade.Task;
 import org.apache.ambari.server.state.stack.upgrade.UpdateStackGrouping;
 import org.apache.ambari.server.state.stack.upgrade.UpdateStackGrouping;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.filefilter.FileFilterUtils;
-import org.apache.commons.io.filefilter.IOFileFilter;
 import org.junit.After;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Before;
@@ -64,6 +58,7 @@ import org.junit.experimental.categories.Category;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 
 
+import com.google.common.collect.Sets;
 import com.google.inject.Guice;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Injector;
 import com.google.inject.persist.PersistService;
 import com.google.inject.persist.PersistService;
@@ -92,59 +87,6 @@ public class UpgradePackTest {
     injector.getInstance(PersistService.class).stop();
     injector.getInstance(PersistService.class).stop();
   }
   }
 
 
-  @Test
-  @SuppressWarnings("unchecked")
-  public void findAndValidateUpgradePacks() throws Exception {
-
-    IOFileFilter filter = new IOFileFilter() {
-      @Override
-      public boolean accept(File dir, String name) {
-        return false;
-      }
-
-      @Override
-      public boolean accept(File file) {
-        // file has the folder named 'upgrades', ends with '.xml' and is NOT 'config-upgrade.xml'
-        if (file.getAbsolutePath().contains("upgrades") &&
-            file.getAbsolutePath().endsWith(".xml") &&
-            !file.getAbsolutePath().contains("config-upgrade.xml")) {
-
-          return true;
-        }
-
-        return false;
-      }
-    };
-
-    List<File> files = new ArrayList<>();
-
-    files.addAll(FileUtils.listFiles(new File("src/main/resources/stacks"), filter,
-      FileFilterUtils.directoryFileFilter()));
-
-    files.addAll(FileUtils.listFiles(new File("src/test/resources/stacks"), filter,
-        FileFilterUtils.directoryFileFilter()));
-
-    files.addAll(FileUtils.listFiles(new File("src/test/resources/stacks_with_upgrade_cycle"), filter,
-        FileFilterUtils.directoryFileFilter()));
-
-    ModuleFileUnmarshaller unmarshaller = new ModuleFileUnmarshaller();
-
-    for (File file : files) {
-      String fileContent = FileUtils.readFileToString(file, "UTF-8");
-
-      // these things must be in upgrade packs for them to work anyway
-      if (fileContent.contains("<upgrade") && fileContent.contains("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")) {
-        if (!fileContent.contains("xsi:noNamespaceSchemaLocation=\"upgrade-pack.xsd\"")) {
-          String msg = String.format("File %s appears to be an upgrade pack, but does not define 'upgrade-pack.xsd' as its schema",
-              file.getAbsolutePath());
-          Assert.fail(msg);
-        } else {
-          unmarshaller.unmarshal(UpgradePack.class, file, true);
-        }
-      }
-    }
-  }
-
   @Test
   @Test
   public void testExistence() throws Exception {
   public void testExistence() throws Exception {
     Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("foo", "bar");
     Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("foo", "bar");
@@ -192,10 +134,13 @@ public class UpgradePackTest {
     assertNotNull(pc.preTasks);
     assertNotNull(pc.preTasks);
     assertNotNull(pc.postTasks);
     assertNotNull(pc.postTasks);
     assertNotNull(pc.tasks);
     assertNotNull(pc.tasks);
-    assertNull(pc.preDowngradeTasks);
-    assertNull(pc.postDowngradeTasks);
+    assertNotNull(pc.preDowngradeTasks);
+    assertNotNull(pc.postDowngradeTasks);
     assertEquals(1, pc.tasks.size());
     assertEquals(1, pc.tasks.size());
 
 
+    assertEquals(3, pc.preDowngradeTasks.size());
+    assertEquals(1, pc.postDowngradeTasks.size());
+
     assertEquals(Task.Type.RESTART, pc.tasks.get(0).getType());
     assertEquals(Task.Type.RESTART, pc.tasks.get(0).getType());
     assertEquals(RestartTask.class, pc.tasks.get(0).getClass());
     assertEquals(RestartTask.class, pc.tasks.get(0).getClass());
 
 
@@ -556,7 +501,7 @@ public class UpgradePackTest {
     ServiceCheckGrouping scGroup = (ServiceCheckGrouping) group;
     ServiceCheckGrouping scGroup = (ServiceCheckGrouping) group;
     Set<String> priorityServices = scGroup.getPriorities();
     Set<String> priorityServices = scGroup.getPriorities();
     assertEquals(4, priorityServices.size());
     assertEquals(4, priorityServices.size());
-    Iterator serviceIterator = priorityServices.iterator();
+    Iterator<String> serviceIterator = priorityServices.iterator();
     assertEquals("ZOOKEEPER", serviceIterator.next());
     assertEquals("ZOOKEEPER", serviceIterator.next());
     assertEquals("HBASE", serviceIterator.next());
     assertEquals("HBASE", serviceIterator.next());
 
 
@@ -609,6 +554,105 @@ public class UpgradePackTest {
     assertEquals(Grouping.class, upgradePack.getAllGroups().get(1).getClass());
     assertEquals(Grouping.class, upgradePack.getAllGroups().get(1).getClass());
   }
   }
 
 
+  @Test
+  public void testDowngradeComponentTasks() throws Exception {
+    Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("HDP", "2.1.1");
+    UpgradePack upgradePack = upgrades.get("upgrade_component_tasks_test");
+    assertNotNull(upgradePack);
+
+    Map<String, Map<String, ProcessingComponent>> components = upgradePack.getTasks();
+    assertTrue(components.containsKey("ZOOKEEPER"));
+    assertTrue(components.containsKey("HDFS"));
+
+    Map<String, ProcessingComponent> zkMap = components.get("ZOOKEEPER");
+    Map<String, ProcessingComponent> hdfsMap = components.get("HDFS");
+
+    assertTrue(zkMap.containsKey("ZOOKEEPER_SERVER"));
+    assertTrue(zkMap.containsKey("ZOOKEEPER_CLIENT"));
+    assertTrue(hdfsMap.containsKey("NAMENODE"));
+    assertTrue(hdfsMap.containsKey("DATANODE"));
+    assertTrue(hdfsMap.containsKey("HDFS_CLIENT"));
+    assertTrue(hdfsMap.containsKey("JOURNALNODE"));
+
+    ProcessingComponent zkServer = zkMap.get("ZOOKEEPER_SERVER");
+    ProcessingComponent zkClient = zkMap.get("ZOOKEEPER_CLIENT");
+    ProcessingComponent hdfsNN = hdfsMap.get("NAMENODE");
+    ProcessingComponent hdfsDN = hdfsMap.get("DATANODE");
+    ProcessingComponent hdfsClient = hdfsMap.get("HDFS_CLIENT");
+    ProcessingComponent hdfsJN = hdfsMap.get("JOURNALNODE");
+
+    // ZK server has only pretasks defined, with pre-downgrade being a copy of pre-upgrade
+    assertNotNull(zkServer.preTasks);
+    assertNotNull(zkServer.preDowngradeTasks);
+    assertNull(zkServer.postTasks);
+    assertNull(zkServer.postDowngradeTasks);
+    assertEquals(1, zkServer.preTasks.size());
+    assertEquals(1, zkServer.preDowngradeTasks.size());
+
+    // ZK client has only post-tasks defined, with post-downgrade being a copy of pre-upgrade
+    assertNull(zkClient.preTasks);
+    assertNull(zkClient.preDowngradeTasks);
+    assertNotNull(zkClient.postTasks);
+    assertNotNull(zkClient.postDowngradeTasks);
+    assertEquals(1, zkClient.postTasks.size());
+    assertEquals(1, zkClient.postDowngradeTasks.size());
+
+    // NN has only pre-tasks defined, with an empty pre-downgrade
+    assertNotNull(hdfsNN.preTasks);
+    assertNotNull(hdfsNN.preDowngradeTasks);
+    assertNull(hdfsNN.postTasks);
+    assertNull(hdfsNN.postDowngradeTasks);
+    assertEquals(1, hdfsNN.preTasks.size());
+    assertEquals(0, hdfsNN.preDowngradeTasks.size());
+
+    // DN has only post-tasks defined, with post-downgrade being empty
+    assertNull(hdfsDN.preTasks);
+    assertNull(hdfsDN.preDowngradeTasks);
+    assertNotNull(hdfsDN.postTasks);
+    assertNotNull(hdfsDN.postDowngradeTasks);
+    assertEquals(1, hdfsDN.postTasks.size());
+    assertEquals(0, hdfsDN.postDowngradeTasks.size());
+
+    // HDFS client has only post and post-downgrade tasks
+    assertNull(hdfsClient.preTasks);
+    assertNotNull(hdfsClient.preDowngradeTasks);
+    assertNull(hdfsClient.postTasks);
+    assertNotNull(hdfsClient.postDowngradeTasks);
+    assertEquals(1, hdfsClient.preDowngradeTasks.size());
+    assertEquals(1, hdfsClient.postDowngradeTasks.size());
+
+    // JN has differing tasks for pre and post downgrade
+    assertNotNull(hdfsJN.preTasks);
+    assertNotNull(hdfsJN.preDowngradeTasks);
+    assertNotNull(hdfsJN.postTasks);
+    assertNotNull(hdfsJN.postDowngradeTasks);
+    assertEquals(1, hdfsJN.preTasks.size());
+    assertEquals(2, hdfsJN.preDowngradeTasks.size());
+    assertEquals(1, hdfsJN.postTasks.size());
+    assertEquals(2, hdfsJN.postDowngradeTasks.size());
+
+    // make sure all ids are accounted for
+
+    Set<String> allIds = Sets.newHashSet("some_id", "some_id1", "some_id2", "some_id3", "some_id4", "some_id5");
+
+    @SuppressWarnings("unchecked")
+    Set<List<Task>> allTasks = Sets.newHashSet(hdfsJN.preTasks, hdfsJN.preDowngradeTasks,
+        hdfsJN.postTasks, hdfsJN.postDowngradeTasks);
+
+    for (List<Task> list : allTasks) {
+      for (Task t : list) {
+        assertEquals(ConfigureTask.class, t.getClass());
+
+        ConfigureTask ct = (ConfigureTask) t;
+        assertTrue(allIds.contains(ct.id));
+
+        allIds.remove(ct.id);
+      }
+    }
+
+    assertTrue(allIds.isEmpty());
+  }
+
 
 
   private int indexOf(Map<String, ?> map, String keyToFind) {
   private int indexOf(Map<String, ?> map, String keyToFind) {
     int result = -1;
     int result = -1;

+ 4 - 0
ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_bucket_test.xml

@@ -58,6 +58,8 @@
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
         
         
+        <pre-downgrade copy-upgrade="true" />
+        
         <upgrade />
         <upgrade />
         
         
         <post-upgrade>
         <post-upgrade>
@@ -86,6 +88,8 @@
           
           
         </post-upgrade>
         </post-upgrade>
         
         
+        <post-downgrade copy-upgrade="true" />
+        
         
         
       </component>
       </component>
     </service>
     </service>

+ 133 - 0
ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_component_tasks_test.xml

@@ -0,0 +1,133 @@
+<?xml version="1.0"?>
+<!--
+   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.
+-->
+<upgrade xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="upgrade-pack.xsd">
+  <target>2.2.*.*</target>
+  <target-stack>HDP-2.2.0</target-stack>
+  <type>ROLLING</type>
+  <prerequisite-checks />
+  
+  <order>
+    <group name="ZOOKEEPER" title="Zookeeper">
+      <service name="ZOOKEEPER">
+        <component>ZOOKEEPER_SERVER</component>
+        <component>ZOOKEEPER_CLIENT</component>
+      </service>
+    </group>
+    
+    <group name="HDFS" title="HDFS">
+      <service name="HDFS">
+        <component>NAMENODE</component>
+        <component>DATANODE</component>
+        <component>HDFS_CLIENT</component>
+        <component>JOURNALNODE</component>
+      </service>
+    </group>
+  </order>
+  
+
+  <processing>
+    <service name="ZOOKEEPER">
+      <component name="ZOOKEEPER_SERVER">
+        <pre-upgrade>
+          <task xsi:type="manual">
+            <summary>SUMMARY OF PREPARE</summary>
+            <message>This is a manual task with a placeholder of {{foo/bar}}</message>
+          </task>
+        </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
+        <upgrade>
+          <task xsi:type="restart-task" />
+        </upgrade>
+      </component>
+      
+      <component name="ZOOKEEPER_CLIENT">
+        <upgrade />
+        
+        <post-upgrade>
+          <task xsi:type="configure" id="hdp_2_1_1_zookeeper_new_config_type" />
+        </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
+      </component>
+      
+    </service>
+    
+    <service name="HDFS">
+      <component name="NAMENODE">
+        <pre-upgrade>
+          <task xsi:type="execute" hosts="master">
+            <script>foo</script>
+            <function>list</function>
+          </task>
+        </pre-upgrade>
+        <pre-downgrade />
+        <upgrade>
+          <task xsi:type="restart-task" />
+        </upgrade>
+      </component>
+      
+      <component name="DATANODE">
+        <upgrade>
+          <task xsi:type="restart-task" />
+        </upgrade>
+        <post-upgrade>
+          <task xsi:type="manual">
+            <message>Manual Downgrade</message>
+          </task>
+        </post-upgrade>
+        <post-downgrade />
+      </component>
+      
+      <component name="HDFS_CLIENT">
+        <pre-downgrade>
+          <task xsi:type="configure" id="some_id" />
+        </pre-downgrade>
+        <upgrade />
+        <post-downgrade>
+          <task xsi:type="configure" id="some_id" />
+        </post-downgrade>
+      </component>
+      
+      <component name="JOURNALNODE">
+        <pre-upgrade>
+          <task xsi:type="configure" id="some_id" />
+        </pre-upgrade>
+        
+        <pre-downgrade>
+          <task xsi:type="configure" id="some_id1" />
+          <task xsi:type="configure" id="some_id2" />
+        </pre-downgrade>
+        
+        <upgrade />
+        
+        <post-upgrade>
+          <task xsi:type="configure" id="some_id3" />
+        </post-upgrade>
+        
+        <post-downgrade>
+          <task xsi:type="configure" id="some_id4" />
+          <task xsi:type="configure" id="some_id5" />
+        </post-downgrade>
+        
+        
+        
+      </component>
+    </service>
+    
+
+  </processing>
+</upgrade>

+ 5 - 0
ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_direction.xml

@@ -88,12 +88,17 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
+        
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="foo" />
           <task xsi:type="configure" id="foo" />
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
   </processing>
   </processing>

+ 6 - 0
ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_nonrolling_new_stack.xml

@@ -935,6 +935,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -949,6 +951,8 @@
             <function>delete_storm_local_data</function>
             <function>delete_storm_local_data</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        
+        <pre-downgrade copy-upgrade="true" />
 
 
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
@@ -959,6 +963,8 @@
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
             <message>Please rebuild your topology using the new Storm version dependencies and resubmit it using the newly created jar.</message>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
 
 

+ 8 - 0
ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test.xml

@@ -144,12 +144,14 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="hdp_2_1_1_zookeeper_new_config_type" />
           <task xsi:type="configure" id="hdp_2_1_1_zookeeper_new_config_type" />
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
     
     
@@ -165,6 +167,7 @@
             <message>{{direction.verb.proper}} your database</message>
             <message>{{direction.verb.proper}} your database</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -174,6 +177,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
       <component name="DATANODE">
       <component name="DATANODE">
         <pre-downgrade />
         <pre-downgrade />
@@ -196,6 +200,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
       <component name="NODEMANAGER">
       <component name="NODEMANAGER">
@@ -206,6 +211,7 @@
           </task>
           </task>
           <task xsi:type="configure" id="hdp_2_1_1_nm_pre_upgrade"/>
           <task xsi:type="configure" id="hdp_2_1_1_nm_pre_upgrade"/>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
     </service>
     </service>
@@ -222,6 +228,7 @@
           <task xsi:type="configure" id="hdp_2_1_1_hive_server_conditions_skip"/>
           <task xsi:type="configure" id="hdp_2_1_1_hive_server_conditions_skip"/>
           <task xsi:type="configure" id="hdp_2_1_1_no_conditions_met"/>
           <task xsi:type="configure" id="hdp_2_1_1_no_conditions_met"/>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
        </component>
        </component>
      </service>
      </service>
@@ -244,6 +251,7 @@
             <function>upgrade_oozie_database_and_sharelib</function>
             <function>upgrade_oozie_database_and_sharelib</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>

+ 6 - 0
ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test_checks.xml

@@ -145,12 +145,14 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="hdp_2_1_1_zk_post_upgrade"/>
           <task xsi:type="configure" id="hdp_2_1_1_zk_post_upgrade"/>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
     <service name="HDFS">
     <service name="HDFS">
@@ -165,6 +167,7 @@
             <message>Update your database</message>
             <message>Update your database</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -174,6 +177,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
       <component name="DATANODE">
       <component name="DATANODE">
         <pre-downgrade />
         <pre-downgrade />
@@ -195,6 +199,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
       <component name="NODEMANAGER">
       <component name="NODEMANAGER">
@@ -204,6 +209,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
     </service>
     </service>

+ 8 - 0
ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test_partial.xml

@@ -157,12 +157,14 @@
             <message>This is only for partials</message>
             <message>This is only for partials</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="hdp_2_1_1_zookeeper_new_config_type" />
           <task xsi:type="configure" id="hdp_2_1_1_zookeeper_new_config_type" />
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
     
     
@@ -178,6 +180,7 @@
             <message>{{direction.verb.proper}} your database</message>
             <message>{{direction.verb.proper}} your database</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -187,6 +190,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
       <component name="DATANODE">
       <component name="DATANODE">
         <pre-downgrade />
         <pre-downgrade />
@@ -209,6 +213,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
       <component name="NODEMANAGER">
       <component name="NODEMANAGER">
@@ -219,6 +224,7 @@
           </task>
           </task>
           <task xsi:type="configure" id="hdp_2_1_1_nm_pre_upgrade"/>
           <task xsi:type="configure" id="hdp_2_1_1_nm_pre_upgrade"/>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
     </service>
     </service>
@@ -233,6 +239,7 @@
           <task xsi:type="configure" id="hdp_2_1_1_set_transport_mode"/>
           <task xsi:type="configure" id="hdp_2_1_1_set_transport_mode"/>
           <task xsi:type="configure" id="hdp_2_1_1_hive_server_foo"/>
           <task xsi:type="configure" id="hdp_2_1_1_hive_server_foo"/>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
        </component>
        </component>
      </service>
      </service>
@@ -255,6 +262,7 @@
             <function>upgrade_oozie_database_and_sharelib</function>
             <function>upgrade_oozie_database_and_sharelib</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>

+ 8 - 2
ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_to_new_stack.xml

@@ -142,11 +142,12 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
-        <post-upgrade>
-        </post-upgrade>
+        <post-upgrade />
+        <post-downgrade />
       </component>
       </component>
     </service>
     </service>
     
     
@@ -162,6 +163,7 @@
             <message>{{direction.verb.proper}} your database</message>
             <message>{{direction.verb.proper}} your database</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -171,6 +173,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
       <component name="DATANODE">
       <component name="DATANODE">
         <pre-downgrade />
         <pre-downgrade />
@@ -193,6 +196,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
       <component name="NODEMANAGER">
       <component name="NODEMANAGER">
@@ -202,6 +206,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
     </service>
     </service>
@@ -216,6 +221,7 @@
 
 
           <task xsi:type="configure" id="hdp_2_1_1_test_properties"/>
           <task xsi:type="configure" id="hdp_2_1_1_test_properties"/>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
        </component>
        </component>
      </service>    
      </service>    

+ 7 - 0
ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test.xml

@@ -133,12 +133,14 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="foo" />
           <task xsi:type="configure" id="foo" />
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
     
     
@@ -154,6 +156,7 @@
             <message>{{direction.verb.proper}} your database</message>
             <message>{{direction.verb.proper}} your database</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -163,6 +166,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
       <component name="DATANODE">
       <component name="DATANODE">
         <pre-downgrade />
         <pre-downgrade />
@@ -185,6 +189,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
       <component name="NODEMANAGER">
       <component name="NODEMANAGER">
@@ -194,6 +199,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
     </service>
     </service>
@@ -206,6 +212,7 @@
             <message>The HiveServer port will now change to 10010 if hive is using a binary transfer mode or 10011 if hive is using an http transport mode. You can use "netstat -anp | grep 1001[01]" to determine if the port is available on each of following HiveServer host(s): {{hosts.all}}. If the port is not available, the process using it must be terminated.</message>
             <message>The HiveServer port will now change to 10010 if hive is using a binary transfer mode or 10011 if hive is using an http transport mode. You can use "netstat -anp | grep 1001[01]" to determine if the port is available on each of following HiveServer host(s): {{hosts.all}}. If the port is not available, the process using it must be terminated.</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
        </component>
        </component>
      </service>    
      </service>    

+ 7 - 0
ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_15388.xml

@@ -144,12 +144,14 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="foo" />
           <task xsi:type="configure" id="foo" />
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
 
 
@@ -166,6 +168,7 @@
             <message>{{direction.verb.proper}} your database</message>
             <message>{{direction.verb.proper}} your database</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -175,6 +178,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
       <component name="DATANODE">
       <component name="DATANODE">
         <pre-downgrade />
         <pre-downgrade />
@@ -197,6 +201,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
       <component name="NODEMANAGER">
       <component name="NODEMANAGER">
@@ -206,6 +211,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
     </service>
     </service>
@@ -218,6 +224,7 @@
             <message>The HiveServer port will now change to 10010 if hive is using a binary transfer mode or 10011 if hive is using an http transport mode. You can use "netstat -anp | grep 1001[01]" to determine if the port is available on each of following HiveServer host(s): {{hosts.all}}. If the port is not available, the process using it must be terminated.</message>
             <message>The HiveServer port will now change to 10010 if hive is using a binary transfer mode or 10011 if hive is using an http transport mode. You can use "netstat -anp | grep 1001[01]" to determine if the port is available on each of following HiveServer host(s): {{hosts.all}}. If the port is not available, the process using it must be terminated.</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
        </component>
        </component>
      </service>
      </service>

+ 6 - 0
ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_checks.xml

@@ -151,12 +151,14 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="hdp_2_2_0_zk_post_upgrade"/>
           <task xsi:type="configure" id="hdp_2_2_0_zk_post_upgrade"/>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
     <service name="HDFS">
     <service name="HDFS">
@@ -171,6 +173,7 @@
             <message>Update your database</message>
             <message>Update your database</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -180,6 +183,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
       <component name="DATANODE">
       <component name="DATANODE">
         <pre-downgrade />
         <pre-downgrade />
@@ -201,6 +205,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
       <component name="NODEMANAGER">
       <component name="NODEMANAGER">
@@ -210,6 +215,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
       </component>
       </component>
     </service>
     </service>

+ 2 - 0
ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_host_ordered.xml

@@ -67,12 +67,14 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="foo" />
           <task xsi:type="configure" id="foo" />
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
   </processing>
   </processing>

+ 2 - 0
ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_test_skip_failures.xml

@@ -64,12 +64,14 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task"/>
           <task xsi:type="restart-task"/>
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="foo" />
           <task xsi:type="configure" id="foo" />
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
   </processing>
   </processing>

+ 7 - 0
ambari-server/src/test/resources/stacks_with_upgrade_cycle/HDP/2.2.0/upgrades/upgrade_test_15388.xml

@@ -144,12 +144,14 @@
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
             <message>This is a manual task with a placeholder of {{foo/bar}}</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
         <post-upgrade>
         <post-upgrade>
           <task xsi:type="configure" id="foo"  />
           <task xsi:type="configure" id="foo"  />
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
     </service>
     </service>
 
 
@@ -166,6 +168,7 @@
             <message>{{direction.verb.proper}} your database</message>
             <message>{{direction.verb.proper}} your database</message>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -175,6 +178,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </post-upgrade>
         </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
       </component>
       </component>
       <component name="DATANODE">
       <component name="DATANODE">
         <pre-downgrade />
         <pre-downgrade />
@@ -197,6 +201,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -208,6 +213,7 @@
             <function>list</function>
             <function>list</function>
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade>
         <upgrade>
           <task xsi:type="restart-task" />
           <task xsi:type="restart-task" />
         </upgrade>
         </upgrade>
@@ -225,6 +231,7 @@
           <task xsi:type="configure" id="foo">
           <task xsi:type="configure" id="foo">
           </task>
           </task>
         </pre-upgrade>
         </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
         <upgrade />
         <upgrade />
        </component>
        </component>
      </service>
      </service>