You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ma...@apache.org on 2013/08/23 08:36:30 UTC
git commit: AMBARI-2442. Amabri Client refactoring -1. (Subin M via
mahadev)
Updated Branches:
refs/heads/trunk 81bc7d830 -> 23754e344
AMBARI-2442. Amabri Client refactoring -1. (Subin M via mahadev)
Project: http://git-wip-us.apache.org/repos/asf/incubator-ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ambari/commit/23754e34
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ambari/tree/23754e34
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ambari/diff/23754e34
Branch: refs/heads/trunk
Commit: 23754e344ab034fc53a3f72d40f65acc5a4b37c5
Parents: 81bc7d8
Author: Mahadev Konar <ma...@apache.org>
Authored: Thu Aug 22 23:35:52 2013 -0700
Committer: Mahadev Konar <ma...@apache.org>
Committed: Thu Aug 22 23:35:52 2013 -0700
----------------------------------------------------------------------
.../src/main/python/ambari_client/__init__.py | 0
.../src/main/python/ambari_client/ambari_api.py | 59 ++++++-
.../main/python/ambari_client/core/__init__.py | 0
.../main/python/ambari_client/core/errors.py | 49 ++++++
.../python/ambari_client/core/http_client.py | 162 ++++++++++++++++++
.../python/ambari_client/core/http_utils.py | 52 ++++++
.../python/ambari_client/core/rest_resource.py | 121 ++++++++++++++
.../main/python/ambari_client/http_client.py | 166 -------------------
.../src/main/python/ambari_client/http_utils.py | 56 -------
.../main/python/ambari_client/model/__init__.py | 0
.../python/ambari_client/model/base_model.py | 6 +-
.../main/python/ambari_client/model/cluster.py | 44 ++++-
.../src/main/python/ambari_client/model/host.py | 124 ++++++++++++++
.../main/python/ambari_client/model/paths.py | 10 +-
.../main/python/ambari_client/model/service.py | 26 ++-
.../main/python/ambari_client/model/status.py | 40 +++++
.../main/python/ambari_client/model/utils.py | 4 -
.../python/ambari_client/resources/__init__.py | 0
.../python/ambari_client/resources/clusters.py | 46 ++++-
.../python/ambari_client/resources/hosts.py | 72 ++++++++
.../python/ambari_client/resources/services.py | 5 -
.../main/python/ambari_client/rest_resource.py | 104 ------------
.../src/test/python/TestAmbariClient.py | 8 +-
23 files changed, 777 insertions(+), 377 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/__init__.py b/ambari-client/src/main/python/ambari_client/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/ambari_api.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/ambari_api.py b/ambari-client/src/main/python/ambari_client/ambari_api.py
index 216af87..6cdaf8c 100644
--- a/ambari-client/src/main/python/ambari_client/ambari_api.py
+++ b/ambari-client/src/main/python/ambari_client/ambari_api.py
@@ -14,15 +14,11 @@
# 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.
-'''
-
-
-'''
import logging
-from ambari_client.http_client import HttpClient
-from ambari_client.resources import clusters
-from ambari_client.rest_resource import RestResource
+from ambari_client.core.http_client import HttpClient
+from ambari_client.resources import clusters ,hosts
+from ambari_client.core.rest_resource import RestResource
__docformat__ = "epytext"
@@ -78,6 +74,9 @@ class AmbariClient(RestResource):
"""
return clusters.get_all_clusters(self)
+
+
+
def get_cluster(self, cluster_name):
"""
Get a cluster by cluster_name.
@@ -87,7 +86,51 @@ class AmbariClient(RestResource):
"""
return clusters.get_cluster(self, cluster_name)
-
+
+
+ def get_all_hosts(self):
+ """
+ Get all hosts
+ @return: A list of HostModel objects.
+ """
+ return hosts.get_all_hosts(self)
+
+
+ def get_request_status(self , request_path):
+ """
+ Get request status
+ @return: A StatusModel object.
+ """
+ return "TODO"
+
+
+ def bootstrap_hosts(self , hosts_list ,ssh_key):
+ """
+ Bootstrap hosts.
+ @param hosts list of host_names.
+ @return: A StatusModel object.
+ """
+ return hosts.bootstrap_hosts(self, hosts_list ,ssh_key)
+
+
+ def create_cluster(self, cluster_name, version):
+ """
+ Create a new cluster.
+ @param name Cluster name.
+ @param version HDP version.
+ @return ClusterModel object.
+ """
+ return clusters.create_cluster(self, cluster_name, version)
+
+
+
+ def delete_cluster(self ,cluster_name):
+ """
+ Create a cluster
+ @param root_resource: The root Resource.
+ @param cluster_name: Cluster cluster_name
+ """
+ return clusters.delete_cluster(self, cluster_name)
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/core/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/core/__init__.py b/ambari-client/src/main/python/ambari_client/core/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/core/errors.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/core/errors.py b/ambari-client/src/main/python/ambari_client/core/errors.py
new file mode 100644
index 0000000..7031d52
--- /dev/null
+++ b/ambari-client/src/main/python/ambari_client/core/errors.py
@@ -0,0 +1,49 @@
+#
+# 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.
+
+class ResourceError(Exception):
+
+ def __init__(self, msg=None, code=None, response=None):
+ self.msg = msg or ''
+ self.status_code = code
+ self.response = response
+ Exception.__init__(self)
+
+ def _get_message(self):
+ return self.msg
+
+ def __str__(self):
+ if self.msg:
+ return self.msg
+ try:
+ return self._fmt % self.__dict__
+ except (NameError, ValueError, KeyError), e:
+ return 'exception %s: %s' \
+ % (self.__class__.__name__, str(e))
+
+class ResourceNotFound(ResourceError):
+ """Exception raised when no resource was found.
+ """
+
+class RequestError(Exception):
+ """Exception for incorrect request """
+
+class Unauthorized(ResourceError):
+ """Exception when an authorization is required """
+
+class RequestFailed(ResourceError):
+ """Exception for unexpected HTTP error """
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/core/http_client.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/core/http_client.py b/ambari-client/src/main/python/ambari_client/core/http_client.py
new file mode 100644
index 0000000..5b49be3
--- /dev/null
+++ b/ambari-client/src/main/python/ambari_client/core/http_client.py
@@ -0,0 +1,162 @@
+#
+# 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.
+
+import logging
+import posixpath
+import sys
+import pycurl
+import cStringIO
+import StringIO
+import pdb
+try:
+ import json
+except ImportError:
+ import simplejson as json
+from ambari_client.core.http_utils import uri_encoding
+
+__docformat__ = "epytext"
+
+LOG = logging.getLogger(__name__)
+
+
+class HttpClient(object):
+ """
+ Basic HTTP client for rest APIs.
+ """
+ def __init__(self, host_url, user_name , password ):
+ """
+ @param host_url: The base url to the API.
+
+ """
+
+ self._host_url = host_url.rstrip('/')
+ self._headers = { }
+ self.c = pycurl.Curl()
+ if user_name is not None:
+ self.c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
+ userpass = user_name + ':'
+ if password is not None:
+ userpass += password
+ LOG.debug( "pycurl.USERPWD value = "+str(userpass))
+ self.c.setopt(pycurl.USERPWD, userpass)
+
+
+ def set_headers(self, headers):
+ """
+ Add headers to the request
+ """
+ self._headers = headers
+ return self
+
+ @property
+ def host_url(self):
+ return self._host_url
+
+ def _get_headers(self, headers):
+ res = self._headers.copy()
+ if headers:
+ res.update(headers)
+ return res
+
+ def invoke(self, http_method, path, payload=None, headers=None):
+ """
+ Submit an HTTP request.
+ @param http_method: GET, POST, PUT, DELETE
+ @param path: The path of the resource.
+ @param payload: The payload to attach to the body of the request.
+ @param headers: The headers to set for this request.
+
+ @return: The result of REST request
+ """
+ #pdb.set_trace()
+ LOG.debug ("invoke : http_method = "+str(http_method))
+ # Prepare URL and params
+ url = self._normalize(path)
+ if http_method in ("GET", "DELETE"):
+ if payload is not None:
+ self.logger.warn(
+ "GET http_method does not pass any payload. Path '%s'" % (path,))
+ payload = None
+
+
+ buf = cStringIO.StringIO()
+ self.c.setopt(pycurl.WRITEFUNCTION, buf.write)
+ LOG.debug ("invoke : url = "+str(url))
+ # set http_method
+ if http_method == "GET":
+ self.c.setopt(pycurl.HTTPGET, 1)
+ elif http_method == "HEAD":
+ self.c.setopt(pycurl.HTTPGET, 1)
+ self.c.setopt(pycurl.NOBODY, 1)
+ elif http_method == "POST":
+ self.c.setopt(pycurl.POST, 1)
+ elif http_method == "PUT":
+ self.c.setopt(pycurl.UPLOAD, 1)
+ else:
+ self.c.setopt(pycurl.CUSTOMREQUEST, http_method)
+
+ if http_method in ('POST','PUT'):
+ LOG.debug( "data..........."+str(payload))
+ data = json.dumps(payload)
+ data= data.decode('unicode-escape')
+ LOG.debug( data)
+ data = self._to_bytestring(data)
+ LOG.debug( data)
+ content = StringIO.StringIO(data)
+ LOG.debug( content)
+ content_length = len(data)
+ LOG.debug( "content_length........."+str(content_length))
+
+ if http_method == 'POST':
+ self.c.setopt(pycurl.POSTFIELDSIZE, content_length)
+ else:
+ self.c.setopt(pycurl.INFILESIZE, content_length)
+ self.c.setopt(pycurl.READFUNCTION, content.read)
+
+
+ self.c.setopt(self.c.URL, url)
+ headers = self._get_headers(headers)
+ self.c.setopt(pycurl.HTTPHEADER,
+ ["%s: %s" % pair for pair in sorted(headers.iteritems())])
+
+ LOG.debug ("invoke : pycurl.EFFECTIVE_URL = "+self.c.getinfo(pycurl.EFFECTIVE_URL))
+ try:
+ self.c.perform()
+ except Exception, ex:
+ LOG.debug (sys.stderr, str(ex))
+ raise ex
+ contents_type= self.c.getinfo(pycurl.CONTENT_TYPE)
+ LOG.debug ("invoke : pycurl.CONTENT_TYPE = "+contents_type)
+ code = self.c.getinfo(pycurl.RESPONSE_CODE)
+ LOG.debug ("invoke : pycurl.RESPONSE_CODE = "+str(code))
+ response = buf.getvalue()
+ buf.close()
+ LOG.debug ("invoke : COMPLETED ")
+ return response , code , contents_type
+
+ def _to_bytestring(self ,s):
+# if not isinstance(s, basestring):
+# raise TypeError("value should be a str or unicode")
+ if isinstance(s, unicode):
+ return s.encode('utf-8')
+ return s
+
+ def _normalize(self, path):
+ res = self._host_url
+ if path:
+ res += posixpath.normpath('/' + path.lstrip('/'))
+ return uri_encoding(res)
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/core/http_utils.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/core/http_utils.py b/ambari-client/src/main/python/ambari_client/core/http_utils.py
new file mode 100644
index 0000000..07fea45
--- /dev/null
+++ b/ambari-client/src/main/python/ambari_client/core/http_utils.py
@@ -0,0 +1,52 @@
+#
+# 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.
+
+
+import types
+import urllib
+import urllib2
+
+
+def uri_encoding(url):
+ """
+ Returns an ASCII string version of the URL.
+ """
+ if url is None:
+ return url
+ return urllib.quote(get_utf8_str(url), safe="/#%[]=:;$&()+,!?*@'~")
+
+
+
+def get_utf8_str(strr, encoding='utf-8'):
+ """
+ Returns a utf8 ecoded 'str'.
+ """
+ errors='strict'
+ if not isinstance(strr, basestring):
+ try:
+ return str(strr)
+ except UnicodeEncodeError:
+ if isinstance(strr, Exception):
+ return ' '.join([get_utf8_str(arg, encoding) for arg in strr])
+ return unicode(strr).encode(encoding, errors)
+ elif isinstance(strr, unicode):
+ return strr.encode(encoding, errors)
+ elif strr and encoding != 'utf-8':
+ return strr.decode('utf-8', errors).encode(encoding, errors)
+ else:
+ return strr
+
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/core/rest_resource.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/core/rest_resource.py b/ambari-client/src/main/python/ambari_client/core/rest_resource.py
new file mode 100644
index 0000000..683d1af
--- /dev/null
+++ b/ambari-client/src/main/python/ambari_client/core/rest_resource.py
@@ -0,0 +1,121 @@
+#
+# 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.
+
+try:
+ import json
+except ImportError:
+ import simplejson as json
+import logging
+import posixpath
+
+LOG = logging.getLogger(__name__)
+
+
+class RestResource(object):
+ """
+ RestResource wrapper.
+ """
+ def __init__(self, client, path=""):
+ """
+ @param client: A Client object.
+ @param path: The relative path of the resource.
+ """
+ self._client = client
+ self._path = path.strip('/')
+
+ @property
+ def host_url(self):
+ return self._client.host_url
+
+ def _join_uri(self, relpath):
+ if relpath is None:
+ return self._path
+ return self._path + posixpath.normpath('/' + relpath)
+
+ def _set_headers(self, content_type=None):
+ if content_type:
+ return { 'Content-Type': content_type }
+ return None
+
+
+ def make_invoke(self, http_method, payload, headers, path):
+ return self._client.invoke(http_method, path, payload=payload, headers=headers)
+
+ def invoke(self, http_method, url_path=None, payload=None, headers=None):
+ """
+ Invoke an API http_method.
+ """
+ path = self._join_uri(url_path)
+ resp ,code , content = self.make_invoke(http_method, payload, headers, path)
+
+ LOG.debug ("RESPONSE from the REST request >>>>>>> \n"+str(resp) )
+ LOG.debug ("\n===========================================================")
+ #take care of REST calls with no response
+ if not resp and (code!=200 and code!=201):
+ raise Exception("Command '%s %s' failed with error %s" %(http_method, path,code))
+ if resp and (code==404 or code==405):
+ raise Exception("Command '%s %s' failed with error %s" %(http_method, path,code))
+ try:
+ if (code==200 or code==201) and not resp:
+ return {}
+ json_dict = json.loads(resp)
+ return json_dict
+ except Exception, ex:
+ LOG.error('JSON decode error: %s' % (resp,))
+ raise ex
+
+
+
+ def get(self, path=None):
+ """
+ Invoke the GET method .
+ @param path: resource path
+ @return: A dictionary of the REST result.
+ """
+ return self.invoke("GET", path)
+
+
+ def put(self, path=None, payload=None, content_type=None):
+ """
+ Invoke the PUT method on a resource.
+ @param path: resource path
+ @param payload: Body of the request.
+ @param content_type:
+ @return: A dictionary of the REST result.
+ """
+ return self.invoke("PUT", path, payload,self._set_headers(content_type))
+
+
+ def post(self, path=None, payload=None, content_type=None):
+ """
+ Invoke the POST method on a resource.
+ @param path: resource path
+ @param payload: Body of the request.
+ @param content_type:
+ @return: A dictionary of the REST result.
+ """
+ return self.invoke("POST", path, payload,self._set_headers(content_type))
+
+
+ def delete(self, path=None, payload=None,):
+ """
+ Invoke the DELETE method on a resource.
+ @param path: resource path
+ @param payload: Body of the request.
+ @return: A dictionary of the REST result.
+ """
+ return self.invoke("DELETE", path, payload)
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/http_client.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/http_client.py b/ambari-client/src/main/python/ambari_client/http_client.py
deleted file mode 100644
index a966807..0000000
--- a/ambari-client/src/main/python/ambari_client/http_client.py
+++ /dev/null
@@ -1,166 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-'''
-
-
-
-'''
-import logging
-import posixpath
-import sys
-import pycurl
-import cStringIO
-import StringIO
-import pdb
-try:
- import json
-except ImportError:
- import simplejson as json
-from ambari_client.http_utils import uri_encoding
-
-__docformat__ = "epytext"
-
-LOG = logging.getLogger(__name__)
-
-
-class HttpClient(object):
- """
- Basic HTTP client for rest APIs.
- """
- def __init__(self, host_url, user_name , password ):
- """
- @param host_url: The base url to the API.
-
- """
-
- self._host_url = host_url.rstrip('/')
- self._headers = { }
- self.c = pycurl.Curl()
- if user_name is not None:
- self.c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
- userpass = user_name + ':'
- if password is not None:
- userpass += password
- LOG.debug( "pycurl.USERPWD value = "+str(userpass))
- self.c.setopt(pycurl.USERPWD, userpass)
-
-
- def set_headers(self, headers):
- """
- Add headers to the request
- """
- self._headers = headers
- return self
-
- @property
- def host_url(self):
- return self._host_url
-
- def _get_headers(self, headers):
- res = self._headers.copy()
- if headers:
- res.update(headers)
- return res
-
- def invoke(self, http_method, path, payload=None, headers=None):
- """
- Submit an HTTP request.
- @param http_method: GET, POST, PUT, DELETE
- @param path: The path of the resource.
- @param payload: The payload to attach to the body of the request.
- @param headers: The headers to set for this request.
-
- @return: The result of REST request
- """
- #pdb.set_trace()
- LOG.debug ("invoke : http_method = "+str(http_method))
- # Prepare URL and params
- url = self._normalize(path)
- if http_method in ("GET", "DELETE"):
- if payload is not None:
- self.logger.warn(
- "GET http_method does not pass any payload. Path '%s'" % (path,))
- payload = None
-
-
- buf = cStringIO.StringIO()
- self.c.setopt(pycurl.WRITEFUNCTION, buf.write)
- LOG.debug ("invoke : url = "+str(url))
- # set http_method
- if http_method == "GET":
- self.c.setopt(pycurl.HTTPGET, 1)
- elif http_method == "HEAD":
- self.c.setopt(pycurl.HTTPGET, 1)
- self.c.setopt(pycurl.NOBODY, 1)
- elif http_method == "POST":
- self.c.setopt(pycurl.POST, 1)
- elif http_method == "PUT":
- self.c.setopt(pycurl.UPLOAD, 1)
- else:
- self.c.setopt(pycurl.CUSTOMREQUEST, http_method)
-
- if http_method in ('POST','PUT'):
- LOG.debug( "data..........."+str(payload))
- data = json.dumps(payload)
- data= data.decode('unicode-escape')
- LOG.debug( data)
- data = self._to_bytestring(data)
- LOG.debug( data)
- content = StringIO.StringIO(data)
- LOG.debug( content)
- content_length = len(data)
- LOG.debug( "content_length........."+str(content_length))
-
- if http_method == 'POST':
- self.c.setopt(pycurl.POSTFIELDSIZE, content_length)
- else:
- self.c.setopt(pycurl.INFILESIZE, content_length)
- self.c.setopt(pycurl.READFUNCTION, content.read)
-
-
- self.c.setopt(self.c.URL, url)
- headers = self._get_headers(headers)
- self.c.setopt(pycurl.HTTPHEADER,
- ["%s: %s" % pair for pair in sorted(headers.iteritems())])
-
- LOG.debug ("invoke : pycurl.EFFECTIVE_URL = "+self.c.getinfo(pycurl.EFFECTIVE_URL))
- try:
- self.c.perform()
- except Exception, ex:
- LOG.debug (sys.stderr, str(ex))
- raise ex
- contents_type= self.c.getinfo(pycurl.CONTENT_TYPE)
- LOG.debug ("invoke : pycurl.CONTENT_TYPE = "+contents_type)
- code = self.c.getinfo(pycurl.RESPONSE_CODE)
- LOG.debug ("invoke : pycurl.RESPONSE_CODE = "+str(code))
- response = buf.getvalue()
- buf.close()
- LOG.debug ("invoke : COMPLETED ")
- return response , code , contents_type
-
- def _to_bytestring(self ,s):
-# if not isinstance(s, basestring):
-# raise TypeError("value should be a str or unicode")
- if isinstance(s, unicode):
- return s.encode('utf-8')
- return s
-
- def _normalize(self, path):
- res = self._host_url
- if path:
- res += posixpath.normpath('/' + path.lstrip('/'))
- return uri_encoding(res)
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/http_utils.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/http_utils.py b/ambari-client/src/main/python/ambari_client/http_utils.py
deleted file mode 100644
index 8c53c9e..0000000
--- a/ambari-client/src/main/python/ambari_client/http_utils.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-'''
-
-
-
-'''
-
-import types
-import urllib
-import urllib2
-
-
-def uri_encoding(url):
- """
- Returns an ASCII string version of the URL.
- """
- if url is None:
- return url
- return urllib.quote(get_utf8_str(url), safe="/#%[]=:;$&()+,!?*@'~")
-
-
-
-def get_utf8_str(strr, encoding='utf-8'):
- """
- Returns a utf8 ecoded 'str'.
- """
- errors='strict'
- if not isinstance(strr, basestring):
- try:
- return str(strr)
- except UnicodeEncodeError:
- if isinstance(strr, Exception):
- return ' '.join([get_utf8_str(arg, encoding) for arg in strr])
- return unicode(strr).encode(encoding, errors)
- elif isinstance(strr, unicode):
- return strr.encode(encoding, errors)
- elif strr and encoding != 'utf-8':
- return strr.decode('utf-8', errors).encode(encoding, errors)
- else:
- return strr
-
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/model/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/model/__init__.py b/ambari-client/src/main/python/ambari_client/model/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/model/base_model.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/model/base_model.py b/ambari-client/src/main/python/ambari_client/model/base_model.py
index fe0939b..1c00e60 100644
--- a/ambari-client/src/main/python/ambari_client/model/base_model.py
+++ b/ambari-client/src/main/python/ambari_client/model/base_model.py
@@ -14,10 +14,6 @@
# 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.
-'''
-
-
-'''
import sys
import logging
@@ -45,6 +41,8 @@ class BaseModel(object):
def __init__(self, resource_root, **rw_attrs):
+ #print" ================== base_model\n"
+ print locals()
self._resource_root = resource_root
for k, v in rw_attrs.items():
if k not in self.RW_ATTR:
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/model/cluster.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/model/cluster.py b/ambari-client/src/main/python/ambari_client/model/cluster.py
index 27c9e34..7a012dd 100644
--- a/ambari-client/src/main/python/ambari_client/model/cluster.py
+++ b/ambari-client/src/main/python/ambari_client/model/cluster.py
@@ -14,15 +14,12 @@
# 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.
-'''
-
-
-'''
import logging
+import time
from ambari_client.model.base_model import BaseModel
from ambari_client.model.paths import CLUSTERS_PATH
-from ambari_client.model import service
+from ambari_client.model import service ,host
from ambari_client.model.utils import ModelUtils ,retain_self_helper
@@ -50,8 +47,30 @@ def get_all_clusters(root_resource, details=None):
+def create_cluster(root_resource, cluster_name, version):
+ """
+ Create a cluster
+ @param root_resource: The root Resource.
+ @param cluster_name: Cluster cluster_name
+ @param version: HDP version
+ @return: An ClusterModel object
+ """
+ data={"Clusters":{"version":str(version)}}
+ cluster = ClusterModel(root_resource, cluster_name, version)
+ path = CLUSTERS_PATH+"/%s" % (cluster_name)
+ root_resource.post(path=path , payload=data)
+ return get_cluster(root_resource, cluster_name)
+
+def delete_cluster(root_resource, cluster_name):
+ """
+ Delete a cluster by name
+ @param root_resource: The root Resource object.
+ @param name: Cluster name
+ """
+ root_resource.delete("%s/%s" % (CLUSTERS_PATH, cluster_name))
+ time.sleep(3)
+ return None
-
class ClusterModel(BaseModel):
@@ -82,7 +101,20 @@ class ClusterModel(BaseModel):
"""
return service.get_all_services(self._get_resource_root(), self.cluster_name)
+ def get_all_hosts(self, detail = None):
+ """
+ Get all hosts in this cluster.
+ @return: A list of HostModel objects.
+ """
+ return host.get_all_cluster_hosts(self._get_resource_root(), self.cluster_name)
+
+ def get_host(self, hostname , detail = None):
+ """
+ Get a specific hosts in this cluster.
+ @return: A HostModel object.
+ """
+ return host.get_host(self._get_resource_root(), self.cluster_name, hostname)
class ClusterModelRef(BaseModel):
RW_ATTR = ('cluster_name',)
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/model/host.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/model/host.py b/ambari-client/src/main/python/ambari_client/model/host.py
new file mode 100644
index 0000000..3e7fc48
--- /dev/null
+++ b/ambari-client/src/main/python/ambari_client/model/host.py
@@ -0,0 +1,124 @@
+#
+# 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.
+
+try:
+ import json
+except ImportError:
+ import simplejson as json
+import logging
+from ambari_client.model.base_model import BaseModel , ModelList
+from ambari_client.model.paths import HOSTS_PATH , CLUSTER_HOSTS_PATH , CLUSTER_HOST_PATH ,BOOTSTRAP_PATH
+from ambari_client.model import service ,status
+from ambari_client.model.utils import ModelUtils , retain_self_helper
+
+
+LOG = logging.getLogger(__name__)
+
+def create_host(root_resource, host_name, ip, rack_info=None):
+ """
+ Create a host
+ @param root_resource: The root Resource object.
+ @param host_name: Host name
+ @param ip: IP address
+ @param rack_info: Rack id. Default None
+ @return: An HostModel object
+ """
+ host = HostModel(root_resource, host_name, ip, rack_info)
+ host_list = ModelList([host])
+ body = json.dumps(host_list.to_json_dict())
+ resp = root_resource.post(HOSTS_PATH, data=body)
+ # The server returns a created hosts
+ return get_host(root_resource, host_name)
+
+
+
+
+def get_host(root_resource, cluster_name , host_name):
+ """
+ Lookup up by host_name
+ @param root_resource: The root Resource object.
+ @param cluster_name: Cluster name
+ @param host_name: Host name
+ @return: A HostModel object
+ """
+ path = CLUSTER_HOST_PATH % (cluster_name, host_name)
+ dic = root_resource.get(path)
+ return ModelUtils.create_model(HostModel , dic, root_resource, "Hosts")
+
+
+
+def get_all_hosts(root_resource):
+ """
+ Get all hosts
+ @param root_resource: The root Resource.
+ @return: A list of HostModel objects.
+ """
+ dic = root_resource.get(HOSTS_PATH)
+ return ModelUtils.get_model_list(HostModel, dic, root_resource , "Hosts")
+
+
+
+def get_all_cluster_hosts(root_resource, cluster_name):
+ """
+ Get all hosts in the cluster
+ @param root_resource: The root Resource.
+ @return: A list of HostModel objects.
+ """
+ path = "%s/%s" % (HOSTS_PATH, cluster_name)
+ dic = root_resource.get(path)
+ return ModelUtils.get_model_list(HostModel, dic, root_resource , "Hosts")
+
+
+
+def delete_host(root_resource, host_id):
+ """
+ Delete a host by id
+ @param root_resource: The root Resource object.
+ @param host_id: Host id
+ @return: The deleted HostModel object
+ """
+ resp = root_resource.delete("%s/%s" % (HOSTS_PATH, host_id))
+ return HostModel.from_json_dict(resp, root_resource)
+
+
+def bootstrap_hosts(root_resource , hosts_list,ssh_key):
+ """
+ Bootstrap hosts.
+ @param hosts_list list of host_names.
+ @return: A StatusModel object.
+ """
+ payload_dic = {'sshKey':ssh_key.encode('string_escape') ,'hosts':hosts_list}
+ resp = root_resource.post(BOOTSTRAP_PATH,payload_dic ,content_type="application/json")
+ return ModelUtils.create_model(status.StatusModel, resp, root_resource, "NO_KEY")
+
+
+
+
+class HostModel(BaseModel):
+ RO_ATTR = ('host_state', 'public_host_name')
+ RW_ATTR = ('host_name', 'ip', 'rack_info')
+ REF_ATTR = ('cluster_name',)
+
+ def __init__(self, resource_root, host_name, ip=None , rack_info=None):
+ retain_self_helper(**locals())
+
+ def __str__(self):
+ return "<<HostModel>>: = %s; ip = %s" % (self.host_name, self.ip)
+
+ def _path(self):
+ return HOSTS_PATH + '/' + self.host_name
+
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/model/paths.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/model/paths.py b/ambari-client/src/main/python/ambari_client/model/paths.py
index 9c78230..cc39a2a 100644
--- a/ambari-client/src/main/python/ambari_client/model/paths.py
+++ b/ambari-client/src/main/python/ambari_client/model/paths.py
@@ -14,13 +14,11 @@
# 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.
-'''
-
-
-'''
CLUSTERS_PATH = "/clusters"
SERVICES_PATH = "/clusters/%s/services"
SERVICE_PATH = "/clusters/%s/services/%s"
-
-
+HOSTS_PATH = "/hosts"
+CLUSTER_HOSTS_PATH = "/clusters/%s/hosts"
+CLUSTER_HOST_PATH = "/clusters/%s/hosts/%s"
+BOOTSTRAP_PATH="/bootstrap"
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/model/service.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/model/service.py b/ambari-client/src/main/python/ambari_client/model/service.py
index ff07d6d..03b6421 100644
--- a/ambari-client/src/main/python/ambari_client/model/service.py
+++ b/ambari-client/src/main/python/ambari_client/model/service.py
@@ -13,13 +13,9 @@
# 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.
-'''
-
-
-'''
import logging
-
+import time
from ambari_client.model.base_model import BaseModel
from ambari_client.model.paths import SERVICES_PATH ,SERVICE_PATH
from ambari_client.model.utils import ModelUtils ,retain_self_helper
@@ -39,19 +35,33 @@ def get_service(resource_root, service_name, cluster_name="default"):
dic = resource_root.get(path)
return ModelUtils.create_model(ServiceModel ,dic, resource_root,"ServiceInfo")
-
-
+def create_service(root_resource, service_name, cluster_name):
+ """
+ Create a service
+ @param root_resource: The root Resource object.
+ @param service_name: Service service_name
+ @param cluster_name: Cluster service_name
+ @return: An ServiceModel object
+ """
+ data ={"ServiceInfo":{"service_name":str(service_name)}}
+ service = ServiceModel(root_resource, service_name,cluster_name)
+ path = SERVICE_PATH
+ root_resource.post(path=SERVICE_PATH , payload=data)
+ return get_service(root_resource, service_name, cluster_name)
+
+
class ServiceModel(BaseModel):
RO_ATTR = ('state', 'cluster_name')
RW_ATTR = ('service_name', 'type')
REF_ATTR = ('cluster_name',)
- def __init__(self, resource_root, service_name):
+ def __init__(self, resource_root, service_name ):
#BaseModel.__init__(self, **locals())
retain_self_helper(**locals())
+
def __str__(self):
return "<<ServiceModel>> = %s (cluster_name = %s)" % (self.service_name, self._get_cluster_name())
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/model/status.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/model/status.py b/ambari-client/src/main/python/ambari_client/model/status.py
new file mode 100644
index 0000000..657afdd
--- /dev/null
+++ b/ambari-client/src/main/python/ambari_client/model/status.py
@@ -0,0 +1,40 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+from ambari_client.model.base_model import BaseModel
+from ambari_client.model.utils import retain_self_helper
+from ambari_client.model.paths import BOOTSTRAP_PATH
+LOG = logging.getLogger(__name__)
+
+
+
+
+class StatusModel(BaseModel):
+ RO_ATTR = ()
+ RW_ATTR = ('status','requestId')
+ REF_ATTR = ('cluster_name',)
+
+ def __init__(self, resource_root, status ,requestId=None):
+ #BaseModel.__init__(self, **locals())
+ retain_self_helper(**locals())
+
+ def __str__(self):
+ return "<<StatusModel>> = %s (requestId = %s)" % (self.status, self.requestId)
+
+ def get_request_path(self):
+ return BOOTSTRAP_PATH + '/' + self.requestId
+
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/model/utils.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/model/utils.py b/ambari-client/src/main/python/ambari_client/model/utils.py
index 83c1887..904154d 100644
--- a/ambari-client/src/main/python/ambari_client/model/utils.py
+++ b/ambari-client/src/main/python/ambari_client/model/utils.py
@@ -14,11 +14,7 @@
# 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.
-'''
-
-
-'''
import logging
import sys
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/resources/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/resources/__init__.py b/ambari-client/src/main/python/ambari_client/resources/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/resources/clusters.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/resources/clusters.py b/ambari-client/src/main/python/ambari_client/resources/clusters.py
index 125bec2..0e3f0be 100644
--- a/ambari-client/src/main/python/ambari_client/resources/clusters.py
+++ b/ambari-client/src/main/python/ambari_client/resources/clusters.py
@@ -14,12 +14,7 @@
# 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 import cluster
__docformat__ = "epytext"
@@ -41,4 +36,43 @@ def get_all_clusters(root_resource):
@param root_resource: The root Resource object.
@return: A list of ClusterModel objects in ModelList.
"""
- return cluster.get_all_clusters(root_resource)
\ No newline at end of file
+ return cluster.get_all_clusters(root_resource)
+
+
+def create_cluster(root_resource, cluster_name, version):
+ """
+ Create a cluster
+ @param root_resource: The root Resource.
+ @param cluster_name: Cluster cluster_name
+ @param version: HDP version
+ @return: An ClusterModel object
+ """
+ return cluster.create_cluster(root_resource, cluster_name, version)
+
+
+def delete_cluster(root_resource, cluster_name):
+ """
+ Create a cluster
+ @param root_resource: The root Resource.
+ @param cluster_name: Cluster cluster_name
+ """
+ return cluster.delete_cluster(root_resource, cluster_name)
+
+def create_cluster(root_resource, cluster_name, version):
+ """
+ Create a cluster
+ @param root_resource: The root Resource.
+ @param cluster_name: Cluster cluster_name
+ @param version: HDP version
+ @return: An ClusterModel object
+ """
+ return cluster.create_cluster(root_resource, cluster_name, version)
+
+
+def delete_cluster(root_resource, cluster_name):
+ """
+ Create a cluster
+ @param root_resource: The root Resource.
+ @param cluster_name: Cluster cluster_name
+ """
+ return cluster.delete_cluster(root_resource, cluster_name)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/resources/hosts.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/resources/hosts.py b/ambari-client/src/main/python/ambari_client/resources/hosts.py
new file mode 100644
index 0000000..cc4bcc4
--- /dev/null
+++ b/ambari-client/src/main/python/ambari_client/resources/hosts.py
@@ -0,0 +1,72 @@
+ #
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ambari_client.model import host
+__docformat__ = "epytext"
+
+
+def create_host(root_resource, host_name, ip, rack_info=None):
+ """
+ Create a host
+ @param root_resource: The root Resource.
+ @param host_name: Host name
+ @param ip: IP address
+ @param rack_info: Rack id. Default None
+ @return: An HostModel object
+ """
+ return host.create_host(root_resource, host_name, ip, rack_info=None)
+
+def get_host(root_resource, host_name):
+ """
+ Lookup a host by id
+ @param root_resource: The root Resource.
+ @param host_name: Host name
+ @return: An HostModel object
+ """
+ return host.get_host(root_resource, host_name)
+
+
+
+def get_all_hosts(root_resource):
+ """
+ Get all hosts
+ @param root_resource: The root Resource.
+ @return: A list of HostModel objects.
+ """
+ return host.get_all_hosts(root_resource)
+
+
+
+
+def delete_host(root_resource, host_name):
+ """
+ Delete a host by id
+ @param root_resource: The root Resource.
+ @param host_name: Host name
+ @return: The deleted HostModel object
+ """
+ return host.delete_host(root_resource,host_name)
+
+
+
+def bootstrap_hosts(root_resource , hosts_list ,ssh_key):
+ """
+ Bootstrap hosts.
+ @param hosts list of host_names.
+ @return: A StatusModel object.
+ """
+ return host.bootstrap_hosts(root_resource, hosts_list ,ssh_key)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/resources/services.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/resources/services.py b/ambari-client/src/main/python/ambari_client/resources/services.py
index 3345f95..abddbec 100644
--- a/ambari-client/src/main/python/ambari_client/resources/services.py
+++ b/ambari-client/src/main/python/ambari_client/resources/services.py
@@ -13,11 +13,6 @@
# 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 import service
__docformat__ = "epytext"
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/main/python/ambari_client/rest_resource.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/main/python/ambari_client/rest_resource.py b/ambari-client/src/main/python/ambari_client/rest_resource.py
deleted file mode 100644
index 0f62b52..0000000
--- a/ambari-client/src/main/python/ambari_client/rest_resource.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-'''
-
-
-
-'''
-try:
- import json
-except ImportError:
- import simplejson as json
-import logging
-import posixpath
-
-LOG = logging.getLogger(__name__)
-
-
-class RestResource(object):
- """
- RestResource wrapper.
- """
- def __init__(self, client, path=""):
- """
- @param client: A Client object.
- @param path: The relative path of the resource.
- """
- self._client = client
- self._path = path.strip('/')
-
- @property
- def host_url(self):
- return self._client.host_url
-
- def _join_uri(self, relpath):
- if relpath is None:
- return self._path
- return self._path + posixpath.normpath('/' + relpath)
-
- def _set_headers(self, content_type=None):
- if content_type:
- return { 'Content-Type': content_type }
- return None
-
-
- def make_invoke(self, http_method, payload, headers, path):
- return self._client.invoke(http_method, path, payload=payload, headers=headers)
-
- def invoke(self, http_method, url_path=None, payload=None, headers=None):
- """
- Invoke an API http_method.
- """
- path = self._join_uri(url_path)
- resp ,code , content = self.make_invoke(http_method, payload, headers, path)
-
- LOG.debug ("RESPONSE from the REST request >>>>>>> \n"+str(resp) )
- LOG.debug ("\n===========================================================")
- if not resp and code!=200:
- raise Exception("Command '%s %s' failed" %(http_method, path))
- try:
- if code==200 and not resp:
- return {}
- json_dict = json.loads(resp)
- return json_dict
- except Exception, ex:
- LOG.error('JSON decode error: %s' % (resp,))
- raise ex
-
-
-
- def get(self, path=None):
- """
- Invoke the GET method .
- @param path: resource path
- @return: A dictionary of the REST result.
- """
- return self.invoke("GET", path)
-
-
- def put(self, path=None, payload=None, content_type=None):
- """
- Invoke the PUT method on a resource.
- @param path: resource path
- @param payload: Body of the request.
- @param content_type:
- @return: A dictionary of the REST result.
- """
- return self.invoke("PUT", path, payload,self._set_headers(content_type))
-
-
-
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/23754e34/ambari-client/src/test/python/TestAmbariClient.py
----------------------------------------------------------------------
diff --git a/ambari-client/src/test/python/TestAmbariClient.py b/ambari-client/src/test/python/TestAmbariClient.py
index 891cca1..ed0ff9c 100644
--- a/ambari-client/src/test/python/TestAmbariClient.py
+++ b/ambari-client/src/test/python/TestAmbariClient.py
@@ -49,7 +49,7 @@ class TestAmbariClient(unittest.TestCase):
- @patch("ambari_client.http_client.HttpClient")
+ @patch("ambari_client.core.http_client.HttpClient")
def test_get_all_clusters_valid(self ,http_client):
"""
Get all clusters.
@@ -74,7 +74,7 @@ class TestAmbariClient(unittest.TestCase):
self.assertEqual(all_clusters.to_json_dict(), expected_output, "to_json_dict should convert ModelList")
- @patch("ambari_client.http_client.HttpClient")
+ @patch("ambari_client.core.http_client.HttpClient")
def test_get_cluster_valid(self ,http_client):
"""
Get all clusters.
@@ -98,7 +98,7 @@ class TestAmbariClient(unittest.TestCase):
- @patch("ambari_client.http_client.HttpClient")
+ @patch("ambari_client.core.http_client.HttpClient")
def test_get_all_services_valid(self ,http_client):
"""
Get all services.
@@ -120,7 +120,7 @@ class TestAmbariClient(unittest.TestCase):
self.assertEqual(cluster.to_json_dict(), expected_dict_output, "to_json_dict should convert ClusterModel")
self.assertEqual(len(serviceList), 3, "There should be a 3 services from the response")
- @patch("ambari_client.http_client.HttpClient")
+ @patch("ambari_client.core.http_client.HttpClient")
def test_get_service_valid(self ,http_client):
"""
Get the service.