1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 try:
18 import json
19 except ImportError:
20 import simplejson as json
21 import logging
22 import posixpath
23
24 LOG = logging.getLogger(__name__)
28 """
29 Encapsulates a resource, and provides actions to invoke on it.
30 """
32 """
33 @param client: A Client object.
34 @param relpath: The relative path of the resource.
35 """
36 self._client = client
37 self._path = relpath.strip('/')
38
39 @property
42
44 if relpath is None:
45 return self._path
46 return self._path + posixpath.normpath('/' + relpath)
47
48 - def invoke(self, method, relpath=None, params=None, data=None, headers=None):
49 """
50 Invoke an API method.
51 @return: Raw body or JSON dictionary (if response content type is JSON).
52 """
53 path = self._join_uri(relpath)
54 resp = self._client.execute(method,
55 path,
56 params=params,
57 data=data,
58 headers=headers)
59 try:
60 body = resp.read()
61 except Exception, ex:
62 raise Exception("Command '%s %s' failed: %s" %
63 (method, path, ex))
64
65 self._client.logger.debug(
66 "%s Got response: %s%s" %
67 (method, body[:32], len(body) > 32 and "..." or ""))
68
69
70 if len(body) != 0 and \
71 resp.info().getmaintype() == "application" and \
72 resp.info().getsubtype() == "json":
73 try:
74 json_dict = json.loads(body)
75 return json_dict
76 except Exception, ex:
77 self._client.logger.exception('JSON decode error: %s' % (body,))
78 raise ex
79 else:
80 return body
81
82
83 - def get(self, relpath=None, params=None):
84 """
85 Invoke the GET method on a resource.
86 @param relpath: Optional. A relative path to this resource's path.
87 @param params: Key-value data.
88
89 @return: A dictionary of the JSON result.
90 """
91 return self.invoke("GET", relpath, params)
92
93
94 - def delete(self, relpath=None, params=None):
95 """
96 Invoke the DELETE method on a resource.
97 @param relpath: Optional. A relative path to this resource's path.
98 @param params: Key-value data.
99
100 @return: A dictionary of the JSON result.
101 """
102 return self.invoke("DELETE", relpath, params)
103
104
105 - def post(self, relpath=None, params=None, data=None, contenttype=None):
106 """
107 Invoke the POST method on a resource.
108 @param relpath: Optional. A relative path to this resource's path.
109 @param params: Key-value data.
110 @param data: Optional. Body of the request.
111 @param contenttype: Optional.
112
113 @return: A dictionary of the JSON result.
114 """
115 return self.invoke("POST", relpath, params, data,
116 self._make_headers(contenttype))
117
118
119 - def put(self, relpath=None, params=None, data=None, contenttype=None):
120 """
121 Invoke the PUT method on a resource.
122 @param relpath: Optional. A relative path to this resource's path.
123 @param params: Key-value data.
124 @param data: Optional. Body of the request.
125 @param contenttype: Optional.
126
127 @return: A dictionary of the JSON result.
128 """
129 return self.invoke("PUT", relpath, params, data,
130 self._make_headers(contenttype))
131
132
134 if contenttype:
135 return { 'Content-Type': contenttype }
136 return None
137