|
@@ -15,6 +15,31 @@
|
|
|
* the License.
|
|
|
*/
|
|
|
|
|
|
+var App = require('app');
|
|
|
+
|
|
|
+/**
|
|
|
+ * Default success callback for ajax-requests in this module
|
|
|
+ * @type {Function}
|
|
|
+ */
|
|
|
+var defaultSuccessCallback = function() {
|
|
|
+ App.router.get('applicationController').dataLoading().done(function(initValue) {
|
|
|
+ if (initValue) {
|
|
|
+ App.router.get('backgroundOperationsController').showPopup();
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+/**
|
|
|
+ * Default error callback for ajax-requests in this module
|
|
|
+ * @param {Object} xhr
|
|
|
+ * @param {String} textStatus
|
|
|
+ * @param {String} error
|
|
|
+ * @param {Object} opt
|
|
|
+ * @type {Function}
|
|
|
+ */
|
|
|
+var defaultErrorCallback = function(xhr, textStatus, error, opt) {
|
|
|
+ App.ajax.defaultErrorHandler(xhr, opt.url, 'POST', xhr.status);
|
|
|
+};
|
|
|
+
|
|
|
/**
|
|
|
* Contains helpful utilities for handling batch and scheduled requests.
|
|
|
*/
|
|
@@ -24,35 +49,28 @@ 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.
|
|
|
+ * @param {String} serviceName
|
|
|
*/
|
|
|
- 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;
|
|
|
+ getRollingRestartComponentName: function(serviceName) {
|
|
|
+ var rollingRestartComponents = {
|
|
|
+ HDFS: 'DATANODE',
|
|
|
+ YARN: 'NODEMANAGER',
|
|
|
+ MAPREDUCE: 'TASKTRACKER',
|
|
|
+ HBASE: 'HBASE_REGIONSERVER',
|
|
|
+ STORM: 'SUPERVISOR'
|
|
|
+ };
|
|
|
+ return rollingRestartComponents[serviceName] ? rollingRestartComponents[serviceName] : null;
|
|
|
},
|
|
|
|
|
|
- restartAllServiceHostComponents : function(serviceName, staleConfigsOnly) {
|
|
|
+ /**
|
|
|
+ * 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
|
|
|
+ */
|
|
|
+ restartAllServiceHostComponents: function(serviceName, staleConfigsOnly) {
|
|
|
var service = App.Service.find(serviceName);
|
|
|
if (service) {
|
|
|
- var hostComponents = service.get('hostComponents')
|
|
|
+ var hostComponents = service.get('hostComponents').filterProperty('isClient', false);
|
|
|
if (staleConfigsOnly) {
|
|
|
hostComponents = hostComponents.filterProperty('staleConfigs', true);
|
|
|
}
|
|
@@ -60,42 +78,42 @@ module.exports = {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- restartHostComponents : function(hostComponentsList) {
|
|
|
+ /**
|
|
|
+ * Restart list of host components
|
|
|
+ * @param {Array} hostComponentsList list of host components should be restarted
|
|
|
+ */
|
|
|
+ restartHostComponents: function(hostComponentsList) {
|
|
|
+ /**
|
|
|
+ * Format: {
|
|
|
+ * 'DATANODE': ['host1', 'host2'],
|
|
|
+ * 'NAMENODE': ['host1', 'host3']
|
|
|
+ * ...
|
|
|
+ * }
|
|
|
+ * @type {Object}
|
|
|
+ */
|
|
|
var componentToHostsMap = {};
|
|
|
- var componentToServiceMap = {};
|
|
|
+ var componentServiceMap = App.QuickDataMapper.componentServiceMap();
|
|
|
hostComponentsList.forEach(function(hc) {
|
|
|
var componentName = hc.get('componentName');
|
|
|
if (!componentToHostsMap[componentName]) {
|
|
|
componentToHostsMap[componentName] = [];
|
|
|
}
|
|
|
componentToHostsMap[componentName].push(hc.get('host.hostName'));
|
|
|
- componentToServiceMap[componentName] = hc.get('service.serviceName');
|
|
|
});
|
|
|
- for ( var componentName in componentToHostsMap) {
|
|
|
- var hosts = componentToHostsMap[componentName].join(",");
|
|
|
- var data = {
|
|
|
- serviceName : componentToServiceMap[componentName],
|
|
|
- componentName : componentName,
|
|
|
- hosts : hosts
|
|
|
- }
|
|
|
- var sender = {
|
|
|
- successFunction : function() {
|
|
|
- App.router.get('applicationController').dataLoading().done(function(initValue) {
|
|
|
- if (initValue) {
|
|
|
- App.router.get('backgroundOperationsController').showPopup();
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- errorFunction : function(xhr, textStatus, error, opt) {
|
|
|
- App.ajax.defaultErrorHandler(xhr, opt.url, 'POST', xhr.status);
|
|
|
- }
|
|
|
- }
|
|
|
+ for (var componentName in componentToHostsMap) {
|
|
|
App.ajax.send({
|
|
|
- name : 'restart.service.hostComponents',
|
|
|
- sender : sender,
|
|
|
- data : data,
|
|
|
- success : 'successFunction',
|
|
|
- error : 'errorFunction'
|
|
|
+ name: 'restart.service.hostComponents',
|
|
|
+ sender: {
|
|
|
+ successCallback: defaultSuccessCallback,
|
|
|
+ errorCallback: defaultErrorCallback
|
|
|
+ },
|
|
|
+ data: {
|
|
|
+ serviceName: componentServiceMap[componentName],
|
|
|
+ componentName: componentName,
|
|
|
+ hosts: componentToHostsMap[componentName].join(",")
|
|
|
+ },
|
|
|
+ success: 'successCallback',
|
|
|
+ error: 'errorCallback'
|
|
|
});
|
|
|
}
|
|
|
},
|
|
@@ -103,61 +121,95 @@ module.exports = {
|
|
|
/**
|
|
|
* Makes a REST call to the server requesting the rolling restart of the
|
|
|
* provided host components.
|
|
|
+ * @param {Array} restartHostComponents list of host components should be restarted
|
|
|
+ * @param {Number} batchSize size of each batch
|
|
|
+ * @param {Number} intervalTimeSeconds delay between two batches
|
|
|
+ * @param {Number} tolerateSize task failure tolerance
|
|
|
+ * @param {Function} successCallback
|
|
|
+ * @param {Function} errorCallback
|
|
|
*/
|
|
|
- _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
|
|
|
+ _doPostBatchRollingRestartRequest: function(restartHostComponents, batchSize, intervalTimeSeconds, tolerateSize, successCallback, errorCallback) {
|
|
|
+ errorCallback = errorCallback ? errorCallback : defaultErrorCallback;
|
|
|
+ if (!restartHostComponents.length) {
|
|
|
+ console.log('No batch rolling restart if restartHostComponents is empty!');
|
|
|
+ return;
|
|
|
}
|
|
|
- var sender = {
|
|
|
- successFunction : function() {
|
|
|
- successCallback();
|
|
|
+ App.ajax.send({
|
|
|
+ name: 'rolling_restart.post',
|
|
|
+ sender: {
|
|
|
+ successCallback: successCallback,
|
|
|
+ errorCallback: errorCallback
|
|
|
},
|
|
|
- errorFunction : function(xhr, textStatus, error, opt) {
|
|
|
- errorCallback(xhr, textStatus, error, opt);
|
|
|
+ data: {
|
|
|
+ intervalTimeSeconds: intervalTimeSeconds,
|
|
|
+ tolerateSize: tolerateSize,
|
|
|
+ batches: this.getBatchesForRollingRestartRequest(restartHostComponents, batchSize)
|
|
|
+ },
|
|
|
+ success: 'successCallback',
|
|
|
+ error: 'errorCallback'
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Create list of batches for rolling restart request
|
|
|
+ * @param {Array} restartHostComponents list host components should be restarted
|
|
|
+ * @param {Number} batchSize size of each batch
|
|
|
+ * @returns {Array} list of batches
|
|
|
+ */
|
|
|
+ getBatchesForRollingRestartRequest: function(restartHostComponents, batchSize) {
|
|
|
+ var hostIndex = 0,
|
|
|
+ batches = [],
|
|
|
+ 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++) {
|
|
|
+ var hostNames = [];
|
|
|
+ for ( var hc = 0; hc < batchSize && hostIndex < restartHostComponents.length; hc++) {
|
|
|
+ hostNames.push(restartHostComponents.objectAt(hostIndex++).get('host.hostName'));
|
|
|
+ }
|
|
|
+ if (hostNames.length > 0) {
|
|
|
+ batches.push({
|
|
|
+ "order_id" : count + 1,
|
|
|
+ "type" : "POST",
|
|
|
+ "uri" : App.apiPrefix + "/clusters/" + App.get('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(",")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
- App.ajax.send({
|
|
|
- name : 'rolling_restart.post',
|
|
|
- sender : sender,
|
|
|
- data : data,
|
|
|
- success : 'successFunction',
|
|
|
- error : 'errorFunction'
|
|
|
- });
|
|
|
+ return batches;
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* 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
|
|
|
+ * Rolling restart is supported only for components listed in <code>getRollingRestartComponentName</code>
|
|
|
+ * @see getRollingRestartComponentName
|
|
|
+ * @param {String} hostComponentName
|
|
|
+ * Type of host-component to restart across cluster
|
|
|
* (ex: DATANODE)
|
|
|
- * @param {Boolean}
|
|
|
- * staleConfigsOnly Pre-select host-components which have stale
|
|
|
+ * @param {Boolean} staleConfigsOnly
|
|
|
+ * Pre-select host-components which have stale
|
|
|
* configurations
|
|
|
*/
|
|
|
- launchHostComponentRollingRestart : function(hostComponentName, staleConfigsOnly) {
|
|
|
+ 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") {
|
|
|
+ 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,
|
|
@@ -173,11 +225,10 @@ module.exports = {
|
|
|
}),
|
|
|
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;
|
|
|
+ return;
|
|
|
}
|
|
|
var restartComponents = this.get('innerView.restartHostComponents');
|
|
|
var batchSize = this.get('innerView.batchSize');
|
|
@@ -185,26 +236,13 @@ module.exports = {
|
|
|
var tolerateSize = this.get('innerView.tolerateSize');
|
|
|
self._doPostBatchRollingRestartRequest(restartComponents, batchSize, waitTime, tolerateSize, function() {
|
|
|
dialog.hide();
|
|
|
- App.router.get('applicationController').dataLoading().done(function(initValue) {
|
|
|
- if (initValue) {
|
|
|
- App.router.get('backgroundOperationsController').showPopup();
|
|
|
- }
|
|
|
- });
|
|
|
- }, function(xhr, textStatus, error, opt) {
|
|
|
- App.ajax.defaultErrorHandler(xhr, opt.url, 'POST', xhr.status);
|
|
|
+ defaultSuccessCallback();
|
|
|
});
|
|
|
- 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'),
|
|
|
+ }.observes('innerView.errors')
|
|
|
});
|
|
|
} else {
|
|
|
var msg = Em.I18n.t('rollingrestart.notsupported.hostComponent').format(componentDisplayName);
|
|
@@ -214,10 +252,9 @@ module.exports = {
|
|
|
secondary : false,
|
|
|
msg : msg,
|
|
|
bodyClass : Ember.View.extend({
|
|
|
- template : Ember.Handlebars.compile('<div class="alert alert-warning">{{msg}}</div>'),
|
|
|
- msg : msg
|
|
|
+ template : Ember.Handlebars.compile('<div class="alert alert-warning">{{msg}}</div>')
|
|
|
})
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
+};
|