]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/workunits/rest/test.py
8b55378cf8b6d588c2def15de554b8a4f7fcb628
3 from __future__
import print_function
12 import xml
.etree
.ElementTree
14 BASEURL
= os
.environ
.get('BASEURL', 'http://localhost:5000/api/v0.1')
18 print('FAILURE: url ', r
.url
, file=sys
.stderr
)
19 print(msg
, file=sys
.stderr
)
20 print('Response content: ', r
.text
, file=sys
.stderr
)
21 print('Headers: ', r
.headers
, file=sys
.stderr
)
25 def expect(url
, method
, respcode
, contenttype
, extra_hdrs
=None, data
=None):
26 failmsg
, r
= expect_nofail(url
, method
, respcode
, contenttype
, extra_hdrs
,
33 def expect_nofail(url
, method
, respcode
, contenttype
, extra_hdrs
=None,
36 fdict
= {'get':requests
.get
, 'put':requests
.put
}
37 f
= fdict
[method
.lower()]
38 r
= f(BASEURL
+ '/' + url
, headers
=extra_hdrs
, data
=data
)
40 print('{0} {1}: {2} {3}'.format(method
, url
, contenttype
, r
.status_code
))
42 if r
.status_code
!= respcode
:
43 return 'expected {0}, got {1}'.format(respcode
, r
.status_code
), r
45 r_contenttype
= r
.headers
['content-type']
47 if contenttype
in ['json', 'xml']:
48 contenttype
= 'application/' + contenttype
50 contenttype
= 'text/' + contenttype
52 if contenttype
and r_contenttype
!= contenttype
:
53 return 'expected {0}, got "{1}"'.format(contenttype
, r_contenttype
), r
55 if contenttype
.startswith('application'):
56 if r_contenttype
== 'application/json':
58 # older requests.py doesn't create r.myjson; create it myself
59 r
.myjson
= json
.loads(r
.text
)
60 assert(r
.myjson
is not None)
61 except Exception as e
:
62 return 'Invalid JSON returned: "{0}"'.format(str(e
)), r
64 if r_contenttype
== 'application/xml':
66 # if it's there, squirrel it away for use in the caller
67 r
.tree
= xml
.etree
.ElementTree
.fromstring(r
.text
)
68 except Exception as e
:
69 return 'Invalid XML returned: "{0}"'.format(str(e
)), r
74 JSONHDR
={'accept':'application/json'}
75 XMLHDR
={'accept':'application/xml'}
77 if __name__
== '__main__':
78 expect('auth/export', 'GET', 200, 'plain')
79 expect('auth/export.json', 'GET', 200, 'json')
80 expect('auth/export.xml', 'GET', 200, 'xml')
81 expect('auth/export', 'GET', 200, 'json', JSONHDR
)
82 expect('auth/export', 'GET', 200, 'xml', XMLHDR
)
84 expect('auth/add?entity=client.xx&'
85 'caps=mon&caps=allow&caps=osd&caps=allow+*', 'PUT', 200, 'json',
88 r
= expect('auth/export?entity=client.xx', 'GET', 200, 'plain')
89 # must use text/plain; default is application/x-www-form-urlencoded
90 expect('auth/add?entity=client.xx', 'PUT', 200, 'plain',
91 {'Content-Type':'text/plain'}, data
=r
.text
)
93 r
= expect('auth/list', 'GET', 200, 'plain')
94 assert('client.xx' in r
.text
)
96 r
= expect('auth/list.json', 'GET', 200, 'json')
97 dictlist
= r
.myjson
['output']['auth_dump']
98 xxdict
= [d
for d
in dictlist
if d
['entity'] == 'client.xx'][0]
100 assert('caps' in xxdict
)
101 assert('mon' in xxdict
['caps'])
102 assert('osd' in xxdict
['caps'])
104 expect('auth/get-key?entity=client.xx', 'GET', 200, 'json', JSONHDR
)
105 expect('auth/print-key?entity=client.xx', 'GET', 200, 'json', JSONHDR
)
106 expect('auth/print_key?entity=client.xx', 'GET', 200, 'json', JSONHDR
)
108 expect('auth/caps?entity=client.xx&caps=osd&caps=allow+rw', 'PUT', 200,
110 r
= expect('auth/list.json', 'GET', 200, 'json')
111 dictlist
= r
.myjson
['output']['auth_dump']
112 xxdict
= [d
for d
in dictlist
if d
['entity'] == 'client.xx'][0]
114 assert('caps' in xxdict
)
115 assert(not 'mon' in xxdict
['caps'])
116 assert('osd' in xxdict
['caps'])
117 assert(xxdict
['caps']['osd'] == 'allow rw')
119 # export/import/export, compare
120 r
= expect('auth/export', 'GET', 200, 'plain')
122 assert('client.xx' in exp1
)
123 r
= expect('auth/import', 'PUT', 200, 'plain',
124 {'Content-Type':'text/plain'}, data
=r
.text
)
125 r2
= expect('auth/export', 'GET', 200, 'plain')
126 assert(exp1
== r2
.text
)
127 expect('auth/del?entity=client.xx', 'PUT', 200, 'json', JSONHDR
)
129 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
130 assert('epoch' in r
.myjson
['output'])
132 assert('GLOBAL' in expect('df', 'GET', 200, 'plain').text
)
133 assert('DIRTY' in expect('df?detail=detail', 'GET', 200, 'plain').text
)
134 # test param with no value (treated as param=param)
135 assert('DIRTY' in expect('df?detail', 'GET', 200, 'plain').text
)
137 r
= expect('df', 'GET', 200, 'json', JSONHDR
)
138 assert('total_used_bytes' in r
.myjson
['output']['stats'])
139 r
= expect('df', 'GET', 200, 'xml', XMLHDR
)
140 assert(r
.tree
.find('output/stats/stats/total_used_bytes') is not None)
142 r
= expect('df?detail', 'GET', 200, 'json', JSONHDR
)
143 assert('rd_bytes' in r
.myjson
['output']['pools'][0]['stats'])
144 r
= expect('df?detail', 'GET', 200, 'xml', XMLHDR
)
145 assert(r
.tree
.find('output/stats/pools/pool/stats/rd_bytes') is not None)
147 expect('fsid', 'GET', 200, 'json', JSONHDR
)
148 expect('health', 'GET', 200, 'json', JSONHDR
)
149 expect('health?detail', 'GET', 200, 'json', JSONHDR
)
150 expect('health?detail', 'GET', 200, 'plain')
152 # XXX no ceph -w equivalent yet
154 expect('mds/cluster_down', 'PUT', 200, '')
155 expect('mds/cluster_down', 'PUT', 200, '')
156 expect('mds/cluster_up', 'PUT', 200, '')
157 expect('mds/cluster_up', 'PUT', 200, '')
159 expect('mds/compat/rm_incompat?feature=4', 'PUT', 200, '')
160 expect('mds/compat/rm_incompat?feature=4', 'PUT', 200, '')
162 r
= expect('mds/compat/show', 'GET', 200, 'json', JSONHDR
)
163 assert('incompat' in r
.myjson
['output'])
164 r
= expect('mds/compat/show', 'GET', 200, 'xml', XMLHDR
)
165 assert(r
.tree
.find('output/mds_compat/incompat') is not None)
168 expect('mds/deactivate?who=2', 'PUT', 400, '')
170 r
= expect('mds/dump.xml', 'GET', 200, 'xml')
171 assert(r
.tree
.find('output/mdsmap/created') is not None)
173 expect('fs/flag/set?flag_name=enable_multiple&val=true', 'PUT', 200, '')
174 expect('osd/pool/create?pg_num=1&pool=my_cephfs_metadata', 'PUT', 200, '')
175 expect('osd/pool/create?pg_num=1&pool=my_cephfs_data', 'PUT', 200, '')
176 expect('fs/new?fs_name=mycephfs&metadata=my_cephfs_metadata&data=my_cephfs_data', 'PUT', 200, '')
177 expect('osd/pool/create?pool=data2&pg_num=10', 'PUT', 200, '')
178 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
179 pools
= r
.myjson
['output']['pools']
182 if p
['pool_name'] == 'data2':
184 assert(p
['pg_num'] == 10)
186 assert(poolnum
is not None)
187 expect('mds/add_data_pool?pool={0}'.format(poolnum
), 'PUT', 200, '')
188 expect('mds/remove_data_pool?pool={0}'.format(poolnum
), 'PUT', 200, '')
189 expect('osd/pool/delete?pool=data2&pool2=data2'
190 '&sure=--yes-i-really-really-mean-it', 'PUT', 200, '')
191 expect('mds/set?var=allow_multimds&val=true&confirm=--yes-i-really-mean-it', 'PUT', 200, '')
192 expect('mds/set_max_mds?maxmds=4', 'PUT', 200, '')
193 expect('mds/set?var=max_mds&val=4', 'PUT', 200, '')
194 expect('mds/set?var=max_file_size&val=1048576', 'PUT', 200, '')
195 expect('mds/set?var=allow_new_snaps&val=true&confirm=--yes-i-really-mean-it', 'PUT', 200, '')
196 expect('mds/set?var=allow_new_snaps&val=0', 'PUT', 200, '')
197 expect('mds/set?var=inline_data&val=true&confirm=--yes-i-really-mean-it', 'PUT', 200, '')
198 expect('mds/set?var=inline_data&val=0', 'PUT', 200, '')
199 r
= expect('mds/dump.json', 'GET', 200, 'json')
200 assert(r
.myjson
['output']['max_mds'] == 4)
201 expect('mds/set_max_mds?maxmds=3', 'PUT', 200, '')
202 r
= expect('mds/stat.json', 'GET', 200, 'json')
203 expect('mds/set?var=max_mds&val=2', 'PUT', 200, '')
204 r
= expect('mds/stat.json', 'GET', 200, 'json')
205 assert('epoch' in r
.myjson
['output']['fsmap'])
206 r
= expect('mds/stat.xml', 'GET', 200, 'xml')
207 assert(r
.tree
.find('output/mds_stat/fsmap/epoch') is not None)
209 # more content tests below, just check format here
210 expect('mon/dump.json', 'GET', 200, 'json')
211 expect('mon/dump.xml', 'GET', 200, 'xml')
213 r
= expect('mon/getmap', 'GET', 200, '')
214 assert(len(r
.text
) != 0)
215 r
= expect('mon_status.json', 'GET', 200, 'json')
216 assert('name' in r
.myjson
['output'])
217 r
= expect('mon_status.xml', 'GET', 200, 'xml')
218 assert(r
.tree
.find('output/mon_status/name') is not None)
220 bl
= '192.168.0.1:0/1000'
221 expect('osd/blacklist?blacklistop=add&addr=' + bl
, 'PUT', 200, '')
222 r
= expect('osd/blacklist/ls.json', 'GET', 200, 'json')
223 assert([b
for b
in r
.myjson
['output'] if b
['addr'] == bl
])
224 expect('osd/blacklist?blacklistop=rm&addr=' + bl
, 'PUT', 200, '')
225 r
= expect('osd/blacklist/ls.json', 'GET', 200, 'json')
226 assert([b
for b
in r
.myjson
['output'] if b
['addr'] == bl
] == [])
228 expect('osd/crush/tunables?profile=legacy', 'PUT', 200, '')
229 expect('osd/crush/tunables?profile=bobtail', 'PUT', 200, '')
231 expect('osd/scrub?who=0', 'PUT', 200, '')
232 expect('osd/deep-scrub?who=0', 'PUT', 200, '')
233 expect('osd/repair?who=0', 'PUT', 200, '')
235 expect('osd/set?key=noup', 'PUT', 200, '')
237 expect('osd/down?ids=0', 'PUT', 200, '')
238 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
239 assert(r
.myjson
['output']['osds'][0]['osd'] == 0)
240 assert(r
.myjson
['output']['osds'][0]['up'] == 0)
242 expect('osd/unset?key=noup', 'PUT', 200, '')
244 for i
in range(0,100):
245 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
246 assert(r
.myjson
['output']['osds'][0]['osd'] == 0)
247 if r
.myjson
['output']['osds'][0]['up'] == 1:
250 print("waiting for osd.0 to come back up", file=sys
.stderr
)
253 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
254 assert(r
.myjson
['output']['osds'][0]['osd'] == 0)
255 assert(r
.myjson
['output']['osds'][0]['up'] == 1)
257 r
= expect('osd/find?id=1', 'GET', 200, 'json', JSONHDR
)
258 assert(r
.myjson
['output']['osd'] == 1)
260 expect('osd/out?ids=1', 'PUT', 200, '')
261 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
262 assert(r
.myjson
['output']['osds'][1]['osd'] == 1)
263 assert(r
.myjson
['output']['osds'][1]['in'] == 0)
265 expect('osd/in?ids=1', 'PUT', 200, '')
266 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
267 assert(r
.myjson
['output']['osds'][1]['osd'] == 1)
268 assert(r
.myjson
['output']['osds'][1]['in'] == 1)
270 r
= expect('osd/find?id=0', 'GET', 200, 'json', JSONHDR
)
271 assert(r
.myjson
['output']['osd'] == 0)
273 r
= expect('osd/getmaxosd', 'GET', 200, 'xml', XMLHDR
)
274 assert(r
.tree
.find('output/getmaxosd/max_osd') is not None)
275 r
= expect('osd/getmaxosd', 'GET', 200, 'json', JSONHDR
)
276 saved_maxosd
= r
.myjson
['output']['max_osd']
277 expect('osd/setmaxosd?newmax=10', 'PUT', 200, '')
278 r
= expect('osd/getmaxosd', 'GET', 200, 'json', JSONHDR
)
279 assert(r
.myjson
['output']['max_osd'] == 10)
280 expect('osd/setmaxosd?newmax={0}'.format(saved_maxosd
), 'PUT', 200, '')
281 r
= expect('osd/getmaxosd', 'GET', 200, 'json', JSONHDR
)
282 assert(r
.myjson
['output']['max_osd'] == saved_maxosd
)
284 osd_uuid
=uuid
.uuid1()
285 r
= expect('osd/create?uuid={0}'.format(osd_uuid
), 'PUT', 200, 'json', JSONHDR
)
286 assert('osdid' in r
.myjson
['output'])
287 osdid
= r
.myjson
['output']['osdid']
288 expect('osd/lost?id={0}'.format(osdid
), 'PUT', 400, '')
289 expect('osd/lost?id={0}&sure=--yes-i-really-mean-it'.format(osdid
),
290 'PUT', 200, 'json', JSONHDR
)
291 expect('osd/rm?ids={0}'.format(osdid
), 'PUT', 200, '')
292 r
= expect('osd/ls', 'GET', 200, 'json', JSONHDR
)
293 assert(isinstance(r
.myjson
['output'], list))
294 r
= expect('osd/ls', 'GET', 200, 'xml', XMLHDR
)
295 assert(r
.tree
.find('output/osds/osd') is not None)
297 expect('osd/pause', 'PUT', 200, '')
298 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
299 assert('pauserd,pausewr' in r
.myjson
['output']['flags'])
300 expect('osd/unpause', 'PUT', 200, '')
301 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
302 assert('pauserd,pausewr' not in r
.myjson
['output']['flags'])
304 r
= expect('osd/tree', 'GET', 200, 'json', JSONHDR
)
305 assert('nodes' in r
.myjson
['output'])
306 r
= expect('osd/tree', 'GET', 200, 'xml', XMLHDR
)
307 assert(r
.tree
.find('output/tree/nodes') is not None)
309 expect('osd/pool/create?pool=data2&pg_num=10', 'PUT', 200, '')
310 r
= expect('osd/lspools', 'GET', 200, 'json', JSONHDR
)
311 assert([p
for p
in r
.myjson
['output'] if p
['poolname'] == 'data2'])
312 expect('osd/pool/rename?srcpool=data2&destpool=data3', 'PUT', 200, '')
313 r
= expect('osd/lspools', 'GET', 200, 'json', JSONHDR
)
314 assert([p
for p
in r
.myjson
['output'] if p
['poolname'] == 'data3'])
315 expect('osd/pool/mksnap?pool=data3&snap=datasnap', 'PUT', 200, '')
316 r
= subprocess
.call('rados -p data3 lssnap | grep -q datasnap', shell
=True)
318 expect('osd/pool/rmsnap?pool=data3&snap=datasnap', 'PUT', 200, '')
319 expect('osd/pool/delete?pool=data3', 'PUT', 400, '')
320 expect('osd/pool/delete?pool=data3&pool2=data3&sure=--yes-i-really-really-mean-it', 'PUT', 200, '')
322 r
= expect('osd/stat', 'GET', 200, 'json', JSONHDR
)
323 assert('num_up_osds' in r
.myjson
['output'])
324 r
= expect('osd/stat', 'GET', 200, 'xml', XMLHDR
)
325 assert(r
.tree
.find('output/osdmap/num_up_osds') is not None)
327 r
= expect('osd/ls', 'GET', 200, 'json', JSONHDR
)
328 for osdid
in r
.myjson
['output']:
329 expect('tell/osd.{0}/version'.format(osdid
), 'GET', 200, '')
331 expect('pg/debug?debugop=unfound_objects_exist', 'GET', 200, '')
332 expect('pg/debug?debugop=degraded_pgs_exist', 'GET', 200, '')
333 expect('pg/deep-scrub?pgid=1.0', 'PUT', 200, '')
334 r
= expect('pg/dump', 'GET', 200, 'json', JSONHDR
)
335 assert('pg_stats_sum' in r
.myjson
['output'])
336 r
= expect('pg/dump', 'GET', 200, 'xml', XMLHDR
)
337 assert(r
.tree
.find('output/pg_map/pg_stats_sum') is not None)
339 expect('pg/dump_json', 'GET', 200, 'json', JSONHDR
)
340 expect('pg/dump_pools_json', 'GET', 200, 'json', JSONHDR
)
341 expect('pg/dump_stuck?stuckops=inactive', 'GET', 200, '')
342 expect('pg/dump_stuck?stuckops=unclean', 'GET', 200, '')
343 expect('pg/dump_stuck?stuckops=stale', 'GET', 200, '')
345 r
= expect('pg/getmap', 'GET', 200, '')
346 assert(len(r
.text
) != 0)
348 r
= expect('pg/map?pgid=1.0', 'GET', 200, 'json', JSONHDR
)
349 assert('acting' in r
.myjson
['output'])
350 assert(r
.myjson
['output']['pgid'] == '1.0')
351 r
= expect('pg/map?pgid=1.0', 'GET', 200, 'xml', XMLHDR
)
352 assert(r
.tree
.find('output/pg_map/acting') is not None)
353 assert(r
.tree
.find('output/pg_map/pgid').text
== '1.0')
355 expect('pg/repair?pgid=1.0', 'PUT', 200, '')
356 expect('pg/scrub?pgid=1.0', 'PUT', 200, '')
358 expect('osd/set-full-ratio?ratio=0.90', 'PUT', 200, '')
359 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
360 assert(float(r
.myjson
['output']['full_ratio']) == 0.90)
361 expect('osd/set-full-ratio?ratio=0.95', 'PUT', 200, '')
362 expect('osd/set-backfillfull-ratio?ratio=0.88', 'PUT', 200, '')
363 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
364 assert(float(r
.myjson
['output']['backfillfull_ratio']) == 0.88)
365 expect('osd/set-backfillfull-ratio?ratio=0.90', 'PUT', 200, '')
366 expect('osd/set-nearfull-ratio?ratio=0.90', 'PUT', 200, '')
367 r
= expect('osd/dump', 'GET', 200, 'json', JSONHDR
)
368 assert(float(r
.myjson
['output']['nearfull_ratio']) == 0.90)
369 expect('osd/set-nearfull-ratio?ratio=0.85', 'PUT', 200, '')
371 r
= expect('pg/stat', 'GET', 200, 'json', JSONHDR
)
372 assert('num_pgs' in r
.myjson
['output'])
373 r
= expect('pg/stat', 'GET', 200, 'xml', XMLHDR
)
374 assert(r
.tree
.find('output/pg_summary/num_pgs') is not None)
376 expect('tell/1.0/query', 'GET', 200, 'json', JSONHDR
)
377 expect('quorum?quorumcmd=enter', 'PUT', 200, 'json', JSONHDR
)
378 expect('quorum?quorumcmd=enter', 'PUT', 200, 'xml', XMLHDR
)
379 expect('quorum_status', 'GET', 200, 'json', JSONHDR
)
380 expect('quorum_status', 'GET', 200, 'xml', XMLHDR
)
382 # report's CRC needs to be handled
383 # r = expect('report', 'GET', 200, 'json', JSONHDR)
384 # assert('osd_stats' in r.myjson['output'])
385 # r = expect('report', 'GET', 200, 'xml', XMLHDR)
386 # assert(r.tree.find('output/report/osdmap') is not None)
388 r
= expect('status', 'GET', 200, 'json', JSONHDR
)
389 assert('osdmap' in r
.myjson
['output'])
390 r
= expect('status', 'GET', 200, 'xml', XMLHDR
)
391 assert(r
.tree
.find('output/status/osdmap') is not None)
393 r
= expect('tell/osd.0/version', 'GET', 200, '')
394 assert('ceph version' in r
.text
)
395 expect('tell/osd.999/version', 'GET', 400, '')
396 expect('tell/osd.foo/version', 'GET', 400, '')
398 r
= expect('tell/osd.0/dump_pg_recovery_stats', 'GET', 200, '')
399 assert('Started' in r
.text
)
401 expect('osd/reweight?id=0&weight=0.9', 'PUT', 200, '')
402 expect('osd/reweight?id=0&weight=-1', 'PUT', 400, '')
403 expect('osd/reweight?id=0&weight=1', 'PUT', 200, '')
405 for v
in ['pg_num', 'pgp_num', 'size', 'min_size',
407 r
= expect('osd/pool/get.json?pool=rbd&var=' + v
, 'GET', 200, 'json')
408 assert(v
in r
.myjson
['output'])
410 r
= expect('osd/pool/get.json?pool=rbd&var=size', 'GET', 200, 'json')
411 assert(r
.myjson
['output']['size'] >= 2)
413 expect('osd/pool/set?pool=rbd&var=size&val=3', 'PUT', 200, 'plain')
414 r
= expect('osd/pool/get.json?pool=rbd&var=size', 'GET', 200, 'json')
415 assert(r
.myjson
['output']['size'] == 3)
417 expect('osd/pool/set?pool=rbd&var=size&val=2', 'PUT', 200, 'plain')
418 r
= expect('osd/pool/get.json?pool=rbd&var=size', 'GET', 200, 'json')
419 assert(r
.myjson
['output']['size'] == 2)
421 r
= expect('osd/pool/get.json?pool=rbd&var=crush_rule', 'GET', 200, 'json')
422 assert(r
.myjson
['output']['crush_rule'] == "replicated_rule")