You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2014/07/09 06:29:46 UTC

[3/6] AMBARI-6430. Make new services pluggable to the wizard. (jaimin via yusaku)

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/models/stack_service.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/stack_service.js b/ambari-web/app/models/stack_service.js
new file mode 100644
index 0000000..8085a03
--- /dev/null
+++ b/ambari-web/app/models/stack_service.js
@@ -0,0 +1,382 @@
+/**
+ * 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/helper');
+require('mixins/models/service_mixin');
+require('models/service_config');
+require('utils/configs/defaults_providers/yarn_defaults_provider');
+require('utils/configs/defaults_providers/tez_defaults_provider');
+require('utils/configs/defaults_providers/hive_defaults_provider');
+require('utils/configs/defaults_providers/storm_defaults_provider');
+require('utils/configs/defaults_providers/oozie_defaults_provider');
+require('utils/configs/validators/yarn_configs_validator');
+require('utils/configs/validators/hive_configs_validator');
+require('utils/configs/validators/tez_configs_validator');
+require('utils/configs/validators/mapreduce2_configs_validator');
+require('utils/configs/validators/storm_configs_validator');
+
+/**
+ * This model loads all services supported by the stack
+ * The model maps to the  http://hostname:8080/api/v1/stacks2/HDP/versions/${versionNumber}/stackServices?fields=StackServices/*,serviceComponents/*
+ * @type {*}
+ */
+App.StackService = DS.Model.extend(App.ServiceModelMixin, {
+  comments: DS.attr('string'),
+  configTypes: DS.attr('array'),
+  serviceVersion: DS.attr('string'),
+  stackName: DS.attr('string'),
+  stackVersion: DS.attr('string'),
+  isSelected: DS.attr('boolean', {defaultValue: true}),
+  isInstalled: DS.attr('boolean', {defaultValue: false}),
+  serviceComponents: DS.hasMany('App.StackServiceComponent'),
+  configs: DS.attr('array'),
+
+  // Is the service a distributed filesystem
+  isDFS: function () {
+    var dfsServices = ['HDFS', 'GLUSTERFS'];
+    return dfsServices.contains(this.get('serviceName'));
+  }.property('serviceName'),
+
+  // Primary DFS. used if there is more than one DFS in a stack.
+  // Only one service in the stack should be tagged as primary DFS.
+  isPrimaryDFS: function () {
+    return this.get('serviceName') === 'HDFS';
+  }.property('serviceName'),
+
+  displayNameOnSelectServicePage: function () {
+    var displayName = this.get('displayName');
+    var services = this.get('coSelectedServices').slice();
+    var serviceDisplayNames = services.map(function (item) {
+      return App.format.role(item);
+    }, this);
+    if (!!serviceDisplayNames.length) {
+      serviceDisplayNames.unshift(displayName);
+      displayName = serviceDisplayNames.join(" + ");
+    }
+    return displayName;
+  }.property('coSelectedServices', 'serviceName'),
+
+  isHiddenOnSelectServicePage: function () {
+    var hiddenServices = ['MAPREDUCE2', 'HCATALOG', 'WEBHCAT'];
+    return hiddenServices.contains(this.get('serviceName'));
+  }.property('serviceName'),
+
+  dependentServices: function () {
+    var serviceName = this.get('serviceName');
+    var dependentServices = [];
+    if (App.get('isHadoop2Stack')) {
+      dependentServices = App.StackService.dependency['HDP-2'][serviceName];
+    } else {
+      dependentServices = App.StackService.dependency['HDP-1'][serviceName];
+    }
+    return dependentServices;
+  }.property('serviceName'),
+
+  /**
+   * other services on which the service is dependent
+   */
+  serviceDependency: function () {
+    var serviceName = this.get('serviceName');
+    var serviceDependencyMap, key, serviceDependencies = [];
+    if (App.get('isHadoop2Stack')) {
+      serviceDependencyMap = App.StackService.dependency['HDP-2'];
+    } else {
+      serviceDependencyMap = App.StackService.dependency['HDP-1'];
+    }
+    for (key in serviceDependencyMap) {
+      if (serviceDependencyMap[key].contains(serviceName)) serviceDependencies.pushObject(key);
+    }
+    return  serviceDependencies;
+  }.property('serviceName'),
+
+  // Is the service required for monitoring of other hadoop ecosystem services
+  isMonitoringService: function () {
+    var services = ['NAGIOS', 'GANGLIA'];
+    return services.contains(this.get('serviceName'));
+  }.property('serviceName'),
+
+  coSelectedServices: function () {
+    var coSelectedServices = App.StackService.coSelected[this.get('serviceName')];
+    if (!!coSelectedServices) {
+      return coSelectedServices;
+    } else {
+      return [];
+    }
+  }.property('serviceName'),
+
+  hasClient: function () {
+    var serviceComponents = this.get('serviceComponents');
+    return serviceComponents.someProperty('isClient');
+  }.property('serviceName'),
+
+  isClientOnlyService: function () {
+    var serviceComponents = this.get('serviceComponents');
+    return serviceComponents.everyProperty('isClient');
+  }.property('serviceName'),
+
+  isNoConfigTypes: function () {
+   return !(this.get('configTypes') && this.get('configTypes').length);
+  }.property('configTypes'),
+
+  customReviewHandler: function () {
+    return App.StackService.reviewPageHandlers[this.get('serviceName')];
+  }.property('serviceName'),
+
+  defaultsProviders: function () {
+    var defaultConfigsHandler = App.StackService.defaultConfigsHandler[this.get('serviceName')];
+    return defaultConfigsHandler && defaultConfigsHandler.defaultsProviders;
+  }.property('serviceName'),
+
+  configsValidator: function () {
+    var defaultConfigsHandler = App.StackService.defaultConfigsHandler[this.get('serviceName')];
+    return defaultConfigsHandler && defaultConfigsHandler.configsValidator;
+  }.property('serviceName'),
+
+  /**
+   * configCategories are fetched from  App.StackService.configCategories.
+   * Also configCategories that does not match any serviceComponent of a service and not included in the permissible default pattern are omitted
+   */
+  configCategories: function () {
+    var configCategories = [];
+    var serviceName = this.get('serviceName');
+    var configTypes = this.get('configTypes');
+    var serviceComponents = this.get('serviceComponents');
+    if (configTypes.length) {
+      var pattern = ["General", "CapacityScheduler", "^Advanced", "^Custom", "Falcon - Oozie integration", "FalconStartupSite", "FalconRuntimeSite"];
+      configCategories = App.StackService.configCategories(serviceName).filter(function (_configCategory) {
+        var serviceComponentName = _configCategory.get('name');
+        var isServiceComponent = serviceComponents.someProperty('componentName', serviceComponentName);
+        if (isServiceComponent) return  isServiceComponent;
+        var result = false;
+        pattern.forEach(function (_pattern) {
+          var regex = new RegExp(_pattern);
+          if (regex.test(serviceComponentName)) result = true;
+        });
+        return result;
+      });
+    }
+    return configCategories;
+  }.property('serviceName', 'configTypes', 'serviceComponents'),
+
+  serviceConfigs: function () {
+    var configCategories = [];
+    var serviceName = this.get('serviceName');
+    var serviceComponents = this.get('serviceComponents');
+    configCategories = App.StackService.configCategories(serviceName).filter(function (_configCategory) {
+      var serviceComponentName = _configCategory.get('name');
+      return serviceComponents.someProperty('componentName', serviceComponentName);
+    });
+    return configCategories;
+  }.observes('serviceName', 'serviceComponents')
+
+});
+
+App.StackService.FIXTURES = [];
+
+App.StackService.displayOrder = [
+  'HDFS',
+  'MAPREDUCE',
+  'MAPREDUCE2',
+  'YARN',
+  'TEZ',
+  'NAGIOS',
+  'GANGLIA',
+  'HIVE',
+  'HCATALOG',
+  'WEBHCAT',
+  'HBASE',
+  'PIG',
+  'SQOOP',
+  'OOZIE',
+  'ZOOKEEPER',
+  'HUE',
+  'FALCON',
+  'STORM',
+  'FLUME'
+];
+
+App.StackService.dependency = {
+  'HDP-1': {
+    'MAPREDUCE': ['PIG', 'OOZIE', 'HIVE'],
+    'ZOOKEEPER': ['HBASE', 'HIVE', 'WEBHCAT']
+  },
+  'HDP-2': {
+    'YARN': ['PIG', 'OOZIE', 'HIVE', 'TEZ'],
+    'TEZ': ['YARN'],
+    'OOZIE': ['FALCON'],
+    'ZOOKEEPER': ['HDFS', 'HBASE', 'HIVE', 'WEBHCAT', 'STORM']
+  }
+};
+
+//@TODO: Write unit test for no two keys in the object should have any intersecting elements in their values
+App.StackService.coSelected = {
+  'YARN': ['MAPREDUCE2'],
+  'HIVE': ['HCATALOG', 'WEBHCAT']
+};
+
+
+App.StackService.reviewPageHandlers = {
+  'HIVE': {
+    'Database': 'loadHiveDbValue'
+  },
+  'NAGIOS': {
+    'Administrator': 'loadNagiosAdminValue'
+  },
+  'OOZIE': {
+    'Database': 'loadOozieDbValue'
+  }
+};
+
+App.StackService.defaultConfigsHandler = {
+  YARN: {defaultsProviders: [App.YARNDefaultsProvider.create()], configsValidator: App.YARNConfigsValidator},
+  MAPREDUCE2: {defaultsProviders: [App.YARNDefaultsProvider.create()], configsValidator: App.MapReduce2ConfigsValidator},
+  HIVE: {defaultsProviders: [App.HiveDefaultsProvider.create()], configsValidator: App.HiveConfigsValidator},
+  STORM: {defaultsProviders: [App.STORMDefaultsProvider.create()], configsValidator: App.STORMConfigsValidator},
+  TEZ: {defaultsProviders: [App.TezDefaultsProvider.create()], configsValidator: App.TezConfigsValidator}
+};
+
+App.StackService.configCategories = function (serviceName) {
+  switch (serviceName) {
+    case 'HDFS':
+      return [
+        App.ServiceConfigCategory.create({ name: 'NAMENODE', displayName: 'NameNode'}),
+        App.ServiceConfigCategory.create({ name: 'SECONDARY_NAMENODE', displayName: 'Secondary NameNode'}),
+        App.ServiceConfigCategory.create({ name: 'DATANODE', displayName: 'DataNode'}),
+        App.ServiceConfigCategory.create({ name: 'General', displayName: 'General'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedCoreSite', displayName: 'Custom core-site.xml', siteFileName: 'core-site.xml', canAddProperty: true}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedHDFSSite', displayName: 'Custom hdfs-site.xml', siteFileName: 'hdfs-site.xml', canAddProperty: true}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedHDFSLog4j', displayName: 'Custom log4j.properties', siteFileName: 'hdfs-log4j.xml', canAddProperty: false})
+      ];
+    case 'GLUSTERFS':
+      return [
+        App.ServiceConfigCategory.create({ name: 'General', displayName: 'General'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedGlusterFSSite', displayName : 'Custom core-site.xml', siteFileName: 'core-site.xml', canAddProperty: true})
+      ];
+    case 'MAPREDUCE':
+      return [
+        App.ServiceConfigCategory.create({ name: 'HISTORYSERVER', displayName: 'History Server'}),
+        App.ServiceConfigCategory.create({ name: 'JOBTRACKER', displayName: 'JobTracker'}),
+        App.ServiceConfigCategory.create({ name: 'TASKTRACKER', displayName: 'TaskTracker'}),
+        App.ServiceConfigCategory.create({ name: 'General', displayName: 'General'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedMapredSite', displayName: 'Custom mapred-site.xml', siteFileName: 'mapred-site.xml', canAddProperty: true}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedMapredLog4j', displayName: 'Custom log4j.properties', siteFileName: 'mapreduce-log4j.xml', canAddProperty: false})
+      ];
+    case 'YARN':
+      return [
+        App.ServiceConfigCategory.create({ name: 'RESOURCEMANAGER', displayName: 'Resource Manager'}),
+        App.ServiceConfigCategory.create({ name: 'NODEMANAGER', displayName: 'Node Manager'}),
+        App.ServiceConfigCategory.create({ name: 'APP_TIMELINE_SERVER', displayName: 'Application Timeline Server'}),
+        App.ServiceConfigCategory.create({ name: 'General', displayName: 'General'}),
+        App.ServiceConfigCategory.create({ name: 'CapacityScheduler', displayName: 'Scheduler', isCapacityScheduler: true, isCustomView: true, siteFileName: 'capacity-scheduler.xml', siteFileNames: ['capacity-scheduler.xml', 'mapred-queue-acls.xml'], canAddProperty: App.supports.capacitySchedulerUi}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedYARNSite', displayName: 'Custom yarn-site.xml', siteFileName: 'yarn-site.xml', canAddProperty: true}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedYARNLog4j', displayName: 'Custom log4j.properties', siteFileName: 'yarn-log4j.xml', canAddProperty: false})
+      ];
+    case 'MAPREDUCE2':
+      return [
+        App.ServiceConfigCategory.create({ name: 'HISTORYSERVER', displayName: 'History Server'}),
+        App.ServiceConfigCategory.create({ name: 'General', displayName: 'General'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedMapredSite', displayName: 'Custom mapred-site.xml', siteFileName: 'mapred-site.xml', canAddProperty: true}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedMapredLog4j', displayName: 'Custom log4j.properties', siteFileName: 'mapreduce2-log4j.xml', canAddProperty: false})
+      ];
+    case 'HIVE':
+      return [
+        App.ServiceConfigCategory.create({ name: 'HIVE_METASTORE', displayName: 'Hive Metastore'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedHiveSite', displayName: 'Custom hive-site.xml', siteFileName: 'hive-site.xml', canAddProperty: true}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedHiveLog4j', displayName: 'Custom log4j.properties', siteFileName: 'hive-log4j.xml', canAddProperty: false}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedHiveExecLog4j', displayName: 'Custom hive-exec-log4j', siteFileName: 'hive-exec-log4j.xml', canAddProperty: false})
+      ];
+    case 'WEBHCAT':
+      return [
+        App.ServiceConfigCategory.create({ name: 'WEBHCAT_SERVER', displayName: 'WebHCat Server'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedWebHCatSite', displayName: 'Custom webhcat-site.xml', siteFileName: 'webhcat-site.xml', canAddProperty: true})
+      ];
+    case 'HBASE':
+      return [
+        App.ServiceConfigCategory.create({ name: 'HBASE_MASTER', displayName: 'HBase Master'}),
+        App.ServiceConfigCategory.create({ name: 'HBASE_REGIONSERVER', displayName: 'RegionServer'}),
+        App.ServiceConfigCategory.create({ name: 'General', displayName: 'General'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedHbaseSite', displayName: 'Custom hbase-site.xml', siteFileName: 'hbase-site.xml', canAddProperty: true}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedHbaseLog4j', displayName: 'Custom log4j.properties', siteFileName: 'hbase-log4j.xml', canAddProperty: false})
+      ];
+    case 'ZOOKEEPER':
+      return [
+        App.ServiceConfigCategory.create({ name: 'ZOOKEEPER_SERVER', displayName: 'ZooKeeper Server'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedZooLog4j', displayName: 'Custom log4j.properties', siteFileName: 'zookeeper-log4j.xml', canAddProperty: false}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedZooCfg', displayName: 'Custom zoo.cfg', siteFileName: 'zoo.cfg', canAddProperty: true})
+      ];
+    case 'OOZIE':
+      return [
+        App.ServiceConfigCategory.create({ name: 'OOZIE_SERVER', displayName: 'Oozie Server'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedOozieSite', displayName: 'Custom oozie-site.xml', siteFileName: 'oozie-site.xml', canAddProperty: true}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedOozieLog4j', displayName: 'Custom log4j.properties', siteFileName: 'oozie-log4j.xml', canAddProperty: false})
+      ];
+    case 'PIG':
+    return [
+      App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Custom pig.properties', siteFileName: 'pig-properties.xml', canAddProperty: false}),
+      App.ServiceConfigCategory.create({ name: 'AdvancedPigLog4j', displayName: 'Custom log4j.properties', siteFileName: 'pig-log4j.xml', canAddProperty: false})
+    ];
+    case 'FALCON':
+      return [
+        App.ServiceConfigCategory.create({ name: 'FALCON_SERVER', displayName: 'Falcon Server'}),
+        App.ServiceConfigCategory.create({ name: 'Falcon - Oozie integration', displayName: 'Falcon - Oozie integration'}),
+        App.ServiceConfigCategory.create({ name: 'FalconStartupSite', displayName: 'Falcon startup.properties'}),
+        App.ServiceConfigCategory.create({ name: 'FalconRuntimeSite', displayName: 'Falcon runtime.properties'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedFalconStartupSite', displayName: 'Custom startup.properties', siteFileName: 'falcon-startup.properties.xml', canAddProperty: true}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedFalconRuntimeSite', displayName: 'Custom runtime.properties', siteFileName: 'falcon-runtime.properties.xml', canAddProperty: true})
+      ];
+    case 'STORM':
+      return [
+        App.ServiceConfigCategory.create({ name: 'NIMBUS', displayName: 'Nimbus'}),
+        App.ServiceConfigCategory.create({ name: 'SUPERVISOR', displayName: 'Supervisor'}),
+        App.ServiceConfigCategory.create({ name: 'STORM_UI_SERVER', displayName: 'Storm UI Server'}),
+        App.ServiceConfigCategory.create({ name: 'STORM_REST_API', displayName: 'Storm REST API Server'}),
+        App.ServiceConfigCategory.create({ name: 'DRPC_SERVER', displayName: 'DRPC Server'}),
+        App.ServiceConfigCategory.create({ name: 'General', displayName: 'General'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedStormSite', displayName: 'Custom storm.yaml', siteFileName: 'storm-site.xml', canAddProperty: true})
+      ];
+    case 'TEZ':
+      return [
+        App.ServiceConfigCategory.create({ name: 'General', displayName: 'General'}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced'}),
+        App.ServiceConfigCategory.create({ name: 'AdvancedTezSite', displayName: 'Custom tez-site.xml', siteFileName: 'tez-site.xml', canAddProperty: true})
+      ];
+    case 'FLUME':
+      return [
+        App.ServiceConfigCategory.create({ name: 'FLUME_HANDLER', displayName: 'flume.conf', siteFileName: 'flume-conf', canAddProperty: false})
+      ];
+    case 'HCATALOG':
+      return [];
+    default:
+      return [
+        App.ServiceConfigCategory.create({ name: 'General', displayName: 'General', canAddProperty: false}),
+        App.ServiceConfigCategory.create({ name: 'Advanced', displayName: 'Advanced', canAddProperty: false})
+      ];
+  }
+};

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/models/stack_service_component.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/stack_service_component.js b/ambari-web/app/models/stack_service_component.js
index 51f944a..10e9a51 100644
--- a/ambari-web/app/models/stack_service_component.js
+++ b/ambari-web/app/models/stack_service_component.js
@@ -23,15 +23,22 @@ var App = require('app');
  */
 App.StackServiceComponent = DS.Model.extend({
   componentName: DS.attr('string'),
+  dependencies: DS.attr('array'),
   serviceName: DS.attr('string'),
   componentCategory: DS.attr('string'),
   isMaster: DS.attr('boolean'),
   isClient: DS.attr('boolean'),
   stackName: DS.attr('string'),
   stackVersion: DS.attr('string'),
+  stackService: DS.belongsTo('App.StackService'),
+  serviceComponentId: DS.attr('number', {defaultValue: 1}), // this is used on Assign Master page for multiple masters
 
   displayName: function() {
-    return App.format.components[this.get('componentName')];
+    if (App.format.role(this.get('componentName'))) {
+      return App.format.role(this.get('componentName'));
+    } else {
+      return this.get('componentName');
+    }
   }.property('componentName'),
 
   isSlave: function() {
@@ -68,9 +75,140 @@ App.StackServiceComponent = DS.Model.extend({
 
   isShownOnInstallerAssignMasterPage: function() {
     var component = this.get('componentName');
-    var mastersNotShown = ['MYSQL_SERVER','JOURNALNODE'];
+    var mastersNotShown = ['MYSQL_SERVER'];
     return ((this.get('isMaster') && !mastersNotShown.contains(component)) || component === 'APP_TIMELINE_SERVER');
-  }.property('isMaster','componentName')
+  }.property('isMaster','componentName'),
+
+  isShownOnInstallerSlaveClientPage: function() {
+    var component = this.get('componentName');
+    var slavesNotShown = ['JOURNALNODE','ZKFC','APP_TIMELINE_SERVER','GANGLIA_MONITOR'];
+    return this.get('isSlave') && !slavesNotShown.contains(component);
+  }.property('isSlave','componentName'),
+
+  isShownOnAddServiceAssignMasterPage: function() {
+    var isVisible = this.get('isShownOnInstallerAssignMasterPage');
+    if (App.get('isHaEnabled')) {
+      isVisible =  isVisible && this.get('componentName') !== 'SECONDARY_NAMENODE';
+    }
+    return isVisible;
+  }.property('isShownOnInstallerAssignMasterPage','App.isHaEnabled'),
+
+  isMasterWithMultipleInstances: function() {
+    var masters = ['ZOOKEEPER_SERVER', 'HBASE_MASTER'];
+    return masters.contains(this.get('componentName'));
+  }.property('componentName'),
+
+  /** Some non master components can be assigned as master **/
+  isMasterBehavior: function() {
+    var componentsName = ['APP_TIMELINE_SERVER'];
+    return componentsName.contains(this.get('componentName'));
+  }.property('componentName'),
+
+  /** Some non client components can be assigned as clients **/
+  isClientBehavior: function() {
+    var componentName = ['GANGLIA_MONITOR'];
+    return componentName.contains(this.get('componentName'));
+  }.property('componentName'),
+
+  /** Components that can be installed only if HA enabled **/
+  isHAComponentOnly: function() {
+    var HAComponentNames = ['ZKFC','JOURNALNODE'];
+    return HAComponentNames.contains(this.get('componentName'));
+  }.property('componentName'),
+
+  // Is It require to install the components on all hosts. used in step-6 wizard controller
+  isRequiredOnAllHosts: function() {
+    var service = this.get('stackService');
+    return service.get('isMonitoringService') && this.get('isSlave') ;
+  }.property('stackService','isSlave'),
+
+  // components that are not to be installed with ambari server
+  isNotPreferableOnAmbariServerHost: function() {
+    var service = ['STORM_UI_SERVER', 'DRPC_SERVER', 'STORM_REST_API', 'NIMBUS', 'GANGLIA_SERVER', 'NAGIOS_SERVER', 'HUE_SERVER'];
+    return service.contains(this.get('componentName'));
+  }.property('componentName'),
+
+  // default number of master hosts on Assign Master page:
+  defaultNoOfMasterHosts: function() {
+    var componentName = this.get('componentName');
+     if (this.get('isMasterWithMultipleInstances')) {
+       return App.StackServiceComponent.cardinality(componentName).min;
+     }
+  }.property('componentName'),
+
+  selectionSchemeForMasterComponent: function() {
+    return App.StackServiceComponent.selectionScheme(this.get('componentName'));
+  }.property('componentName'),
+
+  isMasterWithMultipleInstancesHaWizard: function() {
+    var masters = ['NAMENODE', 'JOURNALNODE'];
+    return masters.contains(this.get('componentName'));
+  }.property('componentName'),
+
+  // components that are co-hosted with this component
+  coHostedComponents: function() {
+    var componentName = this.get('componentName');
+    var key, coHostedComponents = [];
+    for (key in App.StackServiceComponent.coHost) {
+      if (App.StackServiceComponent.coHost[key] === componentName) {
+        coHostedComponents.push(key)
+      }
+    }
+    return coHostedComponents;
+  }.property('componentName'),
+
+  // Is any other component co-hosted with this component
+  isOtherComponentCoHosted: function() {
+    return !!this.get('coHostedComponents').length;
+  }.property('coHostedComponents'),
+
+  // Is this component co-hosted with other component
+  isCoHostedComponent: function() {
+    var componentName = this.get('componentName');
+    return !!App.StackServiceComponent.coHost[componentName];
+  }.property('componentName')
+
 });
 
-App.StackServiceComponent.FIXTURES = [];
\ No newline at end of file
+App.StackServiceComponent.FIXTURES = [];
+
+App.StackServiceComponent.selectionScheme = function (componentName){
+  switch (componentName) {
+    case 'NAMENODE' :
+      return {"else": 0};
+    case 'SECONDARY_NAMENODE' :
+      return {"else": 1};
+    case 'HBASE_MASTER':
+      return {"6": 0, "31": 2, "else": 3};
+    case 'JOBTRACKER':
+    case 'HISTORYSERVER':
+    case 'RESOURCEMANAGER':
+    case 'APP_TIMELINE_SERVER':
+      return {"31": 1, "else": 2};
+    case 'OOZIE_SERVER':
+    case 'FALCON_SERVER' :
+      return {"6": 1, "31": 2, "else": 3};
+    case 'HIVE_SERVER' :
+    case 'HIVE_METASTORE' :
+    case 'WEBHCAT_SERVER' :
+      return {"6": 1, "31": 2, "else": 4};
+    default:
+      return {"else": 0};
+  }
+};
+
+App.StackServiceComponent.cardinality = function (componentName) {
+  switch (componentName) {
+    case 'ZOOKEEPER_SERVER':
+      return {min: 3};
+    case 'HBASE_MASTER':
+      return {min: 1};
+    default:
+      return {min:1, max:1};
+  }
+};
+
+App.StackServiceComponent.coHost = {
+  'HIVE_METASTORE': 'HIVE_SERVER',
+  'WEBHCAT_SERVER': 'HIVE_SERVER'
+};

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/routes/add_host_routes.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/add_host_routes.js b/ambari-web/app/routes/add_host_routes.js
index d73499c..2dad8dc 100644
--- a/ambari-web/app/routes/add_host_routes.js
+++ b/ambari-web/app/routes/add_host_routes.js
@@ -102,7 +102,6 @@ module.exports = App.WizardRoute.extend({
       controller.setCurrentStep('1');
       controller.set('hideBackButton', true);
       controller.dataLoading().done(function () {
-        controller.loadServicesFromServer();
         controller.loadAllPriorSteps();
         var wizardStep2Controller = router.get('wizardStep2Controller');
         wizardStep2Controller.set('wizardController', controller);
@@ -184,7 +183,6 @@ module.exports = App.WizardRoute.extend({
         var wizardStep6Controller = router.get('wizardStep6Controller');
         wizardStep6Controller.set('wizardController', controller);
         controller.connectOutlet('wizardStep6', controller.get('content'));
-        wizardStep6Controller.set('isMasters', false);
       });
     },
     back: Em.Router.transitionTo('step2'),

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/routes/add_service_routes.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/add_service_routes.js b/ambari-web/app/routes/add_service_routes.js
index 6cd9d9c..9aa6edb 100644
--- a/ambari-web/app/routes/add_service_routes.js
+++ b/ambari-web/app/routes/add_service_routes.js
@@ -102,9 +102,9 @@ module.exports = App.WizardRoute.extend({
       console.log('in addService.step1:connectOutlets');
       var controller = router.get('addServiceController');
       controller.setCurrentStep('1');
+      controller.setDBProperty('services',undefined);
       controller.set('hideBackButton', true);
       controller.dataLoading().done(function () {
-        controller.loadServicesFromServer();
         controller.loadAllPriorSteps();
         controller.connectOutlet('wizardStep4', controller.get('content.services'));
       })
@@ -153,7 +153,6 @@ module.exports = App.WizardRoute.extend({
         var wizardStep6Controller = router.get('wizardStep6Controller');
         wizardStep6Controller.set('wizardController', controller);
         controller.connectOutlet('wizardStep6', controller.get('content'));
-        wizardStep6Controller.set('isMasters', false);
       })
     },
     back: function(router){

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/routes/installer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/installer.js b/ambari-web/app/routes/installer.js
index e9c4288..637f8b9 100644
--- a/ambari-web/app/routes/installer.js
+++ b/ambari-web/app/routes/installer.js
@@ -204,7 +204,8 @@ module.exports = Em.Route.extend({
       var wizardStep3Controller = router.get('wizardStep3Controller');
       installerController.saveConfirmedHosts(wizardStep3Controller);
       installerController.setDBProperty('bootStatus', true);
-      installerController.loadServicesFromServer();
+      installerController.setDBProperty('selectedServiceNames', undefined);
+      installerController.setDBProperty('installedServiceNames', undefined);
       router.transitionTo('step4');
     },
     exit: function (router) {
@@ -230,7 +231,7 @@ module.exports = Em.Route.extend({
       var controller = router.get('installerController');
       controller.setCurrentStep('4');
       controller.loadAllPriorSteps();
-      controller.connectOutlet('wizardStep4', controller.get('content.services'));
+      controller.connectOutlet('wizardStep4', App.StackService.find());
     },
     back: Em.Router.transitionTo('step3'),
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/routes/main.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/main.js b/ambari-web/app/routes/main.js
index b1f40dd..6b46d19 100644
--- a/ambari-web/app/routes/main.js
+++ b/ambari-web/app/routes/main.js
@@ -706,7 +706,7 @@ module.exports = Em.Route.extend({
           var item = router.get('mainServiceItemController.content');
           //if service is not existed then route to default service
           if (item.get('isLoaded')) {
-            if (item.get('isConfigurable')) {
+            if (router.get('mainServiceItemController.isConfigurable')) {
               router.get('mainServiceItemController').connectOutlet('mainServiceInfoConfigs', item);
             }
             else {

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/templates/main/admin/highAvailability/step2.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/highAvailability/step2.hbs b/ambari-web/app/templates/main/admin/highAvailability/step2.hbs
index d731e89..5fb4964 100644
--- a/ambari-web/app/templates/main/admin/highAvailability/step2.hbs
+++ b/ambari-web/app/templates/main/admin/highAvailability/step2.hbs
@@ -25,53 +25,54 @@
     <form class="form-horizontal" autocomplete="off">
       <!-- View for array controller -->
       {{#each servicesMasters}}
-      <div class="control-group">
-        <label class="control-label">
-          {{#if isCurNameNode}}
-            {{t common.current}}
-          {{/if}}
-          {{#if isAddNameNode}}
-            {{t common.additional}}
-          {{/if}}
-          {{display_name}}:
-        </label>
-        <div class="controls">
-          {{#if view.shouldUseInputs}}
-            {{view App.InputHostView
-            componentBinding="this"
-            disabledBinding="isInstalled" }}
-          {{else}}
-            {{view App.SelectHostView
-            componentBinding="this"
-            disabledBinding="isInstalled"
-            optionValuePath="content.host_name"
-            optionLabelPath="content.host_info" }}
-          {{/if}}
-          {{#if showAddControl}}
-          {{view App.AddControlView componentNameBinding="component_name"}}
-          {{/if}}
-          {{#if showRemoveControl}}
-          {{view App.RemoveControlView componentNameBinding="component_name" zIdBinding="zId"}}
-          {{/if}}
+        <div class="control-group">
+          <label class="control-label">
+            {{#if isCurNameNode}}
+              {{t common.current}}
+            {{/if}}
+            {{#if isAddNameNode}}
+              {{t common.additional}}
+            {{/if}}
+            {{display_name}}:
+          </label>
+
+          <div class="controls">
+            {{#if view.shouldUseInputs}}
+              {{view App.InputHostView
+              componentBinding="this"
+              disabledBinding="isInstalled" }}
+            {{else}}
+              {{view App.SelectHostView
+              componentBinding="this"
+              disabledBinding="isInstalled"
+              optionValuePath="content.host_name"
+              optionLabelPath="content.host_info" }}
+            {{/if}}
+            {{#if showAddControl}}
+              {{view App.AddControlView componentNameBinding="component_name"}}
+            {{/if}}
+            {{#if showRemoveControl}}
+              {{view App.RemoveControlView componentNameBinding="component_name" serviceComponentIddBinding="serviceComponentId"}}
+            {{/if}}
+          </div>
         </div>
-      </div>
       {{/each}}
     </form>
   </div>
 
   <div class="host-assignments span5">
     {{#each masterHostMapping}}
-    <div class="mapping-box round-corners well">
-      <div class="hostString"><span>{{hostInfo}}</span></div>
-      {{#each masterServices}}
-      <span {{bindAttr class="isInstalled:assignedService:newService :round-corners"}}>{{display_name}}</span>
-      {{/each}}
-    </div>
+      <div class="mapping-box round-corners well">
+        <div class="hostString"><span>{{hostInfo}}</span></div>
+        {{#each masterServices}}
+          <span {{bindAttr class="isInstalled:assignedService:newService :round-corners"}}>{{display_name}}</span>
+        {{/each}}
+      </div>
     {{/each}}
 
     {{#if remainingHosts}}
-    <div class="remaining-hosts round-corners well">
-      <span><strong>{{remainingHosts}}</strong> {{t installer.step5.attention}}</span></div>
+      <div class="remaining-hosts round-corners well">
+        <span><strong>{{remainingHosts}}</strong> {{t installer.step5.attention}}</span></div>
     {{/if}}
   </div>
   <div style="clear: both;"></div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/templates/main/service/item.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/service/item.hbs b/ambari-web/app/templates/main/service/item.hbs
index 1fd017a..7b904f0 100644
--- a/ambari-web/app/templates/main/service/item.hbs
+++ b/ambari-web/app/templates/main/service/item.hbs
@@ -64,7 +64,7 @@
         <!-- dropdown menu links -->
 
         <!-- Start/Stop service actions -->
-        {{#unless controller.content.isClientsOnly}}
+        {{#unless controller.isClientsOnlyService}}
           <li {{bindAttr class="controller.isStartDisabled:disabled"}}>
             <a href="javascript:void(null)" {{bindAttr class="controller.isStartDisabled:disabled" }}
               {{action "startService" target="controller"}}>

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/templates/wizard/step4.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step4.hbs b/ambari-web/app/templates/wizard/step4.hbs
index cda6d39..b21d360 100644
--- a/ambari-web/app/templates/wizard/step4.hbs
+++ b/ambari-web/app/templates/wizard/step4.hbs
@@ -37,16 +37,16 @@
     </tr>
     </thead>
     <tbody>
-      {{#each controller}}
-        {{#unless isHidden}}
+    {{#each controller}}
+      {{#unless isHiddenOnSelectServicePage}}
         <tr {{bindAttr class="isSelected:success:"}}>
-          <td><label class="checkbox">{{view Ember.Checkbox disabledBinding="isDisabled" checkedBinding="isSelected"}}{{displayName}}</label>
+          <td><label class="checkbox">{{view Ember.Checkbox disabledBinding="isInstalled" checkedBinding="isSelected"}}{{displayNameOnSelectServicePage}}</label>
           </td>
-          <td>{{version}}</td>
-          <td>{{{description}}}</td>
+          <td>{{serviceVersion}}</td>
+          <td>{{{comments}}}</td>
         </tr>
-        {{/unless}}
-      {{/each}}
+      {{/unless}}
+    {{/each}}
     </tbody>
   </table>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/templates/wizard/step5.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step5.hbs b/ambari-web/app/templates/wizard/step5.hbs
index 4994557..137e181 100644
--- a/ambari-web/app/templates/wizard/step5.hbs
+++ b/ambari-web/app/templates/wizard/step5.hbs
@@ -19,9 +19,8 @@
 <h2>{{title}}</h2>
 <div class="alert alert-info">
   {{t installer.step5.body}}
-  {{#if hasHiveServer}}
-    <br>
-    {{t installer.step5.body.hive}}
+  {{#if view.coHostedComponentText}}
+    {{{view.coHostedComponentText}}}
   {{/if}}
 </div>
 {{#if controller.isLoaded}}
@@ -47,38 +46,34 @@
                   <div class="span4">
                     <div class="control-group">
                       <label class="pts pull-right">
-                        {{#if controller.isReassignHive}}
-                          {{t installer.step5.hiveGroup}}
-                        {{else}}
-                          {{display_name}}:
-                        {{/if}}
+                        {{display_name}}:
                       </label>
                     </div>
                   </div>
                   <div class="span8">
-                    {{#if isHiveCoHost}}
+                    {{#if isServiceCoHost}}
                       <div class="hostName">
                         {{selectedHost}}<i class="icon-asterisks">&#10037;</i>
                       </div>
                     {{else}}
-                    <div class="control-group">
-                      {{#if view.shouldUseInputs}}
-                        {{view App.InputHostView
-                        componentBinding="this"
-                        disabledBinding="isInstalled" }}
-                      {{else}}
-                        {{view App.SelectHostView
-                        componentBinding="this"
-                        disabledBinding="isInstalled"
-                        optionValuePath="content.host_name"
-                        optionLabelPath="content.host_info" }}
-                      {{/if}}
-                      {{#if showAddControl}}
-                        {{view App.AddControlView componentNameBinding="component_name"}}
-                      {{/if}}
-                      {{#if showRemoveControl}}
-                        {{view App.RemoveControlView componentNameBinding="component_name" zIdBinding="zId"}}
-                      {{/if}}
+                      <div class="control-group">
+                        {{#if view.shouldUseInputs}}
+                          {{view App.InputHostView
+                          componentBinding="this"
+                          disabledBinding="isInstalled" }}
+                        {{else}}
+                          {{view App.SelectHostView
+                          componentBinding="this"
+                          disabledBinding="isInstalled"
+                          optionValuePath="content.host_name"
+                          optionLabelPath="content.host_info" }}
+                        {{/if}}
+                        {{#if showAddControl}}
+                          {{view App.AddControlView componentNameBinding="component_name"}}
+                        {{/if}}
+                        {{#if showRemoveControl}}
+                          {{view App.RemoveControlView componentNameBinding="component_name" serviceComponentIdBinding="serviceComponentId"}}
+                        {{/if}}
                       </div>
                     {{/if}}
                   </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/templates/wizard/step6.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step6.hbs b/ambari-web/app/templates/wizard/step6.hbs
index 33911cd..b27f721 100644
--- a/ambari-web/app/templates/wizard/step6.hbs
+++ b/ambari-web/app/templates/wizard/step6.hbs
@@ -18,6 +18,7 @@
 
 <div id="step6">
   <h2>{{view.title}}</h2>
+
   <div class="alert alert-info">{{{view.label}}}</div>
   {{#if errorMessage}}
     <div class="alert alert-error">{{errorMessage}}</div>
@@ -26,39 +27,41 @@
   <div class="pre-scrollable">
     <table class="table table-striped" id="component_assign_table">
       <thead>
-        <tr>
-          <th>{{t common.host}}</th>
-          {{#each header in controller.headers}}
+      <tr>
+        <th>{{t common.host}}</th>
+        {{#each header in controller.headers}}
 
-            <th>
-              <a href="#" {{bindAttr class="header.allChecked:selected:deselected"}}
-                {{action "selectAllNodes" header target="controller"}}>{{t all}}</a>&nbsp;|&nbsp;<a href="#" {{bindAttr class="header.noChecked:selected:deselected"}}
-                {{action "deselectAllNodes" header target="controller"}}>{{t none}}</a>
-            </th>
+          <th>
+            <a href="#" {{bindAttr class="header.allChecked:selected:deselected header.isDisabled:remove-link"}}
+              {{action "selectAllNodes" header target="controller"}}>{{t all}}</a> &nbsp;|&nbsp; <a
+                  href="#" {{bindAttr class="header.noChecked:selected:deselected header.isDisabled:remove-link"}}
+            {{action "deselectAllNodes" header target="controller"}}>{{t none}}</a>
+          </th>
 
-          {{/each}}
-        </tr>
+        {{/each}}
+      </tr>
       </thead>
       <tbody>
-        {{#if view.pageContent}}
-          {{#each host in view.pageContent}}
-            <tr>
-              {{#view App.WizardStep6HostView hostBinding="host" }}
-                <span class="trim_hostname">{{host.hostName}}</span>
-                {{#if host.hasMaster}}
-                  <i class="icon-asterisks">&#10037;</i>
-                {{/if}}
-              {{/view}}
-              {{#each checkbox in host.checkboxes}}
-                <td>
-                  <label class="checkbox">
-                      <input {{bindAttr checked = "checkbox.checked" disabled="checkbox.isInstalled"}} {{action "checkboxClick" checkbox target="view" }} type="checkbox"/>{{checkbox.title}}
-                  </label>
-                </td>
-              {{/each}}
-            </tr>
-          {{/each}}
-        {{/if}}
+      {{#if view.pageContent}}
+        {{#each host in view.pageContent}}
+          <tr>
+            {{#view App.WizardStep6HostView hostBinding="host" }}
+              <span class="trim_hostname">{{host.hostName}}</span>
+              {{#if host.hasMaster}}
+                <i class=icon-asterisks>&#10037;</i>
+              {{/if}}
+            {{/view}}
+            {{#each checkbox in host.checkboxes}}
+              <td>
+                <label class="checkbox">
+                  <input {{bindAttr checked = "checkbox.checked" disabled="checkbox.isInstalled"}} {{action "checkboxClick" checkbox target="view" }}
+                          type="checkbox"/>{{checkbox.title}}
+                </label>
+              </td>
+            {{/each}}
+          </tr>
+        {{/each}}
+      {{/if}}
       </tbody>
     </table>
   </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/templates/wizard/step8.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step8.hbs b/ambari-web/app/templates/wizard/step8.hbs
index 2352736..71915f8 100644
--- a/ambari-web/app/templates/wizard/step8.hbs
+++ b/ambari-web/app/templates/wizard/step8.hbs
@@ -53,7 +53,7 @@
 
     <div>
       {{#if controller.services.length}}
-        <p><b>{{t menu.item.services}}</b></p>
+        <p><b>{{t menu.item.services}}:</b></p>
         <ul>
           {{#each controller.services}}
             <li>

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/utils/ajax/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js
index 3396ac0..9581283 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -954,7 +954,7 @@ var urls = {
     }
   },
   'wizard.service_components': {
-    'real': '{stackUrl}/services?fields=StackServices/comments,StackServices/service_version,serviceComponents/*',
+    'real': '{stackUrl}/services?fields=StackServices/*,serviceComponents/*',
     'mock': '/data/stacks/HDP-2.1/service_components.json',
     'format': function(data) {
       return {

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/utils/component.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/component.js b/ambari-web/app/utils/component.js
deleted file mode 100644
index fd2ef1b..0000000
--- a/ambari-web/app/utils/component.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * Here will be stored slave functions related to components
- * @type {Object}
- */
-
-var App = require('app');
-module.exports = {
-
-  /**
-   * This needs to be done because mapper functions like App.stackServiceComponentMapper.map(data) does not override
-   * but unions the instances. So on re-navigation if the stack is switched and this function is not called then union of
-   * StackServiceComponent of both the stacks will be mapped to the model.
-   */
-  clearStackModel: function() {
-    if (App.StackServiceComponent.find().get('content').length) {
-      App.StackServiceComponent.find().set('content', []);
-    }
-  },
-
-  /**
-   * Format and load info about components to StackServiceComponent model.
-   *
-   * @method loadStackServiceComponentModel
-   * @param data {object} response from server
-   * @return {object} formatted info about components
-   */
-  loadStackServiceComponentModel: function(data) {
-    this.clearStackModel();
-    var serviceComponents = {items: []};
-    data.items.forEach(function(item){
-      item.serviceComponents.forEach(function(_serviceComponent, indx){
-        var stackServiceComponents =  _serviceComponent.StackServiceComponents;
-        var serviceComponent = {
-          component_name: stackServiceComponents.component_name,
-          service_name: stackServiceComponents.service_name,
-          component_category: stackServiceComponents.component_category,
-          is_master: stackServiceComponents.is_master,
-          is_client: stackServiceComponents.is_client,
-          stack_name: stackServiceComponents.stack_name,
-          stack_version: stackServiceComponents.stack_version,
-          id: indx
-        };
-        serviceComponents.items.pushObject(serviceComponent);
-      }, this);
-    }, this);
-    App.stackServiceComponentMapper.map(serviceComponents);
-    App.handleStackDependedComponents();
-    return serviceComponents;
-  }
-};

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/utils/config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js
index 87dd0da..700da2f 100644
--- a/ambari-web/app/utils/config.js
+++ b/ambari-web/app/utils/config.js
@@ -40,7 +40,7 @@ App.config = Em.Object.create({
     "&quot;": '"',
     "&apos;": "'"
   },
-  
+
   CONFIG_GROUP_NAME_MAX_LENGTH: 18,
 
   /**
@@ -51,8 +51,8 @@ App.config = Em.Object.create({
   /**
    * Since values end up in XML files (core-sit.xml, etc.), certain
    * XML sensitive characters should be escaped. If not we will have
-   * an invalid XML document, and services will fail to start. 
-   * 
+   * an invalid XML document, and services will fail to start.
+   *
    * Special characters in XML are defined at
    * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined_entities_in_XML
    *
@@ -61,7 +61,7 @@ App.config = Em.Object.create({
    * @param toXml {Boolean}
    * @return {String}
    */
-  escapeXMLCharacters: function(value, toXML) {
+  escapeXMLCharacters: function (value, toXML) {
     var self = this;
     // To prevent double/triple replacing '&gt;' to '&amp;gt;' to '&amp;amp;gt;', we need
     // to first unescape all XML chars, and then escape them again.
@@ -77,42 +77,87 @@ App.config = Em.Object.create({
     }
   },
 
-  preDefinedServiceConfigs: function () {
+  preDefinedGlobalProperties: [],
+
+  setPreDefinedGlobalProperties: function () {
+    var globalProperties = [];
+    if (App.get('isHadoop2Stack')) {
+      globalProperties = require('data/HDP2/global_properties').configProperties;
+    } else {
+      globalProperties = require('data/global_properties').configProperties;
+    }
+    var preDefinedGlobalProperties = globalProperties;
+    var categories = [];
+    var nonServicePages = require('data/service_configs');
+    var services = App.StackService.find().filterProperty('id');
+
+    // Only services that have configTypes associated with it should display service config page
+    // Also Remove HCatalog from this list. HCatalog has global and hive-site related to it but none of them should be exposed under HCatalog Service
+    // HCatalog should be eventually made a part of Hive Service. See AMBARI-6302 description for further details
+    var servicesWithConfigTypes = services.filter(function (service) {
+      var configtypes = service.get('configTypes');
+      return configtypes && !!configtypes.length && service.get('serviceName') != 'HCATALOG';
+    }, this);
+    var serviceTabs = servicesWithConfigTypes.concat(nonServicePages);
+    serviceTabs.forEach(function (stackService) {
+      categories.pushObjects(stackService.get('configCategories'));
+    });
+    var categoryNames = categories.mapProperty('name').uniq();
+    if (!!categoryNames.length) {
+      preDefinedGlobalProperties = globalProperties.filter(function (_globalProperty) {
+        return !_globalProperty.category || (serviceTabs.someProperty('serviceName', _globalProperty.serviceName) &&
+          categoryNames.contains(_globalProperty.category));
+      });
+    }
+    this.set('preDefinedGlobalProperties', preDefinedGlobalProperties);
+  },
+
+  preDefinedServiceConfigs: [],
+
+  setPreDefinedServiceConfigs: function () {
     var configs = this.get('preDefinedGlobalProperties');
     var services = [];
-    $.extend(true, [], require('data/service_configs')).forEach(function (service) {
-      service.configs = configs.filterProperty('serviceName', service.serviceName);
+    var nonServiceTab = require('data/service_configs');
+    var stackServices = App.StackService.find().filterProperty('id');
+    // Only include services that has configTypes related to them for service configuration page
+    // Also Remove HCatalog from this list. HCatalog has global and hive-site related to it but none of them should be exposed under HCatalog Service
+    // HCatalog should be eventually made a part of Hive Service. See AMBARI-6302 description for further details
+    var servicesWithConfigTypes = stackServices.filter(function (service) {
+      var configtypes = service.get('configTypes');
+      return configtypes && !!configtypes.length && service.get('serviceName') != 'HCATALOG';
+    }, this);
+
+    var allTabs = servicesWithConfigTypes.concat(nonServiceTab);
+    allTabs.forEach(function (service) {
+      var serviceConfigs = configs.filterProperty('serviceName', service.get('serviceName'));
+      serviceConfigs = serviceConfigs.filter(function (_globalProperty) {
+        !_globalProperty.category || service.get('configCategories').someProperty('name', _globalProperty.category);
+      });
+      service.set('configs', serviceConfigs);
       services.push(service);
     });
-    return services;
-  }.property('preDefinedGlobalProperties'),
+    this.set('preDefinedServiceConfigs', services);
+  },
 
   configMapping: function () {
     if (App.get('isHadoop2Stack')) {
-      return $.extend(true, [], require('data/HDP2/config_mapping'));
-    }
-    return $.extend(true, [], require('data/config_mapping'));
-  }.property('App.isHadoop2Stack'),
-
-  preDefinedGlobalProperties: function () {
-    if (App.get('isHadoop2Stack')) {
-      return $.extend(true, [], require('data/HDP2/global_properties').configProperties);
+      return require('data/HDP2/config_mapping');
     }
-    return $.extend(true, [], require('data/global_properties').configProperties);
+    return require('data/config_mapping');
   }.property('App.isHadoop2Stack'),
 
   preDefinedSiteProperties: function () {
     if (App.get('isHadoop2Stack')) {
-      return $.extend(true, [], require('data/HDP2/site_properties').configProperties);
+      return require('data/HDP2/site_properties').configProperties;
     }
-    return $.extend(true, [], require('data/site_properties').configProperties);
+    return require('data/site_properties').configProperties;
   }.property('App.isHadoop2Stack'),
 
   preDefinedCustomConfigs: function () {
     if (App.get('isHadoop2Stack')) {
-      return $.extend(true, [], require('data/HDP2/custom_configs'));
+      return require('data/HDP2/custom_configs');
     }
-    return $.extend(true, [], require('data/custom_configs'));
+    return require('data/custom_configs');
   }.property('App.isHadoop2Stack'),
 
   //categories which contain custom configs
@@ -165,7 +210,7 @@ App.config = Em.Object.create({
   /**
    * Array of global "service/desired_tag/actual_tag" strings which
    * indicate different configurations. We cache these so that
-   * we dont have to recalculate if two tags are difference.
+   * we don't have to recalculate if two tags are difference.
    */
   differentGlobalTagsCache: [],
 
@@ -173,12 +218,13 @@ App.config = Em.Object.create({
     var category = null;
     var serviceConfigMetaData = this.get('preDefinedServiceConfigs').findProperty('serviceName', config.serviceName);
     if (serviceConfigMetaData) {
-      serviceConfigMetaData.configCategories.forEach(function (_category) {
+      var configCategories = serviceConfigMetaData.get('configCategories');
+      configCategories.forEach(function (_category) {
         if (_category.siteFileNames && Array.isArray(_category.siteFileNames) && _category.siteFileNames.contains(config.filename)) {
           category = _category;
         }
       });
-      category = (category == null) ? serviceConfigMetaData.configCategories.findProperty('siteFileName', config.filename) : category;
+      category = (category == null) ? configCategories.findProperty('siteFileName', config.filename) : category;
     }
     return category;
   },
@@ -198,7 +244,7 @@ App.config = Em.Object.create({
   },
   /**
    * calculate config properties:
-   * category, filename, isUserProperty, description   
+   * category, filename, isUserProperty, description
    * @param config
    * @param isAdvanced
    * @param advancedConfigs
@@ -212,7 +258,7 @@ App.config = Em.Object.create({
       }
     } else {
       var advancedProperty = null;
-      if( isAdvanced ){
+      if (isAdvanced) {
         advancedProperty = advancedConfigs.findProperty('name', config.name);
       }
 
@@ -263,22 +309,22 @@ App.config = Em.Object.create({
 
       properties = (properties.length) ? properties.objectAt(0).properties : {};
       for (var index in properties) {
-        var configsPropertyDef =  null;
+        var configsPropertyDef = null;
         var preDefinedConfig = [];
         if (_tag.siteName === 'global') {
-        // Unlike other site where one site maps to ones service, global site contains configurations for multiple services
-        // So Global Configuration should not be filtered out with serviceName.
+          // Unlike other site where one site maps to ones service, global site contains configurations for multiple services
+          // So Global Configuration should not be filtered out with serviceName.
           preDefinedConfig = preDefinedConfigs.filterProperty('name', index);
-          preDefinedConfig.forEach(function(_preDefinedConfig){
+          preDefinedConfig.forEach(function (_preDefinedConfig) {
             var isServiceInstalled = selectedServiceNames.contains(_preDefinedConfig.serviceName);
-              if ( isServiceInstalled || _preDefinedConfig.serviceName === 'MISC') {
-                configsPropertyDef = _preDefinedConfig;
-              }
-          },this);
+            if (isServiceInstalled || _preDefinedConfig.serviceName === 'MISC') {
+              configsPropertyDef = _preDefinedConfig;
+            }
+          }, this);
         } else {
-          configsPropertyDef = preDefinedConfigs.filterProperty('name',index).findProperty('filename',filename);
+          configsPropertyDef = preDefinedConfigs.filterProperty('name', index).findProperty('filename', filename);
           if (!configsPropertyDef) {
-            configsPropertyDef = preDefinedConfigs.filterProperty('name',index).findProperty('serviceName', serviceName);
+            configsPropertyDef = preDefinedConfigs.filterProperty('name', index).findProperty('serviceName', serviceName);
           }
         }
 
@@ -298,7 +344,7 @@ App.config = Em.Object.create({
         if (configsPropertyDef) {
           this.setServiceConfigUiAttributes(serviceConfigObj, configsPropertyDef);
         }
-        
+
         if (_tag.siteName === 'global') {
           if (configsPropertyDef) {
             if (configsPropertyDef.isRequiredByAgent === false) {
@@ -321,22 +367,22 @@ App.config = Em.Object.create({
 
           serviceConfigObj.displayName = configsPropertyDef ? configsPropertyDef.displayName : index;
           this.calculateConfigProperties(serviceConfigObj, isAdvanced, advancedConfigs);
-          
-          if(serviceConfigObj.get('displayType') == 'directories'
+
+          if (serviceConfigObj.get('displayType') == 'directories'
             && (serviceConfigObj.get('category') == 'DataNode'
             || serviceConfigObj.get('category') == 'NameNode')) {
             var dirs = serviceConfigObj.get('value').split(',').sort();
             serviceConfigObj.set('value', dirs.join(','));
             serviceConfigObj.set('defaultValue', dirs.join(','));
           }
-          
-          if(serviceConfigObj.get('displayType') == 'directory'
+
+          if (serviceConfigObj.get('displayType') == 'directory'
             && serviceConfigObj.get('category') == 'SNameNode') {
             var dirs = serviceConfigObj.get('value').split(',').sort();
             serviceConfigObj.set('value', dirs[0]);
             serviceConfigObj.set('defaultValue', dirs[0]);
           }
-          
+
           if (serviceConfigObj.get('displayType') == 'masterHosts') {
             if (typeof(serviceConfigObj.get('value')) == 'string') {
               var value = serviceConfigObj.get('value').replace(/\[|]|'|&apos;/g, "").split(',');
@@ -403,8 +449,8 @@ App.config = Em.Object.create({
       if (_site.length == 1) {
         siteStart.push(_site[0]);
         siteConfigs = siteConfigs.without(_site[0]);
-      } else if (_site.length >1) {
-        _site.forEach(function(site){
+      } else if (_site.length > 1) {
+        _site.forEach(function (site) {
           siteStart.push(site);
           siteConfigs = siteConfigs.without(site);
         }, this);
@@ -427,7 +473,7 @@ App.config = Em.Object.create({
    */
   mergePreDefinedWithStored: function (storedConfigs, advancedConfigs, selectedServiceNames) {
     var mergedConfigs = [];
-    var preDefinedConfigs = $.extend(true, [], this.get('preDefinedGlobalProperties').concat(this.get('preDefinedSiteProperties')));
+    var preDefinedConfigs = this.get('preDefinedGlobalProperties').concat(this.get('preDefinedSiteProperties'));
 
     storedConfigs = (storedConfigs) ? storedConfigs : [];
 
@@ -449,7 +495,7 @@ App.config = Em.Object.create({
       if (storedCfgs.length <= 1 && preDefinedCfgs.length <= 1) {
         var stored = storedCfgs[0];
         var preDefined = preDefinedCfgs[0];
-        
+
         if (preDefined && stored) {
           configData = preDefined;
           configData.value = stored.value;
@@ -462,25 +508,23 @@ App.config = Em.Object.create({
           configData.isRequiredByAgent = (configData.isRequiredByAgent !== undefined) ? configData.isRequiredByAgent : true;
           configData.showLabel = stored.showLabel !== false;
         }
-        else
-          if (!preDefined && stored) {
-            configData = this.addUserProperty(stored, isAdvanced, advancedConfigs);
+        else if (!preDefined && stored) {
+          configData = this.addUserProperty(stored, isAdvanced, advancedConfigs);
+        }
+        else if (preDefined && !stored) {
+          configData = preDefined;
+          configData.isRequiredByAgent = (configData.isRequiredByAgent !== undefined) ? configData.isRequiredByAgent : true;
+          if (isAdvanced) {
+            var advanced = advancedConfigs.findProperty('name', configData.name);
+            this.setPropertyFromStack(configData, advanced);
           }
-          else
-            if (preDefined && !stored) {
-              configData = preDefined;
-              configData.isRequiredByAgent = (configData.isRequiredByAgent !== undefined) ? configData.isRequiredByAgent : true;
-              if (isAdvanced) {
-                var advanced = advancedConfigs.findProperty('name', configData.name);
-                this.setPropertyFromStack(configData,advanced);
-              }
-            }
-        
+        }
+
         if (configData.displayType === 'checkbox') {
           configData.value = configData.value === 'true'; // convert {String} value to {Boolean}
           configData.defaultValue = configData.value;
         }
-      
+
         mergedConfigs.push(configData);
       } else {
         preDefinedCfgs.forEach(function (cfg) {
@@ -494,9 +538,9 @@ App.config = Em.Object.create({
             configData.filename = storedCfg.filename;
             configData.description = storedCfg.description;
             configData.description = storedCfg.showLabel !== false;
-          } else if (isAdvanced){
-              advanced = advancedConfigs.filterProperty('filename', configData.filename).findProperty('name', configData.name);
-              this.setPropertyFromStack(configData,advanced);
+          } else if (isAdvanced) {
+            advanced = advancedConfigs.filterProperty('filename', configData.filename).findProperty('name', configData.name);
+            this.setPropertyFromStack(configData, advanced);
           }
           mergedConfigs.push(configData);
         }, this);
@@ -510,7 +554,7 @@ App.config = Em.Object.create({
    * @param configData {Object} Configs that will be binded to the view on step-7 of installer wizard
    * @param advanced {Object} Config property loaded from Server side stack definition
    */
-  setPropertyFromStack: function(configData,advanced) {
+  setPropertyFromStack: function (configData, advanced) {
 
     // Password fields should be made blank by default in installer wizard
     // irrespective of whatever value is sent from stack definition.
@@ -601,17 +645,18 @@ App.config = Em.Object.create({
     var services = [];
 
     this.get('preDefinedServiceConfigs').forEach(function (serviceConfig) {
-      if (allSelectedServiceNames.contains(serviceConfig.serviceName) || serviceConfig.serviceName === 'MISC') {
-        console.log('pushing ' + serviceConfig.serviceName, serviceConfig);
-        if (!installedServiceNames.contains(serviceConfig.serviceName) || serviceConfig.serviceName === 'MISC') {
-          serviceConfig.showConfig = true;
+      var serviceName = serviceConfig.get('serviceName');
+      if (allSelectedServiceNames.contains(serviceName) || serviceName === 'MISC') {
+        console.log('pushing ' + serviceName, serviceConfig);
+        if (!installedServiceNames.contains(serviceName) || serviceName === 'MISC') {
+          serviceConfig.set('showConfig', true);
         }
         services.push(serviceConfig);
       }
     });
     services.forEach(function (service) {
       var configsByService = [];
-      var serviceConfigs = configs.filterProperty('serviceName', service.serviceName);
+      var serviceConfigs = configs.filterProperty('serviceName', service.get('serviceName'));
       serviceConfigs.forEach(function (_config) {
         _config.isOverridable = (_config.isOverridable === undefined) ? true : _config.isOverridable;
         var serviceConfigProperty = App.ServiceConfigProperty.create(_config);
@@ -623,13 +668,13 @@ App.config = Em.Object.create({
         serviceConfigProperty.validate();
         configsByService.pushObject(serviceConfigProperty);
       }, this);
-      var serviceConfig = this.createServiceConfig(service.serviceName);
-      serviceConfig.set('showConfig', service.showConfig);
+      var serviceConfig = this.createServiceConfig(service.get('serviceName'));
+      serviceConfig.set('showConfig', service.get('showConfig'));
 
       // Use calculated default values for some configs
       var recommendedDefaults = {};
-      if (!storedConfigs && service.defaultsProviders) {
-        service.defaultsProviders.forEach(function (defaultsProvider) {
+      if (!storedConfigs && service.get('defaultsProviders')) {
+        service.get('defaultsProviders').forEach(function (defaultsProvider) {
           var defaults = defaultsProvider.getDefaults(localDB);
           for (var name in defaults) {
             var config = configsByService.findProperty('name', name);
@@ -646,13 +691,13 @@ App.config = Em.Object.create({
           }
         });
       }
-      if (service.configsValidator) {
-        service.configsValidator.set('recommendedDefaults', recommendedDefaults);
-        var validators = service.configsValidator.get('configValidators');
+      if (service.get('configsValidator')) {
+        service.get('configsValidator').set('recommendedDefaults', recommendedDefaults);
+        var validators = service.get('configsValidator').get('configValidators');
         for (var validatorName in validators) {
           var c = configsByService.findProperty('name', validatorName);
           if (c) {
-            c.set('serviceValidator', service.configsValidator);
+            c.set('serviceValidator', service.get('configsValidator'));
           }
         }
       }
@@ -713,10 +758,9 @@ App.config = Em.Object.create({
   createServiceConfig: function (serviceName) {
     var preDefinedServiceConfig = App.config.get('preDefinedServiceConfigs').findProperty('serviceName', serviceName);
     var serviceConfig = App.ServiceConfig.create({
-      filename: preDefinedServiceConfig.filename,
-      serviceName: preDefinedServiceConfig.serviceName,
-      displayName: preDefinedServiceConfig.displayName,
-      configCategories: preDefinedServiceConfig.configCategories,
+      serviceName: preDefinedServiceConfig.get('serviceName'),
+      displayName: preDefinedServiceConfig.get('displayName'),
+      configCategories: preDefinedServiceConfig.get('configCategories'),
       configs: [],
       configGroups: []
     });
@@ -801,9 +845,9 @@ App.config = Em.Object.create({
          * Properties from mapred-queue-acls.xml are ignored unless App.supports.capacitySchedulerUi is true
          * Properties from capacity-scheduler.xml are ignored unless HDP stack version is 2.x or
          * HDP stack version is 1.x and App.supports.capacitySchedulerUi is true.
-          */
+         */
         if ((fileName !== 'mapred-queue-acls.xml' || App.supports.capacitySchedulerUi) &&
-            (fileName !== 'capacity-scheduler.xml' || isHDP2 || App.supports.capacitySchedulerUi)) {
+          (fileName !== 'capacity-scheduler.xml' || isHDP2 || App.supports.capacitySchedulerUi)) {
           properties.push({
             serviceName: serviceName,
             name: item.property_name,
@@ -890,7 +934,7 @@ App.config = Em.Object.create({
             serviceConfig.overrides = [];
           }
           if (!serviceConfig.overrides) {
-           serviceConfig.set('overrides', []);
+            serviceConfig.set('overrides', []);
           }
           console.log("loadServiceConfigGroupOverridesSuccess(): [" + group + "] OVERRODE(" + serviceConfig.name + "): " + serviceConfig.value + " -> " + hostOverrideValue);
           serviceConfig.overrides.push({value: hostOverrideValue, group: group});
@@ -1126,7 +1170,7 @@ App.config = Em.Object.create({
       configCategories.removeObject(snCategory);
     }
   },
-  
+
   /**
    * Launches a dialog where an existing config-group can be selected, or a new
    * one can be created. This is different than the config-group management
@@ -1140,7 +1184,7 @@ App.config = Em.Object.create({
    *  is closed, cancelled or OK is pressed.
    */
 
-  saveGroupConfirmationPopup: function(groupName) {
+  saveGroupConfirmationPopup: function (groupName) {
     App.ModalPopup.show({
       header: Em.I18n.t('config.group.save.confirmation.header'),
       secondary: Em.I18n.t('config.group.save.confirmation.manage.button'),
@@ -1148,7 +1192,7 @@ App.config = Em.Object.create({
       bodyClass: Ember.View.extend({
         templateName: require('templates/common/configs/saveConfigGroup')
       }),
-      onSecondary: function() {
+      onSecondary: function () {
         App.router.get('mainServiceInfoConfigsController').manageConfigurationGroups();
         this.hide();
       }
@@ -1177,7 +1221,7 @@ App.config = Em.Object.create({
     });
   },
 
-  launchConfigGroupSelectionCreationDialog : function(serviceId, configGroups, configProperty, callback, isInstaller) {
+  launchConfigGroupSelectionCreationDialog: function (serviceId, configGroups, configProperty, callback, isInstaller) {
     var self = this;
     var availableConfigGroups = configGroups.slice();
     // delete Config Groups, that already have selected property overridden
@@ -1193,7 +1237,7 @@ App.config = Em.Object.create({
     }, this);
     availableConfigGroups = result;
     var selectedConfigGroup = availableConfigGroups && availableConfigGroups.length > 0 ?
-        availableConfigGroups[0] : null;
+      availableConfigGroups[0] : null;
     var serviceName = App.Service.DisplayNames[serviceId];
     App.ModalPopup.show({
       classNames: [ 'sixty-percent-width-modal' ],
@@ -1206,10 +1250,10 @@ App.config = Em.Object.create({
       warningMessage: '&nbsp;',
       isWarning: false,
       optionSelectConfigGroup: true,
-      optionCreateConfigGroup: function(){
+      optionCreateConfigGroup: function () {
         return !this.get('optionSelectConfigGroup');
       }.property('optionSelectConfigGroup'),
-      hasExistedGroups: function() {
+      hasExistedGroups: function () {
         return !!this.get('availableConfigGroups').length;
       }.property('availableConfigGroups'),
       availableConfigGroups: availableConfigGroups,
@@ -1401,7 +1445,7 @@ App.config = Em.Object.create({
    * PUTs the new configuration-group on the server.
    * Changes possible here are the name, description and
    * host memberships of the configuration-group.
-   * 
+   *
    * @param {App.ConfigGroup} configGroup Configuration group to update
    * @param {Function} successCallback
    * @param {Function} errorCallback
@@ -1414,20 +1458,20 @@ App.config = Em.Object.create({
         tag: configGroup.get('service.id'),
         hosts: [],
         desired_configs: []
-      }  
+      }
     };
-    configGroup.get('hosts').forEach(function(h){
+    configGroup.get('hosts').forEach(function (h) {
       putConfigGroup.ConfigGroup.hosts.push({
         host_name: h
       });
     });
-    configGroup.get('configSiteTags').forEach(function(cst){
+    configGroup.get('configSiteTags').forEach(function (cst) {
       putConfigGroup.ConfigGroup.desired_configs.push({
         type: cst.get('site'),
         tag: cst.get('tag')
       });
     });
-    
+
     var sendData = {
       name: 'config_groups.update',
       data: {
@@ -1437,12 +1481,12 @@ App.config = Em.Object.create({
       success: 'successFunction',
       error: 'errorFunction',
       successFunction: function () {
-        if(successCallback) {
+        if (successCallback) {
           successCallback();
         }
       },
       errorFunction: function (xhr, text, errorThrown) {
-        if(errorCallback) {
+        if (errorCallback) {
           errorCallback(xhr, text, errorThrown);
         }
       }
@@ -1467,12 +1511,12 @@ App.config = Em.Object.create({
       success: 'successFunction',
       error: 'errorFunction',
       successFunction: function () {
-        if(successCallback) {
+        if (successCallback) {
           successCallback();
         }
       },
       errorFunction: function (xhr, text, errorThrown) {
-        if(errorCallback) {
+        if (errorCallback) {
           errorCallback(xhr, text, errorThrown);
         }
       }
@@ -1483,7 +1527,7 @@ App.config = Em.Object.create({
 
   /**
    * Gets all the configuration-groups for the given service.
-   * 
+   *
    * @param serviceId
    *          (string) ID of the service. Ex: HDFS
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/utils/helper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/helper.js b/ambari-web/app/utils/helper.js
index 1072f08..5bff313 100644
--- a/ambari-web/app/utils/helper.js
+++ b/ambari-web/app/utils/helper.js
@@ -316,79 +316,30 @@ App.format = {
    * @property components
    */
   components: {
-    'APP_TIMELINE_SERVER': 'App Timeline Server',
-    'DATANODE': 'DataNode',
+    'API': 'API',
     'DECOMMISSION_DATANODE': 'Update Exclude File',
-    'DRPC_SERVER': 'DRPC Server',
-    'FALCON': 'Falcon',
-    'FALCON_CLIENT': 'Falcon Client',
-    'FALCON_SERVER': 'Falcon Server',
-    'FALCON_SERVICE_CHECK': 'Falcon Service Check',
+    'DRPC': 'DRPC',
     'FLUME_HANDLER': 'Flume Agent',
-    'FLUME_SERVICE_CHECK': 'Flume Service Check',
-    'GANGLIA_MONITOR': 'Ganglia Monitor',
-    'GANGLIA_SERVER': 'Ganglia Server',
-    'GLUSTERFS_CLIENT': 'GLUSTERFS Client',
-    'GLUSTERFS_SERVICE_CHECK': 'GLUSTERFS Service Check',
-    'GMETAD_SERVICE_CHECK': 'Gmetad Service Check',
-    'GMOND_SERVICE_CHECK': 'Gmond Service Check',
-    'HADOOP_CLIENT': 'Hadoop Client',
-    'HBASE_CLIENT': 'HBase Client',
-    'HBASE_MASTER': 'HBase Master',
+    'GLUSTERFS': 'GLUSTERFS',
+    'HBASE': 'HBase',
     'HBASE_REGIONSERVER': 'RegionServer',
-    'HBASE_SERVICE_CHECK': 'HBase Service Check',
     'HCAT': 'HCat',
-    'HCAT_SERVICE_CHECK': 'HCat Service Check',
-    'HDFS_CLIENT': 'HDFS Client',
-    'HDFS_SERVICE_CHECK': 'HDFS Service Check',
+    'HDFS': 'HDFS',
     'HISTORYSERVER': 'History Server',
-    'HIVE_CLIENT': 'Hive Client',
-    'HIVE_METASTORE': 'Hive Metastore',
     'HIVE_SERVER': 'HiveServer2',
-    'HIVE_SERVICE_CHECK': 'Hive Service Check',
-    'HUE_SERVER': 'Hue Server',
-    'JAVA_JCE': 'Java JCE',
-    'JOBTRACKER': 'JobTracker',
-    'JOBTRACKER_SERVICE_CHECK': 'JobTracker Service Check',
-    'JOURNALNODE': 'JournalNode',
-    'KERBEROS_ADMIN_CLIENT': 'Kerberos Admin Client',
-    'KERBEROS_CLIENT': 'Kerberos Client',
-    'KERBEROS_SERVER': 'Kerberos Server',
-    'MAPREDUCE2_CLIENT': 'MapReduce2 Client',
-    'MAPREDUCE2_SERVICE_CHECK': 'MapReduce2 Service Check',
-    'MAPREDUCE_CLIENT': 'MapReduce Client',
-    'MAPREDUCE_SERVICE_CHECK': 'MapReduce Service Check',
-    'MYSQL_SERVER': 'MySQL Server',
-    'NAGIOS_SERVER': 'Nagios Server',
-    'NAMENODE': 'NameNode',
-    'NAMENODE_SERVICE_CHECK': 'NameNode Service Check',
-    'NIMBUS': 'Nimbus',
-    'NODEMANAGER': 'NodeManager',
-    'OOZIE_CLIENT': 'Oozie Client',
-    'OOZIE_SERVER': 'Oozie Server',
-    'OOZIE_SERVICE_CHECK': 'Oozie Service Check',
-    'PIG': 'Pig',
-    'PIG_SERVICE_CHECK': 'Pig Service Check',
-    'RESOURCEMANAGER': 'ResourceManager',
+    'JCE': 'JCE',
+    'MAPREDUCE': 'MapReduce',
+    'MAPREDUCE2': 'MapReduce2',
+    'MYSQL': 'MySQL',
+    'REST': 'REST',
     'SECONDARY_NAMENODE': 'SNameNode',
-    'SQOOP': 'Sqoop',
-    'SQOOP_SERVICE_CHECK': 'Sqoop Service Check',
     'STORM_REST_API': 'Storm REST API Server',
-    'STORM_SERVICE_CHECK': 'Storm Service Check',
-    'STORM_UI_SERVER': 'Storm UI Server',
-    'SUPERVISOR': 'Supervisor',
-    'TASKTRACKER': 'TaskTracker',
-    'TEZ_CLIENT': 'Tez Client',
-    'WEBHCAT_SERVER': 'WebHCat Server',
-    'WEBHCAT_SERVICE_CHECK': 'WebHCat Service Check',
-    'YARN_CLIENT': 'YARN Client',
-    'YARN_SERVICE_CHECK': 'YARN Service Check',
+    'WEBHCAT': 'WebHCat',
+    'YARN': 'YARN',
+    'UI': 'UI',
     'ZKFC': 'ZKFailoverController',
-    'ZOOKEEPER_CLIENT': 'ZooKeeper Client',
-    'ZOOKEEPER_QUORUM_SERVICE_CHECK': 'ZK Quorum Service Check',
-    'ZOOKEEPER_SERVER': 'ZooKeeper Server',
-    'ZOOKEEPER_SERVICE_CHECK': 'ZooKeeper Service Check',
-    'CLIENT': 'Client'
+    'ZOOKEEPER': 'ZooKeeper',
+    'ZOOKEEPER_QUORUM_SERVICE_CHECK': 'ZK Quorum Service Check'
   },
 
   /**
@@ -419,7 +370,32 @@ App.format = {
    * return {string}
    */
   role:function (role) {
-    return this.components[role] ? this.components[role] : '';
+    return this.normalizeName(role);
+  },
+
+  /**
+   * Try to format non predefined names to readable format.
+   *
+   * @method normalizeName
+   * @param name {String} - name to format
+   * @return {String}
+   */
+  normalizeName: function(name) {
+    if (!name || typeof name != 'string') return '';
+    if (this.components[name]) return this.components[name];
+    name = name.toLowerCase();
+    var suffixNoSpaces = ['node','tracker','manager'];
+    var suffixRegExp = new RegExp('(\\w+)(' + suffixNoSpaces.join('|') + ')', 'gi');
+    if (/_/g.test(name)) {
+      name = name.split('_').map(function(singleName) {
+        return this.normalizeName(singleName.toUpperCase());
+      }, this).join(' ');
+    } else if(suffixRegExp.test(name)) {
+      suffixRegExp.lastIndex = 0;
+      var matches = suffixRegExp.exec(name);
+      name = matches[1].capitalize() + matches[2].capitalize();
+    };
+    return name.capitalize();
   },
 
   /**
@@ -448,17 +424,17 @@ App.format = {
       } else if (self.command[item]) {
         result = result + ' ' + self.command[item];
       } else {
-        result = result + ' ' + item;
+        result = result + ' ' + self.role(item);
       }
     });
-    if (result === ' nagios_update_ignore ACTIONEXECUTE') {
+    if (result === ' Nagios Update Ignore Actionexecute') {
        result = Em.I18n.t('common.maintenance.task');
     }
     return result;
   },
 
   /**
-   * Convert uppercase status name to downcase.
+   * Convert uppercase status name to lowercase.
    * <br>
    * <br>PENDING - Not queued yet for a host
    * <br>QUEUED - Queued for a host

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/utils/string_utils.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/string_utils.js b/ambari-web/app/utils/string_utils.js
index 0ce8340..b16852e 100644
--- a/ambari-web/app/utils/string_utils.js
+++ b/ambari-web/app/utils/string_utils.js
@@ -159,5 +159,41 @@ module.exports = {
     }
     var last_slash = path.lastIndexOf('/');
     return (last_slash!=0)?path.substr(0,last_slash):'/';
+  },
+
+  /**
+   * @method getFormattedStringFromArray Get formatted string of elements to display on the UI
+   * Example:
+   * var arr = [ambari, bigdata, hadoop]
+   * getFormattedStringFromArray(arr);  // ambari, bigdata and hadoop
+   * @param array {Array}  Array of elements
+   * @returns {String}
+   */
+  getFormattedStringFromArray: function (array) {
+    var label = '';
+    array.forEach(function (_arrElement) {
+      if (array.length === 1) {
+        label = _arrElement;
+      }
+      else {
+        if (_arrElement !== array[array.length - 1]) {           // [clients.length - 1]
+          label = label + ' ' + _arrElement;
+          if (_arrElement !== array[array.length - 2]) {
+            label = label + ',';
+          }
+        }
+        else {
+          label = label + ' ' + Em.I18n.t('and') + ' ' + _arrElement;
+        }
+      }
+    }, this);
+    return label.trim();
+  },
+
+  pluralize: function(count, singular, plural) {
+    if (count > 1) {
+      return plural;
+    }
+    return singular;
   }
 };

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/views/common/configs/services_config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/services_config.js b/ambari-web/app/views/common/configs/services_config.js
index 1c66e7d..ca07473 100644
--- a/ambari-web/app/views/common/configs/services_config.js
+++ b/ambari-web/app/views/common/configs/services_config.js
@@ -488,14 +488,13 @@ App.ServiceConfigsByCategoryView = Ember.View.extend({
     var serviceName = this.get('service.serviceName');
     var serviceConfigsMetaData = App.config.get('preDefinedServiceConfigs');
     var serviceConfigMetaData = serviceConfigsMetaData.findProperty('serviceName', serviceName);
-    var categoryMetaData = serviceConfigMetaData == null ? null : serviceConfigMetaData.configCategories.findProperty('name', category.get('name'));
+    var categoryMetaData = serviceConfigMetaData == null ? null : serviceConfigMetaData.get('configCategories').findProperty('name', category.get('name'));
     if (categoryMetaData != null) {
       serviceConfigObj.filename = categoryMetaData.siteFileName;
     }
 
     var self = this;
     App.ModalPopup.show({
-      // classNames: ['big-modal'],
       classNames: [ 'sixty-percent-width-modal'],
       header: "Add Property",
       primary: 'Add',

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/views/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host.js b/ambari-web/app/views/main/host.js
index e9c90fd..d267a2b 100644
--- a/ambari-web/app/views/main/host.js
+++ b/ambari-web/app/views/main/host.js
@@ -85,6 +85,11 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
   }.property('filteredCount'),
 
   /**
+   * Stub function
+   */
+  updatePaging: function () {},
+
+  /**
    * flag to toggle displaying selected hosts counter
    */
   showSelectedFilter: function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/views/main/host/addHost/step4_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/addHost/step4_view.js b/ambari-web/app/views/main/host/addHost/step4_view.js
index 68bce18..29f4901 100644
--- a/ambari-web/app/views/main/host/addHost/step4_view.js
+++ b/ambari-web/app/views/main/host/addHost/step4_view.js
@@ -20,12 +20,5 @@
 var App = require('app');
 
 App.AddHostStep4View = Em.View.extend({
-
-  templateName: require('templates/main/host/addHost/step4'),
-
-
-  didInsertElement: function() {
-
-  }
-
+  templateName: require('templates/main/host/addHost/step4')
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/views/main/host/configs_service_menu.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/configs_service_menu.js b/ambari-web/app/views/main/host/configs_service_menu.js
index 53d6a19..0f20a7d 100644
--- a/ambari-web/app/views/main/host/configs_service_menu.js
+++ b/ambari-web/app/views/main/host/configs_service_menu.js
@@ -28,8 +28,8 @@ App.MainHostServiceMenuView = Em.CollectionView.extend({
       hostComponents.forEach(function (hc) {
         var service = hc.get('service');
         if (service) {
-        var serviceName = service.get('serviceName');
-          if(!['PIG', 'SQOOP', 'HCATALOG', 'GANGLIA'].contains(serviceName)){
+          var serviceName = service.get('serviceName');
+          if(!App.get('services.noConfigTypes').concat('HCATALOG').contains(serviceName)){
             if (!services.findProperty('serviceName', serviceName)) {
               services.push(service);
             }
@@ -39,7 +39,8 @@ App.MainHostServiceMenuView = Em.CollectionView.extend({
         }
       });
     }
-    return misc.sortByOrder(App.Service.servicesSortOrder, services);
+    var stackServices = App.StackService.find().mapProperty('serviceName');
+    return misc.sortByOrder(stackServices, services);
   }.property('host'),
   
   host: function(){

http://git-wip-us.apache.org/repos/asf/ambari/blob/00f8d5c5/ambari-web/app/views/main/service/info/summary.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/summary.js b/ambari-web/app/views/main/service/info/summary.js
index 2cdce53..8f66509 100644
--- a/ambari-web/app/views/main/service/info/summary.js
+++ b/ambari-web/app/views/main/service/info/summary.js
@@ -64,7 +64,9 @@ App.MainServiceInfoSummaryView = Em.View.extend({
    */
   collapsedSections: null,
 
-  servicesHaveClients: ["GLUSTERFS", "OOZIE", "ZOOKEEPER", "HIVE", "MAPREDUCE2", "TEZ", "SQOOP", "PIG","FALCON"],
+  servicesHaveClients: function() {
+    return App.get('services.hasClient');
+  }.property('App.services.hasClient'),
 
   sumMasterComponentView : Em.View.extend({
     didInsertElement: function() {
@@ -382,7 +384,7 @@ App.MainServiceInfoSummaryView = Em.View.extend({
    * Alerts panel not display for PIG, SQOOP and TEZ Service
    */
   isNoAlertsService: function () {
-    return !!this.get('service.serviceName') && ['PIG', 'SQOOP', 'TEZ'].contains(this.get('service.serviceName'));
+    return !!this.get('service.serviceName') && App.get('services.clientOnly').contains(this.get('service.serviceName'));
   }.property(''),
 
   gangliaUrl:function () {