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