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  import os 
 18  try: 
 19    import json 
 20  except ImportError: 
 21    import simplejson as json 
 22  import logging 
 23  import posixpath 
 24  import time 
 25  import socket 
 26  try: 
 27    import socks 
 28    socks_server = os.environ.get("SOCKS_SERVER", None) 
 29    if socks_server: 
 30      host, port = socks_server.split(":") 
 31      socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, host, int(port)) 
 32      socket.socket = socks.socksocket 
 33  except ImportError: 
 34    pass 
 35  import urllib2 
 36   
 37  LOG = logging.getLogger(__name__) 
38 39 40 -class Resource(object):
41 """ 42 Encapsulates a resource, and provides actions to invoke on it. 43 """
44 - def __init__(self, client, relpath=""):
45 """ 46 @param client: A Client object. 47 @param relpath: The relative path of the resource. 48 """ 49 self._client = client 50 self._path = relpath.strip('/') 51 self.retries = 3 52 self.retry_sleep = 3
53 54 @property
55 - def base_url(self):
56 return self._client.base_url
57
58 - def _join_uri(self, relpath):
59 if relpath is None: 60 return self._path 61 return self._path + posixpath.normpath('/' + relpath)
62
63 - def invoke(self, method, relpath=None, params=None, data=None, headers=None):
64 """ 65 Invoke an API method. 66 @return: Raw body or JSON dictionary (if response content type is JSON). 67 """ 68 path = self._join_uri(relpath) 69 resp = self._client.execute(method, 70 path, 71 params=params, 72 data=data, 73 headers=headers) 74 try: 75 body = resp.read() 76 except Exception, ex: 77 raise Exception("Command '%s %s' failed: %s" % 78 (method, path, ex)) 79 80 self._client.logger.debug( 81 "%s Got response: %s%s" % 82 (method, body[:32], len(body) > 32 and "..." or "")) 83 84 # Is the response application/json? 85 if len(body) != 0 and \ 86 resp.info().getmaintype() == "application" and \ 87 resp.info().getsubtype() == "json": 88 try: 89 json_dict = json.loads(body) 90 return json_dict 91 except Exception, ex: 92 self._client.logger.exception('JSON decode error: %s' % (body,)) 93 raise ex 94 else: 95 return body
96 97
98 - def get(self, relpath=None, params=None):
99 """ 100 Invoke the GET method on a resource. 101 @param relpath: Optional. A relative path to this resource's path. 102 @param params: Key-value data. 103 104 @return: A dictionary of the JSON result. 105 """ 106 for retry in xrange(self.retries + 1): 107 if retry: 108 time.sleep(self.retry_sleep) 109 try: 110 return self.invoke("GET", relpath, params) 111 except (socket.error, urllib2.URLError) as e: 112 if "timed out" in str(e).lower(): 113 log_message = "Timeout issuing GET request for %s." \ 114 % (self._join_uri(relpath), ) 115 if retry < self.retries: 116 log_message += " Will retry." 117 else: 118 log_message += " No retries left." 119 LOG.warn(log_message, exc_info=True) 120 else: 121 raise 122 else: 123 raise e
124 125
126 - def delete(self, relpath=None, params=None):
127 """ 128 Invoke the DELETE method on a resource. 129 @param relpath: Optional. A relative path to this resource's path. 130 @param params: Key-value data. 131 132 @return: A dictionary of the JSON result. 133 """ 134 return self.invoke("DELETE", relpath, params)
135 136
137 - def post(self, relpath=None, params=None, data=None, contenttype=None):
138 """ 139 Invoke the POST method on a resource. 140 @param relpath: Optional. A relative path to this resource's path. 141 @param params: Key-value data. 142 @param data: Optional. Body of the request. 143 @param contenttype: Optional. 144 145 @return: A dictionary of the JSON result. 146 """ 147 return self.invoke("POST", relpath, params, data, 148 self._make_headers(contenttype))
149 150
151 - def put(self, relpath=None, params=None, data=None, contenttype=None):
152 """ 153 Invoke the PUT method on a resource. 154 @param relpath: Optional. A relative path to this resource's path. 155 @param params: Key-value data. 156 @param data: Optional. Body of the request. 157 @param contenttype: Optional. 158 159 @return: A dictionary of the JSON result. 160 """ 161 return self.invoke("PUT", relpath, params, data, 162 self._make_headers(contenttype))
163 164
165 - def _make_headers(self, contenttype=None):
166 if contenttype: 167 return { 'Content-Type': contenttype } 168 return None
169