AMBARI-14416. Refactor Host Details controller
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6c38d84b Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6c38d84b Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6c38d84b Branch: refs/heads/branch-dev-patch-upgrade Commit: 6c38d84b1152807c0b94f175e090d90ad0c74a28 Parents: 2c7ecd1 Author: Alex Antonenko <hiv...@gmail.com> Authored: Fri Dec 18 18:59:19 2015 +0200 Committer: Alex Antonenko <hiv...@gmail.com> Committed: Fri Dec 18 18:59:19 2015 +0200 ---------------------------------------------------------------------- ambari-web/app/controllers/main/host/details.js | 256 ++++--- ambari-web/app/messages.js | 6 +- ambari-web/app/mixins.js | 1 + .../configs/add_component_config_initializer.js | 303 ++++++++ .../app/utils/configs/config_initializer.js | 622 +++------------ .../utils/configs/config_initializer_class.js | 97 ++- .../configs/control_flow_initializer_mixin.js | 127 ++++ .../configs/ha_config_initializer_class.js | 167 +---- .../configs/hosts_based_initializer_mixin.js | 401 ++++++++++ .../mount_points_based_initializer_mixin.js | 326 ++++++++ .../utils/configs/nn_ha_config_initializer.js | 76 +- .../utils/configs/rm_ha_config_initializer.js | 31 +- .../test/controllers/main/host/details_test.js | 750 ++++++++++++++----- 13 files changed, 2095 insertions(+), 1068 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/controllers/main/host/details.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/host/details.js b/ambari-web/app/controllers/main/host/details.js index ea1a168..8ec521e 100644 --- a/ambari-web/app/controllers/main/host/details.js +++ b/ambari-web/app/controllers/main/host/details.js @@ -20,6 +20,7 @@ var App = require('app'); var batchUtils = require('utils/batch_scheduled_requests'); var hostsManagement = require('utils/hosts'); var stringUtils = require('utils/string_utils'); +require('utils/configs/add_component_config_initializer'); App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDownload, App.InstallComponent, App.InstallNewVersion, { @@ -761,11 +762,56 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow * @method updateZkConfigs */ updateZkConfigs: function (configs) { - var zks = this.getZkServerHosts(); var portValue = configs['zoo.cfg'] && Em.get(configs['zoo.cfg'], 'clientPort'); - var zkPort = typeof portValue === 'udefined' ? '2181' : portValue; - var zksWithPort = this.concatZkNames(zks, zkPort); - this.setZKConfigs(configs, zksWithPort, zks); + var zkPort = typeof portValue === 'undefined' ? '2181' : portValue; + var initializer = App.AddZooKeeperComponentsInitializer; + var hostComponentsTopology = { + masterComponentHosts: [] + }; + var masterComponents = this.bootstrapHostsMapping('ZOOKEEPER_SERVER'); + if (this.get('fromDeleteHost') || this.get('fromDeleteZkServer')) { + this.set('fromDeleteHost', false); + this.set('fromDeleteZkServer', false); + var removedHost = masterComponents.findProperty('hostName', this.get('content.hostName')); + if (!Em.isNone(removedHost)) { + Em.set(removedHost, 'isInstalled', false); + } + } + var dependencies = { + zkClientPort: zkPort + }; + hostComponentsTopology.masterComponentHosts = masterComponents; + Em.keys(configs).forEach(function(fileName) { + var properties = configs[fileName]; + Em.keys(properties).forEach(function(propertyName) { + var propertyDef = { + fileName: fileName, + name: propertyName, + value: properties[propertyName] + }; + var configProperty = initializer.initialValue(propertyDef, hostComponentsTopology, dependencies); + initializer.updateSiteObj(configs[fileName], configProperty); + }); + }); + }, + + /** + * + * @param {string} componentName + * @param {string[]} [hostNames] + * @returns {} + */ + bootstrapHostsMapping: function(componentName, hostNames) { + if (Em.isNone(hostNames)) { + hostNames = App.HostComponent.find().filterProperty('componentName', componentName).mapProperty('hostName'); + } + return hostNames.map(function(hostName) { + return { + component: componentName, + hostName: hostName, + isInstalled: true + }; + }); }, /** @@ -827,35 +873,49 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow * @method onLoadHiveConfigs */ onLoadHiveConfigs: function (data) { - var - hiveMetastoreHost = this.get('hiveMetastoreHost'), - webhcatServerHost = this.get('webhcatServerHost'), - hiveMSHosts = this.getHiveHosts(), - hiveMasterHosts = hiveMSHosts.concat(App.HostComponent.find().filterProperty('componentName', 'HIVE_SERVER').mapProperty('hostName')).uniq().sort().join(','), - configs = {}, - attributes = {}, - port = "", - hiveUser = "", - webhcatUser = ""; - + var hiveMetastoreHost = this.get('hiveMetastoreHost'); + var webhcatServerHost = this.get('webhcatServerHost'); + var port = ""; + var configs = {}; + var attributes = {}; + var localDB = { + masterComponentHosts: this.getHiveHosts() + }; + var dependencies = { + hiveMetastorePort: "" + }; + var initializer = App.AddHiveComponentsInitializer; data.items.forEach(function (item) { configs[item.type] = item.properties; attributes[item.type] = item.properties_attributes || {}; }, this); + port = configs['hive-site']['hive.metastore.uris'].match(/:[0-9]{2,4}/); port = port ? port[0].slice(1) : "9083"; - hiveUser = configs['hive-env']['hive_user']; - webhcatUser = configs['hive-env']['webhcat_user']; + dependencies.hiveMetastorePort = port; + + initializer.setup({ + hiveUser: configs['hive-env']['hive_user'], + webhcatUser: configs['hive-env']['webhcat_user'] + }); + + ['hive-site', 'webhcat-site', 'hive-env', 'core-site'].forEach(function(fileName) { + if (configs[fileName]) { + Em.keys(configs[fileName]).forEach(function(propertyName) { + var propertyDef = { + fileName: fileName, + name: propertyName, + value: configs[fileName][propertyName] + }; + configs[fileName][propertyName] = Em.get(initializer.initialValue(propertyDef, localDB, dependencies), 'value'); + }); + } + }); + + initializer.cleanup(); - for (var i = 0; i < hiveMSHosts.length; i++) { - hiveMSHosts[i] = "thrift://" + hiveMSHosts[i] + ":" + port; - } - configs['hive-site']['hive.metastore.uris'] = hiveMSHosts.join(','); - configs['webhcat-site']['templeton.hive.properties'] = configs['webhcat-site']['templeton.hive.properties'].replace(/thrift.+[0-9]{2,},/i, hiveMSHosts.join('\\,') + ","); - configs['core-site']['hadoop.proxyuser.' + hiveUser + '.hosts'] = hiveMasterHosts; - configs['core-site']['hadoop.proxyuser.' + webhcatUser + '.hosts'] = hiveMasterHosts; var groups = [ { properties: { @@ -953,32 +1013,47 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow deleteWebHCatServer: false, getHiveHosts: function () { - var - hiveHosts = App.HostComponent.find().filterProperty('componentName', 'HIVE_METASTORE').mapProperty('hostName'), - webhcatHosts = App.HostComponent.find().filterProperty('componentName', 'WEBHCAT_SERVER').mapProperty('hostName'), - hiveMetastoreHost = this.get('hiveMetastoreHost'), - webhcatServerHost = this.get('webhcatServerHost'); + var self = this; + var removePerformed = this.get('fromDeleteHost') || this.get('deleteHiveMetaStore') || this.get('deleteHiveServer') || this.get('deleteWebHCatServer'); + var hiveMasterComponents = ['WEBHCAT_SERVER', 'HIVE_METASTORE', 'HIVE_SERVER']; + var masterComponentsMap = hiveMasterComponents.map(function(componentName) { + return self.bootstrapHostsMapping(componentName); + }).reduce(function(p,c) { + return p.concat(c); + }); - hiveHosts = hiveHosts.concat(webhcatHosts).uniq(); + if (removePerformed) { + self.setProperties({ + deleteHiveMetaStore: false, + deleteHiveServer: false, + deleteWebHCatServer: false, + fromDeleteHost: false + }); + masterComponentsMap = masterComponentsMap.map(function(masterComponent) { + masterComponent.isInstalled = masterComponent.hostName !== self.get('content.hostName'); + return masterComponent; + }); + } - if (!!hiveMetastoreHost) { - hiveHosts.push(hiveMetastoreHost); + if (!!this.get('hiveMetastoreHost')) { + masterComponentsMap.push({ + component: 'HIVE_METASTORE', + hostName: this.get('hiveMetastoreHost'), + isInstalled: !removePerformed + }); this.set('hiveMetastoreHost', ''); } - if (!!webhcatServerHost) { - hiveHosts.push(webhcatServerHost); - this.set('webhcatServerHost' ,''); + if (!!this.get('webhcatServerHost')) { + masterComponentsMap.push({ + component: 'WEBHCAT_SERVER', + hostName: this.get('webhcatServerHost'), + isInstalled: !removePerformed + }); + this.set('webhcatServerHost', ''); } - if (this.get('fromDeleteHost') || this.get('deleteHiveMetaStore') || this.get('deleteHiveServer') || this.get('deleteWebHCatServer')) { - this.set('deleteHiveMetaStore', false); - this.set('deleteHiveServer', false); - this.set('deleteWebHCatServer', false); - this.set('fromDeleteHost', false); - hiveHosts = hiveHosts.without(this.get('content.hostName')); - } - return hiveHosts.sort(); + return masterComponentsMap; }, /** @@ -1218,6 +1293,9 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow urlParams.push('(type=yarn-site&tag=' + data.Clusters.desired_configs['yarn-site'].tag + ')'); urlParams.push('(type=zoo.cfg&tag=' + data.Clusters.desired_configs['zoo.cfg'].tag + ')'); } + if (services.someProperty('serviceName', 'ACCUMULO')) { + urlParams.push('(type=accumulo-site&tag=' + data.Clusters.desired_configs['accumulo-site'].tag + ')'); + } return urlParams; }, @@ -1260,62 +1338,31 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow } ); } - this.saveConfigsBatch(groups, 'ZOOKEEPER_SERVER'); - }, - /** - * - * Set new values for some configs (based on available ZooKeeper Servers) - * @param configs {object} - * @param zksWithPort {string} - * @param zks {array} - * @return {Boolean} - */ - setZKConfigs: function (configs, zksWithPort, zks) { - if (typeof configs !== 'object' || !Array.isArray(zks)) return false; - if (App.get('isHaEnabled') && configs['core-site']) { - App.config.updateHostsListValue(configs['core-site'], 'ha.zookeeper.quorum', zksWithPort); - } - if (configs['hbase-site']) { - App.config.updateHostsListValue(configs['hbase-site'], 'hbase.zookeeper.quorum', zks.join(',')); - } - if (configs['accumulo-site']) { - App.config.updateHostsListValue(configs['accumulo-site'], 'instance.zookeeper.host', zksWithPort); - } - if (configs['webhcat-site']) { - App.config.updateHostsListValue(configs['webhcat-site'], 'templeton.zookeeper.hosts', zksWithPort); - } - if (configs['hive-site']) { - App.config.updateHostsListValue(configs['hive-site'], 'hive.cluster.delegation.token.store.zookeeper.connectString', zksWithPort); - } - if (configs['storm-site']) { - configs['storm-site']['storm.zookeeper.servers'] = JSON.stringify(zks).replace(/"/g, "'"); - } - if (App.get('isRMHaEnabled') && configs['yarn-site']) { - App.config.updateHostsListValue(configs['yarn-site'], 'yarn.resourcemanager.zk-address', zksWithPort); + if (App.Service.find().someProperty('serviceName', 'HBASE')) { + groups.push( + { + properties: { + 'hbase-site': configs['hbase-site'] + }, + properties_attributes: { + 'hbase-site': attributes['hbase-site'] + } + } + ); } - if (App.get('isHadoop22Stack')) { - if (configs['hive-site']) { - App.config.updateHostsListValue(configs['hive-site'], 'hive.zookeeper.quorum', zksWithPort); - } - if (configs['yarn-site']) { - App.config.updateHostsListValue(configs['yarn-site'], 'hadoop.registry.zk.quorum', zksWithPort); - App.config.updateHostsListValue(configs['yarn-site'], 'yarn.resourcemanager.zk-address', zksWithPort); - } + if (App.Service.find().someProperty('serviceName', 'ACCUMULO')) { + groups.push( + { + properties: { + 'accumulo-site': configs['accumulo-site'] + }, + properties_attributes: { + 'accumulo-site': attributes['accumulo-site'] + } + } + ); } - return true; - }, - /** - * concatenate URLs to ZOOKEEPER hosts with port "2181", - * as value of config divided by comma - * @param zks {array} - * @param port {string} - */ - concatZkNames: function (zks, port) { - var zks_with_port = ''; - zks.forEach(function (zk) { - zks_with_port += zk + ':' + port + ','; - }); - return zks_with_port.slice(0, -1); + this.saveConfigsBatch(groups, 'ZOOKEEPER_SERVER'); }, /** @@ -1331,21 +1378,6 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow fromDeleteZkServer: false, /** - * Get list of hostnames where ZK Server is installed - * @returns {string[]} - * @method getZkServerHosts - */ - getZkServerHosts: function () { - var zks = App.HostComponent.find().filterProperty('componentName', 'ZOOKEEPER_SERVER').mapProperty('hostName'); - if (this.get('fromDeleteHost') || this.get('fromDeleteZkServer')) { - this.set('fromDeleteHost', false); - this.set('fromDeleteZkServer', false); - return zks.without(this.get('content.hostName')); - } - return zks; - }, - - /** * Send command to server to install selected host component * @param {Object} event * @method installComponent http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index bd71c2f..12402fd 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -2302,14 +2302,14 @@ Em.I18n.translations = { 'host.host.componentFilter.slave':'Slave Components', 'host.host.componentFilter.client':'Client Components', 'hosts.host.deleteComponent.popup.msg1':'Are you sure you want to delete {0}?', - 'hosts.host.deleteComponent.popup.deleteZooKeeperServer':'Deleting <i>ZooKeeper Server</i> may reconfigure such properties:<ul><li>ha.zookeeper.quorum</li><li>hbase.zookeeper.quorum</li><li>templeton.zookeeper.hosts</li><li>yarn.resourcemanager.zk-address</li><li>hive.zookeeper.quorum</li><li>hive.cluster.delegation.token.store.zookeeper.connectString</li></ul>', + 'hosts.host.deleteComponent.popup.deleteZooKeeperServer':'Deleting <i>ZooKeeper Server</i> may reconfigure such properties:<ul><li>ha.zookeeper.quorum</li><li>hbase.zookeeper.quorum</li><li>templeton.zookeeper.hosts</li><li>yarn.resourcemanager.zk-address</li><li>hive.zookeeper.quorum</li><li>hive.cluster.delegation.token.store.zookeeper.connectString</li><li>storm.zookeeper.servers</li><li>instance.zookeeper.host</li></ul>', 'hosts.host.deleteComponent.popup.deleteRangerKMSServer': 'Deleting <i>Ranger KMS Server</i> may reconfigure such properties:<ul><li>hadoop.security.key.provider.path</li><li>dfs.encryption.key.provider.uri</li>', 'hosts.host.deleteComponent.popup.warning':'<b>WARNING!</b> Delete the last <i>{0}</i> component in the cluster?</br>Deleting the last component in the cluster could result in permanent loss of service data.', 'hosts.host.deleteComponent.popup.confirm':'Confirm Delete', 'hosts.host.installComponent.popup.confirm':'Confirm Install', 'hosts.host.installComponent.msg':'Are you sure you want to install {0}?', 'hosts.host.addComponent.msg':'Are you sure you want to add {0}?', - 'hosts.host.addComponent.ZOOKEEPER_SERVER':'Adding ZooKeeper Server may reconfigure such properties:<ul><li>ha.zookeeper.quorum</li><li>hbase.zookeeper.quorum</li><li>templeton.zookeeper.hosts</li><li>yarn.resourcemanager.zk-address</li><li>hive.zookeeper.quorum</li><li>hive.cluster.delegation.token.store.zookeeper.connectString</li></ul>', + 'hosts.host.addComponent.ZOOKEEPER_SERVER':'Adding ZooKeeper Server may reconfigure such properties:<ul><li>ha.zookeeper.quorum</li><li>hbase.zookeeper.quorum</li><li>templeton.zookeeper.hosts</li><li>yarn.resourcemanager.zk-address</li><li>hive.zookeeper.quorum</li><li>hive.cluster.delegation.token.store.zookeeper.connectString</li><li>storm.zookeeper.servers</li><li>instance.zookeeper.host</li></ul>', 'hosts.host.addComponent.NIMBUS': 'Adding Nimbus will reconfigure <b>nimbus.seeds</b>, <b>topology.min.replication.count</b>, <b>topology.max.replication.wait.time.sec</b> properties if they are defined.', 'hosts.host.addComponent.RANGER_KMS_SERVER': 'Adding Ranger KMS Server may reconfigure such properties:<ul><li>hadoop.security.key.provider.path</li><li>dfs.encryption.key.provider.uri</li>', 'hosts.host.addComponent.deleteHostWithZooKeeper':'Deleting host with ZooKeeper Server may reconfigure such properties:<ul><li>ha.zookeeper.quorum</li><li>hbase.zookeeper.quorum</li><li>templeton.zookeeper.hosts</li><li>yarn.resourcemanager.zk-address</li><li>hive.zookeeper.quorum</li><li>hive.cluster.delegation.token.store.zookeeper.connectString</li></ul>', @@ -2819,4 +2819,4 @@ Em.I18n.translations = { 'utils.ajax.defaultErrorPopupBody.statusCode': '{0} status code', 'wizard.inProgress': '{0} in Progress' -}; \ No newline at end of file +}; http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/mixins.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins.js b/ambari-web/app/mixins.js index 276e777..90fbaa2 100644 --- a/ambari-web/app/mixins.js +++ b/ambari-web/app/mixins.js @@ -56,3 +56,4 @@ require('mixins/common/widgets/widget_mixin'); require('mixins/common/widgets/widget_section'); require('mixins/unit_convert/base_unit_convert_mixin'); require('mixins/unit_convert/convert_unit_widget_view_mixin'); +require('utils/configs/mount_points_based_initializer_mixin'); http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/utils/configs/add_component_config_initializer.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/configs/add_component_config_initializer.js b/ambari-web/app/utils/configs/add_component_config_initializer.js new file mode 100644 index 0000000..6fc505c --- /dev/null +++ b/ambari-web/app/utils/configs/add_component_config_initializer.js @@ -0,0 +1,303 @@ +/** + * 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('utils/configs/config_initializer_class'); +require('utils/configs/ha_config_initializer_class'); +require('utils/configs/hosts_based_initializer_mixin'); +require('utils/configs/control_flow_initializer_mixin'); + +var _slice = Array.prototype.slice; + +/** + * Main class responsible for properties computation. + * This class contains all required info to manipulate properties regarding value updates + * during removing/adding components. + * To determine when component removed or added you just need to setup properly localDB object + * and set `isInstalled` flag to `true` where selected component(s) will be located after adding/removing. + * By default all initializer handlers filtering localDB by `isInstalled` `true`. + * + * @mixes App.ControlFlowInitializerMixin + * @mixes App.HostsBasedInitializerMixin + * @type {AddComponentConfigInitializer} + * @augments {HaConfigInitializerClass} + */ +App.AddComponentConfigInitializer = App.HaConfigInitializerClass.extend(App.HostsBasedInitializerMixin, App.ControlFlowInitializerMixin, { + /** + * All initializer properties definition. + * Object format is the same as for App.ConfigInitializerClass.initializers + * @see App.ConfigInitializerClass.initializers + * + * @return {object} property name - initializer map + */ + __defaultInitializers: function() { + return { + 'ha.zookeeper.quorum': this.getNameNodeHAOnlyHostsPortConfig('ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true), + 'hbase.zookeeper.quorum': this.getHostsListComponentConfig('ZOOKEEPER_SERVER', true), + 'instance.zookeeper.host': this.getHostsWithPortConfig('ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true), + 'templeton.zookeeper.hosts': this.getHostsWithPortConfig('ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true), + 'hive.cluster.delegation.token.store.zookeeper.connectString': this.getHostsWithPortConfig('ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true), + 'storm.zookeeper.servers': this.getHostsListComponentJSONStringifiedConfig('ZOOKEEPER_SERVER', true), + 'hive.zookeeper.quorum': this.getHDPStackOnlyHostsPortConfig('2.2', 'ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true), + 'hadoop.registry.zk.quorum': this.getHDPStackOnlyHostsPortConfig('2.2', 'ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true), + 'nimbus.seeds': this.getHostsListComponentJSONStringifiedConfig('NIMBUS', true), + 'hadoop.proxyuser.{{hiveUser}}.hosts': this.getComponentsHostsConfig(['HIVE_SERVER', 'WEBHCAT_SERVER', 'HIVE_METASTORE'], false), + 'hadoop.proxyuser.{{webhcatUser}}.hosts': this.getComponentsHostsConfig(['HIVE_SERVER', 'WEBHCAT_SERVER', 'HIVE_METASTORE'], false, true), + 'hadoop.proxyuser.{{hiveUser}}.hosts': this.getComponentsHostsConfig(['HIVE_SERVER', 'WEBHCAT_SERVER', 'HIVE_METASTORE'], false, true), + 'hive.metastore.uris': this.getHostsWithPortConfig(['WEBHCAT_SERVER', 'HIVE_METASTORE'], 'thrift://', '', ',thrift://', 'hiveMetastorePort', true) + }; + }, + + /** + * All unique initializer definition. + * Object format is the same as for App.ConfigInitializerClass.uniqueInitializers + * @see App.ConfigInitializerClass.uniqueInitializers + * + * @type {Object} + */ + __defaultUniqueInitializers: { + 'yarn.resourcemanager.zk-address': '_initYarnRMZkAdress', + 'templeton.hive.properties': '_initTempletonHiveProperties' + }, + + /** + * Property names to initialize. This attribute should be overrided in class instance. + * `initializers` property will set up according this list from `__defaultUniqueInitializers` and + * `__defaultInitializers` + * + * @type {string[]} + */ + initializeForProperties: null, + + initializers: function() { + return {}; + }.property(), + + uniqueInitializers: {}, + + init: function() { + this._super(); + this._bootstrapInitializers(this.get('initializeForProperties')); + }, + + initializerTypes: [ + { + name: 'json_stringified_value', + method: '_initAsJSONStrigifiedValueConfig' + } + ], + + /** + * @override + * @param {object} settings + */ + setup: function (settings) { + this._updateInitializers(settings); + }, + + /** + * @override + */ + cleanup: function () { + this._restoreInitializers(); + }, + + getJSONStringifiedValueConfig: function() { + return { + type: 'json_stringified_value' + }; + }, + + _initAsJSONStrigifiedValueConfig: function(configProperty, localDB, dependencies, initializer) { + var hostsValue = Em.get(configProperty, 'value').split(Em.getWithDefault(initializer, 'modifier.delimiter', ',')); + var propertyValue = JSON.stringify(hostsValue).replace(/"/g, "'"); + Em.setProperties(configProperty, { + value: propertyValue, + recommendedValue: propertyValue + }); + return configProperty; + }, + + /** + * Perform value update according to hosts. Mutate <code>siteConfigs</code> + * + * @param {object} siteConfigs + * @param {configProperty} configProperty + * @returns {boolean} + */ + updateSiteObj: function(siteConfigs, configProperty) { + if (!siteConfigs || !configProperty) return false; + App.config.updateHostsListValue(siteConfigs, configProperty.name, configProperty.value); + return true; + }, + + /** + * @see App.ControlFlowInitializerMixin.getNameNodeHAControl + * @see App.HostsBasedInitializerMixin.getComponentsHostsConfig + */ + getNameNodeHAOnlyHostsConfig: function(components, asArray) { + return [ + this.getNameNodeHAControl(), + this.getComponentsHostsConfig.apply(this, _slice.call(arguments)) + ]; + }, + + /** + * @override + **/ + getHostsWithPortConfig: function (component, prefix, suffix, delimiter, port, portFromDependencies) { + var ret = this._super.apply(this, _slice.call(arguments)); + ret.componentExists = true; + return ret; + }, + + /** + * @see App.ControlFlowInitializerMixin.getNameNodeHAControl + * @see App.HostsBasedInitializerMixin.getHostsWithPortConfig + */ + getNameNodeHAOnlyHostsPortConfig: function(component, prefix, suffix, delimiter, port, portFromDependencies) { + return [ + this.getNameNodeHAControl(), + this.getHostsWithPortConfig.apply(this, _slice.call(arguments)) + ]; + }, + + /** + * @see App.ControlFlowInitializerMixin.getResourceManagerHAControl + * @see App.HostsBasedInitializerMixin.getHostsWithPortConfig + */ + getResourceManagerHAOnlyHostsPortConfig: function(component, prefix, suffix, delimiter, port, portFromDependencies) { + return [ + this.getResourceManagerHAControl(), + this.getHostsWithPortConfig.apply(this, _slice.call(arguments)) + ]; + }, + + /** + * @see App.HostsBasedInitializerMixin.getHostsListComponentConfig + * @see getJSONStringifiedValueConfig + */ + getHostsListComponentJSONStringifiedConfig: function(component, componentExists, delimiter) { + return [ + this.getHostsListComponentConfig.apply(this, _slice.call(arguments)), + this.getJSONStringifiedValueConfig() + ]; + }, + + /** + * @see App.ControlFlowInitializerMixin.getHDPStackVersionControl + * @see App.HostsBasedInitializerMixin.getHostsWithPortConfig + */ + getHDPStackOnlyHostsPortConfig: function(minStackVersion, component, prefix, suffix, delimiter, port, portFromDependencies) { + return [ + this.getHDPStackVersionControl(minStackVersion), + this.getHostsWithPortConfig.apply(this, _slice.call(arguments, 1)) + ]; + }, + + _initYarnRMZkAdress: function(configProperty, localDB, dependencies) { + if (App.get('isRMHaEnabled') || App.get('isHadoop22Stack')) { + return this._initAsHostsWithPort(configProperty, localDB, dependencies, { + component: 'ZOOKEEPER_SERVER', + componentExists: true, + modifier: { + prefix: '', + suffix: '', + delimiter: ',' + }, + portKey: 'zkClientPort' + }); + } else { + return configProperty; + } + }, + + _initTempletonHiveProperties: function(configProperty, localDB, dependecies, initializer) { + var hostNames = localDB.masterComponentHosts.filter(function(masterComponent) { + return ['WEBHCAT_SERVER', 'HIVE_METASTORE'].contains(masterComponent.component) && masterComponent.isInstalled === true; + }).mapProperty('hostName').uniq().sort(); + var hiveMSHosts = hostNames.map(function(hostName) { + return "thrift://" + hostName + ":" + dependecies.hiveMetastorePort; + }).join('\\,'); + var value = configProperty.value.replace(/thrift.+[0-9]{2,},/i, hiveMSHosts + ","); + Em.setProperties(configProperty, { + value: value, + recommendedValue: value + }); + return configProperty; + }, + + /** + * Set up `this.initializers` and `this.uniqueInitializers` properties according + * to property list names. + * + * @param {string[]} properties list of property names + */ + _bootstrapInitializers: function(properties) { + var initializers = {}, + uniqueInitializers = {}, + defaultInitializers = this.__defaultInitializers(), + defaultUniqueInitializers = this.get('__defaultUniqueInitializers'); + + if (Em.isNone(properties)) { + initializers = this.__defaultInitializers(); + uniqueInitializer = this.get('__defaultUniqueInitializers'); + } else { + properties.forEach(function(propertyName) { + if (defaultInitializers[propertyName]) { + initializers[propertyName] = defaultInitializers[propertyName]; + } else if (defaultUniqueInitializers[propertyName]) { + uniqueInitializers[propertyName] = defaultUniqueInitializers[propertyName]; + } + }); + } + this._setForComputed('initializers', initializers); + this.set('uniqueInitializers', uniqueInitializers); + } +}); + +/** + * ZooKeeper service add/remove components initializer. + * @instance App.AddComponentConfigInitializer + */ +App.AddZooKeeperComponentsInitializer = App.AddComponentConfigInitializer.create({ + initializeForProperties: [ + 'ha.zookeeper.quorum', + 'hbase.zookeeper.quorum', + 'instance.zookeeper.host', + 'templeton.zookeeper.hosts', + 'hive.cluster.delegation.token.store.zookeeper.connectString', + 'yarn.resourcemanager.zk-address', + 'hive.zookeeper.quorum', + 'storm.zookeeper.servers', + 'hadoop.registry.zk.quorum' + ] +}); + +/** + * Hive service add/remove components initializer. + * @instance App.AddComponentConfigInitializer + */ +App.AddHiveComponentsInitializer = App.AddComponentConfigInitializer.create({ + initializeForProperties: [ + 'hive.metastore.uris', + 'templeton.hive.properties', + 'hadoop.proxyuser.{{webhcatUser}}.hosts', + 'hadoop.proxyuser.{{hiveUser}}.hosts' + ] +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/utils/configs/config_initializer.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/configs/config_initializer.js b/ambari-web/app/utils/configs/config_initializer.js index 8c156bb..df520d2 100644 --- a/ambari-web/app/utils/configs/config_initializer.js +++ b/ambari-web/app/utils/configs/config_initializer.js @@ -17,57 +17,11 @@ */ var App = require('app'); -require('utils/configs/config_initializer_class'); var stringUtils = require('utils/string_utils'); -/** - * Regexp for host with port ('hostName:1234') - * - * @type {string} - */ -var hostWithPort = "([\\w|\\.]*)(?=:)"; - -/** - * Regexp for host with port and protocol ('://hostName:1234') - * - * @type {string} - */ -var hostWithPrefix = ":\/\/" + hostWithPort; - -/** - * Regexp used to determine if mount point is windows-like - * - * @type {RegExp} - */ -var winRegex = /^([a-z]):\\?$/; - -/** - * Settings for <code>host_with_component</code>-initializer - * Used for configs with value equal to hostName that has <code>component</code> - * Value may be modified with if <code>withModifier</code> is true (it is by default) - * <code>hostWithPort</code>-regexp will be used in this case - * - * @see _initAsHostWithComponent - * @param {string} component - * @param {boolean} [withModifier=true] - * @return {object} - */ -function getSimpleComponentConfig(component, withModifier) { - if (arguments.length === 1) { - withModifier = true; - } - var config = { - type: 'host_with_component', - component: component - }; - if (withModifier) { - config.modifier = { - type: 'regexp', - regex: hostWithPort - } - } - return config; -} +require('utils/configs/config_initializer_class'); +require('utils/configs/mount_points_based_initializer_mixin'); +require('utils/configs/hosts_based_initializer_mixin'); /** * Zookeeper-based configs don't have any customization settings @@ -82,90 +36,6 @@ function getZKBasedConfig() { } /** - * Almost the same to <code>getSimpleComponentConfig</code>, but with possibility to modify <code>replaceWith</code>-value - * <code>prefix</code> is added before it - * <code>suffix</code> is added after it - * <code>hostWithPrefix</code>-regexp is used - * - * @see _initAsHostWithComponent - * @param {string} component - * @param {string} [prefix] - * @param {string} [suffix] - * @returns {object} - */ -function getComponentConfigWithAffixes (component, prefix, suffix) { - prefix = prefix || ''; - suffix = suffix || ''; - return { - type: 'host_with_component', - component: component, - modifier: { - type: 'regexp', - regex: hostWithPrefix, - prefix: prefix, - suffix: suffix - } - }; -} - -/** - * Settings for <code>hosts_with_components</code>-initializer - * Used for configs with value equal to the hosts list - * May set value as array (if <code>asArray</code> is true) or as comma-sepratated string (if <code>asArray</code> is false) - * - * @see _initAsHostsWithComponents - * @param {string|string[]} components - * @param {boolean} [asArray=false] - * @returns {{type: string, components: string[], asArray: boolean}} - */ -function getComponentsHostsConfig(components, asArray) { - if (1 === arguments.length) { - asArray = false; - } - return { - type: 'hosts_with_components', - components: Em.makeArray(components), - asArray: asArray - }; -} - -/** - * Settings for <code>single_mountpoint</code>-initializer - * Used for configs with value as one of the possible mount points - * - * @see _initAsSingleMountPoint - * @param {string|string[]} components - * @param {string} winReplacer - * @returns {{components: string[], winReplacer: string, type: string}} - */ -function getSingleMountPointConfig(components, winReplacer) { - winReplacer = winReplacer || 'default'; - return { - components: Em.makeArray(components), - winReplacer: winReplacer, - type: 'single_mountpoint' - } -} - -/** - * Settings for <code>multiple_mountpoints</code>-initializer - * Used for configs with value as all of the possible mount points - * - * @see _initAsMultipleMountPoints - * @param {string|string[]} components - * @param {string} winReplacer - * @returns {{components: string[], winReplacer: string, type: string}} - */ -function getMultipleMountPointsConfig(components, winReplacer) { - winReplacer = winReplacer || 'default'; - return { - components: Em.makeArray(components), - winReplacer: winReplacer, - type: 'multiple_mountpoints' - } -} - -/** * Initializer for configs * Used on the cluster install * @@ -183,86 +53,88 @@ function getMultipleMountPointsConfig(components, winReplacer) { * * @instance ConfigInitializer */ -App.ConfigInitializer = App.ConfigInitializerClass.create({ - - initializers: { - 'dfs.namenode.rpc-address': getSimpleComponentConfig('NAMENODE'), - 'dfs.http.address': getSimpleComponentConfig('NAMENODE'), - 'dfs.namenode.http-address': getSimpleComponentConfig('NAMENODE'), - 'dfs.https.address': getSimpleComponentConfig('NAMENODE'), - 'dfs.namenode.https-address': getSimpleComponentConfig('NAMENODE'), - 'dfs.secondary.http.address': getSimpleComponentConfig('SECONDARY_NAMENODE'), - 'dfs.namenode.secondary.http-address': getSimpleComponentConfig('SECONDARY_NAMENODE'), - 'yarn.resourcemanager.hostname': getSimpleComponentConfig('RESOURCEMANAGER', false), - 'yarn.resourcemanager.resource-tracker.address': getSimpleComponentConfig('RESOURCEMANAGER'), - 'yarn.resourcemanager.webapp.https.address': getSimpleComponentConfig('RESOURCEMANAGER'), - 'yarn.resourcemanager.webapp.address': getSimpleComponentConfig('RESOURCEMANAGER'), - 'yarn.resourcemanager.scheduler.address': getSimpleComponentConfig('RESOURCEMANAGER'), - 'yarn.resourcemanager.address': getSimpleComponentConfig('RESOURCEMANAGER'), - 'yarn.resourcemanager.admin.address': getSimpleComponentConfig('RESOURCEMANAGER'), - 'yarn.timeline-service.webapp.address': getSimpleComponentConfig('APP_TIMELINE_SERVER'), - 'yarn.timeline-service.webapp.https.address': getSimpleComponentConfig('APP_TIMELINE_SERVER'), - 'yarn.timeline-service.address': getSimpleComponentConfig('APP_TIMELINE_SERVER'), - 'mapred.job.tracker': getSimpleComponentConfig('JOBTRACKER'), - 'mapred.job.tracker.http.address': getSimpleComponentConfig('JOBTRACKER'), - 'mapreduce.history.server.http.address': getSimpleComponentConfig('HISTORYSERVER'), - 'hive_hostname': getSimpleComponentConfig('HIVE_SERVER', false), - 'oozie_hostname': getSimpleComponentConfig('OOZIE_SERVER', false), - 'oozie.base.url': getComponentConfigWithAffixes('OOZIE_SERVER', '://'), - 'hawq_dfs_url': getSimpleComponentConfig('NAMENODE'), - 'hawq_rm_yarn_address': getSimpleComponentConfig('RESOURCEMANAGER'), - 'hawq_rm_yarn_scheduler_address': getSimpleComponentConfig('RESOURCEMANAGER'), - 'fs.default.name': getComponentConfigWithAffixes('NAMENODE', '://'), - 'fs.defaultFS': getComponentConfigWithAffixes('NAMENODE', '://'), - 'hbase.rootdir': getComponentConfigWithAffixes('NAMENODE', '://'), - 'instance.volumes': getComponentConfigWithAffixes('NAMENODE', '://'), - 'yarn.log.server.url': getComponentConfigWithAffixes('HISTORYSERVER', '://'), - 'mapreduce.jobhistory.webapp.address': getSimpleComponentConfig('HISTORYSERVER'), - 'mapreduce.jobhistory.address': getSimpleComponentConfig('HISTORYSERVER'), - 'kafka.ganglia.metrics.host': getSimpleComponentConfig('GANGLIA_SERVER', false), - 'hive_master_hosts': getComponentsHostsConfig(['HIVE_METASTORE', 'HIVE_SERVER']), - 'hadoop_host': getSimpleComponentConfig('NAMENODE', false), - 'nimbus.host': getSimpleComponentConfig('NIMBUS', false), - 'nimbus.seeds': getComponentsHostsConfig('NIMBUS', true), - 'storm.zookeeper.servers': getComponentsHostsConfig('ZOOKEEPER_SERVER', true), - 'hawq_master_address_host': getSimpleComponentConfig('HAWQMASTER', false), - 'hawq_standby_address_host': getSimpleComponentConfig('HAWQSTANDBY', false), - - '*.broker.url': { - type: 'host_with_component', - component: 'FALCON_SERVER', - modifier: { - type: 'regexp', - regex: 'localhost' - } - }, - - 'zookeeper.connect': getZKBasedConfig(), - 'hive.zookeeper.quorum': getZKBasedConfig(), - 'templeton.zookeeper.hosts': getZKBasedConfig(), - 'hadoop.registry.zk.quorum': getZKBasedConfig(), - 'hive.cluster.delegation.token.store.zookeeper.connectString': getZKBasedConfig(), - 'instance.zookeeper.host': getZKBasedConfig(), - - 'dfs.name.dir': getMultipleMountPointsConfig('NAMENODE', 'file'), - 'dfs.namenode.name.dir': getMultipleMountPointsConfig('NAMENODE', 'file'), - 'dfs.data.dir': getMultipleMountPointsConfig('DATANODE', 'file'), - 'dfs.datanode.data.dir': getMultipleMountPointsConfig('DATANODE', 'file'), - 'yarn.nodemanager.local-dirs': getMultipleMountPointsConfig('NODEMANAGER'), - 'yarn.nodemanager.log-dirs': getMultipleMountPointsConfig('NODEMANAGER'), - 'mapred.local.dir': getMultipleMountPointsConfig(['TASKTRACKER', 'NODEMANAGER']), - 'log.dirs': getMultipleMountPointsConfig('KAFKA_BROKER'), - - 'fs.checkpoint.dir': getSingleMountPointConfig('SECONDARY_NAMENODE', 'file'), - 'dfs.namenode.checkpoint.dir': getSingleMountPointConfig('SECONDARY_NAMENODE', 'file'), - 'yarn.timeline-service.leveldb-timeline-store.path': getSingleMountPointConfig('APP_TIMELINE_SERVER'), - 'yarn.timeline-service.leveldb-state-store.path': getSingleMountPointConfig('APP_TIMELINE_SERVER'), - 'dataDir': getSingleMountPointConfig('ZOOKEEPER_SERVER'), - 'oozie_data_dir': getSingleMountPointConfig('OOZIE_SERVER'), - 'storm.local.dir': getSingleMountPointConfig(['NODEMANAGER', 'NIMBUS']), - '*.falcon.graph.storage.directory': getSingleMountPointConfig('FALCON_SERVER'), - '*.falcon.graph.serialize.path': getSingleMountPointConfig('FALCON_SERVER') - }, +App.ConfigInitializer = App.ConfigInitializerClass.create(App.MountPointsBasedInitializerMixin, App.HostsBasedInitializerMixin, { + + initializers: function() { + return { + 'dfs.namenode.rpc-address': this.getSimpleComponentConfig('NAMENODE'), + 'dfs.http.address': this.getSimpleComponentConfig('NAMENODE'), + 'dfs.namenode.http-address': this.getSimpleComponentConfig('NAMENODE'), + 'dfs.https.address': this.getSimpleComponentConfig('NAMENODE'), + 'dfs.namenode.https-address': this.getSimpleComponentConfig('NAMENODE'), + 'dfs.secondary.http.address': this.getSimpleComponentConfig('SECONDARY_NAMENODE'), + 'dfs.namenode.secondary.http-address': this.getSimpleComponentConfig('SECONDARY_NAMENODE'), + 'yarn.resourcemanager.hostname': this.getSimpleComponentConfig('RESOURCEMANAGER', false), + 'yarn.resourcemanager.resource-tracker.address': this.getSimpleComponentConfig('RESOURCEMANAGER'), + 'yarn.resourcemanager.webapp.https.address': this.getSimpleComponentConfig('RESOURCEMANAGER'), + 'yarn.resourcemanager.webapp.address': this.getSimpleComponentConfig('RESOURCEMANAGER'), + 'yarn.resourcemanager.scheduler.address': this.getSimpleComponentConfig('RESOURCEMANAGER'), + 'yarn.resourcemanager.address': this.getSimpleComponentConfig('RESOURCEMANAGER'), + 'yarn.resourcemanager.admin.address': this.getSimpleComponentConfig('RESOURCEMANAGER'), + 'yarn.timeline-service.webapp.address': this.getSimpleComponentConfig('APP_TIMELINE_SERVER'), + 'yarn.timeline-service.webapp.https.address': this.getSimpleComponentConfig('APP_TIMELINE_SERVER'), + 'yarn.timeline-service.address': this.getSimpleComponentConfig('APP_TIMELINE_SERVER'), + 'mapred.job.tracker': this.getSimpleComponentConfig('JOBTRACKER'), + 'mapred.job.tracker.http.address': this.getSimpleComponentConfig('JOBTRACKER'), + 'mapreduce.history.server.http.address': this.getSimpleComponentConfig('HISTORYSERVER'), + 'hive_hostname': this.getSimpleComponentConfig('HIVE_SERVER', false), + 'oozie_hostname': this.getSimpleComponentConfig('OOZIE_SERVER', false), + 'oozie.base.url': this.getComponentConfigWithAffixes('OOZIE_SERVER', '://'), + 'hawq_dfs_url': this.getSimpleComponentConfig('NAMENODE'), + 'hawq_rm_yarn_address': this.getSimpleComponentConfig('RESOURCEMANAGER'), + 'hawq_rm_yarn_scheduler_address': this.getSimpleComponentConfig('RESOURCEMANAGER'), + 'fs.default.name': this.getComponentConfigWithAffixes('NAMENODE', '://'), + 'fs.defaultFS': this.getComponentConfigWithAffixes('NAMENODE', '://'), + 'hbase.rootdir': this.getComponentConfigWithAffixes('NAMENODE', '://'), + 'instance.volumes': this.getComponentConfigWithAffixes('NAMENODE', '://'), + 'yarn.log.server.url': this.getComponentConfigWithAffixes('HISTORYSERVER', '://'), + 'mapreduce.jobhistory.webapp.address': this.getSimpleComponentConfig('HISTORYSERVER'), + 'mapreduce.jobhistory.address': this.getSimpleComponentConfig('HISTORYSERVER'), + 'kafka.ganglia.metrics.host': this.getSimpleComponentConfig('GANGLIA_SERVER', false), + 'hive_master_hosts': this.getComponentsHostsConfig(['HIVE_METASTORE', 'HIVE_SERVER']), + 'hadoop_host': this.getSimpleComponentConfig('NAMENODE', false), + 'nimbus.host': this.getSimpleComponentConfig('NIMBUS', false), + 'nimbus.seeds': this.getComponentsHostsConfig('NIMBUS', true), + 'storm.zookeeper.servers': this.getComponentsHostsConfig('ZOOKEEPER_SERVER', true), + 'hawq_master_address_host': this.getSimpleComponentConfig('HAWQMASTER', false), + 'hawq_standby_address_host': this.getSimpleComponentConfig('HAWQSTANDBY', false), + + '*.broker.url': { + type: 'host_with_component', + component: 'FALCON_SERVER', + modifier: { + type: 'regexp', + regex: 'localhost' + } + }, + + 'zookeeper.connect': getZKBasedConfig(), + 'hive.zookeeper.quorum': getZKBasedConfig(), + 'templeton.zookeeper.hosts': getZKBasedConfig(), + 'hadoop.registry.zk.quorum': getZKBasedConfig(), + 'hive.cluster.delegation.token.store.zookeeper.connectString': getZKBasedConfig(), + 'instance.zookeeper.host': getZKBasedConfig(), + + 'dfs.name.dir': this.getMultipleMountPointsConfig('NAMENODE', 'file'), + 'dfs.namenode.name.dir': this.getMultipleMountPointsConfig('NAMENODE', 'file'), + 'dfs.data.dir': this.getMultipleMountPointsConfig('DATANODE', 'file'), + 'dfs.datanode.data.dir': this.getMultipleMountPointsConfig('DATANODE', 'file'), + 'yarn.nodemanager.local-dirs': this.getMultipleMountPointsConfig('NODEMANAGER'), + 'yarn.nodemanager.log-dirs': this.getMultipleMountPointsConfig('NODEMANAGER'), + 'mapred.local.dir': this.getMultipleMountPointsConfig(['TASKTRACKER', 'NODEMANAGER']), + 'log.dirs': this.getMultipleMountPointsConfig('KAFKA_BROKER'), + + 'fs.checkpoint.dir': this.getSingleMountPointConfig('SECONDARY_NAMENODE', 'file'), + 'dfs.namenode.checkpoint.dir': this.getSingleMountPointConfig('SECONDARY_NAMENODE', 'file'), + 'yarn.timeline-service.leveldb-timeline-store.path': this.getSingleMountPointConfig('APP_TIMELINE_SERVER'), + 'yarn.timeline-service.leveldb-state-store.path': this.getSingleMountPointConfig('APP_TIMELINE_SERVER'), + 'dataDir': this.getSingleMountPointConfig('ZOOKEEPER_SERVER'), + 'oozie_data_dir': this.getSingleMountPointConfig('OOZIE_SERVER'), + 'storm.local.dir': this.getSingleMountPointConfig(['NODEMANAGER', 'NIMBUS']), + '*.falcon.graph.storage.directory': this.getSingleMountPointConfig('FALCON_SERVER'), + '*.falcon.graph.serialize.path': this.getSingleMountPointConfig('FALCON_SERVER') + } + }.property(''), uniqueInitializers: { 'hadoop.registry.rm.enabled': '_setYarnSliderDependency', @@ -276,28 +148,12 @@ App.ConfigInitializer = App.ConfigInitializerClass.create({ }, initializerTypes: [ - {name: 'host_with_component', method: '_initAsHostWithComponent'}, - {name: 'hosts_with_components', method: '_initAsHostsWithComponents'}, {name: 'zookeeper_based', method: '_initAsZookeeperServersList'}, {name: 'single_mountpoint', method: '_initAsSingleMountPoint'}, {name: 'multiple_mountpoints', method: '_initAsMultipleMountPoints'} ], /** - * Map for methods used as value-modifiers for configProperties with values as mount point(s) - * Used if mount point is win-like (@see winRegex) - * Key: id - * Value: method-name - * - * @type {{default: string, file: string, slashes: string}} - */ - winReplacersMap: { - default: '_defaultWinReplace', - file: '_winReplaceWithFile', - slashes: '_defaultWinReplaceWithAdditionalSlashes' - }, - - /** * Some strange method that should define <code>ranger_admin_password</code> * TODO DELETE as soon as <code>ranger_admin_password</code> will be fetched from stack adviser! * @@ -329,65 +185,6 @@ App.ConfigInitializer = App.ConfigInitializerClass.create({ }, /** - * Initializer for configs with value equal to hostName with needed component - * Value example: 'hostName' - * - * @param {configProperty} configProperty - * @param {topologyLocalDB} localDB - * @param {object} dependencies - * @param {object} initializer - * @returns {Object} - * @private - */ - _initAsHostWithComponent: function (configProperty, localDB, dependencies, initializer) { - var component = localDB.masterComponentHosts.findProperty('component', initializer.component); - if (!component) { - return configProperty; - } - if (initializer.modifier) { - var replaceWith = Em.getWithDefault(initializer.modifier, 'prefix', '') - + component.hostName - + Em.getWithDefault(initializer.modifier, 'suffix', ''); - this.setRecommendedValue(configProperty, initializer.modifier.regex, replaceWith); - } - else { - Em.setProperties(configProperty, { - recommendedValue: component.hostName, - value: component.hostName - }) - } - - return configProperty; - }, - - /** - * Initializer for configs with value equal to hostNames with needed components - * May be array or comma-separated list - * Depends on <code>initializer.asArray</code> (true - array, false - string) - * Value example: 'hostName1,hostName2,hostName3' or ['hostName1', 'hostName2', 'hostName3'] - * - * @param {configProperty} configProperty - * @param {topologyLocalDB} localDB - * @param {object} dependencies - * @param {object} initializer - * @return {Object} - * @private - */ - _initAsHostsWithComponents: function (configProperty, localDB, dependencies, initializer) { - var hostNames = localDB.masterComponentHosts.filter(function (masterComponent) { - return initializer.components.contains(masterComponent.component); - }).mapProperty('hostName'); - if (!initializer.asArray) { - hostNames = hostNames.uniq().join(','); - } - Em.setProperties(configProperty, { - value: hostNames, - recommendedValue: hostNames - }); - return configProperty; - }, - - /** * Unique initializer for <code>hive_database</code>-config * * @param {configProperty} configProperty @@ -508,7 +305,7 @@ App.ConfigInitializer = App.ConfigInitializerClass.create({ */ _initYarnRMzkAddress: function (configProperty, localDB, dependencies) { var value = localDB.masterComponentHosts.filterProperty('component', 'ZOOKEEPER_SERVER').map(function (component) { - return component.hostName + ':' + dependencies.clientPort + return component.hostName + ':' + dependencies.clientPort; }).join(','); Em.setProperties(configProperty, { value: value, @@ -577,252 +374,5 @@ App.ConfigInitializer = App.ConfigInitializerClass.create({ Em.set(configProperty, 'value', value); Em.set(configProperty, 'initialValue', value); return configProperty; - }, - - /** - * Initializer for configs with value as one of the possible mount points - * Only hosts that contains on the components from <code>initializer.components</code> are processed - * Hosts with Windows needs additional processing (@see winReplacersMap) - * Value example: '/', '/some/cool/dir' - * - * @param {configProperty} configProperty - * @param {topologyLocalDB} localDB - * @param {object} dependencies - * @param {object} initializer - * @return {Object} - */ - _initAsSingleMountPoint: function (configProperty, localDB, dependencies, initializer) { - var hostsInfo = this._updateHostInfo(localDB.hosts); - var setOfHostNames = this._getSetOfHostNames(localDB, initializer); - var winReplacersMap = this.get('winReplacersMap'); - // In Add Host Wizard, if we did not select this slave component for any host, then we don't process any further. - if (!setOfHostNames.length) { - return configProperty; - } - var allMountPoints = this._getAllMountPoints(setOfHostNames, hostsInfo); - - var mPoint = allMountPoints[0].mountpoint; - if (mPoint === "/") { - mPoint = Em.get(configProperty, 'recommendedValue'); - } - else { - var mp = mPoint.toLowerCase(); - if (winRegex.test(mp)) { - var methodName = winReplacersMap[initializer.winReplacer]; - mPoint = this[methodName].call(this, configProperty, mp); - } - else { - mPoint = mPoint + Em.get(configProperty, 'recommendedValue'); - } - } - Em.setProperties(configProperty, { - value: mPoint, - recommendedValue: mPoint - }); - - return configProperty; - }, - - /** - * Initializer for configs with value as all of the possible mount points - * Only hosts that contains on the components from <code>initializer.components</code> are processed - * Hosts with Windows needs additional processing (@see winReplacersMap) - * Value example: '/\n/some/cool/dir' (`\n` - is divider) - * - * @param {Object} configProperty - * @param {topologyLocalDB} localDB - * @param {object} dependencies - * @param {object} initializer - * @return {Object} - */ - _initAsMultipleMountPoints: function (configProperty, localDB, dependencies, initializer) { - var hostsInfo = this._updateHostInfo(localDB.hosts); - var self = this; - var setOfHostNames = this._getSetOfHostNames(localDB, initializer); - var winReplacersMap = this.get('winReplacersMap'); - // In Add Host Wizard, if we did not select this slave component for any host, then we don't process any further. - if (!setOfHostNames.length) { - return configProperty; - } - - var allMountPoints = this._getAllMountPoints(setOfHostNames, hostsInfo); - var mPoint = ''; - - allMountPoints.forEach(function (eachDrive) { - if (eachDrive.mountpoint === '/') { - mPoint += Em.get(configProperty, 'recommendedValue') + "\n"; - } - else { - var mp = eachDrive.mountpoint.toLowerCase(); - if (winRegex.test(mp)) { - var methodName = winReplacersMap[initializer.winReplacer]; - mPoint += self[methodName].call(this, configProperty, mp); - } - else { - mPoint += eachDrive.mountpoint + Em.get(configProperty, 'recommendedValue') + "\n"; - } - } - }, this); - - Em.setProperties(configProperty, { - value: mPoint, - recommendedValue: mPoint - }); - - return configProperty; - }, - - /** - * Replace drive-based windows-path with 'file:///' - * - * @param {configProperty} configProperty - * @param {string} mountPoint - * @returns {string} - * @private - */ - _winReplaceWithFile: function (configProperty, mountPoint) { - var winDriveUrl = mountPoint.toLowerCase().replace(winRegex, 'file:///$1:'); - return winDriveUrl + Em.get(configProperty, 'recommendedValue') + '\n'; - }, - - /** - * Replace drive-based windows-path - * - * @param {configProperty} configProperty - * @param {string} mountPoint - * @returns {string} - * @private - */ - _defaultWinReplace: function (configProperty, mountPoint) { - var winDrive = mountPoint.toLowerCase().replace(winRegex, '$1:'); - var winDir = Em.get(configProperty, 'recommendedValue').replace(/\//g, '\\'); - return winDrive + winDir + '\n'; - }, - - /** - * Same to <code>_defaultWinReplace</code>, but with extra-slash in the end - * - * @param {configProperty} configProperty - * @param {string} mountPoint - * @returns {string} - * @private - */ - _defaultWinReplaceWithAdditionalSlashes: function (configProperty, mountPoint) { - var winDrive = mountPoint.toLowerCase().replace(winRegex, '$1:'); - var winDir = Em.get(configProperty, 'recommendedValue').replace(/\//g, '\\\\'); - return winDrive + winDir + '\n'; - }, - - /** - * Update information from localDB using <code>App.Host</code>-model - * - * @param {object} hostsInfo - * @returns {object} - * @private - */ - _updateHostInfo: function (hostsInfo) { - App.Host.find().forEach(function (item) { - if (!hostsInfo[item.get('id')]) { - hostsInfo[item.get('id')] = { - name: item.get('id'), - cpu: item.get('cpu'), - memory: item.get('memory'), - disk_info: item.get('diskInfo'), - bootStatus: "REGISTERED", - isInstalled: true - }; - } - }); - return hostsInfo; - }, - - /** - * Determines if mount point is valid - * Criterias: - * <ul> - * <li>Should has available space</li> - * <li>Should not be home-dir</li> - * <li>Should not be docker-dir</li> - * <li>Should not be boot-dir</li> - * <li>Should not be dev-dir</li> - * </ul> - * - * @param {{mountpoint: string, available: number}} mPoint - * @returns {boolean} true - valid, false - invalid - * @private - */ - _filterMountPoint: function (mPoint) { - var isAvailable = mPoint.available !== 0; - if (!isAvailable) { - return false; - } - - var notHome = !['/', '/home'].contains(mPoint.mountpoint); - var notDocker = !['/etc/resolv.conf', '/etc/hostname', '/etc/hosts'].contains(mPoint.mountpoint); - var notBoot = mPoint.mountpoint && !(mPoint.mountpoint.startsWith('/boot') || mPoint.mountpoint.startsWith('/mnt')); - var notDev = !(['devtmpfs', 'tmpfs', 'vboxsf', 'CDFS'].contains(mPoint.type)); - - return notHome && notDocker && notBoot && notDev; - }, - - /** - * Get list of hostNames from localDB which contains needed components - * - * @param {topologyLocalDB} localDB - * @param {object} initializer - * @returns {string[]} - * @private - */ - _getSetOfHostNames: function (localDB, initializer) { - var masterComponentHostsInDB = Em.getWithDefault(localDB, 'masterComponentHosts', []); - var slaveComponentHostsInDB = Em.getWithDefault(localDB, 'slaveComponentHosts', []); - var hosts = masterComponentHostsInDB.filter(function (master) { - return initializer.components.contains(master.component); - }).mapProperty('hostName'); - - var sHosts = slaveComponentHostsInDB.find(function (slave) { - return initializer.components.contains(slave.componentName); - }); - if (sHosts) { - hosts = hosts.concat(sHosts.hosts.mapProperty('hostName')); - } - return hosts; - }, - - /** - * Get list of all unique valid mount points for hosts - * - * @param {string[]} setOfHostNames - * @param {object} hostsInfo - * @returns {string[]} - * @private - */ - _getAllMountPoints: function (setOfHostNames, hostsInfo) { - var allMountPoints = []; - for (var i = 0; i < setOfHostNames.length; i++) { - var hostname = setOfHostNames[i]; - var mountPointsPerHost = hostsInfo[hostname].disk_info; - var mountPointAsRoot = mountPointsPerHost.findProperty('mountpoint', '/'); - - // If Server does not send any host details information then atleast one mountpoint should be presumed as root - // This happens in a single container Linux Docker environment. - if (!mountPointAsRoot) { - mountPointAsRoot = { - mountpoint: '/' - }; - } - - mountPointsPerHost.filter(this._filterMountPoint).forEach(function (mPoint) { - if( !allMountPoints.findProperty("mountpoint", mPoint.mountpoint)) { - allMountPoints.push(mPoint); - } - }, this); - } - - if (!allMountPoints.length) { - allMountPoints.push(mountPointAsRoot); - } - return allMountPoints; } - }); http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/utils/configs/config_initializer_class.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/configs/config_initializer_class.js b/ambari-web/app/utils/configs/config_initializer_class.js index 3e96fca..0663bc3 100644 --- a/ambari-web/app/utils/configs/config_initializer_class.js +++ b/ambari-web/app/utils/configs/config_initializer_class.js @@ -19,6 +19,12 @@ var App = require('app'); /** + * @typedef {object} initializer + * @property {string} type initializer type name + * @property {boolean} [isChecker] determines control flow callback + */ + +/** * @typedef {object} initializerType * @property {string} name key * @property {string} method function's name (prefer to start method-name with '_init' or '_initAs'). Each method here is called with arguments equal to <code>initialValue</code>-call args. Initializer-settings are added as last argument @@ -32,6 +38,7 @@ var App = require('app'); * @property {string} name config's name * @property {number|string} value current value * @property {string} filename file name where this config is + * @property {number|string} [recommendedValue] value which is recommended */ /** @@ -73,13 +80,19 @@ var App = require('app'); */ App.ConfigInitializerClass = Em.Object.extend({ + _initializerFlowCode: { + next: 0, + skipNext: 1, + skipAll: 2 + }, + concatenatedProperties: ['initializerTypes'], /** * Map with configurations for config initializers * It's used only for initializers which are common for some configs (if not - use <code>uniqueInitializers</code>-map) * Key {string} configProperty-name - * Value {object|object[]} settings for initializer + * Value {initializer|initializer[]} settings for initializer * * @type {object} */ @@ -121,15 +134,31 @@ App.ConfigInitializerClass = Em.Object.extend({ var initializer = initializers[Em.get(configProperty, 'name')]; if (initializer) { initializer = Em.makeArray(initializer); - initializer.forEach(function (init) { + var i = 0; + while(i < initializer.length) { + var init = initializer[i]; var _args = [].slice.call(args); var type = initializerTypes.findProperty('name', init.type); // add initializer-settings _args.push(init); var methodName = type.method; Em.assert('method-initializer is not a function ' + methodName, 'function' === Em.typeOf(self[methodName])); - configProperty = self[methodName].apply(self, _args); - }); + if (init.isChecker) { + var result = self[methodName].apply(self, _args); + if (result === this.flowSkipNext()) { + i++; // skip next + } + else { + if (result === this.flowSkipAll()) { + break; + } + } + } + else { + configProperty = self[methodName].apply(self, _args); + } + i++; + } } return configProperty; }, @@ -148,7 +177,6 @@ App.ConfigInitializerClass = Em.Object.extend({ initialValue: function (configProperty, localDB, dependencies) { var configName = Em.get(configProperty, 'name'); var initializers = this.get('initializers'); - var initializer = initializers[configName]; if (initializer) { return this._defaultInitializer(configProperty, localDB, dependencies); @@ -239,13 +267,13 @@ App.ConfigInitializerClass = Em.Object.extend({ var copyInitializers = Em.copy(originalInitializers, true); this.set('__copyInitializers', copyInitializers); var initializers = this._updateNames('initializers', settings); - this.set('initializers', initializers); + this._setForComputed('initializers', initializers); var originalUniqueInitializers = this.get('uniqueInitializers'); var copyUniqueInitializers = Em.copy(originalUniqueInitializers, true); this.set('__copyUniqueInitializers', copyUniqueInitializers); var uniqueInitializers = this._updateNames('uniqueInitializers', settings); - this.set('uniqueInitializers', uniqueInitializers); + this._setForComputed('uniqueInitializers', uniqueInitializers); }, /** @@ -257,10 +285,10 @@ App.ConfigInitializerClass = Em.Object.extend({ var copyInitializers = this.get('__copyInitializers'); var copyUniqueInitializers = this.get('__copyUniqueInitializers'); if ('object' === Em.typeOf(copyInitializers)) { - this.set('initializers', Em.copy(copyInitializers, true)); + this._setForComputed('initializers', Em.copy(copyInitializers, true)); } if ('object' === Em.typeOf(copyUniqueInitializers)) { - this.set('uniqueInitializers', Em.copy(copyUniqueInitializers, true)); + this._setForComputed('uniqueInitializers', Em.copy(copyUniqueInitializers, true)); } }, @@ -293,6 +321,55 @@ App.ConfigInitializerClass = Em.Object.extend({ source[configName] = initializer; }); return source; - } + }, + + flowNext: function() { + return this.get('_initializerFlowCode.next'); + }, + + flowSkipNext: function() { + return this.get('_initializerFlowCode.skipNext'); + }, + + flowSkipAll: function() { + return this.get('_initializerFlowCode.skipAll'); + }, + /** + * Set value for computed property using `reopen`. Currently used to update 'initializers' + * and 'uniqueInitializers'. + * Used to set value for props like: + * <code>cp: function() { }.property()</code> + * <code> + * var obj = App.ConfigInitializerClass.create({ + * cp: function() { + * return { + * key: "value" + * } + * }.property(), + * setProp: function() { + * this.set('cp', {newKey: "new_value"}); // will not change `cp` value + * }, + * updateProp: function() { + * this._setForComputed('cp', { newKey: "new_value"}); // will update + * } + * }); + * + * obj.get('cp'); // {key: "value"} + * obj.setProp(); + * obj.get('cp'); // {key: "value"} + * obj.updateProp(); + * obj.get('cp'); // {newKey: "new_value"} + * </code> + * @private + * @param {string} key + * @param {*} value + */ + _setForComputed: function(key, value) { + var obj = {}; + obj[key] = function() { + return value; + }.property(); + this.reopen(obj); + } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/utils/configs/control_flow_initializer_mixin.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/configs/control_flow_initializer_mixin.js b/ambari-web/app/utils/configs/control_flow_initializer_mixin.js new file mode 100644 index 0000000..5247586 --- /dev/null +++ b/ambari-web/app/utils/configs/control_flow_initializer_mixin.js @@ -0,0 +1,127 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var App = require('app'); +var stringUtils = require('utils/string_utils'); + +/** + * Mixin with preconfigured initializers that helps to build conditional execution + * based on exit code from App.ConfigInitializerClass._initializerFlowCode. + * Each control flow initializer should has attribute <b>isChecker: true</b> + * Each handler should return exit code value based on App.ConfigInitializerClass._initializerFlowCode. + * + * There are few methods: + * @see App.ConfigInitializerClass.flowNext + * @see App.ConfigInitializerClass.flowSkipNext + * @see App.ConfigInitializerClass.flowSkipAll + * + * For details and examples @see App.AddComponentConfigInitializer + * + * @mixin App.ControlFlowInitializerMixin + */ +App.ControlFlowInitializerMixin = Em.Mixin.create({ + + initializerTypes: [ + { + name: 'namenode_ha_enabled', + method: '_initNameNodeHACheck' + }, + { + name: 'resourcemanager_ha_enabled', + method: '_initResourceManagerHACheck' + }, + { + name: 'hdp_stack_version_checker', + method: '_initHDPStackVersionCheck' + } + ], + + /** + * Control flow initializer based on minimal stack version. + * + * @param {string} minStackVersionNumber + * @return {object} + */ + getHDPStackVersionControl: function(minStackVersionNumber) { + return { type: 'hdp_stack_version_checker', isChecker: true, stackVersion: minStackVersionNumber }; + }, + + /** + * getHDPStackVersionControl handler. + * When stack version satisfies passed minStackVersionNumber computation process will continue. + * If not all next computation will be skipped. + * + * @param {configProperty} configProperty + * @param {topologyLocalDB} localDB + * @param {dependencies} dependencies + * @param {initializer} initializer + * @return {number} _initializerFlowCode exit code + */ + _initHDPStackVersionCheck: function(configProperty, localDB, dependencies, initializer) { + return (stringUtils.compareVersions(App.get('currentStackVersionNumber'), initializer.stackVersion) > -1) ? + this.flowNext() : + this.flowSkipAll(); + }, + + /** + * Control flow initializer based on NameNode HA Status. + * + * @return {initializer} + */ + getNameNodeHAControl: function() { + return { type: 'namenode_ha_enabled', isChecker: true }; + }, + + /** + * getNameNodeHAControl handler. + * When NameNode HA enabled next computation will be performed, either next will be skipped. + * + * @param {configProperty} configProperty + * @param {topologyLocalDB} localDB + * @param {dependencies} dependencies + * @param {initializer} initializer + * @return {number} _initializerFlowCode exit code + */ + _initNameNodeHACheck: function(configProperty, localDB, dependencies) { + return App.get('isHaEnabled') ? this.flowNext() : this.flowSkipNext(); + }, + + /** + * Control flow initializer based on ResourceManager HA Status. + * + * @return {initializer} + */ + getResourceManagerHAControl: function(trueBranch, falseBranch) { + return { type: 'resourcemanager_ha_enabled', isChecker: true }; + }, + + /** + * getResourceManagerHAControl handler. + * When ResourceManager HA enabled next computation will be performed, either next will be skipped. + * + * @param {configProperty} configProperty + * @param {topologyLocalDB} localDB + * @param {dependencies} dependencies + * @param {initializer} initializer + * @return {number} _initializerFlowCode exit code + */ + _initResourceManagerHACheck: function(configProperty, localDB, dependencies) { + return App.get('isRMHaEnabled') ? this.flowNext() : this.flowSkipNext(); + } + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/utils/configs/ha_config_initializer_class.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/configs/ha_config_initializer_class.js b/ambari-web/app/utils/configs/ha_config_initializer_class.js index e7ade94..3477ef1 100644 --- a/ambari-web/app/utils/configs/ha_config_initializer_class.js +++ b/ambari-web/app/utils/configs/ha_config_initializer_class.js @@ -28,171 +28,6 @@ App.HaConfigInitializerClass = App.ConfigInitializerClass.extend({ initializerTypes: [ {name: 'host_with_port', method: '_initAsHostWithPort'}, {name: 'hosts_with_port', method: '_initAsHostsWithPort'} - ], - - /** - * Initializer for configs with value equal to the hostName where some component exists - * Value may be customized with prefix and suffix (see <code>initializer.modifier</code>) - * Port-value is calculated according to <code>initializer.portKey</code> or <code>initializer.port</code> values - * If calculated port-value is empty, it will be skipped (and ':' too) - * Value-examples: 'SOME_COOL_PREFIXhost1:port1SOME_COOL_SUFFIX', 'host1:port2' - * - * @param {configProperty} configProperty - * @param {extendedTopologyLocalDB} localDB - * @param {nnHaConfigDependencies} dependencies - * @param {object} initializer - * @returns {object} - * @private - * @method _initAsHostWithPort - */ - _initAsHostWithPort: function (configProperty, localDB, dependencies, initializer) { - var hostName = localDB.masterComponentHosts.filterProperty('component', initializer.component).findProperty('isInstalled', initializer.componentExists).hostName; - var port = this.__getPort(dependencies, initializer); - var value = initializer.modifier.prefix + hostName + (port ? ':' + port : '') + initializer.modifier.suffix; - Em.setProperties(configProperty, { - value: value, - recommendedValue: value - }); - return configProperty; - }, - - /** - * Initializer for configs with value equal to the list of hosts where some component exists - * Value may be customized with prefix and suffix (see <code>initializer.modifier</code>) - * Delimiter between hostNames also may be customized in the <code>initializer.modifier</code> - * Port-value is calculated according to <code>initializer.portKey</code> or <code>initializer.port</code> values - * If calculated port-value is empty, it will be skipped (and ':' too) - * Value examples: 'SOME_COOL_PREFIXhost1:port,host2:port,host2:portSOME_COOL_SUFFIX', 'host1:port|||host2:port|||host2:port' - * - * @param {configProperty} configProperty - * @param {topologyLocalDB} localDB - * @param {nnHaConfigDependencies} dependencies - * @param {object} initializer - * @returns {object} - * @private - * @method _initAsHostsWithPort - */ - _initAsHostsWithPort: function (configProperty, localDB, dependencies, initializer) { - var hostNames = localDB.masterComponentHosts.filterProperty('component', initializer.component).mapProperty('hostName'); - var port = this.__getPort(dependencies, initializer); - var value = initializer.modifier.prefix + hostNames.map(function (hostName) { - return hostName + (port ? ':' + port : ''); - }).join(initializer.modifier.delimiter) + initializer.modifier.suffix; - Em.setProperties(configProperty, { - value: value, - recommendedValue: value - }); - return configProperty; - }, - - /** - * Returns port-value from <code>dependencies</code> accorfing to <code>initializer.portKey</code> or <code>initializer.port</code> values - * - * @param {nnHaConfigDependencies} dependencies - * @param {object} initializer - * @returns {string|number} - * @private - * @method __getPort - */ - __getPort: function (dependencies, initializer) { - var portKey = initializer.portKey; - if (portKey) { - return dependencies[portKey]; - } - return initializer.port; - } - -}); - -App.HaConfigInitializerClass.reopenClass({ - - /** - * Settings for <code>host_with_port</code>-initializer - * Used for configs with value equal to hostName where some component exists concatenated with port-value - * Port-value is calculated according to <code>port</code> and <code>portFromDependencies</code> values - * If <code>portFromDependencies</code> is <code>true</code>, <code>port</code>-value is used as key of the <code>dependencies</code> (where real port-value is) - * Otherwise - <code>port</code>-value used as is - * If calculated port-value is empty, it will be skipped (and ':' too) - * Value also may be customized with prefix and suffix - * - * @param {string} component needed component - * @param {boolean} componentExists component already exists or just going to be installed - * @param {string} prefix='' - * @param {string} suffix='' - * @param {string} port - * @param {boolean} [portFromDependencies=false] - * @returns {{type: string, component: string, componentExists: boolean, modifier: {prefix: (string), suffix: (string)}}} - * @method getHostWithPortConfig - * @static - */ - getHostWithPortConfig: function (component, componentExists, prefix, suffix, port, portFromDependencies) { - if (arguments.length < 6) { - portFromDependencies = false; - } - prefix = prefix || ''; - suffix = suffix || ''; - var ret = { - type: 'host_with_port', - component: component, - componentExists: componentExists, - modifier: { - prefix: prefix, - suffix: suffix - } - }; - if (portFromDependencies) { - ret.portKey = port; - } - else { - ret.port = port; - } - return ret; - }, - - /** - * Settings for <code>hosts_with_port</code>-initializer - * Used for configs with value equal to the list of hostNames with port - * Value also may be customized with prefix, suffix and delimiter between host:port elements - * Port-value is calculated according to <code>port</code> and <code>portFromDependencies</code> values - * If <code>portFromDependencies</code> is <code>true</code>, <code>port</code>-value is used as key of the <code>dependencies</code> (where real port-value is) - * Otherwise - <code>port</code>-value used as is - * If calculated port-value is empty, it will be skipped (and ':' too) - * - * @param {string} component hosts where this component exists are used as config-value - * @param {string} prefix='' substring added before hosts-list - * @param {string} suffix='' substring added after hosts-list - * @param {string} delimiter=',' delimiter between hosts in the value - * @param {string} port if <code>portFromDependencies</code> is <code>false</code> this value is used as port for hosts - * if <code>portFromDependencies</code> is <code>true</code> `port` is used as key in the <code>dependencies</code> to get real port-value - * @param {boolean} portFromDependencies=false true - use <code>port</code> as key for <code>dependencies</code> to get real port-value, - * false - use <code>port</code> as port-value - * @returns {{type: string, component: string, modifier: {prefix: (string), suffix: (string), delimiter: (string)}}} - * @method getHostsWithPortConfig - * @static - */ - getHostsWithPortConfig: function (component, prefix, suffix, delimiter, port, portFromDependencies) { - if (arguments.length < 6) { - portFromDependencies = false; - } - prefix = prefix || ''; - suffix = suffix || ''; - delimiter = delimiter || ','; - var ret = { - type: 'hosts_with_port', - component: component, - modifier: { - prefix: prefix, - suffix: suffix, - delimiter: delimiter - } - }; - if (portFromDependencies) { - ret.portKey = port; - } - else { - ret.port = port; - } - return ret; - } + ] }); \ No newline at end of file