Browse Source

AMBARI-1058. Implement data loading. (yusaku)

git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/branches/AMBARI-666@1418895 13f79535-47bb-0310-9956-ffa450edef68
Yusaku Sako 12 years ago
parent
commit
3122e9d47d
84 changed files with 3850 additions and 1996 deletions
  1. 2 0
      AMBARI-666-CHANGES.txt
  2. 426 0
      ambari-web/app/assets/data/alerts/alerts.json
  3. 338 0
      ambari-web/app/assets/data/background_operations/list_on_start.json
  4. 225 929
      ambari-web/app/assets/data/dashboard/services.json
  5. 0 320
      ambari-web/app/assets/data/dashboard/servicesHealth.json
  6. 126 0
      ambari-web/app/assets/data/hosts/hosts.json
  7. 12 1
      ambari-web/app/controllers/installer.js
  8. 65 13
      ambari-web/app/controllers/main.js
  9. 7 10
      ambari-web/app/controllers/main/apps_controller.js
  10. 25 2
      ambari-web/app/controllers/main/host.js
  11. 143 2
      ambari-web/app/controllers/main/service/info/configs.js
  12. 1 1
      ambari-web/app/controllers/main/service/info/summary.js
  13. 61 0
      ambari-web/app/controllers/main/service/item.js
  14. 11 10
      ambari-web/app/controllers/wizard/step10_controller.js
  15. 6 1
      ambari-web/app/controllers/wizard/step2_controller.js
  16. 8 8
      ambari-web/app/controllers/wizard/step8_controller.js
  17. 12 12
      ambari-web/app/controllers/wizard/step9_controller.js
  18. 1 1
      ambari-web/app/data/service_components.js
  19. 7 2
      ambari-web/app/initialize.js
  20. 35 0
      ambari-web/app/mappers/alerts_mapper.js
  21. 38 0
      ambari-web/app/mappers/hosts_mapper.js
  22. 45 0
      ambari-web/app/mappers/server_data_mapper.js
  23. 116 0
      ambari-web/app/mappers/services_mapper.js
  24. 22 17
      ambari-web/app/messages.js
  25. 2 1
      ambari-web/app/models.js
  26. 8 104
      ambari-web/app/models/alert.js
  27. 1 7
      ambari-web/app/models/app.js
  28. 16 1
      ambari-web/app/models/job.js
  29. 155 0
      ambari-web/app/models/protoRelations.js
  30. 61 48
      ambari-web/app/models/run.js
  31. 5 2
      ambari-web/app/models/service.js
  32. 12 12
      ambari-web/app/router.js
  33. 0 1
      ambari-web/app/routes/add_host_routes.js
  34. 0 1
      ambari-web/app/routes/add_service_routes.js
  35. 23 17
      ambari-web/app/routes/installer.js
  36. 7 6
      ambari-web/app/routes/main.js
  37. 102 71
      ambari-web/app/styles/application.less
  38. 15 4
      ambari-web/app/styles/apps.less
  39. 2 4
      ambari-web/app/templates/login.hbs
  40. 6 6
      ambari-web/app/templates/main/apps.hbs
  41. 4 4
      ambari-web/app/templates/main/apps/item/bar.hbs
  42. 2 2
      ambari-web/app/templates/main/apps/item/dag.hbs
  43. 2 2
      ambari-web/app/templates/main/apps/list_row.hbs
  44. 26 26
      ambari-web/app/templates/main/background_operations_popup.hbs
  45. 3 3
      ambari-web/app/templates/main/dashboard.hbs
  46. 4 4
      ambari-web/app/templates/main/dashboard/service/hbase.hbs
  47. 4 4
      ambari-web/app/templates/main/dashboard/service/hdfs.hbs
  48. 4 4
      ambari-web/app/templates/main/dashboard/service/hive.hbs
  49. 4 4
      ambari-web/app/templates/main/dashboard/service/mapreduce.hbs
  50. 4 4
      ambari-web/app/templates/main/dashboard/service/oozie.hbs
  51. 4 4
      ambari-web/app/templates/main/dashboard/service/zookeeper.hbs
  52. 9 32
      ambari-web/app/templates/main/host.hbs
  53. 1 1
      ambari-web/app/templates/main/host/details.hbs
  54. 189 104
      ambari-web/app/templates/main/service/info/configs.hbs
  55. 54 6
      ambari-web/app/templates/main/service/info/summary.hbs
  56. 10 21
      ambari-web/app/templates/main/service/item.hbs
  57. 1 1
      ambari-web/app/templates/main/service/menu_item.hbs
  58. 47 0
      ambari-web/app/templates/main/test.hbs
  59. 8 3
      ambari-web/app/templates/wizard/step2.hbs
  60. 1 1
      ambari-web/app/templates/wizard/step9.hbs
  61. 133 3
      ambari-web/app/utils/data_table.js
  62. 11 4
      ambari-web/app/utils/db.js
  63. 1 1
      ambari-web/app/utils/graph.js
  64. 119 0
      ambari-web/app/utils/http_client.js
  65. 36 0
      ambari-web/app/utils/misc.js
  66. 2 0
      ambari-web/app/views.js
  67. 72 0
      ambari-web/app/views/common/combobox.js
  68. 6 1
      ambari-web/app/views/login.js
  69. 3 3
      ambari-web/app/views/main/apps/item/bar_view.js
  70. 12 2
      ambari-web/app/views/main/apps/item/dag_view.js
  71. 127 37
      ambari-web/app/views/main/apps_view.js
  72. 23 27
      ambari-web/app/views/main/dashboard/service.js
  73. 32 12
      ambari-web/app/views/main/host.js
  74. 18 3
      ambari-web/app/views/main/service/info/configs.js
  75. 12 2
      ambari-web/app/views/main/service/info/summary.js
  76. 24 0
      ambari-web/app/views/main/test.js
  77. 39 1
      ambari-web/app/views/wizard/step2_view.js
  78. 2 0
      ambari-web/config.coffee
  79. 1 2
      ambari-web/package.json
  80. 1 1
      ambari-web/pom.xml
  81. 217 0
      ambari-web/vendor/scripts/bootstrap-combobox.js
  82. 53 53
      ambari-web/vendor/scripts/jquery.dataTables.js
  83. 198 0
      ambari-web/vendor/scripts/jquery.periodic.js
  84. 180 0
      ambari-web/vendor/styles/bootstrap-combobox.css

+ 2 - 0
AMBARI-666-CHANGES.txt

@@ -392,6 +392,8 @@ AMBARI-666 branch (unreleased changes)
 
   IMPROVEMENTS
 
+  AMBARI-1058. Implement data loading (yusaku)
+
   AMBARI-956. On unavailability of non-master components, host with least
   number of master components should install all slave and client components. 
   (Jaimin Jetly via yusaku)

+ 426 - 0
ambari-web/app/assets/data/alerts/alerts.json

@@ -0,0 +1,426 @@
+{"alerts": [
+  {
+    "service_description": "Process down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.001 second response time on port 50010",
+    "last_hard_state_change": "1350378326",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878529",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878529",
+    "service_type": "UNKNOWN"
+  },
+  {
+    "service_description": "Storage full",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: Capacity:[], Remaining Capacity:[], percent_full:[0]",
+    "last_hard_state_change": "1350378331",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878395",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878395",
+    "service_type": "UNKNOWN"
+  },
+  {
+    "service_description": "Ganglia [gmetad] Process down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.001 second response time on port 8651",
+    "last_hard_state_change": "1350378335",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878575",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878575",
+    "service_type": "UNKNOWN"
+  },
+  {
+    "service_description": "Ganglia collector [gmond] Process down alert for jobtracker",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.003 second response time on port 8662",
+    "last_hard_state_change": "1350378340",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878575",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878575",
+    "service_type": "UNKNOWN"
+  },
+  {
+    "service_description": "Ganglia collector [gmond] Process down alert for namenode",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.003 second response time on port 8661",
+    "last_hard_state_change": "1350378344",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878575",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878575",
+    "service_type": "UNKNOWN"
+  },
+  {
+    "service_description": "Ganglia collector [gmond] Process down alert for slaves",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.004 second response time on port 8660",
+    "last_hard_state_change": "1350378349",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878575",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878575",
+    "service_type": "UNKNOWN"
+  },
+  {
+    "service_description": "Corrupt\/Missing blocks",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: corrupt_blocks:<0>, missing_blocks:<0>, total_blocks:<135>",
+    "last_hard_state_change": "1350933589",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878469",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "1350933469",
+    "is_flapping": "0",
+    "last_check": "1351878469",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "HDFS Capacity utilization",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: DFSUsedGB:<0>, DFSTotalGB:<784.3>",
+    "last_hard_state_change": "1350378358",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878395",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878395",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "Namenode RPC Latency",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: RpcQueueTime_avg_time:<0> Secs, RpcProcessingTime_avg_time:<0> Secs",
+    "last_hard_state_change": "1350378362",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878395",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878395",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "Percent DataNodes down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: total:<1>, affected:<0>",
+    "last_hard_state_change": "1350378367",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878560",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878560",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "Percent DataNodes storage full",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: total:<1>, affected:<0>",
+    "last_hard_state_change": "1350378371",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878469",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878469",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "JobHistory Web UI down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: Successfully accessed jobhistory Web UI",
+    "last_hard_state_change": "1350378376",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878529",
+    "last_time_warning": "1351216729",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878529",
+    "service_type": "MAPREDUCE"
+  },
+  {
+    "service_description": "JobTracker Web UI down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: Successfully accessed jobtracker Web UI",
+    "last_hard_state_change": "1350378380",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878529",
+    "last_time_warning": "1351216729",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878529",
+    "service_type": "MAPREDUCE"
+  },
+  {
+    "service_description": "Jobtracker CPU utilization",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "2 CPU, average load 3.0% < 200% : OK",
+    "last_hard_state_change": "1350378385",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878395",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878395",
+    "service_type": "MAPREDUCE"
+  },
+  {
+    "service_description": "Jobtracker Process down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.003 second response time on port 50030",
+    "last_hard_state_change": "1351216775",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878575",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "1351216745",
+    "is_flapping": "0",
+    "last_check": "1351878575",
+    "service_type": "MAPREDUCE"
+  },
+  {
+    "service_description": "JobTracker RPC Latency",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: RpcQueueTime_avg_time:<0> Secs, RpcProcessingTime_avg_time:<0.06> Secs",
+    "last_hard_state_change": "1350378394",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878395",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878395",
+    "service_type": "MAPREDUCE"
+  },
+  {
+    "service_description": "Percent TaskTrackers down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: total:<1>, affected:<0>",
+    "last_hard_state_change": "1351216880",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878560",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "1351216850",
+    "is_flapping": "0",
+    "last_check": "1351878560",
+    "service_type": "MAPREDUCE"
+  },
+  {
+    "service_description": "Nagios status log staleness",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "NAGIOS OK: 2 processes, status log updated 9 seconds ago",
+    "last_hard_state_change": "1350937033",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878433",
+    "last_time_warning": "1350936733",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878433",
+    "service_type": "UNKNOWN"
+  },
+  {
+    "service_description": "Namenode Edit logs directory status",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: All Namenode directories are active",
+    "last_hard_state_change": "1350378408",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878560",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878560",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "Namenode Host CPU utilization",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "2 CPU, average load 3.0% < 200% : OK",
+    "last_hard_state_change": "1350378412",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878412",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878412",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "Namenode Process down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.000 second response time on port 8020",
+    "last_hard_state_change": "1350378417",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878559",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878559",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "Namenode Web UI down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: Successfully accessed namenode Web UI",
+    "last_hard_state_change": "1350378421",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878529",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878529",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "Secondary Namenode Process down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.001 second response time on port 50090",
+    "last_hard_state_change": "1350378426",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878560",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878560",
+    "service_type": "HDFS"
+  },
+  {
+    "service_description": "Oozie status check",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "OK: Oozie server status [System mode: NORMAL]",
+    "last_hard_state_change": "1351217029",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878529",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "1351216969",
+    "is_flapping": "0",
+    "last_check": "1351878529",
+    "service_type": "OOZIE"
+  },
+  {
+    "service_description": "Puppet agent down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.001 second response time on port 8139",
+    "last_hard_state_change": "1350378435",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878529",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "0",
+    "is_flapping": "0",
+    "last_check": "1351878529",
+    "service_type": "PUPPET"
+  },
+  {
+    "service_description": "Process down",
+    "host_name": "host",
+    "current_attempt": "1",
+    "current_state": "0",
+    "plugin_output": "TCP OK - 0.000 second response time on port 50060",
+    "last_hard_state_change": "1351216849",
+    "last_hard_state": "0",
+    "last_time_ok": "1351878529",
+    "last_time_warning": "0",
+    "last_time_unknown": "0",
+    "last_time_critical": "1351216789",
+    "is_flapping": "0",
+    "last_check": "1351878529",
+    "service_type": "UNKNOWN"
+  }
+], "hostcounts": {
+  "up_hosts": 1,
+  "down_hosts": 0
+}, "servicestates": {
+  "PUPPET": 0,
+  "MAPREDUCE": "0",
+  "HDFS": "0",
+  "OOZIE": "0"
+}}

+ 338 - 0
ambari-web/app/assets/data/background_operations/list_on_start.json

@@ -0,0 +1,338 @@
+{
+  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/?fields=tasks/*",
+  "items" : [
+    {
+      "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/3",
+      "Requests" : {
+        "id" : 3,
+        "cluster_name" : "mycluster"
+      },
+      "tasks" : [
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/3/tasks/16",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "QUEUED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 16,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 3,
+            "command" : "STOP",
+            "role" : "NAMENODE",
+            "start_time" : 1352125378300,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/3/tasks/15",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 15,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 3,
+            "command" : "STOP",
+            "role" : "DATANODE",
+            "start_time" : 1352125378280,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/3/tasks/17",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 17,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 3,
+            "command" : "STOP",
+            "role" : "SECONDARY_NAMENODE",
+            "start_time" : 1352125378315,
+            "stage_id" : 1
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2",
+      "Requests" : {
+        "id" : 2,
+        "cluster_name" : "mycluster"
+      },
+      "tasks" : [
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/11",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 11,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 2,
+            "command" : "START",
+            "role" : "JOBTRACKER",
+            "start_time" : 1352119106491,
+            "stage_id" : 2
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/14",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 14,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 2,
+            "command" : "EXECUTE",
+            "role" : "MAPREDUCE_SERVICE_CHECK",
+            "start_time" : 1352119157294,
+            "stage_id" : 3
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/13",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 13,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 2,
+            "command" : "START",
+            "role" : "TASKTRACKER",
+            "start_time" : 1352119106518,
+            "stage_id" : 2
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/12",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 12,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 2,
+            "command" : "START",
+            "role" : "SECONDARY_NAMENODE",
+            "start_time" : 1352119106506,
+            "stage_id" : 2
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/9",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 9,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 2,
+            "command" : "START",
+            "role" : "NAMENODE",
+            "start_time" : 1352119024782,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/8",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 8,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 2,
+            "command" : "START",
+            "role" : "DATANODE",
+            "start_time" : 1352119024765,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/10",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 10,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 1,
+            "request_id" : 2,
+            "command" : "EXECUTE",
+            "role" : "HDFS_SERVICE_CHECK",
+            "start_time" : 1352119106480,
+            "stage_id" : 2
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1",
+      "Requests" : {
+        "id" : 1,
+        "cluster_name" : "mycluster"
+      },
+      "tasks" : [
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/1",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 1,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 2,
+            "request_id" : 1,
+            "command" : "INSTALL",
+            "role" : "DATANODE",
+            "start_time" : 1352118607290,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/4",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 4,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 2,
+            "request_id" : 1,
+            "command" : "INSTALL",
+            "role" : "MAPREDUCE_CLIENT",
+            "start_time" : 1352118607672,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/5",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 5,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 2,
+            "request_id" : 1,
+            "command" : "INSTALL",
+            "role" : "NAMENODE",
+            "start_time" : 1352118607808,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/3",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 3,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 2,
+            "request_id" : 1,
+            "command" : "INSTALL",
+            "role" : "JOBTRACKER",
+            "start_time" : 1352118607566,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/7",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 7,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 2,
+            "request_id" : 1,
+            "command" : "INSTALL",
+            "role" : "TASKTRACKER",
+            "start_time" : 1352118608124,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/2",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 2,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 2,
+            "request_id" : 1,
+            "command" : "INSTALL",
+            "role" : "HDFS_CLIENT",
+            "start_time" : 1352118607469,
+            "stage_id" : 1
+          }
+        },
+        {
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/6",
+          "Tasks" : {
+            "exit_code" : 0,
+            "stdout" : "Output",
+            "status" : "COMPLETED",
+            "stderr" : "none",
+            "host_name" : "dev.hortonworks.com",
+            "id" : 6,
+            "cluster_name" : "mycluster",
+            "attempt_cnt" : 2,
+            "request_id" : 1,
+            "command" : "INSTALL",
+            "role" : "SECONDARY_NAMENODE",
+            "start_time" : 1352118607958,
+            "stage_id" : 1
+          }
+        }
+      ]
+    }
+  ]
+}

+ 225 - 929
ambari-web/app/assets/data/dashboard/services.json

@@ -1,43 +1,36 @@
 {
-  "href" : "http://ambari/clusters/mycluster/services?ServiceInfo/service_name!=MISCELLANEOUS&ServiceInfo/service_name!=DASHBOARD&fields=*,components/*,components/host_components/*",
+  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services?ServiceInfo/service_name!=MISCELLANEOUS&ServiceInfo/service_name!=DASHBOARD&fields=components/host_components/*",
   "items" : [
     {
-      "href" : "http://ambari/clusters/mycluster/services/HBASE",
-      "Services" : {
-        "display_name" : "HBase",
-        "description" : "Apache HDFS-based Non-relational Distributed Database",
-        "attributes" : "{ \"runnable\": true, \"mustInstall\": false, \"editable\": true, \"noDisplay\": false }"
-      },
+      "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/MAPREDUCE",
       "ServiceInfo" : {
         "cluster_name" : "mycluster",
-        "state" : "STARTED",
-        "service_name" : "HBASE"
+        "service_name" : "MAPREDUCE"
       },
       "components" : [
         {
-          "href" : "http://ambari/clusters/mycluster/services/HBASE/components/HBASE_MASTER",
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/MAPREDUCE/components/MAPREDUCE_CLIENT",
           "ServiceComponentInfo" : {
             "cluster_name" : "mycluster",
-            "component_name" : "HBASE_MASTER",
-            "service_name" : "HBASE"
+            "component_name" : "MAPREDUCE_CLIENT",
+            "service_name" : "MAPREDUCE"
           },
           "host_components" : [
             {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/HBASE_MASTER",
+              "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/hosts/dev.hortonworks.com/host_components/MAPREDUCE_CLIENT",
               "HostRoles" : {
                 "cluster_name" : "mycluster",
-                "role_id" : "5",
-                "component_name" : "HBASE_MASTER",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
+                "state" : "INSTALLED",
+                "component_name" : "MAPREDUCE_CLIENT",
+                "host_name" : "dev.hortonworks.com"
               },
               "component" : [
                 {
-                  "href" : "http://ambari/clusters/mycluster/services/HBASE/components/HBASE_MASTER",
+                  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/MAPREDUCE/components/MAPREDUCE_CLIENT",
                   "ServiceComponentInfo" : {
                     "cluster_name" : "mycluster",
-                    "component_name" : "HBASE_MASTER",
-                    "service_name" : "HBASE"
+                    "component_name" : "MAPREDUCE_CLIENT",
+                    "service_name" : "MAPREDUCE"
                   }
                 }
               ]
@@ -45,149 +38,81 @@
           ]
         },
         {
-          "href" : "http://ambari/clusters/mycluster/services/HBASE/components/HBASE_REGIONSERVER",
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/MAPREDUCE/components/JOBTRACKER",
           "ServiceComponentInfo" : {
             "cluster_name" : "mycluster",
-            "component_name" : "HBASE_REGIONSERVER",
-            "service_name" : "HBASE"
+            "component_name" : "JOBTRACKER",
+            "service_name" : "MAPREDUCE"
           },
           "host_components" : [
             {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/HBASE_REGIONSERVER",
+              "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/hosts/dev.hortonworks.com/host_components/JOBTRACKER",
               "HostRoles" : {
                 "cluster_name" : "mycluster",
-                "role_id" : "24",
-                "component_name" : "HBASE_REGIONSERVER",
                 "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/HBASE/components/HBASE_REGIONSERVER",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "HBASE_REGIONSERVER",
-                    "service_name" : "HBASE"
-                  }
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HBASE/components/HBASE_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "HBASE_CLIENT",
-            "service_name" : "HBASE"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/HBASE_CLIENT",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "29",
-                "component_name" : "HBASE_CLIENT",
-                "state" : "INSTALLED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/HBASE/components/HBASE_CLIENT",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "HBASE_CLIENT",
-                    "service_name" : "HBASE"
-                  }
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/PIG",
-      "Services" : {
-        "display_name" : "Pig",
-        "description" : "Platform for Analyzing Large Data Sets",
-        "attributes" : "{ \"runnable\": false, \"mustInstall\": false, \"editable\": true, \"noDisplay\": false }"
-      },
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "state" : "INSTALLED",
-        "service_name" : "PIG"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/PIG/components/PIG_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "PIG_CLIENT",
-            "service_name" : "PIG"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/PIG_CLIENT",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "30",
-                "component_name" : "PIG_CLIENT",
-                "state" : "INSTALLED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
+                "component_name" : "JOBTRACKER",
+                "host_name" : "dev.hortonworks.com"
               },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/PIG/components/PIG_CLIENT",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "PIG_CLIENT",
-                    "service_name" : "PIG"
-                  }
+              "metrics" : {
+                "rpc" : {
+                  "rpcAuthorizationSuccesses" : 0,
+                  "SentBytes" : 32961793,
+                  "rpcAuthorizationFailures" : 0,
+                  "ReceivedBytes" : 95243938,
+                  "NumOpenConnections" : 0,
+                  "callQueueLen" : 0,
+                  "RpcQueueTime_num_ops" : 307991,
+                  "rpcAuthenticationSuccesses" : 0,
+                  "RpcProcessingTime_num_ops" : 307991,
+                  "RpcProcessingTime_avg_time" : 0.02941176470588236,
+                  "rpcAuthenticationFailures" : 0,
+                  "RpcQueueTime_avg_time" : 0.14705882352941177
+                },
+                "jvm" : {
+                  "memHeapCommittedM" : 185.1875,
+                  "logFatal" : 0,
+                  "threadsBlocked" : 0,
+                  "gcCount" : 24,
+                  "threadsWaiting" : 22,
+                  "logWarn" : 0,
+                  "logError" : 0,
+                  "memNonHeapCommittedM" : 23.625,
+                  "memNonHeapUsedM" : 23.226303,
+                  "gcTimeMillis" : 714,
+                  "logInfo" : 3,
+                  "threadsNew" : 0,
+                  "memHeapUsedM" : 27.627754,
+                  "threadsTerminated" : 0,
+                  "threadsTimedWaiting" : 8,
+                  "threadsRunnable" : 6
+                },
+                "metricssystem" : {
+                  "dropped_pub_all" : 0,
+                  "num_sources" : 6,
+                  "publish_max_time" : 6.0,
+                  "publish_num_ops" : 9269,
+                  "snapshot_stdev_time" : 0.0,
+                  "snapshot_num_ops" : 64889,
+                  "publish_stdev_time" : 0.0,
+                  "num_sinks" : 1,
+                  "publish_imin_time" : 0.0,
+                  "snapshot_min_time" : 0.0,
+                  "snapshot_imin_time" : 0.0,
+                  "snapshot_imax_time" : 1.401298464324817E-45,
+                  "publish_avg_time" : 0.0,
+                  "publish_min_time" : 0.0,
+                  "snapshot_max_time" : 177.0,
+                  "publish_imax_time" : 1.401298464324817E-45,
+                  "snapshot_avg_time" : 0.0
                 }
-              ]
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/TEMPLETON",
-      "Services" : {
-        "display_name" : "Templeton",
-        "description" : "Webservice APIs for Apache Hadoop",
-        "attributes" : "{ \"runnable\": true, \"mustInstall\": false, \"editable\": true, \"noDisplay\": false }"
-      },
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "state" : "STARTED",
-        "service_name" : "TEMPLETON"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/TEMPLETON/components/TEMPLETON_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "TEMPLETON_CLIENT",
-            "service_name" : "TEMPLETON"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/TEMPLETON_CLIENT",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "34",
-                "component_name" : "TEMPLETON_CLIENT",
-                "state" : "INSTALLED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
               },
               "component" : [
                 {
-                  "href" : "http://ambari/clusters/mycluster/services/TEMPLETON/components/TEMPLETON_CLIENT",
+                  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/MAPREDUCE/components/JOBTRACKER",
                   "ServiceComponentInfo" : {
                     "cluster_name" : "mycluster",
-                    "component_name" : "TEMPLETON_CLIENT",
-                    "service_name" : "TEMPLETON"
+                    "component_name" : "JOBTRACKER",
+                    "service_name" : "MAPREDUCE"
                   }
                 }
               ]
@@ -195,29 +120,81 @@
           ]
         },
         {
-          "href" : "http://ambari/clusters/mycluster/services/TEMPLETON/components/TEMPLETON_SERVER",
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/MAPREDUCE/components/TASKTRACKER",
           "ServiceComponentInfo" : {
             "cluster_name" : "mycluster",
-            "component_name" : "TEMPLETON_SERVER",
-            "service_name" : "TEMPLETON"
+            "component_name" : "TASKTRACKER",
+            "service_name" : "MAPREDUCE"
           },
           "host_components" : [
             {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/TEMPLETON_SERVER",
+              "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/hosts/dev.hortonworks.com/host_components/TASKTRACKER",
               "HostRoles" : {
                 "cluster_name" : "mycluster",
-                "role_id" : "8",
-                "component_name" : "TEMPLETON_SERVER",
                 "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
+                "component_name" : "TASKTRACKER",
+                "host_name" : "dev.hortonworks.com"
+              },
+              "metrics" : {
+                "rpc" : {
+                  "rpcAuthorizationSuccesses" : 0,
+                  "SentBytes" : 0,
+                  "rpcAuthorizationFailures" : 0,
+                  "ReceivedBytes" : 0,
+                  "NumOpenConnections" : 0,
+                  "callQueueLen" : 0,
+                  "RpcQueueTime_num_ops" : 0,
+                  "rpcAuthenticationSuccesses" : 0,
+                  "RpcProcessingTime_num_ops" : 0,
+                  "RpcProcessingTime_avg_time" : 0.0,
+                  "rpcAuthenticationFailures" : 0,
+                  "RpcQueueTime_avg_time" : 0.0
+                },
+                "jvm" : {
+                  "memHeapCommittedM" : 45.5625,
+                  "logFatal" : 0,
+                  "threadsBlocked" : 0,
+                  "gcCount" : 3433,
+                  "threadsWaiting" : 15,
+                  "logWarn" : 0,
+                  "logError" : 0,
+                  "memNonHeapCommittedM" : 23.1875,
+                  "memNonHeapUsedM" : 21.687134,
+                  "gcTimeMillis" : 2142,
+                  "logInfo" : 3,
+                  "threadsNew" : 0,
+                  "memHeapUsedM" : 3.5596008,
+                  "threadsTerminated" : 0,
+                  "threadsTimedWaiting" : 6,
+                  "threadsRunnable" : 6
+                },
+                "metricssystem" : {
+                  "dropped_pub_all" : 0,
+                  "num_sources" : 6,
+                  "publish_max_time" : 21.0,
+                  "publish_num_ops" : 9267,
+                  "snapshot_stdev_time" : 0.0,
+                  "snapshot_num_ops" : 64875,
+                  "publish_stdev_time" : 0.0,
+                  "num_sinks" : 1,
+                  "publish_imin_time" : 1.0,
+                  "snapshot_min_time" : 0.0,
+                  "snapshot_imin_time" : 0.0,
+                  "snapshot_imax_time" : 1.401298464324817E-45,
+                  "publish_avg_time" : 1.0,
+                  "publish_min_time" : 0.0,
+                  "snapshot_max_time" : 5.0,
+                  "publish_imax_time" : 1.0,
+                  "snapshot_avg_time" : 0.0
+                }
               },
               "component" : [
                 {
-                  "href" : "http://ambari/clusters/mycluster/services/TEMPLETON/components/TEMPLETON_SERVER",
+                  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/MAPREDUCE/components/TASKTRACKER",
                   "ServiceComponentInfo" : {
                     "cluster_name" : "mycluster",
-                    "component_name" : "TEMPLETON_SERVER",
-                    "service_name" : "TEMPLETON"
+                    "component_name" : "TASKTRACKER",
+                    "service_name" : "MAPREDUCE"
                   }
                 }
               ]
@@ -227,42 +204,35 @@
       ]
     },
     {
-      "href" : "http://ambari/clusters/mycluster/services/ZOOKEEPER",
-      "Services" : {
-        "display_name" : "ZooKeeper",
-        "description" : "Centralized Service for Configuration Management and Distribution Synchronization",
-        "attributes" : "{ \"runnable\": true, \"mustInstall\": false, \"editable\": false, \"noDisplay\": false }"
-      },
+      "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/HDFS",
       "ServiceInfo" : {
         "cluster_name" : "mycluster",
-        "state" : "STARTED",
-        "service_name" : "ZOOKEEPER"
+        "service_name" : "HDFS"
       },
       "components" : [
         {
-          "href" : "http://ambari/clusters/mycluster/services/ZOOKEEPER/components/ZOOKEEPER_SERVER",
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/HDFS/components/SECONDARY_NAMENODE",
           "ServiceComponentInfo" : {
             "cluster_name" : "mycluster",
-            "component_name" : "ZOOKEEPER_SERVER",
-            "service_name" : "ZOOKEEPER"
+            "component_name" : "SECONDARY_NAMENODE",
+            "service_name" : "HDFS"
           },
           "host_components" : [
             {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/ZOOKEEPER_SERVER",
+              "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/hosts/dev.hortonworks.com/host_components/SECONDARY_NAMENODE",
               "HostRoles" : {
                 "cluster_name" : "mycluster",
-                "role_id" : "4",
-                "component_name" : "ZOOKEEPER_SERVER",
                 "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
+                "component_name" : "SECONDARY_NAMENODE",
+                "host_name" : "dev.hortonworks.com"
               },
               "component" : [
                 {
-                  "href" : "http://ambari/clusters/mycluster/services/ZOOKEEPER/components/ZOOKEEPER_SERVER",
+                  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/HDFS/components/SECONDARY_NAMENODE",
                   "ServiceComponentInfo" : {
                     "cluster_name" : "mycluster",
-                    "component_name" : "ZOOKEEPER_SERVER",
-                    "service_name" : "ZOOKEEPER"
+                    "component_name" : "SECONDARY_NAMENODE",
+                    "service_name" : "HDFS"
                   }
                 }
               ]
@@ -270,111 +240,82 @@
           ]
         },
         {
-          "href" : "http://ambari/clusters/mycluster/services/ZOOKEEPER/components/ZOOKEEPER_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "ZOOKEEPER_CLIENT",
-            "service_name" : "ZOOKEEPER"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/ZOOKEEPER_CLIENT",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "28",
-                "component_name" : "ZOOKEEPER_CLIENT",
-                "state" : "INSTALLED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/ZOOKEEPER/components/ZOOKEEPER_CLIENT",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "ZOOKEEPER_CLIENT",
-                    "service_name" : "ZOOKEEPER"
-                  }
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE",
-      "Services" : {
-        "display_name" : "MapReduce",
-        "description" : "Apache Hadoop Distributed Processing Framework",
-        "attributes" : "{ \"runnable\": true, \"mustInstall\": true, \"editable\": false, \"noDisplay\": false }"
-      },
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "state" : "STARTED",
-        "service_name" : "MAPREDUCE"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE/components/JOBTRACKER",
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/HDFS/components/NAMENODE",
           "ServiceComponentInfo" : {
             "cluster_name" : "mycluster",
-            "component_name" : "JOBTRACKER",
-            "service_name" : "MAPREDUCE"
+            "component_name" : "NAMENODE",
+            "service_name" : "HDFS"
           },
           "host_components" : [
             {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/JOBTRACKER",
+              "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/hosts/dev.hortonworks.com/host_components/NAMENODE",
               "HostRoles" : {
                 "cluster_name" : "mycluster",
-                "role_id" : "3",
-                "component_name" : "JOBTRACKER",
                 "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
+                "component_name" : "NAMENODE",
+                "host_name" : "dev.hortonworks.com"
               },
               "metrics" : {
                 "rpc" : {
-                  "rpcAuthorizationSuccesses" : 8,
-                  "SentBytes" : 187411672,
+                  "rpcAuthorizationSuccesses" : 0,
+                  "SentBytes" : 504011,
                   "rpcAuthorizationFailures" : 0,
-                  "ReceivedBytes" : 570755511,
+                  "ReceivedBytes" : 1055599,
                   "NumOpenConnections" : 0,
                   "callQueueLen" : 0,
-                  "RpcQueueTime_num_ops" : 1751188,
+                  "RpcQueueTime_num_ops" : 3468,
                   "rpcAuthenticationSuccesses" : 0,
-                  "RpcProcessingTime_num_ops" : 1751188,
-                  "RpcProcessingTime_avg_time" : 0.30303030303030304,
+                  "RpcProcessingTime_num_ops" : 3468,
+                  "RpcProcessingTime_avg_time" : 0.0,
                   "rpcAuthenticationFailures" : 0,
-                  "RpcQueueTime_avg_time" : 1.6969696969696975
+                  "RpcQueueTime_avg_time" : 0.6666666666666667
+                },
+                "dfs" : {
+                  "namenode" : {
+                    "AddBlockOps" : 0,
+                    "FileInfoOps" : 0,
+                    "CreateFileOps" : 0,
+                    "GetListingOps" : 0,
+                    "Transactions_num_ops" : 0,
+                    "GetBlockLocations" : 0,
+                    "Syncs_avg_time" : 0.0,
+                    "blockReport_num_ops" : 0,
+                    "Syncs_num_ops" : 0,
+                    "FilesInGetListingOps" : 0,
+                    "Transactions_avg_time" : 0.0,
+                    "FilesCreated" : 0,
+                    "blockReport_avg_time" : 0.0
+                  }
                 },
                 "rpcdetailed" : {
-                  "getProtocolVersion_avg_time" : 0.0,
-                  "getProtocolVersion_num_ops" : 11
+                  "sendHeartbeat_avg_time" : 0.0,
+                  "sendHeartbeat_num_ops" : 3240
                 },
                 "jvm" : {
-                  "memHeapCommittedM" : 185.1875,
+                  "memHeapCommittedM" : 960.0,
                   "logFatal" : 0,
                   "threadsBlocked" : 0,
-                  "gcCount" : 165,
-                  "threadsWaiting" : 59,
+                  "gcCount" : 1,
+                  "threadsWaiting" : 14,
                   "logWarn" : 0,
                   "logError" : 0,
-                  "memNonHeapCommittedM" : 38.722656,
-                  "memNonHeapUsedM" : 25.408173,
-                  "gcTimeMillis" : 3812,
+                  "memNonHeapCommittedM" : 23.1875,
+                  "memNonHeapUsedM" : 20.247017,
+                  "gcTimeMillis" : 55,
                   "logInfo" : 3,
                   "threadsNew" : 0,
-                  "memHeapUsedM" : 150.10947,
+                  "memHeapUsedM" : 136.56186,
                   "threadsTerminated" : 0,
-                  "threadsTimedWaiting" : 10,
+                  "threadsTimedWaiting" : 7,
                   "threadsRunnable" : 6
                 },
                 "metricssystem" : {
                   "dropped_pub_all" : 0,
                   "num_sources" : 6,
-                  "publish_max_time" : 543.0,
-                  "publish_num_ops" : 55219,
+                  "publish_max_time" : 6.0,
+                  "publish_num_ops" : 972,
                   "snapshot_stdev_time" : 0.37796447300922725,
-                  "snapshot_num_ops" : 386539,
+                  "snapshot_num_ops" : 6810,
                   "publish_stdev_time" : 0.0,
                   "num_sinks" : 1,
                   "publish_imin_time" : 0.0,
@@ -383,48 +324,18 @@
                   "snapshot_imax_time" : 1.0,
                   "publish_avg_time" : 0.0,
                   "publish_min_time" : 0.0,
-                  "snapshot_max_time" : 694.0,
+                  "snapshot_max_time" : 10.0,
                   "publish_imax_time" : 1.401298464324817E-45,
-                  "snapshot_avg_time" : 0.14285714285714285
-                }
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE/components/JOBTRACKER",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "JOBTRACKER",
-                    "service_name" : "MAPREDUCE"
-                  }
+                  "snapshot_avg_time" : 0.14285714285714288
                 }
-              ]
-            }
-          ]
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE/components/MAPREDUCE_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "MAPREDUCE_CLIENT",
-            "service_name" : "MAPREDUCE"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/MAPREDUCE_CLIENT",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "27",
-                "component_name" : "MAPREDUCE_CLIENT",
-                "state" : "INSTALLED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
               },
               "component" : [
                 {
-                  "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE/components/MAPREDUCE_CLIENT",
+                  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/HDFS/components/NAMENODE",
                   "ServiceComponentInfo" : {
                     "cluster_name" : "mycluster",
-                    "component_name" : "MAPREDUCE_CLIENT",
-                    "service_name" : "MAPREDUCE"
+                    "component_name" : "NAMENODE",
+                    "service_name" : "HDFS"
                   }
                 }
               ]
@@ -432,66 +343,61 @@
           ]
         },
         {
-          "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE/components/TASKTRACKER",
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/HDFS/components/DATANODE",
           "ServiceComponentInfo" : {
             "cluster_name" : "mycluster",
-            "component_name" : "TASKTRACKER",
-            "service_name" : "MAPREDUCE"
+            "component_name" : "DATANODE",
+            "service_name" : "HDFS"
           },
           "host_components" : [
             {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/TASKTRACKER",
+              "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/hosts/dev.hortonworks.com/host_components/DATANODE",
               "HostRoles" : {
                 "cluster_name" : "mycluster",
-                "role_id" : "22",
-                "component_name" : "TASKTRACKER",
                 "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
+                "component_name" : "DATANODE",
+                "host_name" : "dev.hortonworks.com"
               },
               "metrics" : {
                 "rpc" : {
-                  "rpcAuthorizationSuccesses" : 14,
-                  "SentBytes" : 11141,
+                  "rpcAuthorizationSuccesses" : 0,
+                  "SentBytes" : 0,
                   "rpcAuthorizationFailures" : 0,
-                  "ReceivedBytes" : 40426,
+                  "ReceivedBytes" : 0,
                   "NumOpenConnections" : 0,
                   "callQueueLen" : 0,
-                  "RpcQueueTime_num_ops" : 93,
+                  "RpcQueueTime_num_ops" : 0,
                   "rpcAuthenticationSuccesses" : 0,
-                  "RpcProcessingTime_num_ops" : 93,
-                  "RpcProcessingTime_avg_time" : 0.4,
+                  "RpcProcessingTime_num_ops" : 0,
+                  "RpcProcessingTime_avg_time" : 0.0,
                   "rpcAuthenticationFailures" : 0,
                   "RpcQueueTime_avg_time" : 0.0
                 },
-                "rpcdetailed" : {
-                  "getProtocolVersion_avg_time" : 0.0,
-                  "getProtocolVersion_num_ops" : 14
-                },
                 "jvm" : {
-                  "memHeapCommittedM" : 27.3125,
+                  "memHeapCommittedM" : 45.5625,
                   "logFatal" : 0,
                   "threadsBlocked" : 0,
-                  "gcCount" : 46316,
-                  "threadsWaiting" : 15,
+                  "gcCount" : 14,
+                  "threadsWaiting" : 7,
                   "logWarn" : 0,
                   "logError" : 0,
-                  "memNonHeapCommittedM" : 33.75,
-                  "memNonHeapUsedM" : 23.388573,
-                  "gcTimeMillis" : 367178,
+                  "memNonHeapCommittedM" : 23.1875,
+                  "memNonHeapUsedM" : 18.308372,
+                  "gcTimeMillis" : 67,
                   "logInfo" : 3,
                   "threadsNew" : 0,
-                  "memHeapUsedM" : 23.116539,
+                  "memHeapUsedM" : 2.4481506,
                   "threadsTerminated" : 0,
                   "threadsTimedWaiting" : 7,
-                  "threadsRunnable" : 6
+                  "threadsRunnable" : 7
                 },
                 "metricssystem" : {
                   "dropped_pub_all" : 0,
-                  "num_sources" : 6,
-                  "publish_max_time" : 808.0,
-                  "publish_num_ops" : 55201,
+                  "num_sources" : 5,
+                  "publish_max_time" : 3.0,
+                  "publish_num_ops" : 974,
                   "snapshot_stdev_time" : 0.0,
-                  "snapshot_num_ops" : 386413,
+                  "snapshot_num_ops" : 5841,
                   "publish_stdev_time" : 0.0,
                   "num_sinks" : 1,
                   "publish_imin_time" : 0.0,
@@ -500,161 +406,14 @@
                   "snapshot_imax_time" : 1.401298464324817E-45,
                   "publish_avg_time" : 0.0,
                   "publish_min_time" : 0.0,
-                  "snapshot_max_time" : 656.0,
+                  "snapshot_max_time" : 2.0,
                   "publish_imax_time" : 1.401298464324817E-45,
                   "snapshot_avg_time" : 0.0
                 }
               },
               "component" : [
                 {
-                  "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE/components/TASKTRACKER",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "TASKTRACKER",
-                    "service_name" : "MAPREDUCE"
-                  }
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/SQOOP",
-      "Services" : {
-        "display_name" : "Sqoop",
-        "description" : "Tool for transferring bulk data between Apache Hadoop and structured datastores such as relational databases",
-        "attributes" : "{ \"runnable\": false, \"mustInstall\": false, \"editable\": true, \"noDisplay\": false }"
-      },
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "state" : "INSTALLED",
-        "service_name" : "SQOOP"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/SQOOP/components/SQOOP_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "SQOOP_CLIENT",
-            "service_name" : "SQOOP"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/SQOOP_CLIENT",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "31",
-                "component_name" : "SQOOP_CLIENT",
-                "state" : "INSTALLED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/SQOOP/components/SQOOP_CLIENT",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "SQOOP_CLIENT",
-                    "service_name" : "SQOOP"
-                  }
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/HDFS",
-      "Services" : {
-        "display_name" : "HDFS",
-        "description" : "Apache Hadoop Distributed File System",
-        "attributes" : "{ \"runnable\": true, \"mustInstall\": true, \"editable\": false, \"noDisplay\": false }"
-      },
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "state" : "STARTED",
-        "service_name" : "HDFS"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HDFS/components/DATANODE",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "DATANODE",
-            "service_name" : "HDFS"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/DATANODE",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "23",
-                "component_name" : "DATANODE",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "metrics" : {
-                "rpc" : {
-                  "rpcAuthorizationSuccesses" : 4,
-                  "SentBytes" : 1350,
-                  "rpcAuthorizationFailures" : 0,
-                  "ReceivedBytes" : 2006,
-                  "NumOpenConnections" : 0,
-                  "callQueueLen" : 0,
-                  "RpcQueueTime_num_ops" : 7,
-                  "rpcAuthenticationSuccesses" : 0,
-                  "RpcProcessingTime_num_ops" : 7,
-                  "RpcProcessingTime_avg_time" : 1.0,
-                  "rpcAuthenticationFailures" : 0,
-                  "RpcQueueTime_avg_time" : 0.0
-                },
-                "rpcdetailed" : {
-                  "getProtocolVersion_avg_time" : 0.0,
-                  "getProtocolVersion_num_ops" : 2
-                },
-                "jvm" : {
-                  "memHeapCommittedM" : 84.3125,
-                  "logFatal" : 0,
-                  "threadsBlocked" : 0,
-                  "gcCount" : 1229,
-                  "threadsWaiting" : 8,
-                  "logWarn" : 0,
-                  "logError" : 0,
-                  "memNonHeapCommittedM" : 23.375,
-                  "memNonHeapUsedM" : 21.495056,
-                  "gcTimeMillis" : 8111,
-                  "logInfo" : 3,
-                  "threadsNew" : 0,
-                  "memHeapUsedM" : 28.507965,
-                  "threadsTerminated" : 0,
-                  "threadsTimedWaiting" : 8,
-                  "threadsRunnable" : 12
-                },
-                "metricssystem" : {
-                  "dropped_pub_all" : 0,
-                  "num_sources" : 5,
-                  "publish_max_time" : 501.0,
-                  "publish_num_ops" : 55260,
-                  "snapshot_stdev_time" : 0.408248290463863,
-                  "snapshot_num_ops" : 331565,
-                  "publish_stdev_time" : 0.0,
-                  "num_sinks" : 1,
-                  "publish_imin_time" : 1.0,
-                  "snapshot_min_time" : 0.0,
-                  "snapshot_imin_time" : 0.0,
-                  "snapshot_imax_time" : 1.0,
-                  "publish_avg_time" : 1.0,
-                  "publish_min_time" : 0.0,
-                  "snapshot_max_time" : 585.0,
-                  "publish_imax_time" : 1.0,
-                  "snapshot_avg_time" : 0.16666666666666669
-                }
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/HDFS/components/DATANODE",
+                  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/HDFS/components/DATANODE",
                   "ServiceComponentInfo" : {
                     "cluster_name" : "mycluster",
                     "component_name" : "DATANODE",
@@ -666,7 +425,7 @@
           ]
         },
         {
-          "href" : "http://ambari/clusters/mycluster/services/HDFS/components/HDFS_CLIENT",
+          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/HDFS/components/HDFS_CLIENT",
           "ServiceComponentInfo" : {
             "cluster_name" : "mycluster",
             "component_name" : "HDFS_CLIENT",
@@ -674,17 +433,16 @@
           },
           "host_components" : [
             {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/HDFS_CLIENT",
+              "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/hosts/dev.hortonworks.com/host_components/HDFS_CLIENT",
               "HostRoles" : {
                 "cluster_name" : "mycluster",
-                "role_id" : "26",
-                "component_name" : "HDFS_CLIENT",
                 "state" : "INSTALLED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
+                "component_name" : "HDFS_CLIENT",
+                "host_name" : "dev.hortonworks.com"
               },
               "component" : [
                 {
-                  "href" : "http://ambari/clusters/mycluster/services/HDFS/components/HDFS_CLIENT",
+                  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/services/HDFS/components/HDFS_CLIENT",
                   "ServiceComponentInfo" : {
                     "cluster_name" : "mycluster",
                     "component_name" : "HDFS_CLIENT",
@@ -694,468 +452,6 @@
               ]
             }
           ]
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HDFS/components/SNAMENODE",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "SNAMENODE",
-            "service_name" : "HDFS"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/SNAMENODE",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "2",
-                "component_name" : "SNAMENODE",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/HDFS/components/SNAMENODE",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "SNAMENODE",
-                    "service_name" : "HDFS"
-                  }
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HDFS/components/NAMENODE",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "NAMENODE",
-            "service_name" : "HDFS"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/NAMENODE",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "1",
-                "component_name" : "NAMENODE",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "metrics" : {
-                "rpc" : {
-                  "rpcAuthorizationSuccesses" : 56734,
-                  "SentBytes" : 71919973,
-                  "rpcAuthorizationFailures" : 0,
-                  "ReceivedBytes" : 82615006,
-                  "NumOpenConnections" : 0,
-                  "callQueueLen" : 0,
-                  "RpcQueueTime_num_ops" : 407816,
-                  "rpcAuthenticationSuccesses" : 0,
-                  "RpcProcessingTime_num_ops" : 407816,
-                  "RpcProcessingTime_avg_time" : 0.0,
-                  "rpcAuthenticationFailures" : 0,
-                  "RpcQueueTime_avg_time" : 0.0
-                },
-                "dfs" : {
-                  "namenode" : {
-                    "AddBlockOps" : 178,
-                    "FileInfoOps" : 91688,
-                    "CreateFileOps" : 181,
-                    "GetListingOps" : 73730,
-                    "Transactions_num_ops" : 973,
-                    "GetBlockLocations" : 45,
-                    "Syncs_avg_time" : 4.0,
-                    "blockReport_num_ops" : 137,
-                    "Syncs_num_ops" : 587,
-                    "FilesInGetListingOps" : 188175,
-                    "Transactions_avg_time" : 0.0,
-                    "FilesCreated" : 314,
-                    "blockReport_avg_time" : 1.0
-                  }
-                },
-                "rpcdetailed" : {
-                  "addBlock_avg_time" : 0.0,
-                  "rollFsImage_num_ops" : 26,
-                  "getListing_num_ops" : 82658,
-                  "renewLease_avg_time" : 0.0,
-                  "sendHeartbeat_num_ops" : 183761,
-                  "create_avg_time" : 2.0,
-                  "fsync_num_ops" : 8,
-                  "blockReport_num_ops" : 154,
-                  "create_num_ops" : 181,
-                  "getEditLogSize_num_ops" : 1837,
-                  "rollEditLog_num_ops" : 26,
-                  "rollFsImage_avg_time" : 237.0,
-                  "getBlockLocations_num_ops" : 45,
-                  "getFileInfo_avg_time" : 0.0,
-                  "addBlock_num_ops" : 178,
-                  "getProtocolVersion_avg_time" : 0.0,
-                  "getListing_avg_time" : 0.33333333333333337,
-                  "rollEditLog_avg_time" : 36.0,
-                  "getBlockLocations_avg_time" : 0.0,
-                  "blockReceived_avg_time" : 0.0,
-                  "renewLease_num_ops" : 18186,
-                  "getEditLogSize_avg_time" : 0.0,
-                  "getFileInfo_num_ops" : 101504,
-                  "sendHeartbeat_avg_time" : 0.0,
-                  "complete_avg_time" : 12.0,
-                  "fsync_avg_time" : 0.0,
-                  "complete_num_ops" : 183,
-                  "blockReceived_num_ops" : 177,
-                  "getProtocolVersion_num_ops" : 18437,
-                  "blockReport_avg_time" : 1.0
-                },
-                "jvm" : {
-                  "memHeapCommittedM" : 432.0625,
-                  "logFatal" : 0,
-                  "threadsBlocked" : 0,
-                  "gcCount" : 194029,
-                  "threadsWaiting" : 104,
-                  "logWarn" : 0,
-                  "logError" : 0,
-                  "memNonHeapCommittedM" : 36.847656,
-                  "memNonHeapUsedM" : 23.048737,
-                  "gcTimeMillis" : 218543395,
-                  "logInfo" : 3,
-                  "threadsNew" : 0,
-                  "memHeapUsedM" : 93.0164,
-                  "threadsTerminated" : 0,
-                  "threadsTimedWaiting" : 8,
-                  "threadsRunnable" : 10
-                },
-                "metricssystem" : {
-                  "dropped_pub_all" : 0,
-                  "num_sources" : 6,
-                  "publish_max_time" : 2320.0,
-                  "publish_num_ops" : 55266,
-                  "snapshot_stdev_time" : 0.37796447300922725,
-                  "snapshot_num_ops" : 386868,
-                  "publish_stdev_time" : 0.0,
-                  "num_sinks" : 1,
-                  "publish_imin_time" : 0.0,
-                  "snapshot_min_time" : 0.0,
-                  "snapshot_imin_time" : 0.0,
-                  "snapshot_imax_time" : 1.0,
-                  "publish_avg_time" : 0.0,
-                  "publish_min_time" : 0.0,
-                  "snapshot_max_time" : 2770.0,
-                  "publish_imax_time" : 1.401298464324817E-45,
-                  "snapshot_avg_time" : 0.14285714285714288
-                }
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/HDFS/components/NAMENODE",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "NAMENODE",
-                    "service_name" : "HDFS"
-                  }
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/NAGIOS",
-      "Services" : {
-        "display_name" : "Nagios",
-        "description" : "Nagios-based Monitoring for HDP",
-        "attributes" : "{ \"runnable\": true, \"mustInstall\": true, \"editable\": false, \"noDisplay\": false }"
-      },
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "state" : "STARTED",
-        "service_name" : "NAGIOS"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/NAGIOS/components/NAGIOS_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "NAGIOS_SERVER",
-            "service_name" : "NAGIOS"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/NAGIOS_SERVER",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "10",
-                "component_name" : "NAGIOS_SERVER",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/NAGIOS/components/NAGIOS_SERVER",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "NAGIOS_SERVER",
-                    "service_name" : "NAGIOS"
-                  }
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/HIVE",
-      "Services" : {
-        "display_name" : "Hive/HCatalog",
-        "description" : "Hive - Data Warehouse system for Apache Hadoop, HCatalog - Table and Storage Management service for data created using Apache Hadoop",
-        "attributes" : "{ \"runnable\": true, \"mustInstall\": false, \"editable\": true, \"noDisplay\": false }"
-      },
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "state" : "STARTED",
-        "service_name" : "HIVE"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HIVE/components/HIVE_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "HIVE_SERVER",
-            "service_name" : "HIVE"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/HIVE_SERVER",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "7",
-                "component_name" : "HIVE_SERVER",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/HIVE/components/HIVE_SERVER",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "HIVE_SERVER",
-                    "service_name" : "HIVE"
-                  }
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HIVE/components/HIVE_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "HIVE_CLIENT",
-            "service_name" : "HIVE"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/HIVE_CLIENT",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "33",
-                "component_name" : "HIVE_CLIENT",
-                "state" : "INSTALLED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/HIVE/components/HIVE_CLIENT",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "HIVE_CLIENT",
-                    "service_name" : "HIVE"
-                  }
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HIVE/components/HIVE_MYSQL",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "HIVE_MYSQL",
-            "service_name" : "HIVE"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/HIVE_MYSQL",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "35",
-                "component_name" : "HIVE_MYSQL",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/HIVE/components/HIVE_MYSQL",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "HIVE_MYSQL",
-                    "service_name" : "HIVE"
-                  }
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/GANGLIA",
-      "Services" : {
-        "display_name" : "Ganglia",
-        "description" : "Ganglia-based Metrics Collection for HDP",
-        "attributes" : "{ \"runnable\": true, \"mustInstall\": true, \"editable\": false, \"noDisplay\": false }"
-      },
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "state" : "STARTED",
-        "service_name" : "GANGLIA"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/GANGLIA/components/GANGLIA_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "GANGLIA_SERVER",
-            "service_name" : "GANGLIA"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/GANGLIA_SERVER",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "9",
-                "component_name" : "GANGLIA_SERVER",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/GANGLIA/components/GANGLIA_SERVER",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "GANGLIA_SERVER",
-                    "service_name" : "GANGLIA"
-                  }
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/GANGLIA/components/GANGLIA_MONITOR",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "GANGLIA_MONITOR",
-            "service_name" : "GANGLIA"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/GANGLIA_MONITOR",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "25",
-                "component_name" : "GANGLIA_MONITOR",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/GANGLIA/components/GANGLIA_MONITOR",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "GANGLIA_MONITOR",
-                    "service_name" : "GANGLIA"
-                  }
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/OOZIE",
-      "Services" : {
-        "display_name" : "Oozie",
-        "description" : "Workflow/Coordination system to manage Apache Hadoop jobs",
-        "attributes" : "{ \"runnable\": true, \"mustInstall\": false, \"editable\": true, \"noDisplay\": false }"
-      },
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "state" : "STARTED",
-        "service_name" : "OOZIE"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/OOZIE/components/OOZIE_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "OOZIE_SERVER",
-            "service_name" : "OOZIE"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/OOZIE_SERVER",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "6",
-                "component_name" : "OOZIE_SERVER",
-                "state" : "STARTED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/OOZIE/components/OOZIE_SERVER",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "OOZIE_SERVER",
-                    "service_name" : "OOZIE"
-                  }
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/OOZIE/components/OOZIE_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "component_name" : "OOZIE_CLIENT",
-            "service_name" : "OOZIE"
-          },
-          "host_components" : [
-            {
-              "href" : "http://ambari/clusters/mycluster/hosts/ip-10-38-5-128.ec2.internal/host_components/OOZIE_CLIENT",
-              "HostRoles" : {
-                "cluster_name" : "mycluster",
-                "role_id" : "32",
-                "component_name" : "OOZIE_CLIENT",
-                "state" : "INSTALLED",
-                "host_name" : "ip-10-38-5-128.ec2.internal"
-              },
-              "component" : [
-                {
-                  "href" : "http://ambari/clusters/mycluster/services/OOZIE/components/OOZIE_CLIENT",
-                  "ServiceComponentInfo" : {
-                    "cluster_name" : "mycluster",
-                    "component_name" : "OOZIE_CLIENT",
-                    "service_name" : "OOZIE"
-                  }
-                }
-              ]
-            }
-          ]
         }
       ]
     }

+ 0 - 320
ambari-web/app/assets/data/dashboard/servicesHealth.json

@@ -1,320 +0,0 @@
-{
-  "href" : "http://ambari/clusters/mycluster/services?ServiceInfo/service_name!=MISCELLANEOUS&ServiceInfo/service_name!=DASHBOARD&fields=components/ServiceComponentInfo/state",
-  "items" : [
-    {
-      "href" : "http://ambari/clusters/mycluster/services/NAGIOS",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "NAGIOS"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/NAGIOS/components/NAGIOS_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "NAGIOS_SERVER",
-            "service_name" : "NAGIOS"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/TEMPLETON",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "TEMPLETON"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/TEMPLETON/components/TEMPLETON_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "INSTALLED",
-            "component_name" : "TEMPLETON_CLIENT",
-            "service_name" : "TEMPLETON"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/TEMPLETON/components/TEMPLETON_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "TEMPLETON_SERVER",
-            "service_name" : "TEMPLETON"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/HDFS",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "HDFS"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HDFS/components/DATANODE",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "DATANODE",
-            "service_name" : "HDFS"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HDFS/components/NAMENODE",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "NAMENODE",
-            "service_name" : "HDFS"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HDFS/components/SNAMENODE",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "SNAMENODE",
-            "service_name" : "HDFS"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HDFS/components/HDFS_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "INSTALLED",
-            "component_name" : "HDFS_CLIENT",
-            "service_name" : "HDFS"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/SQOOP",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "SQOOP"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/SQOOP/components/SQOOP_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "INSTALLED",
-            "component_name" : "SQOOP_CLIENT",
-            "service_name" : "SQOOP"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/PIG",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "PIG"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/PIG/components/PIG_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "INSTALLED",
-            "component_name" : "PIG_CLIENT",
-            "service_name" : "PIG"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/HBASE",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "HBASE"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HBASE/components/HBASE_REGIONSERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "HBASE_REGIONSERVER",
-            "service_name" : "HBASE"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HBASE/components/HBASE_MASTER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "HBASE_MASTER",
-            "service_name" : "HBASE"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HBASE/components/HBASE_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "INSTALLED",
-            "component_name" : "HBASE_CLIENT",
-            "service_name" : "HBASE"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/ZOOKEEPER",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "ZOOKEEPER"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/ZOOKEEPER/components/ZOOKEEPER_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "INSTALLED",
-            "component_name" : "ZOOKEEPER_CLIENT",
-            "service_name" : "ZOOKEEPER"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/ZOOKEEPER/components/ZOOKEEPER_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "ZOOKEEPER_SERVER",
-            "service_name" : "ZOOKEEPER"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "MAPREDUCE"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE/components/MAPREDUCE_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "INSTALLED",
-            "component_name" : "MAPREDUCE_CLIENT",
-            "service_name" : "MAPREDUCE"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE/components/JOBTRACKER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "JOBTRACKER",
-            "service_name" : "MAPREDUCE"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/MAPREDUCE/components/TASKTRACKER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "TASKTRACKER",
-            "service_name" : "MAPREDUCE"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/HIVE",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "HIVE"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HIVE/components/HIVE_MYSQL",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "HIVE_MYSQL",
-            "service_name" : "HIVE"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HIVE/components/HIVE_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "INSTALLED",
-            "component_name" : "HIVE_CLIENT",
-            "service_name" : "HIVE"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/HIVE/components/HIVE_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "HIVE_SERVER",
-            "service_name" : "HIVE"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/GANGLIA",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "GANGLIA"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/GANGLIA/components/GANGLIA_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "GANGLIA_SERVER",
-            "service_name" : "GANGLIA"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/GANGLIA/components/GANGLIA_MONITOR",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "GANGLIA_MONITOR",
-            "service_name" : "GANGLIA"
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://ambari/clusters/mycluster/services/OOZIE",
-      "ServiceInfo" : {
-        "cluster_name" : "mycluster",
-        "service_name" : "OOZIE"
-      },
-      "components" : [
-        {
-          "href" : "http://ambari/clusters/mycluster/services/OOZIE/components/OOZIE_CLIENT",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "INSTALLED",
-            "component_name" : "OOZIE_CLIENT",
-            "service_name" : "OOZIE"
-          }
-        },
-        {
-          "href" : "http://ambari/clusters/mycluster/services/OOZIE/components/OOZIE_SERVER",
-          "ServiceComponentInfo" : {
-            "cluster_name" : "mycluster",
-            "state" : "STARTED",
-            "component_name" : "OOZIE_SERVER",
-            "service_name" : "OOZIE"
-          }
-        }
-      ]
-    }
-  ]
-}

+ 126 - 0
ambari-web/app/assets/data/hosts/hosts.json

@@ -0,0 +1,126 @@
+{
+  "href" : "http://localhost:8080/api/hosts?fields=*",
+  "items" : [
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host01",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.1"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host02",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.2"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host03",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.3"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host04",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.4"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host05",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.5"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host06",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.6"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host07",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.7"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host08",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.8"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host09",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.9"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host10",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.10"
+      }
+    },
+    {
+      "href" : "http://localhost:8080/api/hosts/host1",
+      "Hosts" : {
+        "cpu_count" : 1,
+        "total_mem" : 2055208,
+        "os_arch" : "x86_64",
+        "host_name" : "host11",
+        "os_type" : "centos6",
+        "ip" : "10.0.2.11"
+      }
+    }
+  ]
+}

+ 12 - 1
ambari-web/app/controllers/installer.js

@@ -77,9 +77,20 @@ App.InstallerController = Em.Controller.extend({
    * @param completed
    */
   currentStep: function () {
-    return App.get('router').getInstallerCurrentStep();
+    return App.get('router').getWizardCurrentStep('installer');
   }.property(),
 
+  /**
+   * Set current step to new value.
+   * Method moved from App.router.setInstallerCurrentStep
+   * @param currentStep
+   * @param completed
+   */
+  setCurrentStep: function (currentStep, completed) {
+    App.db.setWizardCurrentStep('installer', currentStep, completed);
+    this.set('currentStep', currentStep);
+  },
+
   clusters: null,
 
   isStep1: function () {

+ 65 - 13
ambari-web/app/controllers/main.js

@@ -21,11 +21,14 @@ require('models/background_operation');
 
 App.MainController = Em.Controller.extend({
   name: 'mainController',
-  backgroundOperations: null,
+  backgroundOperations: [],
+  backgroundOperationsCount : 0,
+  backgroundOperationsUrl : '',
   intervalId: false,
-  updateOperationsInterval: 8000,
+  updateOperationsInterval: 6000,
 
   startLoadOperationsPeriodically: function() {
+    this.loadBackgroundOperations();
     this.intervalId = setInterval(this.loadBackgroundOperations, this.get('updateOperationsInterval'));
   },
   stopLoadOperationsPeriodically:function () {
@@ -36,19 +39,68 @@ App.MainController = Em.Controller.extend({
   },
   loadBackgroundOperations: function(){
     var self = App.router.get('mainController');
-    jQuery.getJSON('data/hosts/background_operations/bg_operations.json',
-      function (data) {
-        var backgroundOperations = self.get('backgroundOperations');
-        if(!backgroundOperations || self.get('backgroundOperationsCount') >= 6)
-          self.set('backgroundOperations', data);
-        else backgroundOperations.tasks.pushObjects(data['tasks'])
-      }
-    )
+
+    var url = self.get('backgroundOperationsUrl');
+    if(!url){
+      //cache url, not to execute <code>getClusterName</code> everytime
+      url = (App.testMode) ?
+        '/data/background_operations/list_on_start.json' :
+        '/api/clusters/' + App.router.getClusterName() + '/requests/?fields=tasks/*&tasks/Tasks/status!=COMPLETED';
+      self.set('backgroundOperationsUrl', url);
+    }
+
+    $.ajax({
+      type: "GET",
+      url: url,
+      dataType: 'json',
+      timeout: 5000,
+      success: function (data) {
+        self.updateBackgroundOperations(data);
+      },
+
+      error: function (request, ajaxOptions, error) {
+        //do something
+      },
+
+      statusCode: require('data/statusCodes')
+    });
   },
 
-  backgroundOperationsCount: function() {
-    return this.get('backgroundOperations.tasks.length');
-  }.property('backgroundOperations.tasks.length'),
+  /**
+   * Add new operations to <code>this.backgroundOperations</code> variable
+   * @param data json loaded from server
+   */
+  updateBackgroundOperations : function(data){
+    var runningTasks = [];
+    data.items.forEach(function (item) {
+      item.tasks.forEach(function (task) {
+        if (task.Tasks.status == 'QUEUED') {
+          runningTasks.push(task.Tasks);
+        }
+      });
+    });
+
+    var currentTasks = this.get('backgroundOperations');
+
+    runningTasks.forEach(function(item){
+      var task = currentTasks.findProperty('id', item.id);
+      if(task){
+        currentTasks[currentTasks.indexOf(task)] = item;
+      } else {
+        currentTasks.pushObject(item);
+      }
+    });
+
+    for(var i = currentTasks.length-1; i>=0; i--){
+      var isTaskFinished = !runningTasks.someProperty('id', currentTasks[i].id);
+      if(isTaskFinished){
+        currentTasks.removeAt(i);
+      }
+    }
+
+    this.set('backgroundOperationsCount', currentTasks.length);
+
+  },
 
   showBackgroundOperationsPopup: function(){
     App.ModalPopup.show({

+ 7 - 10
ambari-web/app/controllers/main/apps_controller.js

@@ -68,13 +68,16 @@ App.MainAppsController = Em.ArrayController.extend({
     });
     return r;
   },
+  lastStarClicked: -1,
   /**
    * Click on star on table row
    * @return {Boolean} false for prevent default event handler
    */
-  starClick: function() {
-    event.srcElement.classList.toggle('stared');
-    var id = parseInt(event.srcElement.parentNode.childNodes[1].innerText);
+  starClick: function(event) {
+    event.target.classList.toggle('stared');
+    var cell = event.target.parentNode.parentNode;
+    var row = cell.parentNode;
+    var id = parseInt(jQuery(event.target).parent().children(1).text());
     if (!this.issetStaredRun(id)) {
       this.get('staredRuns').push(this.getRunById(id));
     }
@@ -85,13 +88,7 @@ App.MainAppsController = Em.ArrayController.extend({
       }
     }
     this.set('staredRunsLength', this.get('staredRuns').length);
+    this.set('lastStarClicked', id);
     return false;
-  },
-  /**
-   * Flush all starred runs
-   */
-  clearStars: function() {
-    this.set('staredRuns', []);
-    this.set('staredRunsLength', 0);
   }
 })

+ 25 - 2
ambari-web/app/controllers/main/host.js

@@ -35,6 +35,27 @@ App.MainHostController = Em.ArrayController.extend(App.Pagination, {
   rangeStart:0,
   allChecked:false,
   selectedHostsIds:[],
+  selectedRack:null,
+  assignHostsToRack:function () {
+    var selectedRack = this.get('selectedRack');
+    var sureMessage = this.t('hosts.assignToRack.sure');
+    var hostsIds = this.get('selectedHostsIds');
+
+    var hostString = hostsIds.length + " " + this.t(hostsIds.length > 1 ? "host.plural" : "host.singular");
+
+    if (selectedRack.constructor == 'App.Cluster' && hostsIds.length
+      && confirm(sureMessage.format(hostString, selectedRack.get('clusterName')))) {
+      this.get('content').forEach(function (host) {
+        if (host.get('isChecked')) {
+          host.set('cluster', selectedRack);
+          host.set('isChecked', false);
+        }
+      })
+      this.set('selectedHostsIds', []);
+    }
+
+  }.observes('selectedRack'),
+
   sortingAsc:true,
   isSort:false,
   sortClass:function () {
@@ -83,12 +104,14 @@ App.MainHostController = Em.ArrayController.extend(App.Pagination, {
   onHostChecked:function (host) {
     var selected = this.get('selectedHostsIds');
     host.set('isChecked', !host.get('isChecked'));
-    if (host.get('isChecked')) selected.push(host.get('id'));
-    else {
+    if (host.get('isChecked')) {
+      selected.push(host.get('id'));
+    } else {
       var index = selected.indexOf(host.get('id'));
       if (index != -1) selected.splice(index, 1);
     }
     this.set('isDisabled', selected.length == 0);
+    this.propertyDidChange('selectedHostsIds');
   },
 
   changeSelectedHosts:function () {

+ 143 - 2
ambari-web/app/controllers/main/service/info/configs.js

@@ -17,8 +17,149 @@
  */
 
 var App = require('app');
+require('controllers/wizard/slave_component_groups_controller');
 
 App.MainServiceInfoConfigsController = Em.Controller.extend({
   name: 'mainServiceInfoConfigsController',
-  content: 'Configs'
-})
+  stepConfigs: [], //contains all field properties that are viewed in this service
+  selectedService: null,
+  serviceConfigs: require('data/service_configs'),
+
+  isSubmitDisabled: function () {
+    return !this.stepConfigs.everyProperty('errorCount', 0);
+  }.property('stepConfigs.@each.errorCount'),
+
+  slaveComponentHosts : function(){
+    console.log('slaveComponentHosts');
+    console.log(App.db.getSlaveComponentHosts());
+    return App.db.getSlaveComponentHosts();
+  }.property('content'),
+
+  clearStep: function () {
+    this.get('stepConfigs').clear();
+  },
+
+  serviceConfigProperties: function() {
+    console.log('serviceConfigProperties');
+    console.log(App.db.getServiceConfigProperties());
+    return App.db.getServiceConfigProperties();
+  }.property('content'),
+
+  /**
+   * On load function
+   */
+  loadStep: function () {
+    console.log("TRACE: Loading configure for service");
+
+    this.clearStep();
+    this.renderServiceConfigs(this.serviceConfigs);
+
+    var storedServices = this.get('serviceConfigProperties');
+    if (storedServices) {
+      var configs = new Ember.Set();
+
+      // for all services`
+      this.get('stepConfigs').forEach(function (_content) {
+        //for all components
+        _content.get('configs').forEach(function (_config) {
+
+          var componentVal = storedServices.findProperty('name', _config.get('name'));
+          //if we have config for specified component
+          if(componentVal){
+
+            //set it
+            _config.set('value', componentVal.value)
+          }
+
+        }, this);
+      }, this);
+    }
+
+    console.log('---------------------------------------');
+    console.log(this.get('stepConfigs'));
+
+  },
+
+  /**
+   * Render configs for active services
+   * @param serviceConfigs
+   */
+  renderServiceConfigs: function (serviceConfigs) {
+    serviceConfigs.forEach(function (_serviceConfig) {
+      var serviceConfig = App.ServiceConfig.create({
+        serviceName: _serviceConfig.serviceName,
+        displayName: _serviceConfig.displayName,
+        configCategories: _serviceConfig.configCategories,
+        configs: []
+      });
+
+      if (this.get('content.serviceName') && this.get('content.serviceName').toUpperCase() === serviceConfig.serviceName) {
+        this.loadComponentConfigs(_serviceConfig, serviceConfig);
+
+        console.log('pushing ' + serviceConfig.serviceName);
+        this.get('stepConfigs').pushObject(serviceConfig);
+
+      } else {
+        console.log('skipping ' + serviceConfig.serviceName);
+      }
+    }, this);
+
+    this.set('selectedService', this.get('stepConfigs').objectAt(0));
+  },
+
+  /**
+   * Load child components to service config object
+   * @param _componentConfig
+   * @param componentConfig
+   */
+  loadComponentConfigs: function (_componentConfig, componentConfig) {
+    _componentConfig.configs.forEach(function (_serviceConfigProperty) {
+      var serviceConfigProperty = App.ServiceConfigProperty.create(_serviceConfigProperty);
+      serviceConfigProperty.serviceConfig = componentConfig;
+      serviceConfigProperty.initialValue();
+      componentConfig.configs.pushObject(serviceConfigProperty);
+      serviceConfigProperty.validate();
+    }, this);
+  },
+
+  /**
+   * Save config properties
+   */
+  saveServiceConfigProperties: function () {
+    var serviceConfigProperties = [];
+    this.get('stepConfigs').forEach(function (_content) {
+      _content.get('configs').forEach(function (_configProperties) {
+        var configProperty = {
+          name: _configProperties.get('name'),
+          value: _configProperties.get('value'),
+          service: _configProperties.get('serviceName')
+        };
+        serviceConfigProperties.push(configProperty);
+      }, this);
+
+    }, this);
+
+    App.db.setServiceConfigProperties(serviceConfigProperties);
+    alert('Data saved successfully');
+//    this.set('content.serviceConfigProperties', serviceConfigProperties);
+  }
+});
+
+App.MainServiceSlaveComponentGroupsController = App.SlaveComponentGroupsController.extend({
+  name: 'mainServiceSlaveComponentGroupsController',
+  contentBinding: 'App.router.mainServiceInfoConfigsController.slaveComponentHosts',
+  serviceBinding: 'App.router.mainServiceInfoConfigsController.selectedService',
+
+  selectedComponentName: function () {
+    switch (App.router.get('mainServiceInfoConfigsController.selectedService.serviceName')) {
+      case 'HDFS':
+        return 'DATANODE';
+      case 'MAPREDUCE':
+        return 'TASKTRACKER';
+      case 'HBASE':
+        return 'HBASE_REGIONSERVER';
+      default:
+        return null;
+    }
+  }.property('App.router.mainServiceInfoConfigsController.selectedService')
+});

+ 1 - 1
ambari-web/app/controllers/main/service/info/summary.js

@@ -24,7 +24,7 @@ App.MainServiceInfoSummaryController = Em.Controller.extend({
     var serviceId = this.get('content.serviceName');
     if (serviceId) {
       return this.get('allAlerts').filter(function (item) {
-        return item.get('serviceType').toLowerCase() == serviceId;
+        return item.get('serviceType') && item.get('serviceType').toLowerCase() == serviceId;
       });
     }
     return [];

+ 61 - 0
ambari-web/app/controllers/main/service/item.js

@@ -69,7 +69,45 @@ App.MainServiceItemController = Em.Controller.extend({
 
     return operation;
   },
+  /**
+   * Send specific command to server
+   * @param url
+   * @param data Object to send
+   */
+  sendCommandToServer : function(url, postData){
+    var url =  (App.testMode) ?
+      '/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';
+
+    $.ajax({
+      type: method,
+      url: url,
+      data: JSON.stringify(postData),
+      dataType: 'json',
+      timeout: 5000,
+      success: function (data) {
+        //do something
+      },
+
+      error: function (request, ajaxOptions, error) {
+        //do something
+      },
+
+      statusCode: require('data/statusCodes')
+    });
+  },
+
+  /**
+   * On click callback for <code>start service</code> button
+   * @param event
+   */
   startService: function (event) {
+    if($(event.target).hasClass('disabled')){
+      return;
+    }
+
     var self = this;
     App.ModalPopup.show({
       header: Em.I18n.t('services.service.confirmation.header'),
@@ -78,6 +116,13 @@ App.MainServiceItemController = Em.Controller.extend({
       secondary: 'No',
       onPrimary: function() {
         self.content.set('workStatus', true);
+
+        self.sendCommandToServer('/services/' + self.get('content.serviceName').toUpperCase(),{
+          ServiceInfo:{
+            state: 'STARTED'
+          }
+        });
+
         var newOperation = self.createBackgroundOperation('Service', 'Start');
         newOperation.detail = "Another detail info";
         self.addBackgroundOperation(newOperation);
@@ -88,7 +133,16 @@ App.MainServiceItemController = Em.Controller.extend({
       }
     });
   },
+
+  /**
+   * On click callback for <code>stop service</code> button
+   * @param event
+   */
   stopService: function (event) {
+    if($(event.target).hasClass('disabled')){
+      return;
+    }
+
     var self = this;
     App.ModalPopup.show({
       header: Em.I18n.t('services.service.confirmation.header'),
@@ -97,6 +151,13 @@ App.MainServiceItemController = Em.Controller.extend({
       secondary: 'No',
       onPrimary: function() {
         self.content.set('workStatus', false);
+
+        self.sendCommandToServer('/services/' + self.get('content.serviceName').toUpperCase(),{
+          ServiceInfo:{
+            state: 'INSTALLED'
+          }
+        });
+
         var newOperation = self.createBackgroundOperation('Service', 'Stop');
         newOperation.detail = "Another detail info";
         self.addBackgroundOperation(newOperation);

+ 11 - 10
ambari-web/app/controllers/wizard/step10_controller.js

@@ -141,33 +141,34 @@ App.WizardStep10Controller = Em.Controller.extend({
 
     console.log('STEP10 master components:  ' + JSON.stringify(components));
     components.forEach(function (_component) {
-      switch (_component.component) {
+      var component = Ember.Object.create(_component);
+      switch (component.component) {
         case 'NAMENODE':
-          this.loadNn(_component);
+          this.loadNn(component);
           break;
         case 'SECONDARY_NAMENODE':
-          this.loadSnn(_component);
+          this.loadSnn(component);
           break;
         case 'JOBTRACKER' :
-          this.loadJt(_component);
+          this.loadJt(component);
           break;
         case 'ZOOKEEPER_SERVER' :
-          this.loadZk(_component);
+          this.loadZk(component);
           break;
         case 'HBASE_MASTER':
-          this.loadHb(_component);
+          this.loadHb(component);
           break;
         case 'HIVE_SERVER':
-          this.loadHiveServer(_component);
+          this.loadHiveServer(component);
           break;
         case 'OOZIE_SERVER':
-          this.loadOozieServer(_component);
+          this.loadOozieServer(component);
           break;
         case 'GANGLIA_SERVER':
-          this.loadGanglia(_component)
+          this.loadGanglia(component)
           break;
         case 'NAGIOS_SERVER':
-          this.loadNagios(_component);
+          this.loadNagios(component);
           break;
       }
     }, this);

+ 6 - 1
ambari-web/app/controllers/wizard/step2_controller.js

@@ -92,7 +92,12 @@ App.WizardStep2Controller = Em.Controller.extend({
   }.property('sshKey', 'manualInstall', 'hasSubmitted'),
 
   localRepoError: function () {
-    if (this.get('hasSubmitted') && this.get('localRepo') && this.get('localRepoPath').trim() === '') {
+    if (
+       // (typeof this.get('localRepoPath') === 'undefined') ||
+        !(/^([-a-z0-9._\/]|%[0-9a-f]{2})*$/i.test(this.get('localRepoPath')) ) ||
+        (this.get('hasSubmitted') && this.get('localRepo') && this.get('localRepoPath').trim() === '' )
+       )
+    {
       return Em.I18n.t('installer.step2.localRepo.error.required');
     }
     return null;

+ 8 - 8
ambari-web/app/controllers/wizard/step8_controller.js

@@ -451,6 +451,7 @@ App.WizardStep8Controller = Em.Controller.extend({
       async: false,
       //accepts: 'text',
       dataType: 'text',
+      data: '{"Clusters": {"version" : "HDP-0.1"}}',
       timeout: 5000,
       success: function (data) {
         var jsonData = jQuery.parseJSON(data);
@@ -511,10 +512,7 @@ App.WizardStep8Controller = Em.Controller.extend({
       var components = serviceComponents.filterProperty('service_name', _service);
       components.forEach(function (_component) {
         console.log("value of component is: " + _component.component_name);
-        // TODO: Skipping CLIENT components as we have issues on the server side for integration purposes
-        if (!_component.component_name.match(/CLIENT$/)) {
-          this.createComponent(_service, _component.component_name);
-        }
+        this.createComponent(_service, _component.component_name);
       }, this);
     }, this);
   },
@@ -582,6 +580,7 @@ App.WizardStep8Controller = Em.Controller.extend({
 
     var masterHosts = this.get('content.masterComponentHosts');
     var slaveHosts = this.get('content.slaveComponentHosts');
+    var clients = this.get('content.clients');
     var allHosts = this.get('content.hostsInfo');
 
     masterHosts.forEach(function (_masterHost) {
@@ -601,8 +600,7 @@ App.WizardStep8Controller = Em.Controller.extend({
           slaveObj.component = _client.component_name;
           _slaveHosts.hosts.forEach(function (_slaveHost) {
             slaveObj.hostName = _slaveHost.hostname;
-            // TODO: Skip creation of clients for integration purposes
-            // this.createHostComponent(slaveObj);
+            this.createHostComponent(slaveObj);
           }, this);
         }, this);
       }
@@ -650,10 +648,12 @@ App.WizardStep8Controller = Em.Controller.extend({
       this.createConfigSite(this.createMrSiteObj('MAPREDUCE'));
     }
     if (selectedServices.someProperty('serviceName', 'HBASE')) {
-      this.createConfigSite(this.createHbaseSiteObj('HBASE'));
+      // TODO
+      // this.createConfigSite(this.createHbaseSiteObj('HBASE'));
     }
     if (selectedServices.someProperty('serviceName', 'HIVE')) {
-      this.createConfigSite(this.createHiveSiteObj('HIVE'));
+      // TODO
+      // this.createConfigSite(this.createHiveSiteObj('HIVE'));
     }
   },
 

+ 12 - 12
ambari-web/app/controllers/wizard/step9_controller.js

@@ -116,33 +116,33 @@ App.WizardStep9Controller = Em.Controller.extend({
           case 'PENDING':
             return 'Preparing to install ' + task.role;
           case 'QUEUED' :
-            return task.role + ' is Queued for installation';
+            return task.role + ' is queued for installation';
           case 'IN_PROGRESS':
             return 'Installing ' + task.role;
           case 'COMPLETED' :
             return 'Successfully installed ' + task.role;
           case 'FAILED':
-            return 'Faliure in installing ' + task.role;
+            return 'Failed to install ' + task.role;
         }
       case 'UNINSTALL':
         switch (task.status) {
           case 'PENDING':
             return 'Preparing to uninstall ' + task.role;
           case 'QUEUED' :
-            return task.role + ' is Queued for uninstallation';
+            return task.role + ' is queued for uninstallation';
           case 'IN_PROGRESS':
-            return 'Unnstalling ' + task.role;
+            return 'Uninstalling ' + task.role;
           case 'COMPLETED' :
             return 'Successfully uninstalled ' + task.role;
           case 'FAILED':
-            return 'Faliure in uninstalling ' + task.role;
+            return 'Failed to uninstall ' + task.role;
         }
       case 'START' :
         switch (task.status) {
           case 'PENDING':
             return 'Preparing to start ' + task.role;
           case 'QUEUED' :
-            return task.role + ' is Queued for starting';
+            return task.role + ' is queued for starting';
           case 'IN_PROGRESS':
             return 'Starting ' + task.role;
           case 'COMPLETED' :
@@ -153,13 +153,13 @@ App.WizardStep9Controller = Em.Controller.extend({
       case 'STOP' :
         switch (task.status) {
           case 'PENDING':
-            return 'Preparing to stop ' + role;
+            return 'Preparing to stop ' + task.role;
           case 'QUEUED' :
-            return task.role + ' is Queued for stopping';
+            return task.role + ' is queued for stopping';
           case 'IN_PROGRESS':
             return 'Stopping ' + task.role;
           case 'COMPLETED' :
-            return role + ' stoped successfully';
+            return role + ' stopped successfully';
           case 'FAILED':
             return role + ' failed to stop';
         }
@@ -168,7 +168,7 @@ App.WizardStep9Controller = Em.Controller.extend({
           case 'PENDING':
             return 'Preparing to execute' + task.role;
           case 'QUEUED' :
-            return task.role + ' is Queued for execution';
+            return task.role + ' is queued for execution';
           case 'IN_PROGRESS':
             return 'Execution of ' + task.role + ' in progress';
           case 'COMPLETED' :
@@ -181,7 +181,7 @@ App.WizardStep9Controller = Em.Controller.extend({
           case 'PENDING':
             return 'Preparing to abort ' + task.role;
           case 'QUEUED' :
-            return task.role + ' is Queued for Aborting';
+            return task.role + ' is queued for aborting';
           case 'IN_PROGRESS':
             return 'Aborting ' + task.role;
           case 'COMPLETED' :
@@ -500,7 +500,7 @@ App.WizardStep9Controller = Em.Controller.extend({
   getUrl: function () {
     var clusterName = this.get('content.cluster.name');
     var requestId = App.db.getClusterStatus().requestId;
-    var url = '/api/clusters/' + clusterName + '/requests/' + requestId;
+    var url = '/api/clusters/' + clusterName + '/requests/' + requestId + '?fields=tasks/*';
     console.log("URL for step9 is: " + url);
     return url;
   },

+ 1 - 1
ambari-web/app/data/service_components.js

@@ -45,7 +45,7 @@ module.exports = new Ember.Set([
   {
     service_name: 'HDFS',
     component_name: 'HDFS_CLIENT',
-    display_name: 'Hadoop Client',
+    display_name: 'HDFS Client',
     isMaster: false,
     isClient: true,
     description: 'Client component for HDFS'

+ 7 - 2
ambari-web/app/initialize.js

@@ -19,8 +19,8 @@
 
 window.App = require('app');
 
-//App.testMode = true;
-App.testMode = false;
+App.testMode = true;
+//App.testMode = false;
 
 require('messages');
 require('utils/data_table');
@@ -31,6 +31,11 @@ require('controllers');
 require('views');
 require('router');
 
+require('mappers/server_data_mapper');
+require('mappers/services_mapper');
+
+require('utils/http_client');
+
 App.initialize();
 
 console.log('after initialize');

+ 35 - 0
ambari-web/app/mappers/alerts_mapper.js

@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//todo: refactor it
+App.alertsMapper = App.ServerDataMapper.create({
+  map: function (json) {
+    if (json.alerts) {
+      $.each(json.alerts, function (i, _alert) {
+        var alert = App.store.createRecord(App.Alert, {
+          alertId: _alert.service_description,
+          title: _alert.service_description,
+          serviceType: _alert.service_type,
+          date: new Date(_alert.last_hard_state_change * 1000),
+          status: _alert.current_state,
+          message: _alert.plugin_output
+        });
+      });
+    }
+  }
+});

+ 38 - 0
ambari-web/app/mappers/hosts_mapper.js

@@ -0,0 +1,38 @@
+/**
+ * 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.
+ */
+
+//todo: refactor it
+App.hostsMapper = App.ServerDataMapper.create({
+  map: function (json) {
+    if (json.items) {
+      json.items.forEach(function (data) {
+        if (data.Hosts) {
+          App.store.createRecord(App.Host, {
+            id: data.Hosts.host_name,
+            hostName: data.Hosts.host_name,
+            cpuCount: data.Hosts.cpu_count,
+            totalMem: data.Hosts.total_mem,
+            osArch: data.Hosts.os_arch,
+            osType: data.Hosts.os_type,
+            ip: data.Hosts.ip
+          });
+        }
+      });
+    }
+  }
+});

+ 45 - 0
ambari-web/app/mappers/server_data_mapper.js

@@ -0,0 +1,45 @@
+/**
+ * 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.ServerDataMapper = Em.Object.extend({
+  jsonKey: false,
+  map: function (json) {
+    if (json) {
+      var model = this.get('model');
+      var jsonKey = this.get('jsonKey');
+
+      if (jsonKey && json[jsonKey]) { // if data come as { hdfs: {...} }
+        json = json[jsonKey];
+      }
+
+      $.each(json, function (field, value) {
+        model.set(field, value);
+      })
+    }
+  }
+});
+
+
+App.QuickDataMapper = App.ServerDataMapper.extend({
+  config : {},
+  map : function(json){
+    //todo: move code here
+  }
+});

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

@@ -0,0 +1,116 @@
+/**
+ * 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.servicesMapper = App.ServerDataMapper.create({
+  map: function (json) {
+    if (json.items) {
+      json.items.forEach(function (data) {
+        if (data.ServiceInfo) {
+          var service = App.store.createRecord(App.Service, {
+            id: data.ServiceInfo.service_name.toLowerCase(),
+            serviceName: data.ServiceInfo.service_name.toLowerCase()
+          });
+
+          if (data.components) {
+            var components = service.get('components');
+            $.each(data.components, function (i, _component) {
+              if (_component.ServiceComponentInfo) {
+                var component = App.store.createRecord(App.ServiceComponent, {
+                  id: _component.ServiceComponentInfo.component_name,
+                  componentName: _component.ServiceComponentInfo.component_name
+                });
+                components.pushObject(component);
+
+                if (_component.host_components) {
+                  var hostComponents = component.get('hostComponents');
+                  $.each(_component.host_components, function (j, _hostComponent) {
+                    var _hostRoles = _hostComponent.HostRoles;
+                    var hostComponent = App.store.createRecord(App.HostComponent, {
+                      hostComponentId: _hostRoles.component_name + ":" + _hostRoles.host_name,
+                      host: App.Host.find(_hostRoles.host_name),
+                      hostName: _hostRoles.host_name,
+                      state: _hostRoles.state
+                    });
+                    hostComponents.pushObject(hostComponent);
+                  });
+                }
+              }
+            });
+          }
+        }
+      });
+    }
+  }
+});
+*/
+App.servicesMapper = App.QuickDataMapper.create({
+  config : {
+    id : 'ServiceInfo.service_name',
+    service_name : 'ServiceInfo.service_name',
+    components_key : 'components',
+    components : {
+        id : 'ServiceComponentInfo.component_name',
+        component_name : 'ServiceComponentInfo.component_name',
+        //service_id : 'ServiceComponentInfo.service_name',
+        service_name : 'ServiceComponentInfo.service_name',
+        state: 'host_components[0].HostRoles.state',
+        host_name: 'host_components[0].HostRoles.host_name'
+      }
+  },
+  map:function(json){
+    if(json.items){
+      var result = [];
+      json.items.forEach(function(item){
+        result.push(this.parseIt(item, this.config));
+      }, this)
+
+      App.store.loadMany(App.Service1, result);
+    }
+  },
+  parseIt : function(data, config){
+    var result = {};
+    for(var i in config){
+      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]));
+        }
+      }
+    }
+    return result;
+  },
+  getJsonProperty:function(json, path){
+    var pathArr = path.split('.');
+    var current = json;
+    while(pathArr.length){
+      if(pathArr[0].substr(-1) == ']'){
+        var index = parseInt(pathArr[0].substr(-2,1));
+        var attr = pathArr[0].substr(0, pathArr[0].length-3);
+        current = current[attr][index];
+      } else {
+        current = current[pathArr[0]];
+      }
+      pathArr.splice(0,1);
+    }
+    return current;
+  }
+});

+ 22 - 17
ambari-web/app/messages.js

@@ -26,16 +26,16 @@ Em.I18n.translations = {
   'login.loginButton': 'Sign in',
   'login.error': 'Invalid username/password combination.',
 
-  'services.nagios.description': 'Nagios desc',
-  'services.ganglia.description': 'Ganglia desc',
-  'services.hdfs.description': 'HDFS desc',
-  'services.mapreduce.description': 'MapReduce desc',
-  'services.sqoop.description': 'Sqoop desc',
-  'services.pig.description': 'Pig desc',
-  'services.hive.description': 'Hive/HCat desc',
-  'services.oozie.description': 'Oozie desc',
+  'services.nagios.description': 'Nagios Monitoring and Alerting system',
+  'services.ganglia.description': 'Ganglia Metrics Collection system',
+  'services.hdfs.description': 'Apache Hadoop Distributed File System',
+  'services.mapreduce.description': 'Apache Hadoop Distributed Processing Framework',
+  'services.sqoop.description': 'Tool for transferring bulk data between Apache Hadoop and structured data stores such as relational databases',
+  'services.pig.description': 'Scripting platform for analyzing large datasets',
+  'services.hive.description': 'Data warehouse system for ad-hoc queries & analysis of large datasets and table & storage management service',
+  'services.oozie.description': 'System for workflow coordination and execution of Apache Hadoop jobs',
   'services.zookeeper.description': 'ZooKeeper desc',
-  'services.hbase.description': 'HBase desc',
+  'services.hbase.description': 'Non-relational distributed database and centralized service for configuration management & synchronization',
 
   'topnav.help.href': 'http://incubator.apache.org/ambari/install.html',
 
@@ -57,7 +57,7 @@ Em.I18n.translations = {
   'installer.step2.targetHosts.info': 'Enter a list of host names, one per line',
   'installer.step2.hostPattern.tooltip.title': 'Pattern Expressions',
   'installer.step2.hostPattern.tooltip.content': 'You can use pattern expressions to specify a number of target hosts.  Explain brackets.',
-  'installer.step2.hostName.error.required': 'Host Names cannot be left empty',
+  'installer.step2.hostName.error.required': 'You must specify at least one host name',
   'installer.step2.hostName.error.notRequired': 'Host Names will be ignored if not using SSH to automatically configure hosts',
   'installer.step2.hostName.error.invalid': 'Invalid Host Name(s) - cannot start or end with a hyphen',
   'installer.step2.sshKey': 'Host Connectivity Information',
@@ -69,7 +69,7 @@ Em.I18n.translations = {
     'Ambari Agent on each host in order for the wizard to perform the necessary configurations and software installs.',
   'installer.step2.advancedOption': 'Advanced Options',
   'installer.step2.repoConf': 'Software Repository Configuration File Path',
-  'installer.step2.localRepo.header': 'Software repository',
+  'installer.step2.localRepo.header': 'Software Repository',
   'installer.step2.localRepo.label': 'Use a local software repository',
   'installer.step2.localRepo.error.required': 'Local repository file path is required',
   'installer.step2.localRepo.info': 'The repository configuration file should be installed on each host in your cluster. ' +
@@ -121,9 +121,9 @@ Em.I18n.translations = {
   'installer.step9.body': 'Wait to complete the cluster installation. Installing, Starting and Testing selected services',
   'installer.step9.status.success': 'Successfully installed the cluster',
   'installer.step9.status.failed': 'Failure in installation',
-  'installer.step9.host.status.success': 'success',
-  'installer.step9.host.status.warning': 'tolerable failures encountered',
-  'installer.step9.host.status.failed': 'failures encountered',
+  'installer.step9.host.status.success': 'Success',
+  'installer.step9.host.status.warning': 'Warnings encountered',
+  'installer.step9.host.status.failed': 'Failures encountered',
   'installer.step9.hostLog.popup.header': 'Tasks executed on ',
 
   'installer.step10.header': 'Summary',
@@ -230,6 +230,9 @@ Em.I18n.translations = {
 
   'services.add.header': 'Add Service Wizard',
 
+  'host.singular': 'host',
+  'host.plural': 'hosts',
+
   'hosts.host.start.popup.header': 'Confirmation',
   'hosts.host.stop.popup.header': 'Confirmation',
   'hosts.host.start.popup.body': 'Are you sure?',
@@ -243,6 +246,10 @@ Em.I18n.translations = {
   'hosts.cant.do.popup.header': 'Operation not allowed',
   'hosts.cant.do.popup.masterList.body': 'You cannot delete this host because it is hosting following master services: {0}.',
   'hosts.cant.do.popup.workingList.body': 'You cannot delete this host because following slave services are not fully stopped or decommissioned: {0}.',
+  'hosts.assignToRack.sure': 'Sure you want to assign {0} to {1}?',
+  'hosts.add.header': 'Add Host Wizard',
+  'hosts.add.step2.warning': 'Hosts are already part of the cluster and will be ignored',
+  'hosts.assignRack': 'Assign Rack',
 
   'charts.horizon.chart.showText': 'show',
   'charts.horizon.chart.hideText': 'hide',
@@ -264,9 +271,6 @@ Em.I18n.translations = {
   'metric.more.network': 'Network',
   'metric.more.process': 'Process',
 
-  'hosts.add.header': 'Add Host Wizard',
-  'hosts.add.step2.warning': 'Hosts are already part of the cluster and will be ignored',
-
   'dashboard.services': 'Services',
   'dashboard.services.hosts': 'Hosts',
   'dashboard.services.uptime': '{0} days {1} hrs {2} mins',
@@ -306,6 +310,7 @@ Em.I18n.translations = {
   'dashboard.services.hbase.regionServersSummary': '{0} live / {1} total',
   'dashboard.services.hbase.chart.label': 'Request Count',
 
+
   'timeRange.presets.1hour': '1h',
   'timeRange.presets.12hour': '12h',
   'timeRange.presets.1day': '1d',

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

@@ -35,4 +35,5 @@ require('models/rack');
 require('models/job');
 require('models/run');
 require('models/app');
-require('models/background_operation');
+require('models/background_operation');
+require('models/protoRelations');

+ 8 - 104
ambari-web/app/models/alert.js

@@ -28,13 +28,13 @@ App.AlertStatus = {
  * which comes back from NAGIOS server.
  */
 App.Alert = DS.Model.extend({
-  title: DS.attr('string', {key: 'service_description'}),
-  serviceType: DS.attr('string', {key: 'service_type'}),
-  date: DS.attr('date', {key: 'last_hard_state_change'}),
-  status: DS.attr('string', {key: 'current_state'}),
-  message: DS.attr('string', {key: 'plugin_output'}),
-  primaryKey: 'last_hard_state_change',
-  alerts: DS.hasMany('App.Alert'),
+  alertId: DS.attr('string'),
+  title: DS.attr('string'),
+  serviceType: DS.attr('string'),
+  date: DS.attr('date'),
+  status: DS.attr('string'),
+  message: DS.attr('string'),
+  primaryKey: 'alertId',
 
   /**
    * Used to show correct icon in UI
@@ -113,104 +113,8 @@ App.Alert = DS.Model.extend({
  * RESTAdapter will contact server.
  */
 App.Alert.reopenClass({
-  url: "http://nagiosserver/hdp/nagios/nagios_alerts.php?q1=alerts&alert_type=all"
+//  url: "http://nagiosserver/hdp/nagios/nagios_alerts.php?q1=alerts&alert_type=all"
 });
 
 App.Alert.FIXTURES = [
-  {
-    id: 1,
-    title: 'Corrupt/Missing Block',
-    service_id: 1,
-    date: 'August 29, 2012 17:00',
-    status: 'corrupt',
-    message: 'message'
-  },
-  {
-    id: 2,
-    title: 'Corrupt/Missing Block',
-    service_id: 1,
-    date: 'August 30, 2012 17:00',
-    status: 'ok',
-    message: 'message'
-  },
-  {
-    id: 3,
-    title: 'Corrupt/Missing Block',
-    service_id: 2,
-    date: 'August 29, 2012 17:00',
-    status: 'corrupt',
-    message: 'message'
-  },
-  {
-    id: 4,
-    title: 'Corrupt/Missing Block',
-    service_id: 2,
-    date: 'August 30, 2012 17:00',
-    status: 'ok',
-    message: 'message'
-  },
-  {
-    id: 5,
-    title: 'Corrupt/Missing Block',
-    service_id: 3,
-    date: 'August 29, 2012 17:00',
-    status: 'corrupt',
-    message: 'message'
-  },
-  {
-    id: 6,
-    title: 'Corrupt/Missing Block',
-    service_id: 3,
-    date: 'August 30, 2012 17:00',
-    status: 'ok',
-    message: 'message'
-  },
-  {
-    id: 7,
-    title: 'Corrupt/Missing Block',
-    service_id: 4,
-    date: 'August 29, 2012 17:00',
-    status: 'corrupt',
-    message: 'message'
-  },
-  {
-    id: 8,
-    title: 'Corrupt/Missing Block',
-    service_id: 4,
-    date: 'August 30, 2012 17:00',
-    status: 'ok',
-    message: 'message'
-  },
-  {
-    id: 9,
-    title: 'Corrupt/Missing Block',
-    service_id: 5,
-    date: 'August 29, 2012 17:00',
-    status: 'corrupt',
-    message: 'message'
-  },
-  {
-    id: 10,
-    title: 'Corrupt/Missing Block',
-    service_id: 5,
-    date: 'August 30, 2012 17:00',
-    status: 'ok',
-    message: 'message'
-  },
-  {
-    id: 11,
-    title: 'Corrupt/Missing Block',
-    service_id: 6,
-    date: 'August 29, 2012 17:00',
-    status: 'corrupt',
-    message: 'message'
-  },
-  {
-    id: 12,
-    title: 'Corrupt/Missing Block',
-    service_id: 6,
-    date: 'August 30, 2012 17:00',
-    status: 'ok',
-    message: 'message'
-  }
 ];

+ 1 - 7
ambari-web/app/models/app.js

@@ -25,13 +25,7 @@ App.App = DS.Model.extend({
   numJobsTotal: DS.attr('number'),
   userName: DS.attr('string'),
   executionTime: DS.attr('string'),
-  runs: DS.hasMany('App.Run'),
-  isRunning: function () {
-    if (!this.get('isLoaded')) {
-      return false;
-    }
-    return this.get('runs').someProperty('isRunning', true);
-  }.property('runs.@each.isRunning')
+  runs: DS.hasMany('App.Run')
 });
 
 App.App.FIXTURES = [

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


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

@@ -0,0 +1,155 @@
+/**
+ * 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.Service1 = DS.Model.extend({
+  //primaryKey : 'serviceName',
+  serviceName: DS.attr('string'),
+  description: DS.attr('string'),
+  components: DS.hasMany('App.Service1Component', { embedded: true }),
+
+  displayName: function() {
+    switch (this.get('serviceName').toLowerCase()) {
+      case 'hdfs':
+        return 'HDFS';
+      case 'mapreduce':
+        return 'MapReduce';
+      case 'hbase':
+        return 'HBase';
+      case 'oozie':
+        return 'Oozie';
+      case 'hive':
+        return 'Hive/HCatalog';
+      case 'zookeeper':
+        return 'ZooKeeper';
+      case 'pig':
+        return 'Pig';
+      case 'sqoop':
+        return 'Sqoop';
+      case 'templeton':
+        return 'Templeton';
+      case 'ganglia':
+        return 'Ganglia';
+      case 'nagios':
+        return 'Nagios';
+    }
+    return this.get('serviceName');
+  }.property('serviceName')
+});
+
+App.Service1.Health = {
+  live:"LIVE",
+  dead:"DEAD",
+  start:"STARTING",
+  stop:"STOPPING"
+};
+
+App.Service1Component = DS.Model.extend({
+  componentName: DS.attr('string'),
+  hostComponents: DS.hasMany('App.HostComponent1'),
+  service: DS.belongsTo('App.Service1'),
+  state : DS.attr('string'),
+  host_name : DS.attr('string'),
+
+  displayName: function() {
+    switch (this.get('componentName')) {
+      case 'NAMENODE':
+        return 'NameNode';
+      case 'SNAMENODE':
+        return 'SNameNode';
+      case 'DATANODE':
+        return 'DataNode';
+      case 'HDFS_CLIENT':
+        return 'HDFS Client';
+      case 'JOBTRACKER':
+        return 'JobTracker';
+      case 'TASKTRACKER':
+        return 'TaskTracker';
+      case 'MAPREDUCE_CLIENT':
+        return 'MapReduce Client';
+      case 'ZOOKEEPER_SERVER':
+        return 'ZooKeeper Server';
+      case 'ZOOKEEPER_CLIENT':
+        return 'ZooKeeper Client';
+      case 'HIVE_SERVER':
+        return 'Hive Server';
+      case 'HIVE_CLIENT':
+        return 'Hive Client';
+      case 'HIVE_MYSQL':
+        return 'Hive MySQL';
+      case 'HBASE_MASTER':
+        return 'HBase Master';
+      case 'HBASE_REGIONSERVER':
+        return 'RegionServer';
+      case 'HBASE_CLIENT':
+        return 'HBase Client';
+      case 'PIG_CLIENT':
+        return 'Pig Client';
+      case 'SQOOP_CLIENT':
+        return 'Sqoop Client';
+      case 'TEMPLETON_SERVER':
+        return 'Templeton Server';
+      case 'TEMPLETON_CLIENT':
+        return 'Templeton Client';
+      case 'OOZIE_SERVER':
+        return 'Oozie Server';
+      case 'OOZIE_CLIENT':
+        return 'Oozie Client';
+      case 'NAGIOS_SERVER':
+        return 'Nagios Server';
+      case 'GANGLIA_SERVER':
+        return 'Ganglia Collector';
+      case 'GANGLIA_MONITOR':
+        return 'Ganglia Monitor';
+    }
+    return this.get('componentName');
+  }.property('componentName'),
+
+  isMaster: function() {
+    switch (this.get('componentName')) {
+      case 'NAMENODE':
+      case 'SNAMENODE':
+      case 'JOBTRACKER':
+      case 'ZOOKEEPER_SERVER':
+      case 'HIVE_SERVER':
+      case 'HBASE_MASTER':
+      case 'NAGIOS_SERVER':
+      case 'GANGLIA_SERVER':
+      case 'OOZIE_SERVER':
+      case 'TEMPLETON_SERVER':
+        return true;
+      default:
+        return false;
+    }
+    return this.get('componentName');
+  }.property('componentName')
+});
+
+App.HostComponent1 = DS.Model.extend({
+  primaryKey: 'hostComponentId',
+  hostComponentId: DS.attr('string'), // component_name + host_name
+  state: DS.attr('string'),
+  host: DS.belongsTo('App.Host'),
+  hostName: DS.attr('string')
+});
+
+// A hack to allow App.<model>.find() with the DS.FixtureAdapter
+App.Service1.FIXTURES = [];
+App.Service1Component.FIXTURES = [];
+App.HostComponent1.FIXTURES = [];

+ 61 - 48
ambari-web/app/models/run.js

@@ -19,6 +19,7 @@
 
 var App = require('app');
 var date = require('utils/date');
+var misc = require('utils/misc');
 
 App.Run = DS.Model.extend({
   runId:DS.attr('string'),
@@ -27,22 +28,77 @@ App.Run = DS.Model.extend({
   userName:DS.attr('string'),
   startTime:DS.attr('string'),
   lastUpdateTime:DS.attr('string'),
-  numJobsTotal:DS.attr('number'),
-  numJobsCompleted:DS.attr('number'),
-  input: DS.attr('number'),
-  output: DS.attr('number'),
   appId:DS.attr('number'),
   jobs:DS.hasMany('App.Job'),
+  /**
+   * Number of comleted jobs.
+   * Field calculates dynamicaly using <code>jobs</code> property
+   */
+  numJobsCompleted: function() {
+    return this.get('jobs').filterProperty('status', 'RUNNING').length;
+  }.property('jobs.@each.status'),
   duration: function() {
     return date.dateFormatInterval(parseInt((parseInt(this.get('lastUpdateTime')) - parseInt(this.get('startTime')))/1000));
   }.property('lastUpdateTime', 'startTime'),
+  /**
+   * Status of running jobs
+   * Field calculates dynamicaly using <code>jobs</code> property
+   */
   isRunning: function () {
     if (!this.get('isLoaded')) {
       return false;
     }
-    console.log('RUN: ' + this.get('id')+' '+this.get('jobs').someProperty('status', 'RUNNING'));
     return this.get('jobs').someProperty('status', 'RUNNING');
   }.property('jobs.@each.status'),
+  /**
+   * Sum of input bandwidth for all jobs
+   * Field calculates dynamicaly using <code>jobs</code> property
+   */
+  input: function () {
+    var sum = 0;
+    this.get('jobs').forEach(
+        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
+   */
+  inputFormatted: function () {
+    var input = this.get('input');
+    input = misc.formatBandwidth(input);
+    return input;
+  }.property('input'),
+  /**
+   * Sum of output bandwidth for all jobs
+   * Field calculates dynamicaly using <code>jobs</code> property
+   */
+  output: function () {
+    var sum = 0;
+    this.get('jobs').forEach(
+        function(item){
+          sum += item.get('output') || 0;
+        });
+    return sum;
+  }.property('jobs.@each.output'),
+  /**
+   *  Sum of output bandwidth for all jobs with appropriate measure
+   *  Field calculates dynamicaly using <code>jobs</code> property
+   */
+  outputFormatted: function () {
+    var output = this.get('output');
+    output = misc.formatBandwidth(output);
+    return output;
+  }.property('output'),
+  /**
+   * Number of jobs on this run
+   * Field calculates dynamicaly using <code>jobs</code> property
+   */
+  numJobsTotal: function() {
+    return this.get('jobs.content').length;
+  }.property('jobs'),
   lastUpdateTimeFormatted: function() {
     return date.dateFormat(this.get('lastUpdateTime'));
   }.property('lastUpdateTime')
@@ -57,10 +113,6 @@ App.Run.FIXTURES = [
     user_name:'user3',
     start_time:1347539541501,
     last_update_time:'1347639541501',
-    num_jobs_total:5,
-    num_jobs_completed:0,
-    input: 11,
-    output: 30,
     app_id:1,
     jobs:[1, 2, 3, 4, 5]
   },
@@ -72,10 +124,6 @@ App.Run.FIXTURES = [
     user_name:'user1',
     start_time:1347339951502,
     last_update_time:'1347439951502',
-    num_jobs_total:5,
-    num_jobs_completed:2,
-    input: 10,
-    output: 30,
     app_id:4,
     jobs:[4, 5, 1, 3, 6]
   },
@@ -87,10 +135,6 @@ App.Run.FIXTURES = [
     user_name:'user2',
     start_time:1341539841503,
     last_update_time:'1341639841503',
-    num_jobs_total:5,
-    num_jobs_completed:0,
-    input: 10,
-    output: 30,
     app_id:1,
     jobs:[6, 7, 8, 9, 10]
   },
@@ -102,10 +146,7 @@ App.Run.FIXTURES = [
     user_name:'user1',
     start_time:1347539591504,
     last_update_time:'1347639591504',
-    num_jobs_total:3,
     num_jobs_completed:0,
-    input: 10,
-    output: 30,
     app_id:2,
     jobs:[8, 9, 10]
   },
@@ -117,10 +158,6 @@ App.Run.FIXTURES = [
     user_name:'user5',
     start_time:1347531541505,
     last_update_time:'1347631541505',
-    num_jobs_total:3,
-    num_jobs_completed:0,
-    input: 10,
-    output: 30,
     app_id:2,
     jobs:[8, 9, 10]
   },
@@ -132,10 +169,6 @@ App.Run.FIXTURES = [
     user_name:'user1',
     start_time:1342439541506,
     last_update_time:'1342639541506',
-    num_jobs_total:3,
-    num_jobs_completed:0,
-    input: 10,
-    output: 30,
     app_id:2,
     jobs:[8, 9, 10]
   },
@@ -147,10 +180,6 @@ App.Run.FIXTURES = [
     user_name:'jsmith',
     start_time:1347539541507,
     last_update_time:'1347639541507',
-    num_jobs_total:4,
-    num_jobs_completed:0,
-    input: 10,
-    output: 30,
     app_id:4,
     jobs:[1, 3, 5, 7]
   },
@@ -162,10 +191,6 @@ App.Run.FIXTURES = [
     user_name:'jsmith',
     start_time:1347539541508,
     last_update_time:'1347639541508',
-    num_jobs_total:4,
-    num_jobs_completed:0,
-    input: 10,
-    output: 30,
     app_id:3,
     jobs:[1, 3, 5, 7]
   },
@@ -177,10 +202,6 @@ App.Run.FIXTURES = [
     user_name:'user1',
     start_time:1347539541509,
     last_update_time:'1347639541509',
-    num_jobs_total:4,
-    num_jobs_completed:0,
-    input: 10,
-    output: 30,
     app_id:3,
     jobs:[1, 3, 5, 7]
   },
@@ -192,10 +213,6 @@ App.Run.FIXTURES = [
     user_name:'user1',
     start_time:1347539541510,
     last_update_time:'1347639541510',
-    num_jobs_total:4,
-    num_jobs_completed:0,
-    input: 10,
-    output: 30,
     app_id:3,
     jobs:[1, 3, 5, 7]
   },
@@ -207,10 +224,6 @@ App.Run.FIXTURES = [
     user_name:'user1',
     start_time:1347539541511,
     last_update_time:'1347639541511',
-    num_jobs_total:4,
-    num_jobs_completed:0,
-    input: 10,
-    output: 30,
     app_id:3,
     jobs:[1, 3, 5, 7]
   }

+ 5 - 2
ambari-web/app/models/service.js

@@ -210,9 +210,10 @@ App.Service.FIXTURES = [
   {
     id:4,
     service_name:'zookeeper',
-    label:'Zookeeper',
+    label:'ZooKeeper',
     health_status:App.Service.Health.stop,
     work_status:false,
+    components:[1, 2, 3],
     alerts:[7, 8]
   },
   {
@@ -221,14 +222,16 @@ App.Service.FIXTURES = [
     label:'Oozie',
     health_status:App.Service.Health.dead,
     work_status:false,
+    components:[8],
     alerts:[9, 10]
   },
   {
     id:6,
     service_name:'hive',
-    label:'Hive',
+    label:'Hive + HCatalog',
     health_status:App.Service.Health.dead,
     work_status:false,
+    components:[5],
     alerts:[11, 12]
   }
 ];

+ 12 - 12
ambari-web/app/router.js

@@ -49,21 +49,21 @@ App.Router = Em.Router.extend({
     });*/
   },
 
-
-  setInstallerCurrentStep: function (currentStep, completed) {
-    App.db.setInstallerCurrentStep(currentStep, completed);
-    this.set('installerController.currentStep', currentStep);
+  /**
+   * Temporary fix for getting cluster name
+   * @return {*}
+   */
+  getClusterName: function(){
+    return App.db.getClusterName();
   },
 
+
+  /**
+   * Get current step of Installer wizard
+   * @return {*}
+   */
   getInstallerCurrentStep: function () {
-    var loginName = this.getLoginName();
-    var currentStep = App.db.getInstallerCurrentStep();
-    console.log('getInstallerCurrentStep: loginName=' + loginName + ", currentStep=" + currentStep);
-    if (!currentStep) {
-      currentStep = '1';
-    }
-    console.log('returning currentStep=' + currentStep);
-    return currentStep;
+    return this.getWizardCurrentStep('installer');
   },
 
   /**

+ 0 - 1
ambari-web/app/routes/add_host_routes.js

@@ -24,7 +24,6 @@ module.exports = Em.Route.extend({
 
     Ember.run.next(function () {
       var addHostController = router.get('addHostController');
-      addHostController.loadAllPriorSteps();
       router.transitionTo('step' + addHostController.get('currentStep'));
     });
 

+ 0 - 1
ambari-web/app/routes/add_service_routes.js

@@ -24,7 +24,6 @@ module.exports = Em.Route.extend({
 
     Ember.run.next(function () {
       var addServiceController = router.get('addServiceController');
-      addServiceController.loadAllPriorSteps();
       router.transitionTo('step' + addServiceController.get('currentStep'));
     });
 

+ 23 - 17
ambari-web/app/routes/installer.js

@@ -28,10 +28,12 @@ module.exports = Em.Route.extend({
     if (router.getAuthenticated()) {
       router.get('mainController').stopLoadOperationsPeriodically();
       console.log('In installer with successful authenticated');
-      // router.loadAllPriorSteps(router.getInstallerCurrentStep());
+
       Ember.run.next(function () {
-        router.transitionTo('step' + router.getInstallerCurrentStep());
+        var installerController = router.get('installerController');
+        router.transitionTo('step' + installerController.get('currentStep'));
       });
+
     } else {
       console.log('In installer but its not authenticated');
       console.log('value of authenticated is: ' + router.getAuthenticated());
@@ -49,7 +51,9 @@ module.exports = Em.Route.extend({
       this._super(router, event);
     } else {
       router.set('backBtnForHigherStep', true);
-      router.transitionTo('step' + router.getInstallerCurrentStep());
+
+      var installerController = router.get('installerController');
+      router.transitionTo('step' + installerController.get('currentStep'));
     }
   },
 
@@ -63,7 +67,7 @@ module.exports = Em.Route.extend({
     connectOutlets: function (router) {
       console.log('in installer.step1:connectOutlets');
       var controller = router.get('installerController');
-      router.setInstallerCurrentStep('1', false);
+      controller.setCurrentStep('1', false);
       controller.loadAllPriorSteps();
       controller.connectOutlet('wizardStep1', controller.get('content'));
     },
@@ -81,10 +85,9 @@ module.exports = Em.Route.extend({
     route: '/step2',
     connectOutlets: function (router, context) {
       router.setNavigationFlow('step2');
-      var controller = router.get('installerController');
-      router.setInstallerCurrentStep('2', false);
 
       var controller = router.get('installerController');
+      controller.setCurrentStep('2', false);
       controller.loadAllPriorSteps();
       controller.connectOutlet('wizardStep2', controller.get('content.hosts'));
     },
@@ -118,7 +121,7 @@ module.exports = Em.Route.extend({
     connectOutlets: function (router) {
       console.log('in installer.step3:connectOutlets');
       var controller = router.get('installerController');
-      router.setInstallerCurrentStep('3', false);
+      controller.setCurrentStep('3', false);
       controller.loadAllPriorSteps();
       controller.connectOutlet('wizardStep3', controller.get('content'));
     },
@@ -149,8 +152,8 @@ module.exports = Em.Route.extend({
     route: '/step4',
     connectOutlets: function (router, context) {
       router.setNavigationFlow('step4');
-      router.setInstallerCurrentStep('4', false);
       var controller = router.get('installerController');
+      controller.setCurrentStep('4', false);
       controller.loadAllPriorSteps();
       controller.loadServices();
       controller.connectOutlet('wizardStep4', controller.get('content.services'));
@@ -173,8 +176,9 @@ module.exports = Em.Route.extend({
     route: '/step5',
     connectOutlets: function (router, context) {
       router.setNavigationFlow('step5');
-      router.setInstallerCurrentStep('5', false);
+
       var controller = router.get('installerController');
+      controller.setCurrentStep('5', false);
       controller.loadAllPriorSteps();
       controller.connectOutlet('wizardStep5', controller.get('content'));
     },
@@ -193,8 +197,9 @@ module.exports = Em.Route.extend({
     route: '/step6',
     connectOutlets: function (router, context) {
       router.setNavigationFlow('step6');
-      router.setInstallerCurrentStep('6', false);
+
       var controller = router.get('installerController');
+      controller.setCurrentStep('6', false);
       controller.loadAllPriorSteps();
       controller.connectOutlet('wizardStep6', controller.get('content'));
     },
@@ -217,7 +222,7 @@ module.exports = Em.Route.extend({
     route: '/step7',
     connectOutlets: function (router, context) {
       var controller = router.get('installerController');
-      router.setInstallerCurrentStep('7', false);
+      controller.setCurrentStep('7', false);
       controller.loadAllPriorSteps();
       controller.connectOutlet('wizardStep7', controller.get('content'));
     },
@@ -235,7 +240,7 @@ module.exports = Em.Route.extend({
     connectOutlets: function (router, context) {
       console.log('in installer.step8:connectOutlets');
       var controller = router.get('installerController');
-      router.setInstallerCurrentStep('8', false);
+      controller.setCurrentStep('8', false);
       controller.loadAllPriorSteps();
       controller.connectOutlet('wizardStep8', controller.get('content'));
     },
@@ -254,7 +259,7 @@ module.exports = Em.Route.extend({
     connectOutlets: function (router, context) {
       console.log('in installer.step9:connectOutlets');
       var controller = router.get('installerController');
-      router.setInstallerCurrentStep('9', false);
+      controller.setCurrentStep('9', false);
       controller.loadAllPriorSteps();
       if (!App.testMode) {              //if test mode is ON don't disable prior steps link.
         controller.setLowerStepsDisable(9);
@@ -262,7 +267,7 @@ module.exports = Em.Route.extend({
       controller.connectOutlet('wizardStep9', controller.get('content'));
     },
     back: Em.Router.transitionTo('step8'),
-    retry: function (router, context) {
+    retry: function (router) {
       var installerController = router.get('installerController');
       var wizardStep9Controller = router.get('wizardStep9Controller');
       installerController.installServices();
@@ -282,16 +287,17 @@ module.exports = Em.Route.extend({
     connectOutlets: function (router, context) {
       console.log('in installer.step10:connectOutlets');
       var controller = router.get('installerController');
-      router.setInstallerCurrentStep('10', false);
+      controller.setCurrentStep('10', false);
       controller.loadAllPriorSteps();
       controller.connectOutlet('wizardStep10',controller.get('content'));
     },
     back: Em.Router.transitionTo('step9'),
     complete: function (router, context) {
       if (true) {   // this function will be moved to installerController where it will validate
-        router.setInstallerCurrentStep('1', true);
+        var controller = router.get('installerController');
+        controller.setCurrentStep('1', false);
         router.setSection('main');
-        router.transitionTo('main');
+        router.transitionTo('main.index');
       } else {
         console.log('cluster installation failure');
       }

+ 7 - 6
ambari-web/app/routes/main.js

@@ -23,9 +23,6 @@ module.exports = Em.Route.extend({
     if (router.getAuthenticated()) {
       router.get('mainController').startLoadOperationsPeriodically();
       // TODO: redirect to last known state
-       Ember.run.next(function () {
-         router.transitionTo('dashboard');
-       });
     } else {
       Ember.run.next(function () {
         router.transitionTo('login');
@@ -38,6 +35,13 @@ module.exports = Em.Route.extend({
     redirectsTo:'dashboard'
   }),
 
+  test: Em.Route.extend({
+    route: '/test',
+    connectOutlets:function (router, context) {
+      router.get('mainController').connectOutlet('mainTest');
+    }
+  }),
+
   connectOutlets:function (router, context) {
     router.get('applicationController').connectOutlet('main');
   },
@@ -320,9 +324,6 @@ module.exports = Em.Route.extend({
     service:Em.Route.extend({
       route:'/:service_id',
       connectOutlets:function (router, service) {
-//        if (service.name == "undefined") {
-//          service = App.Service.find(1);
-//        }
         router.get('mainServiceController').connectOutlet('mainServiceItem', service);
         router.transitionTo('summary');
       },

+ 102 - 71
ambari-web/app/styles/application.less

@@ -212,8 +212,23 @@ h1 {
     padding-left: 0;
   }
   #installOptions {
+    .sshKey-file-view {
+      width: 486px;
+      height: 200px;
+      overflow-y: auto;
+      border: 1px solid #ccc;
+      margin-top: 5px;
+      padding: 8px;
+      font-family: Consolas,"Liberation Mono",Courier,monospace;
+    }
+    .manual-install {
+      margin-top: 10px;
+    }
     #targetHosts {
 
+    }
+    .span6{
+      min-width: 504px;
     }
     #hostConnectivity {
       margin-top: 20px;
@@ -247,68 +262,6 @@ h1 {
   #step6 .pre-scrollable {
     max-height: 440px;
   }
-  #serviceConfig {
-    .accordion-heading {
-      background-color: #f0f0f0;
-    }
-    .accordion-group {
-      margin-bottom: 20px;
-      .control-group {
-        margin: 10px 0;
-      }
-      form {
-        margin-bottom: 0;
-      }
-    }
-    .badge {
-      margin-left: 4px;
-    }
-    .slave-component-group-menu {
-      float: left;
-      .nav {
-        margin-bottom: 10px;
-      }
-      .nav li {
-        position: relative;
-        a {
-          padding-right: 24px;
-        }
-        .icon-remove {
-          border: 1px solid white;
-          position: absolute;
-          right: 7px;
-          top: 10px;
-          z-index: 2;
-          cursor: default;
-          color: #555555;
-        }
-        .icon-remove:hover {
-          border: 1px solid grey;
-        }
-      }
-    }
-    .remove-group-error {
-      display: none;
-    }
-    .add-slave-component-group {
-      margin-bottom: 10px;
-    }
-    .master-host, .master-hosts, .slave-hosts {
-      padding-top: 5px;
-      line-height: 20px;
-    }
-    #attention {
-      margin: 20px 0;
-    }
-    .retyped-password {
-      margin-left: 14px;
-    }
-    #slave-hosts-popup {
-      ul {
-        list-style-type: none;
-      }
-    }
-  }
   #deploy {
     #overallProgress {
     }
@@ -336,6 +289,69 @@ h1 {
   }
 }
 
+#serviceConfig {
+  .accordion-heading {
+    background-color: #f0f0f0;
+  }
+  .accordion-group {
+    margin-bottom: 20px;
+    .control-group {
+      margin: 10px 0;
+    }
+    form {
+      margin-bottom: 0;
+    }
+  }
+  .badge {
+    margin-left: 4px;
+  }
+  .slave-component-group-menu {
+    float: left;
+    .nav {
+      margin-bottom: 10px;
+    }
+    .nav li {
+      position: relative;
+      a {
+        padding-right: 24px;
+      }
+      .icon-remove {
+        border: 1px solid white;
+        position: absolute;
+        right: 7px;
+        top: 10px;
+        z-index: 2;
+        cursor: default;
+        color: #555555;
+      }
+      .icon-remove:hover {
+        border: 1px solid grey;
+      }
+    }
+  }
+  .remove-group-error {
+    display: none;
+  }
+  .add-slave-component-group {
+    margin-bottom: 10px;
+  }
+  .master-host, .master-hosts, .slave-hosts {
+    padding-top: 5px;
+    line-height: 20px;
+  }
+  #attention {
+    margin: 20px 0;
+  }
+  .retyped-password {
+    margin-left: 14px;
+  }
+  #slave-hosts-popup {
+    ul {
+      list-style-type: none;
+    }
+  }
+}
+
 a:focus {
   outline: none;
 }
@@ -491,6 +507,7 @@ a:focus {
   border-collapse: collapse;
 
   td.summary-label {
+    width: 180px;
     text-align: right;
   }
 
@@ -628,16 +645,16 @@ a:focus {
 #services-menu {
   .nav-list {
     .tab-marker-position {
-
       background-position: 6px 5px;
       background-repeat: no-repeat;
       list-style: none;
       height: 20px;
       width: 20px;
-      margin-left: 0; //      padding-left: 30px;
-    //      padding-right: 30px;
-    //      background-position: 12px 9px;
-    //      background-repeat: no-repeat;
+      margin-left: 0;
+      // padding-left: 30px;
+      // padding-right: 30px;
+      // background-position: 12px 9px;
+      // background-repeat: no-repeat;
     }
     .health-status-LIVE {
       .tab-marker-position;
@@ -647,6 +664,9 @@ a:focus {
       .tab-marker-position;
       background-image: @status-dead-marker;
     }
+    .health-status-undefined {
+      .tab-marker-position;
+    }
     li {
       line-height: 24px;
     }
@@ -749,6 +769,15 @@ a:focus {
   .health-status-DEAD-YELLOW {
     background-image: @status-dead-yellow-marker;
   }
+  .host-name-search{
+    position: relative;
+    top: 0px;
+    left: 10px;
+  }
+  .host-name-pos{
+    position: relative;
+    top: 10px;
+  }
   .box-header {
     .btn-group {
       float: left;
@@ -766,7 +795,7 @@ a:focus {
       background: #EDF5FC;
     }
     th, td {
-      width: 130px;
+      width: 82px;
     }
     th.first, td.first {
       width: 30px;
@@ -856,6 +885,9 @@ a:focus {
   }
 
   #host-details {
+
+    margin-top: 27px;
+
     .component-operation-button{
       background-color: #E5E5E5;
       background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#E5E5E5), to(#F1F1F1));
@@ -1580,7 +1612,7 @@ ul.inline li {
 
 #host-details > .host-maintenance {
   text-align: right;
-  margin-top: -20px;
+  margin-top: -28px;
 }
 
 #host-details > .host-maintenance > div {
@@ -1626,9 +1658,8 @@ ul.inline li {
 }
 
 #step8-content {
-  max-height: 570px;
+  max-height: 440px;
 }
-
 #step10-content {
   max-height: 440px;
 }

+ 15 - 4
ambari-web/app/styles/apps.less

@@ -5,9 +5,12 @@
   .table thead th{
     vertical-align:top;
   }
-  .avg-table td {
-    text-align:center;
-    border:none;
+  .avg-table {
+    background-color: #F9F9F9;
+    td {
+      text-align:center;
+      border:none;
+    }
   }
   td.avg-star{
     border-left:1px solid #DDD;
@@ -107,9 +110,17 @@
   }
   #graph1 {
     margin-left: 30px;
+    width: 440px;
+    #legend_container {
+      margin: 40px 0 0 20px;
+    }
   }
   #graph2 {
     margin-right: 30px;
+    width: 500px;
+    #tasks_legend_container {
+      margin: 40px 0 0 20px;
+    }
   }
 
   tr.containerRow > td{
@@ -140,7 +151,7 @@
   td .table-striped tbody
   tr:nth-child(odd) td,
   tr:nth-child(even) th{
-    background: none;
+    background-color: none;
   }
 
   .sorting_asc { background: url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAZAAA/+4ADkFkb2JlAGTAAAAAAf/bAIQAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgICAwMDAwMDAwMDAwEBAQEBAQECAQECAgIBAgIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD/8AAEQgAEwATAwERAAIRAQMRAf/EAHgAAAMBAQAAAAAAAAAAAAAAAAAFCAYKAQACAQUAAAAAAAAAAAAAAAAABQMCBAYHCBAAAQUAAQMEAwAAAAAAAAAAAwECBAUGABESByExIghBMxQRAAIBAwMDAwUAAAAAAAAAAAECAwAEBRESBiExUUHhB2GBIhMU/9oADAMBAAIRAxEAPwDvA8k+Qc54sxGj32qlNi0ucrjTj/JqGlmROyJXQ2u/bOsZTmBExPd70/HXmQcW41lOX5+145h0L391KEHhR3Z28Ii6sx9AKgubiO1gaeU6Io19h9TUg/S/7eP+wia3NbBIFbuqiyn3VTCjIMArHHTJarEDGGiNU8vOKVsc7/VxBuGR3yV683X86/Cq/GpssrhP2S8emiSKRm1JS5VfyLH0WfQug7KwZR0CilWHy39++ObQTgkgeV9ux+xq9uc6U8pLfZzP6mClZpKWrvq1DilJAt4Mewh/0hRyBOsaUMoVKLvXtVU6t6+nL/HZTJYi4/rxU81tdbSu+N2Rtp7jcpB0OnUa9aoeOOVdsgDL4I1pFS+NPHmcsQ2+fw+UpLWOwwwWNVQ1kCaIcgaiONkmLGEZrDDXtcnXo5PfjC+5VybKWrWWSyF5cWbEEpJNI6kqdQSrMRqD1B9KjS2t423xoqt5AArb8QVPRwoo4UUcKK//2Q==) no-repeat 85% 50%; }

+ 2 - 4
ambari-web/app/templates/login.hbs

@@ -26,8 +26,6 @@
     <label>{{t login.username}}</label>
     {{view Ember.TextField valueBinding="loginName" class="span4"}}
     <label>{{t login.password}}</label>
-    {{view Ember.TextField type="password" valueBinding="password" class="span4"}}
-    <div>
-        <a class="btn btn-success" {{action "submit" target="controller"}}>{{t login.loginButton}}</a>
-    </div>
+    {{view view.passTextField type="password" valueBinding="password" class="span4"}}
+        <button class="btn btn-success" {{action "submit" target="controller"}}>{{t login.loginButton}}</button>
 </div>

+ 6 - 6
ambari-web/app/templates/main/apps.hbs

@@ -54,12 +54,12 @@
             </tbody>
   </table>
     <div id="filter_info" class="row">
-      <div class="span3">Show:
-        <a href="javascript:void(0)" class="selected" {{action "changeViewType" target="view"}} data-view-type="all">All ({{view.content.length}})</a> &#124;
-        <a href="javascript:void(0)" {{action "changeViewType" target="view"}} data-view-type="filtered">Filtered ({{view.filtered}})</a> &#124;
-        <a href="javascript:void(0)" {{action "changeViewType" target="view"}} data-view-type="starred">Starred ({{view.staredData.count}})</a>
+      <div class="span3" id="filter_buttons">Show:
+        <a href="javascript:void(0)" class="all selected" {{action "clickViewType" target="view"}} data-view-type="all">All ({{view.content.length}})</a> &#124;
+        <a href="javascript:void(0)" class="filtered" {{action "clickViewType" target="view"}} data-view-type="filtered">Filtered ({{view.filtered}})</a> &#124;
+        <a href="javascript:void(0)" class="stared" {{action "clickViewType" target="view"}} data-view-type="starred">Starred ({{view.staredData.count}})</a>
       </div>
-      <div class="span2"><a href="#" {{action "clearFilters" target="view"}}>Clear filters</a>&nbsp;&#124;&nbsp;<a href="#" {{action "clearStars" target="controller"}}>Clear stars</a></div>
+      <div class="span2"><a href="#" {{action "clearFilters" target="view"}}>Clear filters</a>&nbsp;&#124;&nbsp;<a href="#" {{action "clearStars" target="view"}}>Clear stars</a></div>
     </div>
     <div>
     </div>
@@ -78,7 +78,7 @@
       <th>Run Date</th>
     </tr>
     <tr>
-      <th></th>
+      <th>{{view view.starFilterView viewName="starFilterViewInstance"}}</th>
       <th>{{view view.appidFilterView}}</th>
       <th>{{view view.nameFilterView}}</th>
       <th>{{view view.typeSelectView}}</th>

+ 4 - 4
ambari-web/app/templates/main/apps/item/bar.hbs

@@ -29,26 +29,26 @@
 </div>
 <div></div>
 <div id="graph1" class="pull-left">
-  <div style="float:left">
+  <div class="pull-left">
     <div id="graph1_desc" class="graph_desc">
       <h4>Job Timeline</h4>
     </div>
     <div id="chart"></div>
     <div id="timeline1"></div>
   </div>
-  <div id="legend_container" style="margin-top:60px">
+  <div id="legend_container" class="pull-left">
     <div id="legend"></div>
   </div>
 </div>
 <div id="graph2" class="pull-right">
-  <div style="float:left">
+  <div class="pull-left">
     <div id="graph2_desc" class="graph_desc">
       <h4>Job Tasks' View</h4>
     </div>
     <div id="job_tasks"></div>
     <div id="timeline2"></div>
   </div>
-  <div id="tasks_legend_container" style="margin-top:60px">
+  <div id="tasks_legend_container" class="pull-left">
     <div id="tasks_legend"></div>
   </div>
 </div>

+ 2 - 2
ambari-web/app/templates/main/apps/item/dag.hbs

@@ -38,8 +38,8 @@
         <td>{{job.status}}</td>
         <td>{{job.maps}}&nbsp;({{job.mapsProgress}}%)</td>
         <td>{{job.reduces}}&nbsp;({{job.reducesProgress}}%)</td>
-        <td>{{job.input}}</td>
-        <td>{{job.output}}</td>
+        <td>{{job.inputFormatted}}</td>
+        <td>{{job.outputFormatted}}</td>
         <td>{{job.duration}}</td>
       </tr>
       {{/each}}

+ 2 - 2
ambari-web/app/templates/main/apps/list_row.hbs

@@ -22,7 +22,7 @@
 <td>{{run.type}}</td>
 <td>{{run.userName}}</td>
 <td>{{run.numJobsTotal}}</td>
-<td>{{run.input}}</td>
-<td>{{run.output}}</td>
+<td>{{run.inputFormatted}}</td>
+<td>{{run.outputFormatted}}</td>
 <td>{{run.duration}}</td>
 <td>{{run.lastUpdateTimeFormatted}} {{#if run.isRunning}}<b class='red'>*</b>{{/if}}</td>

+ 26 - 26
ambari-web/app/templates/main/background_operations_popup.hbs

@@ -15,30 +15,30 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 -->
-{{#each operation in backgroundOperations.tasks}}
-{{#view App.MainBackgroundOperation 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>exitcode:</dt><dd>{{view.logDetails.exitcode}}</dd>
-      <dt>stdout:</dt><dd>{{view.logDetails.stdout}}</dd>
-      <dt>stderror:</dt><dd>{{view.logDetails.stderror}}</dd>
-    </dl>
-  </div>
-  {{/if}}
-</div>
-{{/view}}
+{{#each operation in backgroundOperations}}
+  {{#view App.MainBackgroundOperation contentBinding="operation"}}
+    <a class="open-details" {{action openDetails target="view"}} href="#">
+      <i {{bindAttr class="view.iconClass"}}></i>
+    </a>
+    {{operation.command}} {{operation.role}} on {{operation.host_name}}
+    <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>exitcode:</dt><dd>{{view.logDetails.exitcode}}</dd>
+          <dt>stdout:</dt><dd>{{view.logDetails.stdout}}</dd>
+          <dt>stderror:</dt><dd>{{view.logDetails.stderror}}</dd>
+        </dl>
+      </div>
+      {{/if}}
+    </div>
+  {{/view}}
 {{/each}}

+ 3 - 3
ambari-web/app/templates/main/dashboard.hbs

@@ -92,8 +92,8 @@
               <div class="span11">
                 <div class="row-fluid">
                   <div class="span8 title">{{title}}
-                    {{#if serviceName}}
-                      <a class="serviceLink" href="{{unbound serviceLink}}">{{serviceName}}</a>
+                    {{#if service.serviceName}}
+                      <a class="serviceLink" href="{{unbound serviceLink}}">{{service.serviceName}}</a>
                     {{/if}}
                   </div>
                   <div class="span4 date-time">{{dateDisplay}}</div>
@@ -107,4 +107,4 @@
       </ul>
     </div>
 	</div>
-</div>
+</div>

+ 4 - 4
ambari-web/app/templates/main/dashboard/service/hbase.hbs

@@ -19,7 +19,7 @@
 <div class="clearfix">
   <div class="name span2">
     {{view App.MainDashboardServiceHealthView serviceBinding="view.service"}}
-    <a {{action selectService view.service href=true}}>{{view.service.label}}</a>
+    <a {{action selectService view.service href=true}}>{{view.service.displayName}}</a>
     {{#if view.criticalAlertsCount}}
     <span class="label label-important alerts-count">{{view.criticalAlertsCount}}</span>
     {{/if}}
@@ -61,9 +61,9 @@
     <td>
       {{#each component in view.service.components}}
       {{#if component.type}}
-      <a href="#" {{action selectHost component.host}}>{{component.componentName}}</a>,
+      <a href="#" {{action selectHost component.host}}>{{component.displayName}}</a>,
       {{else}}
-      <a href="#" {{action filterHosts component}}>{{component.componentName}}</a>
+      <a href="#" {{action filterHosts component}}>{{component.displayName}}</a>
       {{/if}}
       {{/each}}
     </td>
@@ -88,4 +88,4 @@
   </div>
   {{/view}}
   {{/if}}
-</div>
+</div>

+ 4 - 4
ambari-web/app/templates/main/dashboard/service/hdfs.hbs

@@ -19,7 +19,7 @@
 <div class="clearfix">
   <div class="name span2">
     {{view App.MainDashboardServiceHealthView serviceBinding="view.service"}}
-    <a {{action selectService view.service href=true}}>{{view.service.label}}</a>
+    <a {{action selectService view.service href=true}}>{{view.service.displayName}}</a>
     {{#if view.criticalAlertsCount}}
     <span class="label label-important alerts-count">{{view.criticalAlertsCount}}</span>
     {{/if}}
@@ -72,9 +72,9 @@
     <td>
       {{#each component in view.service.components}}
       {{#if component.type}}
-      <a href="#" {{action selectHost component.host}}>{{component.componentName}}</a>,
+      <a href="#" {{action selectHost component.host}}>{{component.displayName}}</a>,
       {{else}}
-      <a href="#" {{action filterHosts component}}>{{component.componentName}}</a>
+      <a href="#" {{action filterHosts component}}>{{component.displayName}}</a>
       {{/if}}
       {{/each}}
     </td>
@@ -99,4 +99,4 @@
       </div>
     {{/view}}
   {{/if}}
-</div>
+</div>

+ 4 - 4
ambari-web/app/templates/main/dashboard/service/hive.hbs

@@ -19,7 +19,7 @@
 <div class="clearfix">
   <div class="name span2">
     {{view App.MainDashboardServiceHealthView serviceBinding="view.service"}}
-    <a {{action selectService view.service href=true}}>{{view.service.label}}</a>
+    <a {{action selectService view.service href=true}}>{{view.service.displayName}}</a>
     {{#if view.criticalAlertsCount}}
     <span class="label label-important alerts-count">{{view.criticalAlertsCount}}</span>
     {{/if}}
@@ -27,10 +27,10 @@
   <div class="summary span">
     {{#each component in view.service.components}}
     {{#if component.type}}
-    <a href="#" {{action selectHost component.host}}>{{component.componentName}}</a>,
+    <a href="#" {{action selectHost component.host}}>{{component.displayName}}</a>,
     {{else}}
-    <a href="#" {{action filterHosts component}}>{{component.componentName}}</a>
+    <a href="#" {{action filterHosts component}}>{{component.displayName}}</a>
     {{/if}}
     {{/each}}
   </div>
-</div>
+</div>

+ 4 - 4
ambari-web/app/templates/main/dashboard/service/mapreduce.hbs

@@ -18,7 +18,7 @@
 <div class="clearfix">
   <div class="name span2">
     {{view App.MainDashboardServiceHealthView serviceBinding="view.service"}}
-    <a {{action selectService view.service href=true}}>{{view.service.label}}</a>
+    <a {{action selectService view.service href=true}}>{{view.service.displayName}}</a>
     {{#if view.criticalAlertsCount}}
       <span class="label label-important alerts-count">{{view.criticalAlertsCount}}</span>
     {{/if}}
@@ -72,9 +72,9 @@
     <td>
       {{#each component in view.service.components}}
       {{#if component.type}}
-      <a href="#" {{action selectHost component.host}}>{{component.componentName}}</a>,
+      <a href="#" {{action selectHost component.host}}>{{component.displayName}}</a>,
       {{else}}
-      <a href="#" {{action filterHosts component}}>{{component.componentName}}</a>
+      <a href="#" {{action filterHosts component}}>{{component.displayName}}</a>
       {{/if}}
       {{/each}}
     </td>
@@ -99,4 +99,4 @@
   </div>
   {{/view}}
   {{/if}}
-</div>
+</div>

+ 4 - 4
ambari-web/app/templates/main/dashboard/service/oozie.hbs

@@ -19,7 +19,7 @@
 <div class="clearfix">
   <div class="name span2">
     {{view App.MainDashboardServiceHealthView serviceBinding="view.service"}}
-    <a {{action selectService view.service href=true}}>{{view.service.label}}</a>
+    <a {{action selectService view.service href=true}}>{{view.service.displayName}}</a>
     {{#if view.criticalAlertsCount}}
     <span class="label label-important alerts-count">{{view.criticalAlertsCount}}</span>
     {{/if}}
@@ -27,10 +27,10 @@
   <div class="summary span">
     {{#each component in view.service.components}}
     {{#if component.type}}
-    <a href="#" {{action selectHost component.host}}>{{component.componentName}}</a>,
+    <a href="#" {{action selectHost component.host}}>{{component.displayName}}</a>,
     {{else}}
-    <a href="#" {{action filterHosts component}}>{{component.componentName}}</a>
+    <a href="#" {{action filterHosts component}}>{{component.displayName}}</a>
     {{/if}}
     {{/each}}
   </div>
-</div>
+</div>

+ 4 - 4
ambari-web/app/templates/main/dashboard/service/zookeeper.hbs

@@ -19,7 +19,7 @@
 <div class="clearfix">
   <div class="name span2">
     {{view App.MainDashboardServiceHealthView serviceBinding="view.service"}}
-    <a {{action selectService view.service href=true}}>{{view.service.label}}</a>
+    <a {{action selectService view.service href=true}}>{{view.service.displayName}}</a>
     {{#if view.criticalAlertsCount}}
     <span class="label label-important alerts-count">{{view.criticalAlertsCount}}</span>
     {{/if}}
@@ -27,10 +27,10 @@
   <div class="summary span">
     {{#each component in view.service.components}}
     {{#if component.type}}
-    <a href="#" {{action selectHost component.host}}>{{component.componentName}}</a>,
+    <a href="#" {{action selectHost component.host}}>{{component.displayName}}</a>,
     {{else}}
-    <a href="#" {{action filterHosts component}}>{{component.componentName}}</a>
+    <a href="#" {{action filterHosts component}}>{{component.displayName}}</a>
     {{/if}}
     {{/each}}
   </div>
-</div>
+</div>

+ 9 - 32
ambari-web/app/templates/main/host.hbs

@@ -18,31 +18,7 @@
 <div id="hosts" class="box">
   <div class="box-header">
     <div class="button-section">
-      <div class="btn-group">
-        <button {{bindAttr disabled="controller.isDisabled"}} class="btn btn-primary dropdown-toggle"
-                                                              data-toggle="dropdown">
-          Assign Rack
-          <span class="caret"></span>
-        </button>
-        <ul class="dropdown-menu">
-          {{#each clusters}}
-          <li>
-            <a href="javascript:void(null)"
-               data-toggle="modal" {{action "assignedToRackPopup" this target="controller"}}>
-              {{clusterName}}
-            </a>
-          </li>
-          {{/each}}
-        </ul>
-      </div>
-     <!-- <button {{bindAttr disabled="controller.isDisabled"}} class="btn btn-primary decommission"
-                                                            data-toggle="modal" {{action "decommissionButtonPopup" target="controller"}}>
-        Decommission
-      </button>
-      <button {{bindAttr disabled="controller.isDisabled"}} class="btn btn-primary"
-                                                            data-toggle="modal" {{action "deleteButtonPopup" target="controller"}}>
-        Delete
-      </button>-->
+      {{view view.RackCombobox}}
       <button class="btn btn-inverse add-host-button" {{action addHost}}>
         <i class="icon-plus icon-white"></i>
         Add New Hosts
@@ -58,15 +34,16 @@
         </label>
       </th>
       <th class="name">
-        <a class="filter-label" href="#" {{action sortByName target="controller" }}>Name
-          {{#if controller.isSort}}
-          <i class="icon-arrow-up"{{bindAttr class="controller.sortClass"}}></i>
-          {{/if}}
-        </a>
+        <div class="host-name-pos">
+          <a class="filter-label" href="#" {{action sortByName target="controller" }}>Name
+            {{#if controller.isSort}}
+            <i class="icon-arrow-up"{{bindAttr class="controller.sortClass"}}></i>
+            {{/if}}
+          </a>
 
-        <div class="span1">
-          {{view Ember.TextField placeholder="search" valueBinding="view.filterByName"}}
+          {{view Ember.TextField class="host-name-search" placeholder="search" valueBinding="view.filterByName"}}
         </div>
+
       </th>
       <th>Rack</th>
       <th>CPU</th>

+ 1 - 1
ambari-web/app/templates/main/host/details.hbs

@@ -20,7 +20,7 @@
   <a href="javascript:void(null)" data-toggle="modal" {{action backToHostsList}}>Hosts</a> /
   <span {{bindAttr class=":host-title view.content.healthClass"}}>{{unbound view.content.hostName}}</span>
   <div class="host-maintenance">
-    <div class="btn-group display-inline-block">
+    <div class="host-maintenance-btn btn-group display-inline-block">
       <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
         {{t services.service.actions.maintenance}}
         <span class="caret"></span>

+ 189 - 104
ambari-web/app/templates/main/service/info/configs.hbs

@@ -16,121 +16,206 @@
 * limitations under the License.
 -->
 
+<!--<div>-->
+    <!--<fieldset class="fieldset">-->
+     <!--<legend>General</legend>-->
+        <!--<div class="row">-->
+           <!--<div class="span2"> <b>Some HDFS config</b> </div>-->
+           <!--<div class="span2"><input type="text"></div>-->
+        <!--</div>-->
+    <!--</fieldset>-->
 
-<div>
-    <fieldset class="fieldset">
-     <legend>General</legend>
-        <div class="row">
-           <div class="span2"> <b>Some HDFS config</b> </div>
-           <div class="span2"><input type="text"></div>
-        </div>
-    </fieldset>
+<!--</div>-->
 
-</div>
+<!--<br>-->
 
-<br>
+<!--<div>-->
+       <!--<fieldset class="fieldset">-->
+        <!--<legend>NameNode</legend>-->
+          <!--<div class="row">-->
+            <!--<div class="span2"><b>NameNodeSet</b> </div>-->
+            <!--<div class="span2">host0001.com.com</div>-->
 
-<div>
-       <fieldset class="fieldset">
-        <legend>NameNode</legend>
-          <div class="row">
-            <div class="span2"><b>NameNodeSet</b> </div>
-            <div class="span2">host0001.com.com</div>
+        <!--</div>-->
+<!--<br>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>NameNode directories</b> dfs.name.dir </div>-->
+            <!--<div class="span2"><textarea placeholder="/grid/hadoop/namenode"></textarea></div>-->
 
-        </div>
-<br>
-        <div class="row">
-            <div class="span2"><b>NameNode directories</b> dfs.name.dir </div>
-            <div class="span2"><textarea placeholder="/grid/hadoop/namenode"></textarea></div>
+        <!--</div>-->
+<!--<br>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>Some NameNode config</b> dfs.name.some </div>-->
+            <!--<div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="2048"><span class="add-on">MB</span></div>-->
+            <!--<div class="span2"></div>-->
 
-        </div>
-<br>
-        <div class="row">
-            <div class="span2"><b>Some NameNode config</b> dfs.name.some </div>
-            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="2048"><span class="add-on">MB</span></div>
-            <div class="span2"></div>
+        <!--</div>-->
+    <!--</fieldset>-->
+<!--</div>-->
+<!--<br>-->
+<!--<div>-->
+    <!--<fieldset class="fieldset">-->
+        <!--<legend>SNameNode</legend>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>Some NameNode host</b> </div>-->
+            <!--<div class="span2">host0002.com.com</div>-->
+        <!--</div>-->
+    <!--</fieldset>-->
+<!--</div>-->
+<!--<br>-->
+<!--<div>-->
+    <!--<fieldset class="fieldset">-->
+        <!--<legend>DataNode (Default)</legend>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>DataNode hosts</b> </div>-->
+            <!--<div class="span3"><a href="#">host003.com.com and 89 more</a> </div>-->
 
-        </div>
-    </fieldset>
-</div>
-<br>
-<div>
-    <fieldset class="fieldset">
-        <legend>SNameNode</legend>
-        <div class="row">
-            <div class="span2"><b>Some NameNode host</b> </div>
-            <div class="span2">host0002.com.com</div>
-        </div>
-    </fieldset>
-</div>
-<br>
-<div>
-    <fieldset class="fieldset">
-        <legend>DataNode (Default)</legend>
-        <div class="row">
-            <div class="span2"><b>DataNode hosts</b> </div>
-            <div class="span3"><a href="#">host003.com.com and 89 more</a> </div>
+        <!--</div>-->
+        <!--<br>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>DataNode directories</b> dfs.data.dir</div>-->
+             <!--<div class="span2"><textarea placeholder="/grid/0/hadoop/datanode-->
+                                                      <!--/grid/1/hadoop/datanode-->
+                                                      <!--/grid/2/hadoop/datanode"></textarea></div>-->
 
-        </div>
-        <br>
-        <div class="row">
-            <div class="span2"><b>DataNode directories</b> dfs.data.dir</div>
-             <div class="span2"><textarea placeholder="/grid/0/hadoop/datanode
-                                                      /grid/1/hadoop/datanode
-                                                      /grid/2/hadoop/datanode"></textarea></div>
+        <!--</div>-->
+        <!--<br>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>Some DataNode config</b> dfs.data.some </div>-->
+            <!--<div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="1024"><span class="add-on">MB</span></div>-->
+            <!--<div class="span2"></div>-->
 
-        </div>
-        <br>
-        <div class="row">
-            <div class="span2"><b>Some DataNode config</b> dfs.data.some </div>
-            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="1024"><span class="add-on">MB</span></div>
-            <div class="span2"></div>
+        <!--</div>-->
+        <!--<br>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>Another DataNode config</b> dfs.data.another</div>-->
+            <!--<div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="512"><span class="add-on">MB</span></div>-->
 
-        </div>
-        <br>
-        <div class="row">
-            <div class="span2"><b>Another DataNode config</b> dfs.data.another</div>
-            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="512"><span class="add-on">MB</span></div>
+        <!--</div>-->
+   <!--</fieldset>-->
+<!--</div>-->
+<!--<br>-->
+<!--<div>-->
+    <!--<fieldset class="fieldset">-->
+        <!--<legend>DataNode Group A</legend>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>DataNode hosts</b> </div>-->
+            <!--<div class="span3"><a href="#">host0090.com.com and 90 more</a> </div>-->
 
-        </div>
-   </fieldset>
-</div>
-<br>
-<div>
-    <fieldset class="fieldset">
-        <legend>DataNode Group A</legend>
-        <div class="row">
-            <div class="span2"><b>DataNode hosts</b> </div>
-            <div class="span3"><a href="#">host0090.com.com and 90 more</a> </div>
+        <!--</div>-->
+        <!--<br>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>DataNode directories</b> dfs.data.dir</div>-->
+            <!--<div class="span2"><textarea placeholder="/grid/0/hadoop/datanode-->
+                                                      <!--/grid/1/hadoop/datanode-->
+                                                      <!--/grid/2/hadoop/datanode-->
+                                                      <!--/grid/3/hadoop/datanode"></textarea></div>-->
 
+        <!--</div>-->
+        <!--<br>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>Some DataNode config</b> dfs.data.another</div>-->
+            <!--<div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="2048"><span class="add-on">MB</span></div>-->
+            <!--<div class="span2"></div>-->
+        <!--</div>-->
+        <!--<br>-->
+        <!--<div class="row">-->
+            <!--<div class="span2"><b>Another DataNode config</b> dfs.data.another</div>-->
+            <!--<div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="128"><span class="add-on">MB</span></div>-->
+        <!--</div>-->
+    <!--</fieldset>-->
+<!--</div>-->
+<!--<br>-->
+      <!--<p align="right"> Need a different settings on certain DataNodes? <a href="#">Add a DataNode group</a>-->
+      <!--<br>-->
+      <!--<br>-->
+      <!--<input class="btn btn-primary" type="button" value="Save and apply changes">-->
+    <!--</p>-->
+     <!--</div>-->
+{{!outlet}}
+<div id="serviceConfig">
+  <div class="accordion">
+    {{#each category in selectedService.configCategories}}
+      <div class="accordion-group">
+        <div class="accordion-heading">
+          <a class="accordion-toggle">
+            {{category.name}}
+          </a>
         </div>
-        <br>
-        <div class="row">
-            <div class="span2"><b>DataNode directories</b> dfs.data.dir</div>
-            <div class="span2"><textarea placeholder="/grid/0/hadoop/datanode
-                                                      /grid/1/hadoop/datanode
-                                                      /grid/2/hadoop/datanode
-                                                      /grid/3/hadoop/datanode"></textarea></div>
 
-        </div>
-        <br>
-        <div class="row">
-            <div class="span2"><b>Some DataNode config</b> dfs.data.another</div>
-            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="2048"><span class="add-on">MB</span></div>
-            <div class="span2"></div>
-        </div>
-        <br>
-        <div class="row">
-            <div class="span2"><b>Another DataNode config</b> dfs.data.another</div>
-            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="128"><span class="add-on">MB</span></div>
-        </div>
-    </fieldset>
-</div>
-<br>
-      <p align="right"> Need a different settings on certain DataNodes? <a href="#">Add a DataNode group</a>
-      <br>
-      <br>
-      <input class="btn btn-primary" type="button" value="Save and apply changes">
-    </p>
-     </div>
-{{outlet}}
+        {{#unless category.isForSlaveComponent}}
+          {{#view App.ServiceConfigsByCategoryView categoryBinding="category" serviceConfigsBinding="selectedService.configs"}}
+            <form class="form-horizontal">
+
+              {{#each view.categoryConfigs}}
+                {{#if isVisible}}
+                  <div {{bindAttr class="errorMessage:error: :control-group"}}>
+                    <label class="control-label">{{displayName}}</label>
+
+                    <div class="controls">
+                      {{view viewClass serviceConfigBinding="this" categoryConfigsBinding="view.categoryConfigs"}}
+                      <span class="help-inline">{{errorMessage}}</span>
+                    </div>
+                  </div>
+                {{/if}}
+              {{/each}}
+
+            </form>
+          {{/view}}
+        {{/unless}}
+
+        {{#if category.isForSlaveComponent}}
+          {{#view App.ServiceConfigsByCategoryView categoryBinding="category" serviceConfigsBinding="selectedService.configs" controllerBinding="App.router.mainServiceSlaveComponentGroupsController"}}
+            <div class="slave-component-group-menu">
+              {{view App.SlaveComponentGroupsMenu}}
+            </div>
+
+            {{#view App.AddSlaveComponentGroupButton slaveComponentNameBinding="category.name"}}
+              <a class="btn add-slave-component-group btn-large" {{action addSlaveComponentGroup target="controller"}}><i
+                class="icon-plus"></i></a>
+            {{/view}}
+            <div class="remove-group-error control-group warning">
+              <span class="help-inline">You cannot delete this group since there are hosts assigned to it. You must assign them to another group before you can delete this group.</span>
+            </div>
+
+            <form class="form-horizontal">
+
+              {{#view App.SlaveComponentChangeGroupNameView}}
+                <label class="control-label">Group name</label>
+
+                <div class="controls">
+                  <div class="span6">
+                    <input class="span9" type="text" {{bindAttr value="view.content.name"}}>
+                    <button class="btn" {{action changeGroupName target="view"}}>Save</button>
+                  </div>
+                  <span class="help-inline">{{view.errorMessage}}</span>
+                </div>
+              {{/view}}
+
+
+              {{#each view.categoryConfigs}}
+                {{#if isVisible}}
+                  <div {{bindAttr class="errorMessage:error: :control-group"}}>
+                    <label class="control-label">{{displayName}}</label>
+
+                    <div class="controls">
+                      {{view viewClass serviceConfigBinding="this" categoryConfigsBinding="view.categoryConfigs"}}
+                      <span class="help-inline">{{errorMessage}}</span>
+                    </div>
+                  </div>
+                {{/if}}
+              {{/each}}
+
+            </form>
+
+          {{/view}}
+        {{/if}}
+      </div>
+    {{/each}}
+  </div>
+  <p class="pull-right">
+    <!--<input class="btn btn-primary" type="button" value="Save and apply changes" {{!bindAttr disabled="isSubmitDisabled"}} />-->
+    <a class="btn btn-primary" {{bindAttr disabled="isSubmitDisabled"}}
+      {{action saveServiceConfigProperties target="controller"}}>Save and apply changes</a>
+  </p>
+</div>

+ 54 - 6
ambari-web/app/templates/main/service/info/summary.hbs

@@ -39,17 +39,23 @@
   <div class="service-content">
     <table id="summary-info" class="table table-bordered table-striped table-condensed">
       <tbody>
+      {{#unless view.serviceStatus.oozie}}
+      {{#unless view.serviceStatus.hive}}
+      {{#unless view.serviceStatus.zookeeper}}
       {{#each component in controller.content.components}}
       <tr>
-        {{#if component.type}}
-        <td class="summary-label">{{component.componentName}}</td>
-        <td><a {{action selectHost component.host}} href="javascript:void(null)">{{component.host.hostName}}</a></td>
+        {{#if component.isMaster}}
+        <td class="summary-label">{{component.displayName}}</td>
+        <td><a {{action selectHost component.host}} href="javascript:void(null)">{{component.hostComponents}}</a></td>
         {{else}}
-        <td class="summary-label">{{component.componentName}}s</td>
-        <td><a {{action filterHosts component}} href="javascript:void(null)">{{component.componentName}}s</a></td>
+        <td class="summary-label">{{component.displayName}}s</td>
+        <td><a {{action filterHosts component}} href="javascript:void(null)">{{component.displayName}}s</a></td>
         {{/if}}
       </tr>
       {{/each}}
+      {{/unless}}
+      {{/unless}}
+      {{/unless}}
       {{#if view.serviceStatus.hdfs}}
       <tr>
         <td>{{t services.service.summary.version}}</td>
@@ -221,6 +227,48 @@
         </td>
       </tr>
       {{/if}}
+      {{#if view.serviceStatus.zookeeper}}
+        <tr>
+          <td class="summary-label">Hosts</td>
+          <td>
+            {{#each component in controller.content.components}}
+              <a {{action selectHost component.host}} href="javascript:void(null)">{{component.host.hostName}}</a>
+           {{/each}}
+          </td>
+        </tr>
+      {{/if}}
+      {{#if view.serviceStatus.oozie}}
+        <tr>
+          <td class="summary-label">Hosts</td>
+          <td>
+            {{#each component in controller.content.components}}
+              <a {{action selectHost component.host}} href="javascript:void(null)">{{component.host.hostName}}</a>
+           {{/each}}
+          </td>
+        </tr>
+      {{/if}}
+      {{#if view.serviceStatus.hive}}
+        <tr>
+          <td class="summary-label">Host</td>
+          <td>
+            {{#each component in controller.content.components}}
+              <a {{action selectHost component.host}} href="javascript:void(null)">{{component.host.hostName}}</a>
+           {{/each}}
+          </td>
+        </tr>
+        <tr>
+          <td>Database</td>
+          <td>{{view.data.hive.database}}</td>
+        </tr>
+        <tr>
+          <td>Database Name</td>
+          <td>{{view.data.hive.databaseName}}</td>
+        </tr>
+        <tr>
+          <td>User</td>
+          <td>{{view.data.hive.user}}</td>
+        </tr>
+      {{/if}}
       </tbody>
     </table>
     {{!view view.moreStatsView}}
@@ -286,4 +334,4 @@
     </div>
   </div>
 </div>
-{{/if}}
+{{/if}}

+ 10 - 21
ambari-web/app/templates/main/service/item.hbs

@@ -32,26 +32,15 @@
       {{/each}}
     </ul>
   </div>
-  {{#if controller.content.workStatus}}
-    <a href="javascript:void(null)" class="btn disabled">
-      <i class="icon-play"></i>
-      Start
-    </a>
-    <a href="javascript:void(null)" class="btn btn-danger"
-       data-toggle="modal" {{action "stopService" target="controller"}}>
-      <i class="icon-stop icon-white"></i>
-      Stop
-    </a>
-  {{else}}
-    <a href="javascript:void(null)" class="btn btn-success"
-       data-toggle="modal" {{action "startService" target="controller"}}>
-      <i class="icon-play icon-white"></i>
-      Start
-    </a>
-    <a href="javascript:void(null)" class="btn disabled">
-      <i class="icon-stop"></i>
-      Stop
-    </a>
-  {{/if}}
+  <a href="javascript:void(null)" {{bindAttr class=":btn controller.content.workStatus:disabled:btn-success" }}
+     data-toggle="modal" {{action "startService" target="controller"}}>
+    <i class="icon-play"></i>
+    Start
+  </a>
+  <a href="javascript:void(null)" {{bindAttr class=":btn controller.content.workStatus:btn-danger:disabled" }}
+     data-toggle="modal" {{action "stopService" target="controller"}}>
+    <i class="icon-stop icon-white"></i>
+    Stop
+  </a>
 </div>
 {{outlet}}

+ 1 - 1
ambari-web/app/templates/main/service/menu_item.hbs

@@ -17,7 +17,7 @@
 -->
 
 <a href="#/main/services/{{unbound view.content.id}}/summary">
-  {{view App.MainDashboardServiceHealthView serviceBinding="view.content"}}&nbsp;<span>{{unbound view.content.label}}</span>
+  {{view App.MainDashboardServiceHealthView serviceBinding="view.content"}}&nbsp;<span>{{unbound view.content.displayName}}</span>
   {{#if view.serviceOperationsCount}}
     <span class="label operations-count" {{action "showBackgroundOperationsPopup" target="App.router.mainServiceItemController"}}>
       {{view.serviceOperationsCount}}

+ 47 - 0
ambari-web/app/templates/main/test.hbs

@@ -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.
+-->
+
+SERVICES
+
+<div>
+  <table style="padding:10px;">
+    <thead>
+    <tr>
+      <th>Service name</th>
+      <th>Component name</th>
+      <th>Component Status</th>
+      <th>Host name</th>
+    </tr>
+    </thead>
+    <tbody>
+    {{#each view.services }}
+    <tr colspan=4>
+      <td style="padding:10px;">{{displayName}}</td>
+    </tr>
+    {{#each components}}
+      <tr>
+        <td></td>
+        <td style="padding:10px;">{{componentName}}</td>
+        <td style="padding:10px;">{{state}}</td>
+        <td style="padding:10px;">{{host_name}}</td>
+      </tr>
+    {{/each}}
+    {{/each}}
+    </tbody>
+  </table>
+</div>

+ 8 - 3
ambari-web/app/templates/wizard/step2.hbs

@@ -54,15 +54,19 @@
       <p>{{t installer.step2.sshKey.info}}</p>
 
       <div {{bindAttr class="sshKeyError:error :control-group"}}>
+        {{#if view.isFileApi}}
+          {{view App.SshKeyFileUploader}}
+          <div {{bindAttr class="view.sshKeyPreviewClass"}}>{{content.sshKey}}</div>
+        {{/if}}
         <div class="controls">
-          {{view Ember.TextArea class="span6" rows="4" placeholder="ssh private key" valueBinding="content.sshKey"}}
+          {{view Ember.TextArea class="span6" rows="4" classBinding="view.sshKeyClass"  id="sshKey" placeholder="ssh private key" disabledBinding="view.sshKeyState" valueBinding="content.sshKey"}}
           {{#if sshKeyError}}
-        <span
-          class="help-inline">{{sshKeyError}}</span>
+          <span class="help-inline">{{sshKeyError}}</span>
           {{/if}}
         </div>
       </div>
 
+      <div class="manual-install">
       <label class="checkbox">
         {{t installer.step2.manualInstall.label}}
         <a href="javascript:void(null)"
@@ -71,6 +75,7 @@
           Learn more</a>
         {{view Ember.Checkbox checkedBinding="content.manualInstall"}}
       </label>
+      </div>
 
       {{#if "manualInstall"}}
       <div class="alert">

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

@@ -109,7 +109,7 @@
 
   <div>
     {{#if view.resultMsg}}
-    <p {{bindAttr class="view.resultMsgColor"}}>{{view.resultMsg}}</p>
+    <p {{bindAttr class="view.resultMsgColor :alert"}}>{{view.resultMsg}}</p>
     {{/if}}
     <div class="btn-area">
       <a

+ 133 - 3
ambari-web/app/utils/data_table.js

@@ -39,6 +39,34 @@ jQuery.extend(jQuery.fn.dataTableExt.oSort, {
 
   "ambari-date-desc": function (a, b) {
     return b - a;
+  },
+  /**
+   * Custom methods for correct bandwidth sorting
+   */
+  "ambari-bandwidth-pre": function (bandwidth_string) {
+    debugger;
+    bandwidth_string = (jQuery(bandwidth_string).text()) ? jQuery(bandwidth_string).text() : bandwidth_string;
+    var convertedRowValue;
+    if (bandwidth_string === '<1KB') {
+      convertedRowValue = 1;
+    } else {
+      var rowValueScale = bandwidth_string.substr(bandwidth_string.length - 2, 2);
+      switch (rowValueScale) {
+        case 'KB':
+          convertedRowValue = parseFloat(bandwidth_string)*1024;
+          break;
+        case 'MB':
+          convertedRowValue = parseFloat(bandwidth_string)*1048576;
+          break;
+      }
+    }
+    return convertedRowValue;
+  },
+  "ambari-bandwidth-asc": function (a, b) {
+    return a - b;
+  },
+  "ambari-bandwidth-desc": function (a, b) {
+    return b - a;
   }
 });
 
@@ -113,10 +141,11 @@ jQuery.extend(jQuery.fn.dataTableExt.oApi, {
 jQuery.extend($.fn.dataTableExt.afnFiltering.push(
     function (oSettings, aData, iDataIndex) {
       var inputFilters = [
+        {iColumn: '0', elementId: 'star_filter', type: 'star'},
         {iColumn: '4', elementId: 'user_filter', type: 'multiple'},
         {iColumn: '5', elementId: 'jobs_filter', type: 'number' },
-        {iColumn: '6', elementId: 'input_filter', type: 'number' },
-        {iColumn: '7', elementId: 'output_filter', type: 'number' },
+        {iColumn: '6', elementId: 'input_filter', type: 'bandwidth' },
+        {iColumn: '7', elementId: 'output_filter', type: 'bandwidth' },
         {iColumn: '8', elementId: 'duration_filter', type: 'time' },
         {iColumn: '9', elementId: 'rundate_filter', type: 'date' }
       ];
@@ -143,8 +172,25 @@ jQuery.extend($.fn.dataTableExt.afnFiltering.push(
               timeFilter(jQuery('#' + inputFilters[i].elementId).val(), aData[inputFilters[i].iColumn]);
             }
             break;
+          case 'bandwidth':
+            if (jQuery('#' + inputFilters[i].elementId).val() && match) {
+              bandwidthFilter(jQuery('#' + inputFilters[i].elementId).val(), aData[inputFilters[i].iColumn]);
+            }
+            break;
+          case 'star':
+            if (jQuery('#' + inputFilters[i].elementId).val() && match) {
+              starFilter(jQuery('#' + inputFilters[i].elementId).val(), aData[inputFilters[i].iColumn]);
+            }
+            break;
         }
       }
+
+      function starFilter(d, rowValue) {
+        match = false;
+        if (rowValue == null) return;
+        if (rowValue.indexOf(d) != -1) match = true;
+      }
+
       function multipleFilter(condition, rowValue) {
         var options = condition.split(',');
         match = false;
@@ -159,7 +205,7 @@ jQuery.extend($.fn.dataTableExt.afnFiltering.push(
         var compareScale = rangeExp.charAt(rangeExp.length - 1);
         var compareValue = isNaN(parseInt(compareScale)) ? parseInt(rangeExp.substr(1, rangeExp.length - 2)) : parseInt(rangeExp.substr(1, rangeExp.length - 1));
         rowValue = (jQuery(rowValue).text()) ? jQuery(rowValue).text() : rowValue;
-        var convertedRowValue = parseInt(rowValue.substr(0, 2)) * 3600 + parseInt(rowValue.substr(3, 5)) * 60 + parseInt(rowValue.substr(6, 8));
+        var convertedRowValue = parseInt(rowValue.substr(0, 2)) * 3600 + parseInt(rowValue.substr(3, 2)) * 60 + parseInt(rowValue.substr(6, 2));
         switch (compareScale) {
           case 'm':
             convertedRowValue /= 60;
@@ -184,6 +230,49 @@ jQuery.extend($.fn.dataTableExt.afnFiltering.push(
         }
       }
 
+      function bandwidthFilter(rangeExp, rowValue) {
+        debugger;
+        var compareChar = rangeExp.charAt(0);
+        var compareScale = rangeExp.charAt(rangeExp.length - 1);
+        var compareValue = isNaN(parseFloat(compareScale)) ? parseFloat(rangeExp.substr(1, rangeExp.length - 2)) : parseFloat(rangeExp.substr(1, rangeExp.length - 1));
+        switch (compareScale) {
+          case 'm':
+            compareValue *= 1048576;
+            break;
+          default:
+            compareValue *= 1024;
+        }
+        rowValue = (jQuery(rowValue).text()) ? jQuery(rowValue).text() : rowValue;
+        var convertedRowValue;
+        if (rowValue === '<1KB') {
+          convertedRowValue = 1;
+        } else {
+          var rowValueScale = rowValue.substr(rowValue.length - 2, 2);
+          switch (rowValueScale) {
+            case 'KB':
+              convertedRowValue = parseFloat(rowValue)*1024;
+              break;
+            case 'MB':
+              convertedRowValue = parseFloat(rowValue)*1048576;
+              break;
+          }
+        }
+        match = false;
+        switch (compareChar) {
+          case '<':
+            if (compareValue > convertedRowValue) match = true;
+            break;
+          case '>':
+            if (compareValue < convertedRowValue) match = true;
+            break;
+          case '=':
+            if (compareValue == convertedRowValue) match = true;
+            break;
+          default:
+            match = false;
+        }
+      }
+
       function dateFilter(condition, rowValue) {
         var nowTime = new Date().getTime();
         var oneDayPast = nowTime - 86400000;
@@ -272,5 +361,46 @@ jQuery.extend(jQuery.fn.dataTableExt.oApi, {
 });
 
 
+jQuery.fn.dataTableExt.oApi.fnGetColumnData = function ( oSettings, iColumn, bUnique, bFiltered, bIgnoreEmpty ) {
+  // check that we have a column id
+  if ( typeof iColumn == "undefined" ) return [];
+
+  // by default we only wany unique data
+  if ( typeof bUnique == "undefined" ) bUnique = true;
+
+  // by default we do want to only look at filtered data
+  if ( typeof bFiltered == "undefined" ) bFiltered = true;
+
+  // by default we do not wany to include empty values
+  if ( typeof bIgnoreEmpty == "undefined" ) bIgnoreEmpty = true;
+
+  // list of rows which we're going to loop through
+  var aiRows;
+
+  // use only filtered rows
+  if (bFiltered == true) aiRows = oSettings.aiDisplay;
+  // use all rows
+  else aiRows = oSettings.aiDisplayMaster; // all row numbers
+
+  // set up data array
+  var asResultData = new Array();
+
+  for (var i=0,c=aiRows.length; i<c; i++) {
+    iRow = aiRows[i];
+    var sValue = this.fnGetData(iRow, iColumn);
+
+    // ignore empty values?
+    if (bIgnoreEmpty == true && sValue.length == 0) continue;
+
+    // ignore unique values?
+    else if (bUnique == true && jQuery.inArray(sValue, asResultData) > -1) continue;
+
+    // else push the value onto the result data array
+    else asResultData.push(sValue);
+  }
+
+  return asResultData;
+};
+
 
 

+ 11 - 4
ambari-web/app/utils/db.js

@@ -273,7 +273,7 @@ App.db.setServiceConfigProperties = function (configProperties) {
 App.db.setClusterStatus = function (status) {
   App.db.data = localStorage.getObject('ambari');
   var user = App.db.data.app.loginName;
-  App.db.data[user].Installer.clusterStatus = status;
+  App.db.data[user].clusterStatus = status;
   console.log('db.setClusterStatus called: ' + JSON.stringify(status));
   localStorage.setObject('ambari', App.db.data);
 }
@@ -315,7 +315,7 @@ App.db.getClusterName = function () {
   console.log('Trace: Entering db:getClusterName function');
   App.db.data = localStorage.getObject('ambari');
   var user = App.db.data.app.loginName;
-  if (user) {
+  if (user && App.db.data[user] && App.db.data[user].Installer) {
     return App.db.data[user].Installer.ClusterName;
   }
 };
@@ -450,7 +450,10 @@ App.db.getHostSlaveComponents = function () {
 App.db.getSlaveComponentHosts = function () {
   App.db.data = localStorage.getObject('ambari');
   var user = App.db.data.app.loginName;
-  return App.db.data[user].Installer.slaveComponentHosts;
+  if(App.db.data[user]&&App.db.data[user].Installer){
+    return App.db.data[user].Installer.slaveComponentHosts;
+  }
+  return null;
 }
 
 App.db.getServiceConfigs = function () {
@@ -469,7 +472,11 @@ App.db.getClusterStatus = function () {
   console.log('TRACE: Entering db:getClusterStatus function');
   App.db.data = localStorage.getObject('ambari');
   var user = App.db.data.app.loginName;
-  return App.db.data[user].Installer.clusterStatus;
+  if(App.db.data[user] && App.db.data[user].clusterStatus){
+    return App.db.data[user].clusterStatus;
+  } else {
+    return null;
+  }
 }
 
 module.exports = App.db;

+ 1 - 1
ambari-web/app/utils/graph.js

@@ -178,7 +178,7 @@ module.exports = {
         var swatch = '<span class="detail_swatch" style="background-color: ' + series.color + '"></span>';
         return swatch + d.label +
           '<br>Run-time: ' + formattedY + '<br>Wait-time: ' + formattedX;
-      },
+      }
 
     });
     var annotator = new Rickshaw.Graph.Annotate({

+ 119 - 0
ambari-web/app/utils/http_client.js

@@ -0,0 +1,119 @@
+/**
+ * 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.HttpClient perform an ajax request
+ */
+App.HttpClient = Em.Object.create({
+
+  /**
+   *
+   * @param jqXHR
+   * @param textStatus
+   * @param errorThrown
+   */
+  defaultErrorHandler: function (jqXHR, textStatus, errorThrown) {
+    var json = $.parseJSON(jqXHR.responseText);
+    if (json) {
+      Em.assert("HttpClient:", json);
+    } else {
+      Em.assert("HttpClient:", errorThrown);
+    }
+  },
+
+  /**
+   * @param {string} url
+   * @param {Object} ajaxOptions
+   * @param {App.ServerDataMapper} mapper - json processor
+   * @param {function} errorHandler
+   * @param {number} interval - frequecy request
+   */
+  request: function (url, ajaxOptions, mapper, errorHandler) {
+
+    if (!errorHandler) {
+      errorHandler = this.defaultErrorHandler;
+    }
+
+    var options = {dataType: 'json'}; // default ajax options;
+
+    $.extend(options, {
+      url: url,
+      success: function (data) {
+        mapper.map(data);
+      },
+      error: errorHandler
+    });
+
+    $.extend(options, ajaxOptions);
+
+    $.ajax(options);
+  },
+
+  /**
+   * @param {string} url
+   * @param {App.ServerDataMapper} mapper - json processor
+   * @param {Object} data - ajax data property
+   * @param {function} errorHandler
+   * @param {number} interval - frequecy request
+   */
+  get: function (url, mapper, data, errorHandler, interval) {
+    var client = this;
+    var request = function () {
+      client.request(url, data, mapper, errorHandler);
+    }
+
+    interval = "" + interval;
+    if (interval.match(/\d+/)) {
+      $.periodic({period: interval}, request);
+    } else {
+      request();
+    }
+  },
+
+  /**
+   * @param {string} url
+   * @param {Object} data - ajax data property
+   * @param {App.ServerDataMapper} mapper - json processor
+   * @param {function} errorHandler
+   * @param {number} interval - frequecy request
+   */
+  post: function (url, data, mapper, errorHandler, interval) {
+    this.get(url, data, mapper, errorHandler, interval);
+  }
+
+//  not realized yet
+//  put:function (url, mapper, errorHandler) {
+//    this.request(url, {}, mapper, errorHandler);
+//  },
+//
+//  delete:function (url, mapper, errorHandler) {
+//    this.request(url, {}, mapper, errorHandler);
+//  }
+});
+
+//App.HttpClient.get("/data/hosts/hosts.json", App.hostsMapper);
+
+App.HttpClient.get("/data/dashboard/services.json", App.servicesMapper);
+
+/*App.HttpClient.get(
+  'http://nagiosserver/hdp/nagios/nagios_alerts.php?q1=alerts&alert_type=all',
+  App.alertsMapper,
+  { dataType: 'jsonp', jsonp: 'jsonp' }
+);*/

+ 36 - 0
ambari-web/app/utils/misc.js

@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+module.exports = {
+  /**
+   * Convert value from bytes to appropriate measure
+   */
+  formatBandwidth: function (value) {
+    if (value) {
+      if (value < 1024) {
+        value = '<1KB';
+      } else {
+        if (value < 1048576) {
+          value = Math.round(value / 102.4) / 10 + 'KB';
+        } else {
+          value = Math.round(value / 104857.6) / 10 + 'MB';
+        }
+      }
+    }
+    return value;
+  }
+};

+ 2 - 0
ambari-web/app/views.js

@@ -22,6 +22,7 @@
 
 require('views/application');
 require('views/common/chart');
+require('views/common/combobox');
 require('views/common/chart/pie');
 require('views/common/chart/linear');
 require('views/common/chart/linear_time');
@@ -32,6 +33,7 @@ require('views/common/form/field');
 require('views/common/quick_view_link_view');
 require('views/login');
 require('views/main');
+require('views/main/test');
 require('views/main/menu');
 require('views/main/charts');
 require('views/main/host');

+ 72 - 0
ambari-web/app/views/common/combobox.js

@@ -0,0 +1,72 @@
+/**
+ * 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.Combobox = Em.Select.extend({
+  classNames:['combobox'],
+  placeholderText:false,
+  disabled:false,
+
+  input:function () {
+    return this.get('combobox').$element;
+  }.property('combobox'),
+
+  button:function () {
+    return this.get('combobox').$button;
+  }.property('combobox'),
+
+  toggleDisabling:function () {
+    var disabled = this.get('disabled') ? 'disabled' : false;
+
+    this.get('input').attr('disabled', disabled);
+    this.get('button').attr('disabled', disabled);
+
+  }.observes('disabled'),
+
+  content:function () {
+    // convert DS.RecordsArray to array;
+    var content = [
+      {}
+    ];
+    var racks = this.get('recordArray');
+
+    racks.forEach(function (cluster, index) {
+      content.push(cluster);
+    });
+
+    return content;
+  }.property('recordArray'),
+  clearTextFieldValue:function () {
+    var options = [];
+
+    this.get('combobox').$element.val('');
+    this.get('combobox').clearTarget();
+
+  },
+  didInsertElement:function () {
+    this._super();
+    this.set('combobox', this.$().combobox().data('combobox'));
+
+    this.clearTextFieldValue(); // fix of script tags in
+
+    if (this.get('placeholderText')) {
+      this.get('combobox').$element.attr('placeholder', this.get('placeholderText'));
+    }
+  }
+});

+ 6 - 1
ambari-web/app/views/login.js

@@ -21,6 +21,11 @@ var App = require('app');
 
 App.LoginView = Em.View.extend({
 
-  templateName: require('templates/login')
+  templateName: require('templates/login'),
+  passTextField : Em.TextField.extend({
+    insertNewline: function(){
+      this.get("controller").submit();
+    }
+  })
 
 });

+ 3 - 3
ambari-web/app/views/main/apps/item/bar_view.js

@@ -33,15 +33,15 @@ App.MainAppsItemBarView = Em.View.extend({
         this.set('activeJob', event.context);
 
     },
-    didInsertElement:function (){
+    didInsertElement:function () {
         this.set('activeJob', this.get('firstJob'));
     },
     draw: function() {
         if(!this.get('activeJob')){
             return;//when job is not defined
         }
-        width = 500;
-        height = 420;
+        width = 300;
+        height = 210;
         var desc1 = $('#graph1_desc');
         var desc2 = $('#graph2_desc');
         $('.rickshaw_graph, .rickshaw_legend, .rickshaw_annotation_timeline').html('');

+ 12 - 2
ambari-web/app/views/main/apps/item/dag_view.js

@@ -60,12 +60,22 @@ App.MainAppsItemDagView = Em.View.extend({
         }
       },
       "iDisplayLength": 5,
-      "aLengthMenu": [[5, 10, 25, 50, -1], [5, 10, 25, 50, "All"]]
+      "aLengthMenu": [[5, 10, 25, 50, -1], [5, 10, 25, 50, "All"]],
+      "aoColumns":[
+        null,
+        null,
+        null,
+        null,
+        null,
+        { "sType":"ambari-bandwidth" },
+        { "sType":"ambari-bandwidth" },
+        null
+      ]
     });
     var dagSchema = this.get('parentView.parentView.content').get('workflowContext');
     var jobs = this.get('jobs');
     var graph = new DagViewer(false, 'dag_viewer')
-        .setPhysicalParametrs(800, 250, -800, 0.01)
+        .setPhysicalParametrs(800, 300, -800, 0.01)
         .setData(dagSchema, jobs)
         .drawDag(10, 20, 100);
   }

+ 127 - 37
ambari-web/app/views/main/apps_view.js

@@ -19,6 +19,7 @@
 var App = require('app');
 var date = require('utils/date');
 var validator = require('utils/validator');
+var misc = require('utils/misc');
 
 App.MainAppsView = Em.View.extend({
   templateName:require('templates/main/apps'),
@@ -31,10 +32,6 @@ App.MainAppsView = Em.View.extend({
       var app = App.store.find(App.App, run.get('appId'));
       run.set('appName', app.get('appName'));
       run.set('type', app.get('type'));
-      run.set('numJobsTotal' ,run.get('jobs').get('content').length);
-      run.get('jobs').forEach(function(job) {
-
-      });
     });
     return content;
   }.property('App.router.mainAppsController.content'),
@@ -46,7 +43,7 @@ App.MainAppsView = Em.View.extend({
    * starred - show only filtered runs with stars selected
    */
   viewType : 'all',
-
+  defaultViewType: 'all',
   /**
    * List of users
    */
@@ -174,6 +171,12 @@ App.MainAppsView = Em.View.extend({
     else {
       youngest = '0000-00-00';
     }
+    avgInput = misc.formatBandwidth(avgInput);
+    minInput = misc.formatBandwidth(minInput);
+    maxInput = misc.formatBandwidth(maxInput);
+    avgOutput = misc.formatBandwidth(avgOutput);
+    minOutput = misc.formatBandwidth(minOutput);
+    maxOutput = misc.formatBandwidth(maxOutput);
     ret = {
       'count': this.get('controller.staredRuns').length,
       'jobs': {
@@ -182,12 +185,12 @@ App.MainAppsView = Em.View.extend({
         'max': maxJobs
       },
       'input': {
-        'avg': avgInput.toFixed(2),
+        'avg': avgInput,
         'min': minInput,
         'max': maxInput
       },
       'output': {
-        'avg': avgOutput.toFixed(2),
+        'avg': avgOutput,
         'min': minOutput,
         'max': maxOutput
       },
@@ -207,17 +210,58 @@ App.MainAppsView = Em.View.extend({
    * Click on big star on the avg block
    */
   avgStarClick: function() {
+    if (this.get('viewType') === 'starred') return;
     this.set('whatAvgShow', !this.get('whatAvgShow'));
     $('a.icon-star.a').toggleClass('active');
   },
+  starClicked: function() {
+    var runIndex = this.get('controller.lastStarClicked');
+    if (runIndex < 0) return;
+    if (!this.get('oTable')) return;
+    var rowIndex = -1;
+    // Get real row index
+    var column = this.get('oTable').fnGetColumnData(0);
+    for (var i = 0; i < column.length; i++) {
+      if (runIndex == $(column[i]).text()) {
+        rowIndex = i;
+        break;
+      }
+    }
+    var perPage = this.get('oTable').fnSettings()['_iDisplayLength']; // How many rows show per page
+    var rowIndexVisible = rowIndex; // rowIndexVisible - rowIndex in current visible part of the table
+    if (perPage !== -1) { // If not show All is selected we should recalculate row index according to other visible rows
+      rowIndexVisible = rowIndex % perPage;
+    }
+    // Update inner dataTable value
+    this.get('oTable').fnUpdate( $('#dataTable tbody tr:eq(' + rowIndexVisible + ') td:eq(0)').html(), this.get('oTable').fnSettings()['aiDisplay'][rowIndex], 0);
+    if (perPage !== -1) { // Change page after reDraw (if show All is selected this will not happens)
+      this.get('oTable').fnPageChange(Math.floor(rowIndex / perPage));
+    }
+  }.observes('controller.lastStarClicked'),
   /**
-   * "turn off" stars in the table
+   * Flush all starred runs
    */
   clearStars: function() {
+    this.get('controller').set('staredRuns', []);
+    this.get('controller').set('staredRunsLength', 0);
+    this.set('viewType', this.get('defaultViewType'));
+    this.set('whatAvgShow', true);
+    $('a.icon-star.a').removeClass('active');
+  },
+  /**
+   * "turn off" stars in the table
+   */
+  resetStars: function() {
+    var self = this;
     if (this.get('controller.staredRunsLength') == 0 && this.get('smallStarsIcons') != null) {
       this.get('smallStarsIcons').removeClass('stared');
-      this.set('whatAvgShow', true);
+      $('#dataTable .icon-star').removeClass('stared');
       $('a.icon-star.a').removeClass('active');
+      this.get('starFilterViewInstance').set('value', '');
+      $('#dataTable tbody tr').each(function(index) {
+        var td = $(this).find('td:eq(0)');
+        self.get('oTable').fnUpdate( td.html(), index, 0);
+      });
     }
   }.observes('controller.staredRunsLength'),
   /**
@@ -227,49 +271,71 @@ App.MainAppsView = Em.View.extend({
     this.clearFilters();
     this.clearStars();
   },
-
+  /**
+   * Display only stared rows
+   */
+  showStared: function() {
+    this.get('starFilterViewInstance').set('value', 'stared');
+    this.set('whatAvgShow', false);
+    $('a.icon-star.a').addClass('active');
+  },
   /**
    * Onclick handler for <code>Show All/Filtered/Starred</code> links
    */
-  changeViewType: function(event){
-    if($(event.toElement).hasClass('selected')){
-      return;
-    }
-
-    $(event.toElement).parent().children('.selected').removeClass('selected');
-    $(event.toElement).addClass('selected');
-
-    var viewType = $(event.toElement).data('view-type');
+  clickViewType: function(event) {
+    this.set('viewType', $(event.target).data('view-type'));
+  },
+  onChangeViewType: function(){
+    var viewType = this.get('viewType');
+    var table = this.get('oTable');
+    var filterButtons = $("#filter_buttons").children();
+    filterButtons.each(function(index, element){
+      $(element).removeClass('selected');
+      if(viewType == $(element).data('view-type')){
+        $(element).addClass('selected');
+      }
+    });
     console.log(viewType);
-
-    switch(viewType){
+    switch(viewType) {
       case 'all':
-        //do stuff here
+        table.fnSettings().oFeatures.bFilter = false;
+        table.fnDraw();
+        table.fnSettings().oFeatures.bFilter = true;
         break;
-
       case 'starred':
+        this.showStared();
         break;
-
       case 'filtered':
-      default:
-        //do stuff here
+        table.fnSettings().oFeatures.bFilter = true;
+        table.fnDraw();
         break;
-    };
+      };
 
-  },
+
+  }.observes('viewType'),
 
   /**
    * jQuery dataTable init
    */
-  didInsertElement:function () {
+  createDataTable: function () {
     var smallStars = $('#dataTable .icon-star');
+    var self = this;
     this.set('smallStarsIcons', smallStars);
     var oTable = this.$('#dataTable').dataTable({
       "sDom": '<"search-bar"f><"clear">rt<"page-bar"lip><"clear">',
       "fnDrawCallback": function( oSettings ) {
-        //change average info after table filtering
-        // no need more. 31.10.2012
+        if(!self.get('oTable')){return}
+        if(self.get('viewType') !== 'all') {
+          if (self.get('viewType') !== 'starred') {
+            self.set('filtered', this.fnSettings().fnRecordsDisplay());
+          }
+        }
+        if(self.get('viewType') === 'all' && self.get('oTable').fnSettings().oFeatures.bFilter){
+          self.set('viewType', 'filtered');
+          self.set('filtered', this.fnSettings().fnRecordsDisplay());
+        }
       },
+      "aaSorting": [],
       "oLanguage": {
         "sSearch": "Search:",
         "sLengthMenu": "Show: _MENU_",
@@ -291,8 +357,8 @@ App.MainAppsView = Em.View.extend({
         null,
         null,
         null,
-        null,
-        null,
+        { "sType":"ambari-bandwidth" },
+        { "sType":"ambari-bandwidth" },
         null,
         { "sType":"ambari-date" }
       ]
@@ -301,6 +367,17 @@ App.MainAppsView = Em.View.extend({
     this.set('filtered', oTable.fnSettings().fnRecordsDisplay());
 
   },
+  didInsertElement: function () {
+    var self = this;
+    /**
+     * Running datatable with delay to take time to load all data
+     */
+    Ember.run.next(function () {
+      Ember.run.next(function () {
+        self.createDataTable();
+      })
+    });
+  },
   /**
    * reset all filters in dataTable
    *
@@ -319,6 +396,7 @@ App.MainAppsView = Em.View.extend({
     }
     });
     this.get('oTable').fnFilterClear();
+    this.set('viewType', this.get('defaultViewType'));
     this.set('filtered',this.get('oTable').fnSettings().fnRecordsDisplay());
     this.setFilteredRuns(this.get('oTable')._('tr', {"filter":"applied"}));
   },
@@ -332,8 +410,8 @@ App.MainAppsView = Em.View.extend({
   applyFilter:function(parentView, iColumn, value) {
       value = (value) ? value : '';
       parentView.get('oTable').fnFilter(value, iColumn);
-      parentView.set('filtered',parentView.get('oTable').fnSettings().fnRecordsDisplay());
   },
+
   /**
    * refresh average info in top block when filtered changes
    */
@@ -353,11 +431,11 @@ App.MainAppsView = Em.View.extend({
     content:['Any', 'Pig', 'Hive', 'mapReduce'],
     change:function(event){
       if(this.get('selection') === 'Any') {
-        this._parentView.get('oTable').fnFilter('', 3);
+        this.get('parentView').get('oTable').fnFilter('', 3);
       } else {
-      this._parentView.get('oTable').fnFilter(this.get('selection'), 3);
+      this.get('parentView').get('oTable').fnFilter(this.get('selection'), 3);
       }
-      this._parentView.set('filtered',this._parentView.get('oTable').fnSettings().fnRecordsDisplay());
+      this.get('parentView').set('filtered',this.get('parentView').get('oTable').fnSettings().fnRecordsDisplay());
     }
   }),
   /**
@@ -375,6 +453,18 @@ App.MainAppsView = Em.View.extend({
       this.get('parentView').get('applyFilter')(this.get('parentView'), 9);
     }
   }),
+  /**
+   * Filter-field for Stars. hidden
+   */
+  starFilterView: Em.TextField.extend({
+    classNames:['input-small'],
+    type:'hidden',
+    placeholder: '',
+    elementId:'star_filter',
+    filtering:function() {
+      this.get('parentView').get('applyFilter')(this.get('parentView'), 0);
+    }.observes('value')
+  }),
   /**
    * Filter-field for AppId
    */

+ 23 - 27
ambari-web/app/views/main/dashboard/service.js

@@ -21,33 +21,33 @@ var App = require('app');
 require('models/alert');
 
 App.MainDashboardServiceHealthView = Em.View.extend({
-  classNameBindings:["healthStatus"],
-  template:Em.Handlebars.compile(""),
-  blink:false,
+  classNameBindings: ["healthStatus"],
+  template: Em.Handlebars.compile(""),
+  blink: false,
   tagName: 'span',
 
-  status:function () {
+  status: function () {
     return this.get('service.healthStatus');
   }.property('service.healthStatus'),
 
-  startBlink:function () {
+  startBlink: function () {
     this.set('blink', true);
   },
 
-  doBlink:function () {
+  doBlink: function () {
     if (this.get('blink') && (this.get("state") == "inDOM")) {
-      this.$().effect("pulsate", { times:1 }, "slow", function () {
+      this.$().effect("pulsate", { times: 1 }, "slow", function () {
         var view = Em.View.views[$(this).attr('id')];
         view.doBlink();
       });
     }
   }.observes('blink'),
 
-  stopBlink:function () {
+  stopBlink: function () {
     this.set('blink', false);
   },
 
-  healthStatus:function () {
+  healthStatus: function () {
     var status = this.get('status');
     switch (status) {
       case App.Service.Health.start:
@@ -66,40 +66,36 @@ App.MainDashboardServiceHealthView = Em.View.extend({
     return 'health-status-' + status + " span";
   }.property('status'),
 
-  didInsertElement:function () {
+  didInsertElement: function () {
     this._super();
     this.doBlink(); // check for blink availability
   }
 });
 
 App.MainDashboardServiceView = Em.View.extend({
-  classNames:['service', 'clearfix'],
-  data:function () {
+  classNames: ['service', 'clearfix'],
+
+  data: function () {
     return this.get('controller.data.' + this.get('serviceName'));
   }.property('controller.data'),
-  service:function () {
+
+  service: function () {
     var services = this.get('controller.services');
     if (services) {
-      thisView = this;
-      var serviceProperty = false;
-      services.forEach(function (service) {
-        if (service.get('serviceName') == thisView.get('serviceName')) {
-          return serviceProperty = service;
-        }
-      })
+      return services.findProperty('serviceName', this.get('serviceName'));
     }
-
-    return serviceProperty;
   }.property('controller.services'),
 
-  criticalAlertsCount:function () {
+  criticalAlertsCount: function () {
     var alerts = this.get('service.alerts');
     var count = 0;
 
-    alerts.forEach(function (alert) {
-      count += (alert.get('status') == App.AlertStatus.negative);
-    });
-
+    if (alerts) {
+      alerts.forEach(function (alert) {
+        count += (alert.get('status') == App.AlertStatus.negative);
+      });
+    }
     return count;
   }.property('service.alerts')
+
 });

+ 32 - 12
ambari-web/app/views/main/host.js

@@ -21,13 +21,13 @@ var App = require('app');
 App.MainHostView = Em.View.extend({
   templateName:require('templates/main/host'),
   filterByName:"",
-  controller: function(){
+  controller:function () {
     return App.router.get('mainHostController');
   }.property(),
   content:function () {
     return App.router.get('mainHostController.content');
   }.property('App.router.mainHostController.content'),
-  componentsIds: [1, 2, 3, 4, 5, 6, 7, 8],
+  componentsIds:[1, 2, 3, 4, 5, 6, 7, 8],
 
   isFilterOpen:false,
 
@@ -45,29 +45,29 @@ App.MainHostView = Em.View.extend({
     App.router.get('mainHostController').filterByComponentsIds();
   },
 
-  allComponentsChecked: false,
-  toggleAllComponents: function(){
+  allComponentsChecked:false,
+  toggleAllComponents:function () {
     this.set('masterComponentsChecked', this.get('allComponentsChecked'));
     this.set('slaveComponentsChecked', this.get('allComponentsChecked'));
   }.observes('allComponentsChecked'),
 
-  masterComponentsChecked: false,
-  toggleMasterComponents: function(){
+  masterComponentsChecked:false,
+  toggleMasterComponents:function () {
     var checked = this.get('masterComponentsChecked');
-    this.get('controller.masterComponents').forEach(function(comp){
+    this.get('controller.masterComponents').forEach(function (comp) {
       comp.set('checkedForHostFilter', checked);
     });
   }.observes('masterComponentsChecked'),
 
-  slaveComponentsChecked: false,
-  toggleSlaveComponents: function(){
+  slaveComponentsChecked:false,
+  toggleSlaveComponents:function () {
     var checked = this.get('slaveComponentsChecked');
-    this.get('controller.slaveComponents').forEach(function(comp){
+    this.get('controller.slaveComponents').forEach(function (comp) {
       comp.set('checkedForHostFilter', checked);
     });
   }.observes('slaveComponentsChecked'),
 
-  didInsertElement: function(){
+  didInsertElement:function () {
     this._super();
     this.set('allComponentsChecked', true); // select all components (checkboxes) on start.
   },
@@ -76,7 +76,7 @@ App.MainHostView = Em.View.extend({
     App.router.get('mainHostController').filterHostsBy('hostName', this.get('filterByName'));
   }.observes('filterByName'),
 
-  closeFilters: function(){
+  closeFilters:function () {
     $(document).unbind('click');
     this.clickFilterButton();
   },
@@ -124,5 +124,25 @@ App.MainHostView = Em.View.extend({
         App.router.get('mainHostController').onHostChecked(this.get('content'));
       }
     })
+  }),
+
+  RackCombobox:App.Combobox.extend({
+    disabled:function () {
+      var selectedHostsIds = App.router.get('mainHostController.selectedHostsIds');
+
+      // when user apply assigning and hosts become unchecked, we need to clear textfield
+      if (!selectedHostsIds.length) {
+        this.clearTextFieldValue();
+      }
+
+      return !selectedHostsIds.length;
+
+    }.property('App.router.mainHostController.selectedHostsIds'),
+
+    recordArray:App.Cluster.find(),
+    placeholderText:Em.I18n.t('hosts.assignRack'),
+    selectionBinding:"App.router.mainHostController.selectedRack",
+    optionLabelPath:"content.clusterName",
+    optionValuePath:"content.id"
   })
 });

+ 18 - 3
ambari-web/app/views/main/service/info/configs.js

@@ -20,7 +20,22 @@ var App = require('app');
 
 App.MainServiceInfoConfigsView = Em.View.extend({
   templateName: require('templates/main/service/info/configs'),
-  alerts: function(){
-    return App.router.get('mainAlertController.content');
-  }.property('App.router.mainAlertController.content')
+  didInsertElement: function () {
+    var controller = this.get('controller');
+    controller.loadStep();
+  }
+});
+
+App.ServiceConfigsByCategoryView = Ember.View.extend({
+
+  content: null,
+
+  category: null,
+  serviceConfigs: null, // General, Advanced, NameNode, SNameNode, DataNode, etc.
+
+  categoryConfigs: function () {
+    return this.get('serviceConfigs').filterProperty('category', this.get('category.name'))
+  }.property('serviceConfigs.@each').cacheable(),
+
+  layout: Ember.Handlebars.compile('<div class="accordion-body collapse in"><div class="accordion-inner">{{yield}}</div></div>')
 });

+ 12 - 2
ambari-web/app/views/main/service/info/summary.js

@@ -23,12 +23,22 @@ App.MainServiceInfoSummaryView = Em.View.extend({
   serviceStatus: {
     hdfs: false,
     mapreduce: false,
-    hbase: false
+    hbase: false,
+    zookeeper: false,
+    oozie: false,
+    hive: false
   },
+
   controller: function () {
     return App.router.get('mainServiceInfoSummaryController');
   }.property(),
-
+  data:{
+    hive:{
+      "database"     : "PostgreSQL",
+      "databaseName" : "hive",
+      "user"         : "hive"
+    }
+  },
   service: function () {
     return this.get('controller.content');
   }.property('controller.content'),

+ 24 - 0
ambari-web/app/views/main/test.js

@@ -0,0 +1,24 @@
+/**
+ * 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.MainTestView = Em.View.extend({
+  templateName: require('templates/main/test'),
+  services: App.Service1.find()
+});

+ 39 - 1
ambari-web/app/views/wizard/step2_view.js

@@ -19,6 +19,27 @@
 
 var App = require('app');
 
+App.SshKeyFileUploader = Ember.View.extend({
+  template:Ember.Handlebars.compile('<input type="file" />'),
+
+  change: function (e) {
+    self=this;
+    if (e.target.files && e.target.files.length == 1) {
+      var file = e.target.files[0];
+      var reader = new FileReader();
+
+      reader.onload = (function(theFile) {
+        return function(e) {
+          $('#sshKey').html(e.target.result);
+          //$('.sshKey-file-view').html(e.target.result);
+          self.set("controller.content.sshKey", e.target.result);
+        };
+      })(file);
+      reader.readAsText(file);
+    }
+  }
+});
+
 App.WizardStep2View = Em.View.extend({
 
   templateName: require('templates/wizard/step2'),
@@ -38,7 +59,24 @@ App.WizardStep2View = Em.View.extend({
     } else {
       this.set('hostNameErr', true);
     }
-  }.observes('controller.hostNameEmptyError', 'controller.hostNameNotRequiredErr', 'controller.hostNameErr')
+  }.observes('controller.hostNameEmptyError', 'controller.hostNameNotRequiredErr', 'controller.hostNameErr'),
+
+  sshKeyState: function(){
+    return this.get("controller").get("content.manualInstall");
+  }.property("controller.content.manualInstall"),
+
+  sshKeyClass:function() {
+    //alert(this.get("isFileApi"))
+    return (this.get("isFileApi")) ? "hide" : "" ;
+  }.property("isFileApi"),
+
+  isFileApi: function () {
+    return (window.File && window.FileReader && window.FileList) ? true : false ;
+  }.property(),
+
+  sshKeyPreviewClass: function() {
+    return (this.get('controller.content.sshKey').trim() != '') ? 'sshKey-file-view help-inline' : 'hidden';
+  }.property('controller.content.sshKey')
 
 });
 

+ 2 - 0
ambari-web/config.coffee

@@ -39,6 +39,7 @@ exports.config =
           'vendor/scripts/ember-data-latest.js',
           'vendor/scripts/ember-i18n-1.2.0.js',
           'vendor/scripts/bootstrap.js',
+          'vendor/scripts/bootstrap-combobox.js'
           'vendor/scripts/d3.v2.js',
           'vendor/scripts/sinon-1.4.2.js',
           'vendor/scripts/cubism.v1.js',
@@ -66,6 +67,7 @@ exports.config =
           'vendor/styles/font-awesome-ie7.css',
           'vendor/styles/cubism.css',
           'vendor/styles/rickshaw.css'
+          'vendor/styles/bootstrap-combobox.css'
         ]
 
     templates:

+ 1 - 2
ambari-web/package.json

@@ -19,8 +19,7 @@
     "uglify-js-brunch": ">= 1.0 < 1.5",
     "clean-css-brunch": ">= 1.0 < 1.5",
     "ember-handlebars-brunch": "git://github.com/icholy/ember-handlebars-brunch.git",
-    "less-brunch": "git://github.com/brunch/less-brunch.git",
-    "d3": ">=2.10.3"
+    "less-brunch": "git://github.com/brunch/less-brunch.git"
   },
   "devDependencies": {
     "mocha": "0.14.0",

+ 1 - 1
ambari-web/pom.xml

@@ -16,7 +16,7 @@
   <artifactId>ambari-web</artifactId>
   <packaging>pom</packaging>
   <name>Ambari Web</name>
-  <version>1.0.3-SNAPSHOT</version>
+  <version>1.0.3</version>
   <description>Ambari Web</description>
   <dependencies>
     <dependency>

+ 217 - 0
ambari-web/vendor/scripts/bootstrap-combobox.js

@@ -0,0 +1,217 @@
+/* =============================================================
+ * bootstrap-combobox.js v1.0.0
+ * =============================================================
+ * Copyright 2012 Daniel Farrell
+ *
+ * Licensed 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.
+ * ============================================================ */
+
+!function ($) {
+
+  "use strict"
+
+  var Combobox = function (element, options) {
+    this.options = $.extend({}, $.fn.combobox.defaults, options)
+    this.$container = this.setup(element)
+    this.$element = this.$container.find('input')
+    this.$button = this.$container.find('.dropdown-toggle')
+    this.$target = this.$container.find('select')
+    this.matcher = this.options.matcher || this.matcher
+    this.sorter = this.options.sorter || this.sorter
+    this.highlighter = this.options.highlighter || this.highlighter
+    this.$menu = $(this.options.menu).appendTo('body')
+    this.placeholder = this.options.placeholder || this.$target.attr('data-placeholder')
+    this.$element.attr('placeholder', this.placeholder)
+    this.shown = false
+    this.selected = false
+    this.refresh()
+    this.listen()
+  }
+
+  /* NOTE: COMBOBOX EXTENDS BOOTSTRAP-TYPEAHEAD.js
+   ========================================== */
+
+  Combobox.prototype = $.extend({}, $.fn.typeahead.Constructor.prototype, {
+
+    constructor:Combobox, setup:function (element) {
+      var select = $(element)
+        , combobox = $(this.options.template)
+      select.before(combobox)
+      select.detach()
+      combobox.append(select)
+      return combobox
+    },
+    parse:function () {
+      var map = {}
+        , source = []
+        , selected = false
+      this.$target.find('option').each(function () {
+        var option = $(this)
+        map[option.text()] = option.val()
+        source.push(option.text())
+        if (option.attr('selected')) selected = option.html()
+      })
+      this.map = map
+      if (selected) {
+        this.$element.val(selected)
+        this.$container.addClass('combobox-selected')
+        this.selected = true
+      }
+      return source
+    },
+    toggle:function () {
+      if (this.$container.hasClass('combobox-selected')) {
+        this.clearTarget()
+        this.$element.val('').focus()
+      } else {
+        if (this.shown) {
+          this.hide()
+        } else {
+          this.lookup()
+        }
+      }
+    },
+    clearTarget:function () {
+      this.$target.val('')
+      this.$container.removeClass('combobox-selected')
+      this.selected = false
+      this.$target.trigger('change')
+    },
+    refresh:function () {
+      this.source = this.parse()
+      this.options.items = this.source.length
+    }
+
+    // modified typeahead function adding container and target handling
+    , select:function () {
+      var val = this.$menu.find('.active').attr('data-value')
+      this.$element.val(val)
+      this.$container.addClass('combobox-selected')
+      this.$target.val(this.map[val])
+      this.$target.trigger('change')
+      this.selected = true
+      return this.hide()
+    }
+
+    // modified typeahead function removing the blank handling
+    , lookup:function (event) {
+      var that = this
+        , items
+        , q
+
+      this.query = this.$element.val()
+
+      items = $.grep(this.source, function (item) {
+        if (that.matcher(item)) return item
+      })
+
+      items = this.sorter(items)
+
+      if (!items.length) {
+        return this.shown ? this.hide() : this
+      }
+
+      return this.render(items.slice(0, this.options.items)).show()
+    }
+
+    // modified typeahead function adding button handling
+    , listen:function () {
+      this.$element
+        .on('blur', $.proxy(this.blur, this))
+        .on('keypress', $.proxy(this.keypress, this))
+        .on('keyup', $.proxy(this.keyup, this))
+
+      if ($.browser.webkit || $.browser.msie) {
+        this.$element.on('keydown', $.proxy(this.keypress, this))
+      }
+
+      this.$menu
+        .on('click', $.proxy(this.click, this))
+        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+
+      this.$button
+        .on('click', $.proxy(this.toggle, this))
+    }
+
+    // modified typeahead function to clear on type and prevent on moving around
+    , keyup:function (e) {
+      switch (e.keyCode) {
+        case 40: // down arrow
+        case 39: // right arrow
+        case 38: // up arrow
+        case 37: // left arrow
+        case 36: // home
+        case 35: // end
+        case 16: // shift
+          break
+
+        case 9: // tab
+        case 13: // enter
+          if (!this.shown) return
+          this.select()
+          break
+
+        case 27: // escape
+          if (!this.shown) return
+          this.hide()
+          break
+
+        default:
+          this.clearTarget()
+          this.lookup()
+      }
+
+      e.stopPropagation()
+      e.preventDefault()
+    }
+
+    // modified typeahead function to only hide menu if it is visible
+    , blur:function (e) {
+      var that = this
+      e.stopPropagation()
+      e.preventDefault()
+      var val = this.$element.val()
+      if (!this.selected && val != "") {
+        this.$element.val("")
+        this.$target.val("").trigger('change')
+      }
+      if (this.shown) {
+        setTimeout(function () {
+          that.hide()
+        }, 150)
+      }
+    }
+  })
+
+  /* COMBOBOX PLUGIN DEFINITION
+   * =========================== */
+
+  $.fn.combobox = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('combobox')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('combobox', (data = new Combobox(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.combobox.defaults = {
+    template:'<div class="combobox-container"><input type="text" autocomplete="off" /><button class="add-on btn dropdown-toggle" data-dropdown="dropdown"><span class="caret"/><span class="combobox-clear"><i class="icon-remove"/></span></button></div>',
+    menu:'<ul class="typeahead typeahead-long dropdown-menu"></ul>',
+    item:'<li><a href="#"></a></li>', placeholder:null
+  }
+
+  $.fn.combobox.Constructor = Combobox
+
+}(window.jQuery);

+ 53 - 53
ambari-web/vendor/scripts/jquery.dataTables.js

@@ -745,7 +745,7 @@
             };
           }
           else if (typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1)) {
-            /* If there is a . in the source string then the data source is in a 
+            /* If there is a . in the source string then the data source is in a
              * nested object so we loop over the data for each level to get the next
              * level down. On each loop we test for undefined, and if found immediately
              * return. This allows entire objects to be missing and sDefaultContent to
@@ -1336,9 +1336,9 @@
           _fnCallbackFire(oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
             _fnGetDataMaster(oSettings), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ]);
 
-          /* 
+          /*
            * Need to remove any old row from the display - note we can't just empty the tbody using
-           * $().html('') since this will unbind the jQuery event handlers (even although the node 
+           * $().html('') since this will unbind the jQuery event handlers (even although the node
            * still exists!) - equally we can't use innerHTML, since IE throws an exception.
            */
           var
@@ -1422,7 +1422,7 @@
           var nHolding = $('<div></div>')[0];
           oSettings.nTable.parentNode.insertBefore(nHolding, oSettings.nTable);
 
-          /* 
+          /*
            * All DataTables are wrapped in a div
            */
           oSettings.nTableWrapper = $('<div id="' + oSettings.sTableId + '_wrapper" class="' + oSettings.oClasses.sWrapper + '" role="grid"></div>')[0];
@@ -1590,7 +1590,7 @@
                 iColspan = (!iColspan || iColspan === 0 || iColspan === 1) ? 1 : iColspan;
                 iRowspan = (!iRowspan || iRowspan === 0 || iRowspan === 1) ? 1 : iRowspan;
 
-                /* There might be colspan cells already in this row, so shift our target 
+                /* There might be colspan cells already in this row, so shift our target
                  * accordingly
                  */
                 iColShifted = fnShiftCol(aLayout, i, iColumn);
@@ -2015,7 +2015,7 @@
           }
           else {
             /*
-             * We are starting a new search or the new search string is smaller 
+             * We are starting a new search or the new search string is smaller
              * then the old one (i.e. delete). Search from the master array
              */
             if (oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||
@@ -2028,7 +2028,7 @@
               _fnBuildSearchArray(oSettings, 1);
 
               /* Search through all records to populate the search array
-               * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1 
+               * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1
                * mapping
                */
               for (i = 0; i < oSettings.aiDisplayMaster.length; i++) {
@@ -2505,7 +2505,7 @@
 
 
         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-         * Note that most of the paging logic is done in 
+         * Note that most of the paging logic is done in
          * DataTable.ext.oPagination
          */
 
@@ -2927,11 +2927,11 @@
            * set the width based on the real headers
            */
 
-          // Apply all styles in one pass. Invalidates layout only once because we don't read any 
+          // Apply all styles in one pass. Invalidates layout only once because we don't read any
           // DOM properties.
           _fnApplyToChildren(zeroOut, anHeadSizers);
 
-          // Read all widths in next pass. Forces layout only once because we do not change 
+          // Read all widths in next pass. Forces layout only once because we do not change
           // any DOM properties.
           _fnApplyToChildren(function (nSizer) {
             aApplied.push(_fnStringToCss($(nSizer).width()));
@@ -3165,8 +3165,8 @@
             }
           }
 
-          /* If the number of columns in the DOM equals the number that we have to process in 
-           * DataTables, then we can use the offsets that are created by the web-browser. No custom 
+          /* If the number of columns in the DOM equals the number that we have to process in
+           * DataTables, then we can use the offsets that are created by the web-browser. No custom
            * sizes can be set in order for this to happen, nor scrolling used
            */
           if (iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums &&
@@ -3275,7 +3275,7 @@
               oNodes = _fnGetUniqueThs(oSettings, $('thead', nCalcTmp)[0]);
             }
 
-            /* Browsers need a bit of a hand when a width is assigned to any columns when 
+            /* Browsers need a bit of a hand when a width is assigned to any columns when
              * x-scrolling as they tend to collapse the table to the min-width, even if
              * we sent the column widths. So we need to keep track of what the table width
              * should be by summing the user given values, and the automatic values
@@ -3542,7 +3542,7 @@
              *  	return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
              *  }
              * Basically we have a test for each sorting column, if the data in that column is equal,
-             * test the next column. If all columns match, then we use a numeric sort on the row 
+             * test the next column. If all columns match, then we use a numeric sort on the row
              * positions in the original data array to provide a stable sort.
              */
             oSettings.aiDisplayMaster.sort(function (a, b) {
@@ -3635,14 +3635,14 @@
 
             /*
              * This is a little bit odd I admit... I declare a temporary function inside the scope of
-             * _fnBuildHead and the click handler in order that the code presented here can be used 
-             * twice - once for when bProcessing is enabled, and another time for when it is 
+             * _fnBuildHead and the click handler in order that the code presented here can be used
+             * twice - once for when bProcessing is enabled, and another time for when it is
              * disabled, as we need to perform slightly different actions.
-             *   Basically the issue here is that the Javascript engine in modern browsers don't 
+             *   Basically the issue here is that the Javascript engine in modern browsers don't
              * appear to allow the rendering engine to update the display while it is still executing
-             * it's thread (well - it does but only after long intervals). This means that the 
+             * it's thread (well - it does but only after long intervals). This means that the
              * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
-             * I force an execution break by using setTimeout - but this breaks the expected 
+             * I force an execution break by using setTimeout - but this breaks the expected
              * thread continuation for the end-developer's point of view (their code would execute
              * too early), so we only do it when we absolutely have to.
              */
@@ -3791,11 +3791,11 @@
             }
           }
 
-          /* 
+          /*
            * Apply the required classes to the table body
            * Note that this is given as a feature switch since it can significantly slow down a sort
            * on large data sets (adding and removing of classes is always slow at the best of times..)
-           * Further to this, note that this code is admittedly fairly ugly. It could be made a lot 
+           * Further to this, note that this code is admittedly fairly ugly. It could be made a lot
            * simpler using jQuery selectors and add/removeClass, but that is significantly slower
            * (on the order of 5 times slower) - hence the direct DOM manipulation here.
            * Note that for deferred drawing we do use jQuery - the reason being that taking the first
@@ -3948,7 +3948,7 @@
           var date = new Date();
           date.setTime(date.getTime() + (iSecs * 1000));
 
-          /* 
+          /*
            * Shocking but true - it would appear IE has major issues with having the path not having
            * a trailing slash on it. We need the cookie to be available based on the path, so we
            * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the
@@ -4502,10 +4502,10 @@
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
 		 *
-		 *      // Filter to 'Webkit' and get all data for 
+		 *      // Filter to 'Webkit' and get all data for
 		 *      oTable.fnFilter('Webkit');
 		 *      var data = oTable._('tr', {"filter": "applied"});
-		 *      
+		 *
 		 *      // Do something with the data
 		 *      alert( data.length+" rows matched the filter" );
 		 *    } );
@@ -4556,7 +4556,7 @@
 		 *        giCount+".3",
 		 *        giCount+".4" ]
 		 *      );
-		 *        
+		 *
 		 *      giCount++;
 		 *    }
          */
@@ -4612,7 +4612,7 @@
 		 *        "sScrollY": "200px",
 		 *        "bPaginate": false
 		 *      } );
-		 *      
+		 *
 		 *      $(window).bind('resize', function () {
 		 *        oTable.fnAdjustColumnSizing();
 		 *      } );
@@ -4640,7 +4640,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
-		 *      
+		 *
 		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
 		 *      oTable.fnClearTable();
 		 *    } );
@@ -4666,7 +4666,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable;
-		 *      
+		 *
 		 *      // 'open' an information row when a row is clicked on
 		 *      $('#example tbody tr').click( function () {
 		 *        if ( oTable.fnIsOpen(this) ) {
@@ -4675,7 +4675,7 @@
 		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
 		 *        }
 		 *      } );
-		 *      
+		 *
 		 *      oTable = $('#example').dataTable();
 		 *    } );
          */
@@ -4710,7 +4710,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
-		 *      
+		 *
 		 *      // Immediately remove the first row
 		 *      oTable.fnDeleteRow( 0 );
 		 *    } );
@@ -4896,7 +4896,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
-		 *      
+		 *
 		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
 		 *      oTable.fnDraw();
 		 *    } );
@@ -4926,7 +4926,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
-		 *      
+		 *
 		 *      // Sometime later - filter...
 		 *      oTable.fnFilter( 'test string' );
 		 *    } );
@@ -5066,7 +5066,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
-		 *      
+		 *
 		 *      // Get the nodes from the table
 		 *      var nNodes = oTable.fnGetNodes( );
 		 *    } );
@@ -5096,15 +5096,15 @@
 		 *      $('#example tbody td').click( function () {
 		 *        // Get the position of the current data from the node
 		 *        var aPos = oTable.fnGetPosition( this );
-		 *        
+		 *
 		 *        // Get the data array for this row
 		 *        var aData = oTable.fnGetData( aPos[0] );
-		 *        
+		 *
 		 *        // Update the data array and return the value
 		 *        aData[ aPos[1] ] = 'clicked';
 		 *        this.innerHTML = 'clicked';
 		 *      } );
-		 *      
+		 *
 		 *      // Init DataTables
 		 *      oTable = $('#example').dataTable();
 		 *    } );
@@ -5134,7 +5134,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable;
-		 *      
+		 *
 		 *      // 'open' an information row when a row is clicked on
 		 *      $('#example tbody tr').click( function () {
 		 *        if ( oTable.fnIsOpen(this) ) {
@@ -5143,7 +5143,7 @@
 		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
 		 *        }
 		 *      } );
-		 *      
+		 *
 		 *      oTable = $('#example').dataTable();
 		 *    } );
          */
@@ -5176,7 +5176,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable;
-		 *      
+		 *
 		 *      // 'open' an information row when a row is clicked on
 		 *      $('#example tbody tr').click( function () {
 		 *        if ( oTable.fnIsOpen(this) ) {
@@ -5185,7 +5185,7 @@
 		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
 		 *        }
 		 *      } );
-		 *      
+		 *
 		 *      oTable = $('#example').dataTable();
 		 *    } );
          */
@@ -5266,7 +5266,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
-		 *      
+		 *
 		 *      // Hide the second column after initialisation
 		 *      oTable.fnSetColumnVis( 1, false );
 		 *    } );
@@ -5345,8 +5345,8 @@
             oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns(oSettings);
           }
 
-          /* Do a redraw incase anything depending on the table columns needs it 
-           * (built-in: scrolling) 
+          /* Do a redraw incase anything depending on the table columns needs it
+           * (built-in: scrolling)
            */
           if (bRedraw === undefined || bRedraw) {
             _fnAdjustColumnSizing(oSettings);
@@ -5367,7 +5367,7 @@
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
 		 *      var oSettings = oTable.fnSettings();
-		 *      
+		 *
 		 *      // Show an example parameter from the settings
 		 *      alert( oSettings._iDisplayStart );
 		 *    } );
@@ -5386,7 +5386,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
-		 *      
+		 *
 		 *      // Sort immediately with columns 0 and 1
 		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
 		 *    } );
@@ -5408,7 +5408,7 @@
          *  @example
          *    $(document).ready(function() {
 		 *      var oTable = $('#example').dataTable();
-		 *      
+		 *
 		 *      // Sort on column 1, when 'sorter' is clicked on
 		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
 		 *    } );
@@ -5434,10 +5434,10 @@
          *
          *  @example
          *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
-		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row
-		 *    } );
+         *      var oTable = $('#example').dataTable();
+         *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
+         *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row
+         *    } );
          */
         this.fnUpdate = function (mData, mRow, iColumn, bRedraw, bAction) {
           var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
@@ -5795,8 +5795,8 @@
           }
 
           if (oInit.bJQueryUI) {
-            /* Use the JUI classes object for display. You could clone the oStdClasses object if 
-             * you want to have multiple tables with multiple independent classes 
+            /* Use the JUI classes object for display. You could clone the oStdClasses object if
+             * you want to have multiple tables with multiple independent classes
              */
             $.extend(oSettings.oClasses, DataTable.ext.oJUIClasses);
 
@@ -5842,7 +5842,7 @@
           /* Language definitions */
           if (oInit.oLanguage.sUrl !== "") {
             /* Get the language definitions from a file - because this Ajax call makes the language
-             * get async to the remainder of this function we use bInitHandedOff to indicate that 
+             * get async to the remainder of this function we use bInitHandedOff to indicate that
              * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
              */
             oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;

+ 198 - 0
ambari-web/vendor/scripts/jquery.periodic.js

@@ -0,0 +1,198 @@
+/*!
+ * jQuery periodic plugin
+ *
+ * Copyright 2010, Tom Anderson
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ */
+
+jQuery.periodic = function (options, callback) {
+
+  // if the first argument is a function then assume the options aren't being passed
+  if (jQuery.isFunction(options)) {
+    callback = options;
+    options = {};
+  }
+
+  // Merge passed settings with default values
+  var settings = jQuery.extend({}, jQuery.periodic.defaults, {
+    ajax_complete : ajaxComplete,
+    increment     : increment,
+    reset         : reset,
+    cancel        : cancel
+  }, options);
+
+  // bookkeeping variables
+  settings.cur_period = settings.period;
+  settings.tid = false;
+  var prev_ajax_response = '';
+
+  run();
+
+  // return settings so user can tweak them externally
+  return settings;
+
+  // run (or restart if already running) the looping construct
+  function run() {
+    // clear/stop existing timer (multiple calls to run() won't result in multiple timers)
+    cancel();
+    // let it rip!
+    settings.tid = setTimeout(function() {
+      // set the context (this) for the callback to the settings object
+      callback.call(settings);
+
+      // compute the next value for cur_period
+      increment();
+
+      // queue up the next run
+      if(settings.tid)
+        run();
+    }, settings.cur_period);
+  }
+
+  // utility function for use with ajax calls
+  function ajaxComplete(xhr, status) {
+    if (status === 'success' && prev_ajax_response !== xhr.responseText) {
+      // reset the period whenever the response changes
+      prev_ajax_response = xhr.responseText;
+      reset();
+    }
+  }
+
+  // compute the next delay
+  function increment() {
+    settings.cur_period *= settings.decay;
+    if (settings.cur_period < settings.period) {
+      // don't let it drop below the minimum
+      reset();
+    } else if (settings.cur_period > settings.max_period) {
+      settings.cur_period = settings.max_period;
+      if (settings.on_max !== undefined) {
+        // call the user-supplied callback if we reach max_period
+        settings.on_max.call(settings);
+      }
+    }
+  }
+
+  function reset() {
+    settings.cur_period = settings.period;
+    // restart with the new timeout
+    run();
+  }
+
+  function cancel() {
+    clearTimeout(settings.tid);
+    settings.tid = null;
+  }
+
+  // other functions we might want to implement
+  function pause() {}
+  function resume() {}
+  function log() {}
+};
+
+jQuery.periodic.defaults = {
+    period       : 4000,      // 4 sec.
+    max_period   : 1800000,   // 30 min.
+    decay        : 1.5,       // time period multiplier
+    on_max       : undefined  // called if max_period is reached
+};
+/*!
+ * jQuery periodic plugin
+ *
+ * Copyright 2010, Tom Anderson
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ */
+
+jQuery.periodic = function (options, callback) {
+
+  // if the first argument is a function then assume the options aren't being passed
+  if (jQuery.isFunction(options)) {
+    callback = options;
+    options = {};
+  }
+
+  // Merge passed settings with default values
+  var settings = jQuery.extend({}, jQuery.periodic.defaults, {
+    ajax_complete : ajaxComplete,
+    increment     : increment,
+    reset         : reset,
+    cancel        : cancel
+  }, options);
+
+  // bookkeeping variables
+  settings.cur_period = settings.period;
+  settings.tid = false;
+  var prev_ajax_response = '';
+
+  run();
+
+  // return settings so user can tweak them externally
+  return settings;
+
+  // run (or restart if already running) the looping construct
+  function run() {
+    // clear/stop existing timer (multiple calls to run() won't result in multiple timers)
+    cancel();
+    // let it rip!
+    settings.tid = setTimeout(function() {
+      // set the context (this) for the callback to the settings object
+      callback.call(settings);
+
+      // compute the next value for cur_period
+      increment();
+      
+      // queue up the next run
+      if(settings.tid)
+        run();
+    }, settings.cur_period);
+  }
+
+  // utility function for use with ajax calls
+  function ajaxComplete(xhr, status) {
+    if (status === 'success' && prev_ajax_response !== xhr.responseText) {
+      // reset the period whenever the response changes
+      prev_ajax_response = xhr.responseText;
+      reset();
+    }
+  }
+
+  // compute the next delay
+  function increment() {
+    settings.cur_period *= settings.decay;
+    if (settings.cur_period < settings.period) {
+      // don't let it drop below the minimum
+      reset();
+    } else if (settings.cur_period > settings.max_period) {
+      settings.cur_period = settings.max_period;
+      if (settings.on_max !== undefined) {
+        // call the user-supplied callback if we reach max_period
+        settings.on_max.call(settings);
+      }
+    }
+  }
+
+  function reset() {
+    settings.cur_period = settings.period;
+    // restart with the new timeout
+    run();
+  }
+
+  function cancel() {
+    clearTimeout(settings.tid);
+    settings.tid = null;
+  }
+  
+  // other functions we might want to implement
+  function pause() {}
+  function resume() {}
+  function log() {}
+};
+
+jQuery.periodic.defaults = {
+    period       : 4000,      // 4 sec.
+    max_period   : 1800000,   // 30 min.
+    decay        : 1.5,       // time period multiplier
+    on_max       : undefined  // called if max_period is reached
+};

+ 180 - 0
ambari-web/vendor/styles/bootstrap-combobox.css

@@ -0,0 +1,180 @@
+.combobox-container {
+    margin-bottom: 5px;
+    *zoom: 1;
+}
+
+.combobox-container:before,
+.combobox-container:after {
+    display: table;
+    content: "";
+}
+
+.combobox-container:after {
+    clear: both;
+}
+
+.combobox-container input,
+.combobox-container .uneditable-input {
+    -webkit-border-radius: 0 3px 3px 0;
+    -moz-border-radius: 0 3px 3px 0;
+    border-radius: 0 3px 3px 0;
+}
+
+.combobox-container input:focus,
+.combobox-container .uneditable-input:focus {
+    position: relative;
+    z-index: 2;
+}
+
+.combobox-container .uneditable-input {
+    border-left-color: #ccc;
+}
+
+.combobox-container .add-on {
+    float: left;
+    display: block;
+    width: auto;
+    min-width: 16px;
+    height: 18px;
+    margin-right: -1px;
+    padding: 4px 5px;
+    font-weight: normal;
+    line-height: 18px;
+    color: #999999;
+    text-align: center;
+    text-shadow: 0 1px 0 #ffffff;
+    background-color: #f5f5f5;
+    border: 1px solid #ccc;
+    -webkit-border-radius: 3px 0 0 3px;
+    -moz-border-radius: 3px 0 0 3px;
+    border-radius: 3px 0 0 3px;
+}
+
+.combobox-container .active {
+    background-color: #a9dba9;
+    border-color: #46a546;
+}
+
+.combobox-container input,
+.combobox-container .uneditable-input {
+    float: left;
+    -webkit-border-radius: 3px 0 0 3px;
+    -moz-border-radius: 3px 0 0 3px;
+    border-radius: 3px 0 0 3px;
+}
+
+.combobox-container .uneditable-input {
+    border-left-color: #eee;
+    border-right-color: #ccc;
+}
+
+.combobox-container .add-on {
+    margin-right: 0;
+    margin-left: -1px;
+    -webkit-border-radius: 0 3px 3px 0;
+    -moz-border-radius: 0 3px 3px 0;
+    border-radius: 0 3px 3px 0;
+}
+
+.combobox-container input:first-child {
+    *margin-left: -160px;
+}
+
+.combobox-container input:first-child + .add-on {
+    *margin-left: -21px;
+}
+
+.combobox-container select {
+    display: inline-block;
+    width: 0;
+    height: 0;
+    border: 0;
+    padding: 0;
+    margin: 0;
+    text-indent: -99999px;
+    *text-indent: 0;
+}
+
+.form-search .combobox-container,
+.form-inline .combobox-container {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: top;
+}
+
+.form-search .combobox-container .add-on,
+.form-inline .combobox-container .add-on {
+    vertical-align: middle;
+}
+
+.combobox-selected .combobox-clear {
+    display: inline-block;
+}
+
+.combobox-selected .caret {
+    display: none;
+}
+
+.combobox-clear {
+    display: none;
+    width: 14px;
+    height: 14px;
+    line-height: 14px;
+    vertical-align: top;
+    opacity: 0.3;
+    filter: alpha(opacity = 30);
+}
+
+.dropdown:hover .combobox-clear,
+.open.dropdown .combobox-clear {
+    opacity: 1;
+    filter: alpha(opacity = 100);
+}
+
+.btn .combobox-clear {
+    margin-top: 1px;
+    margin-left: 1px;
+}
+
+.btn:hover .combobox-clear,
+.open.btn-group .combobox-clear {
+    opacity: 1;
+    filter: alpha(opacity = 100);
+}
+
+.typeahead-long {
+    max-height: 300px;
+    overflow-y: auto;
+}
+
+.control-group.error .combobox-container .add-on {
+    color: #B94A48;
+    border-color: #B94A48;
+}
+
+.control-group.error .combobox-container .caret {
+    border-top-color: #B94A48;
+}
+
+.control-group.warning .combobox-container .add-on {
+    color: #C09853;
+    border-color: #C09853;
+}
+
+.control-group.warning .combobox-container .caret {
+    border-top-color: #C09853;
+}
+
+.control-group.success .combobox-container .add-on {
+    color: #468847;
+    border-color: #468847;
+}
+
+.control-group.success .combobox-container .caret {
+    border-top-color: #468847;
+}
+
+.combobox-container button.add-on {
+    height: 30px;
+    width: 30px;
+}

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