Browse Source

AMBARI-1060. Data loading for App Browser. (yusaku)

git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/branches/AMBARI-666@1418909 13f79535-47bb-0310-9956-ffa450edef68
Yusaku Sako 12 years ago
parent
commit
a02355f314
37 changed files with 859 additions and 527 deletions
  1. 2 0
      AMBARI-666-CHANGES.txt
  2. 198 0
      ambari-web/app/assets/data/apps/jobs.json
  3. 108 0
      ambari-web/app/assets/data/apps/runs.json
  4. 10 0
      ambari-web/app/assets/data/clusters/cluster.json
  5. 66 11
      ambari-web/app/assets/data/hosts/hosts.json
  6. 34 8
      ambari-web/app/controllers/cluster_controller.js
  7. 40 1
      ambari-web/app/controllers/global/background_operations_controller.js
  8. 0 3
      ambari-web/app/controllers/main/apps_controller.js
  9. 104 177
      ambari-web/app/controllers/main/host/details.js
  10. 6 1
      ambari-web/app/controllers/main/service/item.js
  11. 3 0
      ambari-web/app/initialize.js
  12. 40 0
      ambari-web/app/mappers/cluster_mapper.js
  13. 24 3
      ambari-web/app/mappers/hosts_mapper.js
  14. 63 0
      ambari-web/app/mappers/jobs_mapper.js
  15. 47 0
      ambari-web/app/mappers/runs_mapper.js
  16. 15 8
      ambari-web/app/mappers/server_data_mapper.js
  17. 1 0
      ambari-web/app/mappers/services_mapper.js
  18. 1 1
      ambari-web/app/messages.js
  19. 3 39
      ambari-web/app/models/cluster.js
  20. 6 139
      ambari-web/app/models/host.js
  21. 0 27
      ambari-web/app/models/job.js
  22. 2 0
      ambari-web/app/models/protoRelations.js
  23. 2 2
      ambari-web/app/models/rack.js
  24. 10 10
      ambari-web/app/models/run.js
  25. 4 2
      ambari-web/app/routes/installer.js
  26. 3 0
      ambari-web/app/styles/application.less
  27. 0 44
      ambari-web/app/templates/main/host/background_operations_popup.hbs
  28. 2 2
      ambari-web/app/templates/main/host/summary.hbs
  29. 1 1
      ambari-web/app/templates/wizard/step2.hbs
  30. 2 0
      ambari-web/app/templates/wizard/step3.hbs
  31. 10 15
      ambari-web/app/templates/wizard/step9.hbs
  32. 3 3
      ambari-web/app/templates/wizard/step9HostTasksLogPopup.hbs
  33. 2 2
      ambari-web/app/utils/jquery.unique.js
  34. 2 18
      ambari-web/app/views/main/host/details.js
  35. 44 4
      ambari-web/app/views/main/host/summary.js
  36. 1 5
      ambari-web/app/views/main/test.js
  37. 0 1
      ambari-web/app/views/wizard/step9_view.js

+ 2 - 0
AMBARI-666-CHANGES.txt

@@ -398,6 +398,8 @@ AMBARI-666 branch (unreleased changes)
 
   IMPROVEMENTS
 
+  AMBARI-1060. Data loading for App Browser. (yusaku)
+
   AMBARI-993. Hook up login with server authentication. (yusaku)
 
   AMBARI-1059. Refactor cluster management. (yusaku)

+ 198 - 0
ambari-web/app/assets/data/apps/jobs.json

@@ -0,0 +1,198 @@
+{"jobs": [
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0036/job.xml",
+      "elapsedTime": 307122,
+      "inputBytes": 10409082,
+      "jobId": "job_201211040003_0036",
+      "jobName": "PigLatin:script2-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 59144990,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352095518432,
+      "userName": "root",
+      "workflowEntityName": "89",
+      "workflowId": "pig_b6d5cc44-ac51-4ecd-92c7-2e477c2fbed6"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0037/job.xml",
+      "elapsedTime": 251964,
+      "inputBytes": 59145376,
+      "jobId": "job_201211040003_0037",
+      "jobName": "PigLatin:script2-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 27259999,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352095842817,
+      "userName": "root",
+      "workflowEntityName": "97",
+      "workflowId": "pig_b6d5cc44-ac51-4ecd-92c7-2e477c2fbed6"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0038/job.xml",
+      "elapsedTime": 100200,
+      "inputBytes": 54520774,
+      "jobId": "job_201211040003_0038",
+      "jobName": "PigLatin:script2-hadoop.pig",
+      "maps": 2,
+      "outputBytes": 67032,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352096111311,
+      "userName": "root",
+      "workflowEntityName": "103",
+      "workflowId": "pig_b6d5cc44-ac51-4ecd-92c7-2e477c2fbed6"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0019/job.xml",
+      "elapsedTime": 70395,
+      "inputBytes": 650898,
+      "jobId": "job_201211040003_0019",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 64,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352016495104,
+      "userName": "root",
+      "workflowEntityName": "86",
+      "workflowId": "pig_7c779523-6bca-416e-89b3-b01b73a60174"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0016/job.xml",
+      "elapsedTime": 285448,
+      "inputBytes": 10409082,
+      "jobId": "job_201211040003_0016",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 57689830,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352015770967,
+      "userName": "root",
+      "workflowEntityName": "72",
+      "workflowId": "pig_7c779523-6bca-416e-89b3-b01b73a60174"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0017/job.xml",
+      "elapsedTime": 254621,
+      "inputBytes": 57690215,
+      "jobId": "job_201211040003_0017",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 27259999,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352016076858,
+      "userName": "root",
+      "workflowEntityName": "80",
+      "workflowId": "pig_7c779523-6bca-416e-89b3-b01b73a60174"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0020/job.xml",
+      "elapsedTime": 81568,
+      "inputBytes": 650898,
+      "jobId": "job_201211040003_0020",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 659755,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352016582226,
+      "userName": "root",
+      "workflowEntityName": "103",
+      "workflowId": "pig_7c779523-6bca-416e-89b3-b01b73a60174"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0018/job.xml",
+      "elapsedTime": 123283,
+      "inputBytes": 27260386,
+      "jobId": "job_201211040003_0018",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 650512,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352016352319,
+      "userName": "root",
+      "workflowEntityName": "83",
+      "workflowId": "pig_7c779523-6bca-416e-89b3-b01b73a60174"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0001/job.xml",
+      "elapsedTime": 293486,
+      "inputBytes": 10409082,
+      "jobId": "job_201211040003_0001",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 57689830,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352012856094,
+      "userName": "root",
+      "workflowEntityName": "72",
+      "workflowId": "pig_5750f4cf-f0d2-4e3d-a7ce-90912b309c12"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0003/job.xml",
+      "elapsedTime": 126758,
+      "inputBytes": 27260386,
+      "jobId": "job_201211040003_0003",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 650512,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352013446101,
+      "userName": "root",
+      "workflowEntityName": "83",
+      "workflowId": "pig_5750f4cf-f0d2-4e3d-a7ce-90912b309c12"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0005/job.xml",
+      "elapsedTime": 83965,
+      "inputBytes": 650899,
+      "jobId": "job_201211040003_0005",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 659755,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352013682420,
+      "userName": "root",
+      "workflowEntityName": "103",
+      "workflowId": "pig_5750f4cf-f0d2-4e3d-a7ce-90912b309c12"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0002/job.xml",
+      "elapsedTime": 256616,
+      "inputBytes": 57690216,
+      "jobId": "job_201211040003_0002",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 27259999,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352013170737,
+      "userName": "root",
+      "workflowEntityName": "80",
+      "workflowId": "pig_5750f4cf-f0d2-4e3d-a7ce-90912b309c12"
+    },
+    {
+      "confPath": "hdfs://localhost:8020/tmp/hadoop-root/mapred/staging/root/.staging/job_201211040003_0004/job.xml",
+      "elapsedTime": 76603,
+      "inputBytes": 650899,
+      "jobId": "job_201211040003_0004",
+      "jobName": "PigLatin:script1-hadoop.pig",
+      "maps": 1,
+      "outputBytes": 64,
+      "reduces": 1,
+      "status": "SUCCESS",
+      "submitTime": 1352013590129,
+      "userName": "root",
+      "workflowEntityName": "86",
+      "workflowId": "pig_5750f4cf-f0d2-4e3d-a7ce-90912b309c12"
+    }
+  ]
+}

+ 108 - 0
ambari-web/app/assets/data/apps/runs.json

@@ -0,0 +1,108 @@
+{"workflows": [
+    {
+      "elapsedTime": 693129,
+      "numJobsCompleted": 3,
+      "numJobsTotal": 3,
+      "startTime": 1352095518432,
+      "userName": "root",
+      "workflowContext": {
+        "workflowDag": {
+          "entries": [
+            {
+              "source": "89",
+              "targets": [
+                "97"
+              ]
+            },
+            {
+              "source": "97",
+              "targets": [
+                "103"
+              ]
+            }
+          ]
+        }
+      },
+      "workflowId": "pig_b6d5cc44-ac51-4ecd-92c7-2e477c2fbed6",
+      "workflowName": "script2-hadoop.pig"
+    },
+    {
+      "elapsedTime": 892896,
+      "numJobsCompleted": 5,
+      "numJobsTotal": 5,
+      "startTime": 1352015770967,
+      "userName": "root",
+      "workflowContext": {
+        "workflowDag": {
+          "entries": [
+            {
+              "source": "80",
+              "targets": [
+                "83"
+              ]
+            },
+            {
+              "source": "83",
+              "targets": [
+                "86"
+              ]
+            },
+            {
+              "source": "86",
+              "targets": [
+                "103"
+              ]
+            },
+            {
+              "source": "72",
+              "targets": [
+                "80"
+              ]
+            }
+          ]
+        }
+      },
+      "workflowId": "pig_7c779523-6bca-416e-89b3-b01b73a60174",
+      "workflowName": "script1-hadoop.pig"
+    },
+    {
+      "elapsedTime": 910360,
+      "numJobsCompleted": 5,
+      "numJobsTotal": 5,
+      "startTime": 1352012856094,
+      "userName": "root",
+      "workflowContext": {
+        "workflowDag": {
+          "entries": [
+            {
+              "source": "80",
+              "targets": [
+                "83"
+              ]
+            },
+            {
+              "source": "83",
+              "targets": [
+                "86"
+              ]
+            },
+            {
+              "source": "86",
+              "targets": [
+                "103"
+              ]
+            },
+            {
+              "source": "72",
+              "targets": [
+                "80"
+              ]
+            }
+          ]
+        }
+      },
+      "workflowId": "pig_5750f4cf-f0d2-4e3d-a7ce-90912b309c12",
+      "workflowName": "script1-hadoop.pig"
+    }
+  ]
+}

+ 10 - 0
ambari-web/app/assets/data/clusters/cluster.json

@@ -0,0 +1,10 @@
+{
+  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster?fields=Clusters",
+  "Clusters" : {
+    "cluster_name" : "mycluster",
+    "cluster_id" : 1,
+    "version" : "HDP-0.1",
+    "stack_name" : "HDP",
+    "max_hosts_per_rack" : 10
+  }
+}

+ 66 - 11
ambari-web/app/assets/data/hosts/hosts.json

@@ -2,122 +2,177 @@
   "href" : "http://localhost:8080/api/hosts?fields=*",
   "items" : [
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host01",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack1",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host01",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.1"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host02",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack1",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host02",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.2"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host03",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack1",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host03",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.3"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host04",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack1",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host04",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.4"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host05",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack1",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host05",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.5"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host06",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack2",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host06",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.6"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host07",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack2",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host07",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.7"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host08",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack2",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host08",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.8"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host09",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack2",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host09",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.9"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host10",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack2",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host10",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.10"
       }
     },
     {
-      "href" : "http://localhost:8080/api/hosts/host1",
+      "href" : "http://localhost:8080/api/hosts/host11",
       "Hosts" : {
         "cpu_count" : 1,
+        "cluster_name" : "mycluster",
+        "last_registration_time" : 1352357436171,
+        "rack_info" : "/rack3",
         "total_mem" : 2055208,
         "os_arch" : "x86_64",
         "host_name" : "host11",
+        "disk_info" : "[{\"available\":\"47476780\",\"mountpoint\":\"/\",\"used\":\"3605224\",\"percent\":\"8%\",\"size\":\"51606140\",\"type\":\"ext4\"},{\"available\":\"1027100\",\"mountpoint\":\"/dev/shm\",\"used\":\"364\",\"percent\":\"1%\",\"size\":\"1027464\",\"type\":\"tmpfs\"},{\"available\":\"432210\",\"mountpoint\":\"/boot\",\"used\":\"38034\",\"percent\":\"9%\",\"size\":\"495844\",\"type\":\"ext4\"},{\"available\":\"44459808\",\"mountpoint\":\"/home\",\"used\":\"184284\",\"percent\":\"1%\",\"size\":\"47033288\",\"type\":\"ext4\"},{\"available\":\"0\",\"mountpoint\":\"/media/VBOXADDITIONS_4.1.23_80858\",\"used\":\"52206\",\"percent\":\"100%\",\"size\":\"52206\",\"type\":\"iso9660\"}]",
+        "last_heartbeat_time" : 1352357625241,
         "os_type" : "centos6",
         "ip" : "10.0.2.11"
       }

+ 34 - 8
ambari-web/app/controllers/cluster_controller.js

@@ -30,12 +30,14 @@ App.ClusterController = Em.Controller.extend({
         loaded = false;
       }
     }
-
     return loaded;
   }.property('dataLoadList'),
   dataLoadList: Em.Object.create({
-    'hosts': true,
-    'services': false
+    'hosts': false,
+    'jobs': false,
+    'runs': false,
+    'services': false,
+    'cluster' : false
   }),
   /**
    * load cluster name
@@ -50,7 +52,6 @@ App.ClusterController = Em.Controller.extend({
       timeout: 5000,
       success: function (data) {
         self.set('cluster', data.items[0]);
-        self.loadClusterData();
       },
       error: function (request, ajaxOptions, error) {
         //do something
@@ -59,6 +60,10 @@ App.ClusterController = Em.Controller.extend({
       statusCode: require('data/statusCodes')
     });
   },
+
+  getUrl: function(testUrl, url){
+    return (App.testMode) ? testUrl: '/api/clusters/' + this.get('clusterName') + url;
+  },
    /**
    *
    *  load all data and update load status
@@ -68,13 +73,34 @@ App.ClusterController = Em.Controller.extend({
     if(!this.get('clusterName')){
         return;
     }
-    // TODO: load all models
-    /*App.HttpClient.get("/data/hosts/hosts.json", App.hostsMapper,{
+    var clusterUrl = (App.testMode) ? '/data/clusters/cluster.json': '/api/clusters/mycluster?fields=Clusters';
+    var jobsUrl = (App.testMode) ? "/data/apps/jobs.json" : "/api/jobs?fields=*";
+    var runsUrl = (App.testMode) ? "/data/apps/runs.json" : "/api/runs?fields=*";
+    var hostsUrl = (App.testMode) ? "/data/hosts/hosts.json" : "/api/hosts?fields=*";
+    var servicesUrl = (App.testMode) ?
+        "/data/dashboard/services.json" :
+        "/api/clusters/mycluster/services?ServiceInfo/service_name!=MISCELLANEOUS&ServiceInfo/service_name!=DASHBOARD&fields=components/host_components/*";
+    App.HttpClient.get(clusterUrl, App.clusterMapper,{
+      complete:function(jqXHR, textStatus){
+        self.set('dataLoadList.cluster', true);
+      }
+    });
+     App.HttpClient.get(jobsUrl, App.jobsMapper,{
+       complete:function(jqXHR, textStatus) {
+         self.set('dataLoadList.jobs', true);
+       }
+     });
+     App.HttpClient.get(runsUrl, App.runsMapper,{
+       complete:function(jqXHR, textStatus) {
+         self.set('dataLoadList.runs', true);
+       }
+     });
+    App.HttpClient.get(hostsUrl, App.hostsMapper,{
       complete:function(jqXHR, textStatus){
         self.set('dataLoadList.hosts', true);
       }
-    });*/
-    App.HttpClient.get("/data/dashboard/services.json", App.servicesMapper,{
+    });
+    App.HttpClient.get(servicesUrl, App.servicesMapper,{
       complete:function(jqXHR, textStatus){
         self.set('dataLoadList.services', true);
       }

+ 40 - 1
ambari-web/app/controllers/global/background_operations_controller.js

@@ -72,6 +72,10 @@ App.BackgroundOperationsController = Em.Controller.extend({
     }
   },
 
+  getOperationsForRequestId: function(requestId){
+    return this.get('allOperations').filterProperty('request_id', requestId);
+  },
+
   updateInterval: 6000,
   url : '',
 
@@ -169,6 +173,25 @@ App.BackgroundOperationsController = Em.Controller.extend({
     }
 
     this.set('allOperationsCount', currentTasks.length);
+
+    var eventsArray = this.get('eventsArray');
+    if(eventsArray.length){
+
+      var itemsToRemove = [];
+      eventsArray.forEach(function(item){
+        //if when returns true
+        if(item.when(this)){
+          //fire do method
+          item.do();
+          //and remove it
+          itemsToRemove.push(item);
+        }
+      }, this);
+
+      itemsToRemove.forEach(function(item){
+        eventsArray.splice(eventsArray.indexOf(item), 1);
+      });
+    }
   },
 
   /**
@@ -189,6 +212,22 @@ App.BackgroundOperationsController = Em.Controller.extend({
       },
       secondary : null
     });
-  }
+  },
+
+  /**
+   * Exaple of data inside:
+   * {
+   *   when : function(backgroundOperationsController){
+   *     return backgroundOperationsController.getOperationsForRequestId(requestId).length == 0;
+   *   },
+   *   do : function(){
+   *     component.set('status', 'cool');
+   *   }
+   * }
+   *
+   * Function <code>do</code> will be fired once, when <code>when</code> returns true.
+   * Example, how to use it, you can see in app\controllers\main\host\details.js
+   */
+  eventsArray : []
 
 });

+ 0 - 3
ambari-web/app/controllers/main/apps_controller.js

@@ -28,9 +28,6 @@ App.MainAppsController = Em.ArrayController.extend({
   routeHome:function () {
     App.router.transitionTo('main.dashboard');
     var view = Ember.View.views['main_menu'];
-    $.each(view._childViews, function () {
-      this.set('active', this.get('content.routing') == 'dashboard' ? "active" : "");
-    });
   },
   clearFilteredRuns: function() {
     this.set('filteredRuns', []);

+ 104 - 177
ambari-web/app/controllers/main/host/details.js

@@ -22,74 +22,49 @@ App.MainHostDetailsController = Em.Controller.extend({
   name: 'mainHostDetailsController',
   content: null,
   isFromHosts: false,
-  backgroundOperations: [],
-  isStarting: true,
-  isStopping: function(){
-    return !this.get('isStarting');
-  }.property('isStarting'),
-  intervalId: false,
-  checkOperationsInterval: 5000,
-  init: function(){
-    this._super();
-    this.startCheckOperationsLifeTime();
-  },
+
   routeHome:function () {
     App.router.transitionTo('main.dashboard');
-    var view = Ember.View.views['main_menu'];
-    $.each(view._childViews, function () {
-      this.set('active', this.get('content.routing') == 'dashboard' ? "active" : "");
-    });
   },
 
   setBack: function(isFromHosts){
     this.set('isFromHosts', isFromHosts);
   },
 
-  startCheckOperationsLifeTime: function() {
-    this.intervalId = setInterval(this.checkOperationsLifeTime, this.get('checkOperationsInterval'));
-  },
-  stopCheckOperationsLifeTime:function () {
-    if(this.intervalId) {
-      clearInterval(this.intervalId);
-    }
-    this.intervalId = false;
-  },
+  /**
+   * Send specific command to server
+   * @param url
+   * @param data Object to send
+   */
+  sendCommandToServer : function(url, postData, callback){
+    var url =  (App.testMode) ?
+      '/data/wizard/deploy/poll_1.json' : //content is the same as ours
+      '/api/clusters/' + App.router.getClusterName() + url;
 
-  checkOperationsLifeTime: function(){
-    var self = App.router.get('mainHostDetailsController');
-    var backgroundOperations = self.get('backgroundOperations');
-    var time = new Date().getTime();
-    if(backgroundOperations.length){
-      backgroundOperations.forEach(function(operation){
-        if (time - operation.time >= 60*1000){
-          backgroundOperations.removeObject(operation);
-        }
-      })
-    }
-  },
+    var method = App.testMode ? 'GET' : 'PUT';
 
-  hostOperations: function(){
-    var hostName = this.get('content.hostName');
-    return this.get('backgroundOperations').filterProperty('hostName', hostName);
-  }.property('backgroundOperations.length', 'content'),
+    $.ajax({
+      type: method,
+      url: url,
+      data: JSON.stringify(postData),
+      dataType: 'json',
+      timeout: 5000,
+      success: function(data){
+        if(data && data.Requests){
+          callback(data.Requests.id);
+        } else{
+          callback(null);
+          console.log('cannot get request id from ', data);
+        }
+      },
 
-  hostOperationsCount: function() {
-    return this.get('hostOperations.length');
-  }.property('backgroundOperations.length', 'content'),
+      error: function (request, ajaxOptions, error) {
+        //do something
+        callback(null);
+        console.log('error on change component host status')
+      },
 
-  showBackgroundOperationsPopup: function(){
-    App.ModalPopup.show({
-      headerClass: Ember.View.extend({
-        controllerBinding: 'App.router.mainHostDetailsController',
-        template:Ember.Handlebars.compile('{{hostOperationsCount}} Background Operations Running')
-      }),
-      bodyClass: Ember.View.extend({
-        controllerBinding: 'App.router.mainHostDetailsController',
-        templateName: require('templates/main/host/background_operations_popup')
-      }),
-      onPrimary: function() {
-        this.hide();
-      }
+      statusCode: require('data/statusCodes')
     });
   },
 
@@ -102,30 +77,41 @@ App.MainHostDetailsController = Em.Controller.extend({
       secondary: 'No',
       onPrimary: function() {
         var component = event.context;
-        component.set('workStatus', "STARTING");
-        self.componentIndicatorBlink(component);
-        self.setComponentButtonStatus(component,"disabled");
-        //TODO: here must be call to server side
-        setTimeout(function(){
-          self.setComponentButtonStatus(component,"enabled");
-          component.set('workStatus', "STARTED");
-        },10000);
-        var backgroundOperations = self.get('backgroundOperations');
-        backgroundOperations.pushObject({
-          "hostName": self.get('content.hostName'),
-          "role":component.get('componentName'),
-          "command": "START",
-          "time": new Date().getTime(),
-          "details": [
-            {"startTime":"4 min ago", "name":"Some intermediate operation"},
-            {"startTime":"5 min ago", "name":"Component started"}
-          ],
-          "logs":{"exitcode":"404", "stdout":27, "stderror":501}
+
+        self.sendCommandToServer('/hosts/' + self.get('content.hostName') + '/host_components/' + component.get('componentName').toUpperCase(),{
+          HostRoles:{
+            state: 'STARTED'
+          }
+        }, function(requestId){
+
+          if(!requestId){
+            return;
+          }
+
+          console.log('Send request for STARTING successfully');
+          component.set('workStatus', "STARTING");
+
+          if(App.testMode){
+            setTimeout(function(){
+              component.set('workStatus', "STARTED");
+            },10000);
+          } else{
+            App.router.get('backgroundOperationsController.eventsArray').push({
+              "when" : function(controller){
+                var result = (controller.getOperationsForRequestId(requestId).length == 0);
+                console.log('startComponent.when = ', result)
+                return result;
+              },
+              "do" : function(){
+                component.set('workStatus', "STARTED");
+              }
+            });
+          }
+
+          App.router.get('backgroundOperationsController').showPopup();
+
         });
-        self.showBackgroundOperationsPopup();
-        var stopped = self.get('content.components').filterProperty('workStatus', "STOPPING");
-        if (stopped.length == 0)
-          self.set('isStarting', true);
+
         this.hide();
       },
       onSecondary: function() {
@@ -142,30 +128,41 @@ App.MainHostDetailsController = Em.Controller.extend({
       secondary: 'No',
       onPrimary: function() {
         var component = event.context;
-        component.set('workStatus', "STOPPING");
-        self.componentIndicatorBlink(component);
-        self.setComponentButtonStatus(component,"disabled");
-        //TODO: here must be call to server side
-        setTimeout(function(){
-          self.setComponentButtonStatus(component,"enabled");
-          component.set('workStatus', "STOPPED");
-        },10000);
-        var backgroundOperations = self.get('backgroundOperations');
-        backgroundOperations.pushObject({
-          "hostName": self.get('content.hostName'),
-          "role": component.get('componentName'),
-          "command": "STOP",
-          "time": new Date().getTime(),
-          "details": [
-            {"startTime":"4 min ago", "name":"Some intermediate operation"},
-            {"startTime":"5 min ago", "name":"Component stopped"}
-          ],
-          "logs":{"exitcode":"404", "stdout":15, "stderror":501}
+
+        self.sendCommandToServer('/hosts/' + self.get('content.hostName') + '/host_components/' + component.get('componentName').toUpperCase(),{
+          HostRoles:{
+            state: 'INSTALLED'
+          }
+        }, function(requestId){
+          if(!requestId){
+            return
+          }
+
+          console.log('Send request for STOPPING successfully');
+
+          component.set('workStatus', "STOPPING");
+
+          if(App.testMode){
+            setTimeout(function(){
+              component.set('workStatus', "STOPPED");
+            },10000);
+          } else{
+            App.router.get('backgroundOperationsController.eventsArray').push({
+              "when" : function(controller){
+                var result = (controller.getOperationsForRequestId(requestId).length == 0);
+                console.log('stopComponent.when = ', result)
+                return result;
+              },
+              "do" : function(){
+                component.set('workStatus', "STOPPED");
+              }
+            });
+          }
+
+          App.router.get('backgroundOperationsController').showPopup();
+
         });
-        self.showBackgroundOperationsPopup();
-        var started = self.get('content.components').filterProperty('workStatus', "STARTING");
-        if (started.length == 0)
-          self.set('isStarting', false);
+
         this.hide();
       },
       onSecondary: function() {
@@ -174,21 +171,6 @@ App.MainHostDetailsController = Em.Controller.extend({
     });
   },
 
-  setComponentButtonStatus: function(component,status){
-    if(status=="disabled"){
-      $("#component-button-" + component.get("id") ).addClass("disabled");
-    }else{
-      $("#component-button-" + component.get("id") ).removeClass("disabled");
-    }
-  },
-  componentIndicatorBlink: function(component){
-    var self=this;
-    $("#component-button-"+component.get("id")).find(".components-health").effect("pulsate", { times:1 }, "slow", function () {
-      if(component.get('workStatus')==="STOPPING" || component.get('workStatus')==="STARTING")
-        self.componentIndicatorBlink(component);
-    });
-  },
-
   decommission: function(event){
     var self = this;
     App.ModalPopup.show({
@@ -199,19 +181,9 @@ App.MainHostDetailsController = Em.Controller.extend({
       onPrimary: function() {
         var component = event.context;
         component.set('decommissioned', true);
-        var backgroundOperations = self.get('backgroundOperations');
-        backgroundOperations.pushObject({
-          "hostName": self.get('content.hostName'),
-          "role":component.get('componentName'),
-          "command": "DECOMMISSION",
-          "time": new Date().getTime(),
-          "details": [
-            {"startTime":"4 min ago", "name":"Some intermediate operation"},
-            {"startTime":"5 min ago", "name":"Component decommissioned"}
-          ],
-          "logs":{"exitcode":"404", "stdout":27, "stderror":501}
-        });
-        self.showBackgroundOperationsPopup();
+
+        //todo:call to server
+        App.router.get('backgroundOperationsController').showPopup();
         this.hide();
       },
       onSecondary: function() {
@@ -230,53 +202,8 @@ App.MainHostDetailsController = Em.Controller.extend({
       onPrimary: function() {
         var component = event.context;
         component.set('decommissioned', false);
-        var backgroundOperations = self.get('backgroundOperations');
-        backgroundOperations.pushObject({
-          "hostName": self.get('content.hostName'),
-          "role":component.get('componentName'),
-          "command": "RECOMMISSION",
-          "time": new Date().getTime(),
-          "details": [
-            {"startTime":"4 min ago", "name":"Some intermediate operation"},
-            {"startTime":"5 min ago", "name":"Component recommissioned"}
-          ],
-          "logs":{"exitcode":"404", "stdout":27, "stderror":501}
-        });
-        self.showBackgroundOperationsPopup();
-        this.hide();
-      },
-      onSecondary: function() {
-        this.hide();
-      }
-    });
-  },
-  startConfirmPopup: function (event) {
-    var self = this;
-    App.ModalPopup.show({
-      header: Em.I18n.t('hosts.host.start.popup.header'),
-      body: Em.I18n.t('hosts.host.start.popup.body'),
-      primary: 'Yes',
-      secondary: 'No',
-      onPrimary: function() {
-        self.get('content.components').setEach('workStatus', "STARTING");
-        self.set('isStarting', !self.get('isStarting'));
-        this.hide();
-      },
-      onSecondary: function() {
-        this.hide();
-      }
-    });
-  },
-  stopConfirmPopup: function (event) {
-    var self = this;
-    App.ModalPopup.show({
-      header: Em.I18n.t('hosts.host.stop.popup.header'),
-      body: Em.I18n.t('hosts.host.stop.popup.body'),
-      primary: 'Yes',
-      secondary: 'No',
-      onPrimary: function() {
-        self.get('content.components').setEach('workStatus', "STOPPING");
-        self.set('isStarting', !self.get('isStarting'));
+        //todo: call to server
+        App.router.get('backgroundOperationsController').showPopup();
         this.hide();
       },
       onSecondary: function() {

+ 6 - 1
ambari-web/app/controllers/main/service/item.js

@@ -31,7 +31,7 @@ App.MainServiceItemController = Em.Controller.extend({
       '/data/wizard/deploy/poll_1.json' : //content is the same as ours
       '/api/clusters/' + App.router.getClusterName() + url; //'/services/' + this.get('content.serviceName').toUpperCase();
 
-    var method = App.testMode ? 'GET' : 'PUT';
+    var method = App.testMode ? 'GET' : (postData ? 'PUT' : 'POST');
 
     $.ajax({
       type: method,
@@ -159,6 +159,11 @@ App.MainServiceItemController = Em.Controller.extend({
       secondary: 'No',
       onPrimary: function() {
         self.content.set('runSmokeTest', true);
+      
+        var serviceName = self.get('content.serviceName').toUpperCase();
+        var smokeName = serviceName + "_SERVICE_CHECK";
+        self.sendCommandToServer('/services/' + serviceName + '/actions/' + smokeName);
+
         App.router.get('backgroundOperationsController').showPopup();
         this.hide();
       },

+ 3 - 0
ambari-web/app/initialize.js

@@ -34,6 +34,9 @@ require('router');
 require('mappers/server_data_mapper');
 require('mappers/services_mapper');
 require('mappers/hosts_mapper');
+require('mappers/cluster_mapper');
+require('mappers/jobs_mapper');
+require('mappers/runs_mapper');
 
 require('utils/http_client');
 

+ 40 - 0
ambari-web/app/mappers/cluster_mapper.js

@@ -0,0 +1,40 @@
+/**
+ * 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.
+ */
+
+
+App.clusterMapper = App.QuickDataMapper.create({
+    model : App.Cluster,
+    map:function(json){
+      if(!this.get('model')) {return;}
+      if(json){
+        var result = json;
+        result = this.parseIt(result, this.config);
+        App.store.load(this.get('model'), result);
+      }
+    },
+    config : {
+      id:'Clusters.cluster_id',
+      cluster_name: 'Clusters.cluster_name',
+      stackName: 'Clusters.stack_name',
+      version: 'Clusters.version',
+      $hosts: "",
+      $racks: [1,2,3,4],
+      maxHostsPerRack: 'Clusters.max_hosts_per_rack'
+    }
+
+});

+ 24 - 3
ambari-web/app/mappers/hosts_mapper.js

@@ -16,7 +16,28 @@
  * limitations under the License.
  */
 
-//todo: refactor it
-App.hostsMapper = App.ServerDataMapper.create({
-  config: {}
+
+App.hostsMapper = App.QuickDataMapper.create({
+  model : App.Host,
+  config : {
+    id : 'Hosts.host_name',
+    host_name : 'Hosts.host_name',
+    cluster_id: 'Hosts.cluster_name',//1
+    $components: [1,2,3],
+    cpu : 'Hosts.cpu_count',
+    memory : 'Hosts.total_mem',
+    disk_info: 'Hosts.disk_info',
+    $disk_usage: '40',
+    $health_status: 'LIVE',
+    $load_avg: '0.2, 1.2, 2.4',
+    $cpu_usage: 33,
+    $memory_usage: 26,
+    $network_usage: 36,
+    $io_usage: 39,
+    last_heart_beat_time : "Hosts.last_heartbeat_time",
+    os : 'Hosts.os_arch',
+    os_type : 'Hosts.os_type',
+    ip : 'Hosts.ip'
+  }
+
 });

+ 63 - 0
ambari-web/app/mappers/jobs_mapper.js

@@ -0,0 +1,63 @@
+/**
+ * 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.jobsMapper = App.QuickDataMapper.create({
+  model : App.Job,
+  map : function(json) {
+    if(!this.get('model')) {
+      return;
+    }
+    if(json.jobs) {
+      var result = [];
+      json.jobs.forEach(function(item) {
+        result.push(this.parseIt(item, this.config));
+      }, this);
+      App.store.loadMany(this.get('model'), result);
+    }
+  },
+  config : {
+    job_id : 'jobId',
+    $workflow : 1,
+    job_name : 'jobName',
+    workflow_entity_name : 'workflowEntityName',
+    user_name : 'userName',
+    $queue : 'default',
+    $acls : null,
+    conf_path : 'confPath',
+    submit_time : 'submitTime',
+    //"launch_time":1348174627650,
+    //"finish_time":1348174669539,
+    maps : 'maps',
+    reduces : 'reduces',
+    status : 'status',
+    $priority : null,
+    //"finished_maps":12,
+    //"finished_reduces":5,
+    $failed_maps : null,
+    $failed_reduces : null,
+    //"maps_runtime":22299,
+    //"reduces_runtime":11470,
+    $map_counters : null,
+    $reduce_counters : null,
+    $job_counters : null,
+    input : 'inputBytes',
+    output : 'outputBytes'
+  }
+});

+ 47 - 0
ambari-web/app/mappers/runs_mapper.js

@@ -0,0 +1,47 @@
+/**
+ * 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.runsMapper = App.QuickDataMapper.create({
+  model : App.Run,
+  map : function(json) {
+    console.log('json', json.workflows);
+    if(!this.get('model')) {
+      return;
+    }
+    if(json.workflows) {
+      var result = [];
+      json.workflows.forEach(function(item) {
+        result.push(this.parseIt(item, this.config));
+      }, this);
+      console.log('result', result);
+      App.store.loadMany(this.get('model'), result);
+    }
+  },
+  config : {
+    run_id: 'workflowName',
+    $parent_run_id: null,
+    //workflow_context:'{dag: {"1":["2","3"],"2":["3","4"],"4":["2","5"]}}',
+    user_name:'userName',
+    start_time: 'startTime',
+    //last_update_time:'1347639541501',
+    app_id: 'workflowId'
+    //jobs:[1, 2, 3, 4, 5]
+  }
+});

+ 15 - 8
ambari-web/app/mappers/server_data_mapper.js

@@ -39,27 +39,34 @@ App.ServerDataMapper = Em.Object.extend({
 
 App.QuickDataMapper = App.ServerDataMapper.extend({
   config : {},
+  model : null,
   map:function(json){
+    if(!this.get('model')) {return;}
     if(json.items){
       var result = [];
       json.items.forEach(function(item){
         result.push(this.parseIt(item, this.config));
-      }, this)
-    App.store.loadMany(App.Service1, result);
+    }, this)
+    App.store.loadMany(this.get('model'), result);
     }
   },
   parseIt : function(data, config){
     var result = {};
     for(var i in config){
+      if(i.substr(0, 1) === '$'){
+        i = i.substr(1, i.length);
+        result[i] = config['$'+i];
+      } else {
       if(i.substr(-4) !== '_key' && typeof config[i] == 'string'){
         result[i] = this.getJsonProperty(data, config[i]);
       } else if(typeof config[i] == 'object'){
-      result[i] = [];
-      var _data = data[config[i+'_key']];
-      var l = _data.length;
-      for(var index = 0; index<l; index++){
-        result[i].push(this.parseIt(_data[index], config[i]));
-      }
+        result[i] = [];
+        var _data = data[config[i+'_key']];
+        var l = _data.length;
+        for(var index = 0; index<l; index++){
+          result[i].push(this.parseIt(_data[index], config[i]));
+        }
+        }
       }
     }
     return result;

+ 1 - 0
ambari-web/app/mappers/services_mapper.js

@@ -59,6 +59,7 @@ App.servicesMapper = App.ServerDataMapper.create({
 });
 */
 App.servicesMapper = App.QuickDataMapper.create({
+  model : App.Service1,
   config : {
     id : 'ServiceInfo.service_name',
     service_name : 'ServiceInfo.service_name',

+ 1 - 1
ambari-web/app/messages.js

@@ -118,7 +118,7 @@ Em.I18n.translations = {
   'installer.step8.body': 'Please review the cluster configuration before installation',
 
   'installer.step9.header': 'Install, Start and Test',
-  'installer.step9.body': 'Wait to complete the cluster installation. Installing, Starting and Testing selected services',
+  'installer.step9.body': 'Please wait while the selected services are installed, started, and tested on your new cluster.',
   'installer.step9.status.success': 'Successfully installed the cluster',
   'installer.step9.status.failed': 'Failure in installation',
   'installer.step9.host.status.success': 'Success',

+ 3 - 39
ambari-web/app/models/cluster.js

@@ -19,46 +19,16 @@
 
 var App = require('app');
 
-App.User = Em.Object.extend({
-  username: DS.attr("string")
-});
-
-App.User.FIXTURES = [
-  {},
-  {}
-];
-
-App.ClusterModel = Em.Object.extend({
-    clusterName: null,
-    hosts: [],
-    services: []
-
-});
-
-// uncomment if column names are camelized in JSON (or fixture), rather than _ separated
-/*
-DS.Model.reopen({
-    namingConvention: {
-        keyToJSONKey: function(key) {
-            return key;
-        },
-
-        foreignKey: function(key) {
-            return key;
-        }
-    }
-});
-*/
-
 App.Cluster = DS.Model.extend({
   clusterName: DS.attr('string'),
   stackName: DS.attr('string'),
+  version: DS.attr('string'),
   hosts: DS.hasMany('App.Host'),
   racks: DS.hasMany('App.Rack'),
   maxHostsPerRack: DS.attr('number')
 });
 
-App.Cluster.FIXTURES = [
+App.Cluster.FIXTURES = [/*
   {
     id: 1,
     cluster_name: 'cluster1',
@@ -66,11 +36,5 @@ App.Cluster.FIXTURES = [
     hosts: [1, 2, 3, 4],
     racks: [1, 2, 3, 4, 5, 6],
     max_hosts_per_rack: 10
-  },
-  {
-    id: 2,
-    cluster_name: 'cluster2',
-    stack_name: 'BigTop',
-    hosts: [5, 6, 7]
-  }
+  }*/
 ];

+ 6 - 139
ambari-web/app/models/host.js

@@ -35,6 +35,8 @@ App.Host = DS.Model.extend({
   networkUsage: DS.attr('number'),
   ioUsage: DS.attr('number'),
   lastHeartBeatTime: DS.attr('number'),
+  osType: DS.attr("string"),
+  diskInfo: DS.attr('string'),
 
 
   /**
@@ -78,12 +80,12 @@ App.Host = DS.Model.extend({
   }.property('healthStatus')
 });
 
-App.Host.FIXTURES = [
+App.Host.FIXTURES = [/*
   {
     id: 1,
-    host_name: 'z_host1',
+    host_name: 'dev.hortonworks.com',
     cluster_id: 1,
-    components:[1, 3],
+    components:[1, 2, 3, 4, 5],
     cpu: '2x2.5GHz',
     memory: '8GB',
     disk_usage: '40',
@@ -95,140 +97,5 @@ App.Host.FIXTURES = [
     network_usage: 36,
     io_usage: 39,
     last_heart_beat_time : 1351536732366
-  },
-  {
-    id: 2,
-    host_name: 'host2',
-    cluster_id: 1,
-    components:[4, 5, 8],
-    cpu: '2x2.5GHz',
-    memory: '8GB',
-    disk_usage: '20',
-    load_avg: '0.2, 1.2, 2.4',
-    ip: '255.255.255.255',
-    health_status: 'DEAD-ORANGE',
-    cpu_usage: 36,
-    memory_usage: 29,
-    network_usage: 56,
-    io_usage: 69,
-    lastHeartBeatTime : 1351536732366
-  },
-  {
-    id: 3,
-    host_name: 'n_host3',
-    cluster_id: 2,
-    components:[7],
-    health_status: 'DEAD-YELLOW',
-    cpu_usage: 23,
-    memory_usage: 16,
-    network_usage: 16,
-    io_usage: 49
-  },
-  {
-    id: 4,
-    host_name: 'b_host4',
-    cluster_id: 2,
-    components:[],
-    health_status: 'DEAD',
-    cpu_usage: 23,
-    memory_usage: 36,
-    network_usage: 46,
-    io_usage: 39
-  },
-  {
-    id: 5,
-    host_name: 'host5',
-    cluster_id: 1,
-    components:[],
-    cpu: '2x2.5GHz',
-    memory: '8GB',
-    disk_usage: '20',
-    load_avg: '0.2, 1.2, 2.4',
-    ip: '255.255.255.255',
-    health_status: 'DEAD',
-    cpu_usage: 53,
-    memory_usage: 16,
-    network_usage: 16,
-    io_usage: 29
-  },
-  {
-    id: 6,
-    host_name: 'a_host6',
-    cluster_id: 1,
-    components:[],
-    cpu: '2x2.5GHz',
-    memory: '8GB',
-    disk_usage: '20',
-    load_avg: '0.2, 1.2, 2.4',
-    ip: '255.255.255.255',
-    health_status: 'LIVE',
-    cpu_usage: 33,
-    memory_usage: 26,
-    network_usage: 36,
-    io_usage: 39
-  },
-  {
-    id: 7,
-    host_name: 'host7',
-    cluster_id: 1,
-    components:[],
-    cpu: '2x2.5GHz',
-    memory: '8GB',
-    disk_usage: '20',
-    load_avg: '0.2, 1.2, 2.4',
-    ip: '255.255.255.255',
-    health_status: 'LIVE',
-    cpu_usage: 53,
-    memory_usage: 16,
-    network_usage: 16,
-    io_usage: 29
-  },
-  {
-    id: 8,
-    host_name: 'host8',
-    cluster_id: 1,
-    components:[],
-    cpu: '2x2.5GHz',
-    memory: '8GB',
-    disk_usage: '20',
-    load_avg: '0.2, 1.2, 2.4',
-    ip: '255.255.255.255',
-    health_status: 'LIVE',
-    cpu_usage: 53,
-    memory_usage: 11,
-    network_usage: 14,
-    io_usage: 27
-  },
-  {
-    id: 9,
-    host_name: 'host9',
-    cluster_id: 1,
-    components:[],
-    cpu: '2x2.5GHz',
-    memory: '8GB',
-    disk_usage: '20',
-    load_avg: '0.2, 1.2, 2.4',
-    ip: '255.255.255.255',
-    health_status: 'LIVE',
-    cpu_usage: 53,
-    memory_usage: 26,
-    network_usage: 56,
-    io_usage: 19
-  },
-  {
-    id: 10,
-    host_name: 'host10',
-    cluster_id: 1,
-    components:[],
-    cpu: '2x2.5GHz',
-    memory: '8GB',
-    disk_usage: '20',
-    load_avg: '0.2, 1.2, 2.4',
-    ip: '255.255.255.255',
-    health_status: 'LIVE',
-    cpu_usage: 53,
-    memory_usage: 16,
-    network_usage: 16,
-    io_usage: 29
-  }
+  }*/
 ];

File diff suppressed because it is too large
+ 0 - 27
ambari-web/app/models/job.js


+ 2 - 0
ambari-web/app/models/protoRelations.js

@@ -103,3 +103,5 @@ App.HostComponent1 = DS.Model.extend({
 App.Service1.FIXTURES = [];
 App.Service1Component.FIXTURES = [];
 App.HostComponent1.FIXTURES = [];
+
+

+ 2 - 2
ambari-web/app/models/rack.js

@@ -32,7 +32,7 @@ App.Rack.FIXTURES = [
   {
     id: 1,
     name: 'Rack-0',
-    hosts: [1, 2, 3, 4, 8, 9, 10],
+    hosts: ['host01', 'host06', 'host05'],
     status: 'LIVE',
     live_hosts_count: 5,
     critical_hosts_count: 0,
@@ -41,7 +41,7 @@ App.Rack.FIXTURES = [
   {
     id: 2,
     name: 'Rack-1',
-    hosts: [5, 6, 7],
+    hosts: ['host04', 'host02', 'host03'],
     status: 'LIVE',
     live_hosts_count: 2,
     critical_hosts_count: 0,

+ 10 - 10
ambari-web/app/models/run.js

@@ -32,7 +32,7 @@ App.Run = DS.Model.extend({
   jobs:DS.hasMany('App.Job'),
   /**
    * Number of comleted jobs.
-   * Field calculates dynamicaly using <code>jobs</code> property
+   * Field calculates dynamically using <code>jobs</code> property
    */
   numJobsCompleted: function() {
     return this.get('jobs').filterProperty('status', 'RUNNING').length;
@@ -42,7 +42,7 @@ App.Run = DS.Model.extend({
   }.property('lastUpdateTime', 'startTime'),
   /**
    * Status of running jobs
-   * Field calculates dynamicaly using <code>jobs</code> property
+   * Field calculates dynamically using <code>jobs</code> property
    */
   isRunning: function () {
     if (!this.get('isLoaded')) {
@@ -52,19 +52,19 @@ App.Run = DS.Model.extend({
   }.property('jobs.@each.status'),
   /**
    * Sum of input bandwidth for all jobs
-   * Field calculates dynamicaly using <code>jobs</code> property
+   * Field calculates dynamically using <code>jobs</code> property
    */
   input: function () {
     var sum = 0;
     this.get('jobs').forEach(
-        function(item){
+        function(item) {
           sum += item.get('input') || 0;
         });
     return sum;
   }.property('jobs.@each.input'),
   /**
    *  Sum of input bandwidth for all jobs with appropriate measure
-   * Field calculates dynamicaly using <code>jobs</code> property
+   * Field calculates dynamically using <code>jobs</code> property
    */
   inputFormatted: function () {
     var input = this.get('input');
@@ -73,7 +73,7 @@ App.Run = DS.Model.extend({
   }.property('input'),
   /**
    * Sum of output bandwidth for all jobs
-   * Field calculates dynamicaly using <code>jobs</code> property
+   * Field calculates dynamically using <code>jobs</code> property
    */
   output: function () {
     var sum = 0;
@@ -85,7 +85,7 @@ App.Run = DS.Model.extend({
   }.property('jobs.@each.output'),
   /**
    *  Sum of output bandwidth for all jobs with appropriate measure
-   *  Field calculates dynamicaly using <code>jobs</code> property
+   *  Field calculates dynamically using <code>jobs</code> property
    */
   outputFormatted: function () {
     var output = this.get('output');
@@ -94,7 +94,7 @@ App.Run = DS.Model.extend({
   }.property('output'),
   /**
    * Number of jobs on this run
-   * Field calculates dynamicaly using <code>jobs</code> property
+   * Field calculates dynamically using <code>jobs</code> property
    */
   numJobsTotal: function() {
     return this.get('jobs.content').length;
@@ -105,7 +105,7 @@ App.Run = DS.Model.extend({
 });
 
 App.Run.FIXTURES = [
-  {
+  /*{
     id:1,
     run_id:'pig_1',
     parent_run_id:null,
@@ -226,5 +226,5 @@ App.Run.FIXTURES = [
     last_update_time:'1347639541511',
     app_id:3,
     jobs:[1, 3, 5, 7]
-  }
+  }*/
 ];

+ 4 - 2
ambari-web/app/routes/installer.js

@@ -270,8 +270,10 @@ module.exports = Em.Route.extend({
     retry: function (router) {
       var installerController = router.get('installerController');
       var wizardStep9Controller = router.get('wizardStep9Controller');
-      installerController.installServices();
-      wizardStep9Controller.navigateStep();
+      if (!wizardStep9Controller.get('isSubmitDisabled')) {
+        installerController.installServices();
+        wizardStep9Controller.navigateStep();
+      }
     },
     next: function (router) {
       var installerController = router.get('installerController');

+ 3 - 0
ambari-web/app/styles/application.less

@@ -256,6 +256,9 @@ h1 {
         margin-right: 8px;
         line-height: 10px;
       }
+      select {
+        margin-bottom: 0;
+      }
     }
   }
   #step4, #step6 {

+ 0 - 44
ambari-web/app/templates/main/host/background_operations_popup.hbs

@@ -1,44 +0,0 @@
-<!--
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
--->
-{{#each operation in hostOperations}}
-{{#view App.MainHostDetailsOperations contentBinding="operation"}}
-<a class="open-details" {{action openDetails target="view"}} href="#">
-  <i {{bindAttr class="view.iconClass"}}></i>
-</a>
-{{operation.command}} {{operation.role}} on {{operation.hostName}}
-<div class="operation-details">
-  {{#if operation.details.length}}
-    {{#each detail in operation.details}}
-    <div>{{detail.startTime}}: {{detail.name}}</div>
-    {{/each}}
-  {{/if}}
-  <a {{action showOperationLog target="view"}} href="#">
-    {{#if view.isOpenShowLog}}Hide{{else}}Show{{/if}} operation log
-  </a>
-  {{#if view.isOpenShowLog}}
-  <div class="operation-log">
-    <dl class="dl-horizontal">
-      <dt>Exit Code:</dt><dd>{{operation.logs.exitcode}}</dd>
-      <dt>Std Out:</dt><dd>{{operation.logs.stdout}}</dd>
-      <dt>Error:</dt><dd>{{operation.logs.stderror}}</dd>
-    </dl>
-  </div>
-  {{/if}}
-</div>
-{{/view}}
-{{/each}}

+ 2 - 2
ambari-web/app/templates/main/host/summary.hbs

@@ -39,8 +39,8 @@
     {{#each component in view.content.components}}
     {{#view view.ComponentButtonView contentBinding="component"}}
       <div {{bindAttr class=":btn-group view.positionButton:pull-right:pull-left"}}>
-        <button {{bindAttr id="view.buttonId"}} class="component-operation-button btn btn-success dropdown-toggle" data-toggle="dropdown">
-          <span {{bindAttr class="view.indicatorClass"}}></span>
+        <button {{bindAttr class=":component-operation-button :btn :btn-success :dropdown-toggle view.disabledClass"}} data-toggle="dropdown">
+          <span {{bindAttr class=":components-health view.indicatorClass"}}></span>
           {{unbound view.content.componentName}}
           <span class="caret"></span>
         </button>

+ 1 - 1
ambari-web/app/templates/wizard/step2.hbs

@@ -56,7 +56,7 @@
       <div {{bindAttr class="sshKeyError:error :control-group"}}>
         {{#if view.isFileApi}}
           {{view App.SshKeyFileUploader}}
-          <div {{bindAttr class="view.sshKeyPreviewClass"}}>{{content.sshKey}}</div>
+          <pre {{bindAttr class="view.sshKeyPreviewClass"}}>{{content.sshKey}}</pre>
         {{/if}}
         <div class="controls">
           {{view Ember.TextArea class="span6" rows="4" classBinding="view.sshKeyClass"  id="sshKey" placeholder="ssh private key" disabledBinding="view.sshKeyState" valueBinding="content.sshKey"}}

+ 2 - 0
ambari-web/app/templates/wizard/step3.hbs

@@ -34,6 +34,7 @@
                 class="icon-trash icon-white"></i>
           Remove
         </a>
+        {{#if App.testMode}}
         <a class="btn btn-info"
            href="#" {{action mockBtn target="controller" }}>
           mockData
@@ -42,6 +43,7 @@
            href="#" {{action pollBtn target="controller" }}>
           pollData
         </a>
+        {{/if}}
 
         <div id="host-filter" class="dropdown pull-right">
           {{view Ember.Select class="pull-right"

+ 10 - 15
ambari-web/app/templates/wizard/step9.hbs

@@ -39,23 +39,19 @@
   <div class="box">
     <div class="box-header">
       <div class="pull-left">
-        <a
-                class="btn btn-primary " {{bindAttr disabled="isSubmitDisabled"}}
-                href="#" {{action retry }}><i
-                class="icon-repeat icon-white"></i>
+        <a class="btn btn-primary" {{bindAttr disabled="isSubmitDisabled"}}
+           href="#" {{action retry}}><i class="icon-repeat icon-white"></i>
           Retry
         </a>
-        <a
-                class="btn btn-info"
-                href="#" {{action mockBtn target="controller"}}>
+        {{#if App.testMode}}
+        <a class="btn btn-info" href="#" {{action mockBtn target="controller"}}>
           mockData
         </a>
-        <a
-                class="btn btn-primary "
-                href="#" {{action pollBtn target="controller"}}><i
-                class="icon-repeat icon-white"></i>
+        <a class="btn btn-primary"
+           href="#" {{action pollBtn target="controller"}}><i class="icon-repeat icon-white"></i>
           pollData
         </a>
+        {{/if}}
       </div>
 
     </div>
@@ -90,8 +86,8 @@
         </td>
         <td>
           <a {{bindAttr class="view.isFailed:text-error view.isSuccess:text-success view.isWarning:text-warning"}}
-                  href="javascript:void(null)"
-                  data-toggle="modal" {{action hostLogPopup host target="view"}}>{{host.message}}</a>
+            href="javascript:void(null)"
+            data-toggle="modal" {{action hostLogPopup host target="view"}}>{{host.message}}</a>
         </td>
 
         {{/view}}
@@ -112,8 +108,7 @@
     <p {{bindAttr class="view.resultMsgColor :alert"}}>{{view.resultMsg}}</p>
     {{/if}}
     <div class="btn-area">
-      <a
-              class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>Next &rarr;</a>
+      <a class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>Next &rarr;</a>
     </div>
   </div>
 

+ 3 - 3
ambari-web/app/templates/wizard/step9HostTasksLogPopup.hbs

@@ -3,12 +3,12 @@
   {{#each role in view.roles}}
     {{#each taskInfo in role.taskInfos}}
     <div>
-      <a {{action toggleTaskLog taskInfo}}>{{#if taskInfo.isLogHidden}}Show{{else}}Hide{{/if}} {{role.roleName}} {{taskInfo.status}} log</a>
+      <a href="#" {{action toggleTaskLog taskInfo}}>{{#if taskInfo.isLogHidden}}Show{{else}}Hide{{/if}} {{role.roleName}} {{taskInfo.status}} log</a>
       <div {{bindAttr class="taskInfo.isLogHidden:hidden"}}>
         <h5>stderr:</h5>
-        <div class="stderr">{{taskInfo.stderr}}</div>
+        <pre class="stderr">{{taskInfo.stderr}}</pre>
         <h5>stdout:</h5>
-        <div class="stdout">{{taskInfo.stdout}}</div>
+        <pre class="stdout">{{taskInfo.stdout}}</pre>
       </div>
     </div>
     {{/each}}

+ 2 - 2
ambari-web/app/utils/jquery.unique.js

@@ -20,7 +20,7 @@
 
   var _old = $.unique;
 
-  $.unique = function(arr){
+  /*$.unique = function(arr){
 
     // do the default behavior only if we got an array of elements
     if (!!arr[0].nodeType){
@@ -31,5 +31,5 @@
         return $.inArray(v,arr) === k;
       });
     }
-  };
+  };*/
 })(jQuery);

+ 2 - 18
ambari-web/app/views/main/host/details.js

@@ -20,29 +20,13 @@ var App = require('app');
 
 App.MainHostDetailsView = Em.View.extend({
   templateName: require('templates/main/host/details'),
+
   content: function(){
     return App.router.get('mainHostDetailsController.content');
   }.property('App.router.mainHostDetailsController.content'),
+
   maintenance: function(){
     var options = [{action: 'deleteHost', 'label': 'Delete Host'}];
     return options;
   }.property('controller.content')
 });
-
-App.MainHostDetailsOperations = Em.View.extend({
-  content: null,
-  classNames: ['background-operations'],
-  classNameBindings: ['isOpen'],
-  isOpen: false,
-  logDetails: null,
-  isOpenShowLog: false,
-  iconClass: function(){
-    return this.get('isOpen') ? 'icon-minus' : 'icon-plus';
-  }.property('isOpen'),
-  openDetails: function(){
-    this.set('isOpen', !this.get('isOpen'))
-  },
-  showOperationLog:function(){
-    this.set('isOpenShowLog', !this.get('isOpenShowLog'))
-  }
-});

+ 44 - 4
ambari-web/app/views/main/host/summary.js

@@ -20,26 +20,66 @@ var App = require('app');
 
 App.MainHostSummaryView = Em.View.extend({
   templateName: require('templates/main/host/summary'),
+
   content:function(){
     return App.router.get('mainHostDetailsController.content');
   }.property('App.router.mainHostDetailsController.content'),
+
   ComponentButtonView: Em.View.extend({
     content: null,
+
+    /**
+     * Disable element while component is starting/stopping
+     */
+    disabledClass:function(){
+      var workStatus = this.get('content.workStatus');
+      if(['STARTING', 'STOPPING'].contains(workStatus) ){
+        return 'disabled';
+      } else {
+        return '';
+      }
+    }.property('content.workStatus'),
+
     adjustedIndex: function() {
       return this.get('_parentView.contentIndex') + 1;
     }.property(),
+
     positionButton: function() {
       return (this.get("adjustedIndex")%2 == 0) ? true : false;
     }.property('content.id') ,
+
     indicatorClass: function() {
-      return 'components-health health-status-' + this.get('content.workStatus');
+      return 'health-status-' + this.get('content.workStatus');
     }.property('content.workStatus'),
+
     componentCheckStatus : function() {
       return (this.get('content.workStatus') === "STARTED" || this.get('content.workStatus') === "STARTING");
     }.property('content.workStatus'),
-    buttonId: function() {
-      return "component-button-" + this.get('content.id');
-    }.property('content.workStatus'),
+
+    /**
+     * Do blinking for 1 minute
+     */
+    doBlinking : function(){
+      var workStatus = this.get('content.workStatus');
+      var self = this;
+
+      if(['STARTING', 'STOPPING'].contains(workStatus) ){
+        this.$('.components-health').effect("pulsate", null, 1000, function () {
+          self.doBlinking();
+        });
+      }
+    },
+
+    /**
+     * Start blinking when host component is starting/stopping
+     */
+    startBlinking:function(){
+      this.doBlinking();
+    }.observes('content.workStatus'),
+
+    /**
+     * Shows whether we need to show Decommision/Recomission buttons
+     */
     isDataNode: function() {
       return this.get('content.componentName') === 'DataNode';
     }.property('content')

+ 1 - 5
ambari-web/app/views/main/test.js

@@ -20,9 +20,5 @@ var App = require('app');
 
 App.MainTestView = Em.View.extend({
   templateName: require('templates/main/test'),
-  services: App.Service1.find(),
-  hosts: function(){
-      console.log(App.Host.find());
-      return 'hosts';
-  }.property()
+  services: App.Service1.find()
 });

+ 0 - 1
ambari-web/app/views/wizard/step9_view.js

@@ -16,7 +16,6 @@
  * limitations under the License.
  */
 
-
 var App = require('app');
 
 App.WizardStep9View = Em.View.extend({

Some files were not shown because too many files changed in this diff