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);
+ });
+ });
+
+ });
+
});