Skip to content

Commit c6d8a9b

Browse files
committed
Merge pull request #5 from dmsimard/wip-1_4
Implement missing GET calls, binary requests, body type validation
2 parents cb00d05 + 5448bff commit c6d8a9b

4 files changed

Lines changed: 111 additions & 44 deletions

File tree

README.rst

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Client
1111
--------------------------------------------------
1212

1313
The cephclient class takes care of sending calls to the API through HTTP and
14-
handle the responses. It supports queries for JSON, XML or plain text.
14+
handle the responses. It supports queries for JSON, XML, plain text or binary.
1515

1616
Wrapper
1717
--------------------------------------------------
@@ -55,25 +55,16 @@ Instanciate CephWrapper::
5555

5656
Do your request and specify the reponse type you are expecting.
5757

58-
Either ``json``, ``xml`` or ``text`` (default) are available.
59-
60-
text::
61-
62-
response, body = wrapper.get_fsid(body = 'text')
63-
print(response)
64-
65-
====
66-
67-
d5252e7d-75bc-4083-85ed-fe51fa83f62b
68-
58+
Either ``json``, ``xml``, ``text`` (default) or ``binary`` are available.
6959

7060
json::
7161

7262
response, body = wrapper.get_fsid(body = 'json')
73-
print(json.dumps(body, indent=4, separators=(',', ': ')))
63+
print('Response: {0}, Body:\n{1}'.format(response, json.dumps(body, indent=4, separators=(',', ': '))))
7464

7565
====
7666

67+
Response: <Response [200]>, Body:
7768
{
7869
"status": "OK",
7970
"output": {
@@ -85,15 +76,48 @@ json::
8576
xml::
8677

8778
response, body = wrapper.get_fsid(body = 'xml')
88-
print(etree.tostring(body, pretty_print=True))
79+
print('Response: {0}, Body:\n{1}'.format(reponse, etree.tostring(body, pretty_print=True)))
8980

9081
====
9182

83+
Response: <Response [200]>, Body:
9284
<response>
9385
<output>
9486
<fsid><fsid>d5252e7d-75bc-4083-85ed-fe51fa83f62b</fsid></fsid>
9587
</output>
9688
<status>
9789
OK
9890
</status>
99-
</response>
91+
</response>
92+
93+
94+
95+
text::
96+
97+
response, body = wrapper.get_fsid(body = 'text')
98+
print('Response: {0}, Body:\n{1}'.format(response, body))
99+
100+
====
101+
102+
Response: <Response [200]>, Body:
103+
d5252e7d-75bc-4083-85ed-fe51fa83f62b
104+
105+
binary::
106+
107+
response, body = wrapper.mon_getmap(body = 'binary')
108+
# < Do something binary with 'body' >
109+
110+
111+
RELEASE NOTES
112+
==================================================
113+
**0.1.0.2**
114+
115+
- Implemented or fixed missing GET calls (All API GET calls that are not under the '/tell' namespace are now supported)
116+
- Client can optionally raise an exception when requesting a unsupported body type for a provided API call (ex: requesting json through the wrapper for a call that is known to only return binary will raise an exception)
117+
- Client now supports binary type responses (ex: crush map, mon map, etc)
118+
- Improved the README (!)
119+
120+
121+
**0.1.0.1**
122+
123+
- First public release of python-cephclient

cephclient/client.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,27 @@ def _request(self, url, method, **kwargs):
7676
elif kwargs['body'] is 'text':
7777
kwargs['headers']['Accept'] = 'text/plain'
7878
kwargs['headers']['Content-Type'] = 'text/plain'
79+
elif kwargs['body'] is 'binary':
80+
kwargs['headers']['Accept'] = 'application/octet-stream'
81+
kwargs['headers']['Content-Type'] = 'application/octet-stream'
7982
else:
80-
raise exceptions.UnknownRequestType()
81-
82-
del kwargs['body']
83+
raise exceptions.UnsupportedRequestType()
8384
except KeyError:
8485
# Default if body type is unspecified is text/plain
8586
kwargs['headers']['Accept'] = 'text/plain'
8687
kwargs['headers']['Content-Type'] = 'text/plain'
8788

89+
# Optionally verify if requested body type is supported
90+
try:
91+
if kwargs['body'] not in kwargs['supported_body_types']:
92+
raise exceptions.UnsupportedBodyType()
93+
else:
94+
del kwargs['supported_body_types']
95+
except KeyError:
96+
pass
97+
98+
del kwargs['body']
99+
88100
self.log.debug("{0} URL: {1}{2} - {3}".format(method,
89101
self.endpoint,
90102
url,

cephclient/exceptions.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,16 @@ def __str__(self):
2323
return "This function is not yet available/completed."
2424

2525

26-
class UnknownRequestType(Exception):
26+
class UnsupportedRequestType(Exception):
2727
"""
2828
If a requested body type is not mapped
2929
"""
3030
def __str__(self):
3131
return "Unknown request type. Requests available: 'json', 'xml', 'text'."
32+
33+
class UnsupportedBodyType(Exception):
34+
"""
35+
If a requested body type is not mapped
36+
"""
37+
def __str__(self):
38+
return "This type of body is not supported for this API call."

cephclient/wrapper.py

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ def mds_dump(self, epoch = None, **kwargs):
109109

110110

111111
def mds_getmap(self, epoch = None, **kwargs):
112+
kwargs['supported_body_types'] = ['binary']
113+
112114
if epoch is not None:
113115
return self.get('mds/getmap?epoch={0}'.format(epoch), **kwargs)
114116
else:
@@ -153,14 +155,22 @@ def osd_find(self, id, **kwargs):
153155
return self.get('osd/find?id={0}'.format(id), **kwargs)
154156

155157

156-
def osd_getcrushmap(self, **kwargs):
157-
# Could not get this to work yet
158-
raise exceptions.FunctionNotImplemented()
158+
def osd_getcrushmap(self, epoch = None, **kwargs):
159+
kwargs['supported_body_types'] = ['binary']
160+
161+
if epoch is not None:
162+
return self.get('osd/getcrushmap?epoch={0}'.format(epoch), **kwargs)
163+
else:
164+
return self.get('osd/getcrushmap', **kwargs)
165+
159166

167+
def osd_getmap(self, epoch = None, **kwargs):
168+
kwargs['supported_body_types'] = ['binary']
160169

161-
def osd_getmap(self, **kwargs):
162-
# Could not get this to work yet
163-
raise exceptions.FunctionNotImplemented()
170+
if epoch is not None:
171+
return self.get('osd/getmap?epoch={0}'.format(epoch), **kwargs)
172+
else:
173+
return self.get('osd/getmap', **kwargs)
164174

165175

166176
def osd_getmaxosd(self, **kwargs):
@@ -181,8 +191,8 @@ def osd_lspools(self, auid = None, **kwargs):
181191
return self.get('osd/lspools', **kwargs)
182192

183193

184-
def osd_map(self, **kwargs):
185-
raise exceptions.FunctionNotImplemented()
194+
def osd_map(self, pool, object, **kwargs):
195+
return self.get('osd/map?pool={0}&object={1}'.format(pool, object), **kwargs)
186196

187197

188198
def osd_perf(self, **kwargs):
@@ -222,13 +232,17 @@ def mon_dump(self, epoch = None, **kwargs):
222232
return self.get('mon/dump', **kwargs)
223233

224234

225-
def mon_getmap(self, **kwargs):
226-
# Could not get this to work yet
227-
raise exceptions.FunctionNotImplemented()
235+
def mon_getmap(self, epoch = None, **kwargs):
236+
kwargs['supported_body_types'] = ['binary']
228237

238+
if epoch is not None:
239+
return self.get('mon/getmap?epoch={0}'.format(epoch), **kwargs)
240+
else:
241+
return self.get('mon/getmap', **kwargs)
229242

230243
def mon_stat(self, **kwargs):
231-
# TODO: Seems broken ? Returns null.
244+
kwargs['supported_body_types'] = ['text', 'xml']
245+
232246
return self.get('mon/stat', **kwargs)
233247

234248

@@ -240,33 +254,43 @@ def mon_status(self, **kwargs):
240254
# pg GET calls
241255
###
242256
def pg_debug(self, debugop, **kwargs):
243-
return self.get('pg/debug?debugop={0}'.format(debugop), kwargs)
257+
kwargs['supported_body_types'] = ['text', 'xml']
244258

259+
return self.get('pg/debug?debugop={0}'.format(debugop), kwargs)
245260

246-
def pg_dump(self, **kwargs):
247-
raise exceptions.FunctionNotImplemented()
248261

262+
def pg_dump(self, dumpcontents = None, **kwargs):
263+
if dumpcontents is not None:
264+
return self.get('pg/dump?dumpcontents={0}'.format(dumpcontents), **kwargs)
265+
else:
266+
return self.get('pg/dump', **kwargs)
249267

250-
def pg_dump_json(self, **kwargs):
251-
raise exceptions.FunctionNotImplemented()
268+
def pg_dump_json(self, dumpcontents = None, **kwargs):
269+
if dumpcontents is not None:
270+
return self.get('pg/dump_json?dumpcontents={0}'.format(dumpcontents), **kwargs)
271+
else:
272+
return self.get('pg/dump_json', **kwargs)
252273

253274

254275
def pg_dump_pools_json(self, **kwargs):
255-
raise exceptions.FunctionNotImplemented()
276+
return self.get('pg/dump_pools_json', **kwargs)
256277

257278

258-
def pg_dump_stuck(self, **kwargs):
259-
raise exceptions.FunctionNotImplemented()
279+
def pg_dump_stuck(self, stuckops = None, **kwargs):
280+
if stuckops is not None:
281+
return self.get('pg/dump_stuck?stuckops={0}'.format(stuckops), **kwargs)
282+
else:
283+
return self.get('pg/dump_stuck', **kwargs)
260284

261285

262286
def pg_getmap(self, **kwargs):
263-
# Could not get this to work yet
264-
raise exceptions.FunctionNotImplemented()
287+
kwargs['supported_body_types'] = ['binary']
288+
289+
return self.get('pg/getmap', **kwargs)
265290

266291

267-
def pg_map(self, **kwargs):
268-
# Could not get this to work yet
269-
raise exceptions.FunctionNotImplemented()
292+
def pg_map(self, pgid, **kwargs):
293+
return self.get('pg/map?pgid={0}'.format(pgid), **kwargs)
270294

271295

272296
def pg_stat(self, **kwargs):

0 commit comments

Comments
 (0)