/**
* 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');
require('controllers/wizard/slave_component_groups_controller');
var batchUtils = require('utils/batch_scheduled_requests');
var lazyLoading = require('utils/lazy_loading');
App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorMixin, {
name: 'mainServiceInfoConfigsController',
isHostsConfigsPage: false,
forceTransition: false,
isRecommendedLoaded: true,
dataIsLoaded: false,
stepConfigs: [], //contains all field properties that are viewed in this service
selectedService: null,
serviceConfigTags: null,
selectedConfigGroup: null,
configTypesInfo: {
items: [],
supportsFinal: []
},
requestInProgress: null,
selectedServiceConfigTypes: [],
selectedServiceSupportsFinal: [],
configGroups: [],
allConfigs: [],
uiConfigs: [],
customConfig: [],
isApplyingChanges: false,
saveConfigsFlag: true,
isCompareMode: false,
compareServiceVersion: null,
preSelectedConfigVersion: null,
// contain Service Config Property, when user proceed from Select Config Group dialog
overrideToAdd: null,
//version of default config group, configs of which currently applied
currentDefaultVersion: null,
//version selected to view
selectedVersion: null,
// file names of changed configs
modifiedFileNames: [],
// note passed on configs save
serviceConfigVersionNote: '',
versionLoaded: false,
// current cluster-env version
clusterEnvTagVersion: '',
isCurrentSelected: function () {
return App.ServiceConfigVersion.find(this.get('content.serviceName') + "_" + this.get('selectedVersion')).get('isCurrent');
}.property('selectedVersion', 'content.serviceName'),
serviceConfigs: function () {
return App.config.get('preDefinedServiceConfigs');
}.property('App.config.preDefinedServiceConfigs'),
customConfigs: function () {
return App.config.get('preDefinedCustomConfigs');
}.property('App.config.preDefinedCustomConfigs'),
configMapping: function () {
return App.config.get('configMapping');
}.property('App.config.configMapping'),
configs: function () {
return App.config.get('preDefinedSiteProperties');
}.property('App.config.preDefinedSiteProperties'),
secureConfigs: function () {
if (App.get('isHadoop2Stack')) {
return require('data/HDP2/secure_mapping');
} else {
return require('data/secure_mapping');
}
}.property('App.isHadoop2Stack'),
showConfigHistoryFeature: true,
/**
* Map, which contains relation between group and site
* to upload overridden properties
*/
loadedGroupToOverrideSiteToTagMap: {},
/**
* During page load time the cluster level site to tag
* mapping is stored here.
*
* Example:
* {
* 'hdfs-site': 'version1',
* 'core-site': 'version1'
* }
*/
loadedClusterSiteToTagMap: {},
/**
* Holds the actual base service-config server data uploaded.
* This is used by the host-override mechanism to update host
* specific values.
*/
savedSiteNameToServerServiceConfigDataMap: {},
isSubmitDisabled: function () {
return (!(this.get('stepConfigs').everyProperty('errorCount', 0)) || this.get('isApplyingChanges'));
}.property('stepConfigs.@each.errorCount', 'isApplyingChanges'),
isPropertiesChanged: function(){
return this.get('stepConfigs').someProperty('isPropertiesChanged', true);
}.property('stepConfigs.@each.isPropertiesChanged'),
slaveComponentGroups: null,
/**
* Filter text will be located here
*/
filter: '',
/**
* List of filters for config properties to populate filter combobox
*/
propertyFilters: [
{
attributeName: 'isOverridden',
attributeValue: true,
caption: 'common.combobox.dropdown.overridden'
},
{
attributeName: 'isFinal',
attributeValue: true,
caption: 'common.combobox.dropdown.final'
},
{
attributeName: 'hasCompareDiffs',
attributeValue: true,
caption: 'common.combobox.dropdown.changed',
dependentOn: 'isCompareMode'
},
{
attributeName: 'isValid',
attributeValue: false,
caption: 'common.combobox.dropdown.issues'
},
{
attributeName: 'warn',
attributeValue: true,
caption: 'common.combobox.dropdown.warnings'
}
],
/**
* List of heapsize properties not to be parsed
*/
heapsizeException: ['hadoop_heapsize', 'yarn_heapsize', 'nodemanager_heapsize', 'resourcemanager_heapsize', 'apptimelineserver_heapsize', 'jobhistory_heapsize'],
/**
* Regular expression for heapsize properties detection
*/
heapsizeRegExp: /_heapsize|_newsize|_maxnewsize|_permsize|_maxpermsize$/,
/**
* Dropdown menu items in filter combobox
*/
filterColumns: function () {
var filterColumns = [];
this.get('propertyFilters').forEach(function(filter) {
if (Em.isNone(filter.dependentOn) || this.get(filter.dependentOn)) {
filterColumns.push(Ember.Object.create({
attributeName: filter.attributeName,
attributeValue: filter.attributeValue,
name: this.t(filter.caption),
selected: filter.dependentOn ? this.get(filter.dependentOn) : false
}));
}
}, this);
return filterColumns;
}.property('propertyFilters', 'isCompareMode'),
/**
* indicate wtether service config version belongs to default config group
* @method isVersionDefault
* @param version
* @return {Boolean}
*/
isVersionDefault: function(version) {
return (App.ServiceConfigVersion.find(this.get('content.serviceName') + "_" + version).get('groupId') == -1);
},
/**
* register request to view to track his progress
* @param request
*/
trackRequest: function (request) {
this.set('requestInProgress', request);
},
/**
* clear and set properties to default value
*/
clearStep: function () {
if (this.get('requestInProgress') && this.get('requestInProgress').readyState !== 4) {
this.get('requestInProgress').abort();
this.set('requestInProgress', null);
}
this.set("isApplyingChanges", false);
this.set('modifiedFileNames', []);
this.set('isInit', true);
this.set('hash', null);
this.set('forceTransition', false);
this.set('dataIsLoaded', false);
this.set('versionLoaded', false);
this.set('filter', '');
this.get('filterColumns').setEach('selected', false);
this.get('stepConfigs').clear();
this.get('allConfigs').clear();
this.get('uiConfigs').clear();
this.get('customConfig').clear();
this.set('loadedGroupToOverrideSiteToTagMap', {});
this.set('serviceConfigVersionNote', '');
this.set('savedSiteNameToServerServiceConfigDataMap', {});
if (this.get('serviceConfigTags')) {
this.set('serviceConfigTags', null);
}
},
serviceConfigProperties: function () {
return App.db.getServiceConfigProperties();
}.property('content'),
/**
* "Finger-print" of the stepConfigs
. Filled after first configGroup selecting
* Used to determine if some changes were made (when user navigates away from this page)
* {String}
*/
hash: null,
/**
* Is this initial config group changing
* {Boolean}
*/
isInit: true,
restartHosts: Em.A(),
/**
* On load function
*/
loadStep: function () {
console.log("TRACE: Loading configure for service");
this.clearStep();
this.loadClusterEnvSite();
},
/**
* load all tag versions of cluster-env site
* @returns {$.ajax}
*/
loadClusterEnvSite: function () {
var self = this;
return App.ajax.send({
name: 'config.cluster_env_site',
sender: self,
success: 'loadClusterEnvSiteSuccess'
});
},
loadClusterEnvSiteSuccess: function (data) {
// find the latest tag version
var maxVersion = Math.max.apply(this, data.items.mapProperty('version'));
this.set('clusterEnvTagVersion', data.items.findProperty('version', maxVersion).tag);
this.loadServiceConfigs();
},
getHash: function () {
if (!this.get('stepConfigs')[0]) {
return null;
}
var hash = {};
this.get('stepConfigs')[0].configs.forEach(function (config) {
hash[config.get('name')] = {value: config.get('value'), overrides: [], isFinal: config.get('isFinal')};
if (!config.get('overrides')) return;
if (!config.get('overrides.length')) return;
config.get('overrides').forEach(function (override) {
hash[config.get('name')].overrides.push(override.get('value'));
});
});
return JSON.stringify(hash);
},
/**
* Loads service configurations
*/
loadServiceConfigs: function () {
var advancedConfigs = [];
var self = this;
var serviceName = this.get('content.serviceName');
var stackService = App.StackService.find().findProperty('serviceName', serviceName);
if (stackService) {
self.set('configTypesInfo', App.config.getConfigTypesInfoFromService(stackService));
}
this.trackRequest(App.config.loadAdvancedConfig(serviceName, function (properties, xhr) {
if (xhr.statusText === 'abort') return;
advancedConfigs.pushObjects(properties);
self.set('advancedConfigs', advancedConfigs);
self.trackRequest(App.config.loadClusterConfig(function(clusterProperties) {
self.get('advancedConfigs').pushObjects(clusterProperties);
self.trackRequest(self.loadServiceConfigVersions());
}));
}));
},
/**
* get service config versions of current service
*/
loadServiceConfigVersions: function () {
return App.ajax.send({
name: 'service.serviceConfigVersions.get',
data: {
serviceName: this.get('content.serviceName')
},
sender: this,
success: 'loadServiceConfigVersionsSuccess',
error: 'loadServiceConfigVersionsError'
})
},
/**
* load service config versions to model
* set currentDefaultVersion
* @param data
* @param opt
* @param params
*/
loadServiceConfigVersionsSuccess: function (data, opt, params) {
App.serviceConfigVersionsMapper.map(data);
this.set('currentDefaultVersion', data.items.filterProperty('group_id', -1).findProperty('is_current').service_config_version);
if (this.get('preSelectedConfigVersion')) {
this.loadSelectedVersion(this.get('preSelectedConfigVersion.version'));
} else {
this.loadSelectedVersion();
}
},
/**
* error callback of loadServiceConfigVersions()
* override defaultCallback
* @param request
* @param ajaxOptions
* @param error
* @param opt
* @param params
*/
loadServiceConfigVersionsError: Em.K,
/**
* get selected service config version
* In case selected version is undefined then take currentDefaultVersion
* @param version
* @param switchToGroup
*/
loadSelectedVersion: function (version, switchToGroup) {
var self = this;
this.set('versionLoaded', false);
version = version || this.get('currentDefaultVersion');
//version of non-default group require properties from current version of default group to correctly display page
var versions = (this.isVersionDefault(version)) ? [version] : [this.get('currentDefaultVersion'), version];
switchToGroup = (this.isVersionDefault(version) && !switchToGroup) ? this.get('configGroups').findProperty('isDefault') : switchToGroup;
if (self.get('dataIsLoaded') && switchToGroup) {
this.set('selectedConfigGroup', switchToGroup);
}
this.trackRequest(App.ajax.send({
name: 'service.serviceConfigVersions.get.multiple',
sender: this,
data: {
serviceName: this.get('content.serviceName'),
serviceConfigVersions: versions
},
success: 'loadSelectedVersionSuccess'
}).complete(function (xhr) {
if (xhr.statusText === 'abort') return;
if (self.get('dataIsLoaded')) {
self.onConfigGroupChange();
} else {
self.loadServiceTagsAndGroups();
}
}));
},
/**
* set cluster to site tag map
* @param data
* @param opt
* @param params
*/
loadSelectedVersionSuccess: function (data, opt, params) {
var serviceConfigsDef = this.get('serviceConfigs').findProperty('serviceName', this.get('content.serviceName'));
var siteToTagMap = {};
var configTypesRendered = Object.keys(serviceConfigsDef.get('configTypesRendered'));
var selectedVersion = params.serviceConfigVersions.length > 1 ? params.serviceConfigVersions[1] : params.serviceConfigVersions[0];
var configurations = [];
configTypesRendered.forEach(function (siteName) {
data.items.forEach(function (item) {
if (item.group_id == -1) {
configurations = item.configurations;
if (item.configurations.someProperty('type', siteName)) {
siteToTagMap[siteName] = item.configurations.findProperty('type', siteName).tag;
} else {
siteToTagMap[siteName] = 'version1';
}
} else {
//set config tags of non-default config group to load overrides from selected version
this.loadedGroupToOverrideSiteToTagMap[item.group_name] = {};
item.configurations.forEach(function (config) {
this.loadedGroupToOverrideSiteToTagMap[item.group_name][config.type] = config.tag;
}, this)
}
}, this)
}, this);
App.router.get('configurationController').saveToDB(configurations);
// add cluster-env tag
siteToTagMap['cluster-env'] = this.get('clusterEnvTagVersion');
this.loadedClusterSiteToTagMap = siteToTagMap;
this.set('selectedVersion', selectedVersion);
//reset map if selected current version of default group
if (this.get('isCurrentSelected') && selectedVersion === this.get('currentDefaultVersion')) {
this.loadedGroupToOverrideSiteToTagMap = {};
}
},
/**
* load config groups of service
*/
loadServiceTagsAndGroups: function () {
this.trackRequest(App.ajax.send({
name: 'config.tags_and_groups',
sender: this,
data: {
serviceName: this.get('content.serviceName'),
urlParams: "&config_groups/ConfigGroup/tag=" + this.get('content.serviceName')
},
success: 'loadServiceConfigsSuccess'
}));
},
loadServiceConfigsSuccess: function (data, opt, params) {
this.setConfigGroups(data, opt, params);
},
setConfigTags: function (data, opt, params) {
var serviceConfigsDef = this.get('serviceConfigs').findProperty('serviceName', this.get('content.serviceName'));
var siteToTagMap = {};
var configTypesRendered = Object.keys(serviceConfigsDef.get('configTypesRendered'));
configTypesRendered.forEach(function (siteName) {
if (data.Clusters.desired_configs[siteName]) {
siteToTagMap[siteName] = data.Clusters.desired_configs[siteName].tag;
} else {
siteToTagMap[siteName] = 'version1';
}
}, this);
this.loadedClusterSiteToTagMap = siteToTagMap;
},
setConfigGroups: function (data, opt, params) {
var serviceName = this.get('content.serviceName');
var displayName = this.get('content.displayName');
var selectedConfigGroup;
var defaultHosts = App.get('allHostNames');
//parse loaded config groups
var configGroups = [];
if (data && data.config_groups && data.config_groups.length) {
data.config_groups.forEach(function (item) {
item = item.ConfigGroup;
if (item.tag === this.get('content.serviceName')) {
var groupHosts = item.hosts.mapProperty('host_name');
var newConfigGroup = App.ConfigGroup.create({
id: item.id,
name: item.group_name,
description: item.description,
isDefault: false,
parentConfigGroup: null,
service: App.Service.find().findProperty('serviceName', item.tag),
hosts: groupHosts,
configSiteTags: []
});
for (var i = 0; i < groupHosts.length; i++) {
defaultHosts = defaultHosts.without(groupHosts[i]);
}
item.desired_configs.forEach(function (config) {
newConfigGroup.configSiteTags.push(App.ConfigSiteTag.create({
site: config.type,
tag: config.tag
}));
}, this);
// select default selected group for hosts page
if (!selectedConfigGroup && this.get('isHostsConfigsPage') && newConfigGroup.get('hosts').contains(this.get('host.hostName')) && this.get('content.serviceName') === item.tag) {
selectedConfigGroup = newConfigGroup;
}
configGroups.push(newConfigGroup);
}
}, this);
}
this.set('configGroups', configGroups);
var defaultConfigGroup = App.ConfigGroup.create({
name: displayName + " Default",
description: "Default cluster level " + serviceName + " configuration",
isDefault: true,
hosts: defaultHosts,
parentConfigGroup: null,
service: this.get('content'),
serviceName: serviceName,
configSiteTags: []
});
if (!selectedConfigGroup) {
selectedConfigGroup = configGroups.findProperty('name', this.get('preSelectedConfigVersion.groupName')) || defaultConfigGroup;
}
this.get('configGroups').sort(function (configGroupA, configGroupB) {
return (configGroupA.name > configGroupB.name);
});
this.get('configGroups').unshift(defaultConfigGroup);
this.set('selectedConfigGroup', selectedConfigGroup);
this.set('preSelectedConfigVersion', null);
},
onConfigGroupChange: function () {
var self = this;
this.get('stepConfigs').clear();
var selectedConfigGroup = this.get('selectedConfigGroup');
var serviceName = this.get('content.serviceName');
//STEP 1: handle tags from JSON data for host overrides
var configGroupsWithOverrides = selectedConfigGroup.get('isDefault') && !this.get('isHostsConfigsPage') ? this.get('configGroups') : [selectedConfigGroup];
configGroupsWithOverrides.forEach(function (item) {
var groupName = item.get('name');
if (Em.isNone(this.loadedGroupToOverrideSiteToTagMap[groupName])) {
this.loadedGroupToOverrideSiteToTagMap[groupName] = {};
item.get('configSiteTags').forEach(function (siteTag) {
var site = siteTag.get('site');
this.loadedGroupToOverrideSiteToTagMap[groupName][site] = siteTag.get('tag');
}, this);
}
}, this);
//STEP 2: Create an array of objects defining tag names to be polled and new tag names to be set after submit
this.setServiceConfigTags(this.loadedClusterSiteToTagMap);
//STEP 3: Load advanced configs
var advancedConfigs = this.get('advancedConfigs');
//STEP 4: Load on-site config by service from server
App.router.get('configurationController').getConfigsByTags(this.get('serviceConfigTags')).done(function(configGroups){
//Merge on-site configs with pre-defined
var configSet = App.config.mergePreDefinedWithLoaded(configGroups, advancedConfigs, self.get('serviceConfigTags'), serviceName);
configSet = App.config.syncOrderWithPredefined(configSet);
var configs = configSet.configs;
//add custom configs
App.config.addCustomConfigs(configs);
//put properties from capacity-scheduler.xml into one config with textarea view
if (self.get('content.serviceName') === 'YARN') {
configs = App.config.fileConfigsIntoTextarea(configs, 'capacity-scheduler.xml');
}
self.set('allConfigs', configs);
//add configs as names of host components
self.addHostNamesToConfig();
//load configs of version being compared against
self.loadCompareVersionConfigs(self.get('allConfigs')).done(function (isComparison) {
//Load and add overriden configs of group
if (!isComparison && (!self.get('selectedConfigGroup').get('isDefault') || self.get('isCurrentSelected'))) {
App.config.loadServiceConfigGroupOverrides(self.get('allConfigs'), self.get('loadedGroupToOverrideSiteToTagMap'), self.get('configGroups'), self.onLoadOverrides, self);
} else {
self.onLoadOverrides(self.get('allConfigs'));
}
});
});
}.observes('selectedConfigGroup'),
/**
* load version configs for comparison
* @param allConfigs
* @return {object}
*/
loadCompareVersionConfigs: function (allConfigs) {
var dfd = $.Deferred();
var self = this;
var compareServiceVersions = [];
if (this.get('compareServiceVersion')) {
if (!this.isVersionDefault(this.get('compareServiceVersion').get('version'))) {
compareServiceVersions = [this.get('compareServiceVersion').get('version'), this.get('selectedVersion')];
} else {
compareServiceVersions = [this.get('compareServiceVersion').get('version')];
}
this.getCompareVersionConfigs(compareServiceVersions).done(function (json) {
self.initCompareConfig(allConfigs, json);
self.set('compareServiceVersion', null);
self.set('isCompareMode', true);
dfd.resolve(true);
}).fail(function () {
self.set('compareServiceVersion', null);
dfd.resolve(true);
});
} else {
self.set('isCompareMode', false);
allConfigs.setEach('isComparison', false);
dfd.resolve(false);
}
return dfd.promise();
},
/**
* attach analogical config to each property for comparison
* @param allConfigs
* @param json
*/
initCompareConfig: function(allConfigs, json) {
var serviceVersionMap = {};
var configNamesMap = {};
var serviceName = this.get('content.serviceName');
var compareVersionNumber = this.get('compareServiceVersion').get('version');
//indicate whether compared versions are from non-default group
var compareNonDefaultVersions = (json.items.length > 1);
serviceVersionMap[compareVersionNumber] = {};
if (compareNonDefaultVersions) {
serviceVersionMap[this.get('selectedVersion')] = {};
}
allConfigs.mapProperty('name').forEach(function(name) {
configNamesMap[name] = true;
});
json.items.forEach(function (item) {
item.configurations.forEach(function (configuration) {
if (serviceName == 'YARN' && configuration.type == 'capacity-scheduler') {
// put all properties in a single textarea for capacity-scheduler
var value = '';
for (var prop in configuration.properties) {
value += prop + '=' + configuration.properties[prop] + '\n';
}
serviceVersionMap[item.service_config_version][configuration.type + '-' + configuration.type] = {
name: configuration.type,
value: value,
type: configuration.type,
tag: configuration.tag,
version: configuration.version,
service_config_version: item.service_config_version
};
} else {
for (var prop in configuration.properties) {
serviceVersionMap[item.service_config_version][prop + '-' + configuration.type] = {
name: prop,
value: configuration.properties[prop],
type: configuration.type,
tag: configuration.tag,
version: configuration.version,
service_config_version: item.service_config_version
};
if (Em.isNone(configNamesMap[prop])) {
allConfigs.push(this.getMockConfig(prop, serviceName, App.config.getOriginalFileName(configuration.type)));
}
}
}
if (configuration.properties_attributes && configuration.properties_attributes.final) {
for (var final in configuration.properties_attributes.final) {
serviceVersionMap[item.service_config_version][final + '-' + configuration.type].isFinal = (configuration.properties_attributes.final[final] === 'true');
}
}
}, this);
}, this);
if (compareNonDefaultVersions) {
allConfigs.forEach(function (serviceConfig) {
this.setCompareConfigs(serviceConfig, serviceVersionMap, compareVersionNumber, this.get('selectedVersion'));
}, this);
} else {
allConfigs.forEach(function (serviceConfig) {
var serviceCfgVersionMap = serviceVersionMap[this.get('compareServiceVersion').get('version')];
var compareConfig = serviceCfgVersionMap[serviceConfig.name + '-' + App.config.getConfigTagFromFileName(serviceConfig.filename)]
this.setCompareDefaultGroupConfig(serviceConfig, compareConfig);
}, this);
}
},
/**
* set compare properties to service config of non-default group
* @param serviceConfig
* @param serviceVersionMap
* @param compareVersion
* @param selectedVersion
*/
setCompareConfigs: function (serviceConfig, serviceVersionMap, compareVersion, selectedVersion) {
var compareConfig = serviceVersionMap[compareVersion][serviceConfig.name + '-' + App.config.getConfigTagFromFileName(serviceConfig.filename)];
var selectedConfig = serviceVersionMap[selectedVersion][serviceConfig.name + '-' + App.config.getConfigTagFromFileName(serviceConfig.filename)];
serviceConfig.compareConfigs = [];
serviceConfig.isComparison = true;
if (compareConfig && selectedConfig) {
serviceConfig.compareConfigs.push(this.getComparisonConfig(serviceConfig, compareConfig));
serviceConfig.compareConfigs.push(this.getComparisonConfig(serviceConfig, selectedConfig));
serviceConfig.hasCompareDiffs = this.hasCompareDiffs(serviceConfig.compareConfigs[0], serviceConfig.compareConfigs[1]);
} else if (compareConfig && !selectedConfig) {
serviceConfig.compareConfigs.push(this.getComparisonConfig(serviceConfig, compareConfig));
serviceConfig.compareConfigs.push(this.getMockComparisonConfig(selectedConfig, selectedVersion));
serviceConfig.hasCompareDiffs = true;
} else if (!compareConfig && selectedConfig) {
serviceConfig.compareConfigs.push(this.getMockComparisonConfig(selectedConfig, compareVersion));
serviceConfig.compareConfigs.push(this.getComparisonConfig(serviceConfig, selectedConfig));
serviceConfig.hasCompareDiffs = true;
}
},
/**
* init attributes and wrap mock compare config into App.ServiceConfigProperty
* @param serviceConfig
* @param compareConfig
* @return {object}
*/
getMockComparisonConfig: function (serviceConfig, compareServiceVersion) {
var compareObject = $.extend(true, {isComparison: true}, serviceConfig);
compareObject.isEditable = false;
compareObject.serviceVersion = App.ServiceConfigVersion.find(this.get('content.serviceName') + "_" + compareServiceVersion);
compareObject.isMock = true;
compareObject.displayType = 'label';
compareObject = App.ServiceConfigProperty.create(compareObject);
compareObject.set('value', Em.I18n.t('common.property.undefined'));
return compareObject;
},
/**
* init attributes and wrap compare config into App.ServiceConfigProperty
* @param serviceConfig
* @param compareConfig
* @return {object}
*/
getComparisonConfig: function (serviceConfig, compareConfig) {
var compareObject = $.extend(true, {isComparison: true}, serviceConfig);
compareObject.isEditable = false;
if (compareConfig) {
if (serviceConfig.isMock) {
compareObject.displayType = 'string';
compareObject.isMock = false;
}
compareObject.serviceVersion = App.ServiceConfigVersion.find(this.get('content.serviceName') + "_" + compareConfig.service_config_version);
compareObject = App.ServiceConfigProperty.create(compareObject);
compareObject.set('isFinal', compareConfig.isFinal);
compareObject.set('value', App.config.formatOverrideValue(serviceConfig, compareConfig.value));
this.setSupportsFinal(compareObject);
}
return compareObject;
},
/**
* set compare properties to service config of default group
* @param serviceConfig
* @param compareConfig
*/
setCompareDefaultGroupConfig: function (serviceConfig, compareConfig) {
var compareObject = {};
serviceConfig.compareConfigs = [];
serviceConfig.isComparison = true;
//if config isn't reconfigurable then it can't have changed value to compare
if (compareConfig && (serviceConfig.isReconfigurable || serviceConfig.isUserProperty)) {
compareObject = this.getComparisonConfig(serviceConfig, compareConfig);
serviceConfig.hasCompareDiffs = serviceConfig.isMock || this.hasCompareDiffs(serviceConfig, compareObject);
serviceConfig.compareConfigs.push(compareObject);
} else if (serviceConfig.isUserProperty) {
serviceConfig.compareConfigs.push(this.getMockComparisonConfig(serviceConfig, this.get('compareServiceVersion.version')));
serviceConfig.hasCompareDiffs = true;
}
return serviceConfig;
},
/**
* check value and final attribute of original and compare config for differencies
* @param originalConfig
* @param compareConfig
* @return {Boolean}
*/
hasCompareDiffs: function (originalConfig, compareConfig) {
return (originalConfig.value !== compareConfig.value) || (!!originalConfig.isFinal !== (compareConfig.isFinal == true));
},
/**
* generate mock config object
* @param name
* @param serviceName
* @param filename
* @return {Object}
*/
getMockConfig: function (name, serviceName, filename) {
var undefinedConfig = {
description: name,
displayName: name,
id: "site property",
isOverridable: false,
isReconfigurable: false,
isRequired: false,
isRequiredByAgent: false,
isSecureConfig: false,
isUserProperty: true,
isVisible: true,
name: name,
filename: filename,
serviceName: serviceName,
value: Em.I18n.t('common.property.undefined'),
isMock: true,
displayType: 'label'
};
var category = App.config.identifyCategory(undefinedConfig);
undefinedConfig.category = category && category.name;
return undefinedConfig;
},
/**
* get configs of chosen version from server to compare
* @param compareServiceVersions
* @return {$.ajax}
*/
getCompareVersionConfigs: function (compareServiceVersions) {
this.set('versionLoaded', false);
return App.ajax.send({
name: 'service.serviceConfigVersions.get.multiple',
sender: this,
data: {
serviceName: this.get('content.serviceName'),
serviceConfigVersions: compareServiceVersions
}
});
},
checkDatabaseProperties: function (serviceConfig) {
this.hideSinkDatabaseProperties(serviceConfig.configs);
this.hideHiveDatabaseProperties(serviceConfig.configs);
this.hideOozieDatabaseProperties(serviceConfig.configs);
},
hideSinkDatabaseProperties: function (configs) {
if (!['HDFS'].contains(this.get('content.serviceName'))) return;
var property = configs.findProperty('name', 'sink.dbservername');
if (property) property.set('isVisible', false);
var hadoop_user_property = configs.findProperty('name', 'hadoop.user.name');
if(hadoop_user_property)
{
hadoop_user_property.setProperties({
isVisible: false,
isRequired: false
});
}
var hadoop_password_property = configs.findProperty('name', 'hadoop.user.password');
if(hadoop_password_property)
{
hadoop_password_property.setProperties({
isVisible: false,
isRequired: false
});
}
if (configs.someProperty('name', 'sink_database')) {
var sinkDb = configs.findProperty('name', 'sink_database');
if (sinkDb.value === 'Existing MSSQL Server database with integrated authentication') {
configs.findProperty('name', 'sink.dblogin').setProperties({
isVisible: false,
isRequired: false
});
configs.findProperty('name', 'sink.dbpassword').setProperties({
isVisible: false,
isRequired: false
});
}
}
},
hideHiveDatabaseProperties: function (configs) {
if (!['HIVE'].contains(this.get('content.serviceName'))) return;
var property = configs.findProperty('name', 'hive_hostname');
if (property) property.set('isVisible', false);
if (configs.someProperty('name', 'hive_database')) {
var hiveDb = configs.findProperty('name', 'hive_database');
if (hiveDb.value === 'Existing MSSQL Server database with integrated authentication') {
configs.findProperty('name', 'javax.jdo.option.ConnectionUserName').setProperties({
isVisible: false,
isRequired: false
});
configs.findProperty('name', 'javax.jdo.option.ConnectionPassword').setProperties({
isVisible: false,
isRequired: false
});
}
}
},
hideOozieDatabaseProperties: function (configs) {
if (!['OOZIE'].contains(this.get('content.serviceName'))) return;
var property = configs.findProperty('name', 'oozie_hostname');
if (property) property.set('isVisible', false);
if (configs.someProperty('name', 'oozie_database')) {
var oozieDb = configs.findProperty('name', 'oozie_database');
if (oozieDb.value === 'Existing MSSQL Server database with integrated authentication') {
configs.findProperty('name', 'oozie.service.JPAService.jdbc.username').setProperties({
isVisible: false,
isRequired: false
});
configs.findProperty('name', 'oozie.service.JPAService.jdbc.password').setProperties({
isVisible: false,
isRequired: false
});
}
}
},
onLoadOverrides: function (allConfigs) {
var serviceName = this.get('content.serviceName');
var advancedConfigs = this.get('advancedConfigs');
//STEP 10: creation of serviceConfig object which contains configs for current service
var serviceConfig = App.config.createServiceConfig(serviceName);
//STEP11: Make SecondaryNameNode invisible on enabling namenode HA
if (serviceConfig.get('serviceName') === 'HDFS') {
App.config.OnNnHAHideSnn(serviceConfig);
}
serviceConfig = App.config.createServiceConfig(this.get('content.serviceName'));
this.loadConfigs(this.get('allConfigs'), serviceConfig);
this.checkOverrideProperty(serviceConfig);
this.checkDatabaseProperties(serviceConfig);
this.get('stepConfigs').pushObject(serviceConfig);
this.set('selectedService', this.get('stepConfigs').objectAt(0));
this.checkForSecureConfig(this.get('selectedService'));
this.set('dataIsLoaded', true);
this.set('versionLoaded', true);
this.set('hash', this.getHash());
this.set('isInit', false);
},
/**
* Changes format from Object to Array
*
* {
* 'core-site': 'version1',
* 'hdfs-site': 'version1',
* ...
* }
*
* to
*
* [
* {
* siteName: 'core-site',
* tagName: 'version1',
* newTageName: null
* },
* ...
* ]
*
* set tagnames for configuration of the *-site.xml
*/
setServiceConfigTags: function (desiredConfigsSiteTags) {
console.debug("setServiceConfigTags(): Trying to set ", desiredConfigsSiteTags);
var newServiceConfigTags = [];
for (var index in desiredConfigsSiteTags) {
newServiceConfigTags.pushObject({
siteName: index,
tagName: desiredConfigsSiteTags[index],
newTagName: null
}, this);
}
console.debug("setServiceConfigTags(): Setting 'serviceConfigTags' to ", newServiceConfigTags);
this.set('serviceConfigTags', newServiceConfigTags);
},
/**
* check whether the config property is a security related knob
* @param serviceConfig
*/
checkForSecureConfig: function (serviceConfig) {
serviceConfig.get('configs').forEach(function (_config) {
this.get('secureConfigs').forEach(function (_secureConfig) {
if (_config.get('name') === _secureConfig.name) {
_config.set('isSecureConfig', true);
}
}, this)
}, this)
},
/**
* Load child components to service config object
* @param {Array} configs - array of configs
* @param {Object} componentConfig - component config object
* @method loadConfigs
*/
loadConfigs: function (configs, componentConfig) {
var serviceConfigsData = App.StackService.find().findProperty('serviceName', this.get('content.serviceName'));
var defaultGroupSelected = this.get('selectedConfigGroup.isDefault');
configs.forEach(function (_serviceConfigProperty) {
var serviceConfigProperty = this.createConfigProperty(_serviceConfigProperty, defaultGroupSelected, serviceConfigsData);
componentConfig.configs.pushObject(serviceConfigProperty);
serviceConfigProperty.validate();
}, this);
componentConfig.set('initConfigsLength', componentConfig.get('configs.length'));
},
/**
* create {Em.Object} service_cfg_property based on {Object}_serviceConfigProperty and additional info
* @param {Object} _serviceConfigProperty - config object
* @param {Boolean} defaultGroupSelected - true if selected cfg group is default
* @param {Object} serviceConfigsData - service cfg object
* @returns {Ember.Object|null}
* @method createConfigProperty
*/
createConfigProperty: function (_serviceConfigProperty, defaultGroupSelected, serviceConfigsData) {
if (!_serviceConfigProperty) return null;
var overrides = _serviceConfigProperty.overrides;
// we will populate the override properties below
Em.set(_serviceConfigProperty, 'overrides', null);
_serviceConfigProperty.isOverridable = Em.isNone(_serviceConfigProperty.isOverridable) ? true : _serviceConfigProperty.isOverridable;
var serviceConfigProperty = App.ServiceConfigProperty.create(_serviceConfigProperty);
this.setValueForCheckBox(serviceConfigProperty);
this.setSupportsFinal(serviceConfigProperty);
this.setValuesForOverrides(overrides, _serviceConfigProperty, serviceConfigProperty, defaultGroupSelected);
this.setEditability(serviceConfigProperty, defaultGroupSelected);
return serviceConfigProperty;
},
/**
* trigger addOverrideProperty
* @param {Object} componentConfig
* @method checkOverrideProperty
*/
checkOverrideProperty: function (componentConfig) {
var overrideToAdd = this.get('overrideToAdd');
if (overrideToAdd) {
overrideToAdd = componentConfig.configs.filter(function(c){
return c.name == overrideToAdd.name && c.filename == overrideToAdd.filename;
});
if (overrideToAdd[0]) {
this.addOverrideProperty(overrideToAdd[0]);
this.set('overrideToAdd', null);
}
}
},
/**
* set isEditable property of config for admin
* if default cfg group and not on the host config page
* @param {Ember.Object} serviceConfigProperty
* @param {Boolean} defaultGroupSelected
* @method setEditability
*/
setEditability: function (serviceConfigProperty, defaultGroupSelected) {
serviceConfigProperty.set('isEditable', false);
if (serviceConfigProperty.get('isComparison')) return;
if (App.isAccessible('ADMIN') && defaultGroupSelected && !this.get('isHostsConfigsPage') && !serviceConfigProperty.get('group')) {
serviceConfigProperty.set('isEditable', serviceConfigProperty.get('isReconfigurable'));
} else if (serviceConfigProperty.get('group') && this.get('selectedConfigGroup.name') === serviceConfigProperty.get('group.name')) {
serviceConfigProperty.set('isEditable', true);
}
},
/**
* set supportsFinal property of config for admin
* @param {Ember.Object} serviceConfigProperty
* @method setSupportsFinal
*/
setSupportsFinal: function (serviceConfigProperty) {
if (serviceConfigProperty.get('isMock')) return;
var fileName = serviceConfigProperty.get('filename');
var matchingConfigType = this.get('configTypesInfo').supportsFinal.find(function(configType) {
return fileName.startsWith(configType);
});
serviceConfigProperty.set('supportsFinal', !!matchingConfigType);
},
/**
* set override values
* @param overrides
* @param _serviceConfigProperty
* @param serviceConfigProperty
* @param defaultGroupSelected
*/
setValuesForOverrides: function (overrides, _serviceConfigProperty, serviceConfigProperty, defaultGroupSelected) {
if (Em.isNone(overrides)) return;
overrides.forEach(function (override) {
var newSCP = this.createNewSCP(override, _serviceConfigProperty, serviceConfigProperty, defaultGroupSelected);
var parentOverridesArray = serviceConfigProperty.get('overrides');
if (parentOverridesArray == null) {
parentOverridesArray = Em.A([]);
serviceConfigProperty.set('overrides', parentOverridesArray);
}
parentOverridesArray.pushObject(newSCP);
serviceConfigProperty.set('overrideValues', parentOverridesArray.mapProperty('value'));
serviceConfigProperty.set('overrideIsFinalValues', parentOverridesArray.mapProperty('isFinal'));
console.debug("createOverrideProperty(): Added override to main-property:", serviceConfigProperty.get('name'));
}, this);
},
/**
* create new overridden property and set appropriate fields
* @param override
* @param _serviceConfigProperty
* @param serviceConfigProperty
* @param defaultGroupSelected
* @returns {*}
*/
createNewSCP: function (override, _serviceConfigProperty, serviceConfigProperty, defaultGroupSelected) {
var newSCP = App.ServiceConfigProperty.create(_serviceConfigProperty);
newSCP.set('value', override.value);
newSCP.set('isFinal', override.isFinal);
newSCP.set('supportsFinal', serviceConfigProperty.get('supportsFinal'));
newSCP.set('isOriginalSCP', false); // indicated this is overridden value,
newSCP.set('parentSCP', serviceConfigProperty);
if (defaultGroupSelected) {
newSCP.set('group', override.group);
newSCP.set('isEditable', false);
}
return newSCP;
},
/**
* convert string values to boolean for checkboxes
* @param {Ember.Object} serviceConfigProperty
*/
setValueForCheckBox: function (serviceConfigProperty) {
if (serviceConfigProperty.get("displayType") == 'checkbox') {
switch (serviceConfigProperty.get("value")) {
case 'true':
serviceConfigProperty.set("value", true);
serviceConfigProperty.set("defaultValue", true);
break;
case 'false':
serviceConfigProperty.set("value", false);
serviceConfigProperty.set("defaultValue", false);
break;
}
}
},
/**
* Initialize save configs popup
*/
restartServicePopup: function () {
if (this.get("isSubmitDisabled")) {
return;
}
this.set("isApplyingChanges", true);
var self = this;
var header, message, messageClass, status;
var serviceName = this.get('content.serviceName'),
displayName = this.get('content.displayName'),
urlParams = '';
this.serverSideValidation().done(function () {
if (self.isDirChanged()) {
App.showConfirmationPopup(function () {
self.saveConfigs();
}, Em.I18n.t('services.service.config.confirmDirectoryChange').format(displayName), function () {
self.set('isApplyingChanges', false);
});
} else {
self.saveConfigs();
}
}).fail(function () {
self.set('isApplyingChanges', false);
});
},
/**
* Define if user has changed some dir properties
* @return {Boolean}
*/
isDirChanged: function () {
var dirChanged = false;
var serviceName = this.get('content.serviceName');
if (serviceName === 'HDFS') {
var hdfsConfigs = this.get('stepConfigs').findProperty('serviceName', 'HDFS').get('configs');
if (App.get('isHadoop2Stack')) {
if ((hdfsConfigs.findProperty('name', 'dfs.namenode.name.dir') && hdfsConfigs.findProperty('name', 'dfs.namenode.name.dir').get('isNotDefaultValue')) ||
(hdfsConfigs.findProperty('name', 'dfs.namenode.checkpoint.dir') && hdfsConfigs.findProperty('name', 'dfs.namenode.checkpoint.dir').get('isNotDefaultValue')) ||
(hdfsConfigs.findProperty('name', 'dfs.datanode.data.dir') && hdfsConfigs.findProperty('name', 'dfs.datanode.data.dir').get('isNotDefaultValue'))) {
dirChanged = true;
}
} else {
if ((hdfsConfigs.findProperty('name', 'dfs.name.dir') && hdfsConfigs.findProperty('name', 'dfs.name.dir').get('isNotDefaultValue')) ||
(hdfsConfigs.findProperty('name', 'fs.checkpoint.dir') && hdfsConfigs.findProperty('name', 'fs.checkpoint.dir').get('isNotDefaultValue')) ||
(hdfsConfigs.findProperty('name', 'dfs.data.dir') && hdfsConfigs.findProperty('name', 'dfs.data.dir').get('isNotDefaultValue'))) {
dirChanged = true;
}
}
} else if (serviceName === 'MAPREDUCE') {
var mapredConfigs = this.get('stepConfigs').findProperty('serviceName', 'MAPREDUCE').get('configs');
if ((mapredConfigs.findProperty('name', 'mapred.local.dir') && mapredConfigs.findProperty('name', 'mapred.local.dir').get('isNotDefaultValue')) ||
(mapredConfigs.findProperty('name', 'mapred.system.dir') && mapredConfigs.findProperty('name', 'mapred.system.dir').get('isNotDefaultValue'))) {
dirChanged = true;
}
}
return dirChanged;
},
/**
* Save changed configs and config groups
*/
saveConfigs: function () {
var selectedConfigGroup = this.get('selectedConfigGroup');
var configs = this.get('stepConfigs').findProperty('serviceName', this.get('content.serviceName')).get('configs');
var self = this;
if (selectedConfigGroup.get('isDefault')) {
if (this.get('content.serviceName') === 'YARN') {
configs = App.config.textareaIntoFileConfigs(configs, 'capacity-scheduler.xml');
}
var modifiedConfigs = configs
// get only modified and created configs
.filter(function(config) { return config.get('isNotDefaultValue') || config.get('isNotSaved'); })
// get file names and add file names that was modified, for example after property removing
.mapProperty('filename').concat(this.get('modifiedFileNames')).uniq()
// get configs by filename
.map(function(fileName) {
return configs.filterProperty('filename', fileName);
});
if (!!modifiedConfigs.length) {
// concatenate results
modifiedConfigs = modifiedConfigs.reduce(function(current, prev) { return current.concat(prev); });
}
// save modified original configs that have no group
this.saveSiteConfigs(modifiedConfigs.filter(function(config) { return !config.get('group'); }));
/**
* First we put cluster configurations, which automatically creates /configurations
* resources. Next we update host level overrides.
*/
this.doPUTClusterConfigurations();
} else {
var overridenConfigs = [];
var groupHosts = [];
configs.filterProperty('isOverridden', true).forEach(function (config) {
overridenConfigs = overridenConfigs.concat(config.get('overrides'));
});
// find custom original properties that assigned to selected config group
overridenConfigs = overridenConfigs.concat(configs.filterProperty('group')
.filter(function(config) { return config.get('group.name') == self.get('selectedConfigGroup.name'); }));
this.formatConfigValues(overridenConfigs);
selectedConfigGroup.get('hosts').forEach(function (hostName) {
groupHosts.push({"host_name": hostName});
});
this.putConfigGroupChanges({
ConfigGroup: {
"id": selectedConfigGroup.get('id'),
"cluster_name": App.get('clusterName'),
"group_name": selectedConfigGroup.get('name'),
"tag": selectedConfigGroup.get('service.id'),
"description": selectedConfigGroup.get('description'),
"hosts": groupHosts,
"service_config_version_note": this.get('serviceConfigVersionNote'),
"desired_configs": this.buildGroupDesiredConfigs(overridenConfigs)
}
}, true);
}
},
/**
* On save configs handler. Open save configs popup with appropriate message.
*/
onDoPUTClusterConfigurations: function () {
var header, message, messageClass, value, status = 'unknown', urlParams = '',
result = {
flag: this.get('saveConfigsFlag'),
message: null,
value: null
},
extendedModel = App.Service.extendedModel[this.get('content.serviceName')],
currentService = extendedModel ? App[extendedModel].find(this.get('content.serviceName')) : App.Service.find(this.get('content.serviceName'));
if (!result.flag) {
result.message = Em.I18n.t('services.service.config.failSaveConfig');
}
App.router.get('clusterController').updateClusterData();
App.router.get('updateController').updateComponentConfig(function () {
});
var flag = result.flag;
if (result.flag === true) {
header = Em.I18n.t('services.service.config.saved');
message = Em.I18n.t('services.service.config.saved.message');
messageClass = 'alert alert-success';
// warn the user if any of the components are in UNKNOWN state
urlParams += ',ServiceComponentInfo/installed_count,ServiceComponentInfo/total_count';
if (this.get('content.serviceName') === 'HDFS' || App.Service.find().someProperty('id', 'MAPREDUCE')) {
urlParams += '&ServiceComponentInfo/service_name.in(HDFS,MAPREDUCE)'
}
} else {
header = Em.I18n.t('common.failure');
message = result.message;
messageClass = 'alert alert-error';
value = result.value;
}
if(currentService){
App.QuickViewLinks.proto().set('content', currentService);
App.QuickViewLinks.proto().loadTags();
}
this.showSaveConfigsPopup(header, flag, message, messageClass, value, status, urlParams);
},
/**
* Show save configs popup
* @method showSaveConfigsPopup
* @return {App.ModalPopup}
*/
showSaveConfigsPopup: function (header, flag, message, messageClass, value, status, urlParams) {
var self = this;
if (flag) {
this.set('forceTransition', flag);
self.loadStep();
}
return App.ModalPopup.show({
header: header,
primary: Em.I18n.t('ok'),
secondary: null,
onPrimary: function () {
this.hide();
if (!flag) {
self.set('isApplyingChanges', false);
}
},
onClose: function () {
this.hide();
self.set('isApplyingChanges', false);
},
disablePrimary: true,
bodyClass: Ember.View.extend({
flag: flag,
message: function () {
return this.get('isLoaded') ? message : Em.I18n.t('services.service.config.saving.message');
}.property('isLoaded'),
messageClass: function () {
return this.get('isLoaded') ? messageClass : 'alert alert-info';
}.property('isLoaded'),
setDisablePrimary: function () {
this.get('parentView').set('disablePrimary', !this.get('isLoaded'));
}.observes('isLoaded'),
runningHosts: [],
runningComponentCount: 0,
unknownHosts: [],
unknownComponentCount: 0,
siteProperties: value,
isLoaded: false,
componentsFilterSuccessCallback: function (response) {
var count = 0,
view = this,
lazyLoadHosts = function (dest) {
lazyLoading.run({
initSize: 20,
chunkSize: 50,
delay: 50,
destination: dest,
source: hosts,
context: view
});
},
/**
* Map components for their hosts
* Return format:
*
* {
* host1: [component1, component2, ...],
* host2: [component3, component4, ...]
* }
*
* @return {object}
*/
setComponents = function (item, components) {
item.host_components.forEach(function (c) {
var name = c.HostRoles.host_name;
if (!components[name]) {
components[name] = [];
}
components[name].push(App.format.role(item.ServiceComponentInfo.component_name));
});
return components;
},
/**
* Map result of setComponents
to array
* @return {{name: string, components: string}[]}
*/
setHosts = function (components) {
var hosts = [];
Em.keys(components).forEach(function (key) {
hosts.push({
name: key,
components: components[key].join(', ')
});
});
return hosts;
},
components = {},
hosts = [];
switch (status) {
case 'unknown':
response.items.filter(function (item) {
return (item.ServiceComponentInfo.total_count > item.ServiceComponentInfo.started_count + item.ServiceComponentInfo.installed_count);
}).forEach(function (item) {
var total = item.ServiceComponentInfo.total_count,
started = item.ServiceComponentInfo.started_count,
installed = item.ServiceComponentInfo.installed_count,
unknown = total - started + installed;
components = setComponents(item, components);
count += unknown;
});
hosts = setHosts(components);
this.set('unknownComponentCount', count);
lazyLoadHosts(this.get('unknownHosts'));
break;
case 'started':
response.items.filterProperty('ServiceComponentInfo.started_count').forEach(function (item) {
var started = item.ServiceComponentInfo.started_count;
components = setComponents(item, components);
count += started;
hosts = setHosts(components);
});
this.set('runningComponentCount', count);
lazyLoadHosts(this.get('runningHosts'));
break;
}
},
componentsFilterErrorCallback: function () {
this.set('isLoaded', true);
},
didInsertElement: function () {
return App.ajax.send({
name: 'components.filter_by_status',
sender: this,
data: {
clusterName: App.get('clusterName'),
urlParams: urlParams
},
success: 'componentsFilterSuccessCallback',
error: 'componentsFilterErrorCallback'
});
},
getDisplayMessage: function () {
var displayMsg = [];
var siteProperties = this.get('siteProperties');
if (siteProperties) {
siteProperties.forEach(function (_siteProperty) {
var displayProperty = _siteProperty.siteProperty;
var displayNames = _siteProperty.displayNames;
if (displayNames && displayNames.length) {
if (displayNames.length === 1) {
displayMsg.push(displayProperty + Em.I18n.t('as') + displayNames[0]);
} else {
var name;
displayNames.forEach(function (_name, index) {
if (index === 0) {
name = _name;
} else if (index === siteProperties.length - 1) {
name = name + Em.I18n.t('and') + _name;
} else {
name = name + ', ' + _name;
}
}, this);
displayMsg.push(displayProperty + Em.I18n.t('as') + name);
}
} else {
displayMsg.push(displayProperty);
}
}, this);
}
return displayMsg;
}.property('siteProperties'),
runningHostsMessage: function () {
return Em.I18n.t('services.service.config.stopService.runningHostComponents').format(this.get('runningComponentCount'), this.get('runningHosts.length'));
}.property('runningComponentCount', 'runningHosts.length'),
unknownHostsMessage: function () {
return Em.I18n.t('services.service.config.stopService.unknownHostComponents').format(this.get('unknownComponentCount'), this.get('unknownHosts.length'));
}.property('unknownComponentCount', 'unknownHosts.length'),
templateName: require('templates/main/service/info/configs_save_popup')
})
})
},
/**
* construct desired_configs for config groups from overriden properties
* @param configs
* @param timeTag
* @return {Array}
*/
buildGroupDesiredConfigs: function (configs, timeTag) {
var sites = [];
var time = timeTag || (new Date).getTime();
var siteFileNames = configs.mapProperty('filename').uniq();
sites = siteFileNames.map(function (filename) {
return {
type: filename.replace('.xml', ''),
tag: 'version' + time,
properties: []
};
});
configs.forEach(function (config) {
var type = config.get('filename').replace('.xml', '');
var site = sites.findProperty('type', type);
site.properties.push(config);
});
return sites.map(function (site) {
return this.createSiteObj(site.type, site.tag, site.properties);
}, this);
},
/**
* persist properties of config groups to server
* show result popup if showPopup
is true
* @param data {Object}
* @param showPopup {Boolean}
*/
putConfigGroupChanges: function (data, showPopup) {
var ajaxOptions = {
name: 'config_groups.update_config_group',
sender: this,
data: {
id: data.ConfigGroup.id,
configGroup: data
}
};
if (showPopup) {
ajaxOptions.success = "putConfigGroupChangesSuccess";
}
App.ajax.send(ajaxOptions);
},
putConfigGroupChangesSuccess: function () {
this.set('saveConfigsFlag', true);
this.onDoPUTClusterConfigurations();
},
/**
* set sink hostnames in configs
* @param configs
*/
setSinkHostName: function (configs) {
var dbHostPropertyName = null;
if (configs.someProperty('name', 'sink_database')) {
var sinkDb = configs.findProperty('name', 'sink_database');
if (sinkDb.value === 'Existing MSSQL Server database with integrated authentication') {
var existingMSSQLServerHost = configs.findProperty('name', 'sink_existing_mssql_server_host');
if (existingMSSQLServerHost) {
dbHostPropertyName = 'sink_existing_mssql_server_host';
}
configs = configs.without(configs.findProperty('name', 'sink_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'sink_existing_mssql_server_2_host'));
} else if (sinkDb.value === 'Existing MSSQL Server database with sql auth') {
var existingMSSQL2ServerHost = configs.findProperty('name', 'sink_existing_mssql_server_2_host');
if (existingMSSQL2ServerHost) {
dbHostPropertyName = 'sink_existing_mssql_server_2_host';
}
configs = configs.without(configs.findProperty('name', 'sink_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'sink_existing_mssql_server_host'));
}
}
if (dbHostPropertyName) {
var sinkHostNameProperty = App.ServiceConfigProperty.create(App.config.get('preDefinedSiteProperties').findProperty('name', 'sink.dbservername'));
sinkHostNameProperty.set('value', configs.findProperty('name', dbHostPropertyName).get('value'));
configs.pushObject(sinkHostNameProperty);
}
},
/**
* set hive hostnames in configs
* @param configs
*/
setHiveHostName: function (configs) {
var dbHostPropertyName = null;
if (configs.someProperty('name', 'hive_database')) {
var hiveDb = configs.findProperty('name', 'hive_database');
if (hiveDb.value === 'New MySQL Database' || hiveDb.value === 'New PostgreSQL Database') {
var ambariHost = configs.findProperty('name', 'hive_ambari_host');
if (ambariHost) {
ambariHost.name = 'hive_hostname';
}
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_host'));
} else if (hiveDb.value === 'Existing MySQL Database') {
var existingMySqlHost = configs.findProperty('name', 'hive_existing_mysql_host');
if (existingMySqlHost) {
dbHostPropertyName = 'hive_existing_mysql_host';
}
configs = configs.without(configs.findProperty('name', 'hive_ambari_host'));
configs = configs.without(configs.findProperty('name', 'hive_ambari_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_host'));
} else if (hiveDb.value === Em.I18n.t('services.service.config.hive.oozie.postgresql')) {
var existingPostgreSqlHost = configs.findProperty('name', 'hive_existing_postgresql_host');
if (existingPostgreSqlHost) {
dbHostPropertyName = 'hive_existing_postgresql_host';
}
configs = configs.without(configs.findProperty('name', 'hive_ambari_host'));
configs = configs.without(configs.findProperty('name', 'hive_ambari_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_host'));
} else if (hiveDb.value === 'Existing Oracle Database') {
var existingOracleHost = configs.findProperty('name', 'hive_existing_oracle_host');
if (existingOracleHost) {
dbHostPropertyName = 'hive_existing_oracle_host';
}
configs = configs.without(configs.findProperty('name', 'hive_ambari_host'));
configs = configs.without(configs.findProperty('name', 'hive_ambari_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_host'));
} else if (hiveDb.value === 'Existing MSSQL Server database with integrated authentication') {
var existingMSSQLServerHost = configs.findProperty('name', 'hive_existing_mssql_server_host');
if (existingMSSQLServerHost) {
dbHostPropertyName = 'hive_existing_mssql_server_host';
}
configs = configs.without(configs.findProperty('name', 'hive_ambari_host'));
configs = configs.without(configs.findProperty('name', 'hive_ambari_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_2_host'));
} else if (hiveDb.value === 'Existing MSSQL Server database with sql auth') {
var existingMSSQL2ServerHost = configs.findProperty('name', 'hive_existing_mssql_server_2_host');
if (existingMSSQL2ServerHost) {
dbHostPropertyName = 'hive_existing_mssql_server_2_host';
}
configs = configs.without(configs.findProperty('name', 'hive_ambari_host'));
configs = configs.without(configs.findProperty('name', 'hive_ambari_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'hive_existing_mssql_server_host'));
}
}
if (dbHostPropertyName) {
var hiveHostNameProperty = App.ServiceConfigProperty.create(App.config.get('preDefinedSiteProperties').findProperty('name', 'hive_hostname'));
hiveHostNameProperty.set('value', configs.findProperty('name', dbHostPropertyName).get('value'));
configs.pushObject(hiveHostNameProperty);
}
},
/**
* set oozie hostnames in configs
* @param configs
*/
setOozieHostName: function (configs) {
var dbHostPropertyName = null;
if (configs.someProperty('name', 'oozie_database')) {
var oozieDb = configs.findProperty('name', 'oozie_database');
if (oozieDb.value === 'New Derby Database') {
configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_host'));
} else if (oozieDb.value === 'New MySQL Database') {
var ambariHost = configs.findProperty('name', 'oozie_ambari_host');
if (ambariHost) {
ambariHost.name = 'oozie_hostname';
}
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'oozie_derby_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_host'));
} else if (oozieDb.value === 'Existing MySQL Database') {
var existingMySqlHost = configs.findProperty('name', 'oozie_existing_mysql_host');
if (existingMySqlHost) {
dbHostPropertyName = 'oozie_existing_mysql_host';
}
configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'oozie_derby_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_host'));
} else if (oozieDb.value === Em.I18n.t('services.service.config.hive.oozie.postgresql')) {
var existingPostgreSqlHost = configs.findProperty('name', 'oozie_existing_postgresql_host');
if (existingPostgreSqlHost) {
dbHostPropertyName = 'oozie_existing_postgresql_host';
}
configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_host'));
}
else if (oozieDb.value === 'Existing Oracle Database') {
var existingOracleHost = configs.findProperty('name', 'oozie_existing_oracle_host');
if (existingOracleHost) {
dbHostPropertyName = 'oozie_existing_oracle_host';
}
configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_derby_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_host'));
} else if (oozieDb.value === 'Existing MSSQL Server database with integrated authentication') {
var existingMySqlServerHost = configs.findProperty('name', 'oozie_existing_mssql_server_host');
if (existingMySqlServerHost) {
dbHostPropertyName = 'oozie_existing_mssql_server_host';
}
configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'oozie_derby_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_2_host'));
} else if (oozieDb.value === 'Existing MSSQL Server database with sql auth') {
var existingMySql2ServerHost = configs.findProperty('name', 'oozie_existing_mssql_server_2_host');
if (existingMySql2ServerHost) {
dbHostPropertyName = 'oozie_existing_mssql_server_2_host';
}
configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
configs = configs.without(configs.findProperty('name', 'oozie_derby_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_database'));
configs = configs.without(configs.findProperty('name', 'oozie_existing_mssql_server_host'));
}
}
if (dbHostPropertyName) {
var oozieHostNameProperty = App.ServiceConfigProperty.create(App.config.get('preDefinedSiteProperties').findProperty('name', 'oozie_hostname'));
oozieHostNameProperty.set('value', configs.findProperty('name', dbHostPropertyName).get('value'));
configs.pushObject(oozieHostNameProperty);
}
},
/**
* save site configs
* @param configs
*/
saveSiteConfigs: function (configs) {
//storedConfigs contains custom configs as well
this.setHiveHostName(configs);
this.setOozieHostName(configs);
this.setSinkHostName(configs);
this.formatConfigValues(configs);
var mappedConfigs = App.config.excludeUnsupportedConfigs(this.get('configMapping').all(), App.Service.find().mapProperty('serviceName'));
var allUiConfigs = this.loadUiSideConfigs(mappedConfigs);
this.set('uiConfigs', configs.concat(allUiConfigs));
},
formatConfigValues: function (serviceConfigProperties) {
serviceConfigProperties.forEach(function (_config) {
if (typeof _config.get('value') === "boolean") _config.set('value', _config.value.toString());
_config.set('value', App.config.trimProperty(_config, true));
});
},
/**
* return configs from the UI side
* @param configMapping array with configs
* @return {Array}
*/
loadUiSideConfigs: function (configMapping) {
var uiConfig = [];
var configs = configMapping.filterProperty('foreignKey', null);
this.addDynamicProperties(configs);
configs.forEach(function (_config) {
var valueWithOverrides = this.getGlobConfigValueWithOverrides(_config.templateName, _config.value);
if (valueWithOverrides !== null) {
uiConfig.pushObject({
"id": "site property",
"name": _config.name,
"value": valueWithOverrides.value,
"filename": _config.filename,
"overrides": valueWithOverrides.overrides
});
}
}, this);
return uiConfig;
},
addDynamicProperties: function (configs) {
var allConfigs = this.get('stepConfigs').findProperty('serviceName', this.get('content.serviceName')).get('configs');
var templetonHiveProperty = allConfigs.someProperty('name', 'templeton.hive.properties');
if (!templetonHiveProperty && this.get('content.serviceName') === 'HIVE') {
configs.pushObject({
"name": "templeton.hive.properties",
"templateName": ["hivemetastore_host"],
"foreignKey": null,
"value": "hive.metastore.local=false,hive.metastore.uris=thrift://:9083,hive.metastore.sasl.enabled=yes,hive.metastore.execute.setugi=true,hive.metastore.warehouse.dir=/apps/hive/warehouse",
"filename": "webhcat-site.xml"
});
}
},
/**
* return config value
* @param templateName
* @param expression
* @return {Object}
* example: {
* value: '...',
* overrides: {
* 'value1': [h1, h2],
* 'value2': [h3]
* }
* }
*/
getGlobConfigValueWithOverrides: function (templateName, expression) {
var express = expression.match(/<(.*?)>/g);
var value = expression;
var overrideHostToValue = {};
if (express != null) {
express.forEach(function (_express) {
var index = parseInt(_express.match(/\[([\d]*)(?=\])/)[1]);
var globalObj = this.get('allConfigs').findProperty('name', templateName[index]);
if (globalObj) {
var globOverride = globalObj.overrides;
if (globOverride != null) {
for (var ov in globOverride) {
globOverride[ov].forEach(function (host) {
var replacedVal = (host in overrideHostToValue) ? overrideHostToValue[host] : expression;
overrideHostToValue[host] = replacedVal.replace(_express, ov);
}, this);
}
}
value = expression.replace(_express, globalObj.value);
} else {
value = null;
}
}, this);
}
return this.getValueWithOverrides(value, overrideHostToValue)
},
getValueWithOverrides: function (value, overrideHostToValue) {
var valueWithOverrides = {
value: value,
overrides: {}
};
if (!jQuery.isEmptyObject(overrideHostToValue)) {
for (var host in overrideHostToValue) {
var hostVal = overrideHostToValue[host];
if (!(hostVal in valueWithOverrides.overrides)) {
valueWithOverrides.overrides[hostVal] = [];
}
valueWithOverrides.overrides[hostVal].push(host);
}
}
return valueWithOverrides;
},
/**
* Saves cluster level configurations for all necessary sites.
* PUT calls are made to /api/v1/clusters/clusterName for each site.
* @return {Boolean}
* @method doPUTClusterConfigurations
*/
doPUTClusterConfigurations: function () {
this.set('saveConfigsFlag', true);
var serviceConfigTags = this.get('serviceConfigTags');
this.setNewTagNames(serviceConfigTags);
var siteNameToServerDataMap = {};
var configsToSave = [];
serviceConfigTags.forEach(function (_serviceTags) {
var configs = this.createConfigObject(_serviceTags.siteName, _serviceTags.newTagName);
if (configs) {
configsToSave.push(configs);
siteNameToServerDataMap[_serviceTags.siteName] = configs;
}
}, this);
configsToSave = this.filterChangedConfiguration(configsToSave);
if (configsToSave.length > 0) {
this.doPUTClusterConfigurationSites(configsToSave);
} else {
this.onDoPUTClusterConfigurations();
}
this.set("savedSiteNameToServerServiceConfigDataMap", siteNameToServerDataMap);
},
/**
* create different config object depending on siteName
* @param {String} siteName
* @param {String} tagName
* @returns {Object|null}
* @method createConfigObject
*/
createConfigObject: function (siteName, tagName) {
console.log("TRACE: Inside " + siteName);
var configObject = {};
switch (siteName) {
case 'core-site':
if (this.get('content.serviceName') === 'HDFS' || this.get('content.serviceName') === 'GLUSTERFS') {
configObject = this.createCoreSiteObj(tagName);
} else {
return null;
}
break;
default:
var filename = (App.config.get('filenameExceptions').contains(siteName)) ? siteName : siteName + '.xml';
if (filename === 'mapred-queue-acls.xml') {
return null;
}
configObject = this.createSiteObj(siteName, tagName, this.get('uiConfigs').filterProperty('filename', filename));
break;
}
configObject.service_config_version_note = this.get('serviceConfigVersionNote');
return configObject;
},
/**
* filter out unchanged configurations
* @param {Array} configsToSave
* @method filterChangedConfiguration
*/
filterChangedConfiguration: function (configsToSave) {
var changedConfigs = [];
configsToSave.forEach(function (configSite) {
var oldConfig = App.router.get('configurationController').getConfigsByTags([
{siteName: configSite.type, tagName: this.loadedClusterSiteToTagMap[configSite.type]}
]);
oldConfig = oldConfig[0] || {};
var oldProperties = oldConfig.properties || {};
var oldAttributes = oldConfig["properties_attributes"] || {};
var newProperties = configSite.properties || {};
var newAttributes = configSite["properties_attributes"] || {};
if (this.isAttributesChanged(oldAttributes, newAttributes) || this.isConfigChanged(oldProperties, newProperties)) {
changedConfigs.push(configSite);
}
}, this);
return changedConfigs;
},
/**
* Compares the loaded config values with the saving config values.
* @param {Object} loadedConfig -
* loadedConfig: {
* configName1: "configValue1",
* configName2: "configValue2"
* }
* @param {Object} savingConfig
* savingConfig: {
* configName1: "configValue1",
* configName2: "configValue2"
* }
* @returns {boolean}
* @method isConfigChanged
*/
isConfigChanged: function (loadedConfig, savingConfig) {
if (loadedConfig != null && savingConfig != null) {
var seenLoadKeys = [];
for (var loadKey in loadedConfig) {
if (!loadedConfig.hasOwnProperty(loadKey)) continue;
seenLoadKeys.push(loadKey);
var loadValue = loadedConfig[loadKey];
var saveValue = savingConfig[loadKey];
if ("boolean" == typeof(saveValue)) {
saveValue = saveValue.toString();
}
if (saveValue == null) {
saveValue = "null";
}
if (loadValue !== saveValue) {
return true;
}
}
for (var saveKey in savingConfig) {
if (seenLoadKeys.indexOf(saveKey) < 0) {
return true;
}
}
}
return false;
},
/**
* Compares the loaded config properties attributes with the saving config properties attributes.
* @param {Object} oldAttributes -
* oldAttributes: {
* supports: {
* final: {
* "configValue1" : "true",
* "configValue2" : "true"
* }
* }
* }
* @param {Object} newAttributes
* newAttributes: {
* supports: {
* final: {
* "configValue1" : "true",
* "configValue2" : "true"
* }
* }
* }
* @returns {boolean}
* @method isConfigChanged
*/
isAttributesChanged: function (oldAttributes, newAttributes) {
oldAttributes = oldAttributes.final || {};
newAttributes = newAttributes.final || {};
var key;
for (key in oldAttributes) {
if (oldAttributes.hasOwnProperty(key)
&& (!newAttributes.hasOwnProperty(key) || newAttributes[key] !== oldAttributes[key])) {
return true;
}
}
for (key in newAttributes) {
if (newAttributes.hasOwnProperty(key)
&& (!oldAttributes.hasOwnProperty(key) || newAttributes[key] !== oldAttributes[key])) {
return true;
}
}
return false;
},
/**
* Saves configuration of set of sites. The provided data
* contains the site name and tag to be used.
* @param {Object} sites
* @method doPUTClusterConfigurationSites
*/
doPUTClusterConfigurationSites: function (sites) {
App.ajax.send({
name: 'common.service.configurations',
sender: this,
data: {
desired_config: sites
},
success: 'doPUTClusterConfigurationSiteSuccessCallback',
error: 'doPUTClusterConfigurationSiteErrorCallback'
});
},
doPUTClusterConfigurationSiteSuccessCallback: function () {
this.onDoPUTClusterConfigurations();
},
doPUTClusterConfigurationSiteErrorCallback: function () {
this.set('saveConfigsFlag', false);
this.doPUTClusterConfigurationSiteSuccessCallback();
},
/**
* add newTagName property to each config in serviceConfigs
* @param serviceConfigs
*/
setNewTagNames: function (serviceConfigs) {
var time = (new Date).getTime();
serviceConfigs.forEach(function (_serviceConfigs) {
_serviceConfigs.newTagName = 'version' + time;
}, this);
},
/**
* Save "final" attribute for properties
* @param {Array} properties - array of properties
* @returns {Object|null}
* */
getConfigAttributes: function(properties) {
var attributes = {
final: {}
};
var finalAttributes = attributes.final;
var hasAttributes = false;
properties.forEach(function (property) {
if (property.isRequiredByAgent !== false && property.isFinal) {
hasAttributes = true;
finalAttributes[property.name] = "true";
}
});
if (hasAttributes) {
return attributes;
}
return null;
},
/**
* create core site object
* @param tagName
* @return {{"type": String, "tag": String, "properties": Object}}
* @method createCoreSiteObj
*/
createCoreSiteObj: function (tagName) {
var coreSiteObj = this.get('uiConfigs').filterProperty('filename', 'core-site.xml');
var coreSiteProperties = {};
coreSiteObj.forEach(function (_coreSiteObj) {
coreSiteProperties[_coreSiteObj.name] = _coreSiteObj.value;
//this.recordHostOverride(_coreSiteObj, 'core-site', tagName, this);
}, this);
var result = {"type": "core-site", "tag": tagName, "properties": coreSiteProperties};
var attributes = this.getConfigAttributes(coreSiteObj);
if (attributes) {
result['properties_attributes'] = attributes;
}
return result;
},
/**
* create site object
* @param siteName
* @param tagName
* @param siteObj
* @return {Object}
*/
createSiteObj: function (siteName, tagName, siteObj) {
var heapsizeException = this.get('heapsizeException');
var heapsizeRegExp = this.get('heapsizeRegExp');
var siteProperties = {};
siteObj.forEach(function (_siteObj) {
var value = _siteObj.value;
if (_siteObj.isRequiredByAgent == false) return;
// site object name follow the format *permsize/*heapsize and the value NOT ends with "m"
if (heapsizeRegExp.test(_siteObj.name) && !heapsizeException.contains(_siteObj.name) && !(_siteObj.value).endsWith("m")) {
value += "m";
}
siteProperties[_siteObj.name] = value;
switch (siteName) {
case 'falcon-startup.properties':
case 'falcon-runtime.properties':
case 'pig-properties':
siteProperties[_siteObj.name] = value;
break;
default:
siteProperties[_siteObj.name] = this.setServerConfigValue(_siteObj.name, value);
}
}, this);
var result = {"type": siteName, "tag": tagName, "properties": siteProperties};
var attributes = this.getConfigAttributes(siteObj);
if (attributes) {
result['properties_attributes'] = attributes;
}
return result;
},
/**
* This method will be moved to config's decorators class.
*
* For now, provide handling for special properties that need
* be specified in special format required for server.
*
* @param configName {String} - name of config property
* @param value {Mixed} - value of config property
*
* @return {String} - formated value
*/
setServerConfigValue: function (configName, value) {
switch (configName) {
case 'storm.zookeeper.servers':
if( Object.prototype.toString.call( value ) === '[object Array]' ) {
return JSON.stringify(value).replace(/"/g, "'");
} else {
return value;
}
break;
default:
return value;
}
},
/**
* Array of Objects
* {
* hostProperty - hostName property name for current component
* componentName - master componentName
* serviceName - serviceName of component
* serviceUseThis - services that use hostname property of component(componentName)
* m(multiple) - true if can be more than one components installed on cluster
* }
*/
hostComponentsmapping: [
{
hostProperty: 'snamenode_host',
componentName: 'SECONDARY_NAMENODE',
serviceName: 'HDFS',
serviceUseThis: []
},
{
hostProperty: 'jobtracker_host',
componentName: 'JOBTRACKER',
serviceName: 'MAPREDUCE',
serviceUseThis: []
},
{
hostProperty: 'jobtracker_host',
componentName: 'JOBTRACKER',
serviceName: 'MAPREDUCE2',
serviceUseThis: []
},
{
hostProperty: 'hs_host',
componentName: 'HISTORYSERVER',
serviceName: 'MAPREDUCE2',
serviceUseThis: ['YARN']
},
{
hostProperty: 'hs_host',
componentName: 'HISTORYSERVER',
serviceName: 'MAPREDUCE',
serviceUseThis: []
},
{
hostProperty: 'ats_host',
componentName: 'APP_TIMELINE_SERVER',
serviceName: 'YARN',
serviceUseThis: []
},
{
hostProperty: 'rm_host',
componentName: 'RESOURCEMANAGER',
serviceName: 'YARN',
serviceUseThis: []
},
{
hostProperty: 'hivemetastore_host',
componentName: 'HIVE_SERVER',
serviceName: 'HIVE',
serviceUseThis: ['HIVE']
},
{
hostProperty: 'oozieserver_host',
componentName: 'OOZIE_SERVER',
serviceName: 'OOZIE',
serviceUseThis: []
},
{
hostProperty: 'hbasemaster_host',
componentName: 'HBASE_MASTER',
serviceName: 'HBASE',
serviceUseThis: [],
m: true
},
{
hostProperty: 'webhcatserver_host',
componentName: 'WEBHCAT_SERVER',
serviceName: 'HIVE',
serviceUseThis: [],
m: true
},
{
hostProperty: 'zookeeperserver_hosts',
componentName: 'ZOOKEEPER_SERVER',
serviceName: 'ZOOKEEPER',
serviceUseThis: ['HBASE', 'HIVE'],
m: true
},
{
hostProperty: 'stormuiserver_host',
componentName: 'STORM_UI_SERVER',
serviceName: 'STORM',
serviceUseThis: []
},
{
hostProperty: 'drpcserver_host',
componentName: 'DRPC_SERVER',
serviceName: 'STORM',
serviceUseThis: []
},
{
hostProperty: 'storm_rest_api_host',
componentName: 'STORM_REST_API',
serviceName: 'STORM',
serviceUseThis: []
},
{
hostProperty: 'supervisor_hosts',
componentName: 'SUPERVISOR',
serviceName: 'STORM',
serviceUseThis: [],
m: true
}
],
/**
* Adds host name of master component to config;
* @method addHostNamesToGlobalConfig
*/
addHostNamesToConfig: function () {
var serviceName = this.get('content.serviceName');
var configs = this.get('allConfigs');
//namenode_host is required to derive "fs.default.name" a property of core-site
try {
this.setHostForService('HDFS', 'NAMENODE', 'namenode_host', true);
} catch (err) {
console.log("No NameNode Host available. This is expected if you're using GLUSTERFS rather than HDFS.");
}
var hostProperties = this.get('hostComponentsmapping').filter(function (h) {
return h.serviceUseThis.contains(serviceName) || h.serviceName == serviceName;
});
hostProperties.forEach(function (h) {
this.setHostForService(h.serviceName, h.componentName, h.hostProperty, h.m);
}, this);
if (serviceName === 'HIVE') {
var hiveDb = configs.findProperty('name', 'hive_database').value;
if (['Existing MySQL Database', 'Existing Oracle Database', 'Existing PostgreSQL Database', 'Existing MSSQL Server database with integrated authentication', 'Existing MSSQL Server database with sql auth'].contains(hiveDb)) {
configs.findProperty('name', 'hive_hostname').isVisible = true;
}
}
if (serviceName === 'OOZIE') {
var oozieDb = configs.findProperty('name', 'oozie_database').value;
if (['Existing MySQL Database', 'Existing Oracle Database', 'Existing PostgreSQL Database', 'Existing MSSQL Server database with integrated authentication', 'Existing MSSQL Server database with sql auth'].contains(oozieDb)) {
configs.findProperty('name', 'oozie_hostname').isVisible = true;
}
}
if(App.get('isHadoopWindowsStack')) {
if (serviceName === 'HDFS') {
var sinkDB = configs.findProperty('name', 'sink_database').value;
if (['Existing MSSQL Server database with integrated authentication', 'Existing MSSQL Server database with sql auth'].contains(sinkDB)) {
configs.findProperty('name', 'sink.dbservername').isVisible = true;
}
}
}
},
/**
* set host name(s) property for component
* @param {String} serviceName - service name of component
* @param {String} componentName - component name whic host we want to know
* @param {String} hostProperty - name of host property for current component
* @param {Boolean} multiple - true if can be more than one component
* @method setHostForService
*/
setHostForService: function (serviceName, componentName, hostProperty, multiple) {
var configs = this.get('allConfigs');
var serviceConfigs = this.get('serviceConfigs').findProperty('serviceName', serviceName).get('configs');
var hostConfig = serviceConfigs.findProperty('name', hostProperty);
if (hostConfig) {
hostConfig.defaultValue = this.getMasterComponentHostValue(componentName, multiple);
configs.push(hostConfig);
}
},
/**
* get hostName of component
* @param {String} componentName
* @param {Boolean} multiple - true if can be more than one component installed on cluster
* @return {String|Array|Boolean} hostName|hostNames|false if missing component
* @method getMasterComponentHostValue
*/
getMasterComponentHostValue: function (componentName, multiple) {
var components = this.get('content.hostComponents').filterProperty('componentName', componentName);
if (components.length > 0) {
return multiple ? components.mapProperty('hostName') : components[0].get('hostName');
}
return false;
},
/**
* Provides service component name and display-name information for
* the current selected service.
* @return {Em.Array} validComponents - array of valid components
* @method getCurrentServiceComponents
*/
getCurrentServiceComponents: function () {
var components = this.get('content.hostComponents');
var validComponents = Ember.A([]);
var seenComponents = {};
components.forEach(function (component) {
var cn = component.get('componentName');
var cdn = component.get('displayName');
if (!seenComponents[cn]) {
validComponents.push(Ember.Object.create({
componentName: cn,
displayName: cdn,
selected: false
}));
seenComponents[cn] = cn;
}
});
return validComponents;
}.property('content'),
/**
* trigger loadStep
* @method loadStep
*/
doCancel: function () {
Em.run.once(this, 'onConfigGroupChange');
},
/**
* trigger restartAllServiceHostComponents(batchUtils) if confirmed in popup
* @method restartAllStaleConfigComponents
* @return App.showConfirmationFeedBackPopup
*/
restartAllStaleConfigComponents: function () {
var self = this;
var serviceDisplayName = this.get('content.displayName');
var bodyMessage = Em.Object.create({
confirmMsg: Em.I18n.t('services.service.restartAll.confirmMsg').format(serviceDisplayName),
confirmButton: Em.I18n.t('services.service.restartAll.confirmButton'),
additionalWarningMsg: this.get('content.passiveState') === 'OFF' ? Em.I18n.t('services.service.restartAll.warningMsg.turnOnMM').format(serviceDisplayName) : null
});
return App.showConfirmationFeedBackPopup(function (query) {
var selectedService = self.get('content.id');
batchUtils.restartAllServiceHostComponents(selectedService, true, query);
}, bodyMessage);
},
/**
* trigger launchHostComponentRollingRestart(batchUtils)
* @method rollingRestartStaleConfigSlaveComponents
*/
rollingRestartStaleConfigSlaveComponents: function (componentName) {
batchUtils.launchHostComponentRollingRestart(componentName.context, this.get('content.displayName'), this.get('content.passiveState') === "ON", true);
},
/**
* trigger showItemsShouldBeRestarted popup with hosts that requires resetart
* @method showHostsShouldBeRestarted
*/
showHostsShouldBeRestarted: function (restartRequiredHostsAndComponents) {
var hosts = [];
var rhc = this.get('content.restartRequiredHostsAndComponents') || restartRequiredHostsAndComponents;
for (var hostName in rhc) {
hosts.push(hostName);
}
var hostsText = hosts.length == 1 ? Em.I18n.t('common.host') : Em.I18n.t('common.hosts');
hosts = hosts.join(', ');
this.showItemsShouldBeRestarted(hosts, Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(hostsText));
},
/**
* trigger showItemsShouldBeRestarted popup with components that requires resetart
* @method showComponentsShouldBeRestarted
*/
showComponentsShouldBeRestarted: function (restartRequiredHostsAndComponents) {
var rhc = this.get('content.restartRequiredHostsAndComponents') || restartRequiredHostsAndComponents;
var hostsComponets = [];
var componentsObject = {};
for (var hostName in rhc) {
rhc[hostName].forEach(function (hostComponent) {
hostsComponets.push(hostComponent);
if (componentsObject[hostComponent] != undefined) {
componentsObject[hostComponent]++;
} else {
componentsObject[hostComponent] = 1;
}
})
}
var componentsList = [];
for (var obj in componentsObject) {
var componentDisplayName = (componentsObject[obj] > 1) ? obj + 's' : obj;
componentsList.push(componentsObject[obj] + ' ' + componentDisplayName);
}
var componentsText = componentsList.length == 1 ? Em.I18n.t('common.component') : Em.I18n.t('common.components');
hostsComponets = componentsList.join(', ');
this.showItemsShouldBeRestarted(hostsComponets, Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(componentsText));
},
showItemsShouldBeRestarted: function (content, header) {
App.ModalPopup.show({
content: content,
header: header,
bodyClass: Em.View.extend({
templateName: require('templates/common/selectable_popup'),
textareaVisible: false,
textTrigger: function () {
this.set('textareaVisible', !this.get('textareaVisible'));
},
putContentToTextarea: function () {
var content = this.get('parentView.content');
if (this.get('textareaVisible')) {
var wrapper = $(".task-detail-log-maintext");
$('.task-detail-log-clipboard').html(content).width(wrapper.width()).height(wrapper.height());
Em.run.next(function () {
$('.task-detail-log-clipboard').select();
});
}
}.observes('textareaVisible')
}),
secondary: null
});
},
/**
* add new overridden property to config property object
* @param {object} serviceConfigProperty - config property object
* @method addOverrideProperty
*/
addOverrideProperty: function (serviceConfigProperty) {
var overrides = serviceConfigProperty.get('overrides');
if (!overrides) {
overrides = [];
serviceConfigProperty.set('overrides', overrides);
}
// create new override with new value
var newSCP = App.ServiceConfigProperty.create(serviceConfigProperty);
newSCP.set('value', '');
newSCP.set('isOriginalSCP', false); // indicated this is overridden value,
newSCP.set('parentSCP', serviceConfigProperty);
newSCP.set('isEditable', true);
console.debug("createOverrideProperty(): Added:", newSCP, " to main-property:", serviceConfigProperty);
overrides.pushObject(newSCP);
},
/**
* trigger manageConfigurationGroups
* @method manageConfigurationGroup
*/
manageConfigurationGroup: function () {
this.manageConfigurationGroups();
},
manageConfigurationGroups: function (controller) {
var serviceData = (controller && controller.get('selectedService')) || this.get('content');
var serviceName = serviceData.get('serviceName');
var displayName = serviceData.get('displayName');
App.router.get('manageConfigGroupsController').set('isInstaller', !!controller);
App.router.get('manageConfigGroupsController').set('serviceName', serviceName);
if (controller) {
App.router.get('manageConfigGroupsController').set('isAddService', controller.get('content.controllerName') == 'addServiceController');
}
return App.ModalPopup.show({
header: Em.I18n.t('services.service.config_groups_popup.header').format(displayName),
bodyClass: App.MainServiceManageConfigGroupView.extend({
serviceName: serviceName,
displayName: displayName,
controllerBinding: 'App.router.manageConfigGroupsController'
}),
classNames: ['sixty-percent-width-modal', 'manage-configuration-group-popup'],
primary: Em.I18n.t('common.save'),
onPrimary: function () {
var modifiedConfigGroups = this.get('subViewController.hostsModifiedConfigGroups');
// Save modified config-groups
if (!!controller) {
controller.set('selectedService.configGroups', App.router.get('manageConfigGroupsController.configGroups'));
controller.selectedServiceObserver();
if (controller.get('name') == "wizardStep7Controller") {
if (controller.get('selectedService.selected') === false && modifiedConfigGroups.toDelete.length > 0) {
controller.setGroupsToDelete(modifiedConfigGroups.toDelete);
}
App.config.persistWizardStep7ConfigGroups();
this.updateConfigGroupOnServicePage();
}
this.hide();
return;
}
console.log("manageConfigurationGroups(): Saving modified config-groups: ", modifiedConfigGroups);
var self = this;
var errors = [];
var deleteQueriesCounter = modifiedConfigGroups.toClearHosts.length + modifiedConfigGroups.toDelete.length;
var createQueriesCounter = modifiedConfigGroups.toSetHosts.length + modifiedConfigGroups.toCreate.length;
var deleteQueriesRun = false;
var createQueriesRun = false;
var runNextQuery = function () {
if (!deleteQueriesRun && deleteQueriesCounter > 0) {
deleteQueriesRun = true;
modifiedConfigGroups.toClearHosts.forEach(function (cg) {
App.config.clearConfigurationGroupHosts(cg, finishFunction, finishFunction);
}, this);
modifiedConfigGroups.toDelete.forEach(function (cg) {
App.config.deleteConfigGroup(cg, finishFunction, finishFunction);
}, this);
} else if (!createQueriesRun && deleteQueriesCounter < 1) {
createQueriesRun = true;
modifiedConfigGroups.toSetHosts.forEach(function (cg) {
App.config.updateConfigurationGroup(cg, finishFunction, finishFunction);
}, this);
modifiedConfigGroups.toCreate.forEach(function (cg) {
App.config.postNewConfigurationGroup(cg, finishFunction);
}, this);
}
};
var finishFunction = function (xhr, text, errorThrown) {
if (xhr && errorThrown) {
var error = xhr.status + "(" + errorThrown + ") ";
try {
var json = $.parseJSON(xhr.responseText);
error += json.message;
} catch (err) {
}
console.error('Error updating Config Group:', error);
errors.push(error);
}
if (createQueriesRun) {
createQueriesCounter--;
} else {
deleteQueriesCounter--;
}
if (deleteQueriesCounter + createQueriesCounter < 1) {
if (errors.length > 0) {
console.log(errors);
self.get('subViewController').set('errorMessage', errors.join(". "));
} else {
self.updateConfigGroupOnServicePage();
self.hide();
}
} else {
runNextQuery();
}
};
runNextQuery();
},
onSecondary: function () {
this.hide();
},
onClose: function () {
this.hide();
},
subViewController: function () {
return App.router.get('manageConfigGroupsController');
}.property('App.router.manageConfigGroupsController'),
updateConfigGroupOnServicePage: function () {
var subViewController = this.get('subViewController');
var selectedConfigGroup = subViewController.get('selectedConfigGroup');
var managedConfigGroups = subViewController.get('configGroups');
if (!controller) {
controller = App.router.get('mainServiceInfoConfigsController');
controller.set('configGroups', managedConfigGroups);
} else {
controller.set('selectedService.configGroups', managedConfigGroups);
}
var selectEventObject = {};
//check whether selectedConfigGroup exists
if (selectedConfigGroup && controller.get('configGroups').someProperty('name', selectedConfigGroup.get('name'))) {
selectEventObject.context = selectedConfigGroup;
} else {
selectEventObject.context = managedConfigGroups.findProperty('isDefault', true);
}
controller.selectConfigGroup(selectEventObject);
},
updateButtons: function () {
var modified = this.get('subViewController.isHostsModified');
this.set('disablePrimary', !modified);
}.observes('subViewController.isHostsModified'),
secondary: Em.I18n.t('common.cancel'),
didInsertElement: Em.K
});
},
/**
* If user changes cfg group if some configs was changed popup with propose to save changes must be shown
* @param {object} event - triggered event for selecting another config-group
* @method selectConfigGroup
*/
selectConfigGroup: function (event) {
var self = this;
function callback() {
self.doSelectConfigGroup(event);
}
if (!this.get('isInit')) {
if (this.hasUnsavedChanges()) {
this.showSavePopup(null, callback);
return;
}
}
callback();
},
/**
* switch view to selected group
* @param event
* @method selectConfigGroup
*/
doSelectConfigGroup: function (event) {
//clean when switch config group
this.loadedGroupToOverrideSiteToTagMap = {};
var configGroupVersions = App.ServiceConfigVersion.find().filterProperty('groupId', event.context.get('id'));
//check whether config group has config versions
if (configGroupVersions.length > 0) {
this.loadSelectedVersion(configGroupVersions.findProperty('isCurrent').get('version'), event.context);
} else {
this.loadSelectedVersion(null, event.context);
}
},
/**
* Are some unsaved changes available
* @returns {boolean}
*/
hasUnsavedChanges: function () {
return this.get('hash') != this.getHash();
},
/**
* If some configs are changed and user navigates away or select another config-group, show this popup with propose to save changes
* @param {String} path
* @param {object} callback - callback with action to change configs view(change group or version)
* @method showSavePopup
*/
showSavePopup: function (path, callback) {
var self = this;
return App.ModalPopup.show({
header: Em.I18n.t('common.warning'),
bodyClass: Em.View.extend({
templateName: require('templates/common/configs/save_configuration'),
showSaveWarning: true,
notesArea: Em.TextArea.extend({
classNames: ['full-width'],
placeholder: Em.I18n.t('dashboard.configHistory.info-bar.save.popup.placeholder'),
onChangeValue: function() {
this.get('parentView.parentView').set('serviceConfigNote', this.get('value'));
}.observes('value')
})
}),
footerClass: Ember.View.extend({
templateName: require('templates/main/service/info/save_popup_footer')
}),
primary: Em.I18n.t('common.save'),
secondary: Em.I18n.t('common.cancel'),
onSave: function () {
self.set('serviceConfigVersionNote', this.get('serviceConfigNote'));
self.restartServicePopup();
this.hide();
},
onDiscard: function () {
self.set('preSelectedConfigVersion', null);
if (path) {
self.set('forceTransition', true);
App.router.route(path);
} else if (callback) {
// Prevent multiple popups
self.set('hash', self.getHash());
callback();
}
this.hide();
},
onCancel: function () {
this.hide();
}
});
}
});