Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

AMBARI-1059. Refactor cluster management. (yusaku)

  • Loading branch information...
commit 9b15091e8f0ebae95f513fc27a4bf075bd052eda 1 parent 750bc81
Yusaku Sako authored

Showing 64 changed files with 1,799 additions and 786 deletions. Show diff stats Hide diff stats

  1. +42 14 ambari-web/app/assets/data/apps/runs.json
  2. +65 7 ambari-web/app/assets/data/wizard/bootstrap/single_host_information.json
  3. BIN  ambari-web/app/assets/img/spinner.gif
  4. +3 3 ambari-web/app/controllers/application.js
  5. +52 22 ambari-web/app/controllers/global/background_operations_controller.js
  6. +20 71 ambari-web/app/controllers/installer.js
  7. +15 4 ambari-web/app/controllers/main.js
  8. +12 23 ambari-web/app/controllers/main/host/add_controller.js
  9. +7 18 ambari-web/app/controllers/main/service/add_controller.js
  10. +79 8 ambari-web/app/controllers/wizard.js
  11. +14 0 ambari-web/app/controllers/wizard/slave_component_groups_controller.js
  12. +2 2 ambari-web/app/controllers/wizard/step10_controller.js
  13. +3 19 ambari-web/app/controllers/wizard/step1_controller.js
  14. +71 16 ambari-web/app/controllers/wizard/step2_controller.js
  15. +137 68 ambari-web/app/controllers/wizard/step3_controller.js
  16. +1 0  ambari-web/app/controllers/wizard/step5_controller.js
  17. +41 21 ambari-web/app/controllers/wizard/step7_controller.js
  18. +379 217 ambari-web/app/controllers/wizard/step8_controller.js
  19. +25 32 ambari-web/app/controllers/wizard/step9_controller.js
  20. +2 1  ambari-web/app/data/config_mapping.js
  21. +226 11 ambari-web/app/data/config_properties.js
  22. +9 1 ambari-web/app/data/service_components.js
  23. +1 1  ambari-web/app/data/service_configs.js
  24. +11 11 ambari-web/app/messages.js
  25. +6 3 ambari-web/app/models/hosts.js
  26. +106 0 ambari-web/app/models/service_config.js
  27. +37 2 ambari-web/app/router.js
  28. +14 10 ambari-web/app/routes/add_host_routes.js
  29. +8 7 ambari-web/app/routes/add_service_routes.js
  30. +13 15 ambari-web/app/routes/installer.js
  31. +2 2 ambari-web/app/routes/main.js
  32. +128 14 ambari-web/app/styles/application.less
  33. +5 9 ambari-web/app/templates/application.hbs
  34. +1 1  ambari-web/app/templates/login.hbs
  35. +6 10 ambari-web/app/templates/main.hbs
  36. +29 23 ambari-web/app/templates/main/background_operations_popup.hbs
  37. +6 2 ambari-web/app/templates/main/charts/linear_time.hbs
  38. +1 1  ambari-web/app/templates/main/dashboard/service/hive.hbs
  39. +2 1  ambari-web/app/templates/main/dashboard/service/oozie.hbs
  40. +2 1  ambari-web/app/templates/main/dashboard/service/zookeeper.hbs
  41. +2 2 ambari-web/app/templates/main/service/info/configs.hbs
  42. +2 0  ambari-web/app/templates/main/service/info/summary.hbs
  43. +13 12 ambari-web/app/templates/wizard/step2.hbs
  44. +14 11 ambari-web/app/templates/wizard/step3.hbs
  45. +2 2 ambari-web/app/templates/wizard/step7.hbs
  46. +6 3 ambari-web/app/utils/data_table.js
  47. +15 17 ambari-web/app/utils/db.js
  48. +2 1  ambari-web/app/utils/graph.js
  49. +24 16 ambari-web/app/utils/helper.js
  50. +60 26 ambari-web/app/views/common/chart/linear_time.js
  51. +10 1 ambari-web/app/views/common/modal_popup.js
  52. +6 0 ambari-web/app/views/login.js
  53. +19 2 ambari-web/app/views/main.js
  54. +8 1 ambari-web/app/views/main/dashboard/cluster_metrics/cpu.js
  55. +2 5 ambari-web/app/views/main/host.js
  56. +9 1 ambari-web/app/views/main/host/metrics/cpu.js
  57. +1 1  ambari-web/app/views/main/menu.js
  58. +1 1  ambari-web/app/views/main/service/info/metrics/mapreduce/jvm_heap.js
  59. +1 1  ambari-web/app/views/main/service/info/metrics/mapreduce/jvm_threads.js
  60. +7 1 ambari-web/app/views/main/service/info/summary.js
  61. +3 3 ambari-web/app/views/main/service/item.js
  62. +2 1  ambari-web/app/views/wizard/step1_view.js
  63. +6 6 ambari-web/app/views/wizard/step2_view.js
  64. +1 1  ambari-web/app/views/wizard/step9_view.js
56 ambari-web/app/assets/data/apps/runs.json
@@ -53,7 +53,9 @@
53 53 }
54 54 },
55 55 "workflowId": "hive_7c779523-6bca-416e-89b3-b01b73a60174",
56   - "workflowName": "script1-hadoop.pig"
  56 + "workflowName": "script1-hadoop.pig",
  57 + "inputBytes": 473423,
  58 + "outputBytes": 82434
57 59 },
58 60 {
59 61 "elapsedTime": 910360,
@@ -84,7 +86,9 @@
84 86 }
85 87 },
86 88 "workflowId": "pig_5750f4cf-f0d2-4e3d-a7ce-90912b309c12",
87   - "workflowName": "script1-hadoop.pig"
  89 + "workflowName": "script1-hadoop.pig",
  90 + "inputBytes": 923423,
  91 + "outputBytes": 32434
88 92 },
89 93 {
90 94 "elapsedTime": 920579,
@@ -115,7 +119,9 @@
115 119 }
116 120 },
117 121 "workflowId": "mr_25547729-88f9-4287-a45a-64901a82f22b",
118   - "workflowName": "script1-hadoop.pig"
  122 + "workflowName": "script1-hadoop.pig",
  123 + "inputBytes": 623423,
  124 + "outputBytes": 42434
119 125 },
120 126 {
121 127 "elapsedTime": 687631,
@@ -138,7 +144,9 @@
138 144 }
139 145 },
140 146 "workflowId": "hive_a5b9c06f-96d2-4ea8-80e0-3c063ae831d4",
141   - "workflowName": "script2-hadoop.pig"
  147 + "workflowName": "script2-hadoop.pig",
  148 + "inputBytes": 483423,
  149 + "outputBytes": 82434
142 150 },
143 151 {
144 152 "elapsedTime": 905375,
@@ -169,7 +177,9 @@
169 177 }
170 178 },
171 179 "workflowId": "pig_90ac94ff-20c4-4637-8b1c-51379cfe10df",
172   - "workflowName": "script1-hadoop.pig"
  180 + "workflowName": "script1-hadoop.pig",
  181 + "inputBytes": 428423,
  182 + "outputBytes": 32434
173 183 },
174 184 {
175 185 "elapsedTime": 683055,
@@ -192,7 +202,9 @@
192 202 }
193 203 },
194 204 "workflowId": "hive_c832f923-9bd4-421f-9a51-8f45991d91de",
195   - "workflowName": "script2-hadoop.pig"
  205 + "workflowName": "script2-hadoop.pig",
  206 + "inputBytes": 723423,
  207 + "outputBytes": 62434
196 208 },
197 209 {
198 210 "elapsedTime": 35150977,
@@ -223,7 +235,9 @@
223 235 }
224 236 },
225 237 "workflowId": "mr_a0aade31-47f8-475b-b887-60a79bcea5c4",
226   - "workflowName": "script1-hadoop.pig"
  238 + "workflowName": "script1-hadoop.pig",
  239 + "inputBytes": 463423,
  240 + "outputBytes": 57434
227 241 },
228 242 {
229 243 "elapsedTime": 888790,
@@ -254,7 +268,9 @@
254 268 }
255 269 },
256 270 "workflowId": "pig_b4365f79-18da-4db6-bbfd-e8a850d6c6e8",
257   - "workflowName": "script1-hadoop.pig"
  271 + "workflowName": "script1-hadoop.pig",
  272 + "inputBytes": 723423,
  273 + "outputBytes": 82434
258 274 },
259 275 {
260 276 "elapsedTime": 902653,
@@ -285,7 +301,9 @@
285 301 }
286 302 },
287 303 "workflowId": "hive_b6bf29a4-324f-4435-8ed3-bee10622ea48",
288   - "workflowName": "script1-hadoop.pig"
  304 + "workflowName": "script1-hadoop.pig",
  305 + "inputBytes": 923423,
  306 + "outputBytes": 52434
289 307 },
290 308 {
291 309 "elapsedTime": 884834,
@@ -316,7 +334,9 @@
316 334 }
317 335 },
318 336 "workflowId": "pig_a6a6fb32-b3fd-4427-ab54-449d0895fbb2",
319   - "workflowName": "script1-hadoop.pig"
  337 + "workflowName": "script1-hadoop.pig",
  338 + "inputBytes": 403423,
  339 + "outputBytes": 82434
320 340 },
321 341 {
322 342 "elapsedTime": 674392,
@@ -339,7 +359,9 @@
339 359 }
340 360 },
341 361 "workflowId": "pig_f69499b1-a504-433e-8904-0760deb5a183",
342   - "workflowName": "script2-hadoop.pig"
  362 + "workflowName": "script2-hadoop.pig",
  363 + "inputBytes": 423123,
  364 + "outputBytes": 52434
343 365 },
344 366 {
345 367 "elapsedTime": 926853,
@@ -370,7 +392,9 @@
370 392 }
371 393 },
372 394 "workflowId": "mr_73e04732-ea7f-43b8-9a2f-0f5a30e665da",
373   - "workflowName": "script1-hadoop.pig"
  395 + "workflowName": "script1-hadoop.pig",
  396 + "inputBytes": 523423,
  397 + "outputBytes": 92434
374 398 },
375 399 {
376 400 "elapsedTime": 0,
@@ -401,7 +425,9 @@
401 425 }
402 426 },
403 427 "workflowId": "pig_31b2111b-cc2e-4024-a8db-d181855a463f",
404   - "workflowName": "script1-hadoop.pig"
  428 + "workflowName": "script1-hadoop.pig",
  429 + "inputBytes": 443423,
  430 + "outputBytes": 32434
405 431 },
406 432 {
407 433 "elapsedTime": 670929,
@@ -424,6 +450,8 @@
424 450 }
425 451 },
426 452 "workflowId": "hive_097d0698-3620-4232-9c79-4deccbf6c98a",
427   - "workflowName": "script2-hadoop.pig"
  453 + "workflowName": "script2-hadoop.pig",
  454 + "inputBytes": 428423,
  455 + "outputBytes": 18434
428 456 }
429 457 ]}
72 ambari-web/app/assets/data/wizard/bootstrap/single_host_information.json
... ... @@ -1,12 +1,70 @@
1 1 {
2   - "href" : "http://localhost:8080/api/v1/hosts?fields=Hosts/total_mem,Hosts/cpu_count",
3   - "items" : [
  2 + "href": "http://localhost:8080/api/v1/hosts?fields=Hosts/total_mem,Hosts/cpu_count",
  3 + "items": [
4 4 {
5   - "href" : "http://localhost:8080/api/v1/hosts/localhost.localdomain",
6   - "Hosts" : {
7   - "cpu_count" : 1,
8   - "total_mem" : 4057989,
9   - "host_name" : "localhost.localdomain"
  5 + "href": "http://localhost:8080/api/v1/hosts/localhost.localdomain",
  6 + "Hosts": {
  7 + "cpu_count": 1,
  8 + "total_mem": 4057989,
  9 + "host_name": "localhost.localdomain",
  10 + "disk_info": [
  11 + {
  12 + "available": "47574176",
  13 + "used": "3507828",
  14 + "percent": "7%",
  15 + "size": "51606140",
  16 + "type": "ext4",
  17 + "mountpoint": "/"
  18 + },
  19 + {
  20 + "available": "47574176",
  21 + "used": "3507828",
  22 + "percent": "7%",
  23 + "size": "51606140",
  24 + "type": "ext4",
  25 + "mountpoint": "/grid/0"
  26 + },
  27 + {
  28 + "available": "1027204",
  29 + "used": "260",
  30 + "percent": "1%",
  31 + "size": "1027464",
  32 + "type": "tmpfs",
  33 + "mountpoint": "/dev/shm"
  34 + },
  35 + {
  36 + "available": "432210",
  37 + "used": "38034",
  38 + "percent": "9%",
  39 + "size": "495844",
  40 + "type": "ext4",
  41 + "mountpoint": "/boot"
  42 + },
  43 + {
  44 + "available": "44459872",
  45 + "used": "184220",
  46 + "percent": "1%",
  47 + "size": "47033288",
  48 + "type": "ext4",
  49 + "mountpoint": "/home"
  50 + },
  51 + {
  52 + "available": "450200708",
  53 + "used": "281534268",
  54 + "percent": "39%",
  55 + "size": "731734976",
  56 + "type": "vboxsf",
  57 + "mountpoint": "/media/sf_ambari"
  58 + },
  59 + {
  60 + "available": "450200708",
  61 + "used": "281534268",
  62 + "percent": "39%",
  63 + "size": "731734976",
  64 + "type": "vboxsf",
  65 + "mountpoint": "/host"
  66 + }
  67 + ]
10 68 }
11 69 }
12 70 ]
BIN  ambari-web/app/assets/img/spinner.gif
6 ambari-web/app/controllers/application.js
@@ -23,12 +23,12 @@ App.ApplicationController = Em.Controller.extend({
23 23
24 24 name: 'applicationController',
25 25 clusterName: function () {
26   - var name = App.db.getClusterName();
  26 + var name = App.router.get('clusterController.clusterName');
27 27 if (name) {
28 28 return name.capitalize();
29 29 }
30   - return '';
31   - }.property(),
  30 + return Em.I18n.t('installer.header');
  31 + }.property('App.router.clusterController.clusterName'),
32 32 isClusterDataLoaded: function() {
33 33 return App.router.get('clusterController.isLoaded');
34 34 }.property('App.router.clusterController.isLoaded'),
74 ambari-web/app/controllers/global/background_operations_controller.js
@@ -28,6 +28,11 @@ App.BackgroundOperationsController = Em.Controller.extend({
28 28
29 29 allOperations: [],
30 30 allOperationsCount : 0,
  31 + executeTasks: [],
  32 +
  33 + getTasksByRole: function (role) {
  34 + return this.get('allOperations').filterProperty('role', role);
  35 + },
31 36
32 37 getOperationsForRequestId: function(requestId){
33 38 return this.get('allOperations').filterProperty('request_id', requestId);
@@ -129,45 +134,69 @@ App.BackgroundOperationsController = Em.Controller.extend({
129 134 }.observes('isWorking'),
130 135
131 136 /**
132   - * Add new operations to <code>this.allOperations</code> variable
  137 + * Update info about background operations
  138 + * Put all tasks with command 'EXECUTE' into <code>executeTasks</code>, other tasks with it they are still running put into <code>runningTasks</code>
  139 + * Put all task that should be shown in popup modal window into <code>this.allOperations</code>
133 140 * @param data json loaded from server
134 141 */
135   - updateBackgroundOperations : function(data){
  142 + updateBackgroundOperations: function (data) {
136 143 var runningTasks = [];
  144 + var executeTasks = this.get('executeTasks');
137 145 data.items.forEach(function (item) {
138 146 item.tasks.forEach(function (task) {
139   - if (task.Tasks.status == 'QUEUED' || task.Tasks.status == 'PENDING') {
140   - runningTasks.push(task.Tasks);
  147 + if (task.Tasks.command == 'EXECUTE') {
  148 + if (!executeTasks.someProperty('id', task.Tasks.id)) {
  149 + executeTasks.push(task.Tasks);
  150 + }
  151 + } else {
  152 + if (task.Tasks.status == 'QUEUED' || task.Tasks.status == 'PENDING' || task.Tasks.status == 'IN_PROGRESS') {
  153 + runningTasks.push(task.Tasks);
  154 + }
141 155 }
142 156 });
143 157 });
144 158
145   - runningTasks = runningTasks.sort(function(a,b){
  159 + for (var i = 0; i < executeTasks.length; i++) {
  160 + if (executeTasks[i].status == 'QUEUED' || executeTasks[i].status == 'PENDING' || executeTasks[i].status == 'IN_PROGRESS') {
  161 + var url = App.testMode ? '/data/background_operations/list_on_start.json' :
  162 + App.apiPrefix + '/clusters/' + App.router.getClusterName() + '/requests/' + executeTasks[i].request_id + '/tasks/' + executeTasks[i].id;
  163 + var j = i;
  164 + $.ajax({
  165 + type: "GET",
  166 + url: url,
  167 + dataType: 'json',
  168 + timeout: App.timeout,
  169 + success: function (data) {
  170 + if (data) {
  171 + executeTasks[j] = data.Tasks;
  172 + }
  173 + },
  174 + error: function () {
  175 + console.log('ERROR: error during executeTask update');
  176 + },
  177 +
  178 + statusCode: require('data/statusCodes')
  179 + });
  180 + }
  181 + }
  182 + ;
  183 + var currentTasks;
  184 + currentTasks = runningTasks.concat(executeTasks);
  185 + currentTasks = currentTasks.sort(function (a, b) {
146 186 return a.id - b.id;
147 187 });
148 188
149   - var currentTasks = this.get('allOperations');
150   -
151   - runningTasks.forEach(function(item){
152   - var task = currentTasks.findProperty('id', item.id);
153   - if(task){
154   - currentTasks[currentTasks.indexOf(task)] = item;
155   - } else {
156   - currentTasks.pushObject(item);
  189 + this.get('allOperations').filterProperty('isOpen').mapProperty('id').forEach(function(id){
  190 + if (currentTasks.someProperty('id', id)) {
  191 + currentTasks.findProperty('id', id).isOpen = true;
157 192 }
158 193 });
159 194
160   - for(var i = currentTasks.length-1; i>=0; i--){
161   - var isTaskFinished = !runningTasks.someProperty('id', currentTasks[i].id);
162   - if(isTaskFinished){
163   - currentTasks.removeAt(i);
164   - }
165   - }
166   -
167   - this.set('allOperationsCount', currentTasks.length);
  195 + this.set('allOperations', currentTasks);
  196 + this.set('allOperationsCount', runningTasks.length + executeTasks.filterProperty('status', 'PENDING').length + executeTasks.filterProperty('status', 'QUEUED').length + executeTasks.filterProperty('status', 'IN_PROGRESS').length);
168 197
169 198 var eventsArray = this.get('eventsArray');
170   - if(eventsArray.length){
  199 + if (eventsArray.length) {
171 200
172 201 var itemsToRemove = [];
173 202 eventsArray.forEach(function(item){
@@ -190,6 +219,7 @@ App.BackgroundOperationsController = Em.Controller.extend({
190 219 * Onclick handler for background operations number located right to logo
191 220 */
192 221 showPopup: function(){
  222 + this.set('executeTasks', []);
193 223 this.loadOperations();
194 224 App.ModalPopup.show({
195 225 headerClass: Ember.View.extend({
91 ambari-web/app/controllers/installer.js
@@ -38,38 +38,8 @@ App.InstallerController = App.WizardController.extend({
38 38 controllerName: 'installerController'
39 39 }),
40 40
41   - /**
42   - * Load clusterInfo(step1) to model
43   - */
44   - loadClusterInfo: function () {
45   - var cStatus = App.db.getClusterStatus() || {status: "", isCompleted: false};
46   - var cluster = {
47   - name: App.db.getClusterName() || "",
48   - status: cStatus.status,
49   - isCompleted: cStatus.isCompleted,
50   - requestId: cStatus.requestId,
51   - installStartTime: cStatus.installStartTime,
52   - installTime: cStatus.installTime
53   - };
54   - this.set('content.cluster', cluster);
55   -
56   - console.log("InstallerController:loadClusterInfo: loaded data ", cluster);
57   - },
58   -
59   - /**
60   - * Save all info about cluster to model
61   - * @param stepController Step1WizardController
62   - */
63   - saveClusterInfo: function (stepController) {
64   - var cluster = stepController.get('content.cluster');
65   - var clusterStatus = {
66   - status: cluster.status,
67   - isCompleted: cluster.isCompleted
68   - };
69   - App.db.setClusterName(cluster.name);
70   - App.db.setClusterStatus(clusterStatus);
71   -
72   - console.log("InstallerController:saveClusterInfo: saved data ", cluster);
  41 + getCluster: function(){
  42 + return jQuery.extend(this.get('clusterStatusTemplate'), {});
73 43 },
74 44
75 45 /**
@@ -95,7 +65,7 @@ App.InstallerController = App.WizardController.extend({
95 65 //TODO : rewire it as model. or not :)
96 66 var hostsInfo = Em.Object.create();
97 67
98   - hostsInfo.hostNames = App.db.getAllHostNames() || ''; //empty string if undefined
  68 + hostsInfo.hostNames = App.db.getAllHostNamesPattern() || ''; //empty string if undefined
99 69
100 70 //TODO : should we check installType for add host wizard????
101 71 var installType = App.db.getInstallType();
@@ -128,7 +98,8 @@ App.InstallerController = App.WizardController.extend({
128 98 //TODO: put data to content.hosts and only then save it)
129 99
130 100 //App.db.setBootStatus(false);
131   - App.db.setAllHostNames(stepController.get('hostNames'));
  101 + App.db.setAllHostNames(stepController.get('hostNameArr').join("\n"));
  102 + App.db.setAllHostNamesPattern(stepController.get('hostNames'));
132 103 App.db.setBootRequestId(stepController.get('bootRequestId'));
133 104 App.db.setHosts(stepController.getHostInfo());
134 105 if (stepController.get('manualInstall') === false) {
@@ -164,6 +135,7 @@ App.InstallerController = App.WizardController.extend({
164 135 name: _host.name,
165 136 cpu: _host.cpu,
166 137 memory: _host.memory,
  138 + disk_info: _host.disk_info,
167 139 bootStatus: _host.bootStatus,
168 140 isInstalled: false
169 141 };
@@ -361,7 +333,7 @@ App.InstallerController = App.WizardController.extend({
361 333 _content.get('configs').forEach(function (_configProperties) {
362 334 var displayType = _configProperties.get('displayType');
363 335 if (displayType === 'directories' || displayType === 'directory') {
364   - var value = _configProperties.get('value').split(/\s+/g).join(',');
  336 + var value = _configProperties.get('value').trim().split(/\s+/g).join(',');
365 337 _configProperties.set('value', value);
366 338 }
367 339 var configProperty = {
@@ -370,6 +342,7 @@ App.InstallerController = App.WizardController.extend({
370 342 value: _configProperties.get('value'),
371 343 defaultValue: _configProperties.get('defaultValue'),
372 344 service: _configProperties.get('serviceName'),
  345 + domain: _configProperties.get('domain'),
373 346 filename: _configProperties.get('filename')
374 347 };
375 348 serviceConfigProperties.push(configProperty);
@@ -386,12 +359,17 @@ App.InstallerController = App.WizardController.extend({
386 359 var slaveCategory = _content.get('configCategories').findProperty('isForSlaveComponent', true);
387 360 slaveCategory.get('slaveConfigs.groups').forEach(function (_group) {
388 361 _group.get('properties').forEach(function (_property) {
  362 + var displayType = _property.get('displayType');
  363 + if (displayType === 'directories' || displayType === 'directory') {
  364 + var value = _property.get('value').trim().split(/\s+/g).join(',');
  365 + _property.set('value', value);
  366 + }
389 367 _property.set('storeValue', _property.get('value'));
390 368 }, this);
391 369 }, this);
392 370 slaveConfigProperties.pushObject(slaveCategory.get('slaveConfigs'));
393 371 }
394   - }, this)
  372 + }, this);
395 373 App.db.setSlaveProperties(slaveConfigProperties);
396 374 this.set('content.slaveGroupProperties', slaveConfigProperties);
397 375 },
@@ -492,7 +470,7 @@ App.InstallerController = App.WizardController.extend({
492 470 case '2':
493 471 this.loadInstallOptions();
494 472 case '1':
495   - this.loadClusterInfo();
  473 + this.load('cluster');
496 474 }
497 475 },
498 476
@@ -609,49 +587,20 @@ App.InstallerController = App.WizardController.extend({
609 587 return serviceComponents;
610 588 },
611 589
612   -
613   - /*
614   - Bootstrap selected hosts.
615   - */
616   - launchBootstrap: function (bootStrapData) {
617   - var self = this;
618   - var requestId = null;
619   - var method = App.testMode ? 'GET' : 'POST';
620   - var url = App.testMode ? '/data/wizard/bootstrap/bootstrap.json' : App.apiPrefix + '/bootstrap';
621   - $.ajax({
622   - type: method,
623   - url: url,
624   - async: false,
625   - data: bootStrapData,
626   - timeout: App.timeout,
627   - contentType: 'application/json',
628   - success: function (data) {
629   - console.log("TRACE: POST bootstrap succeeded");
630   - requestId = data.requestId;
631   - },
632   - error: function () {
633   - console.log("ERROR: POST bootstrap failed");
634   - alert('Bootstrap call failed. Please try again.');
635   - },
636   - statusCode: require('data/statusCodes')
637   - });
638   - return requestId;
639   - },
640   -
641   -
642 590 /**
643 591 * Clear all temporary data
644 592 */
645 593 finish: function () {
646   - this.setCurrentStep('1', false);
  594 + this.setCurrentStep('1');
647 595 App.db.setService(undefined); //not to use this data at AddService page
648 596 App.db.setHosts(undefined);
649 597 App.db.setMasterComponentHosts(undefined);
650 598 App.db.setSlaveComponentHosts(undefined);
651   - App.db.setClusterStatus(undefined);
  599 + App.db.setCluster(undefined);
652 600 App.db.setAllHostNames(undefined);
  601 + App.db.setSlaveProperties(undefined);
  602 + App.db.setSshKey(undefined);
653 603 }
654 604
655   -})
656   -;
  605 +});
657 606
19 ambari-web/app/controllers/main.js
@@ -22,13 +22,25 @@ require('models/background_operation');
22 22 App.MainController = Em.Controller.extend({
23 23 name: 'mainController',
24 24 clusterName: function () {
25   - var name = App.db.getClusterName();
  25 + var name = App.router.get('clusterController.clusterName');
26 26 if (name) {
27 27 var displayName = name.length > 13 ? name.substr(0, 10) + "..." : name;
28 28 return displayName.capitalize();
29 29 }
30   - return '';
31   - }.property(),
  30 + return 'My Cluster';
  31 + }.property('App.router.clusterController.clusterName'),
  32 +
  33 + updateTitle: function(){
  34 + var name = App.router.get('clusterController.clusterName');
  35 + if (name) {
  36 + name = name.length > 13 ? name.substr(0, 10) + "..." : name;
  37 + name = name.capitalize();
  38 + } else{
  39 + name = 'Loading';
  40 + }
  41 + $('title').text('Ambari - ' + name);
  42 + }.observes('App.router.clusterController.clusterName'),
  43 +
32 44 isClusterDataLoaded: function(){
33 45 return App.router.get('clusterController.isLoaded');
34 46 }.property('App.router.clusterController.isLoaded'),
@@ -40,7 +52,6 @@ App.MainController = Em.Controller.extend({
40 52 App.router.get('clusterController').loadClusterData();
41 53 App.router.get('updateController').updateServiceMetric();
42 54 setInterval( this.updateAll , App.contentUpdateInterval);
43   - $('title').text('Ambari - ' + this.get('clusterName'));
44 55 },
45 56 updateAll: function(){
46 57 App.router.get('updateController').updateAll();
35 ambari-web/app/controllers/main/host/add_controller.js
@@ -54,24 +54,10 @@ App.AddHostController = App.WizardController.extend({
54 54 isWizard: true
55 55 }),
56 56
57   - /**
58   - * Load clusterInfo(step1) to model
59   - */
60   - loadClusterInfo: function () {
61   - var cluster = App.db.getClusterStatus();
62   - if (!cluster) {
63   - cluster = {
64   - name: App.router.getClusterName(),
65   - status: undefined,
66   - isCompleted: false,
67   - requestId: undefined,
68   - installStartTime: undefined,
69   - installTime: undefined
70   - };
71   - App.db.setClusterStatus(cluster);
72   - }
73   - this.set('content.cluster', cluster);
74   - console.log("AddHostController:loadClusterInfo: loaded data ", cluster);
  57 + getCluster: function(){
  58 + return jQuery.extend(this.get('clusterStatusTemplate'), {
  59 + name: App.router.getClusterName()
  60 + });
75 61 },
76 62
77 63 showMoreHosts: function () {
@@ -149,7 +135,7 @@ App.AddHostController = App.WizardController.extend({
149 135 hostsInfo.showMoreHostsText = "...and %@ more".fmt(moreHostNames.length);
150 136 }
151 137
152   - hostsInfo.hostNames = App.db.getAllHostNames() || ''; //empty string if undefined
  138 + hostsInfo.hostNames = App.db.getAllHostNamesPattern() || ''; //empty string if undefined
153 139
154 140 var installType = App.db.getInstallType();
155 141 //false if installType not equals 'manual'
@@ -164,6 +150,7 @@ App.AddHostController = App.WizardController.extend({
164 150 hostsInfo.localRepoPath = '';
165 151 }
166 152
  153 + hostsInfo.bootRequestId = App.db.getBootRequestId() || null;
167 154 hostsInfo.sshKey = '';
168 155 hostsInfo.passphrase = '';
169 156 hostsInfo.confirmPassphrase = '';
@@ -180,7 +167,9 @@ App.AddHostController = App.WizardController.extend({
180 167 //TODO: put data to content.hosts and only then save it)
181 168
182 169 //App.db.setBootStatus(false);
183   - App.db.setAllHostNames(stepController.get('hostNames'));
  170 + App.db.setAllHostNames(stepController.get('hostNameArr').join("\n"));
  171 + App.db.setAllHostNamesPattern(stepController.get('hostNames'));
  172 + App.db.setBootRequestId(stepController.get('bootRequestId'));
184 173 App.db.setHosts(stepController.getHostInfo());
185 174 if (stepController.get('manualInstall') === false) {
186 175 App.db.setInstallType({installType: 'ambari' });
@@ -559,7 +548,7 @@ App.AddHostController = App.WizardController.extend({
559 548 case '1':
560 549 this.loadInstallOptions();
561 550 case '0':
562   - this.loadClusterInfo();
  551 + this.load('cluster');
563 552 }
564 553 },
565 554
@@ -625,12 +614,12 @@ App.AddHostController = App.WizardController.extend({
625 614 * Clear all temporary data
626 615 */
627 616 finish: function () {
628   - this.setCurrentStep('1', false);
  617 + this.setCurrentStep('1');
629 618 App.db.setService(undefined); //not to use this data at AddService page
630 619 App.db.setHosts(undefined);
631 620 App.db.setMasterComponentHosts(undefined);
632 621 App.db.setSlaveComponentHosts(undefined);
633   - App.db.setClusterStatus(undefined);
  622 + App.db.setCluster(undefined);
634 623 App.router.get('updateController').updateAll();
635 624 }
636 625
25 ambari-web/app/controllers/main/service/add_controller.js
@@ -54,21 +54,10 @@ App.AddServiceController = App.WizardController.extend({
54 54 isWizard: true
55 55 }),
56 56
57   - /**
58   - * Load clusterInfo(step1) to model
59   - */
60   - loadClusterInfo: function(){
61   - var cluster = App.db.getClusterStatus();
62   - if(!cluster){
63   - cluster = {
64   - name: App.router.getClusterName(),
65   - status: "",
66   - isCompleted: false
67   - };
68   - App.db.setClusterStatus(cluster);
69   - }
70   - this.set('content.cluster', cluster);
71   - console.log("AddServiceController:loadClusterInfo: loaded data ", cluster);
  57 + getCluster: function(){
  58 + return jQuery.extend(this.get('clusterStatusTemplate'), {
  59 + name: App.router.getClusterName()
  60 + });
72 61 },
73 62
74 63 /**
@@ -462,7 +451,7 @@ App.AddServiceController = App.WizardController.extend({
462 451 case '7':
463 452 case '6':
464 453 case '5':
465   - this.loadClusterInfo();
  454 + this.load('cluster');
466 455 case '4':
467 456 this.loadServiceConfigProperties();
468 457 case '3':
@@ -539,12 +528,12 @@ App.AddServiceController = App.WizardController.extend({
539 528 * Clear all temporary data
540 529 */
541 530 finish: function(){
542   - this.setCurrentStep('1', false);
  531 + this.setCurrentStep('1');
543 532 App.db.setService(undefined); //not to use this data at AddService page
544 533 App.db.setHosts(undefined);
545 534 App.db.setMasterComponentHosts(undefined);
546 535 App.db.setSlaveComponentHosts(undefined);
547   - App.db.setClusterStatus(undefined);
  536 + App.db.setCluster(undefined);
548 537 App.db.setAllHostNames(undefined);
549 538 }
550 539
87 ambari-web/app/controllers/wizard.js
@@ -220,15 +220,29 @@ App.WizardController = Em.Controller.extend({
220 220 App.db.setAllHostNames(null);
221 221 },
222 222
  223 + toObject: function(object){
  224 + var result = {};
  225 + for(var i in object){
  226 + if(object.hasOwnProperty(i)){
  227 + result[i] = object[i];
  228 + }
  229 + }
  230 + return result;
  231 + },
  232 +
223 233 /**
224 234 * save status of the cluster. This is called from step8 and step9 to persist install and start requestId
225 235 * @param clusterStatus object with status, isCompleted, requestId, isInstallError and isStartError field.
226 236 */
227 237 saveClusterStatus: function (clusterStatus) {
228   - clusterStatus.name = this.get('content.cluster.name');
  238 + var oldStatus = this.toObject(this.get('content.cluster'));
  239 + clusterStatus = jQuery.extend(oldStatus, clusterStatus);
  240 + if(clusterStatus.requestId &&
  241 + clusterStatus.oldRequestsId.indexOf(clusterStatus.requestId) === -1){
  242 + clusterStatus.oldRequestsId.push(clusterStatus.requestId);
  243 + }
229 244 this.set('content.cluster', clusterStatus);
230   - console.log(this.get('name') + '.saveClusterStatus: ' + JSON.stringify(clusterStatus));
231   - App.db.setClusterStatus(clusterStatus);
  245 + this.save('cluster');
232 246 },
233 247
234 248 /**
@@ -242,7 +256,7 @@ App.WizardController = Em.Controller.extend({
242 256
243 257 var self = this;
244 258 var clusterName = this.get('content.cluster.name');
245   - var url = (App.testMode) ? '/data/wizard/deploy/poll_1.json' : App.apiPrefix + '/clusters/' + clusterName + '/services?ServiceInfo/state=INIT';
  259 + var url = (App.testMode) ? '/data/wizard/deploy/2_hosts/poll_1.json' : App.apiPrefix + '/clusters/' + clusterName + '/services?ServiceInfo/state=INIT';
246 260 var method = (App.testMode) ? 'GET' : 'PUT';
247 261 var data = '{"ServiceInfo": {"state": "INSTALLED"}}';
248 262 $.ajax({
@@ -258,7 +272,7 @@ App.WizardController = Em.Controller.extend({
258 272 console.log("TRACE: In success function for the installService call");
259 273 console.log("TRACE: value of the url is: " + url);
260 274 if (jsonData) {
261   - var requestId = jsonData.href.match(/.*\/(.*)$/)[1];
  275 + var requestId = jsonData.Requests.id;
262 276 console.log('requestId is: ' + requestId);
263 277 var clusterStatus = {
264 278 status: 'PENDING',
@@ -292,13 +306,70 @@ App.WizardController = Em.Controller.extend({
292 306
293 307 },
294 308
  309 + /*
  310 + Bootstrap selected hosts.
  311 + */
  312 + launchBootstrap: function (bootStrapData) {
  313 + var self = this;
  314 + var requestId = null;
  315 + var method = App.testMode ? 'GET' : 'POST';
  316 + var url = App.testMode ? '/data/wizard/bootstrap/bootstrap.json' : App.apiPrefix + '/bootstrap';
  317 + $.ajax({
  318 + type: method,
  319 + url: url,
  320 + async: false,
  321 + data: bootStrapData,
  322 + timeout: App.timeout,
  323 + contentType: 'application/json',
  324 + success: function (data) {
  325 + console.log("TRACE: POST bootstrap succeeded");
  326 + requestId = data.requestId;
  327 + },
  328 + error: function () {
  329 + console.log("ERROR: POST bootstrap failed");
  330 + alert('Bootstrap call failed. Please try again.');
  331 + },
  332 + statusCode: require('data/statusCodes')
  333 + });
  334 + return requestId;
  335 + },
  336 +
  337 + /**
  338 + * Load <code>content.<name></code> variable from localStorage, if wasn't loaded before.
  339 + * If you specify <code>reload</code> to true - it will reload it.
  340 + * @param name
  341 + * @param reload
  342 + * @return {Boolean}
  343 + */
295 344 load: function (name, reload) {
296 345 if (this.get('content.' + name) && !reload) {
297 346 return false;
298 347 }
299   - var result = App.db['get' + name.capitalize()];
300   - if (!result) result = this['get' + name.capitalize()];
  348 + var result = App.db['get' + name.capitalize()]();
  349 + if (!result){
  350 + result = this['get' + name.capitalize()]();
  351 + App.db['set' + name.capitalize()](result);
  352 + console.log(this.get('name') + ": created " + name, result);
  353 + }
301 354 this.set('content.' + name, result);
302   - console.log("Installer controller: loaded" + name, result);
  355 + console.log(this.get('name') + ": loaded " + name, result);
  356 + },
  357 +
  358 + save: function(name){
  359 + var value = this.toObject(this.get('content.' + name));
  360 + App.db['set' + name.capitalize()](value);
  361 + console.log(this.get('name') + ": saved " + name, value);
  362 + },
  363 +
  364 + clusterStatusTemplate : {
  365 + name: "",
  366 + status: "PENDING",
  367 + isCompleted: false,
  368 + requestId: null,
  369 + installStartTime: null,
  370 + installTime: null,
  371 + isInstallError: false,
  372 + isStartError: false,
  373 + oldRequestsId: []
303 374 }
304 375 })
14 ambari-web/app/controllers/wizard/slave_component_groups_controller.js
@@ -47,10 +47,14 @@ App.SlaveComponentGroupsController = Em.ArrayController.extend({
47 47 var categoryConfig = _serviceConfig.get('configCategories');
48 48 if (categoryConfig.someProperty('isForSlaveComponent', true)) {
49 49 var slaveCategory = categoryConfig.findProperty('isForSlaveComponent', true);
  50 + // this.get('content') -> Output of Step 6: Mapping of each slave component and set of hosts it runs on
50 51 if (this.get('content')) {
51 52 if (this.get('content').someProperty('componentName', slaveCategory.get('primaryName'))) {
  53 + // component --> each column in Step 6 is a component ( slave component )
52 54 var component = this.get('content').findProperty('componentName', slaveCategory.get('primaryName'));
  55 + // slaveConfigs --> originally set as null in the class App.SlaveCategory in model/service_config.js
53 56 var slaveConfigs = slaveCategory.get('slaveConfigs');
  57 +
54 58 slaveCategory.set('slaveConfigs', App.SlaveConfigs.create(component));
55 59 var slaveGroups = [];
56 60 if (component.groups) {
@@ -77,6 +81,7 @@ App.SlaveComponentGroupsController = Em.ArrayController.extend({
77 81 }, this);
78 82 },
79 83
  84 + // returns key-value pairs i.e. all fields for slave component for this specific service.
80 85 componentProperties: function (serviceName) {
81 86
82 87 var serviceConfigs = require('data/service_configs').findProperty('serviceName', serviceName);
@@ -96,6 +101,15 @@ App.SlaveComponentGroupsController = Em.ArrayController.extend({
96 101 var slaveConfigs = serviceConfigs.configs.filterProperty('category', componentName);
97 102 slaveConfigs.forEach(function (_serviceConfigProperty) {
98 103 var serviceConfigProperty = App.ServiceConfigProperty.create(_serviceConfigProperty);
  104 +
  105 + switch(serviceConfigProperty.name){
  106 + case 'dfs_data_dir' :
  107 + serviceConfigProperty.initialValue();
  108 + break;
  109 + case 'mapred_local_dir' :
  110 + serviceConfigProperty.initialValue();
  111 + break;
  112 + }
99 113 configs.pushObject(serviceConfigProperty);
100 114 serviceConfigProperty.validate();
101 115 }, this);
4 ambari-web/app/controllers/wizard/step10_controller.js
@@ -115,11 +115,11 @@ App.WizardStep10Controller = Em.Controller.extend({
115 115
116 116 var timedOutTasks = _host.tasks.filterProperty('Tasks.status', 'TIMEDOUT');
117 117 timedOutTasks.forEach(function (_task) {
118   - var abortStatement = clusterState + App.format.role(_task.Tasks.role) + ' timed out on ' + _host.name;
  118 + var timedOutStatement = clusterState + App.format.role(_task.Tasks.role) + ' timed out on ' + _host.name;
119 119 this.get('clusterInfo').findProperty('id', 1).get('status').findProperty('id', 2).get('statements').pushObject(Ember.Object.create({
120 120 status: 'timedout',
121 121 color: 'text-info',
122   - displayStatement: timedOutTasks
  122 + displayStatement: timedOutStatement
123 123 }));
124 124 }, this);
125 125 }, this);
22 ambari-web/app/controllers/wizard/step1_controller.js
@@ -21,31 +21,15 @@ var App = require('app');
21 21 App.WizardStep1Controller = Em.Controller.extend({
22 22 name: 'wizardStep1Controller',
23 23
24   - clusterName: function(){
25   - return this.get('content.cluster.name');
26   - }.property('content.cluster.name'),
27   -
28   -
29 24 hasSubmitted : false,
30 25
31   - clearStep: function() {
32   - this.set('content.cluster.name','');
33   - },
34   -
35 26 loadStep: function () {
36   - var clusterName;
37 27 this.set('hasSubmitted',false);
38   - console.log('The value of the cluster name is: ' + App.db.getClusterName());
39   - if (App.db.getClusterName() !== undefined) {
40   - this.set('clusterName', App.db.getClusterName());
41   - } else {
42   - this.set('clusterNameError','');
43   - this.set('invalidClusterName',true);
44   - }
45 28 },
46 29
47 30 invalidClusterName : function(){
48 31 if(!this.get('hasSubmitted')){
  32 + this.set('clusterNameError', '');
49 33 return false;
50 34 }
51 35
@@ -76,8 +60,8 @@ App.WizardStep1Controller = Em.Controller.extend({
76 60 submit: function () {
77 61 this.set('hasSubmitted', true);
78 62 if (!this.get('invalidClusterName')) {
79   - this.set('content.cluster',{name: this.get('clusterName'), status: 'PENDING', isCompleted: false});
80   - // App.router.get('installerController').saveClusterStatus({status: 'PENDING', isCompleted: false});
  63 + this.set('content.cluster.status', 'PENDING');
  64 + this.set('content.cluster.isCompleted', false);
81 65 App.router.send('next');
82 66 }
83 67 }
87 ambari-web/app/controllers/wizard/step2_controller.js
@@ -21,32 +21,33 @@ var App = require('app');
21 21 App.WizardStep2Controller = Em.Controller.extend({
22 22 name: 'wizardStep2Controller',
23 23 hostNameArr: [],
  24 + isPattern: false,
24 25 bootRequestId: null,
25 26 hasSubmitted: false,
26 27
27 28 hostNames: function () {
28   - return this.get('content.hostNames');
29   - }.property('content.hostNames'),
  29 + return this.get('content.hosts.hostNames');
  30 + }.property('content.hosts.hostNames'),
30 31
31 32 manualInstall: function () {
32   - return this.get('content.manualInstall');
33   - }.property('content.manualInstall'),
  33 + return this.get('content.hosts.manualInstall');
  34 + }.property('content.hosts.manualInstall'),
34 35
35 36 localRepo: function () {
36   - return this.get('content.localRepo');
37   - }.property('content.localRepo'),
  37 + return this.get('content.hosts.localRepo');
  38 + }.property('content.hosts.localRepo'),
38 39
39 40 sshKey: function () {
40   - return this.get('content.sshKey');
41   - }.property('content.sshKey'),
  41 + return this.get('content.hosts.sshKey');
  42 + }.property('content.hosts.sshKey'),
42 43
43 44 passphrase: function () {
44   - return this.get('content.passphrase');
45   - }.property('content.passphrase'),
  45 + return this.get('content.hosts.passphrase');
  46 + }.property('content.hosts.passphrase'),
46 47
47 48 confirmPassphrase: function () {
48   - return this.get('content.confirmPassphrase');
49   - }.property('content.confirmPassphrase'),
  49 + return this.get('content.hosts.confirmPassphrase');
  50 + }.property('content.hosts.confirmPassphrase'),
50 51
51 52 installType: function () {
52 53 if (this.get('manualInstall') === true) {
@@ -98,7 +99,7 @@ App.WizardStep2Controller = Em.Controller.extend({
98 99 hostInfo[hostNameArr[i]] = {
99 100 name: hostNameArr[i],
100 101 installType: this.get('installType'),
101   - bootStatus: 'pending'
  102 + bootStatus: 'PENDING'
102 103 };
103 104 }
104 105
@@ -117,6 +118,45 @@ App.WizardStep2Controller = Em.Controller.extend({
117 118 return false;
118 119 }
119 120
  121 + if(this.isPattern)
  122 + {
  123 + this.hostNamePatternPopup(this.hostNameArr);
  124 + return false;
  125 + }
  126 +
  127 + this.proceedNext();
  128 +
  129 + },
  130 +
  131 + patternExpression: function(){
  132 + var self = this;
  133 + var hostNames = [];
  134 + $.each(this.hostNameArr, function(e,a){
  135 + var start, end, extra = "";
  136 + if(/\[\d*\-\d*\]/.test(a)){
  137 + start=a.match(/\[\d*/);
  138 + end=a.match(/\-\d*/);
  139 + start=start[0].substr(1);
  140 + end=end[0].substr(1);
  141 +
  142 + if(parseInt(start) <= parseInt(end) && parseInt(start) >= 0){
  143 + self.isPattern = true;
  144 + if(start[0] == "0" && start.length > 1)
  145 + {
  146 + extra = start[0];
  147 + }
  148 + for (var i = parseInt(start); i < parseInt(end) + 1; i++) {
  149 + hostNames.push(a.replace(/\[\d*\-\d*\]/, extra+i ))
  150 + }
  151 + }
  152 + }else{
  153 + hostNames.push(a);
  154 + }
  155 + });
  156 + this.hostNameArr = hostNames;
  157 + },
  158 +
  159 + proceedNext: function(){
120 160 if (this.get('manualInstall') === true) {
121 161 this.manualInstallPopup();
122 162 return false;
@@ -129,13 +169,28 @@ App.WizardStep2Controller = Em.Controller.extend({
129 169 return true;
130 170 }
131 171
132   - var requestId = App.get('router.installerController').launchBootstrap(bootStrapData);
  172 + var requestId = App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData);
133 173 if(requestId) {
134   - this.set('bootRequestId',requestId);
135   - App.router.send('next');