You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2015/12/18 18:00:23 UTC
[1/2] ambari git commit: AMBARI-14416. Refactor Host Details
controller
Repository: ambari
Updated Branches:
refs/heads/trunk 2c7ecd12e -> 6c38d84b1
http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/utils/configs/hosts_based_initializer_mixin.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/hosts_based_initializer_mixin.js b/ambari-web/app/utils/configs/hosts_based_initializer_mixin.js
new file mode 100644
index 0000000..5c51c12
--- /dev/null
+++ b/ambari-web/app/utils/configs/hosts_based_initializer_mixin.js
@@ -0,0 +1,401 @@
+/**
+ * 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');
+
+/**
+ * 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;
+
+/**
+ * Mixin describes host name computations initializers and handlers.
+ *
+ * @mixin App.HostsBasedInitializerMixin
+ */
+App.HostsBasedInitializerMixin = Em.Mixin.create({
+
+ initializerTypes: [
+ {name: 'host_with_component', method: '_initAsHostWithComponent'},
+ {name: 'hosts_with_components', method: '_initAsHostsWithComponents'},
+ {name: 'hosts_list_with_component', method: '_initAsHostsListWithComponent'}
+ ],
+
+ /**
+ * 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;
+ },
+
+ /**
+ * 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]
+ * @param {boolean|undefined} [isInstalled=undefined]
+ * @returns {{type: string, components: string[], asArray: boolean}}
+ */
+ getComponentsHostsConfig: function(components, asArray, isInstalled) {
+ if (1 === arguments.length) {
+ asArray = false;
+ }
+ return {
+ type: 'hosts_with_components',
+ components: Em.makeArray(components),
+ asArray: asArray,
+ isInstalled: isInstalled
+ };
+ },
+
+ /**
+ * 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) {
+ var hasFound = initializer.components.contains(masterComponent.component);
+ if (Em.isNone(initializer.isInstalled)) {
+ return hasFound;
+ } else {
+ return hasFound && masterComponent.isInstalled === initializer.isInstalled;
+ }
+ }).sortProperty('hostName').mapProperty('hostName');
+ if (!initializer.asArray) {
+ hostNames = hostNames.uniq().join(',');
+ }
+ Em.setProperties(configProperty, {
+ value: hostNames,
+ recommendedValue: hostNames
+ });
+ return configProperty;
+ },
+
+ /**
+ * 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}
+ */
+ getSimpleComponentConfig: function(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;
+ },
+
+ /**
+ * 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}
+ */
+ getComponentConfigWithAffixes: function(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>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;
+ },
+
+ /**
+ * 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 {object} 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;
+ },
+
+ /**
+ * 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|string[]} component hosts where this component(s) 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;
+ },
+
+ /**
+ * 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 {object} dependencies
+ * @param {object} initializer
+ * @returns {object}
+ * @private
+ * @method _initAsHostsWithPort
+ */
+ _initAsHostsWithPort: function (configProperty, localDB, dependencies, initializer) {
+ var hostNames, hosts;
+ if (Em.isArray(initializer.component)) {
+ hosts = localDB.masterComponentHosts.filter(function(masterComponent) {
+ return initializer.component.contains(masterComponent.component);
+ }).sortProperty('hostName');
+ } else {
+ hosts = localDB.masterComponentHosts.filterProperty('component', initializer.component);
+ }
+ if (Em.isNone(initializer.componentExists)) {
+ hostNames = hosts.mapProperty('hostName');
+ } else {
+ hostNames = hosts.filterProperty('isInstalled', initializer.componentExists).mapProperty('hostName');
+ }
+ var port = this.__getPort(dependencies, initializer);
+ var value = initializer.modifier.prefix + hostNames.uniq().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 {object} 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;
+ },
+
+ /**
+ *
+ * @param {string} component component name
+ * @param {boolean} componentExists
+ * @returns {object}
+ */
+ getHostsListComponentConfig: function(component, componentExists, delimiter) {
+ return {
+ type: 'hosts_list_with_component',
+ component: component,
+ componentExists: componentExists,
+ modifier: {
+ delmitier: Em.isNone(delimiter) ? ',' : delimiter
+ }
+ };
+ },
+
+ /**
+ *
+ * @param {configProperty} configProperty
+ * @param {topologyLocalDB} localDB
+ * @param {object} dependencies
+ * @param {object} initializer
+ * @returns {configProperty}
+ */
+ _initAsHostsListWithComponent: function(configProperty, localDB, dependencies, initializer) {
+ var hostNames = localDB.masterComponentHosts
+ .filterProperty('component', initializer.component)
+ .filterProperty('isInstalled', initializer.componentExists)
+ .mapProperty('hostName')
+ .join(initializer.modifier.delimiter);
+
+ Em.setProperties(configProperty, {
+ value: hostNames,
+ recommendedValue: hostNames
+ });
+ return configProperty;
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/utils/configs/mount_points_based_initializer_mixin.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/mount_points_based_initializer_mixin.js b/ambari-web/app/utils/configs/mount_points_based_initializer_mixin.js
new file mode 100644
index 0000000..1bb9703
--- /dev/null
+++ b/ambari-web/app/utils/configs/mount_points_based_initializer_mixin.js
@@ -0,0 +1,326 @@
+/**
+ * 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');
+
+/**
+ * Regexp used to determine if mount point is windows-like
+ *
+ * @type {RegExp}
+ */
+var winRegex = /^([a-z]):\\?$/;
+
+App.MountPointsBasedInitializerMixin = Em.Mixin.create({
+
+ /**
+ * 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'
+ },
+
+ /**
+ * 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;
+ },
+
+ /**
+ * 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}}
+ */
+ getSingleMountPointConfig: function (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}}
+ */
+ getMultipleMountPointsConfig: function (components, winReplacer) {
+ winReplacer = winReplacer || 'default';
+ return {
+ components: Em.makeArray(components),
+ winReplacer: winReplacer,
+ type: 'multiple_mountpoints'
+ };
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/utils/configs/nn_ha_config_initializer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/nn_ha_config_initializer.js b/ambari-web/app/utils/configs/nn_ha_config_initializer.js
index 80eca42..ce3e1c5 100644
--- a/ambari-web/app/utils/configs/nn_ha_config_initializer.js
+++ b/ambari-web/app/utils/configs/nn_ha_config_initializer.js
@@ -18,6 +18,7 @@
var App = require('app');
require('utils/configs/ha_config_initializer_class');
+require('utils/configs/hosts_based_initializer_mixin');
/**
* @typedef {topologyLocalDB} extendedTopologyLocalDB
@@ -80,43 +81,46 @@ function getReplaceNamespaceConfig(toReplace) {
*
* @class {NnHaConfigInitializer}
*/
-App.NnHaConfigInitializer = App.HaConfigInitializerClass.create({
+App.NnHaConfigInitializer = App.HaConfigInitializerClass.create(App.HostsBasedInitializerMixin, {
- initializers: {
- 'dfs.ha.namenodes.${dfs.nameservices}': getRenameWithNamespaceConfig('${dfs.nameservices}'),
- 'dfs.namenode.rpc-address.${dfs.nameservices}.nn1': [
- App.HaConfigInitializerClass.getHostWithPortConfig('NAMENODE', true, '', '', 'nnRpcPort', true),
- getRenameWithNamespaceConfig('${dfs.nameservices}')
- ],
- 'dfs.namenode.rpc-address.${dfs.nameservices}.nn2': [
- App.HaConfigInitializerClass.getHostWithPortConfig('NAMENODE', false, '', '', '8020', false),
- getRenameWithNamespaceConfig('${dfs.nameservices}')
- ],
- 'dfs.namenode.http-address.${dfs.nameservices}.nn1': [
- App.HaConfigInitializerClass.getHostWithPortConfig('NAMENODE', true, '', '', 'nnHttpPort', true),
- getRenameWithNamespaceConfig('${dfs.nameservices}')
- ],
- 'dfs.namenode.http-address.${dfs.nameservices}.nn2': [
- App.HaConfigInitializerClass.getHostWithPortConfig('NAMENODE', false, '', '', '50070', false),
- getRenameWithNamespaceConfig('${dfs.nameservices}')
- ],
- 'dfs.namenode.https-address.${dfs.nameservices}.nn1': [
- App.HaConfigInitializerClass.getHostWithPortConfig('NAMENODE', true, '', '', 'nnHttpsPort', true),
- getRenameWithNamespaceConfig('${dfs.nameservices}')
- ],
- 'dfs.namenode.https-address.${dfs.nameservices}.nn2': [
- App.HaConfigInitializerClass.getHostWithPortConfig('NAMENODE', false, '', '', '50470', false),
- getRenameWithNamespaceConfig('${dfs.nameservices}')
- ],
- 'dfs.client.failover.proxy.provider.${dfs.nameservices}': getRenameWithNamespaceConfig('${dfs.nameservices}'),
- 'dfs.nameservices': getNamespaceConfig(),
- 'fs.defaultFS': getNamespaceConfig('hdfs://'),
- 'dfs.namenode.shared.edits.dir': [
- App.HaConfigInitializerClass.getHostsWithPortConfig('JOURNALNODE', 'qjournal://', '/${dfs.nameservices}', ';', '8485', false),
- getReplaceNamespaceConfig('${dfs.nameservices}')
- ],
- 'ha.zookeeper.quorum': App.HaConfigInitializerClass.getHostsWithPortConfig('ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true)
- },
+ initializers: function () {
+
+ return {
+ 'dfs.ha.namenodes.${dfs.nameservices}': getRenameWithNamespaceConfig('${dfs.nameservices}'),
+ 'dfs.namenode.rpc-address.${dfs.nameservices}.nn1': [
+ this.getHostWithPortConfig('NAMENODE', true, '', '', 'nnRpcPort', true),
+ getRenameWithNamespaceConfig('${dfs.nameservices}')
+ ],
+ 'dfs.namenode.rpc-address.${dfs.nameservices}.nn2': [
+ this.getHostWithPortConfig('NAMENODE', false, '', '', '8020', false),
+ getRenameWithNamespaceConfig('${dfs.nameservices}')
+ ],
+ 'dfs.namenode.http-address.${dfs.nameservices}.nn1': [
+ this.getHostWithPortConfig('NAMENODE', true, '', '', 'nnHttpPort', true),
+ getRenameWithNamespaceConfig('${dfs.nameservices}')
+ ],
+ 'dfs.namenode.http-address.${dfs.nameservices}.nn2': [
+ this.getHostWithPortConfig('NAMENODE', false, '', '', '50070', false),
+ getRenameWithNamespaceConfig('${dfs.nameservices}')
+ ],
+ 'dfs.namenode.https-address.${dfs.nameservices}.nn1': [
+ this.getHostWithPortConfig('NAMENODE', true, '', '', 'nnHttpsPort', true),
+ getRenameWithNamespaceConfig('${dfs.nameservices}')
+ ],
+ 'dfs.namenode.https-address.${dfs.nameservices}.nn2': [
+ this.getHostWithPortConfig('NAMENODE', false, '', '', '50470', false),
+ getRenameWithNamespaceConfig('${dfs.nameservices}')
+ ],
+ 'dfs.client.failover.proxy.provider.${dfs.nameservices}': getRenameWithNamespaceConfig('${dfs.nameservices}'),
+ 'dfs.nameservices': getNamespaceConfig(),
+ 'fs.defaultFS': getNamespaceConfig('hdfs://'),
+ 'dfs.namenode.shared.edits.dir': [
+ this.getHostsWithPortConfig('JOURNALNODE', 'qjournal://', '/${dfs.nameservices}', ';', '8485', false),
+ getReplaceNamespaceConfig('${dfs.nameservices}')
+ ],
+ 'ha.zookeeper.quorum': this.getHostsWithPortConfig('ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true)
+ };
+ }.property(),
uniqueInitializers: {
'hbase.rootdir': '_initHbaseRootDir',
http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/app/utils/configs/rm_ha_config_initializer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/rm_ha_config_initializer.js b/ambari-web/app/utils/configs/rm_ha_config_initializer.js
index 44bd45b..0255b27 100644
--- a/ambari-web/app/utils/configs/rm_ha_config_initializer.js
+++ b/ambari-web/app/utils/configs/rm_ha_config_initializer.js
@@ -18,6 +18,7 @@
var App = require('app');
require('utils/configs/config_initializer_class');
+require('utils/configs/hosts_based_initializer_mixin');
/**
* Settings for <code>rm_hosts_with_port</code> initializer
@@ -39,24 +40,26 @@ function getRmHaHostsWithPort(port) {
*
* @class {RmHaConfigInitializer}
*/
-App.RmHaConfigInitializer = App.HaConfigInitializerClass.create({
+App.RmHaConfigInitializer = App.HaConfigInitializerClass.create(App.HostsBasedInitializerMixin, {
- initializers: {
- 'yarn.resourcemanager.hostname.rm1': App.HaConfigInitializerClass.getHostWithPortConfig('RESOURCEMANAGER', true, '', '', ''),
- 'yarn.resourcemanager.hostname.rm2': App.HaConfigInitializerClass.getHostWithPortConfig('RESOURCEMANAGER', false,'', '', ''),
- 'yarn.resourcemanager.zk-address': App.HaConfigInitializerClass.getHostsWithPortConfig('ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true),
- 'yarn.resourcemanager.webapp.address.rm1': App.HaConfigInitializerClass.getHostWithPortConfig('RESOURCEMANAGER', true, '', '', 'webAddressPort', true),
- 'yarn.resourcemanager.webapp.address.rm2': App.HaConfigInitializerClass.getHostWithPortConfig('RESOURCEMANAGER', false, '', '', 'webAddressPort', true),
- 'yarn.resourcemanager.webapp.https.address.rm1': App.HaConfigInitializerClass.getHostWithPortConfig('RESOURCEMANAGER', true, '', '', 'httpsWebAddressPort', true),
- 'yarn.resourcemanager.webapp.https.address.rm2': App.HaConfigInitializerClass.getHostWithPortConfig('RESOURCEMANAGER', false, '', '', 'httpsWebAddressPort', true),
- 'yarn.resourcemanager.ha': getRmHaHostsWithPort(8032),
- 'yarn.resourcemanager.scheduler.ha': getRmHaHostsWithPort(8030)
- },
+ initializers: function () {
+ return {
+ 'yarn.resourcemanager.hostname.rm1': this.getHostWithPortConfig('RESOURCEMANAGER', true, '', '', ''),
+ 'yarn.resourcemanager.hostname.rm2': this.getHostWithPortConfig('RESOURCEMANAGER', false,'', '', ''),
+ 'yarn.resourcemanager.zk-address': this.getHostsWithPortConfig('ZOOKEEPER_SERVER', '', '', ',', 'zkClientPort', true),
+ 'yarn.resourcemanager.webapp.address.rm1': this.getHostWithPortConfig('RESOURCEMANAGER', true, '', '', 'webAddressPort', true),
+ 'yarn.resourcemanager.webapp.address.rm2': this.getHostWithPortConfig('RESOURCEMANAGER', false, '', '', 'webAddressPort', true),
+ 'yarn.resourcemanager.webapp.https.address.rm1': this.getHostWithPortConfig('RESOURCEMANAGER', true, '', '', 'httpsWebAddressPort', true),
+ 'yarn.resourcemanager.webapp.https.address.rm2': this.getHostWithPortConfig('RESOURCEMANAGER', false, '', '', 'httpsWebAddressPort', true),
+ 'yarn.resourcemanager.ha': getRmHaHostsWithPort(8032),
+ 'yarn.resourcemanager.scheduler.ha': getRmHaHostsWithPort(8030)
+ };
+ }.property(),
initializerTypes: [
{name: 'rm_hosts_with_port', method: '_initRmHaHostsWithPort'},
],
-
+
/**
* Initializer for configs that should be updated with yarn resourcemanager ha host addresses with port
*
@@ -81,4 +84,4 @@ App.RmHaConfigInitializer = App.HaConfigInitializerClass.create({
return configProperty;
}
-});
\ No newline at end of file
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/6c38d84b/ambari-web/test/controllers/main/host/details_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/host/details_test.js b/ambari-web/test/controllers/main/host/details_test.js
index 9c8e4ad..947ec82 100644
--- a/ambari-web/test/controllers/main/host/details_test.js
+++ b/ambari-web/test/controllers/main/host/details_test.js
@@ -33,7 +33,6 @@ function getController() {
})
});
}
-
describe('App.MainHostDetailsController', function () {
beforeEach(function () {
@@ -1044,15 +1043,9 @@ describe('App.MainHostDetailsController', function () {
};
beforeEach(function () {
- sinon.stub(controller, "getZkServerHosts", Em.K);
- sinon.stub(controller, "concatZkNames", Em.K);
- sinon.stub(controller, "setZKConfigs", Em.K);
sinon.stub(controller, 'saveConfigsBatch', Em.K);
});
afterEach(function () {
- controller.getZkServerHosts.restore();
- controller.concatZkNames.restore();
- controller.setZKConfigs.restore();
controller.saveConfigsBatch.restore();
});
@@ -1097,203 +1090,281 @@ describe('App.MainHostDetailsController', function () {
});
});
- describe('#setZKConfigs()', function () {
- it('configs is null', function () {
- expect(controller.setZKConfigs(null)).to.be.false;
- });
- it('zks is null', function () {
- expect(controller.setZKConfigs({}, '', null)).to.be.false;
- });
- it('isHaEnabled = true', function () {
- var configs = {'core-site': {}};
- App.HostComponent.find().clear();
- App.store.load(App.Service, {
- id: 'HDFS',
- service_name: 'HDFS'
+ describe('#updateZkConfigs()', function () {
+ var makeHostComponentModel = function(componentName, hostNames) {
+ return hostNames.map(function(hostName) {
+ return {
+ componentName: componentName,
+ hostName: hostName
+ };
});
- App.propertyDidChange('isHaEnabled');
- expect(controller.setZKConfigs(configs, 'host1:2181', [])).to.be.true;
- expect(configs).to.eql({
- "core-site": {
- "ha.zookeeper.quorum": "host1:2181"
+ };
+
+ var tests = [
+ {
+ appGetterStubs: {
+ isHaEnabled: true
+ },
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "core-site": {
+ "ha.zookeeper.quorum": "host2:8080"
+ }
+ },
+ m: 'NameNode HA enabled, ha.zookeeper.quorum config should be updated',
+ e: {
+ configs: {
+ "core-site": {
+ "ha.zookeeper.quorum": "host1:2181,host2:2181"
+ }
+ }
}
- });
- App.store.load(App.HostComponent, {
- id: 'SECONDARY_NAMENODE_host1',
- component_name: 'SECONDARY_NAMENODE'
- });
- App.propertyDidChange('isHaEnabled');
- });
- it('hbase-site is present', function () {
- var configs = {'hbase-site': {}};
- expect(controller.setZKConfigs(configs, '', ['host1', 'host2'])).to.be.true;
- expect(configs).to.eql({
- "hbase-site": {
- "hbase.zookeeper.quorum": "host1,host2"
+ },
+ {
+ appGetterStubs: {
+ isHaEnabled: false
+ },
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "core-site": {
+ "ha.zookeeper.quorum": "host3:8080"
+ }
+ },
+ m: 'NameNode HA disabled, ha.zookeeper.quorum config should be untouched',
+ e: {
+ configs: {
+ "core-site": {
+ "ha.zookeeper.quorum": "host3:8080"
+ }
+ }
}
- });
- });
- it('accumulo-site is present', function () {
- var configs = {'accumulo-site': {}};
- expect(controller.setZKConfigs(configs, 'host1:2181', [])).to.be.true;
- expect(configs).to.eql({
- "accumulo-site": {
- "instance.zookeeper.host": 'host1:2181'
+ },
+ {
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "hbase-site": {
+ "hbase.zookeeper.quorum": "host3"
+ }
+ },
+ m: 'hbase.zookeeper.quorum property update test',
+ e: {
+ configs: {
+ "hbase-site": {
+ "hbase.zookeeper.quorum": "host1,host2"
+ }
+ }
}
- });
- });
- it('webhcat-site is present', function () {
- var configs = {'webhcat-site': {}};
- expect(controller.setZKConfigs(configs, 'host1:2181', [])).to.be.true;
- expect(configs).to.eql({
- "webhcat-site": {
- "templeton.zookeeper.hosts": "host1:2181"
+ },
+ {
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ ctrlStubs: {
+ 'content.hostName': 'host2',
+ fromDeleteHost: true
+ },
+ configs: {
+ "zoo.cfg": {
+ "clientPort": "1919"
+ },
+ "accumulo-site": {
+ "instance.zookeeper.host": "host3:2020"
+ }
+ },
+ m: 'instance.zookeeper.host property update test, zookeper marked to delete from host2',
+ e: {
+ configs: {
+ "zoo.cfg": {
+ "clientPort": "1919"
+ },
+ "accumulo-site": {
+ "instance.zookeeper.host": "host1:1919"
+ }
+ }
}
- });
- });
- it('hive-site is present and stack < 2.2', function () {
- var version = App.get('currentStackVersion');
- var configs = {'hive-site': {}};
- App.set('currentStackVersion', 'HDP-2.1.0');
- expect(controller.setZKConfigs(configs, 'host1:2181', [])).to.be.true;
- expect(configs).to.eql({
- "hive-site": {
- 'hive.cluster.delegation.token.store.zookeeper.connectString': "host1:2181"
+ },
+ {
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "webhcat-site": {
+ "templeton.zookeeper.hosts": "host3:2020"
+ }
+ },
+ m: 'templeton.zookeeper.hosts property update test',
+ e: {
+ configs: {
+ "webhcat-site": {
+ "templeton.zookeeper.hosts": "host1:2181,host2:2181"
+ }
+ }
}
- });
- App.set('currentStackVersion', version);
- });
- it('hive-site is present and stack > 2.2', function () {
- var version = App.get('currentStackVersion');
- var configs = {'hive-site': {}};
- App.set('currentStackVersion', 'HDP-2.2.0');
- expect(controller.setZKConfigs(configs, 'host1:2181', [])).to.be.true;
- expect(configs).to.eql({
- "hive-site": {
- 'hive.cluster.delegation.token.store.zookeeper.connectString': "host1:2181",
- 'hive.zookeeper.quorum': "host1:2181"
+ },
+ {
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "hive-site": {
+ "hive.cluster.delegation.token.store.zookeeper.connectString": "host3:2020"
+ }
+ },
+ m: 'hive.cluster.delegation.token.store.zookeeper.connectString property update test',
+ e: {
+ configs: {
+ "hive-site": {
+ "hive.cluster.delegation.token.store.zookeeper.connectString": "host1:2181,host2:2181"
+ }
+ }
}
- });
- App.set('currentStackVersion', version);
- });
- it('yarn-site is present and stack > 2.2', function () {
- var version = App.get('currentStackVersion');
- var configs = {'yarn-site': {}};
- App.set('currentStackVersion', 'HDP-2.2.0');
- expect(controller.setZKConfigs(configs, 'host1:2181', [])).to.be.true;
- expect(configs).to.eql({
- "yarn-site": {
- 'hadoop.registry.zk.quorum': "host1:2181",
- 'yarn.resourcemanager.zk-address': "host1:2181"
+ },
+ {
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "storm-site": {
+ "storm.zookeeper.servers": "['host3','host2']"
+ }
+ },
+ m: 'storm.zookeeper.servers property update test',
+ e: {
+ configs: {
+ "storm-site": {
+ "storm.zookeeper.servers": "['host1','host2']"
+ }
+ }
}
- });
- App.set('currentStackVersion', version);
- });
- it('storm-site is present', function () {
- var configs = {'storm-site': {}};
- expect(controller.setZKConfigs(configs, '', ["host1", 'host2'])).to.be.true;
- expect(configs).to.eql({
- "storm-site": {
- "storm.zookeeper.servers": "['host1','host2']"
+ },
+ {
+ appGetterStubs: {
+ isRMHaEnabled: true
+ },
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "yarn-site": {
+ "yarn.resourcemanager.zk-address": "host3:2181"
+ }
+ },
+ m: 'yarn.resourcemanager.zk-address property, ResourceManager HA enabled. Property value should be changed.',
+ e: {
+ configs: {
+ "yarn-site": {
+ "yarn.resourcemanager.zk-address": "host1:2181,host2:2181"
+ }
+ }
}
- });
- });
- it('isRMHaEnabled true', function () {
- var configs = {'yarn-site': {}};
- sinon.stub(App, 'get').withArgs('isRMHaEnabled').returns(true);
- expect(controller.setZKConfigs(configs, 'host1:2181', ['host1', 'host2'])).to.be.true;
- expect(configs).to.eql({
- "yarn-site": {
- "yarn.resourcemanager.zk-address": "host1:2181"
+ },
+ {
+ appGetterStubs: {
+ isRMHaEnabled: false
+ },
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "yarn-site": {
+ "yarn.resourcemanager.zk-address": "host3:2181"
+ }
+ },
+ m: 'yarn.resourcemanager.zk-address property, ResourceManager HA not activated. Property value should be untouched.',
+ e: {
+ configs: {
+ "yarn-site": {
+ "yarn.resourcemanager.zk-address": "host3:2181"
+ }
+ }
}
- });
- App.get.restore();
- });
- });
-
- describe('#concatZkNames()', function () {
- it('No ZooKeeper hosts', function () {
- expect(controller.concatZkNames([])).to.equal('');
- });
- it('One ZooKeeper host', function () {
- expect(controller.concatZkNames(['host1'], '2181')).to.equal('host1:2181');
- });
- it('Two ZooKeeper hosts', function () {
- expect(controller.concatZkNames(['host1', 'host2'], '2181')).to.equal('host1:2181,host2:2181');
- });
- });
-
- describe('#getZkServerHosts()', function () {
-
- beforeEach(function () {
- controller.set('content', {});
- });
-
- afterEach(function () {
- App.HostComponent.find.restore();
- });
-
- it('No ZooKeeper hosts, fromDeleteHost = false', function () {
- sinon.stub(App.HostComponent, 'find', function () {
- return []
- });
- controller.set('fromDeleteHost', false);
- expect(controller.getZkServerHosts()).to.be.empty;
- });
-
- it('No ZooKeeper hosts, fromDeleteHost = true', function () {
- sinon.stub(App.HostComponent, 'find', function () {
- return []
- });
- controller.set('fromDeleteHost', true);
- expect(controller.getZkServerHosts()).to.be.empty;
- expect(controller.get('fromDeleteHost')).to.be.false;
- });
-
- it('One ZooKeeper host, fromDeleteHost = false', function () {
- controller.set('fromDeleteHost', false);
- sinon.stub(App.HostComponent, 'find', function () {
- return [
- {
- id: 'ZOOKEEPER_SERVER_host1',
- componentName: 'ZOOKEEPER_SERVER',
- hostName: 'host1'
+ },
+ {
+ appGetterStubs: {
+ currentStackVersionNumber: '2.2'
+ },
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "hive-site": {
+ "hive.zookeeper.quorum": "host3:2181"
}
- ]
- });
- expect(controller.getZkServerHosts()).to.eql(['host1']);
- });
-
- it('One ZooKeeper host match current host name, fromDeleteHost = true', function () {
- sinon.stub(App.HostComponent, 'find', function () {
- return [
- {
- id: 'ZOOKEEPER_SERVER_host1',
- componentName: 'ZOOKEEPER_SERVER',
- hostName: 'host1'
+ },
+ m: 'hive.zookeeper.quorum property, current stack version is 2.2 property should be updated.',
+ e: {
+ configs: {
+ "hive-site": {
+ "hive.zookeeper.quorum": "host1:2181,host2:2181"
+ }
}
- ]
- });
- controller.set('fromDeleteHost', true);
- controller.set('content.hostName', 'host1');
- expect(controller.getZkServerHosts()).to.be.empty;
- expect(controller.get('fromDeleteHost')).to.be.false;
- });
-
- it('One ZooKeeper host does not match current host name, fromDeleteHost = true', function () {
- sinon.stub(App.HostComponent, 'find', function () {
- return [
- {
- id: 'ZOOKEEPER_SERVER_host1',
- componentName: 'ZOOKEEPER_SERVER',
- hostName: 'host1'
+ }
+ },
+ {
+ appGetterStubs: {
+ currentStackVersionNumber: '2.1'
+ },
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "hive-site": {
+ "hive.zookeeper.quorum": "host3:2181"
}
- ]
+ },
+ m: 'hive.zookeeper.quorum property, current stack version is 2.1 property should be untouched.',
+ e: {
+ configs: {
+ "hive-site": {
+ "hive.zookeeper.quorum": "host3:2181"
+ }
+ }
+ }
+ },
+ {
+ appGetterStubs: {
+ currentStackVersionNumber: '2.1'
+ },
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "yarn-site": {
+ "hadoop.registry.zk.quorum": "host3:2181"
+ }
+ },
+ m: 'hadoop.registry.zk.quorum property, current stack version is 2.1 property should be untouched.',
+ e: {
+ configs: {
+ "yarn-site": {
+ "hadoop.registry.zk.quorum": "host3:2181"
+ }
+ }
+ }
+ },
+ {
+ appGetterStubs: {
+ currentStackVersionNumber: '2.2'
+ },
+ hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+ configs: {
+ "yarn-site": {
+ "hadoop.registry.zk.quorum": "host3:2181"
+ }
+ },
+ m: 'hadoop.registry.zk.quorum property, current stack version is 2.2 property should be changed.',
+ e: {
+ configs: {
+ "yarn-site": {
+ "hadoop.registry.zk.quorum": "host1:2181,host2:2181"
+ }
+ }
+ }
+ }
+ ];
+
+ tests.forEach(function(test) {
+ it(test.m, function() {
+ if (test.appGetterStubs) {
+ Em.keys(test.appGetterStubs).forEach(function(key) {
+ sinon.stub(App, 'get').withArgs(key).returns(test.appGetterStubs[key]);
+ });
+ }
+ if (test.ctrlStubs) {
+ var stub = sinon.stub(controller, 'get');
+ Em.keys(test.ctrlStubs).forEach(function(key) {
+ stub.withArgs(key).returns(test.ctrlStubs[key]);
+ });
+ }
+ sinon.stub(App.HostComponent, 'find').returns(test.hostComponentModel);
+ controller.updateZkConfigs(test.configs);
+ expect(test.configs).to.be.eql(test.e.configs);
+ if (test.ctrlStubs) controller.get.restore();
+ if (test.appGetterStubs) App.get.restore();
+ App.HostComponent.find.restore();
});
- controller.set('fromDeleteHost', true);
- controller.set('content.hostName', 'host2');
- expect(controller.getZkServerHosts()[0]).to.equal("host1");
- expect(controller.get('fromDeleteHost')).to.be.false;
});
});
@@ -3090,7 +3161,11 @@ describe('App.MainHostDetailsController', function () {
Em.keys(item.input).forEach(function (key) {
controller.set(key, item.input[key]);
});
- expect(controller.getHiveHosts().toArray()).to.eql(item.hiveHosts);
+ var hostsMap = controller.getHiveHosts().toArray();
+ var expectedHosts = hostsMap.filter(function(hostInfo) {
+ return ['WEBHCAT_SERVER', 'HIVE_METASTORE'].contains(hostInfo.component) && hostInfo.isInstalled === true;
+ }).mapProperty('hostName').uniq();
+ expect(expectedHosts).to.include.same.members(item.hiveHosts);
expect(controller.get('hiveMetastoreHost')).to.be.empty;
expect(controller.get('webhcatServerHost')).to.be.empty;
expect(controller.get('fromDeleteHost')).to.be.false;
@@ -3412,4 +3487,297 @@ describe('App.MainHostDetailsController', function () {
});
});
+ describe('#onLoadHiveConfigs', function() {
+
+ beforeEach(function() {
+ sinon.stub(controller, 'saveConfigsBatch', Em.K);
+ });
+
+ afterEach(function() {
+ controller.saveConfigsBatch.restore();
+ });
+
+ var makeHostComponentModel = function(componentName, hostNames) {
+ if (Em.isArray(componentName)) {
+ return componentName.map(function(componentName, index) {
+ return makeHostComponentModel(componentName, hostNames[index]);
+ }).reduce(function(p,c) { return p.concat(c); }, []);
+ }
+ return hostNames.map(function(hostName) {
+ return {
+ componentName: componentName,
+ hostName: hostName
+ };
+ });
+ };
+
+ var makeFileNameProps = function(fileName, configs) {
+ var ret = {
+ type: fileName,
+ properties: {}
+ };
+ var propRet = {};
+ configs.forEach(function(property) {
+ propRet[property[0]] = property[1];
+ });
+ ret.properties = propRet;
+ return ret;
+ };
+
+ var makeEmptyPropAttrs = function() {
+ var fileNames = Array.prototype.slice.call(arguments);
+ var ret = {};
+ fileNames.forEach(function(fileName) {
+ ret[fileName] = {};
+ });
+ return ret;
+ };
+
+ var inlineComponentHostInfo = function(hostComponentModel) {
+ return hostComponentModel.mapProperty('componentName').uniq()
+ .map(function(componentName) {
+ return componentName + ":" + hostComponentModel.filterProperty('componentName', componentName).mapProperty('hostName').join();
+ }).join(',');
+ };
+
+ var tests = [
+ {
+ hostComponentModel: makeHostComponentModel(['HIVE_SERVER', 'HIVE_METASTORE'], [['host1', 'host2'], ['host1']]),
+ configs: {
+ items: [
+ makeFileNameProps('hive-site', [
+ ['hive.metastore.uris', 'thrift://host1:9090']
+ ]),
+ makeFileNameProps('hive-env', [
+ ['hive_user', 'hive_user_val'],
+ ['webhcat_user', 'webhcat_user_val']
+ ]),
+ makeFileNameProps('webhcat-site', [
+ ['templeton.hive.properties', 'hive.metastore.local=false,hive.metastore.uris=thrift://host1:9083,hive.metastore.sasl.enabled=false']
+ ]),
+ makeFileNameProps('core-site', [
+ ['hadoop.proxyuser.hive_user_val.hosts', 'host1'],
+ ['hadoop.proxyuser.webhcat_user_val.hosts', 'host1']
+ ])
+ ]
+ },
+ m: 'Components: {0}, appropriate configs should be changed, thrift port 9090, Controller stubs: {1}',
+ e: {
+ configs: [
+ {
+ "properties": {
+ "hive-site": makeFileNameProps('hive-site', [
+ ['hive.metastore.uris', 'thrift://host1:9090']
+ ]).properties,
+ "webhcat-site": makeFileNameProps('webhcat-site', [
+ ['templeton.hive.properties', 'hive.metastore.local=false,hive.metastore.uris=thrift://host1:9090,hive.metastore.sasl.enabled=false']
+ ]).properties,
+ "hive-env": makeFileNameProps('hive-env', [
+ ['hive_user', 'hive_user_val'],
+ ['webhcat_user', 'webhcat_user_val']
+ ]).properties
+ },
+ "properties_attributes": makeEmptyPropAttrs("hive-site", "webhcat-site", "hive-env")
+ },
+ {
+ "properties": {
+ "core-site": makeFileNameProps('core-site', [
+ ['hadoop.proxyuser.hive_user_val.hosts', 'host1,host2'],
+ ['hadoop.proxyuser.webhcat_user_val.hosts', 'host1,host2']
+ ]).properties
+ },
+ "properties_attributes": makeEmptyPropAttrs("core-site")
+ },
+ ]
+ }
+ },
+ {
+ hostComponentModel: makeHostComponentModel(['HIVE_SERVER', 'HIVE_METASTORE', 'WEBHCAT_SERVER'], [['host1', 'host2'], ['host1'], ['host2']]),
+ ctrlStubs: {
+ webhcatServerHost: 'host3'
+ },
+ configs: {
+ items: [
+ makeFileNameProps('hive-site', [
+ ['hive.metastore.uris', 'thrift://host1']
+ ]),
+ makeFileNameProps('hive-env', [
+ ['hive_user', 'hive_user_val'],
+ ['webhcat_user', 'webhcat_user_val']
+ ]),
+ makeFileNameProps('webhcat-site', [
+ ['templeton.hive.properties', 'hive.metastore.local=false,hive.metastore.uris=thrift://host1:9083,hive.metastore.sasl.enabled=false']
+ ]),
+ makeFileNameProps('core-site', [
+ ['hadoop.proxyuser.hive_user_val.hosts', 'host1'],
+ ['hadoop.proxyuser.webhcat_user_val.hosts', 'host1']
+ ])
+ ]
+ },
+ m: 'Components: {0}, appropriate configs should be changed, thrift port should be default 9083, Controller Stubs: {1}',
+ e: {
+ configs: [
+ {
+ "properties": {
+ "hive-site": makeFileNameProps('hive-site', [
+ ['hive.metastore.uris', 'thrift://host1:9083,thrift://host2:9083,thrift://host3:9083']
+ ]).properties,
+ "webhcat-site": makeFileNameProps('webhcat-site', [
+ ['templeton.hive.properties', 'hive.metastore.local=false,hive.metastore.uris=thrift://host1:9083\\,thrift://host2:9083\\,thrift://host3:9083,hive.metastore.sasl.enabled=false']
+ ]).properties,
+ "hive-env": makeFileNameProps('hive-env', [
+ ['hive_user', 'hive_user_val'],
+ ['webhcat_user', 'webhcat_user_val']
+ ]).properties
+ },
+ "properties_attributes": makeEmptyPropAttrs("hive-site", "webhcat-site", "hive-env")
+ },
+ {
+ "properties": {
+ "core-site": makeFileNameProps('core-site', [
+ ['hadoop.proxyuser.hive_user_val.hosts', 'host1,host2,host3'],
+ ['hadoop.proxyuser.webhcat_user_val.hosts', 'host1,host2,host3']
+ ]).properties
+ },
+ "properties_attributes": makeEmptyPropAttrs("core-site")
+ },
+ ]
+ }
+ },
+ {
+ hostComponentModel: makeHostComponentModel(['HIVE_SERVER', 'HIVE_METASTORE', 'WEBHCAT_SERVER'], [['host1'], ['host1'], ['host1']]),
+ ctrlStubs: {
+ webhcatServerHost: 'host3',
+ hiveMetastoreHost: 'host2'
+ },
+ configs: {
+ items: [
+ makeFileNameProps('hive-site', [
+ ['hive.metastore.uris', 'thrift://host1:1111']
+ ]),
+ makeFileNameProps('hive-env', [
+ ['hive_user', 'hive_user_val'],
+ ['webhcat_user', 'webhcat_user_val']
+ ]),
+ makeFileNameProps('webhcat-site', [
+ ['templeton.hive.properties', 'hive.metastore.local=false,hive.metastore.uris=thrift://host1:9083,hive.metastore.sasl.enabled=false']
+ ]),
+ makeFileNameProps('core-site', [
+ ['hadoop.proxyuser.hive_user_val.hosts', 'host1'],
+ ['hadoop.proxyuser.webhcat_user_val.hosts', 'host1']
+ ])
+ ]
+ },
+ m: 'Components: {0}, appropriate configs should be changed, thrift port should be 1111, Controller Stubs: {1}',
+ e: {
+ configs: [
+ {
+ "properties": {
+ "hive-site": makeFileNameProps('hive-site', [
+ ['hive.metastore.uris', 'thrift://host1:1111,thrift://host2:1111,thrift://host3:1111']
+ ]).properties,
+ "webhcat-site": makeFileNameProps('webhcat-site', [
+ ['templeton.hive.properties', 'hive.metastore.local=false,hive.metastore.uris=thrift://host1:1111\\,thrift://host2:1111\\,thrift://host3:1111,hive.metastore.sasl.enabled=false']
+ ]).properties,
+ "hive-env": makeFileNameProps('hive-env', [
+ ['hive_user', 'hive_user_val'],
+ ['webhcat_user', 'webhcat_user_val']
+ ]).properties
+ },
+ "properties_attributes": makeEmptyPropAttrs("hive-site", "webhcat-site", "hive-env")
+ },
+ {
+ "properties": {
+ "core-site": makeFileNameProps('core-site', [
+ ['hadoop.proxyuser.hive_user_val.hosts', 'host1,host2,host3'],
+ ['hadoop.proxyuser.webhcat_user_val.hosts', 'host1,host2,host3']
+ ]).properties
+ },
+ "properties_attributes": makeEmptyPropAttrs("core-site")
+ },
+ ]
+ }
+ },
+ {
+ hostComponentModel: makeHostComponentModel(['HIVE_SERVER', 'HIVE_METASTORE', 'WEBHCAT_SERVER'], [['host1', 'host2'], ['host1','host2'], ['host1', 'host3']]),
+ ctrlStubs: {
+ fromDeleteHost: true,
+ 'content.hostName': 'host2',
+ webhcatServerHost: '',
+ hiveMetastoreHost: ''
+ },
+ configs: {
+ items: [
+ makeFileNameProps('hive-site', [
+ ['hive.metastore.uris', 'thrift://host1:1111']
+ ]),
+ makeFileNameProps('hive-env', [
+ ['hive_user', 'hive_user_val'],
+ ['webhcat_user', 'webhcat_user_val']
+ ]),
+ makeFileNameProps('webhcat-site', [
+ ['templeton.hive.properties', 'hive.metastore.local=false,hive.metastore.uris=thrift://host1:9083,hive.metastore.sasl.enabled=false']
+ ]),
+ makeFileNameProps('core-site', [
+ ['hadoop.proxyuser.hive_user_val.hosts', 'host1'],
+ ['hadoop.proxyuser.webhcat_user_val.hosts', 'host1']
+ ])
+ ]
+ },
+ m: 'Components: {0}, appropriate configs should be changed, thrift port should be default 9083, Controller Stubs: {1}',
+ e: {
+ configs: [
+ {
+ "properties": {
+ "hive-site": makeFileNameProps('hive-site', [
+ ['hive.metastore.uris', 'thrift://host1:1111,thrift://host3:1111']
+ ]).properties,
+ "webhcat-site": makeFileNameProps('webhcat-site', [
+ ['templeton.hive.properties', 'hive.metastore.local=false,hive.metastore.uris=thrift://host1:1111\\,thrift://host3:1111,hive.metastore.sasl.enabled=false']
+ ]).properties,
+ "hive-env": makeFileNameProps('hive-env', [
+ ['hive_user', 'hive_user_val'],
+ ['webhcat_user', 'webhcat_user_val']
+ ]).properties
+ },
+ "properties_attributes": makeEmptyPropAttrs("hive-site", "webhcat-site", "hive-env")
+ },
+ {
+ "properties": {
+ "core-site": makeFileNameProps('core-site', [
+ ['hadoop.proxyuser.hive_user_val.hosts', 'host1,host3'],
+ ['hadoop.proxyuser.webhcat_user_val.hosts', 'host1,host3']
+ ]).properties
+ },
+ "properties_attributes": makeEmptyPropAttrs("core-site")
+ },
+ ]
+ }
+ }
+ ];
+
+ tests.forEach(function(test) {
+ it(test.m.format(inlineComponentHostInfo(test.hostComponentModel), test.ctrlStubs ? JSON.stringify(test.ctrlStubs) : 'None'), function() {
+ if (test.appGetterStubs) {
+ Em.keys(test.appGetterStubs).forEach(function(key) {
+ sinon.stub(App, 'get').withArgs(key).returns(test.appGetterStubs[key]);
+ });
+ }
+ if (test.ctrlStubs) {
+ var stub = sinon.stub(controller, 'get');
+ Em.keys(test.ctrlStubs).forEach(function(key) {
+ stub.withArgs(key).returns(test.ctrlStubs[key]);
+ });
+ }
+ sinon.stub(App.HostComponent, 'find').returns(test.hostComponentModel);
+ controller.onLoadHiveConfigs(test.configs);
+ var configs = controller.saveConfigsBatch.args[0];
+ var properties = configs[0];
+ expect(properties).to.be.eql(test.e.configs);
+ if (test.ctrlStubs) controller.get.restore();
+ if (test.appGetterStubs) App.get.restore();
+ App.HostComponent.find.restore();
+ });
+ });
+ });
});
[2/2] ambari git commit: AMBARI-14416. Refactor Host Details
controller
Posted by al...@apache.org.
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/trunk
Commit: 6c38d84b1152807c0b94f175e090d90ad0c74a28
Parents: 2c7ecd1
Author: Alex Antonenko <hi...@gmail.com>
Authored: Fri Dec 18 18:59:19 2015 +0200
Committer: Alex Antonenko <hi...@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