This is an automated email from the ASF dual-hosted git repository.

ababiichuk pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 3c4f830  AMBARI-23052 Extend service actions dropdowns with 
namespace-specific items. (ababiichuk)
3c4f830 is described below

commit 3c4f83048bd35e5b11838dfbdc11eb765f208cfc
Author: aBabiichuk <ababiic...@hortonworks.com>
AuthorDate: Fri Feb 23 19:49:13 2018 +0200

    AMBARI-23052 Extend service actions dropdowns with namespace-specific 
items. (ababiichuk)
---
 ambari-web/app/app.js                              |   2 +-
 ambari-web/app/controllers/main/service/item.js    | 281 +++++++++++++------
 ambari-web/app/messages.js                         |   6 +
 ambari-web/app/models/host_component.js            |  87 +++++-
 ambari-web/app/models/service.js                   |   6 +
 ambari-web/app/models/service/hdfs.js              |  25 +-
 .../app/templates/main/service/info/summary.hbs    |   2 +-
 ambari-web/app/templates/main/service/item.hbs     |  73 ++---
 ambari-web/app/utils/ajax/ajax.js                  |  26 ++
 ambari-web/app/utils/batch_scheduled_requests.js   |  45 +++-
 ambari-web/app/views/main/service/info/summary.js  |  23 +-
 ambari-web/app/views/main/service/item.js          | 298 +++++++++++----------
 .../test/controllers/main/service/item_test.js     |  87 +++---
 ambari-web/test/views/main/service/item_test.js    |  41 ++-
 14 files changed, 641 insertions(+), 361 deletions(-)

diff --git a/ambari-web/app/app.js b/ambari-web/app/app.js
index d3d5bf9..2334cb2 100644
--- a/ambari-web/app/app.js
+++ b/ambari-web/app/app.js
@@ -243,7 +243,7 @@ module.exports = Em.Application.create({
   }.property('router.clusterController.dataLoadList.services', 
'router.clusterController.isServiceContentFullyLoaded'),
 
   hasNameNodeFederation: function () {
-    return App.HostComponent.find().filterProperty('componentName', 
'NAMENODE').length > 2;
+    return 
App.HDFSService.find().objectAt(0).get('masterComponentGroups.length') > 1;
   }.property('router.clusterController.dataLoadList.services', 
'router.clusterController.isServiceContentFullyLoaded'),
 
   /**
diff --git a/ambari-web/app/controllers/main/service/item.js 
b/ambari-web/app/controllers/main/service/item.js
index 5bd160f..a4a8ca1 100644
--- a/ambari-web/app/controllers/main/service/item.js
+++ b/ambari-web/app/controllers/main/service/item.js
@@ -253,14 +253,15 @@ App.MainServiceItemController = 
Em.Controller.extend(App.SupportClientConfigsDow
   startStopPopupSuccessCallback: function (data, ajaxOptions, params) {
     if (data && data.Requests) {
       params.query.set('status', 'SUCCESS');
-      var config = 
this.get('callBackConfig')[(JSON.parse(ajaxOptions.data)).Body.ServiceInfo.state];
-      var self = this;
       if (App.get('testMode')) {
-        self.set('content.workStatus', App.Service.Health[config.f]);
-        self.get('content.hostComponents').setEach('workStatus', 
App.HostComponentStatus[config.f]);
-        setTimeout(function () {
-          self.set('content.workStatus', App.Service.Health[config.c2]);
-          self.get('content.hostComponents').setEach('workStatus', 
App.HostComponentStatus[config.hs]);
+        const requestData = JSON.parse(ajaxOptions.data),
+          state = requestData.Body.ServiceInfo.state || 
requestData.Body.HostRoles.state,
+          config = this.get('callBackConfig')[state];
+        this.set('content.workStatus', App.Service.Health[config.f]);
+        this.get('content.hostComponents').setEach('workStatus', 
App.HostComponentStatus[config.f]);
+        setTimeout(() => {
+          this.set('content.workStatus', App.Service.Health[config.c2]);
+          this.get('content.hostComponents').setEach('workStatus', 
App.HostComponentStatus[config.hs]);
         }, App.get('testModeDelayForActions'));
       }
       // load data (if we need to show this background operations popup) from 
persist
@@ -279,41 +280,83 @@ App.MainServiceItemController = 
Em.Controller.extend(App.SupportClientConfigsDow
   },
   /**
    * Confirmation popup for start/stop services
-   * @param event
    * @param serviceHealth - 'STARTED' or 'INSTALLED'
    */
-  startStopPopup: function(event, serviceHealth) {
-    if ($(event.target).hasClass('disabled') || 
$(event.target.parentElement).hasClass('disabled')) {
-      return;
-    }
-    var self = this;
-    var serviceDisplayName = this.get('content.displayName');
-    var isMaintenanceOFF = this.get('content.passiveState') === 'OFF';
-
-    var msg = isMaintenanceOFF && serviceHealth == 'INSTALLED'? 
Em.I18n.t('services.service.stop.warningMsg.turnOnMM').format(serviceDisplayName)
 : null;
-    msg = self.addAdditionalWarningMessage(serviceHealth, msg, 
serviceDisplayName);
-
-    var bodyMessage = Em.Object.create({
-      putInMaintenance: (serviceHealth == 'INSTALLED' && isMaintenanceOFF) || 
(serviceHealth == 'STARTED' && !isMaintenanceOFF),
-      turnOnMmMsg: serviceHealth == 'INSTALLED' ? 
Em.I18n.t('passiveState.turnOnFor').format(serviceDisplayName) : 
Em.I18n.t('passiveState.turnOffFor').format(serviceDisplayName),
-      confirmMsg: serviceHealth == 'INSTALLED'? 
Em.I18n.t('services.service.stop.confirmMsg').format(serviceDisplayName) : 
Em.I18n.t('services.service.start.confirmMsg').format(serviceDisplayName),
-      confirmButton: serviceHealth == 'INSTALLED'? 
Em.I18n.t('services.service.stop.confirmButton') : 
Em.I18n.t('services.service.start.confirmButton'),
-      additionalWarningMsg:  msg
+  startStopPopup: function (serviceHealth) {
+    const serviceDisplayName = this.get('content.displayName'),
+      isMaintenanceOFF = this.get('content.passiveState') === 'OFF';
+
+    let msg = isMaintenanceOFF && serviceHealth === 'INSTALLED' ?
+      
Em.I18n.t('services.service.stop.warningMsg.turnOnMM').format(serviceDisplayName)
 : null;
+    msg = this.addAdditionalWarningMessage(serviceHealth, msg, 
serviceDisplayName);
+
+    const bodyMessage = Em.Object.create({
+      putInMaintenance: (serviceHealth === 'INSTALLED' && isMaintenanceOFF) ||
+        (serviceHealth === 'STARTED' && !isMaintenanceOFF),
+      turnOnMmMsg: serviceHealth === 'INSTALLED' ?
+        Em.I18n.t('passiveState.turnOnFor').format(serviceDisplayName) :
+        Em.I18n.t('passiveState.turnOffFor').format(serviceDisplayName),
+      confirmMsg: serviceHealth === 'INSTALLED'
+        ? 
Em.I18n.t('services.service.stop.confirmMsg').format(serviceDisplayName) :
+        
Em.I18n.t('services.service.start.confirmMsg').format(serviceDisplayName),
+      confirmButton: serviceHealth === 'INSTALLED' ?
+        Em.I18n.t('services.service.stop.confirmButton') : 
Em.I18n.t('services.service.start.confirmButton'),
+      additionalWarningMsg: msg
     });
 
     // check HDFS NameNode checkpoint before stop service
-    if (this.get('content.serviceName') == 'HDFS' && serviceHealth == 
'INSTALLED' &&
-      this.get('content.hostComponents').filterProperty('componentName', 
'NAMENODE').someProperty('workStatus', App.HostComponentStatus.started)) {
+    if (serviceHealth === 'INSTALLED' && this.hasStartedNameNode()) {
       this.checkNnLastCheckpointTime(function () {
-        return App.showConfirmationFeedBackPopup(function(query, 
runMmOperation) {
-          self.set('isPending', true);
-          self.startStopWithMmode(serviceHealth, query, runMmOperation);
+        return App.showConfirmationFeedBackPopup((query, runMmOperation) => {
+          this.set('isPending', true);
+          this.startStopWithMmode(serviceHealth, query, runMmOperation);
         }, bodyMessage);
       });
     } else {
-      return App.showConfirmationFeedBackPopup(function(query, runMmOperation) 
{
-        self.set('isPending', true);
-        self.startStopWithMmode(serviceHealth, query, runMmOperation);
+      return App.showConfirmationFeedBackPopup((query, runMmOperation) => {
+        this.set('isPending', true);
+        this.startStopWithMmode(serviceHealth, query, runMmOperation);
+      }, bodyMessage);
+    }
+  },
+
+  /**
+   * Confirmation popup for start/stop services
+   * @param context
+   * @param serviceHealth - 'STARTED' or 'INSTALLED'
+   */
+  startStopCertainPopup: function (context, serviceHealth) {
+    const {components, hosts, label} = context,
+      serviceDisplayName = this.get('content.displayName'),
+      isMaintenanceOFF = this.get('content.passiveState') === 'OFF',
+      confirmDisplayName = 
Em.I18n.t('services.service.componentsInNameSpace').format(label);
+    let msg = isMaintenanceOFF && serviceHealth == 'INSTALLED' ?
+      
Em.I18n.t('services.service.stopCertain.warningMsg.turnOnMM').format(serviceDisplayName)
 : null;
+    msg = this.addAdditionalWarningMessage(serviceHealth, msg, 
serviceDisplayName);
+    const bodyMessage = Em.Object.create({
+      putInMaintenance: (serviceHealth === 'INSTALLED' && isMaintenanceOFF) ||
+        (serviceHealth === 'STARTED' && !isMaintenanceOFF),
+      turnOnMmMsg: serviceHealth === 'INSTALLED' ?
+        Em.I18n.t('passiveState.turnOnFor').format(serviceDisplayName) :
+        Em.I18n.t('passiveState.turnOffFor').format(serviceDisplayName),
+      confirmMsg: serviceHealth === 'INSTALLED' ?
+        
Em.I18n.t('services.service.stop.confirmMsg').format(confirmDisplayName) :
+        
Em.I18n.t('services.service.start.confirmMsg').format(confirmDisplayName),
+      confirmButton: serviceHealth === 'INSTALLED' ?
+        Em.I18n.t('services.service.stop.confirmButton') :
+        Em.I18n.t('services.service.start.confirmButton'),
+      additionalWarningMsg: msg
+    });
+    // check HDFS NameNode checkpoint before stop components
+    if (serviceHealth === 'INSTALLED' && this.hasStartedNameNode(label)) {
+      this.checkNnLastCheckpointTime(() => 
App.showConfirmationFeedBackPopup((query, runMmOperation) => {
+        this.set('isPending', true);
+        this.startStopWithMmode(serviceHealth, query, runMmOperation, 
components, hosts, label);
+      }, bodyMessage));
+    } else {
+      return App.showConfirmationFeedBackPopup((query, runMmOperation) => {
+        this.set('isPending', true);
+        this.startStopWithMmode(serviceHealth, query, runMmOperation, 
components, hosts, label);
       }, bodyMessage);
     }
   },
@@ -459,62 +502,89 @@ App.MainServiceItemController = 
Em.Controller.extend(App.SupportClientConfigsDow
     return msg;
   },
 
-  startStopWithMmode: function(serviceHealth, query, runMmOperation) {
-    var self = this;
+  startStopWithMmode: function(serviceHealth, query, runMmOperation, 
components, hosts, label) {
     if (runMmOperation) {
-      if (serviceHealth == "STARTED") {
-        this.startStopPopupPrimary(serviceHealth, query).complete(function() {
-          batchUtils.turnOnOffPassiveRequest("OFF", 
Em.I18n.t('passiveState.turnOff'), 
self.get('content.serviceName').toUpperCase());
+      if (serviceHealth === 'STARTED') {
+        this.startStopPopupPrimary(serviceHealth, query, components, hosts, 
label).complete(() => {
+          batchUtils.turnOnOffPassiveRequest('OFF', 
Em.I18n.t('passiveState.turnOff'), 
this.get('content.serviceName').toUpperCase());
         });
       } else {
-        batchUtils.turnOnOffPassiveRequest("ON", 
Em.I18n.t('passiveState.turnOn'), 
this.get('content.serviceName').toUpperCase()).complete(function() {
-          self.startStopPopupPrimary(serviceHealth, query);
+        batchUtils.turnOnOffPassiveRequest('ON', 
Em.I18n.t('passiveState.turnOn'), 
this.get('content.serviceName').toUpperCase()).complete(() => {
+          this.startStopPopupPrimary(serviceHealth, query, components, hosts, 
label);
         })
       }
     } else {
-      this.startStopPopupPrimary(serviceHealth, query);
+      this.startStopPopupPrimary(serviceHealth, query, components, hosts, 
label);
     }
-
   },
 
-  startStopPopupPrimary: function (serviceHealth, query) {
-    var requestInfo = (serviceHealth == "STARTED")
-        ? 
App.BackgroundOperationsController.CommandContexts.START_SERVICE.format(this.get('content.serviceName'))
-        : 
App.BackgroundOperationsController.CommandContexts.STOP_SERVICE.format(this.get('content.serviceName'));
-
-    var data = {
-      'context': requestInfo,
-      'serviceName': this.get('content.serviceName').toUpperCase(),
-      'ServiceInfo': {
-        'state': serviceHealth
-      },
-      'query': query
-    };
+  startStopPopupPrimary: function (serviceHealth, query, components, hosts, 
label) {
+    const isStart = (serviceHealth === 'STARTED'),
+      serviceName = this.get('content.serviceName');
+    if (components || hosts) {
+      batchUtils.getComponentsFromServer({
+        hosts,
+        components,
+        passiveState: 'OFF',
+        displayParams: ['host_components/HostRoles/component_name']
+      }, data => {
+        const contextKey = isStart ? 'services.service.startAllComponents' : 
'services.service.stopAllComponents',
+          context = Em.I18n.t(contextKey).format(label),
+          requestQuery = data.items.map(host => {
+            const hostName = host.Hosts.host_name,
+              componentNames = 
host.host_components.mapProperty('HostRoles.component_name').join(',');
+            return 
`(HostRoles/component_name.in(${componentNames})&HostRoles/host_name=${hostName})`
+          }).join('|');
+        App.ajax.send({
+          name: 'common.service.host_component.update',
+          sender: this,
+          data: {
+            context,
+            serviceName: serviceName.toUpperCase(),
+            state: serviceHealth,
+            query: requestQuery
+          },
+          showLoadingPopup: true
+        });
+      });
+    } else {
+      const context = isStart
+          ? 
App.BackgroundOperationsController.CommandContexts.START_SERVICE.format(serviceName)
+          : 
App.BackgroundOperationsController.CommandContexts.STOP_SERVICE.format(serviceName),
+        data = {
+          context,
+          serviceName: serviceName.toUpperCase(),
+          ServiceInfo: {
+            state: serviceHealth
+          },
+          query,
+          success: 'startStopPopupSuccessCallback',
+          error: 'startStopPopupErrorCallback'
+        };
 
-    return App.ajax.send({
-      'name': 'common.service.update',
-      'sender': this,
-      'success': 'startStopPopupSuccessCallback',
-      'error': 'startStopPopupErrorCallback',
-      'data': data,
-      'showLoadingPopup': true
-    });
+      return App.ajax.send({
+        name: 'common.service.update',
+        sender: this,
+        success: 'startStopPopupSuccessCallback',
+        error: 'startStopPopupErrorCallback',
+        data: data,
+        showLoadingPopup: true
+      });
+    }
   },
 
   /**
    * On click callback for <code>start service</code> button
-   * @param event
    */
-  startService: function (event) {
-    this.startStopPopup(event, App.HostComponentStatus.started);
+  startService: function () {
+    this.startStopPopup(App.HostComponentStatus.started);
   },
 
   /**
    * On click callback for <code>stop service</code> button
-   * @param event
    */
-  stopService: function (event) {
-    this.startStopPopup(event, App.HostComponentStatus.stopped);
+  stopService: function () {
+    this.startStopPopup(App.HostComponentStatus.stopped);
   },
 
   /**
@@ -836,19 +906,18 @@ App.MainServiceItemController = 
Em.Controller.extend(App.SupportClientConfigsDow
     });
   },
 
-  restartAllHostComponents : function(serviceName) {
-    var serviceDisplayName = this.get('content.displayName');
-    var bodyMessage = Em.Object.create({
-      putInMaintenance: this.get('content.passiveState') === 'OFF',
-      turnOnMmMsg: 
Em.I18n.t('passiveState.turnOnFor').format(serviceDisplayName),
-      confirmMsg: 
Em.I18n.t('services.service.restartAll.confirmMsg').format(serviceDisplayName),
-      confirmButton: Em.I18n.t('services.service.restartAll.confirmButton'),
-      additionalWarningMsg: this.get('content.passiveState') === 'OFF' ? 
Em.I18n.t('services.service.restartAll.warningMsg.turnOnMM').format(serviceDisplayName):
 null
-     });
+  restartAllHostComponents: function (serviceName) {
+    const serviceDisplayName = this.get('content.displayName'),
+      bodyMessage = Em.Object.create({
+        putInMaintenance: this.get('content.passiveState') === 'OFF',
+        turnOnMmMsg: 
Em.I18n.t('passiveState.turnOnFor').format(serviceDisplayName),
+        confirmMsg: 
Em.I18n.t('services.service.restartAll.confirmMsg').format(serviceDisplayName),
+        confirmButton: Em.I18n.t('services.service.restartAll.confirmButton'),
+        additionalWarningMsg: this.get('content.passiveState') === 'OFF' ? 
Em.I18n.t('services.service.restartAll.warningMsg.turnOnMM').format(serviceDisplayName)
 : null
+      });
 
     // check HDFS NameNode checkpoint before stop service
-    if (this.get('content.serviceName') == 'HDFS' &&
-      this.get('content.hostComponents').filterProperty('componentName', 
'NAMENODE').someProperty('workStatus', App.HostComponentStatus.started)) {
+    if (this.hasStartedNameNode()) {
       this.checkNnLastCheckpointTime(function () {
         return App.showConfirmationFeedBackPopup(function(query, 
runMmOperation) {
           batchUtils.restartAllServiceHostComponents(serviceDisplayName, 
serviceName, false, query, runMmOperation);
@@ -861,6 +930,58 @@ App.MainServiceItemController = 
Em.Controller.extend(App.SupportClientConfigsDow
     }
   },
 
+  restartCertainHostComponents: function (context) {
+    const serviceDisplayName = this.get('content.displayName'),
+      {components, hosts, label, serviceName} = context;
+    if (hosts) {
+      const bodyMessage = Em.Object.create({
+        putInMaintenance: this.get('content.passiveState') === 'OFF',
+        turnOnMmMsg: 
Em.I18n.t('passiveState.turnOnFor').format(serviceDisplayName),
+        confirmMsg: 
Em.I18n.t('services.service.restartAll.confirmMsg').format(Em.I18n.t('services.service.componentsInNameSpace').format(label)),
+        confirmButton: Em.I18n.t('services.service.restartAll.confirmButton'),
+        additionalWarningMsg: this.get('content.passiveState') === 'OFF' ?
+          
Em.I18n.t('services.service.restartCertain.warningMsg.turnOnMM').format(serviceDisplayName)
 : null
+      });
+      if (this.hasStartedNameNode(label)) {
+        this.checkNnLastCheckpointTime(function () {
+          return App.showConfirmationFeedBackPopup(function (query, 
runMmOperation) {
+            batchUtils.restartCertainServiceHostComponents(serviceName, 
components, hosts, label, query, runMmOperation);
+          }, bodyMessage);
+        });
+      } else {
+        App.showConfirmationFeedBackPopup(function (query, runMmOperation) {
+          batchUtils.restartCertainServiceHostComponents(serviceName, 
components, hosts, label, query, runMmOperation);
+        }, bodyMessage);
+      }
+    } else {
+      this.restartAllHostComponents(serviceName);
+    }
+  },
+
+  startCertainHostComponents: function (context) {
+    if (context.hosts) {
+      this.startStopCertainPopup(context, App.HostComponentStatus.started);
+    } else {
+      this.startService();
+    }
+  },
+
+  stopCertainHostComponents: function (context) {
+    if (context.hosts) {
+      this.startStopCertainPopup(context, App.HostComponentStatus.stopped);
+    } else {
+      this.stopService();
+    }
+  },
+
+  hasStartedNameNode: function (nameSpace) {
+    return this.get('content.serviceName') == 'HDFS' && 
this.get('content.hostComponents').some(component => {
+        return component.get('componentName') === 'NAMENODE'
+          && (!nameSpace || component.get('haNameSpace') === nameSpace)
+          && component.get('workStatus') === App.HostComponentStatus.started;
+      });
+  },
+
   turnOnOffPassive: function(label) {
     var self = this;
     var state = this.get('content.passiveState') == 'OFF' ? 'ON' : 'OFF';
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index fa2100f..11db9ce 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1963,6 +1963,7 @@ Em.I18n.translations = {
   'admin.stackUpgrade.dialog.skipped.failures':'There were automatically 
skipped failed steps.  Please resolve each failure before continuing with the 
upgrade.',
   'services.service.start':'Start',
   'services.service.stop':'Stop',
+  'services.service.allComponents':'All Components',
   'services.service.metrics':'Metrics',
   'services.nothingToAdd':'Nothing to add',
   'services.service.summary.version':'Version',
@@ -2313,6 +2314,8 @@ Em.I18n.translations = {
   'services.service.add':'Add Service',
   'services.service.startAll':'Start All',
   'services.service.stopAll':'Stop All',
+  'services.service.startAllComponents': 'Start all components for {0}',
+  'services.service.stopAllComponents': 'Stop all components for {0}',
   'services.service.restartAllRequired':'Restart All Required',
   'services.service.downloadAllClientConfigs':'Download All Client Configs',
   'services.service.startAll.confirmMsg' : 'You are about to start all 
services',
@@ -2324,10 +2327,13 @@ Em.I18n.translations = {
   'services.service.stop.confirmButton': 'Confirm Stop',
   'services.service.start.confirmButton' : 'Confirm Start',
   'services.service.stop.warningMsg.turnOnMM': 'This will generate alerts as 
the service is stopped. To suppress alerts, turn on Maintenance Mode for {0} 
prior to stopping.',
+  'services.service.stopCertain.warningMsg.turnOnMM': 'This will generate 
alerts as components are stopped. To suppress alerts, turn on Maintenance Mode 
for {0} prior to stopping.',
   'services.service.stop.warningMsg.dependent.services': 'Stopping {0} may 
impair the functioning of its dependent service(s): {1}.',
   'services.service.restartAll.confirmButton': 'Confirm Restart All',
   'services.service.restartAll.confirmMsg': 'You are about to restart {0}',
   'services.service.restartAll.warningMsg.turnOnMM': 'This will trigger alerts 
as the service is restarted. To suppress alerts, turn on Maintenance Mode for 
{0} prior to running restart all',
+  'services.service.restartCertain.warningMsg.turnOnMM': 'This will trigger 
alerts as components are restarted. To suppress alerts, turn on Maintenance 
Mode for {0} prior to running restart all',
+  'services.service.componentsInNameSpace': 'components in {0} namespace',
   'services.service.stop.HDFS.warningMsg.checkPointNA': 'Could not determine 
the age of the last HDFS checkpoint. Please ensure that you have a recent 
checkpoint. Otherwise, the NameNode(s) can take a very long time to start up.',
   'services.service.stop.HDFS.warningMsg.checkPointTooOld.instructions':
     '<br><ol>' +
diff --git a/ambari-web/app/models/host_component.js 
b/ambari-web/app/models/host_component.js
index f028aab..7b60a27 100644
--- a/ambari-web/app/models/host_component.js
+++ b/ambari-web/app/models/host_component.js
@@ -295,22 +295,55 @@ App.HostComponentStatus = {
 };
 
 App.HostComponentActionMap = {
-  getMap: function(ctx) {
-    var NN = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'NAMENODE');
-    var RM = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'RESOURCEMANAGER');
-    var RA = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'RANGER_ADMIN');
-    var HM = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'HAWQMASTER');
-    var HS = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'HAWQSTANDBY');
-    var HMComponent = App.MasterComponent.find('HAWQMASTER');
-    var HSComponent = App.MasterComponent.find('HAWQSTANDBY');
+  getMap: function (ctx) {
+    const NN = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'NAMENODE'),
+      RM = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'RESOURCEMANAGER'),
+      RA = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'RANGER_ADMIN'),
+      HM = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'HAWQMASTER'),
+      HS = 
ctx.get('controller.content.hostComponents').findProperty('componentName', 
'HAWQSTANDBY'),
+      HMComponent = App.MasterComponent.find('HAWQMASTER'),
+      HSComponent = App.MasterComponent.find('HAWQSTANDBY'),
+      hasMultipleMasterComponentGroups = 
ctx.get('service.hasMultipleMasterComponentGroups'),
+      isClientsOnlyService = ctx.get('controller.isClientsOnlyService'),
+      isStartDisabled = ctx.get('controller.isStartDisabled'),
+      isStopDisabled = ctx.get('controller.isStopDisabled');
 
     return {
+      START_ALL: {
+        action: hasMultipleMasterComponentGroups ? '' : 'startService',
+        label: Em.I18n.t('services.service.start'),
+        cssClass: `glyphicon glyphicon-play ${isStartDisabled ? 'disabled' : 
'enabled'}`,
+        isHidden: isClientsOnlyService,
+        disabled: isStartDisabled,
+        hasSubmenu: !isStartDisabled && hasMultipleMasterComponentGroups,
+        submenuOptions: !isStartDisabled && hasMultipleMasterComponentGroups ? 
this.getMastersSubmenu(ctx, 'startCertainHostComponents') : []
+      },
+      STOP_ALL: {
+        action: hasMultipleMasterComponentGroups ? '' : 'stopService',
+        label: Em.I18n.t('services.service.stop'),
+        cssClass: `glyphicon glyphicon-stop ${isStopDisabled ? 'disabled' : 
'enabled'}`,
+        isHidden: isClientsOnlyService,
+        disabled: isStopDisabled,
+        hasSubmenu: !isStopDisabled && hasMultipleMasterComponentGroups,
+        submenuOptions: !isStopDisabled && hasMultipleMasterComponentGroups ? 
this.getMastersSubmenu(ctx, 'stopCertainHostComponents') : []
+      },
       RESTART_ALL: {
-        action: 'restartAllHostComponents',
+        action: hasMultipleMasterComponentGroups ? '' : 
'restartAllHostComponents',
         context: ctx.get('serviceName'),
-        label: Em.I18n.t('restart.service.all'),
-        cssClass: 'glyphicon glyphicon-repeat',
-        disabled: false
+        label: hasMultipleMasterComponentGroups ? Em.I18n.t('common.restart') 
: Em.I18n.t('restart.service.all'),
+        cssClass: 'glyphicon glyphicon-time',
+        disabled: false,
+        hasSubmenu: hasMultipleMasterComponentGroups,
+        submenuOptions: hasMultipleMasterComponentGroups ? 
this.getMastersSubmenu(ctx, 'restartCertainHostComponents') : []
+      },
+      RESTART_NAMENODES: {
+        action: '',
+        label: 
Em.I18n.t('rollingrestart.dialog.title').format(pluralize(App.format.role('NAMENODE',
 false))),
+        cssClass: 'glyphicon glyphicon-time',
+        isHidden: !hasMultipleMasterComponentGroups,
+        disabled: false,
+        hasSubmenu: true,
+        submenuOptions: this.getMastersSubmenu(ctx, 
'restartCertainHostComponents', ['NAMENODE'])
       },
       RUN_SMOKE_TEST: {
         action: 'runSmokeTest',
@@ -513,5 +546,35 @@ App.HostComponentActionMap = {
         //todo: provide disabled flag
       }
     };
+  },
+
+  getMastersSubmenu: function (context, action, components) {
+    const serviceName = context.get('service.serviceName'),
+      groups = context.get('service.masterComponentGroups') || [],
+      allItem = {
+        action,
+        context: Object.assign({
+          label: Em.I18n.t('services.service.allComponents')
+        }, components ? {
+          components,
+          hosts: groups.mapProperty('hosts').reduce((acc, groupHosts) => 
[...acc, ...groupHosts], []).uniq()
+        } : {
+          serviceName
+        }),
+        disabled: false
+      },
+      groupItems = groups.map(group => {
+        return {
+          action,
+          context: {
+            label: group.title,
+            hosts: group.hosts,
+            components: components || group.components,
+            serviceName
+          },
+          disabled: false
+        };
+      });
+    return [allItem, ...groupItems];
   }
 };
diff --git a/ambari-web/app/models/service.js b/ambari-web/app/models/service.js
index 138ba70..f9bedb1 100644
--- a/ambari-web/app/models/service.js
+++ b/ambari-web/app/models/service.js
@@ -41,6 +41,12 @@ App.Service = DS.Model.extend({
   slaveComponents: DS.hasMany('App.SlaveComponent'),
   masterComponents: DS.hasMany('App.MasterComponent'),
 
+  masterComponentGroups: DS.attr('array', {
+    defaultValue: []
+  }),
+
+  hasMultipleMasterComponentGroups: 
Em.computed.gt('masterComponentGroups.length', 1),
+
   /**
    * Check master/slave component state of service
    * and general services state to define if it can be removed
diff --git a/ambari-web/app/models/service/hdfs.js 
b/ambari-web/app/models/service/hdfs.js
index cacbd65..fa279f9 100644
--- a/ambari-web/app/models/service/hdfs.js
+++ b/ambari-web/app/models/service/hdfs.js
@@ -52,7 +52,30 @@ App.HDFSService = App.Service.extend({
   upgradeStatus: DS.attr('string'),
   safeModeStatus: DS.attr('string'),
   nameNodeRpc: DS.attr('number'),
-  metricsNotAvailable: DS.attr('boolean')
+  metricsNotAvailable: DS.attr('boolean'),
+  masterComponentGroups: function () {
+    let result = [];
+    this.get('hostComponents').forEach(component => {
+      const nameSpace = component.get('haNameSpace');
+      if (nameSpace) {
+        const hostName = component.get('hostName'),
+          existingNameSpace = result.findProperty('name', nameSpace),
+          currentNameSpace = existingNameSpace || {
+              name: nameSpace,
+              title: nameSpace,
+              hosts: [],
+              components: ['NAMENODE', 'ZKFC']
+            };
+        if (!existingNameSpace) {
+          result.push(currentNameSpace);
+        }
+        if (!currentNameSpace.hosts.contains(hostName)) {
+          currentNameSpace.hosts.push(hostName);
+        }
+      }
+    });
+    return result;
+  }.property('hostComponents')
 });
 
 App.HDFSService.FIXTURES = [];
diff --git a/ambari-web/app/templates/main/service/info/summary.hbs 
b/ambari-web/app/templates/main/service/info/summary.hbs
index 73ef14c..5f6219a 100644
--- a/ambari-web/app/templates/main/service/info/summary.hbs
+++ b/ambari-web/app/templates/main/service/info/summary.hbs
@@ -50,7 +50,7 @@
   <ul class="nav nav-tabs">
     {{#each group in view.mastersObj}}
       <li {{bindAttr class="group.isActive:active"}}>
-        <a href="#" {{action setActiveComponentGroup group.title 
target="view"}}>{{group.title}}</a>
+        <a href="#" {{action setActiveComponentGroup group.name 
target="view"}}>{{group.title}}</a>
       </li>
     {{/each}}
   </ul>
diff --git a/ambari-web/app/templates/main/service/item.hbs 
b/ambari-web/app/templates/main/service/item.hbs
index 9abcaf3..ad616e8 100644
--- a/ambari-web/app/templates/main/service/item.hbs
+++ b/ambari-web/app/templates/main/service/item.hbs
@@ -32,53 +32,32 @@
       <ul class="pull-right dropdown-menu">
         <!-- dropdown menu links -->
 
-        <!-- Start/Stop service actions -->
-        {{#isAuthorized "SERVICE.START_STOP"}}
-        {{#unless controller.isClientsOnlyService}}
-          <li {{bindAttr class="controller.isStartDisabled:disabled"}}>
-            <a href="javascript:void(null)" {{bindAttr 
class="controller.isStartDisabled:disabled" }}
-              {{action "startService" target="controller"}}>
-              <i {{bindAttr class=":glyphicon :glyphicon-play 
controller.isStartDisabled:disabled:enabled" }}></i>
-              {{t services.service.start}}
-            </a>
-          </li>
-          <li {{bindAttr class="controller.isStopDisabled:disabled"}}>
-            <a href="javascript:void(null)" {{bindAttr 
class="controller.isStopDisabled:disabled" }}
-              data-toggle="modal" {{action "stopService" target="controller"}}>
-              <i {{bindAttr class=":glyphicon :glyphicon-stop 
controller.isStopDisabled:disabled:enabled" }}></i>
-              {{t services.service.stop}}
-            </a>
-          </li>
-        {{/unless}}
-        {{/isAuthorized}}
-        {{#isAuthorized "SERVICE.RUN_CUSTOM_COMMAND, 
SERVICE.RUN_SERVICE_CHECK, SERVICE.TOGGLE_MAINTENANCE, SERVICE.ENABLE_HA"}}
-          {{#if view.maintenance.length}}
-            <!-- Other service actions -->
-            {{#each option in view.maintenance}}
-              {{#unless option.isHidden}}
-                <li {{bindAttr class="option.disabled 
option.hasSubmenu:dropdown-submenu option.hasSubmenu:submenu-left"}}>
-                  <a {{action "doAction" option target="controller" 
href=true}} {{bindAttr data-title="option.tooltip"}} rel="HealthTooltip">
-                      <i {{bindAttr class="option.cssClass"}}></i>
-                      {{option.label}}
-                  </a>
-                  {{#if option.hasSubmenu}}
-                    <div class="dropdown-menu-wrap">
-                      <ul class="dropdown-menu">
-                        {{#each item in option.submenuOptions}}
-                          <li>
-                            <a {{action "doAction" item target="controller" 
href=true}}>{{item.context.label}}</a>
-                          </li>
-                        {{/each}}
-                      </ul>
-                    </div>
-                  {{/if}}
-                </li>
-              {{/unless}}
-            {{/each}}
-          {{else}}
-            {{view App.SpinnerView classNames="service-button-spinner"}}
-          {{/if}}
-        {{/isAuthorized}}
+        {{#if view.maintenance.length}}
+          <!-- Service actions -->
+          {{#each option in view.maintenance}}
+            {{#unless option.isHidden}}
+              <li {{bindAttr class="option.disabled 
option.hasSubmenu:dropdown-submenu option.hasSubmenu:submenu-left"}}>
+                <a {{action "doAction" option target="controller" href=true}} 
{{bindAttr data-title="option.tooltip"}} rel="HealthTooltip">
+                  <i {{bindAttr class="option.cssClass"}}></i>
+                  {{option.label}}
+                </a>
+                {{#if option.hasSubmenu}}
+                  <div class="dropdown-menu-wrap">
+                    <ul class="dropdown-menu">
+                      {{#each item in option.submenuOptions}}
+                        <li>
+                          <a {{action "doAction" item target="controller" 
href=true}}>{{item.context.label}}</a>
+                        </li>
+                      {{/each}}
+                    </ul>
+                  </div>
+                {{/if}}
+              </li>
+            {{/unless}}
+          {{/each}}
+        {{else}}
+          {{view App.SpinnerView classNames="service-button-spinner"}}
+        {{/if}}
       </ul>
     </div>
   {{/if}}
diff --git a/ambari-web/app/utils/ajax/ajax.js 
b/ambari-web/app/utils/ajax/ajax.js
index ec07b6b..af229c4 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -330,6 +330,32 @@ var urls = {
     }
   },
 
+  'common.service.host_component.update': {
+    'real': '/clusters/{clusterName}/host_components',
+    'mock': '',
+    'type': 'PUT',
+    'format': function (data) {
+      return {
+        data: JSON.stringify({
+          RequestInfo: {
+            context: data.context,
+            operation_level: {
+              level: 'SERVICE',
+              cluster_name: data.clusterName,
+              service_name: data.serviceName
+            },
+            query: data.query
+          },
+          Body: {
+            HostRoles: {
+              state: data.state
+            }
+          }
+        })
+      }
+    }
+  },
+
   'common.host.host_component.passive': {
     'real': 
'/clusters/{clusterName}/hosts/{hostName}/host_components/{componentName}',
     'mock': '',
diff --git a/ambari-web/app/utils/batch_scheduled_requests.js 
b/ambari-web/app/utils/batch_scheduled_requests.js
index c3201e4..0e5a58f 100644
--- a/ambari-web/app/utils/batch_scheduled_requests.js
+++ b/ambari-web/app/utils/batch_scheduled_requests.js
@@ -73,8 +73,7 @@ module.exports = {
    * @param {bool} runMmOperation
    */
   restartAllServiceHostComponents: function(serviceDisplayName, serviceName, 
staleConfigsOnly, query, runMmOperation) {
-    var self = this;
-    var context = staleConfigsOnly ?
+    const context = staleConfigsOnly ?
       
Em.I18n.t('rollingrestart.context.allWithStaleConfigsForSelectedService').format(serviceDisplayName)
 :
       
Em.I18n.t('rollingrestart.context.allForSelectedService').format(serviceDisplayName);
 
@@ -86,18 +85,40 @@ module.exports = {
       staleConfigs: staleConfigsOnly ? staleConfigsOnly : null,
       passiveState: 'OFF',
       displayParams: ['host_components/HostRoles/component_name']
-    }, function (data) {
-      var hostComponents = [];
-      data.items.forEach(function (host) {
-        host.host_components.forEach(function (hostComponent) {
-          hostComponents.push(Em.Object.create({
-            componentName: hostComponent.HostRoles.component_name,
-            hostName: host.Hosts.host_name
-          }))
-        });
+    }, data => {
+      const hostComponents = this.getRestartComponentsArray(data);
+      this.restartHostComponents(hostComponents, context, 'SERVICE', query);
+    });
+  },
+
+  restartCertainServiceHostComponents: function (serviceName, components, 
hosts, label, query, runMmOperation) {
+    const context = 
Em.I18n.t('rollingrestart.context.allForSelectedService').format(label);
+    if (runMmOperation) {
+      this.turnOnOffPassiveRequest('ON', 
Em.I18n.t('passiveState.turnOnFor').format(serviceName), serviceName);
+    }
+    this.getComponentsFromServer({
+      services: serviceName && [serviceName],
+      hosts,
+      components,
+      passiveState: 'OFF',
+      displayParams: ['host_components/HostRoles/component_name']
+    }, data => {
+      const hostComponents = this.getRestartComponentsArray(data);
+      this.restartHostComponents(hostComponents, context, 'SERVICE', query);
+    });
+  },
+
+  getRestartComponentsArray: function (data) {
+    let hostComponents = [];
+    data.items.forEach(host => {
+      host.host_components.forEach(hostComponent => {
+        hostComponents.push(Em.Object.create({
+          componentName: hostComponent.HostRoles.component_name,
+          hostName: host.Hosts.host_name
+        }));
       });
-      self.restartHostComponents(hostComponents, context, "SERVICE", query);
     });
+    return hostComponents;
   },
 
   /**
diff --git a/ambari-web/app/views/main/service/info/summary.js 
b/ambari-web/app/views/main/service/info/summary.js
index 3260456..e35ca40 100644
--- a/ambari-web/app/views/main/service/info/summary.js
+++ b/ambari-web/app/views/main/service/info/summary.js
@@ -431,28 +431,27 @@ App.MainServiceInfoSummaryView = Em.View.extend({
   getGroupedMasterComponents: function (components) {
     switch (this.get('serviceName')) {
       case 'HDFS':
-        const hostComponents = this.get('service.hostComponents'),
+        const masterComponentGroups = 
this.get('service.masterComponentGroups'),
+          hostComponents = this.get('service.hostComponents'),
           zkfcs = hostComponents.filterProperty('componentName', 'ZKFC'),
-          hasNameNodeFederation = App.get('hasNameNodeFederation');
+          hasNameNodeFederation = 
this.get('service.hasMultipleMasterComponentGroups');
         let groups = [];
         hostComponents.forEach(component => {
           if (component.get('isMaster') && component.get('componentName') !== 
'JOURNALNODE') {
             const hostName = component.get('hostName'),
               zkfc = zkfcs.findProperty('hostName', hostName);
             if (hasNameNodeFederation) {
-              const title = component.get('haNameSpace'),
-                existingGroup = groups.findProperty('title', title),
-                currentGroup = existingGroup || {
-                    title,
-                    isActive: title === this.get('activeMasterComponentGroup'),
-                    components: [],
-                    hosts: []
-                  };
+              const name = component.get('haNameSpace'),
+                existingGroup = groups.findProperty('name', name),
+                currentGroup = existingGroup || Object.assign({}, 
masterComponentGroups.findProperty('name', name));
               if (!existingGroup) {
                 groups.push(currentGroup);
+                Em.setProperties(currentGroup, {
+                  isActive: name === this.get('activeMasterComponentGroup'),
+                  components: []
+                });
               }
               currentGroup.components.push(component);
-              currentGroup.hosts.push(hostName);
               if (zkfc) {
                 zkfc.set('isSubComponent', true);
                 currentGroup.components.push(zkfc);
@@ -484,6 +483,6 @@ App.MainServiceInfoSummaryView = Em.View.extend({
 
   setActiveComponentGroup: function (event) {
     const groupName = event.context;
-    this.get('mastersObj').forEach(group => Em.set(group, 'isActive', 
group.title === groupName));
+    this.get('mastersObj').forEach(group => Em.set(group, 'isActive', 
group.name === groupName));
   }
 });
diff --git a/ambari-web/app/views/main/service/item.js 
b/ambari-web/app/views/main/service/item.js
index dc6f568..9240af8 100644
--- a/ambari-web/app/views/main/service/item.js
+++ b/ambari-web/app/views/main/service/item.js
@@ -127,181 +127,191 @@ App.MainServiceItemView = Em.View.extend({
     var serviceCheckSupported = 
App.get('services.supportsServiceCheck').contains(service.get('serviceName'));
     var hasConfigTab = this.get('hasConfigTab');
     var excludedCommands = this.get('mastersExcludedCommands');
+    var serviceName = service.get('serviceName');
+    var hasMultipleMasterComponentGroups = 
this.get('service.hasMultipleMasterComponentGroups');
 
-    if (this.get('controller.isClientsOnlyService')) {
-      if (serviceCheckSupported) {
-        options.push(actionMap.RUN_SMOKE_TEST);
-      }
-      if (hasConfigTab) {
-             options.push(actionMap.REFRESH_CONFIGS);
-           }
-    } else {
-      if (this.get('serviceName') === 'FLUME') {
-        options.push(actionMap.REFRESH_CONFIGS);
-      }
-      if (this.get('serviceName') === 'YARN') {
-        options.push(actionMap.REFRESHQUEUES);
-      }
-      options.push(actionMap.RESTART_ALL);
-      allSlaves.concat(allMasters).filter(function (_component) {
-        return App.get('components.rollinRestartAllowed').contains(_component);
-      }).forEach(function(_component) {
-        var _componentNamePluralized = pluralize(App.format.role(_component, 
false));
-        options.push(self.createOption(actionMap.ROLLING_RESTART, {
-          context: _component,
-          label: 
actionMap.ROLLING_RESTART.label.format(_componentNamePluralized)
-        }));
-      });
-      allMasters.filter(function(master) {
-        return App.get('components.reassignable').contains(master);
-      }).forEach(function(master) {
-        options.push(self.createOption(actionMap.MOVE_COMPONENT, {
-          context: master,
-          label: actionMap.MOVE_COMPONENT.label.format(App.format.role(master, 
false)),
-          disabled: App.allHostNames.length === 
App.HostComponent.find().filterProperty('componentName', 
master).mapProperty('hostName').length
-        }));
-      });
-      // add "Manage JournalNode" when NNHA is enabled and there is more hosts 
than JNs
-      var JNCount = App.HostComponent.find().filterProperty('componentName', 
'JOURNALNODE').get('length');
-      if (App.get('supports.manageJournalNode') && service.get('serviceName') 
== 'HDFS' && service.get('serviceTypes').contains('HA_MODE')
+    if (App.isAuthorized('SERVICE.START_STOP')) {
+      options.push(actionMap.START_ALL);
+      options.push(actionMap.STOP_ALL);
+    }
+    if (App.isAuthorized('SERVICE.RUN_CUSTOM_COMMAND, 
SERVICE.RUN_SERVICE_CHECK, SERVICE.TOGGLE_MAINTENANCE, SERVICE.ENABLE_HA')) {
+      if (this.get('controller.isClientsOnlyService')) {
+        if (serviceCheckSupported) {
+          options.push(actionMap.RUN_SMOKE_TEST);
+        }
+        if (hasConfigTab) {
+          options.push(actionMap.REFRESH_CONFIGS);
+        }
+      } else {
+        if (this.get('serviceName') === 'FLUME') {
+          options.push(actionMap.REFRESH_CONFIGS);
+        }
+        if (this.get('serviceName') === 'YARN') {
+          options.push(actionMap.REFRESHQUEUES);
+        }
+        options.push(actionMap.RESTART_ALL);
+        if (hasMultipleMasterComponentGroups && this.get('serviceName') === 
'HDFS') {
+          options.push(actionMap.RESTART_NAMENODES);
+        }
+        allSlaves.concat(allMasters).filter(function (_component) {
+          return 
App.get('components.rollinRestartAllowed').contains(_component);
+        }).forEach(function (_component) {
+          var _componentNamePluralized = pluralize(App.format.role(_component, 
false));
+          options.push(self.createOption(actionMap.ROLLING_RESTART, {
+            context: _component,
+            label: 
actionMap.ROLLING_RESTART.label.format(_componentNamePluralized)
+          }));
+        });
+        allMasters.filter(function (master) {
+          return App.get('components.reassignable').contains(master);
+        }).forEach(function (master) {
+          options.push(self.createOption(actionMap.MOVE_COMPONENT, {
+            context: master,
+            label: 
actionMap.MOVE_COMPONENT.label.format(App.format.role(master, false)),
+            disabled: App.allHostNames.length === 
App.HostComponent.find().filterProperty('componentName', 
master).mapProperty('hostName').length
+          }));
+        });
+        // add "Manage JournalNode" when NNHA is enabled and there is more 
hosts than JNs
+        var JNCount = App.HostComponent.find().filterProperty('componentName', 
'JOURNALNODE').get('length');
+        if (App.get('supports.manageJournalNode') && 
service.get('serviceName') == 'HDFS' && 
service.get('serviceTypes').contains('HA_MODE')
           && (App.router.get('mainHostController.totalCount') > JNCount || 
JNCount > 3)) {
-        options.push(actionMap.MANAGE_JN);
-      }
-      if (service.get('serviceTypes').contains('HA_MODE') && 
App.isAuthorized('SERVICE.ENABLE_HA')) {
-        switch (service.get('serviceName')) {
-          case 'HDFS':
-            options.push(actionMap.TOGGLE_NN_HA);
-            break;
-          case 'YARN':
-            options.push(actionMap.TOGGLE_RM_HA);
-            break;
-          case 'RANGER':
-            options.push(actionMap.TOGGLE_RA_HA);
-            break;
-          case 'HAWQ':
-            options.push(actionMap.TOGGLE_ADD_HAWQ_STANDBY);
-            break;
+          options.push(actionMap.MANAGE_JN);
         }
-      }
-      if (service.get('serviceTypes').contains('FEDERATION') && 
App.isAuthorized('SERVICE.ENABLE_HA')) {
-        switch (service.get('serviceName')) {
-          case 'HDFS':
-            options.push(actionMap.TOGGLE_NN_FEDERATION);
-            break;
+        if (service.get('serviceTypes').contains('HA_MODE') && 
App.isAuthorized('SERVICE.ENABLE_HA')) {
+          switch (service.get('serviceName')) {
+            case 'HDFS':
+              options.push(actionMap.TOGGLE_NN_HA);
+              break;
+            case 'YARN':
+              options.push(actionMap.TOGGLE_RM_HA);
+              break;
+            case 'RANGER':
+              options.push(actionMap.TOGGLE_RA_HA);
+              break;
+            case 'HAWQ':
+              options.push(actionMap.TOGGLE_ADD_HAWQ_STANDBY);
+              break;
+          }
         }
-      }
-      if (serviceCheckSupported) {
-        options.push(actionMap.RUN_SMOKE_TEST);
-      }
-      options.push(actionMap.TOGGLE_PASSIVE);
-      var serviceName = service.get('serviceName');
-      var nnComponent = 
App.StackServiceComponent.find().findProperty('componentName', 'NAMENODE');
-      var knoxGatewayComponent = 
App.StackServiceComponent.find().findProperty('componentName', 'KNOX_GATEWAY');
-      if (serviceName === 'HDFS' && nnComponent) {
-        var namenodeCustomCommands = nnComponent.get('customCommands');
-        if (namenodeCustomCommands && 
namenodeCustomCommands.contains('REBALANCEHDFS')) {
-          options.push(actionMap.REBALANCEHDFS);
+        if (service.get('serviceTypes').contains('FEDERATION') && 
App.isAuthorized('SERVICE.ENABLE_HA')) {
+          switch (service.get('serviceName')) {
+            case 'HDFS':
+              options.push(actionMap.TOGGLE_NN_FEDERATION);
+              break;
+          }
         }
-      }
-
-      if (serviceName === 'KNOX' && knoxGatewayComponent) {
-        var knoxGatewayCustomCommands = 
knoxGatewayComponent.get('customCommands');
-        knoxGatewayCustomCommands.forEach(function(command) {
-          if (actionMap[command]) {
-            options.push(actionMap[command]);
+        if (serviceCheckSupported) {
+          options.push(actionMap.RUN_SMOKE_TEST);
+        }
+        options.push(actionMap.TOGGLE_PASSIVE);
+        var nnComponent = 
App.StackServiceComponent.find().findProperty('componentName', 'NAMENODE');
+        var knoxGatewayComponent = 
App.StackServiceComponent.find().findProperty('componentName', 'KNOX_GATEWAY');
+        if (serviceName === 'HDFS' && nnComponent) {
+          var namenodeCustomCommands = nnComponent.get('customCommands');
+          if (namenodeCustomCommands && 
namenodeCustomCommands.contains('REBALANCEHDFS')) {
+            options.push(actionMap.REBALANCEHDFS);
           }
-        });
-      }
+        }
 
-      if (serviceName === 'HIVE') {
-        var hiveServerInteractiveComponent = 
App.StackServiceComponent.find().findProperty('componentName', 
'HIVE_SERVER_INTERACTIVE');
-        var isHiveInteractiveServerPresent = 
allMasters.contains('HIVE_SERVER_INTERACTIVE');
-        if (hiveServerInteractiveComponent && isHiveInteractiveServerPresent) {
-          var LLAPCustomCommands = 
hiveServerInteractiveComponent.get('customCommands');
-          LLAPCustomCommands.forEach(function (command) {
+        if (serviceName === 'KNOX' && knoxGatewayComponent) {
+          var knoxGatewayCustomCommands = 
knoxGatewayComponent.get('customCommands');
+          knoxGatewayCustomCommands.forEach(function (command) {
             if (actionMap[command]) {
               options.push(actionMap[command]);
             }
           });
         }
-      }
 
-      /**
-       * Display all custom commands of Master and StandBy on Service page.
-       **/
-      if(serviceName === 'HAWQ') {
-        var hawqMasterComponent = 
App.StackServiceComponent.find().findProperty('componentName','HAWQMASTER');
-        var hawqStandByComponent = 
App.StackServiceComponent.find().findProperty('componentName','HAWQSTANDBY');
-        [hawqMasterComponent,hawqStandByComponent].forEach(function(component){
-          component.get('customCommands').forEach(function(command){
-            options.push(self.createOption(actionMap[command], {
-              context: {
-                label: actionMap[command].context,
-                service: component.get('serviceName'),
-                component: component.get('componentName'),
-                command: command
+        if (serviceName === 'HIVE') {
+          var hiveServerInteractiveComponent = 
App.StackServiceComponent.find().findProperty('componentName', 
'HIVE_SERVER_INTERACTIVE');
+          var isHiveInteractiveServerPresent = 
allMasters.contains('HIVE_SERVER_INTERACTIVE');
+          if (hiveServerInteractiveComponent && 
isHiveInteractiveServerPresent) {
+            var LLAPCustomCommands = 
hiveServerInteractiveComponent.get('customCommands');
+            LLAPCustomCommands.forEach(function (command) {
+              if (actionMap[command]) {
+                options.push(actionMap[command]);
               }
-            }));
+            });
+          }
+        }
+
+        /**
+         * Display all custom commands of Master and StandBy on Service page.
+         **/
+        if (serviceName === 'HAWQ') {
+          var hawqMasterComponent = 
App.StackServiceComponent.find().findProperty('componentName', 'HAWQMASTER');
+          var hawqStandByComponent = 
App.StackServiceComponent.find().findProperty('componentName', 'HAWQSTANDBY');
+          [hawqMasterComponent, hawqStandByComponent].forEach(function 
(component) {
+            component.get('customCommands').forEach(function (command) {
+              options.push(self.createOption(actionMap[command], {
+                context: {
+                  label: actionMap[command].context,
+                  service: component.get('serviceName'),
+                  component: component.get('componentName'),
+                  command: command
+                }
+              }));
+            });
           });
-        });
-      }
+        }
 
-      if(App.isAuthorized('HOST.ADD_DELETE_COMPONENTS')){
-        self.addActionMap().filterProperty('service', 
serviceName).forEach(function(item) {
-        if (App.get('components.addableToHost').contains(item.component)) {
+        if (App.isAuthorized('HOST.ADD_DELETE_COMPONENTS')) {
+          self.addActionMap().filterProperty('service', 
serviceName).forEach(function (item) {
+            if (App.get('components.addableToHost').contains(item.component)) {
 
-          var isEnabled = 
App.HostComponent.find().filterProperty('componentName', item.component).length 
< App.get('allHostNames.length');
+              var isEnabled = 
App.HostComponent.find().filterProperty('componentName', item.component).length 
< App.get('allHostNames.length');
 
-          if (item.component === 'OOZIE_SERVER') {
-            isEnabled = isEnabled && 
!(Em.isEmpty(self.get('controller.configs.oozie-env.oozie_database')) || 
self.get('controller.configs.oozie-env.oozie_database') === 'New Derby 
Database');
-          }
+              if (item.component === 'OOZIE_SERVER') {
+                isEnabled = isEnabled && 
!(Em.isEmpty(self.get('controller.configs.oozie-env.oozie_database')) || 
self.get('controller.configs.oozie-env.oozie_database') === 'New Derby 
Database');
+              }
 
-          item.action = 'addComponent';
-          item.disabled = isEnabled ? '' : 'disabled';
-          item.tooltip = isEnabled ? '' : 
Em.I18n.t('services.summary.allHostsAlreadyRunComponent').format(item.component);
-          item.context = item.component;
+              item.action = 'addComponent';
+              item.disabled = isEnabled ? '' : 'disabled';
+              item.tooltip = isEnabled ? '' : 
Em.I18n.t('services.summary.allHostsAlreadyRunComponent').format(item.component);
+              item.context = item.component;
 
-          options.push(item);
+              options.push(item);
+            }
+          });
         }
-       });
-      }
-
-      if (App.get('isKerberosEnabled')){
-        options.push(actionMap.REGENERATE_KEYTAB_FILE_OPERATIONS);
-      }
-
-      allMasters.forEach(function(master) {
-        var component = App.StackServiceComponent.find(master);
-        var commands = component.get('customCommands');
 
-        if (!commands.length) {
-          return;
+        if (App.get('isKerberosEnabled')) {
+          options.push(actionMap.REGENERATE_KEYTAB_FILE_OPERATIONS);
         }
 
-        commands.forEach(function(command) {
-          if (excludedCommands[master] && 
excludedCommands[master].contains(command)){
+        allMasters.forEach(function (master) {
+          var component = App.StackServiceComponent.find(master);
+          var commands = component.get('customCommands');
+
+          if (!commands.length) {
             return;
           }
 
-          options.push(self.createOption(actionMap.MASTER_CUSTOM_COMMAND, {
-            label: 
Em.I18n.t('services.service.actions.run.executeCustomCommand.menu').format(App.format.normalizeNameBySeparators(command,
 ["_", "-", " "])),
-            context: {
-              label: 
Em.I18n.t('services.service.actions.run.executeCustomCommand.menu').format(App.format.normalizeNameBySeparators(command,
 ["_", "-", " "])),
-              service: component.get('serviceName'),
-              component: component.get('componentName'),
-              command: command
+          commands.forEach(function (command) {
+            if (excludedCommands[master] && 
excludedCommands[master].contains(command)) {
+              return;
             }
-          }));
+
+            options.push(self.createOption(actionMap.MASTER_CUSTOM_COMMAND, {
+              label: 
Em.I18n.t('services.service.actions.run.executeCustomCommand.menu').format(App.format.normalizeNameBySeparators(command,
 ["_", "-", " "])),
+              context: {
+                label: 
Em.I18n.t('services.service.actions.run.executeCustomCommand.menu').format(App.format.normalizeNameBySeparators(command,
 ["_", "-", " "])),
+                service: component.get('serviceName'),
+                component: component.get('componentName'),
+                command: command
+              }
+            }));
+          });
         });
-      });
-    }
+      }
 
-    if (hasConfigTab) {
-      options.push(actionMap.DOWNLOAD_CLIENT_CONFIGS);
-    }
+      if (hasConfigTab) {
+        options.push(actionMap.DOWNLOAD_CLIENT_CONFIGS);
+      }
 
-    if (App.isAuthorized("SERVICE.ADD_DELETE_SERVICES") && 
App.supports.enableAddDeleteServices) {
-      options.push(actionMap.DELETE_SERVICE);
+      if (App.isAuthorized("SERVICE.ADD_DELETE_SERVICES") && 
App.supports.enableAddDeleteServices) {
+        options.push(actionMap.DELETE_SERVICE);
+      }
     }
 
     if (this.get('maintenance.length')) {
diff --git a/ambari-web/test/controllers/main/service/item_test.js 
b/ambari-web/test/controllers/main/service/item_test.js
index 6162603..2ac35a2 100644
--- a/ambari-web/test/controllers/main/service/item_test.js
+++ b/ambari-web/test/controllers/main/service/item_test.js
@@ -283,12 +283,12 @@ describe('App.MainServiceItemController', function () {
       mainServiceItemController.startStopPopup.restore();
     });
     it("start service", function () {
-      mainServiceItemController.startService({});
-      
expect(mainServiceItemController.startStopPopup.calledWith({},App.HostComponentStatus.started)).to.equal(true);
+      mainServiceItemController.startService();
+      
expect(mainServiceItemController.startStopPopup.calledWith(App.HostComponentStatus.started)).to.equal(true);
     });
     it("stop service", function () {
-      mainServiceItemController.stopService({});
-      
expect(mainServiceItemController.startStopPopup.calledWith({},App.HostComponentStatus.stopped)).to.equal(true);
+      mainServiceItemController.stopService();
+      
expect(mainServiceItemController.startStopPopup.calledWith(App.HostComponentStatus.stopped)).to.equal(true);
     });
   });
 
@@ -356,27 +356,26 @@ describe('App.MainServiceItemController', function () {
   });
 
   describe("#startStopPopup", function () {
-    var el = document.createElement("BUTTON");
-    el.disabled = false;
-    var event = {
-      target: el
-    };
     var mainServiceItemController = App.MainServiceItemController.create({
       content: {
-        serviceName: "HDFS",
-        hostComponents: [ {
-          componentName: 'NAMENODE',
-          workStatus: 'INSTALLED'
-        }]
+        serviceName: 'HDFS',
+        hostComponents: [
+          Em.Object.create({
+            componentName: 'NAMENODE',
+            workStatus: 'INSTALLED'
+          })
+        ]
       }
     });
     var mainServiceItemControllerHdfsStarted = 
App.MainServiceItemController.create({
       content: {
-        serviceName: "HDFS",
-        hostComponents: [ {
-          componentName: 'NAMENODE',
-          workStatus: 'STARTED'
-        }]
+        serviceName: 'HDFS',
+        hostComponents: [
+          Em.Object.create({
+            componentName: 'NAMENODE',
+            workStatus: 'STARTED'
+          })
+        ]
       }
     });
     beforeEach(function () {
@@ -394,12 +393,12 @@ describe('App.MainServiceItemController', function () {
       Em.I18n.t.restore();
     });
     it("start start/stop service popup", function () {
-      mainServiceItemController.startStopPopup(event, "").onPrimary();
+      mainServiceItemController.startStopPopup("").onPrimary();
       
expect(mainServiceItemController.startStopPopupPrimary.calledOnce).to.equal(true);
     });
 
     it ("should popup warning to check last checkpoint time if work status is 
STARTED", function() {
-      mainServiceItemControllerHdfsStarted.startStopPopup(event, "INSTALLED");
+      mainServiceItemControllerHdfsStarted.startStopPopup("INSTALLED");
       
expect(mainServiceItemControllerHdfsStarted.checkNnLastCheckpointTime.calledOnce).to.equal(true);
     });
 
@@ -445,13 +444,13 @@ describe('App.MainServiceItemController', function () {
       });
 
       it ("should confirm stop if serviceHealth is INSTALLED", function() {
-        mainServiceItemController.startStopPopup(event, "INSTALLED");
+        mainServiceItemController.startStopPopup("INSTALLED");
         
expect(Em.I18n.t.calledWith('services.service.stop.confirmMsg')).to.be.ok;
         
expect(Em.I18n.t.calledWith('services.service.stop.confirmButton')).to.be.ok;
       });
 
       it ("should confirm start if serviceHealth is not INSTALLED", function() 
{
-        mainServiceItemController.startStopPopup(event, "");
+        mainServiceItemController.startStopPopup("");
         
expect(Em.I18n.t.calledWith('services.service.start.confirmMsg')).to.be.ok;
         
expect(Em.I18n.t.calledWith('services.service.start.confirmButton')).to.be.ok;
       });
@@ -459,7 +458,7 @@ describe('App.MainServiceItemController', function () {
       it ("should not display a dependent list if it is to start a service", 
function() {
         var _mainServiceItemController = App.MainServiceItemController.create(
             {content: {serviceName: "HDFS", passiveState:'OFF'}});
-        _mainServiceItemController.startStopPopup(event, "");
+        _mainServiceItemController.startStopPopup("");
         
expect(Em.I18n.t.calledWith('services.service.stop.warningMsg.dependent.services')).to.not.be.ok;
       });
 
@@ -467,15 +466,17 @@ describe('App.MainServiceItemController', function () {
         beforeEach(function () {
           var _mainServiceItemController = 
App.MainServiceItemController.create(
             {content: {
-              serviceName: "HDFS",
+              serviceName: 'HDFS',
               passiveState:'OFF',
-              hostComponents: [{
-                componentName: 'NAMENODE',
-                workStatus: 'INSTALLED'
-              }]
+              hostComponents: [
+                Em.Object.create({
+                  componentName: 'NAMENODE',
+                  workStatus: 'INSTALLED'
+                })
+              ]
             }}
           );
-          _mainServiceItemController.startStopPopup(event, "INSTALLED");
+          _mainServiceItemController.startStopPopup("INSTALLED");
           this.dependencies = 
Em.I18n.t('services.service.stop.warningMsg.dependent.services').format("HDFS", 
"HBase,YARN");
           this.msg = 
Em.I18n.t('services.service.stop.warningMsg.turnOnMM').format("HDFS");
           this.fullMsg = 
_mainServiceItemController.addAdditionalWarningMessage("INSTALLED", this.msg, 
"HDFS");
@@ -497,7 +498,7 @@ describe('App.MainServiceItemController', function () {
         beforeEach(function () {
           var _mainServiceItemController = 
App.MainServiceItemController.create(
             {content: {serviceName: "HIVE", passiveState:'OFF'}});
-          _mainServiceItemController.startStopPopup(event, "INSTALLED");
+          _mainServiceItemController.startStopPopup("INSTALLED");
           this.dependencies = 
Em.I18n.t('services.service.stop.warningMsg.dependent.services').format("HIVE", 
"Spark");
           this.msg = 
Em.I18n.t('services.service.stop.warningMsg.turnOnMM').format("HIVE");
           this.fullMsg = 
_mainServiceItemController.addAdditionalWarningMessage("INSTALLED", this.msg, 
"HIVE");
@@ -521,11 +522,13 @@ describe('App.MainServiceItemController', function () {
     var temp = batchUtils.restartAllServiceHostComponents;
     var mainServiceItemController = App.MainServiceItemController.create({
       content: {
-        serviceName: "HDFS",
-        hostComponents: [{
-          componentName: 'NAMENODE',
-          workStatus: 'STARTED'
-        }]
+        serviceName: 'HDFS',
+        hostComponents: [
+          Em.Object.create({
+            componentName: 'NAMENODE',
+            workStatus: 'STARTED'
+          })
+        ]
       }
     });
     beforeEach(function () {
@@ -548,11 +551,13 @@ describe('App.MainServiceItemController', function () {
     it("start restartAllHostComponents for service", function () {
       var controller = App.MainServiceItemController.create({
         content: {
-          serviceName: "HDFS",
-          hostComponents: [{
-            componentName: 'NAMENODE',
-            workStatus: 'INSTALLED'
-          }]
+          serviceName: 'HDFS',
+          hostComponents: [
+            Em.Object.create({
+              componentName: 'NAMENODE',
+              workStatus: 'INSTALLED'
+            })
+          ]
         }
       });
       controller.restartAllHostComponents({}).onPrimary();
diff --git a/ambari-web/test/views/main/service/item_test.js 
b/ambari-web/test/views/main/service/item_test.js
index b86d021..f2ea9f4 100644
--- a/ambari-web/test/views/main/service/item_test.js
+++ b/ambari-web/test/views/main/service/item_test.js
@@ -173,7 +173,9 @@ describe('App.MainServiceItemView', function () {
             })
           ],
           result: [
-            {"action": "restartAllHostComponents", "context": "HDFS", "label": 
"Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": false},
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
+            {"action": "restartAllHostComponents", "context": "HDFS", "label": 
"Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": false},
             {"action": "rollingRestart", "label": "Restart DataNodes", 
"cssClass": "glyphicon glyphicon-time", "disabled": false, "context": 
"DATANODE"},
             {"action": "reassignMaster", "context": "NAMENODE", "label": "Move 
NameNode", "cssClass": "glyphicon glyphicon-share-alt", "disabled": false},
             {"action": "reassignMaster", "context": "SECONDARY_NAMENODE", 
"label": "Move SNameNode", "cssClass": "glyphicon glyphicon-share-alt", 
"disabled": false},
@@ -207,7 +209,9 @@ describe('App.MainServiceItemView', function () {
             {'isAddDisabled-ZOOKEEPER_SERVER': 'disabled'}
           ],
           result: [
-            {"action": "restartAllHostComponents", "context": "ZOOKEEPER", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": 
false},
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
+            {"action": "restartAllHostComponents", "context": "ZOOKEEPER", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": 
false},
             {"action": "runSmokeTest", "label": "Run Service Check", 
"cssClass": "glyphicon glyphicon-thumbs-up", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance 
Mode for ZooKeeper", "label": "Turn On Maintenance Mode", "cssClass": 
"icon-medkit", "disabled": false},
             {"cssClass": "glyphicon glyphicon-plus", "label": "Add ZooKeeper 
Server", "service": "ZOOKEEPER", "component": "ZOOKEEPER_SERVER", "action": 
"addComponent", "disabled": "", tooltip: ''},
@@ -244,8 +248,10 @@ describe('App.MainServiceItemView', function () {
             })
           ],
           result: [
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
             {"action": "refreshYarnQueues", "customCommand": "REFRESHQUEUES", 
"context": "Refresh YARN Capacity Scheduler", "label": "Refresh YARN Capacity 
Scheduler", "cssClass": "glyphicon glyphicon-refresh", "disabled": false},
-            {"action": "restartAllHostComponents", "context": "YARN", "label": 
"Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": false},
+            {"action": "restartAllHostComponents", "context": "YARN", "label": 
"Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": false},
             {"action": "rollingRestart", "label": "Restart NodeManagers", 
"cssClass": "glyphicon glyphicon-time", "disabled": false, "context": 
"NODEMANAGER"},
             {"action": "reassignMaster", "context": "APP_TIMELINE_SERVER", 
"label": "Move App Timeline Server", "cssClass": "glyphicon 
glyphicon-share-alt", "disabled": false},
             {"action": "reassignMaster", "context": "RESOURCEMANAGER", 
"label": "Move ResourceManager", "cssClass": "glyphicon glyphicon-share-alt", 
"disabled": false},
@@ -274,7 +280,9 @@ describe('App.MainServiceItemView', function () {
             })
           ],
           result: [
-            {"action": "restartAllHostComponents", "context": "MAPREDUCE2", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": 
false},
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
+            {"action": "restartAllHostComponents", "context": "MAPREDUCE2", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": 
false},
             {"action": "runSmokeTest", "label": "Run Service Check", 
"cssClass": "glyphicon glyphicon-thumbs-up", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance 
Mode for MapReduce2", "label": "Turn On Maintenance Mode", "cssClass": 
"icon-medkit", "disabled": false},
             {"action": "downloadClientConfigs", "label": "Download Client 
Configs", "cssClass": "glyphicon glyphicon-download-alt", "isHidden": false, 
"disabled": false, "hasSubmenu": false, "submenuOptions": []}
@@ -294,7 +302,9 @@ describe('App.MainServiceItemView', function () {
             })
           ],
           result: [
-            {"action": "restartAllHostComponents", "context": "KAFKA", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": 
false},
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
+            {"action": "restartAllHostComponents", "context": "KAFKA", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": 
false},
             {"action": "runSmokeTest", "label": "Run Service Check", 
"cssClass": "glyphicon glyphicon-thumbs-up", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance 
Mode for Kafka", "label": "Turn On Maintenance Mode", "cssClass": 
"icon-medkit", "disabled": false},
             {"action": "downloadClientConfigs", "label": "Download Client 
Configs", "cssClass": "glyphicon glyphicon-download-alt", "isHidden": true, 
"disabled": false, "hasSubmenu": false, "submenuOptions": []}
@@ -318,8 +328,10 @@ describe('App.MainServiceItemView', function () {
             {'isAddDisabled-FLUME_HANDLER': ''}
           ],
           result: [
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
             {"action": "refreshConfigs", "label": "Refresh configs", 
"cssClass": "glyphicon glyphicon-refresh", "disabled": false},
-            {"action": "restartAllHostComponents", "context": "FLUME", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": 
false},
+            {"action": "restartAllHostComponents", "context": "FLUME", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": 
false},
             {"action": "rollingRestart", "label": "Restart Flumes", 
"cssClass": "glyphicon glyphicon-time", "disabled": false, "context": 
"FLUME_HANDLER"},
             {"action": "runSmokeTest", "label": "Run Service Check", 
"cssClass": "glyphicon glyphicon-thumbs-up", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance 
Mode for Flume", "label": "Turn On Maintenance Mode", "cssClass": 
"icon-medkit", "disabled": false},
@@ -355,7 +367,9 @@ describe('App.MainServiceItemView', function () {
             {'isAddDisabled-HBASE_MASTER': ''}
           ],
           result: [
-            {"action": "restartAllHostComponents", "context": "HBASE", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": 
false},
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
+            {"action": "restartAllHostComponents", "context": "HBASE", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": 
false},
             {"action": "rollingRestart", "label": "Restart RegionServers", 
"cssClass": "glyphicon glyphicon-time", "disabled": false, "context": 
"HBASE_REGIONSERVER"},
             {"action": "runSmokeTest", "label": "Run Service Check", 
"cssClass": "glyphicon glyphicon-thumbs-up", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance 
Mode for HBase", "label": "Turn On Maintenance Mode", "cssClass": 
"icon-medkit", "disabled": false},
@@ -382,7 +396,9 @@ describe('App.MainServiceItemView', function () {
             })
           ],
           result: [
-            {"action": "restartAllHostComponents", "context": "OOZIE", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": 
false},
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
+            {"action": "restartAllHostComponents", "context": "OOZIE", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": 
false},
             {"action": "reassignMaster", "context": "OOZIE_SERVER", "label": 
"Move Oozie Server", "cssClass": "glyphicon glyphicon-share-alt", "disabled": 
false},
             {"action": "runSmokeTest", "label": "Run Service Check", 
"cssClass": "glyphicon glyphicon-thumbs-up", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance 
Mode for Oozie", "label": "Turn On Maintenance Mode", "cssClass": 
"icon-medkit", "disabled": false},
@@ -404,7 +420,9 @@ describe('App.MainServiceItemView', function () {
             })
           ],
           result: [
-            {"action": "restartAllHostComponents", "context": "KNOX", "label": 
"Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": false},
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
+            {"action": "restartAllHostComponents", "context": "KNOX", "label": 
"Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": false},
             {"action": "runSmokeTest", "label": "Run Service Check", 
"cssClass": "glyphicon glyphicon-thumbs-up", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance 
Mode for Knox", "label": "Turn On Maintenance Mode", "cssClass": "icon-medkit", 
"disabled": false},
             {"action": "startLdapKnox", "customCommand": "STARTDEMOLDAP", 
"context": "Start Demo LDAP", "label": "Start Demo LDAP", "cssClass": 
"glyphicon glyphicon-play-sign", "disabled": false},
@@ -426,7 +444,9 @@ describe('App.MainServiceItemView', function () {
             })
           ],
           result: [
-            {"action": "restartAllHostComponents", "context": "STORM", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-repeat", "disabled": 
false},
+            {"action": "startService", "label": "Start", "cssClass": 
"glyphicon glyphicon-play enabled", "disabled": false},
+            {"action": "stopService", "label": "Stop", "cssClass": "glyphicon 
glyphicon-stop enabled", "disabled": false},
+            {"action": "restartAllHostComponents", "context": "STORM", 
"label": "Restart All", "cssClass": "glyphicon glyphicon-time", "disabled": 
false},
             {"action": "runSmokeTest", "label": "Run Service Check", 
"cssClass": "glyphicon glyphicon-thumbs-up", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance 
Mode for Storm", "label": "Turn On Maintenance Mode", "cssClass": 
"icon-medkit", "disabled": false},
             {"action": "downloadClientConfigs", "label": "Download Client 
Configs", "cssClass": "glyphicon glyphicon-download-alt", "isHidden": true, 
"disabled": false, "hasSubmenu": false, "submenuOptions": []}
@@ -547,6 +567,7 @@ describe('App.MainServiceItemView', function () {
               }),
               isSeveralClients: false,
               clientComponents: [],
+              isStartDisabled: false,
               isStopDisabled: false,
               isSmokeTestDisabled: false
             }),

-- 
To stop receiving notification emails like this one, please contact
ababiic...@apache.org.

Reply via email to