You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2015/10/21 05:42:40 UTC

[2/2] ambari git commit: AMBARI-13441. If Ambari Server is not part of the cluster, basic operations throw 500 (NPE) when Kerberos is enabled (even if it is Manual Kerberos) (rlevas)

AMBARI-13441. If Ambari Server is not part of the cluster, basic operations throw 500 (NPE) when Kerberos is enabled (even if it is Manual Kerberos) (rlevas)


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

Branch: refs/heads/branch-2.1
Commit: 24ce16b5a3ced0944caa516fe07fc446435ce036
Parents: d2dc263
Author: Robert Levas <rl...@hortonworks.com>
Authored: Tue Oct 20 20:42:25 2015 -0700
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Tue Oct 20 20:42:25 2015 -0700

----------------------------------------------------------------------
 .../actionmanager/ActionDBAccessorImpl.java     |  57 ++--
 .../server/actionmanager/ActionScheduler.java   |  65 +++-
 .../server/actionmanager/HostRoleCommand.java   |   6 +-
 .../ambari/server/actionmanager/Stage.java      | 200 +++++++-----
 .../server/controller/KerberosHelperImpl.java   |   2 +-
 .../internal/UpgradeResourceProvider.java       |  24 +-
 .../server/orm/dao/HostRoleCommandDAO.java      |  23 +-
 .../orm/entities/HostRoleCommandEntity.java     |   4 +-
 .../serveraction/ServerActionExecutor.java      |   2 +-
 .../server/upgrade/UpgradeCatalog213.java       |   7 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   2 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   2 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   2 +-
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |   2 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |   2 +-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   2 +-
 .../ambari/server/actionmanager/StageTest.java  |   4 +-
 .../actionmanager/TestActionDBAccessorImpl.java |  36 +--
 .../actionmanager/TestActionScheduler.java      | 309 +++++++------------
 .../AmbariManagementControllerTest.java         |  10 +-
 .../internal/UpgradeResourceProviderTest.java   |  18 +-
 .../serveraction/ServerActionExecutorTest.java  |   8 +-
 .../server/stageplanner/TestStagePlanner.java   |   4 +-
 .../server/upgrade/UpgradeCatalog213Test.java   |  19 ++
 24 files changed, 424 insertions(+), 386 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
index 30da833..21d9f2b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
@@ -54,6 +54,7 @@ import org.apache.ambari.server.utils.LoopBody;
 import org.apache.ambari.server.utils.Parallel;
 import org.apache.ambari.server.utils.ParallelLoopResult;
 import org.apache.ambari.server.utils.StageUtils;
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -297,35 +298,45 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
         HostRoleCommandEntity hostRoleCommandEntity = hostRoleCommand.constructNewPersistenceEntity();
         hostRoleCommandEntity.setStage(stageEntity);
 
-        HostEntity hostEntity = hostDAO.findById(hostRoleCommandEntity.getHostId());
-        if (hostEntity == null) {
-          String msg = String.format("Host %s doesn't exist in database", hostRoleCommandEntity.getHostName());
-          LOG.error(msg);
-          throw new AmbariException(msg);
-        }
-        hostRoleCommandEntity.setHostEntity(hostEntity);
+        HostEntity hostEntity = null;
+
         hostRoleCommandDAO.create(hostRoleCommandEntity);
 
-        assert hostRoleCommandEntity.getTaskId() != null;
         hostRoleCommand.setTaskId(hostRoleCommandEntity.getTaskId());
 
-        try {
-          // Get the in-memory host object and its prefix to construct the output and error log paths.
-          Host hostObject = clusters.getHost(hostRoleCommandEntity.getHostName());
-          String prefix = hostObject.getPrefix();
-          if (null != prefix && !prefix.isEmpty()) {
-            if (!prefix.endsWith("/")) {
-              prefix = prefix + "/";
+        String prefix = "";
+        String output = "output-" + hostRoleCommandEntity.getTaskId() + ".txt";
+        String error = "errors-" + hostRoleCommandEntity.getTaskId() + ".txt";
+
+        if (null != hostRoleCommandEntity.getHostId()) {
+          hostEntity = hostDAO.findById(hostRoleCommandEntity.getHostId());
+          if (hostEntity == null) {
+            String msg = String.format("Host %s doesn't exist in database", hostRoleCommandEntity.getHostName());
+            LOG.error(msg);
+            throw new AmbariException(msg);
+          }
+          hostRoleCommandEntity.setHostEntity(hostEntity);
+
+          try {
+            // Get the in-memory host object and its prefix to construct the output and error log paths.
+            Host hostObject = clusters.getHost(hostEntity.getHostName());
+
+            if (!StringUtils.isBlank(hostObject.getPrefix())) {
+              prefix = hostObject.getPrefix();
+              if (!prefix.endsWith("/")) {
+                prefix = prefix + "/";
+              }
             }
-            hostRoleCommand.setOutputLog(prefix + "output-" + hostRoleCommandEntity.getTaskId() + ".txt");
-            hostRoleCommand.setErrorLog(prefix + "errors-" + hostRoleCommandEntity.getTaskId() + ".txt");
-            hostRoleCommandEntity.setOutputLog(hostRoleCommand.getOutputLog());
-            hostRoleCommandEntity.setErrorLog(hostRoleCommand.getErrorLog());
+          } catch (AmbariException e) {
+            LOG.warn("Exception in getting prefix for host and setting output and error log files.  Using no prefix");
           }
-        } catch (AmbariException e) {
-          LOG.warn("Exception in getting prefix for host and setting output and error log files.");
         }
 
+        hostRoleCommand.setOutputLog(prefix + output);
+        hostRoleCommand.setErrorLog(prefix + error);
+        hostRoleCommandEntity.setOutputLog(hostRoleCommand.getOutputLog());
+        hostRoleCommandEntity.setErrorLog(hostRoleCommand.getErrorLog());
+
         ExecutionCommandEntity executionCommandEntity = hostRoleCommand.constructExecutionCommandEntity();
         executionCommandEntity.setHostRoleCommand(hostRoleCommandEntity);
 
@@ -334,7 +345,9 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
 
         executionCommandDAO.create(hostRoleCommandEntity.getExecutionCommand());
         hostRoleCommandDAO.merge(hostRoleCommandEntity);
-        hostDAO.merge(hostEntity);
+        if (null != hostEntity) {
+          hostDAO.merge(hostEntity);
+        }
       }
 
       for (RoleSuccessCriteriaEntity roleSuccessCriteriaEntity : stageEntity.getRoleSuccessCriterias()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionScheduler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionScheduler.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionScheduler.java
index 1e019b7..7b5adca 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionScheduler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionScheduler.java
@@ -89,7 +89,7 @@ class ActionScheduler implements Runnable {
   private final ActionDBAccessor db;
   private final short maxAttempts;
   private final ActionQueue actionQueue;
-  private final Clusters fsmObject;
+  private final Clusters clusters;
   private final AmbariEventPublisher ambariEventPublisher;
   private boolean taskTimeoutAdjustment = true;
   private final HostsMap hostsMap;
@@ -126,7 +126,7 @@ class ActionScheduler implements Runnable {
   private Cache<String, Map<String, String>> hostParamsStageCache;
 
   public ActionScheduler(long sleepTimeMilliSec, long actionTimeoutMilliSec,
-                         ActionDBAccessor db, ActionQueue actionQueue, Clusters fsmObject,
+                         ActionDBAccessor db, ActionQueue actionQueue, Clusters clusters,
                          int maxAttempts, HostsMap hostsMap,
                          UnitOfWork unitOfWork, AmbariEventPublisher ambariEventPublisher,
                          Configuration configuration) {
@@ -135,7 +135,7 @@ class ActionScheduler implements Runnable {
     actionTimeout = actionTimeoutMilliSec;
     this.db = db;
     this.actionQueue = actionQueue;
-    this.fsmObject = fsmObject;
+    this.clusters = clusters;
     this.ambariEventPublisher = ambariEventPublisher;
     this.maxAttempts = (short) maxAttempts;
     serverActionExecutor = new ServerActionExecutor(db, sleepTimeMilliSec);
@@ -343,7 +343,7 @@ class ActionScheduler implements Runnable {
         Map<ExecutionCommand, String> commandsToAbort = new HashMap<ExecutionCommand, String>();
         if (!eventMap.isEmpty()) {
           LOG.debug("==> processing {} serviceComponentHostEvents...", eventMap.size());
-          Cluster cluster = fsmObject.getCluster(stage.getClusterName());
+          Cluster cluster = clusters.getCluster(stage.getClusterName());
           if (cluster != null) {
             Map<ServiceComponentHostEvent, String> failedEvents = cluster.processServiceComponentHostEvents(eventMap);
 
@@ -523,14 +523,22 @@ class ActionScheduler implements Runnable {
 
     Cluster cluster = null;
     if (null != s.getClusterName()) {
-      cluster = fsmObject.getCluster(s.getClusterName());
+      cluster = clusters.getCluster(s.getClusterName());
     }
 
     for (String host : s.getHosts()) {
+
       List<ExecutionCommandWrapper> commandWrappers = s.getExecutionCommands(host);
-      Host hostObj = fsmObject.getHost(host);
+      Host hostObj = null;
+      try {
+        hostObj = clusters.getHost(host);
+      } catch (AmbariException e) {
+        LOG.debug("Host {} not found, stage is likely a server side action", host);
+      }
+
       int i_my = 0;
       LOG.trace("===>host=" + host);
+
       for(ExecutionCommandWrapper wrapper : commandWrappers) {
         ExecutionCommand c = wrapper.getExecutionCommand();
         String roleStr = c.getRole();
@@ -682,7 +690,7 @@ class ActionScheduler implements Runnable {
                                        boolean ignoreTransitionException) {
 
     try {
-      Cluster cluster = fsmObject.getCluster(clusterName);
+      Cluster cluster = clusters.getCluster(clusterName);
 
       ServiceComponentHostOpFailedEvent failedEvent =
         new ServiceComponentHostOpFailedEvent(componentName,
@@ -748,6 +756,17 @@ class ActionScheduler implements Runnable {
     return roleStats;
   }
 
+  /**
+   * Checks if timeout is required.
+   * @param status      the status of the current role
+   * @param stage       the stage
+   * @param host        the host object; can be {@code null} for server-side tasks
+   * @param role        the role
+   * @param currentTime the current
+   * @param taskTimeout the amount of time to determine timeout
+   * @return {@code true} if timeout is needed
+   * @throws AmbariException
+   */
   private boolean timeOutActionNeeded(HostRoleStatus status, Stage stage,
       Host host, String role, long currentTime, long taskTimeout) throws
     AmbariException {
@@ -755,29 +774,47 @@ class ActionScheduler implements Runnable {
         ( ! status.equals(HostRoleStatus.IN_PROGRESS) )) {
       return false;
     }
+
     // Fast fail task if host state is unknown
-    if (host.getState().equals(HostState.HEARTBEAT_LOST)) {
+    if (null != host && host.getState().equals(HostState.HEARTBEAT_LOST)) {
       LOG.debug("Timing out action since agent is not heartbeating.");
       return true;
     }
+
+    // tasks are held in a variety of in-memory maps that require a hostname key
+    // host being null is ok - that means it's a server-side task
+    String hostName = (null == host) ? null : host.getHostName();
+
     // If we have other command in progress for this stage do not timeout this one
-    if (hasCommandInProgress(stage, host.getHostName())
+    if (hasCommandInProgress(stage, hostName)
             && !status.equals(HostRoleStatus.IN_PROGRESS)) {
       return false;
     }
-    if (currentTime > stage.getLastAttemptTime(host.getHostName(), role)
+    if (currentTime > stage.getLastAttemptTime(hostName, role)
         + taskTimeout) {
       return true;
     }
     return false;
   }
 
-  private boolean hasCommandInProgress(Stage stage, String host) {
-    List<ExecutionCommandWrapper> commandWrappers = stage.getExecutionCommands(host);
+  /**
+   * Determines if at least one task for a given hostname in the specified stage is in progress.
+   * <p/>
+   * If the specified hostname is <code>null</code>, the Ambari Server host is assumed.
+   * See {@link Stage#getSafeHost(String)}.
+   *
+   * @param stage    a stage
+   * @param hostname a host name, if null the Ambari Server host is assumed
+   * @return true if at least one task for the given hostname in the specified stage is in progress; otherwize false
+   * @see Stage#getExecutionCommands(String)
+   * @see Stage#getHostRoleStatus(String, String)
+   */
+  private boolean hasCommandInProgress(Stage stage, String hostname) {
+    List<ExecutionCommandWrapper> commandWrappers = stage.getExecutionCommands(hostname);
     for (ExecutionCommandWrapper wrapper : commandWrappers) {
       ExecutionCommand c = wrapper.getExecutionCommand();
       String roleStr = c.getRole();
-      HostRoleStatus status = stage.getHostRoleStatus(host, roleStr);
+      HostRoleStatus status = stage.getHostRoleStatus(hostname, roleStr);
       if (status == HostRoleStatus.IN_PROGRESS) {
         return true;
       }
@@ -944,7 +981,7 @@ class ActionScheduler implements Runnable {
       // "Distribute repositories/install packages" action has been issued
       // against a concrete host without binding to a cluster)
       Long clusterId = clusterName != null ?
-              fsmObject.getCluster(clusterName).getClusterId() : null;
+              clusters.getCluster(clusterName).getClusterId() : null;
       ActionFinalReportReceivedEvent event = new ActionFinalReportReceivedEvent(
               clusterId, hostname, null,
               role);

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java
index fec76ab..9585dc4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java
@@ -141,7 +141,11 @@ public class HostRoleCommand {
     taskId = hostRoleCommandEntity.getTaskId();
     stageId = hostRoleCommandEntity.getStage().getStageId();
     requestId = hostRoleCommandEntity.getStage().getRequestId();
-    hostId = hostRoleCommandEntity.getHostId();
+
+    if (null != hostRoleCommandEntity.getHostId()) {
+      hostId = hostRoleCommandEntity.getHostId();
+    }
+
     hostName = hostRoleCommandEntity.getHostName();
     role = hostRoleCommandEntity.getRole();
     status = hostRoleCommandEntity.getStatus();

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
index 22b2ca4..8b2703c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
@@ -57,6 +57,14 @@ import com.google.inject.persist.Transactional;
 //required to persist an action.
 public class Stage {
 
+  /**
+   * Used because in-memory storage of commands requires a hostname for maps
+   * when the underlying store does not (host_id is {@code null}).  We also
+   * don't want stages getting confused with Ambari vs cluster hosts, so
+   * don't use {@link StageUtils#getHostName()}
+   */
+  private static final String INTERNAL_HOSTNAME = "_internal_ambari";
+
   private static Logger LOG = LoggerFactory.getLogger(Stage.class);
   private final long requestId;
   private String clusterName;
@@ -86,12 +94,6 @@ public class Stage {
   @Inject
   private HostRoleCommandFactory hostRoleCommandFactory;
 
-  @Inject
-  private HostRoleCommandDAO hostRoleCommandDAO;
-
-  @Inject
-  private ActionDBAccessor dbAccessor;
-
   @AssistedInject
   public Stage(@Assisted long requestId,
       @Assisted("logDir") String logDir,
@@ -119,8 +121,6 @@ public class Stage {
   public Stage(@Assisted StageEntity stageEntity, HostRoleCommandDAO hostRoleCommandDAO,
                ActionDBAccessor dbAccessor, Clusters clusters, HostRoleCommandFactory hostRoleCommandFactory) {
     this.hostRoleCommandFactory = hostRoleCommandFactory;
-    this.hostRoleCommandDAO = hostRoleCommandDAO;
-    this.dbAccessor = dbAccessor;
 
     requestId = stageEntity.getRequestId();
     stageId = stageEntity.getStageId();
@@ -146,7 +146,11 @@ public class Stage {
     Collection<HostRoleCommand> commands = dbAccessor.getTasks(taskIds);
 
     for (HostRoleCommand command : commands) {
-      String hostname = command.getHostName();
+      // !!! some commands won't have a hostname, because they are server-side and
+      // don't hold that information.  In that case, use the special key to
+      // use in the map
+      String hostname = getSafeHost(command.getHostName());
+
       if (!hostRoleCommands.containsKey(hostname)) {
         hostRoleCommands.put(hostname, new LinkedHashMap<String, HostRoleCommand>());
       }
@@ -358,39 +362,6 @@ public class Stage {
   }
 
   /**
-   * Creates server-side execution command.
-   * <p/>
-   * The action name for this command is expected to be the classname of a
-   * {@link org.apache.ambari.server.serveraction.ServerAction} implementation which will be
-   * instantiated and invoked as needed.
-   *
-   * @param actionName    a String declaring the action name (in the form of a classname) to execute
-   * @param role          the Role for this command
-   * @param command       the RoleCommand for this command
-   * @param clusterName   a String identifying the cluster on which to to execute this command
-   * @param event         a ServiceComponentHostServerActionEvent
-   * @param commandParams a Map of String to String data used to pass to the action - this may be
-   *                      empty or null if no data is relevant
-   * @param commandDetail a String declaring a descriptive name to pass to the action - null or an
-   *                      empty string indicates no value is to be set
-   * @param configTags    a Map of configuration tags to set for this command - if null, no
-   *                      configurations will be available for the command
-   * @param timeout       an Integer declaring the timeout for this action - if null, a default
-   * @param retryAllowed   indicates whether retry after failure is allowed
-   */
-  public synchronized void addServerActionCommand(String actionName, Role role, RoleCommand command,
-      String clusterName, ServiceComponentHostServerActionEvent event,
-      @Nullable Map<String, String> commandParams, @Nullable String commandDetail,
-      @Nullable Map<String, Map<String, String>> configTags, @Nullable Integer timeout,
-      boolean retryAllowed, boolean autoSkipFailure) {
-    addServerActionCommand(actionName, null, role, command, clusterName, StageUtils.getHostName(),
-        event, commandParams, commandDetail, configTags, timeout, retryAllowed, autoSkipFailure);
-  }
-
-  /**
-   * THIS METHOD IS TO WORKAROUND A BUG! The assumption of the framework is that
-   * the Ambari Server is installed on a host WITHIN the cluster, which is not
-   * always true. This method adds a host parameter.
    * <p/>
    * Creates server-side execution command.
    * <p/>
@@ -411,8 +382,6 @@ public class Stage {
    * @param clusterName
    *          a String identifying the cluster on which to to execute this
    *          command
-   * @param hostName
-   *          the name of the host
    * @param event
    *          a ServiceComponentHostServerActionEvent
    * @param commandParams
@@ -431,13 +400,13 @@ public class Stage {
    *          indicates whether retry after failure is allowed
    */
   public synchronized void addServerActionCommand(String actionName, @Nullable String userName,
-      Role role, RoleCommand command, String clusterName, String hostName,
+      Role role, RoleCommand command, String clusterName,
       ServiceComponentHostServerActionEvent event, @Nullable Map<String, String> commandParams,
       @Nullable String commandDetail, @Nullable Map<String, Map<String, String>> configTags,
       @Nullable Integer timeout, boolean retryAllowed, boolean autoSkipFailure) {
 
-    ExecutionCommandWrapper commandWrapper = addGenericExecutionCommand(clusterName, hostName, role,
-        command, event, retryAllowed, autoSkipFailure);
+    ExecutionCommandWrapper commandWrapper = addGenericExecutionCommand(clusterName,
+        INTERNAL_HOSTNAME, role, command, event, retryAllowed, autoSkipFailure);
 
     ExecutionCommand cmd = commandWrapper.getExecutionCommand();
 
@@ -469,7 +438,7 @@ public class Stage {
     cmd.setRoleParams(roleParams);
 
     if(commandDetail != null) {
-      HostRoleCommand hostRoleCommand = getHostRoleCommand(hostName, role.toString());
+      HostRoleCommand hostRoleCommand = getHostRoleCommand(INTERNAL_HOSTNAME, role.toString());
       if (hostRoleCommand != null) {
         hostRoleCommand.setCommandDetail(commandDetail);
         hostRoleCommand.setCustomCommandName(actionName);
@@ -546,25 +515,49 @@ public class Stage {
     return requestContext;
   }
 
-  public long getLastAttemptTime(String host, String role) {
-    return hostRoleCommands.get(host).get(role).getLastAttemptTime();
+  /**
+   * @param hostname  the hostname; {@code null} for a server-side stage
+   * @param role      the role
+   * @return the last attempt time
+   */
+  public long getLastAttemptTime(String hostname, String role) {
+    return hostRoleCommands.get(getSafeHost(hostname)).get(role).getLastAttemptTime();
   }
 
-  public short getAttemptCount(String host, String role) {
-    return hostRoleCommands.get(host).get(role).getAttemptCount();
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @return the number of attempts
+   */
+  public short getAttemptCount(String hostname, String role) {
+    return hostRoleCommands.get(getSafeHost(hostname)).get(role).getAttemptCount();
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   */
   public void incrementAttemptCount(String hostname, String role) {
-    hostRoleCommands.get(hostname).get(role).incrementAttemptCount();
+    hostRoleCommands.get(getSafeHost(hostname)).get(role).incrementAttemptCount();
   }
 
-  public void setLastAttemptTime(String host, String role, long t) {
-    hostRoleCommands.get(host).get(role).setLastAttemptTime(t);
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @param t           the last time the role was attempted
+   */
+  public void setLastAttemptTime(String hostname, String role, long t) {
+    hostRoleCommands.get(getSafeHost(hostname)).get(role).setLastAttemptTime(t);
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @return            the wrapper
+   */
   public ExecutionCommandWrapper getExecutionCommandWrapper(String hostname,
       String role) {
-    HostRoleCommand hrc = hostRoleCommands.get(hostname).get(role);
+    HostRoleCommand hrc = hostRoleCommands.get(getSafeHost(hostname)).get(role);
     if (hrc != null) {
       return hrc.getExecutionCommandWrapper();
     } else {
@@ -572,47 +565,95 @@ public class Stage {
     }
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @return  the list of commands for the host
+   */
   public List<ExecutionCommandWrapper> getExecutionCommands(String hostname) {
     checkWrappersLoaded();
-    return commandsToSend.get(hostname);
+    return commandsToSend.get(getSafeHost(hostname));
   }
 
+/**
+ * @param hostname    the hostname; {@code null} for a server-side stage
+ * @param role        the role
+ * @return the start time for the task
+ */
   public long getStartTime(String hostname, String role) {
-    return hostRoleCommands.get(hostname).get(role).getStartTime();
+    return hostRoleCommands.get(getSafeHost(hostname)).get(role).getStartTime();
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @param startTime   the start time
+   */
   public void setStartTime(String hostname, String role, long startTime) {
-    hostRoleCommands.get(hostname).get(role).setStartTime(startTime);
+    hostRoleCommands.get(getSafeHost(hostname)).get(role).setStartTime(startTime);
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @return the status
+   */
   public HostRoleStatus getHostRoleStatus(String hostname, String role) {
-    return hostRoleCommands.get(hostname).get(role).getStatus();
+    return hostRoleCommands.get(getSafeHost(hostname)).get(role).getStatus();
   }
 
-  public void setHostRoleStatus(String host, String role,
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @param status      the status
+   */
+  public void setHostRoleStatus(String hostname, String role,
       HostRoleStatus status) {
-    hostRoleCommands.get(host).get(role).setStatus(status);
+    hostRoleCommands.get(getSafeHost(hostname)).get(role).setStatus(status);
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param roleStr     the role name
+   * @return the wrapper event
+   */
   public ServiceComponentHostEventWrapper getFsmEvent(String hostname, String roleStr) {
-    return hostRoleCommands.get(hostname).get(roleStr).getEvent();
+    return hostRoleCommands.get(getSafeHost(hostname)).get(roleStr).getEvent();
   }
 
-
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @param exitCode    the exit code
+   */
   public void setExitCode(String hostname, String role, int exitCode) {
-    hostRoleCommands.get(hostname).get(role).setExitCode(exitCode);
+    hostRoleCommands.get(getSafeHost(hostname)).get(role).setExitCode(exitCode);
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @return the exit code
+   */
   public int getExitCode(String hostname, String role) {
-    return hostRoleCommands.get(hostname).get(role).getExitCode();
+    return hostRoleCommands.get(getSafeHost(hostname)).get(role).getExitCode();
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @param stdErr      the standard error string
+   */
   public void setStderr(String hostname, String role, String stdErr) {
-    hostRoleCommands.get(hostname).get(role).setStderr(stdErr);
+    hostRoleCommands.get(getSafeHost(hostname)).get(role).setStderr(stdErr);
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @param stdOut      the standard output string
+   */
   public void setStdout(String hostname, String role, String stdOut) {
-    hostRoleCommands.get(hostname).get(role).setStdout(stdOut);
+    hostRoleCommands.get(getSafeHost(hostname)).get(role).setStdout(stdOut);
   }
 
   public synchronized boolean isStageInProgress() {
@@ -667,10 +708,16 @@ public class Stage {
    * This method should be used only in stage planner. To add
    * a new execution command use
    * {@link #addHostRoleExecutionCommand(String, org.apache.ambari.server.Role, org.apache.ambari.server.RoleCommand, org.apache.ambari.server.state.ServiceComponentHostEvent, String, String, boolean)}
+   * @param origStage the stage
+   * @param hostname  the hostname; {@code null} for a server-side stage
+   * @param r         the role
    */
   public synchronized void addExecutionCommandWrapper(Stage origStage,
       String hostname, Role r) {
     //used on stage creation only, no need to check if wrappers loaded
+
+    hostname = getSafeHost(hostname);
+
     String role = r.toString();
     if (commandsToSend.get(hostname) == null) {
       commandsToSend.put(hostname, new ArrayList<ExecutionCommandWrapper>());
@@ -685,8 +732,13 @@ public class Stage {
         origStage.getHostRoleCommand(hostname, role));
   }
 
+  /**
+   * @param hostname    the hostname; {@code null} for a server-side stage
+   * @param role        the role
+   * @return the role command
+   */
   public HostRoleCommand getHostRoleCommand(String hostname, String role) {
-    return hostRoleCommands.get(hostname).get(role);
+    return hostRoleCommands.get(getSafeHost(hostname)).get(role);
   }
 
   /**
@@ -773,4 +825,14 @@ public class Stage {
     builder.append("STAGE DESCRIPTION END\n");
     return builder.toString();
   }
+
+  /**
+   * Helper to make sure the hostname is non-null for internal command map.
+   * @param hostname  the hostname for the map key
+   * @return the hostname when not {@code null}, otherwise {@link #INTERNAL_HOSTNAME}
+   */
+  private static String getSafeHost(String hostname) {
+    return (null == hostname) ? INTERNAL_HOSTNAME : hostname;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
index 20b4658..f35305e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
@@ -1655,7 +1655,7 @@ public class KerberosHelperImpl implements KerberosHelper {
                                         Integer timeout) throws AmbariException {
 
     Stage stage = createNewStage(id, cluster, requestId, requestContext, clusterHostInfo, commandParams, hostParams);
-    stage.addServerActionCommand(actionClass.getName(), Role.AMBARI_SERVER_ACTION,
+    stage.addServerActionCommand(actionClass.getName(), null, Role.AMBARI_SERVER_ACTION,
         RoleCommand.EXECUTE, cluster.getClusterName(), event, commandParameters, commandDetail,
         ambariManagementController.findConfigurationTagsWithOverrides(cluster, null), timeout,
         false, false);

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
index d1b5102..ecf22c2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
@@ -23,7 +23,6 @@ import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.VERSION;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
@@ -72,7 +71,6 @@ import org.apache.ambari.server.orm.dao.HostRoleCommandStatusSummaryDTO;
 import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
 import org.apache.ambari.server.orm.dao.RequestDAO;
 import org.apache.ambari.server.orm.dao.UpgradeDAO;
-import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.RequestEntity;
 import org.apache.ambari.server.orm.entities.StackEntity;
@@ -1309,21 +1307,6 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     String itemDetail = entity.getText();
     String stageText = StringUtils.abbreviate(entity.getText(), 255);
 
-    String hostName = null;
-    Collection<Long> hostIds = cluster.getAllHostsDesiredConfigs().keySet();
-    if (!hostIds.isEmpty()) {
-      Long hostId = hostIds.iterator().next();
-      HostEntity hostEntity = s_hostDAO.findById(hostId);
-      if (hostEntity != null) {
-        hostName = hostEntity.getHostName();
-      }
-    }
-
-    if (StringUtils.isBlank(hostName)) {
-      throw new AmbariException(
-          "Could not retrieve an arbitrary host name to use for the server-side command.");
-    }
-
     switch (task.getType()) {
       case MANUAL: {
         ManualTask mt = (ManualTask) task;
@@ -1395,9 +1378,10 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     stage.setStageId(stageId);
     entity.setStageId(Long.valueOf(stageId));
 
-    stage.addServerActionCommand(task.getImplementationClass(), null, Role.AMBARI_SERVER_ACTION,
-        RoleCommand.EXECUTE, cluster.getClusterName(), hostName,
-        new ServiceComponentHostServerActionEvent(hostName, System.currentTimeMillis()), commandParams,
+    stage.addServerActionCommand(task.getImplementationClass(),
+        getManagementController().getAuthName(), Role.AMBARI_SERVER_ACTION, RoleCommand.EXECUTE,
+        cluster.getClusterName(),
+        new ServiceComponentHostServerActionEvent(null, System.currentTimeMillis()), commandParams,
         itemDetail, null, Integer.valueOf(1200), allowRetry,
         context.isComponentFailureAutoSkipped());
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
index f04c868..da4afbf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
@@ -32,7 +32,6 @@ import java.util.Map;
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
 
-import org.apache.ambari.server.actionmanager.HostRoleCommand;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.HostEntity;
@@ -241,13 +240,21 @@ public class HostRoleCommandDAO {
 
   @RequiresSession
   public List<HostRoleCommandEntity> findByHostRole(String hostName, long requestId, long stageId, String role) {
-    TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery("SELECT command " +
-        "FROM HostRoleCommandEntity command " +
-        "WHERE command.hostEntity.hostName=?1 AND command.requestId=?2 " +
-        "AND command.stageId=?3 AND command.role=?4 " +
-        "ORDER BY command.taskId", HostRoleCommandEntity.class);
-
-    return daoUtils.selectList(query, hostName, requestId, stageId, role);
+    if (null == hostName) {
+      TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery("SELECT command " +
+          "FROM HostRoleCommandEntity command " +
+          "WHERE command.hostEntity IS NULL AND command.requestId=?1 " +
+          "AND command.stageId=?2 AND command.role=?3 " +
+          "ORDER BY command.taskId", HostRoleCommandEntity.class);
+      return daoUtils.selectList(query, requestId, stageId, role);
+    } else {
+      TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery("SELECT command " +
+          "FROM HostRoleCommandEntity command " +
+          "WHERE command.hostEntity.hostName=?1 AND command.requestId=?2 " +
+          "AND command.stageId=?3 AND command.role=?4 " +
+          "ORDER BY command.taskId", HostRoleCommandEntity.class);
+      return daoUtils.selectList(query, hostName, requestId, stageId, role);
+    }
   }
 
   @RequiresSession

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java
index c005efc..763111b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java
@@ -77,7 +77,7 @@ public class HostRoleCommandEntity {
   @Basic
   private Long stageId;
 
-  @Column(name = "host_id", insertable = false, updatable = false, nullable = false)
+  @Column(name = "host_id", insertable = false, updatable = false, nullable = true)
   @Basic
   private Long hostId;
 
@@ -170,7 +170,7 @@ public class HostRoleCommandEntity {
   private StageEntity stage;
 
   @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH})
-  @JoinColumn(name = "host_id", referencedColumnName = "host_id", nullable = false)
+  @JoinColumn(name = "host_id", referencedColumnName = "host_id", nullable = true)
   private HostEntity hostEntity;
 
   @OneToOne(mappedBy = "hostRoleCommandEntity", cascade = CascadeType.REMOVE)

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/serveraction/ServerActionExecutor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/ServerActionExecutor.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/ServerActionExecutor.java
index 670e925..4c241d1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/ServerActionExecutor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/ServerActionExecutor.java
@@ -329,7 +329,7 @@ public class ServerActionExecutor {
       commandReport = createErrorReport("Unknown error condition");
     }
 
-    db.updateHostRoleState(executionCommand.getHostname(), hostRoleCommand.getRequestId(),
+    db.updateHostRoleState(null, hostRoleCommand.getRequestId(),
         hostRoleCommand.getStageId(), executionCommand.getRole(), commandReport);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java
index 3695faa..be43e71 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog213.java
@@ -106,6 +106,9 @@ public class UpgradeCatalog213 extends AbstractUpgradeCatalog {
   public static final String UPGRADE_TYPE_COL = "upgrade_type";
   public static final String REPO_VERSION_TABLE = "repo_version";
 
+  private static final String HOST_ROLE_COMMAND_TABLE = "host_role_command";
+  private static final String HOST_ID_COL = "host_id";
+
   private static final String KERBEROS_DESCRIPTOR_TABLE = "kerberos_descriptor";
   private static final String KERBEROS_DESCRIPTOR_NAME_COLUMN = "kerberos_descriptor_name";
   private static final String KERBEROS_DESCRIPTOR_COLUMN = "kerberos_descriptor";
@@ -163,6 +166,10 @@ public class UpgradeCatalog213 extends AbstractUpgradeCatalog {
   @Override
   protected void executeDDLUpdates() throws AmbariException, SQLException {
     executeUpgradeDDLUpdates();
+
+    // Alter the host_role_command table to allow host_id to be nullable
+    dbAccessor.alterColumn(HOST_ROLE_COMMAND_TABLE, new DBColumnInfo(HOST_ID_COL, Long.class, null, null, true));
+
     addKerberosDescriptorTable();
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 4ffe8da..9330310 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -226,7 +226,7 @@ CREATE TABLE host_role_command (
   retry_allowed SMALLINT DEFAULT 0 NOT NULL,
   event LONGTEXT NOT NULL,
   exitcode INTEGER NOT NULL,
-  host_id BIGINT NOT NULL,
+  host_id BIGINT,
   last_attempt_time BIGINT NOT NULL,
   request_id BIGINT NOT NULL,
   role VARCHAR(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 8fb6e68..8b36f9e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -216,7 +216,7 @@ CREATE TABLE host_role_command (
   retry_allowed NUMBER(1) DEFAULT 0 NOT NULL,
   event CLOB NULL,
   exitcode NUMBER(10) NOT NULL,
-  host_id NUMBER(19) NOT NULL,
+  host_id NUMBER(19),
   last_attempt_time NUMBER(19) NOT NULL,
   request_id NUMBER(19) NOT NULL,
   role VARCHAR2(255) NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index fb98757..764396e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -228,7 +228,7 @@ CREATE TABLE host_role_command (
   retry_allowed SMALLINT DEFAULT 0 NOT NULL,
   event VARCHAR(32000) NOT NULL,
   exitcode INTEGER NOT NULL,
-  host_id BIGINT NOT NULL,
+  host_id BIGINT,
   last_attempt_time BIGINT NOT NULL,
   request_id BIGINT NOT NULL,
   role VARCHAR(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index 098444b..dbca53e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -259,7 +259,7 @@ CREATE TABLE ambari.host_role_command (
   retry_allowed SMALLINT DEFAULT 0 NOT NULL,
   event VARCHAR(32000) NOT NULL,
   exitcode INTEGER NOT NULL,
-  host_id BIGINT NOT NULL,
+  host_id BIGINT,
   last_attempt_time BIGINT NOT NULL,
   request_id BIGINT NOT NULL,
   role VARCHAR(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index 8eacfa8..2f93825 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -215,7 +215,7 @@ CREATE TABLE host_role_command (
   retry_allowed SMALLINT DEFAULT 0 NOT NULL,
   event TEXT NOT NULL,
   exitcode INTEGER NOT NULL,
-  host_id NUMERIC(19) NOT NULL,
+  host_id NUMERIC(19),
   last_attempt_time NUMERIC(19) NOT NULL,
   request_id NUMERIC(19) NOT NULL,
   role VARCHAR(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index a947ce0..ef90205 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -245,7 +245,7 @@ CREATE TABLE host_role_command (
   retry_allowed SMALLINT DEFAULT 0 NOT NULL,
   event VARCHAR(MAX) NOT NULL,
   exitcode INTEGER NOT NULL,
-  host_id BIGINT NOT NULL,
+  host_id BIGINT,
   last_attempt_time BIGINT NOT NULL,
   request_id BIGINT NOT NULL,
   role VARCHAR(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/StageTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/StageTest.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/StageTest.java
index c1bd8bc..663d68d 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/StageTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/StageTest.java
@@ -67,11 +67,11 @@ public class StageTest {
     stage.addServerActionCommand(ConfigureAction.class.getName(),
         "user1", Role.AMBARI_SERVER_ACTION,
         RoleCommand.EXECUTE,
-        "cluster1", SERVER_HOST_NAME,
+        "cluster1",
         new ServiceComponentHostServerActionEvent(StageUtils.getHostName(), System.currentTimeMillis()),
         Collections.<String, String> emptyMap(), null, null, 1200, false, false);
 
-    List<ExecutionCommandWrapper> executionCommands = stage.getExecutionCommands(SERVER_HOST_NAME);
+    List<ExecutionCommandWrapper> executionCommands = stage.getExecutionCommands(null);
     assertEquals(1, executionCommands.size());
 
     String actionUserName = executionCommands.get(0).getExecutionCommand().getRoleParams().get(ServerAction.ACTION_USER_NAME);

http://git-wip-us.apache.org/repos/asf/ambari/blob/24ce16b5/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
index 798261b..f88cf8e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -37,7 +36,6 @@ import org.apache.ambari.server.agent.CommandReport;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.BaseRequest;
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.controller.ExecuteActionRequest;
 import org.apache.ambari.server.controller.HostsMap;
 import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.orm.DBAccessor;
@@ -355,7 +353,6 @@ public class TestActionDBAccessorImpl {
     assertEquals(HostRoleStatus.QUEUED, stage.getHostRoleStatus(hostName, actionName));
     assertEquals(HostRoleStatus.PENDING, entities.get(0).getStatus());
 
-    long now = System.currentTimeMillis();
     db.hostRoleScheduled(stage, hostName, actionName);
 
     entities = hostRoleCommandDAO.findByHostRole(
@@ -383,25 +380,25 @@ public class TestActionDBAccessorImpl {
 
   @Test
   public void testServerActionScheduled() throws InterruptedException, AmbariException {
-    populateActionDBWithServerAction(db, serverHostName, requestId, stageId);
+    populateActionDBWithServerAction(db, null, requestId, stageId);
 
     final String roleName = Role.AMBARI_SERVER_ACTION.toString();
     Stage stage = db.getStage(StageUtils.getActionId(requestId, stageId));
-    assertEquals(HostRoleStatus.PENDING, stage.getHostRoleStatus(serverHostName, roleName));
+    assertEquals(HostRoleStatus.PENDING, stage.getHostRoleStatus(null, roleName));
     List<HostRoleCommandEntity> entities =
-        hostRoleCommandDAO.findByHostRole(serverHostName, requestId, stageId, roleName);
+        hostRoleCommandDAO.findByHostRole(null, requestId, stageId, roleName);
 
     assertEquals(HostRoleStatus.PENDING, entities.get(0).getStatus());
-    stage.setHostRoleStatus(serverHostName, roleName, HostRoleStatus.QUEUED);
+    stage.setHostRoleStatus(null, roleName, HostRoleStatus.QUEUED);
 
-    entities = hostRoleCommandDAO.findByHostRole(serverHostName, requestId, stageId, roleName);
-    assertEquals(HostRoleStatus.QUEUED, stage.getHostRoleStatus(serverHostName, roleName));
+    entities = hostRoleCommandDAO.findByHostRole(null, requestId, stageId, roleName);
+    assertEquals(HostRoleStatus.QUEUED, stage.getHostRoleStatus(null, roleName));
     assertEquals(HostRoleStatus.PENDING, entities.get(0).getStatus());
 
-    db.hostRoleScheduled(stage, serverHostName, roleName);
+    db.hostRoleScheduled(stage, null, roleName);
 
     entities = hostRoleCommandDAO.findByHostRole(
-        serverHostName, requestId, stageId, roleName);
+        null, requestId, stageId, roleName);
     assertEquals(HostRoleStatus.QUEUED, entities.get(0).getStatus());
 
 
@@ -409,8 +406,8 @@ public class TestActionDBAccessorImpl {
       @Override
       public void run() {
         Stage stage1 = db.getStage("23-31");
-        stage1.setHostRoleStatus(serverHostName, roleName, HostRoleStatus.COMPLETED);
-        db.hostRoleScheduled(stage1, serverHostName, roleName);
+        stage1.setHostRoleStatus(null, roleName, HostRoleStatus.COMPLETED);
+        db.hostRoleScheduled(stage1, null, roleName);
         injector.getInstance(EntityManager.class).clear();
       }
     };
@@ -419,7 +416,7 @@ public class TestActionDBAccessorImpl {
     thread.join();
 
     injector.getInstance(EntityManager.class).clear();
-    entities = hostRoleCommandDAO.findByHostRole(serverHostName, requestId, stageId, roleName);
+    entities = hostRoleCommandDAO.findByHostRole(null, requestId, stageId, roleName);
     assertEquals("Concurrent update failed", HostRoleStatus.COMPLETED, entities.get(0).getStatus());
   }
 
@@ -766,8 +763,6 @@ public class TestActionDBAccessorImpl {
     final RequestResourceFilter resourceFilter = new RequestResourceFilter("HBASE", "HBASE_MASTER", null);
     List<RequestResourceFilter> resourceFilters = new
       ArrayList<RequestResourceFilter>() {{ add(resourceFilter); }};
-    ExecuteActionRequest executeActionRequest = new ExecuteActionRequest
-        ("cluster1", null, actionName, resourceFilters, null, null, false);
     Request request = new Request(stages, clusters);
     db.persistActions(request);
   }
@@ -777,17 +772,10 @@ public class TestActionDBAccessorImpl {
     Stage s = stageFactory.createNew(requestId, "/a/b", "cluster1", 1L, "action db accessor test",
         "", "commandParamsStage", "hostParamsStage");
     s.setStageId(stageId);
-    s.addServerActionCommand(serverActionName, Role.AMBARI_SERVER_ACTION,
+    s.addServerActionCommand(serverActionName, null, Role.AMBARI_SERVER_ACTION,
         RoleCommand.ACTIONEXECUTE, clusterName, null, null, "command details", null, 300, false, false);
     List<Stage> stages = new ArrayList<Stage>();
     stages.add(s);
-    final RequestResourceFilter resourceFilter = new RequestResourceFilter("AMBARI", "SERVER", Arrays.asList(hostname));
-    List<RequestResourceFilter> resourceFilters = new
-        ArrayList<RequestResourceFilter>() {{
-          add(resourceFilter);
-        }};
-    ExecuteActionRequest executeActionRequest = new ExecuteActionRequest
-        ("cluster1", null, serverActionName, resourceFilters, null, null, false);
     Request request = new Request(stages, clusters);
     db.persistActions(request);
   }