You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by mp...@apache.org on 2017/06/22 15:28:12 UTC

[1/4] ambari git commit: AMBARI-21201. Add ConfigChange event to capture config changes (mpapirkovskyy)

Repository: ambari
Updated Branches:
  refs/heads/branch-3.0-perf 670a08eed -> 421ac2776


http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java
index a2d2270..2cf7b80 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java
@@ -18,15 +18,23 @@
 
 package org.apache.ambari.server.events;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.controller.internal.CalculatedStatus;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
+import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
 import org.apache.ambari.server.orm.entities.RequestEntity;
 import org.apache.ambari.server.topology.TopologyManager;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class RequestUpdateEvent extends AmbariUpdateEvent {
 
-  private Long clusterId;
+  private String clusterName;
   private Long endTime;
   private Long requestId;
   private Double progressPercent;
@@ -34,16 +42,29 @@ public class RequestUpdateEvent extends AmbariUpdateEvent {
   private HostRoleStatus requestStatus;
   private Long startTime;
 
+  @JsonProperty("Tasks")
+  private List<HostRoleCommand> hostRoleCommands = new ArrayList<>();
 
-  public RequestUpdateEvent(RequestEntity requestEntity, HostRoleCommandDAO hostRoleCommandDAO, TopologyManager topologyManager) {
+  public RequestUpdateEvent(RequestEntity requestEntity,
+                            HostRoleCommandDAO hostRoleCommandDAO,
+                            TopologyManager topologyManager,
+                            String clusterName,
+                            List<HostRoleCommandEntity> hostRoleCommandEntities) {
     super(Type.REQUEST);
-    this.clusterId = requestEntity.getClusterId();
+    this.clusterName = clusterName;
     this.endTime = requestEntity.getEndTime();
     this.requestId = requestEntity.getRequestId();
     this.progressPercent = CalculatedStatus.statusFromRequest(hostRoleCommandDAO, topologyManager, requestEntity.getRequestId()).getPercent();
     this.requestContext = requestEntity.getRequestContext();
     this.requestStatus = requestEntity.getStatus();
     this.startTime = requestEntity.getStartTime();
+
+    for (HostRoleCommandEntity hostRoleCommandEntity : hostRoleCommandEntities) {
+      hostRoleCommands.add(new HostRoleCommand(hostRoleCommandEntity.getTaskId(),
+          hostRoleCommandEntity.getRequestId(),
+          hostRoleCommandEntity.getStatus(),
+          hostRoleCommandEntity.getHostName()));
+    }
   }
 
   public Long getRequestId() {
@@ -54,12 +75,12 @@ public class RequestUpdateEvent extends AmbariUpdateEvent {
     this.requestId = requestId;
   }
 
-  public Long getClusterId() {
-    return clusterId;
+  public String getClusterName() {
+    return clusterName;
   }
 
-  public void setClusterId(Long clusterId) {
-    this.clusterId = clusterId;
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
   }
 
   public String getRequestContext() {
@@ -101,4 +122,50 @@ public class RequestUpdateEvent extends AmbariUpdateEvent {
   public void setStartTime(Long startTime) {
     this.startTime = startTime;
   }
+
+  public class HostRoleCommand {
+    private Long id;
+    private Long requestId;
+    private HostRoleStatus status;
+    private String hostName;
+
+    public HostRoleCommand(Long id, Long requestId, HostRoleStatus status, String hostName) {
+      this.id = id;
+      this.requestId = requestId;
+      this.status = status;
+      this.hostName = hostName;
+    }
+
+    public Long getId() {
+      return id;
+    }
+
+    public void setId(Long id) {
+      this.id = id;
+    }
+
+    public Long getRequestId() {
+      return requestId;
+    }
+
+    public void setRequestId(Long requestId) {
+      this.requestId = requestId;
+    }
+
+    public HostRoleStatus getStatus() {
+      return status;
+    }
+
+    public void setStatus(HostRoleStatus status) {
+      this.status = status;
+    }
+
+    public String getHostName() {
+      return hostName;
+    }
+
+    public void setHostName(String hostName) {
+      this.hostName = hostName;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java
index 49d2f78..cfab422 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java
@@ -17,29 +17,34 @@
  */
 package org.apache.ambari.server.events;
 
-import java.util.Map;
+import java.util.TreeMap;
 
+import org.apache.ambari.server.agent.stomp.dto.Hashable;
 import org.apache.ambari.server.agent.stomp.dto.TopologyCluster;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class TopologyUpdateEvent extends AmbariUpdateEvent {
-  @JsonProperty("clustersTopologies")
-  private Map<String, TopologyCluster> clusters;
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class TopologyUpdateEvent extends AmbariUpdateEvent implements Hashable {
+  @JsonProperty("clusters")
+  private TreeMap<String, TopologyCluster> clusters;
+
+  private String hash;
 
   private EventType eventType;
 
-  public TopologyUpdateEvent(Map<String, TopologyCluster> clusters, EventType eventType) {
+  public TopologyUpdateEvent(TreeMap<String, TopologyCluster> clusters, EventType eventType) {
     super(Type.TOPOLOGY);
     this.clusters = clusters;
     this.eventType = eventType;
   }
 
-  public Map<String, TopologyCluster> getClusters() {
+  public TreeMap<String, TopologyCluster> getClusters() {
     return clusters;
   }
 
-  public void setClusters(Map<String, TopologyCluster> clusters) {
+  public void setClusters(TreeMap<String, TopologyCluster> clusters) {
     this.clusters = clusters;
   }
 
@@ -51,8 +56,20 @@ public class TopologyUpdateEvent extends AmbariUpdateEvent {
     this.eventType = eventType;
   }
 
+  public String getHash() {
+    return hash;
+  }
+
+  public void setHash(String hash) {
+    this.hash = hash;
+  }
+
+  public static TopologyUpdateEvent emptyUpdate() {
+    return new TopologyUpdateEvent(null, null);
+  }
+
   public enum EventType {
-    ADD,
+    CREATE,
     DELETE,
     UPDATE
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
index 0976fd5..c34b95a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
@@ -18,12 +18,15 @@
 package org.apache.ambari.server.events.listeners.alerts;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.locks.Lock;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.EagerSingleton;
+import org.apache.ambari.server.api.query.render.AlertSummaryGroupedRenderer;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.controller.RootServiceResponseFactory.Components;
@@ -149,6 +152,7 @@ public class AlertReceivedListener {
 
     List<AlertEvent> alertEvents = new ArrayList<>(20);
     List<Alert> updatedAlerts = new ArrayList<>();
+    Map<String, AlertSummaryGroupedRenderer.AlertDefinitionSummary> summaries = new HashMap<>();
 
     for (Alert alert : alerts) {
       // jobs that were running when a service/component/host was changed
@@ -220,13 +224,7 @@ public class AlertReceivedListener {
 
           // this new alert must reflect the correct MM state for the
           // service/component/host
-          MaintenanceState maintenanceState = MaintenanceState.OFF;
-          try {
-            maintenanceState = m_maintenanceStateHelper.get().getEffectiveState(clusterId, alert);
-          } catch (Exception exception) {
-            LOG.error("Unable to determine the maintenance mode state for {}, defaulting to OFF",
-                alert, exception);
-          }
+          MaintenanceState maintenanceState = getMaintenanceState(alert, clusterId);
 
           current = new AlertCurrentEntity();
           current.setMaintenanceState(maintenanceState);
@@ -346,6 +344,11 @@ public class AlertReceivedListener {
         // create the event to fire later
         alertEvents.add(new AlertStateChangeEvent(clusterId, alert, current, oldState, oldFirmness));
         updatedAlerts.add(alert);
+
+        // create alert update to fire event to UI
+        MaintenanceState maintenanceState = getMaintenanceState(alert, clusterId);
+        AlertSummaryGroupedRenderer.updateSummary(summaries, definition.getDefinitionId(),
+            definition.getDefinitionName(), alertState, alert.getTimestamp(), maintenanceState, alert.getText());
       }
     }
 
@@ -357,9 +360,20 @@ public class AlertReceivedListener {
     for (AlertEvent eventToFire : alertEvents) {
       m_alertEventPublisher.publish(eventToFire);
     }
-    if (!updatedAlerts.isEmpty()) {
-      stateUpdateEventPublisher.publish(new AlertUpdateEvent(updatedAlerts));
+    if (!summaries.isEmpty()) {
+      stateUpdateEventPublisher.publish(new AlertUpdateEvent(summaries));
+    }
+  }
+
+  private MaintenanceState getMaintenanceState(Alert alert, Long clusterId) {
+    MaintenanceState maintenanceState = MaintenanceState.OFF;
+    try {
+      maintenanceState = m_maintenanceStateHelper.get().getEffectiveState(clusterId, alert);
+    } catch (Exception exception) {
+      LOG.error("Unable to determine the maintenance mode state for {}, defaulting to OFF",
+          alert, exception);
     }
+    return maintenanceState;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListener.java
index 9eb9f77..6bb3b69 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListener.java
@@ -1,4 +1,3 @@
-
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -28,6 +27,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.ambari.server.ClusterNotFoundException;
 import org.apache.ambari.server.EagerSingleton;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.actionmanager.HostRoleCommand;
@@ -35,14 +35,18 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.actionmanager.Request;
 import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.controller.internal.CalculatedStatus;
+import org.apache.ambari.server.events.NamedHostRoleCommandUpdateEvent;
 import org.apache.ambari.server.events.RequestUpdateEvent;
 import org.apache.ambari.server.events.TaskCreateEvent;
 import org.apache.ambari.server.events.TaskUpdateEvent;
 import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
 import org.apache.ambari.server.events.publishers.TaskEventPublisher;
+import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
 import org.apache.ambari.server.orm.dao.RequestDAO;
 import org.apache.ambari.server.orm.dao.StageDAO;
+import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
 import org.apache.ambari.server.orm.entities.RequestEntity;
 import org.apache.ambari.server.orm.entities.RoleSuccessCriteriaEntity;
 import org.apache.ambari.server.orm.entities.StageEntity;
@@ -102,17 +106,20 @@ public class TaskStatusListener {
 
   private StateUpdateEventPublisher stateUpdateEventPublisher;
 
+  private ClusterDAO clusterDAO;
 
   @Inject
   public TaskStatusListener(TaskEventPublisher taskEventPublisher, StageDAO stageDAO, RequestDAO requestDAO,
                             StateUpdateEventPublisher stateUpdateEventPublisher,
                             HostRoleCommandDAO hostRoleCommandDAO,
-                            TopologyManager topologyManager) {
+                            TopologyManager topologyManager,
+                            ClusterDAO clusterDAO) {
     this.stageDAO = stageDAO;
     this.requestDAO = requestDAO;
     this.stateUpdateEventPublisher = stateUpdateEventPublisher;
     this.hostRoleCommandDAO = hostRoleCommandDAO;
     this.topologyManager = topologyManager;
+    this.clusterDAO = clusterDAO;
     taskEventPublisher.register(this);
   }
 
@@ -134,7 +141,7 @@ public class TaskStatusListener {
    * @param event Consumes {@link TaskUpdateEvent}.
    */
   @Subscribe
-  public void onTaskUpdateEvent(TaskUpdateEvent event) {
+  public void onTaskUpdateEvent(TaskUpdateEvent event) throws ClusterNotFoundException {
     LOG.debug("Received task update event {}", event);
     List<HostRoleCommand> hostRoleCommandListAll = event.getHostRoleCommands();
     List<HostRoleCommand>  hostRoleCommandWithReceivedStatus =  new ArrayList<>();
@@ -155,6 +162,19 @@ public class TaskStatusListener {
       }
     }
 
+    for (HostRoleCommand hostRoleCommand : hostRoleCommandWithReceivedStatus) {
+      NamedHostRoleCommandUpdateEvent namedHostRoleCommandUpdateEvent = new NamedHostRoleCommandUpdateEvent(hostRoleCommand.getTaskId(),
+          hostRoleCommand.getRequestId(),
+          hostRoleCommand.getHostName(),
+          hostRoleCommand.getEndTime(),
+          hostRoleCommand.getStatus(),
+          hostRoleCommand.getErrorLog(),
+          hostRoleCommand.getOutputLog(),
+          hostRoleCommand.getStderr(),
+          hostRoleCommand.getStdout()
+      );
+      stateUpdateEventPublisher.publish(namedHostRoleCommandUpdateEvent);
+    }
     updateActiveTasksMap(hostRoleCommandWithReceivedStatus);
     Boolean didAnyStageStatusUpdated = updateActiveStagesStatus(stagesWithReceivedTaskStatus, hostRoleCommandListAll);
     // Presumption: If there is no update in any of the running stage's status
@@ -273,14 +293,23 @@ public class TaskStatusListener {
    * @param requestIdsWithReceivedTaskStatus set of request ids that has received tasks status
    * @param stagesWithChangedTaskStatus set of stages that have received tasks with changed status
    */
-  private void updateActiveRequestsStatus(final Set<Long> requestIdsWithReceivedTaskStatus, Set<StageEntityPK> stagesWithChangedTaskStatus) {
+  private void updateActiveRequestsStatus(final Set<Long> requestIdsWithReceivedTaskStatus, Set<StageEntityPK> stagesWithChangedTaskStatus) throws ClusterNotFoundException {
     for (Long reportedRequestId : requestIdsWithReceivedTaskStatus) {
       if (activeRequestMap.containsKey(reportedRequestId)) {
         ActiveRequest request =  activeRequestMap.get(reportedRequestId);
         Boolean didStatusChange = updateRequestStatus(reportedRequestId, stagesWithChangedTaskStatus);
         if (didStatusChange) {
           RequestEntity updated = requestDAO.updateStatus(reportedRequestId, request.getStatus(), request.getDisplayStatus());
-          stateUpdateEventPublisher.publish(new RequestUpdateEvent(updated, hostRoleCommandDAO, topologyManager));
+          ClusterEntity clusterEntity = clusterDAO.findById(updated.getClusterId());
+          if (clusterEntity == null) {
+            throw new ClusterNotFoundException(updated.getClusterId());
+          }
+          List<HostRoleCommandEntity> hostRoleCommandEntities = hostRoleCommandDAO.findByRequest(updated.getRequestId());
+          stateUpdateEventPublisher.publish(new RequestUpdateEvent(updated,
+              hostRoleCommandDAO,
+              topologyManager,
+              clusterEntity.getClusterName(),
+              hostRoleCommandEntities));
         }
         if (request.isCompleted() && isAllTasksCompleted(reportedRequestId)) {
           // Request is considered ton have been finished if request status and all of it's tasks status are completed

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceConfigDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceConfigDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceConfigDAO.java
index 49ad682..de2d25a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceConfigDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceConfigDAO.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.server.orm.dao;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -103,6 +104,19 @@ public class ServiceConfigDAO {
     return result;
   }
 
+  @RequiresSession
+  public ServiceConfigEntity getLastServiceConfigVersionsForGroup(Long configGroupId) {
+    if (configGroupId == null) {
+      return null;
+    }
+    List<ServiceConfigEntity> result =
+        getLastServiceConfigVersionsForGroups(new ArrayList<>(Arrays.asList(configGroupId)));
+    if (result.isEmpty()) {
+      return null;
+    }
+    return result.get(0);
+  }
+
 
 
   @RequiresSession
@@ -145,6 +159,26 @@ public class ServiceConfigDAO {
   }
 
   /**
+   *  Gets the latest service config versions of default config group for a service
+   * @param clusterId
+   *          the cluster (not {@code null}).
+   * @param serviceName
+   *          Name of the service whose latest service config versions needs to be retrieved .
+   * @return all default group service configurations for the cluster and service.
+   */
+  @RequiresSession
+  public ServiceConfigEntity getLastServiceConfigForServiceDefaultGroup(Long clusterId, String serviceName) {
+    TypedQuery<ServiceConfigEntity> query = entityManagerProvider.get().createNamedQuery(
+        "ServiceConfigEntity.findLatestServiceConfigsByServiceDefaultGroup",
+        ServiceConfigEntity.class);
+
+    query.setParameter("clusterId", clusterId);
+    query.setParameter("serviceName", serviceName);
+
+    return daoUtils.selectOne(query);
+  }
+
+  /**
    * Get all service configurations for the specified cluster and stack. This
    * will return different versions of the same configuration (HDFS v1 and v2)
    * if they exist.

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java
index a7ee0f6..50dcd1c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java
@@ -51,6 +51,7 @@ import javax.persistence.TableGenerator;
     @NamedQuery(name = "ServiceConfigEntity.findAllServiceConfigsByStack", query = "SELECT serviceConfig FROM ServiceConfigEntity serviceConfig WHERE serviceConfig.clusterId=:clusterId AND serviceConfig.stack=:stack"),
     @NamedQuery(name = "ServiceConfigEntity.findLatestServiceConfigsByStack", query = "SELECT serviceConfig FROM ServiceConfigEntity serviceConfig WHERE serviceConfig.clusterId = :clusterId AND (serviceConfig.groupId = null OR serviceConfig.groupId IN (SELECT cg.groupId from ConfigGroupEntity cg)) AND serviceConfig.version = (SELECT MAX(serviceConfig2.version) FROM ServiceConfigEntity serviceConfig2 WHERE serviceConfig2.clusterId= :clusterId AND serviceConfig2.stack = :stack AND serviceConfig2.serviceName = serviceConfig.serviceName)"),
     @NamedQuery(name = "ServiceConfigEntity.findLatestServiceConfigsByService", query = "SELECT scv FROM ServiceConfigEntity scv WHERE scv.clusterId = :clusterId AND scv.serviceName = :serviceName AND (scv.groupId = null OR scv.groupId IN (SELECT cg.groupId from ConfigGroupEntity cg)) AND scv.version = (SELECT MAX(scv2.version) FROM ServiceConfigEntity scv2 WHERE (scv2.serviceName = :serviceName AND scv2.clusterId = :clusterId) AND (scv2.groupId = scv.groupId OR (scv2.groupId IS NULL AND scv.groupId IS NULL)))"),
+    @NamedQuery(name = "ServiceConfigEntity.findLatestServiceConfigsByServiceDefaultGroup", query = "SELECT scv FROM ServiceConfigEntity scv WHERE scv.clusterId = :clusterId AND scv.serviceName = :serviceName AND scv.groupId = null AND scv.version = (SELECT MAX(scv2.version) FROM ServiceConfigEntity scv2 WHERE (scv2.serviceName = :serviceName AND scv2.clusterId = :clusterId) AND scv2.groupId IS NULL)"),
     @NamedQuery(name = "ServiceConfigEntity.findLatestServiceConfigsByCluster", query = "SELECT scv FROM ServiceConfigEntity scv WHERE scv.clusterId = :clusterId AND scv.serviceConfigId IN (SELECT MAX(scv1.serviceConfigId) FROM ServiceConfigEntity scv1 WHERE (scv1.clusterId = :clusterId) AND (scv1.groupId IS NULL) GROUP BY scv1.serviceName)")})
 public class ServiceConfigEntity {
   @Id

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java
index f6d5557..1caa0e3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java
@@ -66,6 +66,7 @@ public class Alert {
    */
 
   @JsonProperty("name")
+  @com.fasterxml.jackson.annotation.JsonProperty("name")
   public String getName() {
     return name;
   }
@@ -74,6 +75,7 @@ public class Alert {
    * @return the service
    */
   @JsonProperty("service")
+  @com.fasterxml.jackson.annotation.JsonProperty("service")
   public String getService() {
     return service;
   }
@@ -82,6 +84,7 @@ public class Alert {
    * @return the component
    */
   @JsonProperty("component")
+  @com.fasterxml.jackson.annotation.JsonProperty("component")
   public String getComponent() {
     return component;
   }
@@ -90,6 +93,7 @@ public class Alert {
    * @return the host
    */
   @JsonProperty("host")
+  @com.fasterxml.jackson.annotation.JsonProperty("host")
   public String getHostName() {
     return hostName;
   }
@@ -98,6 +102,7 @@ public class Alert {
    * @return the state
    */
   @JsonProperty("state")
+  @com.fasterxml.jackson.annotation.JsonProperty("state")
   public AlertState getState() {
     return state;
   }
@@ -106,6 +111,7 @@ public class Alert {
    * @return a short descriptive label for the alert
    */
   @JsonProperty("label")
+  @com.fasterxml.jackson.annotation.JsonProperty("label")
   public String getLabel() {
     return label;
   }
@@ -114,6 +120,7 @@ public class Alert {
    * @param alertLabel a short descriptive label for the alert
    */
   @JsonProperty("label")
+  @com.fasterxml.jackson.annotation.JsonProperty("label")
   public void setLabel(String alertLabel) {
     label = alertLabel;
   }
@@ -122,6 +129,7 @@ public class Alert {
    * @return detail text about the alert
    */
   @JsonProperty("text")
+  @com.fasterxml.jackson.annotation.JsonProperty("text")
   public String getText() {
     return text;
   }
@@ -130,52 +138,62 @@ public class Alert {
    * @param alertText detail text about the alert
    */
   @JsonProperty("text")
+  @com.fasterxml.jackson.annotation.JsonProperty("text")
   public void setText(String alertText) {
     // middle-ellipsize the text to reduce the size to 32617 characters
     text = StringUtils.abbreviateMiddle(alertText, "…", MAX_ALERT_TEXT_SIZE);
   }
 
   @JsonProperty("instance")
+  @com.fasterxml.jackson.annotation.JsonProperty("instance")
   public String getInstance() {
     return instance;
   }
 
   @JsonProperty("instance")
+  @com.fasterxml.jackson.annotation.JsonProperty("instance")
   public void setInstance(String instance) {
     this.instance = instance;
   }
 
   @JsonProperty("name")
+  @com.fasterxml.jackson.annotation.JsonProperty("name")
   public void setName(String name) {
     this.name = name;
   }
 
   @JsonProperty("service")
+  @com.fasterxml.jackson.annotation.JsonProperty("service")
   public void setService(String service) {
     this.service = service;
   }
 
   @JsonProperty("component")
+  @com.fasterxml.jackson.annotation.JsonProperty("component")
   public void setComponent(String component) {
     this.component = component;
   }
 
   @JsonProperty("host")
+  @com.fasterxml.jackson.annotation.JsonProperty("host")
   public void setHostName(String hostName) {
     this.hostName = hostName;
   }
 
   @JsonProperty("state")
+  @com.fasterxml.jackson.annotation.JsonProperty("state")
   public void setState(AlertState state) {
     this.state = state;
   }
 
   @JsonProperty("timestamp")
+  @com.fasterxml.jackson.annotation.JsonProperty("timestamp")
   public void setTimestamp(long ts) {
     timestamp = ts;
   }
 
   @JsonProperty("timestamp")
+  @com.fasterxml.jackson.annotation.JsonProperty("timestamp")
   public long getTimestamp() {
     return timestamp;
   }
@@ -184,11 +202,13 @@ public class Alert {
    * @return
    */
   @JsonProperty("cluster")
+  @com.fasterxml.jackson.annotation.JsonProperty("cluster")
   public String getCluster() {
     return cluster;
   }
 
   @JsonProperty("cluster")
+  @com.fasterxml.jackson.annotation.JsonProperty("cluster")
   public void setCluster(String cluster){
     this.cluster = cluster;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
index 05b50ab..c661ebc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
@@ -32,9 +32,11 @@ import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.agent.stomp.dto.ClusterConfigs;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.events.AgentConfigsUpdateEvent;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
@@ -346,6 +348,70 @@ public class ConfigHelper {
   }
 
   /**
+   * Retrieves effective configurations for specified cluster and tags and merge them with
+   * present before in {@code configurations}
+   * @param configurations configurations will be merged with effective cluster configurations
+   * @param configurationTags configuration tags for cluster's desired configs
+   * @param cluster cluster to configs retrieving
+   */
+  public void getAndMergeHostConfigs(Map<String, Map<String, String>> configurations,
+                                     Map<String, Map<String, String>> configurationTags,
+                                     Cluster cluster) {
+    if (null != configurationTags && !configurationTags.isEmpty()) {
+      Map<String, Map<String, String>> configProperties =
+          getEffectiveConfigProperties(cluster, configurationTags);
+
+      // Apply the configurations present before on top of derived configs
+      for (Map.Entry<String, Map<String, String>> entry : configProperties.entrySet()) {
+        String type = entry.getKey();
+        Map<String, String> allLevelMergedConfig = entry.getValue();
+
+        if (configurations.containsKey(type)) {
+          Map<String, String> mergedConfig = getMergedConfig(allLevelMergedConfig,
+              configurations.get(type));
+
+          configurations.get(type).clear();
+          configurations.get(type).putAll(mergedConfig);
+
+        } else {
+          configurations.put(type, new HashMap<>());
+          configurations.get(type).putAll(allLevelMergedConfig);
+        }
+      }
+    }
+  }
+
+  /**
+   * Retrieves effective configuration attributes for specified cluster and tags and merge them with
+   * present before in {@code configurationAttributes}
+   * @param configurationAttributes configuration attributes will be merged with effective ones on the cluster
+   * @param configurationTags  configuration tags for cluster's desired configs
+   * @param cluster cluster to config attributes retrieving
+   */
+  public void getAndMergeHostConfigAttributes(Map<String, Map<String, Map<String, String>>> configurationAttributes,
+                                     Map<String, Map<String, String>> configurationTags,
+                                     Cluster cluster) {
+    if (null != configurationTags && !configurationTags.isEmpty()) {
+      Map<String, Map<String, Map<String, String>>> configAttributes =
+          getEffectiveConfigAttributes(cluster, configurationTags);
+
+      for (Map.Entry<String, Map<String, Map<String, String>>> attributesOccurrence : configAttributes.entrySet()) {
+        String type = attributesOccurrence.getKey();
+        Map<String, Map<String, String>> attributes = attributesOccurrence.getValue();
+
+        if (configurationAttributes != null) {
+          if (!configurationAttributes.containsKey(type)) {
+            configurationAttributes.put(type,
+                new TreeMap<>());
+          }
+          cloneAttributesMap(attributes,
+              configurationAttributes.get(type));
+        }
+      }
+    }
+  }
+
+  /**
    * Merge override attributes with original ones.
    * If overrideConfig#getPropertiesAttributes does not contain occurrence of override for any of
    * properties from overrideConfig#getProperties then persisted attribute should be removed.
@@ -1494,4 +1560,36 @@ public class ConfigHelper {
     }
   }
 
+  /**
+   * Collects actual configurations and configuration attributes for specified host.
+   * @param hostName host name to collect configurations and configuration attributes
+   * @return event ready to send to agent
+   * @throws AmbariException
+   */
+  public AgentConfigsUpdateEvent getHostActualConfigs(String hostName) throws AmbariException {
+    TreeMap<String, ClusterConfigs> clustersConfigs = new TreeMap<>();
+
+    for (Cluster cl : clusters.getClusters().values()) {
+      Map<String, Map<String, String>> configurations = new HashMap<>();
+      Map<String, Map<String, Map<String, String>>> configurationAttributes = new HashMap<>();
+      Map<String, DesiredConfig> clusterDesiredConfigs = cl.getDesiredConfigs();
+
+      Map<String, Map<String, String>> configTags =
+          getEffectiveDesiredTags(cl, hostName, clusterDesiredConfigs);
+
+      getAndMergeHostConfigs(configurations, configTags, cl);
+      getAndMergeHostConfigAttributes(configurationAttributes, configTags, cl);
+
+      // remove empty entries
+      configurations.entrySet().removeIf(e -> e.getValue().isEmpty());
+      configurationAttributes.entrySet().removeIf(e -> e.getValue().isEmpty());
+
+      clustersConfigs.put(Long.toString(cl.getClusterId()),
+          new ClusterConfigs(configurations, configurationAttributes));
+    }
+
+    AgentConfigsUpdateEvent agentConfigsUpdateEvent = new AgentConfigsUpdateEvent(clustersConfigs);
+    return agentConfigsUpdateEvent;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java
index 3995c23..2e44a7f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java
@@ -44,6 +44,8 @@ public interface ServiceComponent {
 
   String getServiceName();
 
+  String getDisplayName();
+
   long getClusterId();
 
   String getClusterName();

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
index dbc7464..3cd000f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
@@ -251,6 +251,11 @@ public class ServiceComponentImpl implements ServiceComponent {
   }
 
   @Override
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  @Override
   public long getClusterId() {
     return service.getClusterId();
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index f41c620..5ad929d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -2302,7 +2302,10 @@ public class ClusterImpl implements Cluster {
         List<ClusterConfigEntity> configEntities = getClusterConfigEntitiesByService(serviceName);
         serviceConfigEntity.setClusterConfigEntities(configEntities);
       }
-
+      Set<String> changedConfigs = getChangedConfigTypes(serviceConfigEntity,
+          configGroup == null ? null : configGroup.getId(),
+          clusterId,
+          serviceName);
 
       long nextServiceConfigVersion = serviceConfigDAO.findNextServiceConfigVersion(clusterId,
           serviceName);
@@ -2325,7 +2328,7 @@ public class ClusterImpl implements Cluster {
         serviceConfigEntity = serviceConfigDAO.merge(serviceConfigEntity);
       }
       stateUpdateEventPublisher.publish(new ConfigsUpdateEvent(serviceConfigEntity,
-          configGroup == null ? null : configGroup.getName(), groupHostNames));
+          configGroup == null ? null : configGroup.getName(), groupHostNames, changedConfigs));
     } finally {
       clusterGlobalLock.writeLock().unlock();
     }
@@ -2624,6 +2627,8 @@ public class ClusterImpl implements Cluster {
         throw new IllegalArgumentException("Config group {} doesn't exist");
       }
     }
+    Set<String> changedConfigs = getChangedConfigTypes(serviceConfigEntity,
+        serviceConfigEntity.getGroupId(), clusterId, serviceName);
 
     ClusterEntity clusterEntity = getClusterEntity();
     long nextServiceConfigVersion = serviceConfigDAO.findNextServiceConfigVersion(
@@ -2650,7 +2655,10 @@ public class ClusterImpl implements Cluster {
     }
 
     serviceConfigDAO.create(serviceConfigEntityClone);
-    stateUpdateEventPublisher.publish(new ConfigsUpdateEvent(serviceConfigEntityClone, configGroupName, groupHostNames));
+    stateUpdateEventPublisher.publish(new ConfigsUpdateEvent(serviceConfigEntityClone,
+        configGroupName,
+        groupHostNames,
+        changedConfigs));
 
     return convertToServiceConfigVersionResponse(serviceConfigEntityClone);
   }
@@ -3457,4 +3465,70 @@ public class ClusterImpl implements Cluster {
     // suspended goes in role params
     roleParams.put(KeyNames.UPGRADE_SUSPENDED, Boolean.TRUE.toString().toLowerCase());
   }
+
+  /**
+   * Calculates cluster config types were changed during configs change.
+   * @param currentServiceConfigEntity service config entity with populated current cluster configs
+   * @param configGroupId id of config group contained changed configs. Can be null in case group is default
+   * @param clusterId cluster id
+   * @param serviceName service name configs were changed for
+   * @return set of type names of cluster configs were changed
+   */
+  private Set<String> getChangedConfigTypes(ServiceConfigEntity currentServiceConfigEntity,
+                                            Long configGroupId, Long clusterId, String serviceName) {
+    ServiceConfigEntity previousServiceConfigEntity;
+    List<ClusterConfigEntity> previousConfigEntities = new ArrayList<>();
+    List<ClusterConfigEntity> currentConfigEntities = new ArrayList<>();
+    currentConfigEntities.addAll(currentServiceConfigEntity.getClusterConfigEntities());
+    // Retrieve group cluster configs
+    if (configGroupId != null) {
+      previousServiceConfigEntity =
+          serviceConfigDAO.getLastServiceConfigVersionsForGroup(configGroupId);
+      if (previousServiceConfigEntity != null) {
+        previousConfigEntities.addAll(previousServiceConfigEntity.getClusterConfigEntities());
+      }
+    }
+    // Service config with custom group contains not all config types, so it is needed
+    // to complement it with configs from default group
+    previousServiceConfigEntity =
+        serviceConfigDAO.getLastServiceConfigForServiceDefaultGroup(clusterId, serviceName);
+    if (previousServiceConfigEntity != null) {
+      for (ClusterConfigEntity clusterConfigEntity : previousServiceConfigEntity.getClusterConfigEntities()) {
+        // Add only configs not present yet
+        ClusterConfigEntity exist =
+            previousConfigEntities.stream()
+                .filter(c -> c.getType().equals(clusterConfigEntity.getType())).findAny().orElse(null);
+        if (exist == null) {
+          previousConfigEntities.add(clusterConfigEntity);
+        }
+        // Complement current custom group service config to correct comparing
+        if (configGroupId != null) {
+          exist = currentConfigEntities.stream()
+              .filter(c -> c.getType().equals(clusterConfigEntity.getType())).findAny().orElse(null);
+          if (exist == null) {
+            currentConfigEntities.add(clusterConfigEntity);
+          }
+        }
+      }
+    }
+    Map<String, String> previousConfigs = new HashMap<>();
+    Map<String, String> currentConfigs = new HashMap<>();
+    for (ClusterConfigEntity clusterConfigEntity : currentConfigEntities) {
+      currentConfigs.put(clusterConfigEntity.getType(), clusterConfigEntity.getData());
+    }
+    for (ClusterConfigEntity clusterConfigEntity : previousConfigEntities) {
+      previousConfigs.put(clusterConfigEntity.getType(), clusterConfigEntity.getData());
+    }
+    // Get diff for current and previous sets of cluster configs
+    Set<Entry<String, String>> diff1 = new HashSet<>(currentConfigs.entrySet());
+    Set<Entry<String, String>> diff2 = new HashSet<>(previousConfigs.entrySet());
+    diff1.removeAll(previousConfigs.entrySet());
+    diff2.removeAll(currentConfigs.entrySet());
+    diff1.addAll(diff2);
+    Set<String> changedConfigs = new HashSet<>();
+    for (Entry<String, String> diff : diff1) {
+      changedConfigs.add(diff.getKey());
+    }
+    return changedConfigs;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
index 2bc1e68..d59af00 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
@@ -27,6 +27,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -37,11 +38,14 @@ import org.apache.ambari.server.ClusterNotFoundException;
 import org.apache.ambari.server.DuplicateResourceException;
 import org.apache.ambari.server.HostNotFoundException;
 import org.apache.ambari.server.agent.DiskInfo;
+import org.apache.ambari.server.agent.stomp.dto.TopologyCluster;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.events.HostRegisteredEvent;
 import org.apache.ambari.server.events.HostsAddedEvent;
 import org.apache.ambari.server.events.HostsRemovedEvent;
+import org.apache.ambari.server.events.TopologyUpdateEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
+import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
 import org.apache.ambari.server.orm.dao.HostConfigMappingDAO;
@@ -160,6 +164,9 @@ public class ClustersImpl implements Clusters {
   private AmbariEventPublisher eventPublisher;
 
   @Inject
+  private StateUpdateEventPublisher stateUpdateEventPublisher;
+
+  @Inject
   public ClustersImpl(ClusterDAO clusterDAO, ClusterFactory clusterFactory, HostDAO hostDAO,
       HostFactory hostFactory) {
 
@@ -263,6 +270,14 @@ public class ClustersImpl implements Clusters {
         Collections.newSetFromMap(new ConcurrentHashMap<Host, Boolean>()));
 
     cluster.setCurrentStackVersion(stackId);
+
+    TreeMap<String, TopologyCluster> addedClusters = new TreeMap<>();
+    TopologyCluster addedCluster = new TopologyCluster();
+    addedCluster.setClusterName(clusterName);
+    addedClusters.put(Long.toString(cluster.getClusterId()), addedCluster);
+    TopologyUpdateEvent topologyUpdateEvent = new TopologyUpdateEvent(addedClusters,
+        TopologyUpdateEvent.EventType.UPDATE);
+    stateUpdateEventPublisher.publish(topologyUpdateEvent);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
index 6ba9ff7..149481a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
@@ -905,13 +906,15 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
     if (stateEntity != null) {
       stateEntity.setVersion(version);
       stateEntity = hostComponentStateDAO.merge(stateEntity);
-      Map<String, TopologyCluster> topologyUpdates = new HashMap<>();
+      TreeMap<String, TopologyCluster> topologyUpdates = new TreeMap<>();
       topologyUpdates.put(Long.toString(getClusterId()), new TopologyCluster());
       Long hostId = getHost().getHostId();
       topologyUpdates.get(Long.toString(getClusterId())).addTopologyComponent(TopologyComponent.newBuilder()
           .setComponentName(getServiceComponentName())
+          .setServiceName(getServiceName())
           .setVersion(stateEntity.getVersion())
           .setHostIds(new HashSet<>(Collections.singletonList(hostId)))
+          .setHostNames(new HashSet<>(Collections.singletonList(hostName)))
           .build());
       TopologyUpdateEvent hostComponentVersionUpdate = new TopologyUpdateEvent(topologyUpdates,
           TopologyUpdateEvent.EventType.UPDATE);
@@ -1417,6 +1420,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
       eventPublisher.publish(event);
       deleteMetaData.addDeletedHostComponent(componentName,
+          serviceName,
           hostName,
           getHost().getHostId(),
           Long.toString(clusterId),

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyDeleteFormer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyDeleteFormer.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyDeleteFormer.java
index 199f127..1ba4cc9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyDeleteFormer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyDeleteFormer.java
@@ -19,9 +19,8 @@
 package org.apache.ambari.server.topology;
 
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Map;
+import java.util.TreeMap;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.agent.stomp.dto.TopologyCluster;
@@ -60,7 +59,7 @@ public class TopologyDeleteFormer {
   }
 
   public void processDeleteCluster(String clusterId) {
-    Map<String, TopologyCluster> topologyUpdates = new HashMap<>();
+    TreeMap<String, TopologyCluster> topologyUpdates = new TreeMap<>();
     topologyUpdates.put(clusterId, new TopologyCluster());
     TopologyUpdateEvent topologyUpdateEvent = new TopologyUpdateEvent(
         topologyUpdates,
@@ -69,14 +68,16 @@ public class TopologyDeleteFormer {
     stateUpdateEventPublisher.publish(topologyUpdateEvent);
   }
 
-  public Map<String, TopologyCluster> createUpdateFromDeleteMetaData(DeleteHostComponentStatusMetaData metaData) {
-    Map<String, TopologyCluster> topologyUpdates = new HashMap<>();
+  public TreeMap<String, TopologyCluster> createUpdateFromDeleteMetaData(DeleteHostComponentStatusMetaData metaData) {
+    TreeMap<String, TopologyCluster> topologyUpdates = new TreeMap<>();
 
     for (DeleteHostComponentStatusMetaData.HostComponent hostComponent : metaData.getRemovedHostComponents()) {
       TopologyComponent deletedComponent = TopologyComponent.newBuilder()
           .setComponentName(hostComponent.getComponentName())
+          .setServiceName(hostComponent.getServiceName())
           .setVersion(hostComponent.getVersion())
           .setHostIds(new HashSet<>(Arrays.asList(hostComponent.getHostId())))
+          .setHostNames(new HashSet<>(Arrays.asList(hostComponent.getHostName())))
           .build();
 
       String clusterId = hostComponent.getClusterId();
@@ -89,6 +90,9 @@ public class TopologyDeleteFormer {
       } else {
         topologyUpdates.get(clusterId).getTopologyComponents()
             .stream().filter(t -> t.equals(deletedComponent))
+            .forEach(t -> t.addHostName(hostComponent.getHostName()));
+        topologyUpdates.get(clusterId).getTopologyComponents()
+            .stream().filter(t -> t.equals(deletedComponent))
             .forEach(t -> t.addHostId(hostComponent.getHostId()));
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListenerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListenerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListenerTest.java
index 896b576..c76090e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListenerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/tasks/TaskStatusListenerTest.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.ambari.server.ClusterNotFoundException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.actionmanager.ExecutionCommandWrapperFactory;
@@ -34,6 +35,7 @@ import org.apache.ambari.server.events.TaskCreateEvent;
 import org.apache.ambari.server.events.TaskUpdateEvent;
 import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
 import org.apache.ambari.server.events.publishers.TaskEventPublisher;
+import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ExecutionCommandDAO;
 import org.apache.ambari.server.orm.dao.HostDAO;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
@@ -66,7 +68,7 @@ public class TaskStatusListenerTest extends EasyMockSupport {
 
 
   @Test
-  public void testOnTaskUpdateEvent() {
+  public void testOnTaskUpdateEvent() throws ClusterNotFoundException {
     List<HostRoleCommand> hostRoleCommands = new ArrayList<>();
     ServiceComponentHostEvent serviceComponentHostEvent = createNiceMock(ServiceComponentHostEvent.class);
     HostDAO hostDAO = createNiceMock(HostDAO.class);
@@ -93,6 +95,7 @@ public class TaskStatusListenerTest extends EasyMockSupport {
     TopologyManager topologyManager = createNiceMock(TopologyManager.class);
     RequestDAO requestDAO = createNiceMock(RequestDAO.class);
     StageEntity stageEntity = createNiceMock(StageEntity.class);
+    ClusterDAO clusterDAO = createNiceMock(ClusterDAO.class);
     RequestEntity requestEntity = createNiceMock(RequestEntity.class);
     EasyMock.expect(stageEntity.getStatus()).andReturn(hostRoleStatus).anyTimes();;
     EasyMock.expect(stageEntity.getDisplayStatus()).andReturn(hostRoleStatus).anyTimes();
@@ -115,7 +118,7 @@ public class TaskStatusListenerTest extends EasyMockSupport {
 
     TaskCreateEvent event = new TaskCreateEvent(hostRoleCommands);
     TaskStatusListener listener = new TaskStatusListener(publisher,stageDAO,requestDAO,statePublisher,
-        hostRoleCommandDAO,topologyManager);
+        hostRoleCommandDAO,topologyManager, clusterDAO);
 
     Assert.assertTrue(listener.getActiveTasksMap().isEmpty());
     Assert.assertTrue(listener.getActiveStageMap().isEmpty());


[2/4] ambari git commit: AMBARI-21201. Add ConfigChange event to capture config changes (mpapirkovskyy)

Posted by mp...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 2a3e4bc..a53570c 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
@@ -19,27 +19,27 @@
 package org.apache.ambari.server.agent.stomp.dto;
 
 import java.util.List;
-import java.util.Map;
+import java.util.TreeMap;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class ComponentStatusReports {
 
   @JsonProperty("clustersReports")
-  private Map<String, List<ComponentStatusReport>> componentStatusReports;
+  private TreeMap<String, List<ComponentStatusReport>> componentStatusReports;
 
   public ComponentStatusReports() {
   }
 
-  public ComponentStatusReports(Map<String, List<ComponentStatusReport>> componentStatusReports) {
+  public ComponentStatusReports(TreeMap<String, List<ComponentStatusReport>> componentStatusReports) {
     this.componentStatusReports = componentStatusReports;
   }
 
-  public Map<String, List<ComponentStatusReport>> getComponentStatusReports() {
+  public TreeMap<String, List<ComponentStatusReport>> getComponentStatusReports() {
     return componentStatusReports;
   }
 
-  public void setComponentStatusReports(Map<String, List<ComponentStatusReport>> componentStatusReports) {
+  public void setComponentStatusReports(TreeMap<String, List<ComponentStatusReport>> componentStatusReports) {
     this.componentStatusReports = componentStatusReports;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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
new file mode 100644
index 0000000..19f9597
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hash.java
@@ -0,0 +1,41 @@
+/**
+ * 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;
+
+/**
+ * Is used to contain hash code in request from agent
+ */
+public class Hash {
+  private String hash;
+
+  public Hash(String hash) {
+    this.hash = hash;
+  }
+
+  public Hash() {
+  }
+
+  public String getHash() {
+    return hash;
+  }
+
+  public void setHash(String hash) {
+    this.hash = hash;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hashable.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hashable.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hashable.java
new file mode 100644
index 0000000..0035893
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/Hashable.java
@@ -0,0 +1,27 @@
+/**
+ * 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;
+
+/**
+ * Update event object has hash to identify actual version
+ */
+public interface Hashable {
+  String getHash();
+  void setHash(String hash);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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
new file mode 100644
index 0000000..07e85df
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataCluster.java
@@ -0,0 +1,69 @@
+/**
+ * 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 java.util.TreeMap;
+
+import org.apache.ambari.server.state.SecurityType;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+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;
+
+  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");
+    }
+    this.serviceLevelParams = serviceLevelParams;
+    this.clusterLevelParams = clusterLevelParams;
+  }
+
+  public List<String> getStatusCommandsToRun() {
+    return statusCommandsToRun;
+  }
+
+  public void setStatusCommandsToRun(List<String> statusCommandsToRun) {
+    this.statusCommandsToRun = statusCommandsToRun;
+  }
+
+  public TreeMap<String, MetadataServiceInfo> getServiceLevelParams() {
+    return serviceLevelParams;
+  }
+
+  public void setServiceLevelParams(TreeMap<String, MetadataServiceInfo> serviceLevelParams) {
+    this.serviceLevelParams = serviceLevelParams;
+  }
+
+  public TreeMap<String, String> getClusterLevelParams() {
+    return clusterLevelParams;
+  }
+
+  public void setClusterLevelParams(TreeMap<String, String> clusterLevelParams) {
+    this.clusterLevelParams = clusterLevelParams;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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
new file mode 100644
index 0000000..aea8986
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/MetadataServiceInfo.java
@@ -0,0 +1,71 @@
+/**
+ * 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 com.fasterxml.jackson.annotation.JsonProperty;
+
+public class MetadataServiceInfo {
+  private String version;
+  private Boolean credentialStoreEnabled;
+  @JsonProperty("status_commands_timeout")
+  private Long statusCommandsTimeout;
+
+  @JsonProperty("service_package_folder")
+  private String servicePackageFolder;
+
+  public MetadataServiceInfo(String version, Boolean credentialStoreEnabled, Long statusCommandsTimeout,
+                             String servicePackageFolder) {
+    this.version = version;
+    this.credentialStoreEnabled = credentialStoreEnabled;
+    this.statusCommandsTimeout = statusCommandsTimeout;
+    this.servicePackageFolder = servicePackageFolder;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+
+  public void setVersion(String version) {
+    this.version = version;
+  }
+
+  public Boolean getCredentialStoreEnabled() {
+    return credentialStoreEnabled;
+  }
+
+  public void setCredentialStoreEnabled(Boolean credentialStoreEnabled) {
+    this.credentialStoreEnabled = credentialStoreEnabled;
+  }
+
+  public Long getStatusCommandsTimeout() {
+    return statusCommandsTimeout;
+  }
+
+  public void setStatusCommandsTimeout(Long statusCommandsTimeout) {
+    this.statusCommandsTimeout = statusCommandsTimeout;
+  }
+
+  public String getServicePackageFolder() {
+    return servicePackageFolder;
+  }
+
+  public void setServicePackageFolder(String servicePackageFolder) {
+    this.servicePackageFolder = servicePackageFolder;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 4ddb8a6..7a464df 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
@@ -18,13 +18,22 @@
 package org.apache.ambari.server.agent.stomp.dto;
 
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 
+import org.apache.ambari.server.events.TopologyUpdateEvent;
+
 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<>();
+
+  @JsonProperty("hosts")
   private Set<TopologyHost> topologyHosts = new HashSet<>();
 
   public TopologyCluster() {
@@ -35,6 +44,45 @@ public class TopologyCluster {
     this.topologyHosts = topologyHosts;
   }
 
+  public void update(Set<TopologyComponent> componentsToUpdate, Set<TopologyHost> hostsToUpdate,
+                     TopologyUpdateEvent.EventType eventType) {
+    for (TopologyComponent componentToUpdate : componentsToUpdate) {
+      boolean updated = false;
+      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();
+          } else {
+            existsComponent.updateComponent(componentToUpdate);
+          }
+          updated = true;
+        }
+      }
+      if (!updated && eventType.equals(TopologyUpdateEvent.EventType.UPDATE)) {
+        getTopologyComponents().add(componentToUpdate);
+      }
+    }
+    for (TopologyHost hostToUpdate : hostsToUpdate) {
+      boolean updated = false;
+      for (Iterator<TopologyHost> iter = getTopologyHosts().iterator(); iter.hasNext() && !updated; ) {
+        TopologyHost existsHost = iter.next();
+        if (existsHost.equals(hostToUpdate)) {
+          if (eventType.equals(TopologyUpdateEvent.EventType.DELETE)) {
+            iter.remove();
+          } else {
+            existsHost.updateHost(hostToUpdate);
+          }
+          updated = true;
+        }
+      }
+      if (!updated && eventType.equals(TopologyUpdateEvent.EventType.UPDATE)) {
+        getTopologyHosts().add(hostToUpdate);
+      }
+    }
+  }
+
   public Set<TopologyComponent> getTopologyComponents() {
     return topologyComponents;
   }
@@ -58,4 +106,12 @@ public class TopologyCluster {
   public void addTopologyComponent(TopologyComponent topologyComponent) {
     topologyComponents.add(topologyComponent);
   }
+
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 019c933..dabbe94 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
@@ -18,7 +18,13 @@
 
 package org.apache.ambari.server.agent.stomp.dto;
 
+import java.util.HashSet;
 import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 
@@ -26,9 +32,12 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 public class TopologyComponent {
   private String componentName;
   private String serviceName;
+  private String displayName;
   private String version;
   private Set<Long> hostIds;
-  private TopologyStatusCommandParams statusCommandParams;
+  private Set<String> hostNames;
+  private Set<String> publicHostNames;
+  private TreeMap<String, String> componentLevelParams;
 
   private TopologyComponent() {
   }
@@ -52,6 +61,11 @@ public class TopologyComponent {
       return this;
     }
 
+    public Builder setDisplayName(String displayName) {
+      TopologyComponent.this.setDisplayName(displayName);
+      return this;
+    }
+
     public Builder setVersion(String version) {
       TopologyComponent.this.setVersion(version);
       return this;
@@ -62,8 +76,18 @@ public class TopologyComponent {
       return this;
     }
 
-    public Builder setStatusCommandParams(TopologyStatusCommandParams statusCommandParams) {
-      TopologyComponent.this.setStatusCommandParams(statusCommandParams);
+    public Builder setHostNames(Set<String> hostNames) {
+      TopologyComponent.this.setHostNames(hostNames);
+      return this;
+    }
+
+    public Builder setPublicHostNames(Set<String> publicHostNames) {
+      TopologyComponent.this.setPublicHostNames(publicHostNames);
+      return this;
+    }
+
+    public Builder setComponentLevelParams(TreeMap<String, String> componentLevelParams) {
+      TopologyComponent.this.setComponentLevelParams(componentLevelParams);
       return this;
     }
 
@@ -72,6 +96,36 @@ public class TopologyComponent {
     }
   }
 
+  public void updateComponent(TopologyComponent componentToUpdate) {
+    //TODO will be a need to change to multi-instance usage
+    if (componentToUpdate.getComponentName().equals(getComponentName())) {
+      if (StringUtils.isNotEmpty(componentToUpdate.getVersion())) {
+        setVersion(componentToUpdate.getVersion());
+      }
+      if (CollectionUtils.isNotEmpty(componentToUpdate.getHostIds())) {
+        if (hostIds == null) {
+          hostIds = new HashSet<>();
+        }
+        hostIds.addAll(componentToUpdate.getHostIds());
+      }
+      if (CollectionUtils.isNotEmpty(componentToUpdate.getHostNames())) {
+        if (hostNames == null) {
+          hostNames = new HashSet<>();
+        }
+        hostNames.addAll(componentToUpdate.getHostNames());
+      }
+      if (CollectionUtils.isNotEmpty(componentToUpdate.getPublicHostNames())) {
+        if (publicHostNames == null) {
+          publicHostNames = new HashSet<>();
+        }
+        publicHostNames.addAll(componentToUpdate.getPublicHostNames());
+      }
+      if (MapUtils.isNotEmpty(componentToUpdate.getComponentLevelParams())) {
+        componentLevelParams.putAll(componentToUpdate.getComponentLevelParams());
+      }
+    }
+  }
+
   public String getComponentName() {
     return componentName;
   }
@@ -108,14 +162,43 @@ public class TopologyComponent {
     this.hostIds.add(hostId);
   }
 
-  public TopologyStatusCommandParams getStatusCommandParams() {
-    return statusCommandParams;
+  public void addHostName(String hostName) {
+    this.hostNames.add(hostName);
+  }
+
+  public TreeMap<String, String> getComponentLevelParams() {
+    return componentLevelParams;
+  }
+
+  public void setComponentLevelParams(TreeMap<String, String> componentLevelParams) {
+    this.componentLevelParams = componentLevelParams;
+  }
+
+  public Set<String> getHostNames() {
+    return hostNames;
+  }
+
+  public void setHostNames(Set<String> hostNames) {
+    this.hostNames = hostNames;
   }
 
-  public void setStatusCommandParams(TopologyStatusCommandParams statusCommandParams) {
-    this.statusCommandParams = statusCommandParams;
+  public String getDisplayName() {
+    return displayName;
   }
 
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
+  public Set<String> getPublicHostNames() {
+    return publicHostNames;
+  }
+
+  public void setPublicHostNames(Set<String> publicHostNames) {
+    this.publicHostNames = publicHostNames;
+  }
+
+
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
@@ -124,13 +207,13 @@ public class TopologyComponent {
     TopologyComponent that = (TopologyComponent) o;
 
     if (!componentName.equals(that.componentName)) return false;
-    return version.equals(that.version);
+    return serviceName.equals(that.serviceName);
   }
 
   @Override
   public int hashCode() {
     int result = componentName.hashCode();
-    result = 31 * result + version.hashCode();
+    result = 31 * result + serviceName.hashCode();
     return result;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 1718711..84e3cff 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
@@ -17,6 +17,12 @@
  */
 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;
 
 @JsonInclude(JsonInclude.Include.NON_NULL)
@@ -25,6 +31,8 @@ public class TopologyHost {
   private String hostName;
   private String rackName;
   private String ipv4;
+  private TreeMap<String, String> hostLevelParams;
+  private RecoveryConfig recoveryConfig;
 
   public TopologyHost() {
   }
@@ -33,11 +41,31 @@ public class TopologyHost {
     this.hostId = hostId;
   }
 
-  public TopologyHost(Long hostId, String hostName, String rackName, String ipv4) {
+  public TopologyHost(Long hostId, String hostName, String rackName, String ipv4, RecoveryConfig recoveryConfig,
+                      TreeMap<String, String> hostLevelParams) {
     this.hostId = hostId;
     this.hostName = hostName;
     this.rackName = rackName;
     this.ipv4 = ipv4;
+    this.recoveryConfig = recoveryConfig;
+    this.hostLevelParams = hostLevelParams;
+  }
+
+  public void updateHost(TopologyHost hostToUpdate) {
+    if (hostToUpdate.getHostId().equals(getHostId())) {
+      if (StringUtils.isNotEmpty(hostToUpdate.getHostName())) {
+        setHostName(hostToUpdate.getHostName());
+      }
+      if (StringUtils.isNotEmpty(hostToUpdate.getRackName())) {
+        setRackName(hostToUpdate.getRackName());
+      }
+      if (StringUtils.isNotEmpty(hostToUpdate.getIpv4())) {
+        setIpv4(hostToUpdate.getIpv4());
+      }
+      if (MapUtils.isNotEmpty(hostToUpdate.getHostLevelParams())) {
+        hostLevelParams.putAll(hostToUpdate.getHostLevelParams());
+      }
+    }
   }
 
   public Long getHostId() {
@@ -72,6 +100,22 @@ 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/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyStatusCommandParams.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyStatusCommandParams.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyStatusCommandParams.java
deleted file mode 100644
index 1574066..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/TopologyStatusCommandParams.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * 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 com.fasterxml.jackson.annotation.JsonInclude;
-
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class TopologyStatusCommandParams {
-  private String script;
-  private String servicePackageFolder;
-
-  public TopologyStatusCommandParams(String script, String servicePackageFolder) {
-    this.script = script;
-    this.servicePackageFolder = servicePackageFolder;
-  }
-
-  public String getScript() {
-    return script;
-  }
-
-  public void setScript(String script) {
-    this.script = script;
-  }
-
-  public String getServicePackageFolder() {
-    return servicePackageFolder;
-  }
-
-  public void setServicePackageFolder(String servicePackageFolder) {
-    this.servicePackageFolder = servicePackageFolder;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 9d3ab9d..fe0198b 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
@@ -29,23 +29,27 @@ public final class AlertStateSummary {
    * The {@link AlertState#OK} state information.
    */
   @JsonProperty(value = "OK")
+  @com.fasterxml.jackson.annotation.JsonProperty(value = "OK")
   public final AlertStateValues Ok = new AlertStateValues();
 
   /**
    * The {@link AlertState#WARNING} state information.
    */
   @JsonProperty(value = "WARNING")
+  @com.fasterxml.jackson.annotation.JsonProperty(value = "WARNING")
   public final AlertStateValues Warning = new AlertStateValues();
 
   /**
    * The {@link AlertState#CRITICAL} state information.
    */
   @JsonProperty(value = "CRITICAL")
+  @com.fasterxml.jackson.annotation.JsonProperty(value = "CRITICAL")
   public final AlertStateValues Critical = new AlertStateValues();
 
   /**
    * The {@link AlertState#UNKNOWN} state information.
    */
   @JsonProperty(value = "UNKNOWN")
+  @com.fasterxml.jackson.annotation.JsonProperty(value = "UNKNOWN")
   public final AlertStateValues Unknown = new AlertStateValues();
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 261aa21..a99a648 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
@@ -20,6 +20,8 @@ package org.apache.ambari.server.api.query.render;
 import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
+
 /**
  * The {@link AlertStateValues} class holds various information about an alert
  * state, such as the number of instances of that state and the most recent
@@ -30,24 +32,29 @@ public final class AlertStateValues {
    * The total count of non-maintenance mode instances.
    */
   @JsonProperty(value = "count")
+  @com.fasterxml.jackson.annotation.JsonProperty(value = "count")
   public int Count = 0;
 
   /**
    * The time of the last state change.
    */
   @JsonProperty(value = "original_timestamp")
+  @com.fasterxml.jackson.annotation.JsonProperty(value = "original_timestamp")
   public long Timestamp = 0;
 
   /**
    * The total count of instances in maintenance mode.
    */
   @JsonProperty(value = "maintenance_count")
+  @com.fasterxml.jackson.annotation.JsonProperty(value = "maintenance_count")
   public int MaintenanceCount = 0;
 
   /**
    * The most recently received text from any instance of the alert.
    */
   @JsonProperty(value = "latest_text")
+  @com.fasterxml.jackson.annotation.JsonProperty(value = "latest_text")
   @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+  @JsonInclude(JsonInclude.Include.NON_NULL)
   public String AlertText = null;
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 71f82ad..a2664fa 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
@@ -138,69 +138,7 @@ public class AlertSummaryGroupedRenderer extends AlertSummaryRenderer {
       MaintenanceState maintenanceState = (MaintenanceState) resource.getPropertyValue(AlertResourceProvider.ALERT_MAINTENANCE_STATE);
       String alertText = (String) resource.getPropertyValue(AlertResourceProvider.ALERT_TEXT);
 
-      // NPE sanity
-      if (null == state) {
-        state = AlertState.UNKNOWN;
-      }
-
-      // NPE sanity
-      long originalTimestamp = 0;
-      if (null != originalTimestampObject) {
-        originalTimestamp = originalTimestampObject.longValue();
-      }
-
-      // NPE sanity
-      boolean isMaintenanceModeEnabled = false;
-      if (null != maintenanceState && maintenanceState != MaintenanceState.OFF) {
-        isMaintenanceModeEnabled = true;
-      }
-
-      // create the group summary info if it doesn't exist yet
-      AlertDefinitionSummary groupSummaryInfo = summaries.get(definitionName);
-      if (null == groupSummaryInfo) {
-        groupSummaryInfo = new AlertDefinitionSummary();
-        groupSummaryInfo.Id = definitionId;
-        groupSummaryInfo.Name = definitionName;
-
-        summaries.put(definitionName, groupSummaryInfo);
-      }
-
-      // set and increment the correct values based on state
-      final AlertStateValues alertStateValues;
-      switch (state) {
-        case CRITICAL: {
-          alertStateValues = groupSummaryInfo.State.Critical;
-          break;
-        }
-        case OK: {
-          alertStateValues = groupSummaryInfo.State.Ok;
-          break;
-        }
-        case WARNING: {
-          alertStateValues = groupSummaryInfo.State.Warning;
-          break;
-        }
-        default:
-        case UNKNOWN: {
-          alertStateValues = groupSummaryInfo.State.Unknown;
-          break;
-        }
-      }
-
-      // update the maintenance count if in MM is enabled, otherwise the
-      // regular count
-      if (isMaintenanceModeEnabled) {
-        alertStateValues.MaintenanceCount++;
-      } else {
-        alertStateValues.Count++;
-      }
-
-      // check to see if this alerts time is sooner; if so, keep track of it
-      // and of its text
-      if (originalTimestamp > alertStateValues.Timestamp) {
-        alertStateValues.Timestamp = originalTimestamp;
-        alertStateValues.AlertText = alertText;
-      }
+      updateSummary(summaries, definitionId, definitionName, state, originalTimestampObject, maintenanceState, alertText);
     }
 
     Set<Entry<String, AlertDefinitionSummary>> entrySet = summaries.entrySet();
@@ -222,6 +160,74 @@ public class AlertSummaryGroupedRenderer extends AlertSummaryRenderer {
     return groupedSummary;
   }
 
+  public static void updateSummary(Map<String, AlertDefinitionSummary> summaries, Long definitionId, String definitionName,
+                            AlertState state, Long originalTimestampObject, MaintenanceState maintenanceState,
+                            String alertText) {
+    // NPE sanity
+    if (null == state) {
+      state = AlertState.UNKNOWN;
+    }
+
+    // NPE sanity
+    long originalTimestamp = 0;
+    if (null != originalTimestampObject) {
+      originalTimestamp = originalTimestampObject.longValue();
+    }
+
+    // NPE sanity
+    boolean isMaintenanceModeEnabled = false;
+    if (null != maintenanceState && maintenanceState != MaintenanceState.OFF) {
+      isMaintenanceModeEnabled = true;
+    }
+
+    // create the group summary info if it doesn't exist yet
+    AlertDefinitionSummary groupSummaryInfo = summaries.get(definitionName);
+    if (null == groupSummaryInfo) {
+      groupSummaryInfo = new AlertDefinitionSummary();
+      groupSummaryInfo.Id = definitionId;
+      groupSummaryInfo.Name = definitionName;
+
+      summaries.put(definitionName, groupSummaryInfo);
+    }
+
+    // set and increment the correct values based on state
+    final AlertStateValues alertStateValues;
+    switch (state) {
+      case CRITICAL: {
+        alertStateValues = groupSummaryInfo.State.Critical;
+        break;
+      }
+      case OK: {
+        alertStateValues = groupSummaryInfo.State.Ok;
+        break;
+      }
+      case WARNING: {
+        alertStateValues = groupSummaryInfo.State.Warning;
+        break;
+      }
+      default:
+      case UNKNOWN: {
+        alertStateValues = groupSummaryInfo.State.Unknown;
+        break;
+      }
+    }
+
+    // update the maintenance count if in MM is enabled, otherwise the
+    // regular count
+    if (isMaintenanceModeEnabled) {
+      alertStateValues.MaintenanceCount++;
+    } else {
+      alertStateValues.Count++;
+    }
+
+    // check to see if this alerts time is sooner; if so, keep track of it
+    // and of its text
+    if (originalTimestamp > alertStateValues.Timestamp) {
+      alertStateValues.Timestamp = originalTimestamp;
+      alertStateValues.AlertText = alertText;
+    }
+  }
+
   /**
    * {@inheritDoc}
    * <p/>
@@ -245,12 +251,15 @@ public class AlertSummaryGroupedRenderer extends AlertSummaryRenderer {
    */
   public final static class AlertDefinitionSummary {
     @JsonProperty(value = "definition_id")
+    @com.fasterxml.jackson.annotation.JsonProperty(value = "definition_id")
     public long Id;
 
     @JsonProperty(value = "definition_name")
+    @com.fasterxml.jackson.annotation.JsonProperty(value = "definition_name")
     public String Name;
 
     @JsonProperty(value = "summary")
+    @com.fasterxml.jackson.annotation.JsonProperty(value = "summary")
     public final AlertStateSummary State = new AlertStateSummary();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 4887d52..65e5fd2 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
@@ -43,7 +43,6 @@ import javax.xml.bind.JAXBException;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ParentObjectNotFoundException;
 import org.apache.ambari.server.StackAccessException;
-import org.apache.ambari.server.agent.stomp.dto.TopologyStatusCommandParams;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
@@ -62,7 +61,6 @@ import org.apache.ambari.server.stack.StackManager;
 import org.apache.ambari.server.stack.StackManagerFactory;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
-import org.apache.ambari.server.state.CommandScriptDefinition;
 import org.apache.ambari.server.state.ComponentInfo;
 import org.apache.ambari.server.state.DependencyInfo;
 import org.apache.ambari.server.state.ExtensionInfo;
@@ -1487,29 +1485,4 @@ public class AmbariMetaInfo {
 
     return versionDefinitions;
   }
-
-  //TODO will be a need to change to multi-instance usage
-  public TopologyStatusCommandParams getStatusCommandParams(StackId stackId, String serviceName, String componentName) throws AmbariException {
-    ServiceInfo serviceInfo = getService(stackId.getStackName(),
-        stackId.getStackVersion(), serviceName);
-    ComponentInfo componentInfo = getComponent(
-        stackId.getStackName(), stackId.getStackVersion(),
-        serviceName, componentName);
-
-    String scriptName = null;
-    CommandScriptDefinition script = componentInfo.getCommandScript();
-    if (serviceInfo.getSchemaVersion().equals(AmbariMetaInfo.SCHEMA_VERSION_2)) {
-      if (script != null) {
-        scriptName = script.getScript();
-      } else {
-        String message = String.format("Component %s of service %s has not " +
-            "command script defined", componentName, serviceName);
-        throw new AmbariException(message);
-      }
-    }
-    String servicePackageFolder = serviceInfo.getServicePackageFolder();
-    return new TopologyStatusCommandParams(scriptName, servicePackageFolder);
-  }
-
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 17bc718..c11763c 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
@@ -755,7 +755,7 @@ public class AmbariCustomCommandExecutionHelper {
       }
     }
 
-    String commandTimeout = configs.getDefaultAgentTaskTimeout(false);
+    String commandTimeout = getStatusCommandTimeout(serviceInfo);
 
     if (serviceInfo.getSchemaVersion().equals(AmbariMetaInfo.SCHEMA_VERSION_2)) {
       // Service check command is not custom command
@@ -763,9 +763,6 @@ public class AmbariCustomCommandExecutionHelper {
       if (script != null) {
         commandParams.put(SCRIPT, script.getScript());
         commandParams.put(SCRIPT_TYPE, script.getScriptType().toString());
-        if (script.getTimeout() > 0) {
-          commandTimeout = String.valueOf(script.getTimeout());
-        }
       } else {
         String message = String.format("Service %s has no command script " +
             "defined. It is not possible to run service check" +
@@ -775,12 +772,6 @@ public class AmbariCustomCommandExecutionHelper {
       // We don't need package/repo information to perform service check
     }
 
-    // Try to apply overridden service check timeout value if available
-    Long overriddenTimeout = configs.getAgentServiceCheckTaskTimeout();
-    if (!overriddenTimeout.equals(Configuration.AGENT_SERVICE_CHECK_TASK_TIMEOUT.getDefaultValue())) {
-      commandTimeout = String.valueOf(overriddenTimeout);
-    }
-
     commandParams.put(COMMAND_TIMEOUT, commandTimeout);
     String checkType = configHelper.getValueFromDesiredConfigurations(cluster, ConfigHelper.CLUSTER_ENV, ConfigHelper.SERVICE_CHECK_TYPE);
     if (ConfigHelper.SERVICE_CHECK_MINIMAL.equals(checkType)) {
@@ -1485,4 +1476,30 @@ public class AmbariCustomCommandExecutionHelper {
     hosts.removeAll(removedHosts);
     return removedHosts;
   }
+
+  public String getStatusCommandTimeout(ServiceInfo serviceInfo) throws AmbariException {
+    String commandTimeout = configs.getDefaultAgentTaskTimeout(false);
+
+    if (serviceInfo.getSchemaVersion().equals(AmbariMetaInfo.SCHEMA_VERSION_2)) {
+      // Service check command is not custom command
+      CommandScriptDefinition script = serviceInfo.getCommandScript();
+      if (script != null) {
+        if (script.getTimeout() > 0) {
+          commandTimeout = String.valueOf(script.getTimeout());
+        }
+      } else {
+        String message = String.format("Service %s has no command script " +
+            "defined. It is not possible to run service check" +
+            " for this service", serviceInfo.getName());
+        throw new AmbariException(message);
+      }
+    }
+
+    // Try to apply overridden service check timeout value if available
+    Long overriddenTimeout = configs.getAgentServiceCheckTaskTimeout();
+    if (!overriddenTimeout.equals(Configuration.AGENT_SERVICE_CHECK_TASK_TIMEOUT.getDefaultValue())) {
+      commandTimeout = String.valueOf(overriddenTimeout);
+    }
+    return commandTimeout;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 52497f2..134979e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -18,6 +18,8 @@
 
 package org.apache.ambari.server.controller;
 
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AGENT_STACK_RETRY_COUNT;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AGENT_STACK_RETRY_ON_UNAVAILABILITY;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_DRIVER;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_PASSWORD;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_URL;
@@ -27,10 +29,19 @@ import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_R
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_TIMEOUT;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.CUSTOM_FOLDER;
 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;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JCE_NAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_NAME;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.MAX_DURATION_OF_RETRIES;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.MYSQL_JDBC_URL;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.NOT_MANAGED_HDFS_PATH_LIST;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.ORACLE_JDBC_URL;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.PACKAGE_LIST;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.PACKAGE_VERSION;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.REPO_INFO;
@@ -38,6 +49,8 @@ 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.SERVICE_REPO_INFO;
+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.UNLIMITED_KEY_JCE_REQUIRED;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.USER_GROUPS;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.USER_LIST;
@@ -89,6 +102,8 @@ import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.actionmanager.StageFactory;
 import org.apache.ambari.server.agent.ExecutionCommand;
 import org.apache.ambari.server.agent.ExecutionCommand.KeyNames;
+import org.apache.ambari.server.agent.stomp.dto.MetadataCluster;
+import org.apache.ambari.server.agent.stomp.dto.MetadataServiceInfo;
 import org.apache.ambari.server.agent.stomp.dto.TopologyCluster;
 import org.apache.ambari.server.agent.stomp.dto.TopologyComponent;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
@@ -109,6 +124,7 @@ import org.apache.ambari.server.controller.metrics.MetricsCollectorHAManager;
 import org.apache.ambari.server.controller.metrics.timeline.cache.TimelineMetricCacheProvider;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.customactions.ActionDefinition;
+import org.apache.ambari.server.events.MetadataUpdateEvent;
 import org.apache.ambari.server.events.TopologyUpdateEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
@@ -327,7 +343,10 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   private StateUpdateEventPublisher stateUpdateEventPublisher;
 
   @Inject
-  TopologyDeleteFormer topologyDeleteFormer;
+  private TopologyDeleteFormer topologyDeleteFormer;
+
+  @Inject
+  private AmbariCustomCommandExecutionHelper ambariCustomCommandExecutionHelper;
 
   /**
    * The KerberosHelper to help setup for enabling for disabling Kerberos
@@ -723,7 +742,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
   private TopologyUpdateEvent getAddedComponentsTopologyEvent(Set<ServiceComponentHostRequest> requests)
     throws AmbariException {
-    Map<String, TopologyCluster> topologyUpdates = new HashMap<>();
+    TreeMap<String, TopologyCluster> topologyUpdates = new TreeMap<>();
     for (ServiceComponentHostRequest request : requests) {
       String serviceName = request.getServiceName();
       String componentName = request.getComponentName();
@@ -731,10 +750,15 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       Collection<Host> clusterHosts = cluster.getHosts();
       Service s = cluster.getService(serviceName);
       ServiceComponent sc = s.getServiceComponent(componentName);
-      Set<String> hostNames = cluster.getHosts(serviceName, componentName);
+      String hostName = request.getHostname();
       Set<Long> hostIds = clusterHosts.stream()
-          .filter(h -> hostNames.contains(h.getHostName()))
+          .filter(h -> hostName.equals(h.getHostName()))
           .map(h -> h.getHostId()).collect(Collectors.toSet());
+      Set<String> publicHostNames = clusterHosts.stream()
+          .filter(h -> hostName.equals(h.getHostName()))
+          .map(h -> h.getPublicHostName()).collect(Collectors.toSet());
+      Set<String> hostNames = new HashSet<>();
+      hostNames.add(hostName);
       ServiceComponentHost sch = sc.getServiceComponentHost(request.getHostname());
 
       StackId stackId = cluster.getDesiredStackVersion();
@@ -742,17 +766,27 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       TopologyComponent newComponent = TopologyComponent.newBuilder()
           .setComponentName(sch.getServiceComponentName())
           .setServiceName(sch.getServiceName())
+          .setDisplayName(sc.getDisplayName())
           .setVersion(sch.getVersion())
           .setHostIds(hostIds)
-          .setStatusCommandParams(ambariMetaInfo.getStatusCommandParams(stackId, serviceName, componentName))
+          .setHostNames(hostNames)
+          .setPublicHostNames(publicHostNames)
+          .setComponentLevelParams(getTopologyComponentLevelParams(stackId, serviceName, componentName, cluster.getSecurityType()))
           .build();
       String clusterId = Long.toString(cluster.getClusterId());
       if (!topologyUpdates.containsKey(clusterId)) {
         topologyUpdates.put(clusterId, new TopologyCluster());
       }
-      topologyUpdates.get(clusterId).addTopologyComponent(newComponent);
+      if (topologyUpdates.get(clusterId).getTopologyComponents().contains(newComponent)) {
+        Set<TopologyComponent> newComponents = new HashSet<>();
+        newComponents.add(newComponent);
+        topologyUpdates.get(clusterId).update(newComponents, Collections.emptySet(),
+            TopologyUpdateEvent.EventType.UPDATE);
+      } else {
+        topologyUpdates.get(clusterId).addTopologyComponent(newComponent);
+      }
     }
-    return new TopologyUpdateEvent(topologyUpdates, TopologyUpdateEvent.EventType.ADD);
+    return new TopologyUpdateEvent(topologyUpdates, TopologyUpdateEvent.EventType.UPDATE);
   }
 
   private void setMonitoringServicesRestartRequired(
@@ -2476,14 +2510,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       hostParams.put(DB_DRIVER_FILENAME, configs.getMySQLJarName());
     }
 
-    List<String> clientsToUpdateConfigsList = componentInfo.getClientsToUpdateConfigs();
-    if (clientsToUpdateConfigsList == null) {
-      clientsToUpdateConfigsList = new ArrayList<>();
-      clientsToUpdateConfigsList.add("*");
-    }
-
-    String clientsToUpdateConfigs = gson.toJson(clientsToUpdateConfigsList);
-    hostParams.put(CLIENTS_TO_UPDATE_CONFIGS, clientsToUpdateConfigs);
+    hostParams.put(CLIENTS_TO_UPDATE_CONFIGS, getClientsToUpdateConfigs(componentInfo));
 
     // If we are starting a component, calculate whether the unlimited key JCE policy is
     // required for the relevant host.  One of the following indicates that the unlimited
@@ -2492,17 +2519,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     //   * The component explicitly requires it whether Kerberos is enabled or not (example, SMARTSENSE/HST_SERVER)
     //   * The component explicitly requires it only when Kerberos is enabled AND Kerberos is enabled (example, most components)
     //
-    UnlimitedKeyJCERequirement unlimitedKeyJCERequirement = componentInfo.getUnlimitedKeyJCERequired();
-    // Ensure that the unlimited key requirement is set. If null, the default value should be used.
-    if(unlimitedKeyJCERequirement == null) {
-      unlimitedKeyJCERequirement = UnlimitedKeyJCERequirement.DEFAULT;
-    }
-
-    boolean unlimitedKeyJCEPolicyRequired = (UnlimitedKeyJCERequirement.ALWAYS == unlimitedKeyJCERequirement) ||
-        ((UnlimitedKeyJCERequirement.KERBEROS_ENABLED == unlimitedKeyJCERequirement) && (cluster.getSecurityType() == SecurityType.KERBEROS));
-
     // Set/update the unlimited_key_jce_required value as needed
-    hostParams.put(UNLIMITED_KEY_JCE_REQUIRED, (unlimitedKeyJCEPolicyRequired) ? "true" : "false");
+    hostParams.put(UNLIMITED_KEY_JCE_REQUIRED, (getUnlimitedKeyJCERequirement(componentInfo, cluster.getSecurityType())) ? "true" : "false");
 
     execCmd.setHostLevelParams(hostParams);
 
@@ -5622,4 +5640,148 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     return QuickLinkVisibilityControllerFactory.get(quickLinkProfileJson);
   }
 
+  /**
+   * Collects metadata info about clusters for agent.
+   * @return metadata info about clusters
+   * @throws AmbariException
+   */
+  public MetadataUpdateEvent getClustersMetadata() throws AmbariException {
+    TreeMap<String, MetadataCluster> metadataClusters = new TreeMap<>();
+
+    for (Cluster cl : clusters.getClusters().values()) {
+      StackId stackId = cl.getDesiredStackVersion();
+
+      SecurityType securityType = cl.getSecurityType();
+
+      TreeMap<String, MetadataServiceInfo> serviceLevelParams = new TreeMap<>();
+      Collection<ServiceInfo> servicesInfo = ambariMetaInfo.getServices(stackId.getStackName(),
+          stackId.getStackVersion()).values();
+      for (ServiceInfo serviceInfo : servicesInfo) {
+        Long statusCommandTimeout = null;
+        if (serviceInfo.getCommandScript() != null) {
+          statusCommandTimeout = new Long (ambariCustomCommandExecutionHelper.getStatusCommandTimeout(serviceInfo));
+        }
+
+        String servicePackageFolder = serviceInfo.getServicePackageFolder();
+
+        serviceLevelParams.put(serviceInfo.getName(),
+            new MetadataServiceInfo(serviceInfo.getVersion(),
+                serviceInfo.isCredentialStoreEnabled(),
+                statusCommandTimeout,
+                servicePackageFolder));
+      }
+
+      MetadataCluster metadataCluster = new MetadataCluster(securityType,
+          serviceLevelParams,
+          getMetadataClusterLevelParams(cl, stackId));
+      metadataClusters.put(Long.toString(cl.getClusterId()), metadataCluster);
+    }
+
+    MetadataUpdateEvent metadataUpdateEvent = new MetadataUpdateEvent(metadataClusters);
+    return metadataUpdateEvent;
+  }
+
+  private String getClientsToUpdateConfigs(ComponentInfo componentInfo) {
+    List<String> clientsToUpdateConfigsList = componentInfo.getClientsToUpdateConfigs();
+    if (clientsToUpdateConfigsList == null) {
+      clientsToUpdateConfigsList = new ArrayList<>();
+      clientsToUpdateConfigsList.add("*");
+    }
+    return gson.toJson(clientsToUpdateConfigsList);
+  }
+
+  private Boolean getUnlimitedKeyJCERequirement(ComponentInfo componentInfo, SecurityType clusterSecurityType) {
+    UnlimitedKeyJCERequirement unlimitedKeyJCERequirement = componentInfo.getUnlimitedKeyJCERequired();
+    // Ensure that the unlimited key requirement is set. If null, the default value should be used.
+    if(unlimitedKeyJCERequirement == null) {
+      unlimitedKeyJCERequirement = UnlimitedKeyJCERequirement.DEFAULT;
+    }
+
+    return (UnlimitedKeyJCERequirement.ALWAYS == unlimitedKeyJCERequirement) ||
+        ((UnlimitedKeyJCERequirement.KERBEROS_ENABLED == unlimitedKeyJCERequirement) &&
+            (clusterSecurityType == SecurityType.KERBEROS));
+
+  }
+
+  //TODO will be a need to change to multi-instance usage
+  public TreeMap<String, String> getTopologyComponentLevelParams(StackId stackId, String serviceName, String componentName,
+                                                             SecurityType clusterSecurityType) throws AmbariException {
+    ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(),
+        stackId.getStackVersion(), serviceName);
+    ComponentInfo componentInfo = ambariMetaInfo.getComponent(
+        stackId.getStackName(), stackId.getStackVersion(),
+        serviceName, componentName);
+
+    String scriptName = null;
+    CommandScriptDefinition script = componentInfo.getCommandScript();
+    if (serviceInfo.getSchemaVersion().equals(AmbariMetaInfo.SCHEMA_VERSION_2)) {
+      if (script != null) {
+        scriptName = script.getScript();
+      } else {
+        String message = String.format("Component %s of service %s has not " +
+            "command script defined", componentName, serviceName);
+        throw new AmbariException(message);
+      }
+    }
+
+    TreeMap<String, String> statusCommandParams = new TreeMap<>();
+    statusCommandParams.put(ExecutionCommand.KeyNames.CLIENTS_TO_UPDATE_CONFIGS,
+        getClientsToUpdateConfigs(componentInfo));
+    statusCommandParams.put(ExecutionCommand.KeyNames.UNLIMITED_KEY_JCE_REQUIRED,
+         Boolean.toString(getUnlimitedKeyJCERequirement(componentInfo, clusterSecurityType)));
+    statusCommandParams.put(KeyNames.SCRIPT, scriptName);
+    return statusCommandParams;
+  }
+
+  public TreeMap<String, String> getMetadataClusterLevelParams(Cluster cluster, StackId stackId) throws AmbariException {
+    TreeMap<String, String> clusterLevelParams = new TreeMap<>();
+    clusterLevelParams.put(JDK_LOCATION, getJdkResourceUrl());
+    clusterLevelParams.put(JAVA_HOME, getJavaHome());
+    clusterLevelParams.put(JAVA_VERSION, String.valueOf(configs.getJavaVersion()));
+    clusterLevelParams.put(JDK_NAME, getJDKName());
+    clusterLevelParams.put(JCE_NAME, getJCEName());
+    clusterLevelParams.put(STACK_NAME, stackId.getStackName());
+    clusterLevelParams.put(STACK_VERSION, stackId.getStackVersion());
+    clusterLevelParams.put(DB_NAME, getServerDB());
+    clusterLevelParams.put(MYSQL_JDBC_URL, getMysqljdbcUrl());
+    clusterLevelParams.put(ORACLE_JDBC_URL, getOjdbcUrl());
+    clusterLevelParams.put(DB_DRIVER_FILENAME, configs.getMySQLJarName());
+    clusterLevelParams.putAll(getRcaParameters());
+    clusterLevelParams.put(HOST_SYS_PREPPED, configs.areHostsSysPrepped());
+    clusterLevelParams.put(AGENT_STACK_RETRY_ON_UNAVAILABILITY, configs.isAgentStackRetryOnInstallEnabled());
+    clusterLevelParams.put(AGENT_STACK_RETRY_COUNT, configs.getAgentStackRetryOnInstallCount());
+
+    StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(), stackId.getStackVersion());
+    clusterLevelParams.put(HOOKS_FOLDER, stackInfo.getStackHooksFolder());
+
+    Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs();
+    Set<String> notManagedHdfsPathSet = configHelper.getPropertyValuesWithPropertyType(stackId,
+        PropertyType.NOT_MANAGED_HDFS_PATH, cluster, desiredConfigs);
+    String notManagedHdfsPathList = gson.toJson(notManagedHdfsPathSet);
+    clusterLevelParams.put(NOT_MANAGED_HDFS_PATH_LIST, notManagedHdfsPathList);
+
+    Set<String> userSet = configHelper.getPropertyValuesWithPropertyType(stackId, PropertyType.USER, cluster, desiredConfigs);
+    String userList = gson.toJson(userSet);
+    clusterLevelParams.put(USER_LIST, userList);
+
+    //Create a user_group mapping and send it as part of the hostLevelParams
+    Map<String, Set<String>> userGroupsMap = configHelper.createUserGroupsMap(
+        stackId, cluster, desiredConfigs);
+    String userGroups = gson.toJson(userGroupsMap);
+    clusterLevelParams.put(USER_GROUPS, userGroups);
+
+    Set<String> groupSet = configHelper.getPropertyValuesWithPropertyType(stackId, PropertyType.GROUP, cluster, desiredConfigs);
+    String groupList = gson.toJson(groupSet);
+    clusterLevelParams.put(GROUP_LIST, groupList);
+
+    return clusterLevelParams;
+  }
+
+  public TreeMap<String, String> getTopologyHostLevelParams(Cluster cluster, Host host) throws AmbariException {
+    TreeMap<String, String> hostLevelParams = new TreeMap<>();
+    String repoInfo = customCommandExecutionHelper.getRepoInfo(cluster, host);
+
+    hostLevelParams.put(REPO_INFO, repoInfo);
+    return hostLevelParams;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DeleteHostComponentStatusMetaData.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DeleteHostComponentStatusMetaData.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DeleteHostComponentStatusMetaData.java
index 1a4e34a..477add7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DeleteHostComponentStatusMetaData.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DeleteHostComponentStatusMetaData.java
@@ -32,9 +32,10 @@ public class DeleteHostComponentStatusMetaData extends DeleteStatusMetaData {
     removedHostComponents = new HashSet<>();
   }
 
-  public void addDeletedHostComponent(String componentName, String hostName, Long hostId,
+  public void addDeletedHostComponent(String componentName, String serviceName, String hostName, Long hostId,
                                       String clusterId, String version) {
-    removedHostComponents.add(new HostComponent(componentName, hostId, clusterId, version));
+    removedHostComponents.add(new HostComponent(componentName, serviceName, hostId,
+        hostName, clusterId, version));
     addDeletedKey(componentName + "/" + hostName);
   }
 
@@ -52,13 +53,18 @@ public class DeleteHostComponentStatusMetaData extends DeleteStatusMetaData {
 
   public class HostComponent {
     private String componentName;
+    private String serviceName;
     private Long hostId;
+    private String hostName;
     private String clusterId;
     private String version;
 
-    public HostComponent(String componentName, Long hostId, String clusterId, String version) {
+    public HostComponent(String componentName, String serviceName, Long hostId, String hostName,
+                         String clusterId, String version) {
       this.componentName = componentName;
+      this.serviceName = serviceName;
       this.hostId = hostId;
+      this.hostName = hostName;
       this.clusterId = clusterId;
       this.version = version;
     }
@@ -71,14 +77,6 @@ public class DeleteHostComponentStatusMetaData extends DeleteStatusMetaData {
       this.componentName = componentName;
     }
 
-    public Long getHostId() {
-      return hostId;
-    }
-
-    public void setHostName(Long hostId) {
-      this.hostId = hostId;
-    }
-
     public String getClusterId() {
       return clusterId;
     }
@@ -94,5 +92,29 @@ public class DeleteHostComponentStatusMetaData extends DeleteStatusMetaData {
     public void setVersion(String version) {
       this.version = version;
     }
+
+    public String getServiceName() {
+      return serviceName;
+    }
+
+    public void setServiceName(String serviceName) {
+      this.serviceName = serviceName;
+    }
+
+    public String getHostName() {
+      return hostName;
+    }
+
+    public void setHostName(String hostName) {
+      this.hostName = hostName;
+    }
+
+    public Long getHostId() {
+      return hostId;
+    }
+
+    public void setHostId(Long hostId) {
+      this.hostId = hostId;
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
index 1b16b5e..74508c1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
@@ -28,6 +28,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ClusterNotFoundException;
@@ -35,9 +36,11 @@ import org.apache.ambari.server.DuplicateResourceException;
 import org.apache.ambari.server.HostNotFoundException;
 import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.ParentObjectNotFoundException;
+import org.apache.ambari.server.agent.RecoveryConfigHelper;
 import org.apache.ambari.server.agent.stomp.dto.TopologyCluster;
 import org.apache.ambari.server.agent.stomp.dto.TopologyHost;
 import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.AmbariManagementControllerImpl;
 import org.apache.ambari.server.controller.ConfigurationRequest;
 import org.apache.ambari.server.controller.HostRequest;
 import org.apache.ambari.server.controller.HostResponse;
@@ -174,6 +177,12 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
   @Inject
   private StateUpdateEventPublisher stateUpdateEventPublisher;
 
+  @Inject
+  private RecoveryConfigHelper recoveryConfigHelper;
+
+  @Inject
+  private AmbariManagementControllerImpl ambariManagementController;
+
   // ----- Constructors ----------------------------------------------------
 
   /**
@@ -515,7 +524,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
     Map<String, Map<String, String>> hostAttributes = new HashMap<>();
     Set<String> allClusterSet = new HashSet<>();
 
-    Map<String, TopologyCluster> addedTopologies = new HashMap<>();
+    TreeMap<String, TopologyCluster> addedTopologies = new TreeMap<>();
     for (HostRequest hostRequest : hostRequests) {
       if (hostRequest.getHostname() != null &&
           !hostRequest.getHostname().isEmpty() &&
@@ -529,7 +538,8 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
         if (hostRequest.getHostAttributes() != null) {
           hostAttributes.put(hostRequest.getHostname(), hostRequest.getHostAttributes());
         }
-        String clusterId = Long.toString(clusters.getCluster(hostRequest.getClusterName()).getClusterId());
+        Cluster cl = clusters.getCluster(hostRequest.getClusterName());
+        String clusterId = Long.toString(cl.getClusterId());
         if (!addedTopologies.containsKey(clusterId)) {
           addedTopologies.put(clusterId, new TopologyCluster());
         }
@@ -537,7 +547,10 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
         addedTopologies.get(clusterId).addTopologyHost(new TopologyHost(addedHost.getHostId(),
             addedHost.getHostName(),
             addedHost.getRackInfo(),
-            addedHost.getIPv4()));
+            addedHost.getIPv4(),
+            recoveryConfigHelper.getRecoveryConfig(clusters.getCluster(hostRequest.getClusterName()).getClusterName(),
+                addedHost.getHostName()),
+            ambariManagementController.getTopologyHostLevelParams(cl, addedHost)));
       }
     }
     clusters.updateHostWithClusterAndAttributes(hostClustersMap, hostAttributes);
@@ -545,7 +558,8 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
     for (String clusterName : allClusterSet) {
       clusters.getCluster(clusterName).recalculateAllClusterVersionStates();
     }
-    TopologyUpdateEvent topologyUpdateEvent = new TopologyUpdateEvent(addedTopologies, TopologyUpdateEvent.EventType.ADD);
+    TopologyUpdateEvent topologyUpdateEvent =
+        new TopologyUpdateEvent(addedTopologies, TopologyUpdateEvent.EventType.UPDATE);
     stateUpdateEventPublisher.publish(topologyUpdateEvent);
   }
 
@@ -723,7 +737,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
       }
     }
 
-    Map<String, TopologyCluster> topologyUpdates = new HashMap<>();
+    TreeMap<String, TopologyCluster> topologyUpdates = new TreeMap<>();
     for (HostRequest request : requests) {
       if (LOG.isDebugEnabled()) {
         LOG.debug("Received an updateHost request"
@@ -905,7 +919,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
     Set<String> hostsClusters = new HashSet<>();
     Set<String> hostNames = new HashSet<>();
     Set<Cluster> allClustersWithHosts = new HashSet<>();
-    Map<String, TopologyCluster> topologyUpdates = new HashMap<>();
+    TreeMap<String, TopologyCluster> topologyUpdates = new TreeMap<>();
     for (HostRequest hostRequest : requests) {
       // Assume the user also wants to delete it entirely, including all clusters.
       String hostname = hostRequest.getHostname();
@@ -944,24 +958,6 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
         for (String key : componentDeleteStatus.getDeletedKeys()) {
           deleteStatusMetaData.addDeletedKey(key);
         }
-        /*for (DeleteHostComponentStatusMetaData.HostComponent hostComponent : componentDeleteStatus.getRemovedHostComponents()) {
-          String clusterId = hostComponent.getClusterId();
-          if (!topologyUpdates.containsKey(clusterId)) {
-            topologyUpdates.put(clusterId, new TopologyCluster());
-          }
-          TopologyComponent deletedComponent = new TopologyComponent(hostComponent.getComponentName(),
-              null,
-              hostComponent.getVersion(),
-              new HashSet<>(Arrays.asList(hostId)),
-              null);
-          if (!topologyUpdates.get(clusterId).getTopologyComponents().contains(deletedComponent)) {
-            topologyUpdates.get(clusterId).addTopologyComponent(deletedComponent);
-          } else {
-            topologyUpdates.get(clusterId).getTopologyComponents()
-                .stream().filter(t -> t.equals(deletedComponent))
-                .forEach(t -> t.addHostId(hostId));
-          }
-        }*/
         for (String key : componentDeleteStatus.getExceptionForKeys().keySet()) {
           deleteStatusMetaData.addException(key, componentDeleteStatus.getExceptionForKeys().get(key));
         }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/AgentConfigsUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AgentConfigsUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AgentConfigsUpdateEvent.java
new file mode 100644
index 0000000..23f3559
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AgentConfigsUpdateEvent.java
@@ -0,0 +1,62 @@
+/**
+ * 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.events;
+
+import java.util.TreeMap;
+
+import org.apache.ambari.server.agent.stomp.dto.ClusterConfigs;
+import org.apache.ambari.server.agent.stomp.dto.Hashable;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AgentConfigsUpdateEvent extends AmbariUpdateEvent implements Hashable {
+
+  private String hash;
+
+  @JsonProperty("clusters")
+  private TreeMap<String, ClusterConfigs> clustersConfigs = new TreeMap<>();
+
+  public AgentConfigsUpdateEvent(TreeMap<String, ClusterConfigs> clustersConfigs) {
+    super(Type.AGENT_CONFIGS);
+    this.clustersConfigs = clustersConfigs;
+  }
+
+  public TreeMap<String, ClusterConfigs> getClustersConfigs() {
+    return clustersConfigs;
+  }
+
+  public void setClustersConfigs(TreeMap<String, ClusterConfigs> clustersConfigs) {
+    this.clustersConfigs = clustersConfigs;
+  }
+
+  @Override
+  public String getHash() {
+    return hash;
+  }
+
+  public void setHash(String hash) {
+    this.hash = hash;
+  }
+
+  public static AgentConfigsUpdateEvent emptyUpdate() {
+    return new AgentConfigsUpdateEvent(null);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java
index 73862d5..52e2180 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java
@@ -18,24 +18,24 @@
 
 package org.apache.ambari.server.events;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
 
-import org.apache.ambari.server.state.Alert;
+import org.apache.ambari.server.api.query.render.AlertSummaryGroupedRenderer;
 
 public class AlertUpdateEvent extends AmbariUpdateEvent {
-  private List<Alert> alerts = new ArrayList<>();
+  private Map<String, AlertSummaryGroupedRenderer.AlertDefinitionSummary> summaries = new HashMap<>();
 
-  public AlertUpdateEvent(List<Alert> alerts) {
+  public AlertUpdateEvent(Map<String, AlertSummaryGroupedRenderer.AlertDefinitionSummary> summaries) {
     super(Type.ALERT);
-    this.alerts = alerts;
+    this.summaries = summaries;
   }
 
-  public List<Alert> getAlerts() {
-    return alerts;
+  public Map<String, AlertSummaryGroupedRenderer.AlertDefinitionSummary> getSummaries() {
+    return summaries;
   }
 
-  public void setAlerts(List<Alert> alerts) {
-    this.alerts = alerts;
+  public void setSummaries(Map<String, AlertSummaryGroupedRenderer.AlertDefinitionSummary> summaries) {
+    this.summaries = summaries;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java
index 2b7efa6..b075179 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java
@@ -44,13 +44,12 @@ public abstract class AmbariUpdateEvent {
   public enum Type {
     ALERT("/events/alerts", "events.alerts"),
     METADATA("/events/metadata", "events.metadata"),
-    TOPOLOGY("/events/topology", "events.topology_update"),
+    TOPOLOGY("/events/topologies", "events.topology_update"),
     AGENT_CONFIGS("/events/configs", "events.agent.configs"),
     CONFIGS("/events/configs", "events.configs"),
     HOSTCOMPONENT("/events/hostcomponents", "events.hostcomponents"),
     NAMEDHOSTCOMPONENT("/events/tasks/", "events.hostrolecommands.named"),
     REQUEST("/events/requests", "events.requests"),
-    NAMEDREQUEST("/events/requests", "events.requests.named"),
     COMMAND("/user/commands", "events.commands");
 
     private String destination;

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java
index b6eec10..26f6622 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java
@@ -19,7 +19,9 @@
 package org.apache.ambari.server.events;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
@@ -34,13 +36,14 @@ public class ConfigsUpdateEvent extends AmbariUpdateEvent {
   private String user;
   private String note;
   private List<String> hostNames;
-  private Long createtime;
+  private Long createTime;
   private String groupName;
-  //TODO configs
 
   private List<ClusterConfig> configs = new ArrayList<>();
+  private Set<String> changedConfigTypes = new HashSet<>();
 
-  public ConfigsUpdateEvent(ServiceConfigEntity configs, String configGroupName, List<String> hostNames) {
+  public ConfigsUpdateEvent(ServiceConfigEntity configs, String configGroupName, List<String> hostNames,
+                            Set<String> changedConfigTypes) {
     super(Type.CONFIGS);
     this.serviceConfigId = configs.getServiceConfigId();
     this.clusterId = configs.getClusterEntity().getClusterId();
@@ -56,8 +59,9 @@ public class ConfigsUpdateEvent extends AmbariUpdateEvent {
         clusterConfigEntity.getTag(),
         clusterConfigEntity.getVersion()));
     }
-    this.createtime = configs.getCreateTimestamp();
+    this.createTime = configs.getCreateTimestamp();
     this.groupName = configGroupName;
+    this.changedConfigTypes = changedConfigTypes;
   }
 
   public Long getServiceConfigId() {
@@ -132,12 +136,12 @@ public class ConfigsUpdateEvent extends AmbariUpdateEvent {
     this.configs = configs;
   }
 
-  public Long getCreatetime() {
-    return createtime;
+  public Long getCreateTime() {
+    return createTime;
   }
 
-  public void setCreatetime(Long createtime) {
-    this.createtime = createtime;
+  public void setCreateTime(Long createTime) {
+    this.createTime = createTime;
   }
 
   public String getGroupName() {
@@ -148,6 +152,14 @@ public class ConfigsUpdateEvent extends AmbariUpdateEvent {
     this.groupName = groupName;
   }
 
+  public Set<String> getChangedConfigTypes() {
+    return changedConfigTypes;
+  }
+
+  public void setChangedConfigTypes(Set<String> changedConfigTypes) {
+    this.changedConfigTypes = changedConfigTypes;
+  }
+
   public class ClusterConfig {
     private Long clusterId;
     private String type;

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java
index fc660a6..6e7ee90 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java
@@ -17,9 +17,46 @@
  */
 package org.apache.ambari.server.events;
 
-public class MetadataUpdateEvent extends AmbariUpdateEvent {
+import java.util.Map;
+import java.util.TreeMap;
 
-  public MetadataUpdateEvent() {
+import org.apache.ambari.server.agent.stomp.dto.Hashable;
+import org.apache.ambari.server.agent.stomp.dto.MetadataCluster;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class MetadataUpdateEvent extends AmbariUpdateEvent implements Hashable {
+
+  private String hash;
+
+  @JsonProperty("clusters")
+  private TreeMap<String, MetadataCluster> metadataClusters = new TreeMap<>();
+
+  public MetadataUpdateEvent(TreeMap<String, MetadataCluster> metadataClusters) {
     super(Type.METADATA);
+    this.metadataClusters = metadataClusters;
+  }
+
+  public Map<String, MetadataCluster> getMetadataClusters() {
+    return metadataClusters;
+  }
+
+  public void setMetadataClusters(TreeMap<String, MetadataCluster> metadataClusters) {
+    this.metadataClusters = metadataClusters;
+  }
+
+  @Override
+  public String getHash() {
+    return hash;
+  }
+
+  public void setHash(String hash) {
+    this.hash = hash;
+  }
+
+  public static MetadataUpdateEvent emptyUpdate() {
+    return new MetadataUpdateEvent(null);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/events/NamedHostRoleCommandUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/NamedHostRoleCommandUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/NamedHostRoleCommandUpdateEvent.java
new file mode 100644
index 0000000..3096347
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/NamedHostRoleCommandUpdateEvent.java
@@ -0,0 +1,127 @@
+/**
+ * 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.events;
+
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class NamedHostRoleCommandUpdateEvent extends AmbariUpdateEvent {
+
+  private Long id;
+  private Long requestId;
+  private String hostName;
+  private Long endTime;
+  private HostRoleStatus status;
+  private String errorLog;
+  private String outLog;
+  private String stderr;
+  private String stdout;
+
+  public NamedHostRoleCommandUpdateEvent(Long id, Long requestId, String hostName, Long endTime, HostRoleStatus status, String errorLog, String outLog, String stderr, String stdout) {
+    super(Type.NAMEDHOSTCOMPONENT);
+    this.id = id;
+    this.requestId = requestId;
+    this.hostName = hostName;
+    this.endTime = endTime;
+    this.status = status;
+    this.errorLog = errorLog;
+    this.outLog = outLog;
+    this.stderr = stderr;
+    this.stdout = stdout;
+  }
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Long getRequestId() {
+    return requestId;
+  }
+
+  public void setRequestId(Long requestId) {
+    this.requestId = requestId;
+  }
+
+  public String getHostName() {
+    return hostName;
+  }
+
+  public void setHostName(String hostName) {
+    this.hostName = hostName;
+  }
+
+  public Long getEndTime() {
+    return endTime;
+  }
+
+  public void setEndTime(Long endTime) {
+    this.endTime = endTime;
+  }
+
+  public HostRoleStatus getStatus() {
+    return status;
+  }
+
+  public void setStatus(HostRoleStatus status) {
+    this.status = status;
+  }
+
+  public String getErrorLog() {
+    return errorLog;
+  }
+
+  public void setErrorLog(String errorLog) {
+    this.errorLog = errorLog;
+  }
+
+  public String getOutLog() {
+    return outLog;
+  }
+
+  public void setOutLog(String outLog) {
+    this.outLog = outLog;
+  }
+
+  public String getStderr() {
+    return stderr;
+  }
+
+  public void setStderr(String stderr) {
+    this.stderr = stderr;
+  }
+
+  public String getStdout() {
+    return stdout;
+  }
+
+  public void setStdout(String stdout) {
+    this.stdout = stdout;
+  }
+
+  @Override
+  public String getDestination() {
+    return super.getDestination() + getId();
+  }
+}


[4/4] ambari git commit: AMBARI-21200. Add serverside event metrics to track system health (mpapirkovskyy)

Posted by mp...@apache.org.
AMBARI-21200. Add serverside event metrics to track system health (mpapirkovskyy)


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

Branch: refs/heads/branch-3.0-perf
Commit: 1e64135c1c692870f8e831f5d5d2a3ff739627ba
Parents: 670a08e
Author: Myroslav Papirkovskyi <mp...@hortonworks.com>
Authored: Thu Jun 8 17:55:19 2017 +0300
Committer: Myroslav Papirkovskyi <mp...@hortonworks.com>
Committed: Thu Jun 22 18:25:50 2017 +0300

----------------------------------------------------------------------
 ambari-server/conf/unix/metrics.properties      |   3 +-
 .../ambari/server/events/AlertUpdateEvent.java  |   8 +-
 .../ambari/server/events/AmbariUpdateEvent.java |  50 ++++++++-
 .../ambari/server/events/CommandEvent.java      |   7 +-
 .../server/events/ConfigsUpdateEvent.java       |   8 +-
 .../server/events/HostComponentUpdateEvent.java |   8 +-
 .../server/events/MetadataUpdateEvent.java      |   8 +-
 .../server/events/RequestUpdateEvent.java       |   8 +-
 .../server/events/TopologyUpdateEvent.java      |   8 +-
 .../metrics/system/impl/MetricsServiceImpl.java |   6 ++
 .../system/impl/StompEventsMetricsSource.java   | 107 +++++++++++++++++++
 11 files changed, 180 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/conf/unix/metrics.properties
----------------------------------------------------------------------
diff --git a/ambari-server/conf/unix/metrics.properties b/ambari-server/conf/unix/metrics.properties
index efbfb04..96748d2 100644
--- a/ambari-server/conf/unix/metrics.properties
+++ b/ambari-server/conf/unix/metrics.properties
@@ -20,10 +20,11 @@
 #################### Metrics Source Configs #####################
 
 #Metric sources : jvm,database
-metric.sources=jvm
+metric.sources=jvm,event
 
 #### JVM Source Configs ###
 source.jvm.class=org.apache.ambari.server.metrics.system.impl.JvmMetricsSource
+source.event.class=org.apache.ambari.server.metrics.system.impl.StompEventsMetricsSource
 source.jvm.interval=10
 
 #### Database Source Configs ###

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java
index df5ab4d..73862d5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertUpdateEvent.java
@@ -23,10 +23,11 @@ import java.util.List;
 
 import org.apache.ambari.server.state.Alert;
 
-public class AlertUpdateEvent implements AmbariUpdateEvent {
+public class AlertUpdateEvent extends AmbariUpdateEvent {
   private List<Alert> alerts = new ArrayList<>();
 
   public AlertUpdateEvent(List<Alert> alerts) {
+    super(Type.ALERT);
     this.alerts = alerts;
   }
 
@@ -37,9 +38,4 @@ public class AlertUpdateEvent implements AmbariUpdateEvent {
   public void setAlerts(List<Alert> alerts) {
     this.alerts = alerts;
   }
-
-  @Override
-  public String getDestination() {
-    return "/events/alerts";
-  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java
index 62f253b..2b7efa6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariUpdateEvent.java
@@ -19,8 +19,54 @@ package org.apache.ambari.server.events;
 
 import java.beans.Transient;
 
-public interface AmbariUpdateEvent {
+public abstract class AmbariUpdateEvent {
+  protected final Type type;
+
+  public AmbariUpdateEvent(Type type) {
+    this.type = type;
+  }
+
+  @Transient
+  public Type getType() {
+    return type;
+  }
+
+  @Transient
+  public String getDestination() {
+    return type.getDestination();
+  }
 
   @Transient
-  String getDestination();
+  public String getMetricName() {
+    return type.getMetricName();
+  }
+
+  public enum Type {
+    ALERT("/events/alerts", "events.alerts"),
+    METADATA("/events/metadata", "events.metadata"),
+    TOPOLOGY("/events/topology", "events.topology_update"),
+    AGENT_CONFIGS("/events/configs", "events.agent.configs"),
+    CONFIGS("/events/configs", "events.configs"),
+    HOSTCOMPONENT("/events/hostcomponents", "events.hostcomponents"),
+    NAMEDHOSTCOMPONENT("/events/tasks/", "events.hostrolecommands.named"),
+    REQUEST("/events/requests", "events.requests"),
+    NAMEDREQUEST("/events/requests", "events.requests.named"),
+    COMMAND("/user/commands", "events.commands");
+
+    private String destination;
+    private String metricName;
+
+    Type(String destination, String metricName) {
+      this.destination = destination;
+      this.metricName = metricName;
+    }
+
+    public String getDestination() {
+      return destination;
+    }
+
+    public String getMetricName() {
+      return metricName;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/events/CommandEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/CommandEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/CommandEvent.java
index cee2fa3..80245aa 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/CommandEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/CommandEvent.java
@@ -17,9 +17,8 @@
  */
 package org.apache.ambari.server.events;
 
-public class CommandEvent implements AmbariUpdateEvent {
-  @Override
-  public String getDestination() {
-    return "/command";
+public class CommandEvent extends AmbariUpdateEvent {
+  public CommandEvent() {
+    super(Type.COMMAND);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java
index 738badb..b6eec10 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/ConfigsUpdateEvent.java
@@ -24,7 +24,7 @@ import java.util.List;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
 
-public class ConfigsUpdateEvent implements AmbariUpdateEvent {
+public class ConfigsUpdateEvent extends AmbariUpdateEvent {
 
   private Long serviceConfigId;
   private Long clusterId;
@@ -41,6 +41,7 @@ public class ConfigsUpdateEvent implements AmbariUpdateEvent {
   private List<ClusterConfig> configs = new ArrayList<>();
 
   public ConfigsUpdateEvent(ServiceConfigEntity configs, String configGroupName, List<String> hostNames) {
+    super(Type.CONFIGS);
     this.serviceConfigId = configs.getServiceConfigId();
     this.clusterId = configs.getClusterEntity().getClusterId();
     this.serviceName = configs.getServiceName();
@@ -147,11 +148,6 @@ public class ConfigsUpdateEvent implements AmbariUpdateEvent {
     this.groupName = groupName;
   }
 
-  @Override
-  public String getDestination() {
-    return "/events/configs";
-  }
-
   public class ClusterConfig {
     private Long clusterId;
     private String type;

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/events/HostComponentUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/HostComponentUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/HostComponentUpdateEvent.java
index 7500fca..08ed9e0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/HostComponentUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/HostComponentUpdateEvent.java
@@ -21,7 +21,7 @@ package org.apache.ambari.server.events;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.state.State;
 
-public class HostComponentUpdateEvent implements AmbariUpdateEvent {
+public class HostComponentUpdateEvent extends AmbariUpdateEvent {
 
   private Long id;
   private Long clusterId;
@@ -31,6 +31,7 @@ public class HostComponentUpdateEvent implements AmbariUpdateEvent {
   private State currentState;
 
   public HostComponentUpdateEvent(HostComponentStateEntity stateEntity) {
+    super(Type.HOSTCOMPONENT);
     this.id = stateEntity.getId();
     this.clusterId = stateEntity.getClusterId();
     this.serviceName = stateEntity.getServiceName();
@@ -86,9 +87,4 @@ public class HostComponentUpdateEvent implements AmbariUpdateEvent {
   public void setCurrentState(State currentState) {
     this.currentState = currentState;
   }
-
-  @Override
-  public String getDestination() {
-    return "/events/hostcomponents";
-  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java
index 956b73c..fc660a6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/MetadataUpdateEvent.java
@@ -17,9 +17,9 @@
  */
 package org.apache.ambari.server.events;
 
-public class MetadataUpdateEvent implements AmbariUpdateEvent {
-  @Override
-  public String getDestination() {
-    return "/events/metadata";
+public class MetadataUpdateEvent extends AmbariUpdateEvent {
+
+  public MetadataUpdateEvent() {
+    super(Type.METADATA);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java
index 682ce50..a2d2270 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/RequestUpdateEvent.java
@@ -24,7 +24,7 @@ import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
 import org.apache.ambari.server.orm.entities.RequestEntity;
 import org.apache.ambari.server.topology.TopologyManager;
 
-public class RequestUpdateEvent implements AmbariUpdateEvent {
+public class RequestUpdateEvent extends AmbariUpdateEvent {
 
   private Long clusterId;
   private Long endTime;
@@ -36,6 +36,7 @@ public class RequestUpdateEvent implements AmbariUpdateEvent {
 
 
   public RequestUpdateEvent(RequestEntity requestEntity, HostRoleCommandDAO hostRoleCommandDAO, TopologyManager topologyManager) {
+    super(Type.REQUEST);
     this.clusterId = requestEntity.getClusterId();
     this.endTime = requestEntity.getEndTime();
     this.requestId = requestEntity.getRequestId();
@@ -100,9 +101,4 @@ public class RequestUpdateEvent implements AmbariUpdateEvent {
   public void setStartTime(Long startTime) {
     this.startTime = startTime;
   }
-
-  @Override
-  public String getDestination() {
-    return "/events/requests";
-  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java
index 9655924..49d2f78 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/TopologyUpdateEvent.java
@@ -23,13 +23,14 @@ import org.apache.ambari.server.agent.stomp.dto.TopologyCluster;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class TopologyUpdateEvent implements AmbariUpdateEvent {
+public class TopologyUpdateEvent extends AmbariUpdateEvent {
   @JsonProperty("clustersTopologies")
   private Map<String, TopologyCluster> clusters;
 
   private EventType eventType;
 
   public TopologyUpdateEvent(Map<String, TopologyCluster> clusters, EventType eventType) {
+    super(Type.TOPOLOGY);
     this.clusters = clusters;
     this.eventType = eventType;
   }
@@ -50,11 +51,6 @@ public class TopologyUpdateEvent implements AmbariUpdateEvent {
     this.eventType = eventType;
   }
 
-  @Override
-  public String getDestination() {
-    return "/events/topology";
-  }
-
   public enum EventType {
     ADD,
     DELETE,

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/MetricsServiceImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/MetricsServiceImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/MetricsServiceImpl.java
index ab8ce8b..09a7a8f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/MetricsServiceImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/MetricsServiceImpl.java
@@ -23,6 +23,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
 import org.apache.ambari.server.metrics.system.MetricsService;
 import org.apache.ambari.server.metrics.system.MetricsSink;
 import org.apache.ambari.server.metrics.system.MetricsSource;
@@ -42,6 +43,8 @@ public class MetricsServiceImpl implements MetricsService {
 
   @Inject
   AmbariManagementController amc;
+  @Inject
+  StateUpdateEventPublisher stateUpdateEventPublisher;
 
   @Override
   public void start() {
@@ -109,6 +112,9 @@ public class MetricsServiceImpl implements MetricsService {
         AbstractMetricsSource src = (AbstractMetricsSource) sourceClass.newInstance();
         src.init(MetricsConfiguration.getSubsetConfiguration(configuration, "source." + sourceName + "."), sink);
         sources.put(sourceName, src);
+        if (src instanceof StompEventsMetricsSource) {
+          stateUpdateEventPublisher.register(src);
+        }
         src.start();
       }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/1e64135c/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/StompEventsMetricsSource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/StompEventsMetricsSource.java b/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/StompEventsMetricsSource.java
new file mode 100644
index 0000000..dfc1484
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/metrics/system/impl/StompEventsMetricsSource.java
@@ -0,0 +1,107 @@
+/**
+ * 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.metrics.system.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.ambari.server.events.AmbariUpdateEvent;
+import org.apache.ambari.server.metrics.system.MetricsSink;
+import org.apache.ambari.server.metrics.system.SingleMetric;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.eventbus.Subscribe;
+
+/**
+ * Collects metrics about number of events by types and publishes to configured Metric Sink.
+ */
+public class StompEventsMetricsSource extends AbstractMetricsSource {
+  private static Logger LOG = LoggerFactory.getLogger(StompEventsMetricsSource.class);
+
+  private Map<AmbariUpdateEvent.Type, Long> events = new HashMap<>();
+  private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
+
+  private final String EVENTS_TOTAL_METRIC = "events.total";
+  private final String AVERAGE_METRIC_SUFFIX = ".avg";
+
+  private int interval = 60;
+
+  @Override
+  public void init(MetricsConfiguration configuration, MetricsSink sink) {
+    super.init(configuration, sink);
+    for (AmbariUpdateEvent.Type type : AmbariUpdateEvent.Type.values()) {
+      events.put(type, 0L);
+    }
+
+  }
+
+  @Override
+  public void start() {
+    LOG.info("Starting stomp events source...");
+    try {
+      executor.scheduleWithFixedDelay(new Runnable() {
+        @Override
+        public void run() {
+          List<SingleMetric> events = getEvents();
+          if (!events.isEmpty()) {
+            sink.publish(events);
+            LOG.debug("********* Published stomp events metrics to sink **********");
+          }
+        }
+      }, interval, interval, TimeUnit.SECONDS);
+    } catch (Exception e) {
+      LOG.info("Throwing exception when starting stomp events source", e);
+    }
+  }
+
+  private List<SingleMetric> getEvents() {
+    List<SingleMetric> metrics = new ArrayList<>();
+    Long totalEventsCounter = 0L;
+    synchronized (events) {
+      for (Map.Entry<AmbariUpdateEvent.Type, Long> event : events.entrySet()) {
+        totalEventsCounter += event.getValue();
+        metrics.add(new SingleMetric(event.getKey().getMetricName(), event.getValue(), System.currentTimeMillis()));
+
+        String averageMetricName = event.getKey().getMetricName() + AVERAGE_METRIC_SUFFIX;
+        Double eventsPerSecond = event.getValue() == 0 ? -1 : (double) interval / (double) event.getValue();
+        metrics.add(new SingleMetric(averageMetricName,
+                eventsPerSecond, System.currentTimeMillis()));
+        events.put(event.getKey(), 0L);
+      }
+      metrics.add(new SingleMetric(EVENTS_TOTAL_METRIC, totalEventsCounter, System.currentTimeMillis()));
+
+      String totalAverageMetricName = EVENTS_TOTAL_METRIC + AVERAGE_METRIC_SUFFIX;
+      Double eventsPerSecond = totalEventsCounter == 0 ? -1 : (double) interval / (double) totalEventsCounter;
+      metrics.add(new SingleMetric(totalAverageMetricName,
+              eventsPerSecond, System.currentTimeMillis()));
+    }
+    return metrics;
+  }
+
+  @Subscribe
+  public void onUpdateEvent(AmbariUpdateEvent ambariUpdateEvent) {
+    AmbariUpdateEvent.Type metricType = ambariUpdateEvent.getType();
+    events.put(metricType, events.get(metricType) + 1);
+  }
+}


[3/4] ambari git commit: AMBARI-21201. Add ConfigChange event to capture config changes (mpapirkovskyy)

Posted by mp...@apache.org.
AMBARI-21201. Add ConfigChange event to capture config changes (mpapirkovskyy)


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

Branch: refs/heads/branch-3.0-perf
Commit: 421ac277649f697f022501b17d767c27c83d946e
Parents: 1e64135
Author: Myroslav Papirkovskyi <mp...@hortonworks.com>
Authored: Thu Jun 8 18:02:42 2017 +0300
Committer: Myroslav Papirkovskyi <mp...@hortonworks.com>
Committed: Thu Jun 22 18:25:50 2017 +0300

----------------------------------------------------------------------
 .../actionmanager/ActionDBAccessorImpl.java     |   6 +-
 .../actionmanager/ExecutionCommandWrapper.java  |  44 +---
 .../apache/ambari/server/agent/AgentEnv.java    |  21 ++
 .../server/agent/AgentSessionManager.java       |   4 +
 .../server/agent/AlertDefinitionCommand.java    |   5 +
 .../server/agent/AlertExecutionCommand.java     |   3 +
 .../ambari/server/agent/CancelCommand.java      |   2 +
 .../ambari/server/agent/CommandReport.java      |  26 +++
 .../apache/ambari/server/agent/DiskInfo.java    |  14 ++
 .../ambari/server/agent/ExecutionCommand.java   |  24 +++
 .../apache/ambari/server/agent/HeartBeat.java   |   9 +
 .../ambari/server/agent/HeartBeatHandler.java   |  74 +------
 .../ambari/server/agent/HeartBeatResponse.java  |  12 ++
 .../apache/ambari/server/agent/HostInfo.java    |  62 ++++++
 .../apache/ambari/server/agent/HostStatus.java  |   4 +
 .../ambari/server/agent/RecoveryConfig.java     |   7 +
 .../ambari/server/agent/RecoveryReport.java     |   4 +
 .../apache/ambari/server/agent/Register.java    |   2 +
 .../server/agent/RegistrationResponse.java      |   8 +
 .../ambari/server/agent/StatusCommand.java      |  12 ++
 .../agent/stomp/AgentClusterDataHolder.java     | 112 ++++++++++
 .../agent/stomp/AgentCurrentDataController.java |  77 +++++++
 .../server/agent/stomp/HeartbeatController.java |  14 +-
 .../server/agent/stomp/MetadataHolder.java      |  55 +++++
 .../server/agent/stomp/TopologyHolder.java      | 159 ++++++++++++++
 .../server/agent/stomp/dto/ClusterConfigs.java  |  50 +++++
 .../agent/stomp/dto/ComponentStatusReports.java |  10 +-
 .../ambari/server/agent/stomp/dto/Hash.java     |  41 ++++
 .../ambari/server/agent/stomp/dto/Hashable.java |  27 +++
 .../server/agent/stomp/dto/MetadataCluster.java |  69 ++++++
 .../agent/stomp/dto/MetadataServiceInfo.java    |  71 +++++++
 .../server/agent/stomp/dto/TopologyCluster.java |  56 +++++
 .../agent/stomp/dto/TopologyComponent.java      | 101 ++++++++-
 .../server/agent/stomp/dto/TopologyHost.java    |  46 +++-
 .../stomp/dto/TopologyStatusCommandParams.java  |  47 ----
 .../api/query/render/AlertStateSummary.java     |   6 +-
 .../api/query/render/AlertStateValues.java      |   9 +-
 .../render/AlertSummaryGroupedRenderer.java     | 135 ++++++------
 .../server/api/services/AmbariMetaInfo.java     |  27 ---
 .../AmbariCustomCommandExecutionHelper.java     |  37 +++-
 .../AmbariManagementControllerImpl.java         | 212 ++++++++++++++++---
 .../DeleteHostComponentStatusMetaData.java      |  44 +++-
 .../internal/HostResourceProvider.java          |  44 ++--
 .../server/events/AgentConfigsUpdateEvent.java  |  62 ++++++
 .../ambari/server/events/AlertUpdateEvent.java  |  20 +-
 .../ambari/server/events/AmbariUpdateEvent.java |   3 +-
 .../server/events/ConfigsUpdateEvent.java       |  28 ++-
 .../server/events/MetadataUpdateEvent.java      |  41 +++-
 .../events/NamedHostRoleCommandUpdateEvent.java | 127 +++++++++++
 .../server/events/RequestUpdateEvent.java       |  81 ++++++-
 .../server/events/TopologyUpdateEvent.java      |  33 ++-
 .../listeners/alerts/AlertReceivedListener.java |  32 ++-
 .../listeners/tasks/TaskStatusListener.java     |  39 +++-
 .../ambari/server/orm/dao/ServiceConfigDAO.java |  34 +++
 .../orm/entities/ServiceConfigEntity.java       |   1 +
 .../org/apache/ambari/server/state/Alert.java   |  20 ++
 .../ambari/server/state/ConfigHelper.java       |  98 +++++++++
 .../ambari/server/state/ServiceComponent.java   |   2 +
 .../server/state/ServiceComponentImpl.java      |   5 +
 .../server/state/cluster/ClusterImpl.java       |  80 ++++++-
 .../server/state/cluster/ClustersImpl.java      |  15 ++
 .../svccomphost/ServiceComponentHostImpl.java   |   6 +-
 .../server/topology/TopologyDeleteFormer.java   |  14 +-
 .../listeners/tasks/TaskStatusListenerTest.java |   7 +-
 64 files changed, 2136 insertions(+), 404 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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 d372844..d5ae5b5 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
@@ -361,15 +361,16 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
     RequestEntity requestEntity = request.constructNewPersistenceEntity();
 
     Long clusterId = -1L;
+    String clusterName = null;
     Long requestId = requestEntity.getRequestId();
     ClusterEntity clusterEntity = clusterDAO.findById(request.getClusterId());
     if (clusterEntity != null) {
       clusterId = clusterEntity.getClusterId();
+      clusterName = clusterEntity.getClusterName();
     }
 
     requestEntity.setClusterId(clusterId);
     requestDAO.create(requestEntity);
-    stateUpdateEventPublisher.publish(new RequestUpdateEvent(requestEntity, hostRoleCommandDAO, topologyManager));
 
     //TODO wire request to cluster
     List<StageEntity> stageEntities = new ArrayList<>(request.getStages().size());
@@ -460,6 +461,9 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
 
     TaskCreateEvent taskCreateEvent = new TaskCreateEvent(hostRoleCommands);
     taskEventPublisher.publish(taskCreateEvent);
+    List<HostRoleCommandEntity> hostRoleCommandEntities = hostRoleCommandDAO.findByRequest(requestEntity.getRequestId());
+    stateUpdateEventPublisher.publish(new RequestUpdateEvent(requestEntity,
+        hostRoleCommandDAO, topologyManager, clusterName, hostRoleCommandEntities));
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
index fe6707e..1f92ce7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
@@ -17,7 +17,6 @@
  */
 package org.apache.ambari.server.actionmanager;
 
-import java.util.HashMap;
 import java.util.Map;
 import java.util.TreeMap;
 
@@ -137,46 +136,9 @@ public class ExecutionCommandWrapper {
       // now that the tags have been updated (if necessary), fetch the
       // configurations
       Map<String, Map<String, String>> configurationTags = executionCommand.getConfigurationTags();
-      if (null != configurationTags && !configurationTags.isEmpty()) {
-        Map<String, Map<String, String>> configProperties = configHelper
-            .getEffectiveConfigProperties(cluster, configurationTags);
-
-        // Apply the configurations saved with the Execution Cmd on top of
-        // derived configs - This will take care of all the hacks
-        for (Map.Entry<String, Map<String, String>> entry : configProperties.entrySet()) {
-          String type = entry.getKey();
-          Map<String, String> allLevelMergedConfig = entry.getValue();
-
-          if (configurations.containsKey(type)) {
-            Map<String, String> mergedConfig = configHelper.getMergedConfig(allLevelMergedConfig,
-                configurations.get(type));
-
-            configurations.get(type).clear();
-            configurations.get(type).putAll(mergedConfig);
-
-          } else {
-            configurations.put(type, new HashMap<String, String>());
-            configurations.get(type).putAll(allLevelMergedConfig);
-          }
-        }
-
-        Map<String, Map<String, Map<String, String>>> configAttributes = configHelper.getEffectiveConfigAttributes(
-            cluster, executionCommand.getConfigurationTags());
-
-        for (Map.Entry<String, Map<String, Map<String, String>>> attributesOccurrence : configAttributes.entrySet()) {
-          String type = attributesOccurrence.getKey();
-          Map<String, Map<String, String>> attributes = attributesOccurrence.getValue();
-
-          if (executionCommand.getConfigurationAttributes() != null) {
-            if (!executionCommand.getConfigurationAttributes().containsKey(type)) {
-              executionCommand.getConfigurationAttributes().put(type,
-                  new TreeMap<String, Map<String, String>>());
-            }
-            configHelper.cloneAttributesMap(attributes,
-                executionCommand.getConfigurationAttributes().get(type));
-            }
-        }
-      }
+      configHelper.getAndMergeHostConfigs(configurations, configurationTags, cluster);
+      configHelper.getAndMergeHostConfigAttributes(executionCommand.getConfigurationAttributes(),
+          configurationTags, cluster);
     } catch (ClusterNotFoundException cnfe) {
       // it's possible that there are commands without clusters; in such cases,
       // just return the de-serialized command and don't try to read configs

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentEnv.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentEnv.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentEnv.java
index 92cdd58..382c985 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentEnv.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentEnv.java
@@ -163,24 +163,28 @@ public class AgentEnv {
      * Java processes running on the system.  Default empty array.
      */
     @SerializedName("activeJavaProcs")
+    @com.fasterxml.jackson.annotation.JsonProperty("activeJavaProcs")
     private JavaProc[] activeJavaProcs = new JavaProc[0];
 
     /**
      * The current time when agent send the host check report
      */
     @SerializedName("agentTimeStampAtReporting")
+    @com.fasterxml.jackson.annotation.JsonProperty("agentTimeStampAtReporting")
     private long agentTimeStampAtReporting = 0;
 
     /**
      * The current time when host check report was received
      */
     @SerializedName("serverTimeStampAtReporting")
+    @com.fasterxml.jackson.annotation.JsonProperty("serverTimeStampAtReporting")
     private long serverTimeStampAtReporting = 0;
 
     /**
      * Live services running on the agent
      */
     @SerializedName("liveServices")
+    @com.fasterxml.jackson.annotation.JsonProperty("liveServices")
     private LiveService[] liveServices = new LiveService[0];
 
     public void setAgentTimeStampAtReporting(long currentTime) {
@@ -218,10 +222,13 @@ public class AgentEnv {
 
   public static class PackageDetail {
     @SerializedName("name")
+    @com.fasterxml.jackson.annotation.JsonProperty("name")
     private String pkgName;
     @SerializedName("version")
+    @com.fasterxml.jackson.annotation.JsonProperty("version")
     private String pkgVersion;
     @SerializedName("repoName")
+    @com.fasterxml.jackson.annotation.JsonProperty("repoName")
     private String pkgRepoName;
 
     public void setName(String name) {
@@ -254,8 +261,10 @@ public class AgentEnv {
    */
   public static class Directory {
     @SerializedName("name")
+    @com.fasterxml.jackson.annotation.JsonProperty("name")
     private String dirName;
     @SerializedName("type")
+    @com.fasterxml.jackson.annotation.JsonProperty("type")
     private String dirType;
     
     public void setName(String name) {
@@ -280,12 +289,16 @@ public class AgentEnv {
    */
   public static class JavaProc {
     @SerializedName("user")        
+    @com.fasterxml.jackson.annotation.JsonProperty("user")
     private String user;
     @SerializedName("pid") 
+    @com.fasterxml.jackson.annotation.JsonProperty("pid")
     private int pid = 0;
     @SerializedName("hadoop") 
+    @com.fasterxml.jackson.annotation.JsonProperty("hadoop")
     private boolean is_hadoop = false;
     @SerializedName("command") 
+    @com.fasterxml.jackson.annotation.JsonProperty("command")
     private String command;
     
     public void setUser(String user) {
@@ -323,8 +336,10 @@ public class AgentEnv {
   
   public static class Alternative {
     @SerializedName("name")
+    @com.fasterxml.jackson.annotation.JsonProperty("name")
     private String altName;
     @SerializedName("target")
+    @com.fasterxml.jackson.annotation.JsonProperty("target")
     private String altTarget;
     
     public void setName(String name) {
@@ -346,10 +361,13 @@ public class AgentEnv {
 
   public static class LiveService {
     @SerializedName("name")
+    @com.fasterxml.jackson.annotation.JsonProperty("name")
     private String svcName;
     @SerializedName("status")
+    @com.fasterxml.jackson.annotation.JsonProperty("status")
     private String svcStatus;
     @SerializedName("desc")
+    @com.fasterxml.jackson.annotation.JsonProperty("desc")
     private String svcDesc;
 
     public void setName(String name) {
@@ -379,10 +397,13 @@ public class AgentEnv {
 
   public static class ExistingUser {
     @SerializedName("name")
+    @com.fasterxml.jackson.annotation.JsonProperty("name")
     private String name;
     @SerializedName("homeDir")
+    @com.fasterxml.jackson.annotation.JsonProperty("homeDir")
     private String homeDir;
     @SerializedName("status")
+    @com.fasterxml.jackson.annotation.JsonProperty("status")
     private String status;
 
     public void setUserName(String userName) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentSessionManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentSessionManager.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentSessionManager.java
index d9b595a..496a697 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentSessionManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/AgentSessionManager.java
@@ -39,6 +39,10 @@ public class AgentSessionManager {
     registeredHosts.put(sessionId, registeredHost);
   }
 
+  public boolean isRegistered(String sessionId) {
+    return registeredHosts.containsKey(sessionId);
+  }
+
   public Host getHost(String sessionId) throws HostNotRegisteredException {
     if (registeredHosts.containsKey(sessionId)) {
       return registeredHosts.get(sessionId);

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertDefinitionCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertDefinitionCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertDefinitionCommand.java
index 4d2e048..07029c7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertDefinitionCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertDefinitionCommand.java
@@ -41,18 +41,23 @@ import com.google.gson.annotations.SerializedName;
  */
 public class AlertDefinitionCommand extends AgentCommand {
   @SerializedName("clusterName")
+  @com.fasterxml.jackson.annotation.JsonProperty("clusterName")
   private final String m_clusterName;
 
   @SerializedName("hostName")
+  @com.fasterxml.jackson.annotation.JsonProperty("hostName")
   private final String m_hostName;
 
   @SerializedName("hash")
+  @com.fasterxml.jackson.annotation.JsonProperty("hash")
   private final String m_hash;
 
   @SerializedName("alertDefinitions")
+  @com.fasterxml.jackson.annotation.JsonProperty("alertDefinitions")
   private final List<AlertDefinition> m_definitions;
 
   @SerializedName("configurations")
+  @com.fasterxml.jackson.annotation.JsonProperty("configurations")
   private Map<String, Map<String, String>> m_configurations;
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertExecutionCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertExecutionCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertExecutionCommand.java
index b0781da..7a1bd8b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertExecutionCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/AlertExecutionCommand.java
@@ -33,18 +33,21 @@ public class AlertExecutionCommand extends AgentCommand {
    * The name of the cluster.
    */
   @SerializedName("clusterName")
+  @com.fasterxml.jackson.annotation.JsonProperty("clusterName")
   private final String m_clusterName;
 
   /**
    * The agent hostname.
    */
   @SerializedName("hostName")
+  @com.fasterxml.jackson.annotation.JsonProperty("hostName")
   private final String m_hostName;
 
   /**
    * The definition to run.
    */
   @SerializedName("alertDefinition")
+  @com.fasterxml.jackson.annotation.JsonProperty("alertDefinition")
   private final AlertDefinition m_definition;
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/CancelCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/CancelCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/CancelCommand.java
index 7aa24c8..ea4ccc2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/CancelCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/CancelCommand.java
@@ -29,9 +29,11 @@ public class CancelCommand extends AgentCommand {
   }
 
   @SerializedName("target_task_id")
+  @com.fasterxml.jackson.annotation.JsonProperty("target_task_id")
   private long targetTaskId;
 
   @SerializedName("reason")
+  @com.fasterxml.jackson.annotation.JsonProperty("reason")
   private String reason;
 
   public long getTargetTaskId() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandReport.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandReport.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandReport.java
index 2c20ae9..bca562a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandReport.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandReport.java
@@ -39,122 +39,146 @@ public class CommandReport {
   private Map<String, Map<String, String>> configurationTags;
 
   @JsonProperty("customCommand")
+  @com.fasterxml.jackson.annotation.JsonProperty("customCommand")
   public String getCustomCommand() {
     return customCommand;
   }
 
   @JsonProperty("customCommand")
+  @com.fasterxml.jackson.annotation.JsonProperty("customCommand")
   public void setCustomCommand(String customCommand) {
     this.customCommand = customCommand;
   }
 
   @JsonProperty("taskId")
+  @com.fasterxml.jackson.annotation.JsonProperty("taskId")
   public long getTaskId() {
     return taskId;
   }
   
   @JsonProperty("taskId")
+  @com.fasterxml.jackson.annotation.JsonProperty("taskId")
   public void setTaskId(long taskId) {
     this.taskId = taskId;
   }
   
   @JsonProperty("clusterName")
+  @com.fasterxml.jackson.annotation.JsonProperty("clusterName")
   public void setClusterName(String clusterName) {
     this.clusterName = clusterName;
   }
   
   @JsonProperty("clusterName")
+  @com.fasterxml.jackson.annotation.JsonProperty("clusterName")
   public String getClusterName() {
     return this.clusterName;
   }
 
   @JsonProperty("actionId")
+  @com.fasterxml.jackson.annotation.JsonProperty("actionId")
   public String getActionId() {
     return this.actionId;
   }
   
   @JsonProperty("actionId")
+  @com.fasterxml.jackson.annotation.JsonProperty("actionId")
   public void setActionId(String actionId) {
     this.actionId = actionId;
   }
   
   @JsonProperty("stderr")
+  @com.fasterxml.jackson.annotation.JsonProperty("stderr")
   public String getStdErr() {
     return this.stderr;
   }
   
   @JsonProperty("stderr")
+  @com.fasterxml.jackson.annotation.JsonProperty("stderr")
   public void setStdErr(String stderr) {
     this.stderr = stderr;
   }
   
   @JsonProperty("exitcode")
+  @com.fasterxml.jackson.annotation.JsonProperty("exitcode")
   public int getExitCode() {
     return this.exitCode;
   }
   
   @JsonProperty("exitcode")
+  @com.fasterxml.jackson.annotation.JsonProperty("exitcode")
   public void setExitCode(int exitCode) {
     this.exitCode = exitCode;
   }
   
   @JsonProperty("stdout")
+  @com.fasterxml.jackson.annotation.JsonProperty("stdout")
   public String getStdOut() {
     return this.stdout;
   }
   
   @JsonProperty("stdout")
+  @com.fasterxml.jackson.annotation.JsonProperty("stdout")
   public void setStdOut(String stdout) {
     this.stdout = stdout;
   }
 
   @JsonProperty("structuredOut")
+  @com.fasterxml.jackson.annotation.JsonProperty("structuredOut")
   public String getStructuredOut() {
     return this.structuredOut;
   }
 
 
   @JsonProperty("structuredOut")
+  @com.fasterxml.jackson.annotation.JsonProperty("structuredOut")
   public void setStructuredOut(String structuredOut) {
     this.structuredOut = structuredOut;
   }
 
   @JsonProperty("roleCommand")
+  @com.fasterxml.jackson.annotation.JsonProperty("roleCommand")
   public String getRoleCommand() {
     return this.roleCommand;
   }
 
   @JsonProperty("roleCommand")
+  @com.fasterxml.jackson.annotation.JsonProperty("roleCommand")
   public void setRoleCommand(String roleCommand) {
     this.roleCommand = roleCommand;
   }
 
   @JsonProperty("role")
+  @com.fasterxml.jackson.annotation.JsonProperty("role")
   public String getRole() {
     return role;
   }
   
   @JsonProperty("role")
+  @com.fasterxml.jackson.annotation.JsonProperty("role")
   public void setRole(String role) {
     this.role = role;
   }
   
   @JsonProperty("status")
+  @com.fasterxml.jackson.annotation.JsonProperty("status")
   public String getStatus() {
     return status;
   }
   
   @JsonProperty("status")
+  @com.fasterxml.jackson.annotation.JsonProperty("status")
   public void setStatus(String status) {
     this.status = status;
   }
   
   @JsonProperty("serviceName")
+  @com.fasterxml.jackson.annotation.JsonProperty("serviceName")
   public String getServiceName() {
     return serviceName;
   }
   
   @JsonProperty("serviceName")
+  @com.fasterxml.jackson.annotation.JsonProperty("serviceName")
   public void setServiceName(String serviceName) {
     this.serviceName = serviceName;
   }
@@ -163,6 +187,7 @@ public class CommandReport {
    * @param tags the config tags that match this command
    */
   @JsonProperty("configurationTags")
+  @com.fasterxml.jackson.annotation.JsonProperty("configurationTags")
   public void setConfigurationTags(Map<String, Map<String,String>> tags) {
     configurationTags = tags;
   }
@@ -172,6 +197,7 @@ public class CommandReport {
    * if none are present
    */
   @JsonProperty("configurationTags")
+  @com.fasterxml.jackson.annotation.JsonProperty("configurationTags")
   public Map<String, Map<String,String>> getConfigurationTags() {
     return configurationTags;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/DiskInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/DiskInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/DiskInfo.java
index 0f345b8..6d4738c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/DiskInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/DiskInfo.java
@@ -59,71 +59,85 @@ public class DiskInfo {
   public DiskInfo() {}
 
   @JsonProperty("available")
+  @com.fasterxml.jackson.annotation.JsonProperty("available")
   public void setAvailable(String available) {
     this.available = available;
   }
   
   @JsonProperty("available")
+  @com.fasterxml.jackson.annotation.JsonProperty("available")
   public String getAvailable() {
     return this.available;
   }
 
   @JsonProperty("mountpoint")
+  @com.fasterxml.jackson.annotation.JsonProperty("mountpoint")
   public String getMountPoint() {
     return this.mountpoint;
   }
   
   @JsonProperty("mountpoint")
+  @com.fasterxml.jackson.annotation.JsonProperty("mountpoint")
   public void setMountPoint(String mountpoint) {
     this.mountpoint = mountpoint;
   }
 
   @JsonProperty("type")
+  @com.fasterxml.jackson.annotation.JsonProperty("type")
   public String getType() {
     return this.type;
   }
 
   @JsonProperty("type")
+  @com.fasterxml.jackson.annotation.JsonProperty("type")
   public void setType(String type) {
     this.type = type;
   }
   
   @JsonProperty("used")
+  @com.fasterxml.jackson.annotation.JsonProperty("used")
   public String getUsed() {
     return this.used;
   }
 
   @JsonProperty("used")
+  @com.fasterxml.jackson.annotation.JsonProperty("used")
   public void setUsed(String used) {
     this.used = used;
   }
   
   @JsonProperty("percent")
+  @com.fasterxml.jackson.annotation.JsonProperty("percent")
   public String getPercent() {
     return this.percent;
   }
   
   @JsonProperty("percent")
+  @com.fasterxml.jackson.annotation.JsonProperty("percent")
   public void setPercent(String percent) {
     this.percent = percent;
   }
   
   @JsonProperty("size")
+  @com.fasterxml.jackson.annotation.JsonProperty("size")
   public String getSize() {
     return this.size;
   }
   
   @JsonProperty("size")
+  @com.fasterxml.jackson.annotation.JsonProperty("size")
   public void setSize(String size) {
     this.size = size;
   }
 
   @JsonProperty("device")
+  @com.fasterxml.jackson.annotation.JsonProperty("device")
   public String getDevice() {
     return device;
   }
 
   @JsonProperty("device")
+  @com.fasterxml.jackson.annotation.JsonProperty("device")
   public void setDevice(String device) {
     this.device = device;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
index 8c726a0..c2579a9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
@@ -46,70 +46,92 @@ public class ExecutionCommand extends AgentCommand {
   }
 
   @SerializedName("clusterName")
+  @com.fasterxml.jackson.annotation.JsonProperty("clusterName")
   private String clusterName;
 
   @SerializedName("requestId")
+  @com.fasterxml.jackson.annotation.JsonProperty("requestId")
   private long requestId;
 
   @SerializedName("stageId")
+  @com.fasterxml.jackson.annotation.JsonProperty("stageId")
   private long stageId;
 
   @SerializedName("taskId")
+  @com.fasterxml.jackson.annotation.JsonProperty("taskId")
   private long taskId;
 
   @SerializedName("commandId")
+  @com.fasterxml.jackson.annotation.JsonProperty("commandId")
   private String commandId;
 
   @SerializedName("hostname")
+  @com.fasterxml.jackson.annotation.JsonProperty("hostname")
   private String hostname;
 
   @SerializedName("role")
+  @com.fasterxml.jackson.annotation.JsonProperty("role")
   private String role;
 
   @SerializedName("hostLevelParams")
+  @com.fasterxml.jackson.annotation.JsonProperty("hostLevelParams")
   private Map<String, String> hostLevelParams = new HashMap<>();
 
   @SerializedName("roleParams")
+  @com.fasterxml.jackson.annotation.JsonProperty("roleParams")
   private Map<String, String> roleParams = null;
 
   @SerializedName("roleCommand")
+  @com.fasterxml.jackson.annotation.JsonProperty("roleCommand")
   private RoleCommand roleCommand;
 
   @SerializedName("clusterHostInfo")
+  @com.fasterxml.jackson.annotation.JsonProperty("clusterHostInfo")
   private Map<String, Set<String>> clusterHostInfo =
     new HashMap<>();
 
   @SerializedName("configurations")
+  @com.fasterxml.jackson.annotation.JsonProperty("configurations")
   private Map<String, Map<String, String>> configurations;
 
   @SerializedName("configuration_attributes")
+  @com.fasterxml.jackson.annotation.JsonProperty("configuration_attributes")
   private Map<String, Map<String, Map<String, String>>> configurationAttributes;
 
   @SerializedName("configurationTags")
+  @com.fasterxml.jackson.annotation.JsonProperty("configurationTags")
   private Map<String, Map<String, String>> configurationTags;
 
   @SerializedName("forceRefreshConfigTagsBeforeExecution")
+  @com.fasterxml.jackson.annotation.JsonProperty("forceRefreshConfigTagsBeforeExecution")
   private boolean forceRefreshConfigTagsBeforeExecution = false;
 
   @SerializedName("commandParams")
+  @com.fasterxml.jackson.annotation.JsonProperty("commandParams")
   private Map<String, String> commandParams = new HashMap<>();
 
   @SerializedName("serviceName")
+  @com.fasterxml.jackson.annotation.JsonProperty("serviceName")
   private String serviceName;
 
   @SerializedName("serviceType")
+  @com.fasterxml.jackson.annotation.JsonProperty("serviceType")
   private String serviceType;
 
   @SerializedName("componentName")
+  @com.fasterxml.jackson.annotation.JsonProperty("componentName")
   private String componentName;
 
   @SerializedName("kerberosCommandParams")
+  @com.fasterxml.jackson.annotation.JsonProperty("kerberosCommandParams")
   private List<Map<String, String>> kerberosCommandParams = new ArrayList<>();
 
   @SerializedName("localComponents")
+  @com.fasterxml.jackson.annotation.JsonProperty("localComponents")
   private Set<String> localComponents = new HashSet<>();
 
   @SerializedName("availableServices")
+  @com.fasterxml.jackson.annotation.JsonProperty("availableServices")
   private Map<String, String> availableServices = new HashMap<>();
 
   /**
@@ -117,6 +139,7 @@ public class ExecutionCommand extends AgentCommand {
    * service is enabled for credential store use.
    */
   @SerializedName("credentialStoreEnabled")
+  @com.fasterxml.jackson.annotation.JsonProperty("credentialStoreEnabled")
   private String credentialStoreEnabled;
 
   /**
@@ -142,6 +165,7 @@ public class ExecutionCommand extends AgentCommand {
    *   </pre>
    */
   @SerializedName("configuration_credentials")
+  @com.fasterxml.jackson.annotation.JsonProperty("configuration_credentials")
   private Map<String, Map<String, String>> configurationCredentials;
 
   public void setConfigurationCredentials(Map<String, Map<String, String>> configurationCredentials) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeat.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeat.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeat.java
index 7d5f78c..922f6ee 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeat.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeat.java
@@ -32,7 +32,10 @@ import org.codehaus.jackson.annotate.JsonProperty;
  */
 
 public class HeartBeat {
+
+  @com.fasterxml.jackson.annotation.JsonProperty("id")
   private long responseId = -1;
+
   private long timestamp;
   private String hostname;
   List<CommandReport> reports = new ArrayList<>();
@@ -87,11 +90,13 @@ public class HeartBeat {
   }
 
   @JsonProperty("reports")
+  @com.fasterxml.jackson.annotation.JsonProperty("reports")
   public List<CommandReport> getReports() {
     return reports;
   }
 
   @JsonProperty("reports")
+  @com.fasterxml.jackson.annotation.JsonProperty("reports")
   public void setReports(List<CommandReport> reports) {
     this.reports = reports;
   }
@@ -121,21 +126,25 @@ public class HeartBeat {
   }
 
   @JsonProperty("componentStatus")
+  @com.fasterxml.jackson.annotation.JsonProperty("componentStatus")
   public List<ComponentStatus> getComponentStatus() {
     return componentStatus;
   }
 
   @JsonProperty("componentStatus")
+  @com.fasterxml.jackson.annotation.JsonProperty("componentStatus")
   public void setComponentStatus(List<ComponentStatus> componentStatus) {
     this.componentStatus = componentStatus;
   }
 
   @JsonProperty("mounts")
+  @com.fasterxml.jackson.annotation.JsonProperty("mounts")
   public List<DiskInfo> getMounts() {
     return mounts;
   }
 
   @JsonProperty("mounts")
+  @com.fasterxml.jackson.annotation.JsonProperty("mounts")
   public void setMounts(List<DiskInfo> mounts) {
     this.mounts = mounts;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
index 67ec87d..e890761 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
@@ -22,25 +22,18 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.regex.Pattern;
-import java.util.stream.Collectors;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.HostNotFoundException;
 import org.apache.ambari.server.actionmanager.ActionManager;
-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.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.events.TopologyUpdateEvent;
 import org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileReader;
 import org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileReaderFactory;
 import org.apache.ambari.server.serveraction.kerberos.KerberosServerAction;
@@ -51,8 +44,6 @@ import org.apache.ambari.server.state.ComponentInfo;
 import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.HostState;
-import org.apache.ambari.server.state.Service;
-import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.StackId;
@@ -63,7 +54,6 @@ import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
 import org.apache.ambari.server.state.host.HostHealthyHeartbeatEvent;
 import org.apache.ambari.server.state.host.HostRegistrationRequestEvent;
 import org.apache.ambari.server.state.host.HostStatusUpdatesReceivedEvent;
-import org.apache.ambari.server.state.host.HostUnhealthyHeartbeatEvent;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.ambari.server.utils.VersionUtils;
 import org.apache.commons.codec.binary.Base64;
@@ -223,13 +213,8 @@ public class HeartBeatHandler {
     }
 
     try {
-      if (heartbeat.getNodeStatus().getStatus().equals(HostStatus.Status.HEALTHY)) {
-        hostObject.handleEvent(new HostHealthyHeartbeatEvent(hostname, now,
-            heartbeat.getAgentEnv(), heartbeat.getMounts()));
-      } else {
-        hostObject.handleEvent(new HostUnhealthyHeartbeatEvent(hostname, now,
-            null));
-      }
+      hostObject.handleEvent(new HostHealthyHeartbeatEvent(hostname, now,
+          heartbeat.getAgentEnv(), heartbeat.getMounts()));
     } catch (InvalidStateTransitionException ex) {
       LOG.warn("Asking agent to re-register due to " + ex.getMessage(), ex);
       hostObject.setState(HostState.INIT);
@@ -353,7 +338,7 @@ public class HeartBeatHandler {
     return osType.toLowerCase();
   }
 
-  protected HeartBeatResponse createRegisterCommand() {
+  public HeartBeatResponse createRegisterCommand() {
     HeartBeatResponse response = new HeartBeatResponse();
     RegistrationCommand regCmd = new RegistrationCommand();
     response.setResponseId(0);
@@ -481,59 +466,6 @@ public class HeartBeatHandler {
   }
 
   /**
-   * 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
-   * @throws InvalidStateTransitionException
-   * @throws AmbariException
-   */
-  //TODO need move to better place
-  public TopologyUpdateEvent getInitialClusterTopology()
-      throws InvalidStateTransitionException, AmbariException {
-    Map<String, TopologyCluster> topologyClusters = new HashMap<>();
-    for (Cluster cl : clusterFsm.getClusters().values()) {
-      Collection<Host> clusterHosts = cl.getHosts();
-      Set<TopologyComponent> topologyComponents = new HashSet<>();
-      Set<TopologyHost> topologyHosts = new HashSet<>();
-      for (Host host : clusterHosts) {
-        topologyHosts.add(new TopologyHost(host.getHostId(), host.getHostName(),
-            host.getRackInfo(), host.getIPv4()));
-      }
-      for (Service service : cl.getServices().values()) {
-        for (ServiceComponent component : service.getServiceComponents().values()) {
-          Map<String, ServiceComponentHost> componentsMap = component.getServiceComponentHosts();
-          if (!componentsMap.isEmpty()) {
-
-            //TODO will be a need to change to multi-instance usage
-            ServiceComponentHost sch = componentsMap.entrySet().iterator().next().getValue();
-
-            Set<String> hostNames = cl.getHosts(sch.getServiceName(), sch.getServiceComponentName());
-            Set<Long> hostOrderIds = clusterHosts.stream()
-                .filter(h -> hostNames.contains(h.getHostName()))
-                .map(h -> h.getHostId()).collect(Collectors.toSet());
-            String serviceName = sch.getServiceName();
-            String componentName = sch.getServiceComponentName();
-            StackId stackId = cl.getDesiredStackVersion();
-
-            TopologyComponent topologyComponent = TopologyComponent.newBuilder()
-                .setComponentName(sch.getServiceComponentName())
-                .setServiceName(sch.getServiceName())
-                .setVersion(sch.getVersion())
-                .setHostIds(hostOrderIds)
-                .setStatusCommandParams(ambariMetaInfo.getStatusCommandParams(stackId, serviceName, componentName))
-                .build();
-            topologyComponents.add(topologyComponent);
-          }
-        }
-      }
-      topologyClusters.put(Long.toString(cl.getClusterId()),
-          new TopologyCluster(topologyComponents, topologyHosts));
-    }
-    TopologyUpdateEvent topologyUpdateEvent = new TopologyUpdateEvent(topologyClusters,
-        TopologyUpdateEvent.EventType.UPDATE);
-    return topologyUpdateEvent;
-  }
-
-  /**
    * Annotate the response with some housekeeping details.
    * hasMappedComponents - indicates if any components are mapped to the host
    * hasPendingTasks - indicates if any tasks are pending for the host (they may not be sent yet)

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatResponse.java
index 0cfc68d..b46bac9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatResponse.java
@@ -29,15 +29,19 @@ import com.google.gson.annotations.SerializedName;
 public class HeartBeatResponse {
 
   @SerializedName("responseId")
+  @com.fasterxml.jackson.annotation.JsonProperty("id")
   private long responseId;
 
   @SerializedName("executionCommands")
+  @com.fasterxml.jackson.annotation.JsonProperty("executionCommands")
   private List<ExecutionCommand> executionCommands = new ArrayList<>();
 
   @SerializedName("statusCommands")
+  @com.fasterxml.jackson.annotation.JsonProperty("statusCommands")
   private List<StatusCommand> statusCommands = new ArrayList<>();
 
   @SerializedName("cancelCommands")
+  @com.fasterxml.jackson.annotation.JsonProperty("cancelCommands")
   private List<CancelCommand> cancelCommands = new ArrayList<>();
 
   /**
@@ -48,6 +52,7 @@ public class HeartBeatResponse {
    * the agent to abandon all alert definitions that are scheduled.
    */
   @SerializedName("alertDefinitionCommands")
+  @com.fasterxml.jackson.annotation.JsonProperty("alertDefinitionCommands")
   private List<AlertDefinitionCommand> alertDefinitionCommands = null;
 
   /**
@@ -55,24 +60,31 @@ public class HeartBeatResponse {
    * immediately.
    */
   @SerializedName("alertExecutionCommands")
+  @com.fasterxml.jackson.annotation.JsonProperty("alertExecutionCommands")
   private List<AlertExecutionCommand> alertExecutionCommands = null;
 
   @SerializedName("registrationCommand")
+  @com.fasterxml.jackson.annotation.JsonProperty("registrationCommand")
   private RegistrationCommand registrationCommand;
 
   @SerializedName("restartAgent")
+  @com.fasterxml.jackson.annotation.JsonProperty("restartAgent")
   private boolean restartAgent = false;
 
   @SerializedName("hasMappedComponents")
+  @com.fasterxml.jackson.annotation.JsonProperty("hasMappedComponents")
   private boolean hasMappedComponents = false;
 
   @SerializedName("hasPendingTasks")
+  @com.fasterxml.jackson.annotation.JsonProperty("hasPendingTasks")
   private boolean hasPendingTasks = false;
 
   @SerializedName("recoveryConfig")
+  @com.fasterxml.jackson.annotation.JsonProperty("recoveryConfig")
   private RecoveryConfig recoveryConfig;
 
   @SerializedName("clusterSize")
+  @com.fasterxml.jackson.annotation.JsonProperty("clusterSize")
   private int clusterSize = -1;
 
   public long getResponseId() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/HostInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HostInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HostInfo.java
index d1e5dbc..1c27bbb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HostInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HostInfo.java
@@ -63,311 +63,373 @@ public class HostInfo {
 
 
   @JsonProperty("architecture")
+  @com.fasterxml.jackson.annotation.JsonProperty("architecture")
   public String getArchitecture() {
     return this.architecture;
   }
 
   @JsonProperty("architecture")
+  @com.fasterxml.jackson.annotation.JsonProperty("architecture")
   public void setArchitecture(String architecture) {
     this.architecture = architecture;
   }
 
   @JsonProperty("domain")
+  @com.fasterxml.jackson.annotation.JsonProperty("domain")
   public String getDomain() {
     return this.domain;
   }
 
   @JsonProperty("domain")
+  @com.fasterxml.jackson.annotation.JsonProperty("domain")
   public void setDomain(String domain) {
     this.domain = domain;
   }
 
   @JsonProperty("fqdn")
+  @com.fasterxml.jackson.annotation.JsonProperty("fqdn")
   public String getFQDN() {
     return this.fqdn;
   }
 
   @JsonProperty("fqdn")
+  @com.fasterxml.jackson.annotation.JsonProperty("fqdn")
   public void setFQDN(String fqdn) {
     this.fqdn = fqdn;
   }
 
   @JsonProperty("hardwareisa")
+  @com.fasterxml.jackson.annotation.JsonProperty("hardwareisa")
   public String getHardwareIsa() {
     return hardwareisa;
   }
 
   @JsonProperty("hardwareisa")
+  @com.fasterxml.jackson.annotation.JsonProperty("hardwareisa")
   public void setHardwareIsa(String hardwareisa) {
     this.hardwareisa = hardwareisa;
   }
 
   @JsonProperty("hardwaremodel")
+  @com.fasterxml.jackson.annotation.JsonProperty("hardwaremodel")
   public String getHardwareModel() {
     return this.hardwaremodel;
   }
 
   @JsonProperty("hardwaremodel")
+  @com.fasterxml.jackson.annotation.JsonProperty("hardwaremodel")
   public void setHardwareModel(String hardwaremodel) {
     this.hardwaremodel = hardwaremodel;
   }
 
   @JsonProperty("hostname")
+  @com.fasterxml.jackson.annotation.JsonProperty("hostname")
   public String getHostName() {
     return this.hostname;
   }
 
   @JsonProperty("hostname")
+  @com.fasterxml.jackson.annotation.JsonProperty("hostname")
   public void setHostName(String hostname) {
     this.hostname = hostname;
   }
 
   @JsonProperty("id")
+  @com.fasterxml.jackson.annotation.JsonProperty("id")
   public String getAgentUserId() {
     return id;
   }
 
   @JsonProperty("id")
+  @com.fasterxml.jackson.annotation.JsonProperty("id")
   public void setAgentUserId(String id) {
     this.id = id;
   }
 
   @JsonProperty("interfaces")
+  @com.fasterxml.jackson.annotation.JsonProperty("interfaces")
   public String getInterfaces() {
     return this.interfaces;
   }
 
   @JsonProperty("interfaces")
+  @com.fasterxml.jackson.annotation.JsonProperty("interfaces")
   public void setInterfaces(String interfaces) {
     this.interfaces = interfaces;
   }
 
   @JsonProperty("ipaddress")
+  @com.fasterxml.jackson.annotation.JsonProperty("ipaddress")
   public String getIPAddress() {
     return this.ipaddress;
   }
 
   @JsonProperty("ipaddress")
+  @com.fasterxml.jackson.annotation.JsonProperty("ipaddress")
   public void setIPAddress(String ipaddress) {
     this.ipaddress = ipaddress;
   }
 
   @JsonProperty("kernel")
+  @com.fasterxml.jackson.annotation.JsonProperty("kernel")
   public String getKernel() {
     return this.kernel;
   }
 
   @JsonProperty("kernel")
+  @com.fasterxml.jackson.annotation.JsonProperty("kernel")
   public void setKernel(String kernel) {
     this.kernel = kernel;
   }
 
   @JsonProperty("kernelmajversion")
+  @com.fasterxml.jackson.annotation.JsonProperty("kernelmajversion")
   public String getKernelMajVersion() {
     return this.kernelmajversion;
   }
 
   @JsonProperty("kernelmajversion")
+  @com.fasterxml.jackson.annotation.JsonProperty("kernelmajversion")
   public void setKernelMajVersion(String kernelmajversion) {
     this.kernelmajversion = kernelmajversion;
   }
 
   @JsonProperty("kernelrelease")
+  @com.fasterxml.jackson.annotation.JsonProperty("kernelrelease")
   public String getKernelRelease() {
     return this.kernelrelease;
   }
 
   @JsonProperty("kernelrelease")
+  @com.fasterxml.jackson.annotation.JsonProperty("kernelrelease")
   public void setKernelRelease(String kernelrelease) {
     this.kernelrelease = kernelrelease;
   }
 
   @JsonProperty("kernelversion")
+  @com.fasterxml.jackson.annotation.JsonProperty("kernelversion")
   public String getKernelVersion() {
     return this.kernelversion;
   }
 
   @JsonProperty("kernelversion")
+  @com.fasterxml.jackson.annotation.JsonProperty("kernelversion")
   public void setKernelVersion(String kernelversion) {
     this.kernelversion = kernelversion;
   }
 
   @JsonProperty("macaddress")
+  @com.fasterxml.jackson.annotation.JsonProperty("macaddress")
   public String getMacAddress() {
     return this.macaddress;
   }
 
   @JsonProperty("macaddress")
+  @com.fasterxml.jackson.annotation.JsonProperty("macaddress")
   public void setMacAddress(String macaddress) {
     this.macaddress = macaddress;
   }
 
   @JsonProperty("memoryfree")
+  @com.fasterxml.jackson.annotation.JsonProperty("memoryfree")
   public long getFreeMemory() {
     return this.memoryfree;
   }
 
   @JsonProperty("memoryfree")
+  @com.fasterxml.jackson.annotation.JsonProperty("memoryfree")
   public void setFreeMemory(long memoryfree) {
     this.memoryfree = memoryfree;
   }
 
   @JsonProperty("memorysize")
+  @com.fasterxml.jackson.annotation.JsonProperty("memorysize")
   public long getMemorySize() {
     return this.memorysize;
   }
 
   @JsonProperty("memorysize")
+  @com.fasterxml.jackson.annotation.JsonProperty("memorysize")
   public void setMemorySize(long memorysize) {
     this.memorysize = memorysize;
   }
 
   @JsonProperty("mounts")
+  @com.fasterxml.jackson.annotation.JsonProperty("mounts")
   public List<DiskInfo> getMounts() {
     return this.mounts;
   }
 
   @JsonProperty("mounts")
+  @com.fasterxml.jackson.annotation.JsonProperty("mounts")
   public void setMounts(List<DiskInfo> mounts) {
     this.mounts = mounts;
   }
 
   @JsonProperty("memorytotal")
+  @com.fasterxml.jackson.annotation.JsonProperty("memorytotal")
   public long getMemoryTotal() {
     return this.memorytotal;
   }
 
   @JsonProperty("memorytotal")
+  @com.fasterxml.jackson.annotation.JsonProperty("memorytotal")
   public void setMemoryTotal(long memorytotal) {
     this.memorytotal = memorytotal;
   }
 
   @JsonProperty("netmask")
+  @com.fasterxml.jackson.annotation.JsonProperty("netmask")
   public String getNetMask() {
     return this.netmask;
   }
 
   @JsonProperty("netmask")
+  @com.fasterxml.jackson.annotation.JsonProperty("netmask")
   public void setNetMask(String netmask) {
     this.netmask = netmask;
   }
 
   @JsonProperty("operatingsystem")
+  @com.fasterxml.jackson.annotation.JsonProperty("operatingsystem")
   public String getOS() {
     return this.operatingsystem;
   }
 
   @JsonProperty("operatingsystem")
+  @com.fasterxml.jackson.annotation.JsonProperty("operatingsystem")
   public void setOS(String operatingsystem) {
     this.operatingsystem = operatingsystem;
   }
 
   @JsonProperty("operatingsystemrelease")
+  @com.fasterxml.jackson.annotation.JsonProperty("operatingsystemrelease")
   public String getOSRelease() {
     return this.operatingsystemrelease;
   }
 
   @JsonProperty("operatingsystemrelease")
+  @com.fasterxml.jackson.annotation.JsonProperty("operatingsystemrelease")
   public void setOSRelease(String operatingsystemrelease) {
     this.operatingsystemrelease = operatingsystemrelease;
   }
 
   @JsonProperty("osfamily")
+  @com.fasterxml.jackson.annotation.JsonProperty("osfamily")
   public String getOSFamily() {
     return this.osfamily;
   }
 
   @JsonProperty("osfamily")
+  @com.fasterxml.jackson.annotation.JsonProperty("osfamily")
   public void setOSFamily(String osfamily) {
     this.osfamily = osfamily;
   }
 
   @JsonProperty("physicalprocessorcount")
+  @com.fasterxml.jackson.annotation.JsonProperty("physicalprocessorcount")
   public int getPhysicalProcessorCount() {
     return this.physicalprocessorcount;
   }
 
   @JsonProperty("physicalprocessorcount")
+  @com.fasterxml.jackson.annotation.JsonProperty("physicalprocessorcount")
   public void setPhysicalProcessorCount(int physicalprocessorcount) {
     this.physicalprocessorcount = physicalprocessorcount;
   }
 
   @JsonProperty("processorcount")
+  @com.fasterxml.jackson.annotation.JsonProperty("processorcount")
   public int getProcessorCount() {
     return this.processorcount;
   }
 
   @JsonProperty("processorcount")
+  @com.fasterxml.jackson.annotation.JsonProperty("processorcount")
   public void setProcessorCount(int processorcount) {
     this.processorcount = processorcount;
   }
 
   @JsonProperty("selinux")
+  @com.fasterxml.jackson.annotation.JsonProperty("selinux")
   public boolean getSeLinux() {
     return selinux;
   }
 
   @JsonProperty("selinux")
+  @com.fasterxml.jackson.annotation.JsonProperty("selinux")
   public void setSeLinux(boolean selinux) {
     this.selinux = selinux;
   }
 
   @JsonProperty("swapfree")
+  @com.fasterxml.jackson.annotation.JsonProperty("swapfree")
   public String getSwapFree() {
     return this.swapfree;
   }
 
   @JsonProperty("swapfree")
+  @com.fasterxml.jackson.annotation.JsonProperty("swapfree")
   public void setSwapFree(String swapfree) {
     this.swapfree = swapfree;
   }
 
   @JsonProperty("swapsize")
+  @com.fasterxml.jackson.annotation.JsonProperty("swapsize")
   public String getSwapSize() {
     return swapsize;
   }
 
   @JsonProperty("swapsize")
+  @com.fasterxml.jackson.annotation.JsonProperty("swapsize")
   public void setSwapSize(String swapsize) {
     this.swapsize = swapsize;
   }
 
   @JsonProperty("timezone")
+  @com.fasterxml.jackson.annotation.JsonProperty("timezone")
   public String getTimeZone() {
     return this.timezone;
   }
 
   @JsonProperty("timezone")
+  @com.fasterxml.jackson.annotation.JsonProperty("timezone")
   public void setTimeZone(String timezone) {
     this.timezone = timezone;
   }
 
   @JsonProperty("uptime")
+  @com.fasterxml.jackson.annotation.JsonProperty("uptime")
   public String getUptime() {
     return this.uptime;
   }
 
   @JsonProperty("uptime")
+  @com.fasterxml.jackson.annotation.JsonProperty("uptime")
   public void setUpTime(String uptime) {
     this.uptime = uptime;
   }
 
   @JsonProperty("uptime_hours")
+  @com.fasterxml.jackson.annotation.JsonProperty("uptime_hours")
   public long getUptimeHours() {
     return this.uptime_hours;
   }
 
   @JsonProperty("uptime_hours")
+  @com.fasterxml.jackson.annotation.JsonProperty("uptime_hours")
   public void setUpTimeHours(long uptime_hours) {
     this.uptime_hours = uptime_hours;
   }
 
   @JsonProperty("uptime_days")
+  @com.fasterxml.jackson.annotation.JsonProperty("uptime_days")
   public long getUpTimeDays() {
     return this.uptime_days;
   }
 
   @JsonProperty("uptime_days")
+  @com.fasterxml.jackson.annotation.JsonProperty("uptime_days")
   public void setUpTimeDays(long uptime_days) {
     this.uptime_days = uptime_days;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/HostStatus.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HostStatus.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HostStatus.java
index 2d021e9..3633038 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HostStatus.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HostStatus.java
@@ -43,21 +43,25 @@ public class HostStatus {
   }
 
   @JsonProperty("status")
+  @com.fasterxml.jackson.annotation.JsonProperty("status")
   public Status getStatus() {
     return status;
   }
 
   @JsonProperty("status")
+  @com.fasterxml.jackson.annotation.JsonProperty("status")
   public void setStatus(Status status) {
     this.status = status;
   }
 
   @JsonProperty("cause")
+  @com.fasterxml.jackson.annotation.JsonProperty("cause")
   public String getCause() {
     return cause;
   }
 
   @JsonProperty("cause")
+  @com.fasterxml.jackson.annotation.JsonProperty("cause")
   public void setCause(String cause) {
     this.cause = cause;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryConfig.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryConfig.java
index 235da11..e54fcfd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryConfig.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryConfig.java
@@ -33,24 +33,31 @@ public class RecoveryConfig {
   }
 
   @SerializedName("type")
+  @com.fasterxml.jackson.annotation.JsonProperty("type")
   private String type;
 
   @SerializedName("maxCount")
+  @com.fasterxml.jackson.annotation.JsonProperty("maxCount")
   private String maxCount;
 
   @SerializedName("windowInMinutes")
+  @com.fasterxml.jackson.annotation.JsonProperty("windowInMinutes")
   private String windowInMinutes;
 
   @SerializedName("retryGap")
+  @com.fasterxml.jackson.annotation.JsonProperty("retryGap")
   private String retryGap;
 
   @SerializedName("maxLifetimeCount")
+  @com.fasterxml.jackson.annotation.JsonProperty("maxLifetimeCount")
   private String maxLifetimeCount;
 
   @SerializedName("components")
+  @com.fasterxml.jackson.annotation.JsonProperty("components")
   private String enabledComponents;
 
   @SerializedName("recoveryTimestamp")
+  @com.fasterxml.jackson.annotation.JsonProperty("recoveryTimestamp")
   private long recoveryTimestamp;
 
   public String getEnabledComponents() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryReport.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryReport.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryReport.java
index 47af7c1..69eb837 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryReport.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/RecoveryReport.java
@@ -34,21 +34,25 @@ public class RecoveryReport {
 
 
   @JsonProperty("summary")
+  @com.fasterxml.jackson.annotation.JsonProperty("summary")
   public String getSummary() {
     return summary;
   }
 
   @JsonProperty("summary")
+  @com.fasterxml.jackson.annotation.JsonProperty("summary")
   public void setSummary(String summary) {
     this.summary = summary;
   }
 
   @JsonProperty("component_reports")
+  @com.fasterxml.jackson.annotation.JsonProperty("component_reports")
   public List<ComponentRecoveryReport> getComponentReports() {
     return componentReports;
   }
 
   @JsonProperty("component_reports")
+  @com.fasterxml.jackson.annotation.JsonProperty("component_reports")
   public void setComponentReports(List<ComponentRecoveryReport> componentReports) {
     this.componentReports = componentReports;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/Register.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/Register.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/Register.java
index a571afd..1a81de3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/Register.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/Register.java
@@ -37,11 +37,13 @@ public class Register {
   private String prefix;
 
   @JsonProperty("responseId")
+  @com.fasterxml.jackson.annotation.JsonProperty("id")
   public int getResponseId() {
     return responseId;
   }
 
   @JsonProperty("responseId")
+  @com.fasterxml.jackson.annotation.JsonProperty("id")
   public void setResponseId(int responseId) {
     this.responseId=responseId;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/RegistrationResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/RegistrationResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/RegistrationResponse.java
index 8efefde..46f3bb4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/RegistrationResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/RegistrationResponse.java
@@ -31,6 +31,7 @@ import org.codehaus.jackson.annotate.JsonProperty;
  */
 public class RegistrationResponse {
   @JsonProperty("response")
+  @com.fasterxml.jackson.annotation.JsonProperty("response")
   private RegistrationStatus response;
 
   /**
@@ -38,6 +39,7 @@ public class RegistrationResponse {
    * alert definitions it needs to schedule.
    */
   @JsonProperty("alertDefinitionCommands")
+  @com.fasterxml.jackson.annotation.JsonProperty("alertDefinitionCommands")
   private List<AlertDefinitionCommand> alertDefinitionCommands = new ArrayList<>();
 
   /**
@@ -47,25 +49,31 @@ public class RegistrationResponse {
    *                different version of agent and server)
    */
   @JsonProperty("exitstatus")
+  @com.fasterxml.jackson.annotation.JsonProperty("exitstatus")
   private int exitstatus;
 
   /**
    * log - message, which will be printed to agents  log
    */
   @JsonProperty("log")
+  @com.fasterxml.jackson.annotation.JsonProperty("log")
   private String log;
 
   //Response id to start with, usually zero.
   @JsonProperty("responseId")
+  @com.fasterxml.jackson.annotation.JsonProperty("id")
   private long responseId;
 
   @JsonProperty("recoveryConfig")
+  @com.fasterxml.jackson.annotation.JsonProperty("recoveryConfig")
   private RecoveryConfig recoveryConfig;
 
   @JsonProperty("agentConfig")
+  @com.fasterxml.jackson.annotation.JsonProperty("agentConfig")
   private Map<String, String> agentConfig;
 
   @JsonProperty("statusCommands")
+  @com.fasterxml.jackson.annotation.JsonProperty("statusCommands")
   private List<StatusCommand> statusCommands = null;
 
   public RegistrationStatus getResponseStatus() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/StatusCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/StatusCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/StatusCommand.java
index 9c17e00..8dabbc2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/StatusCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/StatusCommand.java
@@ -34,39 +34,51 @@ public class StatusCommand extends AgentCommand {
   }
 
   @SerializedName("clusterName")
+  @com.fasterxml.jackson.annotation.JsonProperty("clusterName")
   private String clusterName;
 
   @SerializedName("serviceName")
+  @com.fasterxml.jackson.annotation.JsonProperty("serviceName")
   private String serviceName;
 
   @SerializedName("componentName")
+  @com.fasterxml.jackson.annotation.JsonProperty("componentName")
   private String componentName;
 
   @SerializedName("configurations")
+  @com.fasterxml.jackson.annotation.JsonProperty("configurations")
   private Map<String, Map<String, String>> configurations;
 
   @SerializedName("configuration_attributes")
+  @com.fasterxml.jackson.annotation.JsonProperty("configuration_attributes")
   private Map<String, Map<String, Map<String, String>>> configurationAttributes;
 
   @SerializedName("commandParams")
+  @com.fasterxml.jackson.annotation.JsonProperty("commandParams")
   private Map<String, String> commandParams = new HashMap<>();
 
   @SerializedName("hostLevelParams")
+  @com.fasterxml.jackson.annotation.JsonProperty("hostLevelParams")
   private Map<String, String> hostLevelParams = new HashMap<>();
 
   @SerializedName("hostname")
+  @com.fasterxml.jackson.annotation.JsonProperty("hostname")
   private String hostname = null;
 
   @SerializedName("payloadLevel")
+  @com.fasterxml.jackson.annotation.JsonProperty("payloadLevel")
   private StatusCommandPayload payloadLevel = StatusCommandPayload.DEFAULT;
 
   @SerializedName("desiredState")
+  @com.fasterxml.jackson.annotation.JsonProperty("desiredState")
   private State desiredState;
 
   @SerializedName("hasStaleConfigs")
+  @com.fasterxml.jackson.annotation.JsonProperty("hasStaleConfigs")
   private Boolean hasStaleConfigs;
 
   @SerializedName("executionCommandDetails")
+  @com.fasterxml.jackson.annotation.JsonProperty("executionCommandDetails")
   private ExecutionCommand executionCommand;
 
   public ExecutionCommand getExecutionCommand() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentClusterDataHolder.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentClusterDataHolder.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentClusterDataHolder.java
new file mode 100644
index 0000000..e3038b6
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentClusterDataHolder.java
@@ -0,0 +1,112 @@
+/**
+ * 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.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.agent.stomp.dto.Hashable;
+import org.apache.commons.lang.StringUtils;
+
+import com.google.gson.Gson;
+
+/**
+ * Is used to saving and updating last version of event
+ * @param <T> event with hash to control version
+ */
+public abstract class AgentClusterDataHolder<T extends Hashable> {
+  private String parentHash;
+  private String currentHash;
+  private T data;
+
+  public final String salt = "";
+
+  public T getUpdateIfChanged(String agentHash) throws AmbariException {
+    if (StringUtils.isEmpty(agentHash) || (StringUtils.isNotEmpty(agentHash) && !agentHash.equals(currentHash))) {
+      if (data == null) {
+        data = getCurrentData();
+        parentHash = currentHash;
+        currentHash = getHash(data);
+        data.setHash(currentHash);
+      }
+      return data;
+    }
+    return getEmptyData();
+  }
+
+  protected abstract T getCurrentData() throws AmbariException;
+
+  protected abstract T getEmptyData();
+
+  protected void regenerateHash() {
+    setCurrentHash(null);
+    setParentHash(getCurrentHash());
+    setCurrentHash(getHash(getData()));
+    getData().setHash(getCurrentHash());
+  }
+
+  protected String getHash(T data) {
+    String json = new Gson().toJson(data);
+    String generatedPassword = null;
+    try {
+      MessageDigest md = MessageDigest.getInstance("SHA-512");
+      md.update(salt.getBytes("UTF-8"));
+      byte[] bytes = md.digest(json.getBytes("UTF-8"));
+      StringBuilder sb = new StringBuilder();
+      for(int i=0; i< bytes.length ;i++){
+        sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
+      }
+      generatedPassword = sb.toString();
+    }
+    catch (NoSuchAlgorithmException e){
+      e.printStackTrace();
+    } catch (UnsupportedEncodingException e) {
+      e.printStackTrace();
+    }
+    return generatedPassword;
+  }
+
+  public abstract void updateData(T update) throws AmbariException;
+
+  public String getParentHash() {
+    return parentHash;
+  }
+
+  public void setParentHash(String parentHash) {
+    this.parentHash = parentHash;
+  }
+
+  public String getCurrentHash() {
+    return currentHash;
+  }
+
+  public void setCurrentHash(String currentHash) {
+    this.currentHash = currentHash;
+  }
+
+  public T getData() {
+    return data;
+  }
+
+  public void setData(T data) {
+    this.data = data;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentCurrentDataController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentCurrentDataController.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentCurrentDataController.java
new file mode 100644
index 0000000..f0f18cc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/AgentCurrentDataController.java
@@ -0,0 +1,77 @@
+/**
+ * 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 org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.agent.AgentSessionManager;
+import org.apache.ambari.server.agent.stomp.dto.Hash;
+import org.apache.ambari.server.events.AgentConfigsUpdateEvent;
+import org.apache.ambari.server.events.MetadataUpdateEvent;
+import org.apache.ambari.server.events.TopologyUpdateEvent;
+import org.apache.ambari.server.state.ConfigHelper;
+import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.messaging.handler.annotation.MessageMapping;
+import org.springframework.messaging.simp.annotation.SendToUser;
+import org.springframework.messaging.simp.annotation.SubscribeMapping;
+import org.springframework.stereotype.Controller;
+
+import com.google.inject.Injector;
+
+@Controller
+@SendToUser("/")
+@MessageMapping("/agents")
+public class AgentCurrentDataController {
+  private static Log LOG = LogFactory.getLog(AgentCurrentDataController.class);
+  private final AgentSessionManager agentSessionManager;
+  private final TopologyHolder topologyHolder;
+  private final MetadataHolder metadataHolder;
+  private final ConfigHelper configHelper;
+
+  //TODO remove after hash generation implementing
+  private final String CONFIGS_HASH_STUB = "stubhash";
+
+  public AgentCurrentDataController(Injector injector) {
+    agentSessionManager = injector.getInstance(AgentSessionManager.class);
+    topologyHolder = injector.getInstance(TopologyHolder.class);
+    metadataHolder = injector.getInstance(MetadataHolder.class);
+    configHelper = injector.getInstance(ConfigHelper.class);
+  }
+
+  @SubscribeMapping("/topologies")
+  public TopologyUpdateEvent getCurrentTopology(Hash hash) throws AmbariException, InvalidStateTransitionException {
+    return topologyHolder.getUpdateIfChanged(hash.getHash());
+  }
+
+  @SubscribeMapping("/metadata")
+  public MetadataUpdateEvent getCurrentMetadata(Hash hash) throws AmbariException {
+    return metadataHolder.getUpdateIfChanged(hash.getHash());
+  }
+
+  //TODO method should returns empty response in case hash is relevant
+  @SubscribeMapping("/configs")
+  public AgentConfigsUpdateEvent getCurrentConfigs(@Header String simpSessionId, Hash hash) throws AmbariException {
+    String currentHash = CONFIGS_HASH_STUB;
+    AgentConfigsUpdateEvent agentConfigsUpdateEvent = configHelper.getHostActualConfigs(
+          agentSessionManager.getHost(simpSessionId).getHostName());
+    agentConfigsUpdateEvent.setHash(currentHash);
+    return agentConfigsUpdateEvent;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HeartbeatController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HeartbeatController.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HeartbeatController.java
index b56449e..81fb300 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HeartbeatController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/HeartbeatController.java
@@ -27,7 +27,6 @@ import org.apache.ambari.server.agent.HeartBeatResponse;
 import org.apache.ambari.server.agent.Register;
 import org.apache.ambari.server.agent.RegistrationResponse;
 import org.apache.ambari.server.agent.RegistrationStatus;
-import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
 import org.apache.ambari.server.state.cluster.ClustersImpl;
 import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
 import org.apache.commons.logging.Log;
@@ -48,13 +47,11 @@ public class HeartbeatController {
   private final HeartBeatHandler hh;
   private final ClustersImpl clusters;
   private final AgentSessionManager agentSessionManager;
-  private final StateUpdateEventPublisher stateUpdateEventPublisher;
 
   public HeartbeatController(Injector injector) {
     hh = injector.getInstance(HeartBeatHandler.class);
     clusters = injector.getInstance(ClustersImpl.class);
     agentSessionManager = injector.getInstance(AgentSessionManager.class);
-    stateUpdateEventPublisher = injector.getInstance(StateUpdateEventPublisher.class);
   }
 
   @SubscribeMapping("/register")
@@ -75,17 +72,24 @@ public class HeartbeatController {
       response.setLog(ex.getMessage());
       return response;
     }
-    stateUpdateEventPublisher.publish(hh.getInitialClusterTopology());
+    agentSessionManager.register(simpSessionId,
+        clusters.getHost(message.getHostname()));
     return response;
   }
 
   @SubscribeMapping("/heartbeat")
-  public HeartBeatResponse heartbeat(HeartBeat message) {
+  public HeartBeatResponse heartbeat(@Header String simpSessionId, HeartBeat message) {
     if (LOG.isDebugEnabled()) {
       LOG.debug("Received Heartbeat message " + message);
     }
     HeartBeatResponse heartBeatResponse;
     try {
+      if (!agentSessionManager.isRegistered(simpSessionId)) {
+        //Server restarted, or unknown host.
+        LOG.error(String.format("Host with [%s] sessionId not registered", simpSessionId));
+        return hh.createRegisterCommand();
+      }
+      message.setHostname(agentSessionManager.getHost(simpSessionId).getHostName());
       heartBeatResponse = hh.handleHeartBeat(message);
       if (LOG.isDebugEnabled()) {
         LOG.debug("Sending heartbeat response with response id " + heartBeatResponse.getResponseId());

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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
new file mode 100644
index 0000000..b1adcbe
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/MetadataHolder.java
@@ -0,0 +1,55 @@
+/**
+ * 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 org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementControllerImpl;
+import org.apache.ambari.server.events.MetadataUpdateEvent;
+import org.apache.ambari.server.events.publishers.StateUpdateEventPublisher;
+
+import com.google.common.eventbus.Subscribe;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+@Singleton
+public class MetadataHolder extends AgentClusterDataHolder<MetadataUpdateEvent> {
+
+  @Inject
+  private AmbariManagementControllerImpl ambariManagementController;
+
+  @Inject
+  public MetadataHolder(StateUpdateEventPublisher stateUpdateEventPublisher) {
+    stateUpdateEventPublisher.register(this);
+  }
+
+  @Override
+  public MetadataUpdateEvent getCurrentData() throws AmbariException {
+    return ambariManagementController.getClustersMetadata();
+  }
+
+  @Subscribe
+  public void updateData(MetadataUpdateEvent update) throws AmbariException {
+    setData(getCurrentData());
+    regenerateHash();
+  }
+
+  @Override
+  protected MetadataUpdateEvent getEmptyData() {
+    return MetadataUpdateEvent.emptyUpdate();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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
new file mode 100644
index 0000000..a4a7580
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/TopologyHolder.java
@@ -0,0 +1,159 @@
+/**
+ * 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.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ClusterNotFoundException;
+import org.apache.ambari.server.agent.HeartBeatHandler;
+import org.apache.ambari.server.agent.RecoveryConfigHelper;
+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.TopologyUpdateEvent;
+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 org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
+import org.apache.ambari.server.state.ServiceComponentHost;
+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;
+
+@Singleton
+public class TopologyHolder extends AgentClusterDataHolder<TopologyUpdateEvent> {
+  @Inject
+  private HeartBeatHandler heartBeatHandler;
+
+  @Inject
+  private RecoveryConfigHelper recoveryConfigHelper;
+
+  @Inject
+  private AmbariManagementControllerImpl ambariManagementController;
+
+  @Inject
+  private Clusters clusters;
+
+  @Inject
+  public TopologyHolder(StateUpdateEventPublisher stateUpdateEventPublisher) {
+    stateUpdateEventPublisher.register(this);
+  }
+
+  /**
+   * 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
+   * @throws InvalidStateTransitionException
+   * @throws AmbariException
+   */
+  @Override
+  public TopologyUpdateEvent getCurrentData() throws AmbariException {
+    TreeMap<String, TopologyCluster> topologyClusters = new TreeMap<>();
+    for (Cluster cl : clusters.getClusters().values()) {
+      Collection<Host> clusterHosts = cl.getHosts();
+      Set<TopologyComponent> topologyComponents = new HashSet<>();
+      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)));
+      }
+      for (Service service : cl.getServices().values()) {
+        for (ServiceComponent component : service.getServiceComponents().values()) {
+          Map<String, ServiceComponentHost> componentsMap = component.getServiceComponentHosts();
+          if (!componentsMap.isEmpty()) {
+
+            //TODO will be a need to change to multi-instance usage
+            ServiceComponentHost sch = componentsMap.entrySet().iterator().next().getValue();
+
+            Set<String> hostNames = cl.getHosts(sch.getServiceName(), sch.getServiceComponentName());
+            Set<Long> hostOrderIds = clusterHosts.stream()
+                .filter(h -> hostNames.contains(h.getHostName()))
+                .map(h -> h.getHostId()).collect(Collectors.toSet());
+            String serviceName = sch.getServiceName();
+            String componentName = sch.getServiceComponentName();
+            StackId stackId = cl.getDesiredStackVersion();
+
+            TopologyComponent topologyComponent = TopologyComponent.newBuilder()
+                .setComponentName(sch.getServiceComponentName())
+                .setServiceName(sch.getServiceName())
+                .setVersion(sch.getVersion())
+                .setHostIds(hostOrderIds)
+                .setComponentLevelParams(ambariManagementController.getTopologyComponentLevelParams(stackId, serviceName,
+                    componentName, cl.getSecurityType()))
+                .build();
+            topologyComponents.add(topologyComponent);
+          }
+        }
+      }
+      topologyClusters.put(Long.toString(cl.getClusterId()),
+          new TopologyCluster(topologyComponents, topologyHosts));
+    }
+    TopologyUpdateEvent topologyUpdateEvent = new TopologyUpdateEvent(topologyClusters,
+        TopologyUpdateEvent.EventType.CREATE);
+    return topologyUpdateEvent;
+  }
+
+  @Subscribe
+  public void updateData(TopologyUpdateEvent update) throws AmbariException {
+    if (getData() == null) {
+      setData(getCurrentData());
+    }
+    TopologyUpdateEvent.EventType eventType = update.getEventType();
+    for (Map.Entry<String, TopologyCluster> updatedCluster : update.getClusters().entrySet()) {
+      String clusterId = updatedCluster.getKey();
+      TopologyCluster cluster = updatedCluster.getValue();
+      if (getData().getClusters().containsKey(clusterId)) {
+        if (eventType.equals(TopologyUpdateEvent.EventType.DELETE) &&
+            CollectionUtils.isEmpty(getData().getClusters().get(clusterId).getTopologyComponents()) &&
+            CollectionUtils.isEmpty(getData().getClusters().get(clusterId).getTopologyHosts())) {
+          getData().getClusters().remove(clusterId);
+        } else {
+          getData().getClusters().get(clusterId).update(update.getClusters().get(clusterId).getTopologyComponents(),
+              update.getClusters().get(clusterId).getTopologyHosts(), eventType);
+        }
+      } else {
+        if (eventType.equals(TopologyUpdateEvent.EventType.UPDATE)) {
+          getData().getClusters().put(clusterId, cluster);
+        } else {
+          throw new ClusterNotFoundException(Long.getLong(clusterId));
+        }
+      }
+    }
+
+    regenerateHash();
+  }
+
+  @Override
+  protected TopologyUpdateEvent getEmptyData() {
+    return TopologyUpdateEvent.emptyUpdate();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/421ac277/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
new file mode 100644
index 0000000..b9339a7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/ClusterConfigs.java
@@ -0,0 +1,50 @@
+/**
+ * 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.Map;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class ClusterConfigs {
+  private Map<String, Map<String, String>> configurations;
+  private Map<String, Map<String, Map<String, String>>> configurationAttributes;
+
+  public ClusterConfigs(Map<String, Map<String, String>> configurations, Map<String, Map<String, Map<String, String>>> configurationAttributes) {
+    this.configurations = configurations;
+    this.configurationAttributes = configurationAttributes;
+  }
+
+  public Map<String, Map<String, String>> getConfigurations() {
+    return configurations;
+  }
+
+  public void setConfigurations(Map<String, Map<String, String>> configurations) {
+    this.configurations = configurations;
+  }
+
+  public Map<String, Map<String, Map<String, String>>> getConfigurationAttributes() {
+    return configurationAttributes;
+  }
+
+  public void setConfigurationAttributes(Map<String, Map<String, Map<String, String>>> configurationAttributes) {
+    this.configurationAttributes = configurationAttributes;
+  }
+}