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/23 21:18:01 UTC
git commit: AMBARI-4390. Add ability to abort Rolling Restart.
(srimanth)
Updated Branches:
refs/heads/trunk 67b7c76fd -> e5d440b4f
AMBARI-4390. Add ability to abort Rolling Restart. (srimanth)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/e5d440b4
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/e5d440b4
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/e5d440b4
Branch: refs/heads/trunk
Commit: e5d440b4f1eb342e0bcd92b792fdc4240a44395f
Parents: 67b7c76
Author: Srimanth Gunturi <sg...@hortonworks.com>
Authored: Wed Jan 22 15:26:51 2014 -0800
Committer: Srimanth Gunturi <sg...@hortonworks.com>
Committed: Thu Jan 23 11:51:03 2014 -0800
----------------------------------------------------------------------
.../global/background_operations_controller.js | 75 +++++++++++++++++---
ambari-web/app/controllers/main/service.js | 8 ++-
ambari-web/app/controllers/main/service/item.js | 4 +-
ambari-web/app/messages.js | 3 +
ambari-web/app/styles/application.less | 7 ++
.../templates/common/host_progress_popup.hbs | 18 +++++
ambari-web/app/utils/ajax.js | 13 ++++
.../app/utils/batch_scheduled_requests.js | 75 +++++++++++++++++++-
ambari-web/app/utils/host_progress_popup.js | 69 +++++++++++++++++-
9 files changed, 255 insertions(+), 17 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/e5d440b4/ambari-web/app/controllers/global/background_operations_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/background_operations_controller.js b/ambari-web/app/controllers/global/background_operations_controller.js
index 04a5339..9905cef 100644
--- a/ambari-web/app/controllers/global/background_operations_controller.js
+++ b/ambari-web/app/controllers/global/background_operations_controller.js
@@ -178,7 +178,9 @@ App.BackgroundOperationsController = Em.Controller.extend({
hostsMap: {},
tasks: [],
dependentService: requestParams.dependentService,
- previousTaskStatusMap: {}
+ sourceRequestScheduleId: request.Requests.source_schedule_id,
+ previousTaskStatusMap: {},
+ contextCommand: requestParams.contextCommand
});
self.get("services").unshift(rq);
}
@@ -202,15 +204,24 @@ App.BackgroundOperationsController = Em.Controller.extend({
parseRequestContext: function (requestContext) {
var parsedRequestContext;
var service;
- var command;
+ var contextCommand;
if (requestContext) {
- if (requestContext.indexOf("_PARSE_") !== -1) {
- command = requestContext.split('.')[1];
- service = requestContext.split('.')[2];
- if (service === 'ALL_SERVICES') {
- parsedRequestContext = Em.I18n.t("requestInfo." + command.toLowerCase()).format(Em.I18n.t('common.allServices'));
- } else {
- parsedRequestContext = Em.I18n.t("requestInfo." + command.toLowerCase()).format(App.Service.DisplayNames[service]);
+ if (requestContext.indexOf(App.BackgroundOperationsController.CommandContexts.PREFIX) !== -1) {
+ var contextSplits = requestContext.split('.');
+ contextCommand = contextSplits[1];
+ service = contextSplits[2];
+ switch(contextCommand){
+ case "STOP":
+ case "START":
+ if (service === 'ALL_SERVICES') {
+ parsedRequestContext = Em.I18n.t("requestInfo." + contextCommand.toLowerCase()).format(Em.I18n.t('common.allServices'));
+ } else {
+ parsedRequestContext = Em.I18n.t("requestInfo." + contextCommand.toLowerCase()).format(App.Service.DisplayNames[service]);
+ }
+ break;
+ case "ROLLING-RESTART":
+ parsedRequestContext = Em.I18n.t("rollingrestart.rest.context").format(App.format.role(service), contextSplits[3], contextSplits[4]);
+ break;
}
} else {
parsedRequestContext = requestContext;
@@ -220,7 +231,8 @@ App.BackgroundOperationsController = Em.Controller.extend({
}
return {
requestContext: parsedRequestContext,
- dependentService: service
+ dependentService: service,
+ contextCommand: contextCommand
}
},
@@ -246,3 +258,46 @@ App.BackgroundOperationsController = Em.Controller.extend({
}
});
+
+/**
+ * Each background operation has a context in which it operates.
+ * Generally these contexts are fixed messages. However, we might
+ * want to associate semantics to this context - like showing, disabling
+ * buttons when certain operations are in progress.
+ *
+ * To make this possible we have command contexts where the context
+ * is not a human readable string, but a pattern indicating the command
+ * it is running. When UI shows these, they are translated into human
+ * readable strings.
+ *
+ * General pattern of context names is "_PARSE_.{COMMAND}.{ID}[.{Additional-Data}...]"
+ */
+App.BackgroundOperationsController.CommandContexts = {
+ PREFIX : "_PARSE_",
+ /**
+ * Stops all services
+ */
+ STOP_ALL_SERVICES : "_PARSE_.STOP.ALL_SERVICES",
+ /**
+ * Starts all services
+ */
+ START_ALL_SERVICES : "_PARSE_.START.ALL_SERVICES",
+ /**
+ * Starts service indicated by serviceID.
+ * @param {String} serviceID Parameter {0}. Example: HDFS
+ */
+ START_SERVICE : "_PARSE_.START.{0}",
+ /**
+ * Stops service indicated by serviceID.
+ * @param {String} serviceID Parameter {0}. Example: HDFS
+ */
+ STOP_SERVICE : "_PARSE_.STOP.{0}",
+ /**
+ * Performs rolling restart of componentID in batches.
+ * This context is the batchNumber batch out of totalBatchCount batches.
+ * @param {String} componentID Parameter {0}. Example "DATANODE"
+ * @param {Number} batchNumber Parameter {1}. Batch number of this batch. Example 3.
+ * @param {Number} totalBatchCount Parameter {2}. Total number of batches. Example 10.
+ */
+ ROLLING_RESTART : "_PARSE_.ROLLING-RESTART.{0}.{1}.{2}"
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e5d440b4/ambari-web/app/controllers/main/service.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service.js b/ambari-web/app/controllers/main/service.js
index 766fee3..27c26e2 100644
--- a/ambari-web/app/controllers/main/service.js
+++ b/ambari-web/app/controllers/main/service.js
@@ -121,9 +121,13 @@ App.MainServiceController = Em.ArrayController.extend({
allServicesCall: function(state) {
var data;
if (state == 'stopAllService') {
- data = '{"RequestInfo": {"context" :"_PARSE_.STOP.ALL_SERVICES"}, "Body": {"ServiceInfo": {"state": "INSTALLED"}}}';
+ data = '{"RequestInfo": {"context" :"' +
+ App.BackgroundOperationsController.CommandContexts.STOP_ALL_SERVICES +
+ '"}, "Body": {"ServiceInfo": {"state": "INSTALLED"}}}';
} else {
- data = '{"RequestInfo": {"context" :"_PARSE_.START.ALL_SERVICES"}, "Body": {"ServiceInfo": {"state": "STARTED"}}}';
+ data = '{"RequestInfo": {"context" :"' +
+ App.BackgroundOperationsController.CommandContexts.START_ALL_SERVICES +
+ '"}, "Body": {"ServiceInfo": {"state": "STARTED"}}}';
}
App.ajax.send({
http://git-wip-us.apache.org/repos/asf/ambari/blob/e5d440b4/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 91e353c..b1c7b27 100644
--- a/ambari-web/app/controllers/main/service/item.js
+++ b/ambari-web/app/controllers/main/service/item.js
@@ -103,9 +103,9 @@ App.MainServiceItemController = Em.Controller.extend({
startStopPopupPrimary: function (serviceHealth) {
var requestInfo = "";
if (serviceHealth == "STARTED") {
- requestInfo = '_PARSE_.START.' + this.get('content.serviceName');
+ requestInfo = App.BackgroundOperationsController.CommandContexts.START_SERVICE.format(this.get('content.serviceName'));
} else {
- requestInfo = '_PARSE_.STOP.' + this.get('content.serviceName');
+ requestInfo = App.BackgroundOperationsController.CommandContexts.STOP_SERVICE.format(this.get('content.serviceName'));
}
App.ajax.send({
http://git-wip-us.apache.org/repos/asf/ambari/blob/e5d440b4/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index e41b8df..1bf7a52 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -202,6 +202,9 @@ Em.I18n.translations = {
'hostPopup.status.category.aborted':'Aborted ({0})',
'hostPopup.status.category.timedout':'Timedout ({0})',
'hostPopup.header.postFix':' Background Operations Running',
+ 'hostPopup.bgop.sourceRequestSchedule.running': 'Future operations of this batch request can be aborted',
+ 'hostPopup.bgop.sourceRequestSchedule.aborted': 'Future operations of this batch request have been aborted',
+ 'hostPopup.bgop.abort.rollingRestart': 'Abort Rolling Restart',
'question.sure':'Are you sure?',
http://git-wip-us.apache.org/repos/asf/ambari/blob/e5d440b4/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index 30aabb6..50015c7 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -1443,6 +1443,13 @@ width:100%;
cursor: pointer;
}
+ .request-schedule-abort {
+ margin-top: 7px;
+ .btn {
+ margin-top: -5px;
+ }
+ }
+
.task-top-wrap {
width: 100%;
http://git-wip-us.apache.org/repos/asf/ambari/blob/e5d440b4/ambari-web/app/templates/common/host_progress_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/host_progress_popup.hbs b/ambari-web/app/templates/common/host_progress_popup.hbs
index 7e43c9c..3827820 100644
--- a/ambari-web/app/templates/common/host_progress_popup.hbs
+++ b/ambari-web/app/templates/common/host_progress_popup.hbs
@@ -82,6 +82,24 @@
}}
</div>
</div>
+ {{#if view.isRequestSchedule}}
+ {{#if view.sourceRequestScheduleRunning}}
+ <div class="alert alert-info request-schedule-abort">
+ {{t hostPopup.bgop.sourceRequestSchedule.running}}
+ <button type="button" class="btn btn-warning pull-right"
+ {{action doAbortRequestSchedule view.sourceRequestScheduleId target="view"}}>
+ {{view.requestScheduleAbortLabel}}
+ </button>
+ </div>
+ {{/if}}
+ {{#if view.sourceRequestScheduleAborted}}
+ <div class="alert alert-info request-schedule-abort">
+ {{t hostPopup.bgop.sourceRequestSchedule.aborted}}
+ </div>
+ {{/if}}
+ {{/if}}
+ </div>
+ </div>
<div id="host-info">
{{#if view.isHostEmptyList}}
<div class="log-list-wrap">{{t hostPopup.noHostsToShow}}</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/e5d440b4/ambari-web/app/utils/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax.js b/ambari-web/app/utils/ajax.js
index fb1ae7d..c7d73a1 100644
--- a/ambari-web/app/utils/ajax.js
+++ b/ambari-web/app/utils/ajax.js
@@ -1294,6 +1294,19 @@ var urls = {
}
}
},
+ 'request_schedule.delete': {
+ 'real': '/clusters/{clusterName}/request_schedules/{request_schedule_id}',
+ 'mock': '',
+ 'format' : function(data) {
+ return {
+ type : 'DELETE',
+ }
+ }
+ },
+ 'request_schedule.get': {
+ 'real': '/clusters/{clusterName}/request_schedules/{request_schedule_id}',
+ 'mock': '',
+ },
'restart.service.hostComponents' : {
'real' : '/clusters/{clusterName}/requests',
'mock' : '',
http://git-wip-us.apache.org/repos/asf/ambari/blob/e5d440b4/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 bf9164f..33dad38 100644
--- a/ambari-web/app/utils/batch_scheduled_requests.js
+++ b/ambari-web/app/utils/batch_scheduled_requests.js
@@ -163,7 +163,6 @@ module.exports = {
batchCount = Math.ceil(restartHostComponents.length / batchSize),
sampleHostComponent = restartHostComponents.objectAt(0),
componentName = sampleHostComponent.get('componentName'),
- componentDisplayName = App.format.role(componentName),
serviceName = sampleHostComponent.get('service.serviceName');
for ( var count = 0; count < batchCount; count++) {
@@ -178,7 +177,7 @@ module.exports = {
"uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
"RequestBodyInfo" : {
"RequestInfo" : {
- "context" : Em.I18n.t('rollingrestart.rest.context').format(componentDisplayName, (count + 1), batchCount),
+ "context" : "_PARSE_.ROLLING-RESTART." + componentName + "." + (count + 1) + "." + batchCount,
"command" : "RESTART",
"service_name" : serviceName,
"component_name" : componentName,
@@ -258,5 +257,77 @@ module.exports = {
})
});
}
+ },
+
+ /**
+ * Retrieves the latest information about a specific request schedule
+ * identified by 'requestScheduleId'
+ *
+ * @param {Number}
+ * requestScheduleId ID of the request schedule to get
+ * @param {Function}
+ * successCallback Called with request_schedule data from server. An
+ * empty object returned for invalid ID.
+ * @param {Function}
+ * errorCallback Optional error callback. Default behavior is to
+ * popup default error dialog.
+ */
+ getRequestSchedule: function(requestScheduleId, successCallback, errorCallback) {
+ if (requestScheduleId != null && !isNaN(requestScheduleId) && requestScheduleId > -1) {
+ errorCallback = 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);
+ }
+ },
+ data : {
+ request_schedule_id : requestScheduleId,
+ },
+ success : 'successCallbackFunction',
+ error : 'errorCallbackFunction'
+ });
+ } else {
+ successCallback({});
+ }
+ },
+
+ /**
+ * Attempts to abort a specific request schedule identified by 'requestScheduleId'
+ *
+ * @param {Number}
+ * requestScheduleId ID of the request schedule to get
+ * @param {Function}
+ * successCallback Called when request schedule successfully aborted
+ * @param {Function}
+ * errorCallback Optional error callback. Default behavior is to
+ * popup default error dialog.
+ */
+ doAbortRequestSchedule: function(requestScheduleId, successCallback, errorCallback) {
+ if (requestScheduleId != null && !isNaN(requestScheduleId) && requestScheduleId > -1) {
+ errorCallback = errorCallback ? errorCallback : defaultErrorCallback;
+ App.ajax.send({
+ name : 'request_schedule.delete',
+ sender : {
+ successCallbackFunction : function(data) {
+ successCallback(data);
+ },
+ errorCallbackFunction : function(xhr, textStatus, error, opt) {
+ errorCallback(xhr, textStatus, error, opt);
+ }
+ },
+ data : {
+ request_schedule_id : requestScheduleId,
+ },
+ success : 'successCallbackFunction',
+ error : 'errorCallbackFunction'
+ });
+ } else {
+ successCallback({});
+ }
}
};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/e5d440b4/ambari-web/app/utils/host_progress_popup.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/host_progress_popup.js b/ambari-web/app/utils/host_progress_popup.js
index e20b7da..fe921eb 100644
--- a/ambari-web/app/utils/host_progress_popup.js
+++ b/ambari-web/app/utils/host_progress_popup.js
@@ -17,6 +17,7 @@
*/
var App = require('app');
+var batchUtils = require('utils/batch_scheduled_requests');
/**
* App.HostPopup is for the popup that shows up upon clicking already-performed or currently-in-progress operations
@@ -244,7 +245,9 @@ App.HostPopup = Em.Object.create({
icon: status[1],
barColor: status[2],
isInProgress: status[3],
- barWidth: "width:" + service.progress + "%;"
+ barWidth: "width:" + service.progress + "%;",
+ sourceRequestScheduleId: service.get('sourceRequestScheduleId'),
+ contextCommand: service.get('contextCommand')
});
allNewServices.push(newService);
});
@@ -467,6 +470,10 @@ App.HostPopup = Em.Object.create({
isHostEmptyList: true,
isTasksEmptyList: true,
controller: this,
+ sourceRequestScheduleId: -1,
+ sourceRequestScheduleRunning: false,
+ sourceRequestScheduleAborted: false,
+ sourceRequestScheduleCommand: null,
hosts: self.get('hosts'),
services: self.get('servicesInfo'),
@@ -722,8 +729,68 @@ App.HostPopup = Em.Object.create({
this.set('hosts', this.get('hosts').concat(servicesInfo.slice(50, servicesInfo.length)));
});
}
+ // Determine if source request schedule is present
+ this.set('sourceRequestScheduleId', event.context.get("sourceRequestScheduleId"));
+ this.set('sourceRequestScheduleCommand', event.context.get('contextCommand'));
+ this.refreshRequestScheduleInfo();
},
+ isRequestSchedule : function() {
+ var id = this.get('sourceRequestScheduleId');
+ return id != null && !isNaN(id) && id > -1;
+ }.property('sourceRequestScheduleId'),
+
+ refreshRequestScheduleInfo : function() {
+ var self = this;
+ var id = this.get('sourceRequestScheduleId');
+ batchUtils.getRequestSchedule(id, function(data) {
+ if (data != null && data.RequestSchedule.status != null) {
+ switch (data.RequestSchedule.status) {
+ case 'DISABLED':
+ self.set('sourceRequestScheduleRunning', false);
+ self.set('sourceRequestScheduleAborted', true);
+ break;
+ case 'COMPLETED':
+ self.set('sourceRequestScheduleRunning', false);
+ self.set('sourceRequestScheduleAborted', false);
+ break;
+ case 'SCHEDULED':
+ self.set('sourceRequestScheduleRunning', true);
+ self.set('sourceRequestScheduleAborted', false);
+ break;
+ }
+ } else {
+ self.set('sourceRequestScheduleRunning', false);
+ self.set('sourceRequestScheduleAborted', false);
+ }
+ }, function(xhr, textStatus, error, opt) {
+ console.log("Error getting request schedule information: ", textStatus, error, opt);
+ self.set('sourceRequestScheduleRunning', false);
+ self.set('sourceRequestScheduleAborted', false);
+ });
+ }.observes('sourceRequestScheduleId'),
+
+ /**
+ * Attempts to abort the current request schedule
+ */
+ doAbortRequestSchedule: function(event){
+ var self = this;
+ var id = event.context;
+ console.log("Aborting request schedule: ", id);
+ batchUtils.doAbortRequestSchedule(id, function(){
+ self.refreshRequestScheduleInfo();
+ });
+ },
+
+ requestScheduleAbortLabel : function() {
+ var label = Em.I18n.t("common.abort");
+ var command = this.get('sourceRequestScheduleCommand');
+ if (command != null && "ROLLING-RESTART" == command) {
+ label = Em.I18n.t("hostPopup.bgop.abort.rollingRestart");
+ }
+ return label;
+ }.property('sourceRequestScheduleCommand'),
+
/**
* Onclick handler for selected Host
* @param event