http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentHostDataHolder.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentHostDataHolder.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentHostDataHolder.java
new file mode 100644
index 0000000..792f10e
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentHostDataHolder.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.agent.stomp;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.agent.stomp.dto.Hashable;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Is used to saving and updating last version of event in host scope
+ * @param <T> event with hash to control version
+ */
+public abstract class AgentHostDataHolder<T extends Hashable> extends 
AgentDataHolder {
+  private Map<String, T> data = new HashMap<>();
+
+  public T getUpdateIfChanged(String agentHash, String hostName) throws 
AmbariException {
+    if (StringUtils.isEmpty(agentHash) || (StringUtils.isNotEmpty(agentHash) 
&& (!data.containsKey(hostName)
+        || !agentHash.equals(data.get(hostName).getHash())))) {
+      if (!data.containsKey(hostName)) {
+        data.put(hostName, getCurrentData(hostName));
+        data.get(hostName).setHash(getHash(data.get(hostName)));
+      }
+      return data.get(hostName);
+    }
+    return getEmptyData();
+  }
+
+  protected abstract T getCurrentData(String hostName) throws AmbariException;
+
+  protected abstract T getEmptyData();
+
+  protected void regenerateHash(String hostName) {
+    getData(hostName).setHash(null);
+    getData(hostName).setHash(getHash(getData(hostName)));
+  }
+
+  public abstract void updateData(T update) throws AmbariException;
+
+  public Map<String, T> getData() {
+    return data;
+  }
+
+  public void setData(Map<String, T> data) {
+    this.data = data;
+  }
+
+  public T getData(String hostName) {
+    return data.get(hostName);
+  }
+
+  public void setData(T data, String hostName) {
+    this.data.put(hostName, data);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentReportsController.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentReportsController.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentReportsController.java
index 60bd197..0152d89 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentReportsController.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentReportsController.java
@@ -25,10 +25,13 @@ import javax.ws.rs.WebApplicationException;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.agent.AgentSessionManager;
+import org.apache.ambari.server.agent.CommandReport;
 import org.apache.ambari.server.agent.ComponentStatus;
 import org.apache.ambari.server.agent.HeartBeatHandler;
+import org.apache.ambari.server.agent.stomp.dto.CommandStatusReports;
 import org.apache.ambari.server.agent.stomp.dto.ComponentStatusReport;
 import org.apache.ambari.server.agent.stomp.dto.ComponentStatusReports;
+import org.apache.ambari.server.agent.stomp.dto.HostStatusReport;
 import org.apache.ambari.server.state.cluster.ClustersImpl;
 import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
 import org.apache.commons.logging.Log;
@@ -63,10 +66,14 @@ public class AgentReportsController {
     for (Map.Entry<String, List<ComponentStatusReport>> clusterReport : 
message.getComponentStatusReports().entrySet()) {
       for (ComponentStatusReport report : clusterReport.getValue()) {
         ComponentStatus componentStatus = new ComponentStatus();
-        
componentStatus.setClusterName(clusters.getCluster(report.getClusterId()).getClusterName());
+        componentStatus.setClusterId(report.getClusterId());
         componentStatus.setComponentName(report.getComponentName());
         componentStatus.setServiceName(report.getServiceName());
-        componentStatus.setStatus(report.getStatus().toString());
+        if 
(report.getCommand().equals(ComponentStatusReport.CommandStatusCommand.STATUS)) 
{
+          componentStatus.setStatus(report.getStatus().toString());
+        } else {
+          componentStatus.setSecurityState(report.getStatus().toString());
+        }
         statuses.add(componentStatus);
       }
     }
@@ -75,4 +82,21 @@ public class AgentReportsController {
         agentSessionManager.getHost(simpSessionId).getHostName());
   }
 
+  @SubscribeMapping("/commands_status")
+  public void handleCommandReportStatus(@Header String simpSessionId, 
CommandStatusReports message)
+      throws WebApplicationException, InvalidStateTransitionException, 
AmbariException {
+    List<CommandReport> statuses = new ArrayList<>();
+    for (Map.Entry<String, List<CommandReport>> clusterReport : 
message.getClustersComponentReports().entrySet()) {
+      statuses.addAll(clusterReport.getValue());
+    }
+
+    hh.handleCommandReportStatus(statuses,
+        agentSessionManager.getHost(simpSessionId).getHostName());
+  }
+
+  @SubscribeMapping("/host_status")
+  public void handleHostReportStatus(@Header String simpSessionId, 
HostStatusReport message) throws AmbariException {
+    hh.handleHostReportStatus(message, 
agentSessionManager.getHost(simpSessionId).getHostName());
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HostLevelParamsHolder.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HostLevelParamsHolder.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HostLevelParamsHolder.java
new file mode 100644
index 0000000..db093f8
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HostLevelParamsHolder.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.agent.stomp;
+
+import java.util.TreeMap;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.agent.RecoveryConfigHelper;
+import org.apache.ambari.server.agent.stomp.dto.HostLevelParamsCluster;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.events.HostLevelParamsUpdateEvent;
+import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Host;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+@Singleton
+public class HostLevelParamsHolder extends 
AgentHostDataHolder<HostLevelParamsUpdateEvent> {
+
+  @Inject
+  private RecoveryConfigHelper recoveryConfigHelper;
+
+  @Inject
+  private AmbariMetaInfo ambariMetaInfo;
+
+  @Inject
+  private Clusters clusters;
+
+  private StateUpdateEventPublisher stateUpdateEventPublisher;
+
+  @Inject
+  public HostLevelParamsHolder(StateUpdateEventPublisher 
stateUpdateEventPublisher) {
+    this.stateUpdateEventPublisher = stateUpdateEventPublisher;
+    stateUpdateEventPublisher.register(this);
+  }
+
+  @Override
+  public HostLevelParamsUpdateEvent getCurrentData(String hostName) throws 
AmbariException {
+    TreeMap<String, HostLevelParamsCluster> hostLevelParamsClusters = new 
TreeMap<>();
+    for (Cluster cl : clusters.getClustersForHost(hostName)) {
+      Host host = clusters.getHost(hostName);
+      HostLevelParamsCluster hostLevelParamsCluster = new 
HostLevelParamsCluster(
+          ambariMetaInfo.getRepoInfo(cl, host),
+          recoveryConfigHelper.getRecoveryConfig(cl.getClusterName(), 
hostName));
+
+      hostLevelParamsClusters.put(Long.toString(cl.getClusterId()),
+          hostLevelParamsCluster);
+    }
+    HostLevelParamsUpdateEvent hostLevelParamsUpdateEvent = new 
HostLevelParamsUpdateEvent(hostLevelParamsClusters);
+    return hostLevelParamsUpdateEvent;
+  }
+
+  public void updateData(HostLevelParamsUpdateEvent update) throws 
AmbariException {
+    //TODO implement update host level params process
+    setData(update, update.getHostName());
+    regenerateHash(update.getHostName());
+    update.setHash(getData(update.getHostName()).getHash());
+    stateUpdateEventPublisher.publish(update);
+  }
+
+  @Override
+  protected HostLevelParamsUpdateEvent getEmptyData() {
+    return HostLevelParamsUpdateEvent.emptyUpdate();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/MetadataHolder.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/MetadataHolder.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/MetadataHolder.java
index b1adcbe..b7e6806 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/MetadataHolder.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/MetadataHolder.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,12 +17,15 @@
  */
 package org.apache.ambari.server.agent.stomp;
 
+import java.util.Map;
+
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.agent.stomp.dto.MetadataCluster;
 import org.apache.ambari.server.controller.AmbariManagementControllerImpl;
 import org.apache.ambari.server.events.MetadataUpdateEvent;
 import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
+import org.apache.commons.collections.MapUtils;
 
-import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
@@ -33,19 +36,34 @@ public class MetadataHolder extends 
AgentClusterDataHolder<MetadataUpdateEvent>
   private AmbariManagementControllerImpl ambariManagementController;
 
   @Inject
-  public MetadataHolder(StateUpdateEventPublisher stateUpdateEventPublisher) {
-    stateUpdateEventPublisher.register(this);
-  }
+  private StateUpdateEventPublisher stateUpdateEventPublisher;
 
   @Override
   public MetadataUpdateEvent getCurrentData() throws AmbariException {
     return ambariManagementController.getClustersMetadata();
   }
 
-  @Subscribe
   public void updateData(MetadataUpdateEvent update) throws AmbariException {
-    setData(getCurrentData());
+    if (getData() == null) {
+      setData(getCurrentData());
+    }
+    if (MapUtils.isNotEmpty(update.getMetadataClusters())) {
+      for (Map.Entry<String, MetadataCluster> metadataClusterEntry : 
update.getMetadataClusters().entrySet()) {
+        if 
(getData().getMetadataClusters().containsKey(metadataClusterEntry.getKey())) {
+          
getData().getMetadataClusters().get(metadataClusterEntry.getKey()).getClusterLevelParams().putAll(
+              metadataClusterEntry.getValue().getClusterLevelParams());
+          
getData().getMetadataClusters().get(metadataClusterEntry.getKey()).getServiceLevelParams().putAll(
+              metadataClusterEntry.getValue().getServiceLevelParams());
+          
getData().getMetadataClusters().get(metadataClusterEntry.getKey()).getStatusCommandsToRun().addAll(
+              metadataClusterEntry.getValue().getStatusCommandsToRun());
+        } else {
+          getData().getMetadataClusters().put(metadataClusterEntry.getKey(), 
metadataClusterEntry.getValue());
+        }
+      }
+    }
     regenerateHash();
+    update.setHash(getData().getHash());
+    stateUpdateEventPublisher.publish(update);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/TopologyHolder.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/TopologyHolder.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/TopologyHolder.java
index a4a7580..0da5d83 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/TopologyHolder.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/TopologyHolder.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -32,6 +32,7 @@ import 
org.apache.ambari.server.agent.stomp.dto.TopologyCluster;
 import org.apache.ambari.server.agent.stomp.dto.TopologyComponent;
 import org.apache.ambari.server.agent.stomp.dto.TopologyHost;
 import org.apache.ambari.server.controller.AmbariManagementControllerImpl;
+import org.apache.ambari.server.events.TopologyAgentUpdateEvent;
 import org.apache.ambari.server.events.TopologyUpdateEvent;
 import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
 import org.apache.ambari.server.state.Cluster;
@@ -44,7 +45,6 @@ import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
 import org.apache.commons.collections.CollectionUtils;
 
-import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
@@ -62,11 +62,21 @@ public class TopologyHolder extends 
AgentClusterDataHolder<TopologyUpdateEvent>
   @Inject
   private Clusters clusters;
 
+  protected StateUpdateEventPublisher stateUpdateEventPublisher;
+
   @Inject
   public TopologyHolder(StateUpdateEventPublisher stateUpdateEventPublisher) {
+    this.stateUpdateEventPublisher = stateUpdateEventPublisher;
     stateUpdateEventPublisher.register(this);
   }
 
+  @Override
+  public TopologyUpdateEvent getUpdateIfChanged(String agentHash) throws 
AmbariException {
+    TopologyUpdateEvent topologyUpdateEvent = 
super.getUpdateIfChanged(agentHash);
+    prepareAgentTopology(topologyUpdateEvent);
+    return topologyUpdateEvent;
+  }
+
   /**
    * Is used during agent registering to provide base info about clusters 
topology.
    * @return filled TopologyUpdateEvent with info about all components and 
hosts in all clusters
@@ -82,9 +92,7 @@ public class TopologyHolder extends 
AgentClusterDataHolder<TopologyUpdateEvent>
       Set<TopologyHost> topologyHosts = new HashSet<>();
       for (Host host : clusterHosts) {
         topologyHosts.add(new TopologyHost(host.getHostId(), 
host.getHostName(),
-            host.getRackInfo(), host.getIPv4(), 
recoveryConfigHelper.getRecoveryConfig(cl.getClusterName(),
-            host.getHostName()),
-            ambariManagementController.getTopologyHostLevelParams(cl, host)));
+            host.getRackInfo(), host.getIPv4()));
       }
       for (Service service : cl.getServices().values()) {
         for (ServiceComponent component : 
service.getServiceComponents().values()) {
@@ -109,6 +117,7 @@ public class TopologyHolder extends 
AgentClusterDataHolder<TopologyUpdateEvent>
                 .setHostIds(hostOrderIds)
                 
.setComponentLevelParams(ambariManagementController.getTopologyComponentLevelParams(stackId,
 serviceName,
                     componentName, cl.getSecurityType()))
+                
.setCommandParams(ambariManagementController.getTopologyCommandParams(stackId, 
serviceName, componentName))
                 .build();
             topologyComponents.add(topologyComponent);
           }
@@ -122,7 +131,6 @@ public class TopologyHolder extends 
AgentClusterDataHolder<TopologyUpdateEvent>
     return topologyUpdateEvent;
   }
 
-  @Subscribe
   public void updateData(TopologyUpdateEvent update) throws AmbariException {
     if (getData() == null) {
       setData(getCurrentData());
@@ -144,12 +152,34 @@ public class TopologyHolder extends 
AgentClusterDataHolder<TopologyUpdateEvent>
         if (eventType.equals(TopologyUpdateEvent.EventType.UPDATE)) {
           getData().getClusters().put(clusterId, cluster);
         } else {
-          throw new ClusterNotFoundException(Long.getLong(clusterId));
+          throw new ClusterNotFoundException(Long.parseLong(clusterId));
         }
       }
     }
 
     regenerateHash();
+    update.setHash(getData().getHash());
+    stateUpdateEventPublisher.publish(update);
+
+    // it is not allowed to change existent update event before arriving to 
listener and converting to json
+    // so it is better to create copy
+    TopologyUpdateEvent copiedUpdate = update.deepCopy();
+    TopologyAgentUpdateEvent topologyAgentUpdateEvent = new 
TopologyAgentUpdateEvent(copiedUpdate.getClusters(),
+        copiedUpdate.getHash(),
+        copiedUpdate.getEventType());
+    prepareAgentTopology(topologyAgentUpdateEvent);
+    stateUpdateEventPublisher.publish(topologyAgentUpdateEvent);
+  }
+
+  private void prepareAgentTopology(TopologyUpdateEvent topologyUpdateEvent) {
+    if (topologyUpdateEvent.getClusters() != null) {
+      for (TopologyCluster topologyCluster : 
topologyUpdateEvent.getClusters().values()) {
+        for (TopologyComponent topologyComponent : 
topologyCluster.getTopologyComponents()) {
+          topologyComponent.setHostNames(new HashSet<>());
+          topologyComponent.setPublicHostNames(new HashSet<>());
+        }
+      }
+    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ClusterConfigs.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ClusterConfigs.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ClusterConfigs.java
index b9339a7..6e01cac 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ClusterConfigs.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ClusterConfigs.java
@@ -47,4 +47,23 @@ public class ClusterConfigs {
   public void setConfigurationAttributes(Map<String, Map<String, Map<String, 
String>>> configurationAttributes) {
     this.configurationAttributes = configurationAttributes;
   }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ClusterConfigs that = (ClusterConfigs) o;
+
+    if (configurations != null ? !configurations.equals(that.configurations) : 
that.configurations != null)
+      return false;
+    return configurationAttributes != null ? 
configurationAttributes.equals(that.configurationAttributes) : 
that.configurationAttributes == null;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = configurations != null ? configurations.hashCode() : 0;
+    result = 31 * result + (configurationAttributes != null ? 
configurationAttributes.hashCode() : 0);
+    return result;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/CommandStatusReports.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/CommandStatusReports.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/CommandStatusReports.java
new file mode 100644
index 0000000..3693c4c
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/CommandStatusReports.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.agent.stomp.dto;
+
+import java.util.List;
+import java.util.TreeMap;
+
+import org.apache.ambari.server.agent.CommandReport;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class CommandStatusReports {
+
+  @JsonProperty("clusters")
+  private TreeMap<String, List<CommandReport>> clustersComponentReports;
+
+  public CommandStatusReports() {
+  }
+
+  public TreeMap<String, List<CommandReport>> getClustersComponentReports() {
+    return clustersComponentReports;
+  }
+
+  public void setClustersComponentReports(TreeMap<String, List<CommandReport>> 
clustersComponentReports) {
+    this.clustersComponentReports = clustersComponentReports;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ComponentStatusReports.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ComponentStatusReports.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ComponentStatusReports.java
index a53570c..ac327d4 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ComponentStatusReports.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ComponentStatusReports.java
@@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class ComponentStatusReports {
 
-  @JsonProperty("clustersReports")
+  @JsonProperty("clusters")
   private TreeMap<String, List<ComponentStatusReport>> componentStatusReports;
 
   public ComponentStatusReports() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ExecutionCommandsCluster.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ExecutionCommandsCluster.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ExecutionCommandsCluster.java
new file mode 100644
index 0000000..7874230
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ExecutionCommandsCluster.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.agent.stomp.dto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ambari.server.agent.CancelCommand;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class ExecutionCommandsCluster {
+
+  @JsonProperty("commands")
+  private List<org.apache.ambari.server.agent.ExecutionCommand> 
executionCommands = new ArrayList<>();
+
+  @JsonProperty("cancelCommands")
+  private List<CancelCommand> cancelCommands = new ArrayList<>();
+
+  public 
ExecutionCommandsCluster(List<org.apache.ambari.server.agent.ExecutionCommand> 
executionCommands, List<CancelCommand> cancelCommands) {
+    this.executionCommands = executionCommands;
+    this.cancelCommands = cancelCommands;
+  }
+
+  public List<org.apache.ambari.server.agent.ExecutionCommand> 
getExecutionCommands() {
+    return executionCommands;
+  }
+
+  public void 
setExecutionCommands(List<org.apache.ambari.server.agent.ExecutionCommand> 
executionCommands) {
+    this.executionCommands = executionCommands;
+  }
+
+  public List<CancelCommand> getCancelCommands() {
+    return cancelCommands;
+  }
+
+  public void setCancelCommands(List<CancelCommand> cancelCommands) {
+    this.cancelCommands = cancelCommands;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ExecutionCommandsCluster that = (ExecutionCommandsCluster) o;
+
+    if (executionCommands != null ? 
!executionCommands.equals(that.executionCommands) : that.executionCommands != 
null)
+      return false;
+    return cancelCommands != null ? cancelCommands.equals(that.cancelCommands) 
: that.cancelCommands == null;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = executionCommands != null ? executionCommands.hashCode() : 0;
+    result = 31 * result + (cancelCommands != null ? cancelCommands.hashCode() 
: 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hash.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hash.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hash.java
index 19f9597..8a62d6b 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hash.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hash.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostLevelParamsCluster.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostLevelParamsCluster.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostLevelParamsCluster.java
new file mode 100644
index 0000000..e4e28bf
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostLevelParamsCluster.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.agent.stomp.dto;
+
+import java.util.List;
+
+import org.apache.ambari.server.agent.RecoveryConfig;
+import org.apache.ambari.server.state.RepositoryInfo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class HostLevelParamsCluster {
+
+  private List<RepositoryInfo> repoInfo;
+  private RecoveryConfig recoveryConfig;
+
+  public HostLevelParamsCluster(List<RepositoryInfo> repoInfo, RecoveryConfig 
recoveryConfig) {
+    this.repoInfo = repoInfo;
+    this.recoveryConfig = recoveryConfig;
+  }
+
+  public List<RepositoryInfo> getRepoInfo() {
+    return repoInfo;
+  }
+
+  public void setRepoInfo(List<RepositoryInfo> repoInfo) {
+    this.repoInfo = repoInfo;
+  }
+
+  public RecoveryConfig getRecoveryConfig() {
+    return recoveryConfig;
+  }
+
+  public void setRecoveryConfig(RecoveryConfig recoveryConfig) {
+    this.recoveryConfig = recoveryConfig;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostStatusReport.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostStatusReport.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostStatusReport.java
new file mode 100644
index 0000000..9af406f
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostStatusReport.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.agent.stomp.dto;
+
+import java.util.List;
+
+import org.apache.ambari.server.agent.AgentEnv;
+import org.apache.ambari.server.agent.DiskInfo;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class HostStatusReport {
+
+  @JsonProperty("agentEnv")
+  private AgentEnv agentEnv;
+
+  @JsonProperty("mounts")
+  private List<DiskInfo> mounts;
+
+  public HostStatusReport() {
+  }
+
+  public AgentEnv getAgentEnv() {
+    return agentEnv;
+  }
+
+  public void setAgentEnv(AgentEnv agentEnv) {
+    this.agentEnv = agentEnv;
+  }
+
+  public List<DiskInfo> getMounts() {
+    return mounts;
+  }
+
+  public void setMounts(List<DiskInfo> mounts) {
+    this.mounts = mounts;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataCluster.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataCluster.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataCluster.java
index 07e85df..3ee5ad6 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataCluster.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataCluster.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,8 +17,8 @@
  */
 package org.apache.ambari.server.agent.stomp.dto;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.TreeMap;
 
 import org.apache.ambari.server.state.SecurityType;
@@ -29,25 +29,27 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 @JsonInclude(JsonInclude.Include.NON_EMPTY)
 public class MetadataCluster {
   @JsonProperty("status_commands_to_run")
-  private List<String> statusCommandsToRun = new ArrayList<>();
-  private TreeMap<String, MetadataServiceInfo> serviceLevelParams;
-  private TreeMap<String, String> clusterLevelParams;
+  private Set<String> statusCommandsToRun = new HashSet<>();
+  private TreeMap<String, MetadataServiceInfo> serviceLevelParams = new 
TreeMap<>();
+  private TreeMap<String, String> clusterLevelParams = new TreeMap<>();
 
   public MetadataCluster(SecurityType securityType, 
TreeMap<String,MetadataServiceInfo> serviceLevelParams,
                          TreeMap<String, String> clusterLevelParams) {
-    this.statusCommandsToRun.add("STATUS");
-    if (SecurityType.KERBEROS.equals(securityType)) {
-      this.statusCommandsToRun.add("SECURITY_STATUS");
+    if (securityType != null) {
+      this.statusCommandsToRun.add("STATUS");
+      if (SecurityType.KERBEROS.equals(securityType)) {
+        this.statusCommandsToRun.add("SECURITY_STATUS");
+      }
     }
     this.serviceLevelParams = serviceLevelParams;
     this.clusterLevelParams = clusterLevelParams;
   }
 
-  public List<String> getStatusCommandsToRun() {
+  public Set<String> getStatusCommandsToRun() {
     return statusCommandsToRun;
   }
 
-  public void setStatusCommandsToRun(List<String> statusCommandsToRun) {
+  public void setStatusCommandsToRun(Set<String> statusCommandsToRun) {
     this.statusCommandsToRun = statusCommandsToRun;
   }
 
@@ -66,4 +68,26 @@ public class MetadataCluster {
   public void setClusterLevelParams(TreeMap<String, String> 
clusterLevelParams) {
     this.clusterLevelParams = clusterLevelParams;
   }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    MetadataCluster that = (MetadataCluster) o;
+
+    if (statusCommandsToRun != null ? 
!statusCommandsToRun.equals(that.statusCommandsToRun) : 
that.statusCommandsToRun != null)
+      return false;
+    if (serviceLevelParams != null ? 
!serviceLevelParams.equals(that.serviceLevelParams) : that.serviceLevelParams 
!= null)
+      return false;
+    return clusterLevelParams != null ? 
clusterLevelParams.equals(that.clusterLevelParams) : that.clusterLevelParams == 
null;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = statusCommandsToRun != null ? statusCommandsToRun.hashCode() 
: 0;
+    result = 31 * result + (serviceLevelParams != null ? 
serviceLevelParams.hashCode() : 0);
+    result = 31 * result + (clusterLevelParams != null ? 
clusterLevelParams.hashCode() : 0);
+    return result;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataServiceInfo.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataServiceInfo.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataServiceInfo.java
index aea8986..a84b509 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataServiceInfo.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataServiceInfo.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -68,4 +68,28 @@ public class MetadataServiceInfo {
   public void setServicePackageFolder(String servicePackageFolder) {
     this.servicePackageFolder = servicePackageFolder;
   }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    MetadataServiceInfo that = (MetadataServiceInfo) o;
+
+    if (version != null ? !version.equals(that.version) : that.version != 
null) return false;
+    if (credentialStoreEnabled != null ? 
!credentialStoreEnabled.equals(that.credentialStoreEnabled) : 
that.credentialStoreEnabled != null)
+      return false;
+    if (statusCommandsTimeout != null ? 
!statusCommandsTimeout.equals(that.statusCommandsTimeout) : 
that.statusCommandsTimeout != null)
+      return false;
+    return servicePackageFolder != null ? 
servicePackageFolder.equals(that.servicePackageFolder) : 
that.servicePackageFolder == null;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = version != null ? version.hashCode() : 0;
+    result = 31 * result + (credentialStoreEnabled != null ? 
credentialStoreEnabled.hashCode() : 0);
+    result = 31 * result + (statusCommandsTimeout != null ? 
statusCommandsTimeout.hashCode() : 0);
+    result = 31 * result + (servicePackageFolder != null ? 
servicePackageFolder.hashCode() : 0);
+    return result;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyCluster.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyCluster.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyCluster.java
index 7a464df..c350b5f6 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyCluster.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyCluster.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,14 +22,13 @@ import java.util.Iterator;
 import java.util.Set;
 
 import org.apache.ambari.server.events.TopologyUpdateEvent;
+import org.apache.commons.collections.SetUtils;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 @JsonInclude(JsonInclude.Include.NON_EMPTY)
 public class TopologyCluster {
-  private String clusterName;
-
   @JsonProperty("components")
   private Set<TopologyComponent> topologyComponents = new HashSet<>();
 
@@ -51,9 +50,12 @@ public class TopologyCluster {
       for (Iterator<TopologyComponent> iter = 
getTopologyComponents().iterator(); iter.hasNext() && !updated; ) {
         TopologyComponent existsComponent = iter.next();
         if (existsComponent.equals(componentToUpdate)) {
-          //TODO add case removing not all hostcomponents
           if (eventType.equals(TopologyUpdateEvent.EventType.DELETE)) {
-            iter.remove();
+            if (SetUtils.isEqualSet(existsComponent.getHostIds(), 
componentToUpdate.getHostIds())) {
+              iter.remove();
+            } else {
+              existsComponent.removeComponent(componentToUpdate);
+            }
           } else {
             existsComponent.updateComponent(componentToUpdate);
           }
@@ -95,6 +97,22 @@ public class TopologyCluster {
     return topologyHosts;
   }
 
+  public Set<TopologyHost> deepCopyTopologyHosts() {
+    return topologyHosts;
+  }
+
+  public TopologyCluster deepCopyCluster() {
+    Set<TopologyComponent> copiedComponents = new HashSet<>();
+    for (TopologyComponent topologyComponent : topologyComponents) {
+      copiedComponents.add(topologyComponent.deepCopy());
+    }
+    Set<TopologyHost> copiedHosts = new HashSet<>();
+    for (TopologyHost topologyHost : topologyHosts) {
+      copiedHosts.add(topologyHost.deepCopy());
+    }
+    return new TopologyCluster(copiedComponents, copiedHosts);
+  }
+
   public void setTopologyHosts(Set<TopologyHost> topologyHosts) {
     this.topologyHosts = topologyHosts;
   }
@@ -107,11 +125,22 @@ public class TopologyCluster {
     topologyComponents.add(topologyComponent);
   }
 
-  public String getClusterName() {
-    return clusterName;
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    TopologyCluster that = (TopologyCluster) o;
+
+    if (topologyComponents != null ? 
!topologyComponents.equals(that.topologyComponents) : that.topologyComponents 
!= null)
+      return false;
+    return topologyHosts != null ? topologyHosts.equals(that.topologyHosts) : 
that.topologyHosts == null;
   }
 
-  public void setClusterName(String clusterName) {
-    this.clusterName = clusterName;
+  @Override
+  public int hashCode() {
+    int result = topologyComponents != null ? topologyComponents.hashCode() : 
0;
+    result = 31 * result + (topologyHosts != null ? topologyHosts.hashCode() : 
0);
+    return result;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyComponent.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyComponent.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyComponent.java
index dabbe94..1060232 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyComponent.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyComponent.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -28,7 +28,7 @@ import org.apache.commons.lang.StringUtils;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 
-@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
 public class TopologyComponent {
   private String componentName;
   private String serviceName;
@@ -38,6 +38,7 @@ public class TopologyComponent {
   private Set<String> hostNames;
   private Set<String> publicHostNames;
   private TreeMap<String, String> componentLevelParams;
+  private TreeMap<String, String> commandParams;
 
   private TopologyComponent() {
   }
@@ -91,6 +92,11 @@ public class TopologyComponent {
       return this;
     }
 
+    public Builder setCommandParams(TreeMap<String, String> commandParams) {
+      TopologyComponent.this.setCommandParams(commandParams);
+      return this;
+    }
+
     public TopologyComponent build() {
       return TopologyComponent.this;
     }
@@ -123,9 +129,45 @@ public class TopologyComponent {
       if (MapUtils.isNotEmpty(componentToUpdate.getComponentLevelParams())) {
         
componentLevelParams.putAll(componentToUpdate.getComponentLevelParams());
       }
+      if (MapUtils.isNotEmpty(componentToUpdate.getCommandParams())) {
+        commandParams.putAll(componentToUpdate.getCommandParams());
+      }
+    }
+  }
+
+  public void removeComponent(TopologyComponent componentToRemove) {
+    if (componentToRemove.getComponentName().equals(getComponentName())) {
+      if (CollectionUtils.isNotEmpty(componentToRemove.getHostIds())) {
+        if (hostIds != null) {
+          hostIds.removeAll(componentToRemove.getHostIds());
+        }
+      }
+      if (CollectionUtils.isNotEmpty(componentToRemove.getHostNames())) {
+        if (hostNames != null) {
+          hostNames.removeAll(componentToRemove.getHostNames());
+        }
+      }
+      if (CollectionUtils.isNotEmpty(componentToRemove.getPublicHostNames())) {
+        if (publicHostNames != null) {
+          publicHostNames.removeAll(componentToRemove.getPublicHostNames());
+        }
+      }
     }
   }
 
+  public  TopologyComponent deepCopy() {
+    return TopologyComponent.newBuilder().setComponentName(getComponentName())
+        .setDisplayName(getDisplayName())
+        .setServiceName(getServiceName())
+        .setVersion(getVersion())
+        .setComponentLevelParams(getComponentLevelParams() == null ? null : 
new TreeMap<>(getComponentLevelParams()))
+        .setHostIds(getHostIds() == null ? null : new HashSet<>(getHostIds()))
+        .setHostNames(getHostNames() == null ? null : new 
HashSet<>(getHostNames()))
+        .setPublicHostNames(getPublicHostNames() == null ? null : new 
HashSet<>(getPublicHostNames()))
+        .setCommandParams(getCommandParams() == null ? null : new 
TreeMap<>(getCommandParams()))
+        .build();
+  }
+
   public String getComponentName() {
     return componentName;
   }
@@ -198,6 +240,13 @@ public class TopologyComponent {
     this.publicHostNames = publicHostNames;
   }
 
+  public TreeMap<String, String> getCommandParams() {
+    return commandParams;
+  }
+
+  public void setCommandParams(TreeMap<String, String> commandParams) {
+    this.commandParams = commandParams;
+  }
 
   @Override
   public boolean equals(Object o) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyHost.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyHost.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyHost.java
index 84e3cff..8d2b627 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyHost.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyHost.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,10 +17,6 @@
  */
 package org.apache.ambari.server.agent.stomp.dto;
 
-import java.util.TreeMap;
-
-import org.apache.ambari.server.agent.RecoveryConfig;
-import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
@@ -31,8 +27,6 @@ public class TopologyHost {
   private String hostName;
   private String rackName;
   private String ipv4;
-  private TreeMap<String, String> hostLevelParams;
-  private RecoveryConfig recoveryConfig;
 
   public TopologyHost() {
   }
@@ -41,14 +35,11 @@ public class TopologyHost {
     this.hostId = hostId;
   }
 
-  public TopologyHost(Long hostId, String hostName, String rackName, String 
ipv4, RecoveryConfig recoveryConfig,
-                      TreeMap<String, String> hostLevelParams) {
+  public TopologyHost(Long hostId, String hostName, String rackName, String 
ipv4) {
     this.hostId = hostId;
     this.hostName = hostName;
     this.rackName = rackName;
     this.ipv4 = ipv4;
-    this.recoveryConfig = recoveryConfig;
-    this.hostLevelParams = hostLevelParams;
   }
 
   public void updateHost(TopologyHost hostToUpdate) {
@@ -62,12 +53,13 @@ public class TopologyHost {
       if (StringUtils.isNotEmpty(hostToUpdate.getIpv4())) {
         setIpv4(hostToUpdate.getIpv4());
       }
-      if (MapUtils.isNotEmpty(hostToUpdate.getHostLevelParams())) {
-        hostLevelParams.putAll(hostToUpdate.getHostLevelParams());
-      }
     }
   }
 
+  public TopologyHost deepCopy() {
+    return new TopologyHost(getHostId(), getHostName(), getRackName(), 
getIpv4());
+  }
+
   public Long getHostId() {
     return hostId;
   }
@@ -100,22 +92,6 @@ public class TopologyHost {
     this.ipv4 = ipv4;
   }
 
-  public RecoveryConfig getRecoveryConfig() {
-    return recoveryConfig;
-  }
-
-  public void setRecoveryConfig(RecoveryConfig recoveryConfig) {
-    this.recoveryConfig = recoveryConfig;
-  }
-
-  public TreeMap<String, String> getHostLevelParams() {
-    return hostLevelParams;
-  }
-
-  public void setHostLevelParams(TreeMap<String, String> hostLevelParams) {
-    this.hostLevelParams = hostLevelParams;
-  }
-
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateSummary.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateSummary.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateSummary.java
index fe0198b..d1672b7 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateSummary.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateSummary.java
@@ -52,4 +52,26 @@ public final class AlertStateSummary {
   @JsonProperty(value = "UNKNOWN")
   @com.fasterxml.jackson.annotation.JsonProperty(value = "UNKNOWN")
   public final AlertStateValues Unknown = new AlertStateValues();
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    AlertStateSummary that = (AlertStateSummary) o;
+
+    if (Ok != null ? !Ok.equals(that.Ok) : that.Ok != null) return false;
+    if (Warning != null ? !Warning.equals(that.Warning) : that.Warning != 
null) return false;
+    if (Critical != null ? !Critical.equals(that.Critical) : that.Critical != 
null) return false;
+    return Unknown != null ? Unknown.equals(that.Unknown) : that.Unknown == 
null;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = Ok != null ? Ok.hashCode() : 0;
+    result = 31 * result + (Warning != null ? Warning.hashCode() : 0);
+    result = 31 * result + (Critical != null ? Critical.hashCode() : 0);
+    result = 31 * result + (Unknown != null ? Unknown.hashCode() : 0);
+    return result;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateValues.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateValues.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateValues.java
index a99a648..63d72f5 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateValues.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertStateValues.java
@@ -57,4 +57,26 @@ public final class AlertStateValues {
   @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
   @JsonInclude(JsonInclude.Include.NON_NULL)
   public String AlertText = null;
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    AlertStateValues that = (AlertStateValues) o;
+
+    if (Count != that.Count) return false;
+    if (Timestamp != that.Timestamp) return false;
+    if (MaintenanceCount != that.MaintenanceCount) return false;
+    return AlertText != null ? AlertText.equals(that.AlertText) : 
that.AlertText == null;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = Count;
+    result = 31 * result + (int) (Timestamp ^ (Timestamp >>> 32));
+    result = 31 * result + MaintenanceCount;
+    result = 31 * result + (AlertText != null ? AlertText.hashCode() : 0);
+    return result;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryGroupedRenderer.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryGroupedRenderer.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryGroupedRenderer.java
index a2664fa..c8c495e 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryGroupedRenderer.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryGroupedRenderer.java
@@ -261,5 +261,25 @@ public class AlertSummaryGroupedRenderer extends 
AlertSummaryRenderer {
     @JsonProperty(value = "summary")
     @com.fasterxml.jackson.annotation.JsonProperty(value = "summary")
     public final AlertStateSummary State = new AlertStateSummary();
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      AlertDefinitionSummary that = (AlertDefinitionSummary) o;
+
+      if (Id != that.Id) return false;
+      if (Name != null ? !Name.equals(that.Name) : that.Name != null) return 
false;
+      return State != null ? State.equals(that.State) : that.State == null;
+    }
+
+    @Override
+    public int hashCode() {
+      int result = (int) (Id ^ (Id >>> 32));
+      result = 31 * result + (Name != null ? Name.hashCode() : 0);
+      result = 31 * result + (State != null ? State.hashCode() : 0);
+      return result;
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
index 65e5fd2..ca4eed9 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
@@ -53,9 +53,14 @@ import 
org.apache.ambari.server.events.AlertDefinitionRegistrationEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.metadata.AmbariServiceAlertDefinitions;
 import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
+import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
 import org.apache.ambari.server.orm.dao.MetainfoDAO;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
 import org.apache.ambari.server.orm.entities.MetainfoEntity;
+import org.apache.ambari.server.orm.entities.OperatingSystemEntity;
+import org.apache.ambari.server.orm.entities.RepositoryEntity;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.stack.StackDirectory;
 import org.apache.ambari.server.stack.StackManager;
 import org.apache.ambari.server.stack.StackManagerFactory;
@@ -64,9 +69,11 @@ import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ComponentInfo;
 import org.apache.ambari.server.state.DependencyInfo;
 import org.apache.ambari.server.state.ExtensionInfo;
+import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.OperatingSystemInfo;
 import org.apache.ambari.server.state.PropertyInfo;
 import org.apache.ambari.server.state.RepositoryInfo;
+import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.StackId;
@@ -155,6 +162,12 @@ public class AmbariMetaInfo {
   @Inject
   private OsFamily osFamily;
 
+  @Inject
+  private Gson gson;
+
+  @Inject
+  private ClusterVersionDAO clusterVersionDAO;
+
   /**
    * ALL_SUPPORTED_OS is dynamically generated list from loaded families from 
os_family.json
    * Instead of append values here, please, add new families in json for tests 
and production
@@ -1485,4 +1498,132 @@ public class AmbariMetaInfo {
 
     return versionDefinitions;
   }
+  /**
+   * Get repository info given a cluster and host.
+   *
+   * @param cluster  the cluster
+   * @param host     the host
+   *
+   * @return the repo info
+   *
+   * @throws AmbariException if the repository information can not be obtained
+   */
+  public String getRepoInfoString(Cluster cluster, Host host) throws 
AmbariException {
+
+    return getRepoInfoString(cluster, host.getOsType(), host.getOsFamily(), 
host.getHostName());
+  }
+
+  public String getRepoInfoString(Cluster cluster, String hostOSType, String 
hostOSFamily, String hostName) throws AmbariException {
+    return gson.toJson(getRepoInfo(cluster, hostOSType, hostOSFamily, 
hostName));
+  }
+
+  /**
+   * Get repository info given a cluster and host.
+   *
+   * @param cluster  the cluster
+   * @param host     the host
+   *
+   * @return the repo info
+   *
+   * @throws AmbariException if the repository information can not be obtained
+   */
+  public List<RepositoryInfo> getRepoInfo(Cluster cluster, Host host) throws 
AmbariException {
+
+    return getRepoInfo(cluster, host.getOsType(), host.getOsFamily(), 
host.getHostName());
+  }
+
+  public List<RepositoryInfo> getRepoInfo(Cluster cluster, String hostOSType, 
String hostOSFamily, String hostName) throws AmbariException {
+
+    StackId stackId = cluster.getDesiredStackVersion();
+
+    Map<String, List<RepositoryInfo>> repos = getRepository(
+        stackId.getStackName(), stackId.getStackVersion());
+
+    String family = osFamily.find(hostOSType);
+    if (null == family) {
+      family = hostOSFamily;
+    }
+
+    List<RepositoryInfo> repoInfos = new ArrayList<>();
+
+    // !!! check for the most specific first
+    if (repos.containsKey(hostOSType)) {
+      repoInfos = repos.get(hostOSType);
+    } else if (null != family && repos.containsKey(family)) {
+      repoInfos = repos.get(family);
+    } else {
+      LOG.warn("Could not retrieve repo information for host"
+          + ", hostname=" + hostName
+          + ", clusterName=" + cluster.getClusterName()
+          + ", stackInfo=" + stackId.getStackId());
+    }
+
+    if (null != repoInfos) {
+      updateBaseUrls(cluster, repoInfos);
+      return repoInfos;
+    } else {
+      return null;
+    }
+  }
+  /**
+   * Checks repo URLs against the current version for the cluster and makes
+   * adjustments to the Base URL when the current is different.
+   * @param cluster   the cluster to load the current version
+   * @param repoInfos the array containing stack repo data
+   */
+  private void updateBaseUrls(Cluster cluster, List<RepositoryInfo> repoInfos) 
throws AmbariException {
+    ClusterVersionEntity cve = cluster.getCurrentClusterVersion();
+
+    if (null == cve) {
+      List<ClusterVersionEntity> list = 
clusterVersionDAO.findByClusterAndState(cluster.getClusterName(),
+          RepositoryVersionState.INIT);
+
+      if (!list.isEmpty()) {
+        if (list.size() > 1) {
+          throw new AmbariException(String.format("The cluster can only be 
initialized by one version: %s found",
+              list.size()));
+        } else {
+          cve = list.get(0);
+        }
+      }
+    }
+
+    if (null == cve || null == cve.getRepositoryVersion()) {
+      LOG.info("Cluster {} has no specific Repository Versions.  Using 
stack-defined values", cluster.getClusterName());
+      return;
+    }
+
+    RepositoryVersionEntity rve = cve.getRepositoryVersion();
+
+    for (Iterator<RepositoryInfo> iter = repoInfos.iterator(); iter.hasNext(); 
) {
+
+      RepositoryInfo repositoryInfo = iter.next();
+
+      String repoId = repositoryInfo.getRepoId();
+      String repoName = repositoryInfo.getRepoName();
+      String baseUrl = repositoryInfo.getBaseUrl();
+      String osType = repositoryInfo.getOsType();
+
+      if (null == repoId || null == baseUrl || null == osType || null == 
repoName) {
+        continue;
+      }
+
+      boolean toResult = false;
+      for (OperatingSystemEntity ose : rve.getOperatingSystems()) {
+        if (ose.getOsType().equals(osType) && ose.isAmbariManagedRepos()) {
+          for (RepositoryEntity re : ose.getRepositories()) {
+            if (re.getName().equals(repoName) &&
+                re.getRepositoryId().equals(repoId) &&
+                !re.getBaseUrl().equals(baseUrl)) {
+              repositoryInfo.setBaseUrl(re.getBaseUrl());
+            }
+          }
+          toResult = true;
+        }
+      }
+      if (!toResult) {
+        iter.remove();
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index 55a4f50..d61ca2e 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -2045,6 +2045,13 @@ public class Configuration {
       "agent.threadpool.size.max", 25);
 
   /**
+   * The thread pool size for spring messaging.
+   */
+  @Markdown(description = "Thread pool size for spring messaging")
+  public static final ConfigurationProperty<Integer> 
MESSAGING_THREAD_POOL_SIZE = new ConfigurationProperty<>(
+      "messaging.threadpool.size", 1);
+
+  /**
    * The maximum number of threads used to extract Ambari Views when Ambari
    * Server is starting up.
    */
@@ -4673,6 +4680,13 @@ public class Configuration {
   }
 
   /**
+   * @return max thread pool size for clients, default 25
+   */
+  public int getSpringMessagingThreadPoolSize() {
+    return Integer.parseInt(getProperty(MESSAGING_THREAD_POOL_SIZE));
+  }
+
+  /**
    * @return max thread pool size for agents, default 25
    */
   public int getAgentThreadPoolSize() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/AgentStompConfig.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/AgentStompConfig.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/AgentStompConfig.java
index cadfd62..387bdda 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/AgentStompConfig.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/AgentStompConfig.java
@@ -22,15 +22,23 @@ import org.apache.ambari.server.api.stomp.TestController;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
+import org.springframework.messaging.simp.config.ChannelRegistration;
 import 
org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
 import 
org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
 import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
 
+import com.google.inject.Injector;
+
 @Configuration
 @EnableWebSocketMessageBroker
 @ComponentScan(basePackageClasses = {TestController.class, 
HeartbeatController.class})
 @Import(RootStompConfig.class)
 public class AgentStompConfig extends AbstractWebSocketMessageBrokerConfigurer 
{
+  private org.apache.ambari.server.configuration.Configuration configuration;
+
+  public AgentStompConfig(Injector injector) {
+    configuration = 
injector.getInstance(org.apache.ambari.server.configuration.Configuration.class);
+  }
 
   @Override
   public void registerStompEndpoints(StompEndpointRegistry registry) {
@@ -38,4 +46,14 @@ public class AgentStompConfig extends 
AbstractWebSocketMessageBrokerConfigurer {
         .setAllowedOrigins("*");
 
   }
+
+  @Override
+  public void configureClientInboundChannel(ChannelRegistration registration) {
+    
registration.taskExecutor().corePoolSize(configuration.getSpringMessagingThreadPoolSize());
+  }
+
+  @Override
+  public void configureClientOutboundChannel(ChannelRegistration registration) 
{
+    
registration.taskExecutor().corePoolSize(configuration.getSpringMessagingThreadPoolSize());
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/ApiStompConfig.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/ApiStompConfig.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/ApiStompConfig.java
index 0d8a08b..170fa17 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/ApiStompConfig.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/ApiStompConfig.java
@@ -47,6 +47,7 @@ public class ApiStompConfig extends 
AbstractWebSocketMessageBrokerConfigurer {
   public void registerStompEndpoints(StompEndpointRegistry registry) {
     registry.addEndpoint("/v1")
         .setAllowedOrigins("*");
+    registry.addEndpoint("/v1")
+        .setAllowedOrigins("*").withSockJS();
   }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/RootStompConfig.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/RootStompConfig.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/RootStompConfig.java
index 7ca3166..667022e 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/RootStompConfig.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/spring/RootStompConfig.java
@@ -23,6 +23,7 @@ import java.util.List;
 import javax.servlet.ServletContext;
 
 import org.apache.ambari.server.api.AmbariSendToMethodReturnValueHandler;
+import org.apache.ambari.server.events.listeners.requests.StateUpdateListener;
 import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,6 +42,8 @@ import 
org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy;
 import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
 
+import com.google.inject.Injector;
+
 @Configuration
 public class RootStompConfig {
 
@@ -54,6 +57,11 @@ public class RootStompConfig {
   }
 
   @Bean
+  public StateUpdateListener requestStatusListener(Injector injector) {
+    return new StateUpdateListener(injector);
+  }
+
+  @Bean
   public DefaultHandshakeHandler handshakeHandler() {
 
     return new DefaultHandshakeHandler(

http://git-wip-us.apache.org/repos/asf/ambari/blob/44c1cb51/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
index c11763c..02e52ea 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
@@ -27,7 +27,6 @@ import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.CUSTOM_CO
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_DRIVER_FILENAME;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_NAME;
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.GROUP_LIST;
-import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOST_SYS_PREPPED;
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JAVA_HOME;
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JAVA_VERSION;
@@ -40,7 +39,6 @@ import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.ORACLE_JD
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.REPO_INFO;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
-import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_NAME;
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_VERSION;
 import static 
org.apache.ambari.server.agent.ExecutionCommand.KeyNames.USER_GROUPS;
@@ -76,9 +74,6 @@ import org.apache.ambari.server.metadata.ActionMetadata;
 import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
 import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
-import org.apache.ambari.server.orm.entities.OperatingSystemEntity;
-import org.apache.ambari.server.orm.entities.RepositoryEntity;
-import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.CommandScriptDefinition;
@@ -91,7 +86,6 @@ import org.apache.ambari.server.state.HostComponentAdminState;
 import org.apache.ambari.server.state.HostState;
 import org.apache.ambari.server.state.MaintenanceState;
 import org.apache.ambari.server.state.PropertyInfo.PropertyType;
-import org.apache.ambari.server.state.RepositoryInfo;
 import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
@@ -109,9 +103,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
@@ -326,10 +317,6 @@ public class AmbariCustomCommandExecutionHelper {
     AmbariMetaInfo ambariMetaInfo = managementController.getAmbariMetaInfo();
     ServiceInfo serviceInfo = ambariMetaInfo.getService(
         stackId.getStackName(), stackId.getStackVersion(), serviceName);
-    StackInfo stackInfo = ambariMetaInfo.getStack
-       (stackId.getStackName(), stackId.getStackVersion());
-
-    ClusterVersionEntity effectiveClusterVersion = 
cluster.getEffectiveClusterVersion();
 
     CustomCommandDefinition customCommandDefinition = null;
     ComponentInfo ci = serviceInfo.getComponentByName(componentName);
@@ -404,10 +391,8 @@ public class AmbariCustomCommandExecutionHelper {
 
       Map<String, String> hostLevelParams = new TreeMap<>();
 
-      hostLevelParams.put(CUSTOM_COMMAND, commandName);
-
       // Set parameters required for re-installing clients on restart
-      hostLevelParams.put(REPO_INFO, getRepoInfo(cluster, host));
+      hostLevelParams.put(REPO_INFO, ambariMetaInfo.getRepoInfoString(cluster, 
host));
       hostLevelParams.put(STACK_NAME, stackId.getStackName());
       hostLevelParams.put(STACK_VERSION, stackId.getStackVersion());
 
@@ -439,9 +424,10 @@ public class AmbariCustomCommandExecutionHelper {
           commandParams.put(key, additionalCommandParams.get(key));
         }
       }
+      commandParams.put(CUSTOM_COMMAND, commandName);
 
       boolean isInstallCommand = 
commandName.equals(RoleCommand.INSTALL.toString());
-      int commandTimeout = 
Short.valueOf(configs.getDefaultAgentTaskTimeout(isInstallCommand)).intValue();
+      String commandTimeout = 
configs.getDefaultAgentTaskTimeout(isInstallCommand);
 
       ComponentInfo componentInfo = ambariMetaInfo.getComponent(
           stackId.getStackName(), stackId.getStackVersion(),
@@ -455,7 +441,7 @@ public class AmbariCustomCommandExecutionHelper {
           commandParams.put(SCRIPT, script.getScript());
           commandParams.put(SCRIPT_TYPE, script.getScriptType().toString());
           if (script.getTimeout() > 0) {
-            commandTimeout = script.getTimeout();
+            commandTimeout = String.valueOf(script.getTimeout());
           }
         } else {
           String message = String.format("Component %s has not command script 
" +
@@ -466,19 +452,7 @@ public class AmbariCustomCommandExecutionHelper {
         // We don't need package/repo information to perform service check
       }
 
-      // !!! the action execution context timeout is the final say, but make 
sure it's at least 60 seconds
-      if (null != actionExecutionContext.getTimeout()) {
-        commandTimeout = actionExecutionContext.getTimeout().intValue();
-        commandTimeout = Math.max(60, commandTimeout);
-      }
-
-      commandParams.put(COMMAND_TIMEOUT, "" + commandTimeout);
-      commandParams.put(SERVICE_PACKAGE_FOLDER, 
serviceInfo.getServicePackageFolder());
-      commandParams.put(HOOKS_FOLDER, stackInfo.getStackHooksFolder());
-
-      if (effectiveClusterVersion != null) {
-       commandParams.put(KeyNames.VERSION, 
effectiveClusterVersion.getRepositoryVersion().getVersion());
-      }
+      commandParams.put(COMMAND_TIMEOUT, commandTimeout);
 
       Map<String, String> roleParams = execCmd.getRoleParams();
       if (roleParams == null) {
@@ -779,8 +753,6 @@ public class AmbariCustomCommandExecutionHelper {
       actualTimeout = actualTimeout < MIN_STRICT_SERVICE_CHECK_TIMEOUT ? 
MIN_STRICT_SERVICE_CHECK_TIMEOUT : actualTimeout;
       commandParams.put(COMMAND_TIMEOUT, Integer.toString(actualTimeout));
     }
-    commandParams.put(SERVICE_PACKAGE_FOLDER, 
serviceInfo.getServicePackageFolder());
-    commandParams.put(HOOKS_FOLDER, stackInfo.getStackHooksFolder());
 
     execCmd.setCommandParams(commandParams);
 
@@ -1149,115 +1121,8 @@ public class AmbariCustomCommandExecutionHelper {
     }
   }
 
-  /**
-   * Get repository info given a cluster and host.
-   *
-   * @param cluster  the cluster
-   * @param host     the host
-   *
-   * @return the repo info
-   *
-   * @throws AmbariException if the repository information can not be obtained
-   */
-  public String getRepoInfo(Cluster cluster, Host host) throws AmbariException 
{
-
-    return getRepoInfo(cluster, host.getOsType(), host.getOsFamily(), 
host.getHostName());
-  }
-
-  public String getRepoInfo(Cluster cluster, String hostOSType, String 
hostOSFamily, String hostName) throws AmbariException {
-
-    StackId stackId = cluster.getDesiredStackVersion();
-
-    Map<String, List<RepositoryInfo>> repos = ambariMetaInfo.getRepository(
-            stackId.getStackName(), stackId.getStackVersion());
-
-    String family = os_family.find(hostOSType);
-    if (null == family) {
-      family = hostOSFamily;
-    }
-
-    JsonElement gsonList = null;
-
-    // !!! check for the most specific first
-    if (repos.containsKey(hostOSType)) {
-      gsonList = gson.toJsonTree(repos.get(hostOSType));
-    } else if (null != family && repos.containsKey(family)) {
-      gsonList = gson.toJsonTree(repos.get(family));
-    } else {
-      LOG.warn("Could not retrieve repo information for host"
-              + ", hostname=" + hostName
-              + ", clusterName=" + cluster.getClusterName()
-              + ", stackInfo=" + stackId.getStackId());
-    }
-
-    if (null != gsonList) {
-      gsonList = updateBaseUrls(cluster, JsonArray.class.cast(gsonList));
-      return gsonList.toString();
-    } else {
-      return "";
-    }
-  }
-
-  /**
-   * Checks repo URLs against the current version for the cluster and makes
-   * adjustments to the Base URL when the current is different.
-   * @param cluster   the cluster to load the current version
-   * @param jsonArray the array containing stack repo data
-   */
-  private JsonArray updateBaseUrls(Cluster cluster, JsonArray jsonArray) 
throws AmbariException {
-    ClusterVersionEntity cve = cluster.getCurrentClusterVersion();
-
-    if (null == cve) {
-      List<ClusterVersionEntity> list = 
clusterVersionDAO.findByClusterAndState(cluster.getClusterName(),
-          RepositoryVersionState.INIT);
-
-      if (!list.isEmpty()) {
-        if (list.size() > 1) {
-          throw new AmbariException(String.format("The cluster can only be 
initialized by one version: %s found",
-              list.size()));
-        } else {
-          cve = list.get(0);
-        }
-      }
-    }
-
-    if (null == cve || null == cve.getRepositoryVersion()) {
-      LOG.info("Cluster {} has no specific Repository Versions.  Using 
stack-defined values", cluster.getClusterName());
-      return jsonArray;
-    }
 
-    RepositoryVersionEntity rve = cve.getRepositoryVersion();
 
-    JsonArray result = new JsonArray();
-
-    for (JsonElement e : jsonArray) {
-      JsonObject obj = e.getAsJsonObject();
-
-      String repoId = obj.has("repoId") ? obj.get("repoId").getAsString() : 
null;
-      String repoName = obj.has("repoName") ? 
obj.get("repoName").getAsString() : null;
-      String baseUrl = obj.has("baseUrl") ? obj.get("baseUrl").getAsString() : 
null;
-      String osType = obj.has("osType") ? obj.get("osType").getAsString() : 
null;
-
-      if (null == repoId || null == baseUrl || null == osType || null == 
repoName) {
-        continue;
-      }
-
-      for (OperatingSystemEntity ose : rve.getOperatingSystems()) {
-        if (ose.getOsType().equals(osType) && ose.isAmbariManagedRepos()) {
-          for (RepositoryEntity re : ose.getRepositories()) {
-            if (re.getName().equals(repoName) &&
-                re.getRepositoryId().equals(repoId) &&
-                !re.getBaseUrl().equals(baseUrl)) {
-              obj.addProperty("baseUrl", re.getBaseUrl());
-            }
-          }
-        result.add(e);
-        }
-      }
-    }
-
-    return result;
-  }
 
 
   /**

Reply via email to