You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2018/04/27 13:06:22 UTC

[ambari] branch branch-feature-AMBARI-14714 updated: [AMBARI-23697] Replace Cluster install_packages with an Upgrade Plan Installation (#1101)

This is an automated email from the ASF dual-hosted git repository.

ncole pushed a commit to branch branch-feature-AMBARI-14714
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/branch-feature-AMBARI-14714 by this push:
     new 0e3c8bb  [AMBARI-23697] Replace Cluster install_packages with an Upgrade Plan Installation (#1101)
0e3c8bb is described below

commit 0e3c8bbf678f566d93d49c02f811f929b7609f15
Author: ncole <nc...@hortonworks.com>
AuthorDate: Fri Apr 27 09:06:20 2018 -0400

    [AMBARI-23697] Replace Cluster install_packages with an Upgrade Plan Installation (#1101)
    
    * AMBARI-23697. Replace Cluster install_packages with an Upgrade Plan Installation
    
    * Updated commit for review
---
 .../ambari/annotations/ExperimentalFeature.java    |    7 +-
 .../api/resources/ResourceInstanceFactoryImpl.java |    5 +
 .../server/api/services/UpgradePlanService.java    |   14 +
 .../server/controller/ActionExecutionContext.java  |    4 +
 .../controller/internal/DefaultProviderModule.java |    2 +
 .../UpgradePlanInstallResourceProvider.java        |  441 +++++++
 .../ambari/server/controller/spi/Resource.java     |    2 +
 .../ambari/server/orm/dao/MpackHostStateDAO.java   |   22 +
 .../server/orm/entities/MpackHostStateEntity.java  |    6 +-
 .../server/orm/entities/ServiceGroupEntity.java    |    8 +
 .../apache/ambari/server/state/ServiceGroup.java   |    8 +
 .../ambari/server/state/ServiceGroupImpl.java      |   20 +
 .../org/apache/ambari/server/state/StackInfo.java  |   10 +
 .../stack/upgrade/RepositoryVersionHelper.java     |   22 +
 .../system_action_definitions.xml                  |    4 +-
 .../custom_actions/scripts/install_packages.py     |  480 --------
 .../custom_actions/scripts/mpack_packages.py       |  215 ++++
 .../python/custom_actions/TestInstallPackages.py   | 1278 --------------------
 18 files changed, 785 insertions(+), 1763 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/annotations/ExperimentalFeature.java b/ambari-server/src/main/java/org/apache/ambari/annotations/ExperimentalFeature.java
index 5cdbfaa..c5cff1f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/annotations/ExperimentalFeature.java
+++ b/ambari-server/src/main/java/org/apache/ambari/annotations/ExperimentalFeature.java
@@ -49,5 +49,10 @@ public enum ExperimentalFeature {
    * Used to mark code that is required for successful removal and refactoring
    * when repo versions are dropped.
    */
-  REPO_VERSION_REMOVAL;
+  REPO_VERSION_REMOVAL,
+
+  /**
+   * Use this annotation when a test needs to be written.
+   */
+  UNIT_TEST_REQUIRED;
 }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index d7e7fda..19296eb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -458,6 +458,11 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
             Resource.Type.UpgradePlan, "upgrade_plan", "upgrade_plans");
         break;
 
+      case UpgradePlanInstall:
+        resourceDefinition = new SimpleResourceDefinition(
+            Resource.Type.UpgradePlanInstall, "upgrade_plan_install", "upgrade_plan_installs");
+        break;
+
       case UpgradeSummary:
         resourceDefinition = new SimpleResourceDefinition(
             Resource.Type.UpgradeSummary, "upgrade_summary", "upgrade_summary");
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradePlanService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradePlanService.java
index 256addd..cb2882e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradePlanService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradePlanService.java
@@ -88,6 +88,20 @@ public class UpgradePlanService extends BaseService {
         createResourceInstance(id));
   }
 
+  @PUT @ApiIgnore
+  @Path("{upgradePlanId}/install")
+  @Produces(MediaType.TEXT_PLAIN)
+  public Response installPlan(String body, @Context HttpHeaders headers,
+      @Context UriInfo ui, @PathParam("upgradePlanId") Long id) {
+
+    Map<Resource.Type, String> mapIds = new HashMap<>();
+    mapIds.put(Resource.Type.Cluster, m_clusterName);
+    mapIds.put(Resource.Type.UpgradePlanInstall, id.toString());
+
+    return handleRequest(headers, body, ui, Request.Type.PUT,
+        createResource(Resource.Type.UpgradePlanInstall, mapIds));
+  }
+
   @DELETE @ApiIgnore // until documented
   @Path("{upgradePlanId}")
   @Produces(MediaType.TEXT_PLAIN)
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
index 9affac8..c0be480 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
@@ -143,6 +143,10 @@ public class ActionExecutionContext {
     return expectedServiceGroupName;
   }
 
+  public void setExpectedServiceGroupName(String name) {
+    expectedServiceGroupName = name;
+  }
+
   public String getExpectedServiceName() {
     return expectedServiceName;
   }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
index 220e48d..a23447d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
@@ -116,6 +116,8 @@ public class DefaultProviderModule extends AbstractProviderModule {
         return new UpgradeItemResourceProvider(managementController);
       case UpgradePlan:
         return new UpgradePlanResourceProvider(managementController);
+      case UpgradePlanInstall:
+        return new UpgradePlanInstallResourceProvider(managementController);
       case UpgradeSummary:
         return new UpgradeSummaryResourceProvider(managementController);
       case PreUpgradeCheck:
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradePlanInstallResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradePlanInstallResourceProvider.java
new file mode 100644
index 0000000..370cb82
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradePlanInstallResourceProvider.java
@@ -0,0 +1,441 @@
+/*
+ * 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.controller.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.ambari.annotations.Experimental;
+import org.apache.ambari.annotations.ExperimentalFeature;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.Role;
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.actionmanager.ActionManager;
+import org.apache.ambari.server.actionmanager.RequestFactory;
+import org.apache.ambari.server.actionmanager.Stage;
+import org.apache.ambari.server.actionmanager.StageFactory;
+import org.apache.ambari.server.agent.ExecutionCommand.KeyNames;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.ActionExecutionContext;
+import org.apache.ambari.server.controller.AmbariActionExecutionHelper;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.RequestStatusResponse;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.dao.MpackDAO;
+import org.apache.ambari.server.orm.dao.MpackHostStateDAO;
+import org.apache.ambari.server.orm.dao.ServiceGroupDAO;
+import org.apache.ambari.server.orm.dao.UpgradePlanDAO;
+import org.apache.ambari.server.orm.entities.HostEntity;
+import org.apache.ambari.server.orm.entities.MpackEntity;
+import org.apache.ambari.server.orm.entities.MpackHostStateEntity;
+import org.apache.ambari.server.orm.entities.RepoOsEntity;
+import org.apache.ambari.server.orm.entities.ServiceGroupEntity;
+import org.apache.ambari.server.orm.entities.UpgradePlanDetailEntity;
+import org.apache.ambari.server.orm.entities.UpgradePlanEntity;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.Mpack;
+import org.apache.ambari.server.state.MpackInstallState;
+import org.apache.ambari.server.state.OsSpecific;
+import org.apache.ambari.server.state.StackInfo;
+import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.persist.Transactional;
+
+/**
+ * Manages upgrade plans.
+ */
+@StaticallyInject
+@Experimental(feature=ExperimentalFeature.UNIT_TEST_REQUIRED)
+public class UpgradePlanInstallResourceProvider extends AbstractControllerResourceProvider {
+
+  private static final String UPGRADE_PLAN_INSTALL = "UpgradePlanInstall" + PropertyHelper.EXTERNAL_PATH_SEP;
+
+  protected static final String UPGRADE_PLAN_INSTALL_ID             = UPGRADE_PLAN_INSTALL + "id";
+  protected static final String UPGRADE_PLAN_INSTALL_CLUSTER_NAME   = UPGRADE_PLAN_INSTALL + "cluster_name";
+  protected static final String UPGRADE_PLAN_INSTALL_SUCCESS_FACTOR = UPGRADE_PLAN_INSTALL + "success_factor";
+  protected static final String UPGRADE_PLAN_INSTALL_FORCE          = UPGRADE_PLAN_INSTALL + "force";
+
+  private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = ImmutableMap.<Resource.Type, String>builder()
+      .put(Resource.Type.UpgradePlanInstall, UPGRADE_PLAN_INSTALL_ID)
+      .put(Resource.Type.Cluster, UPGRADE_PLAN_INSTALL_CLUSTER_NAME)
+      .build();
+
+  private static final Set<String> PK_PROPERTY_IDS = Sets.newHashSet(KEY_PROPERTY_IDS.values());
+
+  private static final Set<String> PROPERTY_IDS = Sets.newHashSet(
+      UPGRADE_PLAN_INSTALL_ID,
+      UPGRADE_PLAN_INSTALL_CLUSTER_NAME);
+
+  protected static final String MPACK_PACKAGES_ACTION = "mpack_packages";
+  protected static final String INSTALL_PACKAGES = "Install Version";
+
+  /**
+   * The default success factor that will be used when determining if a stage's
+   * failure should cause other stages to abort. Consider a scenario with 1000
+   * hosts, broken up into 10 stages. Each stage would have 100 hosts. If the
+   * success factor was 100%, then any failure in stage 1 woudl cause all 9
+   * other stages to abort. If set to 90%, then 10 hosts would need to fail for
+   * the other stages to abort. This is necessary to prevent the abortion of
+   * stages based on 1 or 2 errant hosts failing in a large cluster's stack
+   * distribution.
+   */
+  private static final float DEFAULT_SUCCESS_FACTOR = 0.85f;
+
+  /**
+   * Used to deserialize the repository JSON into an object.
+   */
+  @Inject
+  private static Gson s_gson;
+
+  @Inject
+  private static UpgradePlanDAO s_upgradePlanDAO;
+
+  @Inject
+  private static ServiceGroupDAO s_serviceGroupDAO;
+
+  @Inject
+  private static MpackDAO s_mpackDAO;
+
+  @Inject
+  private static MpackHostStateDAO s_mpackHostStateDAO;
+
+  @Inject
+  private static RequestFactory s_requestFactory;
+
+  @Inject
+  private static StageFactory s_stageFactory;
+
+  @Inject
+  private static Configuration s_configuration;
+
+  @Inject
+  private static RepositoryVersionHelper s_repoHelper;
+
+  @Inject
+  private static Provider<AmbariActionExecutionHelper> s_actionExecutionHelper;
+
+
+  /**
+   * Constructor.
+   *
+   * @param controller the controller
+   */
+  UpgradePlanInstallResourceProvider(AmbariManagementController controller) {
+    super(Resource.Type.UpgradePlanInstall, PROPERTY_IDS, KEY_PROPERTY_IDS, controller);
+
+    setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.CLUSTER_UPGRADE_DOWNGRADE_STACK));
+  }
+
+  @Override
+  public RequestStatus createResourcesAuthorized(final Request request)
+      throws SystemException,
+      UnsupportedPropertyException, ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+
+    throw new SystemException("Upgrade plan installs cannot be created.  Update the resource instead.");
+  }
+
+  @Override
+  public Set<Resource> getResourcesAuthorized(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+
+    throw new SystemException("Upgrade plan installs cannot be requested");
+  }
+
+  @Override
+  public RequestStatus updateResourcesAuthorized(final Request request,
+      Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+
+    Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
+
+    if (propertyMaps.isEmpty()) {
+      throw new IllegalArgumentException("At least one upgrade plan should be specified.");
+    } else if (propertyMaps.size() > 1) {
+      throw new IllegalArgumentException("Only one upgrade plan may be installed at one time.");
+    }
+
+    // !!! The Highlander Principle: in the end, there can be only one
+    Map<String, Object> propertyMap = propertyMaps.iterator().next();
+
+    if (!propertyMap.containsKey(UPGRADE_PLAN_INSTALL_CLUSTER_NAME)) {
+      throw new IllegalArgumentException("Cluster name is not specified");
+    } else if (!propertyMap.containsKey(UPGRADE_PLAN_INSTALL_ID)) {
+      throw new IllegalArgumentException("Upgrade plan id is required");
+    }
+
+
+    String clusterName = propertyMap.get(UPGRADE_PLAN_INSTALL_CLUSTER_NAME).toString();
+    Cluster cluster = null;
+    try {
+      cluster = getManagementController().getClusters().getCluster(clusterName);
+    } catch (AmbariException e) {
+      throw new IllegalArgumentException(e);
+    }
+
+    String upgradePlanIdString = propertyMap.get(UPGRADE_PLAN_INSTALL_ID).toString();
+    Long upgradePlanId = NumberUtils.toLong(upgradePlanIdString, -1L);
+    if (-1L == upgradePlanId) {
+      throw new IllegalArgumentException("Upgrade plan id was specified, but is not a long");
+    }
+
+    UpgradePlanEntity upgradePlan = s_upgradePlanDAO.findByPK(upgradePlanId);
+    if (null == upgradePlan) {
+      throw new IllegalArgumentException(String.format("Upgrade plan %s was not found", upgradePlanId));
+    }
+
+    boolean forceAll = false;
+    if (propertyMap.containsKey(UPGRADE_PLAN_INSTALL_FORCE)) {
+      String forceAllString = propertyMap.get(UPGRADE_PLAN_INSTALL_FORCE).toString();
+      forceAll = BooleanUtils.toBoolean(forceAllString);
+    }
+
+    Float successFactor = DEFAULT_SUCCESS_FACTOR;
+    if (propertyMap.containsKey(UPGRADE_PLAN_INSTALL_SUCCESS_FACTOR)) {
+      String successFactorString = propertyMap.get(UPGRADE_PLAN_INSTALL_SUCCESS_FACTOR).toString();
+      successFactor = NumberUtils.toFloat(successFactorString, DEFAULT_SUCCESS_FACTOR);
+    }
+
+    RequestStageContainer installRequest = null;
+    try {
+      installRequest = createOrchestration(cluster, upgradePlan, successFactor, forceAll);
+    } catch (AmbariException e) {
+      throw new IllegalArgumentException(e);
+    }
+
+    RequestStatusResponse response = installRequest.getRequestStatusResponse();
+
+    return getRequestStatus(response);
+  }
+
+  @Transactional(rollbackOn= {AmbariException.class, RuntimeException.class})
+  RequestStageContainer createOrchestration(Cluster cluster, UpgradePlanEntity upgradePlan,
+      float successFactor, boolean forceInstall) throws AmbariException, SystemException {
+
+    // TODO - API calls (elsewhere) that make checks for compatible mpacks and selected SGs
+
+    // for each plan detail, the mpack and selected SG has has already been
+    // predetermined via compatibility
+
+    // !!! a single host may get more than one mpack to install.  those are different
+    // !!! host name -> set of mpack package names
+    Map<HostEntity, Set<MpackInstallDetail>> details = new HashMap<>();
+
+    for (UpgradePlanDetailEntity upgradePlanEntity : upgradePlan.getDetails()) {
+      long serviceGroupId = upgradePlanEntity.getServiceGroupId();
+      ServiceGroupEntity serviceGroup = s_serviceGroupDAO.findByPK(serviceGroupId);
+
+      // is this even possible?
+      if (null == serviceGroup.getStack().getMpackId()) {
+        continue;
+      }
+
+      MpackEntity targetMpackEntity = s_mpackDAO.findById(upgradePlanEntity.getMpackTargetId());
+      StackInfo targetStack = getManagementController().getAmbariMetaInfo()
+          .getStack(targetMpackEntity.getStackId());
+
+      // find all hosts for the service group via its mpack
+      List<MpackHostStateEntity> mpackHosts = s_mpackHostStateDAO.findByMpackAndInstallState(
+          serviceGroup.getStack().getMpackId(), MpackInstallState.INSTALLED);
+
+      if (CollectionUtils.isEmpty(mpackHosts)) {
+        throw new SystemException("Cannot install upgrade plan as the current mpack is not installed.");
+      }
+
+      mpackHosts.forEach(mpackHostStateEntity ->
+        {
+          Host host = cluster.getHost(mpackHostStateEntity.getHostName());
+          HostEntity hostEntity = mpackHostStateEntity.getHostEntity();
+          String osFamily = host.getOsFamily();
+
+          List<OsSpecific.Package> packages = new ArrayList<>();
+
+          OsSpecific anyPackages = targetStack.getOsSpecifics().get(AmbariMetaInfo.ANY_OS);
+          OsSpecific familyPackages = targetStack.getOsSpecificsSafe().get(osFamily);
+          // !!! TODO get service specific package names
+
+          Arrays.stream(new OsSpecific[] {anyPackages, familyPackages})
+            .filter(osSpecific -> null != osSpecific && CollectionUtils.isNotEmpty(osSpecific.getPackages()))
+            .forEach(osSpecific -> {
+              packages.addAll(osSpecific.getPackages());
+            });
+
+          if (!details.containsKey(hostEntity)) {
+            details.put(hostEntity, new HashSet<>());
+          }
+
+          MpackInstallDetail installDetail = new MpackInstallDetail(targetMpackEntity, packages);
+          installDetail.serviceGroupName = serviceGroup.getServiceGroupName();
+          details.get(hostEntity).add(installDetail);
+        });
+    }
+
+    // !!! at this point we have a map of hosts and the installations that each one needs to run.
+
+    RequestStageContainer stageContainer = createRequest();
+
+    Iterator<Entry<HostEntity, Set<MpackInstallDetail>>> hostMapIterator = details.entrySet().iterator();
+
+    int maxTasks = s_configuration.getAgentPackageParallelCommandsLimit();
+    int hostCount = details.size();
+    int batchCount = (int) (Math.ceil((double) hostCount / maxTasks));
+
+
+    long stageId = stageContainer.getLastStageId() + 1;
+    if (0L == stageId) {
+      stageId = 1L;
+    }
+
+    ArrayList<Stage> stages = new ArrayList<>(batchCount);
+    for (int batchId = 1; batchId <= batchCount; batchId++) {
+      // Create next stage
+      String stageName;
+      if (batchCount > 1) {
+        stageName = String.format(INSTALL_PACKAGES + ". Batch %d of %d", batchId,
+            batchCount);
+      } else {
+        stageName = INSTALL_PACKAGES;
+      }
+
+      Stage stage = s_stageFactory.createNew(stageContainer.getId(), "/tmp/ambari", cluster.getClusterName(),
+          cluster.getClusterId(), stageName, "{}", "{}");
+
+      stage.getSuccessFactors().put(Role.valueOf(MPACK_PACKAGES_ACTION), successFactor);
+      stage.setStageId(stageId);
+      stageId++;
+
+      // add the stage that was just created
+      stages.add(stage);
+
+      // Populate with commands for host
+      for (int i = 0; i < maxTasks && hostMapIterator.hasNext(); i++) {
+        Entry<HostEntity, Set<MpackInstallDetail>> entry = hostMapIterator.next();
+        HostEntity host = entry.getKey();
+
+        // add host to this stage
+        RequestResourceFilter filter = new RequestResourceFilter(null, null, null,
+                Collections.singletonList(host.getHostName()));
+
+        List<OsSpecific.Package> packages = new ArrayList<>();
+        entry.getValue().forEach(d -> { packages.addAll(d.mpackPackages); });
+
+        Map<String, String> roleParams = ImmutableMap.<String, String>builder()
+            .put(KeyNames.PACKAGE_LIST, s_gson.toJson(packages))
+            .build();
+
+        // !!! this loop PROBABLY won't work out, but leave for now to get things going
+        for (MpackInstallDetail mpackDetail : entry.getValue()) {
+          ActionExecutionContext actionContext = new ActionExecutionContext(cluster.getClusterName(),
+              MPACK_PACKAGES_ACTION, Collections.singletonList(filter), roleParams);
+
+          actionContext.setTimeout(Short.valueOf(s_configuration.getDefaultAgentTaskTimeout(true)));
+          actionContext.setExpectedServiceGroupName(mpackDetail.serviceGroupName);
+
+          Host h = cluster.getHost(host.getHostName());
+          Mpack mpack = getManagementController().getAmbariMetaInfo().getMpack(mpackDetail.mpackId);
+          RepoOsEntity repoOsEntity = s_repoHelper.getOSEntityForHost(mpackDetail.mpackEntity, h);
+
+          // this isn't being placed correctly elsewhere
+          actionContext.addVisitor(command -> {
+            try {
+              command.setClusterSettings(cluster.getClusterSettingsNameValueMap());
+            } catch (AmbariException e) {
+              LOG.warn("Could not set cluster settings on the command", e);
+            }
+          });
+
+          s_repoHelper.addCommandRepositoryToContext(actionContext, mpack, repoOsEntity);
+
+          s_actionExecutionHelper.get().addExecutionCommandsToStage(actionContext, stage, null);
+        }
+      }
+    }
+
+    stageContainer.addStages(stages);
+    stageContainer.persist();
+
+    return stageContainer;
+  }
+
+  @Override
+  public RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    throw new SystemException("Upgrade plan installs cannot be removed");
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return PK_PROPERTY_IDS;
+  }
+
+  private RequestStageContainer createRequest() {
+    ActionManager actionManager = getManagementController().getActionManager();
+
+    RequestStageContainer requestStages = new RequestStageContainer(
+            actionManager.getNextRequestId(), null, s_requestFactory, actionManager);
+    requestStages.setRequestContext(INSTALL_PACKAGES);
+
+    return requestStages;
+  }
+
+  private static class MpackInstallDetail {
+    private MpackEntity mpackEntity;
+    private long mpackId = -1L;
+    private List<OsSpecific.Package> mpackPackages = new ArrayList<>();
+    private String serviceGroupName;
+
+    private MpackInstallDetail(MpackEntity entity, List<OsSpecific.Package> packages) {
+      mpackEntity = entity;
+      mpackId = entity.getId();
+      mpackPackages = packages;
+    }
+  }
+
+}
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index 57f7e28..7661ea1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -160,6 +160,7 @@ public interface Resource {
     UpgradeGroup,
     UpgradeItem,
     UpgradePlan,
+    UpgradePlanInstall,
     UpgradeSummary,
     PreUpgradeCheck,
     Stage,
@@ -299,6 +300,7 @@ public interface Resource {
     public static final Type UpgradeGroup = InternalType.UpgradeGroup.getType();
     public static final Type UpgradeItem = InternalType.UpgradeItem.getType();
     public static final Type UpgradePlan = InternalType.UpgradePlan.getType();
+    public static final Type UpgradePlanInstall = InternalType.UpgradePlanInstall.getType();
     public static final Type UpgradeSummary = InternalType.UpgradeSummary.getType();
     public static final Type PreUpgradeCheck = InternalType.PreUpgradeCheck.getType();
     public static final Type Stage = InternalType.Stage.getType();
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MpackHostStateDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MpackHostStateDAO.java
index 18abf89..8aa5b73 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MpackHostStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MpackHostStateDAO.java
@@ -136,6 +136,28 @@ public class MpackHostStateDAO extends CrudDAO<MpackHostStateEntity, Long> {
   }
 
   /**
+   * Retrieve all of the matching install states for any mpack on the given
+   * host.
+   *
+   * @param mpackId
+   *          the ID of the mpack
+   * @param hostName
+   *          FQDN of host
+   * @return all of the hosts in the cluster which have entries for the
+   *         specified mpack.
+   */
+  @RequiresSession
+  public List<MpackHostStateEntity> findByMpackAndInstallState(Long mpackId, MpackInstallState state) {
+    final TypedQuery<MpackHostStateEntity> query = entityManagerProvider.get().createNamedQuery(
+        "findInstallStateByMpackAndState", MpackHostStateEntity.class);
+    query.setParameter("mpackId", mpackId);
+    query.setParameter("mpackInstallState", state);
+
+    return daoUtils.selectList(query);
+  }
+
+
+  /**
    * Removes all of the associated mpack host states for a given host.
    *
    * @param hostName
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MpackHostStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MpackHostStateEntity.java
index c3384a3..b2907a9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MpackHostStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MpackHostStateEntity.java
@@ -67,8 +67,10 @@ import org.apache.ambari.server.state.MpackInstallState;
         query = "SELECT mpackHostState FROM MpackHostStateEntity mpackHostState WHERE mpackHostState.mpackId = :mpackId AND mpackHostState.hostEntity.hostName=:hostName"),
     @NamedQuery(
         name = "findInstallStateByStateAndHost",
-        query = "SELECT mpackHostState FROM MpackHostStateEntity mpackHostState WHERE mpackHostState.hostEntity.hostName=:hostName AND mpackHostState.state = :mpackInstallState") })
-
+        query = "SELECT mpackHostState FROM MpackHostStateEntity mpackHostState WHERE mpackHostState.hostEntity.hostName=:hostName AND mpackHostState.state = :mpackInstallState"),
+    @NamedQuery(
+        name = "findInstallStateByMpackAndState",
+        query = "SELECT mpackHostState FROM MpackHostStateEntity mpackHostState WHERE mpackHostState.mpackId = :mpackId AND mpackHostState.state = :mpackInstallState") })
 public class MpackHostStateEntity {
 
   /**
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java
index 56644c7..04e29f8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java
@@ -91,6 +91,10 @@ public class ServiceGroupEntity {
   @OneToMany(mappedBy="serviceGroupDependency")
   private List<ServiceGroupDependencyEntity> dependencies;
 
+  @OneToMany(mappedBy="serviceGroupEntity")
+  private List<ClusterServiceEntity> clusterServices;
+
+
   public Long getClusterId() {
     return clusterId;
   }
@@ -139,6 +143,10 @@ public class ServiceGroupEntity {
     this.serviceGroupDependencies = serviceGroupDependencies;
   }
 
+  public List<ClusterServiceEntity> getClusterServices() {
+    return clusterServices;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java
index 6055724..ba4daec 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java
@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.state;
 
+import java.util.Collection;
 import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
@@ -87,4 +88,11 @@ public interface ServiceGroup {
    * @param stackEntity the stack to set.
    */
   void setStack(StackEntity stackEntity);
+
+  /**
+   * @return the services associated with this service group.
+   *
+   * @throws AmbariException
+   */
+  Collection<Service> getServices() throws AmbariException;
 }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
index 63a7e01..aed1de6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
@@ -18,9 +18,11 @@
 
 package org.apache.ambari.server.state;
 
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.services.ServiceGroupKey;
@@ -52,6 +54,7 @@ public class ServiceGroupImpl implements ServiceGroup {
   private final ClusterDAO clusterDAO;
   private final StackDAO stackDAO;
   private final ServiceGroupDAO serviceGroupDAO;
+  private final ServiceFactory serviceFactory;
   private final AmbariEventPublisher eventPublisher;
   private final Clusters clusters;
 
@@ -68,6 +71,7 @@ public class ServiceGroupImpl implements ServiceGroup {
                           ClusterDAO clusterDAO,
                           StackDAO stackDAO,
                           ServiceGroupDAO serviceGroupDAO,
+                          ServiceFactory serviceFactory,
                           AmbariEventPublisher eventPublisher,
                           Clusters clusters) throws AmbariException {
 
@@ -76,6 +80,7 @@ public class ServiceGroupImpl implements ServiceGroup {
     this.clusterDAO = clusterDAO;
     this.stackDAO = stackDAO;
     this.serviceGroupDAO = serviceGroupDAO;
+    this.serviceFactory = serviceFactory;
     this.eventPublisher = eventPublisher;
 
     this.serviceGroupName = serviceGroupName;
@@ -101,6 +106,7 @@ public class ServiceGroupImpl implements ServiceGroup {
                           ClusterDAO clusterDAO,
                           StackDAO stackDAO,
                           ServiceGroupDAO serviceGroupDAO,
+                          ServiceFactory serviceFactory,
                           AmbariEventPublisher eventPublisher,
                           Clusters clusters) throws AmbariException {
     this.cluster = cluster;
@@ -108,6 +114,7 @@ public class ServiceGroupImpl implements ServiceGroup {
     this.clusterDAO = clusterDAO;
     this.stackDAO = stackDAO;
     this.serviceGroupDAO = serviceGroupDAO;
+    this.serviceFactory = serviceFactory;
     this.eventPublisher = eventPublisher;
 
     serviceGroupId = serviceGroupEntity.getServiceGroupId();
@@ -370,4 +377,17 @@ public class ServiceGroupImpl implements ServiceGroup {
     serviceGroupEntity.setStack(stackEntity);
     serviceGroupEntity = serviceGroupDAO.merge(serviceGroupEntity);
   }
+
+  @Override
+  public Collection<Service> getServices() throws AmbariException {
+
+    Cluster cluster = getCluster();
+    ServiceGroupEntity serviceGroup = getServiceGroupEntity();
+
+    // !!! not sure how performant this is going to be.  possible optimization point.
+    return serviceGroup.getClusterServices().stream().map(entity -> {
+      return serviceFactory.createExisting(cluster, this, entity);
+    }).collect(Collectors.toList());
+  }
+
 }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
index 1ce6b74..0cfb8d1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
@@ -33,6 +33,7 @@ import org.apache.ambari.server.controller.StackVersionResponse;
 import org.apache.ambari.server.stack.Validable;
 import org.apache.ambari.server.state.repository.VersionDefinitionXml;
 import org.apache.ambari.server.state.stack.ConfigUpgradePack;
+import org.apache.ambari.server.state.stack.LatestRepoCallable;
 import org.apache.ambari.server.state.stack.RepositoryXml;
 import org.apache.ambari.server.state.stack.StackRoleCommandOrder;
 import org.apache.ambari.server.state.stack.UpgradePack;
@@ -112,6 +113,15 @@ public class StackInfo implements Comparable<StackInfo>, Validable {
     return stackOsSpecificsMap;
   }
 
+  /**
+   * Exposes  map of os-specific details.
+   * @return  map of OS specific details keyed by family
+   */
+  public Map<String, OsSpecific> getOsSpecificsSafe() {
+    return (null != stackOsSpecificsMap) ? stackOsSpecificsMap : new HashMap<>();
+  }
+
+
   public void setOsSpecifics(Map<String, OsSpecific> serviceOsSpecificsMap) {
     this.stackOsSpecificsMap = serviceOsSpecificsMap;
   }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java
index 84b11f9..fc64c69 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/RepositoryVersionHelper.java
@@ -438,6 +438,28 @@ public class RepositoryVersionHelper {
       long mpackId = serviceGroup.getMpackId();
       Mpack mpack = ambariMetaInfo.getMpack(mpackId);
 
+      addCommandRepositoryToContext(context, mpack, osEntity);
+
+    } catch (AmbariException ambariException) {
+      throw new SystemException(ambariException.getMessage(), ambariException);
+    }
+  }
+
+  /**
+   * Adds a command repository to the action context for the supplied mpack.  This is
+   * primarily called when distributing packages of a different mpack for a compatible
+   * service group
+   * @param context
+   *          the context
+   * @param mpack
+   *          the target mpack
+   * @param osEntity
+   *          the OS family
+   * @throws SystemException
+   */
+  public void addCommandRepositoryToContext(ActionExecutionContext context,
+      Mpack mpack, RepoOsEntity osEntity) throws SystemException {
+    try {
       final CommandRepository commandRepo = getCommandRepository(mpack, osEntity);
 
       context.addVisitor(command -> {
diff --git a/ambari-server/src/main/resources/custom_action_definitions/system_action_definitions.xml b/ambari-server/src/main/resources/custom_action_definitions/system_action_definitions.xml
index 0f50256..ccea252 100644
--- a/ambari-server/src/main/resources/custom_action_definitions/system_action_definitions.xml
+++ b/ambari-server/src/main/resources/custom_action_definitions/system_action_definitions.xml
@@ -64,9 +64,9 @@
     <permissions>CLUSTER.MODIFY_CONFIGS, SERVICE.MODIFY_CONFIGS</permissions>
   </actionDefinition>
   <actionDefinition>
-    <actionName>install_packages</actionName>
+    <actionName>mpack_packages</actionName>
     <actionType>SYSTEM</actionType>
-    <inputs>base_urls, package_list</inputs>
+    <inputs>package_list</inputs>
     <targetService/>
     <targetComponent/>
     <defaultTimeout>60</defaultTimeout>
diff --git a/ambari-server/src/main/resources/custom_actions/scripts/install_packages.py b/ambari-server/src/main/resources/custom_actions/scripts/install_packages.py
deleted file mode 100644
index 9cc3aef..0000000
--- a/ambari-server/src/main/resources/custom_actions/scripts/install_packages.py
+++ /dev/null
@@ -1,480 +0,0 @@
-#!/usr/bin/env python
-"""
-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.
-
-"""
-import signal
-import os
-import re
-
-import ambari_simplejson as json
-
-from ambari_commons.os_check import OSCheck
-from ambari_commons.shell import RepoCallContext
-from ambari_commons.str_utils import cbool, cint
-from ambari_commons.repo_manager import ManagerFactory
-from resource_management.core.exceptions import Fail
-from resource_management.core.logger import Logger
-from resource_management.libraries.functions import conf_select
-from resource_management.libraries.functions import stack_tools
-from resource_management.libraries.functions.stack_select import get_stack_versions
-from resource_management.libraries.functions.repo_version_history \
-    import read_actual_version_from_history_file, write_actual_version_to_history_file, REPO_VERSION_HISTORY_FILE
-from resource_management.core.resources.system import Link
-from resource_management.libraries.functions import StackFeature
-from resource_management.libraries.functions.repository_util import CommandRepository
-from resource_management.libraries.functions.stack_features import check_stack_feature
-from resource_management.libraries.script.script import Script
-from resource_management.core import sudo
-
-
-class InstallPackages(Script):
-  """
-  This script is a part of Rolling Upgrade workflow and is described at
-  appropriate design doc.
-  It installs repositories to the node and then installs packages.
-  For now, repositories are installed into individual files.
-  """
-
-  UBUNTU_REPO_COMPONENTS_POSTFIX = ["main"]
-
-  def __init__(self):
-    super(InstallPackages, self).__init__()
-
-    self.repo_mgr = ManagerFactory.get()
-    self.repo_files = {}
-
-  def actionexecute(self, env):
-    num_errors = 0
-
-    # Parse parameters
-    config = Script.get_config()
-
-    try:
-      command_repository = CommandRepository(config['repositoryFile'])
-    except KeyError:
-      raise Fail("The command repository indicated by 'repositoryFile' was not found")
-
-    # Handle a SIGTERM and SIGINT gracefully
-    signal.signal(signal.SIGTERM, self.abort_handler)
-    signal.signal(signal.SIGINT, self.abort_handler)
-
-    self.repository_version = command_repository.version_string
-
-    # Select dict that contains parameters
-    try:
-      package_list = json.loads(config['roleParams']['package_list'])
-      stack_id = config['roleParams']['stack_id']
-    except KeyError:
-      pass
-
-    self.stack_name = Script.get_stack_name()
-    if self.stack_name is None:
-      raise Fail("Cannot determine the stack name")
-
-    self.stack_root_folder = Script.get_stack_root()
-    if self.stack_root_folder is None:
-      raise Fail("Cannot determine the stack's root directory")
-
-    if self.repository_version is None:
-      raise Fail("Cannot determine the repository version to install")
-
-    self.repository_version = self.repository_version.strip()
-
-    try:
-      if not command_repository.items:
-        Logger.warning(
-          "Repository list is empty. Ambari may not be managing the repositories for {0}.".format(
-            self.repository_version))
-      else:
-        Logger.info(
-          "Will install packages for repository version {0}".format(self.repository_version))
-        new_repo_files = Script.repository_util.create_repo_files()
-        self.repo_files.update(new_repo_files)
-    except Exception as err:
-      Logger.logger.exception("Cannot install repository files. Error: {0}".format(str(err)))
-      num_errors += 1
-
-    # Build structured output with initial values
-    self.structured_output = {
-      'package_installation_result': 'FAIL',
-      'mpack_id': command_repository.mpack_id
-    }
-
-    self.put_structured_out(self.structured_output)
-
-    try:
-      # check package manager non-completed transactions
-      if self.repo_mgr.check_uncompleted_transactions():
-        self.repo_mgr.print_uncompleted_transaction_hint()
-        num_errors += 1
-    except Exception as e:  # we need to ignore any exception
-      Logger.warning("Failed to check for uncompleted package manager transactions: " + str(e))
-
-    if num_errors > 0:
-      raise Fail("Failed to distribute repositories/install packages")
-
-    # Initial list of versions, used to compute the new version installed
-    self.old_versions = get_stack_versions(self.stack_root_folder)
-
-    try:
-      is_package_install_successful = False
-      ret_code = self.install_packages(package_list)
-      if ret_code == 0:
-        self.structured_output['package_installation_result'] = 'SUCCESS'
-        self.put_structured_out(self.structured_output)
-        is_package_install_successful = True
-      else:
-        num_errors += 1
-    except Exception as err:
-      num_errors += 1
-      Logger.logger.exception("Could not install packages. Error: {0}".format(str(err)))
-
-    # Provide correct exit code
-    if num_errors > 0:
-      raise Fail("Failed to distribute repositories/install packages")
-
-    self._fix_default_links_for_current()
-    # if installing a version of HDP that needs some symlink love, then create them
-    if is_package_install_successful and 'actual_version' in self.structured_output:
-      self._relink_configurations_with_conf_select(stack_id, self.structured_output['actual_version'])
-
-  def _fix_default_links_for_current(self):
-    """
-    If a prior version of Ambari did not correctly reverse the conf symlinks, then they would
-    be put into a bad state when distributing a new stack. For example:
-
-    /etc/component/conf (directory)
-    <stack-root>/v1/component/conf -> /etc/component/conf
-
-    When distributing v2, we'd detect the /etc/component/conf problems and would try to adjust it:
-    /etc/component/conf -> <stack-root>/current/component/conf
-    <stack-root>/v2/component/conf -> /etc/component/v2/0
-
-    The problem is that v1 never gets changed (since the stack being distributed is v2), and
-    we end up with a circular link:
-    /etc/component/conf -> <stack-root>/current/component/conf
-    <stack-root>/v1/component/conf -> /etc/component/conf
-
-    :return: None
-    """
-    Logger.info("Attempting to fix any configuration symlinks which are not in the correct state")
-    from resource_management.libraries.functions import stack_select
-    restricted_packages = conf_select.get_restricted_packages()
-
-    if 0 == len(restricted_packages):
-      Logger.info("There are no restricted conf-select packages for this installation")
-    else:
-      Logger.info("Restricting conf-select packages to {0}".format(restricted_packages))
-
-    for package_name, directories in conf_select.get_package_dirs().iteritems():
-      Logger.info("Attempting to fix the default conf links for {0}".format(package_name))
-      Logger.info("The following directories will be fixed for {0}: {1}".format(package_name, str(directories)))
-
-      component_name = None
-      for directory_struct in directories:
-        if "component" in directory_struct:
-          component_name = directory_struct["component"]
-
-      if component_name:
-        stack_version = stack_select.get_stack_version_before_install(component_name)
-      else:
-        Logger.warning("Unable to fix {0} since stack using outdated stack_packages.json".format(package_name))
-        return
-
-      if 0 == len(restricted_packages) or package_name in restricted_packages:
-        if stack_version:
-          conf_select.convert_conf_directories_to_symlinks(package_name, stack_version, directories)
-        else:
-          Logger.warning(
-            "Unable to fix {0} since there is no known installed version for this component".format(package_name))
-
-  def _relink_configurations_with_conf_select(self, stack_id, stack_version):
-    """
-    Sets up the required structure for /etc/<component>/conf symlinks and <stack-root>/current
-    configuration symlinks IFF the current stack is < HDP 2.3+ and the new stack is >= HDP 2.3
-
-    stack_id:  stack id, ie HDP-2.3
-    stack_version:  version to set, ie 2.3.0.0-1234
-    """
-    if stack_id is None:
-      Logger.info("Cannot create config links when stack_id is not defined")
-      return
-
-    args = stack_id.upper().split('-')
-    if len(args) != 2:
-      Logger.info("Unrecognized stack id {0}, cannot create config links".format(stack_id))
-      return
-
-    target_stack_version = args[1]
-    if not (target_stack_version and check_stack_feature(StackFeature.CONFIG_VERSIONING, target_stack_version)):
-      Logger.info("Configuration symlinks are not needed for {0}".format(stack_version))
-      return
-
-    # After upgrading hdf-select package from HDF-2.X to HDF-3.Y, we need to create this symlink
-    if self.stack_name.upper() == "HDF" \
-            and not sudo.path_exists("/usr/bin/conf-select") and sudo.path_exists("/usr/bin/hdfconf-select"):
-      Link("/usr/bin/conf-select", to="/usr/bin/hdfconf-select")
-
-    restricted_packages = conf_select.get_restricted_packages()
-
-    if 0 == len(restricted_packages):
-      Logger.info("There are no restricted conf-select packages for this installation")
-    else:
-      Logger.info("Restricting conf-select packages to {0}".format(restricted_packages))
-
-    for package_name, directories in conf_select.get_package_dirs().iteritems():
-      if 0 == len(restricted_packages) or package_name in restricted_packages:
-        conf_select.convert_conf_directories_to_symlinks(package_name, stack_version, directories)
-
-
-  def compute_actual_version(self):
-    """
-    After packages are installed, determine what the new actual version is.
-    """
-
-    # If the repo contains a build number, optimistically assume it to be the actual_version. It will get changed
-    # to correct value if it is not
-    self.actual_version = None
-    self.repo_version_with_build_number = None
-    if self.repository_version:
-      m = re.search("[\d\.]+-\d+", self.repository_version)
-      if m:
-        # Contains a build number
-        self.repo_version_with_build_number = self.repository_version
-        self.structured_output['actual_version'] = self.repo_version_with_build_number  # This is the best value known so far.
-        self.put_structured_out(self.structured_output)
-
-    Logger.info("Attempting to determine actual version with build number.")
-    Logger.info("Old versions: {0}".format(self.old_versions))
-
-    new_versions = get_stack_versions(self.stack_root_folder)
-    Logger.info("New versions: {0}".format(new_versions))
-
-    deltas = set(new_versions) - set(self.old_versions)
-    Logger.info("Deltas: {0}".format(deltas))
-
-    # Get version without build number
-    normalized_repo_version = self.repository_version.split('-')[0]
-
-    if 1 == len(deltas):
-      self.actual_version = next(iter(deltas)).strip()
-      self.structured_output['actual_version'] = self.actual_version
-      self.put_structured_out(self.structured_output)
-      write_actual_version_to_history_file(normalized_repo_version, self.actual_version)
-      Logger.info(
-        "Found actual version {0} by checking the delta between versions before and after installing packages".format(
-          self.actual_version))
-    else:
-      # If the first install attempt does a partial install and is unable to report this to the server,
-      # then a subsequent attempt will report an empty delta. For this reason, we search for a best fit version for the repo version
-      Logger.info("Cannot determine actual version installed by checking the delta between versions "
-                  "before and after installing package")
-      Logger.info("Will try to find for the actual version by searching for best possible match in the list of versions installed")
-      self.actual_version = self.find_best_fit_version(new_versions, self.repository_version)
-      if self.actual_version is not None:
-        self.actual_version = self.actual_version.strip()
-        self.structured_output['actual_version'] = self.actual_version
-        self.put_structured_out(self.structured_output)
-        Logger.info("Found actual version {0} by searching for best possible match".format(self.actual_version))
-      else:
-        msg = "Could not determine actual version installed. Try reinstalling packages again."
-        raise Fail(msg)
-
-  def check_partial_install(self):
-    """
-    If an installation did not complete successfully, check if installation was partially complete and
-    log the partially completed version to REPO_VERSION_HISTORY_FILE.
-    :return:
-    """
-    Logger.info("Installation of packages failed. Checking if installation was partially complete")
-    Logger.info("Old versions: {0}".format(self.old_versions))
-
-    new_versions = get_stack_versions(self.stack_root_folder)
-    Logger.info("New versions: {0}".format(new_versions))
-
-    deltas = set(new_versions) - set(self.old_versions)
-    Logger.info("Deltas: {0}".format(deltas))
-
-    # Get version without build number
-    normalized_repo_version = self.repository_version.split('-')[0]
-
-    if 1 == len(deltas):
-      # Some packages were installed successfully. Log this version to REPO_VERSION_HISTORY_FILE
-      partial_install_version = next(iter(deltas)).strip()
-      write_actual_version_to_history_file(normalized_repo_version, partial_install_version)
-      Logger.info("Version {0} was partially installed. ".format(partial_install_version))
-
-  def find_best_fit_version(self, versions, repo_version):
-    """
-    Given a list of installed versions and a repo version, search for a version that best fits the repo version
-    If the repo version is found in the list of installed versions, return the repo version itself.
-    If the repo version is not found in the list of installed versions
-    normalize the repo version and use the REPO_VERSION_HISTORY_FILE file to search the list.
-
-    :param versions: List of versions installed
-    :param repo_version: Repo version to search
-    :return: Matching version, None if no match was found.
-    """
-    if versions is None or repo_version is None:
-      return None
-
-    build_num_match = re.search("[\d\.]+-\d+", repo_version)
-    if build_num_match and repo_version in versions:
-      # If repo version has build number and is found in the list of versions, return it as the matching version
-      Logger.info("Best Fit Version: Resolved from repo version with valid build number: {0}".format(repo_version))
-      return repo_version
-
-    # Get version without build number
-    normalized_repo_version = repo_version.split('-')[0]
-
-    # Find all versions that match the normalized repo version
-    match_versions = filter(lambda x: x.startswith(normalized_repo_version), versions)
-    if match_versions:
-
-      if len(match_versions) == 1:
-        # Resolved without conflicts
-        Logger.info("Best Fit Version: Resolved from normalized repo version without conflicts: {0}".format(match_versions[0]))
-        return match_versions[0]
-
-      # Resolve conflicts using REPO_VERSION_HISTORY_FILE
-      history_version = read_actual_version_from_history_file(normalized_repo_version)
-
-      # Validate history version retrieved is valid
-      if history_version in match_versions:
-        Logger.info("Best Fit Version: Resolved from normalized repo version using {0}: {1}".format(REPO_VERSION_HISTORY_FILE, history_version))
-        return history_version
-
-    # No matching version
-    return None
-
-
-  def install_packages(self, package_list):
-    """
-    Actually install the packages using the package manager.
-    :param package_list: List of package names to install
-    :return: Returns 0 if no errors were found, and 1 otherwise.
-    """
-    ret_code = 0
-    
-    config = self.get_config()
-    agent_stack_retry_on_unavailability = cbool(config['ambariLevelParams']['agent_stack_retry_on_unavailability'])
-    agent_stack_retry_count = cint(config['ambariLevelParams']['agent_stack_retry_count'])
-
-    # Install packages
-    packages_were_checked = False
-    packages_installed_before = []
-    stack_selector_package = stack_tools.get_stack_tool_package(stack_tools.STACK_SELECTOR_NAME)
-
-    try:
-      # install the stack-selector; we need to supply the action as "upgrade" here since the normal
-      # install command will skip if the package is already installed in the system.
-      # This is required for non-versioned components, like stack-select, since each version of
-      # the stack comes with one. Also, scope the install by repository since we need to pick a
-      # specific repo that the stack-select tools are coming out of in case there are multiple
-      # patches installed
-      repositories = config['repositoryFile']['repositories']
-      command_repos = CommandRepository(config['repositoryFile'])
-      repository_ids = [repository['repoId'] for repository in repositories]
-      repos_to_use = {}
-      for repo_id in repository_ids:
-        if repo_id in self.repo_files:
-          repos_to_use[repo_id] = self.repo_files[repo_id]
-
-      self.repo_mgr.upgrade_package(stack_selector_package, RepoCallContext(
-        use_repos=repos_to_use,
-        retry_on_repo_unavailability=agent_stack_retry_on_unavailability,
-        retry_count=agent_stack_retry_count))
-
-      packages_installed_before = self.repo_mgr.installed_packages()
-      packages_installed_before = [package[0] for package in packages_installed_before]
-      packages_were_checked = True
-      filtered_package_list = self.filter_package_list(package_list)
-      try:
-        available_packages_in_repos = self.repo_mgr.get_available_packages_in_repos(command_repos)
-      except Exception:
-        available_packages_in_repos = []
-      for package in filtered_package_list:
-        name = self.get_package_from_available(package['name'], available_packages_in_repos)
-
-        # This enables upgrading non-versioned packages, despite the fact they exist.
-        # Needed by 'mahout' which is non-version but have to be updated
-        self.repo_mgr.upgrade_package(name, RepoCallContext(
-          retry_on_repo_unavailability=agent_stack_retry_on_unavailability,
-          retry_count=agent_stack_retry_count
-        ))
-    except Exception as err:
-      ret_code = 1
-      Logger.logger.exception("Package Manager failed to install packages. Error: {0}".format(str(err)))
-
-      # Remove already installed packages in case of fail
-      if packages_were_checked and packages_installed_before:
-        packages_installed_after = self.repo_mgr.installed_packages()
-        packages_installed_after = [package[0] for package in packages_installed_after]
-        packages_installed_before = set(packages_installed_before)
-        new_packages_installed = [package for package in packages_installed_after if package not in packages_installed_before]
-
-        if OSCheck.is_ubuntu_family():
-          package_version_string = self.repository_version.replace('.', '-')
-        else:
-          package_version_string = self.repository_version.replace('-', '_')
-          package_version_string = package_version_string.replace('.', '_')
-
-        for package in new_packages_installed:
-          if package_version_string and (package_version_string in package):
-            self.repo_mgr.remove_package(package, RepoCallContext())
-
-    if not self.repo_mgr.verify_dependencies():
-      ret_code = 1
-      Logger.logger.error("Failure while verifying dependencies")
-      Logger.logger.error("*******************************************************************************")
-      Logger.logger.error("Manually verify and fix package dependencies and then re-run install_packages")
-      Logger.logger.error("*******************************************************************************")
-
-    # Compute the actual version in order to save it in structured out
-    try:
-      if ret_code == 0:
-         self.compute_actual_version()
-      else:
-        self.check_partial_install()
-    except Fail as err:
-      ret_code = 1
-      Logger.logger.exception("Failure while computing actual version. Error: {0}".format(str(err)))
-    return ret_code
-
-  def abort_handler(self, signum, frame):
-    Logger.error("Caught signal {0}, will handle it gracefully. Compute the actual version if possible before exiting.".format(signum))
-    self.check_partial_install()
-    
-  def filter_package_list(self, package_list):
-    """
-    Note: that we have skipUpgrade option in metainfo.xml to filter packages,
-    as well as condition option to filter them conditionally,
-    so use this method only if, for some reason the metainfo option cannot be used.
-  
-    :param package_list: original list
-    :return: filtered package_list
-    """
-    filtered_package_list = []
-    for package in package_list:
-      if self.check_package_condition(package):
-        filtered_package_list.append(package)
-    return filtered_package_list
-
-
-if __name__ == "__main__":
-  InstallPackages().execute()
diff --git a/ambari-server/src/main/resources/custom_actions/scripts/mpack_packages.py b/ambari-server/src/main/resources/custom_actions/scripts/mpack_packages.py
new file mode 100644
index 0000000..79a24ea
--- /dev/null
+++ b/ambari-server/src/main/resources/custom_actions/scripts/mpack_packages.py
@@ -0,0 +1,215 @@
+#!/usr/bin/env python
+"""
+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.
+
+"""
+import signal
+
+import ambari_simplejson as json
+
+from ambari_commons.os_check import OSCheck
+from ambari_commons.shell import RepoCallContext
+from ambari_commons.str_utils import cbool, cint
+from ambari_commons.repo_manager import ManagerFactory
+from resource_management.core.exceptions import Fail
+from resource_management.core.logger import Logger
+from resource_management.libraries.functions.repository_util import CommandRepository
+from resource_management.libraries.script.script import Script
+
+
+class MpackPackages(Script):
+  """
+  This script is a part of Upgrade workflow
+  """
+
+  def __init__(self):
+    super(MpackPackages, self).__init__()
+
+    self.repo_mgr = ManagerFactory.get()
+    self.repo_files = {}
+
+  def actionexecute(self, env):
+    num_errors = 0
+
+    # Parse parameters
+    config = Script.get_config()
+
+    try:
+      command_repository = CommandRepository(config['repositoryFile'])
+    except KeyError:
+      raise Fail("The command repository indicated by 'repositoryFile' was not found")
+
+    # Handle a SIGTERM and SIGINT gracefully
+    signal.signal(signal.SIGTERM, self.abort_handler)
+    signal.signal(signal.SIGINT, self.abort_handler)
+
+    self.repository_version = command_repository.version_string
+
+    # Select dict that contains parameters
+    try:
+      package_list = json.loads(config['roleParams']['package_list'])
+    except KeyError:
+      pass
+
+
+    if self.repository_version is None:
+      raise Fail("Cannot determine the repository version to install")
+
+    try:
+      if not command_repository.items:
+        Logger.warning(
+          "Repository list is empty. Ambari may not be managing the repositories for {0}.".format(
+            self.repository_version))
+      else:
+        Logger.info(
+          "Will install packages for repository version {0}".format(self.repository_version))
+    except Exception, err:
+      import traceback
+      traceback.print_exc()
+      Logger.logger.exception("Cannot install repository files. Error: {0}".format(str(err)))
+      num_errors += 1
+
+    # Build structured output with initial values
+    self.structured_output = {
+      'package_installation_result': 'FAIL',
+      'mpack_id': command_repository.mpack_id
+    }
+
+    self.put_structured_out(self.structured_output)
+
+    try:
+      # check package manager non-completed transactions
+      if self.repo_mgr.check_uncompleted_transactions():
+        self.repo_mgr.print_uncompleted_transaction_hint()
+        num_errors += 1
+    except Exception as e:  # we need to ignore any exception
+      Logger.warning("Failed to check for uncompleted package manager transactions: " + str(e))
+
+    if num_errors > 0:
+      raise Fail("Failed to distribute repositories/install packages")
+
+    # Initial list of versions, used to compute the new version installed
+
+    try:
+      ret_code = self.install_packages(package_list)
+      if ret_code == 0:
+        self.structured_output['package_installation_result'] = 'SUCCESS'
+        self.put_structured_out(self.structured_output)
+      else:
+        num_errors += 1
+    except Exception as err:
+      num_errors += 1
+      Logger.logger.exception("Could not install packages. Error: {0}".format(str(err)))
+
+    # Provide correct exit code
+    if num_errors > 0:
+      raise Fail("Failed to distribute repositories/install packages")
+
+  def install_packages(self, package_list):
+    """
+    Actually install the packages using the package manager.
+    :param package_list: List of package names to install
+    :return: Returns 0 if no errors were found, and 1 otherwise.
+    """
+    ret_code = 0
+    
+    config = self.get_config()
+    agent_stack_retry_on_unavailability = cbool(config['ambariLevelParams']['agent_stack_retry_on_unavailability'])
+    agent_stack_retry_count = cint(config['ambariLevelParams']['agent_stack_retry_count'])
+
+    # Install packages
+    packages_were_checked = False
+    packages_installed_before = []
+#    stack_selector_package = stack_tools.get_stack_tool_package(stack_tools.STACK_SELECTOR_NAME)
+
+    try:
+      repositories = config['repositoryFile']['repositories']
+      command_repos = CommandRepository(config['repositoryFile'])
+      repository_ids = [repository['repoId'] for repository in repositories]
+      repos_to_use = {}
+      for repo_id in repository_ids:
+        if repo_id in self.repo_files:
+          repos_to_use[repo_id] = self.repo_files[repo_id]
+
+      packages_installed_before = self.repo_mgr.installed_packages()
+      packages_installed_before = [package[0] for package in packages_installed_before]
+      packages_were_checked = True
+      filtered_package_list = self.filter_package_list(package_list)
+      try:
+        available_packages_in_repos = self.repo_mgr.get_available_packages_in_repos(command_repos)
+      except Exception:
+        available_packages_in_repos = []
+      for package in filtered_package_list:
+        name = self.get_package_from_available(package['name'], available_packages_in_repos)
+
+        # This enables upgrading non-versioned packages, despite the fact they exist.
+        # Needed by 'mahout' which is non-version but have to be updated
+        self.repo_mgr.upgrade_package(name, RepoCallContext(
+          retry_on_repo_unavailability=agent_stack_retry_on_unavailability,
+          retry_count=agent_stack_retry_count
+        ))
+    except Exception as err:
+      ret_code = 1
+      Logger.logger.exception("Package Manager failed to install packages. Error: {0}".format(str(err)))
+
+      # Remove already installed packages in case of fail
+      if packages_were_checked and packages_installed_before:
+        packages_installed_after = self.repo_mgr.installed_packages()
+        packages_installed_after = [package[0] for package in packages_installed_after]
+        packages_installed_before = set(packages_installed_before)
+        new_packages_installed = [package for package in packages_installed_after if package not in packages_installed_before]
+
+        if OSCheck.is_ubuntu_family():
+          package_version_string = self.repository_version.replace('.', '-')
+        else:
+          package_version_string = self.repository_version.replace('-', '_')
+          package_version_string = package_version_string.replace('.', '_')
+
+        for package in new_packages_installed:
+          if package_version_string and (package_version_string in package):
+            self.repo_mgr.remove_package(package, RepoCallContext())
+
+    if not self.repo_mgr.verify_dependencies():
+      ret_code = 1
+      Logger.logger.error("Failure while verifying dependencies")
+      Logger.logger.error("*******************************************************************************")
+      Logger.logger.error("Manually verify and fix package dependencies and then re-run install_packages")
+      Logger.logger.error("*******************************************************************************")
+
+    return ret_code
+
+  def abort_handler(self, signum, frame):
+    pass
+
+  def filter_package_list(self, package_list):
+    """
+    Note: that we have skipUpgrade option in metainfo.xml to filter packages,
+    as well as condition option to filter them conditionally,
+    so use this method only if, for some reason the metainfo option cannot be used.
+  
+    :param package_list: original list
+    :return: filtered package_list
+    """
+    filtered_package_list = []
+    for package in package_list:
+      if self.check_package_condition(package):
+        filtered_package_list.append(package)
+    return filtered_package_list
+
+
+if __name__ == "__main__":
+  MpackPackages().execute()
diff --git a/ambari-server/src/test/python/custom_actions/TestInstallPackages.py b/ambari-server/src/test/python/custom_actions/TestInstallPackages.py
deleted file mode 100644
index 9c8306d..0000000
--- a/ambari-server/src/test/python/custom_actions/TestInstallPackages.py
+++ /dev/null
@@ -1,1278 +0,0 @@
-#!/usr/bin/env python
-
-'''
-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.
-'''
-import json
-import os
-from ambari_commons import subprocess32
-import select
-
-from stacks.utils.RMFTestCase import *
-from mock.mock import patch, MagicMock
-from resource_management.core.base import Resource
-from resource_management.core.exceptions import Fail
-from resource_management.libraries.script import Script
-
-OLD_VERSION_STUB = '2.1.0.0-400'
-VERSION_STUB_WITHOUT_BUILD_NUMBER = '2.2.0.1'
-VERSION_STUB = '2.2.0.1-885'
-
-subproc_mock = MagicMock()
-subproc_mock.return_value = MagicMock()
-subproc_stdout = MagicMock()
-subproc_mock.return_value.stdout = subproc_stdout
-
-
-@patch.object(os, "read", new=MagicMock(return_value=None))
-@patch.object(select, "select", new=MagicMock(return_value=([subproc_stdout], None, None)))
-@patch("pty.openpty", new = MagicMock(return_value=(1,5)))
-@patch.object(os, "close", new=MagicMock())
-@patch.object(subprocess32, "Popen", new=subproc_mock)
-class TestInstallPackages(RMFTestCase):
-
-  def setUp(self):
-    self.maxDiff = None
-
-  @staticmethod
-  def _add_packages(*args):
-    return [
-      ["pkg1", "1.0", "repo"],
-      ["pkg2", "2.0", "repo2"]
-    ]
-
-  @staticmethod
-  def _add_packages_available(*args):
-    return [
-      ["hadoop_2_2_0_1_885", "1.0", "HDP-2.2"],
-      ["hadooplzo_2_2_0_1_885", "1.0", "HDP-2.2"],
-      ["hadoop_2_2_0_1_885-libhdfs", "1.0", "HDP-2.2"]
-    ]
-
-  @staticmethod
-  def _add_packages_lookUpYum(*args):
-    return TestInstallPackages._add_packages_available(*args)
-
-  def test_get_installed_package_version(self):
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-    from ambari_commons.shell import SubprocessCallResult
-
-    r = SubprocessCallResult("3.1.0.0-54.el7.centos", "", 0)
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-    with patch("ambari_commons.shell.subprocess_executor") as checked_call_mock:
-      checked_call_mock.return_value = r
-      expected_version = pkg_manager.get_installed_package_version("test")
-      self.assertEquals("3.1.0.0-54", expected_version)
-
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_normal_flow_rhel(self,
-                            subprocess_with_timeout,
-                            write_actual_version_to_history_file_mock,
-                            read_actual_version_from_history_file_mock,
-                            stack_versions_mock,
-                            put_structured_out_mock,
-                            get_provider, list_ambari_managed_repos_mock):
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      [VERSION_STUB]
-    ]
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_lookUpYum
-      available_packages.side_effect = TestInstallPackages._add_packages_lookUpYum
-      installed_packages.side_effect = TestInstallPackages._add_packages_lookUpYum
-
-      get_provider.return_value = pkg_manager
-
-      list_ambari_managed_repos_mock.return_value = []
-      repo_file_name = 'ambari-hdp-1'
-      use_repos = { 'HDP-UTILS-1.1.0.20': repo_file_name, 'HDP-2.2': repo_file_name }
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_file="install_packages_config.json",
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-      )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-      self.assertResourceCalled('Repository', 'HDP-UTILS-1.1.0.20',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP-UTILS', 'main'],
-                                repo_template='[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=False,
-      )
-      self.assertResourceCalled('Repository', 'HDP-2.2',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP', 'main'],
-                                repo_template='[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=True,
-      )
-      self.assertNoMoreResources()
-
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_no_repos(self,
-                            subprocess_with_timeout,
-                            write_actual_version_to_history_file_mock,
-                            read_actual_version_from_history_file_mock,
-                            stack_versions_mock,
-                            put_structured_out_mock, get_provider):
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      [VERSION_STUB]
-    ]
-
-    config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-    with open(config_file, "r") as f:
-      command_json = json.load(f)
-
-    command_json['repositoryFile']['repositories'] = []
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict = command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-      )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-
-      self.assertNoMoreResources()
-
-  @patch("ambari_commons.os_check.OSCheck.is_suse_family")
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_normal_flow_sles(self, subprocess_with_timeout, write_actual_version_to_history_file_mock,
-                            read_actual_version_from_history_file_mock,
-                            stack_versions_mock, put_structured_out_mock,
-                            get_provider, list_ambari_managed_repos_mock, is_suse_family_mock):
-    is_suse_family_mock = True
-    Script.stack_version_from_distro_select = VERSION_STUB
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      [VERSION_STUB]
-    ]
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-
-      list_ambari_managed_repos_mock.return_value=[]
-      repo_file_name = 'ambari-hdp-1'
-      use_repos = { 'HDP-UTILS-1.1.0.20': repo_file_name, 'HDP-2.2': repo_file_name }
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_file="install_packages_config.json",
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Suse', '11', 'SP1'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-      self.assertResourceCalled('Repository', 'HDP-UTILS-1.1.0.20',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP-UTILS', 'main'],
-                                repo_template='[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=False,
-                                )
-      self.assertResourceCalled('Repository', 'HDP-2.2',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP', 'main'],
-                                repo_template=u'[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=True,
-                                )
-
-      self.assertNoMoreResources()
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.os_check.OSCheck.is_redhat_family")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_exclude_existing_repo(self, subprocess_with_timeout, write_actual_version_to_history_file_mock,
-                                 read_actual_version_from_history_file_mock,
-                                 stack_versions_mock,
-                                 get_provider, put_structured_out_mock,
-                                 is_redhat_family_mock, list_ambari_managed_repos_mock):
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      [VERSION_STUB]
-    ]
-    Script.stack_version_from_distro_select = VERSION_STUB
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_lookUpYum
-      available_packages.side_effect = TestInstallPackages._add_packages_lookUpYum
-      installed_packages.side_effect = TestInstallPackages._add_packages_lookUpYum
-
-      get_provider.return_value = pkg_manager
-      list_ambari_managed_repos_mock.return_value=["HDP-UTILS-2.2.0.1-885"]
-      is_redhat_family_mock.return_value = True
-      repo_file_name = 'ambari-hdp-1'
-      use_repos = { 'HDP-UTILS-1.1.0.20': repo_file_name, 'HDP-2.2': repo_file_name }
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_file="install_packages_config.json",
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-      )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-      self.assertResourceCalled('Repository', 'HDP-UTILS-1.1.0.20',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP-UTILS', 'main'],
-                                repo_template=u'[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=False,
-      )
-      self.assertResourceCalled('Repository', 'HDP-2.2',
-                                base_url='http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP', 'main'],
-                                repo_template=u'[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=True,
-      )
-      self.assertNoMoreResources()
-
-
-  _install_failed = False
-
-  @staticmethod
-  def _add_packages_with_fail():
-    arg = []
-    arg.append(["pkg1_2_2_0_1_885_pack", "1.0", "repo"])
-    arg.append(["pkg2_2_2_0_1_885_pack2", "2.0", "repo2"])
-    if TestInstallPackages._install_failed:
-      arg.append(["should_not_be_removed_pkg1", "1.0", "repo"])
-      arg.append(["hadoop_2_2_0_1_885fake_pkg", "1.0", "repo"])
-      arg.append(["snappy__2_2_0_1_885_fake_pkg", "3.0", "repo2"])
-      arg.append(["ubuntu-like-2-2-0-1-885-fake-pkg", "3.0", "repo2"])
-      arg.append(["should_not_be_removed_pkg2", "3.0", "repo2"])
-
-    return arg
-
-  @staticmethod
-  def _new_with_exception(cls, name, env=None, provider=None, **kwargs):
-    if (name != "snappy-devel"):
-      return Resource.__new__(cls, name, env, provider, **kwargs)
-    else:
-      TestInstallPackages._install_failed = True
-      raise Exception()
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.os_check.OSCheck.is_redhat_family")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.core.resources.packaging.Package.__new__")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_fail(self, subprocess_with_timeout, put_structured_out_mock, Package__mock, get_provider,
-                is_redhat_family_mock, list_ambari_managed_repos_mock):
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_with_fail
-      available_packages.side_effect = TestInstallPackages._add_packages_with_fail
-      installed_packages.side_effect = TestInstallPackages._add_packages_with_fail
-
-      get_provider.return_value = pkg_manager
-
-      is_redhat_family_mock.return_value = True
-      list_ambari_managed_repos_mock.return_value = []
-
-      def side_effect(retcode):
-        TestInstallPackages._install_failed = True
-        raise Exception()
-
-      Package__mock.side_effect = side_effect
-      self.assertRaises(Fail, self.executeScript, "scripts/install_packages.py",
-                        classname="InstallPackages",
-                        command="actionexecute",
-                        config_file="install_packages_config.json",
-                        target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                        os_type=('Redhat', '6.4', 'Final'))
-
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'repository_version_id': 1,
-                        'package_installation_result': 'FAIL',
-                         'actual_version': '2.2.0.1-885'})
-      self.assertResourceCalled('Repository', 'HDP-UTILS-1.1.0.20',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP-UTILS', 'main'],
-                                repo_template=u'[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=u'ambari-hdp-1',
-                                mirror_list=None,
-                                append_to_file=False,
-                                )
-      self.assertResourceCalled('Repository', 'HDP-2.2',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP', 'main'],
-                                repo_template=u'[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=u'ambari-hdp-1',
-                                mirror_list=None,
-                                append_to_file=True,
-                                )
-      self.assertNoMoreResources()
-
-      TestInstallPackages._install_failed = False
-
-
-  @patch("ambari_commons.os_check.OSCheck.is_suse_family")
-  @patch("resource_management.core.resources.packaging.Package")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_format_package_name(self, subprocess_with_timeout, write_actual_version_to_history_file_mock,
-                               read_actual_version_from_history_file_mock,
-                               stack_versions_mock,
-                               get_provider, put_structured_out_mock,
-                               package_mock, is_suse_family_mock):
-    Script.stack_version_from_distro_select = VERSION_STUB
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      [VERSION_STUB]
-    ]
-    read_actual_version_from_history_file_mock.return_value = VERSION_STUB
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-      is_suse_family_mock.return_value = True
-      repo_file_name = 'ambari-hdp-1'
-      use_repos = { 'HDP-UTILS-1.1.0.20': repo_file_name, 'HDP-2.2': repo_file_name }
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_file="install_packages_config.json",
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Suse', '11', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-      self.assertResourceCalled('Repository', 'HDP-UTILS-1.1.0.20',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP-UTILS', 'main'],
-                                repo_template=u'[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=False,
-                                )
-      self.assertResourceCalled('Repository', 'HDP-2.2',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP', 'main'],
-                                repo_template=u'[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=True,
-                                )
-
-      self.assertNoMoreResources()
-
-
-
-  @patch("ambari_commons.os_check.OSCheck.is_suse_family")
-  @patch("resource_management.core.resources.packaging.Package")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_format_package_name_via_repositoryFile(self, subprocess_with_timeout, write_actual_version_to_history_file_mock,
-                                                  read_actual_version_from_history_file_mock,
-                                                  stack_versions_mock,
-                                                  get_provider, put_structured_out_mock,
-                                                  package_mock, is_suse_family_mock):
-    Script.stack_version_from_distro_select = VERSION_STUB
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      [VERSION_STUB]
-    ]
-    read_actual_version_from_history_file_mock.return_value = VERSION_STUB
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-      is_suse_family_mock.return_value = True
-
-
-      config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_repository_file.json"
-      with open(config_file, "r") as f:
-        command_json = json.load(f)
-
-      command_json['repositoryFile']['repoVersion'] = '2.2.0.1-990'
-
-      repo_file_name = 'ambari-hdp-4'
-      use_repos = { 'HDP-UTILS-1.1.0.20-repo-4': repo_file_name, 'HDP-2.2-repo-4': repo_file_name }
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Suse', '11', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 4,
-                         'actual_version': VERSION_STUB})
-      self.assertResourceCalled('Repository', 'HDP-UTILS-1.1.0.20-repo-4',
-                                base_url=u'http://repo1/HDP-UTILS/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP-UTILS', 'main'],
-                                repo_template=u'[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=False,
-                                )
-      self.assertResourceCalled('Repository', 'HDP-2.2-repo-4',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP', 'main'],
-                                repo_template=u'[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=True,
-                                )
-      self.assertNoMoreResources()
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_version_reporting__build_number_defined(self, subprocess_with_timeout,
-                                                         write_actual_version_to_history_file_mock,
-                                                         read_actual_version_from_history_file_mock,
-                                                         stack_versions_mock,
-                                                         put_structured_out_mock, get_provider, list_ambari_managed_repos_mock):
-    stack_versions_mock.side_effect = [
-      [OLD_VERSION_STUB],  # before installation attempt
-      [OLD_VERSION_STUB, VERSION_STUB]
-    ]
-
-    config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-    with open(config_file, "r") as f:
-      command_json = json.load(f)
-
-    command_json['repositoryFile']['repoVersion'] = VERSION_STUB
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-      list_ambari_managed_repos_mock.return_value = []
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-      self.assertTrue(write_actual_version_to_history_file_mock.called)
-      self.assertEquals(write_actual_version_to_history_file_mock.call_args[0], (VERSION_STUB_WITHOUT_BUILD_NUMBER, VERSION_STUB))
-
-      stack_versions_mock.reset_mock()
-      write_actual_version_to_history_file_mock.reset_mock()
-      put_structured_out_mock.reset_mock()
-
-      # Test retrying install again
-      stack_versions_mock.side_effect = [
-        [OLD_VERSION_STUB, VERSION_STUB],
-        [OLD_VERSION_STUB, VERSION_STUB]
-      ]
-      read_actual_version_from_history_file_mock.return_value = VERSION_STUB
-
-      config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-      with open(config_file, "r") as f:
-        command_json = json.load(f)
-
-      command_json['repositoryFile']['repoVersion'] = VERSION_STUB
-
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-      list_ambari_managed_repos_mock.return_value = []
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-
-      self.assertFalse(write_actual_version_to_history_file_mock.called)
-
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("os.path.exists")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_version_reporting__build_number_not_defined_stack_root_present__no_components_installed(self,
-                                                                            subprocess_with_timeout,
-                                                                            exists_mock,
-                                                                            write_actual_version_to_history_file_mock,
-                                                                            read_actual_version_from_history_file_mock,
-                                                                            stack_versions_mock,
-                                                                            put_structured_out_mock, get_provider, list_ambari_managed_repos_mock):
-    exists_mock.return_value = True
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      []
-    ]
-    read_actual_version_from_history_file_mock.return_value = None
-
-    config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-    with open(config_file, "r") as f:
-      command_json = json.load(f)
-
-    command_json['roleParams']['repository_version'] = VERSION_STUB_WITHOUT_BUILD_NUMBER
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-      list_ambari_managed_repos_mock.return_value = []
-
-      try:
-        self.executeScript("scripts/install_packages.py",
-                           classname="InstallPackages",
-                           command="actionexecute",
-                           config_dict=command_json,
-                           target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                           os_type=('Redhat', '6.4', 'Final'),
-                           )
-        self.fail("Should throw exception")
-      except Fail:
-        pass  # Expected
-
-
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args_list[-1][0][0],
-                        { 'actual_version': '2.2.0.1-885',
-                          'package_installation_result': 'FAIL',
-                          'repository_version_id': 1})
-
-      self.assertFalse(write_actual_version_to_history_file_mock.called)
-
-      stack_versions_mock.reset_mock()
-      write_actual_version_to_history_file_mock.reset_mock()
-      put_structured_out_mock.reset_mock()
-
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("os.path.exists")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_version_reporting__build_number_not_defined_stack_root_absent(self,
-                                                                        subprocess_with_timeout,
-                                                                        exists_mock,
-                                                                        write_actual_version_to_history_file_mock,
-                                                                        read_actual_version_from_history_file_mock,
-                                                                        stack_versions_mock,
-                                                                        put_structured_out_mock, get_provider, list_ambari_managed_repos_mock):
-    exists_mock.return_value = False
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      []
-    ]
-    read_actual_version_from_history_file_mock.return_value = None
-
-    config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-    with open(config_file, "r") as f:
-      command_json = json.load(f)
-
-    command_json['repositoryFile']['repoVersion'] = VERSION_STUB_WITHOUT_BUILD_NUMBER
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages
-      available_packages.side_effect = TestInstallPackages._add_packages
-      installed_packages.side_effect = TestInstallPackages._add_packages
-
-      get_provider.return_value = pkg_manager
-
-      list_ambari_managed_repos_mock.return_value = []
-      try:
-        self.executeScript("scripts/install_packages.py",
-                           classname="InstallPackages",
-                           command="actionexecute",
-                           config_dict=command_json,
-                           target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                           os_type=('Redhat', '6.4', 'Final'),
-                           )
-        self.fail("Should throw exception")
-      except Fail:
-        pass  # Expected
-
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args_list[-1][0][0],
-                        {'package_installation_result': 'FAIL',
-                         'repository_version_id': 1})
-
-      self.assertFalse(write_actual_version_to_history_file_mock.called)
-
-      stack_versions_mock.reset_mock()
-      write_actual_version_to_history_file_mock.reset_mock()
-      put_structured_out_mock.reset_mock()
-
-      # Test retrying install again  (correct build number, provided by other nodes, is now received from server)
-
-      stack_versions_mock.side_effect = [
-        [],  # before installation attempt
-        []
-      ]
-      read_actual_version_from_history_file_mock.return_value = None
-
-      config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-      with open(config_file, "r") as f:
-        command_json = json.load(f)
-
-      command_json['repositoryFile']['repoVersion'] = VERSION_STUB
-
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-      list_ambari_managed_repos_mock.return_value = []
-      try:
-        self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-        self.fail("Should throw exception")
-      except Fail:
-        pass  # Expected
-
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'FAIL',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-
-      self.assertFalse(write_actual_version_to_history_file_mock.called)
-
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_version_reporting__build_number_not_defined_stack_root_present(self,
-                                                                    subprocess_with_timeout,
-                                                                    write_actual_version_to_history_file_mock,
-                                                                    read_actual_version_from_history_file_mock,
-                                                                    stack_versions_mock,
-                                                                    put_structured_out_mock, get_provider, list_ambari_managed_repos_mock):
-    stack_versions_mock.side_effect = [
-      [OLD_VERSION_STUB],  # before installation attempt
-      [OLD_VERSION_STUB, VERSION_STUB]
-    ]
-
-    config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-    with open(config_file, "r") as f:
-      command_json = json.load(f)
-
-    command_json['roleParams']['repository_version'] = VERSION_STUB_WITHOUT_BUILD_NUMBER
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-      list_ambari_managed_repos_mock.return_value = []
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-      self.assertTrue(write_actual_version_to_history_file_mock.called)
-      self.assertEquals(write_actual_version_to_history_file_mock.call_args[0], (VERSION_STUB_WITHOUT_BUILD_NUMBER, VERSION_STUB))
-
-      stack_versions_mock.reset_mock()
-      write_actual_version_to_history_file_mock.reset_mock()
-      put_structured_out_mock.reset_mock()
-
-      # Test retrying install again
-      stack_versions_mock.side_effect = [
-        [OLD_VERSION_STUB, VERSION_STUB],
-        [OLD_VERSION_STUB, VERSION_STUB]
-      ]
-      read_actual_version_from_history_file_mock.return_value = VERSION_STUB
-
-      config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-      with open(config_file, "r") as f:
-        command_json = json.load(f)
-
-      command_json['repositoryFile']['repoVersion'] = VERSION_STUB_WITHOUT_BUILD_NUMBER
-
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-      list_ambari_managed_repos_mock.return_value = []
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-
-      self.assertFalse(write_actual_version_to_history_file_mock.called)
-
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_version_reporting__wrong_build_number_specified_stack_root_present(self,
-                                                                        subprocess_with_timeout,
-                                                                        write_actual_version_to_history_file_mock,
-                                                                        read_actual_version_from_history_file_mock,
-                                                                        stack_versions_mock,
-                                                                        put_structured_out_mock, get_provider, list_ambari_managed_repos_mock):
-    stack_versions_mock.side_effect = [
-      [OLD_VERSION_STUB],  # before installation attempt
-      [OLD_VERSION_STUB, VERSION_STUB]
-    ]
-
-    config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-    with open(config_file, "r") as f:
-      command_json = json.load(f)
-
-    command_json['repositoryFile']['repoVersion'] = '2.2.0.1-500'  # User specified wrong build number
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-      list_ambari_managed_repos_mock.return_value = []
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-      self.assertTrue(write_actual_version_to_history_file_mock.called)
-      self.assertEquals(write_actual_version_to_history_file_mock.call_args[0], ('2.2.0.1', VERSION_STUB))
-
-      stack_versions_mock.reset_mock()
-      write_actual_version_to_history_file_mock.reset_mock()
-      put_structured_out_mock.reset_mock()
-
-      # Test retrying install again
-      stack_versions_mock.side_effect = [
-        [OLD_VERSION_STUB, VERSION_STUB],
-        [OLD_VERSION_STUB, VERSION_STUB]
-      ]
-      read_actual_version_from_history_file_mock.return_value = VERSION_STUB
-
-      config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-      with open(config_file, "r") as f:
-        command_json = json.load(f)
-
-      command_json['roleParams']['repository_version'] = '2.2.0.1-500'  # User specified wrong build number
-
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-      list_ambari_managed_repos_mock.return_value = []
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-
-      self.assertFalse(write_actual_version_to_history_file_mock.called)
-
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("os.path.exists")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_version_reporting__wrong_build_number_specified_stack_root_absent(self,
-                                                                            subprocess_with_timeout,
-                                                                            exists_mock,
-                                                                            write_actual_version_to_history_file_mock,
-                                                                            read_actual_version_from_history_file_mock,
-                                                                            stack_versions_mock,
-                                                                            put_structured_out_mock, get_provider, list_ambari_managed_repos_mock):
-    exists_mock.return_value = False
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      []
-    ]
-    read_actual_version_from_history_file_mock.return_value = None
-
-    config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-    with open(config_file, "r") as f:
-      command_json = json.load(f)
-
-    command_json['repositoryFile']['repoVersion'] = VERSION_STUB_WITHOUT_BUILD_NUMBER
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-      list_ambari_managed_repos_mock.return_value = []
-      try:
-        self.executeScript("scripts/install_packages.py",
-                           classname="InstallPackages",
-                           command="actionexecute",
-                           config_dict=command_json,
-                           target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                           os_type=('Redhat', '6.4', 'Final'),
-                           )
-        self.fail("Should throw exception")
-      except Fail:
-        pass  # Expected
-
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args_list[-1][0][0],
-                        {'package_installation_result': 'FAIL',
-                         'repository_version_id': 1})
-
-      self.assertFalse(write_actual_version_to_history_file_mock.called)
-
-      stack_versions_mock.reset_mock()
-      write_actual_version_to_history_file_mock.reset_mock()
-      put_structured_out_mock.reset_mock()
-
-      # Test retrying install again (correct build number, provided by other nodes, is now received from server)
-
-      stack_versions_mock.side_effect = [
-        [],  # before installation attempt
-        []
-      ]
-      read_actual_version_from_history_file_mock.return_value = None
-
-      config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-      with open(config_file, "r") as f:
-        command_json = json.load(f)
-
-      command_json['roleParams']['repository_version'] = VERSION_STUB
-
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-      list_ambari_managed_repos_mock.return_value = []
-      try:
-        self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-        self.fail("Should throw exception")
-      except Fail:
-        pass  # Expected
-
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'FAIL',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-
-      self.assertFalse(write_actual_version_to_history_file_mock.called)
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_version_reporting_with_repository_version(self,
-                                                     subprocess_with_timeout,
-                                                     write_actual_version_to_history_file_mock,
-                                                     read_actual_version_from_history_file_mock,
-                                                     stack_versions_mock,
-                                                     put_structured_out_mock, get_provider, list_ambari_managed_repos_mock):
-    stack_versions_mock.side_effect = [
-      [OLD_VERSION_STUB],  # before installation attempt
-      [OLD_VERSION_STUB, VERSION_STUB]
-    ]
-
-    config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-    with open(config_file, "r") as f:
-      command_json = json.load(f)
-
-    command_json['roleParams']['repository_version'] = VERSION_STUB
-    command_json['roleParams']['repository_version_id'] = '2'
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-      list_ambari_managed_repos_mock.return_value = []
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-      self.assertTrue(write_actual_version_to_history_file_mock.called)
-      self.assertEquals(write_actual_version_to_history_file_mock.call_args[0], (VERSION_STUB_WITHOUT_BUILD_NUMBER, VERSION_STUB))
-
-      stack_versions_mock.reset_mock()
-      write_actual_version_to_history_file_mock.reset_mock()
-      put_structured_out_mock.reset_mock()
-
-      # Test retrying install again
-      stack_versions_mock.side_effect = [
-        [OLD_VERSION_STUB, VERSION_STUB],
-        [OLD_VERSION_STUB, VERSION_STUB]
-      ]
-      read_actual_version_from_history_file_mock.return_value = VERSION_STUB
-
-      config_file = self.get_src_folder() + "/test/python/custom_actions/configs/install_packages_config.json"
-      with open(config_file, "r") as f:
-        command_json = json.load(f)
-
-      command_json['roleParams']['repository_version'] = VERSION_STUB
-      command_json['roleParams']['repository_version_id'] = '2'
-
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-      list_ambari_managed_repos_mock.return_value = []
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_dict=command_json,
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-                         )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 1,
-                         'actual_version': VERSION_STUB})
-
-      self.assertFalse(write_actual_version_to_history_file_mock.called)
-
-  @patch("resource_management.libraries.functions.list_ambari_managed_repos.list_ambari_managed_repos")
-  @patch("ambari_commons.repo_manager.ManagerFactory.get")
-  @patch("resource_management.libraries.script.Script.put_structured_out")
-  @patch("resource_management.libraries.functions.stack_select.get_stack_versions")
-  @patch("resource_management.libraries.functions.repo_version_history.read_actual_version_from_history_file")
-  @patch("resource_management.libraries.functions.repo_version_history.write_actual_version_to_history_file")
-  @patch("ambari_commons.shell.launch_subprocess")
-  def test_normal_flow_rhel_with_command_repo(self,
-                                              subprocess_with_timeout,
-                                              write_actual_version_to_history_file_mock,
-                                              read_actual_version_from_history_file_mock,
-                                              stack_versions_mock,
-                                              put_structured_out_mock,
-                                              get_provider,
-                                              list_ambari_managed_repos_mock):
-    stack_versions_mock.side_effect = [
-      [],  # before installation attempt
-      [VERSION_STUB]
-    ]
-
-    from ambari_commons.os_check import OSConst
-    from ambari_commons.repo_manager import ManagerFactory
-
-    pkg_manager = ManagerFactory.get_new_instance(OSConst.REDHAT_FAMILY)
-
-    with patch.object(pkg_manager, "all_packages") as all_packages, \
-      patch.object(pkg_manager, "available_packages") as available_packages, \
-      patch.object(pkg_manager, "installed_packages") as installed_packages:
-      all_packages.side_effect = TestInstallPackages._add_packages_available
-      available_packages.side_effect = TestInstallPackages._add_packages_available
-      installed_packages.side_effect = TestInstallPackages._add_packages_available
-
-      get_provider.return_value = pkg_manager
-      list_ambari_managed_repos_mock.return_value=[]
-      repo_file_name = 'ambari-hdp-4'
-      use_repos = { 'HDP-UTILS-1.1.0.20-repo-4': repo_file_name, 'HDP-2.2-repo-4': repo_file_name }
-      self.executeScript("scripts/install_packages.py",
-                         classname="InstallPackages",
-                         command="actionexecute",
-                         config_file="install_packages_repository_file.json",
-                         target=RMFTestCase.TARGET_CUSTOM_ACTIONS,
-                         os_type=('Redhat', '6.4', 'Final'),
-      )
-      self.assertTrue(put_structured_out_mock.called)
-      self.assertEquals(put_structured_out_mock.call_args[0][0],
-                        {'package_installation_result': 'SUCCESS',
-                         'repository_version_id': 4,
-                         'actual_version': VERSION_STUB})
-
-      self.assertResourceCalled('Repository', 'HDP-UTILS-1.1.0.20-repo-4',
-                                base_url=u'http://repo1/HDP-UTILS/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP-UTILS', 'main'],
-                                repo_template='[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=False,
-      )
-      self.assertResourceCalled('Repository', 'HDP-2.2-repo-4',
-                                base_url=u'http://repo1/HDP/centos5/2.x/updates/2.2.0.0',
-                                action=['create'],
-                                components=[u'HDP', 'main'],
-                                repo_template='[{{repo_id}}]\nname={{repo_id}}\n{% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}\n\npath=/\nenabled=1\ngpgcheck=0',
-                                repo_file_name=repo_file_name,
-                                mirror_list=None,
-                                append_to_file=True,
-      )
-
-      self.assertNoMoreResources()

-- 
To stop receiving notification emails like this one, please contact
ncole@apache.org.