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 2012/09/20 07:05:00 UTC

svn commit: r1387859 - in /incubator/ambari/branches/AMBARI-666: ./ ambari-web/app/ ambari-web/app/controllers/installer/ ambari-web/app/data/mock/ ambari-web/app/styles/ ambari-web/app/templates/installer/ ambari-web/app/utils/ ambari-web/app/views/in...

Author: yusaku
Date: Thu Sep 20 05:04:59 2012
New Revision: 1387859

URL: http://svn.apache.org/viewvc?rev=1387859&view=rev
Log:
AMBARI-763. Implement Installer Step 6 (Assign Slaves). (yusaku)

Added:
    incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step6_controller.js
    incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/hosts.js
    incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/master_component_hosts.js
    incubator/ambari/branches/AMBARI-666/ambari-web/app/ember.js
    incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step6_view.js
    incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step6_test.js
Removed:
    incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step6.js
Modified:
    incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt
    incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js
    incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step7_controller.js
    incubator/ambari/branches/AMBARI-666/ambari-web/app/messages.js
    incubator/ambari/branches/AMBARI-666/ambari-web/app/styles/application.less
    incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/slave_hosts.hbs
    incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step4.hbs
    incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step6.hbs
    incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js
    incubator/ambari/branches/AMBARI-666/ambari-web/app/views.js
    incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step7_view.js

Modified: incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt (original)
+++ incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt Thu Sep 20 05:04:59 2012
@@ -12,6 +12,8 @@ AMBARI-666 branch (unreleased changes)
 
   NEW FEATURES
 
+  AMBARI-763. Implement Installer Step 6 (Assign Slaves). (yusaku)
+
   AMBARI-760. Fix injection in data access objects to use guice provider.
   (mahadev)
 

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js Thu Sep 20 05:04:59 2012
@@ -26,6 +26,7 @@ require('controllers/installer/step1_con
 require('controllers/installer/step2_controller');
 require('controllers/installer/step3_controller');
 require('controllers/installer/step4_controller');
+require('controllers/installer/step6_controller');
 require('controllers/installer/step7_controller');
 require('controllers/main');
 require('controllers/main/service');

Added: incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step6_controller.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step6_controller.js?rev=1387859&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step6_controller.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step6_controller.js Thu Sep 20 05:04:59 2012
@@ -0,0 +1,163 @@
+/**
+ * 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');
+
+/**
+ * By Step 6, we have the following information stored in App.db and set on this
+ * controller by the router:
+ *
+ *   hosts: App.db.hosts (list of all hosts the user selected in Step 3)
+ *   selectedServiceNames: App.db.selectedServiceNames (the services that the user selected in Step 4)
+ *   masterComponentHosts: App.db.masterComponentHosts (master-components-to-hosts mapping the user selected in Step 5)
+ *
+ * Step 6 will set the following information in App.db:
+ *   hostSlaveComponents: App.db.hostSlaveComponents (hosts-to-slave-components mapping the user selected in Steo 6)
+ *   slaveComponentHosts: App.db.slaveComponentHosts (slave-components-to-hosts mapping the user selected in Step 6)
+ *
+ */
+App.InstallerStep6Controller = Em.Controller.extend({
+
+  hosts: [],
+  // TODO: hook up with user host selection
+  rawHosts: require('data/mock/hosts'),
+  selectedServiceNames: null,
+  masterComponentHosts: require('data/mock/master_component_hosts'),
+
+  hasMasterComponents: function(hostname) {
+    var hasMaster = false;
+    this.get('masterComponentHosts').forEach(function(masterComponent) {
+      if (masterComponent.hosts.contains(hostname)) {
+        hasMaster = true;
+      }
+    });
+    return hasMaster;
+  },
+
+  isAllDataNodes: function() {
+    return this.get('hosts').everyProperty('isDataNode', true);
+  }.property('hosts.@each.isDataNode'),
+
+  isAllTaskTrackers: function() {
+    return this.get('hosts').everyProperty('isTaskTracker', true);
+  }.property('hosts.@each.isTaskTracker'),
+
+  isAllRegionServers: function() {
+    return this.get('hosts').everyProperty('isRegionServer', true);
+  }.property('hosts.@each.isRegionServer'),
+
+  isNoDataNodes: function() {
+    return this.get('hosts').everyProperty('isDataNode', false);
+  }.property('hosts.@each.isDataNode'),
+
+  isNoTaskTrackers: function() {
+    return this.get('hosts').everyProperty('isTaskTracker', false);
+  }.property('hosts.@each.isTaskTracker'),
+
+  isNoRegionServers: function() {
+    return this.get('hosts').everyProperty('isRegionServer', false);
+  }.property('hosts.@each.isRegionServer'),
+
+  selectAllDataNodes: function() {
+    this.get('hosts').setEach('isDataNode', true);
+  },
+
+  selectAllTaskTrackers: function() {
+    this.get('hosts').setEach('isTaskTracker', true);
+  },
+
+  selectAllRegionServers: function() {
+    this.get('hosts').setEach('isRegionServer', true);
+  },
+
+  deselectAllDataNodes: function() {
+    this.get('hosts').setEach('isDataNode', false);
+  },
+
+  deselectAllTaskTrackers: function() {
+    this.get('hosts').setEach('isTaskTracker', false);
+  },
+
+  deselectAllRegionServers: function() {
+    this.get('hosts').setEach('isRegionServer', false);
+  },
+
+  init: function() {
+    this._super();
+    this.get('rawHosts').forEach(function(host) {
+      host.isDataNode = host.isTaskTracker = host.isRegionServer = !this.hasMasterComponents(host.hostname);
+      this.get('hosts').pushObject(Ember.Object.create(host));
+    }, this);
+  },
+
+  validate: function() {
+    return !(this.get('isNoDataNodes') || this.get('isNoTaskTrackers') || this.get('isNoRegionServers'));
+  },
+
+  submit: function() {
+    if (!this.validate()) {
+      this.set('errorMessage', Ember.I18n.t('installer.step6.error.mustSelectOne'));
+      return;
+    }
+    App.db.setHostSlaveComponents(this.get('host'));
+
+    var dataNodeHosts = [];
+    var taskTrackerHosts = [];
+    var regionServerHosts = [];
+
+    this.get('hosts').forEach(function (host) {
+      if (host.get('isDataNode')) {
+        dataNodeHosts.push({
+          hostname: host.hostname,
+          group: 'Default'
+        });
+      }
+      if (host.get('isTaskTracker')) {
+        taskTrackerHosts.push({
+          hostname: host.hostname,
+          group: 'Default'
+        });
+      }
+      if (host.get('isRegionServer')) {
+        regionServerHosts.push({
+          hostname: host.hostname,
+          group: 'Default'
+        });
+      }
+    });
+
+    var slaveComponentHosts = [];
+    slaveComponentHosts.push({
+      componentName: 'DataNode',
+      hosts: dataNodeHosts
+    });
+    slaveComponentHosts.push({
+      componentName: 'TaskTracker',
+      hosts: taskTrackerHosts
+    });
+    slaveComponentHosts.push({
+      componentName: 'RegionServer',
+      hosts: regionServerHosts
+    });
+
+    App.db.setSlaveComponentHosts(slaveComponentHosts);
+
+    App.router.transitionTo('step7');
+
+  }
+});
\ No newline at end of file

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step7_controller.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step7_controller.js?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step7_controller.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step7_controller.js Thu Sep 20 05:04:59 2012
@@ -19,8 +19,7 @@
 var App = require('app');
 
 /**
- * Controller for Step 7 of the Installer Wizard.
- * By Step 7, we have the following information stored in App.db (localStorage) and set on this
+ * By Step 7, we have the following information stored in App.db and set on this
  * controller by the router.
  *
  *   selectedServices: App.db.selectedServices (the services that the user selected in Step 4)
@@ -43,19 +42,28 @@ App.InstallerStep7Controller = Em.ArrayC
   }.property('@each.errorCount'),
 
   // TODO: set attributes from localStorage in router
-  // var selectedServiceNames = App.db.getSelectedServiceNames();
   selectedServiceNames: [ 'HDFS', 'MAPREDUCE', 'GANGLIA', 'NAGIOS', 'HBASE', 'PIG', 'SQOOP', 'OOZIE', 'HIVE', 'ZOOKEEPER'],
-  masterComponentHosts: '',
-  slaveComponentHosts: '',
+  masterComponentHosts: require('data/mock/master_component_hosts'),
+  slaveComponentHosts: require('data/mock/slave_component_hosts'),
 
   doInit: true,
 
   loadConfigs: function() {
 
+    // load dependent data from the database
     var selectedServiceNamesInDB = App.db.getSelectedServiceNames();
     if (selectedServiceNamesInDB !== undefined) {
       this.set('selectedServiceNames', selectedServiceNamesInDB);
     }
+    var masterComponentHostsInDB = App.db.getMasterComponentHosts();
+    if (masterComponentHostsInDB != undefined) {
+      this.set('masterComponentHosts', masterComponentHostsInDB);
+    }
+    var slaveComponentHostsInDB = App.db.getSlaveComponentHosts();
+    if (slaveComponentHostsInDB != undefined) {
+      this.set('slaveComponentHosts', slaveComponentHostsInDB);
+    }
+
     // TODO: check App.db to see if configs have been saved already
     if (this.doInit) {
       var serviceConfigs = require('data/service_configs');
@@ -128,15 +136,22 @@ App.SlaveComponentGroupsController = Emb
 
   name: 'slaveComponentGroupsController',
 
-  // TODO: Set up binding to use actual data
-  //contentBinding: 'App.router.installerStep7Controller.slaveComponentHosts',
-  content: require('data/mock/slave_component_hosts'),
+  contentBinding: 'App.router.installerStep7Controller.slaveComponentHosts',
+
+  selectedComponentName: function() {
+    switch (App.router.get('installerStep7Controller.selectedService.serviceName')) {
+      case 'HDFS':
+        return 'DataNode';
+      case 'MAPREDUCE':
+        return 'TaskTracker';
+      case 'HBASE':
+        return 'RegionServer';
+    }
 
-  selectedComponentName: 'DataNode',
+  }.property('App.router.installerStep7Controller.selectedService'),
 
   showAddSlaveComponentGroup: function (event) {
     var componentName = event.context;
-    this.set('selectedComponentName', componentName);
     App.ModalPopup.show({
       header: componentName + ' Groups',
       bodyClass: Ember.View.extend({
@@ -153,11 +168,11 @@ App.SlaveComponentGroupsController = Emb
   },
 
   hosts: function() {
-    return this.filterProperty('componentName', this.get('selectedComponentName'))[0].hosts;
-  }.property('@each.hosts'),
+    return this.findProperty('componentName', this.get('selectedComponentName')).hosts;
+  }.property('@each.hosts', 'selectedComponentName'),
 
   groups: function() {
-    return this.filterProperty('componentName', this.get('selectedComponentName'))[0].hosts.mapProperty('group').uniq();
-  }.property('@each.hosts')
+    return this.findProperty('componentName', this.get('selectedComponentName')).hosts.mapProperty('group').uniq();
+  }.property('@each.hosts', 'selectedComponentName')
 
 });

Added: incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/hosts.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/hosts.js?rev=1387859&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/hosts.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/hosts.js Thu Sep 20 05:04:59 2012
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+module.exports = [
+  {
+    hostname: 'host0001.company.com'
+  },
+  {
+    hostname: 'host0002.company.com'
+  },
+  {
+    hostname: 'host0003.company.com'
+  },
+  {
+    hostname: 'host0004.company.com'
+  },
+  {
+    hostname: 'host0005.company.com'
+  }
+];
\ No newline at end of file

Added: incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/master_component_hosts.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/master_component_hosts.js?rev=1387859&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/master_component_hosts.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/data/mock/master_component_hosts.js Thu Sep 20 05:04:59 2012
@@ -0,0 +1,76 @@
+/**
+ * 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.
+ */
+
+module.exports = [
+  {
+    componentName: 'NameNode',
+    hosts: [
+      'host0001.company.com'
+    ]
+  },
+  {
+    componentName: 'SNameNode',
+    hosts: [
+      'host0002.company.com'
+    ]
+  },
+  {
+    componentName: 'JobTracker',
+    hosts: [
+      'host0003.company.com'
+    ]
+  },
+  {
+    componentName: 'Hive Metastore',
+    hosts: [
+      'host0003.company.com'
+    ]
+  },
+  {
+    componentName: 'HBase Master',
+    hosts: [
+      'host0003.company.com'
+    ]
+  },
+  {
+    componentName: 'Oozie Server',
+    hosts: [
+      'host0002.company.com'
+    ]
+  },
+  {
+    componentName: 'Nagios Server',
+    hosts: [
+      'host0002.company.com'
+    ]
+  },
+  {
+    componentName: 'Ganglia Collector',
+    hosts: [
+      'host0002.company.com'
+    ]
+  },
+  {
+    componentName: 'ZooKeeper Server',
+    hosts: [
+      'host0001.company.com',
+      'host0002.company.com',
+      'host0003.company.com'
+    ]
+  }
+]
\ No newline at end of file

Added: incubator/ambari/branches/AMBARI-666/ambari-web/app/ember.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/ember.js?rev=1387859&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/ember.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/ember.js Thu Sep 20 05:04:59 2012
@@ -0,0 +1 @@
+module.exports = Ember;
\ No newline at end of file

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/messages.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/messages.js?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/messages.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/messages.js Thu Sep 20 05:04:59 2012
@@ -87,8 +87,11 @@ Em.I18n.translations = {
   'installer.step4.body': 'Choose which services you want to install on your cluster.<br>Note that some services have dependencies (e.g., HBase requires ZooKeeper.)',
 
   'installer.step5.header': 'Assign Masters',
+  'installer.step5.body': 'Assign master components to hosts you want to run them on.',
 
   'installer.step6.header': 'Assign Slaves',
+  'installer.step6.body': 'Assign slave components to hosts you want to run them on.',
+  'installer.step6.error.mustSelectOne': 'You must assign at least one host to each.',
 
   'installer.step7.header': 'Customize Services',
   'installer.step7.body': 'We have come up with recommended configurations for the services you selected.  Customize them as you see fit.',

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/styles/application.less
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/styles/application.less?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/styles/application.less (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/styles/application.less Thu Sep 20 05:04:59 2012
@@ -82,7 +82,7 @@ h1 {
         background-color: #fff;
 
     }
-    #step4 {
+    #step4, #step6 {
         a.selected {
             color: #333;
         }

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/slave_hosts.hbs
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/slave_hosts.hbs?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/slave_hosts.hbs (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/slave_hosts.hbs Thu Sep 20 05:04:59 2012
@@ -5,5 +5,5 @@ No host assigned
 {{value}}
 {{/if}}
 {{#if view.hasMultipleHosts}}
-<a href="#" {{action showEditSlaveComponentGroups view.serviceConfig.category target="App.router.slaveComponentGroupsController"}}>{{value.firstObject}} and {{view.otherLength}} others</a>
+<a href="#" {{action showEditSlaveComponentGroups view.serviceConfig.category target="App.router.slaveComponentGroupsController"}}>{{hosts.firstObject.hostname}} and {{view.otherLength}}</a>
 {{/if}}
\ No newline at end of file

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step4.hbs
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step4.hbs?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step4.hbs (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step4.hbs Thu Sep 20 05:04:59 2012
@@ -17,11 +17,11 @@
 -->
 
 
+<div id="step4">
 <h2>{{t installer.step4.header}}</h2>
 <div class="alert alert-info">
   {{t installer.step4.body}}
 </div>
-<div id="step4">
   <table class="table table-striped">
     <thead>
     <tr>

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step6.hbs
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step6.hbs?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step6.hbs (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step6.hbs Thu Sep 20 05:04:59 2012
@@ -16,9 +16,41 @@
 * limitations under the License.
 -->
 
+<div id="step6">
+  <h2>{{t installer.step6.header}}</h2>
 
-<h2>{{t installer.step6.header}}</h2>
-<div class="btn-area">
+  <div class="alert alert-info">{{t installer.step6.body}}</div>
+  {{#if errorMessage}}
+  <div class="alert alert-error">{{errorMessage}}</div>
+  {{/if}}
+  <table class="table table-striped">
+    <thead>
+    <tr>
+      <th>Host</th>
+      <th>
+        <a href="#" {{bindAttr class="isAllDataNodes:selected:deselected"}} {{action selectAllDataNodes target="controller"}}>all</a> | <a href="#" {{bindAttr class="isNoDataNodes:selected:deselected"}} {{action deselectAllDataNodes target="controller"}}>none</a>
+      </th>
+      <th>
+        <a href="#" {{bindAttr class="isAllTaskTrackers:selected:deselected"}} {{action selectAllTaskTrackers target="controller"}}>all</a> | <a href="#" {{bindAttr class="isNoTaskTrackers:selected:deselected"}} {{action deselectAllTaskTrackers target="controller"}}>none</a>
+      </th>
+      <th>
+        <a href="#" {{bindAttr class="isAllRegionServers:selected:deselected"}} {{action selectAllRegionServers target="controller"}}>all</a> | <a href="#" {{bindAttr class="isNoRegionServers:selected:deselected"}} {{action deselectAllRegionServers target="controller"}}>none</a>
+      </th>
+    </tr>
+    </thead>
+    <tbody>
+    {{#each hosts}}
+    <tr>
+      <td>{{hostname}}</td>
+      <td><label class="checkbox">{{view Ember.Checkbox checkedBinding="isDataNode"}}DataNode</label></td>
+      <td><label class="checkbox">{{view Ember.Checkbox checkedBinding="isTaskTracker"}}TaskTracker</label></td>
+      <td><label class="checkbox">{{view Ember.Checkbox checkedBinding="isRegionServer"}}RegionServer</label></td>
+    </tr>
+    {{/each}}
+    </tbody>
+  </table>
+  <div class="btn-area">
     <a class="btn" {{action back}}>Back</a>
-    <a class="btn btn-success" {{action next}}>Next</a>
+    <a class="btn btn-success" style="float:right" {{action submit target="controller"}}>Next</a>
+  </div>
 </div>
\ No newline at end of file

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js Thu Sep 20 05:04:59 2012
@@ -166,6 +166,27 @@ App.db.setSelectedServiceNames = functio
   localStorage.setObject('ambari', App.db.data);
 }
 
+App.db.setMasterComponentHosts = function(masterComponentHosts) {
+  App.db.data = localStorage.getObject('ambari');
+  var user = App.db.data.app.loginName;
+  App.db.data[user].Installer.masterComponentHosts = masterComponentHosts;
+  localStorage.setObject('ambari', App.db.data);
+}
+
+App.db.setHostSlaveComponents = function(hostSlaveComponents) {
+  App.db.data = localStorage.getObject('ambari');
+  var user = App.db.data.app.loginName;
+  App.db.data[user].Installer.hostSlaveComponents = hostSlaveComponents;
+  localStorage.setObject('ambari', App.db.data);
+}
+
+App.db.setSlaveComponentHosts = function(slaveComponentHosts) {
+  App.db.data = localStorage.getObject('ambari');
+  var user = App.db.data.app.loginName;
+  App.db.data[user].Installer.slaveComponentHosts = slaveComponentHosts;
+  localStorage.setObject('ambari', App.db.data);
+}
+
 /*
  *  getter methods
  */
@@ -234,4 +255,22 @@ App.db.getSelectedServiceNames = functio
   return App.db.data[user].Installer.selectedServiceNames;
 }
 
+App.db.getMasterComponentHosts = function() {
+  App.db.data = localStorage.getObject('ambari');
+  var user = App.db.data.app.loginName;
+  return App.db.data[user].Installer.masterComponentHosts;
+}
+
+App.db.getHostSlaveComponents = function() {
+  App.db.data = localStorage.getObject('ambari');
+  var user = App.db.data.app.loginName;
+  return App.db.data[user].Installer.hostSlaveComponents;
+}
+
+App.db.getSlaveComponentHosts = function() {
+  App.db.data = localStorage.getObject('ambari');
+  var user = App.db.data.app.loginName;
+  return App.db.data[user].Installer.slaveComponentHosts;
+}
+
 module.exports = App.db;

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/views.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/views.js?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/views.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/views.js Thu Sep 20 05:04:59 2012
@@ -38,7 +38,7 @@ require('views/installer/step2_view');
 require('views/installer/step3_view');
 require('views/installer/step4_view');
 require('views/installer/step5');
-require('views/installer/step6');
+require('views/installer/step6_view');
 require('views/installer/step7_view');
 require('views/installer/step8');
 require('views/installer/step9');

Added: incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step6_view.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step6_view.js?rev=1387859&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step6_view.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step6_view.js Thu Sep 20 05:04:59 2012
@@ -0,0 +1,26 @@
+/**
+ * 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');
+
+App.InstallerStep6View = Em.View.extend({
+
+  templateName: require('templates/installer/step6')
+
+});
\ No newline at end of file

Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step7_view.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step7_view.js?rev=1387859&r1=1387858&r2=1387859&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step7_view.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step7_view.js Thu Sep 20 05:04:59 2012
@@ -158,8 +158,6 @@ App.ServiceConfigMasterHostView = Ember.
 
 App.ServiceConfigMultipleHostsDisplay = Ember.Mixin.create(App.ServiceConfigHostPopoverSupport, {
 
-  valueBinding: 'serviceConfig.value',
-
   hasNoHosts: function() {
     return this.get('value').length === 0;
   }.property('value'),
@@ -173,13 +171,20 @@ App.ServiceConfigMultipleHostsDisplay = 
   }.property('value'),
 
   otherLength: function() {
-    return this.get('value').length - 1;
+    var len = this.get('value').length;
+    if (len > 2) {
+      return (len - 1) + ' others';
+    } else {
+      return '1 other';
+    }
   }.property('value')
 
 })
 
 App.ServiceConfigMasterHostsView = Ember.View.extend(App.ServiceConfigMultipleHostsDisplay, {
 
+  valueBinding: 'serviceConfig.value',
+
   classNames: ['master-hosts', 'span6'],
   templateName: require('templates/installer/master_hosts')
 
@@ -188,7 +193,10 @@ App.ServiceConfigMasterHostsView = Ember
 App.ServiceConfigSlaveHostsView = Ember.View.extend(App.ServiceConfigMultipleHostsDisplay, {
 
   classNames: ['slave-hosts', 'span6'],
-  templateName: require('templates/installer/slave_hosts')
+  templateName: require('templates/installer/slave_hosts'),
+
+  controllerBinding: 'App.router.slaveComponentGroupsController',
+  valueBinding: 'App.router.slaveComponentGroupsController.hosts'
 
 });
 

Added: incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step6_test.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step6_test.js?rev=1387859&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step6_test.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step6_test.js Thu Sep 20 05:04:59 2012
@@ -0,0 +1,140 @@
+/**
+ * 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 Ember = require('ember');
+var App = require('app');
+require('controllers/installer/step6_controller');
+
+describe('App.InstallerStep6Controller', function () {
+
+  var HOSTS = [ 'host1', 'host2', 'host3', 'host4' ];
+  App.InstallerStep6Controller.rawHosts = HOSTS;
+  var controller = App.InstallerStep6Controller.create();
+
+  describe('#selectAllDataNodes()', function () {
+    it('should set isDataNode to true on all hosts', function() {
+      controller.selectAllDataNodes();
+      expect(controller.get('hosts').everyProperty('isDataNode', true)).to.equal(true);
+    })
+  })
+
+  describe('#selectAllTaskTrackers()', function () {
+    it('should set isTaskTracker to true on all hosts', function() {
+      controller.selectAllTaskTrackers();
+      expect(controller.get('hosts').everyProperty('isTaskTracker', true)).to.equal(true);
+    })
+  })
+
+  describe('#selectAllRegionServers()', function () {
+    it('should set isRegionServer to true on all hosts', function() {
+      controller.selectAllRegionServers();
+      expect(controller.get('hosts').everyProperty('isRegionServer', true)).to.equal(true);
+    })
+  })
+
+  describe('#isAllDataNodes()', function () {
+
+    beforeEach(function() {
+      controller.get('hosts').setEach('isDataNode', true);
+    })
+
+    it('should return true if isDataNode is true for all services', function() {
+      expect(controller.get('isAllDataNodes')).to.equal(true);
+    })
+
+    it('should return false if isDataNode is false for one host', function() {
+      controller.get('hosts')[0].set('isDataNode', false);
+      expect(controller.get('isAllDataNodes')).to.equal(false);
+    })
+  })
+
+  describe('#isAllTaskTrackers()', function () {
+
+    beforeEach(function() {
+      controller.get('hosts').setEach('isTaskTracker', true);
+    })
+
+    it('should return true if isTaskTracker is true for all hosts', function() {
+      expect(controller.get('isAllTaskTrackers')).to.equal(true);
+    })
+
+    it('should return false if isTaskTracker is false for one host', function() {
+      controller.get('hosts')[0].set('isTaskTracker', false);
+      expect(controller.get('isAllTaskTrackers')).to.equal(false);
+    })
+
+  })
+
+  describe('#isAllRegionServers()', function () {
+
+    beforeEach(function() {
+      controller.get('hosts').setEach('isRegionServer', true);
+    });
+
+    it('should return true if isRegionServer is true for all hosts', function() {
+      expect(controller.get('isAllRegionServers')).to.equal(true);
+    })
+
+    it('should return false if isRegionServer is false for one host', function() {
+      controller.get('hosts')[0].set('isRegionServer', false);
+      expect(controller.get('isAllRegionServers')).to.equal(false);
+    })
+
+  })
+
+  describe('#validate()', function () {
+
+    beforeEach(function() {
+      controller.get('hosts').setEach('isDataNode', true);
+      controller.get('hosts').setEach('isTaskTracker', true);
+      controller.get('hosts').setEach('isRegionServer', true);
+    });
+
+    it('should return false if isDataNode is false for all hosts', function() {
+      controller.get('hosts').setEach('isDataNode', false);
+      expect(controller.validate()).to.equal(false);
+    })
+
+    it('should return false if isTaskTracker is false for all hosts', function() {
+      controller.get('hosts').setEach('isTaskTracker', false);
+      expect(controller.validate()).to.equal(false);
+    })
+
+    it('should return false if isRegionServer is false for all hosts', function() {
+      controller.get('hosts').setEach('isRegionServer', false);
+      expect(controller.validate()).to.equal(false);
+    })
+
+    it('should return true if isDataNode, isTaskTracker, and isRegionServer is true for all hosts', function() {
+      expect(controller.validate()).to.equal(true);
+    })
+
+    it('should return true if isDataNode, isTaskTracker, and isRegionServer is true for only one host', function() {
+      controller.get('hosts').setEach('isDataNode', false);
+      controller.get('hosts').setEach('isTaskTracker', false);
+      controller.get('hosts').setEach('isRegionServer', false);
+      var host = controller.get('hosts')[0];
+      host.set('isDataNode', true);
+      host.set('isTaskTracker', true);
+      host.set('isRegionServer', true);
+      expect(controller.validate()).to.equal(true);
+    })
+
+  })
+
+})
\ No newline at end of file