You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sr...@apache.org on 2013/02/27 20:54:37 UTC

svn commit: r1450939 - in /incubator/ambari/trunk: ./ ambari-web/app/ ambari-web/app/assets/data/wizard/stack/hdp/version01/ ambari-web/app/controllers/main/service/info/ ambari-web/app/controllers/wizard/ ambari-web/app/data/ ambari-web/app/models/ am...

Author: srimanth
Date: Wed Feb 27 19:54:36 2013
New Revision: 1450939

URL: http://svn.apache.org/r1450939
Log:
AMBARI-1509. Frontend: For service configurations provide ability to enter host level exceptions (srimanth)

Added:
    incubator/ambari/trunk/ambari-web/app/templates/common/configs/
    incubator/ambari/trunk/ambari-web/app/templates/common/configs/addPropertyWindow.hbs
    incubator/ambari/trunk/ambari-web/app/templates/common/configs/overriddenProperty.hbs
    incubator/ambari/trunk/ambari-web/app/templates/common/configs/overrideWindow.hbs
    incubator/ambari/trunk/ambari-web/app/templates/common/configs/service_config.hbs
      - copied, changed from r1450930, incubator/ambari/trunk/ambari-web/app/templates/common/service_config.hbs
    incubator/ambari/trunk/ambari-web/app/templates/common/configs/services_config.hbs
      - copied unchanged from r1450930, incubator/ambari/trunk/ambari-web/app/templates/common/services_config.hbs
    incubator/ambari/trunk/ambari-web/app/views/common/configs/
    incubator/ambari/trunk/ambari-web/app/views/common/configs/overriddenProperty_view.js
    incubator/ambari/trunk/ambari-web/app/views/common/configs/services_config.js
      - copied, changed from r1450930, incubator/ambari/trunk/ambari-web/app/views/common/services_config.js
Removed:
    incubator/ambari/trunk/ambari-web/app/templates/common/service_config.hbs
    incubator/ambari/trunk/ambari-web/app/templates/common/services_config.hbs
    incubator/ambari/trunk/ambari-web/app/views/common/services_config.js
Modified:
    incubator/ambari/trunk/CHANGES.txt
    incubator/ambari/trunk/ambari-web/app/assets/data/wizard/stack/hdp/version01/OOZIE.json
    incubator/ambari/trunk/ambari-web/app/controllers/main/service/info/configs.js
    incubator/ambari/trunk/ambari-web/app/controllers/wizard/step7_controller.js
    incubator/ambari/trunk/ambari-web/app/data/service_configs.js
    incubator/ambari/trunk/ambari-web/app/models/service_config.js
    incubator/ambari/trunk/ambari-web/app/styles/application.less
    incubator/ambari/trunk/ambari-web/app/views.js

Modified: incubator/ambari/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1450939&r1=1450938&r2=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Wed Feb 27 19:54:36 2013
@@ -12,6 +12,9 @@ Trunk (unreleased changes):
 
  NEW FEATURES
 
+ AMBARI-1509. Frontend: For service configurations provide ability to 
+ enter host level exceptions (srimanth)
+
  AMBARI-1508. Introduce a new section "Capacity scheduler" under MapReduce
  Service in step7 (Configure services) of Installer and Service 
  Reconfig. (jaimin)

Modified: incubator/ambari/trunk/ambari-web/app/assets/data/wizard/stack/hdp/version01/OOZIE.json
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/assets/data/wizard/stack/hdp/version01/OOZIE.json?rev=1450939&r1=1450938&r2=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/assets/data/wizard/stack/hdp/version01/OOZIE.json (original)
+++ incubator/ambari/trunk/ambari-web/app/assets/data/wizard/stack/hdp/version01/OOZIE.json Wed Feb 27 19:54:36 2013
@@ -31,7 +31,7 @@
   }, {
     "name" : "oozie.service.ConfigurationService.ignore.system.properties",
     "value" : "\n      oozie.service.AuthorizationService.security.enabled\n    ",
-    "description" : "\n      Specifies \"oozie.*\" properties to cannot be overriden via Java system properties.\n      Property names must be separted by commas.\n    ",
+    "description" : "\n      Specifies \"oozie.*\" properties to cannot be overridden via Java system properties.\n      Property names must be separted by commas.\n    ",
     "filename" : "oozie-site.xml"
   }, {
     "name" : "oozie.service.SchedulerService.threads",

Modified: incubator/ambari/trunk/ambari-web/app/controllers/main/service/info/configs.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/controllers/main/service/info/configs.js?rev=1450939&r1=1450938&r2=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/controllers/main/service/info/configs.js (original)
+++ incubator/ambari/trunk/ambari-web/app/controllers/main/service/info/configs.js Wed Feb 27 19:54:36 2013
@@ -261,7 +261,6 @@ App.MainServiceInfoConfigsController = E
   getSitesConfigProperties: function (advancedConfig) {
     var serviceConfigs = [];
     var globalConfigs = [];
-    var localServiceConfigs = this.get('serviceConfigs').findProperty('serviceName', this.get('content.serviceName'));
 
     this.get('serviceConfigTags').forEach(function (_tag) {
       var properties = this.getSiteConfigProperties(_tag.siteName, _tag.tagName);
@@ -318,24 +317,23 @@ App.MainServiceInfoConfigsController = E
           serviceConfigObj.options = this.get('configs').someProperty('name', index) ? this.get('configs').findProperty('name', index).options : null;
           globalConfigs.pushObject(serviceConfigObj);
         } else if (!this.get('configMapping').someProperty('name', index)) {
+          serviceConfigObj.id = 'site property';
+          serviceConfigObj.displayType = 'advanced';
+          serviceConfigObj.displayName = index;
+          serviceConfigObj.serviceName = this.get('content.serviceName');
           if (advancedConfig.someProperty('name', index)) {
-            serviceConfigObj.id = 'site property';
-            serviceConfigObj.serviceName = this.get('content.serviceName');
-            serviceConfigObj.category = 'Advanced';
-            serviceConfigObj.displayName = index;
-            serviceConfigObj.displayType = 'advanced';
             if (advancedConfig.findProperty('name', index).filename) {
               serviceConfigObj.filename = advancedConfig.findProperty('name', index).filename;
             }
-            serviceConfigs.pushObject(serviceConfigObj);
-          } else {
-            serviceConfigObj.id = 'conf-site';
-            serviceConfigObj.serviceName = this.get('content.serviceName');
-            this.get('customConfig').pushObject(serviceConfigObj);
           }
-
+          if (serviceConfigObj.filename === "core-site.xml")
+            serviceConfigObj.category = 'AdvancedCoreSite';
+          else if (serviceConfigObj.filename === "hdfs-site.xml")
+            serviceConfigObj.category = 'AdvancedHDFSSite';
+          else if (serviceConfigObj.filename === "mapred-site.xml")
+            serviceConfigObj.category = 'AdvancedMapredSite';
+          serviceConfigs.pushObject(serviceConfigObj);
         }
-
       }
     }, this);
     this.set('globalConfigs', globalConfigs);
@@ -1072,7 +1070,35 @@ App.MainServiceInfoConfigsController = E
         globalConfigs.push(hbaseMasterHost);
         break;
     }
-  }
+  },
+  
+  /**
+   * Provides service component name and display-name information for 
+   * the current selected service. 
+   */
+  getCurrentServiceComponents: function () {
+    var service = this.get('content');
+    var components = service.get('hostComponents');
+    var validComponents = Ember.A([]);
+    var seenComponents = {};
+    components.forEach(function(component){
+      var cn = component.get('componentName');
+      var cdn = component.get('displayName');
+      if(!seenComponents[cn]){
+        validComponents.push(Ember.Object.create({
+          componentName: cn,
+          displayName: cdn,
+          selected: false
+        }));
+        seenComponents[cn] = cn;
+      }
+    });
+    return validComponents;
+  }.property('content'),
+  
+  getAllHosts: function () {
+    return App.router.get('mainHostController.content');
+  }.property('App.router.mainHostController.content')
 
 });
 

Modified: incubator/ambari/trunk/ambari-web/app/controllers/wizard/step7_controller.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/controllers/wizard/step7_controller.js?rev=1450939&r1=1450938&r2=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/controllers/wizard/step7_controller.js (original)
+++ incubator/ambari/trunk/ambari-web/app/controllers/wizard/step7_controller.js Wed Feb 27 19:54:36 2013
@@ -76,7 +76,7 @@ App.WizardStep7Controller = Em.Controlle
     var serviceConfigs = this.get('serviceConfigs');
     var advancedConfig = this.get('content.advancedServiceConfig') || [];
     this.loadAdvancedConfig(serviceConfigs, advancedConfig);
-    this.loadCustomConfig();
+    //////this.loadCustomConfig();
     this.renderServiceConfigs(serviceConfigs);
     var storedServices = this.get('content.serviceConfigProperties');
     if (storedServices) {
@@ -112,17 +112,21 @@ App.WizardStep7Controller = Em.Controlle
           if (this.get('configMapping').someProperty('name', _config.name)) {
           } else if (!(service.configs.someProperty('name', _config.name))) {
             _config.id = "site property";
-            _config.category = 'Advanced';
+            // ////_config.category = 'Advanced';
+            if (_config.filename === "core-site.xml")
+              _config.category = 'AdvancedCoreSite';
+            else if (_config.filename === "hdfs-site.xml")
+              _config.category = 'AdvancedHDFSSite';
+            else if (_config.filename === "mapred-site.xml")
+              _config.category = 'AdvancedMapredSite';
             _config.displayName = _config.name;
             _config.defaultValue = _config.value;
             // make all advanced configs optional and populated by default
             /*
-             if (/\${.*}/.test(_config.value) || (service.serviceName !== 'OOZIE' && service.serviceName !== 'HBASE')) {
-             _config.isRequired = false;
-             _config.value = '';
-             } else if (/^\s+$/.test(_config.value)) {
-             _config.isRequired = false;
-             }
+             * if (/\${.*}/.test(_config.value) || (service.serviceName !==
+             * 'OOZIE' && service.serviceName !== 'HBASE')) { _config.isRequired =
+             * false; _config.value = ''; } else if
+             * (/^\s+$/.test(_config.value)) { _config.isRequired = false; }
              */
             _config.isRequired = false;
             _config.isVisible = true;
@@ -376,6 +380,91 @@ App.WizardStep7Controller = Em.Controlle
        }
        */
     }
-  }
+  }, 
+  
+  /**
+   * Provides service component name and display-name information for 
+   * the current selected service. 
+   */
+  getCurrentServiceComponents: function () {
+    var selectedServiceName = this.get('selectedService.serviceName');
+    var masterComponents = this.get('content.masterComponentHosts');
+    var slaveComponents = this.get('content.slaveComponentHosts');
+    var scMaps = require('data/service_components');
+    
+    var validComponents = Ember.A([]);
+    var seenComponents = {};
+    masterComponents.forEach(function(component){
+      var cn = component.component
+      var cdn = component.display_name;
+      if(component.serviceId===selectedServiceName && !seenComponents[cn]){
+        validComponents.pushObject(Ember.Object.create({
+          componentName: cn,
+          displayName: cdn,
+          selected: false
+        }));
+        seenComponents[cn] = cn;
+      }
+    });
+    slaveComponents.forEach(function(component){
+      var cn = component.componentName
+      var cdn = component.displayName;
+      var componentDef = scMaps.findProperty('component_name', cn);
+      if(componentDef!=null && selectedServiceName===componentDef.service_name && !seenComponents[cn]){
+        validComponents.pushObject(Ember.Object.create({
+          componentName: cn,
+          displayName: cdn,
+          selected: false
+        }));
+        seenComponents[cn] = cn;
+      }
+    });
+    return validComponents;
+  }.property('content'),
+  
+
+  getAllHosts: function () {
+    // Load hosts
+    var allHosts = Ember.A([]);
+    var hostNameToHostMap = {};
+    var hosts = this.get('content.hosts');
+    for ( var hostName in hosts) {
+      var host = hosts[hostName];
+      hostNameToHostMap[hostName] = App.Host.createRecord({
+        hostName: host.name,
+        publicHostName: host.name,
+        cpu: host.cpu,
+        memory: host.memory
+      });
+      allHosts.pushObject(hostNameToHostMap[hostName]);
+    }
+
+    // Load host-components
+    var masterComponents = this.get('content.masterComponentHosts');
+    var slaveComponents = this.get('content.slaveComponentHosts');
+    masterComponents.forEach(function (component) {
+      var host = hostNameToHostMap[component.hostName];
+      var hc = App.HostComponent.createRecord({
+        componentName: component.component,
+        host: host
+      });
+      if (host != null) {
+        host.get('hostComponents').pushObject(hc);
+      }
+    });
+    slaveComponents.forEach(function (component) {
+      component.hosts.forEach(function (host) {
+        var h = hostNameToHostMap[host.hostName];
+        var hc = App.HostComponent.createRecord({
+          componentName: component.componentName,
+          host: h
+        });
+        if (h != null) {
+          h.get('hostComponents').pushObject(hc);
+        }
+      });
+    });
+    return allHosts;
+  }.property('content')
 
 });

Modified: incubator/ambari/trunk/ambari-web/app/data/service_configs.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/data/service_configs.js?rev=1450939&r1=1450938&r2=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/data/service_configs.js (original)
+++ incubator/ambari/trunk/ambari-web/app/data/service_configs.js Wed Feb 27 19:54:36 2013
@@ -27,11 +27,13 @@ module.exports = [
     displayName: 'HDFS',
     filename: 'hdfs-site',
     configCategories: [
-      App.ServiceConfigCategory.create({ name: 'NameNode'}),
-      App.ServiceConfigCategory.create({ name: 'SNameNode'}),
-      App.ServiceConfigCategory.create({ name: 'DataNode'}),
-      App.ServiceConfigCategory.create({ name: 'General'}),
-      App.ServiceConfigCategory.create({ name: 'Advanced'})
+      App.ServiceConfigCategory.create({ name: 'NameNode', displayName : 'NameNode'}),
+      App.ServiceConfigCategory.create({ name: 'SNameNode', displayName : 'Secondary Name Node'}),
+      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 : 'Advanced Core Site'}),
+      App.ServiceConfigCategory.create({ name: 'AdvancedHDFSSite', displayName : 'Advanced HDFS Site'})
     ],
     configs: configProperties.filterProperty('serviceName', 'HDFS')
   },
@@ -41,11 +43,12 @@ module.exports = [
     displayName: 'MapReduce',
     filename: 'mapred-site',
     configCategories: [
-      App.ServiceConfigCategory.create({ name: 'JobTracker'}),
-      App.ServiceConfigCategory.create({ name: 'TaskTracker'}),
-      App.ServiceConfigCategory.create({ name: 'General'}),
-      App.ServiceConfigCategory.create({ name: 'Capacity Scheduler'}),
-      App.ServiceConfigCategory.create({ name: 'Advanced'})
+      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: 'Capacity Scheduler', displayName : 'Capacity Scheduler'}),
+      App.ServiceConfigCategory.create({ name: 'AdvancedMapredSite', displayName : 'Advanced MapReduce Site'})
     ],
     configs: configProperties.filterProperty('serviceName', 'MAPREDUCE')
   },
@@ -55,8 +58,8 @@ module.exports = [
     displayName: 'Hive/HCat',
     filename: 'hive-site',
     configCategories: [
-      App.ServiceConfigCategory.create({ name: 'Hive Metastore'}),
-      App.ServiceConfigCategory.create({ name: 'Advanced'})
+      App.ServiceConfigCategory.create({ name: 'Hive Metastore', displayName : 'Hive Metastore'}),
+      App.ServiceConfigCategory.create({ name: 'Advanced', displayName : 'Advanced'})
     ],
     configs: configProperties.filterProperty('serviceName', 'HIVE')
   },
@@ -66,7 +69,7 @@ module.exports = [
     displayName: 'WebHCat',
     filename: 'webhcat-site',
     configCategories: [
-      App.ServiceConfigCategory.create({ name: 'Advanced'})
+      App.ServiceConfigCategory.create({ name: 'Advanced', displayName : 'Advanced'})
     ],
     configs: configProperties.filterProperty('serviceName', 'WEBHCAT')
   },
@@ -76,10 +79,10 @@ module.exports = [
     displayName: 'HBase',
     filename: 'hbase-site',
     configCategories: [
-      App.ServiceConfigCategory.create({ name: 'HBase Master'}),
-      App.ServiceConfigCategory.create({ name: 'RegionServer'}),
-      App.ServiceConfigCategory.create({ name: 'General'}),
-      App.ServiceConfigCategory.create({ name: 'Advanced'})
+      App.ServiceConfigCategory.create({ name: 'HBase Master', displayName : 'HBase Master'}),
+      App.ServiceConfigCategory.create({ name: 'RegionServer', displayName : 'RegionServer'}),
+      App.ServiceConfigCategory.create({ name: 'General', displayName : 'General'}),
+      App.ServiceConfigCategory.create({ name: 'Advanced', displayName : 'Advanced'})
     ],
     configs: configProperties.filterProperty('serviceName', 'HBASE')
   },
@@ -88,8 +91,8 @@ module.exports = [
     serviceName: 'ZOOKEEPER',
     displayName: 'ZooKeeper',
     configCategories: [
-      App.ServiceConfigCategory.create({ name: 'ZooKeeper Server'}),
-      App.ServiceConfigCategory.create({ name: 'Advanced'})
+      App.ServiceConfigCategory.create({ name: 'ZooKeeper Server', displayName : 'ZooKeeper Server'}),
+      App.ServiceConfigCategory.create({ name: 'Advanced', displayName : 'Advanced'})
     ],
     configs: configProperties.filterProperty('serviceName', 'ZOOKEEPER')
   },
@@ -99,8 +102,8 @@ module.exports = [
     displayName: 'Oozie',
     filename: 'oozie-site',
     configCategories: [
-      App.ServiceConfigCategory.create({ name: 'Oozie Server'}),
-      App.ServiceConfigCategory.create({ name: 'Advanced'})
+      App.ServiceConfigCategory.create({ name: 'Oozie Server', displayName : 'Oozie Server'}),
+      App.ServiceConfigCategory.create({ name: 'Advanced', displayName : 'Advanced'})
     ],
     configs: configProperties.filterProperty('serviceName', 'OOZIE')
   },
@@ -109,7 +112,7 @@ module.exports = [
     serviceName: 'NAGIOS',
     displayName: 'Nagios',
     configCategories: [
-      App.ServiceConfigCategory.create({ name: 'General'})
+      App.ServiceConfigCategory.create({ name: 'General', displayName : 'General'})
     ],
     configs: configProperties.filterProperty('serviceName', 'NAGIOS')
   },
@@ -119,7 +122,7 @@ module.exports = [
     displayName: 'Misc',
     configCategories: [
       App.ServiceConfigCategory.create({ name: 'General'}),
-      App.ServiceConfigCategory.create({ name: 'Users and Groups'})
+      App.ServiceConfigCategory.create({ name: 'Users and Groups', displayName : 'Users and Groups'})
     ],
     configs: configProperties.filterProperty('serviceName', 'MISC')
   }

Modified: incubator/ambari/trunk/ambari-web/app/models/service_config.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/models/service_config.js?rev=1450939&r1=1450938&r2=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/models/service_config.js (original)
+++ incubator/ambari/trunk/ambari-web/app/models/service_config.js Wed Feb 27 19:54:36 2013
@@ -40,7 +40,10 @@ App.ServiceConfig = Ember.Object.extend(
 
 App.ServiceConfigCategory = Ember.Object.extend({
   name: null,
-
+  /**
+   *  We cant have spaces in the name as this is being used as HTML element id while rendering. Hence we introduced 'displayName' where we can have spaces like 'Secondary Name Node' etc.
+   */
+  displayName: null,
   slaveConfigs: null,
   primaryName: function () {
     switch (this.get('name')) {
@@ -76,7 +79,12 @@ App.ServiceConfigCategory = Ember.Object
       }, this);
     }
     return length;
-  }.property('slaveConfigs.groups.@each.errorCount')
+  }.property('slaveConfigs.groups.@each.errorCount'),
+  
+  isAdvanced : function(){
+    var name = this.get('name');
+    return name.indexOf("Advanced") !== -1 ;
+  }.property('name')
 });
 
 
@@ -118,7 +126,23 @@ App.ServiceConfigProperty = Ember.Object
   errorMessage: '',
   serviceConfig: null, // points to the parent App.ServiceConfig object
   filename: '',
-
+  isOriginalSCP : true, // if true, then this is original SCP instance and its value is not overridden value.
+  parentSCP: null, // This is the main SCP which is overridden by this. Set only when isOriginalSCP is false. 
+  selectedHostOptions : null, // contain array of hosts configured with overridden value
+  overrides : null,
+  /**
+   * No override capabilities for fields which are not edtiable
+   * and fields which represent master hosts.
+   */
+  isOverridable : function() {
+  	var editable = this.get('isEditable');
+  	var dt = this.get('displayType');
+  	return editable && ("masterHost"!=dt);
+  }.property('isEditable', 'displayType'),
+  isOverridden: function() {
+    var overrides = this.get('overrides');
+    return overrides != null;
+  }.property('overrides'),
   init: function () {
     if (this.get('id') === 'puppet var') {
       this.set('value', this.get('defaultValue'));
@@ -396,6 +420,35 @@ App.ServiceConfigProperty = Ember.Object
           }
       }
     }
+
+    if (!isError) {
+      // Check if this value is already in any of the overrides
+      var self = this;
+      var isOriginalSCP = this.get('isOriginalSCP');
+      var parentSCP = this.get('parentSCP');
+      if (!isOriginalSCP) {
+        var hosts = this.get('selectedHostOptions');
+        if(hosts==null || hosts.get('length')<1){
+          this.set('errorMessage', 'Select hosts to apply exception to');
+          isError = true;
+        }
+        if (!isError && parentSCP != null) {
+          if (value === parentSCP.get('value')) {
+            this.set('errorMessage', 'Host exceptions must have different value');
+            isError = true;
+          } else {
+            var overrides = parentSCP.get('overrides');
+            overrides.forEach(function (override) {
+              if (self != override && value === override.get('value')) {
+                self.set('errorMessage', 'Multiple host exceptions cannot have same value');
+                isError = true;
+              }
+            });
+          }
+        }
+      }
+    }
+    
     if (!isError) {
       this.set('errorMessage', '');
     }
@@ -403,3 +456,7 @@ App.ServiceConfigProperty = Ember.Object
 
 });
 
+App.ServiceConfigProperty.SelectListItem = Ember.Object.extend({
+  value :null,
+  label : null
+});

Modified: incubator/ambari/trunk/ambari-web/app/styles/application.less
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/styles/application.less?rev=1450939&r1=1450938&r2=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/styles/application.less (original)
+++ incubator/ambari/trunk/ambari-web/app/styles/application.less Wed Feb 27 19:54:36 2013
@@ -442,13 +442,60 @@ h1 {
     .control-label {
       text-align: left;
     }
-    .control-group {
+    .entry-row {
       margin: 10px 0;
+      .control-label-span{
+        width: auto !important;
+      }
+      .action{
+        margin-left: 7px;
+        margin-right: 3px;
+      }
+      .control-group {
+        margin: 0px;
+        .overrideField {
+          display: block;
+          margin-top: 5px;
+          margin-bottom: 5px;
+        }
+        .error {
+        }
+      }
     }
     form {
       margin-bottom: 0;
     }
   }
+  .accordion-group.AdvancedCoreSite {
+    .control-label {
+      float: none;
+      text-align: left;
+      width: auto;
+    }
+    .controls {
+      margin-left: 0;
+    }
+  }
+  .accordion-group.AdvancedHDFSSite {
+    .control-label {
+      float: none;
+      text-align: left;
+      width: auto;
+    }
+    .controls {
+      margin-left: 0;
+    }
+  }
+  .accordion-group.AdvancedMapredSite {
+    .control-label {
+      float: none;
+      text-align: left;
+      width: auto;
+    }
+    .controls {
+      margin-left: 0;
+    }
+  }
   .accordion-group.Advanced {
     .control-label {
       float: none;
@@ -507,6 +554,19 @@ h1 {
       list-style-type: none;
     }
   }
+  .common-config-category {
+    .action {
+      cursor: pointer;
+      .icon-plus-sign {
+        color: #5AB400;
+        margin-right: 2px;
+      }
+      .icon-minus-sign {
+        color: #FF4B4B;
+        margin-right: 2px;
+      }
+    }
+  }
 }
 
 a:focus {
@@ -614,6 +674,54 @@ a:focus {
 
   .modal-body {
     max-height: 403px;
+    .form-horizontal{
+      .each-row{
+        margin-top: 10px;
+      }
+      .each-row.control-label{
+        float:left;
+        clear:both;
+      }
+      .override-controls{
+        .input-append{
+          input{
+            -webkit-border-radius: 4px 0 0 4px;
+            -moz-border-radius: 4px 0 0 4px;
+            border-radius: 4px 0 0 4px;
+          }
+          .btn-group{
+            display: inline-block;
+            margin-left: -1px;
+            .btn{
+              -webkit-border-radius: 0 4px 4px 0;
+              -moz-border-radius: 0 4px 4px 0;
+              border-radius: 0 4px 4px 0;
+            }
+          }
+        }
+        .hosts-table-container{
+          width:100%;
+          height: 280px;
+          overflow: auto;
+          border: 1px solid #eee;
+        }
+        table{
+          th {
+            background-color: #d9edf7;
+          }
+          margin: 0 auto;
+        }
+        .message{
+          color: #777;
+        }
+      }
+      .control-label{
+         width:auto;
+      }
+      .overrideSelectBox {
+        width:100%;
+      }
+    }
   }
 
   .clear {

Added: incubator/ambari/trunk/ambari-web/app/templates/common/configs/addPropertyWindow.hbs
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/templates/common/configs/addPropertyWindow.hbs?rev=1450939&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/templates/common/configs/addPropertyWindow.hbs (added)
+++ incubator/ambari/trunk/ambari-web/app/templates/common/configs/addPropertyWindow.hbs Wed Feb 27 19:54:36 2013
@@ -0,0 +1,37 @@
+{{!
+* 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.
+}}
+  <form class="form-horizontal">
+    <div class="each-row">
+      <label class="control-label">Type</label>
+      <div class="controls">
+        {{view.serviceConfigProperty.filename}}
+      </div>
+    </div>
+    <div class="each-row">
+      <label class="control-label">Key</label>
+      <div class="controls">
+        {{view Ember.TextField valueBinding="view.serviceConfigProperty.name" class="span4"}}
+      </div>
+    </div>
+    <div class="each-row">
+      <label class="control-label">Value</label>
+      <div class="controls">
+        {{view Ember.TextArea valueBinding="view.serviceConfigProperty.value" rows="4" classNames="span6" }}
+      </div>
+    </div>
+  </form>
\ No newline at end of file

Added: incubator/ambari/trunk/ambari-web/app/templates/common/configs/overriddenProperty.hbs
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/templates/common/configs/overriddenProperty.hbs?rev=1450939&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/templates/common/configs/overriddenProperty.hbs (added)
+++ incubator/ambari/trunk/ambari-web/app/templates/common/configs/overriddenProperty.hbs Wed Feb 27 19:54:36 2013
@@ -0,0 +1,27 @@
+{{!
+* 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.
+}}
+
+{{#each overriddenSCP in view.serviceConfigProperty.overrides}}
+    {{! Here serviceConfigBinding should ideally be serviceConfigPropertyBinding }}
+    <div {{bindAttr class="overriddenSCP.errorMessage:error: :control-group :overrideField"}}>
+      {{view overriddenSCP.viewClass serviceConfigBinding="overriddenSCP" categoryConfigsBinding="view.categoryConfigs"}}
+      <a class="action" href="#" {{action showOverrideWindow overriddenSCP controller target="view" }} >{{overriddenSCP.selectedHostOptions.length}} hosts </a>
+      <a class="action" {{action "removeOverride" overriddenSCP target="view" }} ><i class="icon-minus-sign"></i>Remove</a>
+      <span class="help-inline">{{overriddenSCP.errorMessage}}</span>
+    </div>
+{{/each}}
\ No newline at end of file

Added: incubator/ambari/trunk/ambari-web/app/templates/common/configs/overrideWindow.hbs
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/templates/common/configs/overrideWindow.hbs?rev=1450939&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/templates/common/configs/overrideWindow.hbs (added)
+++ incubator/ambari/trunk/ambari-web/app/templates/common/configs/overrideWindow.hbs Wed Feb 27 19:54:36 2013
@@ -0,0 +1,114 @@
+{{!
+* 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.
+}}
+
+{{! #with view.categoryConfigProperty}}
+  <form class="form-horizontal">
+      <div class="override-controls">
+        <h4 class="message">Select hosts from the list of available hosts</h4>
+        
+        <table style="width: 100%;">
+          <tr>
+            <td>
+              <a href="#" {{action clearFilters target="view" }}>{{view.hostSelectMessage}}</a>
+            </td>
+            <td width="30%">
+              <div class="row">
+                <div class="span2">
+                  <!-- Filter text box with drop-down -->
+		              <div class="input-append">
+		                {{view Ember.TextField valueBinding="view.filterText" id="appendedDropdownButton" placeholder="Filter..." class="span2"}}
+		                <div class="btn-group">
+		                  <button class="btn dropdown-toggle" data-toggle="dropdown">
+		                    <span class="caret"></span>
+		                  </button>
+		                  <ul class="dropdown-menu">
+			                  {{#each column in view.filterColumns}}
+			                    <li>
+			                      <a href="#" {{action selectFilterColumn column target="view"}}>
+			                        {{#if column.selected}}
+	                              <i class='icon-ok-sign'></i>
+	                            {{else}}
+                                <i class='icon-placeholder'></i>
+	                            {{/if}}
+			                        {{column.name}}
+			                      </a>
+			                    </li>
+			                  {{/each}}
+		                  </ul>
+		                </div>
+		              </div>
+                </div>
+                <div class="span2">
+                  <!-- Host-components drop-down -->
+		              <div class="btn-group">
+		                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+		                  Components
+		                  <span class="caret"></span>
+		                </a>
+		                <ul class="dropdown-menu">
+		                  <!-- dropdown menu links -->
+		                  {{#each component in view.filterComponents}}
+                        <li>
+                          <a href="#" {{action selectFilterComponent component target="view"}}>
+                            {{#if component.selected}}
+                              <i class='icon-ok-sign'></i>
+                            {{else}}
+                              <i class='icon-placeholder'></i>
+	                          {{/if}}
+	                          {{component.displayName}}
+	                        </a>
+                        </li>
+                      {{/each}}
+		                </ul>
+                  </div>
+                </div>
+              </div>
+            </td>
+          </tr>
+        </table>
+        <table class="table table-striped hosts-table">
+          <thead>
+            <tr class="success">
+              <th width="10%">
+                {{view Ember.Checkbox checkedBinding="view.allHostsSelected"}}
+              </th>
+              <th width="45%">Host</th>
+              <th width="45%">{{view.filterColumn.name}}</th>
+            </tr>
+          </thead>
+         </table>
+        <div class="hosts-table-container">
+          <table class="table table-striped hosts-table">
+          {{#each entry in view.filteredHosts}}
+            <tr>
+              <td width="10%">
+                {{view Ember.Checkbox checkedBinding="entry.selected"}}
+              </td>
+              <td width="45%">
+                {{entry.host.publicHostName}}
+              </td>
+              <td>
+                {{entry.filterColumnValue}}
+              </td>
+            </tr>
+          {{/each}}
+         </table>
+        </div>
+      </div>
+  </form>
+{{! /with}}
\ No newline at end of file

Copied: incubator/ambari/trunk/ambari-web/app/templates/common/configs/service_config.hbs (from r1450930, incubator/ambari/trunk/ambari-web/app/templates/common/service_config.hbs)
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/templates/common/configs/service_config.hbs?p2=incubator/ambari/trunk/ambari-web/app/templates/common/configs/service_config.hbs&p1=incubator/ambari/trunk/ambari-web/app/templates/common/service_config.hbs&r1=1450930&r2=1450939&rev=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/templates/common/service_config.hbs (original)
+++ incubator/ambari/trunk/ambari-web/app/templates/common/configs/service_config.hbs Wed Feb 27 19:54:36 2013
@@ -18,7 +18,7 @@
 
 <div class="accordion">
   {{#each category in selectedService.configCategories}}
-    <div class="accordion-group {{unbound category.name}}">
+    <div class="accordion-group {{unbound category.name}} common-config-category">
       <div class="accordion-heading" {{action "onToggleBlock" category target="view"}}>
         {{#if category.isCollapsed}}
           <i class='icon-caret-right pull-left accordion-toggle'></i>
@@ -26,7 +26,7 @@
           <i class='icon-caret-down pull-left accordion-toggle'></i>
         {{/if}}
         <a class="accordion-toggle">
-          {{category.name}}
+          {{category.displayName}}
         </a>
       </div>
 
@@ -36,17 +36,33 @@
 
           {{#each view.categoryConfigs}}
             {{#if isVisible}}
-              <div {{bindAttr class="errorMessage:error: :control-group"}}>
-                <label class="control-label">{{displayName}}</label>
-
+              <div class="entry-row">
+                <span {{bindAttr class="errorMessage:error: :control-group :control-label-span"}}>
+                  <label class="control-label">{{displayName}}</label>
+                </span>
                 <div class="controls">
-                  {{view viewClass serviceConfigBinding="this" categoryConfigsBinding="view.categoryConfigs"}}
-                  <span class="help-inline">{{errorMessage}}</span>
+                  {{! Here serviceConfigBinding should ideally be serviceConfigPropertyBinding }}
+                  <div {{bindAttr class="errorMessage:error: :control-group"}}>
+                    {{view viewClass serviceConfigBinding="this" categoryConfigsBinding="view.categoryConfigs" }}
+                    {{#if isOverridable}}
+                      <a class="action" {{action "createOverrideProperty" this target="view" }} ><i class="icon-plus-sign"></i>Exception</a>
+                    {{/if}}
+                    <span class="help-inline">{{errorMessage}}</span>
+                  </div>
+                  {{#if this.isOverridden}}
+                    {{view App.ServiceConfigView.SCPOverriddenRowsView serviceConfigPropertyBinding="this"}}
+                  {{/if}}
                 </div>
               </div>
             {{/if}}
           {{/each}}
 
+          {{! For Advanced, Advanced Core Site, Advanced HDFS Site sections, show the 'Add Property' link.}}
+          {{# if category.isAdvanced }}
+            <div>
+              <a href="#" {{action "showAddPropertyWindow" this target="view" }} >Add Property...</a>
+            </div>
+          {{/if}}
         </form>
       {{/view}}
     </div>

Modified: incubator/ambari/trunk/ambari-web/app/views.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/views.js?rev=1450939&r1=1450938&r2=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/views.js (original)
+++ incubator/ambari/trunk/ambari-web/app/views.js Wed Feb 27 19:54:36 2013
@@ -30,7 +30,8 @@ require('views/common/metric');
 require('views/common/time_range');
 require('views/common/form/field');
 require('views/common/quick_view_link_view');
-require('views/common/services_config');
+require('views/common/configs/services_config');
+require('views/common/configs/overriddenProperty_view');
 require('views/login');
 require('views/main');
 require('views/main/menu');

Added: incubator/ambari/trunk/ambari-web/app/views/common/configs/overriddenProperty_view.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/views/common/configs/overriddenProperty_view.js?rev=1450939&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/views/common/configs/overriddenProperty_view.js (added)
+++ incubator/ambari/trunk/ambari-web/app/views/common/configs/overriddenProperty_view.js Wed Feb 27 19:54:36 2013
@@ -0,0 +1,41 @@
+/**
+ * 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.
+ */
+// SCP means ServiceConfigProperty
+
+var App = require('app');
+
+App.ServiceConfigView.SCPOverriddenRowsView = Ember.View.extend({
+  templateName: require('templates/common/configs/overriddenProperty'),
+  controllerBinding: 'App.router.mainServiceInfoConfigsController',
+  serviceConfigProperty: null, // is passed dynamically at runtime where ever
+  // we are declaring this from configs.hbs ( we are initializing this from UI )
+  categoryConfigs: null, // just declared as viewClass need it
+  
+  showOverrideWindow: function (event) {
+    // App.ServiceConfigsByCategoryView in which the current view is nested
+    this.get('parentView').showOverrideWindow(event);
+  },
+
+  removeOverride: function (event) {
+    // arg 1 SCP means ServiceConfigProperty
+    var scpToBeRemoved = event.contexts[0];
+    var overrides = this.get('serviceConfigProperty.overrides');
+    overrides = overrides.without(scpToBeRemoved);
+    this.set('serviceConfigProperty.overrides', overrides);
+  }
+
+});

Copied: incubator/ambari/trunk/ambari-web/app/views/common/configs/services_config.js (from r1450930, incubator/ambari/trunk/ambari-web/app/views/common/services_config.js)
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/views/common/configs/services_config.js?p2=incubator/ambari/trunk/ambari-web/app/views/common/configs/services_config.js&p1=incubator/ambari/trunk/ambari-web/app/views/common/services_config.js&r1=1450930&r2=1450939&rev=1450939&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/views/common/services_config.js (original)
+++ incubator/ambari/trunk/ambari-web/app/views/common/configs/services_config.js Wed Feb 27 19:54:36 2013
@@ -1,5 +1,3 @@
-
-
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -21,7 +19,7 @@
 var App = require('app');
 
 App.ServicesConfigView = Em.View.extend({
-  templateName: require('templates/common/services_config'),
+  templateName: require('templates/common/configs/services_config'),
   didInsertElement: function () {
     var controller = this.get('controller');
     controller.loadStep();
@@ -29,7 +27,7 @@ App.ServicesConfigView = Em.View.extend(
 });
 
 App.ServiceConfigView = Em.View.extend({
-  templateName: require('templates/common/service_config'),
+  templateName: require('templates/common/configs/service_config'),
   onToggleBlock: function (event) {
     $(document.getElementById(event.context.name)).toggle('blind', 500);
     event.context.set('isCollapsed', !event.context.get('isCollapsed'));
@@ -43,18 +41,292 @@ App.ServiceConfigsByCategoryView = Ember
 
   category: null,
   serviceConfigs: null, // General, Advanced, NameNode, SNameNode, DataNode, etc.
-
+  // total number of
+  // hosts (by
+  // default,
+  // cacheable )
   categoryConfigs: function () {
     return this.get('serviceConfigs').filterProperty('category', this.get('category.name'))
-  }.property('serviceConfigs.@each').cacheable(),
+  }.property('serviceConfigs.@each'),
   didInsertElement: function () {
-    if (this.get('category.name') == 'Advanced') {
+    var elementId = "#" + this.get('category.name');
+    if (this.get('category.name').indexOf('Advanced') != -1) {
       this.set('category.isCollapsed', true);
-      $("#Advanced").hide();
+      $(elementId).hide();
     } else {
       this.set('category.isCollapsed', false);
     }
   },
+  childView: App.ServiceConfigsOverridesView,
+  changeFlag: Ember.Object.create({
+    val: 1
+  }),
+  invokeMe: function () {
+    alert("parent");
+  },
+  isOneOfAdvancedSections: function () {
+    var category = this.get('category');
+    return category.indexOf("Advanced") != -1;
+  },
+  showAddPropertyWindow: function (event) {
+
+    var serviceConfigObj = {
+      name: '',
+      value: '',
+      defaultValue: '',
+      filename: ''
+    };
+
+    var category = this.get('category');
+    serviceConfigObj.displayType = "advanced";
+    serviceConfigObj.category = category.get('name');
+
+    var fileName = null;
+
+    if (category.get('name') === 'AdvancedCoreSite') {
+      serviceConfigObj.filename = "core-site.xml";
+    } else if (category.get('name') === 'AdvancedHDFSSite') {
+      serviceConfigObj.filename = "hdfs-site.xml";
+    } else if (category.get('name') === 'AdvancedMapredSite') {
+      serviceConfigObj.filename = "mapred-site.xml";
+    }
+
+    var self = this;
+    App.ModalPopup.show({
+      // classNames: ['big-modal'],
+      classNames: [ 'sixty-percent-width-modal', 'arun' ],
+      header: "Add Property",
+      primary: 'Save',
+      secondary: 'Cancel',
+      onPrimary: function () {
+        serviceConfigObj.displayName = serviceConfigObj.name;
+        var serviceConfigProperty = App.ServiceConfigProperty.create(serviceConfigObj);
+        self.get('serviceConfigs').pushObject(serviceConfigProperty);
+        this.hide();
+      },
+      onSecondary: function () {
+        this.hide();
+      },
+      bodyClass: Ember.View.extend({
+        templateName: require('templates/common/configs/addPropertyWindow'),
+        controllerBinding: 'App.router.mainServiceInfoConfigsController',
+        serviceConfigProperty: serviceConfigObj
+      })
+    });
+
+  },
+  
+  createOverrideProperty: function (event) {
+    var serviceConfigProperty = event.contexts[0];
+    var self = this;
+    var arrayOfSelectedHosts = [];
+    var newValue = '';
+    var overrides = serviceConfigProperty.get('overrides');
+    if (!overrides) {
+      overrides = []; 
+      serviceConfigProperty.set('overrides', overrides);
+    }
+    // create new override with new value
+    var newSCP = App.ServiceConfigProperty.create(serviceConfigProperty);
+    newSCP.set('value', '');
+    newSCP.set('isOriginalSCP', false); // indicated this is overridden value,
+    newSCP.set('parentSCP', serviceConfigProperty);
+    newSCP.set('selectedHostOptions', Ember.A([]));
+    console.debug("createOverrideProperty(): Added:", newSCP, " to main-property:", serviceConfigProperty)
+    overrides.pushObject(newSCP);
+  },
+  
+  _createDummyHosts: function(){
+    var array = Ember.A([]);
+    for ( var int = 0; int < 50; int++) {
+      array.pushObject(App.Host.createRecord({
+        hostName: 'internal-hostname-'+int+'.acme.com',
+        publicHostName: 'public-host-'+int+'.acme.com',
+        cpu: int,
+        memory: int*1024,
+        ip: int+"."+int*10+"."+int*20+"."+int*30,
+        rack: 'whatrack'+(int%10),
+        
+      }));
+    }
+    return array;
+  },
+  
+  showOverrideWindow: function (event) {
+    // argument 1
+    var serviceConfigProperty = event.contexts[0];
+    var parentServiceConfigProperty = serviceConfigProperty.get('parentSCP');
+    var alreadyOverriddenHosts = [];
+    parentServiceConfigProperty.get('overrides').forEach(function(override){
+      if (override!=null && override!=serviceConfigProperty && override.get('selectedHostOptions')!=null){
+        alreadyOverriddenHosts = alreadyOverriddenHosts.concat(override.get('selectedHostOptions'))
+      }
+    });
+    var selectedHosts = serviceConfigProperty.get('selectedHostOptions');
+    /**
+     * Get all the hosts available for selection. Since data is dependent on
+     * controller, we ask it, instead of doing regular Ember's App.Host.find().
+     * This should be an array of App.Host.
+     */
+    var allHosts = this.get('controller.getAllHosts');
+    //TODO - remove below section
+    if(allHosts.get('length')<5){
+      this._createDummyHosts();
+      allHosts = App.Host.find();
+    }
+    var availableHosts = Ember.A([]);
+    allHosts.forEach(function(host){
+      var hostId = host.get('id');
+      if(alreadyOverriddenHosts.indexOf(hostId)<0){
+        availableHosts.pushObject(Ember.Object.create({
+          selected: selectedHosts.indexOf(hostId)>-1,
+          host: host
+        }));
+      }
+    });
+    /**
+     * From the currently selected service we want the service-components.
+     * We only need an array of objects which have the 'componentName' and
+     * 'displayName' properties. Since each controller has its own objects,
+     * we ask for a normalized array back.
+     */
+    var validComponents = this.get('controller.getCurrentServiceComponents');
+    var self = this;
+    App.ModalPopup.show({
+      classNames: [ 'sixty-percent-width-modal' ],
+      header: "Select Hosts",
+      primary: 'OK',
+      secondary: 'Cancel',
+      onPrimary: function () {
+        console.debug('serviceConfigProperty.(value)=' + serviceConfigProperty.get('value'));
+        console.debug('serviceConfigProperty.(selectedHosts)=' + serviceConfigProperty.get('selectedHosts'));
+        var arrayOfSelectedHosts = [];
+        var selectedHosts = availableHosts.filterProperty('selected', true);
+        selectedHosts.forEach(function(host){
+          arrayOfSelectedHosts.push(host.get('host.id'));
+        });
+        serviceConfigProperty.set('selectedHostOptions', arrayOfSelectedHosts);
+        serviceConfigProperty.validate();
+        console.debug('Selected hosts:', arrayOfSelectedHosts);
+        this.hide();
+      },
+      onSecondary: function () {
+        this.hide();
+      },
+      bodyClass: Ember.View.extend({
+        templateName: require('templates/common/configs/overrideWindow'),
+        controllerBinding: 'App.router.mainServiceInfoConfigsController',
+        message: "Host level Overrides show here",
+        serviceConfigProperty: serviceConfigProperty,
+        filterText: '',
+        availableHosts: availableHosts,
+        filterColumn: null,
+        filterColumns: Ember.A([
+           Ember.Object.create({id:'ip', name:'IP Address', selected:false}),
+           Ember.Object.create({id:'cpu', name:'CPU', selected:false}),
+           Ember.Object.create({id:'memory', name:'RAM', selected:false}),
+           Ember.Object.create({id:'diskUsage', name:'Disk Usage', selected:false}),
+           Ember.Object.create({id:'loadAvg', name:'Load Average', selected:false}),
+           Ember.Object.create({id:'osArch', name:'OS Architecture', selected:false}),
+           Ember.Object.create({id:'osType', name:'OS Type', selected:false})
+        ]),
+        filterComponents: validComponents,
+        filterComponent: null,
+        filteredHosts: function () {
+          var hosts = this.get('availableHosts');
+          var filterText = this.get('filterText');
+          var filteredHosts = Ember.A([]);
+          var self = this;
+          hosts.forEach(function (host) {
+            var skip = false;
+            var ahost = host.get('host');
+            var filterColumn = self.get('filterColumn');
+            if (filterColumn == null) {
+              filterColumn = self.get('filterColumns').objectAt(0);
+            }
+            var value = ahost.get(filterColumn.id);
+            host.set('filterColumnValue', value);
+            if (filterText != null && filterText.length > 0) {
+              if ((value==null || !value.match(filterText)) && !host.get('host.publicHostName').match(filterText)) {
+                skip = true;
+              }
+            }
+            var filterComponent = self.get('filterComponent');
+            if (!skip && filterComponent != null) {
+              var componentFound = false;
+              var fcn = filterComponent.get('componentName');
+              var hcs = ahost.get('hostComponents');
+              if (hcs != null) {
+                hcs.forEach(function (hc) {
+                  if (fcn === hc.get('componentName')) {
+                    componentFound = true;
+                  }
+                });
+              }
+              if (!componentFound) {
+                skip = true;
+              }
+            }
+            if (!skip) {
+              filteredHosts.pushObject(host);
+            }
+          });
+          return filteredHosts;
+        }.property('availableHosts', 'filterText', 'filterColumn', 'filterComponent', 'filterComponent.componentName'),
+        hostColumnValue: function(host, column){
+          return host.get(column.id);
+        },
+        hostSelectMessage: function () {
+          var hosts = this.get('availableHosts');
+          var selectedHosts = hosts.filterProperty('selected', true);
+          return selectedHosts.get('length') + " out of " + hosts.get('length') + " hosts selected";
+        }.property('availableHosts.@each.selected'), 
+        selectFilterColumn: function(event){
+          if(event!=null && event.context!=null && event.context.id!=null){
+            var filterColumn = this.get('filterColumn');
+            if(filterColumn!=null){
+              filterColumn.set('selected', false);
+            }
+            event.context.set('selected', true);
+            this.set('filterColumn', event.context);
+          }
+        },
+        selectFilterComponent: function(event){
+          if(event!=null && event.context!=null && event.context.componentName!=null){
+            var currentFilter = this.get('filterComponent');
+            if(currentFilter!=null){
+              currentFilter.set('selected', false);
+            }
+            if(currentFilter!=null && currentFilter.componentName===event.context.componentName){
+              // selecting the same filter deselects it.
+              this.set('filterComponent', null);
+            }else{
+              this.set('filterComponent', event.context);
+              event.context.set('selected', true);
+            }
+          }
+        },
+        allHostsSelected: false,
+        toggleSelectAllHosts: function(event){
+          if(this.get('allHostsSelected')){
+            // Select all hosts
+            this.get('availableHosts').setEach('selected', true);
+          }else{
+            // Deselect all hosts
+            this.get('availableHosts').setEach('selected', false);
+          }
+        }.observes('allHostsSelected'),
+        clearFilters: function () {
+          var currentFilter = this.get('filterComponent');
+          if (currentFilter != null) {
+            currentFilter.set('selected', false);
+          }
+          this.set('filterComponent', null);
+          this.set('filterText', null);
+        }
+      })
+    });
+  },
   layout: Ember.Handlebars.compile('<div {{bindAttr id="view.category.name"}} class="accordion-body collapse in"><div class="accordion-inner">{{yield}}</div></div>')
 });
 
@@ -71,4 +343,3 @@ App.ServiceConfigTab = Ember.View.extend
     this.$('a[href="#' + serviceName + '"]').tab('show');
   }
 });
-