| /** |
| * 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 stringUtils = require('utils/string_utils'); |
| var fileUtils = require('utils/file_utils'); |
| require('./wizardStep_controller'); |
| |
| App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfigs, App.wizardDeployProgressControllerMixin, App.ConfigOverridable, App.ConfigsSaverMixin, { |
| |
| name: 'wizardStep8Controller', |
| |
| stepName: 'step8', |
| |
| /** |
| * @type {boolean} |
| */ |
| isAddService: Em.computed.equal('content.controllerName', 'addServiceController'), |
| |
| /** |
| * @type {boolean} |
| */ |
| isAddHost: Em.computed.equal('content.controllerName', 'addHostController'), |
| |
| /** |
| * @type {boolean} |
| */ |
| isInstaller: Em.computed.equal('content.controllerName', 'installerController'), |
| |
| /** |
| * List of raw data about cluster that should be displayed |
| * @type {Array} |
| */ |
| rawContent: [ |
| { |
| config_name: 'Admin', |
| display_name: 'Admin Name', |
| config_value: '' |
| }, |
| { |
| config_name: 'cluster', |
| display_name: 'Cluster Name', |
| config_value: '' |
| }, |
| { |
| config_name: 'hosts', |
| display_name: 'Total Hosts', |
| config_value: '' |
| }, |
| { |
| config_name: 'Repo', |
| display_name: 'Local Repository', |
| config_value: '' |
| } |
| ], |
| |
| /** |
| * List of data about cluster (based on formatted <code>rawContent</code>) |
| * @type {Object[]} |
| */ |
| clusterInfo: [], |
| |
| /** |
| * List of services with components assigned to hosts |
| * @type {Object[]} |
| */ |
| services: [], |
| |
| /** |
| * @type {Object[]} |
| */ |
| configs: [], |
| |
| /** |
| * True if Kerberos is installed on the cluster and the kdc_type on the server is set to "none" |
| * @type {Boolean} |
| */ |
| isManualKerberos: Em.computed.equal('App.router.mainAdminKerberosController.kdc_type', 'none'), |
| |
| showDownloadCsv: function () { |
| return !!App.get('router.mainAdminKerberosController.kdc_type') |
| }.property('App.router.mainAdminKerberosController.kdc_type'), |
| |
| |
| /** |
| * Should Submit button be disabled |
| * @type {bool} |
| */ |
| isSubmitDisabled: false, |
| |
| /** |
| * Should Back button be disabled |
| * @type {bool} |
| */ |
| isBackBtnDisabled: false, |
| |
| /** |
| * Is error appears while <code>ajaxQueue</code> executes |
| * @type {bool} |
| */ |
| hasErrorOccurred: false, |
| |
| /** |
| * Are services installed |
| * Used to hide Deploy Progress Bar |
| * @type {bool} |
| */ |
| servicesInstalled: false, |
| |
| /** |
| * List of service config tags |
| * @type {Object[]} |
| */ |
| serviceConfigTags: [], |
| |
| /** |
| * Selected config group |
| * @type {Object} |
| */ |
| selectedConfigGroup: null, |
| |
| /** |
| * List of config groups |
| * @type {Object[]} |
| */ |
| configGroups: [], |
| |
| selectedServices: function () { |
| const services = App.StackService.find().map(service => service); |
| return services; |
| }.property(), |
| |
| selectedMpacks: function() { |
| return this.get('content.selectedMpacks') || this.get('wizardController').getDBProperty('selectedMpacks'); |
| }.property(), |
| |
| downloadConfig: function() { |
| return this.get('content.downloadConfig') || this.get('wizardController').getDBProperty('downloadConfig'); |
| }.property(), |
| |
| getSelectedStack: function() { |
| const selectedStack = this.get('content.selectedStack'); |
| const stack = this.get('wizardController').getStack(selectedStack.name, selectedStack.version); |
| return stack; |
| }, |
| |
| installedServices: function() { |
| const services = App.StackService.find().filter(service => service.get('isInstalled') === true); |
| return services; |
| }.property(), |
| |
| /** |
| * Current cluster name |
| * @type {string} |
| */ |
| clusterName: Em.computed.alias('content.cluster.name'), |
| |
| /** |
| * List of existing cluster names |
| * @type {string[]} |
| */ |
| clusterNames: [], |
| |
| /** |
| * Number of completed cluster delete requests |
| * @type {number} |
| */ |
| clusterDeleteRequestsCompleted: 0, |
| |
| /** |
| * Number of existing repo_versions |
| * @type {number} |
| */ |
| existingRepositoryVersions: 0, |
| |
| /** |
| * Indicates if all cluster delete requests are completed |
| * @type {boolean} |
| */ |
| isAllClusterDeleteRequestsCompleted: Em.computed.equalProperties('clusterDeleteRequestsCompleted', 'clusterNames.length'), |
| |
| /** |
| * Error popup body views for clusters that couldn't be deleted |
| * @type {App.AjaxDefaultErrorPopupBodyView[]} |
| */ |
| clusterDeleteErrorViews: [], |
| |
| /** |
| * Clear current step data |
| * @method clearStep |
| */ |
| clearStep: function () { |
| this.get('services').clear(); |
| this.get('configs').clear(); |
| this.get('clusterInfo').clear(); |
| this.get('serviceConfigTags').clear(); |
| this.set('servicesInstalled', false); |
| this.set('ajaxQueueLength', 0); |
| this.set('ajaxRequestsQueue', App.ajaxQueue.create()); |
| this.set('ajaxRequestsQueue.finishedCallback', this.ajaxQueueFinished); |
| this.get('clusterDeleteErrorViews').clear(); |
| this.set('clusterDeleteRequestsCompleted', 0); |
| }, |
| |
| /** |
| * Load current step data |
| * @method loadStep |
| */ |
| loadStep: function () { |
| this.clearStep(); |
| if (this.get('content.serviceConfigProperties')) { |
| this.formatProperties(); |
| this.loadConfigs(); |
| } |
| this.loadClusterInfo(); |
| this.loadServices(); |
| this.set('isSubmitDisabled', false); |
| this.set('isBackBtnDisabled', false); |
| }, |
| |
| /** |
| * replace whitespace character with coma between directories |
| * @method formatProperties |
| */ |
| formatProperties: function () { |
| this.get('content.serviceConfigProperties').forEach(function (_configProperty) { |
| _configProperty.value = typeof _configProperty.value === "boolean" |
| ? _configProperty.value.toString() : App.config.trimProperty(_configProperty, false); |
| }); |
| }, |
| |
| /** |
| * Load all site properties |
| * @method loadConfigs |
| */ |
| loadConfigs: function () { |
| this.set('configs', this.get('content.serviceConfigProperties').filter(function (config) { |
| return !config.group; |
| })); |
| }, |
| |
| /** |
| * Format <code>content.hosts</code> from Object to Array |
| * @returns {Array} |
| * @method getRegisteredHosts |
| */ |
| getRegisteredHosts: function () { |
| var allHosts = this.get('content.hosts'); |
| var hosts = []; |
| for (var hostName in allHosts) { |
| if (allHosts.hasOwnProperty(hostName)) { |
| if (allHosts[hostName].bootStatus === 'REGISTERED') { |
| allHosts[hostName].hostName = allHosts[hostName].name; |
| hosts.pushObject(allHosts[hostName]); |
| } |
| } |
| } |
| return hosts; |
| }, |
| |
| /** |
| * Load all info about cluster to <code>clusterInfo</code> variable |
| * @method loadClusterInfo |
| */ |
| loadClusterInfo: function () { |
| |
| //Admin name |
| var admin = this.rawContent.findProperty('config_name', 'Admin'); |
| admin.config_value = App.db.getLoginName(); |
| if (admin.config_value) { |
| this.get('clusterInfo').pushObject(Ember.Object.create(admin)); |
| } |
| |
| // cluster name |
| var cluster = this.rawContent.findProperty('config_name', 'cluster'); |
| cluster.config_value = this.get('content.cluster.name'); |
| this.get('clusterInfo').pushObject(Ember.Object.create(cluster)); |
| |
| //hosts |
| var newHostsCount = 0; |
| var totalHostsCount = 0; |
| var hosts = this.get('content.hosts'); |
| for (var hostName in hosts) { |
| newHostsCount += ~~!hosts[hostName].isInstalled; |
| totalHostsCount++; |
| } |
| |
| var totalHostsObj = this.rawContent.findProperty('config_name', 'hosts'); |
| totalHostsObj.config_value = totalHostsCount + ' (' + newHostsCount + ' new)'; |
| this.get('clusterInfo').pushObject(Em.Object.create(totalHostsObj)); |
| |
| //repo |
| if (this.get('isAddService') || this.get('isAddHost')) { |
| // For some stacks there is no info regarding stack versions to upgrade, e.g. HDP-2.1 |
| if (App.StackVersion.find().get('content.length')) { |
| this.loadRepoInfo(); |
| } else { |
| this.loadDefaultRepoInfo(); |
| } |
| } else { |
| // from install wizard |
| var downloadConfig = this.get('downloadConfig'); |
| var selectedStack = this.getSelectedStack(); |
| var allRepos = []; |
| if (selectedStack && selectedStack.get('operatingSystems')) { |
| selectedStack.get('operatingSystems').forEach(function (os) { |
| if (os.get('isSelected')) { |
| os.get('repositories').forEach(function(repo) { |
| if (repo.get('showRepo')) { |
| allRepos.push(Em.Object.create({ |
| base_url: repo.get('baseUrl'), |
| os_type: repo.get('osType'), |
| repo_id: repo.get('repoId') |
| })); |
| } |
| }, this); |
| } |
| }, this); |
| } |
| allRepos.set('display_name', Em.I18n.t("installer.step8.repoInfo.displayName")); |
| this.get('clusterInfo').set('useRedhatSatellite', downloadConfig.useRedhatSatellite); |
| this.get('clusterInfo').set('repoInfo', allRepos); |
| } |
| }, |
| |
| /** |
| * Load repo info for add Service/Host wizard review page |
| * @return {$.ajax|null} |
| * @method loadRepoInfo |
| */ |
| loadRepoInfo: function () { |
| var stackName = App.get('currentStackName'); |
| var currentStackVersionNumber = App.get('currentStackVersionNumber'); |
| var currentStackVersion = App.StackVersion.find().filterProperty('stack', stackName).findProperty('version', currentStackVersionNumber); |
| var currentRepoVersion = currentStackVersion.get('repositoryVersion.repositoryVersion'); |
| |
| return App.ajax.send({ |
| name: 'cluster.load_repo_version', |
| sender: this, |
| data: { |
| stackName: stackName, |
| repositoryVersion: currentRepoVersion |
| }, |
| success: 'loadRepoInfoSuccessCallback', |
| error: 'loadRepoInfoErrorCallback' |
| }); |
| }, |
| |
| /** |
| * Save all repo base URL of all OS type to <code>repoInfo<code> |
| * @param {object} data |
| * @method loadRepoInfoSuccessCallback |
| */ |
| loadRepoInfoSuccessCallback: function (data) { |
| Em.assert('Current repo-version may be only one', data.items.length === 1); |
| if (data.items.length) { |
| var allRepos = this.generateRepoInfo(Em.getWithDefault(data, 'items.0.repository_versions.0.operating_systems', [])); |
| allRepos.set('display_name', Em.I18n.t("installer.step8.repoInfo.displayName")); |
| this.get('clusterInfo').set('repoInfo', allRepos); |
| //if the property is missing, set as false |
| this.get('clusterInfo').set('useRedhatSatellite', data.items[0].repository_versions[0].operating_systems[0].OperatingSystems.ambari_managed_repositories === false); |
| } else { |
| this.loadDefaultRepoInfo(); |
| } |
| }, |
| |
| /** |
| * Generate list regarding info about OS versions and repositories. |
| * |
| * @param {Object{}} oses - OS array |
| * @returns {Em.Object[]} |
| */ |
| generateRepoInfo: function(oses) { |
| return oses.map(function(os) { |
| return os.repositories.map(function (repository) { |
| return Em.Object.create({ |
| base_url: repository.Repositories.base_url, |
| os_type: repository.Repositories.os_type, |
| repo_id: repository.Repositories.repo_id |
| }); |
| }); |
| }).reduce(function(p, c) { return p.concat(c); }); |
| }, |
| |
| /** |
| * Load repo info from stack. Used if installed stack doesn't have upgrade info. |
| * |
| * @returns {$.Deferred} |
| * @method loadDefaultRepoInfo |
| */ |
| loadDefaultRepoInfo: function() { |
| var nameVersionCombo = App.get('currentStackVersion').split('-'); |
| |
| return App.ajax.send({ |
| name: 'cluster.load_repositories', |
| sender: this, |
| data: { |
| stackName: nameVersionCombo[0], |
| stackVersion: nameVersionCombo[1] |
| }, |
| success: 'loadDefaultRepoInfoSuccessCallback', |
| error: 'loadRepoInfoErrorCallback' |
| }); |
| }, |
| |
| /** |
| * @param {Object} data - JSON data from server |
| * @method loadDefaultRepoInfoSuccessCallback |
| */ |
| loadDefaultRepoInfoSuccessCallback: function (data) { |
| var allRepos = this.generateRepoInfo(Em.getWithDefault(data, 'items', [])); |
| allRepos.set('display_name', Em.I18n.t("installer.step8.repoInfo.displayName")); |
| this.get('clusterInfo').set('repoInfo', allRepos); |
| //if the property is missing, set as false |
| this.get('clusterInfo').set('useRedhatSatellite', data.items[0].OperatingSystems.ambari_managed_repositories === false); |
| }, |
| |
| /** |
| * @method loadRepoInfoErrorCallback |
| */ |
| loadRepoInfoErrorCallback: function () { |
| var allRepos = []; |
| allRepos.set('display_name', Em.I18n.t("installer.step8.repoInfo.displayName")); |
| this.get('clusterInfo').set('repoInfo', allRepos); |
| }, |
| |
| /** |
| * Load all info about services to <code>services</code> variable |
| * @method loadServices |
| */ |
| loadServices: function () { |
| this.get('selectedServices').filterProperty('isHiddenOnSelectServicePage', false).forEach(function (service) { |
| var serviceObj = Em.Object.create({ |
| service_name: service.get('serviceName'), |
| display_name: service.get('displayNameOnSelectServicePage'), |
| service_components: Em.A([]) |
| }); |
| service.get('serviceComponents').forEach(function (component) { |
| // show clients for services that have only clients components |
| if ((component.get('isClient') || component.get('isRequiredOnAllHosts')) && !service.get('isClientOnlyService')) return; |
| // no HA component |
| if (component.get('isHAComponentOnly')) return; |
| // skip if component is not allowed on single node cluster |
| if (Object.keys(this.get('content.hosts')).length === 1 && component.get('isNotAllowedOnSingleNodeCluster')) return; |
| var displayName; |
| if (component.get('isClient')) { |
| displayName = Em.I18n.t('common.clients') |
| } else { |
| // remove service name from component display name |
| displayName = App.format.role(component.get('componentName'), false).replace(new RegExp('^' + service.get('serviceName') + '\\s', 'i'), ''); |
| } |
| |
| var componentName = component.get('componentName'); |
| var masterComponents = this.get('content.masterComponentHosts'); |
| var isMasterComponentSelected = masterComponents.someProperty('component', componentName); |
| var isMaster = component.get('isMaster'); |
| |
| if (!isMaster || isMasterComponentSelected) { |
| serviceObj.get('service_components').pushObject(Em.Object.create({ |
| component_name: component.get('isClient') ? Em.I18n.t('common.client').toUpperCase() : component.get('componentName'), |
| display_name: displayName, |
| component_value: this.assignComponentHosts(component) |
| })); |
| } |
| }, this); |
| if (service.get('customReviewHandler')) { |
| for (var displayName in service.get('customReviewHandler')) { |
| serviceObj.get('service_components').pushObject(Em.Object.create({ |
| display_name: displayName, |
| component_value: this.assignComponentHosts(Em.Object.create({ |
| customHandler: service.get('customReviewHandler.' + displayName) |
| })) |
| })); |
| } |
| } |
| this.get('services').pushObject(serviceObj); |
| }, this); |
| }, |
| |
| /** |
| * Set <code>component_value</code> property to <code>component</code> |
| * @param {Em.Object} component |
| * @return {String} |
| * @method assignComponentHosts |
| */ |
| assignComponentHosts: function (component) { |
| var componentValue; |
| if (component.get('customHandler')) { |
| componentValue = this[component.get('customHandler')].call(this, component); |
| } |
| else { |
| if (component.get('isMaster')) { |
| componentValue = this.getMasterComponentValue(component.get('componentName')); |
| } |
| else { |
| var componentName = component.get('isClient') ? Em.I18n.t('common.client').toUpperCase() : component.get('componentName'); |
| var hostsLength = this.get('content.slaveComponentHosts') |
| .findProperty('componentName', componentName).hosts.length; |
| componentValue = hostsLength + Em.I18n.t('installer.step8.host' + (hostsLength > 1 ? 's' : '')); |
| } |
| } |
| return componentValue; |
| }, |
| |
| getMasterComponentValue: function (componentName) { |
| var masterComponents = this.get('content.masterComponentHosts'); |
| var hostsCount = masterComponents.filterProperty('component', componentName).length; |
| return stringUtils.pluralize(hostsCount, |
| masterComponents.findProperty('component', componentName).hostName, |
| hostsCount + ' ' + Em.I18n.t('installer.step8.hosts')); |
| }, |
| |
| loadHiveDbValue: function() { |
| return this.loadDbValue('HIVE'); |
| }, |
| |
| loadOozieDbValue: function() { |
| return this.loadDbValue('OOZIE'); |
| }, |
| |
| /** |
| * Set displayed Hive DB value based on DB type |
| * @method loadHiveDbValue |
| */ |
| loadDbValue: function (serviceName) { |
| var serviceConfigProperties = this.get('content.serviceConfigProperties'); |
| var dbFull = serviceConfigProperties.findProperty('name', serviceName.toLowerCase() + '_database'); |
| //db = serviceConfigProperties.findProperty('name', serviceName.toLowerCase() + '_ambari_database'); |
| //since db.value contains the intial default value of <service>_admin_database (MySQL) and not the actual db type selected, |
| //ignore the value when displaying the database name on the summary page |
| return dbFull ? dbFull.value : ''; |
| }, |
| |
| /** |
| * Set displayed HBase master value |
| * @param {Object} hbaseMaster |
| * @method loadHbaseMasterValue |
| */ |
| loadHbaseMasterValue: function (hbaseMaster) { |
| var hbaseHostName = this.get('content.masterComponentHosts').filterProperty('component', hbaseMaster.component_name); |
| if (hbaseHostName.length === 1) { |
| hbaseMaster.set('component_value', hbaseHostName[0].hostName); |
| } else { |
| hbaseMaster.set('component_value', hbaseHostName[0].hostName + " " + Em.I18n.t('installer.step8.other').format(hbaseHostName.length - 1)); |
| } |
| }, |
| |
| /** |
| * Set displayed ZooKeeper Server value |
| * @param {Object} serverComponent |
| * @method loadZkServerValue |
| */ |
| loadZkServerValue: function (serverComponent) { |
| var zkHostNames = this.get('content.masterComponentHosts').filterProperty('component', serverComponent.component_name).length; |
| var hostSuffix; |
| if (zkHostNames === 1) { |
| hostSuffix = Em.I18n.t('installer.step8.host'); |
| } else { |
| hostSuffix = Em.I18n.t('installer.step8.hosts'); |
| } |
| serverComponent.set('component_value', zkHostNames + hostSuffix); |
| }, |
| |
| /** |
| * Onclick handler for <code>next</code> button |
| * @method submit |
| * @return {void} |
| */ |
| submit: function () { |
| var wizardController; |
| if (!this.get('isSubmitDisabled')) { |
| wizardController = App.router.get(this.get('content.controllerName')); |
| wizardController.setLowerStepsDisable(wizardController.get('currentStep')); |
| this.set('isSubmitDisabled', true); |
| this.set('isBackBtnDisabled', true); |
| this.showRestartWarnings() |
| .then(this.checkKDCSession.bind(this)); |
| } |
| }, |
| |
| /** |
| * Warn user about services that will be restarted during installation. |
| * |
| * @returns {$.Deferred} |
| */ |
| showRestartWarnings: function() { |
| var self = this; |
| var dfd = $.Deferred(); |
| var wizardController = App.router.get(this.get('content.controllerName')); |
| var selectedServiceNames = this.get('selectedServices').mapProperty('serviceName'); |
| var installedServiceNames = this.get('installedServices').mapProperty('serviceName'); |
| |
| if (this.get('isAddService') && selectedServiceNames.contains('OOZIE')) { |
| var affectedServices = ['HDFS', 'YARN'].filter(function(serviceName) { |
| return installedServiceNames.contains(serviceName); |
| }); |
| if (affectedServices.length) { |
| var serviceNames = affectedServices.length > 1 ? |
| '<b>{0}</b> {1} <b>{2}</b>'.format(affectedServices[0], Em.I18n.t('and'), affectedServices[1]) : '<b>' + affectedServices[0] + '</b> '; |
| App.ModalPopup.show({ |
| encodeBody: false, |
| header: Em.I18n.t('common.warning'), |
| body: Em.I18n.t('installer.step8.services.restart.required').format(serviceNames, stringUtils.pluralize(affectedServices.length, Em.I18n.t('common.service').toLowerCase())), |
| secondary: Em.I18n.t('common.cancel'), |
| primary: Em.I18n.t('common.proceedAnyway'), |
| onPrimary: function() { |
| this.hide(); |
| dfd.resolve(); |
| }, |
| onClose: function() { |
| this.hide(); |
| self.set('isSubmitDisabled', false); |
| self.set('isBackBtnDisabled', false); |
| wizardController.setStepsEnable(); |
| dfd.reject(); |
| }, |
| onSecondary: function() { |
| this.onClose(); |
| } |
| }); |
| } else { |
| dfd.resolve(); |
| } |
| } else { |
| dfd.resolve(); |
| } |
| return dfd.promise(); |
| }, |
| |
| checkKDCSession: function() { |
| var self = this; |
| var wizardController = App.router.get(this.get('content.controllerName')); |
| if (!this.get('isInstaller')) { |
| App.get('router.mainAdminKerberosController').getKDCSessionState(this.submitProceed.bind(this), function () { |
| self.set('isSubmitDisabled', false); |
| self.set('isBackBtnDisabled', false); |
| wizardController.setStepsEnable(); |
| if (self.get('isAddService')) { |
| wizardController.setSkipSlavesStep(wizardController.getDBProperty('selectedServiceNames'), 3); |
| } |
| }); |
| } else { |
| this.submitProceed(); |
| } |
| }, |
| |
| /** |
| * Prepare <code>ajaxQueue</code> and start to execute it |
| * @method submitProceed |
| */ |
| submitProceed: function () { |
| var self = this; |
| this.set('clusterDeleteRequestsCompleted', 0); |
| this.get('clusterDeleteErrorViews').clear(); |
| if (this.get('isAddHost')) { |
| App.router.get('addHostController').setLowerStepsDisable(4); |
| } |
| |
| // checkpoint the cluster status on the server so that the user can resume from where they left off |
| switch (this.get('content.controllerName')) { |
| case 'installerController': |
| App.clusterStatus.setClusterStatus({ |
| clusterName: this.get('clusterName'), |
| clusterState: 'CLUSTER_DEPLOY_PREP_2', |
| wizardControllerName: this.get('content.controllerName'), |
| localdb: App.db.data |
| }); |
| break; |
| case 'addHostController': |
| App.clusterStatus.setClusterStatus({ |
| clusterName: this.get('clusterName'), |
| clusterState: 'ADD_HOSTS_DEPLOY_PREP_2', |
| wizardControllerName: this.get('content.controllerName'), |
| localdb: App.db.data |
| }); |
| break; |
| case 'addServiceController': |
| App.clusterStatus.setClusterStatus({ |
| clusterName: this.get('clusterName'), |
| clusterState: 'ADD_SERVICES_DEPLOY_PREP_2', |
| wizardControllerName: this.get('content.controllerName'), |
| localdb: App.db.data |
| }); |
| break; |
| default: |
| break; |
| } |
| // delete any existing clusters to start from a clean slate |
| // before creating a new cluster in install wizard |
| // TODO: modify for multi-cluster support |
| // this.getExistingClusterNames().complete(function () { |
| // var clusterNames = self.get('clusterNames'); |
| // if (self.get('isInstaller') && !App.get('testMode') && clusterNames.length) { |
| // self.deleteClusters(clusterNames); |
| // } else { |
| // self.getExistingVersions(); |
| // } |
| // }); |
| |
| this.startDeploy(); |
| }, |
| |
| /** |
| * Get list of existing cluster names |
| * @returns {object|null} |
| * returns an array of existing cluster names. |
| * returns an empty array if there are no existing clusters. |
| * @method getExistingClusterNames |
| */ |
| getExistingClusterNames: function () { |
| return App.ajax.send({ |
| name: 'wizard.step8.existing_cluster_names', |
| sender: this, |
| success: 'getExistingClusterNamesSuccessCallBack', |
| error: 'getExistingClusterNamesErrorCallback' |
| }); |
| }, |
| |
| /** |
| * Save received list to <code>clusterNames</code> |
| * @param {Object} data |
| * @method getExistingClusterNamesSuccessCallBack |
| */ |
| getExistingClusterNamesSuccessCallBack: function (data) { |
| var clusterNames = data.items.mapProperty('Clusters.cluster_name'); |
| this.set('clusterNames', clusterNames); |
| }, |
| |
| /** |
| * If error appears, set <code>clusterNames</code> to <code>[]</code> |
| * @method getExistingClusterNamesErrorCallback |
| */ |
| getExistingClusterNamesErrorCallback: function () { |
| this.set('clusterNames', []); |
| }, |
| |
| /** |
| * Delete cluster by name |
| * One request for one cluster! |
| * @param {string[]} clusterNames |
| * @method deleteClusters |
| */ |
| deleteClusters: function (clusterNames) { |
| this.get('clusterDeleteErrorViews').clear(); |
| clusterNames.forEach(function (clusterName, index) { |
| App.ajax.send({ |
| name: 'common.delete.cluster', |
| sender: this, |
| data: { |
| name: clusterName, |
| isLast: index === clusterNames.length - 1 |
| }, |
| success: 'deleteClusterSuccessCallback', |
| error: 'deleteClusterErrorCallback' |
| }); |
| }, this); |
| |
| }, |
| |
| /** |
| * Method to execute after successful cluster deletion |
| * @method deleteClusterSuccessCallback |
| */ |
| deleteClusterSuccessCallback: function () { |
| this.incrementProperty('clusterDeleteRequestsCompleted'); |
| if (this.get('isAllClusterDeleteRequestsCompleted')) { |
| if (this.get('clusterDeleteErrorViews.length')) { |
| this.showDeleteClustersErrorPopup(); |
| } else { |
| this.getExistingVersions(); |
| } |
| } |
| }, |
| |
| /** |
| * Method to execute after failed cluster deletion |
| * @param {object} request |
| * @param {string} ajaxOptions |
| * @param {string} error |
| * @param {object} opt |
| * @method deleteClusterErrorCallback |
| */ |
| deleteClusterErrorCallback: function (request, ajaxOptions, error, opt) { |
| this.incrementProperty('clusterDeleteRequestsCompleted'); |
| try { |
| var json = $.parseJSON(request.responseText); |
| var message = json.message; |
| } catch (err) { |
| } |
| this.get('clusterDeleteErrorViews').pushObject(App.AjaxDefaultErrorPopupBodyView.create({ |
| url: opt.url, |
| type: opt.type, |
| status: request.status, |
| message: message |
| })); |
| if (this.get('isAllClusterDeleteRequestsCompleted')) { |
| this.showDeleteClustersErrorPopup(); |
| } |
| }, |
| |
| /** |
| * Show error popup if cluster deletion failed |
| * @method showDeleteClustersErrorPopup |
| */ |
| showDeleteClustersErrorPopup: function () { |
| var self = this; |
| this.setProperties({ |
| isSubmitDisabled: false, |
| isBackBtnDisabled: false |
| }); |
| App.ModalPopup.show({ |
| header: Em.I18n.t('common.error'), |
| secondary: false, |
| onPrimary: function () { |
| this.hide(); |
| }, |
| bodyClass: Em.ContainerView.extend({ |
| childViews: self.get('clusterDeleteErrorViews') |
| }) |
| }); |
| }, |
| |
| /** |
| * Get existing repo_versions |
| * @method getExistingVersions |
| */ |
| getExistingVersions: function () { |
| return App.ajax.send({ |
| name: 'wizard.get_version_definitions', |
| sender: this, |
| success: 'getExistingVersionsSuccessCallback' |
| }); |
| }, |
| |
| /** |
| * @param {Object} data |
| * @method getExistingVersionsSuccessCallback |
| */ |
| getExistingVersionsSuccessCallback: function (data) { |
| if (this.get('isInstaller') && !App.get('testMode') && data.items.length) { |
| this.set('existingRepositoryVersions', data.items.length); |
| this.deleteExistingVersions(data.items); |
| } else { |
| this.startDeploy(); |
| } |
| }, |
| |
| /** |
| * Delete existing repo_versions |
| * @param {Array} versions |
| * @method deleteExistingVersions |
| */ |
| deleteExistingVersions: function (versions) { |
| versions.forEach(function (version) { |
| App.ajax.send({ |
| name: 'wizard.delete_repository_versions', |
| sender: this, |
| data: { |
| id: version.VersionDefinition.id, |
| stackName: version.VersionDefinition.stack_name, |
| stackVersion: version.VersionDefinition.stack_version |
| }, |
| success: 'deleteExistingVersionsSuccessCallback' |
| }); |
| }, this); |
| }, |
| |
| /** |
| * Method to execute after successful version deletion |
| * @method deleteExistingVersionsSuccessCallback |
| */ |
| deleteExistingVersionsSuccessCallback: function () { |
| this.decrementProperty('existingRepositoryVersions'); |
| if (this.get('existingRepositoryVersions') === 0) { |
| this.startDeploy(); |
| } |
| }, |
| |
| /** |
| * updates kerberosDescriptorConfigs |
| * @method updateKerberosDescriptor |
| */ |
| updateKerberosDescriptor: function(instant) { |
| var kerberosDescriptor = this.get('wizardController').getDBProperty('kerberosDescriptorConfigs'); |
| var descriptorExists = this.get('wizardController').getDBProperty('isClusterDescriptorExists') === true; |
| |
| var ajaxOpts = { |
| name: descriptorExists ? 'admin.kerberos.cluster.artifact.update' : 'admin.kerberos.cluster.artifact.create', |
| data: { |
| artifactName: 'kerberos_descriptor', |
| data: { |
| artifact_data: kerberosDescriptor |
| } |
| } |
| }; |
| if (instant) { |
| ajaxOpts.sender = this; |
| App.ajax.send(ajaxOpts); |
| } else { |
| this.addRequestToAjaxQueue(ajaxOpts); |
| } |
| }, |
| |
| /** |
| * Start deploy process |
| * @method startDeploy |
| */ |
| startDeploy: function () { |
| this.createCluster(); |
| this.createServiceGroups(); |
| this.createSelectedServices(); |
| if (!this.get('isAddHost')) { |
| if (this.get('isAddService')) { |
| // for manually enabled Kerberos descriptor was updated on transition to this step |
| if (App.get('isKerberosEnabled') && !this.get('isManualKerberos')) { |
| this.updateKerberosDescriptor(); |
| } |
| var fileNamesToUpdate = this.get('wizardController').getDBProperty('fileNamesToUpdate').uniq(); |
| if (fileNamesToUpdate && fileNamesToUpdate.length) { |
| this.applyConfigurationsToCluster(this.generateDesiredConfigsJSON(this.get('configs'), fileNamesToUpdate)); |
| } |
| } |
| this.configureCluster(); |
| this.createServiceConfigurations(); |
| this.applyConfigurationsToCluster(this.get('serviceConfigTags')); |
| } |
| this.createComponents(); |
| this.registerHostsToCluster(); |
| this.createConfigurationGroups(); |
| this.createMasterHostComponents(); |
| this.createSlaveAndClientsHostComponents(); |
| if (this.get('isAddService')) { |
| this.createAdditionalClientComponents(); |
| } |
| this.createAdditionalHostComponents(); |
| |
| this.set('ajaxQueueLength', this.get('ajaxRequestsQueue.queue.length')); |
| this.get('ajaxRequestsQueue').start(); |
| this.showLoadingIndicator(); |
| }, |
| |
| /** |
| * ******************************************************************* |
| * The following create* functions are called upon submitting Step 8. |
| * ******************************************************************* |
| */ |
| |
| /** |
| * Create cluster using selected stack version |
| * Queued request |
| * @method createCluster |
| */ |
| createCluster: function () { |
| if (!this.get('isInstaller')) return; |
| const selectedStack = this.getSelectedStack() |
| this.addRequestToAjaxQueue({ |
| name: 'wizard.step8.create_cluster', |
| data: { |
| data: JSON.stringify({ "Clusters": {"version": selectedStack.get('stackNameVersion')}}) |
| }, |
| success: 'createClusterSuccess' |
| }); |
| }, |
| |
| createClusterSuccess: function (data, xhr, params) { |
| App.set('clusterName', params.cluster); |
| }, |
| |
| /** |
| * Creates one service group per mpack. |
| * Skip if no mpacks were selected. |
| * Queued request |
| * @method createServiceGroup |
| */ |
| createServiceGroups: function () { |
| if (!this.get('isInstaller')) return; |
| |
| var data = this.createServiceGroupsData(); |
| if (data) { |
| this.addRequestToAjaxQueue({ |
| name: 'wizard.step8.create_service_group', |
| data: { |
| data: JSON.stringify(data) |
| } |
| }); |
| } |
| }, |
| |
| /** |
| * Format data for <code>createServiceGroups</code> request |
| * @returns {Object[]} |
| * @method createServiceGroupsData |
| */ |
| createServiceGroupsData: function () { |
| const mpacks = this.get('selectedMpacks'); |
| |
| if (mpacks) { |
| const serviceGroups = mpacks.map(mpack => ({ |
| "ServiceGroupInfo": { |
| "service_group_name": `${mpack.name}-${mpack.version}`, |
| } |
| }) |
| ); |
| |
| return serviceGroups; |
| } |
| |
| return null; |
| }, |
| |
| /** |
| * Create selected to install services |
| * Queued request |
| * Skipped if no services where selected! |
| * @method createSelectedServices |
| */ |
| createSelectedServices: function () { |
| var data = this.createSelectedServicesData(); |
| if (!data.length) return; |
| this.addRequestToAjaxQueue({ |
| name: 'wizard.step8.create_selected_services', |
| data: { |
| data: JSON.stringify(data) |
| } |
| }); |
| }, |
| |
| /** |
| * Format data for <code>createSelectedServices</code> request |
| * @returns {Object[]} |
| * @method createSelectedServicesData |
| */ |
| createSelectedServicesData: function () { |
| const services = this.get('selectedServices'); |
| const data = services.map(service => ({ |
| "ServiceInfo": { |
| "service_name": service.get('serviceName'), |
| "service_type": service.get('serviceName'), |
| //TODO: mpacks - needs to be revisited when we are no longer hard coding service groups to be named |
| // for mpacks and when the concept of a "selected stack" is no longer a thing |
| "service_group_name": `${service.get('stackName')}-${service.get('stackVersion')}`, |
| "desired_stack": `${service.get('stackName')}-${service.get('stackVersion')}`, |
| } |
| }) |
| ); |
| return data; |
| }, |
| |
| /** |
| * Create components for selected services |
| * Queued requests |
| * One request for each service! |
| * @method createComponents |
| */ |
| createComponents: function () { |
| var serviceComponents = App.StackServiceComponent.find(); |
| this.get('selectedServices').forEach(function (_service) { |
| var serviceName = _service.get('serviceName'); |
| var componentsData = serviceComponents.filterProperty('serviceName', serviceName).map(function (_component) { |
| return { "ServiceComponentInfo": { "component_name": _component.get('componentName') } }; |
| }); |
| |
| // Service must be specified in terms of a query for creating multiple components at the same time. |
| // See AMBARI-1018. |
| this.addRequestToCreateComponent(componentsData, serviceName); |
| }, this); |
| |
| if (this.get('isAddHost')) { |
| var allServiceComponents = []; |
| var services = App.Service.find().mapProperty('serviceName'); |
| services.forEach(function(_service){ |
| var _serviceComponents = App.Service.find(_service).get('serviceComponents'); |
| allServiceComponents = allServiceComponents.concat(_serviceComponents); |
| }, this); |
| this.get('content.slaveComponentHosts').forEach(function (component) { |
| if (component.componentName !== 'CLIENT' && !allServiceComponents.contains(component.componentName)) { |
| this.addRequestToCreateComponent( |
| [{"ServiceComponentInfo": {"component_name": component.componentName}}], |
| App.StackServiceComponent.find().findProperty('componentName', component.componentName).get('serviceName') |
| ); |
| } |
| }, this); |
| this.get('content.clients').forEach(function (component) { |
| if (!allServiceComponents.contains(component.component_name)) { |
| this.addRequestToCreateComponent( |
| [{"ServiceComponentInfo": {"component_name": component.component_name}}], |
| App.StackServiceComponent.find().findProperty('componentName', component.component_name).get('serviceName') |
| ); |
| } |
| }, this); |
| } |
| }, |
| |
| /** |
| * Add request to ajax queue to create service component |
| * @param componentsData |
| * @param serviceName |
| */ |
| addRequestToCreateComponent: function (componentsData, serviceName) { |
| this.addRequestToAjaxQueue({ |
| name: 'wizard.step8.create_components', |
| data: { |
| data: JSON.stringify(componentsData), |
| serviceName: serviceName |
| } |
| }); |
| }, |
| |
| /** |
| * Error callback for new service component request |
| * So, if component doesn't exist we should create it |
| * @param {object} request |
| * @param {object} ajaxOptions |
| * @param {string} error |
| * @param {object} opt |
| * @param {object} params |
| * @method newServiceComponentErrorCallback |
| */ |
| newServiceComponentErrorCallback: function (request, ajaxOptions, error, opt, params) { |
| this.addRequestToAjaxQueue({ |
| name: 'wizard.step8.create_components', |
| data: { |
| serviceName: params.serviceName, |
| data: JSON.stringify({ |
| "components": [ |
| { |
| "ServiceComponentInfo": { |
| "component_name": params.componentName |
| } |
| } |
| ] |
| }) |
| } |
| }); |
| }, |
| |
| /** |
| * Register hosts |
| * Queued request |
| * @method registerHostsToCluster |
| */ |
| registerHostsToCluster: function () { |
| var data = this.createRegisterHostData(); |
| if (!data.length) return; |
| this.addRequestToAjaxQueue({ |
| name: 'wizard.step8.register_host_to_cluster', |
| data: { |
| data: JSON.stringify(data) |
| } |
| }); |
| }, |
| |
| /** |
| * Format request-data for <code>registerHostsToCluster</code> |
| * @returns {Object} |
| * @method createRegisterHostData |
| */ |
| createRegisterHostData: function () { |
| return this.getRegisteredHosts().filterProperty('isInstalled', false).map(function (host) { |
| return {"Hosts": { "host_name": host.hostName}}; |
| }); |
| }, |
| |
| /** |
| * Register new master components |
| * @uses registerHostsToComponent |
| * @method createMasterHostComponents |
| */ |
| createMasterHostComponents: function () { |
| var masterOnAllHosts = []; |
| |
| this.get('content.services').filterProperty('isSelected').forEach(function (service) { |
| service.get('serviceComponents').filterProperty('isRequiredOnAllHosts').forEach(function (component) { |
| if (component.get('isMaster')) { |
| masterOnAllHosts.push(component.get('componentName')); |
| } |
| }, this); |
| }, this); |
| |
| // create master components for only selected services. |
| var selectedMasterComponents = this.get('content.masterComponentHosts').filter(function (_component) { |
| return this.get('selectedServices').mapProperty('serviceName').contains(_component.serviceId) |
| }, this); |
| selectedMasterComponents.mapProperty('component').uniq().forEach(function (component) { |
| var hostNames = []; |
| if (masterOnAllHosts.length > 0) { |
| var compOnAllHosts = false; |
| for (var i=0; i < masterOnAllHosts.length; i++) { |
| if (component === masterOnAllHosts[i]) { |
| compOnAllHosts = true; |
| break; |
| } |
| } |
| if (!compOnAllHosts) { |
| hostNames = selectedMasterComponents.filterProperty('component', component).filterProperty('isInstalled', false).mapProperty('hostName'); |
| this.registerHostsToComponent(hostNames, component); |
| } |
| } else { |
| hostNames = selectedMasterComponents.filterProperty('component', component).filterProperty('isInstalled', false).mapProperty('hostName'); |
| this.registerHostsToComponent(hostNames, component); |
| } |
| }, this); |
| }, |
| |
| getClientsMap: function (flag) { |
| var clients = App.StackServiceComponent.find().filterProperty('isClient'), |
| clientsMap = {}, |
| dependedComponents = flag ? App.StackServiceComponent.find().filterProperty(flag) : App.StackServiceComponent.find(); |
| clients.forEach(function (client) { |
| var clientName = client.get('componentName'); |
| clientsMap[clientName] = Em.A([]); |
| dependedComponents.forEach(function (component) { |
| if (component.dependsOn(client)) |
| clientsMap[clientName].push(component.get('componentName')); |
| }); |
| if (!clientsMap[clientName].length) delete clientsMap[clientName]; |
| }); |
| return clientsMap; |
| }, |
| |
| /** |
| * Register slave components and clients |
| * @uses registerHostsToComponent |
| * @method createSlaveAndClientsHostComponents |
| */ |
| createSlaveAndClientsHostComponents: function () { |
| var masterHosts = this.get('content.masterComponentHosts'); |
| var slaveHosts = this.get('content.slaveComponentHosts'); |
| var clients = this.get('content.clients').filterProperty('isInstalled', false); |
| var slaveOnAllHosts = []; |
| var clientOnAllHosts = []; |
| |
| this.get('content.services').filterProperty('isSelected').forEach(function (service) { |
| service.get('serviceComponents').filterProperty('isRequiredOnAllHosts').forEach(function (component) { |
| if (component.get('isClient')) { |
| clientOnAllHosts.push(component.get('componentName')); |
| } else if (component.get('isSlave')) { |
| slaveOnAllHosts.push(component.get('componentName')); |
| } |
| }, this); |
| }, this); |
| |
| /** |
| * Determines on which hosts client should be installed (based on availability of master components on hosts) |
| * @type {Object} |
| * Format: |
| * <code> |
| * { |
| * CLIENT1: Em.A([MASTER1, MASTER2, ...]), |
| * CLIENT2: Em.A([MASTER3, MASTER1, ...]) |
| * ... |
| * } |
| * </code> |
| */ |
| var clientsToMasterMap = this.getClientsMap('isMaster'), |
| clientsToSlaveMap = this.getClientsMap('isSlave'); |
| |
| slaveHosts.forEach(function (_slave) { |
| var hostNames = []; |
| var compOnAllHosts; |
| if (_slave.componentName !== 'CLIENT') { |
| if (slaveOnAllHosts.length > 0) { |
| compOnAllHosts = false; |
| for (var i=0; i < slaveOnAllHosts.length; i++) { |
| if (_slave.componentName === slaveOnAllHosts[i]) { |
| // component with ALL cardinality should not |
| // registerHostsToComponent in createSlaveAndClientsHostComponents |
| compOnAllHosts = true; |
| break; |
| } |
| } |
| if (!compOnAllHosts) { |
| hostNames = _slave.hosts.filterProperty('isInstalled', false).mapProperty('hostName'); |
| this.registerHostsToComponent(hostNames, _slave.componentName); |
| } |
| } else { |
| hostNames = _slave.hosts.filterProperty('isInstalled', false).mapProperty('hostName'); |
| this.registerHostsToComponent(hostNames, _slave.componentName); |
| } |
| } |
| else { |
| clients.forEach(function (_client) { |
| hostNames = _slave.hosts.mapProperty('hostName'); |
| // The below logic to install clients to existing/New master hosts should not be applied to Add Host wizard. |
| // This is with the presumption that Add Host controller does not add any new Master component to the cluster |
| if (!this.get('isAddHost')) { |
| if (clientsToMasterMap[_client.component_name]) { |
| clientsToMasterMap[_client.component_name].forEach(function (componentName) { |
| masterHosts.filterProperty('component', componentName).forEach(function (_masterHost) { |
| hostNames.pushObject(_masterHost.hostName); |
| }); |
| }); |
| } |
| } |
| if (clientsToSlaveMap[_client.component_name]) { |
| clientsToSlaveMap[_client.component_name].forEach(function (componentName) { |
| slaveHosts.filterProperty('componentName', componentName).forEach(function (slaveHost) { |
| hostNames = hostNames.concat(slaveHost.hosts.mapProperty('hostName')).uniq(); |
| }); |
| }); |
| } |
| if (clientOnAllHosts.length > 0) { |
| compOnAllHosts = false; |
| for (var i=0; i < clientOnAllHosts.length; i++) { |
| if (_client.component_name === clientOnAllHosts[i]) { |
| // component with ALL cardinality should not |
| // registerHostsToComponent in createSlaveAndClientsHostComponents |
| compOnAllHosts = true; |
| break; |
| } |
| } |
| if (!compOnAllHosts) { |
| hostNames = hostNames.uniq(); |
| this.registerHostsToComponent(hostNames, _client.component_name); |
| } |
| } else { |
| hostNames = hostNames.uniq(); |
| this.registerHostsToComponent(hostNames, _client.component_name); |
| } |
| }, this); |
| } |
| }, this); |
| }, |
| |
| /** |
| * This function is specific to addServiceController |
| * Newly introduced master components requires some existing client components to be hosted along with them |
| */ |
| createAdditionalClientComponents: function () { |
| var masterHosts = this.get('content.masterComponentHosts'); |
| var clientHosts = []; |
| if (this.get('content.slaveComponentHosts').someProperty('componentName', 'CLIENT')) { |
| clientHosts = this.get('content.slaveComponentHosts').findProperty('componentName', 'CLIENT').hosts; |
| } |
| var clients = this.get('content.clients').filterProperty('isInstalled', false); |
| var clientsToMasterMap = this.getClientsMap('isMaster'); |
| var clientsToClientMap = this.getClientsMap('isClient'); |
| var installedClients = []; |
| |
| // Get all the installed Client components |
| this.get('content.services').filterProperty('isInstalled').forEach(function (_service) { |
| var serviceClients = App.StackServiceComponent.find().filterProperty('serviceName', _service.get('serviceName')).filterProperty('isClient'); |
| serviceClients.forEach(function (client) { |
| installedClients.push(client.get('componentName')); |
| }, this); |
| }, this); |
| |
| // Check if there is a dependency for being co-hosted between existing client and selected new master |
| installedClients.forEach(function (_clientName) { |
| if (clientsToMasterMap[_clientName] || clientsToClientMap[_clientName]) { |
| var hostNames = []; |
| if (clientsToMasterMap[_clientName]) { |
| clientsToMasterMap[_clientName].forEach(function (componentName) { |
| masterHosts.filterProperty('component', componentName).filterProperty('isInstalled', false).forEach(function (_masterHost) { |
| hostNames.pushObject(_masterHost.hostName); |
| }, this); |
| }, this); |
| } |
| if (clientsToClientMap[_clientName]) { |
| clientsToClientMap[_clientName].forEach(function (componentName) { |
| clientHosts.forEach(function (_clientHost) { |
| var host = this.get('content.hosts')[_clientHost.hostName]; |
| var isClientSelected = clients.someProperty('component_name', componentName); |
| if (host.isInstalled && isClientSelected && !host.hostComponents.someProperty('HostRoles.component_name', componentName)) { |
| hostNames.pushObject(_clientHost.hostName); |
| } |
| }, this); |
| }, this); |
| } |
| hostNames = hostNames.uniq(); |
| if (hostNames.length > 0) { |
| // If a dependency for being co-hosted is derived between existing client and selected new master but that |
| // dependency is already satisfied in the cluster then disregard the derived dependency |
| this.removeClientsFromList(_clientName, hostNames); |
| this.registerHostsToComponent(hostNames, _clientName); |
| if(hostNames.length > 0) { |
| this.get('content.additionalClients').pushObject({hostNames: hostNames, componentName: _clientName}); |
| } |
| } |
| } |
| }, this); |
| }, |
| |
| /** |
| * |
| * @param clientName |
| * @param hostList |
| */ |
| removeClientsFromList: function (clientName, hostList) { |
| var clientHosts = []; |
| var installedHosts = this.get('content.hosts'); |
| for (var hostName in installedHosts) { |
| if (installedHosts[hostName].isInstalled) { |
| if (installedHosts[hostName].hostComponents.mapProperty('HostRoles.component_name').contains(clientName)) { |
| clientHosts.push(hostName); |
| } |
| } |
| } |
| |
| if (clientHosts.length > 0) { |
| clientHosts.forEach(function (hostName) { |
| if (hostList.contains(hostName)) { |
| hostList.splice(hostList.indexOf(hostName), 1); |
| } |
| }, this); |
| } |
| }, |
| |
| /** |
| * Register additional components |
| * Based on availability of some services |
| * @uses registerHostsToComponent |
| * @method createAdditionalHostComponents |
| */ |
| createAdditionalHostComponents: function () { |
| var masterHosts = this.get('content.masterComponentHosts'); |
| |
| // add all components with cardinality == ALL of selected services |
| var registeredHosts = this.getRegisteredHosts(); |
| var notInstalledHosts = registeredHosts.filterProperty('isInstalled', false); |
| this.get('content.services').filterProperty('isSelected').forEach(function (service) { |
| service.get('serviceComponents').filterProperty('isRequiredOnAllHosts').forEach(function (component) { |
| if (service.get('isInstalled') && notInstalledHosts.length) { |
| this.registerHostsToComponent(notInstalledHosts.mapProperty('hostName'), component.get('componentName')); |
| } else if (!service.get('isInstalled') && registeredHosts.length) { |
| this.registerHostsToComponent(registeredHosts.mapProperty('hostName'), component.get('componentName')); |
| } |
| }, this); |
| }, this); |
| |
| // add MySQL Server if Hive is selected |
| var hiveService = this.get('content.services').filterProperty('isSelected', true).filterProperty('isInstalled', false).findProperty('serviceName', 'HIVE'); |
| if (hiveService) { |
| var hiveDb = this.get('content.serviceConfigProperties').findProperty('name', 'hive_database'); |
| if (hiveDb.value === "New MySQL Database") { |
| this.registerHostsToComponent(masterHosts.filterProperty('component', 'HIVE_SERVER').mapProperty('hostName'), 'MYSQL_SERVER'); |
| } else if (hiveDb.value === "New PostgreSQL Database") { |
| this.registerHostsToComponent(masterHosts.filterProperty('component', 'HIVE_SERVER').mapProperty('hostName'), 'POSTGRESQL_SERVER'); |
| } |
| } |
| }, |
| |
| /** |
| * Register component to hosts |
| * Queued request |
| * @param {String[]} hostNames |
| * @param {String} componentName |
| * @method registerHostsToComponent |
| */ |
| registerHostsToComponent: function (hostNames, componentName) { |
| if (!hostNames.length) return; |
| |
| var queryStr = ''; |
| hostNames.forEach(function (hostName) { |
| queryStr += 'Hosts/host_name=' + hostName + '|'; |
| }); |
| //slice off last symbol '|' |
| queryStr = queryStr.slice(0, -1); |
| |
| var data = { |
| "RequestInfo": { |
| "query": queryStr |
| }, |
| "Body": { |
| "host_components": [ |
| { |
| "HostRoles": { |
| "component_name": componentName |
| } |
| } |
| ] |
| } |
| }; |
| |
| this.addRequestToAjaxQueue({ |
| name: 'wizard.step8.register_host_to_component', |
| data: { |
| data: JSON.stringify(data) |
| } |
| }); |
| }, |
| |
| /** |
| * Configure cluster settings |
| */ |
| configureCluster: function () { |
| const clusterSettings = this.get('configs').filterProperty('filename', 'cluster-settings.xml'); |
| const data = []; |
| clusterSettings.forEach(setting => { |
| data.push({ |
| "ClusterSettingInfo": { |
| "cluster_setting_name": setting.name, |
| "cluster_setting_value": setting.value |
| } |
| }) |
| }); |
| |
| this.addRequestToAjaxQueue({ |
| name: 'common.cluster.settings', |
| data: { |
| clusterName: this.get('clusterName'), |
| data: data |
| } |
| }); |
| }, |
| |
| /** |
| * Create config objects for services |
| * @method createServiceConfigurations |
| */ |
| createServiceConfigurations: function () { |
| this.get('selectedServices').forEach(function (service) { |
| Object.keys(service.get('configTypes')).forEach(function (type) { |
| if (!this.get('serviceConfigTags').someProperty('type', type)) { |
| var configs = this.get('configs').filterProperty('filename', App.config.getOriginalFileName(type)); |
| var serviceConfigNote = this.getServiceConfigNote(type, service.get('displayName')); |
| this.get('serviceConfigTags').pushObject(this.createDesiredConfig(type, configs, serviceConfigNote)); |
| } |
| }, this); |
| }, this); |
| this.createNotification(); |
| }, |
| |
| /** |
| * Get config version message |
| * |
| * @param type |
| * @param serviceDisplayName |
| * @returns {*} |
| */ |
| getServiceConfigNote: function(type, serviceDisplayName) { |
| return this.get('isAddService') && type === 'core-site' ? |
| Em.I18n.t('dashboard.configHistory.table.notes.addService') : Em.I18n.t('dashboard.configHistory.table.notes.default').format(serviceDisplayName); |
| }, |
| |
| /** |
| * Send <code>serviceConfigTags</code> to server |
| * Queued request |
| * One request for each service config tag |
| * @param serviceConfigTags |
| * @method applyConfigurationsToCluster |
| */ |
| applyConfigurationsToCluster: function (serviceConfigTags) { |
| var allServices = this.get('installedServices').concat(this.get('selectedServices')); |
| var allConfigData = []; |
| allServices.forEach(function (service) { |
| var serviceConfigData = []; |
| Object.keys(service.get('configTypesRendered')).forEach(function (type) { |
| var serviceConfigTag = serviceConfigTags.findProperty('type', type); |
| if (serviceConfigTag) { |
| serviceConfigData.pushObject(serviceConfigTag); |
| } |
| }, this); |
| if (serviceConfigData.length) { |
| allConfigData.pushObject(JSON.stringify({ |
| Clusters: { |
| desired_config: serviceConfigData.map(function(item) { |
| var props = {}; |
| Em.keys(item.properties).forEach(function(propName) { |
| if (item.properties[propName] !== null) { |
| props[propName] = item.properties[propName]; |
| } |
| }); |
| item.properties = props; |
| return item; |
| }) |
| } |
| })); |
| } |
| }, this); |
| |
| this.addRequestToAjaxQueue({ |
| name: 'common.across.services.configurations', |
| data: { |
| data: '[' + allConfigData.toString() + ']' |
| } |
| }); |
| }, |
| |
| /** |
| * Create and update config groups |
| * @method createConfigurationGroups |
| */ |
| createConfigurationGroups: function () { |
| var configGroups = this.get('content.configGroups').filterProperty('is_default', false); |
| var groupsToDelete = App.router.get(this.get('content.controllerName')).getDBProperty('groupsToDelete'); |
| if (groupsToDelete && groupsToDelete.length > 0) { |
| this.removeInstalledServicesConfigurationGroups(groupsToDelete); |
| } |
| configGroups.forEach(function (configGroup) { |
| if (configGroup.is_for_update || configGroup.is_temporary) { |
| this.saveGroup(configGroup.properties, configGroup, this.getServiceConfigNote('', configGroup.service_id)); |
| } |
| }, this); |
| App.ServiceConfigGroup.deleteTemporaryRecords(); |
| }, |
| |
| /** |
| * add request to create config group to queue |
| * |
| * @param data |
| * @method createConfigGroup |
| */ |
| createConfigGroup: function(data) { |
| this.addRequestToAjaxQueue({ |
| name: 'wizard.step8.apply_configuration_groups', |
| sender: this, |
| data: { |
| data: JSON.stringify(data) |
| } |
| }); |
| }, |
| |
| /** |
| * add request to update config group to queue |
| * |
| * @param data {Object} |
| * @method updateConfigGroup |
| */ |
| updateConfigGroup: function (data) { |
| this.addRequestToAjaxQueue({ |
| name: 'config_groups.update_config_group', |
| sender: this, |
| data: { |
| id: data.ConfigGroup.id, |
| configGroup: data |
| } |
| }); |
| }, |
| |
| /** |
| * Delete selected config groups |
| * @param {Object[]} groupsToDelete |
| * @method removeInstalledServicesConfigurationGroups |
| */ |
| removeInstalledServicesConfigurationGroups: function (groupsToDelete) { |
| var self = this; |
| groupsToDelete.forEach(function (item) { |
| self.deleteConfigurationGroup(Em.Object.create(item)); |
| }); |
| }, |
| |
| /** |
| * Selected and installed services |
| * @override |
| */ |
| currentServices: function() { |
| return this.get('installedServices').concat(this.get('selectedServices')); |
| }.property('installedServices.length', 'selectedServices.length'), |
| |
| /** |
| * Add handling GLUSTREFS properties |
| * @param property |
| * @returns {*} |
| * @override |
| */ |
| formatValueBeforeSave: function(property) { |
| if (this.formatGLUSTERFSProperties(Em.get(property, 'filename'))) { |
| switch (property.name) { |
| case "fs.default.name": |
| return this.get('configs').someProperty('name', 'fs_glusterfs_default_name') ? |
| this.get('configs').findProperty('name', 'fs_glusterfs_default_name').value : null; |
| case "fs.defaultFS": |
| return this.get('configs').someProperty('name', 'glusterfs_defaultFS_name') ? |
| this.get('configs').findProperty('name', 'glusterfs_defaultFS_name').value : null; |
| } |
| } |
| return this._super(property); |
| }, |
| |
| /** |
| * Defines if some GLUSTERFS properties should be changed |
| * |
| * @param {String} type |
| * @returns {boolean} |
| */ |
| formatGLUSTERFSProperties: function(type) { |
| return App.config.getConfigTagFromFileName(type) === 'core-site' |
| && this.get('installedServices').concat(this.get('selectedServices')).someProperty('serviceName', 'GLUSTERFS'); |
| }, |
| |
| |
| /** |
| * Create one Alert Notification (if user select this on step7) |
| * Only for Install Wizard and stack |
| * @method createNotification |
| */ |
| createNotification: function () { |
| if (!this.get('isInstaller')) return; |
| var miscConfigs = this.get('configs').filterProperty('serviceName', 'MISC'), |
| createNotification = miscConfigs.findProperty('name', 'create_notification').value; |
| if (createNotification !== 'yes') return; |
| var predefinedNotificationConfigNames = require('data/configs/alert_notification').mapProperty('name'), |
| configsForNotification = this.get('configs').filterProperty('filename', 'alert_notification'); |
| var properties = {}, |
| names = [ |
| 'ambari.dispatch.recipients', |
| 'mail.smtp.host', |
| 'mail.smtp.port', |
| 'mail.smtp.from', |
| 'mail.smtp.starttls.enable', |
| 'mail.smtp.startssl.enable' |
| ]; |
| if (miscConfigs.findProperty('name', 'smtp_use_auth').value == 'true') { // yes, it's not converted to boolean |
| names.pushObjects(['ambari.dispatch.credential.username', 'ambari.dispatch.credential.password']); |
| } |
| |
| names.forEach(function (name) { |
| properties[name] = miscConfigs.findProperty('name', name).value; |
| }); |
| |
| properties['ambari.dispatch.recipients'] = properties['ambari.dispatch.recipients'].replace(/\s/g, '').split(','); |
| |
| configsForNotification.forEach(function (config) { |
| if (predefinedNotificationConfigNames.contains(config.name)) return; |
| properties[config.name] = config.value; |
| }); |
| |
| var apiObject = { |
| AlertTarget: { |
| name: 'Initial Notification', |
| description: 'Notification created during cluster installing', |
| global: true, |
| notification_type: 'EMAIL', |
| alert_states: ['OK', 'WARNING', 'CRITICAL', 'UNKNOWN'], |
| properties: properties |
| } |
| }; |
| this.addRequestToAjaxQueue({ |
| name: 'alerts.create_alert_notification', |
| data: { |
| urlParams: 'overwrite_existing=true', |
| data: apiObject |
| } |
| }); |
| }, |
| |
| /** |
| * Should ajax-queue progress bar be displayed |
| * @method showLoadingIndicator |
| */ |
| showLoadingIndicator: function () { |
| return App.ModalPopup.show({ |
| |
| header: '', |
| |
| showFooter: false, |
| |
| showCloseButton: false, |
| |
| bodyClass: Em.View.extend({ |
| |
| templateName: require('templates/wizard/step8/step8_log_popup'), |
| |
| controllerBinding: 'App.router.wizardStep8Controller', |
| |
| /** |
| * Css-property for progress-bar |
| * @type {string} |
| */ |
| barWidth: '', |
| progressBarClass: 'progress log_popup', |
| |
| /** |
| * Popup-message |
| * @type {string} |
| */ |
| message: '', |
| |
| /** |
| * Set progress bar width and popup message when ajax-queue requests are processed |
| * @method ajaxQueueChangeObs |
| */ |
| ajaxQueueChangeObs: function () { |
| var length = this.get('controller.ajaxQueueLength'); |
| var left = this.get('controller.ajaxRequestsQueue.queue.length'); |
| this.set('barWidth', 'width: ' + (length - left) / length * 100 + '%;'); |
| this.set('message', Em.I18n.t('installer.step8.deployPopup.message').format(length - left, length)); |
| }.observes('controller.ajaxQueueLength', 'controller.ajaxRequestsQueue.queue.length'), |
| |
| /** |
| * Hide popup when ajax-queue is finished |
| * @method autoHide |
| */ |
| autoHide: function () { |
| if (this.get('controller.servicesInstalled')) { |
| this.get('parentView').hide(); |
| } |
| }.observes('controller.servicesInstalled'), |
| |
| ajaxQueueErrorAppears: function () { |
| if (this.get('controller.hasErrorOccurred')) { |
| this.get('parentView').onClose(); |
| } |
| }.observes('controller.hasErrorOccurred') |
| |
| }) |
| |
| }); |
| }, |
| |
| getComponentsForHost: function(host) { |
| if(!host.hostComponents) { |
| App.router.get('installerController').get('allHosts'); |
| } |
| var componentNameDetail = []; |
| host.hostComponents.mapProperty('componentName').forEach(function (componentName) { |
| if(componentName === 'CLIENT') { |
| this.get('content.clients').mapProperty('component_name').forEach(function (clientComponent) { |
| componentNameDetail.push({ name : clientComponent }); |
| }, this); |
| return; |
| } |
| componentNameDetail.push({ name : componentName }); |
| }, this); |
| return componentNameDetail; |
| }, |
| |
| getPropertyAttributesForConfigType : function(configs) { |
| //Currently only looks for final properties, if any |
| var finalProperties = configs.filterProperty('isFinal', 'true'); |
| var propertyAttributes = {}; |
| finalProperties.forEach(function (finalProperty) { |
| propertyAttributes[finalProperty['name']] = "true"; |
| }); |
| var finalPropertyMap = {}; |
| if (!App.isEmptyObject(finalProperties)) { |
| finalPropertyMap = { |
| "isFinal": propertyAttributes |
| }; |
| } |
| return finalPropertyMap; |
| }, |
| |
| getConfigurationDetailsForConfigType: function(configs) { |
| var configDetails = {}; |
| var self = this; |
| configs.forEach(function (propertyObj) { |
| configDetails[propertyObj['name']] = propertyObj['value']; |
| }, this); |
| var configurationsDetails = { |
| "properties_attributes": self.getPropertyAttributesForConfigType(configs), |
| "properties": configDetails |
| }; |
| return configurationsDetails; |
| }, |
| |
| hostInExistingHostGroup: function (newHost, host_groups) { |
| var hostGroupMatched = false; |
| host_groups.some(function (existingHostGroup) { |
| if(!hostGroupMatched) { |
| var fqdnInHostGroup = existingHostGroup.hosts[0].fqdn; |
| var componentsInExistingHostGroup = this.getRegisteredHosts().filterProperty('hostName', fqdnInHostGroup)[0].hostComponents; |
| if(componentsInExistingHostGroup.length !== newHost.hostComponents.length) { |
| return; |
| } else { |
| var componentMismatch = false; |
| componentsInExistingHostGroup.forEach(function (componentInExistingHostGroup, index) { |
| if(!componentMismatch) { |
| if(!newHost.hostComponents.mapProperty('componentName').includes(componentInExistingHostGroup.componentName)) { |
| componentMismatch = true; |
| } |
| } |
| }); |
| if(!componentMismatch) { |
| hostGroupMatched = true; |
| existingHostGroup["cardinality"] = parseInt(existingHostGroup["cardinality"]) + 1; |
| existingHostGroup.hosts.push({"fqdn" : newHost.hostName}); |
| return true; |
| } |
| } |
| } |
| }, this); |
| return hostGroupMatched; |
| }, |
| |
| hostInChildHostGroup: function (presentHostGroup, configGroupName, hostInConfigGroup) { |
| return presentHostGroup['childHostGroups'].some(function (childHostGroup) { |
| //Check if childHostGroup name is same as this configgroupname, if yes, update childHostGroup else, compare with other childhostgroups |
| if(childHostGroup.configGroupName === configGroupName) { |
| childHostGroup.hosts.push( { "fqdn" : hostInConfigGroup } ); |
| childHostGroup['cardinality'] = childHostGroup['cardinality'] + 1; |
| return true; |
| } |
| }); |
| }, |
| |
| /** |
| * Confirmation popup before generate blueprint |
| */ |
| generateBlueprintConfirmation: function () { |
| var self = this; |
| return App.showConfirmationPopup(function () { |
| self.generateBlueprint(); |
| }, Em.I18n.t('installer.step8.generateBlueprint.popup.msg').format(App.clusterStatus.clusterName) |
| ); |
| }, |
| |
| generateBlueprint: function () { |
| console.log("Prepare blueprint for download..."); |
| var blueprint = {}; |
| var self = this; |
| //service configurations |
| var totalConf = []; |
| //Add cluster-env |
| var clusterEnv = this.get('configs').filterProperty('filename', 'cluster-settings.xml'); |
| var configurations = {}; |
| configurations["cluster-env"] = self.getConfigurationDetailsForConfigType(clusterEnv); |
| totalConf.push(configurations); |
| //Add configurations for selected services |
| this.get('selectedServices').forEach(function (service) { |
| Object.keys(service.get('configTypes')).forEach(function (type) { |
| if (!this.get('serviceConfigTags').someProperty('type', type)) { |
| var configs = this.get('configs').filterProperty('filename', App.config.getOriginalFileName(type)); |
| var configurations = {}; |
| configurations[type] = self.getConfigurationDetailsForConfigType(configs); |
| totalConf.push(configurations); |
| } |
| }, this); |
| }, this); |
| |
| var host_groups = []; |
| var cluster_template_host_groups = []; |
| var counter = 0; |
| |
| this.getRegisteredHosts().filterProperty('isInstalled', false).map(function (host) { |
| if(self.hostInExistingHostGroup(host, host_groups)) { |
| return; |
| } |
| //Create new host_group if host is not mapped to existing host_groups |
| var hostGroupId = "host_group_" + counter; |
| var hostListForGroup = []; |
| hostListForGroup.push({ "fqdn": host.hostName }); |
| var hostGroupDetail = { |
| "name": hostGroupId, |
| "components": self.getComponentsForHost(host), |
| "hosts": hostListForGroup, |
| "cardinality" : 1 |
| }; |
| hostGroupDetail.toJSON = function () { |
| var hostGroupDetailResult = _.omit(this, [ "hosts", "childHostGroups" ]); |
| hostGroupDetailResult["cardinality"] = this["cardinality"].toString(); |
| return hostGroupDetailResult; |
| }; |
| host_groups.push(hostGroupDetail); |
| |
| var clusterTemplateHostGroupDetail = { |
| "name": hostGroupId, |
| "hosts": hostListForGroup |
| }; |
| |
| cluster_template_host_groups.push(clusterTemplateHostGroupDetail); |
| counter++; |
| }, this); |
| |
| this.get('content.configGroups').filterProperty("is_default", false).forEach(function (configGroup) { |
| if (configGroup.properties.length == 0) { |
| return; |
| } |
| configGroup.hosts.forEach(function (hostInConfigGroup) { |
| return host_groups.some(function (presentHostGroup) { |
| return presentHostGroup.hosts.some(function (hostInPresentHostGroup, index) { |
| if (hostInConfigGroup !== hostInPresentHostGroup.fqdn) { |
| return; |
| } |
| //Check if childHostGroup already created |
| if (presentHostGroup['childHostGroups']) { |
| if (self.hostInChildHostGroup(presentHostGroup, configGroup.name, hostInConfigGroup)) { |
| // Update to remove parentHostGroup as all the hosts are added to childHostGroup/s |
| presentHostGroup.hosts.splice(index, 1); |
| presentHostGroup["cardinality"] = presentHostGroup['cardinality'] - 1; |
| return true; |
| } |
| } |
| //create configuration object |
| var hgConfigurations; |
| if(presentHostGroup.hosts.length === 1 && presentHostGroup["configurations"]) { |
| hgConfigurations = presentHostGroup["configurations"][0]; |
| } else if (presentHostGroup["configurations"]) { //Deep copy |
| hgConfigurations = jQuery.extend(true, {}, presentHostGroup["configurations"][0]); |
| } else { |
| hgConfigurations = {}; |
| } |
| configGroup.properties.forEach(function (hgProperties) { |
| var type = App.config.getConfigTagFromFileName(hgProperties.filename); |
| if (!hgConfigurations[type]) { |
| hgConfigurations[type] = { properties: {} }; |
| } |
| hgConfigurations[type]['properties'][hgProperties.name] = hgProperties.value; |
| }); |
| var totalHgConf = []; |
| totalHgConf.push(hgConfigurations); |
| //If only host in presentHostGroup then merge configuration and return |
| if (presentHostGroup.hosts.length === 1) { |
| //If host_group already has configuration, assigned from previously processed config_group |
| if(!presentHostGroup["configurations"]) { |
| presentHostGroup["configurations"] = totalHgConf; |
| } |
| return true; |
| } |
| |
| //Create new host_group from this host |
| var hostGroupId = "host_group_" + counter; |
| counter++; |
| var hostListForGroup = []; |
| hostListForGroup.push({ "fqdn": hostInPresentHostGroup.fqdn }); |
| var hostGroupDetail = { |
| "name": hostGroupId, |
| "components": presentHostGroup.components, |
| "cardinality": 1, |
| "hosts": hostListForGroup, |
| "configurations": totalHgConf, |
| "configGroupName": configGroup.name |
| }; |
| hostGroupDetail.toJSON = function () { |
| var hostGroupDetailResult = _.omit(this, [ "hosts", "configGroupName", "childHostGroups" ]); |
| hostGroupDetailResult["cardinality"] = this["cardinality"].toString(); |
| return hostGroupDetailResult; |
| }; |
| host_groups.push(hostGroupDetail); |
| //Update for clustertemplate file |
| var clusterTemplateHostGroupDetail = { |
| "name": hostGroupId, |
| "hosts": hostListForGroup |
| }; |
| cluster_template_host_groups.push(clusterTemplateHostGroupDetail); |
| //Add newly created host_group as child to existing host_group |
| if (!presentHostGroup['childHostGroups']) { |
| presentHostGroup['childHostGroups'] = []; |
| } |
| presentHostGroup['childHostGroups'].push(hostGroupDetail); |
| presentHostGroup.hosts.splice(index, 1); |
| presentHostGroup["cardinality"] = presentHostGroup['cardinality'] - 1; |
| //return true to indicate that host has been matched |
| return true; |
| }, this); |
| }, this); |
| }, this); |
| }, this); |
| |
| var selectedStack = this.getSelectedStack(); |
| blueprint = { |
| 'configurations': totalConf, |
| 'host_groups': host_groups.filter(function (item) { return item.cardinality > 0; }), |
| 'Blueprints': {'blueprint_name' : App.clusterStatus.clusterName, 'stack_name':selectedStack.get('stackName'), 'stack_version':selectedStack.get('stackVersion')} |
| }; |
| fileUtils.downloadTextFile(JSON.stringify(blueprint), 'json', 'blueprint.json') |
| |
| var cluster_template = { |
| "blueprint": App.clusterStatus.clusterName, |
| "config_recommendation_strategy" : "NEVER_APPLY", |
| "provision_action" : "INSTALL_AND_START", |
| "configurations": [], |
| "host_groups": cluster_template_host_groups.filter(function (item) { return item.hosts.length > 0; }), |
| "Clusters": {'cluster_name': App.clusterStatus.clusterName} |
| }; |
| fileUtils.downloadTextFile(JSON.stringify(cluster_template), 'json', 'clustertemplate.json') |
| }, |
| |
| downloadCSV: function() { |
| App.router.get('kerberosWizardStep5Controller').getCSVData(false); |
| } |
| }); |