Package cm_api :: Module resource
[hide private]
[frames] | no frames]

Source Code for Module cm_api.resource

  1  # Licensed to Cloudera, Inc. under one 
  2  # or more contributor license agreements.  See the NOTICE file 
  3  # distributed with this work for additional information 
  4  # regarding copyright ownership.  Cloudera, Inc. licenses this file 
  5  # to you under the Apache License, Version 2.0 (the 
  6  # "License"); you may not use this file except in compliance 
  7  # with the License.  You may obtain a copy of the License at 
  8  # 
  9  #     http://www.apache.org/licenses/LICENSE-2.0 
 10  # 
 11  # Unless required by applicable law or agreed to in writing, software 
 12  # distributed under the License is distributed on an "AS IS" BASIS, 
 13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 14  # See the License for the specific language governing permissions and 
 15  # limitations under the License. 
 16   
 17  try: 
 18    import json 
 19  except ImportError: 
 20    import simplejson as json 
 21  import logging 
 22  import posixpath 
 23  import time 
 24  import socket 
 25  import urllib2 
 26   
 27  LOG = logging.getLogger(__name__) 
28 29 30 -class Resource(object):
31 """ 32 Encapsulates a resource, and provides actions to invoke on it. 33 """
34 - def __init__(self, client, relpath=""):
35 """ 36 @param client: A Client object. 37 @param relpath: The relative path of the resource. 38 """ 39 self._client = client 40 self._path = relpath.strip('/') 41 self.retries = 3 42 self.retry_sleep = 3
43 44 @property
45 - def base_url(self):
46 return self._client.base_url
47
48 - def _join_uri(self, relpath):
49 if relpath is None: 50 return self._path 51 return self._path + posixpath.normpath('/' + relpath)
52
53 - def invoke(self, method, relpath=None, params=None, data=None, headers=None):
54 """ 55 Invoke an API method. 56 @return: Raw body or JSON dictionary (if response content type is JSON). 57 """ 58 path = self._join_uri(relpath) 59 resp = self._client.execute(method, 60 path, 61 params=params, 62 data=data, 63 headers=headers) 64 try: 65 body = resp.read() 66 except Exception, ex: 67 raise Exception("Command '%s %s' failed: %s" % 68 (method, path, ex)) 69 70 self._client.logger.debug( 71 "%s Got response: %s%s" % 72 (method, body[:32], len(body) > 32 and "..." or "")) 73 74 # Is the response application/json? 75 if len(body) != 0 and \ 76 resp.info().getmaintype() == "application" and \ 77 resp.info().getsubtype() == "json": 78 try: 79 json_dict = json.loads(body) 80 return json_dict 81 except Exception, ex: 82 self._client.logger.exception('JSON decode error: %s' % (body,)) 83 raise ex 84 else: 85 return body
86 87
88 - def get(self, relpath=None, params=None):
89 """ 90 Invoke the GET method on a resource. 91 @param relpath: Optional. A relative path to this resource's path. 92 @param params: Key-value data. 93 94 @return: A dictionary of the JSON result. 95 """ 96 for retry in xrange(self.retries + 1): 97 if retry: 98 time.sleep(self.retry_sleep) 99 try: 100 return self.invoke("GET", relpath, params) 101 except (socket.error, urllib2.URLError) as e: 102 if "timed out" in str(e).lower(): 103 log_message = "Timeout issuing GET request for %s." \ 104 % (self._join_uri(relpath), ) 105 if retry < self.retries: 106 log_message += " Will retry." 107 else: 108 log_message += " No retries left." 109 LOG.warn(log_message, exc_info=True) 110 else: 111 raise 112 else: 113 raise e
114 115
116 - def delete(self, relpath=None, params=None):
117 """ 118 Invoke the DELETE method on a resource. 119 @param relpath: Optional. A relative path to this resource's path. 120 @param params: Key-value data. 121 122 @return: A dictionary of the JSON result. 123 """ 124 return self.invoke("DELETE", relpath, params)
125 126
127 - def post(self, relpath=None, params=None, data=None, contenttype=None):
128 """ 129 Invoke the POST method on a resource. 130 @param relpath: Optional. A relative path to this resource's path. 131 @param params: Key-value data. 132 @param data: Optional. Body of the request. 133 @param contenttype: Optional. 134 135 @return: A dictionary of the JSON result. 136 """ 137 return self.invoke("POST", relpath, params, data, 138 self._make_headers(contenttype))
139 140
141 - def put(self, relpath=None, params=None, data=None, contenttype=None):
142 """ 143 Invoke the PUT method on a resource. 144 @param relpath: Optional. A relative path to this resource's path. 145 @param params: Key-value data. 146 @param data: Optional. Body of the request. 147 @param contenttype: Optional. 148 149 @return: A dictionary of the JSON result. 150 """ 151 return self.invoke("PUT", relpath, params, data, 152 self._make_headers(contenttype))
153 154
155 - def _make_headers(self, contenttype=None):
156 if contenttype: 157 return { 'Content-Type': contenttype } 158 return None
159