ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mpapirkovs...@apache.org
Subject [1/4] ambari git commit: AMBARI-21201. Add ConfigChange event to capture config changes (mpapirkovskyy)
Date Thu, 22 Jun 2017 15:28:12 GMT
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());


Mime
View raw message