You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2015/04/17 23:56:22 UTC

ambari git commit: AMBARI-10580 - Ambari Database Upgrades For Stack Entity Changes (jonathanhurley)

Repository: ambari
Updated Branches:
  refs/heads/trunk 1e631ce38 -> bdf5effbe


AMBARI-10580 - Ambari Database Upgrades For Stack Entity Changes (jonathanhurley)


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

Branch: refs/heads/trunk
Commit: bdf5effbe899c93b7da408417474f1c8cdbb4b2b
Parents: 1e631ce
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Fri Apr 17 17:36:26 2015 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Fri Apr 17 17:56:15 2015 -0400

----------------------------------------------------------------------
 .../server/alerts/StaleAlertRunnable.java       |  11 +-
 .../ambari/server/stack/StackManager.java       |   9 +
 .../services/AmbariServerAlertService.java      |   1 +
 .../server/upgrade/AbstractUpgradeCatalog.java  |   8 +
 .../server/upgrade/SchemaUpgradeHelper.java     |  19 ++
 .../ambari/server/upgrade/UpgradeCatalog.java   |  25 ++-
 .../server/upgrade/UpgradeCatalog200.java       |   2 +-
 .../server/upgrade/UpgradeCatalog210.java       | 217 ++++++++++++++++++-
 .../server/alerts/StaleAlertRunnableTest.java   |  41 +++-
 .../server/upgrade/UpgradeCatalog210Test.java   |  74 +++----
 .../ambari/server/upgrade/UpgradeTest.java      |   2 -
 11 files changed, 342 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/main/java/org/apache/ambari/server/alerts/StaleAlertRunnable.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/alerts/StaleAlertRunnable.java b/ambari-server/src/main/java/org/apache/ambari/server/alerts/StaleAlertRunnable.java
index 40e6fb2..e23dd62 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/alerts/StaleAlertRunnable.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/alerts/StaleAlertRunnable.java
@@ -47,8 +47,10 @@ import com.google.inject.Provider;
 
 /**
  * The {@link StaleAlertRunnable} is used by the
- * {@link AmbariServerAlertService} to check agent heartbeats and fire alert
- * events when an agent host changes state.
+ * {@link AmbariServerAlertService} to check the last time that an alert was
+ * checked and determine if it seems to no longer be running. It will produce a
+ * single alert with {@link AlertState#CRITICAL} along with a textual
+ * description of the alerts that are stale.
  */
 public class StaleAlertRunnable implements Runnable {
 
@@ -154,6 +156,11 @@ public class StaleAlertRunnable implements Runnable {
             continue;
           }
 
+          // skip this alert (who watches the watchers)
+          if (definition.getDefinitionName().equals(STALE_ALERT_DEFINITION_NAME)) {
+            continue;
+          }
+
           // convert minutes to milliseconds for the definition's interval
           long intervalInMillis = definition.getScheduleInterval()
               * MINUTE_TO_MS_CONVERSION;

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
index 1026245..832370d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
@@ -104,6 +104,8 @@ public class StackManager {
       ActionMetadata actionMetadata, StackDAO stackDao)
       throws AmbariException {
 
+    LOG.info("Initializing the stack manager...");
+
     validateStackDirectory(stackRoot);
     validateCommonServicesDirectory(commonServicesRoot);
 
@@ -125,6 +127,8 @@ public class StackManager {
       String stackVersion = stack.getVersion();
 
       if (stackDao.find(stackName, stackVersion) == null) {
+        LOG.info("Adding stack {}-{} to the database", stackName, stackVersion);
+
         StackEntity stackEntity = new StackEntity();
         stackEntity.setStackName(stackName);
         stackEntity.setStackVersion(stackVersion);
@@ -236,6 +240,9 @@ public class StackManager {
    */
   private void validateCommonServicesDirectory(File commonServicesRoot) throws AmbariException {
     if(commonServicesRoot != null) {
+      LOG.info("Validating common services directory {} ...",
+          commonServicesRoot);
+
       String commonServicesRootAbsolutePath = commonServicesRoot.getAbsolutePath();
       if (LOG.isDebugEnabled()) {
         LOG.debug("Loading common services information"
@@ -257,6 +264,8 @@ public class StackManager {
    * @throws AmbariException if the specified stack root directory is invalid
    */
   private void validateStackDirectory(File stackRoot) throws AmbariException {
+    LOG.info("Validating stack directory {} ...", stackRoot);
+
     String stackRootAbsPath = stackRoot.getAbsolutePath();
     if (LOG.isDebugEnabled()) {
       LOG.debug("Loading stack information"

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
index 6669e7b..a13a8c7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
@@ -46,6 +46,7 @@ import com.google.inject.Provider;
 
 /**
  * The {@link AmbariServerAlertService} is used to manage the dynamically loaded
+ * {@link Runnable}s which perform server-side alert checks.
  */
 @AmbariService
 public class AmbariServerAlertService extends AbstractScheduledService {

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
index 863b5da..940be93 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
@@ -391,4 +391,12 @@ public abstract class AbstractUpgradeCatalog implements UpgradeCatalog {
     return "{ upgradeCatalog: sourceVersion = " + getSourceVersion() + ", " +
       "targetVersion = " + getTargetVersion() + " }";
   }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void onPostUpgrade() throws AmbariException, SQLException {
+    // NOOP
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
index 61482c9..1d6095b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
@@ -235,6 +235,23 @@ public class SchemaUpgradeHelper {
     }
   }
 
+  public void executeOnPostUpgrade(List<UpgradeCatalog> upgradeCatalogs)
+      throws AmbariException {
+    LOG.info("Finalizing catalog upgrade.");
+
+    if (upgradeCatalogs != null && !upgradeCatalogs.isEmpty()) {
+      for (UpgradeCatalog upgradeCatalog : upgradeCatalogs) {
+        try {
+          upgradeCatalog.onPostUpgrade();
+          ;
+        } catch (Exception e) {
+          LOG.error("Upgrade failed. ", e);
+          throw new AmbariException(e.getMessage(), e);
+        }
+      }
+    }
+  }
+
   public void resetUIState() throws AmbariException {
     LOG.info("Resetting UI state.");
     try {
@@ -279,6 +296,8 @@ public class SchemaUpgradeHelper {
 
       schemaUpgradeHelper.executeDMLUpdates(upgradeCatalogs);
 
+      schemaUpgradeHelper.executeOnPostUpgrade(upgradeCatalogs);
+
       schemaUpgradeHelper.resetUIState();
 
       LOG.info("Upgrade successful.");

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog.java
index a10b21c..f482dc2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog.java
@@ -17,10 +17,10 @@
  */
 package org.apache.ambari.server.upgrade;
 
-import org.apache.ambari.server.AmbariException;
-
 import java.sql.SQLException;
 
+import org.apache.ambari.server.AmbariException;
+
 /**
  * Interface for upgrading Ambari DB
  */
@@ -30,20 +30,31 @@ public interface UpgradeCatalog {
    * to the new version.
    * @throws AmbariException
    */
-  public void upgradeSchema() throws AmbariException, SQLException;
+  void upgradeSchema() throws AmbariException, SQLException;
 
   /**
    * perform data updates as necessary, requires started persist service
    * @throws AmbariException
    * @throws SQLException
    */
-  public void upgradeData() throws AmbariException, SQLException;
+  void upgradeData() throws AmbariException, SQLException;
+
+  /**
+   * Called after {@link #upgradeSchema()} and {@link #upgradeData()}, this
+   * method is used to perform any operations after the catalog has finished.
+   * Usually, this is cleanup work that does not directly affect the upgrade.
+   *
+   * @throws AmbariException
+   * @throws SQLException
+   */
+  void onPostUpgrade() throws AmbariException, SQLException;
 
   /**
    * Return the version that will be upgraded to
+   * 
    * @return
    */
-  public abstract String getTargetVersion();
+  String getTargetVersion();
 
   /**
    * Return latest source version that can be upgraded from.
@@ -51,11 +62,11 @@ public interface UpgradeCatalog {
    *
    * @return null : default
    */
-  public String getSourceVersion();
+  String getSourceVersion();
 
   /**
    * Returns a list of versions using simplified regex of the Ambari versions that allow running this UpgradeCatalog.
    * @return null : default
    */
-  public String[] getCompatibleVersions();
+  String[] getCompatibleVersions();
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
index e577aa4..4117a1c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
@@ -100,7 +100,7 @@ public class UpgradeCatalog200 extends AbstractUpgradeCatalog {
    */
   @Override
   public String[] getCompatibleVersions() {
-    return new String[] {"2.0.*"};
+    return new String[] { "2.0.*", "2.1.*" };
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
index 884032e..8897657 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
@@ -20,24 +20,29 @@ package org.apache.ambari.server.upgrade;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.orm.DBAccessor.DBColumnInfo;
-import org.apache.ambari.server.orm.dao.ClusterDAO;
-import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
-import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.orm.dao.StackDAO;
+import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.StackId;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.gson.Gson;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 import com.google.inject.persist.Transactional;
@@ -47,7 +52,6 @@ import com.google.inject.persist.Transactional;
  * Upgrade catalog for version 2.1.0.
  */
 public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
-
   private static final String CLUSTERS_TABLE = "clusters";
   private static final String HOSTS_TABLE = "hosts";
   private static final String HOST_COMPONENT_DESIRED_STATE_TABLE = "hostcomponentdesiredstate";
@@ -64,10 +68,21 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
   private static final String WIDGET_LAYOUT_USER_WIDGET_TABLE = "widget_layout_user_widget";
   private static final String VIEW_INSTANCE_TABLE = "viewinstance";
   private static final String VIEW_PARAMETER_TABLE = "viewparameter";
-  private static final String STACK_TABLE_DEFINITION = "stack";
+  private static final String STACK_TABLE = "stack";
+  private static final String REPO_VERSION_TABLE = "repo_version";
 
   private static final String HOST_ID_COL = "host_id";
 
+  // constants for stack table changes
+  private static final String STACK_ID_COLUMN_NAME = "stack_id";
+  private static final String DESIRED_STACK_ID_COLUMN_NAME = "desired_stack_id";
+  private static final String CURRENT_STACK_ID_COLUMN_NAME = "current_stack_id";
+  private static final String DESIRED_STACK_VERSION_COLUMN_NAME = "desired_stack_version";
+  private static final String CURRENT_STACK_VERSION_COLUMN_NAME = "current_stack_version";
+  private static final DBColumnInfo DESIRED_STACK_ID_COLUMN = new DBColumnInfo(DESIRED_STACK_ID_COLUMN_NAME, Long.class, null, null, true);
+  private static final DBColumnInfo CURRENT_STACK_ID_COLUMN = new DBColumnInfo(CURRENT_STACK_ID_COLUMN_NAME, Long.class, null, null, true);
+  private static final DBColumnInfo STACK_ID_COLUMN = new DBColumnInfo(STACK_ID_COLUMN_NAME, Long.class, null, null, true);
+
   /**
    * {@inheritDoc}
    */
@@ -87,6 +102,7 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
   /**
    * {@inheritDoc}
    */
+  @Override
   public String[] getCompatibleVersions() {
     return new String[] {"*"};
   }
@@ -122,6 +138,14 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
   }
 
   /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void onPostUpgrade() throws AmbariException, SQLException {
+    cleanupStackUpdates();
+  }
+
+  /**
    * Execute all of the hosts DDL updates.
    *
    * @throws org.apache.ambari.server.AmbariException
@@ -301,7 +325,7 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
     dbAccessor.dropColumn(HOST_COMPONENT_DESIRED_STATE_TABLE, "host_name");
     dbAccessor.dropColumn(HOST_STATE_TABLE, "host_name");
     // TODO, include other tables.
-    
+
     // view columns for cluster association
     dbAccessor.addColumn(VIEW_INSTANCE_TABLE, new DBColumnInfo("cluster_handle", String.class, 255, null, true));
     dbAccessor.addColumn(VIEW_PARAMETER_TABLE, new DBColumnInfo("cluster_config", String.class, 255, null, true));
@@ -348,24 +372,155 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
   }
 
   /**
-   * Adds the stack table and constraints.
+   * Adds the stack table, FKs, and constraints.
    */
   private void executeStackDDLUpdates() throws AmbariException, SQLException {
-    // alert_definition
+    // stack table creation
     ArrayList<DBColumnInfo> columns = new ArrayList<DBColumnInfo>();
     columns.add(new DBColumnInfo("stack_id", Long.class, null, null, false));
     columns.add(new DBColumnInfo("stack_name", String.class, 255, null, false));
     columns.add(new DBColumnInfo("stack_version", String.class, 255, null,
         false));
 
-    dbAccessor.createTable(STACK_TABLE_DEFINITION, columns, "stack_id");
+    dbAccessor.createTable(STACK_TABLE, columns, "stack_id");
 
-    dbAccessor.executeQuery("ALTER TABLE " + STACK_TABLE_DEFINITION
+    dbAccessor.executeQuery("ALTER TABLE " + STACK_TABLE
         + " ADD CONSTRAINT unq_stack UNIQUE (stack_name,stack_version)", false);
 
     dbAccessor.executeQuery(
         "INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES('stack_id_seq', 0)",
         false);
+
+    // create the new stack ID columns NULLABLE for now since we need to insert
+    // data into them later on (we'll change them to NOT NULL after that)
+    dbAccessor.addColumn(CLUSTERS_TABLE, DESIRED_STACK_ID_COLUMN);
+    dbAccessor.addColumn("hostcomponentdesiredstate", DESIRED_STACK_ID_COLUMN);
+    dbAccessor.addColumn("servicecomponentdesiredstate", DESIRED_STACK_ID_COLUMN);
+    dbAccessor.addColumn("servicedesiredstate", DESIRED_STACK_ID_COLUMN);
+
+    dbAccessor.addFKConstraint(CLUSTERS_TABLE, "fk_clusters_desired_stack_id", DESIRED_STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+    dbAccessor.addFKConstraint("hostcomponentdesiredstate", "fk_hcds_desired_stack_id", DESIRED_STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+    dbAccessor.addFKConstraint("servicecomponentdesiredstate", "fk_scds_desired_stack_id", DESIRED_STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+    dbAccessor.addFKConstraint("servicedesiredstate", "fk_sds_desired_stack_id", DESIRED_STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+
+    dbAccessor.addColumn("clusterstate", CURRENT_STACK_ID_COLUMN);
+    dbAccessor.addColumn("hostcomponentstate", CURRENT_STACK_ID_COLUMN);
+
+    dbAccessor.addFKConstraint("clusterstate", "fk_cs_current_stack_id", CURRENT_STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+    dbAccessor.addFKConstraint("hostcomponentstate", "fk_hcs_current_stack_id", CURRENT_STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+
+    dbAccessor.addColumn("clusterconfig", STACK_ID_COLUMN);
+    dbAccessor.addColumn("serviceconfig", STACK_ID_COLUMN);
+    dbAccessor.addColumn("blueprint", STACK_ID_COLUMN);
+    dbAccessor.addColumn(REPO_VERSION_TABLE, STACK_ID_COLUMN);
+
+    dbAccessor.addFKConstraint("clusterconfig", "fk_clusterconfig_stack_id", STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+    dbAccessor.addFKConstraint("serviceconfig", "fk_serviceconfig_stack_id", STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+    dbAccessor.addFKConstraint("blueprint", "fk_blueprint_stack_id", STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+    dbAccessor.addFKConstraint(REPO_VERSION_TABLE, "fk_repoversion_stack_id", STACK_ID_COLUMN_NAME, STACK_TABLE, STACK_ID_COLUMN_NAME, true);
+
+    // drop the unique constraint for the old column and add the new one
+    dbAccessor.dropConstraint(REPO_VERSION_TABLE, "uq_repo_version_stack_version");
+    dbAccessor.executeQuery("ALTER TABLE repo_version ADD CONSTRAINT uq_repo_version_stack_id UNIQUE (stack_id, version)");
+  }
+
+  /**
+   * Adds the stack table and constraints.
+   */
+  protected void executeStackDMLUpdates() throws AmbariException, SQLException {
+    Gson gson = new Gson();
+
+    injector.getInstance(AmbariMetaInfo.class);
+
+    StackDAO stackDAO = injector.getInstance(StackDAO.class);
+    List<StackEntity> stacks = stackDAO.findAll();
+    Map<Long,String> entityToJsonMap = new HashMap<Long, String>();
+
+    // build a mapping of stack entity to old-school JSON
+    for( StackEntity stack : stacks ){
+      StackId stackId = new StackId(stack.getStackName(),
+          stack.getStackVersion());
+      String stackJson = gson.toJson(stackId);
+      entityToJsonMap.put(stack.getStackId(), stackJson);
+    }
+
+    // use a bulk update on all tables to populate the new FK columns
+    String UPDATE_TEMPLATE = "UPDATE {0} SET {1} = {2} WHERE {3} = ''{4}''";
+    String UPDATE_BLUEPRINT_TEMPLATE = "UPDATE blueprint SET stack_id = {0} WHERE stack_name = ''{1}'' AND stack_version = ''{2}''";
+
+    Set<Long> stackEntityIds = entityToJsonMap.keySet();
+    for (Long stackEntityId : stackEntityIds) {
+      StackEntity stackEntity = stackDAO.findById(stackEntityId);
+      String outdatedJson = entityToJsonMap.get(stackEntityId);
+
+      String clustersSQL = MessageFormat.format(UPDATE_TEMPLATE, "clusters",
+          DESIRED_STACK_ID_COLUMN_NAME, stackEntityId,
+          DESIRED_STACK_VERSION_COLUMN_NAME, outdatedJson);
+
+      String hostComponentDesiredStateSQL = MessageFormat.format(
+          UPDATE_TEMPLATE, "hostcomponentdesiredstate",
+          DESIRED_STACK_ID_COLUMN_NAME, stackEntityId,
+          DESIRED_STACK_VERSION_COLUMN_NAME, outdatedJson);
+
+      String serviceComponentDesiredStateSQL = MessageFormat.format(
+          UPDATE_TEMPLATE, "servicecomponentdesiredstate",
+          DESIRED_STACK_ID_COLUMN_NAME, stackEntityId,
+          DESIRED_STACK_VERSION_COLUMN_NAME, outdatedJson);
+
+      String serviceDesiredStateSQL = MessageFormat.format(UPDATE_TEMPLATE,
+          "servicedesiredstate",
+          DESIRED_STACK_ID_COLUMN_NAME, stackEntityId,
+          DESIRED_STACK_VERSION_COLUMN_NAME, outdatedJson);
+
+      String clusterStateSQL = MessageFormat.format(UPDATE_TEMPLATE,
+          "clusterstate", CURRENT_STACK_ID_COLUMN_NAME, stackEntityId,
+          CURRENT_STACK_VERSION_COLUMN_NAME, outdatedJson);
+
+      String hostComponentStateSQL = MessageFormat.format(UPDATE_TEMPLATE,
+          "hostcomponentstate", CURRENT_STACK_ID_COLUMN_NAME, stackEntityId,
+          CURRENT_STACK_VERSION_COLUMN_NAME, outdatedJson);
+
+      String blueprintSQL = MessageFormat.format(UPDATE_BLUEPRINT_TEMPLATE,
+          stackEntityId, stackEntity.getStackName(),
+          stackEntity.getStackVersion());
+
+      String repoVersionSQL = MessageFormat.format(UPDATE_TEMPLATE,
+          REPO_VERSION_TABLE, STACK_ID_COLUMN_NAME, stackEntityId, "stack",
+          outdatedJson);
+
+      dbAccessor.executeQuery(clustersSQL);
+      dbAccessor.executeQuery(hostComponentDesiredStateSQL);
+      dbAccessor.executeQuery(serviceComponentDesiredStateSQL);
+      dbAccessor.executeQuery(serviceDesiredStateSQL);
+      dbAccessor.executeQuery(clusterStateSQL);
+      dbAccessor.executeQuery(hostComponentStateSQL);
+      dbAccessor.executeQuery(blueprintSQL);
+      dbAccessor.executeQuery(repoVersionSQL);
+    }
+
+    // for the tables with no prior stack, set these based on the cluster's
+    // stack for each cluster defined
+    String INSERT_STACK_ID_TEMPLATE = "UPDATE {0} SET {1} = {2} WHERE cluster_id = {3}";
+    ResultSet resultSet = dbAccessor.executeSelect("SELECT * FROM clusters");
+    while (resultSet.next()) {
+      long clusterId = resultSet.getLong("cluster_id");
+      String stackJson = resultSet.getString(DESIRED_STACK_VERSION_COLUMN_NAME);
+      StackId stackId = gson.fromJson(stackJson, StackId.class);
+
+      StackEntity stackEntity = stackDAO.find(stackId.getStackName(),
+          stackId.getStackVersion());
+
+      String clusterConfigSQL = MessageFormat.format(INSERT_STACK_ID_TEMPLATE,
+          "clusterconfig", STACK_ID_COLUMN_NAME, stackEntity.getStackId(),
+          clusterId);
+
+      String serviceConfigSQL = MessageFormat.format(INSERT_STACK_ID_TEMPLATE,
+          "serviceconfig", STACK_ID_COLUMN_NAME, stackEntity.getStackId(),
+          clusterId);
+
+      dbAccessor.executeQuery(clusterConfigSQL);
+      dbAccessor.executeQuery(serviceConfigSQL);
+    }
   }
 
   /**
@@ -462,7 +617,49 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
   @Override
   protected void executeDMLUpdates() throws AmbariException, SQLException {
     addNewConfigurationsFromXml();
+
     // Initialize all default widgets and widget layouts
     initializeClusterAndServiceWidgets();
+
+    // populate new stack ID columns
+    executeStackDMLUpdates();
+  }
+
+  /**
+   * Adds non NULL constraints and drops outdated columns no longer needed after
+   * the column data migration.
+   */
+  private void cleanupStackUpdates() throws SQLException {
+    DESIRED_STACK_ID_COLUMN.setNullable(false);
+    CURRENT_STACK_ID_COLUMN.setNullable(false);
+    STACK_ID_COLUMN.setNullable(false);
+
+    // make all stack columns NOT NULL now that they are filled in
+    dbAccessor.alterColumn(CLUSTERS_TABLE, DESIRED_STACK_ID_COLUMN);
+    dbAccessor.alterColumn("hostcomponentdesiredstate", DESIRED_STACK_ID_COLUMN);
+    dbAccessor.alterColumn("servicecomponentdesiredstate", DESIRED_STACK_ID_COLUMN);
+    dbAccessor.alterColumn("servicedesiredstate", DESIRED_STACK_ID_COLUMN);
+
+    dbAccessor.alterColumn("clusterstate", CURRENT_STACK_ID_COLUMN);
+    dbAccessor.alterColumn("hostcomponentstate", CURRENT_STACK_ID_COLUMN);
+
+    dbAccessor.alterColumn("clusterconfig", STACK_ID_COLUMN);
+    dbAccessor.alterColumn("serviceconfig", STACK_ID_COLUMN);
+    dbAccessor.alterColumn("blueprint", STACK_ID_COLUMN);
+    dbAccessor.alterColumn(REPO_VERSION_TABLE, STACK_ID_COLUMN);
+
+    // drop unused JSON columns
+    dbAccessor.dropColumn(CLUSTERS_TABLE, DESIRED_STACK_VERSION_COLUMN_NAME);
+    dbAccessor.dropColumn("hostcomponentdesiredstate", DESIRED_STACK_VERSION_COLUMN_NAME);
+    dbAccessor.dropColumn("servicecomponentdesiredstate", DESIRED_STACK_VERSION_COLUMN_NAME);
+    dbAccessor.dropColumn("servicedesiredstate", DESIRED_STACK_VERSION_COLUMN_NAME);
+
+    dbAccessor.dropColumn("clusterstate", CURRENT_STACK_VERSION_COLUMN_NAME);
+    dbAccessor.dropColumn("hostcomponentstate", CURRENT_STACK_VERSION_COLUMN_NAME);
+
+    dbAccessor.dropColumn("blueprint", "stack_name");
+    dbAccessor.dropColumn("blueprint", "stack_version");
+
+    dbAccessor.dropColumn(REPO_VERSION_TABLE, "stack");
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/test/java/org/apache/ambari/server/alerts/StaleAlertRunnableTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/alerts/StaleAlertRunnableTest.java b/ambari-server/src/test/java/org/apache/ambari/server/alerts/StaleAlertRunnableTest.java
index f3e3fa6..94a0bc2 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/alerts/StaleAlertRunnableTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/alerts/StaleAlertRunnableTest.java
@@ -150,11 +150,19 @@ public class StaleAlertRunnableTest {
   @Test
   public void testAllAlertsAreCurrent() {
     // create current alerts that are not stale
+    AlertDefinitionEntity definition1 = new AlertDefinitionEntity();
+    definition1.setClusterId(CLUSTER_ID);
+    definition1.setDefinitionName("foo-definition");
+    definition1.setServiceName("HDFS");
+    definition1.setComponentName("NAMENODE");
+    definition1.setEnabled(true);
+    definition1.setScheduleInterval(1);
+
     AlertCurrentEntity current1 = createNiceMock(AlertCurrentEntity.class);
     AlertHistoryEntity history1 = createNiceMock(AlertHistoryEntity.class);
 
     expect(current1.getAlertHistory()).andReturn(history1).atLeastOnce();
-    expect(history1.getAlertDefinition()).andReturn(m_definition).atLeastOnce();
+    expect(history1.getAlertDefinition()).andReturn(definition1).atLeastOnce();
 
     expect(current1.getMaintenanceState()).andReturn(MaintenanceState.OFF).atLeastOnce();
     expect(current1.getLatestTimestamp()).andReturn(System.currentTimeMillis()).atLeastOnce();
@@ -187,8 +195,7 @@ public class StaleAlertRunnableTest {
     assertEquals(AlertState.OK, alert.getState());
     assertEquals(DEFINITION_NAME, alert.getName());
 
-    verify(m_definition, m_cluster, m_clusters,
-        m_definitionDao);
+    verify(m_cluster, m_clusters, m_definitionDao);
   }
 
   /**
@@ -196,12 +203,21 @@ public class StaleAlertRunnableTest {
    */
   @Test
   public void testStaleAlert() {
+    // create current alerts that are not stale
+    AlertDefinitionEntity definition1 = new AlertDefinitionEntity();
+    definition1.setClusterId(CLUSTER_ID);
+    definition1.setDefinitionName("foo-definition");
+    definition1.setServiceName("HDFS");
+    definition1.setComponentName("NAMENODE");
+    definition1.setEnabled(true);
+    definition1.setScheduleInterval(1);
+
     // create current alerts that are stale
     AlertCurrentEntity current1 = createNiceMock(AlertCurrentEntity.class);
     AlertHistoryEntity history1 = createNiceMock(AlertHistoryEntity.class);
 
     expect(current1.getAlertHistory()).andReturn(history1).atLeastOnce();
-    expect(history1.getAlertDefinition()).andReturn(m_definition).atLeastOnce();
+    expect(history1.getAlertDefinition()).andReturn(definition1).atLeastOnce();
 
     // a really old timestampt to trigger the alert
     expect(current1.getMaintenanceState()).andReturn(MaintenanceState.OFF).atLeastOnce();
@@ -235,7 +251,7 @@ public class StaleAlertRunnableTest {
     assertEquals(AlertState.CRITICAL, alert.getState());
     assertEquals(DEFINITION_NAME, alert.getName());
 
-    verify(m_definition, m_cluster, m_clusters, m_definitionDao);
+    verify(m_cluster, m_clusters, m_definitionDao);
   }
 
   /**
@@ -243,6 +259,15 @@ public class StaleAlertRunnableTest {
    */
   @Test
   public void testStaleAlertInMaintenaceMode() {
+    // create current alerts that are not stale
+    AlertDefinitionEntity definition1 = new AlertDefinitionEntity();
+    definition1.setClusterId(CLUSTER_ID);
+    definition1.setDefinitionName("foo-definition");
+    definition1.setServiceName("HDFS");
+    definition1.setComponentName("NAMENODE");
+    definition1.setEnabled(true);
+    definition1.setScheduleInterval(1);
+
     // create current alerts where 1 is stale but in maintence mode
     AlertCurrentEntity current1 = createNiceMock(AlertCurrentEntity.class);
     AlertHistoryEntity history1 = createNiceMock(AlertHistoryEntity.class);
@@ -250,10 +275,10 @@ public class StaleAlertRunnableTest {
     AlertHistoryEntity history2 = createNiceMock(AlertHistoryEntity.class);
 
     expect(current1.getAlertHistory()).andReturn(history1).atLeastOnce();
-    expect(history1.getAlertDefinition()).andReturn(m_definition).atLeastOnce();
+    expect(history1.getAlertDefinition()).andReturn(definition1).atLeastOnce();
 
     expect(current2.getAlertHistory()).andReturn(history2).atLeastOnce();
-    expect(history2.getAlertDefinition()).andReturn(m_definition).atLeastOnce();
+    expect(history2.getAlertDefinition()).andReturn(definition1).atLeastOnce();
 
     // maintenance mode with a really old timestamp
     expect(current1.getMaintenanceState()).andReturn(MaintenanceState.ON).atLeastOnce();
@@ -292,7 +317,7 @@ public class StaleAlertRunnableTest {
     assertEquals(AlertState.OK, alert.getState());
     assertEquals(DEFINITION_NAME, alert.getName());
 
-    verify(m_definition, m_cluster, m_clusters, m_definitionDao);
+    verify(m_cluster, m_clusters, m_definitionDao);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
index 32d6d1e..714b6b7 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
@@ -18,14 +18,30 @@
 
 package org.apache.ambari.server.upgrade;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Binder;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.google.inject.Module;
-import com.google.inject.Provider;
-import com.google.inject.persist.PersistService;
-import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import static junit.framework.Assert.assertEquals;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.orm.DBAccessor;
@@ -34,42 +50,20 @@ import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
-import org.apache.ambari.server.state.OperatingSystemInfo;
-import org.apache.ambari.server.state.RepositoryInfo;
 import org.apache.ambari.server.state.Service;
-import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.stack.OsFamily;
 import org.easymock.Capture;
-import org.easymock.EasyMockSupport;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-import javax.persistence.EntityManager;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import static org.easymock.EasyMock.capture;
-
-import static junit.framework.Assert.assertEquals;
-import static org.easymock.EasyMock.createMockBuilder;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.createStrictMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.easymock.EasyMock.verify;
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.persist.PersistService;
 
 /**
  * {@link org.apache.ambari.server.upgrade.UpgradeCatalog210} unit tests.
@@ -136,13 +130,16 @@ public class UpgradeCatalog210Test {
   public void testExecuteDMLUpdates() throws Exception {
     Method addNewConfigurationsFromXml =
       AbstractUpgradeCatalog.class.getDeclaredMethod("addNewConfigurationsFromXml");
+
     Method initializeClusterAndServiceWidgets =
       UpgradeCatalog210.class.getDeclaredMethod("initializeClusterAndServiceWidgets");
 
+    Method executeStackDMLUpdates = UpgradeCatalog210.class.getDeclaredMethod("executeStackDMLUpdates");
+
     UpgradeCatalog210 upgradeCatalog210 = createMockBuilder(UpgradeCatalog210.class)
       .addMockedMethod(addNewConfigurationsFromXml)
       .addMockedMethod(initializeClusterAndServiceWidgets)
-      .createMock();
+      .addMockedMethod( executeStackDMLUpdates) .createMock();
 
     upgradeCatalog210.addNewConfigurationsFromXml();
     expectLastCall().once();
@@ -150,6 +147,9 @@ public class UpgradeCatalog210Test {
     upgradeCatalog210.initializeClusterAndServiceWidgets();
     expectLastCall().once();
 
+    upgradeCatalog210.executeStackDMLUpdates();
+    expectLastCall().once();
+
     replay(upgradeCatalog210);
 
     upgradeCatalog210.executeDMLUpdates();

http://git-wip-us.apache.org/repos/asf/ambari/blob/bdf5effb/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
index c1090c8..7455706 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
@@ -61,7 +61,6 @@ import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.utils.VersionUtils;
 import org.apache.ambari.server.view.ViewRegistry;
 import org.easymock.EasyMock;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -74,7 +73,6 @@ import com.google.inject.Key;
 import com.google.inject.TypeLiteral;
 import com.google.inject.persist.PersistService;
 
-@Ignore
 @RunWith(Parameterized.class)
 public class UpgradeTest {
   private static final Logger LOG = LoggerFactory.getLogger(UpgradeTest.class);