Quellcode durchsuchen

Merge remote-tracking branch 'origin/trunk' into trunk

Oleg Nechiporenko vor 10 Jahren
Ursprung
Commit
7711dadb20
39 geänderte Dateien mit 1556 neuen und 305 gelöschten Zeilen
  1. 7 1
      ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
  2. 1 1
      ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
  3. 1 1
      ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html
  4. 1 0
      ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
  5. 1 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/ganglia/GangliaHostPropertyProvider.java
  6. 1 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/ganglia/GangliaPropertyProvider.java
  7. 22 0
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
  8. 1 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/after-INSTALL/scripts/shared_initialization.py
  9. 10 3
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/GANGLIA/package/scripts/ganglia_monitor.py
  10. 4 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/GANGLIA/package/scripts/params.py
  11. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/FALCON/metainfo.xml
  12. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/FLUME/metainfo.xml
  13. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/HBASE/metainfo.xml
  14. 4 56
      ambari-server/src/main/resources/stacks/HDP/2.2/services/HDFS/configuration/hadoop-env.xml
  15. 39 4
      ambari-server/src/main/resources/stacks/HDP/2.2/services/HDFS/metainfo.xml
  16. 18 4
      ambari-server/src/main/resources/stacks/HDP/2.2/services/HIVE/metainfo.xml
  17. 1 4
      ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/configuration/kafka-broker.xml
  18. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/metainfo.xml
  19. 262 0
      ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/metrics.json
  20. 1 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/package/scripts/kafka.py
  21. 1 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/package/scripts/params.py
  22. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/KNOX/metainfo.xml
  23. 19 6
      ambari-server/src/main/resources/stacks/HDP/2.2/services/OOZIE/metainfo.xml
  24. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/PIG/metainfo.xml
  25. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/SLIDER/metainfo.xml
  26. 14 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/SQOOP/metainfo.xml
  27. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/STORM/metainfo.xml
  28. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/TEZ/metainfo.xml
  29. 21 2
      ambari-server/src/main/resources/stacks/HDP/2.2/services/YARN/metainfo.xml
  30. 9 1
      ambari-server/src/main/resources/stacks/HDP/2.2/services/ZOOKEEPER/metainfo.xml
  31. 15 15
      ambari-server/src/test/java/org/apache/ambari/server/controller/ganglia/GangliaPropertyProviderTest.java
  32. 1 1
      ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java
  33. 1 1
      ambari-server/src/test/python/stacks/2.2/configs/default.json
  34. 78 63
      ambari-web/app/controllers/main/host/details.js
  35. 18 4
      ambari-web/app/data/HDP2/site_properties.js
  36. 8 2
      ambari-web/app/models/service_config.js
  37. 12 12
      ambari-web/app/routes/main.js
  38. 874 112
      ambari-web/test/controllers/main/host/details_test.js
  39. 30 0
      ambari-web/test/models/service_config_test.js

+ 7 - 1
ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js

@@ -18,7 +18,7 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('ViewsListCtrl',['$scope', 'View', '$modal', 'Alert', 'ConfirmationModal', function($scope, View, $modal, Alert, ConfirmationModal) {
+.controller('ViewsListCtrl',['$scope', 'View', '$modal', 'Alert', 'ConfirmationModal', '$location', function($scope, View, $modal, Alert, ConfirmationModal, $location) {
   var deferredList = [];
   $scope.$on('$locationChangeStart', function() {
     deferredList.forEach(function(def) {
@@ -114,4 +114,10 @@ angular.module('ambariAdminConsole')
     }
     $scope.filteredViews = result;
   };
+
+  $scope.gotoCreate = function(viewName, isAllowed) {
+    if(isAllowed){
+      $location.path('/views/'+viewName+'/new');
+    }
+  };
 }]);

+ 1 - 1
ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js

@@ -75,7 +75,7 @@ angular.module('ambariAdminConsole')
       controller: 'ViewsEditCtrl'
     },
     create: {
-      url: '/views/:viewId/versions/:version/new',
+      url: '/views/:viewId/new',
       templateUrl: 'views/ambariViews/create.html',
       controller: 'CreateViewInstanceCtrl'
     }

+ 1 - 1
ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html

@@ -80,7 +80,7 @@
           <tr>
             <td class="col-sm-3"></td>
             <td class="col-sm-3">
-              <a tooltip="{{view.canCreateInstance ? '' : 'Unable to create view instances'}}" class="btn btn-default createisntance-btn {{view.canCreateInstance ? '' : 'disabled'}}" href="#/views/{{view.view_name}}/versions/{{view.versionsList[view.versionsList.length-1].ViewVersionInfo.version}}/new"><span class="glyphicon glyphicon-plus"></span> Create Instance</a>
+              <a tooltip="{{view.canCreateInstance ? '' : 'Unable to create view instances'}}" class="btn btn-default createisntance-btn {{view.canCreateInstance ? '' : 'disabled'}}" href ng-click="gotoCreate(view.view_name, view.canCreateInstance);"><span class="glyphicon glyphicon-plus"></span> Create Instance</a>
             </td>
             <td class="col-sm-3"></td>
             <td class="col-sm-3">

+ 1 - 0
ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java

@@ -200,6 +200,7 @@ public class Configuration {
   public static final String CLIENT_API_SSL_KEY_NAME_DEFAULT = "https.key";
   public static final String CLIENT_API_SSL_CRT_NAME_DEFAULT = "https.crt";
   public static final String GLOBAL_CONFIG_TAG = "global";
+  public static final String MAPREDUCE2_LOG4J_CONFIG_TAG = "mapreduce2-log4j";
   public static final String RCA_ENABLED_PROPERTY = "rca_enabled";
   public static final String HIVE_CONFIG_TAG = "hive-site";
   public static final String HIVE_METASTORE_PASSWORD_PROPERTY =

+ 1 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/ganglia/GangliaHostPropertyProvider.java

@@ -49,6 +49,7 @@ public class GangliaHostPropertyProvider extends GangliaPropertyProvider{
     GANGLIA_CLUSTER_NAMES.add("HDPHBaseRegionServer");
     GANGLIA_CLUSTER_NAMES.add("HDPFlumeServer");
     GANGLIA_CLUSTER_NAMES.add("HDPJournalNode");
+    GANGLIA_CLUSTER_NAMES.add("HDPKafka");
   }
 
   // ----- Constructors ------------------------------------------------------

+ 1 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/ganglia/GangliaPropertyProvider.java

@@ -73,6 +73,7 @@ public abstract class GangliaPropertyProvider extends AbstractPropertyProvider {
     GANGLIA_CLUSTER_NAME_MAP.put("JOURNALNODE",        Arrays.asList("HDPJournalNode", "HDPSlaves"));
     GANGLIA_CLUSTER_NAME_MAP.put("NIMBUS",             Collections.singletonList("HDPNimbus"));
     GANGLIA_CLUSTER_NAME_MAP.put("SUPERVISOR",         Collections.singletonList("HDPSupervisor"));
+    GANGLIA_CLUSTER_NAME_MAP.put("KAFKA_BROKER",         Collections.singletonList("HDPKafka"));
   }
 
   protected final static Logger LOG =

+ 22 - 0
ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java

@@ -649,6 +649,28 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
     moveConfigGroupsGlobalToEnv();
     addMissingConfigs();
     updateClusterProvisionState();
+    removeMapred2Log4jConfig();
+  }
+
+  private void removeMapred2Log4jConfig() {
+    ConfigHelper configHelper = injector.getInstance(ConfigHelper.class);
+
+    AmbariManagementController ambariManagementController = injector.getInstance(
+            AmbariManagementController.class);
+    Clusters clusters = ambariManagementController.getClusters();
+    if (clusters == null) {
+      return;
+    }
+    Map<String, Cluster> clusterMap = clusters.getClusters();
+
+    if (clusterMap != null && !clusterMap.isEmpty()) {
+      for (final Cluster cluster : clusterMap.values()) {
+        Config config = cluster.getDesiredConfigByType(Configuration.MAPREDUCE2_LOG4J_CONFIG_TAG);
+        if (config != null) {
+          configHelper.removeConfigsByType(cluster, Configuration.MAPREDUCE2_LOG4J_CONFIG_TAG);
+        }
+      }
+    }
   }
 
   public void updateClusterProvisionState() {

+ 1 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/after-INSTALL/scripts/shared_initialization.py

@@ -23,6 +23,7 @@ def setup_hdp_install_directory():
   import params
   if params.rpm_version:
     Execute(format('ambari-python-wrap /usr/bin/hdp-select set all `ambari-python-wrap /usr/bin/hdp-select versions | grep ^{rpm_version}- | tail -1`'),
+            not_if=format('test -d {versioned_hdp_root}'),
             only_if=format('ls -d /usr/hdp/{rpm_version}-*')
     )
 

+ 10 - 3
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/GANGLIA/package/scripts/ganglia_monitor.py

@@ -33,7 +33,7 @@ class GangliaMonitor(Script):
     self.install_packages(env)
     env.set_params(params)
     self.configure(env)
-    
+
     functions.turn_off_autostart(params.gmond_service_name)
     functions.turn_off_autostart("gmetad") # since the package is installed as well
 
@@ -75,7 +75,7 @@ class GangliaMonitor(Script):
     )
 
     ganglia.config()
-    
+
     self.generate_slave_configs()
 
     Directory(path.join(params.ganglia_dir, "conf.d"),
@@ -133,7 +133,7 @@ class GangliaMonitor(Script):
 
   def generate_master_configs(self):
     import params
-     
+
     if params.has_namenodes:
       generate_daemon("gmond",
                       name = "HDPNameNode",
@@ -211,6 +211,13 @@ class GangliaMonitor(Script):
                       owner = "root",
                       group = params.user_group)
 
+    if params.has_kafka_broker:
+      generate_daemon("gmond",
+                      name = "HDPKafka",
+                      role = "server",
+                      owner = "root",
+                      group = params.user_group)
+
     if params.has_flume:
       generate_daemon("gmond",
                       name = "HDPFlumeServer",

+ 4 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/GANGLIA/package/scripts/params.py

@@ -73,6 +73,8 @@ flume_hosts = set(default("/clusterHostInfo/flume_hosts", []))
 jn_hosts = set(default("/clusterHostInfo/journalnode_hosts", []))
 nimbus_server_hosts = set(default("/clusterHostInfo/nimbus_hosts", []))
 supervisor_server_hosts = set(default("/clusterHostInfo/supervisor_hosts", []))
+kafka_broker_hosts =  set(default("/clusterHostInfo/kafka_broker_hosts", []))
+kafka_ganglia_port = default("/configurations/kafka-broker/kafka.ganglia.metrics.port", 8671)
 
 pure_slave = not hostname in (namenode_host | jtnode_host | rm_host | hs_host | \
                               hbase_master_hosts | slave_hosts | tt_hosts | hbase_rs_hosts | \
@@ -106,6 +108,7 @@ has_flume = not len(flume_hosts) == 0
 has_journalnode = not len(jn_hosts) == 0
 has_nimbus_server = not len(nimbus_server_hosts) == 0
 has_supervisor_server = not len(supervisor_server_hosts) == 0
+has_kafka_broker = not len(kafka_broker_hosts) == 0
 
 ganglia_cluster_names = {
   "jn_hosts": [("HDPJournalNode", 8654)],
@@ -121,6 +124,7 @@ ganglia_cluster_names = {
   "hs_host": [("HDPHistoryServer", 8666)],
   "nimbus_hosts": [("HDPNimbus", 8649)],
   "supervisor_hosts": [("HDPSupervisor", 8650)],
+  "kafka_broker_hosts": [("HDPKafka", kafka_ganglia_port)],
   "ReservedPort1": [("ReservedPort1", 8667)],
   "ReservedPort2": [("ReservedPort2", 8668)],
   "ReservedPort3": [("ReservedPort3", 8669)]

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/FALCON/metainfo.xml

@@ -24,13 +24,21 @@
       <version>0.6.0.2.2.9.9</version>
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>falcon_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>falcon-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
     </service>
   </services>

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/FLUME/metainfo.xml

@@ -25,13 +25,21 @@
 
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>flume_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>flume-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
 
     </service>

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/HBASE/metainfo.xml

@@ -25,13 +25,21 @@
 
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>hbase_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>hbase-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
 
     </service>

+ 4 - 56
ambari-server/src/main/resources/stacks/HDP/2.2/services/HDFS/configuration/hadoop-env.xml

@@ -21,69 +21,17 @@
 -->
 
 <configuration>
-  <property>
-    <name>hdfs_log_dir_prefix</name>
-    <value>/var/log/hadoop</value>
-    <description>Hadoop Log Dir Prefix</description>
-  </property>
-  <property>
-    <name>hadoop_pid_dir_prefix</name>
-    <value>/var/run/hadoop</value>
-    <description>Hadoop PID Dir Prefix</description>
-  </property>
-  <property>
-    <name>hadoop_root_logger</name>
-    <value>INFO,RFA</value>
-    <description>Hadoop Root Logger</description>
-  </property>
-  <property>
-    <name>hadoop_heapsize</name>
-    <value>1024</value>
-    <description>Hadoop maximum Java heap size</description>
-  </property>
-  <property>
-    <name>namenode_heapsize</name>
-    <value>1024</value>
-    <description>NameNode Java heap size</description>
-  </property>
-  <property>
-    <name>namenode_opt_newsize</name>
-    <value>200</value>
-    <description>NameNode new generation size</description>
-  </property>
-  <property>
-    <name>namenode_opt_maxnewsize</name>
-    <value>200</value>
-    <description>NameNode maximum new generation size</description>
-  </property>
   <property>
     <name>namenode_opt_permsize</name>
-    <value>128</value>
+    <value>128m</value>
     <description>NameNode permanent generation size</description>
   </property>
   <property>
     <name>namenode_opt_maxpermsize</name>
-    <value>256</value>
+    <value>256m</value>
     <description>NameNode maximum permanent generation size</description>
   </property>
-  <property>
-    <name>dtnode_heapsize</name>
-    <value>1024</value>
-    <description>DataNode maximum Java heap size</description>
-  </property>
-  <property>
-    <name>proxyuser_group</name>
-    <value>users</value>
-    <property-type>GROUP</property-type>
-    <description>Proxy user group.</description>
-  </property>
-  <property>
-    <name>hdfs_user</name>
-    <value>hdfs</value>
-    <property-type>USER</property-type>
-    <description>User to run HDFS as</description>
-  </property>
-  
+
   <!-- hadoop-env.sh -->
   <property>
     <name>content</name>
@@ -201,4 +149,4 @@ export JAVA_LIBRARY_PATH=${JAVA_LIBRARY_PATH}:/usr/hdp/current/hadoop-client/lib
     </value>
   </property>
   
-</configuration>
+</configuration>

+ 39 - 4
ambari-server/src/main/resources/stacks/HDP/2.2/services/HDFS/metainfo.xml

@@ -27,9 +27,6 @@
         <osSpecific>
           <osFamily>any</osFamily>
           <packages>
-            <package>
-              <name>hadoop_2_2_0_0_*</name>
-            </package>
             <package>
               <name>hadoop-lzo</name>
             </package>
@@ -39,6 +36,9 @@
         <osSpecific>
           <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
+            <package>
+              <name>hadoop_2_2_0_0_*</name>
+            </package>
             <package>
               <name>snappy</name>
             </package>
@@ -59,7 +59,42 @@
             </package>
           </packages>
         </osSpecific>
-            
+
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>hadoop-2-2-0-0-.*-client</name>
+            </package>
+            <package>
+              <name>hadoop-2-2-0-0-.*-hdfs-datanode</name>
+            </package>
+            <package>
+              <name>hadoop-2-2-0-0-.*-hdfs-journalnode</name>
+            </package>
+            <package>
+              <name>hadoop-2-2-0-0-.*-hdfs-namenode</name>
+            </package>
+            <package>
+              <name>hadoop-2-2-0-0-.*-hdfs-secondarynamenode</name>
+            </package>
+            <package>
+              <name>hadoop-2-2-0-0-.*-hdfs-zkfc</name>
+            </package>
+            <package>
+              <name>libsnappy1</name>
+            </package>
+            <package>
+              <name>libsnappy-dev</name>
+            </package>
+            <package>
+              <name>liblzo2-2</name>
+            </package>
+            <package>
+              <name>libhdfs0-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
 
     </service>

+ 18 - 4
ambari-server/src/main/resources/stacks/HDP/2.2/services/HIVE/metainfo.xml

@@ -26,10 +26,15 @@
           <osFamily>any</osFamily>
           <packages>
             <package>
-              <name>hive_2_2_0_0_*</name>
+              <name>mysql-connector-java</name>
             </package>
+          </packages>
+        </osSpecific>
+        <osSpecific>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
+          <packages>
             <package>
-              <name>mysql-connector-java</name>
+              <name>hive_2_2_0_0_*</name>
             </package>
             <package>
               <name>hive_2_2_0_0_*-hcatalog</name>
@@ -37,13 +42,22 @@
             <package>
               <name>hive_2_2_0_0_*-webhcat</name>
             </package>
+            <package>
+              <name>mysql</name>
+            </package>
           </packages>
         </osSpecific>
         <osSpecific>
-          <osFamily>redhat5,redhat6,suse11</osFamily>
+          <osFamily>ubuntu12</osFamily>
           <packages>
             <package>
-              <name>mysql</name>
+              <name>hive-2-2-0-0-.*</name>
+            </package>
+            <package>
+              <name>hive-2-2-0-0-.*-hcatalog</name>
+            </package>
+            <package>
+              <name>hive-2-2-0-0-.*-webhcat</name>
             </package>
           </packages>
         </osSpecific>

+ 1 - 4
ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/configuration/kafka-broker.xml

@@ -289,7 +289,6 @@
       Backoff time between shutdown retries.
     </description>
   </property>
-  <!--
   <property>
     <name>kafka.metrics.reporters</name>
     <value>kafka.ganglia.KafkaGangliaMetricsReporter</value>
@@ -297,7 +296,6 @@
       kafka ganglia metrics reporter
     </description>
   </property>
-
   <property>
     <name>kafka.ganglia.metrics.reporter.enabled</name>
     <value>true</value>
@@ -305,7 +303,6 @@
       kafka ganglia metrics reporter enable
     </description>
   </property>
-  -->
   <property>
     <name>kafka.ganglia.metrics.host</name>
     <value>localhost</value>
@@ -313,7 +310,7 @@
   </property>
   <property>
     <name>kafka.ganglia.metrics.port</name>
-    <value>8649</value>
+    <value>8671</value>
     <description> Ganglia port </description>
   </property>
   <property>

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/metainfo.xml

@@ -47,13 +47,21 @@
       </components>
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>kafka_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>kafka-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
       <commandScript>
         <script>scripts/service_check.py</script>

+ 262 - 0
ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/metrics.json

@@ -0,0 +1,262 @@
+{
+  "KAFKA_BROKER": {
+    "Component": [
+      {
+        "type": "ganglia",
+        "metrics": {
+          "metrics/jvm/uptime":{
+            "metric":"jvm.uptime",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/jvm/heap_usage":{
+            "metric":"jvm.heap_usage",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/jvm/non_heap_usage":{
+            "metric":"jvm.non_heap_usage",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/jvm/thread-states/runnable":{
+            "metric":"jvm.thread-states.runnable",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/jvm/thread-states/blocked":{
+            "metric":"jvm.thread-states.blocked",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/jvm/thread-states/timed_waiting":{
+            "metric":"jvm.thread-states.timed_waiting",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/jvm/thread-states/terminated":{
+            "metric":"jvm.thread-states.terminated",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/jvm/thread_count":{
+            "metric":"jvm.thread_count",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/jvm/daemon_thread_count":{
+            "metric":"jvm.daemon_thread_count",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsMessagesInPerSec/1MinuteRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsMessagesInPerSec.1MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsMessagesInPerSec/5MinuteRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsMessagesInPerSec.5MinuteRate",
+            "pointInTime": false,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsMessagesInPerSec/15MinuteRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsMessagesInPerSec.15MinuteRate",
+            "pointInTime": false,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsMessagesInPerSec/meanRate": {
+            "metric": "kafka.server.BrokerTopicMetrics/AllTopicsMessagesInPerSec/meanRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsMessagesInPerSec/count": {
+            "metric": "kafka.server.BrokerTopicMetrics/AllTopicsMessagesInPerSec.counte",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesInPerSec/1MinuteRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesInPerSec.1MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesInPerSec/5MinuteRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesInPerSec.5MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesInPerSec/15MinuteRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesInPerSec.15MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesInPerSec/meanRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesInPerSec.meanRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesInPerSec/count": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesInPerSec.count",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesOutPerSec/1MinuteRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesOutPerSec.1MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesOutPerSec/5MinuteRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesOutPerSec.5MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesOutPerSec/15MinuteRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesOutPerSec.15MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesOutPerSec/meanRate": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesOutPerSec.meanRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/server/BrokerTopicMetrics/AllTopicsBytesOutPerSec/count": {
+            "metric": "kafka.server.BrokerTopicMetrics.AllTopicsBytesOutPerSec.count",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/KafkaController/ActiveControllerCount": {
+            "metric": "kafka.controller.KafkaController.ActiveControllerCount",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/log/LogFlushStats/LogFlushRateAndTimeMs/meanRate": {
+            "metric": "kafka.log.LogFlushStats.LogFlushRateAndTimeMs.meanRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/log/LogFlushStats/LogFlushRateAndTimeMs/1MinuteRate": {
+            "metric": "kafka.log.LogFlushStats.LogFlushRateAndTimeMs.1MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/log/LogFlushStats/LogFlushRateAndTimeMs/5MinuteRate": {
+            "metric": "kafka.log.LogFlushStats.LogFlushRateAndTimeMs.1MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/log/LogFlushStats/LogFlushRateAndTimeMs/15MinuteRate": {
+            "metric": "kafka.log.LogFlushStats.LogFlushRateAndTimeMs.15MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/log/LogFlushStats/LogFlushRateAndTimeMs/count": {
+            "metric": "kafka.log.LogFlushStats.LogFlushRateAndTimeMs.count",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/ControllerStats/LeaderElectionRateAndTimeMs/meanRate": {
+            "metric": "kafka.controller.ControllerStats.LeaderElectionRateAndTimeMs.meanRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/ControllerStats/LeaderElectionRateAndTimeMs/1MinuteRate": {
+            "metric": "kafka.controller.ControllerStats.LeaderElectionRateAndTimeMs.1MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/ControllerStats/LeaderElectionRateAndTimeMs/5MinuteRate": {
+            "metric": "kafka.controller.ControllerStats.LeaderElectionRateAndTimeMs.5MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/ControllerStats/LeaderElectionRateAndTimeMs/15MinuteRate": {
+            "metric": "kafka.controller.ControllerStats.LeaderElectionRateAndTimeMs.15MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/ControllerStats/LeaderElectionRateAndTimeMs/count": {
+            "metric": "kafka.controller.ControllerStats.LeaderElectionRateAndTimeMs.count",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/ControllerStats/UncleanLeaderElectionsPerSec/1MinuteRate": {
+            "metric": "kafka.controller.ControllerStats.UncleanLeaderElectionsPerSec.1MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/ControllerStats/UncleanLeaderElectionsPerSec/5MinuteRate": {
+            "metric": "kafka.controller.ControllerStats.UncleanLeaderElectionsPerSec.5MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/ControllerStats/UncleanLeaderElectionsPerSec/15MinuteRate": {
+            "metric": "kafka.controller.ControllerStats.UncleanLeaderElectionsPerSec.15MinuteRate",
+            "pointInTime": true,
+            "temporal": true
+          },
+          "metrics/kafka/controller/ControllerStats/OfflinePartitionsCount": {
+              "metric": "kafka.controller.ControllerStats.OfflinePartitionsCount",
+              "pointInTime" :true,
+              "temporal": true
+          },
+          "metrics/kafka/server/ReplicaManager/PartitionCount": {
+              "metric": "kafka.server.ReplicaManager.PartitionCount",
+              "pointInTime" : true,
+              "temporal": true
+          },
+          "metrics/kafka/server/ReplicaManager/LeaderCount": {
+              "metric": "kafka.server.ReplicaManager.LeaderCount",
+              "pointInTime" : true,
+              "temporal": true
+          },
+          "metrics/kafka/server/ReplicaManager/UnderReplicatedPartitions": {
+              "metric": "kafka.server.ReplicaManager.UnderReplicatedPartitions",
+              "pointInTime" :true,
+              "temporal": true
+          },
+          "metrics/kafka/server/ReplicaManager/ISRShrinksPerSec": {
+              "metric": "kafka.server.ReplicaManager.ISRShrinksPerSec",
+              "pointInTime" : true,
+              "temporal": true
+          },
+          "metrics/kafka/server/ReplicaManager/ISRExpandsPerSec": {
+              "metric": "kafka.server.ReplicaManager.ISRExpandsPerSec",
+              "pointInTime" : true,
+              "temporal": true
+          },
+
+          "metrics/kafka/server/ReplicaFetcherManager/Replica-MaxLag": {
+              "metric": "kafka.server.ReplicaFetcherManager.Replica-MaxLag",
+              "pointInTime" : true,
+              "temporal": true
+          },
+          "metrics/kafka/server/ProducerRequestPurgatory/PurgatorySize": {
+              "metric": "kafka.server.ProducerRequestPurgatory.PurgatorySize",
+              "pointInTime" : true,
+              "temporal": true
+          },
+          "metrics/kafka/server/FetchRequestPurgatory/PurgatorySize": {
+              "metric": "kafka.server.FetchRequestPurgatory.PurgatorySize",
+              "pointInTime" : true,
+              "temporal": true
+          },
+          "metrics/kafka/cluster/Partition/$1-UnderReplicated":{
+            "metric":"kafka.cluster.Partition.(\\w+)-UnderReplicated",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/kafka/consumer/ConsumerFetcherManager/$1-MaxLag":{
+            "metric":"kafka.consumer.ConsumerFetcherManager.(\\w+)-MaxLag",
+            "pointInTime":true,
+            "temporal":true
+          },
+          "metrics/kafka/consumer/ConsumerFetcherManager/$1-MinFetch":{
+            "metric":"kafka.consumer.ConsumerFetcherManager.(\\w+)-MinFetch",
+            "pointInTime":true,
+            "temporal":true
+          }
+        }
+      }
+    ]
+  }
+}

+ 1 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/package/scripts/kafka.py

@@ -34,7 +34,7 @@ def kafka():
     brokerid = str(sorted(params.kafka_hosts).index(params.hostname))
     kafka_server_config = mutable_config_dict(params.config['configurations']['kafka-broker'])
     kafka_server_config['broker.id'] = brokerid
-    kafka_server_config['hostname'] = params.hostname
+    kafka_server_config['host.name'] = params.hostname
     conf_dir = params.conf_dir
     properties_config("server.properties",
                       conf_dir=params.conf_dir,

+ 1 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/KAFKA/package/scripts/params.py

@@ -45,7 +45,7 @@ hostname = config['hostname']
 user_group = config['configurations']['cluster-env']['user_group']
 java64_home = config['hostLevelParams']['java_home']
 kafka_env_sh_template = config['configurations']['kafka-env']['content']
-kafka_hosts = config['clusterHostInfo']['zookeeper_hosts']
+kafka_hosts = config['clusterHostInfo']['kafka_broker_hosts']
 kafka_hosts.sort()
 
 zookeeper_hosts = config['clusterHostInfo']['zookeeper_hosts']

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/KNOX/metainfo.xml

@@ -55,13 +55,21 @@
       </components>
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>knox_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>knox-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
       <commandScript>
         <script>scripts/service_check.py</script>

+ 19 - 6
ambari-server/src/main/resources/stacks/HDP/2.2/services/OOZIE/metainfo.xml

@@ -26,22 +26,35 @@
           <osFamily>any</osFamily>
           <packages>
             <package>
-              <name>oozie_2_2_0_0_*</name>
+              <name>zip</name>
             </package>
             <package>
-              <name>oozie_2_2_0_0_*-client</name>
+              <name>mysql-connector-java</name>
             </package>
             <package>
-              <name>falcon_2_2_0_0_*</name>
+              <name>extjs</name>
             </package>
+          </packages>
+        </osSpecific>
+        <osSpecific>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
+          <packages>
             <package>
-              <name>zip</name>
+              <name>oozie_2_2_0_0_*</name>
             </package>
             <package>
-              <name>mysql-connector-java</name>
+              <name>falcon_2_2_0_0_*</name>
+            </package>
+          </packages>
+        </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>oozie-2-2-0-0-.*</name>
             </package>
             <package>
-              <name>extjs</name>
+              <name>falcon-2-2-0-0-.*</name>
             </package>
           </packages>
         </osSpecific>

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/PIG/metainfo.xml

@@ -24,13 +24,21 @@
       <version>0.14.0.2.2.0.0</version>
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>pig_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>pig-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
     </service>
   </services>

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/SLIDER/metainfo.xml

@@ -86,13 +86,21 @@
       </components>
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>slider_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>slider-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
 
       <commandScript>

+ 14 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/SQOOP/metainfo.xml

@@ -24,12 +24,25 @@
       <osSpecifics>
         <osSpecific>
           <osFamily>any</osFamily>
+          <packages>
+            <package>
+              <name>mysql-connector-java</name>
+            </package>
+          </packages>
+        </osSpecific>
+        <osSpecific>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>sqoop_2_2_0_0_*</name>
             </package>
+          </packages>
+        </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
             <package>
-              <name>mysql-connector-java</name>
+              <name>sqoop-2-2-0-0-.*</name>
             </package>
           </packages>
         </osSpecific>

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/STORM/metainfo.xml

@@ -31,13 +31,21 @@
       </components>
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>storm_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>storm-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
     </service>
   </services>

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/TEZ/metainfo.xml

@@ -25,13 +25,21 @@
 
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>tez_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>tez-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
 
     </service>

+ 21 - 2
ambari-server/src/main/resources/stacks/HDP/2.2/services/YARN/metainfo.xml

@@ -32,7 +32,7 @@
       
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>hadoop_2_2_0_0_*-yarn</name>
@@ -42,6 +42,17 @@
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>hadoop-2-2-0-0-.*-yarn</name>
+            </package>
+            <package>
+              <name>hadoop-2-2-0-0-.*-mapreduce</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
     </service>
 
@@ -51,13 +62,21 @@
       <version>2.6.0.2.2.0.0</version>
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>hadoop_2_2_0_0_*-mapreduce</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>hadoop-2-2-0-0-.*-mapreduce</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
       <configuration-dir>configuration-mapred</configuration-dir>
 

+ 9 - 1
ambari-server/src/main/resources/stacks/HDP/2.2/services/ZOOKEEPER/metainfo.xml

@@ -25,13 +25,21 @@
 
       <osSpecifics>
         <osSpecific>
-          <osFamily>any</osFamily>
+          <osFamily>redhat5,redhat6,suse11</osFamily>
           <packages>
             <package>
               <name>zookeeper_2_2_0_0_*</name>
             </package>
           </packages>
         </osSpecific>
+        <osSpecific>
+          <osFamily>ubuntu12</osFamily>
+          <packages>
+            <package>
+              <name>zookeeper-2-2-0-0-.*</name>
+            </package>
+          </packages>
+        </osSpecific>
       </osSpecifics>
 
     </service>

+ 15 - 15
ambari-server/src/test/java/org/apache/ambari/server/controller/ganglia/GangliaPropertyProviderTest.java

@@ -17,19 +17,6 @@
  */
 package org.apache.ambari.server.controller.ganglia;
 
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.expect;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
 import org.apache.ambari.server.configuration.ComponentSSLConfigurationTest;
 import org.apache.ambari.server.controller.internal.PropertyInfo;
@@ -51,6 +38,19 @@ import org.junit.runners.Parameterized;
 import org.powermock.api.easymock.PowerMock;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.expect;
+
 /**
  * Test the Ganglia property provider.
  */
@@ -323,7 +323,7 @@ public class GangliaPropertyProviderTest {
     uriBuilder.setScheme((configuration.isGangliaSSL() ? "https" : "http"));
     uriBuilder.setHost("domU-12-31-39-0E-34-E1.compute-1.internal");
     uriBuilder.setPath("/cgi-bin/rrd.py");
-    uriBuilder.setParameter("c", "HDPJobTracker,HDPHBaseMaster,HDPResourceManager,HDPFlumeServer,HDPSlaves,HDPHistoryServer,HDPJournalNode,HDPTaskTracker,HDPHBaseRegionServer,HDPNameNode");
+    uriBuilder.setParameter("c", "HDPJobTracker,HDPHBaseMaster,HDPKafka,HDPResourceManager,HDPFlumeServer,HDPSlaves,HDPHistoryServer,HDPJournalNode,HDPTaskTracker,HDPHBaseRegionServer,HDPNameNode");
     uriBuilder.setParameter("h", "domU-12-31-39-0E-34-E3.compute-1.internal,domU-12-31-39-0E-34-E1.compute-1.internal,domU-12-31-39-0E-34-E2.compute-1.internal");
     uriBuilder.setParameter("m", "jvm.metrics.gcCount");
     uriBuilder.setParameter("s", "10");
@@ -382,7 +382,7 @@ public class GangliaPropertyProviderTest {
     expectedUri.setScheme((configuration.isGangliaSSL() ? "https" : "http"));
     expectedUri.setHost("domU-12-31-39-0E-34-E1.compute-1.internal");
     expectedUri.setPath("/cgi-bin/rrd.py");
-    expectedUri.setParameter("c", "HDPJobTracker,HDPHBaseMaster,HDPResourceManager,HDPFlumeServer,HDPSlaves,HDPHistoryServer,HDPJournalNode,HDPTaskTracker,HDPHBaseRegionServer,HDPNameNode");
+    expectedUri.setParameter("c", "HDPJobTracker,HDPHBaseMaster,HDPKafka,HDPResourceManager,HDPFlumeServer,HDPSlaves,HDPHistoryServer,HDPJournalNode,HDPTaskTracker,HDPHBaseRegionServer,HDPNameNode");
    
     expectedUri.setParameter("h", hostsList.toString());
     expectedUri.setParameter("m", "jvm.metrics.gcCount");

+ 1 - 1
ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java

@@ -502,7 +502,7 @@ public class UpgradeCatalog170Test {
     expect(amc.getClusters()).andReturn(clusters).anyTimes();
     expect(clusters.getClusters()).andReturn(clustersMap).anyTimes();
     expect(clusters.getClusterById(1L)).andReturn(clustersMap.values().iterator().next()).anyTimes();
-    expect(clusters.getClusters()).andReturn(clustersMap).once();
+    expect(clusters.getClusters()).andReturn(clustersMap).times(2);
     expect(cluster.getDesiredConfigByType("global")).andReturn(config).anyTimes();
     expect(cluster.getDesiredConfigByType("oozie-log4j")).andReturn(config).anyTimes();
     expect(cluster.getClusterId()).andReturn(1L);

+ 1 - 1
ambari-server/src/test/python/stacks/2.2/configs/default.json

@@ -234,7 +234,7 @@
         "jaimin-knox-1.c.pramod-thangali.internal"
       ],
       "kafka_broker_hosts": [
-        "c6402.ambari.apache.org"
+        "c6401.ambari.apache.org"
       ],
        "zookeeper_hosts": [
          "c6401.ambari.apache.org"

+ 78 - 63
ambari-web/app/controllers/main/host/details.js

@@ -110,7 +110,7 @@ App.MainHostDetailsController = Em.Controller.extend({
    * @param {object} component  When <code>null</code> all startable components are started.
    * @param {String} context  Context under which this command is beign sent.
    * @param {String} state - desired state of component can be 'STARTED' or 'STOPPED'
-   * @method sendStartComponentCommand
+   * @method sendComponentCommand
    */
   sendComponentCommand: function (component, context, state) {
     var data = {
@@ -213,7 +213,7 @@ App.MainHostDetailsController = Em.Controller.extend({
     var componentName = component.get('componentName');
     var displayName = component.get('displayName');
     var isLastComponent = (this.getTotalComponent(component) === 1);
-    App.ModalPopup.show({
+    return App.ModalPopup.show({
       header: Em.I18n.t('popup.confirmation.commonHeader'),
       primary: Em.I18n.t('hosts.host.deleteComponent.popup.confirm'),
       bodyClass: Em.View.extend({
@@ -869,7 +869,7 @@ App.MainHostDetailsController = Em.Controller.extend({
    */
   recommission: function (component) {
     var self = this;
-    App.showConfirmationPopup(function () {
+    return App.showConfirmationPopup(function () {
       self.runRecommission.call(self, self.get('content.hostName'), component.get('service.serviceName'));
     });
   },
@@ -1306,8 +1306,6 @@ App.MainHostDetailsController = Em.Controller.extend({
       case "onOffPassiveModeForHost":
         this.onOffPassiveModeForHost(option.context);
         break;
-      default:
-        break;
     }
   },
 
@@ -1431,7 +1429,7 @@ App.MainHostDetailsController = Em.Controller.extend({
     var components = this.get('serviceActiveComponents');
     var componentsLength = Em.isNone(components) ? 0 : components.get('length');
     if (componentsLength > 0) {
-      App.showConfirmationPopup(function () {
+      return App.showConfirmationPopup(function () {
         batchUtils.restartHostComponents(components, Em.I18n.t('rollingrestart.context.allOnSelectedHost').format(self.get('content.hostName')), "HOST");
       });
     }
@@ -1513,10 +1511,10 @@ App.MainHostDetailsController = Em.Controller.extend({
     if (container.zkServerInstalled) {
       var self = this;
       return App.showConfirmationPopup(function () {
-        self._doDeleteHost(container.unknownComponents, container.lastComponents);
+        self.confirmDeleteHost(container.unknownComponents, container.lastComponents);
       }, Em.I18n.t('hosts.host.addComponent.deleteHostWithZooKeeper'));
     } else {
-      this._doDeleteHost(container.unknownComponents, container.lastComponents);
+      this.confirmDeleteHost(container.unknownComponents, container.lastComponents);
     }
   },
 
@@ -1558,11 +1556,11 @@ App.MainHostDetailsController = Em.Controller.extend({
    * Show confirmation popup to delete host
    * @param {string[]} unknownComponents
    * @param {string[]} lastComponents
-   * @method _doDeleteHost
+   * @method confirmDeleteHost
    */
-  _doDeleteHost: function (unknownComponents, lastComponents) {
+  confirmDeleteHost: function (unknownComponents, lastComponents) {
     var self = this;
-    App.ModalPopup.show({
+    return App.ModalPopup.show({
       header: Em.I18n.t('hosts.delete.popup.title'),
       deletePopupBody: function () {
         return Em.I18n.t('hosts.delete.popup.body').format(self.get('content.publicHostName'));
@@ -1593,62 +1591,79 @@ App.MainHostDetailsController = Em.Controller.extend({
         templateName: require('templates/main/host/details/doDeleteHostPopup')
       }),
       onPrimary: function () {
-        self.set('fromDeleteHost', true);
-        var allComponents = self.get('content.hostComponents');
-        var deleteError = null;
-        var dfd = $.Deferred();
         var popup = this;
-        allComponents.forEach(function (component, index) {
-          var length = allComponents.get('length');
-          if (!deleteError) {
-            self._doDeleteHostComponent(component, function () {
-              deleteError = self.get('_deletedHostComponentResult');
-              if (index == length - 1) {
-                dfd.resolve();
-              }
-            });
-          }
-        });
-        dfd.done(function () {
-          if (!deleteError) {
-            App.ajax.send({
-              name: 'common.delete.host',
-              sender: popup,
-              data: {
-                hostName: self.get('content.hostName')
-              },
-              success: 'deleteHostSuccessCallback',
-              error: 'deleteHostErrorCallback'
-            });
-          }
-          else {
-            popup.hide();
-            deleteError.xhr.responseText = "{\"message\": \"" + deleteError.xhr.statusText + "\"}";
-            App.ajax.defaultErrorHandler(deleteError.xhr, deleteError.url, deleteError.method, deleteError.xhr.status);
-          }
-        });
-      },
-      deleteHostSuccessCallback: function (data) {
-        var dialogSelf = this;
-        App.router.get('updateController').updateHost(function () {
-          self.loadConfigs();
-          dialogSelf.hide();
-          App.router.transitionTo('hosts.index');
-        });
-        App.router.get('clusterController').getAllHostNames();
-      },
-      deleteHostErrorCallback: function (xhr, textStatus, errorThrown, opt) {
-        console.log('Error deleting host.');
-        console.log(textStatus);
-        console.log(errorThrown);
-        xhr.responseText = "{\"message\": \"" + xhr.statusText + "\"}";
-        self.loadConfigs();
-        this.hide();
-        App.ajax.defaultErrorHandler(xhr, opt.url, 'DELETE', xhr.status);
+        var completeCallback = function () {
+          popup.hide();
+        };
+        self.doDeleteHost(completeCallback);
       }
     })
   },
 
+  /**
+   * send DELETE calls to components of host and after delete host itself
+   * @param completeCallback
+   * @method doDeleteHost
+   */
+  doDeleteHost: function (completeCallback) {
+    this.set('fromDeleteHost', true);
+    var allComponents = this.get('content.hostComponents');
+    var deleteError = null;
+    var dfd = $.Deferred();
+    var self = this;
+
+    if (allComponents.get('length') > 0) {
+      allComponents.forEach(function (component, index) {
+        var length = allComponents.get('length');
+        if (!deleteError) {
+          this._doDeleteHostComponent(component, function () {
+            deleteError = self.get('_deletedHostComponentResult');
+            if (index == length - 1) {
+              dfd.resolve();
+            }
+          });
+        }
+      }, this);
+    } else {
+      dfd.resolve();
+    }
+    dfd.done(function () {
+      if (!deleteError) {
+        App.ajax.send({
+          name: 'common.delete.host',
+          sender: self,
+          data: {
+            hostName: self.get('content.hostName')
+          },
+          callback: completeCallback,
+          success: 'deleteHostSuccessCallback',
+          error: 'deleteHostErrorCallback'
+        })
+      }
+      else {
+        completeCallback();
+        deleteError.xhr.responseText = "{\"message\": \"" + deleteError.xhr.statusText + "\"}";
+        App.ajax.defaultErrorHandler(deleteError.xhr, deleteError.url, deleteError.method, deleteError.xhr.status);
+      }
+    });
+  },
+  deleteHostSuccessCallback: function (data) {
+    var self = this
+    App.router.get('updateController').updateHost(function () {
+      self.loadConfigs();
+      App.router.transitionTo('hosts.index');
+    });
+    App.router.get('clusterController').getAllHostNames();
+  },
+  deleteHostErrorCallback: function (xhr, textStatus, errorThrown, opt) {
+    console.log('Error deleting host.');
+    console.log(textStatus);
+    console.log(errorThrown);
+    xhr.responseText = "{\"message\": \"" + xhr.statusText + "\"}";
+    this.loadConfigs();
+    App.ajax.defaultErrorHandler(xhr, opt.url, 'DELETE', xhr.status);
+  },
+
   /**
    * Send command to server to restart all host components with stale configs
    * @method restartAllStaleConfigComponents
@@ -1667,7 +1682,7 @@ App.MainHostDetailsController = Em.Controller.extend({
    * @method moveComponent
    */
   moveComponent: function (event) {
-    App.showConfirmationPopup(function () {
+    return App.showConfirmationPopup(function () {
       var component = event.context;
       var reassignMasterController = App.router.get('reassignMasterController');
       reassignMasterController.saveComponentToReassign(component);

+ 18 - 4
ambari-web/app/data/HDP2/site_properties.js

@@ -1690,18 +1690,18 @@ module.exports =
       "isOverridable": false,
       "serviceName": "KNOX",
       "filename": "knox-env.xml",
-      "category": "Advanced knox-env.xml"
+      "category": "Advanced knox-env"
     },
 
   /********************************************* KAFKA *****************************/
     {
       "id": "puppet var",
-      "name": "kafka_broker_host",
+      "name": "kafka_broker_hosts",
       "displayName": "Kafka Broker host",
       "value": "",
       "defaultValue": "",
       "description": "The host that has been assigned to run Kafka Broker",
-      "displayType": "masterHost",
+      "displayType": "masterHosts",
       "isOverridable": false,
       "isVisible": true,
       "isRequiredByAgent": false,
@@ -1781,7 +1781,7 @@ module.exports =
       "displayType": "directory",
       "serviceName": "KAFKA",
       "filename": "kafka-broker.xml",
-      "category": "Advanced kafka-env.xml",
+      "category": "Advanced kafka-env",
       "index": 0
     },
 
@@ -3960,6 +3960,20 @@ module.exports =
       "belongsToService": ["KNOX"],
       "index": 19
     },
+    {
+      "id": "puppet var",
+      "name": "kafka_user",
+      "displayName": "Kafka User",
+      "isReconfigurable": false,
+      "displayType": "user",
+      "isOverridable": false,
+      "isVisible": true,
+      "serviceName": "MISC",
+      "filename": "kafka-env.xml",
+      "category": "Users and Groups",
+      "belongsToService": ["KAFKA"],
+      "index": 20
+    },
     {
       "id": "puppet var",
       "name": "rrdcached_base_dir",

+ 8 - 2
ambari-web/app/models/service_config.js

@@ -481,8 +481,14 @@ App.ServiceConfigProperty = Ember.Object.extend({
       case 'knox_gateway_host':
         this.set('value', masterComponentHostsInDB.findProperty('component', 'KNOX_GATEWAY').hostName);
         break;
-      case 'kafka_broker_host':
-        this.set('value', masterComponentHostsInDB.findProperty('component', 'KAFKA_BROKER').hostName);
+      case 'kafka_broker_hosts':
+        this.set('value', masterComponentHostsInDB.filterProperty('component', 'KAFKA_BROKER').mapProperty('hostName'));
+        break;
+      case 'kafka.ganglia.metrics.host':
+        var gangliaHost =  masterComponentHostsInDB.findProperty('component', 'GANGLIA_SERVER');
+        if (gangliaHost) {
+          this.set('value', gangliaHost.hostName);
+        }
         break;
       case 'hbase.zookeeper.quorum':
         var zkHosts = masterComponentHostsInDB.filterProperty('component', 'ZOOKEEPER_SERVER').mapProperty('hostName');

+ 12 - 12
ambari-web/app/routes/main.js

@@ -26,22 +26,22 @@ module.exports = Em.Route.extend({
     console.log('in /main:enter');
     router.getAuthenticated().done(function (loggedIn) {
       if (loggedIn) {
-        App.router.get('mainViewsController').loadAmbariViews();
-        App.router.get('clusterController').loadClusterName(false).done(function () {
-          if (App.get('testMode')) {
-            router.get('mainController').initialize();
-          } else {
-            if (router.get('clusterInstallCompleted')) {
-              App.router.get('mainController').checkServerClientVersion().done(function () {
+        App.router.get('mainController').checkServerClientVersion().done(function () {
+          App.router.get('mainViewsController').loadAmbariViews();
+          App.router.get('clusterController').loadClusterName(false).done(function () {
+            if (App.get('testMode')) {
+              router.get('mainController').initialize();
+            } else {
+              if (router.get('clusterInstallCompleted')) {
                 App.router.get('clusterController').loadClientServerClockDistance().done(function () {
                   router.get('mainController').initialize();
                 });
-              });
-            }
-            else {
-              App.router.get('clusterController').set('isLoaded', true);
+              }
+              else {
+                App.router.get('clusterController').set('isLoaded', true);
+              }
             }
-          }
+          });
         });
         // TODO: redirect to last known state
       } else {

+ 874 - 112
ambari-web/test/controllers/main/host/details_test.js

@@ -29,19 +29,241 @@ describe('App.MainHostDetailsController', function () {
 
 
   beforeEach(function () {
-    sinon.stub(App.ajax, 'send', Em.K);
+    sinon.stub(App.ajax, 'send').returns({
+      then: Em.K
+    });
     controller = App.MainHostDetailsController.create({
-      securityEnabled: function () {
-        return this.get('mockSecurityStatus');
-      }.property(),
-      content: Em.Object.create(),
-      mockSecurityStatus: false
+      content: Em.Object.create()
     });
   });
   afterEach(function () {
     App.ajax.send.restore();
   });
 
+  describe('#routeHome()', function () {
+    it('transiotion to dashboard', function () {
+      sinon.stub(App.router, 'transitionTo', Em.K);
+      controller.routeHome();
+      expect(App.router.transitionTo.calledWith('main.dashboard.index')).to.be.true;
+      App.router.transitionTo.restore();
+    });
+  });
+
+  describe('#routeToService()', function () {
+    it('transiotion to dashboard', function () {
+      sinon.stub(App.router, 'transitionTo', Em.K);
+      controller.routeToService({context: {'service': 'service'}});
+      expect(App.router.transitionTo.calledWith('main.services.service.summary', {'service': 'service'})).to.be.true;
+      App.router.transitionTo.restore();
+    });
+  });
+
+  describe('#startComponent()', function () {
+    it('call sendComponentCommand', function () {
+      var event = {
+        context: Em.Object.create({
+          displayName: 'comp'
+        })
+      };
+      sinon.stub(App, 'showConfirmationPopup', function (callback) {
+        callback();
+      });
+      sinon.stub(controller, 'sendComponentCommand');
+      controller.startComponent(event);
+      expect(App.showConfirmationPopup.calledOnce).to.be.true;
+      expect(controller.sendComponentCommand.calledWith(Em.Object.create({
+        displayName: 'comp'
+      })), Em.I18n.t('requestInfo.startHostComponent') + " comp", App.HostComponentStatus.started).to.be.true;
+      App.showConfirmationPopup.restore();
+      controller.sendComponentCommand.restore();
+    });
+  });
+
+  describe('#stopComponent()', function () {
+    it('call sendComponentCommand', function () {
+      var event = {
+        context: Em.Object.create({
+          displayName: 'comp'
+        })
+      };
+      sinon.stub(App, 'showConfirmationPopup', function (callback) {
+        callback();
+      });
+      sinon.stub(controller, 'sendComponentCommand');
+      controller.stopComponent(event);
+      expect(App.showConfirmationPopup.calledOnce).to.be.true;
+      expect(controller.sendComponentCommand.calledWith(Em.Object.create({
+        displayName: 'comp'
+      })), Em.I18n.t('requestInfo.stopHostComponent') + " comp", App.HostComponentStatus.started).to.be.true;
+      App.showConfirmationPopup.restore();
+      controller.sendComponentCommand.restore();
+    });
+  });
+
+  describe('#sendComponentCommand()', function () {
+    it('single component', function () {
+      controller.set('content.hostName', 'host1');
+      var component = Em.Object.create({
+        service: {serviceName: 'S1'},
+        componentName: 'COMP1'
+      });
+
+      controller.sendComponentCommand(component, {}, 'state');
+      expect(App.ajax.send.getCall(0).args[0].name).to.be.equal('common.host.host_component.update');
+      expect(App.ajax.send.getCall(0).args[0].data).to.be.eql({
+        "hostName": "host1",
+        "context": {},
+        "component": Em.Object.create({
+          service: {serviceName: 'S1'},
+          componentName: 'COMP1'
+        }),
+        "HostRoles": {
+          "state": "state"
+        },
+        "componentName": "COMP1",
+        "serviceName": "S1"
+      });
+    });
+    it('multiple component', function () {
+      controller.set('content.hostName', 'host1');
+      var component = [
+        Em.Object.create({
+          service: {serviceName: 'S1'},
+          componentName: 'COMP1'
+        }),
+        Em.Object.create({
+          service: {serviceName: 'S1'},
+          componentName: 'COMP2'
+        })
+      ];
+
+      controller.sendComponentCommand(component, {}, 'state');
+      expect(App.ajax.send.getCall(0).args[0].name).to.be.equal('common.host.host_components.update');
+      expect(App.ajax.send.getCall(0).args[0].data).to.be.eql({
+        "hostName": "host1",
+        "context": {},
+        "component": [
+          Em.Object.create({
+            service: {serviceName: 'S1'},
+            componentName: 'COMP1'
+          }),
+          Em.Object.create({
+            service: {serviceName: 'S1'},
+            componentName: 'COMP2'
+          })
+        ],
+        "HostRoles": {
+          "state": "state"
+        },
+        "query": "HostRoles/component_name.in(COMP1,COMP2)"
+      });
+    });
+  });
+
+  describe('#sendComponentCommandSuccessCallback()', function () {
+    beforeEach(function () {
+      sinon.stub(controller, 'mimicWorkStatusChange', Em.K);
+      sinon.stub(controller, 'showBackgroundOperationsPopup', Em.K);
+    });
+    afterEach(function () {
+      controller.showBackgroundOperationsPopup.restore();
+      controller.mimicWorkStatusChange.restore();
+    });
+    it('testMode, starting component', function () {
+      var params = {
+        component: Em.Object.create({}),
+        HostRoles: {
+          state: App.HostComponentStatus.started
+        }
+      };
+
+      App.set('testMode', true);
+      controller.sendComponentCommandSuccessCallback({}, {}, params);
+      expect(controller.mimicWorkStatusChange.calledWith(Em.Object.create({
+        workStatus: App.HostComponentStatus.starting
+      }), App.HostComponentStatus.starting, App.HostComponentStatus.started)).to.be.true;
+      expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
+    });
+    it('testMode, stopping component', function () {
+      var params = {
+        component: Em.Object.create({}),
+        HostRoles: {
+          state: App.HostComponentStatus.stopped
+        }
+      };
+
+      App.set('testMode', true);
+      controller.sendComponentCommandSuccessCallback({}, {}, params);
+      expect(controller.mimicWorkStatusChange.calledWith(Em.Object.create({
+        workStatus: App.HostComponentStatus.stopping
+      }), App.HostComponentStatus.stopping, App.HostComponentStatus.stopped)).to.be.true;
+      expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
+    });
+    it('testMode, stopping component', function () {
+      var params = {
+        component: Em.Object.create({}),
+        HostRoles: {
+          state: App.HostComponentStatus.stopped
+        }
+      };
+
+      App.set('testMode', false);
+      controller.sendComponentCommandSuccessCallback({}, {}, params);
+      expect(controller.mimicWorkStatusChange.called).to.be.false;
+      expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
+    });
+  });
+
+  describe('#ajaxErrorCallback()', function () {
+    it('call componentsUtils.ajaxErrorCallback', function () {
+      sinon.stub(componentsUtils, 'ajaxErrorCallback', Em.K);
+      controller.ajaxErrorCallback('request', 'ajaxOptions', 'error', 'opt', 'params');
+      expect(componentsUtils.ajaxErrorCallback.calledWith('request', 'ajaxOptions', 'error', 'opt', 'params')).to.be.true;
+      componentsUtils.ajaxErrorCallback.restore();
+    });
+  });
+
+  describe('#showBackgroundOperationsPopup()', function () {
+    var mock = {
+      done: function (callback) {
+        callback(this.initValue);
+      }
+    };
+    var bgController = {
+      showPopup: Em.K
+    };
+    beforeEach(function () {
+      var stub = sinon.stub(App.router, 'get');
+      stub.withArgs('applicationController').returns({
+        dataLoading: function () {
+          return mock;
+        }
+      });
+      stub.withArgs('backgroundOperationsController').returns(bgController);
+      sinon.spy(bgController, 'showPopup');
+      sinon.spy(mock, 'done');
+    });
+    afterEach(function () {
+      bgController.showPopup.restore();
+      mock.done.restore();
+      App.router.get.restore();
+    });
+    it('initValue is true, callback is undefined', function () {
+      mock.initValue = true;
+      controller.showBackgroundOperationsPopup();
+      expect(mock.done.calledOnce).to.be.true;
+      expect(bgController.showPopup.calledOnce).to.be.true;
+    });
+    it('initValue is false, callback is defined', function () {
+      mock.initValue = false;
+      var callback = sinon.stub();
+      controller.showBackgroundOperationsPopup(callback);
+      expect(mock.done.calledOnce).to.be.true;
+      expect(bgController.showPopup.calledOnce).to.be.false;
+      expect(callback.calledOnce).to.be.true;
+    });
+  });
+
 
   describe('#serviceActiveComponents', function () {
 
@@ -92,27 +314,26 @@ describe('App.MainHostDetailsController', function () {
       controller.reopen({serviceActiveComponents: [Em.Object.create({
         isClient: false
       })]});
-      expect(controller.get('serviceNonClientActiveComponents')).to.eql( [Em.Object.create({
+      expect(controller.get('serviceNonClientActiveComponents')).to.eql([Em.Object.create({
         isClient: false
       })]);
     });
   });
 
   describe('#deleteComponent()', function () {
-
-    beforeEach(function () {
-      sinon.spy(App.ModalPopup, "show");
-    });
-    afterEach(function () {
-      App.ModalPopup.show.restore();
-    });
-
     it('confirm popup should be displayed', function () {
       var event = {
         context: Em.Object.create({})
       };
-      controller.deleteComponent(event);
+      sinon.spy(App.ModalPopup, "show");
+      sinon.stub(controller, '_doDeleteHostComponent', Em.K);
+
+      var popup = controller.deleteComponent(event);
       expect(App.ModalPopup.show.calledOnce).to.be.true;
+      popup.onPrimary();
+      expect(controller._doDeleteHostComponent.calledWith(Em.Object.create({}))).to.be.true;
+      App.ModalPopup.show.restore();
+      controller._doDeleteHostComponent.restore();
     });
   });
 
@@ -183,8 +404,18 @@ describe('App.MainHostDetailsController', function () {
     });
   });
 
-  describe('#addComponent()', function () {
+  describe('#securityEnabled', function () {
+    it('', function () {
+      sinon.stub(App.router, 'get').withArgs('mainAdminSecurityController.securityEnabled').returns(true);
+
+      controller.propertyDidChange('securityEnabled');
+      expect(controller.get('securityEnabled')).to.be.true;
+      App.router.get.restore();
+    });
+  });
+
 
+  describe('#addComponent()', function () {
     beforeEach(function () {
       sinon.spy(App, "showConfirmationPopup");
       sinon.stub(controller, "addClientComponent", Em.K);
@@ -192,6 +423,9 @@ describe('App.MainHostDetailsController', function () {
       controller.set('content', {hostComponents: [Em.Object.create({
         componentName: "HDFS_CLIENT"
       })]});
+      controller.reopen({
+        securityEnabled: false
+      });
     });
 
     afterEach(function () {
@@ -215,7 +449,7 @@ describe('App.MainHostDetailsController', function () {
       var event = {context: Em.Object.create({
         componentName: 'HIVE_CLIENT'
       })};
-      controller.set('mockSecurityStatus', true);
+      controller.set('securityEnabled', true);
       var popup = controller.addComponent(event);
       expect(App.showConfirmationPopup.calledOnce).to.be.true;
       popup.onPrimary();
@@ -227,7 +461,7 @@ describe('App.MainHostDetailsController', function () {
       var event = {context: Em.Object.create({
         componentName: 'HIVE_CLIENT'
       })};
-      controller.set('mockSecurityStatus', false);
+      controller.set('securityEnabled', false);
       controller.addComponent(event);
       expect(controller.addClientComponent.calledWith(Em.Object.create({
         componentName: 'HIVE_CLIENT'
@@ -430,8 +664,8 @@ describe('App.MainHostDetailsController', function () {
         id: 'HIVE',
         service_name: 'HIVE'
       });
-      var data = {Clusters: {desired_configs: {'webhcat-site': {tag: 1},'hive-site': {tag: 1}}}};
-      expect(controller.constructConfigUrlParams(data)).to.eql(['(type=webhcat-site&tag=1)','(type=hive-site&tag=1)']);
+      var data = {Clusters: {desired_configs: {'webhcat-site': {tag: 1}, 'hive-site': {tag: 1}}}};
+      expect(controller.constructConfigUrlParams(data)).to.eql(['(type=webhcat-site&tag=1)', '(type=hive-site&tag=1)']);
       App.Service.find().clear();
     });
     it('STORM is installed', function () {
@@ -452,6 +686,12 @@ describe('App.MainHostDetailsController', function () {
       expect(controller.constructConfigUrlParams(data)).to.eql(['(type=slider-client&tag=1)']);
       App.Service.find().clear();
     });
+    it('isRMHaEnabled true', function () {
+      sinon.stub(App, 'get').withArgs('isRMHaEnabled').returns(true);
+      var data = {Clusters: {desired_configs: {'yarn-site': {tag: 1}}}};
+      expect(controller.constructConfigUrlParams(data)).to.eql(['(type=yarn-site&tag=1)']);
+      App.get.restore();
+    });
   });
 
   describe('#loadConfigsSuccessCallback()', function () {
@@ -595,6 +835,15 @@ describe('App.MainHostDetailsController', function () {
         "slider.zookeeper.quorum": "host1:2181"
       }});
     });
+    it('isRMHaEnabled true', function () {
+      var configs = {'yarn-site': {}};
+      sinon.stub(App, 'get').withArgs('isRMHaEnabled').returns(true);
+      expect(controller.setZKConfigs(configs, 'host1:2181', ['host1', 'host2'])).to.be.true;
+      expect(configs).to.eql({"yarn-site": {
+        "yarn.resourcemanager.zk-address": "host1,host2"
+      }});
+      App.get.restore();
+    });
   });
 
   describe('#concatZkNames()', function () {
@@ -611,22 +860,26 @@ describe('App.MainHostDetailsController', function () {
 
   describe('#getZkServerHosts()', function () {
 
-    beforeEach(function() {
+    beforeEach(function () {
       controller.set('content', {});
     });
 
-    afterEach(function() {
+    afterEach(function () {
       App.HostComponent.find.restore();
     });
 
     it('No ZooKeeper hosts, fromDeleteHost = false', function () {
-      sinon.stub(App.HostComponent, 'find', function() {return []});
+      sinon.stub(App.HostComponent, 'find', function () {
+        return []
+      });
       controller.set('fromDeleteHost', false);
       expect(controller.getZkServerHosts()).to.be.empty;
     });
 
     it('No ZooKeeper hosts, fromDeleteHost = true', function () {
-      sinon.stub(App.HostComponent, 'find', function() {return []});
+      sinon.stub(App.HostComponent, 'find', function () {
+        return []
+      });
       controller.set('fromDeleteHost', true);
       expect(controller.getZkServerHosts()).to.be.empty;
       expect(controller.get('fromDeleteHost')).to.be.false;
@@ -634,18 +887,26 @@ describe('App.MainHostDetailsController', function () {
 
     it('One ZooKeeper host, fromDeleteHost = false', function () {
       controller.set('fromDeleteHost', false);
-      sinon.stub(App.HostComponent, 'find', function() {return [{id: 'ZOOKEEPER_SERVER_host1',
-        componentName: 'ZOOKEEPER_SERVER',
-        hostName: 'host1'
-      }]});
+      sinon.stub(App.HostComponent, 'find', function () {
+        return [
+          {id: 'ZOOKEEPER_SERVER_host1',
+            componentName: 'ZOOKEEPER_SERVER',
+            hostName: 'host1'
+          }
+        ]
+      });
       expect(controller.getZkServerHosts()).to.eql(['host1']);
     });
 
     it('One ZooKeeper host match current host name, fromDeleteHost = true', function () {
-      sinon.stub(App.HostComponent, 'find', function() {return [{id: 'ZOOKEEPER_SERVER_host1',
-        componentName: 'ZOOKEEPER_SERVER',
-        hostName: 'host1'
-      }]});
+      sinon.stub(App.HostComponent, 'find', function () {
+        return [
+          {id: 'ZOOKEEPER_SERVER_host1',
+            componentName: 'ZOOKEEPER_SERVER',
+            hostName: 'host1'
+          }
+        ]
+      });
       controller.set('fromDeleteHost', true);
       controller.set('content.hostName', 'host1');
       expect(controller.getZkServerHosts()).to.be.empty;
@@ -653,10 +914,14 @@ describe('App.MainHostDetailsController', function () {
     });
 
     it('One ZooKeeper host does not match current host name, fromDeleteHost = true', function () {
-      sinon.stub(App.HostComponent, 'find', function() {return [{id: 'ZOOKEEPER_SERVER_host1',
-        componentName: 'ZOOKEEPER_SERVER',
-        hostName: 'host1'
-      }]});
+      sinon.stub(App.HostComponent, 'find', function () {
+        return [
+          {id: 'ZOOKEEPER_SERVER_host1',
+            componentName: 'ZOOKEEPER_SERVER',
+            hostName: 'host1'
+          }
+        ]
+      });
       controller.set('fromDeleteHost', true);
       controller.set('content.hostName', 'host2');
       expect(controller.getZkServerHosts()[0]).to.equal("host1");
@@ -702,6 +967,25 @@ describe('App.MainHostDetailsController', function () {
     });
   });
 
+  describe('#recommission()', function () {
+
+    beforeEach(function () {
+      sinon.spy(App, "showConfirmationPopup");
+      sinon.stub(controller, "runRecommission", Em.K);
+    });
+    afterEach(function () {
+      App.showConfirmationPopup.restore();
+      controller.runRecommission.restore();
+    });
+
+    it('popup should be displayed', function () {
+      var popup = controller.recommission(Em.Object.create({service: {}}));
+      expect(App.showConfirmationPopup.calledOnce).to.be.true;
+      popup.onPrimary();
+      expect(controller.runRecommission.calledOnce).to.be.true;
+    });
+  });
+
   describe('#runDecommission()', function () {
 
     beforeEach(function () {
@@ -726,6 +1010,12 @@ describe('App.MainHostDetailsController', function () {
       controller.runDecommission('host1', 'MAPREDUCE');
       expect(controller.doDecommission.calledWith('host1', 'MAPREDUCE', "JOBTRACKER", "TASKTRACKER")).to.be.true;
     });
+    it('HBASE service', function () {
+      sinon.stub(controller, 'warnBeforeDecommission', Em.K);
+      controller.runDecommission('host1', 'HBASE');
+      expect(controller.warnBeforeDecommission.calledWith('host1')).to.be.true;
+      controller.warnBeforeDecommission.restore();
+    });
   });
 
   describe('#runRecommission()', function () {
@@ -923,7 +1213,9 @@ describe('App.MainHostDetailsController', function () {
       expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
     });
     it('data has resources', function () {
-      var data = {resources: [{RequestSchedule: {}}]};
+      var data = {resources: [
+        {RequestSchedule: {}}
+      ]};
       expect(controller.decommissionSuccessCallback(data)).to.be.true;
       expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
     });
@@ -1044,7 +1336,7 @@ describe('App.MainHostDetailsController', function () {
   describe('#doStartAllComponents()', function () {
 
     beforeEach(function () {
-      sinon.stub(App, "showConfirmationPopup", Em.K);
+      sinon.spy(App, "showConfirmationPopup");
       controller.reopen({serviceActiveComponents: []});
     });
     afterEach(function () {
@@ -1060,19 +1352,29 @@ describe('App.MainHostDetailsController', function () {
     });
     it('serviceNonClientActiveComponents is correct', function () {
       controller.reopen({
-        serviceNonClientActiveComponents: [{}]
+        serviceNonClientActiveComponents: [
+          {}
+        ]
       });
+      sinon.stub(controller, 'sendComponentCommand', Em.K);
       var popup = controller.doStartAllComponents();
       expect(App.showConfirmationPopup.calledOnce).to.be.true;
-      /*popup.onPrimary();
-       expect(controller.sendStartComponentCommand.calledWith([{}])).to.be.true;*/
+      popup.onPrimary();
+      expect(controller.sendComponentCommand.calledWith(
+        [
+          {}
+        ],
+        Em.I18n.t('hosts.host.maintainance.startAllComponents.context'),
+        App.HostComponentStatus.started)
+      ).to.be.true;
+      controller.sendComponentCommand.restore();
     });
   });
 
   describe('#doStopAllComponents()', function () {
 
     beforeEach(function () {
-      sinon.stub(App, "showConfirmationPopup", Em.K);
+      sinon.spy(App, "showConfirmationPopup");
       controller.reopen({serviceActiveComponents: []});
     });
     afterEach(function () {
@@ -1089,19 +1391,29 @@ describe('App.MainHostDetailsController', function () {
 
     it('serviceNonClientActiveComponents is correct', function () {
       controller.reopen({
-        serviceNonClientActiveComponents: [{}]
+        serviceNonClientActiveComponents: [
+          {}
+        ]
       });
+      sinon.stub(controller, 'sendComponentCommand', Em.K);
       var popup = controller.doStopAllComponents();
       expect(App.showConfirmationPopup.calledOnce).to.be.true;
-      /*popup.onPrimary();
-       expect(controller.sendStopComponentCommand.calledWith([{}])).to.be.true;*/
+      popup.onPrimary();
+      expect(controller.sendComponentCommand.calledWith(
+        [
+          {}
+        ],
+        Em.I18n.t('hosts.host.maintainance.stopAllComponents.context'),
+        App.HostComponentStatus.stopped)
+      ).to.be.true;
+      controller.sendComponentCommand.restore();
     });
   });
 
   describe('#doRestartAllComponents()', function () {
 
     beforeEach(function () {
-      sinon.stub(App, "showConfirmationPopup", Em.K);
+      sinon.spy(App, "showConfirmationPopup");
     });
     afterEach(function () {
       App.showConfirmationPopup.restore();
@@ -1117,12 +1429,22 @@ describe('App.MainHostDetailsController', function () {
 
     it('serviceActiveComponents is correct', function () {
       controller.reopen({
-        serviceActiveComponents: [{}]
+        serviceActiveComponents: [
+          {}
+        ]
       });
+      sinon.stub(batchUtils, 'restartHostComponents', Em.K);
+
       var popup = controller.doRestartAllComponents();
       expect(App.showConfirmationPopup.calledOnce).to.be.true;
-      /*popup.onPrimary();
-       expect(controller.restartHostComponents.calledWith([{}])).to.be.true;*/
+      popup.onPrimary();
+      expect(batchUtils.restartHostComponents.calledWith(
+        [
+          {}
+        ])
+      ).to.be.true;
+      batchUtils.restartHostComponents.restore();
+
     });
   });
 
@@ -1143,7 +1465,7 @@ describe('App.MainHostDetailsController', function () {
       expect(controller.getHostComponentsInfo()).to.eql(result);
     });
     it('content.hostComponents is empty', function () {
-      controller.set('content', {hostComponents :[]});
+      controller.set('content', {hostComponents: []});
       expect(controller.getHostComponentsInfo()).to.eql(result);
     });
     it('content.hostComponents has ZOOKEEPER_SERVER', function () {
@@ -1156,11 +1478,13 @@ describe('App.MainHostDetailsController', function () {
       expect(controller.getHostComponentsInfo().zkServerInstalled).to.be.true;
     });
     it('content.hostComponents has last component', function () {
-      sinon.stub(App.HostComponent, 'find', function() {
-        return [{
-          id: 'TASKTRACKER_host1',
-          componentName: 'TASKTRACKER'
-        }];
+      sinon.stub(App.HostComponent, 'find', function () {
+        return [
+          {
+            id: 'TASKTRACKER_host1',
+            componentName: 'TASKTRACKER'
+          }
+        ];
       });
       controller.set('content', {hostComponents: [Em.Object.create({
         componentName: 'TASKTRACKER',
@@ -1172,13 +1496,15 @@ describe('App.MainHostDetailsController', function () {
       App.HostComponent.find.restore();
     });
     it('content.hostComponents has master non-deletable component', function () {
-      sinon.stub(App.HostComponent, 'find', function() {
-        return [{
-          id: 'TASKTRACKER_host1',
-          componentName: 'TASKTRACKER'
-        }];
+      sinon.stub(App.HostComponent, 'find', function () {
+        return [
+          {
+            id: 'TASKTRACKER_host1',
+            componentName: 'TASKTRACKER'
+          }
+        ];
       });
-      controller.set('content', {hostComponents :[Em.Object.create({
+      controller.set('content', {hostComponents: [Em.Object.create({
         componentName: 'TASKTRACKER',
         workStatus: 'INIT',
         isDeletable: false,
@@ -1190,11 +1516,13 @@ describe('App.MainHostDetailsController', function () {
       App.HostComponent.find.restore();
     });
     it('content.hostComponents has running component', function () {
-      sinon.stub(App.HostComponent, 'find', function() {
-        return [{
-          id: 'TASKTRACKER_host1',
-          componentName: 'TASKTRACKER'
-        }];
+      sinon.stub(App.HostComponent, 'find', function () {
+        return [
+          {
+            id: 'TASKTRACKER_host1',
+            componentName: 'TASKTRACKER'
+          }
+        ];
       });
       controller.set('content', {hostComponents: [Em.Object.create({
         componentName: 'TASKTRACKER',
@@ -1238,11 +1566,13 @@ describe('App.MainHostDetailsController', function () {
       App.HostComponent.find.restore();
     });
     it('content.hostComponents has non-deletable component', function () {
-      sinon.stub(App.HostComponent, 'find', function() {
-        return [{
-          id: 'TASKTRACKER_host1',
-          componentName: 'TASKTRACKER'
-        }];
+      sinon.stub(App.HostComponent, 'find', function () {
+        return [
+          {
+            id: 'TASKTRACKER_host1',
+            componentName: 'TASKTRACKER'
+          }
+        ];
       });
       controller.set('content', {hostComponents: [Em.Object.create({
         componentName: 'TASKTRACKER',
@@ -1254,11 +1584,13 @@ describe('App.MainHostDetailsController', function () {
       App.HostComponent.find.restore();
     });
     it('content.hostComponents has component with UNKNOWN state', function () {
-      sinon.stub(App.HostComponent, 'find', function() {
-        return [{
-          id: 'TASKTRACKER_host1',
-          componentName: 'TASKTRACKER'
-        }];
+      sinon.stub(App.HostComponent, 'find', function () {
+        return [
+          {
+            id: 'TASKTRACKER_host1',
+            componentName: 'TASKTRACKER'
+          }
+        ];
       });
       controller.set('content', {hostComponents: [Em.Object.create({
         componentName: 'TASKTRACKER',
@@ -1274,18 +1606,18 @@ describe('App.MainHostDetailsController', function () {
   describe('#validateAndDeleteHost()', function () {
 
     beforeEach(function () {
-      sinon.stub(App, "showConfirmationPopup", Em.K);
-      sinon.stub(controller, "getHostComponentsInfo", function(){
+      sinon.spy(App, "showConfirmationPopup");
+      sinon.stub(controller, "getHostComponentsInfo", function () {
         return this.get('mockHostComponentsInfo');
       });
       sinon.stub(controller, "raiseDeleteComponentsError", Em.K);
-      sinon.stub(controller, "_doDeleteHost", Em.K);
+      sinon.stub(controller, "confirmDeleteHost", Em.K);
     });
     afterEach(function () {
       App.showConfirmationPopup.restore();
       controller.getHostComponentsInfo.restore();
       controller.raiseDeleteComponentsError.restore();
-      controller._doDeleteHost.restore();
+      controller.confirmDeleteHost.restore();
     });
 
     it('App.supports.deleteHost = false', function () {
@@ -1294,17 +1626,25 @@ describe('App.MainHostDetailsController', function () {
       App.supports.deleteHost = true;
     });
     it('masterComponents exist', function () {
-      controller.set('mockHostComponentsInfo', {masterComponents: [{}]});
+      controller.set('mockHostComponentsInfo', {masterComponents: [
+        {}
+      ]});
       controller.validateAndDeleteHost();
-      expect(controller.raiseDeleteComponentsError.calledWith([{}], 'masterList')).to.be.true;
+      expect(controller.raiseDeleteComponentsError.calledWith([
+        {}
+      ], 'masterList')).to.be.true;
     });
     it('nonDeletableComponents exist', function () {
       controller.set('mockHostComponentsInfo', {
         masterComponents: [],
-        nonDeletableComponents: [{}]
+        nonDeletableComponents: [
+          {}
+        ]
       });
       controller.validateAndDeleteHost();
-      expect(controller.raiseDeleteComponentsError.calledWith([{}], 'nonDeletableList')).to.be.true;
+      expect(controller.raiseDeleteComponentsError.calledWith([
+        {}
+      ], 'nonDeletableList')).to.be.true;
     });
     it('runningComponents exist', function () {
       controller.set('mockHostComponentsInfo', {
@@ -1328,8 +1668,8 @@ describe('App.MainHostDetailsController', function () {
       });
       var popup = controller.validateAndDeleteHost();
       expect(App.showConfirmationPopup.calledOnce).to.be.true;
-      /* popup.onPrimary();
-       expect(controller._doDeleteHost.calledWith([], [])).to.be.true;*/
+      popup.onPrimary();
+      expect(controller.confirmDeleteHost.calledWith([], [])).to.be.true;
     });
     it('zkServerInstalled = false', function () {
       controller.set('mockHostComponentsInfo', {
@@ -1342,7 +1682,7 @@ describe('App.MainHostDetailsController', function () {
         zkServerInstalled: false
       });
       controller.validateAndDeleteHost();
-      expect(controller._doDeleteHost.calledWith([], [])).to.be.true;
+      expect(controller.confirmDeleteHost.calledWith([], [])).to.be.true;
     });
   });
 
@@ -1361,18 +1701,17 @@ describe('App.MainHostDetailsController', function () {
     });
   });
 
-  describe('#_doDeleteHost()', function () {
-
-    beforeEach(function () {
-      sinon.stub(App.ModalPopup, "show", Em.K);
-    });
-    afterEach(function () {
-      App.ModalPopup.show.restore();
-    });
-
+  describe('#confirmDeleteHost()', function () {
     it('Popup should be displayed', function () {
-      controller._doDeleteHost([], []);
+      sinon.spy(App.ModalPopup, "show");
+      sinon.stub(controller, 'doDeleteHost');
+
+      var popup = controller.confirmDeleteHost([], []);
       expect(App.ModalPopup.show.calledOnce).to.be.true;
+      popup.onPrimary();
+      expect(controller.doDeleteHost.calledOnce).to.be.true;
+      App.ModalPopup.show.restore();
+      controller.doDeleteHost.restore();
     });
   });
 
@@ -1388,26 +1727,48 @@ describe('App.MainHostDetailsController', function () {
     });
 
     it('popup should be displayed', function () {
-      controller.set('content', {componentsWithStaleConfigs :[{}]});
+      controller.set('content', {componentsWithStaleConfigs: [
+        {}
+      ]});
       var popup = controller.restartAllStaleConfigComponents();
       expect(App.showConfirmationPopup.calledOnce).to.be.true;
       popup.onPrimary();
-      expect(batchUtils.restartHostComponents.calledWith([{}])).to.be.true;
+      expect(batchUtils.restartHostComponents.calledWith([
+        {}
+      ])).to.be.true;
     });
   });
 
   describe('#moveComponent()', function () {
-
-    beforeEach(function () {
+    it('popup should be displayed', function () {
+      var mock = {
+        saveComponentToReassign: Em.K,
+        getSecurityStatus: Em.K,
+        setCurrentStep: Em.K
+      };
       sinon.spy(App, "showConfirmationPopup");
-    });
-    afterEach(function () {
-      App.showConfirmationPopup.restore();
-    });
+      sinon.stub(App.router, 'get').withArgs('reassignMasterController').returns(mock);
+      sinon.stub(App.router, 'transitionTo', Em.K);
+      sinon.spy(mock, "saveComponentToReassign");
+      sinon.spy(mock, "getSecurityStatus");
+      sinon.spy(mock, "setCurrentStep");
 
-    it('popup should be displayed', function () {
-      var popup = controller.moveComponent();
+      var popup = controller.moveComponent({context: {}});
       expect(App.showConfirmationPopup.calledOnce).to.be.true;
+      popup.onPrimary();
+      expect(App.router.get.calledWith('reassignMasterController')).to.be.true;
+      expect(mock.saveComponentToReassign.calledWith({})).to.be.true;
+      expect(mock.getSecurityStatus.calledOnce).to.be.true;
+      expect(mock.setCurrentStep.calledWith('1')).to.be.true;
+      expect(App.router.transitionTo.calledWith('reassign')).to.be.true;
+
+      App.showConfirmationPopup.restore();
+      App.router.get.restore();
+      App.router.transitionTo.restore();
+      mock.saveComponentToReassign.restore();
+      mock.getSecurityStatus.restore();
+      mock.setCurrentStep.restore();
+
     });
   });
 
@@ -1450,19 +1811,19 @@ describe('App.MainHostDetailsController', function () {
   describe('#getTotalComponent()', function () {
 
     beforeEach(function () {
-      sinon.stub(App.SlaveComponent, 'find', function() {
+      sinon.stub(App.SlaveComponent, 'find', function () {
         return Em.Object.create({
           componentName: "SLAVE",
           totalCount: 1
         });
       });
-      sinon.stub(App.ClientComponent, 'find', function() {
+      sinon.stub(App.ClientComponent, 'find', function () {
         return Em.Object.create({
           componentName: "CLIENT",
           totalCount: 1
         });
       });
-      sinon.stub(App.HostComponent, 'find', function() {
+      sinon.stub(App.HostComponent, 'find', function () {
         return [Em.Object.create({
           componentName: "MASTER",
           totalCount: 1
@@ -1523,7 +1884,7 @@ describe('App.MainHostDetailsController', function () {
     });
   });
 
-  describe('#executeCustomCommands', function() {
+  describe('#executeCustomCommands', function () {
     beforeEach(function () {
       sinon.spy(App, "showConfirmationPopup");
     });
@@ -1539,4 +1900,405 @@ describe('App.MainHostDetailsController', function () {
     });
   });
 
+  describe('#_doDeleteHostComponent()', function () {
+    it('single component', function () {
+      controller.set('content.hostName', 'host1');
+      var component = Em.Object.create({componentName: 'COMP'});
+      controller._doDeleteHostComponent(component);
+      expect(App.ajax.send.getCall(0).args[0].name).to.be.equal('common.delete.host_component');
+      expect(App.ajax.send.getCall(0).args[0].data).to.be.eql({
+        componentName: 'COMP',
+        hostName: 'host1'
+      });
+    });
+    it('all components', function () {
+      controller.set('content.hostName', 'host1');
+      controller._doDeleteHostComponent(null);
+      expect(App.ajax.send.getCall(0).args[0].name).to.be.equal('common.delete.host');
+      expect(App.ajax.send.getCall(0).args[0].data).to.be.eql({
+        componentName: '',
+        hostName: 'host1'
+      });
+    });
+  });
+
+  describe('#_doDeleteHostComponentSuccessCallback()', function () {
+    it('ZOOKEEPER_SERVER component', function () {
+      var data = {
+        componentName: 'ZOOKEEPER_SERVER'
+      }
+      sinon.stub(controller, 'loadConfigs', Em.K);
+      controller._doDeleteHostComponentSuccessCallback({}, {}, data);
+      expect(controller.get('_deletedHostComponentResult')).to.be.null;
+      expect(controller.get('fromDeleteZkServer')).to.be.true;
+      expect(controller.loadConfigs.calledOnce).to.be.true;
+      controller.loadConfigs.restore();
+    });
+    it('Not ZOOKEEPER_SERVER component', function () {
+      var data = {
+        componentName: 'COMP'
+      }
+      controller.set('fromDeleteZkServer', false);
+      controller._doDeleteHostComponentSuccessCallback({}, {}, data);
+      expect(controller.get('_deletedHostComponentResult')).to.be.null;
+      expect(controller.get('fromDeleteZkServer')).to.be.false;
+    });
+  });
+
+  describe('#upgradeComponentSuccessCallback()', function () {
+    beforeEach(function () {
+      sinon.stub(controller, 'showBackgroundOperationsPopup', Em.K);
+      sinon.stub(controller, 'mimicWorkStatusChange', Em.K);
+    });
+    afterEach(function () {
+      controller.mimicWorkStatusChange.restore();
+      controller.showBackgroundOperationsPopup.restore();
+    });
+    it('testMode is true', function () {
+      App.set('testMode', true);
+
+      controller.upgradeComponentSuccessCallback({}, {}, {component: "COMP"});
+      expect(controller.mimicWorkStatusChange.calledWith("COMP", App.HostComponentStatus.starting, App.HostComponentStatus.started)).to.be.true;
+      expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
+    });
+    it('testMode is false', function () {
+      App.set('testMode', false);
+
+      controller.upgradeComponentSuccessCallback({}, {}, {component: "COMP"});
+      expect(controller.mimicWorkStatusChange.called).to.be.false;
+      expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
+    });
+  });
+
+  describe('#refreshComponentConfigsSuccessCallback()', function () {
+    it('call showBackgroundOperationsPopup', function () {
+      sinon.stub(controller, 'showBackgroundOperationsPopup', Em.K);
+      controller.refreshComponentConfigsSuccessCallback();
+      expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
+      controller.showBackgroundOperationsPopup.restore();
+    });
+  });
+
+  describe('#checkZkConfigs()', function () {
+    beforeEach(function () {
+      sinon.stub(controller, 'removeObserver');
+      sinon.stub(controller, 'loadConfigs');
+    });
+    afterEach(function () {
+      controller.loadConfigs.restore();
+      controller.removeObserver.restore();
+      App.router.get.restore();
+    });
+    it('No operations of ZOOKEEPER_SERVER', function () {
+      sinon.stub(App.router, 'get').withArgs('backgroundOperationsController.services').returns([]);
+      controller.checkZkConfigs();
+      expect(controller.removeObserver.called).to.be.false;
+      expect(controller.loadConfigs.called).to.be.false;
+    });
+    it('Operation of ZOOKEEPER_SERVER running', function () {
+      sinon.stub(App.router, 'get').withArgs('backgroundOperationsController.services').returns([Em.Object.create({
+        id: 1,
+        isRunning: true
+      })]);
+      controller.set('zkRequestId', 1);
+      controller.checkZkConfigs();
+      expect(controller.removeObserver.called).to.be.false;
+      expect(controller.loadConfigs.called).to.be.false;
+    });
+    it('Operation of ZOOKEEPER_SERVER finished', function () {
+      sinon.stub(App.router, 'get').withArgs('backgroundOperationsController.services').returns([Em.Object.create({
+        id: 1
+      })]);
+      var clock = sinon.useFakeTimers();
+      controller.set('zkRequestId', 1);
+      controller.checkZkConfigs();
+      expect(controller.removeObserver.calledWith('App.router.backgroundOperationsController.serviceTimestamp', controller, controller.checkZkConfigs)).to.be.true;
+      clock.tick(App.get('componentsUpdateInterval'));
+      expect(controller.loadConfigs.calledOnce).to.be.true;
+      clock.restore();
+    });
+  });
+
+  describe('#_doDeleteHostComponentErrorCallback()', function () {
+    it('call showBackgroundOperationsPopup', function () {
+      controller._doDeleteHostComponentErrorCallback({}, 'textStatus', {}, {url: 'url'});
+      expect(controller.get('_deletedHostComponentResult')).to.be.eql({xhr: {}, url: 'url', method: 'DELETE'});
+    });
+  });
+
+  describe('#installComponentSuccessCallback()', function () {
+    beforeEach(function () {
+      sinon.stub(controller, 'showBackgroundOperationsPopup', Em.K);
+      sinon.stub(controller, 'mimicWorkStatusChange', Em.K);
+    });
+    afterEach(function () {
+      controller.mimicWorkStatusChange.restore();
+      controller.showBackgroundOperationsPopup.restore();
+    });
+    it('testMode is true', function () {
+      App.set('testMode', true);
+
+      controller.installComponentSuccessCallback({}, {}, {component: "COMP"});
+      expect(controller.mimicWorkStatusChange.calledWith("COMP", App.HostComponentStatus.installing, App.HostComponentStatus.stopped)).to.be.true;
+      expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
+    });
+    it('testMode is false', function () {
+      App.set('testMode', false);
+
+      controller.installComponentSuccessCallback({}, {}, {component: "COMP"});
+      expect(controller.mimicWorkStatusChange.called).to.be.false;
+      expect(controller.showBackgroundOperationsPopup.calledOnce).to.be.true;
+    });
+  });
+
+  describe('#showHbaseActiveWarning()', function () {
+    it('popup should be displayed', function () {
+      sinon.spy(App.ModalPopup, "show");
+      var popup = controller.showHbaseActiveWarning(Em.Object.create({service: {}}));
+      expect(App.ModalPopup.show.calledOnce).to.be.true;
+      App.ModalPopup.show.restore();
+    });
+  });
+
+  describe('#updateHost()', function () {
+    it('popup should be displayed', function () {
+      sinon.stub(batchUtils, "infoPassiveState", Em.K);
+      controller.updateHost({}, {}, {passive_state: 'state'});
+      expect(controller.get('content.passiveState')).to.equal('state');
+      expect(batchUtils.infoPassiveState.calledWith('state')).to.be.true;
+      batchUtils.infoPassiveState.restore();
+    });
+  });
+
+  describe('#updateComponentPassiveState()', function () {
+    it('popup should be displayed', function () {
+      controller.set('content.hostName', 'host1');
+      var component = Em.Object.create({
+        componentName: 'COMP1'
+      });
+      controller.updateComponentPassiveState(component, 'state', 'message');
+      expect(App.ajax.send.getCall(0).args[0].data).to.be.eql({
+        "hostName": "host1",
+        "componentName": "COMP1",
+        "component": component,
+        "passive_state": "state",
+        "context": "message"
+      });
+    });
+  });
+
+  describe('#updateHostComponent()', function () {
+    it('popup should be displayed', function () {
+      sinon.stub(batchUtils, "infoPassiveState", Em.K);
+      var params = {
+        component: Em.Object.create(),
+        passive_state: 'state'
+      }
+      controller.updateHostComponent({}, {}, params);
+      expect(params.component.get('passiveState')).to.equal('state');
+      expect(batchUtils.infoPassiveState.calledWith('state')).to.be.true;
+      batchUtils.infoPassiveState.restore();
+    });
+  });
+
+  describe('#toggleMaintenanceMode()', function () {
+    beforeEach(function () {
+      sinon.spy(App, "showConfirmationPopup");
+      sinon.stub(controller, 'updateComponentPassiveState');
+    });
+    afterEach(function () {
+      App.showConfirmationPopup.restore();
+      controller.updateComponentPassiveState.restore();
+    });
+    it('passive state is ON', function () {
+      var event = {context: Em.Object.create({
+        passiveState: 'ON'
+      })};
+      var popup = controller.toggleMaintenanceMode(event);
+      expect(App.showConfirmationPopup.calledOnce).to.be.true;
+      popup.onPrimary();
+      expect(controller.updateComponentPassiveState.calledWith(Em.Object.create({
+        passiveState: 'ON'
+      }), 'OFF')).to.be.true;
+    });
+    it('passive state is OFF', function () {
+      var event = {context: Em.Object.create({
+        passiveState: 'OFF'
+      })};
+      var popup = controller.toggleMaintenanceMode(event);
+      expect(App.showConfirmationPopup.calledOnce).to.be.true;
+      popup.onPrimary();
+      expect(controller.updateComponentPassiveState.calledWith(Em.Object.create({
+        passiveState: 'OFF'
+      }), 'ON')).to.be.true;
+    });
+  });
+
+  describe('#reinstallClients()', function () {
+    beforeEach(function () {
+      sinon.stub(controller, 'sendComponentCommand');
+    });
+    afterEach(function () {
+      controller.sendComponentCommand.restore();
+    });
+    it('No clients to install', function () {
+      var event = {context: [
+        Em.Object.create({
+          workStatus: 'INSTALLED'
+        })
+      ]};
+      controller.reinstallClients(event);
+      expect(controller.sendComponentCommand.called).to.be.false;
+    });
+    it('No clients to install', function () {
+      var event = {context: [
+        Em.Object.create({
+          workStatus: 'INSTALLED'
+        }),
+        Em.Object.create({
+          workStatus: 'INIT'
+        }),
+        Em.Object.create({
+          workStatus: 'INSTALL_FAILED'
+        })
+      ]};
+      controller.reinstallClients(event);
+      expect(controller.sendComponentCommand.calledWith([
+        Em.Object.create({
+          workStatus: 'INIT'
+        }),
+        Em.Object.create({
+          workStatus: 'INSTALL_FAILED'
+        })], Em.I18n.t('host.host.details.installClients'), 'INSTALLED')).to.be.true;
+    });
+  });
+
+  describe("#executeCustomCommandSuccessCallback()", function () {
+    it("BO popup should be shown", function () {
+      var mock = {
+        showPopup: Em.K
+      };
+      sinon.stub(App.router, 'get').returns(mock);
+      sinon.spy(mock, 'showPopup');
+      var data = {
+        Requests: {
+          id: 1
+        }
+      };
+      controller.executeCustomCommandSuccessCallback(data, {}, {});
+
+      expect(App.router.get.calledWith('backgroundOperationsController')).to.be.true;
+      expect(mock.showPopup.calledOnce).to.be.true;
+      App.router.get.restore();
+      mock.showPopup.restore();
+    });
+  });
+
+  describe("#executeCustomCommandErrorCallback()", function () {
+    beforeEach(function () {
+      sinon.stub($, 'parseJSON');
+      sinon.spy(App, 'showAlertPopup');
+    });
+    afterEach(function () {
+      App.showAlertPopup.restore();
+      $.parseJSON.restore();
+    });
+    it("data empty", function () {
+      controller.executeCustomCommandErrorCallback(null);
+
+      expect(App.showAlertPopup.calledWith(Em.I18n.t('services.service.actions.run.executeCustomCommand.error'), Em.I18n.t('services.service.actions.run.executeCustomCommand.error'))).to.be.true;
+      expect($.parseJSON.called).to.be.false;
+    });
+    it("responseText empty", function () {
+      var data = {
+        responseText: null
+      };
+      controller.executeCustomCommandErrorCallback(data);
+
+      expect(App.showAlertPopup.calledWith(Em.I18n.t('services.service.actions.run.executeCustomCommand.error'), Em.I18n.t('services.service.actions.run.executeCustomCommand.error'))).to.be.true;
+      expect($.parseJSON.called).to.be.false;
+    });
+    it("data empty", function () {
+      var data = {
+        responseText: "test"
+      };
+      controller.executeCustomCommandErrorCallback(data);
+      expect(App.showAlertPopup.calledWith(Em.I18n.t('services.service.actions.run.executeCustomCommand.error'), Em.I18n.t('services.service.actions.run.executeCustomCommand.error'))).to.be.true;
+      expect($.parseJSON.calledWith('test')).to.be.true;
+    });
+  });
+
+  describe("#doDeleteHost()", function() {
+    beforeEach(function(){
+      controller.set('fromDeleteHost', false);
+      controller.set('content.hostName', 'host1');
+      sinon.stub(controller, '_doDeleteHostComponent', function (comp, callback) {
+        callback();
+      });
+    });
+    afterEach(function(){
+      controller._doDeleteHostComponent.restore();
+    });
+    it("Host has no components", function() {
+      controller.set('content.hostComponents', Em.A([]));
+      controller.doDeleteHost(Em.K);
+      expect(controller.get('fromDeleteHost')).to.be.true;
+      expect(App.ajax.send.getCall(0).args[0].data.hostName).to.be.equal('host1');
+      expect(App.ajax.send.getCall(0).args[0].name).to.be.equal('common.delete.host');
+    });
+    it("Host has components", function() {
+      controller.set('content.hostComponents', Em.A([Em.Object.create({
+        componentName: 'COMP1'
+      })]));
+      controller.doDeleteHost(Em.K);
+      expect(controller._doDeleteHostComponent.calledWith(Em.Object.create({
+        componentName: 'COMP1'
+      }))).to.be.true;
+      expect(controller.get('fromDeleteHost')).to.be.true;
+      expect(App.ajax.send.getCall(0).args[0].data.hostName).to.be.equal('host1');
+      expect(App.ajax.send.getCall(0).args[0].name).to.be.equal('common.delete.host');
+    });
+  });
+
+  describe("#deleteHostSuccessCallback", function() {
+    it("call updateHost", function() {
+      var mock = {
+        updateHost: function(callback){
+          callback();
+        },
+        getAllHostNames: Em.K
+      };
+      sinon.stub(App.router, 'get').withArgs('updateController').returns(mock).withArgs('clusterController').returns(mock);
+      sinon.spy(mock, 'updateHost');
+      sinon.spy(mock, 'getAllHostNames');
+      sinon.stub(controller, 'loadConfigs', Em.K);
+      sinon.stub(App.router, 'transitionTo', Em.K);
+
+      controller.deleteHostSuccessCallback();
+      expect(App.router.get.calledWith('updateController')).to.be.true;
+      expect(mock.updateHost.calledOnce).to.be.true;
+      expect(controller.loadConfigs.calledOnce).to.be.true;
+      expect(App.router.transitionTo.calledWith('hosts.index')).to.be.true;
+      expect(App.router.get.calledWith('clusterController')).to.be.true;
+      expect(mock.getAllHostNames.calledOnce).to.be.true;
+
+      App.router.get.restore();
+      mock.updateHost.restore();
+      mock.getAllHostNames.restore();
+      controller.loadConfigs.restore();
+      App.router.transitionTo.restore();
+    });
+  });
+
+  describe("#deleteHostErrorCallback", function() {
+    it("call defaultErrorHandler", function() {
+      sinon.stub(controller, 'loadConfigs', Em.K);
+      sinon.stub(App.ajax, 'defaultErrorHandler', Em.K);
+      controller.deleteHostErrorCallback({status: 'status', statusText: "statusText"}, 'textStatus', 'errorThrown', {url: 'url'});
+      expect(controller.loadConfigs.calledOnce).to.be.true;
+      expect(App.ajax.defaultErrorHandler.calledOnce).to.be.true;
+      App.ajax.defaultErrorHandler.restore();
+      controller.loadConfigs.restore();
+    });
+  });
 });

+ 30 - 0
ambari-web/test/models/service_config_test.js

@@ -616,3 +616,33 @@ describe('App.ServiceConfigProperty', function () {
   });
 
 });
+
+describe('initialValue', function () {
+
+  var tests = [
+    {
+      message: 'kafka.ganglia.metrics.host property should have the value of ganglia hostname when ganglia is selected',
+      localDB: {masterComponentHosts: [
+        {component: 'GANGLIA_SERVER', hostName: 'c6401'}
+      ]},
+      expected: 'c6401'
+    },
+    {
+      message: 'kafka.ganglia.metrics.host property should have the value "localhost" when ganglia is not selected',
+      localDB: {masterComponentHosts: [
+        {component: 'NAMENODE', hostName: 'c6401'}
+      ]},
+      expected: 'localhost'
+    }
+  ];
+  var serviceConfigProperty;
+  beforeEach(function () {
+    serviceConfigProperty = App.ServiceConfigProperty.create({name: 'kafka.ganglia.metrics.host', value: 'localhost'});
+  });
+  tests.forEach(function(test){
+    it(test.message, function () {
+      serviceConfigProperty.initialValue(test.localDB);
+      expect(serviceConfigProperty.get('value')).to.equal(test.expected);
+    });
+  });
+});