You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2014/02/04 15:42:55 UTC

git commit: AMBARI-4521. Bulk Ops: Restart on Slaves should popup rolling restart dialog. (onechiporenko)

Updated Branches:
  refs/heads/trunk 7057e558e -> 2d8117e01


AMBARI-4521. Bulk Ops: Restart on Slaves should popup rolling restart dialog. (onechiporenko)


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

Branch: refs/heads/trunk
Commit: 2d8117e01ec89b0d7524b4cb1bdc96d0412ee0a5
Parents: 7057e55
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Tue Feb 4 16:41:05 2014 +0200
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Tue Feb 4 16:42:49 2014 +0200

----------------------------------------------------------------------
 ambari-web/app/app.js                           |   1 +
 ambari-web/app/controllers/main/host.js         |   2 +-
 .../app/utils/batch_scheduled_requests.js       | 130 ++++++++++++-------
 .../app/views/common/rolling_restart_view.js    |  87 +++++++++++--
 .../test/utils/batch_scheduled_requests_test.js |  32 +++++
 5 files changed, 192 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2d8117e0/ambari-web/app/app.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/app.js b/ambari-web/app/app.js
index a8eb611..9d834af 100644
--- a/ambari-web/app/app.js
+++ b/ambari-web/app/app.js
@@ -77,6 +77,7 @@ module.exports = Em.Application.create({
     reassignable: ['NAMENODE', 'SECONDARY_NAMENODE', 'JOBTRACKER', 'RESOURCEMANAGER'],
     restartable: ['APP_TIMELINE_SERVER'],
     deletable: ['SUPERVISOR', 'HBASE_MASTER'],
+    rollinRestartAllowed: ["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER", "SUPERVISOR"],
     slaves: function() {
       return require('data/service_components').filter(function(component){
         return !component.isClient && !component.isMaster

http://git-wip-us.apache.org/repos/asf/ambari/blob/2d8117e0/ambari-web/app/controllers/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host.js b/ambari-web/app/controllers/main/host.js
index 050cfbc..fba9dac 100644
--- a/ambari-web/app/controllers/main/host.js
+++ b/ambari-web/app/controllers/main/host.js
@@ -370,7 +370,7 @@ App.MainHostController = Em.ArrayController.extend({
     });
 
     if (components.length) {
-      batchUtils._doPostBatchRollingRestartRequest(components, components.length, 1, 1);
+      batchUtils.showRollingRestartPopup(components.objectAt(0).get('componentName'), false, components);
     }
     else {
       App.ModalPopup.show({

http://git-wip-us.apache.org/repos/asf/ambari/blob/2d8117e0/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 088c83c..68f7382 100644
--- a/ambari-web/app/utils/batch_scheduled_requests.js
+++ b/ambari-web/app/utils/batch_scheduled_requests.js
@@ -65,7 +65,7 @@ module.exports = {
   /**
    * Facade-function for restarting host components of specific service
    * @param {String} serviceName for which service hostComponents should be restarted
-   * @param {Boolean} staleConfigsOnly restart only hostComponents with <code>staleConfig</code> true
+   * @param {bool} staleConfigsOnly restart only hostComponents with <code>staleConfig</code> true
    */
   restartAllServiceHostComponents: function(serviceName, staleConfigsOnly) {
     var service = App.Service.find(serviceName);
@@ -198,65 +198,95 @@ module.exports = {
    * @param {String} hostComponentName
    *           Type of host-component to restart across cluster
    *          (ex: DATANODE)
-   * @param {Boolean} staleConfigsOnly
+   * @param {bool} staleConfigsOnly
    *           Pre-select host-components which have stale
    *          configurations
    */
   launchHostComponentRollingRestart: function(hostComponentName, staleConfigsOnly) {
+    if (App.get('components.rollinRestartAllowed').contains(hostComponentName)) {
+      this.showRollingRestartPopup(hostComponentName, staleConfigsOnly);
+    }
+    else {
+      this.showWarningRollingRestartPopup(hostComponentName);
+    }
+  },
+
+  /**
+   * Show popup with rolling restart dialog
+   * @param {String} hostComponentName name of the host components that should be restarted
+   * @param {bool} staleConfigsOnly restart only components with <code>staleConfigs</code> = true
+   * @param {App.hostComponent[]} hostComponents list of hostComponents that should be restarted (optional).
+   * Using this parameter will reset hostComponentName
+   */
+  showRollingRestartPopup: function(hostComponentName, staleConfigsOnly, hostComponents) {
+    hostComponents = hostComponents || [];
     var componentDisplayName = App.format.role(hostComponentName);
     if (!componentDisplayName) {
       componentDisplayName = hostComponentName;
     }
-    var self = this;
     var title = Em.I18n.t('rollingrestart.dialog.title').format(componentDisplayName);
-    var allowedHostComponents = ["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER", "SUPERVISOR"];
-    if (allowedHostComponents.contains(hostComponentName)) {
-      App.ModalPopup.show({
-        header : title,
-        hostComponentName : hostComponentName,
-        staleConfigsOnly : staleConfigsOnly,
-        innerView : null,
-        bodyClass : App.RollingRestartView.extend({
-          hostComponentName : hostComponentName,
-          staleConfigsOnly : staleConfigsOnly,
-          didInsertElement : function() {
-            this.set('parentView.innerView', this);
-            this.initialize();
-          }
-        }),
-        classNames : [ 'rolling-restart-popup' ],
-        primary : Em.I18n.t('rollingrestart.dialog.primary'),
-        onPrimary : function() {
-          var dialog = this;
-          if (!dialog.get('enablePrimary')) {
-            return;
-          }
-          var restartComponents = this.get('innerView.restartHostComponents');
-          var batchSize = this.get('innerView.batchSize');
-          var waitTime = this.get('innerView.interBatchWaitTimeSeconds');
-          var tolerateSize = this.get('innerView.tolerateSize');
-          self._doPostBatchRollingRestartRequest(restartComponents, batchSize, waitTime, tolerateSize, function() {
-            dialog.hide();
-            defaultSuccessCallback();
-          });
-        },
-        updateButtons : function() {
-          var errors = this.get('innerView.errors');
-          this.set('enablePrimary', !(errors != null && errors.length > 0))
-        }.observes('innerView.errors')
-      });
-    } else {
-      var msg = Em.I18n.t('rollingrestart.notsupported.hostComponent').format(componentDisplayName);
-      console.log(msg);
-      App.ModalPopup.show({
-        header : title,
-        secondary : false,
-        msg : msg,
-        bodyClass : Ember.View.extend({
-          template : Ember.Handlebars.compile('<div class="alert alert-warning">{{msg}}</div>')
-        })
-      });
+    var viewExtend = {
+      staleConfigsOnly : staleConfigsOnly,
+      hostComponentName : hostComponentName,
+      didInsertElement : function() {
+        this.set('parentView.innerView', this);
+        this.initialize();
+      }
+    };
+    if (hostComponents.length) {
+      viewExtend.allHostComponents = hostComponents;
     }
+
+    var self = this;
+    App.ModalPopup.show({
+      header : title,
+      hostComponentName : hostComponentName,
+      staleConfigsOnly : staleConfigsOnly,
+      innerView : null,
+      bodyClass : App.RollingRestartView.extend(viewExtend),
+      classNames : [ 'rolling-restart-popup' ],
+      primary : Em.I18n.t('rollingrestart.dialog.primary'),
+      onPrimary : function() {
+        var dialog = this;
+        if (!dialog.get('enablePrimary')) {
+          return;
+        }
+        var restartComponents = this.get('innerView.restartHostComponents');
+        var batchSize = this.get('innerView.batchSize');
+        var waitTime = this.get('innerView.interBatchWaitTimeSeconds');
+        var tolerateSize = this.get('innerView.tolerateSize');
+        self._doPostBatchRollingRestartRequest(restartComponents, batchSize, waitTime, tolerateSize, function() {
+          dialog.hide();
+          defaultSuccessCallback();
+        });
+      },
+      updateButtons : function() {
+        var errors = this.get('innerView.errors');
+        this.set('enablePrimary', !(errors != null && errors.length > 0))
+      }.observes('innerView.errors')
+    });
+  },
+
+  /**
+   * Show warning popup about not supported host components
+   * @param {String} hostComponentName
+   */
+  showWarningRollingRestartPopup: function(hostComponentName) {
+    var componentDisplayName = App.format.role(hostComponentName);
+    if (!componentDisplayName) {
+      componentDisplayName = 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({
+      header : title,
+      secondary : false,
+      msg : msg,
+      bodyClass : Em.View.extend({
+        template : Em.Handlebars.compile('<div class="alert alert-warning">{{msg}}</div>')
+      })
+    });
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/2d8117e0/ambari-web/app/views/common/rolling_restart_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/rolling_restart_view.js b/ambari-web/app/views/common/rolling_restart_view.js
index e27dede..045fac7 100644
--- a/ambari-web/app/views/common/rolling_restart_view.js
+++ b/ambari-web/app/views/common/rolling_restart_view.js
@@ -25,12 +25,44 @@ var numberUtils = require('utils/number_utils');
  */
 App.RollingRestartView = Em.View.extend({
   templateName : require('templates/common/rolling_restart_view'),
+
+  /**
+   * Component name for components that should be restarted
+   * @type {String}
+   */
   hostComponentName : null,
+
+  /**
+   * Restart only components with <code>staleConfigs</code>
+   * @type {bool}
+   */
   staleConfigsOnly : false,
+
+  /**
+   * Count of host components in one batch
+   * @type {Number}
+   */
   batchSize : -1,
+
+  /**
+   * Delay between batches
+   * @type {Number}
+   */
   interBatchWaitTimeSeconds : -1,
+
+  /**
+   * @type {Number}
+   */
   tolerateSize : -1,
-  errors : null,
+
+  /**
+   * List of error in batch-request properties
+   * @type {Array}
+   */
+  errors : [],
+  /**
+   * Set initial values for batch-request properties
+   */
   initialize : function() {
     if (this.get('batchSize') == -1 && this.get('interBatchWaitTimeSeconds') == -1 && this.get('tolerateSize') == -1) {
       var restartCount = this.get('restartHostComponents');
@@ -44,6 +76,11 @@ App.RollingRestartView = Em.View.extend({
       this.set('interBatchWaitTimeSeconds', 120);
     }
   },
+
+  /**
+   * Validate batch-request properties
+   * List of errors is saved to <code>errors</code>
+   */
   validate : function() {
     var displayName = this.get('hostComponentDisplayName');
     var totalCount = this.get('restartHostComponents.length');
@@ -67,24 +104,40 @@ App.RollingRestartView = Em.View.extend({
     if (waitError != null) {
       errors.push(Em.I18n.t('rollingrestart.dialog.err.invalid.waitTime').format(waitError));
     }
-    if (errors.length < 1) {
-      errors = null;
-    }
     this.set('errors', errors);
   }.observes('batchSize', 'interBatchWaitTimeSeconds', 'tolerateSize', 'restartHostComponents', 'hostComponentDisplayName'),
+
+  /**
+   * Formatted <code>hostComponentName</code>
+   * @type {String}
+   */
   hostComponentDisplayName : function() {
     return App.format.role(this.get('hostComponentName'));
   }.property('hostComponentName'),
+
+  /**
+   * List of all host components
+   * @type {Array}
+   */
   allHostComponents : function() {
     return App.HostComponent.find().filterProperty('componentName', this.get('hostComponentName'));
   }.property('hostComponentName'),
+
+  /**
+   * List of host components without components in out-of-service state
+   * @type {Array}
+   */
   nonMaintainanceHostComponents : function() {
-    var hostComponents = this.get('allHostComponents');
-    hostComponents = hostComponents.filter(function(item) {
-      return item.get('workStatus') !== App.HostComponentStatus.maintenance;
+    return this.get('allHostComponents').filter(function(item) {
+      return item.get('passiveState') == 'ACTIVE';
     });
-    return hostComponents;
-  }.property('allHostComponents', 'allHostComponents.@each.workStatus'),
+  }.property('allHostComponents', 'allHostComponents.@each.passiveState'),
+
+  /**
+   * List of host components without components in out-of-service state
+   * If <code>staleConfigsOnly</code> is true, components with <code>staleConfigs</code> = false are also filtered
+   * @type {Array}
+   */
   restartHostComponents : function() {
     var hostComponents = this.get('nonMaintainanceHostComponents');
     if (this.get('staleConfigsOnly')) {
@@ -92,6 +145,10 @@ App.RollingRestartView = Em.View.extend({
     }
     return hostComponents;
   }.property('nonMaintainanceHostComponents', 'staleConfigsOnly'),
+
+  /**
+   * @type {String}
+   */
   restartMessage : function() {
     var rhc = this.get('restartHostComponents.length');
     if (rhc > 1) {
@@ -99,6 +156,10 @@ App.RollingRestartView = Em.View.extend({
     }
     return Em.I18n.t('rollingrestart.dialog.msg.restart').format(rhc, this.get('hostComponentDisplayName'))
   }.property('restartHostComponents', 'hostComponentDisplayName'),
+
+  /**
+   * @type {String}
+   */
   maintainanceMessage : function() {
     var allCount = this.get('allHostComponents.length');
     var nonMaintainCount = this.get('nonMaintainanceHostComponents.length');
@@ -112,9 +173,17 @@ App.RollingRestartView = Em.View.extend({
     }
     return null;
   }.property('allHostComponents', 'nonMaintainanceHostComponents', 'hostComponentDisplayName'),
+
+  /**
+   * @type {String}
+   */
   batchSizeMessage : function() {
     return Em.I18n.t('rollingrestart.dialog.msg.componentsAtATime').format(this.get('hostComponentDisplayName'));
   }.property('hostComponentDisplayName'),
+
+  /**
+   * @type {String}
+   */
   staleConfigsOnlyMessage : function() {
     return Em.I18n.t('rollingrestart.dialog.msg.staleConfigsOnly').format(this.get('hostComponentDisplayName'));
   }.property('hostComponentDisplayName')

http://git-wip-us.apache.org/repos/asf/ambari/blob/2d8117e0/ambari-web/test/utils/batch_scheduled_requests_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/batch_scheduled_requests_test.js b/ambari-web/test/utils/batch_scheduled_requests_test.js
index 3c4508e..1964696 100644
--- a/ambari-web/test/utils/batch_scheduled_requests_test.js
+++ b/ambari-web/test/utils/batch_scheduled_requests_test.js
@@ -17,6 +17,7 @@
 
 var App = require('app');
 require('utils/helper');
+require('views/common/rolling_restart_view');
 var batchUtils = require('utils/batch_scheduled_requests');
 
 describe('batch_scheduled_requests', function() {
@@ -86,4 +87,35 @@ describe('batch_scheduled_requests', function() {
     });
   });
 
+  describe('#launchHostComponentRollingRestart', function() {
+
+    beforeEach(function() {
+      sinon.spy(batchUtils, 'showRollingRestartPopup');
+      sinon.spy(batchUtils, 'showWarningRollingRestartPopup');
+    });
+
+    afterEach(function() {
+      batchUtils.showRollingRestartPopup.restore();
+      batchUtils.showWarningRollingRestartPopup.restore();
+    });
+
+    var tests = Em.A([
+      {componentName: 'DATANODE', e:{showRollingRestartPopup:true, showWarningRollingRestartPopup:false}},
+      {componentName: 'TASKTRACKER', e:{showRollingRestartPopup:true, showWarningRollingRestartPopup:false}},
+      {componentName: 'NODEMANAGER', e:{showRollingRestartPopup:true, showWarningRollingRestartPopup:false}},
+      {componentName: 'HBASE_REGIONSERVER', e:{showRollingRestartPopup:true, showWarningRollingRestartPopup:false}},
+      {componentName: 'SUPERVISOR', e:{showRollingRestartPopup:true, showWarningRollingRestartPopup:false}},
+      {componentName: 'SOME_OTHER_COMPONENT', e:{showRollingRestartPopup:false, showWarningRollingRestartPopup:true}}
+    ]);
+
+    tests.forEach(function(test) {
+      it(test.componentName, function() {
+        batchUtils.launchHostComponentRollingRestart(test.componentName);
+        expect(batchUtils.showRollingRestartPopup.calledOnce).to.equal(test.e.showRollingRestartPopup);
+        expect(batchUtils.showWarningRollingRestartPopup.calledOnce).to.equal(test.e.showWarningRollingRestartPopup);
+      });
+    });
+
+  });
+
 });