瀏覽代碼

AMBARI-2234. Host Details Page: Update host component actions and icons depending on state. (yusaku)
AMBARI-2230. Nagios user is presented in Admin > Misc page when Nagios service was not installed. (yusaku)
AMBARI-2231. Service web UI links map to hostnames not resolvable by the client. (yusaku)

git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/trunk@1488035 13f79535-47bb-0310-9956-ffa450edef68

Yusaku Sako 12 年之前
父節點
當前提交
fe0e2c563f
共有 71 個文件被更改,包括 2244 次插入926 次删除
  1. 9 0
      CHANGES.txt
  2. 2 2
      ambari-agent/src/main/puppet/modules/hdp-oozie/manifests/init.pp
  3. 5 5
      ambari-agent/src/main/puppet/modules/hdp-yarn/files/validateYarnComponentStatus.py
  4. 11 1
      ambari-agent/src/main/puppet/modules/hdp-yarn/manifests/nodemanager.pp
  5. 5 4
      ambari-agent/src/main/puppet/modules/hdp-yarn/manifests/params.pp
  6. 6 6
      ambari-agent/src/main/puppet/modules/hdp-yarn/manifests/smoketest.pp
  7. 2 0
      ambari-agent/src/main/python/ambari_agent/Heartbeat.py
  8. 1 0
      ambari-server/docs/api/v1/clusters.md
  9. 1 0
      ambari-server/docs/api/v1/create-cluster.md
  10. 1 0
      ambari-server/docs/api/v1/create-component.md
  11. 1 0
      ambari-server/docs/api/v1/create-host.md
  12. 1 0
      ambari-server/docs/api/v1/create-hostcomponent.md
  13. 1 0
      ambari-server/docs/api/v1/create-service.md
  14. 1 0
      ambari-server/docs/api/v1/delete-cluster.md
  15. 1 0
      ambari-server/docs/api/v1/host-component-resources.md
  16. 1 1
      ambari-server/docs/api/v1/host-components.md
  17. 0 0
      ambari-server/docs/api/v1/index.md
  18. 22 0
      ambari-server/docs/api/v1/job-resources.md
  19. 60 0
      ambari-server/docs/api/v1/jobs-job.md
  20. 42 0
      ambari-server/docs/api/v1/jobs.md
  21. 1 1
      ambari-server/docs/api/v1/services.md
  22. 22 0
      ambari-server/docs/api/v1/taskattempt-resources.md
  23. 48 0
      ambari-server/docs/api/v1/taskattempts-taskattempt.md
  24. 70 0
      ambari-server/docs/api/v1/taskattempts.md
  25. 2 1
      ambari-server/docs/api/v1/update-hostcomponent.md
  26. 26 31
      ambari-server/docs/api/v1/update-service.md
  27. 1 0
      ambari-server/docs/api/v1/update-services.md
  28. 22 0
      ambari-server/docs/api/v1/workflow-resources.md
  29. 57 0
      ambari-server/docs/api/v1/workflows-workflow.md
  30. 48 0
      ambari-server/docs/api/v1/workflows.md
  31. 396 236
      ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
  32. 321 198
      ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
  33. 17 5
      ambari-server/src/main/java/org/apache/ambari/server/state/host/HostImpl.java
  34. 126 77
      ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
  35. 8 8
      ambari-server/src/main/resources/stacks/HDP/1.3.0/repos/repoinfo.xml
  36. 8 8
      ambari-server/src/main/resources/stacks/HDPLocal/1.3.0/repos/repoinfo.xml
  37. 0 0
      ambari-server/src/test/resources/deploy_HDP2.sh
  38. 2 0
      ambari-web/app/config.js
  39. 2 2
      ambari-web/app/controllers/global/cluster_controller.js
  40. 3 0
      ambari-web/app/controllers/main/admin/misc_controller.js
  41. 21 17
      ambari-web/app/controllers/main/host.js
  42. 3 1
      ambari-web/app/controllers/main/host/details.js
  43. 1 14
      ambari-web/app/controllers/wizard/step7_controller.js
  44. 34 103
      ambari-web/app/data/HDP2/config_mapping.js
  45. 252 25
      ambari-web/app/data/HDP2/config_properties.js
  46. 48 24
      ambari-web/app/data/config_properties.js
  47. 2 1
      ambari-web/app/messages.js
  48. 27 7
      ambari-web/app/models/host_component.js
  49. 1 1
      ambari-web/app/models/service.js
  50. 0 4
      ambari-web/app/models/service_config.js
  51. 20 0
      ambari-web/app/styles/application.less
  52. 6 4
      ambari-web/app/templates/main/admin/misc.hbs
  53. 49 32
      ambari-web/app/templates/main/host/summary.hbs
  54. 2 2
      ambari-web/app/templates/wizard/step9HostTasksLogPopup.hbs
  55. 15 5
      ambari-web/app/utils/config.js
  56. 83 1
      ambari-web/app/utils/db.js
  57. 1 1
      ambari-web/app/views/common/configs/services_config.js
  58. 5 0
      ambari-web/app/views/common/filter_view.js
  59. 8 3
      ambari-web/app/views/common/quick_view_link_view.js
  60. 48 1
      ambari-web/app/views/common/sort_view.js
  61. 105 12
      ambari-web/app/views/common/table_view.js
  62. 1 1
      ambari-web/app/views/main/dashboard/service/hbase.js
  63. 1 1
      ambari-web/app/views/main/dashboard/service/hdfs.js
  64. 1 1
      ambari-web/app/views/main/dashboard/service/mapreduce.js
  65. 1 1
      ambari-web/app/views/main/dashboard/service/oozie.js
  66. 45 15
      ambari-web/app/views/main/host.js
  67. 88 50
      ambari-web/app/views/main/host/summary.js
  68. 12 6
      ambari-web/app/views/main/mirroring/datasets_view.js
  69. 10 5
      ambari-web/app/views/main/mirroring/jobs_view.js
  70. 1 1
      ambari-web/app/views/main/service/info/summary.js
  71. 0 1
      pom.xml

+ 9 - 0
CHANGES.txt

@@ -312,6 +312,9 @@ Trunk (unreleased changes):
 
  IMPROVEMENTS
 
+ AMBARI-2234. Host Details Page: Update host component actions and icons
+ depending on state. (yusaku)
+
  AMBARI-2199. Add a legend to Job Timeline. (billie via yusaku)
 
  AMBARI-2212. Change config loading mechanism to allow for different
@@ -906,6 +909,12 @@ Trunk (unreleased changes):
  Farrellee via mahadev)
 
  BUG FIXES
+ 
+ AMBARI-2230. Nagios user is presented in Admin > Misc page when Nagios
+ service was not installed. (yusaku)
+
+ AMBARI-2231. Service web UI links map to hostnames not resolvable by the
+ client. (yusaku)
 
  AMBARI-2239. secure cluster: Namenode and SNamenode should use same
  keytab. (jaimin)

+ 2 - 2
ambari-agent/src/main/puppet/modules/hdp-oozie/manifests/init.pp

@@ -39,13 +39,13 @@ class hdp-oozie(
       configuration => $configuration['oozie-site'],
       owner => $oozie_user,
       group => $hdp::params::user_group,
-      mode => '0660'
+      mode => '0664'
     }
   } else {
     file { "${oozie_config_dir}/oozie-site.xml":
       owner => $oozie_user,
       group => $hdp::params::user_group,
-      mode => '0660'
+      mode => '0664'
     }
   }
 

+ 5 - 5
ambari-agent/src/main/puppet/modules/hdp-yarn/files/validateYarnComponentStatus.py

@@ -27,10 +27,10 @@ HISTORYSERVER ='hs'
 
 STARTED_STATE = 'STARTED'
 
-def validate(component, path, port):
+def validate(component, path, address):
 
   try:
-    url = 'http://localhost:' + str(port) + path
+    url = 'http://' + address + path
     opener = urllib2.build_opener()
     urllib2.install_opener(opener)
     request = urllib2.Request(url)
@@ -71,14 +71,14 @@ def validateResponse(component, response):
 #
 def main():
   parser = optparse.OptionParser(usage="usage: %prog [options] component ")
-  parser.add_option("-p", "--port", dest="port", help="Port for rest api of desired component")
+  parser.add_option("-p", "--port", dest="address", help="Host:Port for REST API of a desired component")
 
 
   (options, args) = parser.parse_args()
 
   component = args[0]
   
-  port = options.port
+  address = options.address
   
   if component == RESOURCEMANAGER:
     path = '/ws/v1/cluster/info'
@@ -87,7 +87,7 @@ def main():
   else:
     parser.error("Invalid component")
 
-  validate(component, path, port)
+  validate(component, path, address)
 
 if __name__ == "__main__":
   main()

+ 11 - 1
ambari-agent/src/main/puppet/modules/hdp-yarn/manifests/nodemanager.pp

@@ -24,6 +24,7 @@ class hdp-yarn::nodemanager(
 ) inherits hdp-yarn::params
 {
   $yarn_user = $hdp-yarn::params::yarn_user
+  $nm_local_dirs = $hdp-yarn::params::nm_local_dirs
   
   if ($service_state == 'no_op') {
   } elsif ($service_state in 'installed_and_configured') {
@@ -36,12 +37,21 @@ class hdp-yarn::nodemanager(
   } elsif ($service_state in ['running','stopped']) {
 
     include hdp-yarn::initialize
- 
+
+    hdp::directory_recursive_create { $nm_local_dirs: 
+      owner       => $yarn_user,
+      context_tag => 'yarn_service',
+      service_state => $service_state,
+      force => true
+    }
+
     hdp-yarn::service{ 'nodemanager':
       ensure       => $service_state,
       user         => $yarn_user
     }
 
+    Hdp::Directory_recursive_create[$nm_local_dirs] -> Hdp-yarn::Service['nodemanager']
+
   } else {
     hdp_fail("TODO not implemented yet: service_state = ${service_state}")
   }

+ 5 - 4
ambari-agent/src/main/puppet/modules/hdp-yarn/manifests/params.pp

@@ -36,8 +36,9 @@ class hdp-yarn::params(
   $yarn_pid_dir_prefix = hdp_default("hadoop/yarn-env/yarn_pid_dir_prefix","/var/run/hadoop-yarn")
   
   ## yarn-site
-  $rm_webui_port = hdp_default("yarn-site/yarn.resourcemanager.webapp.address", "8088")
-  $nm_webui_port = hdp_default("yarn-site/yarn.nodemanager.webapp.address", "8042")
-  $hs_webui_port = hdp_default("yarn-site/mapreduce.jobhistory.address", "19888")
-
+  $rm_webui_address = hdp_default("yarn-site/yarn.resourcemanager.webapp.address", "localhost:8088")
+  $nm_webui_address = hdp_default("yarn-site/yarn.nodemanager.webapp.address", "localhost:8042")
+  $hs_webui_address = hdp_default("mapred-site/mapreduce.jobhistory.webapp.address", "localhost:19888")
+  
+  $nm_local_dirs = hdp_default("yarn-site/yarn.nodemanager.local-dirs", "/yarn/loc/dir") 
 }

+ 6 - 6
ambari-agent/src/main/puppet/modules/hdp-yarn/manifests/smoketest.pp

@@ -22,16 +22,16 @@ class hdp-yarn::smoketest(
   $component_name = undef
 )
 {
-  $rm_webui_port = $hdp-yarn::params::rm_webui_port
-  $nm_webui_port = $hdp-yarn::params::nm_webui_port
-  $hs_webui_port = $hdp-yarn::params::hs_webui_port
+  $rm_webui_address = $hdp-yarn::params::rm_webui_address
+  $nm_webui_address = $hdp-yarn::params::nm_webui_address
+  $hs_webui_address = $hdp-yarn::params::hs_webui_address
 
   if ($component_name == 'resourcemanager') {
     $component_type = 'rm'
-    $component_port = $rm_webui_port
+    $component_address = $rm_webui_address
   } elsif ($component_name == 'historyserver') {
     $component_type = 'hs' 
-    $component_port = $hs_webui_port
+    $component_address = $hs_webui_address
   } else {
     hdp_fail("Unsupported component name: $component_name")
   }
@@ -41,7 +41,7 @@ class hdp-yarn::smoketest(
   $validateStatusFileName = "validateYarnComponentStatus.py"
   $validateStatusFilePath = "/tmp/$validateStatusFileName"
 
-  $validateStatusCmd = "su - ${smoke_test_user} -c 'python $validateStatusFilePath $component_type -p $component_port'"
+  $validateStatusCmd = "su - ${smoke_test_user} -c 'python $validateStatusFilePath $component_type -p $component_address'"
 
   file { $validateStatusFilePath:
     ensure => present,

+ 2 - 0
ambari-agent/src/main/python/ambari_agent/Heartbeat.py

@@ -57,6 +57,8 @@ class Heartbeat:
       heartbeat['reports'] = queueResult['reports']
       heartbeat['componentStatus'] = queueResult['componentStatus']
       pass
+    logger.info("Sending heartbeat with response id: " + str(id) + " and "
+                "timestamp: " + str(timestamp))
     logger.debug("Heartbeat : " + pformat(heartbeat))
 
     if (int(id) >= 0) and state_interval > 0 and (int(id) % state_interval) == 0:

+ 1 - 0
ambari-server/docs/api/v1/clusters.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with

+ 1 - 0
ambari-server/docs/api/v1/create-cluster.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with

+ 1 - 0
ambari-server/docs/api/v1/create-component.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with

+ 1 - 0
ambari-server/docs/api/v1/create-host.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with

+ 1 - 0
ambari-server/docs/api/v1/create-hostcomponent.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with

+ 1 - 0
ambari-server/docs/api/v1/create-service.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with

+ 1 - 0
ambari-server/docs/api/v1/delete-cluster.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with

+ 1 - 0
ambari-server/docs/api/v1/host-component-resources.md

@@ -158,3 +158,4 @@ A component can be stopped through the API by setting its state to be INSTALLED
 The user can update the desired state of a host component through the API to be MAINTENANCE (see [update host component](update-hostcomponent.md)).  When a host component is into maintenance state it is basically taken off line. This state can be used, for example, to move a component like NameNode.  The NameNode component can be put in MAINTENANCE mode and then a new NameNode can be created for the service. 
 
 
+

+ 1 - 1
ambari-server/docs/api/v1/host-components.md

@@ -94,4 +94,4 @@ Returns a collection of components running on a the host named "h1" on the clust
     		},
     		...
 		]
-	}
+	}

文件差異過大導致無法顯示
+ 0 - 0
ambari-server/docs/api/v1/index.md


+ 22 - 0
ambari-server/docs/api/v1/job-resources.md

@@ -0,0 +1,22 @@
+<!---
+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.
+-->
+
+# Job Resources
+ 
+
+- [List jobs](jobs.md)
+- [View job information](jobs-job.md)

+ 60 - 0
ambari-server/docs/api/v1/jobs-job.md

@@ -0,0 +1,60 @@
+<!---
+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.
+-->
+
+View Job Information
+=====
+
+[Back to Resources](index.md#resources)
+
+Returns information about a single job in a given workflow.
+
+    GET /clusters/:name/workflows/:workflowid/jobs/:jobid
+
+**Response**
+
+    200 OK
+    {
+        "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001",
+        "Job" : {
+            "cluster_name" : "c1",
+            "workflow_id" : "mr_201305061943_0001",
+            "job_id" : "job_201305061943_0001",
+            "reduces" : 1,
+            "status" : "SUCCESS",
+            "workflow_entity_name" : "X",
+            "input_bytes" : 2009,
+            "output_bytes" : 1968,
+            "conf_path" : "hdfs://your.server:8020/user/ambari-qa/\\.staging/job_201305061943_0001/job\\.xml",
+            "user_name" : "ambari-qa",
+            "elapsed_time" : 25734,
+            "maps" : 1,
+            "name" : "word count",
+            "submit_time" : 1367883861310
+        },
+        "taskattempts" : [
+            {
+                "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001/taskattempts/attempt_201305061943_0001_m_000000_0",
+                "Job" : {
+                    "cluster_name" : "c1",
+                    "workflow_id" : "mr_201305061943_0001",
+                    "job_id" : "job_201305061943_0001",
+                    "task_attempt_id" : "attempt_201305061943_0001_m_000000_0"
+                }
+            },
+            ...
+        ]
+    }

+ 42 - 0
ambari-server/docs/api/v1/jobs.md

@@ -0,0 +1,42 @@
+<!---
+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.
+-->
+
+List Jobs
+=====
+
+[Back to Resources](index.md#resources)
+
+Returns a collection of all jobs in a given workflow.
+
+    GET /clusters/:name/workflows/:workflowid/jobs
+
+**Response**
+
+    200 OK
+    {
+        "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs",
+        "items" : [
+            {
+                "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001",
+                "Job" : {
+                    "cluster_name" : "c1",
+                    "workflow_id" : "mr_201305061943_0001",
+                    "job_id" : "job_201305061943_0001"
+                }
+            }
+        ]
+    }

+ 1 - 1
ambari-server/docs/api/v1/services.md

@@ -92,4 +92,4 @@ Get the collection of the services for the cluster named "c1".
         	  	}	
         	}
         ]
-    }    
+    }    

+ 22 - 0
ambari-server/docs/api/v1/taskattempt-resources.md

@@ -0,0 +1,22 @@
+<!---
+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.
+-->
+
+# TaskAttempt Resources
+ 
+
+- [List task attempts](taskattempts.md)
+- [View task attempt information](taskattempts-taskattempt.md)

+ 48 - 0
ambari-server/docs/api/v1/taskattempts-taskattempt.md

@@ -0,0 +1,48 @@
+<!---
+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.
+-->
+
+View Task Attempt Information
+=====
+
+[Back to Resources](index.md#resources)
+
+Returns information about a single task attempt for a given job.
+
+    GET /clusters/:name/workflows/:workflowid/jobs/:jobid/taskattempts/:taskattempt
+
+**Response**
+
+    200 OK
+    {
+        "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001/taskattempts/attempt_201305061943_0001_m_000000_0",
+        "TaskAttempt" : {
+            "cluster_name" : "c1",
+            "workflow_id" : "mr_201305061943_0001",
+            "job_id" : "job_201305061943_0001",
+            "task_attempt_id" : "attempt_201305061943_0001_m_000000_0",
+            "status" : "SUCCESS",
+            "finish_time" : 1367883874107,
+            "input_bytes" : 2009,
+            "type" : "MAP",
+            "output_bytes" : 61842,
+            "shuffle_finish_time" : 0,
+            "locality" : "NODE_LOCAL",
+            "start_time" : 1367883871399,
+            "sort_finish_fime" : 0,
+            "map_finish_time" : 1367883874107
+        }
+    }

+ 70 - 0
ambari-server/docs/api/v1/taskattempts.md

@@ -0,0 +1,70 @@
+<!---
+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.
+-->
+
+List Task Attempts
+=====
+
+[Back to Resources](index.md#resources)
+
+Returns a collection of all task attempts for a given job.
+
+    GET /clusters/:name/workflows/:workflowid/jobs/:jobid/taskattempts
+
+**Response**
+
+    200 OK
+    {
+        "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001/taskattempts",
+        "items" : [
+            {
+                "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001/taskattempts/attempt_201305061943_0001_m_000001_0",
+                "TaskAttempt" : {
+                    "cluster_name" : "c1",
+                    "task_attempt_id" : "attempt_201305061943_0001_m_000001_0",
+                    "workflow_id" : "mr_201305061943_0001",
+                    "job_id" : "job_201305061943_0001"
+                }
+            },
+            {
+                "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001/taskattempts/attempt_201305061943_0001_m_000002_0",
+                "TaskAttempt" : {
+                    "cluster_name" : "c1",
+                    "task_attempt_id" : "attempt_201305061943_0001_m_000002_0",
+                    "workflow_id" : "mr_201305061943_0001",
+                    "job_id" : "job_201305061943_0001"
+                }
+            },
+            {
+                "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001/taskattempts/attempt_201305061943_0001_r_000000_0",
+                "TaskAttempt" : {
+                    "cluster_name" : "c1",
+                    "task_attempt_id" : "attempt_201305061943_0001_r_000000_0",
+                    "workflow_id" : "mr_201305061943_0001",
+                    "job_id" : "job_201305061943_0001"
+                }
+            },
+            {
+                "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001/taskattempts/attempt_201305061943_0001_m_000000_0",
+                "TaskAttempt" : {
+                    "cluster_name" : "c1",
+                    "task_attempt_id" : "attempt_201305061943_0001_m_000000_0",
+                    "workflow_id" : "mr_201305061943_0001",
+                    "job_id" : "job_201305061943_0001"
+                }
+            }
+        ]
+    }

+ 2 - 1
ambari-server/docs/api/v1/update-hostcomponent.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with
@@ -127,4 +128,4 @@ Put the NAMENODE component into 'MAINTENANCE' mode.
         "id" : 14,
         "status" : "InProgress"
       }
-    }    
+    }    

+ 26 - 31
ambari-server/docs/api/v1/update-service.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with
@@ -22,39 +23,8 @@ Update Service
 
 **Summary**
 
-
-    PUT /clusters/c1/services/HDFS/
-
-**Body**
-
-Start the HDFS service (update the state of the HDFS service to be ‘STARTED’).
-
-
-    PUT /clusters/c1/services/HDFS
-    {
-      "ServiceInfo": {
-        "state" : "STARTED”
-      }
-    }
-
 Update the service identified by ":serviceName" of the cluster identified by ":clusterName".
 
-**Response**
-
-    202 Accepted
-    {
-      "href" : "http://your.ambari.server/api/v1/clusters/c1/requests/3",
-      "Requests" : {
-        "id" : 3,
-        "status" : "InProgress"
-      } 
-    }
-
-**Example 2**
-
-Stop the HDFS service (update the state of the HDFS service to be ‘INSTALLED’).
-
-
     PUT /clusters/:clusterName/services/:serviceName
 
 
@@ -94,6 +64,31 @@ Stop the HDFS service (update the state of the HDFS service to be ‘INSTALLED
 
 **Example 1**
 
+Start the HDFS service (update the state of the HDFS service to be ‘STARTED’).
+
+
+    PUT /clusters/c1/services/HDFS
+    {
+      "ServiceInfo": {
+        "state" : "STARTED”
+      }
+    }
+
+    202 Accepted
+    {
+      "href" : "http://your.ambari.server/api/v1/clusters/c1/requests/3",
+      "Requests" : {
+        "id" : 3,
+        "status" : "InProgress"
+      } 
+    }
+
+**Example 2**
+
+Stop the HDFS service (update the state of the HDFS service to be ‘INSTALLED’).
+
+
+    PUT /clusters/c1/services/HDFS/
     {
       "ServiceInfo": {
         "state" : "INSTALLED”

+ 1 - 0
ambari-server/docs/api/v1/update-services.md

@@ -1,3 +1,4 @@
+
 <!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements. See the NOTICE file distributed with

+ 22 - 0
ambari-server/docs/api/v1/workflow-resources.md

@@ -0,0 +1,22 @@
+<!---
+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.
+-->
+
+# Workflow Resources
+ 
+
+- [List workflows](workflows.md)
+- [View workflow information](workflows-workflow.md)

+ 57 - 0
ambari-server/docs/api/v1/workflows-workflow.md

@@ -0,0 +1,57 @@
+<!---
+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.
+-->
+
+View Workflow Information
+=====
+
+[Back to Resources](index.md#resources)
+
+Returns information about a single workflow in a given cluster.
+
+    GET /clusters/:name/workflows/:workflowid
+
+**Response**
+
+    200 OK
+    {
+        "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001",
+        "Workflow" : {
+            "cluster_name" : "c1",
+            "workflow_id" : "mr_201305061943_0001"
+            "last_update_time" : 1367883887044,
+            "input_bytes" : 2009,
+            "output_bytes" : 1968,
+            "user_name" : "ambari-qa",
+            "elapsed_time" : 25734,
+            "num_jobs_total" : 1,
+            "num_jobs_completed" : 1,
+            "name" : "word count",
+            "context" : "{\"workflowId\":null,\"workflowName\":null,\"workflowDag\":{\"entries\":[{\"source\":\"X\",\"targets\":[]}]},\"parentWorkflowContext\":null,\"workflowEntityName\":null}",
+            "start_time" : 1367883861310,
+            "parent_id" : null
+        },
+        "jobs" : [
+            {
+                "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001/jobs/job_201305061943_0001",
+                "Job" : {
+                    "cluster_name" : "c1",
+                    "workflow_id" : "mr_201305061943_0001",
+                    "job_id" : "job_201305061943_0001"
+                }
+            }
+        ]
+    }

+ 48 - 0
ambari-server/docs/api/v1/workflows.md

@@ -0,0 +1,48 @@
+<!---
+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.
+-->
+
+List Workflows
+=====
+
+[Back to Resources](index.md#resources)
+
+Returns a collection of all workflows in a given cluster.
+
+    GET /clusters/:name/workflows
+
+**Response**
+
+    200 OK
+    {
+        "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows",
+        "items" : [
+            {
+                "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0001",
+                "Workflow" : {
+                    "cluster_name" : "c1",
+                    "workflow_id" : "mr_201305061943_0001"
+                }
+            },
+            {
+                "href" : "http://your.ambari.server/api/v1/clusters/c1/workflows/mr_201305061943_0002",
+                "Workflow" : {
+                    "cluster_name" : "c1",
+                    "workflow_id" : "mr_201305061943_0002"
+                }
+            }
+        ]
+    }

+ 396 - 236
ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java

@@ -20,6 +20,8 @@ package org.apache.ambari.server.state;
 
 import java.util.*;
 import java.util.Map.Entry;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import com.google.gson.Gson;
 import com.google.inject.Inject;
@@ -41,6 +43,8 @@ public class ServiceComponentImpl implements ServiceComponent {
 
   private final static Logger LOG =
       LoggerFactory.getLogger(ServiceComponentImpl.class);
+  
+  ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
 
   private final Service service;
 
@@ -154,260 +158,374 @@ public class ServiceComponentImpl implements ServiceComponent {
   }
 
   @Override
-  public synchronized String getName() {
-    return desiredStateEntity.getComponentName();
+  public String getName() {
+    readWriteLock.readLock().lock();
+    try {
+      return desiredStateEntity.getComponentName();
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized String getServiceName() {
-    return service.getName();
+  public String getServiceName() {
+    readWriteLock.readLock().lock();
+    try {
+      return service.getName();
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized long getClusterId() {
-    return this.service.getClusterId();
+  public long getClusterId() {
+    readWriteLock.readLock().lock();
+    try {
+      return this.service.getClusterId();
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized Map<String, ServiceComponentHost>
+  public Map<String, ServiceComponentHost>
       getServiceComponentHosts() {
-    return Collections.unmodifiableMap(hostComponents);
+    readWriteLock.readLock().lock();
+    try {
+      return Collections.unmodifiableMap(hostComponents);
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized void addServiceComponentHosts(
+  public void addServiceComponentHosts(
       Map<String, ServiceComponentHost> hostComponents) throws AmbariException {
-    // TODO validation
-    for (Entry<String, ServiceComponentHost> entry :
-      hostComponents.entrySet()) {
-      if (!entry.getKey().equals(entry.getValue().getHostName())) {
-        throw new AmbariException("Invalid arguments in map"
-            + ", hostname does not match the key in map");
+    readWriteLock.writeLock().lock();
+    try {
+      // TODO validation
+      for (Entry<String, ServiceComponentHost> entry :
+          hostComponents.entrySet()) {
+        if (!entry.getKey().equals(entry.getValue().getHostName())) {
+          throw new AmbariException("Invalid arguments in map"
+              + ", hostname does not match the key in map");
+        }
       }
+      for (ServiceComponentHost sch : hostComponents.values()) {
+        addServiceComponentHost(sch);
+      }
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
-    for (ServiceComponentHost sch : hostComponents.values()) {
-      addServiceComponentHost(sch);
-    }
+
   }
 
   @Override
-  public synchronized void addServiceComponentHost(
+  public void addServiceComponentHost(
       ServiceComponentHost hostComponent) throws AmbariException {
-    // TODO validation
-    // TODO ensure host belongs to cluster
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Adding a ServiceComponentHost to ServiceComponent"
-          + ", clusterName=" + service.getCluster().getClusterName()
-          + ", clusterId=" + service.getCluster().getClusterId()
-          + ", serviceName=" + service.getName()
-          + ", serviceComponentName=" + getName()
-          + ", hostname=" + hostComponent.getHostName());
-    }
-    if (hostComponents.containsKey(hostComponent.getHostName())) {
-      throw new AmbariException("Cannot add duplicate ServiceComponentHost"
-          + ", clusterName=" + service.getCluster().getClusterName()
-          + ", clusterId=" + service.getCluster().getClusterId()
-          + ", serviceName=" + service.getName()
-          + ", serviceComponentName=" + getName()
-          + ", hostname=" + hostComponent.getHostName());
+    readWriteLock.writeLock().lock();
+    try {
+      // TODO validation
+      // TODO ensure host belongs to cluster
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Adding a ServiceComponentHost to ServiceComponent"
+            + ", clusterName=" + service.getCluster().getClusterName()
+            + ", clusterId=" + service.getCluster().getClusterId()
+            + ", serviceName=" + service.getName()
+            + ", serviceComponentName=" + getName()
+            + ", hostname=" + hostComponent.getHostName());
+      }
+      if (hostComponents.containsKey(hostComponent.getHostName())) {
+        throw new AmbariException("Cannot add duplicate ServiceComponentHost"
+            + ", clusterName=" + service.getCluster().getClusterName()
+            + ", clusterId=" + service.getCluster().getClusterId()
+            + ", serviceName=" + service.getName()
+            + ", serviceComponentName=" + getName()
+            + ", hostname=" + hostComponent.getHostName());
+      }
+      // FIXME need a better approach of caching components by host
+      ClusterImpl clusterImpl = (ClusterImpl) service.getCluster();
+      clusterImpl.addServiceComponentHost(hostComponent);
+      this.hostComponents.put(hostComponent.getHostName(), hostComponent);
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
-    // FIXME need a better approach of caching components by host
-    ClusterImpl clusterImpl = (ClusterImpl) service.getCluster();
-    clusterImpl.addServiceComponentHost(hostComponent);
-    this.hostComponents.put(hostComponent.getHostName(), hostComponent);
+
   }
 
   @Override
-  public synchronized ServiceComponentHost addServiceComponentHost(
+  public ServiceComponentHost addServiceComponentHost(
       String hostName) throws AmbariException {
-    // TODO validation
-    // TODO ensure host belongs to cluster
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Adding a ServiceComponentHost to ServiceComponent"
-          + ", clusterName=" + service.getCluster().getClusterName()
-          + ", clusterId=" + service.getCluster().getClusterId()
-          + ", serviceName=" + service.getName()
-          + ", serviceComponentName=" + getName()
-          + ", hostname=" + hostName);
-    }
-    if (hostComponents.containsKey(hostName)) {
-      throw new AmbariException("Cannot add duplicate ServiceComponentHost"
-          + ", clusterName=" + service.getCluster().getClusterName()
-          + ", clusterId=" + service.getCluster().getClusterId()
-          + ", serviceName=" + service.getName()
-          + ", serviceComponentName=" + getName()
-          + ", hostname=" + hostName);
-    }
-    ServiceComponentHost hostComponent =
-        serviceComponentHostFactory.createNew(this, hostName, this.isClientComponent());
-    // FIXME need a better approach of caching components by host
-    ClusterImpl clusterImpl = (ClusterImpl) service.getCluster();
-    clusterImpl.addServiceComponentHost(hostComponent);
+    readWriteLock.writeLock().lock();
+    try {
+      // TODO validation
+      // TODO ensure host belongs to cluster
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Adding a ServiceComponentHost to ServiceComponent"
+            + ", clusterName=" + service.getCluster().getClusterName()
+            + ", clusterId=" + service.getCluster().getClusterId()
+            + ", serviceName=" + service.getName()
+            + ", serviceComponentName=" + getName()
+            + ", hostname=" + hostName);
+      }
+      if (hostComponents.containsKey(hostName)) {
+        throw new AmbariException("Cannot add duplicate ServiceComponentHost"
+            + ", clusterName=" + service.getCluster().getClusterName()
+            + ", clusterId=" + service.getCluster().getClusterId()
+            + ", serviceName=" + service.getName()
+            + ", serviceComponentName=" + getName()
+            + ", hostname=" + hostName);
+      }
+      ServiceComponentHost hostComponent =
+          serviceComponentHostFactory.createNew(this, hostName, this.isClientComponent());
+      // FIXME need a better approach of caching components by host
+      ClusterImpl clusterImpl = (ClusterImpl) service.getCluster();
+      clusterImpl.addServiceComponentHost(hostComponent);
 
-    this.hostComponents.put(hostComponent.getHostName(), hostComponent);
+      this.hostComponents.put(hostComponent.getHostName(), hostComponent);
+
+      return hostComponent;
+    } finally {
+      readWriteLock.writeLock().unlock();
+    }
 
-    return hostComponent;
   }
 
   @Override
   public ServiceComponentHost getServiceComponentHost(String hostname)
     throws AmbariException {
-    if (!hostComponents.containsKey(hostname)) {
-      throw new ServiceComponentHostNotFoundException(getClusterName(),
-          getServiceName(), getName(), hostname);
+    readWriteLock.readLock().lock();
+    try {
+      if (!hostComponents.containsKey(hostname)) {
+        throw new ServiceComponentHostNotFoundException(getClusterName(),
+            getServiceName(), getName(), hostname);
+      }
+      return this.hostComponents.get(hostname);
+    } finally {
+      readWriteLock.readLock().unlock();
     }
-    return this.hostComponents.get(hostname);
+
   }
 
   @Override
-  public synchronized State getDesiredState() {
-    return desiredStateEntity.getDesiredState();
+  public State getDesiredState() {
+    readWriteLock.readLock().lock();
+    try {
+      return desiredStateEntity.getDesiredState();
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized void setDesiredState(State state) {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Setting DesiredState of Service"
-          + ", clusterName=" + service.getCluster().getClusterName()
-          + ", clusterId=" + service.getCluster().getClusterId()
-          + ", serviceName=" + service.getName()
-          + ", serviceComponentName=" + getName()
-          + ", oldDesiredState=" + getDesiredState()
-          + ", newDesiredState=" + state);
+  public void setDesiredState(State state) {
+    readWriteLock.writeLock().lock();
+    try {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Setting DesiredState of Service"
+            + ", clusterName=" + service.getCluster().getClusterName()
+            + ", clusterId=" + service.getCluster().getClusterId()
+            + ", serviceName=" + service.getName()
+            + ", serviceComponentName=" + getName()
+            + ", oldDesiredState=" + getDesiredState()
+            + ", newDesiredState=" + state);
+      }
+      desiredStateEntity.setDesiredState(state);
+      saveIfPersisted();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
-    desiredStateEntity.setDesiredState(state);
-    saveIfPersisted();
+
   }
 
   @Override
-  public synchronized Map<String, Config> getDesiredConfigs() {
-    Map<String, Config> map = new HashMap<String, Config>();
-    for (Entry<String, String> entry : desiredConfigs.entrySet()) {
-      Config config = service.getCluster().getConfig(entry.getKey(), entry.getValue());
-      if (null != config) {
-        map.put(entry.getKey(), config);
+  public Map<String, Config> getDesiredConfigs() {
+    readWriteLock.readLock().lock();
+    try {
+      Map<String, Config> map = new HashMap<String, Config>();
+      for (Entry<String, String> entry : desiredConfigs.entrySet()) {
+        Config config = service.getCluster().getConfig(entry.getKey(), entry.getValue());
+        if (null != config) {
+          map.put(entry.getKey(), config);
+        }
       }
-    }
 
-    Map<String, Config> svcConfigs = service.getDesiredConfigs();
-    for (Entry<String, Config> entry : svcConfigs.entrySet()) {
-      if (!map.containsKey(entry.getKey())) {
-        map.put(entry.getKey(), entry.getValue());
+      Map<String, Config> svcConfigs = service.getDesiredConfigs();
+      for (Entry<String, Config> entry : svcConfigs.entrySet()) {
+        if (!map.containsKey(entry.getKey())) {
+          map.put(entry.getKey(), entry.getValue());
+        }
       }
+
+      return Collections.unmodifiableMap(map);
+    } finally {
+      readWriteLock.readLock().unlock();
     }
 
-    return Collections.unmodifiableMap(map);
   }
 
   @Override
-  public synchronized void updateDesiredConfigs(Map<String, Config> configs) {
-
-    for (Entry<String,Config> entry : configs.entrySet()) {
-      boolean contains = false;
-
-      for (ComponentConfigMappingEntity componentConfigMappingEntity : desiredStateEntity.getComponentConfigMappingEntities()) {
-        if (entry.getKey().equals(componentConfigMappingEntity.getConfigType())) {
-          contains = true;
-          componentConfigMappingEntity.setTimestamp(new Date().getTime());
-          componentConfigMappingEntity.setVersionTag(entry.getValue().getVersionTag());
-          if (persisted) {
-            componentConfigMappingDAO.merge(componentConfigMappingEntity);
+  public void updateDesiredConfigs(Map<String, Config> configs) {
+
+    readWriteLock.writeLock().lock();
+    try {
+      for (Entry<String, Config> entry : configs.entrySet()) {
+        boolean contains = false;
+
+        for (ComponentConfigMappingEntity componentConfigMappingEntity : desiredStateEntity.getComponentConfigMappingEntities()) {
+          if (entry.getKey().equals(componentConfigMappingEntity.getConfigType())) {
+            contains = true;
+            componentConfigMappingEntity.setTimestamp(new Date().getTime());
+            componentConfigMappingEntity.setVersionTag(entry.getValue().getVersionTag());
+            if (persisted) {
+              componentConfigMappingDAO.merge(componentConfigMappingEntity);
+            }
           }
         }
-      }
 
-      if (!contains) {
-        ComponentConfigMappingEntity newEntity = new ComponentConfigMappingEntity();
-        newEntity.setClusterId(desiredStateEntity.getClusterId());
-        newEntity.setServiceName(desiredStateEntity.getServiceName());
-        newEntity.setComponentName(desiredStateEntity.getComponentName());
-        newEntity.setConfigType(entry.getKey());
-        newEntity.setVersionTag(entry.getValue().getVersionTag());
-        newEntity.setTimestamp(new Date().getTime());
-        newEntity.setServiceComponentDesiredStateEntity(desiredStateEntity);
-        desiredStateEntity.getComponentConfigMappingEntities().add(newEntity);
+        if (!contains) {
+          ComponentConfigMappingEntity newEntity = new ComponentConfigMappingEntity();
+          newEntity.setClusterId(desiredStateEntity.getClusterId());
+          newEntity.setServiceName(desiredStateEntity.getServiceName());
+          newEntity.setComponentName(desiredStateEntity.getComponentName());
+          newEntity.setConfigType(entry.getKey());
+          newEntity.setVersionTag(entry.getValue().getVersionTag());
+          newEntity.setTimestamp(new Date().getTime());
+          newEntity.setServiceComponentDesiredStateEntity(desiredStateEntity);
+          desiredStateEntity.getComponentConfigMappingEntities().add(newEntity);
 
-      }
+        }
 
 
-      this.desiredConfigs.put(entry.getKey(), entry.getValue().getVersionTag());
+        this.desiredConfigs.put(entry.getKey(), entry.getValue().getVersionTag());
+      }
+
+      saveIfPersisted();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
 
-    saveIfPersisted();
   }
 
   @Override
-  public synchronized StackId getDesiredStackVersion() {
-    return gson.fromJson(desiredStateEntity.getDesiredStackVersion(), StackId.class);
+  public StackId getDesiredStackVersion() {
+    readWriteLock.readLock().lock();
+    try {
+      return gson.fromJson(desiredStateEntity.getDesiredStackVersion(), StackId.class);
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized void setDesiredStackVersion(StackId stackVersion) {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Setting DesiredStackVersion of Service"
-          + ", clusterName=" + service.getCluster().getClusterName()
-          + ", clusterId=" + service.getCluster().getClusterId()
-          + ", serviceName=" + service.getName()
-          + ", serviceComponentName=" + getName()
-          + ", oldDesiredStackVersion=" + getDesiredStackVersion()
-          + ", newDesiredStackVersion=" + stackVersion);
+  public void setDesiredStackVersion(StackId stackVersion) {
+    readWriteLock.writeLock().lock();
+    try {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Setting DesiredStackVersion of Service"
+            + ", clusterName=" + service.getCluster().getClusterName()
+            + ", clusterId=" + service.getCluster().getClusterId()
+            + ", serviceName=" + service.getName()
+            + ", serviceComponentName=" + getName()
+            + ", oldDesiredStackVersion=" + getDesiredStackVersion()
+            + ", newDesiredStackVersion=" + stackVersion);
+      }
+      desiredStateEntity.setDesiredStackVersion(gson.toJson(stackVersion));
+      saveIfPersisted();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
-    desiredStateEntity.setDesiredStackVersion(gson.toJson(stackVersion));
-    saveIfPersisted();
+
   }
 
   @Override
-  public synchronized ServiceComponentResponse convertToResponse() {
-    ServiceComponentResponse r  = new ServiceComponentResponse(
-        getClusterId(), service.getCluster().getClusterName(),
-        service.getName(), getName(), this.desiredConfigs,
-        getDesiredStackVersion().getStackId(),
-        getDesiredState().toString());
-    return r;
+  public ServiceComponentResponse convertToResponse() {
+    readWriteLock.readLock().lock();
+    try {
+      ServiceComponentResponse r = new ServiceComponentResponse(
+          getClusterId(), service.getCluster().getClusterName(),
+          service.getName(), getName(), this.desiredConfigs,
+          getDesiredStackVersion().getStackId(),
+          getDesiredState().toString());
+      return r;
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
   public String getClusterName() {
-    return service.getCluster().getClusterName();
+    readWriteLock.readLock().lock();
+    try {
+      return service.getCluster().getClusterName();
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized void debugDump(StringBuilder sb) {
-    sb.append("ServiceComponent={ serviceComponentName=" + getName()
-        + ", clusterName=" + service.getCluster().getClusterName()
-        + ", clusterId=" + service.getCluster().getClusterId()
-        + ", serviceName=" + service.getName()
-        + ", desiredStackVersion=" + getDesiredStackVersion()
-        + ", desiredState=" + getDesiredState().toString()
-        + ", hostcomponents=[ ");
-    boolean first = true;
-    for(ServiceComponentHost sch : hostComponents.values()) {
-      if (!first) {
-        sb.append(" , ");
-        first = false;
+  public void debugDump(StringBuilder sb) {
+    readWriteLock.readLock().lock();
+    try {
+      sb.append("ServiceComponent={ serviceComponentName=" + getName()
+          + ", clusterName=" + service.getCluster().getClusterName()
+          + ", clusterId=" + service.getCluster().getClusterId()
+          + ", serviceName=" + service.getName()
+          + ", desiredStackVersion=" + getDesiredStackVersion()
+          + ", desiredState=" + getDesiredState().toString()
+          + ", hostcomponents=[ ");
+      boolean first = true;
+      for (ServiceComponentHost sch : hostComponents.values()) {
+        if (!first) {
+          sb.append(" , ");
+          first = false;
+        }
+        sb.append("\n        ");
+        sch.debugDump(sb);
+        sb.append(" ");
       }
-      sb.append("\n        ");
-      sch.debugDump(sb);
-      sb.append(" ");
+      sb.append(" ] }");
+    } finally {
+      readWriteLock.readLock().unlock();
     }
-    sb.append(" ] }");
+
   }
 
   @Override
-  public synchronized boolean isPersisted() {
+  public boolean isPersisted() {
+    readWriteLock.readLock().lock();
+    try {
       return persisted;
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized void persist() {
-    if (!persisted) {
-      persistEntities();
-      refresh();
-      service.refresh();
-      persisted = true;
-    } else {
-      saveIfPersisted();
+  public void persist() {
+    readWriteLock.writeLock().lock();
+    try {
+      if (!persisted) {
+        persistEntities();
+        refresh();
+        service.refresh();
+        persisted = true;
+      } else {
+        saveIfPersisted();
+      }
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
+
   }
 
   @Transactional
@@ -424,23 +542,35 @@ public class ServiceComponentImpl implements ServiceComponent {
 
   @Override
   @Transactional
-  public synchronized void refresh() {
-    if (isPersisted()) {
-      ServiceComponentDesiredStateEntityPK pk = new ServiceComponentDesiredStateEntityPK();
-      pk.setComponentName(getName());
-      pk.setClusterId(getClusterId());
-      pk.setServiceName(getServiceName());
-      // TODO: desiredStateEntity is assigned in unsynchronized way, may be a bug
-      desiredStateEntity = serviceComponentDesiredStateDAO.findByPK(pk);
-      serviceComponentDesiredStateDAO.refresh(desiredStateEntity);
+  public void refresh() {
+    readWriteLock.writeLock().lock();
+    try {
+      if (isPersisted()) {
+        ServiceComponentDesiredStateEntityPK pk = new ServiceComponentDesiredStateEntityPK();
+        pk.setComponentName(getName());
+        pk.setClusterId(getClusterId());
+        pk.setServiceName(getServiceName());
+        // TODO: desiredStateEntity is assigned in unway, may be a bug
+        desiredStateEntity = serviceComponentDesiredStateDAO.findByPK(pk);
+        serviceComponentDesiredStateDAO.refresh(desiredStateEntity);
+      }
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
+
   }
 
   @Transactional
-  private synchronized void saveIfPersisted() {
-    if (isPersisted()) {
-      serviceComponentDesiredStateDAO.merge(desiredStateEntity);
+  private void saveIfPersisted() {
+    readWriteLock.writeLock().lock();
+    try {
+      if (isPersisted()) {
+        serviceComponentDesiredStateDAO.merge(desiredStateEntity);
+      }
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
+
   }
 
   @Override
@@ -449,95 +579,125 @@ public class ServiceComponentImpl implements ServiceComponent {
   }
 
   @Override
-  public synchronized boolean canBeRemoved() {
-    if (!getDesiredState().isRemovableState()) {
-      return false;
-    }
-
-    for (ServiceComponentHost sch : hostComponents.values()) {
-      if (!sch.canBeRemoved()) {
-        LOG.warn("Found non removable hostcomponent when trying to"
-            + " delete service component"
-            + ", clusterName=" + getClusterName()
-            + ", serviceName=" + getServiceName()
-            + ", componentName=" + getName()
-            + ", hostname=" + sch.getHostName());
+  public boolean canBeRemoved() {
+    readWriteLock.readLock().lock();
+    try {
+      if (!getDesiredState().isRemovableState()) {
         return false;
       }
+
+      for (ServiceComponentHost sch : hostComponents.values()) {
+        if (!sch.canBeRemoved()) {
+          LOG.warn("Found non removable hostcomponent when trying to"
+              + " delete service component"
+              + ", clusterName=" + getClusterName()
+              + ", serviceName=" + getServiceName()
+              + ", componentName=" + getName()
+              + ", hostname=" + sch.getHostName());
+          return false;
+        }
+      }
+      return true;
+    } finally {
+      readWriteLock.readLock().unlock();
     }
-    return true;
+
   }
 
   @Override
   @Transactional
-  public synchronized void deleteAllServiceComponentHosts()
+  public void deleteAllServiceComponentHosts()
       throws AmbariException {
-    LOG.info("Deleting all servicecomponenthosts for component"
-        + ", clusterName=" + getClusterName()
-        + ", serviceName=" + getServiceName()
-        + ", componentName=" + getName());
-    for (ServiceComponentHost sch : hostComponents.values()) {
-      if (!sch.canBeRemoved()) {
-        throw new AmbariException("Found non removable hostcomponent "
-            + " when trying to delete"
-            + " all hostcomponents from servicecomponent"
-            + ", clusterName=" + getClusterName()
-            + ", serviceName=" + getServiceName()
-            + ", componentName=" + getName()
-            + ", hostname=" + sch.getHostName());
+    readWriteLock.writeLock().lock();
+    try {
+      LOG.info("Deleting all servicecomponenthosts for component"
+          + ", clusterName=" + getClusterName()
+          + ", serviceName=" + getServiceName()
+          + ", componentName=" + getName());
+      for (ServiceComponentHost sch : hostComponents.values()) {
+        if (!sch.canBeRemoved()) {
+          throw new AmbariException("Found non removable hostcomponent "
+              + " when trying to delete"
+              + " all hostcomponents from servicecomponent"
+              + ", clusterName=" + getClusterName()
+              + ", serviceName=" + getServiceName()
+              + ", componentName=" + getName()
+              + ", hostname=" + sch.getHostName());
+        }
+      }
+
+      for (ServiceComponentHost serviceComponentHost : hostComponents.values()) {
+        serviceComponentHost.delete();
       }
-    }
 
-    for (ServiceComponentHost serviceComponentHost : hostComponents.values()) {
-      serviceComponentHost.delete();
+      hostComponents.clear();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
 
-    hostComponents.clear();
   }
 
   @Override
-  public synchronized void deleteServiceComponentHosts(String hostname)
+  public void deleteServiceComponentHosts(String hostname)
       throws AmbariException {
-    ServiceComponentHost sch = getServiceComponentHost(hostname);
-    LOG.info("Deleting servicecomponenthost for cluster"
-        + ", clusterName=" + getClusterName()
-        + ", serviceName=" + getServiceName()
-        + ", componentName=" + getName()
-        + ", hostname=" + sch.getHostName());
-    if (!sch.canBeRemoved()) {
-      throw new AmbariException("Could not delete hostcomponent from cluster"
+    readWriteLock.writeLock().lock();
+    try {
+      ServiceComponentHost sch = getServiceComponentHost(hostname);
+      LOG.info("Deleting servicecomponenthost for cluster"
           + ", clusterName=" + getClusterName()
           + ", serviceName=" + getServiceName()
           + ", componentName=" + getName()
           + ", hostname=" + sch.getHostName());
+      if (!sch.canBeRemoved()) {
+        throw new AmbariException("Could not delete hostcomponent from cluster"
+            + ", clusterName=" + getClusterName()
+            + ", serviceName=" + getServiceName()
+            + ", componentName=" + getName()
+            + ", hostname=" + sch.getHostName());
+      }
+      sch.delete();
+      hostComponents.remove(hostname);
+
+      // FIXME need a better approach of caching components by host
+      ClusterImpl clusterImpl = (ClusterImpl) service.getCluster();
+      clusterImpl.removeServiceComponentHost(sch);
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
-    sch.delete();
-    hostComponents.remove(hostname);
 
-    // FIXME need a better approach of caching components by host
-    ClusterImpl clusterImpl = (ClusterImpl) service.getCluster();
-    clusterImpl.removeServiceComponentHost(sch);
   }
 
   @Override
-  public synchronized void deleteDesiredConfigs(Set<String> configTypes) {
-    componentConfigMappingDAO.removeByType(configTypes);
-    for (String configType : configTypes) {
-      desiredConfigs.remove(configType);
+  public void deleteDesiredConfigs(Set<String> configTypes) {
+    readWriteLock.writeLock().lock();
+    try {
+      componentConfigMappingDAO.removeByType(configTypes);
+      for (String configType : configTypes) {
+        desiredConfigs.remove(configType);
+      }
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
+
   }
 
   @Override
   @Transactional
-  public synchronized void delete() throws AmbariException {
-    deleteAllServiceComponentHosts();
+  public void delete() throws AmbariException {
+    readWriteLock.writeLock().lock();
+    try {
+      deleteAllServiceComponentHosts();
+
+      if (persisted) {
+        removeEntities();
+        persisted = false;
+      }
 
-    if (persisted) {
-      removeEntities();
-      persisted = false;
+      desiredConfigs.clear();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
 
-    desiredConfigs.clear();
   }
 
   @Transactional

+ 321 - 198
ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java

@@ -20,6 +20,8 @@ package org.apache.ambari.server.state;
 
 import java.util.*;
 import java.util.Map.Entry;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ServiceComponentNotFoundException;
@@ -39,6 +41,7 @@ import com.google.inject.persist.Transactional;
 
 
 public class ServiceImpl implements Service {
+  private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
 
   private ClusterServiceEntity serviceEntity;
   private ServiceDesiredStateEntity serviceDesiredStateEntity;
@@ -141,7 +144,7 @@ public class ServiceImpl implements Service {
 
   @Override
   public String getName() {
-      return serviceEntity.getServiceName();
+    return serviceEntity.getServiceName();
   }
 
   @Override
@@ -150,172 +153,244 @@ public class ServiceImpl implements Service {
   }
 
   @Override
-  public synchronized Map<String, ServiceComponent> getServiceComponents() {
-    return Collections.unmodifiableMap(components);
+  public Map<String, ServiceComponent> getServiceComponents() {
+    readWriteLock.readLock().lock();
+    try {
+      return Collections.unmodifiableMap(components);
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized void addServiceComponents(
+  public void addServiceComponents(
       Map<String, ServiceComponent> components) throws AmbariException {
-    for (ServiceComponent sc : components.values()) {
-      addServiceComponent(sc);
+    readWriteLock.writeLock().lock();
+    try {
+      for (ServiceComponent sc : components.values()) {
+        addServiceComponent(sc);
+      }
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
+
   }
 
   @Override
-  public synchronized void addServiceComponent(ServiceComponent component)
+  public void addServiceComponent(ServiceComponent component)
       throws AmbariException {
-    // TODO validation
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Adding a ServiceComponent to Service"
-          + ", clusterName=" + cluster.getClusterName()
-          + ", clusterId=" + cluster.getClusterId()
-          + ", serviceName=" + getName()
-          + ", serviceComponentName=" + component.getName());
-    }
-    if (components.containsKey(component.getName())) {
-      throw new AmbariException("Cannot add duplicate ServiceComponent"
-          + ", clusterName=" + cluster.getClusterName()
-          + ", clusterId=" + cluster.getClusterId()
-          + ", serviceName=" + getName()
-          + ", serviceComponentName=" + component.getName());
+    readWriteLock.writeLock().lock();
+    try {
+      // TODO validation
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Adding a ServiceComponent to Service"
+            + ", clusterName=" + cluster.getClusterName()
+            + ", clusterId=" + cluster.getClusterId()
+            + ", serviceName=" + getName()
+            + ", serviceComponentName=" + component.getName());
+      }
+      if (components.containsKey(component.getName())) {
+        throw new AmbariException("Cannot add duplicate ServiceComponent"
+            + ", clusterName=" + cluster.getClusterName()
+            + ", clusterId=" + cluster.getClusterId()
+            + ", serviceName=" + getName()
+            + ", serviceComponentName=" + component.getName());
+      }
+      this.components.put(component.getName(), component);
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
-    this.components.put(component.getName(), component);
+
   }
 
   @Override
-  public synchronized ServiceComponent addServiceComponent(
+  public ServiceComponent addServiceComponent(
       String serviceComponentName) throws AmbariException {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Adding a ServiceComponent to Service"
-          + ", clusterName=" + cluster.getClusterName()
-          + ", clusterId=" + cluster.getClusterId()
-          + ", serviceName=" + getName()
-          + ", serviceComponentName=" + serviceComponentName);
-    }
-    if (components.containsKey(serviceComponentName)) {
-      throw new AmbariException("Cannot add duplicate ServiceComponent"
-          + ", clusterName=" + cluster.getClusterName()
-          + ", clusterId=" + cluster.getClusterId()
-          + ", serviceName=" + getName()
-          + ", serviceComponentName=" + serviceComponentName);
+    readWriteLock.writeLock().lock();
+    try {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Adding a ServiceComponent to Service"
+            + ", clusterName=" + cluster.getClusterName()
+            + ", clusterId=" + cluster.getClusterId()
+            + ", serviceName=" + getName()
+            + ", serviceComponentName=" + serviceComponentName);
+      }
+      if (components.containsKey(serviceComponentName)) {
+        throw new AmbariException("Cannot add duplicate ServiceComponent"
+            + ", clusterName=" + cluster.getClusterName()
+            + ", clusterId=" + cluster.getClusterId()
+            + ", serviceName=" + getName()
+            + ", serviceComponentName=" + serviceComponentName);
+      }
+      ServiceComponent component = serviceComponentFactory.createNew(this, serviceComponentName);
+      this.components.put(component.getName(), component);
+      return component;
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
-    ServiceComponent component = serviceComponentFactory.createNew(this, serviceComponentName);
-    this.components.put(component.getName(), component);
-    return component;
+
   }
 
   @Override
   public ServiceComponent getServiceComponent(String componentName)
       throws AmbariException {
-    if (!components.containsKey(componentName)) {
-      throw new ServiceComponentNotFoundException(cluster.getClusterName(),
-          getName(),
-          componentName);
+    readWriteLock.readLock().lock();
+    try {
+      if (!components.containsKey(componentName)) {
+        throw new ServiceComponentNotFoundException(cluster.getClusterName(),
+            getName(),
+            componentName);
+      }
+      return this.components.get(componentName);
+    } finally {
+      readWriteLock.readLock().unlock();
     }
-    return this.components.get(componentName);
+
   }
 
   @Override
-  public synchronized State getDesiredState() {
-    return this.serviceDesiredStateEntity.getDesiredState();
+  public State getDesiredState() {
+    readWriteLock.readLock().lock();
+    try {
+      return this.serviceDesiredStateEntity.getDesiredState();
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized void setDesiredState(State state) {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Setting DesiredState of Service"
-          + ", clusterName=" + cluster.getClusterName()
-          + ", clusterId=" + cluster.getClusterId()
-          + ", serviceName=" + getName()
-          + ", oldDesiredState=" + this.getDesiredState()
-          + ", newDesiredState=" + state);
+  public void setDesiredState(State state) {
+    readWriteLock.writeLock().lock();
+    try {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Setting DesiredState of Service"
+            + ", clusterName=" + cluster.getClusterName()
+            + ", clusterId=" + cluster.getClusterId()
+            + ", serviceName=" + getName()
+            + ", oldDesiredState=" + this.getDesiredState()
+            + ", newDesiredState=" + state);
+      }
+      this.serviceDesiredStateEntity.setDesiredState(state);
+      saveIfPersisted();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
-    this.serviceDesiredStateEntity.setDesiredState(state);
-    saveIfPersisted();
+
   }
 
   @Override
-  public synchronized Map<String, Config> getDesiredConfigs() {
-    Map<String, Config> map = new HashMap<String, Config>();
-    for (Entry<String, String> entry : desiredConfigs.entrySet()) {
-      Config config = cluster.getConfig(entry.getKey(), entry.getValue());
-      if (null != config) {
-        map.put(entry.getKey(), config);
-      } else {
-        // FIXME this is an error - should throw a proper exception
-        throw new RuntimeException("Found an invalid config"
-            + ", clusterName=" + getCluster().getClusterName()
-            + ", serviceName=" + getName()
-            + ", configType=" + entry.getKey()
-            + ", configVersionTag=" + entry.getValue());
+  public Map<String, Config> getDesiredConfigs() {
+    readWriteLock.readLock().lock();
+    try {
+      Map<String, Config> map = new HashMap<String, Config>();
+      for (Entry<String, String> entry : desiredConfigs.entrySet()) {
+        Config config = cluster.getConfig(entry.getKey(), entry.getValue());
+        if (null != config) {
+          map.put(entry.getKey(), config);
+        } else {
+          // FIXME this is an error - should throw a proper exception
+          throw new RuntimeException("Found an invalid config"
+              + ", clusterName=" + getCluster().getClusterName()
+              + ", serviceName=" + getName()
+              + ", configType=" + entry.getKey()
+              + ", configVersionTag=" + entry.getValue());
+        }
       }
+      return Collections.unmodifiableMap(map);
+    } finally {
+      readWriteLock.readLock().unlock();
     }
-    return Collections.unmodifiableMap(map);
+
   }
 
   @Override
-  public synchronized void updateDesiredConfigs(Map<String, Config> configs) {
+  public void updateDesiredConfigs(Map<String, Config> configs) {
+
+    readWriteLock.writeLock().lock();
+    try {
+      for (Entry<String, Config> entry : configs.entrySet()) {
+        boolean contains = false;
+
+        for (ServiceConfigMappingEntity serviceConfigMappingEntity : serviceEntity.getServiceConfigMappings()) {
+          if (entry.getKey().equals(serviceConfigMappingEntity.getConfigType())) {
+            contains = true;
+            serviceConfigMappingEntity.setTimestamp(new Date().getTime());
+            serviceConfigMappingEntity.setVersionTag(entry.getValue().getVersionTag());
+          }
+        }
 
-    for (Entry<String,Config> entry : configs.entrySet()) {
-      boolean contains = false;
+        if (!contains) {
+          ServiceConfigMappingEntity newEntity = new ServiceConfigMappingEntity();
+          newEntity.setClusterId(serviceEntity.getClusterId());
+          newEntity.setServiceName(serviceEntity.getServiceName());
+          newEntity.setConfigType(entry.getKey());
+          newEntity.setVersionTag(entry.getValue().getVersionTag());
+          newEntity.setTimestamp(new Date().getTime());
+          newEntity.setServiceEntity(serviceEntity);
+          serviceEntity.getServiceConfigMappings().add(newEntity);
 
-      for (ServiceConfigMappingEntity serviceConfigMappingEntity : serviceEntity.getServiceConfigMappings()) {
-        if (entry.getKey().equals(serviceConfigMappingEntity.getConfigType())) {
-          contains = true;
-          serviceConfigMappingEntity.setTimestamp(new Date().getTime());
-          serviceConfigMappingEntity.setVersionTag(entry.getValue().getVersionTag());
         }
-      }
 
-      if (!contains) {
-        ServiceConfigMappingEntity newEntity = new ServiceConfigMappingEntity();
-        newEntity.setClusterId(serviceEntity.getClusterId());
-        newEntity.setServiceName(serviceEntity.getServiceName());
-        newEntity.setConfigType(entry.getKey());
-        newEntity.setVersionTag(entry.getValue().getVersionTag());
-        newEntity.setTimestamp(new Date().getTime());
-        newEntity.setServiceEntity(serviceEntity);
-        serviceEntity.getServiceConfigMappings().add(newEntity);
 
+        this.desiredConfigs.put(entry.getKey(), entry.getValue().getVersionTag());
       }
 
-
-      this.desiredConfigs.put(entry.getKey(), entry.getValue().getVersionTag());
+      saveIfPersisted();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
 
-    saveIfPersisted();
 
   }
 
   @Override
-  public synchronized StackId getDesiredStackVersion() {
-    return gson.fromJson(serviceDesiredStateEntity.getDesiredStackVersion(), StackId.class);
+  public StackId getDesiredStackVersion() {
+    readWriteLock.readLock().lock();
+    try {
+      return gson.fromJson(serviceDesiredStateEntity.getDesiredStackVersion(), StackId.class);
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized void setDesiredStackVersion(StackId stackVersion) {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Setting DesiredStackVersion of Service"
-          + ", clusterName=" + cluster.getClusterName()
-          + ", clusterId=" + cluster.getClusterId()
-          + ", serviceName=" + getName()
-          + ", oldDesiredStackVersion=" + getDesiredStackVersion()
-          + ", newDesiredStackVersion=" + stackVersion);
+  public void setDesiredStackVersion(StackId stackVersion) {
+    readWriteLock.writeLock().lock();
+    try {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Setting DesiredStackVersion of Service"
+            + ", clusterName=" + cluster.getClusterName()
+            + ", clusterId=" + cluster.getClusterId()
+            + ", serviceName=" + getName()
+            + ", oldDesiredStackVersion=" + getDesiredStackVersion()
+            + ", newDesiredStackVersion=" + stackVersion);
+      }
+      serviceDesiredStateEntity.setDesiredStackVersion(gson.toJson(stackVersion));
+      saveIfPersisted();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
-    serviceDesiredStateEntity.setDesiredStackVersion(gson.toJson(stackVersion));
-    saveIfPersisted();
+
   }
 
   @Override
-  public synchronized ServiceResponse convertToResponse() {
-    ServiceResponse r = new ServiceResponse(cluster.getClusterId(),
-        cluster.getClusterName(),
-        getName(),
-        desiredConfigs,
-        getDesiredStackVersion().getStackId(),
-        getDesiredState().toString());
-    return r;
+  public ServiceResponse convertToResponse() {
+    readWriteLock.readLock().lock();
+    try {
+      ServiceResponse r = new ServiceResponse(cluster.getClusterId(),
+          cluster.getClusterName(),
+          getName(),
+          desiredConfigs,
+          getDesiredStackVersion().getStackId(),
+          getDesiredState().toString());
+      return r;
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
@@ -324,54 +399,72 @@ public class ServiceImpl implements Service {
   }
 
   @Override
-  public synchronized void debugDump(StringBuilder sb) {
-    sb.append("Service={ serviceName=" + getName()
-        + ", clusterName=" + cluster.getClusterName()
-        + ", clusterId=" + cluster.getClusterId()
-        + ", desiredStackVersion=" + getDesiredStackVersion()
-        + ", desiredState=" + getDesiredState().toString()
-        + ", configs=[");
-    boolean first = true;
-    if (desiredConfigs != null) {
-      for (Entry<String, String> entry : desiredConfigs.entrySet()) {
+  public void debugDump(StringBuilder sb) {
+    readWriteLock.readLock().lock();
+    try {
+      sb.append("Service={ serviceName=" + getName()
+          + ", clusterName=" + cluster.getClusterName()
+          + ", clusterId=" + cluster.getClusterId()
+          + ", desiredStackVersion=" + getDesiredStackVersion()
+          + ", desiredState=" + getDesiredState().toString()
+          + ", configs=[");
+      boolean first = true;
+      if (desiredConfigs != null) {
+        for (Entry<String, String> entry : desiredConfigs.entrySet()) {
+          if (!first) {
+            sb.append(" , ");
+          }
+          first = false;
+          sb.append("{ Config type=" + entry.getKey()
+              + ", versionTag=" + entry.getValue() + "}");
+        }
+      }
+      sb.append("], components=[ ");
+
+      first = true;
+      for (ServiceComponent sc : components.values()) {
         if (!first) {
           sb.append(" , ");
         }
         first = false;
-        sb.append("{ Config type=" + entry.getKey()
-            + ", versionTag=" + entry.getValue() + "}");
+        sb.append("\n      ");
+        sc.debugDump(sb);
+        sb.append(" ");
       }
+      sb.append(" ] }");
+    } finally {
+      readWriteLock.readLock().unlock();
     }
-    sb.append("], components=[ ");
 
-    first = true;
-    for(ServiceComponent sc : components.values()) {
-      if (!first) {
-        sb.append(" , ");
-      }
-      first = false;
-      sb.append("\n      ");
-      sc.debugDump(sb);
-      sb.append(" ");
-    }
-    sb.append(" ] }");
   }
 
   @Override
-  public synchronized boolean isPersisted() {
+  public boolean isPersisted() {
+    readWriteLock.readLock().lock();
+    try {
       return persisted;
+    } finally {
+      readWriteLock.readLock().unlock();
+    }
+
   }
 
   @Override
-  public synchronized void persist() {
-    if (!persisted) {
-      persistEntities();
-      refresh();
-      cluster.refresh();
-      persisted = true;
-    } else {
-      saveIfPersisted();
+  public void persist() {
+    readWriteLock.writeLock().lock();
+    try {
+      if (!persisted) {
+        persistEntities();
+        refresh();
+        cluster.refresh();
+        persisted = true;
+      } else {
+        saveIfPersisted();
+      }
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
+
   }
 
   @Transactional
@@ -398,78 +491,102 @@ public class ServiceImpl implements Service {
 
   @Override
   @Transactional
-  public synchronized void refresh() {
-    if (isPersisted()) {
-      ClusterServiceEntityPK pk = new ClusterServiceEntityPK();
-      pk.setClusterId(getClusterId());
-      pk.setServiceName(getName());
-      serviceEntity = clusterServiceDAO.findByPK(pk);
-      serviceDesiredStateEntity = serviceEntity.getServiceDesiredStateEntity();
-      clusterServiceDAO.refresh(serviceEntity);
-      serviceDesiredStateDAO.refresh(serviceDesiredStateEntity);
+  public void refresh() {
+    readWriteLock.writeLock().lock();
+    try {
+      if (isPersisted()) {
+        ClusterServiceEntityPK pk = new ClusterServiceEntityPK();
+        pk.setClusterId(getClusterId());
+        pk.setServiceName(getName());
+        serviceEntity = clusterServiceDAO.findByPK(pk);
+        serviceDesiredStateEntity = serviceEntity.getServiceDesiredStateEntity();
+        clusterServiceDAO.refresh(serviceEntity);
+        serviceDesiredStateDAO.refresh(serviceDesiredStateEntity);
+      }
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
+
   }
 
   @Override
-  public synchronized boolean canBeRemoved() {
-    if (!getDesiredState().isRemovableState()) {
-      return false;
-    }
-
-    for (ServiceComponent sc : components.values()) {
-      if (!sc.canBeRemoved()) {
-        LOG.warn("Found non removable component when trying to delete service"
-            + ", clusterName=" + cluster.getClusterName()
-            + ", serviceName=" + getName()
-            + ", componentName=" + sc.getName());
+  public boolean canBeRemoved() {
+    readWriteLock.readLock().lock();
+    try {
+      if (!getDesiredState().isRemovableState()) {
         return false;
       }
+
+      for (ServiceComponent sc : components.values()) {
+        if (!sc.canBeRemoved()) {
+          LOG.warn("Found non removable component when trying to delete service"
+              + ", clusterName=" + cluster.getClusterName()
+              + ", serviceName=" + getName()
+              + ", componentName=" + sc.getName());
+          return false;
+        }
+      }
+      return true;
+    } finally {
+      readWriteLock.readLock().unlock();
     }
-    return true;
+
   }
 
   @Override
   @Transactional
-  public synchronized void deleteAllComponents() throws AmbariException {
-    LOG.info("Deleting all components for service"
-        + ", clusterName=" + cluster.getClusterName()
-        + ", serviceName=" + getName());
-    // FIXME check dependencies from meta layer
-    for (ServiceComponent component : components.values()) {
-      if (!component.canBeRemoved()) {
-        throw new AmbariException("Found non removable component when trying to"
-            + " delete all components from service"
-            + ", clusterName=" + cluster.getClusterName()
-            + ", serviceName=" + getName()
-            + ", componentName=" + component.getName());
+  public void deleteAllComponents() throws AmbariException {
+    readWriteLock.writeLock().lock();
+    try {
+      LOG.info("Deleting all components for service"
+          + ", clusterName=" + cluster.getClusterName()
+          + ", serviceName=" + getName());
+      // FIXME check dependencies from meta layer
+      for (ServiceComponent component : components.values()) {
+        if (!component.canBeRemoved()) {
+          throw new AmbariException("Found non removable component when trying to"
+              + " delete all components from service"
+              + ", clusterName=" + cluster.getClusterName()
+              + ", serviceName=" + getName()
+              + ", componentName=" + component.getName());
+        }
+      }
+
+      for (ServiceComponent serviceComponent : components.values()) {
+        serviceComponent.delete();
       }
-    }
 
-    for (ServiceComponent serviceComponent : components.values()) {
-      serviceComponent.delete();
+      components.clear();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
 
-    components.clear();
   }
 
   @Override
-  public synchronized void deleteServiceComponent(String componentName)
+  public void deleteServiceComponent(String componentName)
       throws AmbariException {
-    ServiceComponent component = getServiceComponent(componentName);
-    LOG.info("Deleting servicecomponent for cluster"
-        + ", clusterName=" + cluster.getClusterName()
-        + ", serviceName=" + getName()
-        + ", componentName=" + componentName);
-    // FIXME check dependencies from meta layer
-    if (!component.canBeRemoved()) {
-      throw new AmbariException("Could not delete component from cluster"
+    readWriteLock.writeLock().lock();
+    try {
+      ServiceComponent component = getServiceComponent(componentName);
+      LOG.info("Deleting servicecomponent for cluster"
           + ", clusterName=" + cluster.getClusterName()
           + ", serviceName=" + getName()
           + ", componentName=" + componentName);
+      // FIXME check dependencies from meta layer
+      if (!component.canBeRemoved()) {
+        throw new AmbariException("Could not delete component from cluster"
+            + ", clusterName=" + cluster.getClusterName()
+            + ", serviceName=" + getName()
+            + ", componentName=" + componentName);
+      }
+
+      component.delete();
+      components.remove(componentName);
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
 
-    component.delete();
-    components.remove(componentName);
   }
 
   @Override
@@ -479,15 +596,21 @@ public class ServiceImpl implements Service {
 
   @Override
   @Transactional
-  public synchronized void delete() throws AmbariException {
-    deleteAllComponents();
+  public void delete() throws AmbariException {
+    readWriteLock.writeLock().lock();
+    try {
+      deleteAllComponents();
+
+      if (persisted) {
+        removeEntities();
+        persisted = false;
+      }
 
-    if (persisted) {
-      removeEntities();
-      persisted = false;
+      desiredConfigs.clear();
+    } finally {
+      readWriteLock.writeLock().unlock();
     }
 
-    desiredConfigs.clear();
   }
 
   @Transactional

+ 17 - 5
ambari-server/src/main/java/org/apache/ambari/server/state/host/HostImpl.java

@@ -355,6 +355,9 @@ public class HostImpl implements Host {
     }
   }
 
+  /**
+   * @param hostInfo
+   */
   @Override
   public void importHostInfo(HostInfo hostInfo) {
     try {
@@ -457,17 +460,26 @@ public class HostImpl implements Host {
     }
   }
 
-  /**
-   * @param hostInfo
-   */
   @Override
   public void setLastAgentEnv(AgentEnv env) {
-    lastAgentEnv = env;
+    writeLock.lock();
+    try {
+      lastAgentEnv = env;
+    } finally {
+      writeLock.unlock();
+    }
+
   }
   
   @Override
   public AgentEnv getLastAgentEnv() {
-    return lastAgentEnv;
+    readLock.lock();
+    try {
+      return lastAgentEnv;
+    } finally {
+      readLock.unlock();
+    }
+
   }
 
   @Override

+ 126 - 77
ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java

@@ -64,8 +64,9 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   // FIXME need more debug logs
 
-  private final Lock readLock;
-  private final Lock writeLock;
+  private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
+  private final Lock readLock = readWriteLock.readLock();
+  private final Lock writeLock = readWriteLock.writeLock();
 
   private final ServiceComponent serviceComponent;
   private final Host host;
@@ -600,9 +601,6 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
       this.stateMachine = daemonStateMachineFactory.make(this);
     }
 
-    ReadWriteLock rwLock = new ReentrantReadWriteLock();
-    this.readLock = rwLock.readLock();
-    this.writeLock = rwLock.writeLock();
     this.serviceComponent = serviceComponent;
 
     stateEntity = new HostComponentStateEntity();
@@ -641,9 +639,6 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
                                   @Assisted HostComponentDesiredStateEntity desiredStateEntity,
                                   Injector injector) {
     injector.injectMembers(this);
-    ReadWriteLock rwLock = new ReentrantReadWriteLock();
-    this.readLock = rwLock.readLock();
-    this.writeLock = rwLock.writeLock();
     this.serviceComponent = serviceComponent;
 
 
@@ -678,8 +673,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public State getState() {
+    readLock.lock();
     try {
-      readLock.lock();
       return stateMachine.getCurrentState();
     }
     finally {
@@ -689,8 +684,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public void setState(State state) {
+    writeLock.lock();
     try {
-      writeLock.lock();
       stateMachine.setCurrentState(state);
       stateEntity.setCurrentState(state);
       saveIfPersisted();
@@ -746,20 +741,32 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public String getServiceComponentName() {
-    return serviceComponent.getName();
+    readLock.lock();
+    try {
+      return serviceComponent.getName();
+    } finally {
+      readLock.unlock();
+    }
+
   }
 
   @Override
   public String getHostName() {
-    return host.getHostName();
+    readLock.lock();
+    try {
+      return host.getHostName();
+    } finally {
+      readLock.unlock();
+    }
+
   }
 
   /**
    * @return the lastOpStartTime
    */
   public long getLastOpStartTime() {
+    readLock.lock();
     try {
-      readLock.lock();
       return lastOpStartTime;
     }
     finally {
@@ -771,8 +778,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
    * @param lastOpStartTime the lastOpStartTime to set
    */
   public void setLastOpStartTime(long lastOpStartTime) {
+    writeLock.lock();
     try {
-      writeLock.lock();
       this.lastOpStartTime = lastOpStartTime;
     }
     finally {
@@ -784,8 +791,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
    * @return the lastOpEndTime
    */
   public long getLastOpEndTime() {
+    readLock.lock();
     try {
-      readLock.lock();
       return lastOpEndTime;
     }
     finally {
@@ -797,8 +804,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
    * @param lastOpEndTime the lastOpEndTime to set
    */
   public void setLastOpEndTime(long lastOpEndTime) {
+    writeLock.lock();
     try {
-      writeLock.lock();
       this.lastOpEndTime = lastOpEndTime;
     }
     finally {
@@ -810,8 +817,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
    * @return the lastOpLastUpdateTime
    */
   public long getLastOpLastUpdateTime() {
+    readLock.lock();
     try {
-      readLock.lock();
       return lastOpLastUpdateTime;
     }
     finally {
@@ -823,8 +830,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
    * @param lastOpLastUpdateTime the lastOpLastUpdateTime to set
    */
   public void setLastOpLastUpdateTime(long lastOpLastUpdateTime) {
+    writeLock.lock();
     try {
-      writeLock.lock();
       this.lastOpLastUpdateTime = lastOpLastUpdateTime;
     }
     finally {
@@ -834,17 +841,29 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public long getClusterId() {
-    return serviceComponent.getClusterId();
+    readLock.lock();
+    try {
+      return serviceComponent.getClusterId();
+    } finally {
+      readLock.unlock();
+    }
+
   }
 
   @Override
   public String getServiceName() {
-    return serviceComponent.getServiceName();
+    readLock.lock();
+    try {
+      return serviceComponent.getServiceName();
+    } finally {
+      readLock.unlock();
+    }
+
   }
 
   Map<String, String> getConfigVersions() {
+    readLock.lock();
     try {
-      readLock.lock();
       if (this.configs != null) {
         return Collections.unmodifiableMap(configs);
       } else {
@@ -859,8 +878,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public Map<String, Config> getConfigs() throws AmbariException {
+    readLock.lock();
     try {
-      readLock.lock();
       Map<String, Config> map = new HashMap<String, Config>();
       Cluster cluster = clusters.getClusterById(getClusterId());
       for (Entry<String, String> entry : configs.entrySet()) {
@@ -879,8 +898,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Transactional
   void setConfigs(Map<String, String> configs) {
+    writeLock.lock();
     try {
-      writeLock.lock();
 
       Set<String> deletedTypes = new HashSet<String>();
       for (String type : this.configs.keySet()) {
@@ -971,8 +990,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public StackId getStackVersion() {
+    readLock.lock();
     try {
-      readLock.lock();
       return gson.fromJson(stateEntity.getCurrentStackVersion(), StackId.class);
     }
     finally {
@@ -982,8 +1001,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public void setStackVersion(StackId stackVersion) {
+    writeLock.lock();
     try {
-      writeLock.lock();
       stateEntity.setCurrentStackVersion(gson.toJson(stackVersion));
       saveIfPersisted();
     }
@@ -995,8 +1014,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public State getDesiredState() {
+    readLock.lock();
     try {
-      readLock.lock();
       return desiredStateEntity.getDesiredState();
     }
     finally {
@@ -1006,8 +1025,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public void setDesiredState(State state) {
+    writeLock.lock();
     try {
-      writeLock.lock();
       desiredStateEntity.setDesiredState(state);
       saveIfPersisted();
     }
@@ -1018,8 +1037,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public Map<String, String> getDesiredConfigVersionsRecursive() {
+    readLock.lock();
     try {
-      readLock.lock();
       Map<String, String> fullDesiredConfigVersions =
           new HashMap<String, String>();
       Map<String, Config> desiredConfs = getDesiredConfigs();
@@ -1037,8 +1056,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
   @Override
   public Map<String, Config> getDesiredConfigs() {
     Map<String, Config> map = new HashMap<String, Config>();
+    readLock.lock();
     try {
-      readLock.lock();
       for (Entry<String, String> entry : desiredConfigs.entrySet()) {
         Config config = clusters.getClusterById(getClusterId()).getConfig(
             entry.getKey(), entry.getValue());
@@ -1067,8 +1086,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
   @Override
   @Transactional
   public void updateDesiredConfigs(Map<String, Config> configs) {
+    writeLock.lock();
     try {
-      writeLock.lock();
 
       for (Entry<String,Config> entry : configs.entrySet()) {
 
@@ -1109,8 +1128,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public StackId getDesiredStackVersion() {
+    readLock.lock();
     try {
-      readLock.lock();
       return gson.fromJson(desiredStateEntity.getDesiredStackVersion(), StackId.class);
     }
     finally {
@@ -1120,8 +1139,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public void setDesiredStackVersion(StackId stackVersion) {
+    writeLock.lock();
     try {
-      writeLock.lock();
       desiredStateEntity.setDesiredStackVersion(gson.toJson(stackVersion));
       saveIfPersisted();
     }
@@ -1132,8 +1151,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public ServiceComponentHostResponse convertToResponse() {
+    readLock.lock();
     try {
-      readLock.lock();
       ServiceComponentHostResponse r = new ServiceComponentHostResponse(
           serviceComponent.getClusterName(),
           serviceComponent.getServiceName(),
@@ -1157,13 +1176,19 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public String getClusterName() {
-    return serviceComponent.getClusterName();
+    readLock.lock();
+    try {
+      return serviceComponent.getClusterName();
+    } finally {
+      readLock.unlock();
+    }
+
   }
 
   @Override
   public void debugDump(StringBuilder sb) {
+    readLock.lock();
     try {
-      readLock.lock();
       sb.append("ServiceComponentHost={ hostname=" + getHostName()
           + ", serviceComponentName=" + serviceComponent.getName()
           + ", clusterName=" + serviceComponent.getClusterName()
@@ -1181,8 +1206,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public boolean isPersisted() {
+    readLock.lock();
     try {
-      readLock.lock();
       return persisted;
     } finally {
       readLock.unlock();
@@ -1191,8 +1216,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public void persist() {
+    writeLock.lock();
     try {
-      writeLock.lock();
       if (!persisted) {
         persistEntities();
         refresh();
@@ -1235,23 +1260,29 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   @Transactional
-  public synchronized void refresh() {
-    if (isPersisted()) {
-      HostComponentStateEntityPK pk = new HostComponentStateEntityPK();
-      HostComponentDesiredStateEntityPK dpk = new HostComponentDesiredStateEntityPK();
-      pk.setClusterId(getClusterId());
-      pk.setComponentName(getServiceComponentName());
-      pk.setServiceName(getServiceName());
-      pk.setHostName(getHostName());
-      dpk.setClusterId(getClusterId());
-      dpk.setComponentName(getServiceComponentName());
-      dpk.setServiceName(getServiceName());
-      dpk.setHostName(getHostName());
-      stateEntity = hostComponentStateDAO.findByPK(pk);
-      desiredStateEntity = hostComponentDesiredStateDAO.findByPK(dpk);
-      hostComponentStateDAO.refresh(stateEntity);
-      hostComponentDesiredStateDAO.refresh(desiredStateEntity);
+  public void refresh() {
+    writeLock.lock();
+    try {
+      if (isPersisted()) {
+        HostComponentStateEntityPK pk = new HostComponentStateEntityPK();
+        HostComponentDesiredStateEntityPK dpk = new HostComponentDesiredStateEntityPK();
+        pk.setClusterId(getClusterId());
+        pk.setComponentName(getServiceComponentName());
+        pk.setServiceName(getServiceName());
+        pk.setHostName(getHostName());
+        dpk.setClusterId(getClusterId());
+        dpk.setComponentName(getServiceComponentName());
+        dpk.setServiceName(getServiceName());
+        dpk.setHostName(getHostName());
+        stateEntity = hostComponentStateDAO.findByPK(pk);
+        desiredStateEntity = hostComponentDesiredStateDAO.findByPK(dpk);
+        hostComponentStateDAO.refresh(stateEntity);
+        hostComponentDesiredStateDAO.refresh(desiredStateEntity);
+      }
+    } finally {
+      writeLock.unlock();
     }
+
   }
 
   @Transactional
@@ -1263,9 +1294,9 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
   }
 
   @Override
-  public synchronized boolean canBeRemoved() {
+  public boolean canBeRemoved() {
+    readLock.lock();
     try {
-      readLock.lock();
 
       return (getDesiredState().isRemovableState() &&
               getState().isRemovableState());
@@ -1277,8 +1308,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public void deleteDesiredConfigs(Set<String> configTypes) {
+    writeLock.lock();
     try {
-      writeLock.lock();
       hostComponentDesiredConfigMappingDAO.removeByType(configTypes);
       for (String configType : configTypes) {
         desiredConfigs.remove(configType);
@@ -1290,8 +1321,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
   @Override
   public void delete() {
+    writeLock.lock();
     try {
-      writeLock.lock();
       if (persisted) {
         removeEntities();
         persisted = false;
@@ -1324,35 +1355,53 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
   
   @Override
   public void updateActualConfigs(Map<String, Map<String, String>> configTags) {
-    actualConfigs = new HashMap<String, DesiredConfig>();
-    
-    String hostName = getHostName();
-    
-    for (Entry<String, Map<String,String>> entry : configTags.entrySet()) {
-      String type = entry.getKey();
-      Map<String, String> values = entry.getValue();
-      
-      String tag = values.get("tag");
-      String hostTag = values.get("host_override_tag");
-      
-      DesiredConfig dc = new DesiredConfig();
-      dc.setVersion(tag);
-      actualConfigs.put(type, dc);
-      if (null != hostTag && null != hostName) {
-        List<HostOverride> list = new ArrayList<HostOverride>();
-        list.add (new HostOverride(hostName, hostTag));
-        dc.setHostOverrides(list);
+    writeLock.lock();
+    try {
+      actualConfigs = new HashMap<String, DesiredConfig>();
+
+      String hostName = getHostName();
+
+      for (Entry<String, Map<String, String>> entry : configTags.entrySet()) {
+        String type = entry.getKey();
+        Map<String, String> values = entry.getValue();
+
+        String tag = values.get("tag");
+        String hostTag = values.get("host_override_tag");
+
+        DesiredConfig dc = new DesiredConfig();
+        dc.setVersion(tag);
+        actualConfigs.put(type, dc);
+        if (null != hostTag && null != hostName) {
+          List<HostOverride> list = new ArrayList<HostOverride>();
+          list.add(new HostOverride(hostName, hostTag));
+          dc.setHostOverrides(list);
+        }
       }
+    } finally {
+      writeLock.unlock();
     }
+
   }
   
   @Override
   public Map<String, DesiredConfig> getActualConfigs() {
-    return actualConfigs;
+    readLock.lock();
+    try {
+      return actualConfigs;
+    } finally {
+      readLock.unlock();
+    }
+
   }
 
   @Override
   public HostState getHostState() {
-    return host.getState();
+    readLock.lock();
+    try {
+      return host.getState();
+    } finally {
+      readLock.unlock();
+    }
+
   }
 }

+ 8 - 8
ambari-server/src/main/resources/stacks/HDP/1.3.0/repos/repoinfo.xml

@@ -18,7 +18,7 @@
 <reposinfo>
   <os type="centos6">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos6</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos6/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -31,7 +31,7 @@
   </os>
   <os type="centos5">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos5</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos5/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -44,7 +44,7 @@
   </os>
   <os type="redhat6">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos6</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos6/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -57,7 +57,7 @@
   </os>
   <os type="redhat5">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos5</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos5/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -70,7 +70,7 @@
   </os>
   <os type="oraclelinux6">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos6</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos6/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -83,7 +83,7 @@
   </os>
   <os type="oraclelinux5">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos5</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos5/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -96,14 +96,14 @@
   </os>
   <os type="suse11">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/suse11</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/suse11/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
   </os>
     <os type="sles11">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/suse11</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/suse11/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>

+ 8 - 8
ambari-server/src/main/resources/stacks/HDPLocal/1.3.0/repos/repoinfo.xml

@@ -18,7 +18,7 @@
 <reposinfo>
   <os type="centos6">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos6</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos6/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -31,7 +31,7 @@
   </os>
   <os type="centos5">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos5</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos5/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -44,7 +44,7 @@
   </os>
   <os type="redhat6">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos6</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos6/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -57,7 +57,7 @@
   </os>
   <os type="redhat5">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos5</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos5/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -70,7 +70,7 @@
   </os>
   <os type="oraclelinux6">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos6</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos6/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -83,7 +83,7 @@
   </os>
   <os type="oraclelinux5">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/centos5</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/centos5/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
@@ -96,14 +96,14 @@
   </os>
   <os type="suse11">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/suse11</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/suse11/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>
   </os>
     <os type="sles11">
     <repo>
-      <baseurl>http://s3.amazonaws.com/dev.hortonworks.com/HDP-1.3.0/repos/suse11</baseurl>
+      <baseurl>http://public-repo-1.hortonworks.com/HDP/suse11/1.x/GA/1.3.0.0</baseurl>
       <repoid>HDP-1.3.0</repoid>
       <reponame>HDP</reponame>
     </repo>

文件差異過大導致無法顯示
+ 0 - 0
ambari-server/src/test/resources/deploy_HDP2.sh


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

@@ -34,6 +34,8 @@ App.componentsUpdateInterval = 6000;
 App.contentUpdateInterval = 15000;
 App.maxRunsForAppBrowser = 500;
 App.pageReloadTime=3600000;
+App.singleNodeInstall = false;
+App.singleNodeAlias = document.location.hostname;
 
 // experimental features are automatically enabled if running on brunch server
 App.enableExperimental = false;

+ 2 - 2
ambari-web/app/controllers/global/cluster_controller.js

@@ -120,7 +120,7 @@ App.ClusterController = Em.Controller.extend({
               if (host) {
                 hostName = host.get('publicHostName');
               }
-              return "http://" + hostName + "/ganglia";
+              return "http://" + (App.singleNodeInstall ? App.singleNodeAlias : hostName) + "/ganglia";
             }
           }
         }
@@ -154,7 +154,7 @@ App.ClusterController = Em.Controller.extend({
               if (host) {
                 hostName = host.get('publicHostName');
               }
-              return "http://" + hostName + "/nagios";
+              return "http://" + (App.singleNodeInstall ? App.singleNodeAlias : hostName) + "/nagios";
             }
           }
         }

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

@@ -42,6 +42,7 @@ App.MainAdminMiscController = App.MainServiceInfoConfigsController.extend({
     });
   },
   loadServiceTagSuccess: function(data, opt, params) {
+    var installedServices = App.Service.find().mapProperty("serviceName");
     var serviceConfigsDef = params.serviceConfigsDef;
     var serviceName = this.get('content.serviceName');
     var loadedClusterSiteToTagMap = {};
@@ -57,6 +58,8 @@ App.MainAdminMiscController = App.MainServiceInfoConfigsController.extend({
 
     var misc_configs = configSet.globalConfigs.filterProperty('serviceName', this.get('selectedService')).filterProperty('category', 'Users and Groups').filterProperty('isVisible', true);
 
+    misc_configs = App.config.miscConfigVisibleProperty(misc_configs, installedServices);
+
     var sortOrder = this.get('configs').filterProperty('serviceName', this.get('selectedService')).filterProperty('category', 'Users and Groups').filterProperty('isVisible', true).mapProperty('name');
 
     var sorted = [];

+ 21 - 17
ambari-web/app/controllers/main/host.js

@@ -23,7 +23,6 @@ var componentHelper = require('utils/component');
 App.MainHostController = Em.ArrayController.extend({
   name:'mainHostController',
   content: App.Host.find(),
-  comeWithFilter: false,
 
   alerts: function () {
     return App.router.get('clusterController.alerts').filterProperty('isOk', false).filterProperty('ignoredForHosts', false);
@@ -56,27 +55,32 @@ App.MainHostController = Em.ArrayController.extend({
    */
   filterByComponent:function (component) {
     var id = component.get('componentName');
-
+    var column = 6;
     this.get('componentsForFilter').setEach('checkedForHostFilter', false);
-    this.get('componentsForFilter').filterProperty('id', id).setEach('checkedForHostFilter', true);
-
-    this.set('comeWithFilter', true);
-  },
 
-  /**
-   * On click callback for decommission button
-   * @param event
-   */
-  decommissionButtonPopup:function () {
-    var self = this;
-    App.showConfirmationPopup(function(){
-      alert('do');
-    });
+    var filterForComponent = {
+      iColumn: column,
+      value: id,
+      type: 'multiple'
+    };
+
+    var filterConditions = App.db.getFilterConditions(this.get('name'));
+    if (filterConditions) {
+      var component = filterConditions.findProperty('iColumn', column);
+      if (component) {
+        component.value = id;
+      }
+      else {
+        filterConditions.push(filterForComponent);
+      }
+      App.db.setFilterConditions(this.get('name'), filterConditions);
+    }
+    else {
+      App.db.setFilterConditions(this.get('name'), [filterForComponent]);
+    }
   },
-
   /**
    * On click callback for delete button
-   * @param event
    */
   deleteButtonPopup:function () {
     var self = this;

+ 3 - 1
ambari-web/app/controllers/main/host/details.js

@@ -50,7 +50,9 @@ App.MainHostDetailsController = Em.Controller.extend({
   /**
    * Send specific command to server
    * @param url
-   * @param data Object to send
+   * @param _method
+   * @param postData
+   * @param callback
    */
   sendCommandToServer : function(url, postData, _method, callback){
     var url =  (App.testMode) ?

+ 1 - 14
ambari-web/app/controllers/wizard/step7_controller.js

@@ -91,20 +91,7 @@ App.WizardStep7Controller = Em.Controller.extend({
    */
   activateSpecialConfigs: function () {
     var miscConfigs = this.get('stepConfigs').findProperty('serviceName', 'MISC').configs;
-    var showProxyGroup = this.get('selectedServiceNames').contains('HIVE') ||
-      this.get('selectedServiceNames').contains('HCATALOG') ||
-      this.get('selectedServiceNames').contains('OOZIE');
-    miscConfigs.findProperty('name', 'proxyuser_group').set('isVisible', showProxyGroup);
-    miscConfigs.findProperty('name', 'hbase_user').set('isVisible', this.get('selectedServiceNames').contains('HBASE'));
-    miscConfigs.findProperty('name', 'mapred_user').set('isVisible', this.get('selectedServiceNames').contains('MAPREDUCE'));
-    miscConfigs.findProperty('name', 'hive_user').set('isVisible', this.get('selectedServiceNames').contains('HIVE'));
-    miscConfigs.findProperty('name', 'hcat_user').set('isVisible', this.get('selectedServiceNames').contains('HCATALOG'));
-    miscConfigs.findProperty('name', 'webhcat_user').set('isVisible', this.get('selectedServiceNames').contains('WEBHCAT'));
-    miscConfigs.findProperty('name', 'oozie_user').set('isVisible', this.get('selectedServiceNames').contains('OOZIE'));
-    miscConfigs.findProperty('name', 'zk_user').set('isVisible', this.get('selectedServiceNames').contains('ZOOKEEPER'));
-    miscConfigs.findProperty('name', 'gmetad_user').set('isVisible', this.get('selectedServiceNames').contains('GANGLIA'));
-    miscConfigs.findProperty('name', 'rrdcached_base_dir').set('isVisible', this.get('selectedServiceNames').contains('GANGLIA'));
-    miscConfigs.findProperty('name', 'nagios_user').set('isVisible', this.get('selectedServiceNames').contains('NAGIOS'));
+    miscConfigs = App.config.miscConfigVisibleProperty(miscConfigs, this.get('selectedServiceNames'));
   },
 
   /**

+ 34 - 103
ambari-web/app/data/HDP2/config_mapping.js

@@ -303,7 +303,7 @@ var configs = [
   },
 /**********************************************yarn-site***************************************/
   {
-    "name": "yarn.resourcemanager.resourcetracker.address",
+    "name": "yarn.resourcemanager.resource-tracker.address",
     "templateName": ["rm_host"],
     "foreignKey": null,
     "value": "hdfs://<templateName[0]>:8025",
@@ -317,7 +317,7 @@ var configs = [
     "filename": "yarn-site.xml"
   },
   {
-    "name": "yarn.resourcemanager.addresss",
+    "name": "yarn.resourcemanager.address",
     "templateName": ["rm_host"],
     "foreignKey": null,
     "value": "hdfs://<templateName[0]>:8050",
@@ -359,30 +359,24 @@ var configs = [
     "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
+  //io.sort.mb -> mapreduce.task.io.sort.mb
   {
-    "name": "io.sort.mb",
-    "templateName": ["io_sort_mb"],
-    "foreignKey": null,
-    "value": "<templateName[0]>",
-    "filename": "mapred-site.xml"
-  },
-  /*{
-    "name": "mapred.cluster.reduce.memory.mb",
-    "templateName": ["mapred_cluster_red_mem_mb"],
+    "name": "mapreduce.task.io.sort.mb",
+    "templateName": ["mapreduce_task_io_sort_mb"],
     "foreignKey": null,
     "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapred.cluster.max.map.memory.mb",
-    "templateName": ["mapred_cluster_max_map_mem_mb"],
+    "name": "mapred.system.dir",
+    "templateName": ["mapred_system_dir"],
     "foreignKey": null,
     "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapred.cluster.max.reduce.memory.mb",
-    "templateName": ["mapred_cluster_max_red_mem_mb"],
+    "name": "mapred.cluster.reduce.memory.mb",
+    "templateName": ["mapred_cluster_red_mem_mb"],
     "foreignKey": null,
     "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
@@ -395,68 +389,12 @@ var configs = [
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapred.hosts.exclude",
-    "templateName": ["hadoop_conf_dir", "mapred_hosts_exclude"],
-    "foreignKey": null,
-    "value": "<templateName[0]>/<templateName[1]>",
-    "filename": "mapred-site.xml"
-  },
-  {
-    "name": "mapred.healthChecker.script.path",
-    "templateName": ["mapred_jobstatus_dir"],
-    "foreignKey": null,
-    "value": "<templateName[0]>",
-    "filename": "mapred-site.xml"
-  },
-  {
-    "name": "mapred.job.tracker.persist.jobstatus.dir",
-    "templateName": ["hadoop_conf_dir"],
-    "foreignKey": null,
-    "value": "<templateName[0]>/health_check",
-    "filename": "mapred-site.xml"
-  },
-  {
-    "name": "mapred.child.java.opts",
-    "templateName": ["mapred_child_java_opts_sz"],
-    "foreignKey": null,
-    "value": "-server -Xmx<templateName[0]>m -Djava.net.preferIPv4Stack=true",
-    "filename": "mapred-site.xml"
-  },
-  {
-    "name": "mapred.cluster.map.memory.mb",
-    "templateName": ["mapred_cluster_map_mem_mb"],
-    "foreignKey": null,
-    "value": "<templateName[0]>",
-    "filename": "mapred-site.xml"
-  },
-  {
-    "name": "io.sort.spill.percent",
-    "templateName": ["io_sort_spill_percent"],
-    "foreignKey": null,
-    "value": "<templateName[0]>",
-    "filename": "mapred-site.xml"
-  },
-  {
-    "name": "mapred.system.dir",
-    "templateName": ["mapred_system_dir"],
+    "name": "mapred.jobtracker.maxtasks.per.job",
+    "templateName": ["maxtasks_per_job"],
     "foreignKey": null,
     "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
-  {
-    "name": "mapred.job.tracker",
-    "templateName": ["jobtracker_host"],
-    "foreignKey": null,
-    "value": "<templateName[0]>:50300",
-    "filename": "mapred-site.xml"
-  },
-  {
-    "name": "mapred.job.tracker.http.address",
-    "templateName": ["jobtracker_host"],
-    "foreignKey": null,
-    "value": "<templateName[0]>:50030",
-    "filename": "mapred-site.xml"
-  },
   {
     "name": "mapred.userlog.retain.hours",
     "templateName": ["mapreduce_userlog_retainhours"],
@@ -465,8 +403,8 @@ var configs = [
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapred.jobtracker.maxtasks.per.job",
-    "templateName": ["maxtasks_per_job"],
+    "name": "mapred.local.dir",
+    "templateName": ["mapred_local_dir"],
     "foreignKey": null,
     "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
@@ -479,61 +417,54 @@ var configs = [
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapreduce.jobtracker.kerberos.principal",
-    "templateName": ["kerberos_domain"],
+    "name": "mapred.tasktracker.map.tasks.maximum",
+    "templateName": ["mapred_map_tasks_max"],
     "foreignKey": null,
-    "value": "jt/_HOST@<templateName[0]>",
+    "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapreduce.tasktracker.kerberos.principal",
-    "templateName": ["kerberos_domain"],
+    "name": "mapred.hosts.exclude",
+    "templateName": ["hadoop_conf_dir", "mapred_hosts_exclude"],
     "foreignKey": null,
-    "value": "tt/_HOST@<templateName[0]>",
+    "value": "<templateName[0]>/<templateName[1]>",
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapreduce.jobtracker.keytab.file",
-    "templateName": ["keytab_path"],
+    "name": "mapred.cluster.max.map.memory.mb",
+    "templateName": ["mapred_cluster_max_map_mem_mb"],
     "foreignKey": null,
-    "value": "<templateName[0]>/jt.service.keytab",
+    "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapreduce.tasktracker.keytab.file",
-    "templateName": ["keytab_path"],
+    "name": "mapred.cluster.max.reduce.memory.mb",
+    "templateName": ["mapred_cluster_max_red_mem_mb"],
     "foreignKey": null,
-    "value": "<templateName[0]>/tt.service.keytab",
+    "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapreduce.history.server.embedded",
-    "templateName": [],
+    "name": "mapred.jobtracker.taskScheduler",
+    "templateName": ["scheduler_name"],
     "foreignKey": null,
-    "value": "false",
+    "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapreduce.history.server.http.address",
-    "templateName": ["jobtracker_host"],
+    "name": "mapred.healthChecker.script.path",
+    "templateName": ["mapred_jobstatus_dir"],
     "foreignKey": null,
-    "value": "<templateName[0]>:51111",
+    "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
   {
-    "name": "mapreduce.jobhistory.kerberos.principal",
-    "templateName": ["kerberos_domain"],
+    "name": "mapred.cluster.map.memory.mb",
+    "templateName": ["mapred_cluster_map_mem_mb"],
     "foreignKey": null,
-    "value": "jt/_HOST@<templateName[0]>",
+    "value": "<templateName[0]>",
     "filename": "mapred-site.xml"
   },
-  {
-    "name": "mapreduce.jobhistory.keytab.file",
-    "templateName": ["keytab_path"],
-    "foreignKey": null,
-    "value": "<templateName[0]>/jt.service.keytab",
-    "filename": "mapred-site.xml"
-  },*/
   /**********************************************hbase-site***************************************/
   {
     "name": "hbase.rootdir",

+ 252 - 25
ambari-web/app/data/HDP2/config_properties.js

@@ -58,7 +58,7 @@
  *
  *   serviceName:
  *     The service that the config property belongs to.
- *     E.g., "HDFS", "MAPREDUCE", "ZOOKEEPER", etc.
+ *     E.g., "HDFS", "MAPREDUCE2", "ZOOKEEPER", etc.
  *
  *   category: the category that the config property belongs to (used for grouping config properties in the UI).
  *     if unspecified, "General" is assumed.
@@ -494,6 +494,209 @@ module.exports =
       "category": "HistoryServer",
       "index": 0
     },
+    {
+      "id": "puppet var",
+      "name": "mapred_local_dir",
+      "displayName": "MapReduce local directories",
+      "description": "Directories for MapReduce to store intermediate data files",
+      "defaultValue": "",
+      "defaultDirectory": "/hadoop/mapred",
+      "displayType": "directories",
+      "isReconfigurable": true,
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_cluster_red_mem_mb",
+      "displayName": "Cluster's Reduce slot size (virtual memory)",
+      "description": "The virtual memory size of a single Reduce slot in the MapReduce framework",
+      "defaultValue": "-1",
+      "displayType": "int",
+      "unit": "MB",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_map_tasks_max",
+      "displayName": "Number of Map slots per node",
+      "description": "Number of slots that Map tasks that run simultaneously can occupy on a TaskTracker",
+      "defaultValue": "4",
+      "displayType": "int",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_job_map_mem_mb",
+      "displayName": "Default virtual memory for a job's map-task",
+      "description": "Virtual memory for single Map task",
+      "defaultValue": "-1",
+      "displayType": "int",
+      "unit": "MB",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_job_red_mem_mb",
+      "displayName": "Default virtual memory for a job's reduce-task",
+      "description": "Virtual memory for single Reduce task",
+      "defaultValue": "-1",
+      "displayType": "int",
+      "unit": "MB",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapreduce_task_io_sort_mb",
+      "displayName": "Map-side sort buffer memory",
+      "description": "The total amount of Map-side buffer memory to use while sorting files (Expert-only configuration)",
+      "defaultValue": "200",
+      "displayType": "int",
+      "unit": "MB",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapreduce_userlog_retainhours",
+      "displayName": "Job log retention (hours)",
+      "description": "The maximum time, in hours, for which the user-logs are to be retained after the job completion.",
+      "defaultValue": "24",
+      "displayType": "int",
+      "unit": "hours",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "maxtasks_per_job",
+      "displayName": "Maximum number tasks for a Job",
+      "description": "Maximum number of tasks for a single Job",
+      "defaultValue": "-1",
+      "displayType": "int",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_cluster_max_map_mem_mb",
+      "displayName": "Upper limit on virtual memory for single Map task",
+      "description": "Upper limit on virtual memory size for a single Map task of any MapReduce job",
+      "defaultValue": "-1",
+      "displayType": "int",
+      "unit": "MB",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_cluster_max_red_mem_mb",
+      "displayName": "Upper limit on virtual memory for single Reduce task",
+      "description": "Upper limit on virtual memory size for a single Reduce task of any MapReduce job",
+      "defaultValue": "-1",
+      "displayType": "int",
+      "unit": "MB",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "scheduler_name",
+      "displayName": "MapReduce Capacity Scheduler",
+      "description": "The scheduler to use for scheduling of MapReduce jobs",
+      "defaultValue": "org.apache.hadoop.mapred.CapacityTaskScheduler",
+      "displayType": "advanced",
+      "isOverridable": false,
+      "isVisible": true,
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_cluster_map_mem_mb",
+      "displayName": "Cluster's Map slot size (virtual memory)",
+      "description": "The virtual memory size of a single Map slot in the MapReduce framework",
+      "defaultValue": "-1",
+      "displayType": "int",
+      "unit": "MB",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_system_dir",
+      "displayName": "MapReduce system directories",
+      "description": "",
+      "defaultValue": "/mapred/system",
+      "displayType": "directories",
+      "isReconfigurable": true,
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "MAPREDUCE2",
+      "category": "Advanced"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_hosts_include",
+      "displayName": "Include hosts",
+      "description": "Include enetered hosts",
+      "defaultValue": "mapred.include",
+      "displayType": "directories",
+      "isVisible": false,
+      "serviceName": "MAPREDUCE2",
+      "domain": "global",
+      "category": "Advanced"
+    },
+    {
+      "id": "puppet var",
+      "name": "task_controller",
+      "displayName": "task_controller",
+      "description": "",
+      "defaultValue": "org.apache.hadoop.mapred.DefaultTaskController",
+      "displayType": "advanced",
+      "isVisible": false,
+      "serviceName": "MAPREDUCE2",
+      "domain": "global",
+      "category": "Advanced"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_hosts_exclude",
+      "displayName": "Exclude hosts",
+      "description": "Exclude entered hosts",
+      "defaultValue": "mapred.exclude",
+      "displayType": "directories",
+      "isVisible": false,
+      "serviceName": "MAPREDUCE2",
+      "domain": "global",
+      "category": "Advanced"
+    },
+    {
+      "id": "puppet var",
+      "name": "mapred_jobstatus_dir",
+      "displayName": "Job Status directory",
+      "description": "Directory path to view job status",
+      "defaultValue": "file:////mapred/jobstatus",
+      "displayType": "advanced",
+      "isVisible": false,
+      "serviceName": "MAPREDUCE2",
+      "domain": "global",
+      "category": "Advanced"
+    },
   /**********************************************YARN***************************************/
     {
       "id": "puppet var",
@@ -1695,7 +1898,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1710,7 +1914,8 @@ module.exports =
       "filename": "core-site.xml",
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HIVE","WEBHCAT","OOZIE"]
     },
     {
       "id": "puppet var",
@@ -1724,7 +1929,8 @@ module.exports =
       "filename": "hdfs-site.xml",
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Advanced"
+      "category": "Advanced",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1738,7 +1944,8 @@ module.exports =
       "filename": "hdfs-site.xml",
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Advanced"
+      "category": "Advanced",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1751,7 +1958,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1764,7 +1972,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1777,7 +1986,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1790,7 +2000,8 @@ module.exports =
       "displayType": "directory",
       "isVisible": false,
       "domain": "global",
-      "serviceName": "MISC"
+      "serviceName": "MISC",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1804,7 +2015,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Advanced"
+      "category": "Advanced",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1818,7 +2030,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Advanced"
+      "category": "Advanced",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1832,7 +2045,8 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "domain": "global",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HDFS"]
     },
     {
       "id": "puppet var",
@@ -1846,7 +2060,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["MAPREDUCE"]
     },
     {
       "id": "puppet var",
@@ -1860,7 +2075,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HBASE"]
     },
     {
       "id": "puppet var",
@@ -1874,7 +2090,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HIVE"]
     },
     {
       "id": "puppet var",
@@ -1888,7 +2105,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HCATALOG"]
     },
     {
       "id": "puppet var",
@@ -1902,7 +2120,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["WEBHCAT"]
     },
     {
       "id": "puppet var",
@@ -1916,7 +2135,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["OOZIE"]
     },
     {
       "id": "puppet var",
@@ -1930,7 +2150,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["ZOOKEEPER"]
     },
     {
       "id": "puppet var",
@@ -1944,7 +2165,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["GANGLIA"]
     },
     {
       "id": "puppet var",
@@ -1958,7 +2180,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName":"MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -1972,7 +2195,8 @@ module.exports =
       "domain": "global",
       "isVisible": true,
       "serviceName":"MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["NAGIOS"]
     },
     {
       "id": "puppet var",
@@ -1986,7 +2210,8 @@ module.exports =
       "isVisible": App.supports.customizeSmokeTestUser,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HDFS"]
     },
     {
       "id": "puppet var",
@@ -2000,7 +2225,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HDFS"]
     },
     {
       "id": "puppet var",
@@ -2012,7 +2238,8 @@ module.exports =
       "isOverridable": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":["GANGLIA"]
     }
   ]
 };

+ 48 - 24
ambari-web/app/data/config_properties.js

@@ -2132,7 +2132,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -2147,7 +2148,8 @@ module.exports =
       "filename": "core-site.xml",
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HIVE","WEBHCAT","OOZIE"]
     },
     {
       "id": "puppet var",
@@ -2161,7 +2163,8 @@ module.exports =
       "filename": "hdfs-site.xml",
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Advanced"
+      "category": "Advanced",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -2175,7 +2178,8 @@ module.exports =
       "filename": "hdfs-site.xml",
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Advanced"
+      "category": "Advanced",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -2188,7 +2192,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -2201,7 +2206,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -2214,7 +2220,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":[]
     },
     /*
     {
@@ -2269,7 +2276,8 @@ module.exports =
       "displayType": "directory",
       "isVisible": false,
       "domain": "global",
-      "serviceName": "MISC"
+      "serviceName": "MISC",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -2283,7 +2291,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Advanced"
+      "category": "Advanced",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -2297,7 +2306,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Advanced"
+      "category": "Advanced",
+      "belongsToService":[]
     },
     /*
     {
@@ -2413,7 +2423,8 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "domain": "global",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HDFS"]
     },
     {
       "id": "puppet var",
@@ -2427,7 +2438,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["MAPREDUCE"]
     },
     {
       "id": "puppet var",
@@ -2441,7 +2453,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HBASE"]
     },
     {
       "id": "puppet var",
@@ -2455,7 +2468,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HIVE"]
     },
     {
       "id": "puppet var",
@@ -2469,7 +2483,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HCATALOG"]
     },
     {
       "id": "puppet var",
@@ -2483,7 +2498,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["WEBHCAT"]
     },
     {
       "id": "puppet var",
@@ -2497,7 +2513,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["OOZIE"]
     },
     /*
     {
@@ -2568,7 +2585,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["ZOOKEEPER"]
     },
     {
       "id": "puppet var",
@@ -2582,7 +2600,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["GANGLIA"]
     },
     {
       "id": "puppet var",
@@ -2596,7 +2615,8 @@ module.exports =
       "isVisible": false,
       "domain": "global",
       "serviceName":"MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":[]
     },
     {
       "id": "puppet var",
@@ -2610,7 +2630,8 @@ module.exports =
       "domain": "global",
       "isVisible": true,
       "serviceName":"MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["NAGIOS"]
     },
     {
       "id": "puppet var",
@@ -2624,7 +2645,8 @@ module.exports =
       "isVisible": App.supports.customizeSmokeTestUser,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HDFS"]
     },
     {
       "id": "puppet var",
@@ -2638,7 +2660,8 @@ module.exports =
       "isVisible": true,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "Users and Groups"
+      "category": "Users and Groups",
+      "belongsToService":["HDFS"]
     },
     /*
     {
@@ -2664,7 +2687,8 @@ module.exports =
       "isOverridable": false,
       "domain": "global",
       "serviceName": "MISC",
-      "category": "General"
+      "category": "General",
+      "belongsToService":["GANGLIA"]
     }
   ]
 };

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

@@ -115,6 +115,7 @@ Em.I18n.translations = {
   'common.search': 'Search',
   'common.confirm': 'Confirm',
   'common.upgrade': 'Upgrade',
+  'common.reUpgrade': 'Retry Upgrade',
   'common.security':'Security',
   'common.cluster':'Cluster',
   'common.add': 'Add',
@@ -128,7 +129,7 @@ Em.I18n.translations = {
   'common.abort': 'Abort',
   'common.misc': 'Misc',
   'common.operations': 'Operations',
-  'common.install': 'Install',
+  'common.reinstall': 'Re-Install',
   'common.errorPopup.header': 'An error has been encountered',
   'common.use': 'Use',
   'common.stacks': 'Stacks',

+ 27 - 7
ambari-web/app/models/host_component.js

@@ -88,7 +88,33 @@ App.HostComponent = DS.Model.extend({
       }
     }
     return decommissioning;
-  }.property('componentName', 'host.hostName', 'App.router.mainServiceController.hdfsService.decommissionDataNodes.@each.hostName')
+  }.property('componentName', 'host.hostName', 'App.router.mainServiceController.hdfsService.decommissionDataNodes.@each.hostName'),
+  /**
+   * User friendly host component status
+   */
+  componentTextStatus: function () {
+    var value = this.get("workStatus");
+
+    switch(value){
+      case "INSTALLING":
+        return 'Installing...';
+      case "INSTALL_FAILED":
+        return 'Install Failed';
+      case "INSTALLED":
+        return 'Stopped';
+      case "STARTED":
+        return 'Started';
+      case "STARTING":
+        return 'Starting...';
+      case "STOPPING":
+        return 'Stopping...';
+      case "UNKNOWN":
+        return 'Heartbeat lost...';
+      case "UPGRADE_FAILED":
+        return 'Upgrade Failed';
+    }
+    return 'Unknown';
+  }.property('workStatus','isDecommissioning')
 });
 
 App.HostComponent.FIXTURES = [];
@@ -98,8 +124,6 @@ App.HostComponentStatus = {
   starting: "STARTING",
   stopped: "INSTALLED",
   stopping: "STOPPING",
-  stop_failed: "STOP_FAILED",
-  start_failed: "START_FAILED",
   install_failed: "INSTALL_FAILED",
   installing: "INSTALLING",
   upgrade_failed: "UPGRADE_FAILED",
@@ -115,10 +139,6 @@ App.HostComponentStatus = {
         return 'installed';
       case this.stopping:
         return 'stopping';
-      case this.stop_failed:
-        return 'stop_failed';
-      case this.start_failed:
-        return 'start_failed';
       case this.install_failed:
         return 'install_failed';
       case this.installing:

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

@@ -57,7 +57,7 @@ App.Service = DS.Model.extend({
       this.set('healthStatus', 'green');
     } else if (components.someProperty('workStatus', App.HostComponentStatus.starting)) {
       this.set('healthStatus', 'green-blinking');
-    } else if (components.someProperty('workStatus', App.HostComponentStatus.stopped) || components.someProperty('workStatus', App.HostComponentStatus.start_failed)) {
+    } else if (components.someProperty('workStatus', App.HostComponentStatus.stopped)) {
       this.set('healthStatus', 'red');
     } else if (components.someProperty('workStatus', App.HostComponentStatus.unknown)) {
       this.set('healthStatus', 'yellow');

+ 0 - 4
ambari-web/app/models/service_config.js

@@ -19,10 +19,6 @@
 var App = require('app');
 var validator = require('utils/validator');
 
-App.ConfigProperties = Ember.ArrayProxy.extend({
-  content: require('data/config_properties').configProperties
-});
-
 App.ServiceConfig = Ember.Object.extend({
   serviceName: '',
   configCategories: [],

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

@@ -2170,6 +2170,14 @@ table.graphs {
     .marker;
   }
 
+  .health-status-color-blue {
+    color:#0000ff;
+  }
+
+  .health-status-color-red {
+    color:#ff0000;
+  }
+
   .health-status-DEAD-ORANGE {
     background-image: @status-dead-orange-marker;
     .marker;
@@ -2242,6 +2250,18 @@ table.graphs {
 
   .host-components .btn-group {
     margin: 0 5px 10px 0;
+
+    .component-text-status{
+      cursor: default;
+      display: block;
+      padding: 3px 20px;
+      clear: both;
+      font-weight: normal;
+      line-height: 20px;
+      color: #333333;
+      white-space: nowrap;
+      font-style: italic;
+    }
   }
 }
 

+ 6 - 4
ambari-web/app/templates/main/admin/misc.hbs

@@ -31,10 +31,12 @@
           </thead>
           <tbody>
             {{#each user in controller.users}}
-              <tr>
-                <td>{{user.displayName}}</td>
-                <td>{{user.value}}</td>
-              </tr>
+              {{#if user.isVisible}}
+                <tr>
+                  <td>{{user.displayName}}</td>
+                  <td>{{user.value}}</td>
+                </tr>
+              {{/if}}
             {{/each}}
           </tbody>
         </table>

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

@@ -64,43 +64,60 @@
             <div class="span5">
               {{#if App.isAdmin}}
               <div class="btn-group">
-                <a {{ bindAttr class=":btn :dropdown-toggle view.disabledClass"}} data-toggle="dropdown">
+                <a {{ bindAttr class=":btn :dropdown-toggle"}} data-toggle="dropdown">
                   {{t common.action}}
                   <span class="caret pull-right"></span>
                 </a>
                 <ul class="dropdown-menu">
+                   <li>
+                      <div class="component-text-status">
+                       {{view.componentTextStatus}}
+                      </div>
+                    </li>
                   {{#if view.isDataNode}}
-                  <li {{bindAttr class="view.isDataNodeDecommissionAvailable::hidden"}}>
-                    <a href="javascript:void(null)" data-toggle="modal" {{action "decommission" view.content target="controller"}}>
-                      {{t common.decommission}}
-                    </a>
-                  </li>
-                  <li {{bindAttr class="view.isDataNodeRecommissionAvailable::hidden"}}>
-                    <a href="javascript:void(null)" data-toggle="modal" {{action "recommission" view.content target="controller"}}>
-                      {{t common.recommission}}
-                    </a>
-                  </li>
+                    {{#if view.isDataNodeDecommissionAvailable}}
+                      <li {{bindAttr class="view.noActionAvailable"}}>
+                        <a href="javascript:void(null)" data-toggle="modal" {{action "decommission" view.content target="controller"}}>
+                          {{t common.decommission}}
+                        </a>
+                      </li>
+                    {{/if}}
+                    {{#if view.isDataNodeRecommissionAvailable}}
+                      <li {{bindAttr class="view.noActionAvailable"}}>
+                        <a href="javascript:void(null)" data-toggle="modal" {{action "recommission" view.content target="controller"}}>
+                          {{t common.recommission}}
+                        </a>
+                      </li>
+                    {{/if}}
+                  {{/if}}
+                  {{#if view.isStart}}
+                    <li {{bindAttr class=" view.isDecommissioning:hidden view.noActionAvailable"}}>
+                      <a href="javascript:void(null)" data-toggle="modal" {{action "stopComponent" view.content target="controller"}}>
+                        {{t common.stop}}
+                      </a>
+                    </li>
+                  {{/if}}
+                  {{#unless view.isStart}}
+                    <li {{bindAttr class="view.isUpgradeFailed:hidden view.isInstallFailed:hidden view.isDecommissioning:hidden view.noActionAvailable"}}>
+                      <a href="javascript:void(null)" data-toggle="modal" {{action "startComponent" view.content target="controller"}}>
+                        {{t common.start}}
+                      </a>
+                    </li>
+                  {{/unless}}
+                  {{#if view.isUpgradeFailed}}
+                    <li {{bindAttr class="view.noActionAvailable"}}>
+                      <a href="javascript:void(null)" data-toggle="modal" {{action "upgradeComponent" view.content target="controller"}}>
+                        {{t common.reUpgrade}}
+                      </a>
+                    </li>
+                  {{/if}}
+                  {{#if view.isInstallFailed}}
+                    <li {{bindAttr class="view.noActionAvailable"}}>
+                      <a href="javascript:void(null)" data-toggle="modal" {{action "installComponent" view.content target="controller"}}>
+                        {{t common.reinstall}}
+                      </a>
+                    </li>
                   {{/if}}
-                  <li {{bindAttr class="view.isStart::hidden"}}>
-                    <a href="javascript:void(null)" data-toggle="modal" {{action "stopComponent" view.content target="controller"}}>
-                      {{t common.stop}}
-                    </a>
-                  </li>
-                  <li {{bindAttr class="view.isStart:hidden: view.isInstallFailed:hidden: view.isDataNodeRecommissionAvailable:hidden"}}>
-                    <a href="javascript:void(null)" data-toggle="modal" {{action "startComponent" view.content target="controller"}}>
-                      {{t common.start}}
-                    </a>
-                  </li>
-                  <li {{bindAttr class="view.isUpgradeFailed::hidden"}}>
-                    <a href="javascript:void(null)" data-toggle="modal" {{action "upgradeComponent" view.content target="controller"}}>
-                      {{t common.upgrade}}
-                    </a>
-                  </li>
-                  <li {{bindAttr class="view.isInstallFailed::hidden"}}>
-                    <a href="javascript:void(null)" data-toggle="modal" {{action "installComponent" view.content target="controller"}}>
-                      {{t common.install}}
-                    </a>
-                  </li>
                 </ul>
               </div>
               {{/if}}
@@ -165,4 +182,4 @@
 	  </div>
   </div>
 </div>
-</div>
+</div>

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

@@ -55,8 +55,8 @@
       <span class="task-detail-log-rolename" >{{{view.openedTask.role}} {{view.openedTask.command}}</span>
     </div>
     <div class="task-detail-ico-wrap">
-      <div title="Click to Copy" {{action "textTrigger" taskInfo target="view"}} class="task-detail-copy"><i class="icon-copy"></i> {{t common.copy}}</div>
-      <div title="Open in New Window" {{action openTaskLogInDialog}} class="task-detail-open-dialog"><i class="icon-external-link"></i> {{t common.open}}</div>
+      <a title="Click to Copy" {{action "textTrigger" taskInfo target="view"}} class="task-detail-copy"><i class="icon-copy"></i> {{t common.copy}}</a>
+      <a title="Open in New Window" {{action openTaskLogInDialog}} class="task-detail-open-dialog"><i class="icon-external-link"></i> {{t common.open}}</a>
     </div>
   </div>
   <div class="task-detail-log-info">

+ 15 - 5
ambari-web/app/utils/config.js

@@ -37,9 +37,9 @@ App.config = Em.Object.create({
   configMapping: function() {
       if (stringUtils.compareVersions(App.get('currentStackVersionNumber'), "2.0") === 1 ||
         stringUtils.compareVersions(App.get('currentStackVersionNumber'), "2.0") === 0) {
-        return require('data/config_mapping');
+        return require('data/HDP2/config_mapping');
       }
-      return require('data/HDP2/config_mapping');
+    return require('data/config_mapping');
   }.property('App.currentStackVersionNumber'),
   preDefinedConfigProperties: function() {
     if (stringUtils.compareVersions(App.get('currentStackVersionNumber'), "2.0") === 1 ||
@@ -154,15 +154,16 @@ App.config = Em.Object.create({
       properties = (properties.length) ? properties.objectAt(0).properties : {};
       for (var index in properties) {
         var configsPropertyDef = preDefinedConfigs.findProperty('name', index) || null;
-        var serviceConfigObj = {
+        var serviceConfigObj = App.ServiceConfig.create({
           name: index,
           value: properties[index],
           defaultValue: properties[index],
           filename: _tag.siteName + ".xml",
           isUserProperty: false,
           isOverridable: true,
-          serviceName: serviceName
-        };
+          serviceName: serviceName,
+          belongsToService: []
+        });
 
         if (configsPropertyDef) {
           serviceConfigObj.displayType = configsPropertyDef.displayType;
@@ -174,6 +175,7 @@ App.config = Em.Object.create({
           serviceConfigObj.isOverridable = configsPropertyDef.isOverridable === undefined ? true : configsPropertyDef.isOverridable;
           serviceConfigObj.serviceName = configsPropertyDef ? configsPropertyDef.serviceName : null;
           serviceConfigObj.index = configsPropertyDef.index;
+          serviceConfigObj.belongsToService = configsPropertyDef.belongsToService;
         }
         // MAPREDUCE contains core-site properties but doesn't show them
         if(serviceConfigObj.serviceName === 'MAPREDUCE' && serviceConfigObj.filename === 'core-site.xml'){
@@ -367,6 +369,14 @@ App.config = Em.Object.create({
         break;
     }
   },
+
+  miscConfigVisibleProperty: function (configs, serviceToShow) {
+    configs.forEach(function(item) {
+      item.set("isVisible", item.belongsToService.some(function(cur){return serviceToShow.contains(cur)}));
+    });
+    return configs;
+  },
+
   /**
    * render configs, distribute them by service
    * and wrap each in ServiceConfigProperty object

+ 83 - 1
ambari-web/app/utils/db.js

@@ -49,7 +49,13 @@ App.db.cleanUp = function () {
   App.db.data = {
     'app': {
       'loginName': '',
-      'authenticated': false
+      'authenticated': false,
+      'tables': {
+        'filterConditions': {},
+        'displayLength': {},
+        'startIndex': {},
+        'sortingConditions': {}
+      }
     },
 
     'Installer' : {},
@@ -111,6 +117,46 @@ App.db.setAuthenticated = function (authenticated) {
   console.log('Now present value of authentication is: ' + App.db.data.app.authenticated);
 };
 
+App.db.setFilterConditions = function(name, filterConditions) {
+  console.log('TRACE: Entering db:setFilterConditions function');
+  App.db.data = localStorage.getObject('ambari');
+  if (!App.db.data.app.tables.filterConditions) {
+    App.db.data.app.tables.filterConditions = {};
+  }
+  App.db.data.app.tables.filterConditions[name] = filterConditions;
+  localStorage.setObject('ambari', App.db.data);
+};
+
+App.db.setDisplayLength = function(name, displayLength) {
+  console.log('TRACE: Entering db:setDisplayLength function');
+  App.db.data = localStorage.getObject('ambari');
+  if (!App.db.data.app.tables.displayLength) {
+    App.db.data.app.tables.displayLength = {};
+  }
+  App.db.data.app.tables.displayLength[name] = displayLength;
+  localStorage.setObject('ambari', App.db.data);
+};
+
+App.db.setStartIndex = function(name, startIndex) {
+  console.log('TRACE: Entering db:setStartIndex function');
+  App.db.data = localStorage.getObject('ambari');
+  if (!App.db.data.app.tables.startIndex) {
+    App.db.data.app.tables.startIndex = {};
+  }
+  App.db.data.app.tables.startIndex[name] = startIndex;
+  localStorage.setObject('ambari', App.db.data);
+};
+
+App.db.setSortingStatuses = function(name, sortingConditions) {
+  console.log('TRACE: Entering db:setSortingConditions function');
+  App.db.data = localStorage.getObject('ambari');
+  if (!App.db.data.app.tables.sortingConditions) {
+    App.db.data.app.tables.sortingConditions = {};
+  }
+  App.db.data.app.tables.sortingConditions[name] = sortingConditions;
+  localStorage.setObject('ambari', App.db.data);
+};
+
 App.db.setAllHostNames = function (hostNames) {
   console.log('TRACE: Entering db:setAllHostNames function');
   App.db.data = localStorage.getObject('ambari');
@@ -297,6 +343,42 @@ App.db.getAmbariStacks = function () {
   return App.db.data.app.stacks;
 };
 
+App.db.getFilterConditions = function(name) {
+  console.log('TRACE: Entering db:getFilterConditions function');
+  App.db.data = localStorage.getObject('ambari');
+  if (App.db.data.app.tables.filterConditions[name]) {
+    return App.db.data.app.tables.filterConditions[name];
+  }
+  return null;
+};
+
+App.db.getDisplayLength = function(name) {
+  console.log('TRACE: Entering db:getDisplayLength function');
+  App.db.data = localStorage.getObject('ambari');
+  if (App.db.data.app.tables.displayLength[name]) {
+    return App.db.data.app.tables.displayLength[name];
+  }
+  return null;
+};
+
+App.db.getStartIndex = function(name) {
+  console.log('TRACE: Entering db:getStartIndex function');
+  App.db.data = localStorage.getObject('ambari');
+  if (App.db.data.app.tables.startIndex[name]) {
+    return App.db.data.app.tables.startIndex[name];
+  }
+  return null;
+};
+
+App.db.getSortingStatuses = function(name) {
+  console.log('TRACE: Entering db:getSortingConditions function');
+  App.db.data = localStorage.getObject('ambari');
+  if (App.db.data.app.tables.sortingConditions[name]) {
+    return App.db.data.app.tables.sortingConditions[name];
+  }
+  return null;
+};
+
 /**
  * Return current step for specified Wizard Type
  * @param wizardType

+ 1 - 1
ambari-web/app/views/common/configs/services_config.js

@@ -189,7 +189,7 @@ App.ServiceConfigsByCategoryView = Ember.View.extend({
         var name = this.get('name');
         if(name.trim() != ""){
           if(validator.isValidConfigKey(name)){
-            var configMappingProperty = App.config.configMapping.all().findProperty('name', name);
+            var configMappingProperty = App.config.get('configMapping').all().findProperty('name', name);
             if((configMappingProperty == null) && (!serviceConfigNames.contains(name))){
               this.set("isKeyError", false);
               this.set("errorMessage", "");

+ 5 - 0
ambari-web/app/views/common/filter_view.js

@@ -32,6 +32,11 @@ var wrapperView = Ember.View.extend({
 
   value: null,
 
+  /**
+   * Column index
+   */
+  column: null,
+
   /**
    * If this field is exists we dynamically create hidden input element and set value there.
    * Used for some cases, where this values will be used outside of component

+ 8 - 3
ambari-web/app/views/common/quick_view_link_view.js

@@ -29,13 +29,18 @@ App.QuickViewLinks = Em.View.extend({
     var host;
 
     if (serviceName === 'HDFS') {
-      host = components.findProperty('componentName', 'NAMENODE').get('host.publicHostName');
+      host = App.singleNodeInstall ? App.singleNodeAlias : components.findProperty('componentName', 'NAMENODE').get('host.publicHostName');
     } else if (serviceName === 'MAPREDUCE') {
-      host = components.findProperty('componentName', 'JOBTRACKER').get('host.publicHostName');
+      host = App.singleNodeInstall ? App.singleNodeAlias : components.findProperty('componentName', 'JOBTRACKER').get('host.publicHostName');
     } else if (serviceName === 'HBASE') {
       var component = components.filterProperty('componentName', 'HBASE_MASTER').findProperty('haStatus', 'active');
       if(component){
-        host = component.get('host.publicHostName');
+        if(App.singleNodeInstall){
+          host = App.singleNodeAlias;
+        }else{
+          host = component.get('host.publicHostName');
+        }
+
       }
     }
     if (!host) {

+ 48 - 1
ambari-web/app/views/common/sort_view.js

@@ -17,6 +17,7 @@
  */
 
 var misc = require('utils/misc');
+var App = require('app');
 
 /**
  * Wrapper View for all sort components. Layout template and common actions are located inside of it.
@@ -27,6 +28,51 @@ var misc = require('utils/misc');
  */
 var wrapperView = Em.View.extend({
   tagName: 'tr',
+
+  /**
+   * Load sort statuses from local storage
+   * Works only after finish filtering in the parent View
+   */
+  loadSortStatuses: function() {
+    var statuses = App.db.getSortingStatuses(this.get('controller.name'));
+    if (!this.get('parentView.filteringComplete')) return;
+    if (statuses) {
+      var childViews = this.get('childViews');
+      var self = this;
+      statuses.forEach(function(st) {
+        if (st.status != 'sorting') {
+          var sortOrder = false;
+          if(st.status == 'sorting_desc') {
+            sortOrder = true;
+          }
+          self.sort(childViews.findProperty('name', st.name), sortOrder);
+
+          childViews.findProperty('name', st.name).set('status', (sortOrder)?'sorting_desc':'sorting_asc');
+        }
+        else {
+          childViews.findProperty('name', st.name).set('status', st.status);
+        }
+      });
+      this.get('parentView').showProperPage();
+    }
+  }.observes('parentView.filteringComplete'),
+
+  /**
+   * Save sort statuses to local storage
+   * Works only after finish filtering in the parent View
+   */
+  saveSortStatuses: function() {
+    if (!this.get('parentView.filteringComplete')) return;
+    var statuses = [];
+    this.get('childViews').forEach(function(childView) {
+      statuses.push({
+        name: childView.get('name'),
+        status: childView.get('status')
+      });
+    });
+    App.db.setSortingStatuses(this.get('controller.name'), statuses);
+  }.observes('childViews.@each.status'),
+
   /**
    * sort content by property
    * @param property
@@ -119,7 +165,8 @@ var fieldView = Em.View.extend({
     if(this.get('status') === 'sorting_desc'){
       this.get('parentView').sort(this, false);
       this.set('status', 'sorting_asc');
-    } else {
+    }
+    else {
       this.get('parentView').sort(this, true);
       this.set('status', 'sorting_desc');
     }

+ 105 - 12
ambari-web/app/views/common/table_view.js

@@ -22,13 +22,74 @@ var sort = require('views/common/sort_view');
 
 App.TableView = Em.View.extend({
 
-  didInsertElement: function () {
-    this.set('filterConditions', []);
-    this.filter();
+  /**
+   * Shows if all data is loaded and filtered
+   */
+  filteringComplete: false,
+
+  /**
+   * Loaded from local storage startIndex value
+   */
+  startIndexOnLoad: null,
+  /**
+   * Loaded from local storage displayLength value
+   */
+  displayLengthOnLoad: null,
+
+  /**
+   * Do filtering, using saved in the local storage filter conditions
+   */
+  willInsertElement:function () {
+    var self = this;
+    var name = this.get('controller.name');
+
+    this.set('startIndexOnLoad', App.db.getStartIndex(name));
+    this.set('displayLengthOnLoad', App.db.getDisplayLength(name));
+
+    var filterConditions = App.db.getFilterConditions(name);
+    if (filterConditions) {
+      this.set('filterConditions', filterConditions);
+
+      var childViews = this.get('childViews');
+
+      filterConditions.forEach(function(condition) {
+        var view = childViews.findProperty('column', condition.iColumn);
+        if (view) {
+          view.set('value', condition.value);
+          Em.run.next(function() {
+            view.showClearFilter();
+          });
+        }
+      });
+    }
+
+    Em.run.next(function() {
+      Em.run.next(function() {
+        self.set('filteringComplete', true);
+      });
+    });
   },
 
   /**
-   * return pagination information displayed on the mirroring page
+   * Do pagination after filtering and sorting
+   * Don't call this method! It's already used where it's need
+   */
+  showProperPage: function() {
+    var self = this;
+    Em.run.next(function() {
+      Em.run.next(function() {
+        if (self.get('displayLengthOnLoad')) {
+          self.set('displayLength', self.get('displayLengthOnLoad'));
+        }
+        if(self.get('startIndexOnLoad')) {
+          self.set('startIndex', self.get('startIndexOnLoad'));
+        }
+      });
+    });
+  },
+
+  /**
+   * return pagination information displayed on the page
    */
   paginationInfo: function () {
     return this.t('apps.filters.paginationInfo').format(this.get('startIndex'), this.get('endIndex'), this.get('filteredContent.length'));
@@ -70,16 +131,16 @@ App.TableView = Em.View.extend({
     content: ['10', '25', '50']
   }),
 
-  // start index for displayed content on the mirroring page
+  // start index for displayed content on the page
   startIndex: 1,
 
-  // calculate end index for displayed content on the mirroring page
+  // calculate end index for displayed content on the page
   endIndex: function () {
     return Math.min(this.get('filteredContent.length'), this.get('startIndex') + parseInt(this.get('displayLength')) - 1);
   }.property('startIndex', 'displayLength', 'filteredContent.length'),
 
   /**
-   * onclick handler for previous page button on the mirroring page
+   * onclick handler for previous page button on the page
    */
   previousPage: function () {
     var result = this.get('startIndex') - parseInt(this.get('displayLength'));
@@ -90,7 +151,7 @@ App.TableView = Em.View.extend({
   },
 
   /**
-   * onclick handler for next page button on the mirroring page
+   * onclick handler for next page button on the page
    */
   nextPage: function () {
     var result = this.get('startIndex') + parseInt(this.get('displayLength'));
@@ -99,7 +160,7 @@ App.TableView = Em.View.extend({
     }
   },
 
-  // the number of mirroring to show on every page of the mirroring page view
+  // the number of rows to show on every page
   displayLength: null,
 
   // calculates default value for startIndex property after applying filter or changing displayLength
@@ -112,22 +173,54 @@ App.TableView = Em.View.extend({
    *
    * @param iColumn number of column by which filter
    * @param value
+   * @param type
    */
   updateFilter: function (iColumn, value, type) {
     var filterCondition = this.get('filterConditions').findProperty('iColumn', iColumn);
     if (filterCondition) {
       filterCondition.value = value;
-    } else {
+    }
+    else {
       filterCondition = {
         iColumn: iColumn,
         value: value,
         type: type
-      }
+      };
       this.get('filterConditions').push(filterCondition);
     }
+    this.saveFilterConditions();
     this.filter();
   },
 
+  saveFilterConditions: function() {
+    App.db.setFilterConditions(this.get('controller.name'), this.get('filterConditions'));
+  },
+
+  saveDisplayLength: function() {
+    var self = this;
+    Em.run.next(function() {
+      App.db.setDisplayLength(self.get('controller.name'), self.get('displayLength'));
+    });
+  }.observes('displayLength'),
+
+  saveStartIndex: function() {
+    if (this.get('filteringComplete')) {
+      App.db.setStartIndex(this.get('controller.name'), this.get('startIndex'));
+    }
+  }.observes('startIndex'),
+
+  clearFilterCondition: function() {
+    App.db.setFilterConditions(this.get('controller.name'), null);
+  },
+
+  clearDisplayLength: function() {
+    App.db.setDisplayLength(this.get('controller.name'), null);
+  },
+
+  clearStartIndex: function() {
+    App.db.setStartIndex(this.get('controller.name'), null);
+  },
+
   /**
    * contain filter conditions for each column
    */
@@ -135,7 +228,7 @@ App.TableView = Em.View.extend({
 
   filteredContent: [],
 
-  // contain content to show on the current page of mirroring page view
+  // contain content to show on the current page of data page view
   pageContent: function () {
     return this.get('filteredContent').slice(this.get('startIndex') - 1, this.get('endIndex'));
   }.property('filteredContent.length', 'startIndex', 'endIndex'),

+ 1 - 1
ambari-web/app/views/main/dashboard/service/hbase.js

@@ -80,7 +80,7 @@ App.MainDashboardServiceHbaseView = App.MainDashboardServiceView.extend({
 
   hbaseMasterWebUrl: function () {
     if (this.get('activeMaster.host') && this.get('activeMaster.host').get('publicHostName')) {
-      return "http://" + this.get('activeMaster.host').get('publicHostName') + ":60010";
+      return "http://" + (App.singleNodeInstall ? App.singleNodeAlias : this.get('activeMaster.host').get('publicHostName')) + ":60010";
     }
   }.property('activeMaster'),
 

+ 1 - 1
ambari-web/app/views/main/dashboard/service/hdfs.js

@@ -70,7 +70,7 @@ App.MainDashboardServiceHdfsView = App.MainDashboardServiceView.extend({
   }.property("service.nameNodeStartTime"),
 
   nodeWebUrl: function () {
-    return "http://" + this.get('service').get('nameNode').get('publicHostName') + ":50070";
+    return "http://" + (App.singleNodeInstall ? App.singleNodeAlias :  this.get('service').get('nameNode').get('publicHostName')) + ":50070";
   }.property('service.nameNode'),
 
   nodeHeap: function () {

+ 1 - 1
ambari-web/app/views/main/dashboard/service/mapreduce.js

@@ -22,7 +22,7 @@ App.MainDashboardServiceMapreduceView = App.MainDashboardServiceView.extend({
   templateName: require('templates/main/dashboard/service/mapreduce'),
   serviceName: 'MAPREDUCE',
   jobTrackerWebUrl: function () {
-    return "http://" + this.get('service').get('jobTracker').get('publicHostName') + ":50030";
+    return "http://" + (App.singleNodeInstall ? App.singleNodeAlias : this.get('service').get('jobTracker').get('publicHostName')) + ":50030";
   }.property('service.nameNode'),
 
   Chart: App.ChartLinearView.extend({

+ 1 - 1
ambari-web/app/views/main/dashboard/service/oozie.js

@@ -23,7 +23,7 @@ App.MainDashboardServiceOozieView = App.MainDashboardServiceView.extend({
   templateName: require('templates/main/dashboard/service/oozie'),
 
   webUi: function () {
-    var hostName = this.get('service.hostComponents').findProperty('componentName', 'OOZIE_SERVER').get('host.publicHostName');
+    var hostName = App.singleNodeInstall ? App.singleNodeAlias : this.get('service.hostComponents').findProperty('componentName', 'OOZIE_SERVER').get('host.publicHostName');
     return "http://{0}:11000/oozie".format(hostName);
   }.property('service')
 });

+ 45 - 15
ambari-web/app/views/main/host.js

@@ -27,7 +27,7 @@ App.MainHostView = App.TableView.extend({
     return this.get('controller.content');
   }.property('controller.content.length'),
 
-  didInsertElement:function () {
+  willInsertElement: function() {
     this._super();
   },
 
@@ -60,6 +60,7 @@ App.MainHostView = App.TableView.extend({
     displayName: Em.I18n.t('common.loadAvg'),
     type: 'number'
   }),
+
   HostView:Em.View.extend({
     content:null,
     tagName: 'tr',
@@ -203,8 +204,9 @@ App.MainHostView = App.TableView.extend({
    * Based on <code>filters</code> library
    */
   nameFilterView: filters.createTextView({
+    column: 1,
     onChangeValue: function(){
-      this.get('parentView').updateFilter(1, this.get('value'), 'string');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'string');
     }
   }),
 
@@ -213,8 +215,9 @@ App.MainHostView = App.TableView.extend({
    * Based on <code>filters</code> library
    */
   ipFilterView: filters.createTextView({
+    column: 2,
     onChangeValue: function(){
-      this.get('parentView').updateFilter(2, this.get('value'), 'string');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'string');
     }
   }),
 
@@ -225,8 +228,9 @@ App.MainHostView = App.TableView.extend({
   cpuFilterView: filters.createTextView({
     fieldType: 'input-mini',
     fieldId: 'cpu_filter',
+    column: 3,
     onChangeValue: function(){
-      this.get('parentView').updateFilter(3, this.get('value'), 'number');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'number');
     }
   }),
 
@@ -237,8 +241,9 @@ App.MainHostView = App.TableView.extend({
   loadAvgFilterView: filters.createTextView({
     fieldType: 'input-mini',
     fieldId: 'load_avg_filter',
+    column: 5,
     onChangeValue: function(){
-      this.get('parentView').updateFilter(5, this.get('value'), 'number');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'number');
     }
   }),
 
@@ -249,8 +254,9 @@ App.MainHostView = App.TableView.extend({
   ramFilterView: filters.createTextView({
     fieldType: 'input-mini',
     fieldId: 'ram_filter',
+    column: 4,
     onChangeValue: function(){
-      this.get('parentView').updateFilter(4, this.get('value'), 'ambari-bandwidth');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'ambari-bandwidth');
     }
   }),
 
@@ -259,6 +265,9 @@ App.MainHostView = App.TableView.extend({
    * Based on <code>filters</code> library
    */
   componentsFilterView: filters.createComponentView({
+
+    column: 6,
+
     /**
      * Inner FilterView. Used just to render component. Value bind to <code>mainview.value</code> property
      * Base methods was implemented in <code>filters.componentFieldView</code>
@@ -318,7 +327,7 @@ App.MainHostView = App.TableView.extend({
        */
       applyFilter:function() {
         this._super();
-
+        var self = this;
         var chosenComponents = [];
 
         this.get('masterComponents').filterProperty('checkedForHostFilter', true).forEach(function(item){
@@ -330,21 +339,42 @@ App.MainHostView = App.TableView.extend({
         this.get('clientComponents').filterProperty('checkedForHostFilter', true).forEach(function(item){
           chosenComponents.push(item.get('id'));
         });
-        this.set('value', chosenComponents.toString());
+        Em.run.next(function() {
+          self.set('value', chosenComponents.toString());
+        });
       },
 
-      didInsertElement:function () {
-        if (this.get('controller.comeWithFilter')) {
-          this.applyFilter();
-          this.set('controller.comeWithFilter', false);
-        } else {
-          this.clearFilter();
+      /**
+       * Verify that checked checkboxes are equal to value stored in hidden field (components ids list)
+       */
+      checkComponents: function() {
+        var components = this.get('value').split(',');
+        var self = this;
+        if (components) {
+          components.forEach(function(componentId) {
+            if(!self.tryCheckComponent(self, 'masterComponents', componentId)) {
+              if(!self.tryCheckComponent(self, 'slaveComponents', componentId)) {
+                self.tryCheckComponent(self, 'clientComponents', componentId);
+              }
+            }
+          });
+        }
+      }.observes('value'),
+
+      tryCheckComponent: function(self, category, componentId) {
+        var c = self.get(category).findProperty('id', componentId);
+        if (c) {
+          if (!c.get('checkedForHostFilter')) {
+            c.set('checkedForHostFilter', true);
+            return true;
+          }
         }
+        return false;
       }
 
     }),
     onChangeValue: function(){
-      this.get('parentView').updateFilter(6, this.get('value'), 'multiple');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'multiple');
     }
   }),
 

+ 88 - 50
ambari-web/app/views/main/host/summary.js

@@ -91,14 +91,14 @@ App.MainHostSummaryView = Em.View.extend({
   didInsertElement: function () {
     this.loadDecommissionNodesList();
   },
-  sortedComponents: function() {
+  sortedComponents: function () {
     var slaveComponents = [];
     var masterComponents = [];
-    this.get('content.hostComponents').forEach(function(component){
-      if(component.get('workStatus') != 'INSTALLING'){
-        if(component.get('isMaster')){
+    this.get('content.hostComponents').forEach(function (component) {
+      if (component.get('workStatus') != 'INSTALLING') {
+        if (component.get('isMaster')) {
           masterComponents.push(component);
-        } else if(component.get('isSlave')) {
+        } else if (component.get('isSlave')) {
           slaveComponents.push(component);
         }
       }
@@ -106,16 +106,16 @@ App.MainHostSummaryView = Em.View.extend({
     }, this);
     return masterComponents.concat(slaveComponents);
   }.property('content', 'content.hostComponents.length'),
-  clients: function(){
+  clients: function () {
     var clients = [];
-    this.get('content.hostComponents').forEach(function(component){
-      if(!component.get('componentName')){
+    this.get('content.hostComponents').forEach(function (component) {
+      if (!component.get('componentName')) {
         //temporary fix because of different data in hostComponents and serviceComponents
         return;
       }
       if (!component.get('isSlave') && !component.get('isMaster')) {
         if (clients.length) {
-          clients[clients.length-1].set('isLast', false);
+          clients[clients.length - 1].set('isLast', false);
         }
         component.set('isLast', true);
         clients.push(component);
@@ -126,21 +126,21 @@ App.MainHostSummaryView = Em.View.extend({
 
   addableComponentObject: Em.Object.extend({
     componentName: '',
-    displayName: function(){
+    displayName: function () {
       return App.format.role(this.get('componentName'));
     }.property('componentName')
   }),
-  isAddComponent: function(){
+  isAddComponent: function () {
     return this.get('content.healthClass') !== 'health-status-DEAD-YELLOW';
   }.property('content.healthClass'),
-  addableComponents:function(){
+  addableComponents: function () {
     var components = [];
     var services = App.Service.find();
     var dataNodeExists = false;
     var taskTrackerExists = false;
     var regionServerExists = false;
 
-    this.get('content.hostComponents').forEach(function(component) {
+    this.get('content.hostComponents').forEach(function (component) {
       switch (component.get('componentName')) {
         case 'DATANODE':
           dataNodeExists = true;
@@ -173,74 +173,96 @@ App.MainHostSummaryView = Em.View.extend({
         this.doBlinking();
       }
     },
-    hostComponent: function(){
+    hostComponent: function () {
       var hostComponent = null;
       var serviceComponent = this.get('content');
       var host = App.router.get('mainHostDetailsController.content');
-      if(host){
+      if (host) {
         hostComponent = host.get('hostComponents').findProperty('componentName', serviceComponent.get('componentName'));
       }
       return hostComponent;
     }.property('content', 'App.router.mainHostDetailsController.content'),
-    workStatus: function(){
+    workStatus: function () {
       var workStatus = this.get('content.workStatus');
       var hostComponent = this.get('hostComponent');
-      if(hostComponent){
+      if (hostComponent) {
         workStatus = hostComponent.get('workStatus');
       }
       return workStatus;
-    }.property('content.workStatus','hostComponent.workStatus'),
-    statusClass: function(){
+    }.property('content.workStatus', 'hostComponent.workStatus'),
+
+    /**
+     * Return host component text status
+     */
+    componentTextStatus: function () {
+      var workStatus = this.get("workStatus");
+      var componentTextStatus = this.get('content.componentTextStatus');
+      var hostComponent = this.get('hostComponent');
+      if (hostComponent) {
+        componentTextStatus = hostComponent.get('componentTextStatus');
+        if(this.get("isDataNode"))
+          if(this.get('isDataNodeRecommissionAvailable')){
+            if(App.HostComponentStatus.started == workStatus){
+              componentTextStatus = "Decommissioning...";
+            }else if(App.HostComponentStatus.stopped == workStatus){
+              componentTextStatus = "Decommissioned";
+            }
+          }
+      }
+      return componentTextStatus;
+    }.property('workStatus','isDataNodeRecommissionAvailable'),
+
+    statusClass: function () {
       var statusClass = null;
-      if(this.get('isDataNode')){
-        if(this.get('isDataNodeRecommissionAvailable') && this.get('isStart')){
-          // Orange is shown only when service is started/starting and it is decommissioned.
+
+      //If the component is DataNode
+      if (this.get('isDataNode')) {
+        if (this.get('isDataNodeRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) {
           return 'health-status-DEAD-ORANGE';
         }
       }
-      if(this.get('workStatus') === App.HostComponentStatus.install_failed){
-        return 'icon-remove';
+
+      //Class when install failed
+      if (this.get('workStatus') === App.HostComponentStatus.install_failed) {
+        return 'health-status-color-red icon-cog';
       }
+
+      //Class when installing
+      if (this.get('workStatus') === App.HostComponentStatus.installing) {
+        return 'health-status-color-blue icon-cog';
+      }
+
+      //For all other cases
       return 'health-status-' + App.HostComponentStatus.getKeyName(this.get('workStatus'));
-    }.property('workStatus', 'isDataNodeRecommissionAvailable'),
+    }.property('workStatus', 'isDataNodeRecommissionAvailable', 'this.content.isDecommissioning'),
     /**
      * For Upgrade failed state
      */
-    isUpgradeFailed:function(){
+    isUpgradeFailed: function () {
       return App.HostComponentStatus.getKeyName(this.get('workStatus')) === "upgrade_failed";
     }.property("workStatus"),
     /**
      * For Install failed state
      */
-    isInstallFailed:function(){
+    isInstallFailed: function () {
       return App.HostComponentStatus.getKeyName(this.get('workStatus')) === "install_failed";
     }.property("workStatus"),
-    /**
-     * Disable element while component is starting/stopping
-     */
-    disabledClass:function(){
-      var workStatus = this.get('workStatus');
-      if([App.HostComponentStatus.starting, App.HostComponentStatus.stopping, App.HostComponentStatus.unknown].contains(workStatus) ){
-        return 'disabled';
-      } else {
-        return '';
-      }
-    }.property('workStatus'),
     /**
      * Do blinking for 1 minute
      */
-    doBlinking : function(){
+    doBlinking: function () {
       var workStatus = this.get('workStatus');
       var self = this;
       var pulsate = [ App.HostComponentStatus.starting, App.HostComponentStatus.stopping ].contains(workStatus);
       if (!pulsate && this.get('isDataNode')) {
         var dataNodeComponent = this.get('content');
-        if (dataNodeComponent)
-          pulsate = dataNodeComponent.get('isDecommissioning');
+        if (dataNodeComponent && workStatus != "INSTALLED") {
+          pulsate = this.get('isDataNodeRecommissionAvailable');
+        }
       }
       if (pulsate && !self.get('isBlinking')) {
         self.set('isBlinking', true);
-        uiEffects.pulsate(self.$('.components-health'), 1000, function(){
+        uiEffects.pulsate(self.$('.components-health'), 1000, function () {
           !self.get('isDestroyed') && self.set('isBlinking', false);
           self.doBlinking();
         });
@@ -249,26 +271,42 @@ App.MainHostSummaryView = Em.View.extend({
     /**
      * Start blinking when host component is starting/stopping
      */
-    startBlinking:function(){
+    startBlinking: function () {
       this.$('.components-health').stop(true, true);
       this.$('.components-health').css({opacity: 1.0});
       this.doBlinking();
-    }.observes('workStatus'),
+    }.observes('workStatus','isDataNodeRecommissionAvailable'),
 
-    isStart : function() {
-      return (this.get('workStatus') === App.HostComponentStatus.started || this.get('workStatus') === App.HostComponentStatus.starting);
+    isStart: function () {
+      return (this.get('workStatus') == App.HostComponentStatus.started || this.get('workStatus') == App.HostComponentStatus.starting);
     }.property('workStatus'),
 
-    isInProgress : function() {
-      return (this.get('workStatus') === App.HostComponentStatus.stopping || this.get('workStatus') === App.HostComponentStatus.starting);
+    /**
+     * No action available while component is starting/stopping/unknown
+     */
+    noActionAvailable: function () {
+      var workStatus = this.get('workStatus');
+      if ([App.HostComponentStatus.starting, App.HostComponentStatus.stopping, App.HostComponentStatus.unknown].contains(workStatus)) {
+        return "hidden";
+      }else{
+        return "";
+      }
     }.property('workStatus'),
+
+    isInProgress: function () {
+      return (this.get('workStatus') === App.HostComponentStatus.stopping || this.get('workStatus') === App.HostComponentStatus.starting) || this.get('isDataNodeRecommissionAvailable');
+    }.property('workStatus', 'isDataNodeRecommissionAvailable'),
     /**
      * Shows whether we need to show Decommision/Recomission buttons
      */
-    isDataNode: function() {
+    isDataNode: function () {
       return this.get('content.componentName') === 'DATANODE';
     }.property('content'),
 
+    isDecommissioning: function () {
+      return this.get('isDataNode') &&  this.get("isDataNodeRecommissionAvailable");
+    }.property("workStatus", "isDataNodeRecommissionAvailable"),
+
     /**
      * Set in template via binding from parent view
      */
@@ -287,7 +325,7 @@ App.MainHostSummaryView = Em.View.extend({
     isDataNodeRecommissionAvailable: function () {
       var decommissionHostNames = this.get('decommissionDataNodeHostNames');
       var hostName = App.router.get('mainHostDetailsController.content.hostName');
-      return decommissionHostNames!=null && decommissionHostNames.contains(hostName);
+      return decommissionHostNames != null && decommissionHostNames.contains(hostName);
     }.property('App.router.mainHostDetailsController.content', 'decommissionDataNodeHostNames')
 
   }),

+ 12 - 6
ambari-web/app/views/main/mirroring/datasets_view.js

@@ -83,45 +83,51 @@ App.MainDatasetsView = App.TableView.extend({
    */
   nameFilterView: filters.createTextView({
     fieldType: 'input-small',
+    column: 1,
     onChangeValue: function () {
-      this.get('parentView').updateFilter(1, this.get('value'), 'string');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'string');
     }
   }),
 
   datasetSourceFilterView: filters.createTextView({
     fieldType: 'input-small',
+    column: 2,
     onChangeValue: function () {
-      this.get('parentView').updateFilter(2, this.get('value'), 'string');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'string');
     }
   }),
 
   lastSuccessFilterView: filters.createSelectView({
     fieldType: 'input-medium',
+    column: 3,
     content: ['Any', 'Past 1 Day', 'Past 2 Days', 'Past 7 Days', 'Past 14 Days', 'Past 30 Days'],
     onChangeValue: function () {
-      this.get('parentView').updateFilter(3, this.get('value'), 'date');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'date');
     }
   }),
 
   lastFailFilterView: filters.createSelectView({
     fieldType: 'input-medium',
+    column: 4,
     content: ['Any', 'Past 1 Day', 'Past 2 Days', 'Past 7 Days', 'Past 14 Days', 'Past 30 Days'],
     onChangeValue: function () {
-      this.get('parentView').updateFilter(4, this.get('value'), 'date');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'date');
     }
   }),
 
   lastDurationFilterView: filters.createTextView({
     fieldType: 'input-small',
+    column: 5,
     onChangeValue: function () {
-      this.get('parentView').updateFilter(5, this.get('value'), 'duration');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'duration');
     }
   }),
 
   avgDataFilterView: filters.createTextView({
     fieldType: 'input-small',
+    column: 6,
     onChangeValue: function () {
-      this.get('parentView').updateFilter(6, this.get('value'), 'ambari-bandwidth');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'ambari-bandwidth');
     }
   }),
 

+ 10 - 5
ambari-web/app/views/main/mirroring/jobs_view.js

@@ -67,38 +67,43 @@ App.MainJobsView = App.TableView.extend({
    */
   idFilterView: filters.createTextView({
     fieldType: 'input-small',
+    column: 1,
     onChangeValue: function () {
-      this.get('parentView').updateFilter(1, this.get('value'), 'number');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'number');
     }
   }),
 
   startFilterView: filters.createSelectView({
     fieldType: 'input-small',
+    column: 2,
     content: ['Any', 'Past 1 Day', 'Past 2 Days', 'Past 7 Days', 'Past 14 Days', 'Past 30 Days'],
     onChangeValue: function () {
-      this.get('parentView').updateFilter(2, this.get('value'), 'date');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'date');
     }
   }),
 
   endFilterView: filters.createSelectView({
     fieldType: 'input-medium',
+    column: 3,
     content: ['Any', 'Past 1 Day', 'Past 2 Days', 'Past 7 Days', 'Past 14 Days', 'Past 30 Days'],
     onChangeValue: function () {
-      this.get('parentView').updateFilter(3, this.get('value'), 'date');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'date');
     }
   }),
 
   durationFilterView: filters.createTextView({
     fieldType: 'input-medium',
+    column: 4,
     onChangeValue: function () {
-      this.get('parentView').updateFilter(4, this.get('value'), 'duration');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'duration');
     }
   }),
 
   dataFilterView: filters.createTextView({
     fieldType: 'input-small',
+    column: 5,
     onChangeValue: function () {
-      this.get('parentView').updateFilter(5, this.get('value'), 'ambari-bandwidth');
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'ambari-bandwidth');
     }
   }),
 

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

@@ -174,7 +174,7 @@ App.MainServiceInfoSummaryView = Em.View.extend({
   getServer: function(serviceName) {
     var service=this.get('controller.content');
     if(service.get("id") == serviceName) {
-      return service.get("hostComponents").findProperty('isMaster', true).get("host").get("publicHostName");
+      return (App.singleNodeInstall ? App.singleNodeAlias : service.get("hostComponents").findProperty('isMaster', true).get("host").get("publicHostName"));
     }
     else {
       return '';

+ 0 - 1
pom.xml

@@ -51,7 +51,6 @@
     <module>ambari-project</module>
     <module>ambari-server</module>
     <module>ambari-agent</module>
-    <module>ambari-client</module>
   </modules>
   <build>
     <pluginManagement>

部分文件因文件數量過多而無法顯示