Browse Source

AMBARI-3694. Add unit tests to the ambari-client methods, which are not tested (Eugene Chekanskiy via dlysnichenko)

Lisnichenko Dmitro 11 years ago
parent
commit
5793ae2eb6

+ 1 - 1
ambari-client/src/main/python/ambari_client/model/paths.py

@@ -33,7 +33,7 @@ SERVICE_COMPONENT_PATH = "/clusters/%s/services/%s/components/%s"
 HOST_PATH = "/hosts/%s"
 HOSTS_PATH = "/hosts"
 HOSTS_CREATE_PATH = "/clusters/%s/hosts"
-HOSTS_COMPONENTS_PATH = "/clusters/%s/hosts/%s/host_components?ServiceComponentInfo"
+HOSTS_COMPONENTS_PATH = "/clusters/%s/hosts/%s/host_components?fields=HostRoles/state"
 HOSTS_COMPONENT_PATH = "/clusters/%s/hosts/%s/host_components/%s" 
 HOSTS_ASSIGN_ROLE = "/clusters/%s/hosts?Hosts/host_name=%s"
 

+ 6 - 1
ambari-client/src/main/python/ambari_client/model/service.py

@@ -152,7 +152,12 @@ class ServiceModel(BaseModel):
   def _action(self, data=None):
     path = self._path() 
     resp = self._get_resource_root().put(path, payload=data)
-    return utils.ModelUtils.create_model(status.StatusModel, resp, self._get_resource_root(), "NO_KEY")
+    status_model = utils.ModelUtils.create_model(status.StatusModel, resp, self._get_resource_root(), "NO_KEY")
+    if status_model._get_id() is not None:
+      status_model.request_path = paths.REQUEST_PATH % (self._get_cluster_name(), status_model._get_id())
+    else:
+      status_model.request_path = None
+    return status_model
 
   def start(self):
     """

+ 3 - 3
ambari-client/src/main/python/ambari_client/model/status.py

@@ -38,17 +38,17 @@ class StatusModel(BaseModel):
     return "<<StatusModel>> status = %s ; requestId = %s ;message = %s" % (self.status, self._get_id() , self.get_message())
 
   def get_bootstrap_path(self):
-    return paths.BOOTSTRAP_PATH + '/' + self.requestId
+    return paths.BOOTSTRAP_PATH + '/' + str(self.requestId)
 
   def get_request_path(self):
-    return paths.REQUEST_PATH % (self._get_id())
+    return self.request_path
 
   def get_message(self):
     if hasattr(self, 'message'):
         return self.message
     else:
         None
-    
+
   def is_error(self):
     return (self.status != 200 and self.status != 201 and self.status != 202)  
         

File diff suppressed because it is too large
+ 42 - 0
ambari-client/src/test/python/TestComponentModel.py


+ 76 - 0
ambari-client/src/test/python/TestHostModel.py

@@ -0,0 +1,76 @@
+#!/usr/bin/env python2.6
+
+'''
+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.
+'''
+
+
+from mock.mock import MagicMock, patch
+from HttpClientInvoker import HttpClientInvoker
+
+from ambari_client.ambari_api import  AmbariClient
+
+import unittest
+
+class TestHostModel(unittest.TestCase):
+
+  def create_host(self, http_client_mock = MagicMock()):
+    http_client_mock.invoke.side_effect = HttpClientInvoker.http_client_invoke_side_effects
+    client = AmbariClient("localhost", 8080, "admin", "admin", version=1, client=http_client_mock)
+    cluster = client.get_cluster('test1')
+    host = cluster.get_host('myhost')
+    return host
+
+  def test_get_host_components(self):
+    http_client_mock = MagicMock()
+
+    expected_path = '//clusters/test1/hosts/myhost/host_components?fields=HostRoles/state'
+
+    host = self.create_host(http_client_mock)
+    host_components = host.get_host_components()
+
+    self.assertEqual(host_components[0].component_name,"DATANODE")
+    self.assertEqual(host_components[0].state,"STARTED")
+    self.assertEqual(host_components[3].component_name,"HBASE_MASTER")
+    self.assertEqual(host_components[3].state,"STARTED")
+    http_client_mock.invoke.assert_called_with('GET', expected_path, headers=None, payload=None)
+
+  def test_get_host_component(self):
+    http_client_mock = MagicMock()
+
+    expected_path = '//clusters/test1/hosts/myhost/host_components/DATANODE'
+
+    host =  self.create_host(http_client_mock)
+    component = host.get_host_component("DATANODE")
+
+    self.assertEqual(component.component_name,"DATANODE")
+    self.assertEqual(component.state,"STARTED")
+    self.assertEqual(component.host_name,"myhost")
+
+    http_client_mock.invoke.assert_called_with('GET', expected_path, headers=None, payload=None)
+
+  def test_assign_role(self):
+    http_client_mock = MagicMock()
+
+    expected_path = '//clusters/test1/hosts?Hosts/host_name=myhost'
+    expected_payload = {'host_components': [{'HostRoles': {'component_name': 'GANGLIA_SERVER'}}]}
+
+    host =  self.create_host(http_client_mock)
+    status = host.assign_role("GANGLIA_SERVER")
+
+    self.assertTrue(status.status, 201)
+    http_client_mock.invoke.assert_called_with('POST', expected_path, headers=None, payload=expected_payload)

+ 101 - 0
ambari-client/src/test/python/TestServiceModel.py

@@ -0,0 +1,101 @@
+#!/usr/bin/env python2.6
+
+'''
+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.
+'''
+
+
+from mock.mock import MagicMock, patch
+from HttpClientInvoker import HttpClientInvoker
+
+from ambari_client.ambari_api import  AmbariClient
+
+import unittest
+
+class TestServiceModel(unittest.TestCase):
+
+  def create_service(self, http_client_mock = MagicMock()):
+    http_client_mock.invoke.side_effect = HttpClientInvoker.http_client_invoke_side_effects
+    client = AmbariClient("localhost", 8080, "admin", "admin", version=1, client=http_client_mock)
+    cluster = client.get_cluster('test1')
+    service = cluster.get_service('GANGLIA')
+    return service
+
+  def test_start(self):
+    http_client_mock = MagicMock()
+
+    expected_path = '//clusters/test1/services/GANGLIA'
+    expected_payload = {'ServiceInfo': {'state': 'STARTED'}}
+
+    service = self.create_service(http_client_mock)
+    status = service.start()
+
+    self.assertEqual(status.get_request_path(), 'clusters/test1/requests/19')
+    http_client_mock.invoke.assert_called_with('PUT', expected_path, headers=None, payload=expected_payload)
+
+  def test_stop(self):
+    http_client_mock = MagicMock()
+
+    expected_path = '//clusters/test1/services/GANGLIA'
+    expected_payload = {"ServiceInfo": {"state": "INSTALLED"}}
+
+    service = self.create_service(http_client_mock)
+    status = service.stop()
+
+    self.assertEqual(status.get_request_path(), 'clusters/test1/requests/19')
+    http_client_mock.invoke.assert_called_with('PUT', expected_path, headers=None, payload=expected_payload)
+
+  def test_install(self):
+    http_client_mock = MagicMock()
+
+    expected_path = '//clusters/test1/services/GANGLIA'
+    expected_payload = {"ServiceInfo": {"state": "INSTALLED"}}
+
+    service = self.create_service(http_client_mock)
+    status = service.install()
+
+    self.assertEqual(status.get_request_path(), 'clusters/test1/requests/19')
+    http_client_mock.invoke.assert_called_with('PUT', expected_path, headers=None, payload=expected_payload)
+
+  def test_get_service_components(self):
+    http_client_mock = MagicMock()
+
+    expected_path = '//clusters/test1/services/GANGLIA/components?fields=*'
+
+    service = self.create_service(http_client_mock)
+    components = service.get_service_components()
+
+    self.assertEqual(components[0].component_name, "GANGLIA_MONITOR")
+    self.assertEqual(components[0].state, "STARTED")
+    self.assertEqual(components[1].component_name, "GANGLIA_SERVER")
+    self.assertEqual(components[1].state, "INSTALLED")
+
+    http_client_mock.invoke.assert_called_with('GET', expected_path, headers=None, payload=None)
+
+  def test_get_service_component(self):
+    http_client_mock = MagicMock()
+
+    expected_path = '//clusters/test1/services/GANGLIA/components/GANGLIA_SERVER'
+
+    service = self.create_service(http_client_mock)
+    component = service.get_service_component("GANGLIA_SERVER")
+
+    self.assertEqual(component.component_name, "GANGLIA_SERVER")
+    self.assertEqual(component.service_name, "GANGLIA")
+    self.assertEqual(component.state, "STARTED")
+
+    http_client_mock.invoke.assert_called_with('GET', expected_path, headers=None, payload=None)

+ 78 - 0
ambari-client/src/test/python/TestStatusModel.py

@@ -0,0 +1,78 @@
+#!/usr/bin/env python2.6
+
+'''
+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.
+'''
+
+
+from ambari_client.model.status import StatusModel
+from mock.mock import MagicMock, patch
+from HttpClientInvoker import HttpClientInvoker
+
+from ambari_client.ambari_api import AmbariClient
+import unittest
+
+class TestStatusModel(unittest.TestCase):
+
+  def create_service(self, http_client_mock = MagicMock()):
+    http_client_mock.invoke.side_effect = HttpClientInvoker.http_client_invoke_side_effects
+    client = AmbariClient("localhost", 8080, "admin", "admin", version=1, client=http_client_mock)
+    cluster = client.get_cluster('test1')
+    service = cluster.get_service('GANGLIA')
+    return service
+
+  def create_client(self, http_client_mock = MagicMock()):
+    http_client_mock.invoke.side_effect = HttpClientInvoker.http_client_invoke_side_effects
+    client = AmbariClient("localhost", 8080, "admin", "admin", version=1, client=http_client_mock)
+    return client
+
+  def test_get_request_path(self):
+    http_client_mock = MagicMock()
+
+    expected_payload = {'ServiceInfo': {'state': 'INSTALLED'}}
+    expected_path = '//clusters/test1/services/GANGLIA'
+    expected_request_path = 'clusters/test1/requests/19'
+
+    service = self.create_service(http_client_mock)
+    status = service.stop()
+
+    self.assertEqual(status.get_request_path(), expected_request_path)
+    http_client_mock.invoke.assert_called_with('PUT', expected_path, headers=None, payload=expected_payload)
+
+
+  def test_is_error(self):
+    error_model = StatusModel(None, 400)
+    ok_model =  StatusModel(None, 201)
+
+    self.assertTrue(error_model.is_error())
+    self.assertFalse(ok_model.is_error())
+
+  def test_get_bootstrap_path(self):
+    http_client_mock = MagicMock()
+
+    ssh_key = 'abc!@#$%^&*()_:"|<>?[];\'\\./'
+    host_list = ['dev05.hortonworks.com','dev06.hortonworks.com']
+    expected_path = '//bootstrap'
+    expected_payload = {'hosts': ['dev05.hortonworks.com', 'dev06.hortonworks.com'], 'sshKey': 'abc!@#$%^&*()_:"|<>?[];\\\'\\\\./'}
+    expected_headers = {'Content-Type': 'application/json'}
+    expected_bootstrap_path = '/bootstrap/5'
+
+    client = self.create_client(http_client_mock)
+    resp = client.bootstrap_hosts(host_list, ssh_key)
+
+    self.assertEqual(resp.get_bootstrap_path(),expected_bootstrap_path)
+    http_client_mock.invoke.assert_called_with('POST', expected_path, headers=expected_headers, payload=expected_payload)

+ 133 - 0
ambari-client/src/test/python/json/componentmodel_get_metrics.json

@@ -0,0 +1,133 @@
+{
+    "href" : "http://192.168.64.101:8080/api/v1/clusters/cl1/hosts/myhost/host_components/DATANODE?fields=metrics",
+    "HostRoles" : {
+        "cluster_name" : "cl1",
+        "component_name" : "DATANODE",
+        "host_name" : "myhost"
+    },
+    "host" : {
+        "href" : "http://192.168.64.101:8080/api/v1/clusters/cl1/hosts/myhost"
+    },
+    "metrics" : {
+        "boottime" : 1.383131209E9,
+        "cpu" : {
+            "cpu_aidle" : 0.0,
+            "cpu_idle" : 85.73,
+            "cpu_nice" : 0.0,
+            "cpu_num" : 1.0,
+            "cpu_speed" : 2967.0,
+            "cpu_system" : 6.84583333333,
+            "cpu_user" : 7.42888888889,
+            "cpu_wio" : 0.00416666666667
+        },
+        "dfs" : {
+            "FSNamesystem" : {
+                "HttpPort" : null,
+                "NamenodeAddress" : "{\"myhost\":\"BP-442795920-192.168.64.101-1383132565020\"}",
+                "RpcPort" : "8010",
+                "Version" : "2.2.0.2.0.6.0-76",
+                "VolumeInfo" : "{\"/hadoop/hdfs/data/current\":{\"freeSpace\":495195869184,\"usedSpace\":345120768,\"reservedSpace\":1073741824}}"
+            },
+            "datanode" : {
+                "blockChecksumOp_avg_time" : 0.0,
+                "blockChecksumOp_num_ops" : 0.0,
+                "blockReports_avg_time" : 6.0,
+                "blockReports_num_ops" : 0.0,
+                "block_verification_failures" : 0.0,
+                "blocks_get_local_pathinfo" : 0.0,
+                "blocks_read" : 0.0,
+                "blocks_removed" : 0.0,
+                "blocks_replicated" : 0.0,
+                "blocks_verified" : 0.0,
+                "blocks_written" : 0.0,
+                "bytes_read" : 0.0,
+                "bytes_written" : 0.0,
+                "copyBlockOp_avg_time" : 0.0,
+                "copyBlockOp_num_ops" : 0.0,
+                "heartBeats_avg_time" : 1.69166666667,
+                "heartBeats_num_ops" : 0.336481481481,
+                "readBlockOp_avg_time" : 0.0,
+                "readBlockOp_num_ops" : 0.0,
+                "reads_from_local_client" : 0.0,
+                "reads_from_remote_client" : 0.0,
+                "replaceBlockOp_avg_time" : 0.0,
+                "replaceBlockOp_num_ops" : 0.0,
+                "writeBlockOp_avg_time" : 13.8969072165,
+                "writeBlockOp_num_ops" : 0.0,
+                "writes_from_local_client" : 0.0,
+                "writes_from_remote_client" : 0.0
+            }
+        },
+        "disk" : {
+            "disk_free" : 495.645,
+            "disk_total" : 525.79,
+            "part_max_used" : 11.6
+        },
+        "jvm" : {
+            "HeapMemoryMax" : 1037959168,
+            "HeapMemoryUsed" : 11395264,
+            "NonHeapMemoryMax" : 136314880,
+            "NonHeapMemoryUsed" : 30798600,
+            "gcCount" : 0.0111111111111,
+            "gcTimeMillis" : 388,
+            "logError" : 0.0,
+            "logFatal" : 0.0,
+            "logInfo" : 0.0,
+            "logWarn" : 0.0,
+            "memHeapCommittedM" : 28.5625,
+            "memHeapUsedM" : 11.7175731111,
+            "memNonHeapCommittedM" : 29.625,
+            "memNonHeapUsedM" : 29.36007675,
+            "threadsBlocked" : 0.0,
+            "threadsNew" : 0.0,
+            "threadsRunnable" : 8.04166666667,
+            "threadsTerminated" : 0.0,
+            "threadsTimedWaiting" : 8.91666666667,
+            "threadsWaiting" : 18.0
+        },
+        "load" : {
+            "load_fifteen" : 0.0692222222222,
+            "load_five" : 0.0592777777778,
+            "load_one" : 0.0125555555556
+        },
+        "memory" : {
+            "mem_buffers" : 23914.2666667,
+            "mem_cached" : 160191.855556,
+            "mem_free" : 183983.855556,
+            "mem_shared" : 0.0,
+            "mem_total" : 1922680.0,
+            "swap_free" : 2593920.0,
+            "swap_total" : 2621432.0
+        },
+        "network" : {
+            "bytes_in" : 30989.8874167,
+            "bytes_out" : 98799.6742778,
+            "pkts_in" : 44.9822222222,
+            "pkts_out" : 214.358916667
+        },
+        "process" : {
+            "proc_run" : 2.0,
+            "proc_total" : 682.397222222
+        },
+        "rpc" : {
+            "NumOpenConnections" : 0.0,
+            "ReceivedBytes" : 0.0,
+            "RpcProcessingTime_avg_time" : 0.0,
+            "RpcProcessingTime_num_ops" : 0.0,
+            "RpcQueueTime_avg_time" : 0.0,
+            "RpcQueueTime_num_ops" : 0.0,
+            "SentBytes" : 0.0,
+            "callQueueLen" : 0.0,
+            "rpcAuthenticationFailures" : 0.0,
+            "rpcAuthenticationSuccesses" : 0.0,
+            "rpcAuthorizationFailures" : 0.0,
+            "rpcAuthorizationSuccesses" : 0.0
+        },
+        "ugi" : {
+            "loginFailure_avg_time" : 0.0,
+            "loginFailure_num_ops" : 0.0,
+            "loginSuccess_avg_time" : 0.0,
+            "loginSuccess_num_ops" : 0.0
+        }
+    }
+}

+ 181 - 0
ambari-client/src/test/python/json/hostmodel_get_host_component.json

@@ -0,0 +1,181 @@
+{
+    "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/DATANODE",
+    "HostRoles" : {
+        "cluster_name" : "cl1",
+        "component_name" : "DATANODE",
+        "desired_stack_id" : "HDP-2.0.6",
+        "desired_state" : "STARTED",
+        "host_name" : "myhost",
+        "stack_id" : "HDP-2.0.6",
+        "state" : "STARTED",
+        "actual_configs" : {
+            "capacity-scheduler" : {
+                "tag" : "version1"
+            },
+            "core-site" : {
+                "tag" : "version1"
+            },
+            "global" : {
+                "tag" : "version1"
+            },
+            "hbase-site" : {
+                "tag" : "version1"
+            },
+            "hdfs-site" : {
+                "tag" : "version1"
+            },
+            "hive-site" : {
+                "tag" : "version1"
+            },
+            "mapred-site" : {
+                "tag" : "version1"
+            },
+            "oozie-site" : {
+                "tag" : "version1"
+            },
+            "webhcat-site" : {
+                "tag" : "version1"
+            },
+            "yarn-site" : {
+                "tag" : "version1"
+            }
+        },
+        "configs" : { },
+        "desired_configs" : { }
+    },
+    "host" : {
+        "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+    },
+    "metrics" : {
+        "boottime" : 1.383131209E9,
+        "cpu" : {
+            "cpu_aidle" : 0.0,
+            "cpu_idle" : 86.7238888889,
+            "cpu_nice" : 0.0,
+            "cpu_num" : 1.0,
+            "cpu_speed" : 2967.0,
+            "cpu_system" : 6.43527777778,
+            "cpu_user" : 6.81722222222,
+            "cpu_wio" : 0.0263888888889
+        },
+        "dfs" : {
+            "FSNamesystem" : {
+                "HttpPort" : null,
+                "NamenodeAddress" : "{\"myhost\":\"BP-442795920-192.168.64.101-1383132565020\"}",
+                "RpcPort" : "8010",
+                "Version" : "2.2.0.2.0.6.0-76",
+                "VolumeInfo" : "{\"/hadoop/hdfs/data/current\":{\"freeSpace\":495195308032,\"usedSpace\":345120768,\"reservedSpace\":1073741824}}"
+            },
+            "datanode" : {
+                "blockChecksumOp_avg_time" : 0.0,
+                "blockChecksumOp_num_ops" : 0.0,
+                "blockReports_avg_time" : 6.0,
+                "blockReports_num_ops" : 0.0,
+                "block_verification_failures" : 0.0,
+                "blocks_get_local_pathinfo" : 0.0,
+                "blocks_read" : 0.0,
+                "blocks_removed" : 0.0,
+                "blocks_replicated" : 0.0,
+                "blocks_verified" : 0.0,
+                "blocks_written" : 0.0,
+                "bytes_read" : 0.0,
+                "bytes_written" : 0.0,
+                "copyBlockOp_avg_time" : 0.0,
+                "copyBlockOp_num_ops" : 0.0,
+                "heartBeats_avg_time" : 1.29537037037,
+                "heartBeats_num_ops" : 0.330833333333,
+                "readBlockOp_avg_time" : 0.0,
+                "readBlockOp_num_ops" : 0.0,
+                "reads_from_local_client" : 0.0,
+                "reads_from_remote_client" : 0.0,
+                "replaceBlockOp_avg_time" : 0.0,
+                "replaceBlockOp_num_ops" : 0.0,
+                "writeBlockOp_avg_time" : 13.8969072165,
+                "writeBlockOp_num_ops" : 0.0,
+                "writes_from_local_client" : 0.0,
+                "writes_from_remote_client" : 0.0
+            }
+        },
+        "disk" : {
+            "disk_free" : 495.644319444,
+            "disk_total" : 525.79,
+            "part_max_used" : 11.6
+        },
+        "jvm" : {
+            "HeapMemoryMax" : 1037959168,
+            "HeapMemoryUsed" : 15927976,
+            "NonHeapMemoryMax" : 136314880,
+            "NonHeapMemoryUsed" : 30819952,
+            "gcCount" : 0.0127777777778,
+            "gcTimeMillis" : 409,
+            "logError" : 0.0,
+            "logFatal" : 0.0,
+            "logInfo" : 0.0,
+            "logWarn" : 0.0,
+            "memHeapCommittedM" : 28.5625,
+            "memHeapUsedM" : 11.6042887139,
+            "memNonHeapCommittedM" : 29.625,
+            "memNonHeapUsedM" : 29.3762000417,
+            "threadsBlocked" : 0.0,
+            "threadsNew" : 0.0,
+            "threadsRunnable" : 8.0,
+            "threadsTerminated" : 0.0,
+            "threadsTimedWaiting" : 9.0,
+            "threadsWaiting" : 18.0
+        },
+        "load" : {
+            "load_fifteen" : 0.19775,
+            "load_five" : 0.211194444444,
+            "load_one" : 0.156638888889
+        },
+        "memory" : {
+            "mem_buffers" : 25446.6,
+            "mem_cached" : 160915.911111,
+            "mem_free" : 176156.088889,
+            "mem_shared" : 0.0,
+            "mem_total" : 1922680.0,
+            "swap_free" : 2593928.0,
+            "swap_total" : 2621432.0
+        },
+        "network" : {
+            "bytes_in" : 31580.1931111,
+            "bytes_out" : 102086.367833,
+            "pkts_in" : 45.7961111111,
+            "pkts_out" : 216.703472222
+        },
+        "process" : {
+            "proc_run" : 2.21111111111,
+            "proc_total" : 681.766666667
+        },
+        "rpc" : {
+            "NumOpenConnections" : 0.0,
+            "ReceivedBytes" : 0.0,
+            "RpcProcessingTime_avg_time" : 0.0,
+            "RpcProcessingTime_num_ops" : 0.0,
+            "RpcQueueTime_avg_time" : 0.0,
+            "RpcQueueTime_num_ops" : 0.0,
+            "SentBytes" : 0.0,
+            "callQueueLen" : 0.0,
+            "rpcAuthenticationFailures" : 0.0,
+            "rpcAuthenticationSuccesses" : 0.0,
+            "rpcAuthorizationFailures" : 0.0,
+            "rpcAuthorizationSuccesses" : 0.0
+        },
+        "ugi" : {
+            "loginFailure_avg_time" : 0.0,
+            "loginFailure_num_ops" : 0.0,
+            "loginSuccess_avg_time" : 0.0,
+            "loginSuccess_num_ops" : 0.0
+        }
+    },
+    "component" : [
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/services/HDFS/components/DATANODE",
+            "ServiceComponentInfo" : {
+                "cluster_name" : "cl1",
+                "component_name" : "DATANODE",
+                "service_name" : "HDFS"
+            }
+        }
+    ]
+}

+ 222 - 0
ambari-client/src/test/python/json/hostmodel_get_host_components.json

@@ -0,0 +1,222 @@
+{
+    "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components?fields=HostRoles/state",
+    "items" : [
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/DATANODE",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "DATANODE",
+                "host_name" : "myhost",
+                "state" : "STARTED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/GANGLIA_MONITOR",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "GANGLIA_MONITOR",
+                "host_name" : "myhost",
+                "state" : "STARTED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/HBASE_CLIENT",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "HBASE_CLIENT",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/HBASE_MASTER",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "HBASE_MASTER",
+                "ha_status" : "active",
+                "host_name" : "myhost",
+                "state" : "STARTED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/HBASE_REGIONSERVER",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "HBASE_REGIONSERVER",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/HCAT",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "HCAT",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/HDFS_CLIENT",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "HDFS_CLIENT",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/HIVE_CLIENT",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "HIVE_CLIENT",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/MAPREDUCE2_CLIENT",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "MAPREDUCE2_CLIENT",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/NAMENODE",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "NAMENODE",
+                "host_name" : "myhost",
+                "state" : "STARTED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/NODEMANAGER",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "NODEMANAGER",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/OOZIE_CLIENT",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "OOZIE_CLIENT",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/PIG",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "PIG",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/RESOURCEMANAGER",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "RESOURCEMANAGER",
+                "host_name" : "myhost",
+                "state" : "STARTED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/SQOOP",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "SQOOP",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/YARN_CLIENT",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "YARN_CLIENT",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/ZOOKEEPER_CLIENT",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "ZOOKEEPER_CLIENT",
+                "host_name" : "myhost",
+                "state" : "INSTALLED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        },
+        {
+            "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost/host_components/ZOOKEEPER_SERVER",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "ZOOKEEPER_SERVER",
+                "host_name" : "myhost",
+                "state" : "STARTED"
+            },
+            "host" : {
+                "href" : "http://myhost:8080/api/v1/clusters/cl1/hosts/myhost"
+            }
+        }
+    ]
+}

+ 20 - 0
ambari-client/src/test/python/json/servicemodel_get_component.json

@@ -0,0 +1,20 @@
+{
+    "href" : "http://c6401.ambari.apache.org:8080/api/v1/clusters/cl1/services/GANGLIA/components/GANGLIA_SERVER",
+    "ServiceComponentInfo" : {
+        "cluster_name" : "cl1",
+        "component_name" : "GANGLIA_SERVER",
+        "service_name" : "GANGLIA",
+        "state" : "STARTED",
+        "desired_configs" : { }
+    },
+    "host_components" : [
+        {
+            "href" : "http://c6401.ambari.apache.org:8080/api/v1/clusters/cl1/hosts/c6402.ambari.apache.org/host_components/GANGLIA_SERVER",
+            "HostRoles" : {
+                "cluster_name" : "cl1",
+                "component_name" : "GANGLIA_SERVER",
+                "host_name" : "c6402.ambari.apache.org"
+            }
+        }
+    ]
+}

+ 61 - 0
ambari-client/src/test/python/json/servicemodel_get_components.json

@@ -0,0 +1,61 @@
+{
+  "href" : "http://c6401.ambari.apache.org:8080/api/v1/clusters/cl1/services/GANGLIA/components?fields=*",
+  "items" : [
+    {
+      "href" : "http://c6401.ambari.apache.org:8080/api/v1/clusters/cl1/services/GANGLIA/components/GANGLIA_MONITOR",
+      "ServiceComponentInfo" : {
+        "cluster_name" : "cl1",
+        "component_name" : "GANGLIA_MONITOR",
+        "service_name" : "GANGLIA",
+        "state" : "STARTED",
+        "desired_configs" : { }
+      },
+      "host_components" : [
+        {
+          "href" : "http://c6401.ambari.apache.org:8080/api/v1/clusters/cl1/hosts/c6401.ambari.apache.org/host_components/GANGLIA_MONITOR",
+          "HostRoles" : {
+            "cluster_name" : "cl1",
+            "component_name" : "GANGLIA_MONITOR",
+            "host_name" : "c6401.ambari.apache.org"
+          }
+        },
+        {
+          "href" : "http://c6401.ambari.apache.org:8080/api/v1/clusters/cl1/hosts/c6402.ambari.apache.org/host_components/GANGLIA_MONITOR",
+          "HostRoles" : {
+            "cluster_name" : "cl1",
+            "component_name" : "GANGLIA_MONITOR",
+            "host_name" : "c6402.ambari.apache.org"
+          }
+        },
+        {
+          "href" : "http://c6401.ambari.apache.org:8080/api/v1/clusters/cl1/hosts/c6403.ambari.apache.org/host_components/GANGLIA_MONITOR",
+          "HostRoles" : {
+            "cluster_name" : "cl1",
+            "component_name" : "GANGLIA_MONITOR",
+            "host_name" : "c6403.ambari.apache.org"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://c6401.ambari.apache.org:8080/api/v1/clusters/cl1/services/GANGLIA/components/GANGLIA_SERVER",
+      "ServiceComponentInfo" : {
+        "cluster_name" : "cl1",
+        "component_name" : "GANGLIA_SERVER",
+        "service_name" : "GANGLIA",
+        "state" : "INSTALLED",
+        "desired_configs" : { }
+      },
+      "host_components" : [
+        {
+          "href" : "http://c6401.ambari.apache.org:8080/api/v1/clusters/cl1/hosts/c6402.ambari.apache.org/host_components/GANGLIA_SERVER",
+          "HostRoles" : {
+            "cluster_name" : "cl1",
+            "component_name" : "GANGLIA_SERVER",
+            "host_name" : "c6402.ambari.apache.org"
+          }
+        }
+      ]
+    }
+  ]
+}

+ 4 - 0
ambari-client/src/test/python/json/status_error_with_message.json

@@ -0,0 +1,4 @@
+{
+    "status" : 400,
+    "message" : "java.lang.IllegalArgumentException: No enum const class org.apache.ambari.server.state.State.ILLEGAL_STATE"
+}

+ 7 - 0
ambari-client/src/test/python/json/status_ok_with_id.json

@@ -0,0 +1,7 @@
+{
+    "href" : "http://localhost:8080/api/v1/clusters/test1/requests/19",
+    "Requests" : {
+        "id" : 19,
+        "status" : "InProgress"
+    }
+}

+ 41 - 4
ambari-client/src/test/python/utils/HttpClientInvoker.py

@@ -5,7 +5,8 @@ class HttpClientInvoker():
       
       http_method = args[0]
       url = args[1]
-      
+      payload = kwargs.get("payload",None)
+
       mocked_code = 200 
       mocked_content = "text/plain"
       
@@ -32,6 +33,24 @@ class HttpClientInvoker():
         elif url == "//clusters/test1/configurations?type=mapred-site&tag=version1":
           mocked_response = open('json/clustermodel_get_mapred_site_config.json', 'r').read()
           return mocked_response, mocked_code , mocked_content
+        # HostModel mocking
+        elif url == '//clusters/test1/hosts/myhost/host_components/DATANODE':
+          mocked_response = open('json/hostmodel_get_host_component.json', 'r').read()
+          return mocked_response, mocked_code , mocked_content
+        elif url == '//clusters/test1/hosts/myhost/host_components?fields=HostRoles/state':
+          mocked_response = open('json/hostmodel_get_host_components.json', 'r').read()
+          return mocked_response, mocked_code , mocked_content
+        # ComponentModel mocking
+        elif url == "//clusters/cl1/hosts/myhost/host_components/DATANODE?fields=metrics":
+          mocked_response = open('json/componentmodel_get_metrics.json', 'r').read()
+          return mocked_response, mocked_code , mocked_content
+        # ServiceModel mocking
+        elif url == "//clusters/test1/services/GANGLIA/components?fields=*":
+          mocked_response = open('json/servicemodel_get_components.json', 'r').read()
+          return mocked_response, mocked_code , mocked_content
+        elif url == "//clusters/test1/services/GANGLIA/components/GANGLIA_SERVER":
+          mocked_response = open('json/servicemodel_get_component.json', 'r').read()
+          return mocked_response, mocked_code , mocked_content
         # AmbariClient mocking
         elif url == "//clusters":
           mocked_response = open('json/ambariclient_get_all_clusters.json', 'r').read()
@@ -47,7 +66,7 @@ class HttpClientInvoker():
           return mocked_response, mocked_code , mocked_content
         elif url == "//stacks2/HDP/versions/1.3.0/stackServices/HDFS/serviceComponents?fields=*":
           mocked_response = open('json/ambariclient_get_components.json', 'r').read()
-          return mocked_response, mocked_code , mocked_content            
+          return mocked_response, mocked_code , mocked_content
         # others
         elif url == "//clusters/test1/services/GANGLIA":
           mocked_response = open('json/clustermodel_get_service.json', 'r').read()
@@ -87,8 +106,26 @@ class HttpClientInvoker():
         if url == "//bootstrap":
           mocked_response = open('json/ambariclient_bootstrap_hosts.json', 'r').read()
           return mocked_response, mocked_code , mocked_content
+        elif url == '//clusters/test1/hosts?Hosts/host_name=myhost':
+          mocked_code = 201
+          return "", mocked_code , mocked_content
         else: # POST (generally does not require any response)
           return "", mocked_code , mocked_content
-      else: # PUT (generally does not require any response)     
-        return "", mocked_code , mocked_content
+      else: # PUT (generally does not require any response)
+        # ServiceModel mocking
+        if url == "//clusters/test1/services/GANGLIA":
+          payload_stop = {'ServiceInfo': {'state': 'INSTALLED'}}
+          payload_started = {'ServiceInfo': {'state': 'STARTED'}}
+          payload_illegal = {'ServiceInfo': {'state': 'ILLEGAL_STATE'}}
+          if payload_stop == payload:
+            mocked_response = open('json/status_ok_with_id.json', 'r').read()
+            return mocked_response, mocked_code , mocked_content
+          elif payload_started == payload:
+            mocked_response = open('json/status_ok_with_id.json', 'r').read()
+            return mocked_response, mocked_code , mocked_content
+          elif payload_illegal == payload:
+            mocked_response = open('json/status_error_with_message.json', 'r').read()
+            return mocked_response, mocked_code , mocked_content
+        else:
+          return "", mocked_code , mocked_content
         

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