You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sr...@apache.org on 2014/01/10 22:31:48 UTC
git commit: BUG-12052. Implement rolling restart dialog. (srimanth)
Updated Branches:
refs/heads/trunk dbb345b6a -> 3e81b773f
BUG-12052. Implement rolling restart dialog. (srimanth)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3e81b773
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3e81b773
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3e81b773
Branch: refs/heads/trunk
Commit: 3e81b773f72c06c2ce7a6c07ce9ae1a214712f41
Parents: dbb345b
Author: Srimanth Gunturi <sg...@hortonworks.com>
Authored: Fri Jan 10 12:39:54 2014 -0800
Committer: Srimanth Gunturi <sg...@hortonworks.com>
Committed: Fri Jan 10 13:21:16 2014 -0800
----------------------------------------------------------------------
ambari-web/app/controllers/main/service/item.js | 8 +
ambari-web/app/messages.js | 21 +++
ambari-web/app/styles/application.less | 27 +++
.../templates/common/rolling_restart_view.hbs | 62 +++++++
ambari-web/app/utils/ajax.js | 53 ++++++
.../app/utils/batch_scheduled_requests.js | 167 +++++++++++++++++++
ambari-web/app/views.js | 1 +
.../app/views/common/rolling_restart_view.js | 125 ++++++++++++++
ambari-web/app/views/main/service/item.js | 10 +-
9 files changed, 473 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/3e81b773/ambari-web/app/controllers/main/service/item.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js
index 325e738..72cec23 100644
--- a/ambari-web/app/controllers/main/service/item.js
+++ b/ambari-web/app/controllers/main/service/item.js
@@ -18,6 +18,7 @@
var App = require('app');
var service_components = require('data/service_components');
+var batchUtils = require('utils/batch_scheduled_requests');
App.MainServiceItemController = Em.Controller.extend({
name: 'mainServiceItemController',
@@ -186,6 +187,13 @@ App.MainServiceItemController = Em.Controller.extend({
});
},
+ restartAllHostComponents: function(event) {
+ },
+
+ rollingRestart: function(hostComponentName) {
+ batchUtils.launchHostComponentRollingRestart(hostComponentName, false);
+ },
+
runSmokeTestPrimary: function() {
App.ajax.send({
'name': 'service.item.smoke',
http://git-wip-us.apache.org/repos/asf/ambari/blob/3e81b773/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 9b1d6bf..ea1500d 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1759,6 +1759,27 @@ Em.I18n.translations = {
'mirroring.dateOrder.error': 'End Date must be after Start Date',
'mirroring.required.invalidNumberError' : 'Enter valid number',
+ 'rollingrestart.dialog.title': 'Rolling Restart {0}s',
+ 'rollingrestart.dialog.primary': 'Trigger Restart',
+ 'rollingrestart.notsupported.hostComponent': 'Rolling restart not supported for {0} components',
+ 'rollingrestart.dialog.msg.restart': 'This will restart {0} {1} in batches to keep your cluster operational and minimize downtime.',
+ 'rollingrestart.dialog.msg.restart.plural': 'This will restart {0} {1}s in batches to keep your cluster operational and minimize downtime.',
+ 'rollingrestart.dialog.msg.noRestartHosts': 'There are no {0}s to do rolling restarts',
+ 'rollingrestart.dialog.msg.maintainance': 'Note: {0} {1} in Maintainance Mode will not be restarted',
+ 'rollingrestart.dialog.msg.maintainance.plural': 'Note: {0} {1}s in Maintainance Mode will not be restarted',
+ 'rollingrestart.dialog.msg.componentsAtATime': '{0}s at a time',
+ 'rollingrestart.dialog.msg.timegap.prefix': 'Wait ',
+ 'rollingrestart.dialog.msg.timegap.suffix': 'seconds between batches ',
+ 'rollingrestart.dialog.msg.toleration.prefix': 'Tolerate up to ',
+ 'rollingrestart.dialog.msg.toleration.suffix': 'failures',
+ 'rollingrestart.dialog.err.empty.batchsize': 'Restart batch size cannot be empty',
+ 'rollingrestart.dialog.err.empty.waittime': 'Wait interval cannot be empty',
+ 'rollingrestart.dialog.err.empty.tolerate': 'Failure toleration size cannot be empty',
+ 'rollingrestart.dialog.err.invalid.batchsize': 'Restart batch size should be between 1 and {0}',
+ 'rollingrestart.dialog.err.invalid.waitTime': 'Wait time cannot be negative',
+ 'rollingrestart.dialog.err.invalid.toleratesize': 'Failure toleration cannot be negative',
+ 'rollingrestart.dialog.msg.staleConfigsOnly': 'Only restart {0}s with stale configs',
+ 'rollingrestart.rest.context': 'Rolling Restart of {0}s - batch {1} of {2}',
'menu.item.dashboard':'Dashboard',
'menu.item.heatmaps':'Heatmaps',
http://git-wip-us.apache.org/repos/asf/ambari/blob/3e81b773/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index ab97c5e..e919a43 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -5172,3 +5172,30 @@ i.icon-asterisks {
.margin-bottom-5 {
margin-bottom: 5px;
}
+
+.rolling-restart-view {
+ table {
+ td:first-of-type {
+ width: 30%;
+ text-align: right;
+ }
+ td:nth-of-type(2) {
+ input {
+ margin-left: 7px;
+ margin-right: 5px;
+ }
+ }
+ td:last-of-type {
+ width: 60%;
+ text-align: left;
+ }
+ tr:last-of-type {
+ td {
+ text-align: center;
+ input {
+ vertical-align: top;
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/3e81b773/ambari-web/app/templates/common/rolling_restart_view.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/rolling_restart_view.hbs b/ambari-web/app/templates/common/rolling_restart_view.hbs
new file mode 100644
index 0000000..8b38044
--- /dev/null
+++ b/ambari-web/app/templates/common/rolling_restart_view.hbs
@@ -0,0 +1,62 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class="rolling-restart-view">
+ <div class="alert alert-info">
+ <p>
+ {{view.restartMessage}}
+ </p>
+ {{#if view.maintainanceMessage}}
+ <p>
+ {{view.maintainanceMessage}}
+ </p>
+ {{/if}}
+ </div>
+ <table>
+ <tr>
+ <td>{{t common.restart}}</td>
+ <td>{{view Ember.TextField valueBinding="view.batchSize" class="span1"}}</td>
+ <td>{{view.batchSizeMessage}}</td>
+ </tr>
+ <tr>
+ <td>{{t rollingrestart.dialog.msg.timegap.prefix}}</td>
+ <td>{{view Ember.TextField valueBinding="view.interBatchWaitTimeSeconds" class="span1"}}</td>
+ <td>{{t rollingrestart.dialog.msg.timegap.suffix}}</td>
+ </tr>
+ <tr>
+ <td>{{t rollingrestart.dialog.msg.toleration.prefix}}</td>
+ <td>{{view Ember.TextField valueBinding="view.tolerateSize" class="span1"}}</td>
+ <td>{{t rollingrestart.dialog.msg.toleration.suffix}}</td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ {{view Ember.Checkbox checkedBinding="view.staleConfigsOnly"}}
+ {{view.staleConfigsOnlyMessage}}
+ </td>
+ </tr>
+ </table>
+ {{#if view.errors}}
+ <div class="alert alert-warn">
+ <ul>
+ {{#each error in view.errors}}
+ <li>{{error}}</li>
+ {{/each}}
+ </ul>
+ </div>
+ {{/if}}
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/3e81b773/ambari-web/app/utils/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax.js b/ambari-web/app/utils/ajax.js
index 992f12d..e690b67 100644
--- a/ambari-web/app/utils/ajax.js
+++ b/ambari-web/app/utils/ajax.js
@@ -1269,6 +1269,59 @@ var urls = {
data: JSON.stringify(data.data)
}
}
+ },
+ 'rolling_restart.post': {
+ 'real': '/clusters/{clusterName}/request_schedules',
+ 'mock': '',
+ 'format' : function(data) {
+ var hostIndex = 0;
+ var batchSize = data.batchSize;
+ var hostComponents = data.restartHostComponents;
+ var length = hostComponents.length;
+ var batches = [];
+ var batchCount = Math.ceil(length / batchSize);
+ var sampleHostComponent = hostComponents.objectAt(0);
+ var componentName = sampleHostComponent.get('componentName');
+ var componentDisplayName = App.format.role(componentName);
+ var serviceName = sampleHostComponent.get('service.serviceName');
+ for ( var count = 0; count < batchCount; count++) {
+ var hostNames = [];
+ for ( var hc = 0; hc < batchSize && hostIndex < length; hc++) {
+ hostNames.push(hostComponents.objectAt(hostIndex++).get('host.hostName'));
+ }
+ if (hostNames.length > 0) {
+ batches.push({
+ "order_id" : count + 1,
+ "type" : "POST",
+ "uri" : "/api/v1/clusters/" + data.clusterName + "/requests",
+ "RequestBodyInfo" : {
+ "RequestInfo" : {
+ "context" : Em.I18n.t('rollingrestart.rest.context').format(componentDisplayName, (count + 1), batchCount),
+ "command" : "RESTART",
+ "service_name" : serviceName,
+ "component_name" : componentName,
+ "hosts" : hostNames.join(",")
+ }
+ }
+ });
+ }
+ }
+ return {
+ type : 'POST',
+ data : JSON.stringify([ {
+ "RequestSchedule" : {
+ "batch" : [ {
+ "requests" : batches
+ }, {
+ "batch_settings" : {
+ "batch_separation_in_seconds" : data.intervalTimeSeconds,
+ "task_failure_tolerance" : data.tolerateSize
+ }
+ } ]
+ }
+ } ])
+ }
+ }
}
};
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/3e81b773/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
new file mode 100644
index 0000000..2f8ae78
--- /dev/null
+++ b/ambari-web/app/utils/batch_scheduled_requests.js
@@ -0,0 +1,167 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/**
+ * Contains helpful utilities for handling batch and scheduled requests.
+ */
+module.exports = {
+
+ /**
+ * Some services have components which have a need for rolling restarts. This
+ * method returns the name of the host-component which supports rolling
+ * restarts for a service.
+ */
+ getRollingRestartComponentName : function(serviceName) {
+ var rollingRestartComponent = null;
+ switch (serviceName) {
+ case 'HDFS':
+ rollingRestartComponent = 'DATANODE';
+ break;
+ case 'YARN':
+ rollingRestartComponent = 'NODEMANAGER';
+ break;
+ case 'MAPREDUCE':
+ rollingRestartComponent = 'TASKTRACKER';
+ break;
+ case 'HBASE':
+ rollingRestartComponent = 'HBASE_REGIONSERVER';
+ break;
+ case 'STORM':
+ rollingRestartComponent = 'SUPERVISOR';
+ break;
+ default:
+ break;
+ }
+ return rollingRestartComponent;
+ },
+
+ /**
+ * Makes a REST call to the server requesting the rolling restart of the
+ * provided host components.
+ */
+ doPostBatchRollingRestartRequest : function(restartHostComponents, batchSize, intervalTimeSeconds, tolerateSize, successCallback, errorCallback) {
+ var clusterName = App.get('clusterName');
+ var data = {
+ restartHostComponents : restartHostComponents,
+ batchSize : batchSize,
+ intervalTimeSeconds : intervalTimeSeconds,
+ tolerateSize : tolerateSize,
+ clusterName : clusterName
+ }
+ var sender = {
+ successFunction : function() {
+ successCallback();
+ },
+ errorFunction : function(xhr, textStatus, error, opt) {
+ errorCallback(xhr, textStatus, error, opt);
+ }
+ }
+ App.ajax.send({
+ name : 'rolling_restart.post',
+ sender : sender,
+ data : data,
+ success : 'successFunction',
+ error : 'errorFunction'
+ });
+ },
+
+ /**
+ * Launches dialog to handle rolling restarts of host components.
+ *
+ * Rolling restart is supported for the following host components only
+ * <ul>
+ * <li>Data Nodes (HDFS)
+ * <li>Task Trackers (MapReduce)
+ * <li>Node Managers (YARN)
+ * <li>Region Servers (HBase)
+ * <li>Supervisors (Storm)
+ * </ul>
+ *
+ * @param {String}
+ * hostComponentName Type of host-component to restart across cluster
+ * (ex: DATANODE)
+ * @param {Boolean}
+ * staleConfigsOnly Pre-select host-components which have stale
+ * configurations
+ */
+ launchHostComponentRollingRestart : function(hostComponentName, staleConfigsOnly) {
+ var componentDisplayName = App.format.role(hostComponentName);
+ if (!componentDisplayName) {
+ componentDisplayName = hostComponentName;
+ }
+ var self = this;
+ var title = Em.I18n.t('rollingrestart.dialog.title').format(componentDisplayName)
+ if (hostComponentName == "DATANODE" || hostComponentName == "TASKTRACKER" || hostComponentName == "NODEMANAGER"
+ || hostComponentName == "HBASE_REGIONSERVER" || hostComponentName == "SUPERVISOR") {
+ 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'),
+ secondary : Em.I18n.t('common.cancel'),
+ onPrimary : function() {
+ var dialog = this;
+ if (!dialog.get('enablePrimary')) {
+ return false;
+ }
+ 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();
+ }, function(xhr, textStatus, error, opt) {
+ App.ajax.defaultErrorHandler(xhr, opt.url, 'POST', xhr.status);
+ });
+ return;
+ },
+ onSecondary : function() {
+ this.hide();
+ },
+ onClose : function() {
+ this.hide();
+ },
+ 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>'),
+ msg : msg
+ })
+ });
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/3e81b773/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index 9a9b36a..ed21192 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -25,6 +25,7 @@ require('views/common/chart/pie');
require('views/common/chart/linear');
require('views/common/chart/linear_time');
require('views/common/modal_popup');
+require('views/common/rolling_restart_view');
require('views/common/metric');
require('views/common/time_range');
require('views/common/form/field');
http://git-wip-us.apache.org/repos/asf/ambari/blob/3e81b773/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
new file mode 100644
index 0000000..2671ddd
--- /dev/null
+++ b/ambari-web/app/views/common/rolling_restart_view.js
@@ -0,0 +1,125 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+var App = require('app');
+
+/**
+ * View content of the rolling restart dialog.
+ *
+ * Callers provide the context in which this dialog is invoked.
+ */
+App.RollingRestartView = Em.View.extend({
+ templateName : require('templates/common/rolling_restart_view'),
+ hostComponentName : null,
+ staleConfigsOnly : false,
+ batchSize : -1,
+ interBatchWaitTimeSeconds : -1,
+ tolerateSize : -1,
+ errors : null,
+ initialize : function() {
+ if (this.get('batchSize') == -1 && this.get('interBatchWaitTimeSeconds') == -1 && this.get('tolerateSize') == -1) {
+ var restartCount = this.get('restartHostComponents');
+ var batchSize = 1;
+ if (restartCount > 10) {
+ batchSize = Math.ceil(restartCount / 10);
+ }
+ var tolerateCount = batchSize;
+ this.set('batchSize', batchSize);
+ this.set('tolerateSize', tolerateCount);
+ this.set('interBatchWaitTimeSeconds', 120);
+ }
+ },
+ validate : function() {
+ var displayName = this.get('hostComponentDisplayName');
+ var totalCount = this.get('restartHostComponents.length');
+ var bs = this.get('batchSize');
+ var ts = this.get('tolerateSize');
+ var wait = this.get('interBatchWaitTimeSeconds');
+ var errors = [];
+ if (totalCount < 1) {
+ errors.push(Em.I18n.t('rollingrestart.dialog.msg.noRestartHosts').format(displayName));
+ } else {
+ if (!bs) {
+ errors.push(Em.I18n.t('rollingrestart.dialog.err.empty.batchsize'));
+ } else if (bs > totalCount || bs < 0) {
+ errors.push(Em.I18n.t('rollingrestart.dialog.err.invalid.batchsize').format(totalCount));
+ }
+ if (!ts) {
+ errors.push(Em.I18n.t('rollingrestart.dialog.err.empty.waittime'));
+ } else if (ts < 0) {
+ errors.push(Em.I18n.t('rollingrestart.dialog.err.invalid.toleratesize'));
+ }
+ }
+ if (!wait) {
+ errors.push(Em.I18n.t('rollingrestart.dialog.err.empty.tolerate'));
+ } else if (wait < 0) {
+ errors.push(Em.I18n.t('rollingrestart.dialog.err.invalid.waitTime'));
+ }
+ if (errors.length < 1) {
+ errors = null;
+ }
+ this.set('errors', errors);
+ }.observes('batchSize', 'interBatchWaitTimeSeconds', 'tolerateSize', 'restartHostComponents', 'hostComponentDisplayName'),
+ hostComponentDisplayName : function() {
+ return App.format.role(this.get('hostComponentName'));
+ }.property('hostComponentName'),
+ allHostComponents : function() {
+ return App.HostComponent.find().filterProperty('componentName', this.get('hostComponentName'));
+ }.property('hostComponentName'),
+ nonMaintainanceHostComponents : function() {
+ var hostComponents = this.get('allHostComponents');
+ hostComponents = hostComponents.filter(function(item) {
+ if (item.get('workStatus') !== App.HostComponentStatus.maintenance) {
+ return true;
+ }
+ });
+ return hostComponents;
+ }.property('allHostComponents', 'allHostComponents.@each.workStatus'),
+ restartHostComponents : function() {
+ var hostComponents = this.get('nonMaintainanceHostComponents');
+ if (this.get('staleConfigsOnly')) {
+ hostComponents = hostComponents.filterProperty('staleConfigs', true);
+ }
+ return hostComponents;
+ }.property('nonMaintainanceHostComponents', 'staleConfigsOnly'),
+ restartMessage : function() {
+ var rhc = this.get('restartHostComponents.length');
+ if (rhc > 1) {
+ return Em.I18n.t('rollingrestart.dialog.msg.restart.plural').format(rhc, this.get('hostComponentDisplayName'))
+ }
+ return Em.I18n.t('rollingrestart.dialog.msg.restart').format(rhc, this.get('hostComponentDisplayName'))
+ }.property('restartHostComponents', 'hostComponentDisplayName'),
+ maintainanceMessage : function() {
+ var allCount = this.get('allHostComponents.length');
+ var nonMaintainCount = this.get('nonMaintainanceHostComponents.length');
+ var count = allCount - nonMaintainCount;
+ if (count > 0) {
+ var name = this.get('hostComponentDisplayName');
+ if (count > 1) {
+ return Em.I18n.t('rollingrestart.dialog.msg.maintainance.plural').format(count, name)
+ }
+ return Em.I18n.t('rollingrestart.dialog.msg.maintainance').format(count, name)
+ }
+ return null;
+ }.property('allHostComponents', 'nonMaintainanceHostComponents', 'hostComponentDisplayName'),
+ batchSizeMessage : function() {
+ return Em.I18n.t('rollingrestart.dialog.msg.componentsAtATime').format(this.get('hostComponentDisplayName'));
+ }.property('hostComponentDisplayName'),
+ 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/3e81b773/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 fc1adcf..e67b303 100644
--- a/ambari-web/app/views/main/service/item.js
+++ b/ambari-web/app/views/main/service/item.js
@@ -17,6 +17,7 @@
*/
var App = require('app');
+var batchUtils = require('utils/batch_scheduled_requests');
App.MainServiceItemView = Em.View.extend({
templateName: require('templates/main/service/item'),
@@ -26,7 +27,8 @@ App.MainServiceItemView = Em.View.extend({
var hosts = App.Host.find().content.length;
var allMasters = this.get('controller.content.hostComponents').filterProperty('isMaster').mapProperty('componentName').uniq();
var disabled = this.get('controller.isStopDisabled');
- switch (service.get('serviceName')) {
+ var serviceName = service.get('serviceName');
+ switch (serviceName) {
case 'GANGLIA':
case 'NAGIOS':
break;
@@ -44,6 +46,12 @@ App.MainServiceItemView = Em.View.extend({
default:
options.push({action: 'runSmokeTest', 'label': Em.I18n.t('services.service.actions.run.smoke').format(service.get('serviceName')), disabled:disabled});
}
+
+ var rrComponentName = batchUtils.getRollingRestartComponentName(serviceName);
+ if (rrComponentName) {
+ var label = Em.I18n.t('rollingrestart.dialog.title').format(App.format.role(rrComponentName));
+ options.push({action:'rollingRestart', context: rrComponentName, 'label': label, disabled: false});
+ }
return options;
}.property('controller.content', 'controller.isStopDisabled'),
isMaintenanceActive: function() {