Repository: ambari
Updated Branches:
  refs/heads/trunk e593c5ae3 -> db399a13f


AMBARI-13625. Refactor bulk operation and batch-requests (onechiporenko)


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

Branch: refs/heads/trunk
Commit: db399a13f306e91a4456fb4cd3a597411edb7cc5
Parents: e593c5a
Author: Oleg Nechiporenko <onechipore...@apache.org>
Authored: Thu Oct 29 12:40:24 2015 +0200
Committer: Oleg Nechiporenko <onechipore...@apache.org>
Committed: Thu Oct 29 12:40:24 2015 +0200

----------------------------------------------------------------------
 .../main/host/bulk_operations_controller.js     | 513 ++++++++++---------
 .../app/utils/batch_scheduled_requests.js       | 123 +++--
 ambari-web/app/views/main/service/item.js       |  30 +-
 3 files changed, 358 insertions(+), 308 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/db399a13/ambari-web/app/controllers/main/host/bulk_operations_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/bulk_operations_controller.js 
b/ambari-web/app/controllers/main/host/bulk_operations_controller.js
index ede2da4..3bcb5a5 100644
--- a/ambari-web/app/controllers/main/host/bulk_operations_controller.js
+++ b/ambari-web/app/controllers/main/host/bulk_operations_controller.js
@@ -19,6 +19,7 @@ var App = require('app');
 var batchUtils = require('utils/batch_scheduled_requests');
 var hostsManagement = require('utils/hosts');
 var O = Em.Object;
+
 /**
  * @class BulkOperationsController
  */
@@ -30,6 +31,7 @@ App.BulkOperationsController = Em.Controller.extend({
    * Bulk operation wrapper
    * @param {Object} operationData - data about bulk operation (action, hosts 
or hostComponents etc)
    * @param {Array} hosts - list of affected hosts
+   * @method bulkOperation
    */
   bulkOperation: function (operationData, hosts) {
     if (operationData.componentNameFormatted) {
@@ -37,26 +39,29 @@ App.BulkOperationsController = Em.Controller.extend({
         this.bulkOperationForHostComponentsRestart(operationData, hosts);
       }
       else {
-        if (operationData.action.indexOf('DECOMMISSION') != -1) {
-          this.bulkOperationForHostComponentsDecommission(operationData, 
hosts);
+        if (operationData.action.indexOf('DECOMMISSION') == -1) {
+          this.bulkOperationForHostComponents(operationData, hosts);
         }
         else {
-          this.bulkOperationForHostComponents(operationData, hosts);
+          this.bulkOperationForHostComponentsDecommission(operationData, 
hosts);
         }
       }
     }
     else {
       if (operationData.action === 'SET_RACK_INFO') {
         this.bulkOperationForHostsSetRackInfo(operationData, hosts);
-      } else if (operationData.action === 'RESTART') {
-        this.bulkOperationForHostsRestart(operationData, hosts);
       }
       else {
-        if (operationData.action === 'PASSIVE_STATE') {
-          this.bulkOperationForHostsPassiveState(operationData, hosts);
+        if (operationData.action === 'RESTART') {
+          this.bulkOperationForHostsRestart(operationData, hosts);
         }
         else {
-          this.bulkOperationForHosts(operationData, hosts);
+          if (operationData.action === 'PASSIVE_STATE') {
+            this.bulkOperationForHostsPassiveState(operationData, hosts);
+          }
+          else {
+            this.bulkOperationForHosts(operationData, hosts);
+          }
         }
       }
     }
@@ -66,32 +71,34 @@ App.BulkOperationsController = Em.Controller.extend({
    * Bulk operation (start/stop all) for selected hosts
    * @param {Object} operationData - data about bulk operation (action, 
hostComponents etc)
    * @param {Array} hosts - list of affected hosts
+   * @return {$.ajax}
    */
   bulkOperationForHosts: function (operationData, hosts) {
     var self = this;
-
-    batchUtils.getComponentsFromServer({
+    return batchUtils.getComponentsFromServer({
       hosts: hosts.mapProperty('hostName'),
       passiveState: 'OFF',
       displayParams: ['host_components/HostRoles/component_name']
     }, function (data) {
-      self.bulkOperationForHostsCallback(operationData, data);
+      return self._getComponentsFromServerForHostsCallback(operationData, 
data);
     });
   },
+
   /**
    * run Bulk operation (start/stop all) for selected hosts
    * after host and components are loaded
    * @param operationData
    * @param data
    */
-  bulkOperationForHostsCallback: function (operationData, data) {
+  _getComponentsFromServerForHostsCallback: function (operationData, data) {
     var query = [];
     var hostNames = [];
     var hostsMap = {};
+    var clients = App.components.get('clients');
 
     data.items.forEach(function (host) {
       host.host_components.forEach(function (hostComponent) {
-        if 
(!App.components.get('clients').contains((hostComponent.HostRoles.component_name)))
 {
+        if (!clients.contains((hostComponent.HostRoles.component_name))) {
           if (hostsMap[host.Hosts.host_name]) {
             
hostsMap[host.Hosts.host_name].push(hostComponent.HostRoles.component_name);
           } else {
@@ -103,60 +110,28 @@ App.BulkOperationsController = Em.Controller.extend({
 
     var nn_hosts = [];
     for (var hostName in hostsMap) {
-      var subQuery = '(HostRoles/component_name.in(%@)&HostRoles/host_name=' + 
hostName + ')';
-      var components = hostsMap[hostName];
+      if (hostsMap.hasOwnProperty(hostName)) {
+        var subQuery = '(HostRoles/component_name.in(%@)&HostRoles/host_name=' 
+ hostName + ')';
+        var components = hostsMap[hostName];
 
-      if (components.length) {
-        if (components.indexOf('NAMENODE') >= 0) {
-          nn_hosts.push(hostName);
+        if (components.length) {
+          if (components.contains('NAMENODE')) {
+            nn_hosts.push(hostName);
+          }
+          query.push(subQuery.fmt(components.join(',')));
         }
-        query.push(subQuery.fmt(components.join(',')));
+        hostNames.push(hostName);
       }
-      hostNames.push(hostName);
     }
     hostNames = hostNames.join(",");
     if (query.length) {
       query = query.join('|');
       var self = this;
       // if NameNode included, check HDFS NameNode checkpoint before stop NN
-      if (nn_hosts.length == 1 && operationData.action === 'INSTALLED' && 
App.Service.find().filterProperty('serviceName', 
'HDFS').someProperty('workStatus', App.HostComponentStatus.started)) {
-        var hostName = nn_hosts[0];
-        
App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(function 
() {
-          App.ajax.send({
-            name: 'common.host_components.update',
-            sender: self,
-            data: {
-              query: query,
-              HostRoles: {
-                state: operationData.action
-              },
-              context: operationData.message,
-              hostName: hostNames,
-              noOpsMessage: 
Em.I18n.t('hosts.host.maintainance.allComponents.context')
-            },
-            success: 'bulkOperationForHostComponentsSuccessCallback'
-          });
-        }, hostName);
-      } else if (nn_hosts.length == 2 && operationData.action === 'INSTALLED' 
&& App.Service.find().filterProperty('serviceName', 
'HDFS').someProperty('workStatus', App.HostComponentStatus.started)) {
-        // HA enabled
-        
App.router.get('mainServiceItemController').checkNnLastCheckpointTime(function 
() {
-          App.ajax.send({
-            name: 'common.host_components.update',
-            sender: self,
-            data: {
-              query: query,
-              HostRoles: {
-                state: operationData.action
-              },
-              context: operationData.message,
-              hostName: hostNames,
-              noOpsMessage: 
Em.I18n.t('hosts.host.maintainance.allComponents.context')
-            },
-            success: 'bulkOperationForHostComponentsSuccessCallback'
-          });
-        });
-      } else {
-        App.ajax.send({
+      var isHDFSStarted = 'STARTED' === 
App.Service.find('HDFS').get('workStatus');
+
+      var request = function () {
+        return App.ajax.send({
           name: 'common.host_components.update',
           sender: self,
           data: {
@@ -170,10 +145,21 @@ App.BulkOperationsController = Em.Controller.extend({
           },
           success: 'bulkOperationForHostComponentsSuccessCallback'
         });
+      };
+
+      if (operationData.action === 'INSTALLED' && isHDFSStarted) {
+        if (nn_hosts.length == 1) {
+          return 
App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(request, 
nn_hosts[0]);
+        }
+        if (nn_hosts.length == 2) {
+          // HA enabled
+          return 
App.router.get('mainServiceItemController').checkNnLastCheckpointTime(request);
+        }
       }
+      return request();
     }
     else {
-      App.ModalPopup.show({
+      return App.ModalPopup.show({
         header: Em.I18n.t('rolling.nothingToDo.header'),
         body: 
Em.I18n.t('rolling.nothingToDo.body').format(Em.I18n.t('hosts.host.maintainance.allComponents.context')),
         secondary: false
@@ -182,7 +168,7 @@ App.BulkOperationsController = Em.Controller.extend({
   },
 
   bulkOperationForHostsSetRackInfo: function (operationData, hosts) {
-    hostsManagement.setRackInfo(operationData, hosts);
+    return hostsManagement.setRackInfo(operationData, hosts);
   },
 
   /**
@@ -191,36 +177,51 @@ App.BulkOperationsController = Em.Controller.extend({
    * @param {Ember.Enumerable} hosts - list of affected hosts
    */
   bulkOperationForHostsRestart: function (operationData, hosts) {
-    batchUtils.getComponentsFromServer({
+    return batchUtils.getComponentsFromServer({
       passiveState: 'OFF',
       hosts: hosts.mapProperty('hostName'),
       displayParams: ['host_components/HostRoles/component_name']
-    }, function (data) {
-      var hostComponents = [];
-      data.items.forEach(function (host) {
-        host.host_components.forEach(function (hostComponent) {
-          hostComponents.push(O.create({
-            componentName: hostComponent.HostRoles.component_name,
-            hostName: host.Hosts.host_name
-          }));
-        })
-      });
-      // if NameNode included, check HDFS NameNode checkpoint before restart NN
-      var nn_count = hostComponents.filterProperty('componentName', 
'NAMENODE').get('length');
-      if (nn_count == 1 && App.Service.find().filterProperty('serviceName', 
'HDFS').someProperty('workStatus', App.HostComponentStatus.started)) {
-        var hostName = hostComponents.findProperty('componentName', 
'NAMENODE').get('hostName');
-        
App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(function 
() {
-          batchUtils.restartHostComponents(hostComponents, 
Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
-        }, hostName);
-      } else if (nn_count == 2 && 
App.Service.find().filterProperty('serviceName', 
'HDFS').someProperty('workStatus', App.HostComponentStatus.started)) {
+    }, this._getComponentsFromServerForRestartCallback);
+  },
+
+  /**
+   *
+   * @param {object} data
+   * @private
+   * @method _getComponentsFromServerCallback
+   */
+  _getComponentsFromServerForRestartCallback: function (data) {
+    var hostComponents = [];
+    data.items.forEach(function (host) {
+      host.host_components.forEach(function (hostComponent) {
+        hostComponents.push(O.create({
+          componentName: hostComponent.HostRoles.component_name,
+          hostName: host.Hosts.host_name
+        }));
+      })
+    });
+    // if NameNode included, check HDFS NameNode checkpoint before restart NN
+    var isHDFSStarted = 'STARTED' === 
App.Service.find('HDFS').get('workStatus');
+    var namenodes = hostComponents.filterProperty('componentName', 'NAMENODE');
+    var nn_count = namenodes.get('length');
+
+    if (nn_count == 1 && isHDFSStarted) {
+      var hostName = namenodes.get('firstObject.hostName');
+      
App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(function 
() {
+        batchUtils.restartHostComponents(hostComponents, 
Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
+      }, hostName);
+    }
+    else {
+      if (nn_count == 2 && isHDFSStarted) {
         // HA enabled
         
App.router.get('mainServiceItemController').checkNnLastCheckpointTime(function 
() {
           batchUtils.restartHostComponents(hostComponents, 
Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
         });
-      } else {
+      }
+      else {
         batchUtils.restartHostComponents(hostComponents, 
Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
       }
-    });
+    }
   },
 
   /**
@@ -231,40 +232,51 @@ App.BulkOperationsController = Em.Controller.extend({
   bulkOperationForHostsPassiveState: function (operationData, hosts) {
     var self = this;
 
-    batchUtils.getComponentsFromServer({
+    return batchUtils.getComponentsFromServer({
       hosts: hosts.mapProperty('hostName'),
       displayParams: ['Hosts/maintenance_state']
     }, function (data) {
-      var hostNames = [];
+      return 
self._getComponentsFromServerForPassiveStateCallback(operationData, data)
+    });
+  },
 
-      data.items.forEach(function (host) {
-        if (host.Hosts.maintenance_state !== operationData.state) {
-          hostNames.push(host.Hosts.host_name);
-        }
-      });
-      if (hostNames.length) {
-        App.ajax.send({
-          name: 'bulk_request.hosts.passive_state',
-          sender: self,
-          data: {
-            hostNames: hostNames.join(','),
-            passive_state: operationData.state,
-            requestInfo: operationData.message
-          },
-          success: 'updateHostPassiveState'
-        });
-      } else {
-        App.ModalPopup.show({
-          header: Em.I18n.t('rolling.nothingToDo.header'),
-          body: Em.I18n.t('hosts.bulkOperation.passiveState.nothingToDo.body'),
-          secondary: false
-        });
+  /**
+   *
+   * @param {object} operationData
+   * @param {object} data
+   * @returns {$.ajax|App.ModalPopup}
+   * @private
+   * @method _getComponentsFromServerForPassiveStateCallback
+   */
+  _getComponentsFromServerForPassiveStateCallback: function (operationData, 
data) {
+    var hostNames = [];
+
+    data.items.forEach(function (host) {
+      if (host.Hosts.maintenance_state !== operationData.state) {
+        hostNames.push(host.Hosts.host_name);
       }
     });
+    if (hostNames.length) {
+      return App.ajax.send({
+        name: 'bulk_request.hosts.passive_state',
+        sender: this,
+        data: {
+          hostNames: hostNames.join(','),
+          passive_state: operationData.state,
+          requestInfo: operationData.message
+        },
+        success: 'updateHostPassiveState'
+      });
+    }
+    return App.ModalPopup.show({
+      header: Em.I18n.t('rolling.nothingToDo.header'),
+      body: Em.I18n.t('hosts.bulkOperation.passiveState.nothingToDo.body'),
+      secondary: false
+    });
   },
 
   updateHostPassiveState: function (data, opt, params) {
-    batchUtils.infoPassiveState(params.passive_state);
+    return batchUtils.infoPassiveState(params.passive_state);
   },
   /**
    * Bulk operation for selected hostComponents
@@ -274,35 +286,44 @@ App.BulkOperationsController = Em.Controller.extend({
   bulkOperationForHostComponents: function (operationData, hosts) {
     var self = this;
 
-    batchUtils.getComponentsFromServer({
+    return batchUtils.getComponentsFromServer({
       components: [operationData.componentName],
       hosts: hosts.mapProperty('hostName'),
       passiveState: 'OFF'
     }, function (data) {
-      if (data.items.length) {
-        var hostsWithComponentInProperState = 
data.items.mapProperty('Hosts.host_name');
-        App.ajax.send({
-          name: 'common.host_components.update',
-          sender: self,
-          data: {
-            HostRoles: {
-              state: operationData.action
-            },
-            query: 'HostRoles/component_name=' + operationData.componentName + 
'&HostRoles/host_name.in(' + hostsWithComponentInProperState.join(',') + 
')&HostRoles/maintenance_state=OFF',
-            context: operationData.message + ' ' + 
operationData.componentNameFormatted,
-            level: 'SERVICE',
-            noOpsMessage: operationData.componentNameFormatted
+      return 
self._getComponentsFromServerForHostComponentsCallback(operationData, data)
+    });
+  },
+
+  /**
+   *
+   * @param {object} operationData
+   * @param {object} data
+   * @returns {$.ajax|App.ModalPopup}
+   * @private
+   */
+  _getComponentsFromServerForHostComponentsCallback: function (operationData, 
data) {
+    if (data.items) {
+      var hostsWithComponentInProperState = 
data.items.mapProperty('Hosts.host_name');
+      return App.ajax.send({
+        name: 'common.host_components.update',
+        sender: this,
+        data: {
+          HostRoles: {
+            state: operationData.action
           },
-          success: 'bulkOperationForHostComponentsSuccessCallback'
-        });
-      }
-      else {
-        App.ModalPopup.show({
-          header: Em.I18n.t('rolling.nothingToDo.header'),
-          body: 
Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
-          secondary: false
-        });
-      }
+          query: 'HostRoles/component_name=' + operationData.componentName + 
'&HostRoles/host_name.in(' + hostsWithComponentInProperState.join(',') + 
')&HostRoles/maintenance_state=OFF',
+          context: operationData.message + ' ' + 
operationData.componentNameFormatted,
+          level: 'SERVICE',
+          noOpsMessage: operationData.componentNameFormatted
+        },
+        success: 'bulkOperationForHostComponentsSuccessCallback'
+      });
+    }
+    return App.ModalPopup.show({
+      header: Em.I18n.t('rolling.nothingToDo.header'),
+      body: 
Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
+      secondary: false
     });
   },
 
@@ -314,13 +335,13 @@ App.BulkOperationsController = Em.Controller.extend({
   bulkOperationForHostComponentsDecommission: function (operationData, hosts) {
     var self = this;
 
-    batchUtils.getComponentsFromServer({
+    return batchUtils.getComponentsFromServer({
       components: [operationData.realComponentName],
       hosts: hosts.mapProperty('hostName'),
       passiveState: 'OFF',
       displayParams: ['host_components/HostRoles/state']
     }, function (data) {
-      self.bulkOperationForHostComponentsDecommissionCallBack(operationData, 
data)
+      return 
self._getComponentsFromServerForHostComponentsDecommissionCallBack(operationData,
 data)
     });
   },
 
@@ -329,8 +350,9 @@ App.BulkOperationsController = Em.Controller.extend({
    * after host and components are loaded
    * @param operationData
    * @param data
+   * @method _getComponentsFromServerForHostComponentsDecommissionCallBack
    */
-  bulkOperationForHostComponentsDecommissionCallBack: function (operationData, 
data) {
+  _getComponentsFromServerForHostComponentsDecommissionCallBack: function 
(operationData, data) {
     var service = App.Service.find(operationData.serviceName);
     var components = [];
 
@@ -426,72 +448,76 @@ App.BulkOperationsController = Em.Controller.extend({
    */
   warnBeforeDecommissionSuccess: function(data, opt, params) {
     if (Em.get(data, 'items.length')) {
-      App.router.get('mainHostDetailsController').showHbaseActiveWarning();
-    } else {
-      
App.router.get('mainHostDetailsController').checkRegionServerState(params.hostNames);
+      return 
App.router.get('mainHostDetailsController').showHbaseActiveWarning();
     }
+    return 
App.router.get('mainHostDetailsController').checkRegionServerState(params.hostNames);
   },
+
   /**
    * Bulk restart for selected hostComponents
    * @param {Object} operationData
    * @param {Array} hosts
    */
   bulkOperationForHostComponentsRestart: function (operationData, hosts) {
-    var service = App.Service.find(operationData.serviceName);
-
-    batchUtils.getComponentsFromServer({
+    var self = this;
+    return batchUtils.getComponentsFromServer({
       components: [operationData.componentName],
       hosts: hosts.mapProperty('hostName'),
       passiveState: 'OFF',
       displayParams: ['Hosts/maintenance_state', 
'host_components/HostRoles/stale_configs', 
'host_components/HostRoles/maintenance_state']
     }, function (data) {
-      var wrappedHostComponents = [];
-
-      data.items.forEach(function (host) {
-        host.host_components.forEach(function (hostComponent) {
-          wrappedHostComponents.push(O.create({
-            componentName: hostComponent.HostRoles.component_name,
-            serviceName: operationData.serviceName,
-            hostName: host.Hosts.host_name,
-            hostPassiveState: host.Hosts.maintenance_state,
-            staleConfigs: hostComponent.HostRoles.stale_configs,
-            passiveState: hostComponent.HostRoles.maintenance_state
-          }))
-        });
+      return 
self._getComponentsFromServerForHostComponentsRestartCallback(operationData, 
data);
+    });
+  },
+
+  _getComponentsFromServerForHostComponentsRestartCallback: function 
(operationData, data) {
+    var wrappedHostComponents = [];
+    var service = App.Service.find(operationData.serviceName);
+
+    data.items.forEach(function (host) {
+      host.host_components.forEach(function (hostComponent) {
+        wrappedHostComponents.push(O.create({
+          componentName: hostComponent.HostRoles.component_name,
+          serviceName: operationData.serviceName,
+          hostName: host.Hosts.host_name,
+          hostPassiveState: host.Hosts.maintenance_state,
+          staleConfigs: hostComponent.HostRoles.stale_configs,
+          passiveState: hostComponent.HostRoles.maintenance_state
+        }));
       });
+    });
 
-      if (wrappedHostComponents.length) {
-        
batchUtils.showRollingRestartPopup(wrappedHostComponents.objectAt(0).get('componentName'),
 service.get('displayName'), service.get('passiveState') === "ON", false, 
wrappedHostComponents);
-      } else {
-        App.ModalPopup.show({
-          header: Em.I18n.t('rolling.nothingToDo.header'),
-          body: 
Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
-          secondary: false
-        });
-      }
+    if (wrappedHostComponents.length) {
+      return 
batchUtils.showRollingRestartPopup(wrappedHostComponents.objectAt(0).get('componentName'),
 service.get('displayName'), service.get('passiveState') === "ON", false, 
wrappedHostComponents);
+    }
+    return App.ModalPopup.show({
+      header: Em.I18n.t('rolling.nothingToDo.header'),
+      body: 
Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
+      secondary: false
     });
   },
 
   updateHostComponentsPassiveState: function (data, opt, params) {
-    batchUtils.infoPassiveState(params.passive_state);
+    return batchUtils.infoPassiveState(params.passive_state);
   },
+
   /**
    * Show BO popup after bulk request
+   * @method bulkOperationForHostComponentsSuccessCallback
    */
   bulkOperationForHostComponentsSuccessCallback: function (data, opt, params, 
req) {
     if (!data && req.status == 200) {
-      App.ModalPopup.show({
+      return App.ModalPopup.show({
         header: Em.I18n.t('rolling.nothingToDo.header'),
         body: Em.I18n.t('rolling.nothingToDo.body').format(params.noOpsMessage 
|| Em.I18n.t('hosts.host.maintainance.allComponents.context')),
         secondary: false
       });
-    } else {
-      
App.router.get('userSettingsController').dataLoading('show_bg').done(function 
(initValue) {
-        if (initValue) {
-          App.router.get('backgroundOperationsController').showPopup();
-        }
-      });
     }
+    return 
App.router.get('userSettingsController').dataLoading('show_bg').done(function 
(initValue) {
+      if (initValue) {
+        App.router.get('backgroundOperationsController').showPopup();
+      }
+    });
   },
 
   /**
@@ -501,14 +527,14 @@ App.BulkOperationsController = Em.Controller.extend({
    * @param {String} divider - string to separate hostNames
    * @param {Number} minShown - min amount of hostName to be shown
    * @returns {String} hostNames
-   * @method showHostNames
+   * @method _showHostNames
+   * @private
    */
-  showHostNames: function(hostNames, divider, minShown) {
+  _showHostNames: function(hostNames, divider, minShown) {
     if (hostNames.length > minShown) {
       return hostNames.slice(0, minShown).join(divider) + divider + 
Em.I18n.t("installer.step8.other").format(hostNames.length - minShown);
-    } else {
-      return hostNames.join(divider);
     }
+    return hostNames.join(divider);
   },
 
   /**
@@ -554,13 +580,11 @@ App.BulkOperationsController = Em.Controller.extend({
   },
 
   getHostsForBulkOperations: function (queryParams, operationData, 
loadingPopup) {
-    var params = 
App.router.get('updateController').computeParameters(queryParams);
-
-    App.ajax.send({
+    return App.ajax.send({
       name: 'hosts.bulk.operations',
       sender: this,
       data: {
-        parameters: params,
+        parameters: 
App.router.get('updateController').computeParameters(queryParams),
         operationData: operationData,
         loadingPopup: loadingPopup
       },
@@ -568,7 +592,7 @@ App.BulkOperationsController = Em.Controller.extend({
     });
   },
 
-  convertHostsObjects: function (hosts) {
+  _convertHostsObjects: function (hosts) {
     return hosts.map(function (host) {
       return {
         index: host.index,
@@ -582,72 +606,45 @@ App.BulkOperationsController = Em.Controller.extend({
   },
 
   getHostsForBulkOperationSuccessCallback: function(json, opt, param) {
-    var self = this,
-      operationData = param.operationData,
-      hosts = this.convertHostsObjects(App.hostsMapper.map(json, true));
+    var self = this;
+    var operationData = param.operationData;
+    var hosts = this._convertHostsObjects(App.hostsMapper.map(json, true));
     // no hosts - no actions
     if (!hosts.length) {
       console.log('No bulk operation if no hosts selected.');
       return;
     }
-    var hostNames = hosts.mapProperty('hostName');
-    var hostsToSkip = [];
-    if (operationData.action == "DECOMMISSION") {
-      var hostComponentStatusMap = {}; // "DATANODE_c6401.ambari.apache.org" 
=> "STARTED"
-      var hostComponentIdMap = {}; // "DATANODE_c6401.ambari.apache.org" => 
"DATANODE"
-      if (json.items) {
-        json.items.forEach(function(host) {
-          if (host.host_components) {
-            host.host_components.forEach(function(component) {
-              hostComponentStatusMap[component.id] = component.HostRoles.state;
-              hostComponentIdMap[component.id] = 
component.HostRoles.component_name;
-            });
-          }
-        });
-      }
-      hostsToSkip = hosts.filter(function(host) {
-        var invalidStateComponents = 
host.hostComponents.filter(function(component) {
-          return hostComponentIdMap[component] == 
operationData.realComponentName && hostComponentStatusMap[component] == 
'INSTALLED';
-        });
-        return invalidStateComponents.length > 0;
-      });
-    }
-    var hostNamesSkipped = hostsToSkip.mapProperty('hostName');
-    if (operationData.action === 'PASSIVE_STATE') {
-      hostNamesSkipped = [];
-      var outOfSyncHosts = 
App.StackVersion.find().findProperty('isCurrent').get('outOfSyncHosts');
-      for (var i = 0; i < outOfSyncHosts.length; i++) {
-        if (hostNames.contains(outOfSyncHosts[i])) {
-          hostNamesSkipped.push(outOfSyncHosts[i]);
-        }
-      }
-    }
-    var message;
-    if (operationData.componentNameFormatted) {
-      message = 
Em.I18n.t('hosts.bulkOperation.confirmation.hostComponents').format(operationData.message,
 operationData.componentNameFormatted, hostNames.length);
-    }
-    else {
-      message = 
Em.I18n.t('hosts.bulkOperation.confirmation.hosts').format(operationData.message,
 hostNames.length);
-    }
 
-    if (param.loadingPopup) {
-      param.loadingPopup.hide();
+    Em.tryInvoke(param.loadingPopup, 'hide');
+
+    if ('SET_RACK_INFO' === operationData.action) {
+      return self.bulkOperation(operationData, hosts);
     }
 
-    if (operationData.action === 'SET_RACK_INFO') {
-      self.bulkOperation(operationData, hosts);
-      return;
+    var hostNames = hosts.mapProperty('hostName');
+    var hostNamesSkipped = [];
+    if ('DECOMMISSION' === operationData.action) {
+      hostNamesSkipped = this._getSkippedForDecommissionHosts(json, hosts, 
operationData);
+    }
+    if ('PASSIVE_STATE' === operationData.action) {
+      hostNamesSkipped = this._getSkippedForPassiveStateHosts(hosts);
     }
 
-    App.ModalPopup.show({
+    var message = operationData.componentNameFormatted ?
+      
Em.I18n.t('hosts.bulkOperation.confirmation.hostComponents').format(operationData.message,
 operationData.componentNameFormatted, hostNames.length) :
+      
Em.I18n.t('hosts.bulkOperation.confirmation.hosts').format(operationData.message,
 hostNames.length);
+
+    return App.ModalPopup.show({
       header: Em.I18n.t('hosts.bulkOperation.confirmation.header'),
       hostNames: hostNames.join("\n"),
-      visibleHosts: self.showHostNames(hostNames, "\n", 3),
-      hostNamesSkippedVisible: self.showHostNames(hostNamesSkipped, "\n", 3),
+      visibleHosts: self._showHostNames(hostNames, "\n", 3),
+      hostNamesSkippedVisible: self._showHostNames(hostNamesSkipped, "\n", 3),
+      expanded: false,
+
       hostNamesSkipped: function() {
         return hostNamesSkipped.length ? hostNamesSkipped.join("\n") : false;
       }.property(),
-      expanded: false,
+
       didInsertElement: function() {
         this.set('expanded', hostNames.length <= 3);
       },
@@ -655,9 +652,12 @@ App.BulkOperationsController = Em.Controller.extend({
         self.bulkOperation(operationData, hosts);
         this._super();
       },
+
       bodyClass: Em.View.extend({
         templateName: 
require('templates/main/host/bulk_operation_confirm_popup'),
         message: message,
+        textareaVisible: false,
+
         warningInfo: function() {
           switch (operationData.action) {
             case "DECOMMISSION":
@@ -669,15 +669,17 @@ App.BulkOperationsController = Em.Controller.extend({
               return ""
           }
         }.property(),
-        textareaVisible: false,
+
         textTrigger: function() {
-          this.set('textareaVisible', !this.get('textareaVisible'));
+          this.toggleProperty('textareaVisible');
         },
+
         showAll: function() {
           this.set('parentView.visibleHosts', 
this.get('parentView.hostNames'));
           this.set('parentView.hostNamesSkippedVisible', 
this.get('parentView.hostNamesSkipped'));
           this.set('parentView.expanded', true);
         },
+
         putHostNamesToTextarea: function() {
           var hostNames = this.get('parentView.hostNames');
           if (this.get('textareaVisible')) {
@@ -688,8 +690,57 @@ App.BulkOperationsController = Em.Controller.extend({
             });
           }
         }.observes('textareaVisible')
+
       })
     });
+  },
+
+  /**
+   * @param {object} json
+   * @param {object[]} hosts
+   * @param {object} operationData
+   * @returns {string[]}
+   * @private
+   * @method _getSkippedForDecommissionHosts
+   */
+  _getSkippedForDecommissionHosts: function (json, hosts, operationData) {
+    var hostComponentStatusMap = {}; // "DATANODE_c6401.ambari.apache.org" => 
"STARTED"
+    var hostComponentIdMap = {}; // "DATANODE_c6401.ambari.apache.org" => 
"DATANODE"
+    if (json.items) {
+      json.items.forEach(function(host) {
+        if (host.host_components) {
+          host.host_components.forEach(function(component) {
+            hostComponentStatusMap[component.id] = component.HostRoles.state;
+            hostComponentIdMap[component.id] = 
component.HostRoles.component_name;
+          });
+        }
+      });
+    }
+    return hosts.filter(function(host) {
+      return host.hostComponents.filter(function(component) {
+        return hostComponentIdMap[component] == 
operationData.realComponentName && hostComponentStatusMap[component] == 
'INSTALLED';
+      }).length > 0;
+    }).mapProperty('hostName');
+  },
+
+  /**
+   * Exclude <code>outOfSyncHosts</code> hosts for PASSIVE request
+   *
+   * @param {object[]} hosts
+   * @returns {string[]}
+   * @private
+   * @method _getSkippedForPassiveStateHosts
+   */
+  _getSkippedForPassiveStateHosts: function (hosts) {
+    var hostNames = hosts.mapProperty('hostName');
+    var hostNamesSkipped = [];
+    var outOfSyncHosts = 
App.StackVersion.find().findProperty('isCurrent').get('outOfSyncHosts');
+    for (var i = 0; i < outOfSyncHosts.length; i++) {
+      if (hostNames.contains(outOfSyncHosts[i])) {
+        hostNamesSkipped.push(outOfSyncHosts[i]);
+      }
+    }
+    return hostNamesSkipped;
   }
 
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/db399a13/ambari-web/app/utils/batch_scheduled_requests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/batch_scheduled_requests.js 
b/ambari-web/app/utils/batch_scheduled_requests.js
index 09d86c8..c350b59 100644
--- a/ambari-web/app/utils/batch_scheduled_requests.js
+++ b/ambari-web/app/utils/batch_scheduled_requests.js
@@ -35,6 +35,7 @@ var defaultSuccessCallback = function(data, ajaxOptions, 
params) {
  * @param {String} textStatus
  * @param {String} error
  * @param {Object} opt
+ * @param {Object} params
  * @type {Function}
  */
 var defaultErrorCallback = function(xhr, textStatus, error, opt, params) {
@@ -73,7 +74,9 @@ module.exports = {
    */
   restartAllServiceHostComponents: function(serviceDisplayName, serviceName, 
staleConfigsOnly, query, runMmOperation) {
     var self = this;
-    var context = staleConfigsOnly ? 
Em.I18n.t('rollingrestart.context.allWithStaleConfigsForSelectedService').format(serviceDisplayName)
 : 
Em.I18n.t('rollingrestart.context.allForSelectedService').format(serviceDisplayName);
+    var context = staleConfigsOnly ?
+      
Em.I18n.t('rollingrestart.context.allWithStaleConfigsForSelectedService').format(serviceDisplayName)
 :
+      
Em.I18n.t('rollingrestart.context.allForSelectedService').format(serviceDisplayName);
 
     if (runMmOperation) {
       this.turnOnOffPassiveRequest('ON', 
Em.I18n.t('passiveState.turnOnFor').format(serviceName), serviceName);
@@ -99,7 +102,7 @@ module.exports = {
 
   /**
    * construct URL from parameters for request in 
<code>getComponentsFromServer()</code>
-   * @param options
+   * @param {object} options
    * @return {{fields: string, params: string}}
    */
   constructComponentsCallUrl: function (options) {
@@ -222,7 +225,7 @@ module.exports = {
     if (hostComponentsList.length > 0) {
       var serviceComponentName = hostComponentsList[0].get("componentName");
       var serviceName = 
App.StackServiceComponent.find(serviceComponentName).get('serviceName');
-      var operation_level = this.getOperationLevelobject(level, serviceName,
+      var operation_level = this.getOperationLevelObject(level, serviceName,
         serviceComponentName);
     }
 
@@ -251,18 +254,21 @@ module.exports = {
    * @param {String} serviceName
    * @param {String} componentName
    * @returns {Object} {{level: *, cluster_name: *}} - operation level object
-   * @method getOperationLevelobject - create operation level object to be 
included into ajax query
+   * @method getOperationLevelObject - create operation level object to be 
included into ajax query
    */
-  getOperationLevelobject: function(level, serviceName, componentName) {
+  getOperationLevelObject: function(level, serviceName, componentName) {
     var operationLevel = {
       "level": level,
       "cluster_name": App.get("clusterName")
     };
     if (level === "SERVICE") {
       operationLevel["service_name"] = serviceName;
-    } else if(level !== "HOST") {
-      operationLevel["service_name"] = serviceName;
-      operationLevel["hostcomponent_name"] = componentName;
+    }
+    else {
+      if (level !== "HOST") {
+        operationLevel["service_name"] = serviceName;
+        operationLevel["hostcomponent_name"] = componentName;
+      }
     }
     return operationLevel;
   },
@@ -282,6 +288,7 @@ module.exports = {
       'success': 'successCallback'
     });
   },
+
   /**
    * Makes a REST call to the server requesting the rolling restart of the
    * provided host components.
@@ -289,17 +296,18 @@ module.exports = {
    * @param {Number} batchSize size of each batch
    * @param {Number} intervalTimeSeconds delay between two batches
    * @param {Number} tolerateSize task failure tolerance
-   * @param {callback} successCallback
-   * @param {callback} errorCallback
+   * @param {callback} [successCallback]
+   * @param {callback} [errorCallback]
    */
   _doPostBatchRollingRestartRequest: function(restartHostComponents, 
batchSize, intervalTimeSeconds, tolerateSize, successCallback, errorCallback) {
     successCallback = successCallback || defaultSuccessCallback;
     errorCallback = errorCallback || defaultErrorCallback;
+
     if (!restartHostComponents.length) {
       console.log('No batch rolling restart if no restartHostComponents 
provided!');
       return;
     }
-    App.ajax.send({
+    return App.ajax.send({
       name: 'rolling_restart.post',
       sender: {
         successCallback: successCallback,
@@ -334,7 +342,7 @@ module.exports = {
       for ( var hc = 0; hc < batchSize && hostIndex < 
restartHostComponents.length; hc++) {
         
hostNames.push(restartHostComponents.objectAt(hostIndex++).get('hostName'));
       }
-      if (hostNames.length > 0) {
+      if (hostNames.length) {
         batches.push({
           "order_id" : count + 1,
           "type" : "POST",
@@ -370,18 +378,19 @@ module.exports = {
    */
   launchHostComponentRollingRestart: function(hostComponentName, serviceName, 
isMaintenanceModeOn, staleConfigsOnly, skipMaintenance) {
     if 
(App.get('components.rollinRestartAllowed').contains(hostComponentName)) {
-      this.showRollingRestartPopup(hostComponentName, serviceName, 
isMaintenanceModeOn, staleConfigsOnly, null, skipMaintenance);
-    }
-    else {
-      this.showWarningRollingRestartPopup(hostComponentName);
+      return this.showRollingRestartPopup(hostComponentName, serviceName, 
isMaintenanceModeOn, staleConfigsOnly, null, skipMaintenance);
     }
+    return this.showWarningRollingRestartPopup(hostComponentName);
   },
 
   /**
    * Show popup with rolling restart dialog
    * @param {String} hostComponentName name of the host components that should 
be restarted
+   * @param {String} serviceName
+   * @param {boolean} isMaintenanceModeOn
    * @param {bool} staleConfigsOnly restart only components with 
<code>staleConfigs</code> = true
-   * @param {App.hostComponent[]} hostComponents list of hostComponents that 
should be restarted (optional).
+   * @param {App.hostComponent[]} [hostComponents] list of hostComponents that 
should be restarted
+   * @param {boolean} [skipMaintenance]
    * Using this parameter will reset hostComponentName
    */
   showRollingRestartPopup: function(hostComponentName, serviceName, 
isMaintenanceModeOn, staleConfigsOnly, hostComponents, skipMaintenance) {
@@ -406,29 +415,30 @@ module.exports = {
         this.set('parentView.innerView', this);
         if (hostComponents.length) {
           view.initialize();
-        } else {
-          self.getComponentsFromServer({
-            components: [hostComponentName],
-            displayParams: ['host_components/HostRoles/stale_configs', 
'Hosts/maintenance_state', 'host_components/HostRoles/maintenance_state'],
-            staleConfigs: staleConfigsOnly ? staleConfigsOnly : null
-          }, function (data) {
-            var wrappedHostComponents = [];
-            data.items.forEach(function (host) {
-              host.host_components.forEach(function(hostComponent){
-                wrappedHostComponents.push(Em.Object.create({
-                  componentName: hostComponent.HostRoles.component_name,
-                  serviceName: 
App.StackServiceComponent.find(hostComponent.HostRoles.component_name).get('serviceName'),
-                  hostName: host.Hosts.host_name,
-                  staleConfigs: hostComponent.HostRoles.stale_configs,
-                  hostPassiveState: host.Hosts.maintenance_state,
-                  passiveState: hostComponent.HostRoles.maintenance_state
-                }));
-              });
+          return;
+        }
+
+        self.getComponentsFromServer({
+          components: [hostComponentName],
+          displayParams: ['host_components/HostRoles/stale_configs', 
'Hosts/maintenance_state', 'host_components/HostRoles/maintenance_state'],
+          staleConfigs: staleConfigsOnly ? staleConfigsOnly : null
+        }, function (data) {
+          var wrappedHostComponents = [];
+          data.items.forEach(function (host) {
+            host.host_components.forEach(function(hostComponent) {
+              wrappedHostComponents.push(Em.Object.create({
+                componentName: hostComponent.HostRoles.component_name,
+                serviceName: 
App.StackServiceComponent.find(hostComponent.HostRoles.component_name).get('serviceName'),
+                hostName: host.Hosts.host_name,
+                staleConfigs: hostComponent.HostRoles.stale_configs,
+                hostPassiveState: host.Hosts.maintenance_state,
+                passiveState: hostComponent.HostRoles.maintenance_state
+              }));
             });
-            view.set('allHostComponents', wrappedHostComponents);
-            view.initialize();
           });
-        }
+          view.set('allHostComponents', wrappedHostComponents);
+          view.initialize();
+        });
       }
     };
     if (hostComponents.length) {
@@ -472,14 +482,11 @@ module.exports = {
    * @param {String} hostComponentName
    */
   showWarningRollingRestartPopup: function(hostComponentName) {
-    var componentDisplayName = App.format.role(hostComponentName);
-    if (!componentDisplayName) {
-      componentDisplayName = hostComponentName;
-    }
+    var componentDisplayName = App.format.role(hostComponentName) || 
hostComponentName;
     var title = 
Em.I18n.t('rollingrestart.dialog.title').format(componentDisplayName);
     var msg = 
Em.I18n.t('rollingrestart.notsupported.hostComponent').format(componentDisplayName);
-    console.log(msg);
-    App.ModalPopup.show({
+
+    return App.ModalPopup.show({
       header : title,
       secondary : false,
       msg : msg,
@@ -491,18 +498,16 @@ module.exports = {
 
   /**
    * Warn user that alerts will be updated in few minutes
-   * @param {String} hostComponentName
+   * @param {String} passiveState
    */
   infoPassiveState: function(passiveState) {
     var enabled = passiveState == 'OFF' ? 'enabled' : 'suppressed';
     App.ModalPopup.show({
       header: Em.I18n.t('common.information'),
       secondary: null,
-      bodyClass: Ember.View.extend({
-        template: Ember.Handlebars.compile('<p>{{view.message}}</p>'),
-        message: function() {
-          return 
Em.I18n.t('hostPopup.warning.alertsTimeOut').format(passiveState.toLowerCase(), 
enabled);
-        }.property()
+      bodyClass: Em.View.extend({
+        template: Em.Handlebars.compile('<p>{{view.message}}</p>'),
+        message: 
Em.I18n.t('hostPopup.warning.alertsTimeOut').format(passiveState.toLowerCase(), 
enabled)
       })
     });
   },
@@ -519,16 +524,12 @@ module.exports = {
    */
   getRequestSchedule: function(requestScheduleId, successCallback, 
errorCallback) {
     if (requestScheduleId != null && !isNaN(requestScheduleId) && 
requestScheduleId > -1) {
-      errorCallback = errorCallback ? errorCallback : defaultErrorCallback;
+      errorCallback = errorCallback || defaultErrorCallback;
       App.ajax.send({
         name : 'request_schedule.get',
         sender : {
-          successCallbackFunction : function(data) {
-            successCallback(data);
-          },
-          errorCallbackFunction : function(xhr, textStatus, error, opt) {
-            errorCallback(xhr, textStatus, error, opt);
-          }
+          successCallbackFunction: successCallback,
+          errorCallbackFunction: errorCallback
         },
         data : {
           request_schedule_id : requestScheduleId
@@ -555,12 +556,8 @@ module.exports = {
       App.ajax.send({
         name : 'common.delete.request_schedule',
         sender : {
-          successCallbackFunction : function(data) {
-            successCallback(data);
-          },
-          errorCallbackFunction : function(xhr, textStatus, error, opt) {
-            errorCallback(xhr, textStatus, error, opt);
-          }
+          successCallbackFunction: successCallback,
+          errorCallbackFunction: errorCallback
         },
         data : {
           request_schedule_id : requestScheduleId

http://git-wip-us.apache.org/repos/asf/ambari/blob/db399a13/ambari-web/app/views/main/service/item.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/item.js 
b/ambari-web/app/views/main/service/item.js
index d141229..bfa98ca 100644
--- a/ambari-web/app/views/main/service/item.js
+++ b/ambari-web/app/views/main/service/item.js
@@ -17,7 +17,6 @@
  */
 
 var App = require('app');
-var batchUtils = require('utils/batch_scheduled_requests');
 
 App.MainServiceItemView = Em.View.extend({
   templateName: require('templates/main/service/item'),
@@ -230,19 +229,19 @@ App.MainServiceItemView = Em.View.extend({
       options.push(actionMap.DOWNLOAD_CLIENT_CONFIGS);
     }
 
-    if (!this.get('maintenance').length) {
-      this.set('maintenance', options);
-    } else {
+    if (this.get('maintenance.length')) {
       this.get('maintenance').forEach(function(option, index) {
-        if ( JSON.stringify(option) != JSON.stringify(options[index])  ) {
+        if (JSON.stringify(option) != JSON.stringify(options[index])) {
           self.get('maintenance').removeAt(index).insertAt(index, 
options[index]);
         }
       });
       options.forEach(function(opt, index) {
-        if ( JSON.stringify(opt) != 
JSON.stringify(self.get('maintenance')[index])  ) {
+        if (JSON.stringify(opt) != 
JSON.stringify(self.get('maintenance')[index])) {
           self.get('maintenance').pushObject(opt);
         }
       });
+    } else {
+      this.set('maintenance', options);
     }
     this.set('isMaintenanceSet', true);
   },
@@ -267,19 +266,22 @@ App.MainServiceItemView = Em.View.extend({
     this.get('controller').setStartStopState();
   },
 
+  maintenanceObsFields: ['isStopDisabled', 'isClientsOnlyService', 
'content.isRestartRequired', 'isServicesInfoLoaded'],
+
   willInsertElement: function () {
-    this.addObserver('controller.isStopDisabled', this, 'observeMaintenance');
-    this.addObserver('controller.isClientsOnlyService', this, 
'observeMaintenance');
-    this.addObserver('controller.content.isRestartRequired', this, 
'observeMaintenance');
-    this.addObserver('controller.isServicesInfoLoaded', this, 
'observeMaintenance');
+    var self = this;
+    this.get('maintenanceObsFields').forEach(function (field) {
+      self.addObserver('controller.' + field, self, 'observeMaintenance');
+    });
   },
 
   willDestroyElement: function() {
-    this.removeObserver('controller.isStopDisabled', this, 
'observeMaintenance');
-    this.removeObserver('controller.isClientsOnlyService', this, 
'observeMaintenance');
-    this.removeObserver('controller.content.isRestartRequired', this, 
'observeMaintenance');
-    this.removeObserver('controller.isServicesInfoLoaded', this, 
'observeMaintenance');
+    var self = this;
+    this.get('maintenanceObsFields').forEach(function (field) {
+      self.removeObserver('controller.' + field, self, 'observeMaintenance');
+    });
   },
+
   service:function () {
     var svc = this.get('controller.content');
     var svcName = svc.get('serviceName');

Reply via email to