Repository: ambari Updated Branches: refs/heads/trunk e593c5ae3 -> db399a13f
AMBARI-13625. Refactor bulk operation and batch-requests (onechiporenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/db399a13 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/db399a13 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/db399a13 Branch: refs/heads/trunk Commit: db399a13f306e91a4456fb4cd3a597411edb7cc5 Parents: e593c5a Author: Oleg Nechiporenko <onechipore...@apache.org> Authored: Thu Oct 29 12:40:24 2015 +0200 Committer: Oleg Nechiporenko <onechipore...@apache.org> Committed: Thu Oct 29 12:40:24 2015 +0200 ---------------------------------------------------------------------- .../main/host/bulk_operations_controller.js | 513 ++++++++++--------- .../app/utils/batch_scheduled_requests.js | 123 +++-- ambari-web/app/views/main/service/item.js | 30 +- 3 files changed, 358 insertions(+), 308 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/db399a13/ambari-web/app/controllers/main/host/bulk_operations_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/host/bulk_operations_controller.js b/ambari-web/app/controllers/main/host/bulk_operations_controller.js index ede2da4..3bcb5a5 100644 --- a/ambari-web/app/controllers/main/host/bulk_operations_controller.js +++ b/ambari-web/app/controllers/main/host/bulk_operations_controller.js @@ -19,6 +19,7 @@ var App = require('app'); var batchUtils = require('utils/batch_scheduled_requests'); var hostsManagement = require('utils/hosts'); var O = Em.Object; + /** * @class BulkOperationsController */ @@ -30,6 +31,7 @@ App.BulkOperationsController = Em.Controller.extend({ * Bulk operation wrapper * @param {Object} operationData - data about bulk operation (action, hosts or hostComponents etc) * @param {Array} hosts - list of affected hosts + * @method bulkOperation */ bulkOperation: function (operationData, hosts) { if (operationData.componentNameFormatted) { @@ -37,26 +39,29 @@ App.BulkOperationsController = Em.Controller.extend({ this.bulkOperationForHostComponentsRestart(operationData, hosts); } else { - if (operationData.action.indexOf('DECOMMISSION') != -1) { - this.bulkOperationForHostComponentsDecommission(operationData, hosts); + if (operationData.action.indexOf('DECOMMISSION') == -1) { + this.bulkOperationForHostComponents(operationData, hosts); } else { - this.bulkOperationForHostComponents(operationData, hosts); + this.bulkOperationForHostComponentsDecommission(operationData, hosts); } } } else { if (operationData.action === 'SET_RACK_INFO') { this.bulkOperationForHostsSetRackInfo(operationData, hosts); - } else if (operationData.action === 'RESTART') { - this.bulkOperationForHostsRestart(operationData, hosts); } else { - if (operationData.action === 'PASSIVE_STATE') { - this.bulkOperationForHostsPassiveState(operationData, hosts); + if (operationData.action === 'RESTART') { + this.bulkOperationForHostsRestart(operationData, hosts); } else { - this.bulkOperationForHosts(operationData, hosts); + if (operationData.action === 'PASSIVE_STATE') { + this.bulkOperationForHostsPassiveState(operationData, hosts); + } + else { + this.bulkOperationForHosts(operationData, hosts); + } } } } @@ -66,32 +71,34 @@ App.BulkOperationsController = Em.Controller.extend({ * Bulk operation (start/stop all) for selected hosts * @param {Object} operationData - data about bulk operation (action, hostComponents etc) * @param {Array} hosts - list of affected hosts + * @return {$.ajax} */ bulkOperationForHosts: function (operationData, hosts) { var self = this; - - batchUtils.getComponentsFromServer({ + return batchUtils.getComponentsFromServer({ hosts: hosts.mapProperty('hostName'), passiveState: 'OFF', displayParams: ['host_components/HostRoles/component_name'] }, function (data) { - self.bulkOperationForHostsCallback(operationData, data); + return self._getComponentsFromServerForHostsCallback(operationData, data); }); }, + /** * run Bulk operation (start/stop all) for selected hosts * after host and components are loaded * @param operationData * @param data */ - bulkOperationForHostsCallback: function (operationData, data) { + _getComponentsFromServerForHostsCallback: function (operationData, data) { var query = []; var hostNames = []; var hostsMap = {}; + var clients = App.components.get('clients'); data.items.forEach(function (host) { host.host_components.forEach(function (hostComponent) { - if (!App.components.get('clients').contains((hostComponent.HostRoles.component_name))) { + if (!clients.contains((hostComponent.HostRoles.component_name))) { if (hostsMap[host.Hosts.host_name]) { hostsMap[host.Hosts.host_name].push(hostComponent.HostRoles.component_name); } else { @@ -103,60 +110,28 @@ App.BulkOperationsController = Em.Controller.extend({ var nn_hosts = []; for (var hostName in hostsMap) { - var subQuery = '(HostRoles/component_name.in(%@)&HostRoles/host_name=' + hostName + ')'; - var components = hostsMap[hostName]; + if (hostsMap.hasOwnProperty(hostName)) { + var subQuery = '(HostRoles/component_name.in(%@)&HostRoles/host_name=' + hostName + ')'; + var components = hostsMap[hostName]; - if (components.length) { - if (components.indexOf('NAMENODE') >= 0) { - nn_hosts.push(hostName); + if (components.length) { + if (components.contains('NAMENODE')) { + nn_hosts.push(hostName); + } + query.push(subQuery.fmt(components.join(','))); } - query.push(subQuery.fmt(components.join(','))); + hostNames.push(hostName); } - hostNames.push(hostName); } hostNames = hostNames.join(","); if (query.length) { query = query.join('|'); var self = this; // if NameNode included, check HDFS NameNode checkpoint before stop NN - if (nn_hosts.length == 1 && operationData.action === 'INSTALLED' && App.Service.find().filterProperty('serviceName', 'HDFS').someProperty('workStatus', App.HostComponentStatus.started)) { - var hostName = nn_hosts[0]; - App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(function () { - App.ajax.send({ - name: 'common.host_components.update', - sender: self, - data: { - query: query, - HostRoles: { - state: operationData.action - }, - context: operationData.message, - hostName: hostNames, - noOpsMessage: Em.I18n.t('hosts.host.maintainance.allComponents.context') - }, - success: 'bulkOperationForHostComponentsSuccessCallback' - }); - }, hostName); - } else if (nn_hosts.length == 2 && operationData.action === 'INSTALLED' && App.Service.find().filterProperty('serviceName', 'HDFS').someProperty('workStatus', App.HostComponentStatus.started)) { - // HA enabled - App.router.get('mainServiceItemController').checkNnLastCheckpointTime(function () { - App.ajax.send({ - name: 'common.host_components.update', - sender: self, - data: { - query: query, - HostRoles: { - state: operationData.action - }, - context: operationData.message, - hostName: hostNames, - noOpsMessage: Em.I18n.t('hosts.host.maintainance.allComponents.context') - }, - success: 'bulkOperationForHostComponentsSuccessCallback' - }); - }); - } else { - App.ajax.send({ + var isHDFSStarted = 'STARTED' === App.Service.find('HDFS').get('workStatus'); + + var request = function () { + return App.ajax.send({ name: 'common.host_components.update', sender: self, data: { @@ -170,10 +145,21 @@ App.BulkOperationsController = Em.Controller.extend({ }, success: 'bulkOperationForHostComponentsSuccessCallback' }); + }; + + if (operationData.action === 'INSTALLED' && isHDFSStarted) { + if (nn_hosts.length == 1) { + return App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(request, nn_hosts[0]); + } + if (nn_hosts.length == 2) { + // HA enabled + return App.router.get('mainServiceItemController').checkNnLastCheckpointTime(request); + } } + return request(); } else { - App.ModalPopup.show({ + return App.ModalPopup.show({ header: Em.I18n.t('rolling.nothingToDo.header'), body: Em.I18n.t('rolling.nothingToDo.body').format(Em.I18n.t('hosts.host.maintainance.allComponents.context')), secondary: false @@ -182,7 +168,7 @@ App.BulkOperationsController = Em.Controller.extend({ }, bulkOperationForHostsSetRackInfo: function (operationData, hosts) { - hostsManagement.setRackInfo(operationData, hosts); + return hostsManagement.setRackInfo(operationData, hosts); }, /** @@ -191,36 +177,51 @@ App.BulkOperationsController = Em.Controller.extend({ * @param {Ember.Enumerable} hosts - list of affected hosts */ bulkOperationForHostsRestart: function (operationData, hosts) { - batchUtils.getComponentsFromServer({ + return batchUtils.getComponentsFromServer({ passiveState: 'OFF', hosts: hosts.mapProperty('hostName'), displayParams: ['host_components/HostRoles/component_name'] - }, function (data) { - var hostComponents = []; - data.items.forEach(function (host) { - host.host_components.forEach(function (hostComponent) { - hostComponents.push(O.create({ - componentName: hostComponent.HostRoles.component_name, - hostName: host.Hosts.host_name - })); - }) - }); - // if NameNode included, check HDFS NameNode checkpoint before restart NN - var nn_count = hostComponents.filterProperty('componentName', 'NAMENODE').get('length'); - if (nn_count == 1 && App.Service.find().filterProperty('serviceName', 'HDFS').someProperty('workStatus', App.HostComponentStatus.started)) { - var hostName = hostComponents.findProperty('componentName', 'NAMENODE').get('hostName'); - App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(function () { - batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST"); - }, hostName); - } else if (nn_count == 2 && App.Service.find().filterProperty('serviceName', 'HDFS').someProperty('workStatus', App.HostComponentStatus.started)) { + }, this._getComponentsFromServerForRestartCallback); + }, + + /** + * + * @param {object} data + * @private + * @method _getComponentsFromServerCallback + */ + _getComponentsFromServerForRestartCallback: function (data) { + var hostComponents = []; + data.items.forEach(function (host) { + host.host_components.forEach(function (hostComponent) { + hostComponents.push(O.create({ + componentName: hostComponent.HostRoles.component_name, + hostName: host.Hosts.host_name + })); + }) + }); + // if NameNode included, check HDFS NameNode checkpoint before restart NN + var isHDFSStarted = 'STARTED' === App.Service.find('HDFS').get('workStatus'); + var namenodes = hostComponents.filterProperty('componentName', 'NAMENODE'); + var nn_count = namenodes.get('length'); + + if (nn_count == 1 && isHDFSStarted) { + var hostName = namenodes.get('firstObject.hostName'); + App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(function () { + batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST"); + }, hostName); + } + else { + if (nn_count == 2 && isHDFSStarted) { // HA enabled App.router.get('mainServiceItemController').checkNnLastCheckpointTime(function () { batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST"); }); - } else { + } + else { batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST"); } - }); + } }, /** @@ -231,40 +232,51 @@ App.BulkOperationsController = Em.Controller.extend({ bulkOperationForHostsPassiveState: function (operationData, hosts) { var self = this; - batchUtils.getComponentsFromServer({ + return batchUtils.getComponentsFromServer({ hosts: hosts.mapProperty('hostName'), displayParams: ['Hosts/maintenance_state'] }, function (data) { - var hostNames = []; + return self._getComponentsFromServerForPassiveStateCallback(operationData, data) + }); + }, - data.items.forEach(function (host) { - if (host.Hosts.maintenance_state !== operationData.state) { - hostNames.push(host.Hosts.host_name); - } - }); - if (hostNames.length) { - App.ajax.send({ - name: 'bulk_request.hosts.passive_state', - sender: self, - data: { - hostNames: hostNames.join(','), - passive_state: operationData.state, - requestInfo: operationData.message - }, - success: 'updateHostPassiveState' - }); - } else { - App.ModalPopup.show({ - header: Em.I18n.t('rolling.nothingToDo.header'), - body: Em.I18n.t('hosts.bulkOperation.passiveState.nothingToDo.body'), - secondary: false - }); + /** + * + * @param {object} operationData + * @param {object} data + * @returns {$.ajax|App.ModalPopup} + * @private + * @method _getComponentsFromServerForPassiveStateCallback + */ + _getComponentsFromServerForPassiveStateCallback: function (operationData, data) { + var hostNames = []; + + data.items.forEach(function (host) { + if (host.Hosts.maintenance_state !== operationData.state) { + hostNames.push(host.Hosts.host_name); } }); + if (hostNames.length) { + return App.ajax.send({ + name: 'bulk_request.hosts.passive_state', + sender: this, + data: { + hostNames: hostNames.join(','), + passive_state: operationData.state, + requestInfo: operationData.message + }, + success: 'updateHostPassiveState' + }); + } + return App.ModalPopup.show({ + header: Em.I18n.t('rolling.nothingToDo.header'), + body: Em.I18n.t('hosts.bulkOperation.passiveState.nothingToDo.body'), + secondary: false + }); }, updateHostPassiveState: function (data, opt, params) { - batchUtils.infoPassiveState(params.passive_state); + return batchUtils.infoPassiveState(params.passive_state); }, /** * Bulk operation for selected hostComponents @@ -274,35 +286,44 @@ App.BulkOperationsController = Em.Controller.extend({ bulkOperationForHostComponents: function (operationData, hosts) { var self = this; - batchUtils.getComponentsFromServer({ + return batchUtils.getComponentsFromServer({ components: [operationData.componentName], hosts: hosts.mapProperty('hostName'), passiveState: 'OFF' }, function (data) { - if (data.items.length) { - var hostsWithComponentInProperState = data.items.mapProperty('Hosts.host_name'); - App.ajax.send({ - name: 'common.host_components.update', - sender: self, - data: { - HostRoles: { - state: operationData.action - }, - query: 'HostRoles/component_name=' + operationData.componentName + '&HostRoles/host_name.in(' + hostsWithComponentInProperState.join(',') + ')&HostRoles/maintenance_state=OFF', - context: operationData.message + ' ' + operationData.componentNameFormatted, - level: 'SERVICE', - noOpsMessage: operationData.componentNameFormatted + return self._getComponentsFromServerForHostComponentsCallback(operationData, data) + }); + }, + + /** + * + * @param {object} operationData + * @param {object} data + * @returns {$.ajax|App.ModalPopup} + * @private + */ + _getComponentsFromServerForHostComponentsCallback: function (operationData, data) { + if (data.items) { + var hostsWithComponentInProperState = data.items.mapProperty('Hosts.host_name'); + return App.ajax.send({ + name: 'common.host_components.update', + sender: this, + data: { + HostRoles: { + state: operationData.action }, - success: 'bulkOperationForHostComponentsSuccessCallback' - }); - } - else { - App.ModalPopup.show({ - header: Em.I18n.t('rolling.nothingToDo.header'), - body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted), - secondary: false - }); - } + query: 'HostRoles/component_name=' + operationData.componentName + '&HostRoles/host_name.in(' + hostsWithComponentInProperState.join(',') + ')&HostRoles/maintenance_state=OFF', + context: operationData.message + ' ' + operationData.componentNameFormatted, + level: 'SERVICE', + noOpsMessage: operationData.componentNameFormatted + }, + success: 'bulkOperationForHostComponentsSuccessCallback' + }); + } + return App.ModalPopup.show({ + header: Em.I18n.t('rolling.nothingToDo.header'), + body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted), + secondary: false }); }, @@ -314,13 +335,13 @@ App.BulkOperationsController = Em.Controller.extend({ bulkOperationForHostComponentsDecommission: function (operationData, hosts) { var self = this; - batchUtils.getComponentsFromServer({ + return batchUtils.getComponentsFromServer({ components: [operationData.realComponentName], hosts: hosts.mapProperty('hostName'), passiveState: 'OFF', displayParams: ['host_components/HostRoles/state'] }, function (data) { - self.bulkOperationForHostComponentsDecommissionCallBack(operationData, data) + return self._getComponentsFromServerForHostComponentsDecommissionCallBack(operationData, data) }); }, @@ -329,8 +350,9 @@ App.BulkOperationsController = Em.Controller.extend({ * after host and components are loaded * @param operationData * @param data + * @method _getComponentsFromServerForHostComponentsDecommissionCallBack */ - bulkOperationForHostComponentsDecommissionCallBack: function (operationData, data) { + _getComponentsFromServerForHostComponentsDecommissionCallBack: function (operationData, data) { var service = App.Service.find(operationData.serviceName); var components = []; @@ -426,72 +448,76 @@ App.BulkOperationsController = Em.Controller.extend({ */ warnBeforeDecommissionSuccess: function(data, opt, params) { if (Em.get(data, 'items.length')) { - App.router.get('mainHostDetailsController').showHbaseActiveWarning(); - } else { - App.router.get('mainHostDetailsController').checkRegionServerState(params.hostNames); + return App.router.get('mainHostDetailsController').showHbaseActiveWarning(); } + return App.router.get('mainHostDetailsController').checkRegionServerState(params.hostNames); }, + /** * Bulk restart for selected hostComponents * @param {Object} operationData * @param {Array} hosts */ bulkOperationForHostComponentsRestart: function (operationData, hosts) { - var service = App.Service.find(operationData.serviceName); - - batchUtils.getComponentsFromServer({ + var self = this; + return batchUtils.getComponentsFromServer({ components: [operationData.componentName], hosts: hosts.mapProperty('hostName'), passiveState: 'OFF', displayParams: ['Hosts/maintenance_state', 'host_components/HostRoles/stale_configs', 'host_components/HostRoles/maintenance_state'] }, function (data) { - var wrappedHostComponents = []; - - data.items.forEach(function (host) { - host.host_components.forEach(function (hostComponent) { - wrappedHostComponents.push(O.create({ - componentName: hostComponent.HostRoles.component_name, - serviceName: operationData.serviceName, - hostName: host.Hosts.host_name, - hostPassiveState: host.Hosts.maintenance_state, - staleConfigs: hostComponent.HostRoles.stale_configs, - passiveState: hostComponent.HostRoles.maintenance_state - })) - }); + return self._getComponentsFromServerForHostComponentsRestartCallback(operationData, data); + }); + }, + + _getComponentsFromServerForHostComponentsRestartCallback: function (operationData, data) { + var wrappedHostComponents = []; + var service = App.Service.find(operationData.serviceName); + + data.items.forEach(function (host) { + host.host_components.forEach(function (hostComponent) { + wrappedHostComponents.push(O.create({ + componentName: hostComponent.HostRoles.component_name, + serviceName: operationData.serviceName, + hostName: host.Hosts.host_name, + hostPassiveState: host.Hosts.maintenance_state, + staleConfigs: hostComponent.HostRoles.stale_configs, + passiveState: hostComponent.HostRoles.maintenance_state + })); }); + }); - if (wrappedHostComponents.length) { - batchUtils.showRollingRestartPopup(wrappedHostComponents.objectAt(0).get('componentName'), service.get('displayName'), service.get('passiveState') === "ON", false, wrappedHostComponents); - } else { - App.ModalPopup.show({ - header: Em.I18n.t('rolling.nothingToDo.header'), - body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted), - secondary: false - }); - } + if (wrappedHostComponents.length) { + return batchUtils.showRollingRestartPopup(wrappedHostComponents.objectAt(0).get('componentName'), service.get('displayName'), service.get('passiveState') === "ON", false, wrappedHostComponents); + } + return App.ModalPopup.show({ + header: Em.I18n.t('rolling.nothingToDo.header'), + body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted), + secondary: false }); }, updateHostComponentsPassiveState: function (data, opt, params) { - batchUtils.infoPassiveState(params.passive_state); + return batchUtils.infoPassiveState(params.passive_state); }, + /** * Show BO popup after bulk request + * @method bulkOperationForHostComponentsSuccessCallback */ bulkOperationForHostComponentsSuccessCallback: function (data, opt, params, req) { if (!data && req.status == 200) { - App.ModalPopup.show({ + return App.ModalPopup.show({ header: Em.I18n.t('rolling.nothingToDo.header'), body: Em.I18n.t('rolling.nothingToDo.body').format(params.noOpsMessage || Em.I18n.t('hosts.host.maintainance.allComponents.context')), secondary: false }); - } else { - App.router.get('userSettingsController').dataLoading('show_bg').done(function (initValue) { - if (initValue) { - App.router.get('backgroundOperationsController').showPopup(); - } - }); } + return App.router.get('userSettingsController').dataLoading('show_bg').done(function (initValue) { + if (initValue) { + App.router.get('backgroundOperationsController').showPopup(); + } + }); }, /** @@ -501,14 +527,14 @@ App.BulkOperationsController = Em.Controller.extend({ * @param {String} divider - string to separate hostNames * @param {Number} minShown - min amount of hostName to be shown * @returns {String} hostNames - * @method showHostNames + * @method _showHostNames + * @private */ - showHostNames: function(hostNames, divider, minShown) { + _showHostNames: function(hostNames, divider, minShown) { if (hostNames.length > minShown) { return hostNames.slice(0, minShown).join(divider) + divider + Em.I18n.t("installer.step8.other").format(hostNames.length - minShown); - } else { - return hostNames.join(divider); } + return hostNames.join(divider); }, /** @@ -554,13 +580,11 @@ App.BulkOperationsController = Em.Controller.extend({ }, getHostsForBulkOperations: function (queryParams, operationData, loadingPopup) { - var params = App.router.get('updateController').computeParameters(queryParams); - - App.ajax.send({ + return App.ajax.send({ name: 'hosts.bulk.operations', sender: this, data: { - parameters: params, + parameters: App.router.get('updateController').computeParameters(queryParams), operationData: operationData, loadingPopup: loadingPopup }, @@ -568,7 +592,7 @@ App.BulkOperationsController = Em.Controller.extend({ }); }, - convertHostsObjects: function (hosts) { + _convertHostsObjects: function (hosts) { return hosts.map(function (host) { return { index: host.index, @@ -582,72 +606,45 @@ App.BulkOperationsController = Em.Controller.extend({ }, getHostsForBulkOperationSuccessCallback: function(json, opt, param) { - var self = this, - operationData = param.operationData, - hosts = this.convertHostsObjects(App.hostsMapper.map(json, true)); + var self = this; + var operationData = param.operationData; + var hosts = this._convertHostsObjects(App.hostsMapper.map(json, true)); // no hosts - no actions if (!hosts.length) { console.log('No bulk operation if no hosts selected.'); return; } - var hostNames = hosts.mapProperty('hostName'); - var hostsToSkip = []; - if (operationData.action == "DECOMMISSION") { - var hostComponentStatusMap = {}; // "DATANODE_c6401.ambari.apache.org" => "STARTED" - var hostComponentIdMap = {}; // "DATANODE_c6401.ambari.apache.org" => "DATANODE" - if (json.items) { - json.items.forEach(function(host) { - if (host.host_components) { - host.host_components.forEach(function(component) { - hostComponentStatusMap[component.id] = component.HostRoles.state; - hostComponentIdMap[component.id] = component.HostRoles.component_name; - }); - } - }); - } - hostsToSkip = hosts.filter(function(host) { - var invalidStateComponents = host.hostComponents.filter(function(component) { - return hostComponentIdMap[component] == operationData.realComponentName && hostComponentStatusMap[component] == 'INSTALLED'; - }); - return invalidStateComponents.length > 0; - }); - } - var hostNamesSkipped = hostsToSkip.mapProperty('hostName'); - if (operationData.action === 'PASSIVE_STATE') { - hostNamesSkipped = []; - var outOfSyncHosts = App.StackVersion.find().findProperty('isCurrent').get('outOfSyncHosts'); - for (var i = 0; i < outOfSyncHosts.length; i++) { - if (hostNames.contains(outOfSyncHosts[i])) { - hostNamesSkipped.push(outOfSyncHosts[i]); - } - } - } - var message; - if (operationData.componentNameFormatted) { - message = Em.I18n.t('hosts.bulkOperation.confirmation.hostComponents').format(operationData.message, operationData.componentNameFormatted, hostNames.length); - } - else { - message = Em.I18n.t('hosts.bulkOperation.confirmation.hosts').format(operationData.message, hostNames.length); - } - if (param.loadingPopup) { - param.loadingPopup.hide(); + Em.tryInvoke(param.loadingPopup, 'hide'); + + if ('SET_RACK_INFO' === operationData.action) { + return self.bulkOperation(operationData, hosts); } - if (operationData.action === 'SET_RACK_INFO') { - self.bulkOperation(operationData, hosts); - return; + var hostNames = hosts.mapProperty('hostName'); + var hostNamesSkipped = []; + if ('DECOMMISSION' === operationData.action) { + hostNamesSkipped = this._getSkippedForDecommissionHosts(json, hosts, operationData); + } + if ('PASSIVE_STATE' === operationData.action) { + hostNamesSkipped = this._getSkippedForPassiveStateHosts(hosts); } - App.ModalPopup.show({ + var message = operationData.componentNameFormatted ? + Em.I18n.t('hosts.bulkOperation.confirmation.hostComponents').format(operationData.message, operationData.componentNameFormatted, hostNames.length) : + Em.I18n.t('hosts.bulkOperation.confirmation.hosts').format(operationData.message, hostNames.length); + + return App.ModalPopup.show({ header: Em.I18n.t('hosts.bulkOperation.confirmation.header'), hostNames: hostNames.join("\n"), - visibleHosts: self.showHostNames(hostNames, "\n", 3), - hostNamesSkippedVisible: self.showHostNames(hostNamesSkipped, "\n", 3), + visibleHosts: self._showHostNames(hostNames, "\n", 3), + hostNamesSkippedVisible: self._showHostNames(hostNamesSkipped, "\n", 3), + expanded: false, + hostNamesSkipped: function() { return hostNamesSkipped.length ? hostNamesSkipped.join("\n") : false; }.property(), - expanded: false, + didInsertElement: function() { this.set('expanded', hostNames.length <= 3); }, @@ -655,9 +652,12 @@ App.BulkOperationsController = Em.Controller.extend({ self.bulkOperation(operationData, hosts); this._super(); }, + bodyClass: Em.View.extend({ templateName: require('templates/main/host/bulk_operation_confirm_popup'), message: message, + textareaVisible: false, + warningInfo: function() { switch (operationData.action) { case "DECOMMISSION": @@ -669,15 +669,17 @@ App.BulkOperationsController = Em.Controller.extend({ return "" } }.property(), - textareaVisible: false, + textTrigger: function() { - this.set('textareaVisible', !this.get('textareaVisible')); + this.toggleProperty('textareaVisible'); }, + showAll: function() { this.set('parentView.visibleHosts', this.get('parentView.hostNames')); this.set('parentView.hostNamesSkippedVisible', this.get('parentView.hostNamesSkipped')); this.set('parentView.expanded', true); }, + putHostNamesToTextarea: function() { var hostNames = this.get('parentView.hostNames'); if (this.get('textareaVisible')) { @@ -688,8 +690,57 @@ App.BulkOperationsController = Em.Controller.extend({ }); } }.observes('textareaVisible') + }) }); + }, + + /** + * @param {object} json + * @param {object[]} hosts + * @param {object} operationData + * @returns {string[]} + * @private + * @method _getSkippedForDecommissionHosts + */ + _getSkippedForDecommissionHosts: function (json, hosts, operationData) { + var hostComponentStatusMap = {}; // "DATANODE_c6401.ambari.apache.org" => "STARTED" + var hostComponentIdMap = {}; // "DATANODE_c6401.ambari.apache.org" => "DATANODE" + if (json.items) { + json.items.forEach(function(host) { + if (host.host_components) { + host.host_components.forEach(function(component) { + hostComponentStatusMap[component.id] = component.HostRoles.state; + hostComponentIdMap[component.id] = component.HostRoles.component_name; + }); + } + }); + } + return hosts.filter(function(host) { + return host.hostComponents.filter(function(component) { + return hostComponentIdMap[component] == operationData.realComponentName && hostComponentStatusMap[component] == 'INSTALLED'; + }).length > 0; + }).mapProperty('hostName'); + }, + + /** + * Exclude <code>outOfSyncHosts</code> hosts for PASSIVE request + * + * @param {object[]} hosts + * @returns {string[]} + * @private + * @method _getSkippedForPassiveStateHosts + */ + _getSkippedForPassiveStateHosts: function (hosts) { + var hostNames = hosts.mapProperty('hostName'); + var hostNamesSkipped = []; + var outOfSyncHosts = App.StackVersion.find().findProperty('isCurrent').get('outOfSyncHosts'); + for (var i = 0; i < outOfSyncHosts.length; i++) { + if (hostNames.contains(outOfSyncHosts[i])) { + hostNamesSkipped.push(outOfSyncHosts[i]); + } + } + return hostNamesSkipped; } }); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/db399a13/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 09d86c8..c350b59 100644 --- a/ambari-web/app/utils/batch_scheduled_requests.js +++ b/ambari-web/app/utils/batch_scheduled_requests.js @@ -35,6 +35,7 @@ var defaultSuccessCallback = function(data, ajaxOptions, params) { * @param {String} textStatus * @param {String} error * @param {Object} opt + * @param {Object} params * @type {Function} */ var defaultErrorCallback = function(xhr, textStatus, error, opt, params) { @@ -73,7 +74,9 @@ module.exports = { */ restartAllServiceHostComponents: function(serviceDisplayName, serviceName, staleConfigsOnly, query, runMmOperation) { var self = this; - var context = staleConfigsOnly ? Em.I18n.t('rollingrestart.context.allWithStaleConfigsForSelectedService').format(serviceDisplayName) : Em.I18n.t('rollingrestart.context.allForSelectedService').format(serviceDisplayName); + var context = staleConfigsOnly ? + Em.I18n.t('rollingrestart.context.allWithStaleConfigsForSelectedService').format(serviceDisplayName) : + Em.I18n.t('rollingrestart.context.allForSelectedService').format(serviceDisplayName); if (runMmOperation) { this.turnOnOffPassiveRequest('ON', Em.I18n.t('passiveState.turnOnFor').format(serviceName), serviceName); @@ -99,7 +102,7 @@ module.exports = { /** * construct URL from parameters for request in <code>getComponentsFromServer()</code> - * @param options + * @param {object} options * @return {{fields: string, params: string}} */ constructComponentsCallUrl: function (options) { @@ -222,7 +225,7 @@ module.exports = { if (hostComponentsList.length > 0) { var serviceComponentName = hostComponentsList[0].get("componentName"); var serviceName = App.StackServiceComponent.find(serviceComponentName).get('serviceName'); - var operation_level = this.getOperationLevelobject(level, serviceName, + var operation_level = this.getOperationLevelObject(level, serviceName, serviceComponentName); } @@ -251,18 +254,21 @@ module.exports = { * @param {String} serviceName * @param {String} componentName * @returns {Object} {{level: *, cluster_name: *}} - operation level object - * @method getOperationLevelobject - create operation level object to be included into ajax query + * @method getOperationLevelObject - create operation level object to be included into ajax query */ - getOperationLevelobject: function(level, serviceName, componentName) { + getOperationLevelObject: function(level, serviceName, componentName) { var operationLevel = { "level": level, "cluster_name": App.get("clusterName") }; if (level === "SERVICE") { operationLevel["service_name"] = serviceName; - } else if(level !== "HOST") { - operationLevel["service_name"] = serviceName; - operationLevel["hostcomponent_name"] = componentName; + } + else { + if (level !== "HOST") { + operationLevel["service_name"] = serviceName; + operationLevel["hostcomponent_name"] = componentName; + } } return operationLevel; }, @@ -282,6 +288,7 @@ module.exports = { 'success': 'successCallback' }); }, + /** * Makes a REST call to the server requesting the rolling restart of the * provided host components. @@ -289,17 +296,18 @@ module.exports = { * @param {Number} batchSize size of each batch * @param {Number} intervalTimeSeconds delay between two batches * @param {Number} tolerateSize task failure tolerance - * @param {callback} successCallback - * @param {callback} errorCallback + * @param {callback} [successCallback] + * @param {callback} [errorCallback] */ _doPostBatchRollingRestartRequest: function(restartHostComponents, batchSize, intervalTimeSeconds, tolerateSize, successCallback, errorCallback) { successCallback = successCallback || defaultSuccessCallback; errorCallback = errorCallback || defaultErrorCallback; + if (!restartHostComponents.length) { console.log('No batch rolling restart if no restartHostComponents provided!'); return; } - App.ajax.send({ + return App.ajax.send({ name: 'rolling_restart.post', sender: { successCallback: successCallback, @@ -334,7 +342,7 @@ module.exports = { for ( var hc = 0; hc < batchSize && hostIndex < restartHostComponents.length; hc++) { hostNames.push(restartHostComponents.objectAt(hostIndex++).get('hostName')); } - if (hostNames.length > 0) { + if (hostNames.length) { batches.push({ "order_id" : count + 1, "type" : "POST", @@ -370,18 +378,19 @@ module.exports = { */ launchHostComponentRollingRestart: function(hostComponentName, serviceName, isMaintenanceModeOn, staleConfigsOnly, skipMaintenance) { if (App.get('components.rollinRestartAllowed').contains(hostComponentName)) { - this.showRollingRestartPopup(hostComponentName, serviceName, isMaintenanceModeOn, staleConfigsOnly, null, skipMaintenance); - } - else { - this.showWarningRollingRestartPopup(hostComponentName); + return this.showRollingRestartPopup(hostComponentName, serviceName, isMaintenanceModeOn, staleConfigsOnly, null, skipMaintenance); } + return this.showWarningRollingRestartPopup(hostComponentName); }, /** * Show popup with rolling restart dialog * @param {String} hostComponentName name of the host components that should be restarted + * @param {String} serviceName + * @param {boolean} isMaintenanceModeOn * @param {bool} staleConfigsOnly restart only components with <code>staleConfigs</code> = true - * @param {App.hostComponent[]} hostComponents list of hostComponents that should be restarted (optional). + * @param {App.hostComponent[]} [hostComponents] list of hostComponents that should be restarted + * @param {boolean} [skipMaintenance] * Using this parameter will reset hostComponentName */ showRollingRestartPopup: function(hostComponentName, serviceName, isMaintenanceModeOn, staleConfigsOnly, hostComponents, skipMaintenance) { @@ -406,29 +415,30 @@ module.exports = { this.set('parentView.innerView', this); if (hostComponents.length) { view.initialize(); - } else { - self.getComponentsFromServer({ - components: [hostComponentName], - displayParams: ['host_components/HostRoles/stale_configs', 'Hosts/maintenance_state', 'host_components/HostRoles/maintenance_state'], - staleConfigs: staleConfigsOnly ? staleConfigsOnly : null - }, function (data) { - var wrappedHostComponents = []; - data.items.forEach(function (host) { - host.host_components.forEach(function(hostComponent){ - wrappedHostComponents.push(Em.Object.create({ - componentName: hostComponent.HostRoles.component_name, - serviceName: App.StackServiceComponent.find(hostComponent.HostRoles.component_name).get('serviceName'), - hostName: host.Hosts.host_name, - staleConfigs: hostComponent.HostRoles.stale_configs, - hostPassiveState: host.Hosts.maintenance_state, - passiveState: hostComponent.HostRoles.maintenance_state - })); - }); + return; + } + + self.getComponentsFromServer({ + components: [hostComponentName], + displayParams: ['host_components/HostRoles/stale_configs', 'Hosts/maintenance_state', 'host_components/HostRoles/maintenance_state'], + staleConfigs: staleConfigsOnly ? staleConfigsOnly : null + }, function (data) { + var wrappedHostComponents = []; + data.items.forEach(function (host) { + host.host_components.forEach(function(hostComponent) { + wrappedHostComponents.push(Em.Object.create({ + componentName: hostComponent.HostRoles.component_name, + serviceName: App.StackServiceComponent.find(hostComponent.HostRoles.component_name).get('serviceName'), + hostName: host.Hosts.host_name, + staleConfigs: hostComponent.HostRoles.stale_configs, + hostPassiveState: host.Hosts.maintenance_state, + passiveState: hostComponent.HostRoles.maintenance_state + })); }); - view.set('allHostComponents', wrappedHostComponents); - view.initialize(); }); - } + view.set('allHostComponents', wrappedHostComponents); + view.initialize(); + }); } }; if (hostComponents.length) { @@ -472,14 +482,11 @@ module.exports = { * @param {String} hostComponentName */ showWarningRollingRestartPopup: function(hostComponentName) { - var componentDisplayName = App.format.role(hostComponentName); - if (!componentDisplayName) { - componentDisplayName = hostComponentName; - } + var componentDisplayName = App.format.role(hostComponentName) || 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({ + + return App.ModalPopup.show({ header : title, secondary : false, msg : msg, @@ -491,18 +498,16 @@ module.exports = { /** * Warn user that alerts will be updated in few minutes - * @param {String} hostComponentName + * @param {String} passiveState */ infoPassiveState: function(passiveState) { var enabled = passiveState == 'OFF' ? 'enabled' : 'suppressed'; App.ModalPopup.show({ header: Em.I18n.t('common.information'), secondary: null, - bodyClass: Ember.View.extend({ - template: Ember.Handlebars.compile('<p>{{view.message}}</p>'), - message: function() { - return Em.I18n.t('hostPopup.warning.alertsTimeOut').format(passiveState.toLowerCase(), enabled); - }.property() + bodyClass: Em.View.extend({ + template: Em.Handlebars.compile('<p>{{view.message}}</p>'), + message: Em.I18n.t('hostPopup.warning.alertsTimeOut').format(passiveState.toLowerCase(), enabled) }) }); }, @@ -519,16 +524,12 @@ module.exports = { */ getRequestSchedule: function(requestScheduleId, successCallback, errorCallback) { if (requestScheduleId != null && !isNaN(requestScheduleId) && requestScheduleId > -1) { - errorCallback = errorCallback ? errorCallback : defaultErrorCallback; + 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); - } + successCallbackFunction: successCallback, + errorCallbackFunction: errorCallback }, data : { request_schedule_id : requestScheduleId @@ -555,12 +556,8 @@ module.exports = { App.ajax.send({ name : 'common.delete.request_schedule', sender : { - successCallbackFunction : function(data) { - successCallback(data); - }, - errorCallbackFunction : function(xhr, textStatus, error, opt) { - errorCallback(xhr, textStatus, error, opt); - } + successCallbackFunction: successCallback, + errorCallbackFunction: errorCallback }, data : { request_schedule_id : requestScheduleId http://git-wip-us.apache.org/repos/asf/ambari/blob/db399a13/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 d141229..bfa98ca 100644 --- a/ambari-web/app/views/main/service/item.js +++ b/ambari-web/app/views/main/service/item.js @@ -17,7 +17,6 @@ */ var App = require('app'); -var batchUtils = require('utils/batch_scheduled_requests'); App.MainServiceItemView = Em.View.extend({ templateName: require('templates/main/service/item'), @@ -230,19 +229,19 @@ App.MainServiceItemView = Em.View.extend({ options.push(actionMap.DOWNLOAD_CLIENT_CONFIGS); } - if (!this.get('maintenance').length) { - this.set('maintenance', options); - } else { + if (this.get('maintenance.length')) { this.get('maintenance').forEach(function(option, index) { - if ( JSON.stringify(option) != JSON.stringify(options[index]) ) { + if (JSON.stringify(option) != JSON.stringify(options[index])) { self.get('maintenance').removeAt(index).insertAt(index, options[index]); } }); options.forEach(function(opt, index) { - if ( JSON.stringify(opt) != JSON.stringify(self.get('maintenance')[index]) ) { + if (JSON.stringify(opt) != JSON.stringify(self.get('maintenance')[index])) { self.get('maintenance').pushObject(opt); } }); + } else { + this.set('maintenance', options); } this.set('isMaintenanceSet', true); }, @@ -267,19 +266,22 @@ App.MainServiceItemView = Em.View.extend({ this.get('controller').setStartStopState(); }, + maintenanceObsFields: ['isStopDisabled', 'isClientsOnlyService', 'content.isRestartRequired', 'isServicesInfoLoaded'], + willInsertElement: function () { - this.addObserver('controller.isStopDisabled', this, 'observeMaintenance'); - this.addObserver('controller.isClientsOnlyService', this, 'observeMaintenance'); - this.addObserver('controller.content.isRestartRequired', this, 'observeMaintenance'); - this.addObserver('controller.isServicesInfoLoaded', this, 'observeMaintenance'); + var self = this; + this.get('maintenanceObsFields').forEach(function (field) { + self.addObserver('controller.' + field, self, 'observeMaintenance'); + }); }, willDestroyElement: function() { - this.removeObserver('controller.isStopDisabled', this, 'observeMaintenance'); - this.removeObserver('controller.isClientsOnlyService', this, 'observeMaintenance'); - this.removeObserver('controller.content.isRestartRequired', this, 'observeMaintenance'); - this.removeObserver('controller.isServicesInfoLoaded', this, 'observeMaintenance'); + var self = this; + this.get('maintenanceObsFields').forEach(function (field) { + self.removeObserver('controller.' + field, self, 'observeMaintenance'); + }); }, + service:function () { var svc = this.get('controller.content'); var svcName = svc.get('serviceName');