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/26 22:59:34 UTC
svn commit: r1390724 - in /incubator/ambari/branches/AMBARI-666: ./
ambari-web/app/ ambari-web/app/controllers/installer/
ambari-web/app/styles/ ambari-web/app/templates/installer/
ambari-web/app/views/installer/ ambari-web/test/installer/
Author: yusaku
Date: Wed Sep 26 20:59:33 2012
New Revision: 1390724
URL: http://svn.apache.org/viewvc?rev=1390724&view=rev
Log:
AMBARI-768. Implement step 5 of installer wizard (Assign Masters). (Ananya Sen via yusaku)
Added:
incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step5_controller.js
incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step5_view.js
incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step5_test.js
Removed:
incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step5.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/styles/application.less
incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step5.hbs
incubator/ambari/branches/AMBARI-666/ambari-web/app/views.js
incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step1_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=1390724&r1=1390723&r2=1390724&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt (original)
+++ incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt Wed Sep 26 20:59:33 2012
@@ -12,6 +12,9 @@ AMBARI-666 branch (unreleased changes)
NEW FEATURES
+ AMBARI-768. Implement step 5 of installer wizard (Assign Masters).
+ (Ananya Sen via yusaku)
+
AMBARI-767. Add bootstrap script to ssh in parallel and setup agents on a
list of hosts. (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=1390724&r1=1390723&r2=1390724&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js Wed Sep 26 20:59:33 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/step5_controller');
require('controllers/installer/step6_controller');
require('controllers/installer/step7_controller');
require('controllers/main');
Added: incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step5_controller.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step5_controller.js?rev=1390724&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step5_controller.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step5_controller.js Wed Sep 26 20:59:33 2012
@@ -0,0 +1,352 @@
+/**
+ * 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');
+
+//mock data
+
+//input
+App.selectedServices = [ 'HDFS', 'MapReduce', 'Ganglia', 'Nagios', 'HBase', 'Pig', 'Sqoop', 'Oozie', 'Hive', 'ZooKeeper'];
+
+App.hosts = [
+ {
+ host_name: 'host1',
+ cluster_name: "test",
+ total_mem: 7,
+ cpu_count: 2
+ },
+ {
+ host_name: 'host2',
+ cluster_name: "test",
+ total_mem: 4,
+ cpu_count: 2
+ },
+ {
+ host_name: 'host3',
+ cluster_name: "test",
+ total_mem: 8,
+ cpu_count: 2
+ },
+ {
+ host_name: 'host4',
+ cluster_name: "test",
+ total_mem: 8,
+ cpu_count: 2
+ },
+ {
+ host_name: 'host5',
+ cluster_name: "test",
+ total_mem: 8,
+ cpu_count: 2
+ }
+];
+
+App.masterServices = [
+ {
+ component_name: "NameNode",
+ selectedHost: 'host1',
+ availableHosts: [] // filled dynAmically
+ },
+ {
+ component_name: "ZooKeeper",
+ selectedHost: 'host3',
+ availableHosts: [] // filled dynAmically
+ },
+ {
+ component_name: "JobTracker",
+ selectedHost: 'host2',
+ availableHosts: [] // filled dynAmically
+ },
+ {
+ component_name: "HBase Master",
+ selectedHost: 'host3',
+ availableHosts: [] // filled dynAmically
+ }
+];
+
+//mapping format
+//masterHostMapping = [
+// {
+// host_name: 'host1',
+// masterServices: [{component_name:"NamedNode"}, {component_name:"Jobtracker"}]
+// },
+// {
+// host_name: 'host2',
+// masterServices: [{component_name:"NamedNode"}, {component_name:"Jobtracker"}]
+// }
+// ];
+
+//end - mock data
+
+App.InstallerStep5Controller = Em.Controller.extend({
+ //properties
+ name: "installerStep5Controller",
+
+ hosts: [],
+ selectedServices: [],
+ selectedServicesMasters: [],
+
+ masterHostMapping: function () {
+ var mapping = [], mappingObject, self = this, mappedHosts, hostObj, hostInfo;
+ //get the unique assigned hosts and find the master services assigned to them
+
+ mappedHosts = this.get("selectedServicesMasters").mapProperty("selectedHost").uniq();
+
+ mappedHosts.forEach(function (item) {
+ hostObj = self.get("hosts").findProperty("host_name", item);
+ hostInfo = " ( " + hostObj.get("total_mem") + "GB" + " " + hostObj.get("cpu_count") + "cores )";
+
+ mappingObject = Ember.Object.create({
+ host_name: item,
+ hostInfo: hostInfo,
+ masterServices: self.get("selectedServicesMasters").filterProperty("selectedHost", item)
+ });
+
+ mapping.pushObject(mappingObject);
+ }, this);
+
+ mapping.sort(this.sortHostsByName);
+
+ return mapping;
+
+ }.property("selectedServicesMasters.@each.selectedHost"),
+
+ remainingHosts: function () {
+ return (this.get("hosts.length") - this.get("masterHostMapping.length"));
+ }.property("selectedServicesMasters.@each.selectedHost"),
+
+ hasZookeeper: function () {
+ return this.selectedServices.findProperty("service_name", "ZooKeeper");
+ }.property("selectedServices"),
+
+ //methods
+ getAvailableHosts: function (componentName) {
+ var assignableHosts = [],
+ zookeeperHosts = null;
+
+ if (componentName === "ZooKeeper") {
+ zookeeperHosts = this.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").mapProperty("selectedHost").uniq();
+
+ this.get("hosts").forEach(function (item) {
+ if (!(zookeeperHosts.contains(item.get("host_name")))) {
+ assignableHosts.pushObject(item);
+ }
+ }, this);
+
+ return assignableHosts;
+
+ } else {
+ return this.get("hosts");
+ }
+ },
+
+ assignHostToMaster: function (masterService, selectedHost, zId) {
+ if (selectedHost && masterService) {
+
+ if ((masterService === "ZooKeeper") && zId) {
+ this.get('selectedServicesMasters').findProperty("zId", zId).set("selectedHost", selectedHost);
+ this.rebalanceZookeeperHosts();
+ }
+ else {
+ this.get('selectedServicesMasters').findProperty("component_name", masterService).set("selectedHost", selectedHost);
+ }
+
+ }
+ },
+
+ addZookeepers: function () {
+ /*
+ *Logic: If ZooKeeper service is selected then there can be
+ * minimum 1 ZooKeeper master in total, and
+ * maximum 1 ZooKeeper on every host
+ */
+ var maxNumZooKeepers = this.get("hosts.length"),
+ currentZooKeepers = this.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper"),
+ newZookeeper = null,
+ zookeeperHosts = null,
+ suggestedHost = null,
+ i = 0,
+ lastZoo = null;
+
+ //work only if the Zookeeper service is selected in previous step
+ if (!this.get("selectedServices").mapProperty("service_name").contains("ZooKeeper")) {
+ return false;
+ }
+
+ if (currentZooKeepers.get("length") < maxNumZooKeepers) {
+ currentZooKeepers.set("lastObject.showAddControl", false);
+ if (currentZooKeepers.get("length") > 1) {
+ currentZooKeepers.set("lastObject.showRemoveControl", true);
+ }
+
+ //create a new zookeeper based on an existing one
+ newZookeeper = Ember.Object.create({});
+ lastZoo = currentZooKeepers.get("lastObject");
+ newZookeeper.set("component_name", lastZoo.get("component_name"));
+ newZookeeper.set("selectedHost", lastZoo.get("selectedHost"));
+ newZookeeper.set("availableHosts", this.getAvailableHosts("ZooKeeper"));
+
+ if (currentZooKeepers.get("length") === (maxNumZooKeepers - 1)) {
+ newZookeeper.set("showAddControl", false);
+ } else {
+ newZookeeper.set("showAddControl", true);
+ }
+ newZookeeper.set("showRemoveControl", true);
+
+ //get recommended host for the new Zookeeper server
+ zookeeperHosts = currentZooKeepers.mapProperty("selectedHost").uniq();
+
+ for (i = 0; i < this.get("hosts.length"); i++) {
+ if (!(zookeeperHosts.contains(this.get("hosts")[i].get("host_name")))) {
+ suggestedHost = this.get("hosts")[i].get("host_name");
+ break;
+ }
+ }
+
+ newZookeeper.set("selectedHost", suggestedHost);
+ newZookeeper.set("zId", (currentZooKeepers.get("lastObject.zId") + 1));
+
+ this.get("selectedServicesMasters").pushObject(newZookeeper);
+
+ this.rebalanceZookeeperHosts();
+
+ return true;
+ }
+ return false;//if no more zookeepers can be added
+ },
+
+ removeZookeepers: function (zId) {
+ var currentZooKeepers;
+
+ //work only if the Zookeeper service is selected in previous step
+ if (!this.get("selectedServices").mapProperty("service_name").contains("ZooKeeper")) {
+ return false;
+ }
+
+ currentZooKeepers = this.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper");
+
+ if (currentZooKeepers.get("length") > 1) {
+ this.get("selectedServicesMasters").removeAt(this.get("selectedServicesMasters").indexOf(this.get("selectedServicesMasters").findProperty("zId", zId)));
+
+ currentZooKeepers = this.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper");
+ if (currentZooKeepers.get("length") < this.get("hosts.length")) {
+ currentZooKeepers.set("lastObject.showAddControl", true);
+ }
+
+ this.rebalanceZookeeperHosts();
+
+ return true;
+ }
+
+ return false;
+
+ },
+
+ rebalanceZookeeperHosts: function () {
+ //for a zookeeper update the available hosts for the other zookeepers
+
+ var currentZooKeepers = this.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper"),
+ zooHosts = currentZooKeepers.mapProperty("selectedHost"),
+ availableZooHosts = [],
+ preparedAvailableHosts = null;
+
+ //get all hosts available for zookeepers
+ this.get("hosts").forEach(function (item) {
+ if (!zooHosts.contains(item.get("host_name"))) {
+ availableZooHosts.pushObject(item);
+ }
+ }, this);
+
+ currentZooKeepers.forEach(function (item) {
+ preparedAvailableHosts = availableZooHosts.slice(0);
+ preparedAvailableHosts.pushObject(this.get("hosts").findProperty("host_name", item.get("selectedHost")))
+ preparedAvailableHosts.sort(this.sortHostsByConfig, this);
+ item.set("availableHosts", preparedAvailableHosts);
+ }, this);
+
+ },
+
+ sortHostsByConfig: function (a, b) {
+ //currently handling only total memory on the host
+ if (a.total_mem < b.total_mem) {
+ return 1;
+ }
+ else {
+ return -1;
+ }
+ },
+
+ sortHostsByName: function (a, b) {
+ if (a.host_name > b.host_name) {
+ return 1;
+ }
+ else {
+ return -1;
+ }
+ },
+
+ /*
+ * Initialize the model data
+ */
+ init: function () {
+ var zookeeperComponent = null, componentObj = null, hostObj = null;
+ this._super();
+
+ //wrap the model data into
+
+ App.hosts.forEach(function (item) {
+ hostObj = Ember.Object.create(item);
+ hostObj.set("host_info", "" + hostObj.get("host_name") + " ( " + hostObj.get("total_mem") + "GB" + " " + hostObj.get("cpu_count") + "cores )");
+ this.get("hosts").pushObject(hostObj);
+ }, this);
+
+ //sort the hosts
+ this.get("hosts").sort(this.sortHostsByConfig);
+
+ //todo: build masters from config instead
+ App.masterServices.forEach(function (item) {
+ //add the zookeeper component at the end if exists
+ if (item.component_name === "ZooKeeper") {
+ zookeeperComponent = Ember.Object.create(item);
+ } else {
+ componentObj = Ember.Object.create(item);
+ componentObj.set("availableHosts", this.get("hosts").slice(0));
+ this.get("selectedServicesMasters").pushObject(componentObj);
+ }
+ }, this);
+
+ //while initialization of the controller there will be only 1 zookeeper server
+
+ if (zookeeperComponent) {
+ zookeeperComponent.set("showAddControl", true);
+ zookeeperComponent.set("showRemoveControl", false);
+ zookeeperComponent.set("zId", 1);
+ zookeeperComponent.set("availableHosts", this.get("hosts").slice(0));
+ this.get("selectedServicesMasters").pushObject(Ember.Object.create(zookeeperComponent));
+ }
+
+ App.selectedServices.forEach(function (item) {
+ this.get("selectedServices").pushObject(Ember.Object.create({service_name: item}));
+ }, this);
+
+ }
+
+});
+
+
+
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=1390724&r1=1390723&r2=1390724&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 Wed Sep 26 20:59:33 2012
@@ -130,3 +130,91 @@ a:focus {
outline: none;
}
+/*assign masters*/
+
+.assign-masters {
+ .select-hosts{
+ width:50%;
+ float:left;
+ white-space:nowrap;
+ }
+
+ .round-corners{
+ border-radius: 8px;
+ -webkit-border-radius: 8px;
+ -moz-border-radius: 8px;
+ }
+
+ .host-assignments{
+ float:right;
+ width:45%;
+ }
+
+ .remaining-hosts{
+ padding:25px;
+ border-top:solid 1px #cccccc;
+ border-left:solid 1px #cccccc;
+ border-right:groove 5px #cccccc;
+ border-bottom:groove 5px #cccccc;
+ margin-top:20px;
+ background-color: #FCF8E3;
+ color: #C09853;
+ }
+
+ .host-assignments .mapping-box{
+ border:solid 1px #cccccc;
+ padding: 8px;
+ margin-bottom:10px;
+ background-color: #FFFAFA;
+ }
+
+ .host-assignments .assignedService{
+ padding:5px;
+ border:solid 1px #cccccc;
+ margin:2px;
+ background-color: #69BE28;
+ color:white;
+ white-space: nowrap;
+ font-size: 0.9em;
+ }
+
+ .form-horizontal .controls {
+ margin-left: 110px;
+ }
+
+ .form-horizontal .control-label {
+ width:100px;
+ }
+
+ .form-horizontal .control-group select {
+ width:75%;
+ min-width:100px;
+ max-width:250px;
+ }
+
+ .hostString{
+ margin-bottom: 5px;
+ }
+
+ .controls .badge{
+ background-color: #ADC299;
+ color: #ffffff;
+ cursor: pointer;
+ font-weight: bold;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+ }
+
+ .assign-master .controls .badge:hover{
+ background-color: #99B280;
+ }
+
+ .alertFlag{
+ font-size: 1.3em;
+ color: #B94A48;
+ font-weight: bold;
+ vertical-align: middle;
+ }
+}
+
+/*end assign masters*/
+
Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step5.hbs
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step5.hbs?rev=1390724&r1=1390723&r2=1390724&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step5.hbs (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/templates/installer/step5.hbs Wed Sep 26 20:59:33 2012
@@ -16,9 +16,65 @@
* limitations under the License.
-->
-
<h2>{{t installer.step5.header}}</h2>
+<div class="alert alert-info">
+ {{t installer.step5.body}}
+</div>
+<div class="assign-masters">
+ <div class="select-hosts">
+ <form class="form-horizontal">
+ <!-- View for array controller -->
+ {{#each selectedServicesMasters}}
+ <div class="control-group">
+ <label class="control-label">{{component_name}}:</label>
+
+ <div class="controls">
+ {{view App.SelectHostView
+ contentBinding="availableHosts"
+ optionValuePath="content.host_name"
+ optionLabelPath="content.host_info"
+ selectedHostBinding="selectedHost"
+ serviceNameBinding="component_name"
+ zIdBinding="zId"
+ }}
+
+ {{#if showAddControl}}
+ {{view App.AddControlView
+ componentNameBinding="component_name"
+ }}
+ {{/if}}
+ {{#if showRemoveControl}}
+ {{view App.RemoveControlView
+ zIdBinding="zId"
+ }}
+ {{/if}}
+
+ </div>
+ </div>
+ {{/each}}
+
+ </form>
+ </div>
+
+ <div class="host-assignments">
+ {{#each masterHostMapping}}
+ <div class="mapping-box round-corners well">
+ <div class="hostString"><span><strong>{{host_name}}</strong></span><span>{{hostInfo}}</span></div>
+ {{#each masterServices}}
+ <span class="assignedService round-corners">{{component_name}}</span>
+ {{/each}}
+
+ </div>
+ {{/each}}
+
+ {{#if remainingHosts}}
+ <div class="remaining-hosts round-corners well">
+ <span><strong>{{remainingHosts}}</strong> {{t installer.step5.attention}}</span></div>
+ {{/if}}
+ </div>
+ <div style="clear: both;"></div>
+</div>
<div class="btn-area">
- <a class="btn" {{action back}}>Back</a>
- <a class="btn btn-success" {{action next}}>Next</a>
+ <a class="btn" {{action back}}>Back</a>
+ <a class="btn btn-success" {{action next}}>Next</a>
</div>
\ No newline at end of file
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=1390724&r1=1390723&r2=1390724&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/views.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/views.js Wed Sep 26 20:59:33 2012
@@ -37,7 +37,7 @@ require('views/installer/step1_view');
require('views/installer/step2_view');
require('views/installer/step3_view');
require('views/installer/step4_view');
-require('views/installer/step5');
+require('views/installer/step5_view');
require('views/installer/step6_view');
require('views/installer/step7_view');
require('views/installer/step8');
Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step1_view.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step1_view.js?rev=1390724&r1=1390723&r2=1390724&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step1_view.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step1_view.js Wed Sep 26 20:59:33 2012
@@ -25,4 +25,5 @@ App.InstallerStep1View = Em.View.extend(
didInsertElement: function () {
$("[rel=popover]").popover({'placement': 'right', 'trigger': 'hover'});
}
+
});
Added: incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step5_view.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step5_view.js?rev=1390724&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step5_view.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/views/installer/step5_view.js Wed Sep 26 20:59:33 2012
@@ -0,0 +1,67 @@
+/**
+ * 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.InstallerStep5View = Em.View.extend({
+
+ templateName: require('templates/installer/step5'),
+
+ submit: function (e) {
+ App.router.transitionTo('step6');
+ }
+
+});
+
+App.SelectHostView = Em.Select.extend({
+ content: [],
+ zId: null,
+ selectedHost: null,
+ serviceName: null,
+
+ change: function () {
+ App.router.get('installerStep5Controller').assignHostToMaster(this.get("serviceName"), this.get("value"), this.get("zId"));
+ },
+
+ didInsertElement: function () {
+ this.set("value", this.get("selectedHost"));
+ }
+});
+
+App.AddControlView = Em.View.extend({
+ componentName: null,
+ tagName: "span",
+ classNames: ["badge", "badge-important"],
+ template: Ember.Handlebars.compile('+'),
+
+ click: function (event) {
+ App.router.get('installerStep5Controller').addZookeepers();
+ }
+});
+
+App.RemoveControlView = Em.View.extend({
+ zId: null,
+ tagName: "span",
+ classNames: ["badge", "badge-important"],
+ template: Ember.Handlebars.compile('-'),
+
+ click: function (event) {
+ App.router.get('installerStep5Controller').removeZookeepers(this.get("zId"));
+ }
+});
Added: incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step5_test.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step5_test.js?rev=1390724&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step5_test.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step5_test.js Wed Sep 26 20:59:33 2012
@@ -0,0 +1,152 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+require('controllers/installer/step5_controller');
+
+describe('App.InstallerStep5Controller', function () {
+
+ var controller = App.InstallerStep5Controller.create();
+
+ describe('#getAvailableHosts()', function () {
+ it('should generate available hosts for a new zookeeper service', function () {
+ var hostsForNewZookeepers = controller.getAvailableHosts("ZooKeeper"),
+ ok = true, i = 0, masters = null;
+
+ //test that the hosts found, do not have Zookeeper master assigned to them
+ for (i = 0; i < hostsForNewZookeepers.get("length"); i++) {
+ masters = controller.get("selectedServicesMasters").filterProperty(hostsForNewZookeepers[i].get("host_name"));
+ if (masters.findProperty("component_name", "ZooKeeper")) {
+ ok = false;
+ break;
+ }
+ }
+
+ expect(ok).to.equal(true);
+ })
+
+ it('should return all hosts for services other than ZooKeeper', function () {
+ var hostsForNewZookeepers = controller.getAvailableHosts("");
+
+ expect(hostsForNewZookeepers.get("length")).to.equal(controller.get("hosts.length"));
+ })
+ })
+
+ describe('#assignHostToMaster()', function () {
+ it('should assign the selected host to the master service', function () {
+ //test non-zookeeper master
+ var SERVICE_MASTER = "NameNode",
+ HOST = "host4", ZID, status;
+
+ controller.assignHostToMaster(SERVICE_MASTER, HOST);
+ expect(controller.get("selectedServicesMasters").findProperty("component_name", "NameNode").get("selectedHost")).to.equal(HOST);
+ })
+
+ it('should assign the selected host to the ZooKeeper master service', function () {
+ //test non-zookeeper master
+ var SERVICE_MASTER = "ZooKeeper",
+ HOST = "host4", ZID = 2;
+
+ //test zookeeper master assignment with
+ if (controller.addZookeepers()) {
+ controller.assignHostToMaster(SERVICE_MASTER, HOST, ZID);
+ expect(controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").findProperty("zId", ZID).get("selectedHost")).to.equal(HOST);
+ }
+ })
+ })
+
+ describe('#addZookeepers()', function () {
+ it('should add a new ZooKeeper', function () {
+ var newLength = 0;
+ if (controller.get("selectedServices").mapProperty("service_name").contains("ZooKeeper")
+ && controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").get("length") < controller.get("hosts.length")) {
+ newLength = controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").get("length");
+ controller.addZookeepers();
+ expect(controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").get("length")).to.equal(newLength + 1);
+ }
+ })
+
+ it('should add ZooKeepers up to the number of hosts', function () {
+ var currentZooKeepers = controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper"),
+ success = true;
+
+ //add ZooKeepers as long as possible
+ if (currentZooKeepers) {
+ while (success) {
+ success = controller.addZookeepers();
+ }
+
+ expect(controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").get("length")).to.equal(controller.get("hosts.length"));
+ }
+ })
+ })
+
+ describe('#removeZookeepers()', function () {
+ it('should remove a ZooKeeper', function () {
+ var newLength = 0;
+ if (controller.get("selectedServices").mapProperty("service_name").contains("ZooKeeper")) {
+ if (controller.addZookeepers()) {
+ newLength = controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").get("length");
+ controller.removeZookeepers(2);
+ expect(controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").get("length")).to.equal(newLength - 1);
+ }
+ }
+ })
+
+ it('should fail to remove a ZooKeeper if there is only 1', function () {
+ var currentZooKeepers = controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper"),
+ success = true;
+
+ //remove ZooKeepers as long as possible
+ if (currentZooKeepers) {
+ while (success) {
+ success = controller.removeZookeepers(controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").get("lastObject.zId"));
+ }
+
+ expect(controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").get("length")).to.equal(1);
+ }
+ })
+
+ })
+
+ describe('#rebalanceZookeeperHosts()', function () {
+ it('should rebalance hosts for ZooKeeper', function () {
+ //assign a host to a zookeeper and then rebalance the available hosts for the other zookeepers
+ var zookeepers = controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper"),
+ aZookeeper = null, aHost = null, i = 0, ok = true;
+
+ if (zookeepers.get("length") > 1) {
+ aZookeeper = controller.get("selectedServicesMasters").filterProperty("component_name", "ZooKeeper").findProperty("zId", 1);
+ aHost = aZookeeper.get("availableHosts")[0];
+ aZookeeper.set("selectedHost", aHost.get("host_name"));
+
+ controller.rebalanceZookeeperHosts();
+
+ for (i = 0; i < zookeepers.get("length"); i++) {
+ if (zookeepers[i].get("availableHosts").mapProperty("host_name").contains(aHost)) {
+ ok = false;
+ break;
+ }
+ }
+
+ expect(ok).to.equal(true);
+ }
+ })
+ })
+
+})
\ No newline at end of file