ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nc...@apache.org
Subject ambari git commit: AMBARI-13591. RU and EU: Allow set-current to force a version into the db (ncole)
Date Thu, 29 Oct 2015 20:35:35 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-2.1 49746d8c3 -> ade69a111


AMBARI-13591. RU and EU: Allow set-current to force a version into the db (ncole)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ade69a11
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ade69a11
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ade69a11

Branch: refs/heads/branch-2.1
Commit: ade69a111e9026774ce8cb97f4fe9c6113eed677
Parents: 49746d8
Author: Nate Cole <ncole@hortonworks.com>
Authored: Thu Oct 29 16:28:56 2015 -0400
Committer: Nate Cole <ncole@hortonworks.com>
Committed: Thu Oct 29 16:29:15 2015 -0400

----------------------------------------------------------------------
 .../ClusterStackVersionResourceProvider.java    | 158 +++++++++++-------
 .../server/orm/dao/ClusterVersionDAO.java       |  36 ++++-
 .../orm/dao/HostComponentDesiredStateDAO.java   |  19 ++-
 .../server/orm/dao/HostComponentStateDAO.java   |  28 ++++
 .../ambari/server/orm/dao/HostVersionDAO.java   |  32 ++++
 ambari-server/src/main/python/ambari-server.py  |   2 +-
 .../main/python/ambari_server/serverUpgrade.py  |   8 +-
 ...ClusterStackVersionResourceProviderTest.java | 160 +++++++++++++++++++
 .../src/test/python/TestServerUpgrade.py        |  55 ++++++-
 9 files changed, 427 insertions(+), 71 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ade69a11/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
index 9a93d24..02a5a1a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
@@ -17,10 +17,18 @@
  */
 package org.apache.ambari.server.controller.internal;
 
-import com.google.gson.Gson;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Provider;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.StaticallyInject;
@@ -51,11 +59,10 @@ import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
+import org.apache.ambari.server.orm.dao.HostComponentStateDAO;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
 import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
-import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
-import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.orm.entities.HostVersionEntity;
 import org.apache.ambari.server.orm.entities.OperatingSystemEntity;
 import org.apache.ambari.server.orm.entities.RepositoryEntity;
@@ -74,17 +81,11 @@ import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.lang.StringUtils;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.persist.Transactional;
 
 /**
  * Resource provider for cluster stack versions resources.
@@ -102,6 +103,7 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
   protected static final String CLUSTER_STACK_VERSION_HOST_STATES_PROPERTY_ID = PropertyHelper.getPropertyId("ClusterStackVersions",
"host_states");
   protected static final String CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID  = PropertyHelper.getPropertyId("ClusterStackVersions",
"repository_version");
   protected static final String CLUSTER_STACK_VERSION_STAGE_SUCCESS_FACTOR  = PropertyHelper.getPropertyId("ClusterStackVersions",
"success_factor");
+  protected static final String CLUSTER_STACK_VERSION_FORCE = "ClusterStackVersions/force";
 
   protected static final String INSTALL_PACKAGES_ACTION = "install_packages";
   protected static final String INSTALL_PACKAGES_FULL_NAME = "Install version";
@@ -141,6 +143,7 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
       add(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID);
       add(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID);
       add(CLUSTER_STACK_VERSION_STAGE_SUCCESS_FACTOR);
+      add(CLUSTER_STACK_VERSION_FORCE);
     }
   };
 
@@ -187,6 +190,9 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
   @Inject
   private static Injector injector;
 
+  @Inject
+  private static HostComponentStateDAO hostComponentStateDAO;
+
   /**
    * We have to include such a hack here, because if we
    * make finalizeUpgradeAction field static and request injection
@@ -575,57 +581,73 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
       Cluster cluster = getManagementController().getClusters().getCluster(clName);
       cluster.setDesiredStackVersion(stackId);
 
-      Map<String, String> args = new HashMap<String, String>();
-      if (newStateStr.equals(RepositoryVersionState.CURRENT.toString())) {
-        // Finalize upgrade workflow
-        args.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-      } else if (newStateStr.equals(RepositoryVersionState.INSTALLED.toString())) {
-        // Finalize downgrade workflow
-        args.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "downgrade");
-      } else {
-        throw new IllegalArgumentException(
-          String.format("Invalid desired state %s. Should be either CURRENT or INSTALLED",
-                  newStateStr));
+      String forceCurrent = (String) propertyMap.get(CLUSTER_STACK_VERSION_FORCE);
+      boolean force = false;
+      if (null != forceCurrent) {
+        force = Boolean.parseBoolean(forceCurrent);
       }
 
-      // Get a host name to populate the hostrolecommand table's hostEntity.
-      String defaultHostName = null;
-      // TODO: remove direct access to cluster entity completely
-      ClusterEntity clusterEntity = clusterDAO.findByName(clName);
-      List<HostEntity> hosts = new ArrayList(clusterEntity.getHostEntities());
-      if (hosts != null && !hosts.isEmpty()) {
-        Collections.sort(hosts);
-        defaultHostName = hosts.get(0).getHostName();
-      }
-      if (defaultHostName == null) {
-        throw new AmbariException("Could not find at least one host to set the command for");
-      }
 
-      args.put(FinalizeUpgradeAction.VERSION_KEY, desiredRepoVersion);
-      args.put(FinalizeUpgradeAction.CLUSTER_NAME_KEY, clName);
+      if (!force) {
 
-      ExecutionCommand command = new ExecutionCommand();
-      command.setCommandParams(args);
-      command.setClusterName(clName);
-      finalizeUpgradeAction.setExecutionCommand(command);
+        Map<String, String> args = new HashMap<String, String>();
+        if (newStateStr.equals(RepositoryVersionState.CURRENT.toString())) {
+          // Finalize upgrade workflow
+          args.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
+        } else if (newStateStr.equals(RepositoryVersionState.INSTALLED.toString())) {
+          // Finalize downgrade workflow
+          args.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "downgrade");
+        } else {
+          throw new IllegalArgumentException(
+            String.format("Invalid desired state %s. Should be either CURRENT or INSTALLED",
+                    newStateStr));
+        }
 
-      HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(defaultHostName,
-              Role.AMBARI_SERVER_ACTION, null, null);
-      finalizeUpgradeAction.setHostRoleCommand(hostRoleCommand);
+        // Get a host name to populate the hostrolecommand table's hostEntity.
+        String defaultHostName;
+        ArrayList<Host> hosts = new ArrayList<Host>(cluster.getHosts());
+        if (!hosts.isEmpty()) {
+          defaultHostName = hosts.get(0).getHostName();
+        } else {
+          throw new AmbariException("Could not find at least one host to set the command
for");
+        }
 
-      CommandReport report = finalizeUpgradeAction.execute(null);
+        args.put(FinalizeUpgradeAction.VERSION_KEY, desiredRepoVersion);
+        args.put(FinalizeUpgradeAction.CLUSTER_NAME_KEY, clName);
 
-      LOG.info("Finalize output:");
-      LOG.info("STDOUT: {}", report.getStdOut());
-      LOG.info("STDERR: {}", report.getStdErr());
+        ExecutionCommand command = new ExecutionCommand();
+        command.setCommandParams(args);
+        command.setClusterName(clName);
+        finalizeUpgradeAction.setExecutionCommand(command);
 
-      if (report.getStatus().equals(HostRoleStatus.COMPLETED.toString())) {
-        return getRequestStatus(null);
+        HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(defaultHostName,
+                Role.AMBARI_SERVER_ACTION, null, null);
+        finalizeUpgradeAction.setHostRoleCommand(hostRoleCommand);
+
+        CommandReport report = finalizeUpgradeAction.execute(null);
+
+        LOG.info("Finalize output:");
+        LOG.info("STDOUT: {}", report.getStdOut());
+        LOG.info("STDERR: {}", report.getStdErr());
+
+        if (report.getStatus().equals(HostRoleStatus.COMPLETED.toString())) {
+          return getRequestStatus(null);
+        } else {
+          String detailedOutput = "Finalization failed. More details: \n" +
+                  "STDOUT: " + report.getStdOut() + "\n" +
+                  "STDERR: " + report.getStdErr();
+          throw new SystemException(detailedOutput);
+        }
       } else {
-        String detailedOutput = "Finalization failed. More details: \n" +
-                "STDOUT: " + report.getStdOut() + "\n" +
-                "STDERR: " + report.getStdErr();
-        throw new SystemException(detailedOutput);
+        // !!! revisit for PU
+        ClusterVersionEntity current = cluster.getCurrentClusterVersion();
+
+        if (!current.getRepositoryVersion().equals(rve)) {
+          updateVersionStates(current.getClusterId(), current.getRepositoryVersion(), rve);
+        }
+
+
+        return getRequestStatus(null);
       }
     } catch (AmbariException e) {
       e.printStackTrace();
@@ -670,4 +692,22 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
 
     return healthyHosts;
   }
+
+  /**
+   * Updates the version states.  Transactional to ensure only one transaction for all updates
+   * @param clusterId the cluster
+   * @param current   the repository that is current for the cluster
+   * @param target    the target repository
+   */
+  @Transactional
+  protected void updateVersionStates(Long clusterId, RepositoryVersionEntity current,
+      RepositoryVersionEntity target) {
+
+    clusterVersionDAO.updateVersions(clusterId, target, current);
+
+    hostVersionDAO.updateVersions(target, current);
+
+    hostComponentStateDAO.updateVersions(target.getVersion());
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ade69a11/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java
index 8d4c5ee..1b00a3e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java
@@ -23,7 +23,6 @@ import javax.persistence.NoResultException;
 import javax.persistence.NonUniqueResultException;
 import javax.persistence.TypedQuery;
 
-import com.google.inject.persist.Transactional;
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
@@ -32,6 +31,7 @@ import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.StackId;
 
 import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
 
 /**
  * The {@link ClusterVersionDAO} class manages the {@link ClusterVersionEntity} instances
associated with a cluster.
@@ -176,4 +176,38 @@ public class ClusterVersionDAO extends CrudDAO<ClusterVersionEntity,
Long>{
     this.create(clusterVersionEntity);
     return clusterVersionEntity;
   }
+
+  /**
+   * Updates the cluster version's existing CURRENT record to the INSTALLED, and the target
+   * becomes CURRENT.
+   * @param clusterId the cluster
+   * @param target    the repo version that will be marked as CURRENT
+   * @param current   the cluster's current record to be marked INSTALLED
+   */
+  @Transactional
+  public void updateVersions(Long clusterId, RepositoryVersionEntity target, RepositoryVersionEntity
current) {
+    // !!! first update target to be current
+    StringBuilder sb = new StringBuilder("UPDATE ClusterVersionEntity cve");
+    sb.append(" SET cve.state = ?1 ");
+    sb.append(" WHERE cve.clusterId = ?2");
+    sb.append(" AND cve.repositoryVersion = ?3");
+
+    TypedQuery<Long> query = entityManagerProvider.get().createQuery(sb.toString(),
Long.class);
+    daoUtils.executeUpdate(query, RepositoryVersionState.CURRENT, clusterId, target);
+
+    // !!! then move existing current to installed
+    sb = new StringBuilder("UPDATE ClusterVersionEntity cve");
+    sb.append(" SET cve.state = ?1 ");
+    sb.append(" WHERE cve.clusterId = ?2");
+    sb.append(" AND cve.repositoryVersion = ?3");
+    sb.append(" AND cve.state = ?4");
+
+    query = entityManagerProvider.get().createQuery(sb.toString(), Long.class);
+    daoUtils.executeUpdate(query, RepositoryVersionState.INSTALLED, clusterId, current,
+        RepositoryVersionState.CURRENT);
+
+    entityManagerProvider.get().clear();
+  }
+
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ade69a11/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
index 2620c8c..46da9da 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
@@ -18,19 +18,21 @@
 
 package org.apache.ambari.server.orm.dao;
 
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import com.google.inject.persist.Transactional;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntityPK;
 import org.apache.ambari.server.orm.entities.HostEntity;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.TypedQuery;
-import java.util.List;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
 
 @Singleton
 public class HostComponentDesiredStateDAO {
@@ -106,4 +108,5 @@ public class HostComponentDesiredStateDAO {
   public void removeByPK(HostComponentDesiredStateEntityPK primaryKey) {
     remove(findByPK(primaryKey));
   }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ade69a11/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
index d5707be..4441b56 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.orm.dao;
 
+import java.util.Arrays;
 import java.util.List;
 
 import javax.persistence.EntityManager;
@@ -27,6 +28,7 @@ import javax.persistence.TypedQuery;
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.HostEntity;
+import org.apache.ambari.server.state.UpgradeState;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -182,4 +184,30 @@ public class HostComponentStateDAO {
     hostEntity.removeHostComponentStateEntity(hostComponentStateEntity);
     hostDAO.merge(hostEntity);
   }
+
+  /**
+   * Marks hosts components to the specified version that are NOT already set or "UNKNOWN".
+   * Also marks all host components as not being upgraded.
+   *
+   * @param version the version
+   */
+  @Transactional
+  public void updateVersions(String version) {
+    // !!! first the version
+    StringBuilder sb = new StringBuilder("UPDATE HostComponentStateEntity hostComponent");
+    sb.append(" SET hostComponent.version = ?1 ");
+    sb.append(" WHERE hostComponent.version NOT IN ?2");
+
+    TypedQuery<Long> query = entityManagerProvider.get().createQuery(sb.toString(),
Long.class);
+    daoUtils.executeUpdate(query, version, Arrays.asList(version, "UNKNOWN"));
+
+    // !!! now the upgrade state
+    sb = new StringBuilder("UPDATE HostComponentStateEntity hostComponent");
+    sb.append(" SET hostComponent.upgradeState = ?1");
+
+    query = entityManagerProvider.get().createQuery(sb.toString(), Long.class);
+    daoUtils.executeUpdate(query, UpgradeState.NONE);
+
+    entityManagerProvider.get().clear();
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ade69a11/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
index ad617af..ae63263 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
@@ -28,6 +28,7 @@ import javax.persistence.TypedQuery;
 
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.HostVersionEntity;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.StackId;
 
@@ -192,4 +193,35 @@ public class HostVersionDAO extends CrudDAO<HostVersionEntity, Long>
{
       this.remove(hostVersion);
     }
   }
+
+  /**
+   * Updates the host versions existing CURRENT record to the INSTALLED, and the target
+   * becomes CURRENT.
+   * @param target    the repo version that all hosts to mark as CURRENT
+   * @param current   the repo version that all hosts marked as INSTALLED
+   */
+  @Transactional
+  public void updateVersions(RepositoryVersionEntity target, RepositoryVersionEntity current)
{
+    // !!! first update target to be current
+    StringBuilder sb = new StringBuilder("UPDATE HostVersionEntity hve");
+    sb.append(" SET hve.state = ?1 ");
+    sb.append(" WHERE hve.repositoryVersion = ?2");
+
+    TypedQuery<Long> query = entityManagerProvider.get().createQuery(sb.toString(),
Long.class);
+    daoUtils.executeUpdate(query, RepositoryVersionState.CURRENT, target);
+
+    // !!! then move existing current to installed
+    sb = new StringBuilder("UPDATE HostVersionEntity hve");
+    sb.append(" SET hve.state = ?1 ");
+    sb.append(" WHERE hve.repositoryVersion = ?2");
+    sb.append(" AND hve.state = ?3");
+
+    query = entityManagerProvider.get().createQuery(sb.toString(), Long.class);
+    daoUtils.executeUpdate(query, RepositoryVersionState.INSTALLED, current,
+        RepositoryVersionState.CURRENT);
+
+
+    entityManagerProvider.get().clear();
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ade69a11/ambari-server/src/main/python/ambari-server.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari-server.py b/ambari-server/src/main/python/ambari-server.py
index 2963322..9f8f925 100755
--- a/ambari-server/src/main/python/ambari-server.py
+++ b/ambari-server/src/main/python/ambari-server.py
@@ -372,7 +372,7 @@ def init_parser_options(parser):
                     dest="jdbc_db")
   parser.add_option('--cluster-name', default=None, help="Cluster name", dest="cluster_name")
   parser.add_option('--version-display-name', default=None, help="Display name of desired
repo version", dest="desired_repo_version")
-
+  parser.add_option('--force-version', action="store_true", default=False, help="Force version
to current", dest="force_repo_version")
 
 @OsFamilyFuncImpl(OSConst.WINSRV_FAMILY)
 def are_cmd_line_db_args_blank(options):

http://git-wip-us.apache.org/repos/asf/ambari/blob/ade69a11/ambari-server/src/main/python/ambari_server/serverUpgrade.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari_server/serverUpgrade.py b/ambari-server/src/main/python/ambari_server/serverUpgrade.py
index 7048812..f05082f 100644
--- a/ambari-server/src/main/python/ambari_server/serverUpgrade.py
+++ b/ambari-server/src/main/python/ambari_server/serverUpgrade.py
@@ -411,7 +411,8 @@ def set_current(options):
   data = {
     "ClusterStackVersions": {
       "repository_version": finalize_options.desired_repo_version,
-      "state": "CURRENT"
+      "state": "CURRENT",
+      "force": "true" if finalize_options.force_repo_version else "false"
     }
   }
 
@@ -497,5 +498,10 @@ class SetCurrentVersionOptions:
     except AttributeError:
       self.desired_repo_version = None
 
+    try:
+      self.force_repo_version = options.force_repo_version
+    except AttributeError:
+      self.force_repo_version = False
+
   def no_finalize_options_set(self):
     return self.cluster_name is None or self.desired_repo_version is None

http://git-wip-us.apache.org/repos/asf/ambari/blob/ade69a11/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
index 7b37483..b41416e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProviderTest.java
@@ -60,7 +60,10 @@ import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
+import org.apache.ambari.server.orm.dao.HostComponentStateDAO;
 import org.apache.ambari.server.orm.dao.HostDAO;
+import org.apache.ambari.server.orm.dao.HostVersionDAO;
 import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
 import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
 import org.apache.ambari.server.orm.dao.StackDAO;
@@ -111,6 +114,9 @@ public class ClusterStackVersionResourceProviderTest {
   private Configuration configuration;
   private StageFactory stageFactory;
 
+  private HostVersionDAO hostVersionDAO;
+  private HostComponentStateDAO hostComponentStateDAO;
+
   private String operatingSystemsJson = "[\n" +
           "   {\n" +
           "      \"repositories\":[\n" +
@@ -134,6 +140,9 @@ public class ClusterStackVersionResourceProviderTest {
   public void setup() throws Exception {
     // Create instances of mocks
     repositoryVersionDAOMock = createNiceMock(RepositoryVersionDAO.class);
+    hostVersionDAO = createNiceMock(HostVersionDAO.class);
+    hostComponentStateDAO = createNiceMock(HostComponentStateDAO.class);
+
     configHelper = createNiceMock(ConfigHelper.class);
     InMemoryDefaultTestModule inMemoryModule = new InMemoryDefaultTestModule();
     Properties properties = inMemoryModule.getProperties();
@@ -150,6 +159,7 @@ public class ClusterStackVersionResourceProviderTest {
     stackDAO = injector.getInstance(StackDAO.class);
     clusterDAO = injector.getInstance(ClusterDAO.class);
     hostDAO = injector.getInstance(HostDAO.class);
+
   }
 
   @After
@@ -449,6 +459,153 @@ public class ClusterStackVersionResourceProviderTest {
     Assert.assertEquals(clusterEntity.getDesiredStack(), newDesiredStack);
   }
 
+  /**
+   * Tests manual finalization scenario
+   * @throws Exception
+   */
+  @Test
+  public void testUpdateResourcesWithForce() throws Exception {
+
+
+    Resource.Type type = Resource.Type.ClusterStackVersion;
+    String clusterName = "Cluster100";
+
+    AmbariManagementController managementController = createMock(AmbariManagementController.class);
+
+    StackId stackId = new StackId("HDP", "2.0.1");
+    StackEntity stackEntity = stackDAO.find(stackId.getStackName(), stackId.getStackVersion());
+    Assert.assertNotNull(stackEntity);
+
+    ResourceTypeEntity resourceTypeEntity = resourceTypeDAO.findById(ResourceTypeEntity.CLUSTER_RESOURCE_TYPE);
+    if (resourceTypeEntity == null) {
+      resourceTypeEntity = new ResourceTypeEntity();
+      resourceTypeEntity.setId(ResourceTypeEntity.CLUSTER_RESOURCE_TYPE);
+      resourceTypeEntity.setName(ResourceTypeEntity.CLUSTER_RESOURCE_TYPE_NAME);
+      resourceTypeEntity = resourceTypeDAO.merge(resourceTypeEntity);
+    }
+    ResourceEntity resourceEntity = new ResourceEntity();
+    resourceEntity.setResourceType(resourceTypeEntity);
+
+    final Host host1 = createNiceMock("host1", Host.class);
+    final Host host2 = createNiceMock("host2", Host.class);
+
+    expect(host1.getHostName()).andReturn("host1").anyTimes();
+    expect(host2.getHostName()).andReturn("host2").anyTimes();
+    replay(host1, host2);
+
+    ServiceComponentHost sch = createMock(ServiceComponentHost.class);
+    List<ServiceComponentHost> schs = Collections.singletonList(sch);
+
+    Cluster cluster = createNiceMock(Cluster.class);
+    cluster.setClusterName(clusterName);
+
+    ArrayList<Host> hosts = new ArrayList<Host>() {{
+      add(host1);
+      add(host2);
+    }};
+
+    Clusters clusters = createNiceMock(Clusters.class);
+    expect(clusters.getCluster(anyObject(String.class))).andReturn(cluster);
+
+    RepositoryVersionEntity repoVersion = new RepositoryVersionEntity();
+    repoVersion.setOperatingSystems(operatingSystemsJson);
+    StackEntity newDesiredStack = stackDAO.find("HDP", "2.0.1");
+    repoVersion.setStack(newDesiredStack);
+
+    final ServiceOsSpecific.Package hivePackage = new ServiceOsSpecific.Package();
+    hivePackage.setName("hive");
+    final ServiceOsSpecific.Package mysqlPackage = new ServiceOsSpecific.Package();
+    mysqlPackage.setName("mysql");
+    mysqlPackage.setSkipUpgrade(Boolean.TRUE);
+    List<ServiceOsSpecific.Package> packages = new ArrayList<ServiceOsSpecific.Package>()
{{
+      add(hivePackage);
+      add(mysqlPackage);
+    }};
+
+    ActionManager actionManager = createNiceMock(ActionManager.class);
+
+    RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
+    ResourceProviderFactory resourceProviderFactory = createNiceMock(ResourceProviderFactory.class);
+    ResourceProvider csvResourceProvider = createNiceMock(ClusterStackVersionResourceProvider.class);
+
+    AbstractControllerResourceProvider.init(resourceProviderFactory);
+
+    Map<String, Map<String, String>> hostConfigTags = new HashMap<String,
Map<String, String>>();
+    expect(configHelper.getEffectiveDesiredTags(anyObject(ClusterImpl.class), anyObject(String.class))).andReturn(hostConfigTags);
+
+    expect(managementController.getClusters()).andReturn(clusters).anyTimes();
+    expect(managementController.getAmbariMetaInfo()).andReturn(ambariMetaInfo).anyTimes();
+    expect(managementController.getAuthName()).andReturn("admin").anyTimes();
+    expect(managementController.getActionManager()).andReturn(actionManager).anyTimes();
+    expect(managementController.getJdkResourceUrl()).andReturn("/JdkResourceUrl").anyTimes();
+    expect(managementController.getPackagesForServiceHost(anyObject(ServiceInfo.class),
+            (Map<String, String>) anyObject(List.class), anyObject(String.class))).andReturn(packages).anyTimes();
+
+    expect(resourceProviderFactory.getHostResourceProvider(anyObject(Set.class), anyObject(Map.class),
+            eq(managementController))).andReturn(csvResourceProvider).anyTimes();
+
+    expect(cluster.getCurrentStackVersion()).andReturn(stackId);
+    expect(cluster.getServiceComponentHosts(anyObject(String.class))).andReturn(schs).anyTimes();
+
+    RepositoryVersionEntity currentRepo = new RepositoryVersionEntity();
+    currentRepo.setVersion("2.2.2.0-2122");
+    ClusterVersionEntity current = new ClusterVersionEntity();
+    current.setRepositoryVersion(currentRepo);
+
+    Capture<StackId> capturedStackId = new Capture<StackId>();
+    cluster.setDesiredStackVersion(capture(capturedStackId));
+      expectLastCall().once();
+    expect(cluster.getHosts()).andReturn(hosts).anyTimes();
+    expect(cluster.getCurrentClusterVersion()).andReturn(current).anyTimes();
+
+    expect(sch.getServiceName()).andReturn("HIVE").anyTimes();
+
+    expect(repositoryVersionDAOMock.findByDisplayName(anyObject(String.class))).andReturn(repoVersion);
+
+    clusterVersionDAO.updateVersions((Long) anyObject(),
+        (RepositoryVersionEntity) anyObject(), (RepositoryVersionEntity) anyObject());
+    expectLastCall().once();
+
+    hostVersionDAO.updateVersions((RepositoryVersionEntity) anyObject(), (RepositoryVersionEntity)
anyObject());
+    expectLastCall().once();
+
+    hostComponentStateDAO.updateVersions((String) anyObject());
+    expectLastCall().once();
+
+    // replay
+    replay(managementController, response, clusters, resourceProviderFactory, csvResourceProvider,
+            cluster, repositoryVersionDAOMock, configHelper, sch, actionManager, clusterVersionDAO,
+            hostVersionDAO, hostComponentStateDAO);
+
+    ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
+            type,
+            PropertyHelper.getPropertyIds(type),
+            PropertyHelper.getKeyPropertyIds(type),
+            managementController);
+
+    injector.injectMembers(provider);
+
+
+    // add the property map to a set for the request.  add more maps for multiple creates
+    Map<String, Object> properties = new LinkedHashMap<String, Object>();
+
+    // add properties to the request map
+    properties.put(ClusterStackVersionResourceProvider.CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID,
clusterName);
+    properties.put(ClusterStackVersionResourceProvider.CLUSTER_STACK_VERSION_STATE_PROPERTY_ID,
"CURRENT");
+    properties.put(ClusterStackVersionResourceProvider.CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID,
"HDP-2.2.2.0-2561");
+    properties.put(ClusterStackVersionResourceProvider.CLUSTER_STACK_VERSION_FORCE, "true");
+
+    // create the request
+    Request request = PropertyHelper.getUpdateRequest(properties, null);
+
+    provider.updateResources(request, null);
+
+    // verify
+    verify(managementController, response, clusterVersionDAO, hostVersionDAO, hostComponentStateDAO);
+    Assert.assertEquals(capturedStackId.getValue(),
+            new StackId(newDesiredStack.getStackName(), newDesiredStack.getStackVersion()));
+  }
+
 
   public class MockModule extends AbstractModule {
     @Override
@@ -457,6 +614,9 @@ public class ClusterStackVersionResourceProviderTest {
       bind(ConfigHelper.class).toInstance(configHelper);
       bind(Configuration.class).toInstance(configuration);
       bind(StageFactory.class).toInstance(stageFactory);
+      bind(ClusterVersionDAO.class).toInstance(clusterVersionDAO);
+      bind(HostVersionDAO.class).toInstance(hostVersionDAO);
+      bind(HostComponentStateDAO.class).toInstance(hostComponentStateDAO);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ade69a11/ambari-server/src/test/python/TestServerUpgrade.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/TestServerUpgrade.py b/ambari-server/src/test/python/TestServerUpgrade.py
index 7ef74b2..50e023f 100644
--- a/ambari-server/src/test/python/TestServerUpgrade.py
+++ b/ambari-server/src/test/python/TestServerUpgrade.py
@@ -39,6 +39,7 @@ class TestServerUpgrade(TestCase):
     options = MagicMock()
     options.cluster_name = 'cc'
     options.desired_repo_version = 'HDP-2.2.2.0-2561'
+    options.force_repo_version = None
 
     # Case when server is not running
     is_server_runing_mock.return_value = False, None
@@ -75,11 +76,63 @@ class TestServerUpgrade(TestCase):
     self.assertTrue(urlopen_mock.called)
     request = urlopen_mock.call_args_list[0][0][0]
     self.assertEquals(request._Request__original, 'http://127.0.0.1:8080/api/v1/clusters/cc/stack_versions')
-    self.assertEquals(request.data, '{"ClusterStackVersions": {"state": "CURRENT", "repository_version":
"HDP-2.2.2.0-2561"}}')
+    self.assertEquals(request.data, '{"ClusterStackVersions": {"state": "CURRENT", "repository_version":
"HDP-2.2.2.0-2561", "force": "false"}}')
     self.assertEquals(request.origin_req_host, '127.0.0.1')
     self.assertEquals(request.headers, {'X-requested-by': 'ambari', 'Authorization': 'Basic
ZHVtbXlfc3RyaW5nOmR1bW15X3N0cmluZw=='})
 
+  @patch("ambari_server.serverUpgrade.is_server_runing")
+  @patch('ambari_server.serverUpgrade.SetCurrentVersionOptions.no_finalize_options_set')
+  @patch('ambari_server.serverUpgrade.get_validated_string_input')
+  @patch('ambari_server.serverUpgrade.get_ambari_properties')
+  @patch('ambari_server.serverUtils.get_ambari_server_api_base')
+  @patch('ambari_commons.logging_utils.get_verbose')
+  @patch('urllib2.urlopen')
+  def test_set_current_with_force(self, urlopen_mock, get_verbose_mock, get_ambari_server_api_base_mock,
+                       get_ambari_properties_mock, get_validated_string_input_mock,
+                       no_finalize_options_set_mock, is_server_runing_mock):
+    options = MagicMock()
+    options.cluster_name = 'cc'
+    options.desired_repo_version = 'HDP-2.2.2.0-2561'
+    options.force_repo_version = True
 
+    # Case when server is not running
+    is_server_runing_mock.return_value = False, None
+    try:
+      set_current(options)
+      self.fail("Server is not running - should error out")
+    except FatalException:
+      pass  # expected
+
+
+    is_server_runing_mock.return_value = True, 11111
+
+    # Test insufficient options case
+    no_finalize_options_set_mock.return_value = True
+    try:
+      set_current(options)
+      self.fail("Should error out")
+    except FatalException:
+      pass  # expected
+
+    no_finalize_options_set_mock.return_value = False
+
+    # Test normal flow
+    get_validated_string_input_mock.return_value = 'dummy_string'
+
+    p = get_ambari_properties_mock.return_value
+    p.get_property.side_effect = ["8080", "false"]
+
+    get_ambari_server_api_base_mock.return_value = 'http://127.0.0.1:8080/api/v1/'
+    get_verbose_mock.retun_value = False
+
+    set_current(options)
+
+    self.assertTrue(urlopen_mock.called)
+    request = urlopen_mock.call_args_list[0][0][0]
+    self.assertEquals(request._Request__original, 'http://127.0.0.1:8080/api/v1/clusters/cc/stack_versions')
+    self.assertEquals(request.data, '{"ClusterStackVersions": {"state": "CURRENT", "repository_version":
"HDP-2.2.2.0-2561", "force": "true"}}')
+    self.assertEquals(request.origin_req_host, '127.0.0.1')
+    self.assertEquals(request.headers, {'X-requested-by': 'ambari', 'Authorization': 'Basic
ZHVtbXlfc3RyaW5nOmR1bW15X3N0cmluZw=='})
 
   def testCurrentVersionOptions(self):
     # Negative test cases


Mime
View raw message