You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ds...@apache.org on 2014/05/22 23:12:29 UTC

git commit: AMBARI-5859 Provide host specific aggregate metrics on Cluster resource (dsen)

Repository: ambari
Updated Branches:
  refs/heads/trunk 5376252a6 -> 42b08d22a


AMBARI-5859 Provide host specific aggregate metrics on Cluster resource (dsen)


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

Branch: refs/heads/trunk
Commit: 42b08d22a519c40f81195c511ed5afd2ab20600d
Parents: 5376252
Author: Dmitry Sen <ds...@hortonworks.com>
Authored: Fri May 23 00:07:34 2014 +0300
Committer: Dmitry Sen <ds...@hortonworks.com>
Committed: Fri May 23 00:07:34 2014 +0300

----------------------------------------------------------------------
 .../server/controller/ClusterResponse.java      |  31 ++-
 .../internal/AbstractProviderModule.java        |   6 +
 .../internal/ClusterResourceProvider.java       |   6 +-
 .../nagios/NagiosPropertyProvider.java          |  53 +++--
 .../server/state/ClusterHealthReport.java       | 216 +++++++++++++++++++
 .../server/state/cluster/ClusterImpl.java       | 106 ++++++++-
 .../src/main/resources/properties.json          |   4 +-
 .../server/controller/ClusterResponseTest.java  |   7 +-
 .../internal/ClusterResourceProviderTest.java   |  18 +-
 .../nagios/NagiosPropertyProviderTest.java      |  45 +++-
 .../server/state/cluster/ClusterTest.java       |  41 +++-
 11 files changed, 497 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
index 598958f..e8a60c8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
@@ -23,6 +23,7 @@ import java.util.Set;
 
 import org.apache.ambari.server.state.DesiredConfig;
 import org.apache.ambari.server.state.State;
+import org.apache.ambari.server.state.ClusterHealthReport;
 
 public class ClusterResponse {
 
@@ -37,14 +38,22 @@ public class ClusterResponse {
   private Map<String, DesiredConfig> desiredConfigs;
   
   private String provisioningState;
+
+  private Integer totalHosts;
+
+  private ClusterHealthReport clusterHealthReport;
   
-  public ClusterResponse(Long clusterId, String clusterName, State provisioningState,
-      Set<String> hostNames, String desiredStackVersion) {
+  public ClusterResponse(Long clusterId, String clusterName,
+    State provisioningState, Set<String> hostNames, Integer totalHosts,
+    String desiredStackVersion, ClusterHealthReport clusterHealthReport) {
+
     super();
     this.clusterId = clusterId;
     this.clusterName = clusterName;
     this.hostNames = hostNames;
+    this.totalHosts = totalHosts;
     this.desiredStackVersion = desiredStackVersion;
+    this.clusterHealthReport = clusterHealthReport;
     
     if (null != provisioningState)
       this.provisioningState = provisioningState.name();
@@ -89,6 +98,7 @@ public class ClusterResponse {
         + ", clusterId=" + clusterId
         + ", provisioningState=" + provisioningState
         + ", desiredStackVersion=" + desiredStackVersion
+        + ", totalHosts=" + totalHosts
         + ", hosts=[");
     
     if (hostNames != null) {
@@ -101,7 +111,9 @@ public class ClusterResponse {
         sb.append(hostName);
       }
     }
-    sb.append("] }");
+    sb.append("]"
+        + ", clusterHealthReport= " + clusterHealthReport
+        + "}");
     return sb.toString();
   }
 
@@ -152,4 +164,17 @@ public class ClusterResponse {
     return desiredConfigs;
   }
 
+  /**
+   * @return total number of hosts in the cluster
+   */
+  public Integer getTotalHosts() {
+    return totalHosts;
+  }
+
+  /**
+   * @return cluster health report
+   */
+  public ClusterHealthReport getClusterHealthReport() {
+    return clusterHealthReport;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
index 0ff3e62..711e64e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractProviderModule.java
@@ -402,6 +402,12 @@ public abstract class AbstractProviderModule implements ProviderModule, Resource
               ComponentSSLConfiguration.instance(),
               this,
               PropertyHelper.getPropertyId("Clusters", "cluster_name")));
+          providers.add(new NagiosPropertyProvider(type,
+              new URLStreamProvider(
+                PROPERTY_REQUEST_CONNECT_TIMEOUT, NAGIOS_READ_TIMEOUT,
+                configuration),
+              "Clusters/cluster_name",
+              "Clusters/version"));
           break;
         case Service:
           providers.add(new NagiosPropertyProvider(type,

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
index 8bd354a..2aa9ea1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
@@ -78,6 +78,8 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
   protected static final String CLUSTER_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "version");  
   protected static final String CLUSTER_PROVISIONING_STATE_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "provisioning_state");
   protected static final String CLUSTER_DESIRED_CONFIGS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_configs");
+  protected static final String CLUSTER_TOTAL_HOSTS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "total_hosts");
+  protected static final String CLUSTER_HEALTH_REPORT_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "health_report");
   protected static final String BLUEPRINT_PROPERTY_ID = PropertyHelper.getPropertyId(null, "blueprint");
 
   private static Set<String> pkPropertyIds =
@@ -189,7 +191,9 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
       setResourceProperty(resource, CLUSTER_ID_PROPERTY_ID, response.getClusterId(), requestedIds);
       setResourceProperty(resource, CLUSTER_NAME_PROPERTY_ID, response.getClusterName(), requestedIds);
       setResourceProperty(resource, CLUSTER_PROVISIONING_STATE_PROPERTY_ID, response.getProvisioningState(), requestedIds);
-      setResourceProperty(resource, CLUSTER_DESIRED_CONFIGS_PROPERTY_ID, response.getDesiredConfigs(), requestedIds);      
+      setResourceProperty(resource, CLUSTER_DESIRED_CONFIGS_PROPERTY_ID, response.getDesiredConfigs(), requestedIds);
+      setResourceProperty(resource, CLUSTER_TOTAL_HOSTS_PROPERTY_ID, response.getTotalHosts(), requestedIds);
+      setResourceProperty(resource, CLUSTER_HEALTH_REPORT_PROPERTY_ID, response.getClusterHealthReport(), requestedIds);
       
       resource.setProperty(CLUSTER_VERSION_PROPERTY_ID,
           response.getDesiredStackVersion());

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/main/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProvider.java
index a0785f8..52e84e0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProvider.java
@@ -23,9 +23,11 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -83,7 +85,7 @@ public class NagiosPropertyProvider extends BaseProvider implements PropertyProv
   
   private static final List<String> IGNORABLE_FOR_HOSTS = new ArrayList<String>(
       Arrays.asList("percent"));
-  
+
   // holds alerts for clusters.  clusterName is the key
   private static final Map<String, List<NagiosAlert>> CLUSTER_ALERTS =
       new ConcurrentHashMap<String, List<NagiosAlert>>();
@@ -238,10 +240,12 @@ public class NagiosPropertyProvider extends BaseProvider implements PropertyProv
     int passive = 0;
     
     List<Map<String, Object>> alerts = new ArrayList<Map<String, Object>>();
+
+    Set<String> processedHosts = new HashSet<String>();
     
     for (NagiosAlert alert : allAlerts) {
       boolean match = false;
-      
+
       switch (resourceType.getInternalType()) {
         case Service:
           match = alert.getService().equals(matchValue);
@@ -261,12 +265,25 @@ public class NagiosPropertyProvider extends BaseProvider implements PropertyProv
             }
           }
           break;
+        case Cluster:
+          if (!processedHosts.contains(alert.getHost())) {
+            match = true;
+            Iterator<String> it = IGNORABLE_FOR_HOSTS.iterator();
+            String desc = alert.getDescription();
+            while (it.hasNext() && match) {
+              if (-1 != desc.toLowerCase().indexOf(it.next()))
+                match = false;
+            }
+          }
+          break;
         default:
           break;
       }
-      
+
       if (match) {
 
+        processedHosts.add(alert.getHost());
+
         // status = the return code from the plugin that controls
         // whether an alert is sent out (0 when using wrapper)
         // actual_status = the actual process result
@@ -301,17 +318,20 @@ public class NagiosPropertyProvider extends BaseProvider implements PropertyProv
           passive++;
         } else {
           switch (alert.getStatus()) {
-          case 0:
-            ok++;
-            break;
-          case 1:
-            warning++;
-            break;
-          case 2:
-            critical++;
-            break;
-          default:
-            break;
+            case 0:
+              ok++;
+              break;
+            case 1:
+              warning++;
+              break;
+            case 2:
+              critical++;
+              break;
+            case 3:
+              passive++;
+              break;
+            default:
+              break;
           }
         }
         
@@ -324,8 +344,11 @@ public class NagiosPropertyProvider extends BaseProvider implements PropertyProv
     setResourceProperty(res, ALERT_SUMMARY_CRITICAL_PROPERTY_ID, Integer.valueOf(critical), requestedIds);
     setResourceProperty(res, ALERT_SUMMARY_PASSIVE_PROPERTY_ID, Integer.valueOf(passive), requestedIds);
     
-    if (!alerts.isEmpty())
+    if (!alerts.isEmpty() &&
+      (resourceType.getInternalType() != Resource.InternalType.Cluster)) {
+
       setResourceProperty(res, ALERT_DETAIL_PROPERTY_ID, alerts, requestedIds);
+    }
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterHealthReport.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterHealthReport.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterHealthReport.java
new file mode 100644
index 0000000..4be44c6
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterHealthReport.java
@@ -0,0 +1,216 @@
+/**
+ * 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.state;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Cluster Health Report (part of Clusters API response)
+ */
+public class ClusterHealthReport {
+
+  private int staleConfigsHosts;
+  private int maintenanceStateHosts;
+
+  private int healthyStateHosts;
+  private int unhealthyStateHosts;
+  private int heartbeatLostStateHosts;
+  private int initStateHosts;
+
+  private int healthyStatusHosts;
+  private int unhealthyStatusHosts;
+  private int unknownStatusHosts;
+  private int alertStatusHosts;
+
+  /**
+   * @return number of hosts having stale_config set to true
+   */
+  @JsonProperty("Host/stale_config")
+  public int getStaleConfigsHosts() {
+    return staleConfigsHosts;
+  }
+
+  /**
+   * @param staleConfigsHosts number of hosts having stale_config set to true
+   */
+  public void setStaleConfigsHosts(int staleConfigsHosts) {
+    this.staleConfigsHosts = staleConfigsHosts;
+  }
+
+  /**
+   * @return number of hosts having maintenance state on
+   */
+  @JsonProperty("Host/maintenance_state")
+  public int getMaintenanceStateHosts() {
+    return maintenanceStateHosts;
+  }
+
+  /**
+   * @param maintenanceStateHosts number of hosts having maintenance state on
+   */
+  public void setMaintenanceStateHosts(int maintenanceStateHosts) {
+    this.maintenanceStateHosts = maintenanceStateHosts;
+  }
+
+  /**
+   * @return number of hosts having host state HEALTHY
+   */
+  @JsonProperty("Host/host_state/HEALTHY")
+  public int getHealthyStateHosts() {
+    return healthyStateHosts;
+  }
+
+  /**
+   * @param healthyStateHosts number of hosts having host state HEALTHY
+   */
+  public void setHealthyStateHosts(int healthyStateHosts) {
+    this.healthyStateHosts = healthyStateHosts;
+  }
+
+  /**
+   * @return number of hosts having host state UNHEALTHY
+   */
+  @JsonProperty("Host/host_state/UNHEALTHY")
+  public int getUnhealthyStateHosts() {
+    return unhealthyStateHosts;
+  }
+
+  /**
+   * @param unhealthyStateHosts number of hosts having host state UNHEALTHY
+   */
+  public void setUnhealthyStateHosts(int unhealthyStateHosts) {
+    this.unhealthyStateHosts = unhealthyStateHosts;
+  }
+
+  /**
+   * @return number of hosts having host state INIT
+   */
+  @JsonProperty("Host/host_state/INIT")
+  public int getInitStateHosts() {
+    return initStateHosts;
+  }
+
+  /**
+   * @param initStateHosts number of hosts having host state INIT
+   */
+  public void setInitStateHosts(int initStateHosts) {
+    this.initStateHosts = initStateHosts;
+  }
+
+  /**
+   * @return number of hosts having host status HEALTHY
+   */
+  @JsonProperty("Host/host_status/HEALTHY")
+  public int getHealthyStatusHosts() {
+    return healthyStatusHosts;
+  }
+
+  /**
+   * @param healthyStatusHosts number of hosts having host status HEALTHY
+   */
+  public void setHealthyStatusHosts(int healthyStatusHosts) {
+    this.healthyStatusHosts = healthyStatusHosts;
+  }
+
+  /**
+   * @return number of hosts having host status UNHEALTHY
+   */
+  @JsonProperty("Host/host_status/UNHEALTHY")
+  public int getUnhealthyStatusHosts() {
+    return unhealthyStatusHosts;
+  }
+
+  /**
+   * @param unhealthyStatusHosts number of hosts having host status UNHEALTHY
+   */
+  public void setUnhealthyStatusHosts(int unhealthyStatusHosts) {
+    this.unhealthyStatusHosts = unhealthyStatusHosts;
+  }
+
+  /**
+   * @return number of hosts having host status UNKNOWN
+   */
+  @JsonProperty("Host/host_status/UNKNOWN")
+  public int getUnknownStatusHosts() {
+    return unknownStatusHosts;
+  }
+
+  /**
+   * @param unknownStatusHosts number of hosts having host status UNKNOWN
+   */
+  public void setUnknownStatusHosts(int unknownStatusHosts) {
+    this.unknownStatusHosts = unknownStatusHosts;
+  }
+
+  /**
+   * @return number of hosts having host status ALERT
+   */
+  @JsonProperty("Host/host_status/ALERT")
+  public int getAlertStatusHosts() {
+    return alertStatusHosts;
+  }
+
+  /**
+   * @param alertStatusHosts number of hosts having host status ALERT
+   */
+  public void setAlertStatusHosts(int alertStatusHosts) {
+    this.alertStatusHosts = alertStatusHosts;
+  }
+
+  /**
+   * @return number of hosts having host status HEARTBEAT_LOST
+   */
+  @JsonProperty("Host/host_state/HEARTBEAT_LOST")
+  public int getHeartbeatLostStateHosts() {
+    return heartbeatLostStateHosts;
+  }
+
+  /**
+   * @param heartbeatLostStateHosts number of hosts
+   *                                having host status HEARTBEAT_LOST
+   */
+  public void setHeartbeatLostStateHosts(int heartbeatLostStateHosts) {
+    this.heartbeatLostStateHosts = heartbeatLostStateHosts;
+  }
+
+  public ClusterHealthReport() {
+
+  }
+
+  @Override
+  public String toString() {
+    return "ClusterHealthReport{" +
+      "staleConfigsHosts=" + staleConfigsHosts +
+      ", maintenanceStateHosts=" + maintenanceStateHosts +
+      ", healthyStateHosts=" + healthyStateHosts +
+      ", unhealthyStateHosts=" + unhealthyStateHosts +
+      ", heartbeatLostStateHosts=" + heartbeatLostStateHosts +
+      ", initStateHosts=" + initStateHosts +
+      ", healthyStatusHosts=" + healthyStatusHosts +
+      ", unhealthyStatusHosts=" + unhealthyStatusHosts +
+      ", unknownStatusHosts=" + unknownStatusHosts +
+      ", alertStatusHosts=" + alertStatusHosts +
+      '}';
+  }
+}
+
+
+
+
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/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 f0cedb6..f2020d1 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
@@ -40,6 +40,7 @@ import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ServiceComponentHostNotFoundException;
 import org.apache.ambari.server.ServiceNotFoundException;
 import org.apache.ambari.server.controller.ClusterResponse;
+import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.orm.cache.ConfigGroupHostMapping;
 import org.apache.ambari.server.orm.cache.HostConfigMapping;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
@@ -57,13 +58,17 @@ import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigFactory;
+import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.DesiredConfig;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.MaintenanceState;
 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.ServiceFactory;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.State;
+import org.apache.ambari.server.state.ClusterHealthReport;
 import org.apache.ambari.server.state.configgroup.ConfigGroup;
 import org.apache.ambari.server.state.configgroup.ConfigGroupFactory;
 import org.apache.ambari.server.state.scheduler.RequestExecution;
@@ -142,6 +147,10 @@ public class ClusterImpl implements Cluster {
   private ConfigGroupHostMappingDAO configGroupHostMappingDAO;
   @Inject
   private RequestExecutionFactory requestExecutionFactory;
+  @Inject
+  private ConfigHelper configHelper;
+  @Inject
+  private MaintenanceStateHelper maintenanceStateHelper;
 
   private volatile boolean svcHostsLoaded = false;
 
@@ -1084,10 +1093,10 @@ public class ClusterImpl implements Cluster {
     try {
       readWriteLock.readLock().lock();
       try {
+        Map<String, Host> hosts = clusters.getHostsForCluster(getClusterName());
         ClusterResponse r = new ClusterResponse(getClusterId(), 
-          getClusterName(), getProvisioningState(), 
-          clusters.getHostsForCluster(getClusterName()).keySet(),
-          getDesiredStackVersion().getStackId());
+          getClusterName(), getProvisioningState(), hosts.keySet(), hosts.size(),
+          getDesiredStackVersion().getStackId(), getClusterHealthReport());
 
         return r;
       } finally {
@@ -1417,4 +1426,95 @@ public class ClusterImpl implements Cluster {
     return getHostsDesiredConfigs(hostnames);
   }
 
+  private ClusterHealthReport getClusterHealthReport() throws AmbariException {
+
+    int staleConfigsHosts = 0;
+    int maintenanceStateHosts = 0;
+
+    int healthyStateHosts = 0;
+    int unhealthyStateHosts = 0;
+    int initStateHosts = 0;
+    int healthyStatusHosts = 0;
+
+    int unhealthyStatusHosts = 0;
+    int unknownStatusHosts = 0;
+    int alertStatusHosts = 0;
+    int heartbeatLostStateHosts = 0;
+
+    Set<String> hostnames;
+
+    try {
+      hostnames = clusters.getHostsForCluster(clusterEntity.getClusterName()).keySet();
+    } catch (AmbariException ignored) {
+      hostnames = Collections.emptySet();
+    }
+
+    for (String hostname : hostnames) {
+
+      Host host = clusters.getHost(hostname);
+
+      switch (host.getState()) {
+        case HEALTHY:
+          healthyStateHosts++;
+          break;
+        case UNHEALTHY:
+          unhealthyStateHosts++;
+          break;
+        case INIT:
+          initStateHosts++;
+          break;
+        case HEARTBEAT_LOST:
+          heartbeatLostStateHosts++;
+          break;
+      }
+
+      switch (host.getHealthStatus().getHealthStatus()) {
+        case HEALTHY:
+          healthyStatusHosts++;
+          break;
+        case UNHEALTHY:
+          unhealthyStatusHosts++;
+          break;
+        case UNKNOWN:
+          unknownStatusHosts++;
+          break;
+        case ALERT:
+          alertStatusHosts++;
+          break;
+      }
+
+      boolean staleConfig = false;
+      boolean maintenanceState = false;
+
+      if (serviceComponentHostsByHost.containsKey(hostname)) {
+        for (ServiceComponentHost sch : serviceComponentHostsByHost.get(hostname)) {
+          staleConfig = configHelper.isStaleConfigs(sch) ? true : staleConfig;
+          maintenanceState =
+            maintenanceStateHelper.getEffectiveState(sch) == MaintenanceState.ON ?
+              true : maintenanceState;
+        }
+      }
+
+      if (staleConfig) {
+        staleConfigsHosts++;
+      }
+      if (maintenanceState) {
+        maintenanceStateHosts++;
+      }
+    }
+
+    ClusterHealthReport chr = new ClusterHealthReport();
+    chr.setAlertStatusHosts(alertStatusHosts);
+    chr.setHealthyStateHosts(healthyStateHosts);
+    chr.setUnknownStatusHosts(unknownStatusHosts);
+    chr.setUnhealthyStatusHosts(unhealthyStatusHosts);
+    chr.setUnhealthyStateHosts(unhealthyStateHosts);
+    chr.setStaleConfigsHosts(staleConfigsHosts);
+    chr.setMaintenanceStateHosts(maintenanceStateHosts);
+    chr.setInitStateHosts(initStateHosts);
+    chr.setHeartbeatLostStateHosts(heartbeatLostStateHosts);
+    chr.setHealthyStatusHosts(healthyStatusHosts);
+
+    return chr;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/main/resources/properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json
index 0cb32e7..9c6dd9c 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -6,6 +6,8 @@
         "Clusters/version",
         "Clusters/state",
         "Clusters/desired_configs",
+        "Clusters/total_hosts",
+        "Clusters/health_report",
         "_"
     ],
     "Service":[
@@ -307,7 +309,7 @@
         "TaskAttempt/status",
         "TaskAttempt/locality"
     ],
-     "RootService":[
+    "RootService":[
         "RootService/service_name"
     ],
     "RootServiceComponent":[

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/test/java/org/apache/ambari/server/controller/ClusterResponseTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/ClusterResponseTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/ClusterResponseTest.java
index c07a6ed..050b80a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/ClusterResponseTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/ClusterResponseTest.java
@@ -36,18 +36,21 @@ public class ClusterResponseTest {
     hostNames.add("h1");
 
     ClusterResponse r1 =
-        new ClusterResponse(clusterId, clusterName, provisioningState, hostNames, "bar");
+        new ClusterResponse(clusterId, clusterName, provisioningState,
+          hostNames, hostNames.size(), "bar", null);
     
     Assert.assertEquals(clusterId, r1.getClusterId());
     Assert.assertEquals(clusterName, r1.getClusterName());
     Assert.assertEquals(provisioningState.name(), r1.getProvisioningState());
     Assert.assertArrayEquals(hostNames.toArray(), r1.getHostNames().toArray());
+    Assert.assertEquals(Integer.valueOf(1), r1.getTotalHosts());
     Assert.assertEquals("bar", r1.getDesiredStackVersion());
   }
 
   @Test
   public void testToString() {
-    ClusterResponse r = new ClusterResponse(null, null, null, null, null);
+    ClusterResponse r =
+      new ClusterResponse(null, null, null, null, null, null, null);
     r.toString();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
index 901d55f..9f51ac7 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
@@ -1882,17 +1882,17 @@ public class ClusterResourceProviderTest {
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
 
     Set<ClusterResponse> allResponse = new HashSet<ClusterResponse>();
-    allResponse.add(new ClusterResponse(100L, "Cluster100", State.INSTALLED, null, null));
-    allResponse.add(new ClusterResponse(101L, "Cluster101", State.INSTALLED, null, null));
-    allResponse.add(new ClusterResponse(102L, "Cluster102", State.INSTALLED, null, null));
-    allResponse.add(new ClusterResponse(103L, "Cluster103", State.INSTALLED, null, null));
-    allResponse.add(new ClusterResponse(104L, "Cluster104", State.INSTALLED, null, null));
+    allResponse.add(new ClusterResponse(100L, "Cluster100", State.INSTALLED, null, null, null, null));
+    allResponse.add(new ClusterResponse(101L, "Cluster101", State.INSTALLED, null, null, null, null));
+    allResponse.add(new ClusterResponse(102L, "Cluster102", State.INSTALLED, null, null, null, null));
+    allResponse.add(new ClusterResponse(103L, "Cluster103", State.INSTALLED, null, null, null, null));
+    allResponse.add(new ClusterResponse(104L, "Cluster104", State.INSTALLED, null, null, null, null));
 
     Set<ClusterResponse> nameResponse = new HashSet<ClusterResponse>();
-    nameResponse.add(new ClusterResponse(102L, "Cluster102", State.INSTALLED, null, null));
+    nameResponse.add(new ClusterResponse(102L, "Cluster102", State.INSTALLED, null, null, null, null));
 
     Set<ClusterResponse> idResponse = new HashSet<ClusterResponse>();
-    idResponse.add(new ClusterResponse(103L, "Cluster103", State.INSTALLED, null, null));
+    idResponse.add(new ClusterResponse(103L, "Cluster103", State.INSTALLED, null, null, null, null));
 
     // set expectations
     expect(managementController.getClusters(EasyMock.<Set<ClusterRequest>>anyObject())).andReturn(allResponse).once();
@@ -1961,7 +1961,7 @@ public class ClusterResourceProviderTest {
     RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
 
     Set<ClusterResponse> nameResponse = new HashSet<ClusterResponse>();
-    nameResponse.add(new ClusterResponse(102L, "Cluster102", State.INIT, null, null));
+    nameResponse.add(new ClusterResponse(102L, "Cluster102", State.INIT, null, null, null, null));
 
     Map<String, String> mapRequestProps = new HashMap<String, String>();
     mapRequestProps.put("context", "Called from a test");
@@ -2023,7 +2023,7 @@ public class ClusterResourceProviderTest {
     RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
 
     Set<ClusterResponse> nameResponse = new HashSet<ClusterResponse>();
-    nameResponse.add(new ClusterResponse(100L, "Cluster100", State.INSTALLED, null, null));
+    nameResponse.add(new ClusterResponse(100L, "Cluster100", State.INSTALLED, null, null, null, null));
 
     Map<String, String> mapRequestProps = new HashMap<String, String>();
     mapRequestProps.put("context", "Called from a test");

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/test/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProviderTest.java
index b0cf585..b16457d 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/nagios/NagiosPropertyProviderTest.java
@@ -145,7 +145,50 @@ public class NagiosPropertyProviderTest {
     Assert.assertEquals(1, set.size());
 
   }
-  
+
+  @Test
+  public void testNagiosClusterAlerts() throws Exception {
+
+    TestStreamProvider streamProvider = new TestStreamProvider("nagios_alerts.txt");
+
+    NagiosPropertyProvider npp = new NagiosPropertyProvider(Resource.Type.Cluster,
+      streamProvider,
+      "Clusters/cluster_name",
+      "Clusters/version");
+    npp.forceReset();
+
+    Resource resource = new ResourceImpl(Resource.Type.Cluster);
+    resource.setProperty("Clusters/cluster_name", "c1");
+    resource.setProperty("Clusters/version", "HDP-2.0.6");
+
+    // request with an empty set should get all supported properties
+    Request request = PropertyHelper.getReadRequest(Collections.<String>emptySet(), new HashMap<String, TemporalInfo>());
+
+    Set<Resource> set = npp.populateResources(Collections.singleton(resource), request, null);
+    Assert.assertEquals(1, set.size());
+
+    Resource res = set.iterator().next();
+
+    Map<String, Map<String, Object>> values = res.getPropertiesMap();
+
+    Assert.assertTrue(values.containsKey("alerts/summary"));
+
+    Map<String, Object> summary = values.get("alerts/summary");
+    Assert.assertEquals(4L, summary.size());
+    Assert.assertTrue(summary.containsKey("OK"));
+    Assert.assertTrue(summary.containsKey("WARNING"));
+    Assert.assertTrue(summary.containsKey("CRITICAL"));
+    Assert.assertTrue(summary.containsKey("PASSIVE"));
+    Assert.assertFalse(summary.containsKey("detail"));
+
+    //Totally 4 hosts, no hosts with no alerts
+    Assert.assertTrue(summary.get("OK").equals(Integer.valueOf(0)));
+    Assert.assertTrue(summary.get("WARNING").equals(Integer.valueOf(1)));
+    Assert.assertTrue(summary.get("CRITICAL").equals(Integer.valueOf(2)));
+    Assert.assertTrue(summary.get("PASSIVE").equals(Integer.valueOf(1)));
+
+  }
+
   @Test
   public void testNoNagiosServerCompoonent() throws Exception {
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/42b08d22/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java
index 5bc8852..49f69dc 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java
@@ -459,7 +459,46 @@ public class ClusterTest {
     ClusterResponse r = c1.convertToResponse();
     Assert.assertEquals(c1.getClusterId(), r.getClusterId().longValue());
     Assert.assertEquals(c1.getClusterName(), r.getClusterName());
-    Assert.assertEquals(1, r.getHostNames().size());
+    Assert.assertEquals(Integer.valueOf(1), r.getTotalHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getAlertStatusHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getHealthyStatusHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getUnhealthyStatusHosts());
+    Assert.assertEquals(1, r.getClusterHealthReport().getUnknownStatusHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getStaleConfigsHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getMaintenanceStateHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getHealthyStateHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getHeartbeatLostStateHosts());
+    Assert.assertEquals(1, r.getClusterHealthReport().getInitStateHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getUnhealthyStateHosts());
+
+    clusters.addHost("h2");
+    Host host = clusters.getHost("h2");
+    host.setIPv4("ipv4");
+    host.setIPv6("ipv6");
+
+    Map<String, String> hostAttributes = new HashMap<String, String>();
+    hostAttributes.put("os_family", "redhat");
+    hostAttributes.put("os_release_version", "5.9");
+    host.setHostAttributes(hostAttributes);
+    host.setState(HostState.HEALTHY);
+    host.setHealthStatus(new HostHealthStatus(HostHealthStatus.HealthStatus.HEALTHY, ""));
+    host.persist();
+    c1.setDesiredStackVersion(new StackId("HDP-2.0.6"));
+    clusters.mapHostToCluster("h2", "c1");
+
+    r = c1.convertToResponse();
+
+    Assert.assertEquals(Integer.valueOf(2), r.getTotalHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getAlertStatusHosts());
+    Assert.assertEquals(1, r.getClusterHealthReport().getHealthyStatusHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getUnhealthyStatusHosts());
+    Assert.assertEquals(1, r.getClusterHealthReport().getUnknownStatusHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getStaleConfigsHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getMaintenanceStateHosts());
+    Assert.assertEquals(1, r.getClusterHealthReport().getHealthyStateHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getHeartbeatLostStateHosts());
+    Assert.assertEquals(1, r.getClusterHealthReport().getInitStateHosts());
+    Assert.assertEquals(0, r.getClusterHealthReport().getUnhealthyStateHosts());
 
     // TODO write unit tests for debug dump
     StringBuilder sb = new StringBuilder();