Repository: ambari Updated Branches: refs/heads/branch-2.5 8c7248b90 -> 58203347a
AMBARI-18941. When HS2Interactive is enabled, any hive config change results in a CS queue refresh. (Vivek Ratnaval via yusaku) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/58203347 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/58203347 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/58203347 Branch: refs/heads/branch-2.5 Commit: 58203347a01c6823170e4e8bcfe76d022b4a5723 Parents: 8c7248b Author: Yusaku Sako <yus...@hortonworks.com> Authored: Tue Dec 27 12:35:26 2016 -0800 Committer: Yusaku Sako <yus...@hortonworks.com> Committed: Tue Dec 27 12:35:26 2016 -0800 ---------------------------------------------------------------------- ambari-web/app/controllers/main/service.js | 67 ++------------- ambari-web/app/messages.js | 2 + .../configs/component_actions_by_configs.js | 64 ++++++++++++++ .../app/models/configs/theme/config_action.js | 12 ++- ambari-web/app/templates/common/modal_popup.hbs | 6 +- ambari-web/app/utils/ajax/ajax.js | 15 +++- .../app/utils/batch_scheduled_requests.js | 88 ++++---------------- ambari-web/app/views/common/modal_popup.js | 3 + .../common/modal_popups/confirmation_popup.js | 5 +- .../test/controllers/main/service_test.js | 23 ----- .../test/utils/batch_scheduled_requests_test.js | 23 ----- 11 files changed, 117 insertions(+), 191 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/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 d6fbfbb..2677723 100644 --- a/ambari-web/app/controllers/main/service.js +++ b/ambari-web/app/controllers/main/service.js @@ -323,68 +323,11 @@ App.MainServiceController = Em.ArrayController.extend({ * @returns {$.ajax} */ restartHostComponents: function () { - var batches, hiveInteractive = App.HostComponent.find().findProperty('componentName', 'HIVE_SERVER_INTERACTIVE'); - var isYARNQueueRefreshRequired = hiveInteractive && hiveInteractive.get('staleConfigs'); - var ajaxData = { - "RequestInfo": { - "command": "RESTART", - "context": "Restart all required services", - "operation_level": "host_component" - }, - "Requests/resource_filters": [ - { - "hosts_predicate": "HostRoles/stale_configs=true" - } - ] - }; - - if (isYARNQueueRefreshRequired) { - batches = [ - { - "order_id": 1, - "type": "POST", - "uri": App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests", - "RequestBodyInfo": { - "RequestInfo": { - "context": "Refresh YARN Capacity Scheduler", - "command": "REFRESHQUEUES", - "parameters/forceRefreshConfigTags": "capacity-scheduler" - }, - "Requests/resource_filters": [{ - "service_name": "YARN", - "component_name": "RESOURCEMANAGER", - "hosts": App.HostComponent.find().findProperty('componentName', 'RESOURCEMANAGER').get('hostName') - }] - } - }, - { - "order_id": 2, - "type": "POST", - "uri": App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests", - "RequestBodyInfo": ajaxData - } - ]; - - App.ajax.send({ - name: 'common.batch.request_schedules', - sender: this, - data: { - intervalTimeSeconds: 1, - tolerateSize: 0, - batches: batches - }, - success: 'restartAllRequiredSuccessCallback' - }); - } else { - App.ajax.send({ - name: 'request.post', - sender: this, - data: { - data: ajaxData - }, - success: 'restartAllRequiredSuccessCallback' - }); - } + App.ajax.send({ + name: 'restart.staleConfigs', + sender: this, + success: 'restartAllRequiredSuccessCallback' + }); }, /** http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index 6d7ad98..bb433a2 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -415,6 +415,8 @@ Em.I18n.translations = { 'popup.highlight':'click to highlight', 'popup.confirmation.commonHeader':'Confirmation', + 'popup.confirmation.refreshYarnQueues.body':'It is strongly recommended to <strong>Refresh Yarn Queues</strong> after making a change to the capacity scheduler configuration. Would you like to proceed?', + 'popup.confirmation.refreshYarnQueues.buttonText':'Refresh Yarn Queues', 'popup.prompt.commonHeader':'Prompt', 'popup.confirmationFeedBack.sending':'Sending...', 'popup.confirmationFeedBack.query.fail':'Request failed', http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js b/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js index 9271675..11ee3ac 100644 --- a/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js +++ b/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js @@ -26,6 +26,13 @@ var stringUtils = require('utils/string_utils'); */ App.ComponentActionsByConfigs = Em.Mixin.create({ + configAction: null, + + /** + * Flag to check if Yarn Queues have been refreshed already + */ + isYarnQueueRefreshed: false, + /** * Do component add/delete actions as inferred from value of service configs * @public @@ -34,11 +41,66 @@ App.ComponentActionsByConfigs = Em.Mixin.create({ doConfigActions: function() { var serviceConfigs = this.get('stepConfigs').findProperty('serviceName', this.get('content.serviceName')).get('configs'); var configActionComponents = serviceConfigs.filterProperty('configActionComponent'); + this.isYarnQueueRefreshed = false; this.doComponentDeleteActions(configActionComponents); this.doComponentAddActions(configActionComponents); + this.showPopup(); }, /** + * Method to show confirmation popup before sending an ajax request + */ + showPopup: function() { + var config_actions = App.ConfigAction.find().filterProperty('actionType', 'showPopup'); + var self = this; + if (config_actions.length) { + config_actions.forEach(function (config_action) { + var configs = self.get('allConfigs').filterProperty('filename', config_action.get('fileName')).filter(function (item) { + return item.get('value') !== item.get('initialValue'); + }); + + if (configs.length) { + if(config_action.get('fileName') === 'capacity-scheduler.xml' && !self.isYarnQueueRefreshed) { + self.configAction = config_action; + App.showConfirmationPopup(function () { + self.popupPrimaryButtonCallback(config_action); + }, config_action.get('popupProperties').body, null, Em.I18n.t('popup.confirmation.commonHeader'), config_action.get('popupProperties').primaryButton.label, false, 'refresh_yarn_queues') + } + } + }); + } + }, + + popupPrimaryButtonCallback: function (config_action) { + var hosts = App.Service.find(config_action.get('serviceName')).get('hostComponents').filterProperty('componentName', config_action.get('componentName')).mapProperty('hostName'); + var self = this; + App.ajax.send({ + name : config_action.get('popupProperties').primaryButton.metaData.name, + sender: self, + data : { + command : config_action.get('popupProperties').primaryButton.metaData.command, + context : config_action.get('popupProperties').primaryButton.metaData.context, + hosts : hosts.join(','), + serviceName : config_action.get('serviceName'), + componentName : config_action.get('componentName'), + forceRefreshConfigTags : config_action.get('configName') + }, + error : 'popupPrimaryButtonCallbackError' + }); + }, + + popupPrimaryButtonCallbackError: function(data) { + var error = this.configAction.get('popupProperties').errorMessage; + if(data && data.responseText){ + try { + var json = $.parseJSON(data.responseText); + error += json.message; + } catch (err) {} + } + App.showAlertPopup(this.configAction.get('popupProperties').errorMessage, error, null); + }, + + /** * Method informs if any component will be added/deleted on saving configurations * @return {boolean} * @public @@ -331,6 +393,8 @@ App.ComponentActionsByConfigs = Em.Mixin.create({ var commandName = 'REFRESHQUEUES'; var tag = 'capacity-scheduler'; var hostNames = App.Service.find(serviceName).get('hostComponents').filterProperty('componentName', componentName).mapProperty('hostName'); + // Set the flag to true + this.isYarnQueueRefreshed = true; batches.push({ "type": 'POST', "uri": App.get('apiPrefix') + "/clusters/" + App.get('clusterName') + "/requests", http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/ambari-web/app/models/configs/theme/config_action.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/configs/theme/config_action.js b/ambari-web/app/models/configs/theme/config_action.js index 9105e1a..27955d5 100644 --- a/ambari-web/app/models/configs/theme/config_action.js +++ b/ambari-web/app/models/configs/theme/config_action.js @@ -37,8 +37,6 @@ App.ConfigAction = DS.Model.extend({ */ fileName: DS.attr('string'), - - /** * conditional String which can be evaluated to boolean result. * If evaluated result of this staring is true then use the statement provided by `then` attribute. @@ -47,8 +45,14 @@ App.ConfigAction = DS.Model.extend({ if: DS.attr('string'), then: DS.attr('string'), else: DS.attr('string'), - hostComponentConfig: DS.attr('object') - + hostComponentConfig: DS.attr('object', { + defaultValue: function () { return {}; } + }), + actionType: DS.attr('string'), + popupProperties: DS.attr('object', { + defaultValue: function () { return {}; } + }), + serviceName: DS.attr('string') }); App.ConfigAction.FIXTURES = [ http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/ambari-web/app/templates/common/modal_popup.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/common/modal_popup.hbs b/ambari-web/app/templates/common/modal_popup.hbs index 1d67a41..5bc3f2b 100644 --- a/ambari-web/app/templates/common/modal_popup.hbs +++ b/ambari-web/app/templates/common/modal_popup.hbs @@ -48,13 +48,13 @@ {{else}} <div class="modal-footer"> {{#if view.third}} - <button {{bindAttr disabled="view.disableThird" class=":btn view.thirdClass"}} {{action onThird target="view"}}>{{view.third}}</button> + <button {{bindAttr disabled="view.disableThird" class=":btn view.thirdClass" id="view.thirdId"}} {{action onThird target="view"}}>{{view.third}}</button> {{/if}} {{#if view.secondary}} - <button {{bindAttr disabled="view.disableSecondary" class=":btn view.secondaryClass"}} {{action onSecondary target="view"}}>{{view.secondary}}</button> + <button {{bindAttr disabled="view.disableSecondary" class=":btn view.secondaryClass" id="view.secondaryId"}} {{action onSecondary target="view"}}>{{view.secondary}}</button> {{/if}} {{#if view.primary}} - <button {{bindAttr disabled="view.disablePrimary" class=":btn view.primaryClass"}} {{action onPrimary target="view"}}>{{view.primary}}</button> + <button {{bindAttr disabled="view.disablePrimary" class=":btn view.primaryClass" id="view.primaryId"}} {{action onPrimary target="view"}}>{{view.primary}}</button> {{/if}} </div> {{/if}} http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/ambari-web/app/utils/ajax/ajax.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js index 011999f..2cdc395 100644 --- a/ambari-web/app/utils/ajax/ajax.js +++ b/ambari-web/app/utils/ajax/ajax.js @@ -2351,13 +2351,24 @@ var urls = { } }, - 'request.post': { + 'restart.staleConfigs': { 'real': "/clusters/{clusterName}/requests", 'mock': "", 'format': function (data) { return { type: 'POST', - data: JSON.stringify(data.data) + data: JSON.stringify({ + "RequestInfo": { + "command": "RESTART", + "context": "Restart all required services", + "operation_level": "host_component" + }, + "Requests/resource_filters": [ + { + "hosts_predicate": "HostRoles/stale_configs=true" + } + ] + }) } } }, http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/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 c9828a4..b8ae955 100644 --- a/ambari-web/app/utils/batch_scheduled_requests.js +++ b/ambari-web/app/utils/batch_scheduled_requests.js @@ -203,16 +203,9 @@ module.exports = { */ var componentToHostsMap = {}; var hosts = []; - var batches, refreshYARNQueues = false; - hostComponentsList.forEach(function(hc) { var hostName = hc.get('hostName'); var componentName = hc.get('componentName'); - - if (componentName === 'HIVE_SERVER_INTERACTIVE') { - refreshYARNQueues = true; - } - if (!componentToHostsMap[componentName]) { componentToHostsMap[componentName] = []; } @@ -238,72 +231,21 @@ module.exports = { if (resource_filters.length) { - if (refreshYARNQueues) { - batches = [ - { - "order_id": 1, - "type": "POST", - "uri": App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests", - "RequestBodyInfo": { - "RequestInfo": { - "context": "Refresh YARN Capacity Scheduler", - "command": "REFRESHQUEUES", - "parameters/forceRefreshConfigTags": "capacity-scheduler" - }, - "Requests/resource_filters": [{ - "service_name": "YARN", - "component_name": "RESOURCEMANAGER", - "hosts": App.HostComponent.find().findProperty('componentName', 'RESOURCEMANAGER').get('hostName') - }] - } - }, - { - "order_id": 2, - "type": "POST", - "uri": App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests", - "RequestBodyInfo": { - "RequestInfo": { - "context": context, - "command": "RESTART", - "operation_level": operation_level - }, - "Requests/resource_filters": resource_filters - } - } - ]; - - App.ajax.send({ - name: 'common.batch.request_schedules', - sender: { - successCallback: defaultSuccessCallback, - errorCallback: defaultErrorCallback - }, - data: { - intervalTimeSeconds: 1, - tolerateSize: 0, - batches: batches, - query: query - }, - success: 'successCallback', - error: 'errorCallback' - }); - } else { - App.ajax.send({ - name: 'restart.hostComponents', - sender: { - successCallback: defaultSuccessCallback, - errorCallback: defaultErrorCallback - }, - data: { - context: context, - resource_filters: resource_filters, - query: query, - operation_level: operation_level - }, - success: 'successCallback', - error: 'errorCallback' - }); - } + App.ajax.send({ + name: 'restart.hostComponents', + sender: { + successCallback: defaultSuccessCallback, + errorCallback: defaultErrorCallback + }, + data: { + context: context, + resource_filters: resource_filters, + query: query, + operation_level: operation_level + }, + success: 'successCallback', + error: 'errorCallback' + }); } }, http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/ambari-web/app/views/common/modal_popup.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/modal_popup.js b/ambari-web/app/views/common/modal_popup.js index a530ed8..c6361fb 100644 --- a/ambari-web/app/views/common/modal_popup.js +++ b/ambari-web/app/views/common/modal_popup.js @@ -37,6 +37,9 @@ App.ModalPopup = Ember.View.extend({ primaryClass: 'btn-success', secondaryClass: '', thirdClass: '', + primaryId: '', + secondaryId: '', + thirdId: '', onPrimary: function () { this.hide(); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/ambari-web/app/views/common/modal_popups/confirmation_popup.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/modal_popups/confirmation_popup.js b/ambari-web/app/views/common/modal_popups/confirmation_popup.js index fbcc882..dc7f596 100644 --- a/ambari-web/app/views/common/modal_popups/confirmation_popup.js +++ b/ambari-web/app/views/common/modal_popups/confirmation_popup.js @@ -29,7 +29,7 @@ var App = require('app'); * @param {Boolean} isCritical * @return {*} */ -App.showConfirmationPopup = function (primary, body, secondary, header, primaryText, isCritical) { +App.showConfirmationPopup = function (primary, body, secondary, header, primaryText, isCritical, staticId) { if (!primary) { return false; } @@ -39,6 +39,9 @@ App.showConfirmationPopup = function (primary, body, secondary, header, primaryT header: header || Em.I18n.t('popup.confirmation.commonHeader'), body: body || Em.I18n.t('question.sure'), primaryClass: isCritical ? 'btn-danger' : 'btn-success', + primaryId: staticId ? staticId + '_primary' : '', + secondaryId: staticId ? staticId + '_secondary' : '', + thirdId: staticId ? staticId + '_third' : '', onPrimary: function () { this.hide(); primary(); http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/ambari-web/test/controllers/main/service_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/service_test.js b/ambari-web/test/controllers/main/service_test.js index 440c26e..0421a43 100644 --- a/ambari-web/test/controllers/main/service_test.js +++ b/ambari-web/test/controllers/main/service_test.js @@ -703,27 +703,4 @@ describe('App.MainServiceController', function () { expect(mock.showPopup.calledOnce).to.be.true; }); }); - - describe('#restartHostComponents', function () { - - beforeEach(function () { - this.mock = sinon.stub(App.HostComponent, 'find'); - }); - afterEach(function () { - App.HostComponent.find.restore(); - }); - - it('should make batch request to refresh YARN queues', function () { - this.mock.returns([Em.Object.create({componentName: 'HIVE_SERVER_INTERACTIVE', staleConfigs: true}), Em.Object.create({componentName: 'RESOURCEMANAGER', staleConfigs: false})]); - mainServiceController.restartHostComponents(); - expect(testHelpers.findAjaxRequest('name', 'common.batch.request_schedules')).not.to.be.undefined; - }); - - it('should make single request without refresh YARN queues', function () { - this.mock.returns([Em.Object.create({componentName: 'HIVE_SERVER_INTERACTIVE', staleConfigs: false}), Em.Object.create({componentName: 'RESOURCEMANAGER', staleConfigs: false})]); - mainServiceController.restartHostComponents(); - expect(testHelpers.findAjaxRequest('name', 'request.post')).not.to.be.undefined; - }); - - }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/58203347/ambari-web/test/utils/batch_scheduled_requests_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/utils/batch_scheduled_requests_test.js b/ambari-web/test/utils/batch_scheduled_requests_test.js index 20b190b..c282350 100644 --- a/ambari-web/test/utils/batch_scheduled_requests_test.js +++ b/ambari-web/test/utils/batch_scheduled_requests_test.js @@ -20,8 +20,6 @@ require('utils/helper'); require('views/common/rolling_restart_view'); var batchUtils = require('utils/batch_scheduled_requests'); var modelSetup = require('test/init_model_test'); -var testHelpers = require('test/helpers'); - describe('batch_scheduled_requests', function() { beforeEach(function(){ @@ -133,25 +131,4 @@ describe('batch_scheduled_requests', function() { }); - describe('#restartHostComponents', function () { - - beforeEach(function () { - sinon.stub(App.HostComponent, 'find').returns([Em.Object.create({componentName: 'RESOURCEMANAGER', hostName: '1'})]); - }); - afterEach(function () { - App.HostComponent.find.restore(); - }); - - it('should make batch request to refresh YARN queues', function () { - batchUtils.restartHostComponents([Em.Object.create({componentName: 'HIVE_SERVER_INTERACTIVE'})]); - expect(testHelpers.findAjaxRequest('name', 'common.batch.request_schedules')).to.exists; - }); - - it('should make single request without refresh YARN queues', function () { - batchUtils.restartHostComponents([Em.Object.create({componentName: 'NAMENODE'})]); - expect(testHelpers.findAjaxRequest('name', 'restart.hostComponents')).to.exists; - }); - - }); - });