| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| var App = require('app'); |
| var batchUtils = require('utils/batch_scheduled_requests'); |
| var hostsManagement = require('utils/hosts'); |
| var stringUtils = require('utils/string_utils'); |
| require('utils/configs/add_component_config_initializer'); |
| |
| App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDownload, App.InstallComponent, App.InstallNewVersion, App.CheckHostMixin, App.TrackRequestMixin, { |
| |
| name: 'mainHostDetailsController', |
| |
| /** |
| * Viewed host |
| * @type {App.Host|null} |
| */ |
| content: null, |
| |
| /** |
| * Is check host procedure finished |
| * @type {bool} |
| */ |
| checkHostFinished: null, |
| |
| /** |
| * Does user come from hosts page |
| * @type {bool} |
| */ |
| isFromHosts: false, |
| |
| /** |
| * Determines whether we are adding Hive Server2 component |
| * @type {bool} |
| */ |
| addHiveServer: false, |
| |
| /** |
| * Determines whether we are adding ZooKeeper Server component |
| * @type {bool} |
| */ |
| addZooKeeperServer: false, |
| |
| /** |
| * path to page visited before |
| * @type {string} |
| */ |
| referer: '', |
| |
| /** |
| * Host on which Hive Metastore will be added |
| * @type {string} |
| */ |
| hiveMetastoreHost: '', |
| |
| /** |
| * Deferred object will be resolved when Oozie configs are downloaded |
| * @type {object} |
| */ |
| isOozieConfigLoaded: $.Deferred(), |
| |
| /** |
| * @type {bool} |
| */ |
| isOozieServerAddable: true, |
| |
| isConfigsLoadingInProgress: false, |
| |
| addDeleteComponentsMap: { |
| 'ZOOKEEPER_SERVER': { |
| addPropertyName: 'addZooKeeperServer', |
| deletePropertyName: 'fromDeleteZkServer', |
| configTagsCallbackName: 'loadZookeeperConfigs', |
| configsCallbackName: 'saveZkConfigs' |
| }, |
| 'HIVE_METASTORE': { |
| deletePropertyName: 'deleteHiveMetaStore', |
| hostPropertyName: 'hiveMetastoreHost', |
| configTagsCallbackName: 'loadHiveConfigs', |
| configsCallbackName: 'onLoadHiveConfigs' |
| }, |
| 'WEBHCAT_SERVER': { |
| deletePropertyName: 'deleteWebHCatServer', |
| hostPropertyName: 'webhcatServerHost', |
| configTagsCallbackName: 'loadWebHCatConfigs', |
| configsCallbackName: 'onLoadHiveConfigs' |
| }, |
| 'HIVE_SERVER': { |
| addPropertyName: 'addHiveServer', |
| deletePropertyName: 'deleteHiveServer', |
| configTagsCallbackName: 'loadHiveConfigs', |
| configsCallbackName: 'onLoadHiveConfigs' |
| }, |
| 'NIMBUS': { |
| deletePropertyName: 'deleteNimbusHost', |
| hostPropertyName: 'nimbusHost', |
| configTagsCallbackName: 'loadStormConfigs', |
| configsCallbackName: 'onLoadStormConfigs' |
| }, |
| 'ATLAS_SERVER': { |
| deletePropertyName: 'deleteAtlasServer', |
| hostPropertyName: 'atlasServer', |
| configTagsCallbackName: 'loadAtlasConfigs', |
| configsCallbackName: 'onLoadAtlasConfigs' |
| }, |
| 'RANGER_KMS_SERVER': { |
| deletePropertyName: 'deleteRangerKMSServer', |
| hostPropertyName: 'rangerKMSServerHost', |
| configTagsCallbackName: 'loadRangerConfigs', |
| configsCallbackName: 'onLoadRangerConfigs' |
| } |
| }, |
| |
| zooKeeperRelatedServices: [ |
| { |
| serviceName: 'HIVE', |
| typesToLoad: ['hive-site', 'webhcat-site'], |
| typesToSave: ['hive-site', 'webhcat-site'] |
| }, |
| { |
| serviceName: 'YARN', |
| typesToLoad: ['yarn-site', 'zoo.cfg'], |
| typesToSave: ['yarn-site'] |
| }, |
| { |
| serviceName: 'HBASE', |
| typesToLoad: ['hbase-site'], |
| typesToSave: ['hbase-site'] |
| }, |
| { |
| serviceName: 'ACCUMULO', |
| typesToLoad: ['accumulo-site'], |
| typesToSave: ['accumulo-site'] |
| }, |
| { |
| serviceName: 'KAFKA', |
| typesToLoad: ['kafka-broker'], |
| typesToSave: ['kafka-broker'] |
| }, |
| { |
| serviceName: 'ATLAS', |
| typesToLoad: ['application-properties', 'infra-solr-env'], |
| typesToSave: ['application-properties'] |
| }, |
| { |
| serviceName: 'STORM', |
| typesToLoad: ['storm-site'], |
| typesToSave: ['storm-site'] |
| } |
| ], |
| |
| /** |
| * Determines whether adding/deleting host component requires configs changes |
| * @type {Boolean} |
| */ |
| isReconfigureRequired: false, |
| |
| /** |
| * Contains component-related config properties loaded from server |
| * @type {Object|null} |
| */ |
| configs: null, |
| |
| /** |
| * Array of all properties affected by adding/deleting host component |
| * @type {Array} |
| */ |
| allPropertiesToChange: [], |
| |
| /** |
| * Array of editable properties affected by adding/deleting host component |
| * @type {Array} |
| */ |
| recommendedPropertiesToChange: [], |
| |
| /** |
| * Array of non-editable properties affected by adding/deleting host component |
| * @type {Array} |
| */ |
| requiredPropertiesToChange: [], |
| |
| /** |
| * Properties affected by adding/deleting host component, grouped by service, formatted for PUT call |
| * @type {Array} |
| */ |
| groupedPropertiesToChange: [], |
| |
| hasPropertiesToChange: Em.computed.or('recommendedPropertiesToChange.length', 'requiredPropertiesToChange.length'), |
| |
| addDeleteComponentPopupBody: Em.View.extend({ |
| templateName: require('templates/main/host/details/addDeleteComponentPopup'), |
| commonMessage: '', |
| manualKerberosWarning: App.get('router.mainAdminKerberosController.isManualKerberos') ? |
| Em.I18n.t('hosts.host.manualKerberosWarning') : '', |
| lastComponent: false, |
| lastComponentError: '', |
| fromServiceSummary: false, |
| selectedHost: null, |
| anyHostsWithoutComponent: true |
| }), |
| |
| saveLoadedConfigs: function (data) { |
| this.set('configs', { |
| items: data.items.map((item) => { |
| return { |
| type: item.type, |
| properties_attributes: item.properties_attributes, |
| properties: Em.copy(item.properties) |
| } |
| }) |
| }); |
| }, |
| |
| clearConfigsChanges: function (shouldKeepLoadedConfigs) { |
| var arrayNames = ['allPropertiesToChange', 'recommendedPropertiesToChange', 'requiredPropertiesToChange', 'groupedPropertiesToChange']; |
| this.abortRequests(); |
| arrayNames.forEach(function (arrayName) { |
| this.get(arrayName).clear(); |
| }, this); |
| this.set('isReconfigureRequired', false); |
| if (!shouldKeepLoadedConfigs) { |
| this.set('configs', null); |
| } |
| }, |
| |
| applyConfigsCustomization: function () { |
| this.get('recommendedPropertiesToChange').forEach(function (property) { |
| var value = property.saveRecommended ? property.recommendedValue : property.initialValue, |
| filename = property.propertyFileName; |
| if (this.get('groupedPropertiesToChange.length')) { |
| var group = this.get('groupedPropertiesToChange').find(function (item) { |
| return item.properties.hasOwnProperty(filename); |
| }); |
| if (group) { |
| group.properties[filename][property.propertyName] = value; |
| } |
| } |
| }, this); |
| }, |
| |
| /** |
| * Open dashboard page |
| * @method routeHome |
| */ |
| routeHome: function () { |
| App.router.transitionTo('main.dashboard.index'); |
| }, |
| |
| /** |
| * List of active (not in passive state) host components |
| * @type {Ember.Enumerable} |
| */ |
| serviceActiveComponents: function () { |
| return this.get('content.hostComponents').filterProperty('service.isInPassive', false); |
| }.property('content.hostComponents'), |
| |
| /** |
| * List of active host components which aren't clients |
| * @type {Ember.Enumerable} |
| */ |
| serviceNonClientActiveComponents: Em.computed.filterBy('serviceActiveComponents', 'isClient', false), |
| |
| /** |
| * send command to server to start selected host component |
| * @param {object} event |
| * @method startComponent |
| */ |
| startComponent: function (event) { |
| var self = this; |
| var component = event.context; |
| return App.showConfirmationPopup(function () { |
| var context = Em.I18n.t('requestInfo.startHostComponent') + " " + component.get('displayName'); |
| self.sendComponentCommand(component, context, App.HostComponentStatus.started); |
| }, Em.I18n.t('question.sure.start').format(component.get('displayName'))); |
| }, |
| |
| /** |
| * send command to server to stop selected host component |
| * @param {object} event |
| * @method startComponent |
| */ |
| stopComponent: function (event) { |
| var self = this; |
| var component = event.context; |
| if (event.context.get('componentName') === 'NAMENODE' ) { |
| this.checkNnLastCheckpointTime(function () { |
| return App.showConfirmationPopup(function () { |
| var context = Em.I18n.t('requestInfo.stopHostComponent') + " " + component.get('displayName'); |
| self.sendComponentCommand(component, context, App.HostComponentStatus.stopped); |
| }, Em.I18n.t('question.sure.stop').format(component.get('displayName'))); |
| }); |
| } else { |
| return App.showConfirmationPopup(function () { |
| var context = Em.I18n.t('requestInfo.stopHostComponent') + " " + component.get('displayName'); |
| self.sendComponentCommand(component, context, App.HostComponentStatus.stopped); |
| }, Em.I18n.t('question.sure.stop').format(component.get('displayName'))); |
| } |
| }, |
| /** |
| * PUTs a command to server to start/stop a component. If no |
| * specific component is provided, all components are started. |
| * @param {object} component When <code>null</code> all startable components are started. |
| * @param {String} context Context under which this command is beign sent. |
| * @param {String} state - desired state of component can be 'STARTED' or 'STOPPED' |
| * @method sendComponentCommand |
| */ |
| sendComponentCommand: function (component, context, state) { |
| var data = { |
| hostName: this.get('content.hostName'), |
| context: context, |
| component: component, |
| HostRoles: { |
| state: state |
| } |
| }; |
| if (Array.isArray(component)) { |
| data.query = "HostRoles/component_name.in(" + component.mapProperty('componentName').join(',') + ")"; |
| } else { |
| data.componentName = component.get('componentName'); |
| data.serviceName = component.get('service.serviceName'); |
| } |
| App.ajax.send({ |
| name: (Array.isArray(component)) ? 'common.host.host_components.update' : 'common.host.host_component.update', |
| sender: this, |
| data: data, |
| success: 'sendComponentCommandSuccessCallback', |
| error: 'ajaxErrorCallback', |
| showLoadingPopup: true |
| }); |
| }, |
| |
| /** |
| * Success callback for stop/start host component request |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method stopComponentSuccessCallback |
| */ |
| sendComponentCommandSuccessCallback: function (data, opt, params) { |
| var running = (params.HostRoles.state === App.HostComponentStatus.stopped) ? App.HostComponentStatus.stopping : App.HostComponentStatus.starting; |
| params.component.set('workStatus', running); |
| if (App.get('testMode')) { |
| this.mimicWorkStatusChange(params.component, running, params.HostRoles.state); |
| } |
| this.showBackgroundOperationsPopup(); |
| }, |
| |
| /** |
| * Return true if hdfs user data is loaded via App.MainServiceInfoConfigsController |
| */ |
| getHdfsUser: function () { |
| var self = this; |
| var dfd = $.Deferred(); |
| var miscController = App.MainAdminServiceAccountsController.create(); |
| miscController.loadUsers(); |
| miscController.addObserver('dataIsLoaded', this, function() { |
| if (miscController.get('dataIsLoaded') && miscController.get('users')) { |
| if (miscController.get('users').someProperty('name', 'hdfs_user')) { |
| self.set('hdfsUser', miscController.get('users').findProperty('name', 'hdfs_user').get('value')); |
| } else { |
| self.set('hdfsUser', '<hdfs-user>'); |
| } |
| dfd.resolve(); |
| miscController.destroy(); |
| } |
| }); |
| return dfd.promise(); |
| }, |
| |
| /** |
| * this function will be called from :1) stop NN 2) restart NN 3) stop all components |
| * @param callback - callback function to continue next operation |
| * @param hostname - namenode host (by default is current host) |
| */ |
| checkNnLastCheckpointTime: function(callback, hostName) { |
| var self = this; |
| this.pullNnCheckPointTime(hostName).complete(function () { |
| var isNNCheckpointTooOld = self.get('isNNCheckpointTooOld'); |
| self.set('isNNCheckpointTooOld', null); |
| if (isNNCheckpointTooOld) { |
| // too old |
| self.getHdfsUser().done(function() { |
| var msg = Em.Object.create({ |
| confirmMsg: Em.I18n.t('services.service.stop.HDFS.warningMsg.checkPointTooOld').format(App.nnCheckpointAgeAlertThreshold) + |
| Em.I18n.t('services.service.stop.HDFS.warningMsg.checkPointTooOld.makeSure') + |
| Em.I18n.t('services.service.stop.HDFS.warningMsg.checkPointTooOld.instructions.singleHost.login').format(isNNCheckpointTooOld) + |
| Em.I18n.t('services.service.stop.HDFS.warningMsg.checkPointTooOld.instructions').format(self.get('hdfsUser')), |
| confirmButton: Em.I18n.t('common.next') |
| }); |
| return App.showConfirmationFeedBackPopup(callback, msg); |
| }); |
| } else if (isNNCheckpointTooOld == null) { |
| // not available |
| return App.showConfirmationPopup( |
| callback, Em.I18n.t('services.service.stop.HDFS.warningMsg.checkPointNA'), null, |
| Em.I18n.t('common.warning'), Em.I18n.t('common.proceedAnyway'), 'danger' |
| ); |
| } else { |
| // still young |
| callback(); |
| } |
| }); |
| }, |
| |
| pullNnCheckPointTime: function (hostName) { |
| return App.ajax.send({ |
| name: 'common.host_component.getNnCheckPointTime', |
| sender: this, |
| data: { |
| host: hostName || this.get('content.hostName') |
| }, |
| success: 'parseNnCheckPointTime' |
| }); |
| }, |
| |
| parseNnCheckPointTime: function (data) { |
| var lastCheckpointTime = Em.get(data, 'metrics.dfs.FSNamesystem.LastCheckpointTime'); |
| var hostName = Em.get(data, 'HostRoles.host_name'); |
| |
| if (Em.get(data, 'metrics.dfs.FSNamesystem.HAState') === 'active') { |
| if (!lastCheckpointTime) { |
| this.set("isNNCheckpointTooOld", null); |
| } else { |
| var time_criteria = App.nnCheckpointAgeAlertThreshold; // time in hours to define how many hours ago is too old |
| var time_ago = (Math.round(App.dateTime() / 1000) - (time_criteria * 3600)) *1000; |
| if (lastCheckpointTime <= time_ago) { |
| // too old, set the effected hostName |
| this.set("isNNCheckpointTooOld", hostName); |
| } else { |
| // still young |
| this.set("isNNCheckpointTooOld", false); |
| } |
| } |
| } else if (Em.get(data, 'metrics.dfs.FSNamesystem.HAState') === 'standby') { |
| this.set("isNNCheckpointTooOld", false); |
| } |
| }, |
| |
| /** |
| * mimic status transition in test mode |
| * @param entity |
| * @param transitionalState |
| * @param finalState |
| */ |
| mimicWorkStatusChange: function (entity, transitionalState, finalState) { |
| if (Em.isArray(entity)) { |
| entity.forEach(function (item) { |
| item.set('workStatus', transitionalState); |
| setTimeout(function () { |
| item.set('workStatus', finalState); |
| }, App.testModeDelayForActions); |
| }); |
| } else { |
| entity.set('workStatus', transitionalState); |
| setTimeout(function () { |
| entity.set('workStatus', finalState); |
| }, App.testModeDelayForActions); |
| } |
| }, |
| |
| /** |
| * load data (if we need to show this background operations popup) from persist |
| * @param callback |
| */ |
| showBackgroundOperationsPopup: function (callback) { |
| App.router.get('userSettingsController').dataLoading('show_bg').done(function (initValue) { |
| if (initValue) { |
| App.router.get('backgroundOperationsController').showPopup(); |
| } |
| if (typeof callback === 'function') { |
| callback(); |
| } |
| }); |
| }, |
| |
| /** |
| * Send command to server to delete selected host component |
| * @param {object} event |
| * @method deleteComponent |
| */ |
| deleteComponent: function (event) { |
| if ($(event.target).closest('li').hasClass('disabled')) { |
| return; |
| } |
| const component = event.context; |
| const componentName = component.get('componentName'); |
| const componentsMapItem = this.get('addDeleteComponentsMap')[componentName]; |
| |
| if (componentsMapItem) { |
| this.deleteAndReconfigureComponent(componentsMapItem, component); |
| } else if (componentName === 'JOURNALNODE') { |
| return App.showConfirmationPopup(function () { |
| App.router.transitionTo('main.services.manageJournalNode'); |
| }, Em.I18n.t('hosts.host.deleteComponent.popup.deleteJournalNodeMsg')); |
| } else { |
| return this.showReconfigurationPopupPreDelete(component, () => this._doDeleteHostComponent(componentName)); |
| } |
| }, |
| |
| /** |
| * |
| * @param {object} componentsMapItem |
| * @param {App.HostComponent} component |
| * @returns {App.ModalPopup} |
| */ |
| deleteAndReconfigureComponent: function(componentsMapItem, component) { |
| if (componentsMapItem.deletePropertyName) { |
| this.set(componentsMapItem.deletePropertyName, true); |
| } |
| this.loadComponentRelatedConfigs(componentsMapItem.configTagsCallbackName, componentsMapItem.configsCallbackName); |
| return this.showReconfigurationPopupPreDelete(component, () => { |
| this._doDeleteHostComponent(component.get('componentName')).done(() => { |
| this.applyConfigsCustomization(); |
| this.putConfigsToServer(this.get('groupedPropertiesToChange'), component.get('componentName')); |
| this.clearConfigsChanges(); |
| }); |
| }); |
| }, |
| |
| showReconfigurationPopupPreDelete: function (component, primary = Em.K, commonMessage) { |
| const isLastComponent = (this.getTotalComponent(component) === 1), |
| componentDisplayName = component.get('displayName'); |
| |
| return App.ModalPopup.show({ |
| header: Em.I18n.t('popup.confirmation.commonHeader'), |
| controller: this, |
| hasPropertiesToChange: false, |
| classNameBindings: ['controller.hasPropertiesToChange:common-modal-wrapper'], |
| modalDialogClasses: function () { |
| return this.get('controller.hasPropertiesToChange') ? ['modal-xlg'] : []; |
| }.property('controller.hasPropertiesToChange'), |
| primary: Em.I18n.t('hosts.host.deleteComponent.popup.confirm'), |
| bodyClass: this.get('addDeleteComponentPopupBody').extend({ |
| commonMessage: commonMessage || Em.I18n.t('hosts.host.deleteComponent.popup.msg1').format(componentDisplayName), |
| recommendedPropertiesToChange: this.get('recommendedPropertiesToChange'), |
| requiredPropertiesToChange: this.get('requiredPropertiesToChange'), |
| lastComponentError: Em.I18n.t('hosts.host.deleteComponent.popup.warning').format(componentDisplayName), |
| lastComponent: isLastComponent |
| }), |
| isChecked: !isLastComponent, |
| disablePrimary: function () { |
| return (this.get('controller.isReconfigureRequired') && this.get('controller.isConfigsLoadingInProgress')) || !this.get('isChecked'); |
| }.property('controller.isReconfigureRequired', 'controller.isConfigsLoadingInProgress', 'isChecked'), |
| onPrimary: function () { |
| this._super(); |
| primary(); |
| }, |
| onSecondary: function () { |
| this._super(); |
| this.get('controller').clearConfigsChanges(); |
| }, |
| onClose: function () { |
| this._super(); |
| this.get('controller').clearConfigsChanges(); |
| } |
| }); |
| }, |
| |
| /** |
| * get total count of host-components |
| * @method getTotalComponent |
| * @param component |
| * @return {Number} |
| */ |
| getTotalComponent: function (component) { |
| var count; |
| if (component.get('isSlave')) { |
| count = App.SlaveComponent.find(component.get('componentName')).get('totalCount'); |
| } else if (component.get('isClient')) { |
| count = App.ClientComponent.find(component.get('componentName')).get('totalCount'); |
| } else { |
| count = App.HostComponent.find().filterProperty('componentName', component.get('componentName')).get('length'); |
| } |
| return count || 0; |
| }, |
| |
| /** |
| * Trigger to reset list of master/slaves components on the view |
| * @type {bool} |
| */ |
| redrawComponents: false, |
| |
| /** |
| * Deletes the given host component, or all host components. |
| * |
| * @param {string} componentName |
| * @return {$.ajax} |
| * @method _doDeleteHostComponent |
| */ |
| _doDeleteHostComponent: function (componentName) { |
| return App.ajax.send({ |
| name: (Em.isNone(componentName)) ? 'common.delete.host' : 'common.delete.host_component', |
| sender: this, |
| data: { |
| componentName: componentName || '', |
| hostName: this.get('content.hostName') |
| }, |
| success: '_doDeleteHostComponentSuccessCallback', |
| error: '_doDeleteHostComponentErrorCallback', |
| showLoadingPopup: true |
| }); |
| }, |
| |
| /** |
| * Error of delete component(s) request |
| * @type {object} |
| */ |
| _deletedHostComponentError: null, |
| |
| /** |
| * Success callback for delete host component request |
| * @method _doDeleteHostComponentSuccessCallback |
| */ |
| _doDeleteHostComponentSuccessCallback: function (response, request, data) { |
| this.set('_deletedHostComponentError', null); |
| }, |
| |
| /** |
| * Error-callback for delete host component request |
| * @param {object} xhr |
| * @param {string} textStatus |
| * @param {object} errorThrown |
| * @param {object} data |
| * @method _doDeleteHostComponentErrorCallback |
| */ |
| _doDeleteHostComponentErrorCallback: function (xhr, textStatus, errorThrown, data) { |
| this.set('_deletedHostComponentError', {xhr: xhr, url: data.url, method: 'DELETE'}); |
| }, |
| |
| /** |
| * Send command to server to upgrade selected host component |
| * @param {object} event |
| * @method upgradeComponent |
| */ |
| upgradeComponent: function (event) { |
| var self = this; |
| var component = event.context; |
| return App.showConfirmationPopup(function () { |
| App.ajax.send({ |
| name: 'host.host_component.upgrade', |
| sender: self, |
| data: { |
| component: component, |
| hostName: self.get('content.hostName'), |
| componentName: component.get('componentName'), |
| data: JSON.stringify({ |
| RequestInfo: { |
| "context": Em.I18n.t('requestInfo.upgradeHostComponent') + " " + component.get('displayName') |
| }, |
| Body: { |
| HostRoles: { |
| stack_id: 'HDP-1.2.2', |
| state: 'INSTALLED' |
| } |
| } |
| }) |
| }, |
| success: 'upgradeComponentSuccessCallback', |
| error: 'ajaxErrorCallback' |
| }); |
| }, Em.I18n.t('question.sure.upgrade').format(component.get('displayName'))); |
| }, |
| |
| /** |
| * Success callback for upgrade host component request |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method upgradeComponentSuccessCallback |
| */ |
| upgradeComponentSuccessCallback: function (data, opt, params) { |
| if (App.get('testMode')) { |
| this.mimicWorkStatusChange(params.component, App.HostComponentStatus.starting, App.HostComponentStatus.started); |
| } |
| this.showBackgroundOperationsPopup(); |
| }, |
| |
| /** |
| * Send command to server to restart selected components |
| * @param {object} event |
| * @method restartComponent |
| */ |
| restartComponent: function (event) { |
| var component = event.context; |
| if (event.context.get('componentName') === 'NAMENODE') { |
| this.checkNnLastCheckpointTime(function () { |
| return App.showConfirmationPopup(function () { |
| batchUtils.restartHostComponents([component], Em.I18n.t('rollingrestart.context.selectedComponentOnSelectedHost').format(component.get('displayName')), "HOST_COMPONENT"); |
| }, Em.I18n.t('question.sure.restart').format(component.get('displayName'))); |
| }); |
| } else { |
| return App.showConfirmationPopup(function () { |
| batchUtils.restartHostComponents([component], Em.I18n.t('rollingrestart.context.selectedComponentOnSelectedHost').format(component.get('displayName')), "HOST_COMPONENT"); |
| }, Em.I18n.t('question.sure.restart').format(component.get('displayName'))); |
| } |
| }, |
| |
| /** |
| * add component as <code>addComponent<code> method but perform |
| * kdc session state if cluster is secure; |
| * @param event |
| */ |
| addComponentWithCheck: function (event) { |
| App.get('router.mainAdminKerberosController').getSecurityType(function (event) { |
| App.get('router.mainAdminKerberosController').getKDCSessionState(this.addComponent.bind(this, event)); |
| }.bind(this, event)); |
| }, |
| /** |
| * Send command to server to install selected host component |
| * @param {object} event |
| * @method addComponent |
| */ |
| addComponent: function (event) { |
| var |
| component = event.context, |
| hostName = this.get('content.hostName'), |
| componentName = component.get('componentName'), |
| missedComponents = event.fromServiceSummary ? [] : this.checkComponentDependencies(componentName, { |
| scope: 'host', |
| installedComponents: this.get('content.hostComponents').mapProperty('componentName') |
| }), |
| isManualKerberos = App.get('router.mainAdminKerberosController.isManualKerberos'), |
| manualKerberosWarning = isManualKerberos ? Em.I18n.t('hosts.host.manualKerberosWarning') : '', |
| componentsMapItem = this.get('addDeleteComponentsMap')[componentName]; |
| |
| if (missedComponents.length) { |
| const popupMessage = Em.I18n.t('host.host.addComponent.popup.dependedComponents.body').format(component.get('displayName'), |
| stringUtils.getFormattedStringFromArray(missedComponents.map(function (cName) { |
| return App.StackServiceComponent.find(cName).get('displayName'); |
| }))); |
| return App.showAlertPopup(Em.I18n.t('host.host.addComponent.popup.dependedComponents.header'), popupMessage); |
| } |
| |
| if (componentsMapItem) { |
| this.addAndReconfigureComponent(componentsMapItem, hostName, component, event.fromServiceSummary); |
| } else if (componentName === 'JOURNALNODE') { |
| return App.showConfirmationPopup(function () { |
| App.router.transitionTo('main.services.manageJournalNode'); |
| }, Em.I18n.t('hosts.host.addComponent.' + componentName) + manualKerberosWarning); |
| } else { |
| return this.showAddComponentPopup(component, hostName, () => { |
| // hostname should be taken via this.get('content.hostName') because the host could be selected later |
| this.installHostComponentCall(this.get('content.hostName'), component); |
| }, event.fromServiceSummary); |
| } |
| }, |
| |
| /** |
| * |
| * @param {object} componentsMapItem |
| * @param {string} hostName |
| * @param {App.HostComponent} component |
| * @param {boolean} fromServiceSummary |
| * @returns {*} |
| */ |
| addAndReconfigureComponent: function(componentsMapItem, hostName, component, fromServiceSummary) { |
| if (componentsMapItem.hostPropertyName) { |
| this.set(componentsMapItem.hostPropertyName, hostName); |
| } |
| if (componentsMapItem.addPropertyName) { |
| this.set(componentsMapItem.addPropertyName, true); |
| } |
| this.loadComponentRelatedConfigs(componentsMapItem.configTagsCallbackName, componentsMapItem.configsCallbackName); |
| return this.showAddComponentPopup(component, hostName, () => { |
| this.installAndReconfigureComponent(this.get('content.hostName'), component, componentsMapItem); |
| }, fromServiceSummary); |
| }, |
| |
| /** |
| * |
| * @param {string} hostName |
| * @param {App.HostComponent} component |
| * @param {object} componentsMapItem |
| */ |
| installAndReconfigureComponent: function(hostName, component, componentsMapItem) { |
| this.applyConfigsCustomization(); |
| this.installHostComponentCall(hostName, component).done(() => { |
| this.putConfigsToServer(this.get('groupedPropertiesToChange'), component.get('componentName')); |
| }).always(() => { |
| this.set(componentsMapItem.addPropertyName, false); |
| this.clearConfigsChanges(); |
| }); |
| }, |
| |
| showAddComponentPopup: function (component, hostName, primary, fromServiceSummary) { |
| var self = this, |
| componentName = component.get('componentName'), |
| componentDisplayName = component.get('displayName'), |
| componentsMapItem = this.get('addDeleteComponentsMap')[componentName], |
| commonMessage = Em.I18n.t('hosts.host.addComponent.msg').format(componentDisplayName); |
| |
| return App.ModalPopup.show({ |
| header: Em.I18n.t('popup.confirmation.commonHeader'), |
| controller: self, |
| hasPropertiesToChange: false, |
| classNameBindings: ['hasPropertiesToChange:common-modal-wrapper'], |
| modalDialogClasses: function () { |
| return this.get('controller.hasPropertiesToChange') ? ['modal-xlg'] : []; |
| }.property('controller.hasPropertiesToChange'), |
| primary: Em.I18n.t('hosts.host.addComponent.popup.confirm'), |
| bodyClass: self.get('addDeleteComponentPopupBody').extend({ |
| commonMessage: commonMessage, |
| fromServiceSummary: fromServiceSummary, |
| addComponentMsg: Em.I18n.t('hosts.host.addComponent.msg').format(componentDisplayName), |
| selectHostMsg: Em.I18n.t('services.summary.selectHostForComponent').format(componentDisplayName), |
| thereIsNoHostsMsg: Em.I18n.t('services.summary.allHostsAlreadyRunComponent').format(componentDisplayName), |
| hostsWithoutComponent: function () { |
| if (this.get('fromServiceSummary')) { |
| const hostsWithComponent = App.HostComponent.find().filterProperty('componentName', componentName).mapProperty('hostName'); |
| return App.get('allHostNames').filter((hostname) => !hostsWithComponent.contains(hostname)); |
| } else { |
| return []; |
| } |
| }.property('fromServiceSummary'), |
| anyHostsWithoutComponent: Em.computed.or('!fromServiceSummary', 'hostsWithoutComponent.length'), |
| selectedHostObserver: function () { |
| const selectedHostName = this.get('selectedHost'); |
| if (!self.get('content')) { |
| self.set('content', {}); |
| } |
| self.setProperties({ |
| 'content.hostName': selectedHostName |
| }); |
| if (componentsMapItem) { |
| const configs = self.get('configs'); |
| const params = configs && configs.params || {}; |
| if (componentsMapItem.hostPropertyName) { |
| self.set(componentsMapItem.hostPropertyName, selectedHostName); |
| } |
| if (componentsMapItem.addPropertyName) { |
| self.set(componentsMapItem.addPropertyName, true); |
| } |
| if (configs) { |
| self.clearConfigsChanges(true); |
| self.set('isReconfigureRequired', true); |
| self.set('isConfigsLoadingInProgress', true); |
| self[componentsMapItem.configsCallbackName](configs, null, params); |
| } else { |
| self.loadComponentRelatedConfigs(componentsMapItem.configTagsCallbackName, componentsMapItem.configsCallbackName); |
| } |
| } |
| }.observes('selectedHost') |
| }), |
| disablePrimary: Em.computed.and('controller.isReconfigureRequired', 'controller.isConfigsLoadingInProgress'), |
| onPrimary: function () { |
| this._super(); |
| if (primary) { |
| primary(); |
| } |
| }, |
| onSecondary: function () { |
| this._super(); |
| self.clearConfigsChanges(); |
| }, |
| onClose: function () { |
| this._super(); |
| self.clearConfigsChanges(); |
| } |
| }); |
| }, |
| |
| loadComponentRelatedConfigs: function (configTagsCallbackName, configsCallbackName) { |
| this.clearConfigsChanges(); |
| this.set('isReconfigureRequired', true); |
| this.set('isConfigsLoadingInProgress', true); |
| this.isServiceMetricsLoaded(() => { |
| this.loadConfigs(configTagsCallbackName, configsCallbackName); |
| }); |
| }, |
| |
| /** |
| * Success callback for install host component request (sent in <code>addNewComponentSuccessCallback</code>) |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method installNewComponentSuccessCallback |
| */ |
| installNewComponentSuccessCallback: function (data, opt, params) { |
| if (!data || !data.Requests || !data.Requests.id) { |
| return false; |
| } |
| |
| if (App.get('testMode')) { |
| this.mimicWorkStatusChange(params.component, App.HostComponentStatus.installing, App.HostComponentStatus.stopped); |
| } |
| |
| this.showBackgroundOperationsPopup(); |
| return true; |
| }, |
| |
| /** |
| * Call <code>setRackInfo</code> function to show Set Rack Id popup |
| * @param data |
| */ |
| setRackId: function (data) { |
| var rack = data.context.get('rack'); |
| var hosts = [data.context]; |
| var operationData = {message: Em.I18n.t('hosts.host.details.setRackId')}; |
| hostsManagement.setRackInfo(operationData, hosts, rack); |
| }, |
| |
| /** |
| * Success callback for load configs request |
| * @param {object} data |
| * @method loadOozieConfigs |
| */ |
| loadOozieConfigs: function (data) { |
| return App.ajax.send({ |
| name: 'admin.get.all_configurations', |
| sender: this, |
| data: { |
| urlParams: '(type=oozie-env&tag=' + data.Clusters.desired_configs['oozie-env'].tag + ')' |
| }, |
| success: 'onLoadOozieConfigs', |
| error: 'onLoadConfigsErrorCallback' |
| }); |
| }, |
| |
| /** |
| * get Oozie database config and set databaseType |
| * @param {object} data |
| * @method onLoadOozieConfigs |
| */ |
| onLoadOozieConfigs: function (data) { |
| var configs = {}; |
| data.items.forEach(function (item) { |
| $.extend(configs, item.properties); |
| }); |
| this.set('isOozieServerAddable', !(Em.isEmpty(configs["oozie_database"]) || configs["oozie_database"] === 'New Derby Database')); |
| this.get('isOozieConfigLoaded').resolve(); |
| }, |
| |
| |
| /** |
| * Success callback for Storm load configs request |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method loadStormConfigs |
| */ |
| loadStormConfigs: function (data, opt, params) { |
| var request = App.ajax.send({ |
| name: 'admin.get.all_configurations', |
| sender: this, |
| data: { |
| urlParams: '(type=storm-site&tag=' + data.Clusters.desired_configs['storm-site'].tag + ')' |
| }, |
| success: params.callback |
| }); |
| this.trackRequest(request); |
| }, |
| |
| /** |
| * Success callback for Atlas load configs request |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method loadAtlasConfigs |
| */ |
| loadAtlasConfigs: function (data, opt, params) { |
| var request = App.ajax.send({ |
| name: 'admin.get.all_configurations', |
| sender: this, |
| data: { |
| urlParams: '(type=application-properties&tag=' + data.Clusters.desired_configs['application-properties'].tag + ')' |
| }, |
| success: params.callback |
| }); |
| this.trackRequest(request); |
| }, |
| |
| /** |
| * Update zk configs |
| * @param {object} configs |
| * @method updateZkConfigs |
| */ |
| updateZkConfigs: function (configs) { |
| const portValue = configs['zoo.cfg'] && Em.get(configs['zoo.cfg'], 'clientPort'), |
| zkPort = typeof portValue === 'undefined' ? '2181' : portValue, |
| infraSolrZnode = configs['infra-solr-env'] ? Em.get(configs['infra-solr-env'], 'infra_solr_znode') : '/ambari-solr', |
| initializer = App.AddZooKeeperComponentsInitializer, |
| hostComponentsTopology = { |
| masterComponentHosts: [] |
| }, |
| propertiesToChange = this.get('allPropertiesToChange'), |
| masterComponents = this.bootstrapHostsMapping('ZOOKEEPER_SERVER'); |
| if (this.get('fromDeleteHost') || this.get('fromDeleteZkServer')) { |
| this.set('fromDeleteHost', false); |
| this.set('fromDeleteZkServer', false); |
| let removedHost = masterComponents.findProperty('hostName', this.get('content.hostName')); |
| if (!Em.isNone(removedHost)) { |
| Em.set(removedHost, 'isInstalled', false); |
| } |
| } else if (this.get('addZooKeeperServer')) { |
| this.set('addZooKeeperServer', false); |
| masterComponents.push({ |
| component: 'ZOOKEEPER_SERVER', |
| hostName: this.get('content.hostName'), |
| isInstalled: true |
| }); |
| } |
| const dependencies = { |
| zkClientPort: zkPort, |
| infraSolrZnode |
| }; |
| hostComponentsTopology.masterComponentHosts = masterComponents; |
| Em.keys(configs).forEach(fileName => { |
| const properties = configs[fileName]; |
| Em.keys(properties).forEach(propertyName => { |
| const currentValue = properties[propertyName], |
| propertyDef = { |
| fileName, |
| name: propertyName, |
| value: currentValue |
| }, |
| configProperty = initializer.initialValue(propertyDef, hostComponentsTopology, dependencies); |
| initializer.updateSiteObj(configs[fileName], configProperty); |
| if (currentValue !== configs[fileName][propertyName]) { |
| const service = App.config.get('serviceByConfigTypeMap')[fileName], |
| configObject = App.configsCollection.getConfigByName(propertyName, fileName), |
| displayName = configObject && configObject.displayName; |
| propertiesToChange.pushObject({ |
| propertyFileName: fileName, |
| propertyName, |
| propertyTitle: configObject && Em.I18n.t('installer.controls.serviceConfigPopover.title').format(displayName, displayName === propertyName ? '' : propertyName), |
| propertyDescription: configObject && configObject.description, |
| serviceDisplayName: service && service.get('displayName'), |
| initialValue: currentValue, |
| recommendedValue: propertyDef.value |
| }); |
| } |
| }); |
| }); |
| }, |
| |
| /** |
| * |
| * @param {string} componentName |
| * @param {string[]} [hostNames] |
| * @returns {} |
| */ |
| bootstrapHostsMapping: function(componentName, hostNames) { |
| if (Em.isNone(hostNames)) { |
| hostNames = App.HostComponent.find().filterProperty('componentName', componentName).mapProperty('hostName'); |
| } |
| return hostNames.map(function(hostName) { |
| return { |
| component: componentName, |
| hostName: hostName, |
| isInstalled: true |
| }; |
| }); |
| }, |
| |
| /** |
| * update and save Storm related configs to server |
| * @param {object} data |
| * @method onLoadStormConfigs |
| */ |
| onLoadStormConfigs: function (data) { |
| const nimbusHost = this.get('nimbusHost'), |
| stormNimbusHosts = this.getStormNimbusHosts(), |
| configs = {}, |
| attributes = {}, |
| propertiesToChange = this.get('allPropertiesToChange'); |
| |
| this.saveLoadedConfigs(data); |
| data.items.forEach(item => { |
| configs[item.type] = item.properties; |
| attributes[item.type] = item.properties_attributes || {}; |
| }); |
| |
| this.updateZkConfigs(configs); |
| |
| const propertyName = 'nimbus.seeds', |
| propertyFileName = 'storm-site', |
| nimbusSeedsInit = configs[propertyFileName][propertyName], |
| nimbusSeedsRecommended = JSON.stringify(stormNimbusHosts).replace(/"/g, "'"); |
| configs[propertyFileName][propertyName] = nimbusSeedsRecommended; |
| if (this.get('isReconfigureRequired') && nimbusSeedsInit !== nimbusSeedsRecommended) { |
| const service = App.config.get('serviceByConfigTypeMap')[propertyFileName], |
| configObject = App.configsCollection.getConfigByName(propertyName, propertyFileName), |
| displayName = configObject && configObject.displayName; |
| propertiesToChange.pushObject({ |
| propertyFileName, |
| propertyName, |
| propertyTitle: configObject && Em.I18n.t('installer.controls.serviceConfigPopover.title').format(displayName, displayName === propertyName ? '' : propertyName), |
| propertyDescription: configObject && configObject.description, |
| serviceDisplayName: service && service.get('displayName'), |
| initialValue: nimbusSeedsInit, |
| recommendedValue: nimbusSeedsRecommended |
| }); |
| } |
| const groups = [ |
| { |
| properties: { |
| [propertyFileName]: configs[propertyFileName] |
| }, |
| properties_attributes: { |
| [propertyFileName]: attributes[propertyFileName] |
| } |
| } |
| ]; |
| this.setConfigsChanges(groups); |
| }, |
| |
| onLoadAtlasConfigs: function(data) { |
| const atlasServer = this.get('atlasServer'), |
| atlasServerHosts = this.getAtlasServerHosts(), |
| configs = {}, |
| attributes = {}, |
| propertiesToChange = this.get('allPropertiesToChange'); |
| |
| this.saveLoadedConfigs(data); |
| data.items.forEach(item => { |
| configs[item.type] = item.properties; |
| attributes[item.type] = item.properties_attributes || {}; |
| }); |
| |
| const propertyFileName = 'application-properties', |
| propertyName = 'atlas.rest.address', |
| atlasAddresses = configs[propertyFileName][propertyName], |
| hostMask = atlasAddresses.split(',')[0].replace(/([https|http]*\:\/\/)(.*?)(:[0-9]+)/, '$1{hostname}$3'), |
| atlasAddressesRecommended = atlasServerHosts.map(hostName => hostMask.replace('{hostname}', hostName)).join(','); |
| configs[propertyFileName][propertyName] = atlasAddressesRecommended; |
| if (this.get('isReconfigureRequired') && atlasAddresses !== atlasAddressesRecommended) { |
| var service = App.config.get('serviceByConfigTypeMap')[propertyFileName], |
| configObject = App.configsCollection.getConfigByName(propertyName, propertyFileName), |
| displayName = configObject && configObject.displayName; |
| propertiesToChange.pushObject({ |
| propertyFileName, |
| propertyName, |
| propertyTitle: configObject && Em.I18n.t('installer.controls.serviceConfigPopover.title').format(displayName, displayName === propertyName ? '' : propertyName), |
| propertyDescription: configObject && configObject.description, |
| serviceDisplayName: service && service.get('displayName'), |
| initialValue: atlasAddresses, |
| recommendedValue: atlasAddressesRecommended |
| }); |
| } |
| const groups = [ |
| { |
| properties: { |
| [propertyFileName]: configs[propertyFileName] |
| }, |
| properties_attributes: { |
| [propertyFileName]: attributes[propertyFileName] |
| } |
| } |
| ]; |
| this.setConfigsChanges(groups); |
| }, |
| |
| /** |
| * Success callback for load configs request |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method loadWebHCatConfigs |
| */ |
| loadWebHCatConfigs: function (data, opt, params) { |
| const urlParams = this.getUrlParamsForConfigsRequest(data, ['hive-site', 'webhcat-site', 'hive-env', 'core-site']), |
| request = App.ajax.send({ |
| name: 'admin.get.all_configurations', |
| sender: this, |
| data: { |
| webHCat: true, |
| urlParams |
| }, |
| success: params.callback |
| }); |
| this.trackRequest(request); |
| return request; |
| }, |
| |
| /** |
| * Success callback for load configs request |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method loadHiveConfigs |
| */ |
| loadHiveConfigs: function (data, opt, params) { |
| const urlParams = this.getUrlParamsForConfigsRequest(data, ['hive-site', 'webhcat-site', 'hive-env', 'core-site']), |
| request = App.ajax.send({ |
| name: 'admin.get.all_configurations', |
| sender: this, |
| data: { |
| urlParams |
| }, |
| success: params.callback |
| }); |
| this.trackRequest(request); |
| return request; |
| }, |
| |
| /** |
| * update and save Hive related configs to server |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method onLoadHiveConfigs |
| */ |
| onLoadHiveConfigs: function (data, opt, params) { |
| let port = ""; |
| const configs = {}, |
| attributes = {}, |
| userSetup = {}, |
| localDB = { |
| masterComponentHosts: this.getHiveHosts() |
| }, |
| dependencies = { |
| hiveMetastorePort: "" |
| }, |
| initializer = params.webHCat ? App.AddWebHCatComponentsInitializer : App.AddHiveComponentsInitializer; |
| this.saveLoadedConfigs(data); |
| this.set('configs.params', { |
| webHCat: params.webHCat |
| }); |
| data.items.forEach(item => { |
| configs[item.type] = item.properties; |
| attributes[item.type] = item.properties_attributes || {}; |
| }); |
| const propertiesToChange = this.get('allPropertiesToChange'); |
| |
| port = configs['hive-site']['hive.metastore.uris'].match(/:[0-9]{2,4}/); |
| port = port ? port[0].slice(1) : "9083"; |
| |
| dependencies.hiveMetastorePort = port; |
| |
| if (params.webHCat) { |
| userSetup.webhcatUser = configs['hive-env']['webhcat_user']; |
| } else { |
| userSetup.hiveUser = configs['hive-env']['hive_user']; |
| } |
| |
| initializer.setup(userSetup); |
| |
| ['hive-site', 'webhcat-site', 'hive-env', 'core-site'].forEach(fileName => { |
| if (configs[fileName]) { |
| Em.keys(configs[fileName]).forEach(propertyName => { |
| const currentValue = configs[fileName][propertyName], |
| propertyDef = { |
| fileName, |
| name: propertyName, |
| value: currentValue |
| }, |
| configProperty = initializer.initialValue(propertyDef, localDB, dependencies); |
| initializer.updateSiteObj(configs[fileName], configProperty); |
| if (this.get('isReconfigureRequired') && currentValue !== configs[fileName][propertyName]) { |
| const service = App.config.get('serviceByConfigTypeMap')[fileName], |
| configObject = App.configsCollection.getConfigByName(propertyName, fileName), |
| displayName = configObject && configObject.displayName; |
| propertiesToChange.pushObject({ |
| propertyFileName: fileName, |
| propertyName, |
| propertyTitle: configObject && Em.I18n.t('installer.controls.serviceConfigPopover.title').format(displayName, displayName === propertyName ? '' : propertyName), |
| propertyDescription: configObject && configObject.description, |
| serviceDisplayName: service && service.get('displayName'), |
| initialValue: currentValue, |
| recommendedValue: propertyDef.value |
| }); |
| } |
| }); |
| } |
| }); |
| |
| initializer.cleanup(); |
| |
| var groups = [ |
| { |
| properties: { |
| 'hive-site': configs['hive-site'], |
| 'webhcat-site': configs['webhcat-site'], |
| 'hive-env': configs['hive-env'] |
| }, |
| properties_attributes: { |
| 'hive-site': attributes['hive-site'], |
| 'webhcat-site': attributes['webhcat-site'], |
| 'hive-env': attributes['hive-env'] |
| } |
| }, |
| { |
| properties: { |
| 'core-site': configs['core-site'] |
| }, |
| properties_attributes: { |
| 'core-site': attributes['core-site'] |
| } |
| } |
| ]; |
| this.setConfigsChanges(groups); |
| }, |
| |
| /** |
| * save configs' sites in batch |
| * @param groups |
| * @param componentName |
| */ |
| putConfigsToServer: function (groups, componentName) { |
| const dfd = $.Deferred(); |
| const requests = []; |
| if (groups.length) { |
| groups.forEach(function (group) { |
| const desiredConfigs = []; |
| const properties = group.properties; |
| |
| for (let site in properties) { |
| if (!properties.hasOwnProperty(site) || Em.isNone(properties[site])) continue; |
| desiredConfigs.push({ |
| "type": site, |
| "properties": properties[site], |
| "properties_attributes": group.properties_attributes[site], |
| "service_config_version_note": Em.I18n.t('hosts.host.configs.save.note').format(App.format.role(componentName, false)) |
| }); |
| } |
| if (desiredConfigs.length > 0) { |
| requests.push(App.ajax.send({ |
| name: 'common.service.configurations', |
| sender: this, |
| data: { |
| desired_config: desiredConfigs, |
| componentName: componentName |
| } |
| })); |
| } |
| }, this); |
| $.when(requests).done(dfd.resolve).fail(dfd.reject).then(() => { |
| // If user adding component which require config changes from Configs page then configs should be reloaded |
| if (App.router.get('location.location.hash').contains('configs')) { |
| App.router.get('mainServiceInfoConfigsController').loadStep(); |
| } |
| }); |
| } else { |
| dfd.resolve(); |
| } |
| return dfd.promise(); |
| }, |
| |
| /** |
| * Delete Hive Metastore is performed |
| * @type {bool} |
| */ |
| deleteHiveMetaStore: false, |
| |
| /** |
| * Delete WebHCat Server is performed |
| * |
| * @type {bool} |
| */ |
| deleteWebHCatServer: false, |
| |
| getHiveHosts: function () { |
| var self = this; |
| var removePerformed = this.get('fromDeleteHost') || this.get('deleteHiveMetaStore') || this.get('deleteHiveServer') || this.get('deleteWebHCatServer'); |
| var hiveMasterComponents = ['WEBHCAT_SERVER', 'HIVE_METASTORE', 'HIVE_SERVER']; |
| var masterComponentsMap = hiveMasterComponents.map(function(componentName) { |
| return self.bootstrapHostsMapping(componentName); |
| }).reduce(function(p,c) { |
| return p.concat(c); |
| }); |
| |
| if (removePerformed) { |
| self.setProperties({ |
| deleteHiveMetaStore: false, |
| deleteHiveServer: false, |
| deleteWebHCatServer: false, |
| fromDeleteHost: false |
| }); |
| masterComponentsMap = masterComponentsMap.map(function(masterComponent) { |
| masterComponent.isInstalled = masterComponent.hostName !== self.get('content.hostName'); |
| return masterComponent; |
| }); |
| } |
| |
| if (!!this.get('hiveMetastoreHost')) { |
| masterComponentsMap.push({ |
| component: 'HIVE_METASTORE', |
| hostName: this.get('hiveMetastoreHost'), |
| isInstalled: !removePerformed |
| }); |
| this.set('hiveMetastoreHost', ''); |
| } |
| |
| if (!!this.get('webhcatServerHost')) { |
| masterComponentsMap.push({ |
| component: 'WEBHCAT_SERVER', |
| hostName: this.get('webhcatServerHost'), |
| isInstalled: !removePerformed |
| }); |
| this.set('webhcatServerHost', ''); |
| } |
| |
| return masterComponentsMap; |
| }, |
| |
| /** |
| * Success callback for load configs request |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method loadRangerConfigs |
| */ |
| loadRangerConfigs: function (data, opt, params) { |
| const urlParams = this.getUrlParamsForConfigsRequest(data, ['core-site', 'hdfs-site', 'kms-env', 'kms-site']), |
| request = App.ajax.send({ |
| name: 'admin.get.all_configurations', |
| sender: this, |
| data: { |
| urlParams |
| }, |
| success: params.callback |
| }); |
| this.trackRequest(request); |
| }, |
| |
| /** |
| * update and save Hive hive.metastore.uris config to server |
| * @param {object} data |
| * @method onLoadRangerConfigs |
| */ |
| onLoadRangerConfigs: function (data) { |
| const hdfsProperties = [ |
| { |
| type: 'core-site', |
| name: 'hadoop.security.key.provider.path' |
| }, |
| { |
| type: 'hdfs-site', |
| name: 'dfs.encryption.key.provider.uri' |
| } |
| ], |
| kmsSiteProperties = [ |
| { |
| name: 'hadoop.kms.cache.enable', |
| notHaValue: 'true', |
| haValue: 'false' |
| }, |
| { |
| name: 'hadoop.kms.cache.timeout.ms', |
| notHaValue: '600000', |
| haValue: '0' |
| }, |
| { |
| name: 'hadoop.kms.current.key.cache.timeout.ms', |
| notHaValue: '30000', |
| haValue: '0' |
| }, |
| { |
| name: 'hadoop.kms.authentication.signer.secret.provider', |
| notHaValue: 'random', |
| haValue: 'zookeeper' |
| }, |
| { |
| name: 'hadoop.kms.authentication.signer.secret.provider.zookeeper.auth.type', |
| notHaValue: 'kerberos', |
| haValue: 'none' |
| }, |
| { |
| name: 'hadoop.kms.authentication.signer.secret.provider.zookeeper.connection.string', |
| notHaValue: '#HOSTNAME#:#PORT#,...', |
| haValue: this.getZookeeperConnectionString() |
| } |
| ], |
| rkmsHosts = this.getRangerKMSServerHosts(), |
| rkmsHostsStr = rkmsHosts.join(';'), |
| isHA = rkmsHosts.length > 1, |
| rkmsPort = data.items.findProperty('type', 'kms-env').properties['kms_port'], |
| newValue = 'kms://http@' + rkmsHostsStr + ':' + rkmsPort + '/kms', |
| coreSiteConfigs = data.items.findProperty('type', 'core-site'), |
| hdfsSiteConfigs = data.items.findProperty('type', 'hdfs-site'), |
| kmsSiteConfigs = data.items.findProperty('type', 'kms-site'), |
| groups = [ |
| { |
| properties: { |
| 'core-site': coreSiteConfigs.properties, |
| 'hdfs-site': hdfsSiteConfigs.properties |
| }, |
| properties_attributes: { |
| 'core-site': coreSiteConfigs.properties_attributes, |
| 'hdfs-site': hdfsSiteConfigs.properties_attributes |
| } |
| }, |
| { |
| properties: { |
| 'kms-site': kmsSiteConfigs.properties |
| }, |
| properties_attributes: { |
| 'kms-site': kmsSiteConfigs.properties_attributes |
| } |
| } |
| ], |
| propertiesToChange = this.get('allPropertiesToChange'); |
| |
| this.saveLoadedConfigs(data); |
| |
| hdfsProperties.forEach(property => { |
| const typeConfigs = data.items.findProperty('type', property.type).properties, |
| currentValue = typeConfigs[property.name], |
| pattern = new RegExp('^kms:\\/\\/http@(.+):' + rkmsPort + '\\/kms$'), |
| patternMatch = currentValue && currentValue.match(pattern), |
| currentHostsList = patternMatch && patternMatch[1].split(';').sort().join(';'); |
| if (currentHostsList !== rkmsHostsStr) { |
| typeConfigs[property.name] = newValue; |
| if (this.get('isReconfigureRequired')) { |
| const propertyFileName = property.type, |
| propertyName = property.name, |
| service = App.config.get('serviceByConfigTypeMap')[propertyFileName], |
| configObject = App.configsCollection.getConfigByName(propertyName, propertyFileName), |
| displayName = configObject && configObject.displayName; |
| propertiesToChange.pushObject({ |
| propertyFileName, |
| propertyName, |
| propertyTitle: configObject && Em.I18n.t('installer.controls.serviceConfigPopover.title').format(displayName, displayName === propertyName ? '' : propertyName), |
| propertyDescription: configObject && configObject.description, |
| serviceDisplayName: service && service.get('displayName'), |
| initialValue: currentValue, |
| recommendedValue: newValue, |
| saveRecommended: true |
| }); |
| } |
| } |
| }); |
| |
| kmsSiteProperties.forEach(function (property) { |
| var currentValue = kmsSiteConfigs.properties[property.name]; |
| var newValue = isHA ? property.haValue : property.notHaValue; |
| kmsSiteConfigs.properties[property.name] = newValue; |
| |
| propertiesToChange.pushObject({ |
| propertyFileName: 'kms-site', |
| propertyName: property.name, |
| serviceDisplayName: App.Service.find().findProperty('serviceName', 'RANGER_KMS').get('displayName'), |
| initialValue: currentValue, |
| recommendedValue: newValue, |
| saveRecommended: true |
| }); |
| }); |
| this.setConfigsChanges(groups); |
| }, |
| |
| /** |
| * Delete Hive Metastore is performed |
| * @type {bool} |
| */ |
| deleteRangerKMSServer: false, |
| |
| getRangerKMSServerHosts: function () { |
| var rkmsHosts = App.HostComponent.find().filterProperty('componentName', 'RANGER_KMS_SERVER').mapProperty('hostName'); |
| var rangerKMSServerHost = this.get('rangerKMSServerHost'); |
| |
| if (!!rangerKMSServerHost) { |
| rkmsHosts.push(rangerKMSServerHost); |
| } |
| |
| if (this.get('fromDeleteHost') || this.get('deleteRangerKMSServer')) { |
| return rkmsHosts.without(this.get('content.hostName')); |
| } |
| return rkmsHosts.sort(); |
| }, |
| |
| getZookeeperConnectionString: function () { |
| var zookeeperHosts = App.MasterComponent.find('ZOOKEEPER_SERVER').get('hostNames'); |
| return zookeeperHosts.map(function (host) { |
| return host + ':2181'; |
| }).join(','); |
| }, |
| |
| /** |
| * Delete Storm Nimbus is performed |
| * @type {bool} |
| */ |
| deleteNimbusHost: false, |
| |
| getStormNimbusHosts: function () { |
| var |
| stormNimbusHosts = App.HostComponent.find().filterProperty('componentName', 'NIMBUS').mapProperty('hostName'), |
| nimbusHost = this.get('nimbusHost'); |
| |
| if (!!nimbusHost) { |
| stormNimbusHosts.push(nimbusHost); |
| this.set('nimbusHost', ''); |
| } |
| |
| if (this.get('fromDeleteHost') || this.get('deleteNimbusHost')) { |
| this.set('deleteNimbusHost', false); |
| this.set('fromDeleteHost', false); |
| return stormNimbusHosts.without(this.get('content.hostName')); |
| } |
| return stormNimbusHosts.sort(); |
| }, |
| |
| getAtlasServerHosts: function () { |
| var |
| atlasServerHosts = App.HostComponent.find().filterProperty('componentName', 'ATLAS_SERVER').mapProperty('hostName'), |
| atlasServer = this.get('atlasServer'); |
| |
| if (!!atlasServer) { |
| atlasServerHosts.push(atlasServer); |
| this.set('atlasServer', ''); |
| } |
| |
| if (this.get('fromDeleteHost') || this.get('deleteAtlasServer')) { |
| this.set('deleteAtlasServer', false); |
| this.set('fromDeleteHost', false); |
| return atlasServerHosts.without(this.get('content.hostName')); |
| } |
| return atlasServerHosts.sort(); |
| }, |
| |
| /** |
| * Send command to server to resfresh configs of selected component |
| * @param {object} event |
| * @method refreshComponentConfigs |
| */ |
| refreshComponentConfigs: function (event) { |
| var self = this; |
| return App.showConfirmationPopup(function () { |
| var component = event.context; |
| var context = Em.I18n.t('requestInfo.refreshComponentConfigs').format(component.get('displayName')); |
| self.sendRefreshComponentConfigsCommand(component, context); |
| }); |
| }, |
| |
| /** |
| * PUTs a command to server to refresh configs of host component. |
| * @param {object} component |
| * @param {object} context Context under which this command is beign sent. |
| * @method sendRefreshComponentConfigsCommand |
| */ |
| sendRefreshComponentConfigsCommand: function (component, context) { |
| var resource_filters = [ |
| { |
| service_name: component.get('service.serviceName'), |
| component_name: component.get('componentName'), |
| hosts: component.get('host.hostName') |
| } |
| ]; |
| App.ajax.send({ |
| name: 'host.host_component.refresh_configs', |
| sender: this, |
| data: { |
| resource_filters: resource_filters, |
| context: context |
| }, |
| success: 'refreshComponentConfigsSuccessCallback', |
| showLoadingPopup: true |
| }); |
| }, |
| |
| /** |
| * Success callback for refresh host component configs request |
| * @method refreshComponentConfigsSuccessCallback |
| */ |
| refreshComponentConfigsSuccessCallback: function () { |
| this.showBackgroundOperationsPopup(); |
| }, |
| |
| /** |
| * Load configs |
| * This function when used without a callback should be always used from successcallback function of the promise `App.router.get('mainController').isLoading.call(App.router.get('clusterController'), 'isServiceContentFullyLoaded').done(promise)` |
| * This is required to make sure that service metrics API determining the HA state of components is loaded |
| * @method loadConfigs |
| */ |
| loadConfigs: function (configTagsCallback, configsCallback) { |
| var request = App.ajax.send({ |
| name: 'config.tags', |
| sender: this, |
| data: { |
| callback: configsCallback |
| }, |
| success: configTagsCallback, |
| error: 'onLoadConfigsErrorCallback' |
| }); |
| this.trackRequest(request); |
| }, |
| |
| /** |
| * onLoadConfigsErrorCallback |
| * @method onLoadConfigsErrorCallback |
| */ |
| onLoadConfigsErrorCallback: function () { |
| this.get('isOozieConfigLoaded').reject(); |
| }, |
| |
| /** |
| * Success callback for load configs request |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method loadZookeeperConfigs |
| */ |
| loadZookeeperConfigs: function (data, opt, params) { |
| var urlParams = this.constructZookeeperConfigUrlParams(data); |
| if (urlParams.length > 0) { |
| var request = App.ajax.send({ |
| name: 'reassign.load_configs', |
| sender: this, |
| data: { |
| urlParams: urlParams.join('|') |
| }, |
| success: params.callback |
| }); |
| this.trackRequest(request); |
| return true; |
| } |
| this.set('isConfigsLoadingInProgress', false); |
| return false; |
| }, |
| |
| /** |
| * construct URL params for query, that load configs |
| * @param data {Object} |
| * @return {Array} |
| */ |
| constructZookeeperConfigUrlParams: function (data) { |
| var urlParams = []; |
| var services = App.Service.find(); |
| var zooKeeperRelatedServices = this.get('zooKeeperRelatedServices').slice(0); |
| if (App.get('isHaEnabled')) { |
| zooKeeperRelatedServices.push({ |
| serviceName: 'HDFS', |
| typesToLoad: ['core-site'], |
| typesToSave: ['core-site'] |
| }); |
| } |
| zooKeeperRelatedServices.forEach(function (service) { |
| if (services.someProperty('serviceName', service.serviceName)) { |
| service.typesToLoad.forEach(function (type) { |
| if (data.Clusters.desired_configs[type]) { |
| urlParams.push('(type=' + type + '&tag=' + data.Clusters.desired_configs[type].tag + ')'); |
| } |
| }); |
| } |
| }); |
| return urlParams; |
| }, |
| |
| /** |
| * save new ZooKeeper configs to server |
| * @param {object} data |
| * @method saveZkConfigs |
| */ |
| saveZkConfigs: function (data) { |
| var configs = {}; |
| var attributes = {}; |
| this.saveLoadedConfigs(data); |
| data.items.forEach(function (item) { |
| configs[item.type] = item.properties; |
| attributes[item.type] = item.properties_attributes || {}; |
| }, this); |
| |
| this.updateZkConfigs(configs); |
| var groups = []; |
| var installedServiceNames = App.Service.find().mapProperty('serviceName'); |
| var zooKeeperRelatedServices = this.get('zooKeeperRelatedServices').slice(0); |
| if (App.get('isHaEnabled')) { |
| zooKeeperRelatedServices.push({ |
| serviceName: 'HDFS', |
| typesToLoad: ['core-site'], |
| typesToSave: ['core-site'] |
| }); |
| } |
| zooKeeperRelatedServices.forEach(function (service) { |
| if (installedServiceNames.contains(service.serviceName)) { |
| var group = { |
| properties: {}, |
| properties_attributes: {} |
| }; |
| service.typesToSave.forEach(function (type) { |
| group.properties[type] = configs[type]; |
| group.properties_attributes[type] = attributes[type]; |
| }); |
| groups.push(group); |
| } |
| }); |
| this.setConfigsChanges(groups); |
| }, |
| |
| /** |
| * Is deleteHost action id fired |
| * @type {bool} |
| */ |
| fromDeleteHost: false, |
| |
| /** |
| * Is ZooKeeper Server being deleted from host |
| * @type {bool} |
| */ |
| fromDeleteZkServer: false, |
| |
| /** |
| * Send command to server to install selected host component |
| * @param {Object} event |
| * @method installComponent |
| */ |
| installComponent: function (event) { |
| var self = this; |
| var component = event.context; |
| var componentName = component.get('componentName'); |
| var displayName = component.get('displayName'); |
| |
| return App.ModalPopup.show({ |
| primary: Em.I18n.t('hosts.host.installComponent.popup.confirm'), |
| header: Em.I18n.t('popup.confirmation.commonHeader'), |
| installComponentMessage: Em.I18n.t('hosts.host.installComponent.msg').format(displayName), |
| bodyClass: Em.View.extend({ |
| templateName: require('templates/main/host/details/installComponentPopup') |
| }), |
| onPrimary: function () { |
| var _this = this; |
| App.get('router.mainAdminKerberosController').getSecurityType(function () { |
| App.get('router.mainAdminKerberosController').getKDCSessionState(function () { |
| _this.hide(); |
| |
| App.ajax.send({ |
| name: 'common.host.host_component.update', |
| sender: self, |
| data: { |
| hostName: self.get('content.hostName'), |
| serviceName: component.get('service.serviceName'), |
| componentName: componentName, |
| component: component, |
| context: Em.I18n.t('requestInfo.installHostComponent') + " " + displayName, |
| HostRoles: { |
| state: 'INSTALLED' |
| } |
| }, |
| success: 'installComponentSuccessCallback', |
| error: 'ajaxErrorCallback', |
| showLoadingPopup: true |
| }); |
| }) |
| }); |
| } |
| }); |
| }, |
| |
| /** |
| * Success callback for install component request |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method installComponentSuccessCallback |
| */ |
| installComponentSuccessCallback: function (data, opt, params) { |
| if (App.get('testMode')) { |
| this.mimicWorkStatusChange(params.component, App.HostComponentStatus.installing, App.HostComponentStatus.stopped); |
| } |
| this.showBackgroundOperationsPopup(); |
| }, |
| |
| /** |
| * Send command to server to run decommission on DATANODE, TASKTRACKER, NODEMANAGER, REGIONSERVER |
| * @param {App.HostComponent} component |
| * @param {callback} callback |
| * @method decommission |
| */ |
| decommission: function (component, callback) { |
| var self = this; |
| return App.showConfirmationPopup(function () { |
| self.runDecommission.call(self, self.get('content.hostName'), component.get('service.serviceName')); |
| if (callback) { |
| callback() |
| } |
| }, Em.I18n.t('question.sure.decommission').format(component.get('service.serviceName'))); |
| }, |
| /** |
| * identify correct component to run decommission on them by service name, |
| * in result run proper decommission method |
| * @param hostName |
| * @param svcName |
| */ |
| runDecommission: function (hostName, svcName) { |
| switch (svcName) { |
| case 'HDFS': |
| this.doDecommission(hostName, svcName, "NAMENODE", "DATANODE"); |
| break; |
| case 'YARN': |
| this.doDecommission(hostName, svcName, "RESOURCEMANAGER", "NODEMANAGER"); |
| break; |
| case 'HBASE': |
| this.warnBeforeDecommission(hostName); |
| } |
| }, |
| |
| /** |
| * Send command to server to run recommission on DATANODE, TASKTRACKER, NODEMANAGER |
| * @param {App.HostComponent} component |
| * @param {callback} callback |
| * @method recommission |
| */ |
| recommission: function (component, callback) { |
| var self = this; |
| return App.showConfirmationPopup(function () { |
| self.runRecommission.call(self, self.get('content.hostName'), component.get('service.serviceName')); |
| if (callback) { |
| callback() |
| } |
| }, Em.I18n.t('question.sure.recommission').format(component.get('service.serviceName'))); |
| }, |
| /** |
| * identify correct component to run recommission on them by service name, |
| * in result run proper recommission method |
| * @param hostName |
| * @param svcName |
| */ |
| runRecommission: function (hostName, svcName) { |
| switch (svcName) { |
| case 'HDFS': |
| this.doRecommissionAndStart(hostName, svcName, "NAMENODE", "DATANODE"); |
| break; |
| case 'YARN': |
| this.doRecommissionAndStart(hostName, svcName, "RESOURCEMANAGER", "NODEMANAGER"); |
| break; |
| case 'HBASE': |
| this.doRecommissionAndStart(hostName, svcName, "HBASE_MASTER", "HBASE_REGIONSERVER"); |
| } |
| this.showBackgroundOperationsPopup(); |
| }, |
| |
| /** |
| * Performs Decommission (for DN, TT and NM) |
| * @param {string} hostName |
| * @param {string} serviceName |
| * @param {string} componentName |
| * @param {string} slaveType |
| * @method doDecommission |
| */ |
| doDecommission: function (hostName, serviceName, componentName, slaveType) { |
| var contextNameString = 'hosts.host.' + slaveType.toLowerCase() + '.decommission'; |
| var context = Em.I18n.t(contextNameString); |
| App.ajax.send({ |
| name: 'host.host_component.decommission_slave', |
| sender: this, |
| data: { |
| context: context, |
| command: 'DECOMMISSION', |
| hostName: hostName, |
| serviceName: serviceName, |
| componentName: componentName, |
| slaveType: slaveType |
| }, |
| success: 'decommissionSuccessCallback', |
| error: 'decommissionErrorCallback', |
| showLoadingPopup: true |
| }); |
| }, |
| |
| /** |
| * check is hbase regionserver in mm. If so - run decommission |
| * otherwise shows warning |
| * @method warnBeforeDecommission |
| * @param {string} hostNames - list of host when run from bulk operations or current host |
| */ |
| warnBeforeDecommission: function (hostNames) { |
| if (this.get('content.hostComponents').findProperty('componentName', 'HBASE_REGIONSERVER').get('passiveState') == "OFF") { |
| this.showHbaseActiveWarning(); |
| } else { |
| this.checkRegionServerState(hostNames); |
| } |
| }, |
| |
| /** |
| * send call to check is this regionserver last in cluster which has desired_admin_state property "INSERVICE" |
| * @method checkRegionServerState |
| * @param hostNames |
| */ |
| checkRegionServerState: function (hostNames) { |
| return App.ajax.send({ |
| name: 'host.region_servers.in_inservice', |
| sender: this, |
| data: { |
| hostNames: hostNames |
| }, |
| success: 'checkRegionServerStateSuccessCallback' |
| }); |
| }, |
| |
| /** |
| * check is this regionserver last in cluster which has desired_admin_state property "INSERVICE" |
| * @method checkRegionServerStateSuccessCallback |
| * @param data |
| * @param opt |
| * @param params |
| */ |
| checkRegionServerStateSuccessCallback: function (data, opt, params) { |
| var hostArray = params.hostNames.split(","); |
| var decommissionPossible = (data.items.mapProperty('HostRoles.host_name').filter(function (hostName) { |
| return !hostArray.contains(hostName); |
| }, this).length >= 1); |
| if (decommissionPossible) { |
| this.doDecommissionRegionServer(params.hostNames, "HBASE", "HBASE_MASTER", "HBASE_REGIONSERVER"); |
| } else { |
| this.showRegionServerWarning(); |
| } |
| }, |
| |
| /** |
| * show warning that regionserver is last in cluster which has desired_admin_state property "INSERVICE" |
| * @method showRegionServerWarning |
| * @param hostNames |
| */ |
| showRegionServerWarning: function () { |
| return App.ModalPopup.show({ |
| header: Em.I18n.t('common.warning'), |
| message: Em.I18n.t('hosts.host.hbase_regionserver.decommission.warning'), |
| bodyClass: Ember.View.extend({ |
| template: Em.Handlebars.compile('<div class="alert alert-warning">{{message}}</div>') |
| }), |
| secondary: false |
| }); |
| }, |
| |
| /** |
| * shows warning: put hbase regionserver in passive state |
| * @method showHbaseActiveWarning |
| * @return {App.ModalPopup} |
| */ |
| showHbaseActiveWarning: function () { |
| return App.ModalPopup.show({ |
| header: Em.I18n.t('common.warning'), |
| message: Em.I18n.t('hostPopup.recommendation.beforeDecommission').format(App.format.components["HBASE_REGIONSERVER"]), |
| bodyClass: Ember.View.extend({ |
| template: Em.Handlebars.compile('<div class="alert alert-warning">{{message}}</div>') |
| }), |
| secondary: false |
| }); |
| }, |
| |
| /** |
| * Performs Decommission (for RegionServer) |
| * @method doDecommissionRegionServer |
| * @param {string} hostNames - list of host when run from bulk operations or current host |
| * @param {string} serviceName - serviceName |
| * @param {string} componentName - master compoent name |
| * @param {string} slaveType - slave component name |
| */ |
| doDecommissionRegionServer: function (hostNames, serviceName, componentName, slaveType) { |
| var batches = [ |
| { |
| "order_id": 1, |
| "type": "POST", |
| "uri": "/clusters/" + App.get('clusterName') + "/requests", |
| "RequestBodyInfo": { |
| "RequestInfo": { |
| "context": Em.I18n.t('hosts.host.regionserver.decommission.batch1'), |
| "command": "DECOMMISSION", |
| "exclusive": "true", |
| "parameters": { |
| "slave_type": slaveType, |
| "excluded_hosts": hostNames |
| }, |
| 'operation_level': { |
| level: "HOST_COMPONENT", |
| cluster_name: App.get('clusterName'), |
| host_name: hostNames, |
| service_name: serviceName |
| } |
| }, |
| "Requests/resource_filters": [ |
| {"service_name": serviceName, "component_name": componentName} |
| ] |
| } |
| }]; |
| var id = 2; |
| var hAray = hostNames.split(","); |
| for (var i = 0; i < hAray.length; i++) { |
| batches.push({ |
| "order_id": id, |
| "type": "PUT", |
| "uri": "/clusters/" + App.get('clusterName') + "/hosts/" + hAray[i] + "/host_components/" + slaveType, |
| "RequestBodyInfo": { |
| "RequestInfo": { |
| context: Em.I18n.t('hosts.host.regionserver.decommission.batch2'), |
| exclusive: true, |
| operation_level: { |
| level: "HOST_COMPONENT", |
| cluster_name: App.get('clusterName'), |
| host_name: hostNames, |
| service_name: serviceName || null |
| } |
| }, |
| "Body": { |
| HostRoles: { |
| state: "INSTALLED" |
| } |
| } |
| } |
| }); |
| id++; |
| } |
| batches.push({ |
| "order_id": id, |
| "type": "POST", |
| "uri": "/clusters/" + App.get('clusterName') + "/requests", |
| "RequestBodyInfo": { |
| "RequestInfo": { |
| "context": Em.I18n.t('hosts.host.regionserver.decommission.batch3'), |
| "command": "DECOMMISSION", |
| "service_name": serviceName, |
| "component_name": componentName, |
| "parameters": { |
| "slave_type": slaveType, |
| "excluded_hosts": hostNames, |
| "mark_draining_only": true |
| }, |
| 'operation_level': { |
| level: "HOST_COMPONENT", |
| cluster_name: App.get('clusterName'), |
| host_name: hostNames, |
| service_name: serviceName |
| } |
| }, |
| "Requests/resource_filters": [ |
| {"service_name": serviceName, "component_name": componentName} |
| ] |
| } |
| }); |
| App.ajax.send({ |
| name: 'common.batch.request_schedules', |
| sender: this, |
| data: { |
| intervalTimeSeconds: 1, |
| tolerateSize: 0, |
| batches: batches |
| }, |
| success: 'decommissionSuccessCallback', |
| error: 'decommissionErrorCallback', |
| showLoadingPopup: true |
| }); |
| }, |
| |
| /** |
| * Error callback for decommission requests |
| * @param {object} request |
| * @param {object} ajaxOptions |
| * @param {string} error |
| * @method decommissionErrorCallback |
| */ |
| decommissionErrorCallback: function (request, ajaxOptions, error) { |
| }, |
| |
| /** |
| * Success ajax response for Recommission/Decommission slaves |
| * @param {object} data |
| * @method decommissionSuccessCallback |
| * @return {Boolean} |
| */ |
| decommissionSuccessCallback: function (data) { |
| if (data && (data.Requests || data.resources[0].RequestSchedule)) { |
| this.showBackgroundOperationsPopup(); |
| return true; |
| } else { |
| return false; |
| } |
| }, |
| |
| /** |
| * Performs Recommission and Start |
| * @param {string} hostNames |
| * @param {string} serviceName |
| * @param {string} componentName |
| * @param {string} slaveType |
| * @method doRecommissionAndStart |
| */ |
| doRecommissionAndStart: function (hostNames, serviceName, componentName, slaveType) { |
| var contextNameString_1 = 'hosts.host.' + slaveType.toLowerCase() + '.recommission'; |
| var context_1 = Em.I18n.t(contextNameString_1); |
| var contextNameString_2 = 'requestInfo.startHostComponent.' + slaveType.toLowerCase(); |
| var startContext = Em.I18n.t(contextNameString_2); |
| var params = { |
| "slave_type": slaveType, |
| "included_hosts": hostNames |
| }; |
| if (serviceName == "HBASE") { |
| params.mark_draining_only = true; |
| } |
| var batches = [ |
| { |
| "order_id": 1, |
| "type": "POST", |
| "uri": "/clusters/" + App.get('clusterName') + "/requests", |
| "RequestBodyInfo": { |
| "RequestInfo": { |
| "context": context_1, |
| "command": "DECOMMISSION", |
| "exclusive": "true", |
| "parameters": params, |
| 'operation_level': { |
| level: "HOST_COMPONENT", |
| cluster_name: App.get('clusterName'), |
| host_name: hostNames, |
| service_name: serviceName |
| } |
| }, |
| "Requests/resource_filters": [ |
| {"service_name": serviceName, "component_name": componentName} |
| ] |
| } |
| }]; |
| var id = 2; |
| var hAray = hostNames.split(","); |
| for (var i = 0; i < hAray.length; i++) { |
| batches.push({ |
| "order_id": id, |
| "type": "PUT", |
| "uri": "/clusters/" + App.get('clusterName') + "/hosts/" + hAray[i] + "/host_components/" + slaveType, |
| "RequestBodyInfo": { |
| "RequestInfo": { |
| context: startContext, |
| operation_level: { |
| level: "HOST_COMPONENT", |
| cluster_name: App.get('clusterName'), |
| host_name: hostNames, |
| service_name: serviceName || null |
| } |
| }, |
| "Body": { |
| HostRoles: { |
| state: "STARTED" |
| } |
| } |
| } |
| }); |
| id++; |
| } |
| App.ajax.send({ |
| name: 'common.batch.request_schedules', |
| sender: this, |
| data: { |
| intervalTimeSeconds: 1, |
| tolerateSize: 1, |
| batches: batches |
| }, |
| success: 'decommissionSuccessCallback', |
| error: 'decommissionErrorCallback', |
| showLoadingPopup: true |
| }); |
| }, |
| |
| /** |
| * Handler for host-menu items actions |
| * @param {object} option |
| * @method doAction |
| */ |
| doAction: function (option) { |
| switch (option.context.action) { |
| case "deleteHost": |
| this.validateAndDeleteHost(); |
| break; |
| case "startAllComponents": |
| if (!this.get('content.isNotHeartBeating')) this.doStartAllComponents(); |
| break; |
| case "stopAllComponents": |
| if (!this.get('content.isNotHeartBeating')) this.doStopAllComponents(); |
| break; |
| case "restartAllComponents": |
| if (!this.get('content.isNotHeartBeating')) this.doRestartAllComponents(); |
| break; |
| case "onOffPassiveModeForHost": |
| this.onOffPassiveModeForHost(option.context); |
| break; |
| case "setRackId": |
| this.setRackIdForHost(); |
| break; |
| case "checkHost": |
| this.runHostCheckConfirmation(); |
| break; |
| case "regenerateKeytabFileOperations": |
| this.regenerateKeytabFileOperations(); |
| break; |
| } |
| }, |
| |
| /** |
| * Turn On/Off Passive Mode for host |
| * @param {object} context |
| * @method onOffPassiveModeForHost |
| */ |
| onOffPassiveModeForHost: function (context) { |
| var state = context.active ? 'ON' : 'OFF'; |
| var self = this; |
| var message = Em.I18n.t('hosts.host.details.for.postfix').format(context.label); |
| var popupInfo = Em.I18n.t('hosts.passiveMode.popup').format(context.active ? 'On' : 'Off', this.get('content.hostName')); |
| if (state === 'OFF') { |
| var currentHostVersion = this.get('content.stackVersions') && this.get('content.stackVersions').findProperty('isCurrent'), |
| hostVersion = currentHostVersion && currentHostVersion.get('repoVersion'), |
| currentVersion = App.StackVersion.find().findProperty('isCurrent'), |
| clusterVersion = currentVersion && currentVersion.get('repositoryVersion.repositoryVersion'); |
| if (hostVersion !== clusterVersion) { |
| var msg = Em.I18n.t("hosts.passiveMode.popup.version.mismatch").format(this.get('content.hostName'), clusterVersion); |
| popupInfo += '<br/><div class="alert alert-warning">' + msg + '</div>'; |
| } |
| } |
| return App.showConfirmationPopup(function () { |
| self.hostPassiveModeRequest(state, message); |
| }, popupInfo); |
| }, |
| |
| /** |
| * Set rack id for host |
| * @method setRackIdForHost |
| */ |
| setRackIdForHost: function () { |
| var hostNames = [{hostName: this.get('content.hostName')}]; |
| var rack = this.get('content.rack'); |
| var operationData = {message: Em.I18n.t('hosts.host.details.setRackId')}; |
| hostsManagement.setRackInfo(operationData, hostNames, rack); |
| }, |
| |
| /** |
| * Send request to get passive state for host |
| * @param {string} state |
| * @param {string} message |
| * @method hostPassiveModeRequest |
| */ |
| hostPassiveModeRequest: function (state, message) { |
| App.ajax.send({ |
| name: 'bulk_request.hosts.passive_state', |
| sender: this, |
| data: { |
| hostNames: this.get('content.hostName'), |
| passive_state: state, |
| requestInfo: message |
| }, |
| success: 'updateHost' |
| }); |
| }, |
| |
| /** |
| * Success callback for receiving host passive state |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method updateHost |
| */ |
| updateHost: function (data, opt, params) { |
| this.set('content.passiveState', params.passive_state); |
| batchUtils.infoPassiveState(params.passive_state); |
| }, |
| |
| /** |
| * Send request to get passive state for hostComponent |
| * @param {object} component - hostComponentn object |
| * @param {string} state |
| * @param {string} message |
| * @method hostPassiveModeRequest |
| */ |
| updateComponentPassiveState: function (component, state, message) { |
| App.ajax.send({ |
| name: 'common.host.host_component.passive', |
| sender: this, |
| data: { |
| hostName: this.get('content.hostName'), |
| componentName: component.get('componentName'), |
| component: component, |
| passive_state: state, |
| context: message |
| }, |
| success: 'updateHostComponent' |
| }); |
| }, |
| |
| /** |
| * Success callback for receiving hostComponent passive state |
| * @param {object} data |
| * @param {object} opt |
| * @param {object} params |
| * @method updateHost |
| */ |
| updateHostComponent: function (data, opt, params) { |
| params.component.set('passiveState', params.passive_state); |
| batchUtils.infoPassiveState(params.passive_state); |
| }, |
| |
| /** |
| * Show confirmation popup for action "start all components" |
| * @method doStartAllComponents |
| */ |
| doStartAllComponents: function () { |
| var self = this; |
| var components = this.get('serviceNonClientActiveComponents'); |
| |
| if (components && components.get('length')) { |
| return App.showConfirmationPopup(function () { |
| self.sendComponentCommand(components, Em.I18n.t('hosts.host.maintainance.startAllComponents.context'), App.HostComponentStatus.started); |
| }, Em.I18n.t('question.sure.startAll')); |
| } |
| }, |
| |
| /** |
| * Show confirmation popup for action "stop all components" |
| * @method doStopAllComponents |
| */ |
| doStopAllComponents: function () { |
| var self = this; |
| var components = this.get('serviceNonClientActiveComponents'); |
| |
| if (components && components.get('length')) { |
| if (components.someProperty('componentName', 'NAMENODE') && |
| this.get('content.hostComponents').filterProperty('componentName', 'NAMENODE').someProperty('workStatus', App.HostComponentStatus.started)) { |
| this.checkNnLastCheckpointTime(function () { |
| App.showConfirmationPopup(function () { |
| self.sendComponentCommand(components, Em.I18n.t('hosts.host.maintainance.stopAllComponents.context'), App.HostComponentStatus.stopped); |
| }, Em.I18n.t('question.sure.stopAll')); |
| }); |
| } else { |
| return App.showConfirmationPopup(function () { |
| self.sendComponentCommand(components, Em.I18n.t('hosts.host.maintainance.stopAllComponents.context'), App.HostComponentStatus.stopped); |
| }, Em.I18n.t('question.sure.stopAll')); |
| } |
| } |
| }, |
| |
| /** |
| * Show confirmation popup for action "restart all components" |
| * @method doRestartAllComponents |
| */ |
| doRestartAllComponents: function () { |
| var self = this; |
| var components = this.get('serviceActiveComponents'); |
| |
| if (components && components.get('length')) { |
| if (components.someProperty('componentName', 'NAMENODE') && |
| this.get('content.hostComponents').filterProperty('componentName', 'NAMENODE').someProperty('workStatus', App.HostComponentStatus.started)) { |
| this.checkNnLastCheckpointTime(function () { |
| App.showConfirmationPopup(function () { |
| batchUtils.restartHostComponents(components, Em.I18n.t('rollingrestart.context.allOnSelectedHost').format(self.get('content.hostName')), "HOST"); |
| }, Em.I18n.t('question.sure.restartAll')); |
| }); |
| } else { |
| return App.showConfirmationPopup(function () { |
| batchUtils.restartHostComponents(components, Em.I18n.t('rollingrestart.context.allOnSelectedHost').format(self.get('content.hostName')), "HOST"); |
| }, Em.I18n.t('question.sure.restartAll')); |
| } |
| } |
| }, |
| |
| /** |
| * get info about host-components, exactly: |
| * - host-components grouped by status, features |
| * - flag, that indicate whether ZooKeeper Server is installed |
| * @return {Object} |
| */ |
| getHostComponentsInfo: function (hostComponents) { |
| const componentsOnHost = hostComponents || this.get('content.hostComponents'); |
| const stoppedStates = [App.HostComponentStatus.stopped, |
| App.HostComponentStatus.install_failed, |
| App.HostComponentStatus.upgrade_failed, |
| App.HostComponentStatus.init, |
| App.HostComponentStatus.unknown]; |
| const container = { |
| isReconfigureRequired: false, |
| lastComponents: [], |
| masterComponents: [], |
| nonAddableMasterComponents: [], |
| lastMasterComponents: [], |
| runningComponents: [], |
| nonDeletableComponents: [], |
| unknownComponents: [], |
| toDecommissionComponents: [] |
| }; |
| const addDeleteComponentsMap = this.get('addDeleteComponentsMap'); |
| |
| if (componentsOnHost && componentsOnHost.get('length') > 0) { |
| componentsOnHost.forEach(function (cInstance) { |
| if (addDeleteComponentsMap[cInstance.get('componentName')]) { |
| container.isReconfigureRequired = true; |
| } |
| let isLastComponent = false; |
| if (this.getTotalComponent(cInstance) === 1) { |
| container.lastComponents.push(cInstance.get('displayName')); |
| isLastComponent = true; |
| } |
| const workStatus = cInstance.get('workStatus'); |
| |
| if (cInstance.get('isMaster')) { |
| const displayName = cInstance.get('displayName'); |
| container.masterComponents.push(displayName); |
| if (!App.StackServiceComponent.find(cInstance.get('componentName')).get('isMasterAddableInstallerWizard')) { |
| container.nonAddableMasterComponents.push(displayName); |
| } |
| if (isLastComponent) { |
| container.lastMasterComponents.push(displayName); |
| } |
| } |
| if (stoppedStates.indexOf(workStatus) < 0) { |
| container.runningComponents.push(cInstance.get('displayName')); |
| } |
| if (!cInstance.get('isDeletable')) { |
| container.nonDeletableComponents.push(cInstance.get('displayName')); |
| } |
| if (workStatus === App.HostComponentStatus.unknown) { |
| container.unknownComponents.push(cInstance.get('displayName')); |
| } |
| if (App.get('components.decommissionAllowed').contains(cInstance.get('componentName')) && !cInstance.get('view.isComponentRecommissionAvailable')) { |
| container.toDecommissionComponents.push(cInstance.get('displayName')); |
| } |
| }, this); |
| } |
| return container; |
| }, |
| |
| /** |
| * Run host check confirmation |
| * @method runHostCheckConfirmation |
| */ |
| runHostCheckConfirmation: function () { |
| var self = this; |
| var popupInfo = Em.I18n.t('hosts.checkHost.popup').format(this.get('content.hostName')); |
| |
| return App.showConfirmationPopup(function () { |
| self.runHostCheck(); |
| }, popupInfo); |
| }, |
| |
| getDataForHostCheck: function () { |
| var hostName = this.get('content.hostName'); |
| var jdk_location = App.router.get('clusterController.ambariProperties.jdk_location'); |
| var RequestInfo = { |
| "action": "check_host", |
| "context": "Check host", |
| "parameters": { |
| "hosts" : hostName, |
| "check_execute_list": "last_agent_env_check,installed_packages,existing_repos,transparentHugePage", |
| "jdk_location" : jdk_location, |
| "threshold": "20" |
| } |
| }; |
| |
| return { |
| RequestInfo: RequestInfo, |
| resource_filters: {"hosts": hostName} |
| }; |
| }, |
| |
| /** |
| * Callback for runHostCheckConfirmation |
| * @method runHostCheck |
| */ |
| runHostCheck: function () { |
| var dataForCheckHostRequest = this.getDataForHostCheck(); |
| |
| this.setProperties({ |
| stopChecking: false, |
| checkHostFinished: false, |
| isRerun: false |
| }); |
| this.setBootHostsProp(); |
| this.showHostWarningsPopup(); |
| this.requestToPerformHostCheck(dataForCheckHostRequest); |
| }, |
| |
| /** |
| * Shape controller's bootHosts property needed to host check |
| * @method setBootHostsProp |
| */ |
| setBootHostsProp: function () { |
| var host = this.get('content'); |
| var bootHosts = []; |
| |
| host.name = host.get('hostName'); |
| bootHosts.push(host); |
| |
| this.set('bootHosts', bootHosts); |
| }, |
| |
| /** |
| * Open popup that contain hosts' warnings |
| * @return {App.ModalPopup} |
| * @method showHostWarningsPopup |
| */ |
| showHostWarningsPopup: function () { |
| var self = this; |
| |
| return App.ModalPopup.show({ |
| |
| header: Em.I18n.t('installer.step3.warnings.popup.header'), |
| |
| secondary: Em.I18n.t('installer.step3.hostWarningsPopup.rerunChecks'), |
| |
| primary: Em.I18n.t('common.close'), |
| |
| autoHeight: false, |
| |
| onPrimary: function () { |
| self.set('checksUpdateStatus', null); |
| this.hide(); |
| }, |
| |
| onClose: function () { |
| self.set('checksUpdateStatus', null); |
| this.hide(); |
| }, |
| |
| onSecondary: function () { |
| self.set('checkHostFinished', false); |
| self.rerunChecks(); |
| }, |
| |
| didInsertElement: function () { |
| this._super(); |
| this.fitHeight(); |
| }, |
| |
| footerClass: App.WizardStep3HostWarningPopupFooter.reopen({ |
| footerControllerBinding: 'App.router.mainHostDetailsController', |
| checkHostFinished: function () { |
| return this.get('footerController.checkHostFinished'); |
| }.property('footerController.checkHostFinished') |
| }), |
| |
| bodyClass: App.WizardStep3HostWarningPopupBody.reopen({ |
| bodyControllerBinding: 'App.router.mainHostDetailsController', |
| checkHostFinished: function () { |
| return this.get('bodyController.checkHostFinished'); |
| }.property('bodyController.checkHostFinished') |
| }) |
| }); |
| }, |
| |
| |
| /** |
| * Deletion of hosts not supported for this version |
| * @method validateAndDeleteHost |
| */ |
| validateAndDeleteHost: function () { |
| const container = this.getHostComponentsInfo(); |
| |
| if (container.nonDeletableComponents.length > 0) { |
| this.raiseDeleteComponentsError(container, 'nonDeletableList'); |
| return; |
| } else if (container.nonAddableMasterComponents.length > 0) { |
| this.raiseDeleteComponentsError(container, 'masterList'); |
| return; |
| } else if (container.runningComponents.length > 0) { |
| this.raiseDeleteComponentsError(container, 'runningList'); |
| return; |
| } else if(container.lastMasterComponents.length > 0) { |
| this.raiseDeleteComponentsError(container, 'lastMasterList'); |
| return; |
| } |
| |
| this.set('fromDeleteHost', true); |
| |
| if (container.isReconfigureRequired) { |
| this.reconfigureAndDeleteHost(container); |
| } else { |
| this.confirmDeleteHost(container); |
| } |
| }, |
| |
| /** |
| * |
| * @param {object} container |
| */ |
| reconfigureAndDeleteHost: function(container) { |
| const addDeleteComponentsMap = this.get('addDeleteComponentsMap'); |
| const hostName = this.get('content.hostName'); |
| const reconfiguredComponents = []; |
| const componentStub = Em.Object.create(); |
| |
| this.get('content.hostComponents').forEach((component) => { |
| const componentsMapItem = addDeleteComponentsMap[component.get('componentName')]; |
| if (componentsMapItem) { |
| reconfiguredComponents.push(component.get('displayName')); |
| if (componentsMapItem.hostPropertyName) { |
| this.set(componentsMapItem.hostPropertyName, hostName); |
| } |
| if (componentsMapItem.addPropertyName) { |
| this.set(componentsMapItem.addPropertyName, true); |
| } |
| this.loadComponentRelatedConfigs(componentsMapItem.configTagsCallbackName, componentsMapItem.configsCallbackName); |
| } |
| }); |
| this.showReconfigurationPopupPreDelete(componentStub, () => { |
| this.confirmDeleteHost(container); |
| }, Em.I18n.t('hosts.host.delete.componentsRequireReconfigure').format(reconfiguredComponents.join(', '))); |
| }, |
| |
| /** |
| * Show popup with info about reasons why host can't be deleted |
| * @param {string[]} components |
| * @param {string} type |
| * @method raiseDeleteComponentsError |
| */ |
| raiseDeleteComponentsError: function (container, type) { |
| App.ModalPopup.show({ |
| header: Em.I18n.t('hosts.cant.do.popup.title'), |
| type: type, |
| showBodyEnd: Em.computed.existsIn('type', ['runningList', 'masterList', 'lastMasterList']), |
| container: container, |
| components: function(){ |
| var container = this.get('container'); |
| switch (this.get('type')) { |
| case 'masterList': |
| return container.nonAddableMasterComponents; |
| case 'nonDeletableList': |
| return container.nonDeletableComponents; |
| case 'runningList': |
| return container.runningComponents; |
| case 'lastMasterList': |
| return container.lastMasterComponents; |
| } |
| }.property('type'), |
| componentsStr: function () { |
| return this.get('components').join(", "); |
| }.property('components.[]'), |
| componentsBody: Em.computed.i18nFormat('hosts.cant.do.popup.' + type + '.body', 'components.length'), |
| componentsBodyEnd: function () { |
| if (this.get('showBodyEnd')) { |
| return Em.I18n.t('hosts.cant.do.popup.' + type + '.body.end').format(App.get('components.decommissionAllowed').map(function(c){return App.format.role(c, false)}).join(", ")); |
| } |
| return ''; |
| }.property(), |
| bodyClass: Em.View.extend({ |
| templateName: require('templates/main/host/details/raiseDeleteComponentErrorPopup') |
| }), |
| secondary: null |
| }); |
| }, |
| |
| /** |
| * Show confirmation popup to delete host |
| * @param {Object} container |
| * @method confirmDeleteHost |
| */ |
| confirmDeleteHost: function (container) { |
| var self = this; |
| return App.ModalPopup.show({ |
| header: Em.I18n.t('hosts.delete.popup.title'), |
| deletePopupBody: Em.I18n.t('hosts.delete.popup.body').format(self.get('content.publicHostName')), |
| lastComponent: function () { |
| if (container.lastComponents && container.lastComponents.length) { |
| this.set('isChecked', false); |
| return true; |
| } else { |
| this.set('isChecked', true); |
| return false; |
| } |
| }.property(), |
| disablePrimary: Em.computed.not('isChecked'), |
| isChecked: false, |
| lastComponentError: Em.View.extend({ |
| template: Em.Handlebars.compile(Em.I18n.t('hosts.delete.popup.body.msg4').format(container.lastComponents)) |
| }), |
| unknownComponents: function () { |
| if (container.unknownComponents && container.unknownComponents.length) { |
| return container.unknownComponents.join(", "); |
| } |
| return ''; |
| }.property(), |
| decommissionWarning: Em.View.extend({ |
| template: Em.Handlebars.compile(Em.I18n.t('hosts.delete.popup.body.msg7').format(container.toDecommissionComponents.join(', '))) |
| }), |
| toDecommissionComponents: container.toDecommissionComponents, |
| bodyClass: Em.View.extend({ |
| templateName: require('templates/main/host/details/doDeleteHostPopup') |
| }), |
| onPrimary: function () { |
| this.hide(); |
| self.doDeleteHost(); |
| } |
| }); |
| }, |
| |
| /** |
| * send DELETE calls to components of host and after delete host itself |
| * @method doDeleteHost |
| */ |
| doDeleteHost: function () { |
| const allComponents = this.get('content.hostComponents'); |
| const addDeleteComponentsMap = this.get('addDeleteComponentsMap'); |
| const deleteRequests = []; |
| let deleteError = null; |
| const dfd = $.Deferred(); |
| |
| if (allComponents.get('length') > 0) { |
| allComponents.forEach(function (component) { |
| deleteRequests.push(this._doDeleteHostComponent(component.get('componentName'))); |
| }, this); |
| $.when(deleteRequests).done(() => { |
| if (this.get('isReconfigureRequired')) { |
| const reconfiguredComponents = allComponents |
| .filter((component) => addDeleteComponentsMap[component.get('componentName')]) |
| .mapProperty('displayName').join(', '); |
| this.applyConfigsCustomization(); |
| this.putConfigsToServer(this.get('groupedPropertiesToChange'), reconfiguredComponents); |
| this.clearConfigsChanges(); |
| } |
| this.deleteHostCall(); |
| }).fail(() => { |
| deleteError = this.get('_deletedHostComponentError'); |
| deleteError.xhr.responseText = "{\"message\": \"" + deleteError.xhr.statusText + "\"}"; |
| App.ajax.defaultErrorHandler(deleteError.xhr, deleteError.url, deleteError.type, deleteError.xhr.status); |
| }).always(dfd.resolve); |
| } else { |
| dfd.resolve(); |
| } |
| return dfd.promise(); |
| }, |
| |
| deleteHostCall: function() { |
| return App.ajax.send({ |
| name: 'common.delete.host', |
| sender: this, |
| data: { |
| hostName: this.get('content.hostName') |
| }, |
| success: 'deleteHostCallSuccessCallback', |
| error: 'deleteHostCallErrorCallback', |
| showLoadingPopup: true |
| }); |
| }, |
| |
| deleteHostCallSuccessCallback: function (data, rq, requestBody) { |
| App.router.get('updateController').updateHost(function () { |
| App.router.transitionTo('hosts.index'); |
| }); |
| if (!!(requestBody && requestBody.hostName)) { |
| var remainingHosts = App.db.getSelectedHosts().removeObject(requestBody.hostName); |
| App.db.setSelectedHosts(remainingHosts); |
| App.hostsMapper.deleteRecord(App.Host.find().findProperty('hostName', requestBody.hostName)); |
| } |
| App.router.get('clusterController').getAllHostNames(); |
| }, |
| deleteHostCallErrorCallback: function (xhr, textStatus, errorThrown, opt) { |
| xhr.responseText = "{\"message\": \"" + xhr.statusText + "\"}"; |
| App.ajax.defaultErrorHandler(xhr, opt.url, 'DELETE', xhr.status); |
| }, |
| |
| /** |
| * Send command to server to restart all host components with stale configs |
| * @method restartAllStaleConfigComponents |
| */ |
| restartAllStaleConfigComponents: function () { |
| var self = this; |
| var staleComponents = self.get('content.componentsWithStaleConfigs'); |
| if (staleComponents.someProperty('componentName', 'NAMENODE') && |
| this.get('content.hostComponents').filterProperty('componentName', 'NAMENODE').someProperty('workStatus', App.HostComponentStatus.started)) { |
| this.checkNnLastCheckpointTime(function () { |
| App.showConfirmationPopup(function () { |
| batchUtils.restartHostComponents(staleComponents, Em.I18n.t('rollingrestart.context.allWithStaleConfigsOnSelectedHost').format(self.get('content.hostName')), "HOST"); |
| }); |
| }); |
| } else { |
| return App.showConfirmationPopup(function () { |
| batchUtils.restartHostComponents(staleComponents, Em.I18n.t('rollingrestart.context.allWithStaleConfigsOnSelectedHost').format(self.get('content.hostName')), "HOST"); |
| }); |
| } |
| |
| }, |
| |
| /** |
| * open Reassign Master Wizard with selected component |
| * @param {object} event |
| * @method moveComponent |
| */ |
| moveComponent: function (event) { |
| var component = event.context; |
| if ($(event.target).closest('li').hasClass('disabled')) { |
| return; |
| } |
| return App.showConfirmationPopup(function () { |
| var reassignMasterController = App.router.get('reassignMasterController'); |
| reassignMasterController.saveComponentToReassign(component); |
| reassignMasterController.setCurrentStep('1'); |
| App.router.transitionTo('reassign'); |
| }, Em.I18n.t('question.sure.move').format(component.get('displayName'))); |
| }, |
| |
| /** |
| * Restart clients host components to apply config changes |
| * @param {object} event |
| * @method refreshConfigs |
| */ |
| refreshConfigs: function (event) { |
| var self = this; |
| var components = event.context; |
| if (components.get('length') > 0) { |
| return App.showConfirmationPopup(function () { |
| batchUtils.restartHostComponents(components, Em.I18n.t('rollingrestart.context.allClientsOnSelectedHost').format(self.get('content.hostName')), "HOST"); |
| }, Em.I18n.t('question.sure.refresh').format(self.get('content.hostName')) ); |
| } |
| }, |
| |
| toggleMaintenanceMode: function (event) { |
| var state, message, self = this; |
| if (event.context.get('isImpliedState')) return null; |
| state = event.context.get('passiveState') === "ON" ? "OFF" : "ON"; |
| message = Em.I18n.t('passiveState.turn' + state.toCapital() + 'For').format(event.context.get('displayName')); |
| return App.showConfirmationPopup(function () { |
| self.updateComponentPassiveState(event.context, state, message); |
| }, Em.I18n.t('question.sure.maintenance').format(event.context.get('displayName')) ); |
| }, |
| |
| downloadClientConfigs: function (event) { |
| this.downloadClientConfigsCall({ |
| hostName: event.context.get('hostName'), |
| componentName: event.context.get('componentName'), |
| resourceType: this.resourceTypeEnum.HOST_COMPONENT |
| }); |
| }, |
| |
| /** |
| * This controller action is called from the template when user clicks to download configs for "All Clients On Host" |
| */ |
| downloadAllClientConfigs: function () { |
| var self = this; |
| this.downloadClientConfigsCall({ |
| hostName: self.get('content.hostName'), |
| resourceType: this.resourceTypeEnum.HOST |
| }); |
| }, |
| |
| installClients: function (components) { |
| var clientsToInstall = [], |
| clientsToAdd = [], |
| missedComponents = [], |
| dependentComponents = [], |
| self = this; |
| components.forEach(function (component) { |
| if (['INIT', 'INSTALL_FAILED'].contains(component.get('workStatus'))) { |
| clientsToInstall.push(component); |
| } else if (typeof component.get('workStatus') == 'undefined') { |
| clientsToAdd.push(component); |
| } |
| }); |
| clientsToAdd.forEach(function (component, index, array) { |
| var dependencies = this.checkComponentDependencies(component.get('componentName'), { |
| scope: 'host', |
| installedComponents: this.get('content.hostComponents').mapProperty('componentName') |
| }).reject(function (componentName) { |
| return array.mapProperty('componentName').contains(componentName); |
| }); |
| if (dependencies.length) { |
| missedComponents.pushObjects(dependencies); |
| dependentComponents.push(component.get('displayName')); |
| } |
| }, this); |
| missedComponents = missedComponents.uniq(); |
| if (missedComponents.length) { |
| var popupMessage = Em.I18n.t('host.host.addComponent.popup.clients.dependedComponents.body').format(stringUtils.getFormattedStringFromArray(dependentComponents), |
| stringUtils.getFormattedStringFromArray(missedComponents.map(function (componentName) { |
| return App.StackServiceComponent.find(componentName).get('displayName'); |
| }))); |
| App.showAlertPopup(Em.I18n.t('host.host.addComponent.popup.dependedComponents.header'), popupMessage); |
| } else { |
| App.get('router.mainAdminKerberosController').getSecurityType(function () { |
| App.get('router.mainAdminKerberosController').getKDCSessionState(function () { |
| var sendInstallCommand = function () { |
| if (clientsToInstall.length) { |
| self.sendComponentCommand(clientsToInstall, Em.I18n.t('host.host.details.installClients'), 'INSTALLED'); |
| } |
| }; |
| if (clientsToAdd.length) { |
| var message = stringUtils.getFormattedStringFromArray(clientsToAdd.mapProperty('displayName')), |
| componentObject = Em.Object.create({ |
| displayName: message |
| }); |
| self.showAddComponentPopup(componentObject, self.get('content.hostName'), function () { |
| sendInstallCommand(); |
| clientsToAdd.forEach(function (component) { |
| self.installHostComponentCall(self.get('content.hostName'), component); |
| }); |
| }); |
| } else { |
| sendInstallCommand(); |
| } |
| }); |
| }.bind(this)); |
| } |
| }, |
| |
| /** |
| * Check if all required components are installed on host. |
| * Available options: |
| * scope: 'host' - dependency level `host`,`cluster` or `*`. |
| * hostName: 'example.com' - host name to search installed components |
| * installedComponents: ['A', 'B'] - names of installed components |
| * |
| * By default scope level is `*` |
| * For host level dependency you should specify at least `hostName` or `installedComponents` attribute. |
| * |
| * @param {String} componentName |
| * @param {Object} opt - options. Allowed options are `hostName`, `installedComponents`, `scope`. |
| * @return {Array} - names of missed components |
| */ |
| checkComponentDependencies: function (componentName, opt) { |
| opt = opt || {}; |
| opt.scope = opt.scope || '*'; |
| var installedComponents; |
| switch (opt.scope) { |
| case 'host': |
| Em.assert("You should pass at least `hostName` or `installedComponents` to options.", opt.hostName || opt.installedComponents); |
| installedComponents = opt.installedComponents || App.HostComponent.find().filterProperty('hostName', opt.hostName).mapProperty('componentName').uniq(); |
| break; |
| default: |
| // @todo: use more appropriate value regarding installed components |
| installedComponents = opt.installedComponents || App.HostComponent.find().mapProperty('componentName').uniq(); |
| break; |
| } |
| var component = App.StackServiceComponent.find(componentName); |
| const excludeExclusiveDependencies = (d) => d.type !== 'exclusive'; |
| return component.missingDependencies(installedComponents, opt) |
| .filter(excludeExclusiveDependencies) //If type is "exclusive" the dependent component should never be co-hosted. |
| .map(function(componentDependency) { |
| return componentDependency.chooseCompatible(); |
| }); |
| }, |
| |
| /** |
| * On click handler for custom command from items menu |
| * @param context |
| */ |
| executeCustomCommand: function(event) { |
| var controller = this; |
| var context = event.context; |
| return App.showConfirmationPopup(function() { |
| App.ajax.send({ |
| name : 'service.item.executeCustomCommand', |
| sender: controller, |
| data : { |
| command : context.command, |
| context : context.context || Em.I18n.t('services.service.actions.run.executeCustomCommand.context').format(context.command), |
| hosts : context.hosts, |
| serviceName : context.service, |
| componentName : context.component |
| }, |
| success : 'executeCustomCommandSuccessCallback', |
| error : 'executeCustomCommandErrorCallback' |
| }); |
| }); |
| }, |
| |
| executeCustomCommandSuccessCallback : function(data, ajaxOptions, params) { |
| if (data.Requests.id) { |
| App.router.get('userSettingsController').dataLoading('show_bg').done(function (initValue) { |
| if (initValue) { |
| App.router.get('backgroundOperationsController').showPopup(); |
| } |
| }); |
| } |
| }, |
| executeCustomCommandErrorCallback : function(data) { |
| var error = Em.I18n.t('services.service.actions.run.executeCustomCommand.error'); |
| if(data && data.responseText){ |
| try { |
| var json = $.parseJSON(data.responseText); |
| error += json.message; |
| } catch (err) {} |
| } |
| App.showAlertPopup(Em.I18n.t('services.service.actions.run.executeCustomCommand.error'), error); |
| }, |
| |
| /** |
| * Call callback after loading service metrics |
| * @param callback |
| */ |
| isServiceMetricsLoaded: function(callback) { |
| App.router.get('mainController').isLoading.call(App.router.get('clusterController'), 'isServiceContentFullyLoaded').done(callback); |
| }, |
| |
| setConfigsChangesForDisplay: function () { |
| if (App.get('router.clusterController.isConfigsPropertiesLoaded')) { |
| this.get('allPropertiesToChange').forEach(function (property) { |
| var stackProperty = App.configsCollection.getConfigByName(property.propertyName, property.propertyFileName); |
| if (stackProperty && (!stackProperty.isEditable || !stackProperty.isReconfigurable)) { |
| this.get('requiredPropertiesToChange').pushObject(property); |
| } else { |
| Em.set(property, 'saveRecommended', true); |
| this.get('recommendedPropertiesToChange').pushObject(property); |
| } |
| }, this); |
| this.set('isConfigsLoadingInProgress', false); |
| this.removeObserver('App.router.clusterController.isConfigsPropertiesLoaded', this, 'setConfigsChangesForDisplay'); |
| } |
| }, |
| |
| setConfigsChanges: function (groups) { |
| this.get('groupedPropertiesToChange').pushObjects(groups); |
| if (this.get('allPropertiesToChange.length')) { |
| if (App.get('router.clusterController.isConfigsPropertiesLoaded')) { |
| this.setConfigsChangesForDisplay(); |
| } else { |
| this.addObserver('App.router.clusterController.isConfigsPropertiesLoaded', this, 'setConfigsChangesForDisplay'); |
| } |
| } else { |
| this.set('isConfigsLoadingInProgress', false); |
| } |
| }, |
| |
| recoverHost: function() { |
| var components = this.get('content.hostComponents'); |
| var hostName = this.get('content.hostName'); |
| var self = this; |
| var batches = [ |
| { |
| "order_id": 1, |
| "type": "PUT", |
| "uri": "/clusters/" + App.get('clusterName') + "/hosts/" + hostName + "/host_components", |
| "RequestBodyInfo": { |
| "RequestInfo": { |
| context: Em.I18n.t('hosts.host.recover.initAllComponents.context'), |
| operation_level: { |
| level: "HOST", |
| cluster_name: App.get('clusterName'), |
| host_name: hostName |
| }, |
| query: "HostRoles/component_name.in(" + components.mapProperty('componentName').join(',') + ")" |
| }, |
| "Body": { |
| HostRoles: { |
| state: "INIT" |
| } |
| } |
| } |
| }]; |
| batches.push( |
| { |
| "order_id": 2, |
| "type": "PUT", |
| "uri": "/clusters/" + App.get('clusterName') + "/hosts/" + hostName + "/host_components", |
| "RequestBodyInfo": { |
| "RequestInfo": { |
| context: Em.I18n.t('hosts.host.recover.installAllComponents.context'), |
| operation_level: { |
| level: "HOST", |
| cluster_name: App.get('clusterName'), |
| host_name: hostName |
| }, |
| query: "HostRoles/component_name.in(" + components.mapProperty('componentName').join(',') + ")" |
| }, |
| "Body": { |
| HostRoles: { |
| state: "INSTALLED" |
| } |
| } |
| } |
| }); |
| |
| if(App.get('isKerberosEnabled')) { |
| batches.push({ |
| "order_id": 3, |
| "type": "PUT", |
| "uri": "/clusters/" + App.get('clusterName'), |
| "RequestBodyInfo": { |
| "RequestInfo": { |
| context: Em.I18n.t('hosts.host.recover.regenerateKeytabs.context'), |
| query: "regenerate_keytabs=all®enerate_hosts=" + hostName + "&config_update_policy=none", |
| }, |
| "Body": { |
| Clusters: { |
| security_type: "KERBEROS" |
| } |
| } |
| } |
| }); |
| } |
| App.get('router.mainAdminKerberosController').getSecurityType(function () { |
| App.get('router.mainAdminKerberosController').getKDCSessionState(function () { |
| self._doRecoverHost(batches); |
| }); |
| }); |
| }, |
| |
| _doRecoverHost: function (batches) { |
| App.ajax.send ({ |
| name: 'common.batch.request_schedules', |
| sender: this, |
| data: { |
| intervalTimeSeconds: 1, |
| tolerateSize: 0, |
| batches: batches |
| }, |
| success:'recoverHostSuccessCallback', |
| showLoadingPopup: true |
| }); |
| }, |
| |
| recoverHostSuccessCallback: function (data) { |
| if (data && (data.Requests || data.resources[0].RequestSchedule)) { |
| this.showBackgroundOperationsPopup(); |
| return true; |
| } else { |
| return false; |
| } |
| }, |
| |
| recoverHostDisabled: function() { |
| |
| var isDisabled = false; |
| var allowedStates = [App.HostComponentStatus.stopped, App.HostComponentStatus.install_failed, App.HostComponentStatus.init]; |
| this.get('content.hostComponents').forEach(function (component) { |
| isDisabled = isDisabled ? true : !allowedStates.contains(component.get('workStatus')); |
| }); |
| return isDisabled; |
| }.property('content.hostComponents.@each.workStatus'), |
| |
| confirmRecoverHost: function() { |
| var self = this; |
| var componentsNotStopped = []; |
| var allowedStates = [App.HostComponentStatus.stopped, App.HostComponentStatus.install_failed, App.HostComponentStatus.init]; |
| this.get('content.hostComponents').forEach(function (component) { |
| if(!allowedStates.contains(component.get('workStatus'))) { |
| componentsNotStopped.push(component.get('componentName')); |
| } |
| }); |
| if(componentsNotStopped.length) { |
| App.ModalPopup.show({ |
| header: Em.I18n.t('hosts.recover.error.popup.title'), |
| recoverErrorPopupBody: Em.I18n.t('hosts.recover.error.popup.body').format(componentsNotStopped.toString()), |
| componentsStr: componentsNotStopped.toString(), |
| bodyClass: Em.View.extend({ |
| templateName: require('templates/main/host/details/recoverHostErrorPopup') |
| }), |
| secondary: false |
| }); |
| } else { |
| App.ModalPopup.show({ |
| header: Em.I18n.t('hosts.recover.popup.title'), |
| bodyClass: Em.View.extend({ |
| templateName: require('templates/main/host/details/recoverHostPopup') |
| }), |
| primary: Em.I18n.t('yes'), |
| secondary: Em.I18n.t('no'), |
| onPrimary: function () { |
| self.recoverHost(); |
| this.hide(); |
| } |
| }); |
| } |
| }, |
| |
| |
| regenerateKeytabFileOperations: function () { |
| var self = this; |
| var hostName = this.content.get('hostName'); |
| var clusterName = App.get('clusterName'); |
| return App.showConfirmationPopup(function() { |
| return App.ajax.send({ |
| name: "admin.kerberos_security.regenerate_keytabs.host", |
| sender: self, |
| data: { |
| clusterName: clusterName, |
| hostName: hostName |
| }, |
| success: 'regenerateKeytabFileOperationsRequestSuccess', |
| error: 'regenerateKeytabFileOperationsRequestError' |
| }); |
| }, Em.I18n.t('question.sure.regenerateKeytab.host').format(hostName)); |
| }, |
| |
| regenerateKeytabFileOperationsRequestSuccess: function(){ |
| App.router.get('backgroundOperationsController').showPopup(); |
| }, |
| |
| regenerateKeytabFileOperationsRequestError: function () { |
| App.showAlertPopup(Em.I18n.t('common.error'), Em.I18n.t('alerts.notifications.regenerateKeytab.host.error').format(this.content.get('hostName'))); |
| }, |
| |
| /** |
| * Returns URL parameters for configs request by certain tags |
| * @param {object} data - object with desired configs tags received from API |
| * @param {string[]} configTypes - list of config types |
| * @returns {string} |
| */ |
| getUrlParamsForConfigsRequest: function (data, configTypes) { |
| return configTypes.map(type => { |
| const tag = Em.get(data, `Clusters.desired_configs.${type}.tag`); |
| return tag ? `(type=${type}&tag=${tag})` : null; |
| }).compact().join('|'); |
| } |
| |
| }); |