]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | """ |
2 | Rgw admin testing against a running instance | |
3 | """ | |
4 | # The test cases in this file have been annotated for inventory. | |
5 | # To extract the inventory (in csv format) use the command: | |
6 | # | |
7 | # grep '^ *# TESTCASE' | sed 's/^ *# TESTCASE //' | |
8 | # | |
181888fb | 9 | # to run this standalone: |
f38dd50b TL |
10 | # 1. uncomment vstart_runner lines to run locally against a vstart cluster |
11 | # 2. run: | |
12 | # $ python qa/tasks/radosgw_admin.py [--user=uid] --host=host --port=port | |
7c673cae | 13 | |
7c673cae FG |
14 | import json |
15 | import logging | |
16 | import time | |
17 | import datetime | |
181888fb | 18 | import sys |
7c673cae | 19 | |
20effc67 | 20 | from io import StringIO |
f67539c2 | 21 | from queue import Queue |
7c673cae FG |
22 | |
23 | import boto.exception | |
24 | import boto.s3.connection | |
25 | import boto.s3.acl | |
26 | ||
27 | import httplib2 | |
28 | ||
20effc67 | 29 | #import pdb |
7c673cae | 30 | |
f38dd50b | 31 | #import tasks.vstart_runner |
20effc67 TL |
32 | from tasks.rgw import RGWEndpoint |
33 | from tasks.util.rgw import rgwadmin as tasks_util_rgw_rgwadmin | |
34 | from tasks.util.rgw import get_user_summary, get_user_successful_ops | |
7c673cae FG |
35 | |
36 | log = logging.getLogger(__name__) | |
37 | ||
20effc67 TL |
38 | def rgwadmin(*args, **kwargs): |
39 | ctx = args[0] | |
40 | # Is this a local runner? | |
41 | omit_sudo = hasattr(ctx.rgw, 'omit_sudo') and ctx.rgw.omit_sudo == True | |
42 | omit_tdir = hasattr(ctx.rgw, 'omit_tdir') and ctx.rgw.omit_tdir == True | |
43 | return tasks_util_rgw_rgwadmin(*args, **kwargs, omit_sudo=omit_sudo, omit_tdir=omit_tdir) | |
44 | ||
181888fb FG |
45 | def usage_acc_findentry2(entries, user, add=True): |
46 | for e in entries: | |
47 | if e['user'] == user: | |
48 | return e | |
49 | if not add: | |
50 | return None | |
51 | e = {'user': user, 'buckets': []} | |
52 | entries.append(e) | |
53 | return e | |
54 | def usage_acc_findsum2(summaries, user, add=True): | |
55 | for e in summaries: | |
56 | if e['user'] == user: | |
57 | return e | |
58 | if not add: | |
59 | return None | |
60 | e = {'user': user, 'categories': [], | |
61 | 'total': {'bytes_received': 0, | |
62 | 'bytes_sent': 0, 'ops': 0, 'successful_ops': 0 }} | |
63 | summaries.append(e) | |
64 | return e | |
65 | def usage_acc_update2(x, out, b_in, err): | |
66 | x['bytes_sent'] += b_in | |
67 | x['bytes_received'] += out | |
68 | x['ops'] += 1 | |
69 | if not err: | |
70 | x['successful_ops'] += 1 | |
71 | def usage_acc_validate_fields(r, x, x2, what): | |
72 | q=[] | |
73 | for field in ['bytes_sent', 'bytes_received', 'ops', 'successful_ops']: | |
74 | try: | |
75 | if x2[field] < x[field]: | |
76 | q.append("field %s: %d < %d" % (field, x2[field], x[field])) | |
77 | except Exception as ex: | |
78 | r.append( "missing/bad field " + field + " in " + what + " " + str(ex)) | |
79 | return | |
80 | if len(q) > 0: | |
81 | r.append("incomplete counts in " + what + ": " + ", ".join(q)) | |
82 | class usage_acc: | |
83 | def __init__(self): | |
84 | self.results = {'entries': [], 'summary': []} | |
85 | def findentry(self, user): | |
86 | return usage_acc_findentry2(self.results['entries'], user) | |
87 | def findsum(self, user): | |
88 | return usage_acc_findsum2(self.results['summary'], user) | |
89 | def e2b(self, e, bucket, add=True): | |
90 | for b in e['buckets']: | |
91 | if b['bucket'] == bucket: | |
92 | return b | |
93 | if not add: | |
94 | return None | |
95 | b = {'bucket': bucket, 'categories': []} | |
96 | e['buckets'].append(b) | |
97 | return b | |
98 | def c2x(self, c, cat, add=True): | |
99 | for x in c: | |
100 | if x['category'] == cat: | |
101 | return x | |
102 | if not add: | |
103 | return None | |
104 | x = {'bytes_received': 0, 'category': cat, | |
105 | 'bytes_sent': 0, 'ops': 0, 'successful_ops': 0 } | |
106 | c.append(x) | |
107 | return x | |
108 | def update(self, c, cat, user, out, b_in, err): | |
109 | x = self.c2x(c, cat) | |
110 | usage_acc_update2(x, out, b_in, err) | |
e306af50 | 111 | if not err and cat == 'create_bucket' and 'owner' not in x: |
181888fb FG |
112 | x['owner'] = user |
113 | def make_entry(self, cat, bucket, user, out, b_in, err): | |
114 | if cat == 'create_bucket' and err: | |
115 | return | |
116 | e = self.findentry(user) | |
117 | b = self.e2b(e, bucket) | |
118 | self.update(b['categories'], cat, user, out, b_in, err) | |
119 | s = self.findsum(user) | |
120 | x = self.c2x(s['categories'], cat) | |
121 | usage_acc_update2(x, out, b_in, err) | |
122 | x = s['total'] | |
123 | usage_acc_update2(x, out, b_in, err) | |
124 | def generate_make_entry(self): | |
125 | return lambda cat,bucket,user,out,b_in,err: self.make_entry(cat, bucket, user, out, b_in, err) | |
126 | def get_usage(self): | |
127 | return self.results | |
128 | def compare_results(self, results): | |
e306af50 | 129 | if 'entries' not in results or 'summary' not in results: |
181888fb FG |
130 | return ['Missing entries or summary'] |
131 | r = [] | |
132 | for e in self.results['entries']: | |
133 | try: | |
134 | e2 = usage_acc_findentry2(results['entries'], e['user'], False) | |
135 | except Exception as ex: | |
136 | r.append("malformed entry looking for user " | |
137 | + e['user'] + " " + str(ex)) | |
138 | break | |
139 | if e2 == None: | |
140 | r.append("missing entry for user " + e['user']) | |
141 | continue | |
142 | for b in e['buckets']: | |
143 | c = b['categories'] | |
144 | if b['bucket'] == 'nosuchbucket': | |
9f95a23c | 145 | print("got here") |
181888fb FG |
146 | try: |
147 | b2 = self.e2b(e2, b['bucket'], False) | |
148 | if b2 != None: | |
149 | c2 = b2['categories'] | |
150 | except Exception as ex: | |
151 | r.append("malformed entry looking for bucket " | |
152 | + b['bucket'] + " in user " + e['user'] + " " + str(ex)) | |
153 | break | |
154 | if b2 == None: | |
155 | r.append("can't find bucket " + b['bucket'] | |
156 | + " in user " + e['user']) | |
157 | continue | |
158 | for x in c: | |
159 | try: | |
160 | x2 = self.c2x(c2, x['category'], False) | |
161 | except Exception as ex: | |
162 | r.append("malformed entry looking for " | |
163 | + x['category'] + " in bucket " + b['bucket'] | |
164 | + " user " + e['user'] + " " + str(ex)) | |
165 | break | |
166 | usage_acc_validate_fields(r, x, x2, "entry: category " | |
167 | + x['category'] + " bucket " + b['bucket'] | |
168 | + " in user " + e['user']) | |
169 | for s in self.results['summary']: | |
170 | c = s['categories'] | |
171 | try: | |
172 | s2 = usage_acc_findsum2(results['summary'], s['user'], False) | |
173 | except Exception as ex: | |
174 | r.append("malformed summary looking for user " + e['user'] | |
175 | + " " + str(ex)) | |
176 | break | |
9f95a23c TL |
177 | if s2 == None: |
178 | r.append("missing summary for user " + e['user'] + " " + str(ex)) | |
179 | continue | |
181888fb FG |
180 | try: |
181 | c2 = s2['categories'] | |
182 | except Exception as ex: | |
183 | r.append("malformed summary missing categories for user " | |
184 | + e['user'] + " " + str(ex)) | |
185 | break | |
186 | for x in c: | |
187 | try: | |
188 | x2 = self.c2x(c2, x['category'], False) | |
189 | except Exception as ex: | |
190 | r.append("malformed summary looking for " | |
191 | + x['category'] + " user " + e['user'] + " " + str(ex)) | |
192 | break | |
193 | usage_acc_validate_fields(r, x, x2, "summary: category " | |
194 | + x['category'] + " in user " + e['user']) | |
195 | x = s['total'] | |
196 | try: | |
197 | x2 = s2['total'] | |
198 | except Exception as ex: | |
199 | r.append("malformed summary looking for totals for user " | |
9f95a23c | 200 | + e['user'] + " " + str(ex)) |
181888fb FG |
201 | break |
202 | usage_acc_validate_fields(r, x, x2, "summary: totals for user" + e['user']) | |
203 | return r | |
204 | ||
205 | def ignore_this_entry(cat, bucket, user, out, b_in, err): | |
206 | pass | |
207 | class requestlog_queue(): | |
208 | def __init__(self, add): | |
f67539c2 | 209 | self.q = Queue(1000) |
181888fb FG |
210 | self.adder = add |
211 | def handle_request_data(self, request, response, error=False): | |
212 | now = datetime.datetime.now() | |
9f95a23c TL |
213 | if error: |
214 | pass | |
215 | elif response.status < 200 or response.status >= 400: | |
216 | error = True | |
92f5a8d4 | 217 | self.q.put({'t': now, 'o': request, 'i': response, 'e': error}) |
181888fb FG |
218 | def clear(self): |
219 | with self.q.mutex: | |
220 | self.q.queue.clear() | |
221 | def log_and_clear(self, cat, bucket, user, add_entry = None): | |
222 | while not self.q.empty(): | |
223 | j = self.q.get() | |
9f95a23c | 224 | bytes_out = 0 |
92f5a8d4 | 225 | if 'Content-Length' in j['o'].headers: |
9f95a23c | 226 | bytes_out = int(j['o'].headers['Content-Length']) |
181888fb | 227 | bytes_in = 0 |
f67539c2 | 228 | msg = j['i'].msg |
e306af50 TL |
229 | if 'content-length'in msg: |
230 | bytes_in = int(msg['content-length']) | |
181888fb | 231 | log.info('RL: %s %s %s bytes_out=%d bytes_in=%d failed=%r' |
9f95a23c TL |
232 | % (cat, bucket, user, bytes_out, bytes_in, j['e'])) |
233 | if add_entry == None: | |
234 | add_entry = self.adder | |
235 | add_entry(cat, bucket, user, bytes_out, bytes_in, j['e']) | |
181888fb | 236 | |
7c673cae FG |
237 | def create_presigned_url(conn, method, bucket_name, key_name, expiration): |
238 | return conn.generate_url(expires_in=expiration, | |
239 | method=method, | |
240 | bucket=bucket_name, | |
241 | key=key_name, | |
242 | query_auth=True, | |
243 | ) | |
244 | ||
245 | def send_raw_http_request(conn, method, bucket_name, key_name, follow_redirects = False): | |
246 | url = create_presigned_url(conn, method, bucket_name, key_name, 3600) | |
9f95a23c | 247 | print(url) |
7c673cae FG |
248 | h = httplib2.Http() |
249 | h.follow_redirects = follow_redirects | |
250 | return h.request(url, method) | |
251 | ||
252 | ||
253 | def get_acl(key): | |
254 | """ | |
255 | Helper function to get the xml acl from a key, ensuring that the xml | |
256 | version tag is removed from the acl response | |
257 | """ | |
f67539c2 | 258 | raw_acl = key.get_xml_acl().decode() |
7c673cae FG |
259 | |
260 | def remove_version(string): | |
261 | return string.split( | |
262 | '<?xml version="1.0" encoding="UTF-8"?>' | |
263 | )[-1] | |
264 | ||
265 | def remove_newlines(string): | |
266 | return string.strip('\n') | |
267 | ||
268 | return remove_version( | |
269 | remove_newlines(raw_acl) | |
270 | ) | |
271 | ||
20effc67 TL |
272 | def cleanup(ctx, client): |
273 | # remove objects and buckets | |
274 | (err, out) = rgwadmin(ctx, client, ['bucket', 'list'], check_status=True) | |
275 | try: | |
276 | for bucket in out: | |
277 | (err, out) = rgwadmin(ctx, client, [ | |
278 | 'bucket', 'rm', '--bucket', bucket, '--purge-objects'], | |
279 | check_status=True) | |
280 | except: | |
281 | pass | |
282 | ||
283 | # remove test user(s) | |
284 | users = ['foo', 'fud', 'bar', 'bud'] | |
285 | users.reverse() | |
286 | for user in users: | |
287 | try: | |
288 | (err, out) = rgwadmin(ctx, client, [ | |
289 | 'user', 'rm', '--uid', user], | |
290 | check_status=True) | |
291 | except: | |
292 | pass | |
293 | ||
294 | # remove custom placement | |
295 | try: | |
296 | zonecmd = ['zone', 'placement', 'rm', '--rgw-zone', 'default', | |
297 | '--placement-id', 'new-placement'] | |
298 | (err, out) = rgwadmin(ctx, client, zonecmd, check_status=True) | |
299 | except: | |
300 | pass | |
301 | ||
7c673cae FG |
302 | def task(ctx, config): |
303 | """ | |
304 | Test radosgw-admin functionality against a running rgw instance. | |
305 | """ | |
306 | global log | |
307 | ||
7c673cae FG |
308 | assert ctx.rgw.config, \ |
309 | "radosgw_admin task needs a config passed from the rgw task" | |
310 | config = ctx.rgw.config | |
311 | log.debug('config is: %r', config) | |
312 | ||
313 | clients_from_config = config.keys() | |
314 | ||
315 | # choose first client as default | |
e306af50 | 316 | client = next(iter(clients_from_config)) |
7c673cae | 317 | |
7c673cae FG |
318 | # once the client is chosen, pull the host name and assigned port out of |
319 | # the role_endpoints that were assigned by the rgw task | |
11fdf7f2 | 320 | endpoint = ctx.rgw.role_endpoints[client] |
7c673cae | 321 | |
20effc67 TL |
322 | cleanup(ctx, client) |
323 | ||
7c673cae FG |
324 | ## |
325 | user1='foo' | |
326 | user2='fud' | |
9f95a23c TL |
327 | user3='bar' |
328 | user4='bud' | |
7c673cae FG |
329 | subuser1='foo:foo1' |
330 | subuser2='foo:foo2' | |
331 | display_name1='Foo' | |
332 | display_name2='Fud' | |
9f95a23c | 333 | display_name3='Bar' |
7c673cae | 334 | email='foo@foo.com' |
7c673cae FG |
335 | access_key='9te6NH5mcdcq0Tc5i8i1' |
336 | secret_key='Ny4IOauQoL18Gp2zM7lC1vLmoawgqcYP/YGcWfXu' | |
337 | access_key2='p5YnriCv1nAtykxBrupQ' | |
338 | secret_key2='Q8Tk6Q/27hfbFSYdSkPtUqhqx1GgzvpXa4WARozh' | |
9f95a23c TL |
339 | access_key3='NX5QOQKC6BH2IDN8HC7A' |
340 | secret_key3='LnEsqNNqZIpkzauboDcLXLcYaWwLQ3Kop0zAnKIn' | |
7c673cae FG |
341 | swift_secret1='gpS2G9RREMrnbqlp29PP2D36kgPR1tm72n5fPYfL' |
342 | swift_secret2='ri2VJQcKSYATOY6uaDUX7pxgkW+W1YmC6OCxPHwy' | |
343 | ||
344 | bucket_name='myfoo' | |
345 | bucket_name2='mybar' | |
346 | ||
347 | # connect to rgw | |
348 | connection = boto.s3.connection.S3Connection( | |
349 | aws_access_key_id=access_key, | |
350 | aws_secret_access_key=secret_key, | |
351 | is_secure=False, | |
11fdf7f2 TL |
352 | port=endpoint.port, |
353 | host=endpoint.hostname, | |
7c673cae FG |
354 | calling_format=boto.s3.connection.OrdinaryCallingFormat(), |
355 | ) | |
20effc67 TL |
356 | connection.auth_region_name='us-east-1' |
357 | ||
7c673cae FG |
358 | connection2 = boto.s3.connection.S3Connection( |
359 | aws_access_key_id=access_key2, | |
360 | aws_secret_access_key=secret_key2, | |
361 | is_secure=False, | |
11fdf7f2 TL |
362 | port=endpoint.port, |
363 | host=endpoint.hostname, | |
7c673cae FG |
364 | calling_format=boto.s3.connection.OrdinaryCallingFormat(), |
365 | ) | |
20effc67 TL |
366 | connection2.auth_region_name='us-east-1' |
367 | ||
9f95a23c TL |
368 | connection3 = boto.s3.connection.S3Connection( |
369 | aws_access_key_id=access_key3, | |
370 | aws_secret_access_key=secret_key3, | |
371 | is_secure=False, | |
372 | port=endpoint.port, | |
373 | host=endpoint.hostname, | |
374 | calling_format=boto.s3.connection.OrdinaryCallingFormat(), | |
375 | ) | |
20effc67 | 376 | connection3.auth_region_name='us-east-1' |
7c673cae | 377 | |
181888fb FG |
378 | acc = usage_acc() |
379 | rl = requestlog_queue(acc.generate_make_entry()) | |
380 | connection.set_request_hook(rl) | |
381 | connection2.set_request_hook(rl) | |
9f95a23c | 382 | connection3.set_request_hook(rl) |
181888fb | 383 | |
7c673cae FG |
384 | # legend (test cases can be easily grep-ed out) |
385 | # TESTCASE 'testname','object','method','operation','assertion' | |
181888fb FG |
386 | |
387 | # TESTCASE 'usage-show0' 'usage' 'show' 'all usage' 'succeeds' | |
388 | (err, summary0) = rgwadmin(ctx, client, ['usage', 'show'], check_status=True) | |
389 | ||
7c673cae FG |
390 | # TESTCASE 'info-nosuch','user','info','non-existent user','fails' |
391 | (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user1]) | |
392 | assert err | |
393 | ||
394 | # TESTCASE 'create-ok','user','create','w/all valid info','succeeds' | |
395 | (err, out) = rgwadmin(ctx, client, [ | |
396 | 'user', 'create', | |
397 | '--uid', user1, | |
398 | '--display-name', display_name1, | |
399 | '--email', email, | |
400 | '--access-key', access_key, | |
401 | '--secret', secret_key, | |
402 | '--max-buckets', '4' | |
403 | ], | |
404 | check_status=True) | |
405 | ||
406 | # TESTCASE 'duplicate email','user','create','existing user email','fails' | |
407 | (err, out) = rgwadmin(ctx, client, [ | |
408 | 'user', 'create', | |
409 | '--uid', user2, | |
410 | '--display-name', display_name2, | |
411 | '--email', email, | |
412 | ]) | |
413 | assert err | |
414 | ||
415 | # TESTCASE 'info-existing','user','info','existing user','returns correct info' | |
416 | (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user1], check_status=True) | |
417 | assert out['user_id'] == user1 | |
418 | assert out['email'] == email | |
419 | assert out['display_name'] == display_name1 | |
420 | assert len(out['keys']) == 1 | |
421 | assert out['keys'][0]['access_key'] == access_key | |
422 | assert out['keys'][0]['secret_key'] == secret_key | |
423 | assert not out['suspended'] | |
424 | ||
7c673cae FG |
425 | # TESTCASE 'suspend-ok','user','suspend','active user','succeeds' |
426 | (err, out) = rgwadmin(ctx, client, ['user', 'suspend', '--uid', user1], | |
427 | check_status=True) | |
428 | ||
429 | # TESTCASE 'suspend-suspended','user','suspend','suspended user','succeeds w/advisory' | |
430 | (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user1], check_status=True) | |
431 | assert out['suspended'] | |
432 | ||
433 | # TESTCASE 're-enable','user','enable','suspended user','succeeds' | |
434 | (err, out) = rgwadmin(ctx, client, ['user', 'enable', '--uid', user1], check_status=True) | |
435 | ||
436 | # TESTCASE 'info-re-enabled','user','info','re-enabled user','no longer suspended' | |
437 | (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user1], check_status=True) | |
438 | assert not out['suspended'] | |
439 | ||
440 | # TESTCASE 'add-keys','key','create','w/valid info','succeeds' | |
441 | (err, out) = rgwadmin(ctx, client, [ | |
442 | 'key', 'create', '--uid', user1, | |
443 | '--access-key', access_key2, '--secret', secret_key2, | |
444 | ], check_status=True) | |
445 | ||
446 | # TESTCASE 'info-new-key','user','info','after key addition','returns all keys' | |
447 | (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user1], | |
448 | check_status=True) | |
449 | assert len(out['keys']) == 2 | |
450 | assert out['keys'][0]['access_key'] == access_key2 or out['keys'][1]['access_key'] == access_key2 | |
451 | assert out['keys'][0]['secret_key'] == secret_key2 or out['keys'][1]['secret_key'] == secret_key2 | |
452 | ||
453 | # TESTCASE 'rm-key','key','rm','newly added key','succeeds, key is removed' | |
454 | (err, out) = rgwadmin(ctx, client, [ | |
455 | 'key', 'rm', '--uid', user1, | |
456 | '--access-key', access_key2, | |
457 | ], check_status=True) | |
458 | assert len(out['keys']) == 1 | |
459 | assert out['keys'][0]['access_key'] == access_key | |
460 | assert out['keys'][0]['secret_key'] == secret_key | |
461 | ||
462 | # TESTCASE 'add-swift-key','key','create','swift key','succeeds' | |
463 | subuser_access = 'full' | |
464 | subuser_perm = 'full-control' | |
465 | ||
466 | (err, out) = rgwadmin(ctx, client, [ | |
467 | 'subuser', 'create', '--subuser', subuser1, | |
468 | '--access', subuser_access | |
469 | ], check_status=True) | |
470 | ||
471 | # TESTCASE 'add-swift-key','key','create','swift key','succeeds' | |
472 | (err, out) = rgwadmin(ctx, client, [ | |
473 | 'subuser', 'modify', '--subuser', subuser1, | |
474 | '--secret', swift_secret1, | |
475 | '--key-type', 'swift', | |
476 | ], check_status=True) | |
477 | ||
478 | # TESTCASE 'subuser-perm-mask', 'subuser', 'info', 'test subuser perm mask durability', 'succeeds' | |
479 | (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user1]) | |
480 | ||
481 | assert out['subusers'][0]['permissions'] == subuser_perm | |
482 | ||
483 | # TESTCASE 'info-swift-key','user','info','after key addition','returns all keys' | |
484 | (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user1], check_status=True) | |
485 | assert len(out['swift_keys']) == 1 | |
486 | assert out['swift_keys'][0]['user'] == subuser1 | |
487 | assert out['swift_keys'][0]['secret_key'] == swift_secret1 | |
488 | ||
489 | # TESTCASE 'add-swift-subuser','key','create','swift sub-user key','succeeds' | |
490 | (err, out) = rgwadmin(ctx, client, [ | |
491 | 'subuser', 'create', '--subuser', subuser2, | |
492 | '--secret', swift_secret2, | |
493 | '--key-type', 'swift', | |
494 | ], check_status=True) | |
495 | ||
496 | # TESTCASE 'info-swift-subuser','user','info','after key addition','returns all sub-users/keys' | |
497 | (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user1], check_status=True) | |
498 | assert len(out['swift_keys']) == 2 | |
499 | assert out['swift_keys'][0]['user'] == subuser2 or out['swift_keys'][1]['user'] == subuser2 | |
500 | assert out['swift_keys'][0]['secret_key'] == swift_secret2 or out['swift_keys'][1]['secret_key'] == swift_secret2 | |
501 | ||
502 | # TESTCASE 'rm-swift-key1','key','rm','subuser','succeeds, one key is removed' | |
503 | (err, out) = rgwadmin(ctx, client, [ | |
504 | 'key', 'rm', '--subuser', subuser1, | |
505 | '--key-type', 'swift', | |
506 | ], check_status=True) | |
507 | assert len(out['swift_keys']) == 1 | |
508 | ||
509 | # TESTCASE 'rm-subuser','subuser','rm','subuser','success, subuser is removed' | |
510 | (err, out) = rgwadmin(ctx, client, [ | |
511 | 'subuser', 'rm', '--subuser', subuser1, | |
512 | ], check_status=True) | |
513 | assert len(out['subusers']) == 1 | |
514 | ||
515 | # TESTCASE 'rm-subuser-with-keys','subuser','rm','subuser','succeeds, second subser and key is removed' | |
516 | (err, out) = rgwadmin(ctx, client, [ | |
517 | 'subuser', 'rm', '--subuser', subuser2, | |
518 | '--key-type', 'swift', '--purge-keys', | |
519 | ], check_status=True) | |
520 | assert len(out['swift_keys']) == 0 | |
521 | assert len(out['subusers']) == 0 | |
522 | ||
523 | # TESTCASE 'bucket-stats','bucket','stats','no session/buckets','succeeds, empty list' | |
524 | (err, out) = rgwadmin(ctx, client, ['bucket', 'stats', '--uid', user1], | |
525 | check_status=True) | |
526 | assert len(out) == 0 | |
527 | ||
7c673cae FG |
528 | # TESTCASE 'bucket-stats2','bucket','stats','no buckets','succeeds, empty list' |
529 | (err, out) = rgwadmin(ctx, client, ['bucket', 'list', '--uid', user1], check_status=True) | |
530 | assert len(out) == 0 | |
531 | ||
532 | # create a first bucket | |
533 | bucket = connection.create_bucket(bucket_name) | |
534 | ||
181888fb FG |
535 | rl.log_and_clear("create_bucket", bucket_name, user1) |
536 | ||
7c673cae FG |
537 | # TESTCASE 'bucket-list','bucket','list','one bucket','succeeds, expected list' |
538 | (err, out) = rgwadmin(ctx, client, ['bucket', 'list', '--uid', user1], check_status=True) | |
539 | assert len(out) == 1 | |
540 | assert out[0] == bucket_name | |
541 | ||
181888fb FG |
542 | bucket_list = connection.get_all_buckets() |
543 | assert len(bucket_list) == 1 | |
544 | assert bucket_list[0].name == bucket_name | |
545 | ||
546 | rl.log_and_clear("list_buckets", '', user1) | |
547 | ||
7c673cae FG |
548 | # TESTCASE 'bucket-list-all','bucket','list','all buckets','succeeds, expected list' |
549 | (err, out) = rgwadmin(ctx, client, ['bucket', 'list'], check_status=True) | |
550 | assert len(out) >= 1 | |
551 | assert bucket_name in out; | |
552 | ||
553 | # TESTCASE 'max-bucket-limit,'bucket','create','4 buckets','5th bucket fails due to max buckets == 4' | |
554 | bucket2 = connection.create_bucket(bucket_name + '2') | |
181888fb | 555 | rl.log_and_clear("create_bucket", bucket_name + '2', user1) |
7c673cae | 556 | bucket3 = connection.create_bucket(bucket_name + '3') |
181888fb | 557 | rl.log_and_clear("create_bucket", bucket_name + '3', user1) |
7c673cae | 558 | bucket4 = connection.create_bucket(bucket_name + '4') |
181888fb | 559 | rl.log_and_clear("create_bucket", bucket_name + '4', user1) |
7c673cae FG |
560 | # the 5th should fail. |
561 | failed = False | |
562 | try: | |
563 | connection.create_bucket(bucket_name + '5') | |
564 | except Exception: | |
565 | failed = True | |
566 | assert failed | |
181888fb | 567 | rl.log_and_clear("create_bucket", bucket_name + '5', user1) |
7c673cae FG |
568 | |
569 | # delete the buckets | |
570 | bucket2.delete() | |
181888fb | 571 | rl.log_and_clear("delete_bucket", bucket_name + '2', user1) |
7c673cae | 572 | bucket3.delete() |
181888fb | 573 | rl.log_and_clear("delete_bucket", bucket_name + '3', user1) |
7c673cae | 574 | bucket4.delete() |
181888fb | 575 | rl.log_and_clear("delete_bucket", bucket_name + '4', user1) |
7c673cae FG |
576 | |
577 | # TESTCASE 'bucket-stats3','bucket','stats','new empty bucket','succeeds, empty list' | |
578 | (err, out) = rgwadmin(ctx, client, [ | |
579 | 'bucket', 'stats', '--bucket', bucket_name], check_status=True) | |
580 | assert out['owner'] == user1 | |
581 | bucket_id = out['id'] | |
582 | ||
583 | # TESTCASE 'bucket-stats4','bucket','stats','new empty bucket','succeeds, expected bucket ID' | |
584 | (err, out) = rgwadmin(ctx, client, ['bucket', 'stats', '--uid', user1], check_status=True) | |
585 | assert len(out) == 1 | |
586 | assert out[0]['id'] == bucket_id # does it return the same ID twice in a row? | |
587 | ||
588 | # use some space | |
589 | key = boto.s3.key.Key(bucket) | |
590 | key.set_contents_from_string('one') | |
181888fb | 591 | rl.log_and_clear("put_obj", bucket_name, user1) |
7c673cae FG |
592 | |
593 | # TESTCASE 'bucket-stats5','bucket','stats','after creating key','succeeds, lists one non-empty object' | |
594 | (err, out) = rgwadmin(ctx, client, [ | |
595 | 'bucket', 'stats', '--bucket', bucket_name], check_status=True) | |
596 | assert out['id'] == bucket_id | |
597 | assert out['usage']['rgw.main']['num_objects'] == 1 | |
598 | assert out['usage']['rgw.main']['size_kb'] > 0 | |
599 | ||
9f95a23c TL |
600 | #validate we have a positive user stats now |
601 | (err, out) = rgwadmin(ctx, client, | |
602 | ['user', 'stats','--uid', user1, '--sync-stats'], | |
603 | check_status=True) | |
604 | assert out['stats']['size'] > 0 | |
605 | ||
7c673cae FG |
606 | # reclaim it |
607 | key.delete() | |
181888fb | 608 | rl.log_and_clear("delete_obj", bucket_name, user1) |
7c673cae FG |
609 | |
610 | # TESTCASE 'bucket unlink', 'bucket', 'unlink', 'unlink bucket from user', 'fails', 'access denied error' | |
611 | (err, out) = rgwadmin(ctx, client, | |
612 | ['bucket', 'unlink', '--uid', user1, '--bucket', bucket_name], | |
613 | check_status=True) | |
614 | ||
615 | # create a second user to link the bucket to | |
616 | (err, out) = rgwadmin(ctx, client, [ | |
617 | 'user', 'create', | |
618 | '--uid', user2, | |
619 | '--display-name', display_name2, | |
620 | '--access-key', access_key2, | |
621 | '--secret', secret_key2, | |
622 | '--max-buckets', '1', | |
623 | ], | |
624 | check_status=True) | |
625 | ||
626 | # try creating an object with the first user before the bucket is relinked | |
627 | denied = False | |
628 | key = boto.s3.key.Key(bucket) | |
629 | ||
630 | try: | |
631 | key.set_contents_from_string('two') | |
632 | except boto.exception.S3ResponseError: | |
633 | denied = True | |
634 | ||
635 | assert not denied | |
181888fb | 636 | rl.log_and_clear("put_obj", bucket_name, user1) |
7c673cae FG |
637 | |
638 | # delete the object | |
639 | key.delete() | |
181888fb | 640 | rl.log_and_clear("delete_obj", bucket_name, user1) |
7c673cae FG |
641 | |
642 | # link the bucket to another user | |
643 | (err, out) = rgwadmin(ctx, client, ['metadata', 'get', 'bucket:{n}'.format(n=bucket_name)], | |
644 | check_status=True) | |
645 | ||
646 | bucket_data = out['data'] | |
647 | assert bucket_data['bucket']['name'] == bucket_name | |
648 | ||
649 | bucket_id = bucket_data['bucket']['bucket_id'] | |
650 | ||
651 | # link the bucket to another user | |
652 | (err, out) = rgwadmin(ctx, client, ['bucket', 'link', '--uid', user2, '--bucket', bucket_name, '--bucket-id', bucket_id], | |
653 | check_status=True) | |
654 | ||
655 | # try to remove user, should fail (has a linked bucket) | |
656 | (err, out) = rgwadmin(ctx, client, ['user', 'rm', '--uid', user2]) | |
657 | assert err | |
658 | ||
659 | # TESTCASE 'bucket unlink', 'bucket', 'unlink', 'unlink bucket from user', 'succeeds, bucket unlinked' | |
660 | (err, out) = rgwadmin(ctx, client, ['bucket', 'unlink', '--uid', user2, '--bucket', bucket_name], | |
661 | check_status=True) | |
662 | ||
663 | # relink the bucket to the first user and delete the second user | |
664 | (err, out) = rgwadmin(ctx, client, | |
665 | ['bucket', 'link', '--uid', user1, '--bucket', bucket_name, '--bucket-id', bucket_id], | |
666 | check_status=True) | |
667 | ||
668 | (err, out) = rgwadmin(ctx, client, ['user', 'rm', '--uid', user2], | |
669 | check_status=True) | |
670 | ||
9f95a23c TL |
671 | #TESTCASE 'bucket link', 'bucket', 'tenanted user', 'succeeds' |
672 | tenant_name = "testx" | |
673 | # create a tenanted user to link the bucket to | |
674 | (err, out) = rgwadmin(ctx, client, [ | |
675 | 'user', 'create', | |
676 | '--tenant', tenant_name, | |
677 | '--uid', 'tenanteduser', | |
678 | '--display-name', 'tenanted-user', | |
679 | '--access-key', access_key2, | |
680 | '--secret', secret_key2, | |
681 | '--max-buckets', '1', | |
682 | ], | |
683 | check_status=True) | |
684 | ||
685 | # link the bucket to a tenanted user | |
686 | (err, out) = rgwadmin(ctx, client, ['bucket', 'link', '--bucket', '/' + bucket_name, '--tenant', tenant_name, '--uid', 'tenanteduser'], | |
687 | check_status=True) | |
688 | ||
689 | # check if the bucket name has tenant/ prefix | |
690 | (err, out) = rgwadmin(ctx, client, ['metadata', 'get', 'bucket:{n}'.format(n= tenant_name + '/' + bucket_name)], | |
691 | check_status=True) | |
692 | ||
693 | bucket_data = out['data'] | |
694 | assert bucket_data['bucket']['name'] == bucket_name | |
695 | assert bucket_data['bucket']['tenant'] == tenant_name | |
696 | ||
697 | # relink the bucket to the first user and delete the tenanted user | |
698 | (err, out) = rgwadmin(ctx, client, | |
699 | ['bucket', 'link', '--bucket', tenant_name + '/' + bucket_name, '--uid', user1], | |
700 | check_status=True) | |
701 | ||
702 | (err, out) = rgwadmin(ctx, client, ['user', 'rm', '--tenant', tenant_name, '--uid', 'tenanteduser'], | |
703 | check_status=True) | |
704 | ||
7c673cae FG |
705 | # TESTCASE 'object-rm', 'object', 'rm', 'remove object', 'succeeds, object is removed' |
706 | ||
707 | # upload an object | |
708 | object_name = 'four' | |
709 | key = boto.s3.key.Key(bucket, object_name) | |
710 | key.set_contents_from_string(object_name) | |
181888fb FG |
711 | rl.log_and_clear("put_obj", bucket_name, user1) |
712 | ||
713 | # fetch it too (for usage stats presently) | |
e306af50 | 714 | s = key.get_contents_as_string(encoding='ascii') |
181888fb FG |
715 | rl.log_and_clear("get_obj", bucket_name, user1) |
716 | assert s == object_name | |
717 | # list bucket too (for usage stats presently) | |
718 | keys = list(bucket.list()) | |
719 | rl.log_and_clear("list_bucket", bucket_name, user1) | |
720 | assert len(keys) == 1 | |
721 | assert keys[0].name == object_name | |
7c673cae FG |
722 | |
723 | # now delete it | |
724 | (err, out) = rgwadmin(ctx, client, | |
725 | ['object', 'rm', '--bucket', bucket_name, '--object', object_name], | |
726 | check_status=True) | |
727 | ||
728 | # TESTCASE 'bucket-stats6','bucket','stats','after deleting key','succeeds, lists one no objects' | |
729 | (err, out) = rgwadmin(ctx, client, [ | |
730 | 'bucket', 'stats', '--bucket', bucket_name], | |
731 | check_status=True) | |
732 | assert out['id'] == bucket_id | |
733 | assert out['usage']['rgw.main']['num_objects'] == 0 | |
734 | ||
735 | # list log objects | |
736 | # TESTCASE 'log-list','log','list','after activity','succeeds, lists one no objects' | |
737 | (err, out) = rgwadmin(ctx, client, ['log', 'list'], check_status=True) | |
738 | assert len(out) > 0 | |
739 | ||
740 | for obj in out: | |
741 | # TESTCASE 'log-show','log','show','after activity','returns expected info' | |
742 | if obj[:4] == 'meta' or obj[:4] == 'data' or obj[:18] == 'obj_delete_at_hint': | |
743 | continue | |
744 | ||
745 | (err, rgwlog) = rgwadmin(ctx, client, ['log', 'show', '--object', obj], | |
746 | check_status=True) | |
747 | assert len(rgwlog) > 0 | |
748 | ||
20effc67 TL |
749 | # skip any entry for which there is no bucket name--e.g., list_buckets, |
750 | # since that is valid but cannot pass the following checks | |
751 | entry_bucket_name = rgwlog['bucket'] | |
752 | if entry_bucket_name.strip() != "": | |
753 | # exempt bucket_name2 from checking as it was only used for multi-region tests | |
754 | assert rgwlog['bucket'].find(bucket_name) == 0 or rgwlog['bucket'].find(bucket_name2) == 0 | |
755 | assert rgwlog['bucket'] != bucket_name or rgwlog['bucket_id'] == bucket_id | |
756 | assert rgwlog['bucket_owner'] == user1 or rgwlog['bucket'] == bucket_name + '5' or rgwlog['bucket'] == bucket_name2 | |
757 | for entry in rgwlog['log_entries']: | |
758 | log.debug('checking log entry: ', entry) | |
759 | assert entry['bucket'] == rgwlog['bucket'] | |
760 | possible_buckets = [bucket_name + '5', bucket_name2] | |
761 | user = entry['user'] | |
762 | assert user == user1 or user.endswith('system-user') or \ | |
763 | rgwlog['bucket'] in possible_buckets | |
7c673cae FG |
764 | |
765 | # TESTCASE 'log-rm','log','rm','delete log objects','succeeds' | |
766 | (err, out) = rgwadmin(ctx, client, ['log', 'rm', '--object', obj], | |
767 | check_status=True) | |
768 | ||
769 | # TODO: show log by bucket+date | |
770 | ||
7c673cae FG |
771 | # TESTCASE 'user-suspend2','user','suspend','existing user','succeeds' |
772 | (err, out) = rgwadmin(ctx, client, ['user', 'suspend', '--uid', user1], | |
773 | check_status=True) | |
774 | ||
775 | # TESTCASE 'user-suspend3','user','suspend','suspended user','cannot write objects' | |
181888fb | 776 | denied = False |
7c673cae FG |
777 | try: |
778 | key = boto.s3.key.Key(bucket) | |
779 | key.set_contents_from_string('five') | |
780 | except boto.exception.S3ResponseError as e: | |
181888fb | 781 | denied = True |
7c673cae FG |
782 | assert e.status == 403 |
783 | ||
181888fb FG |
784 | assert denied |
785 | rl.log_and_clear("put_obj", bucket_name, user1) | |
786 | ||
7c673cae FG |
787 | # TESTCASE 'user-renable2','user','enable','suspended user','succeeds' |
788 | (err, out) = rgwadmin(ctx, client, ['user', 'enable', '--uid', user1], | |
789 | check_status=True) | |
790 | ||
791 | # TESTCASE 'user-renable3','user','enable','reenabled user','can write objects' | |
792 | key = boto.s3.key.Key(bucket) | |
793 | key.set_contents_from_string('six') | |
181888fb | 794 | rl.log_and_clear("put_obj", bucket_name, user1) |
7c673cae FG |
795 | |
796 | # TESTCASE 'gc-list', 'gc', 'list', 'get list of objects ready for garbage collection' | |
797 | ||
798 | # create an object large enough to be split into multiple parts | |
799 | test_string = 'foo'*10000000 | |
800 | ||
801 | big_key = boto.s3.key.Key(bucket) | |
802 | big_key.set_contents_from_string(test_string) | |
181888fb | 803 | rl.log_and_clear("put_obj", bucket_name, user1) |
7c673cae FG |
804 | |
805 | # now delete the head | |
806 | big_key.delete() | |
181888fb | 807 | rl.log_and_clear("delete_obj", bucket_name, user1) |
7c673cae FG |
808 | |
809 | # wait a bit to give the garbage collector time to cycle | |
810 | time.sleep(15) | |
811 | ||
20effc67 | 812 | (err, out) = rgwadmin(ctx, client, ['gc', 'list', '--include-all']) |
7c673cae FG |
813 | assert len(out) > 0 |
814 | ||
815 | # TESTCASE 'gc-process', 'gc', 'process', 'manually collect garbage' | |
816 | (err, out) = rgwadmin(ctx, client, ['gc', 'process'], check_status=True) | |
817 | ||
818 | #confirm | |
20effc67 | 819 | (err, out) = rgwadmin(ctx, client, ['gc', 'list', '--include-all']) |
7c673cae | 820 | |
20effc67 TL |
821 | # don't assume rgw_gc_obj_min_wait has been overridden |
822 | omit_tdir = hasattr(ctx.rgw, 'omit_tdir') and ctx.rgw.omit_tdir == True | |
823 | if omit_tdir==False: | |
824 | assert len(out) == 0 | |
7c673cae FG |
825 | |
826 | # TESTCASE 'rm-user-buckets','user','rm','existing user','fails, still has buckets' | |
827 | (err, out) = rgwadmin(ctx, client, ['user', 'rm', '--uid', user1]) | |
828 | assert err | |
829 | ||
830 | # delete should fail because ``key`` still exists | |
831 | try: | |
832 | bucket.delete() | |
833 | except boto.exception.S3ResponseError as e: | |
834 | assert e.status == 409 | |
181888fb | 835 | rl.log_and_clear("delete_bucket", bucket_name, user1) |
7c673cae FG |
836 | |
837 | key.delete() | |
181888fb | 838 | rl.log_and_clear("delete_obj", bucket_name, user1) |
7c673cae | 839 | bucket.delete() |
181888fb | 840 | rl.log_and_clear("delete_bucket", bucket_name, user1) |
7c673cae FG |
841 | |
842 | # TESTCASE 'policy', 'bucket', 'policy', 'get bucket policy', 'returns S3 policy' | |
843 | bucket = connection.create_bucket(bucket_name) | |
181888fb | 844 | rl.log_and_clear("create_bucket", bucket_name, user1) |
7c673cae FG |
845 | |
846 | # create an object | |
847 | key = boto.s3.key.Key(bucket) | |
848 | key.set_contents_from_string('seven') | |
181888fb | 849 | rl.log_and_clear("put_obj", bucket_name, user1) |
7c673cae FG |
850 | |
851 | # should be private already but guarantee it | |
852 | key.set_acl('private') | |
181888fb | 853 | rl.log_and_clear("put_acls", bucket_name, user1) |
7c673cae FG |
854 | |
855 | (err, out) = rgwadmin(ctx, client, | |
f67539c2 | 856 | ['policy', '--bucket', bucket.name, '--object', key.key.decode()], |
7c673cae FG |
857 | check_status=True, format='xml') |
858 | ||
859 | acl = get_acl(key) | |
181888fb | 860 | rl.log_and_clear("get_acls", bucket_name, user1) |
7c673cae FG |
861 | |
862 | assert acl == out.strip('\n') | |
863 | ||
864 | # add another grantee by making the object public read | |
865 | key.set_acl('public-read') | |
181888fb | 866 | rl.log_and_clear("put_acls", bucket_name, user1) |
7c673cae FG |
867 | |
868 | (err, out) = rgwadmin(ctx, client, | |
f67539c2 | 869 | ['policy', '--bucket', bucket.name, '--object', key.key.decode()], |
7c673cae FG |
870 | check_status=True, format='xml') |
871 | ||
872 | acl = get_acl(key) | |
181888fb | 873 | rl.log_and_clear("get_acls", bucket_name, user1) |
7c673cae FG |
874 | |
875 | assert acl == out.strip('\n') | |
876 | ||
877 | # TESTCASE 'rm-bucket', 'bucket', 'rm', 'bucket with objects', 'succeeds' | |
878 | bucket = connection.create_bucket(bucket_name) | |
181888fb | 879 | rl.log_and_clear("create_bucket", bucket_name, user1) |
7c673cae FG |
880 | key_name = ['eight', 'nine', 'ten', 'eleven'] |
881 | for i in range(4): | |
882 | key = boto.s3.key.Key(bucket) | |
883 | key.set_contents_from_string(key_name[i]) | |
181888fb | 884 | rl.log_and_clear("put_obj", bucket_name, user1) |
7c673cae FG |
885 | |
886 | (err, out) = rgwadmin(ctx, client, | |
887 | ['bucket', 'rm', '--bucket', bucket_name, '--purge-objects'], | |
888 | check_status=True) | |
889 | ||
890 | # TESTCASE 'caps-add', 'caps', 'add', 'add user cap', 'succeeds' | |
891 | caps='user=read' | |
892 | (err, out) = rgwadmin(ctx, client, ['caps', 'add', '--uid', user1, '--caps', caps]) | |
893 | ||
894 | assert out['caps'][0]['perm'] == 'read' | |
895 | ||
896 | # TESTCASE 'caps-rm', 'caps', 'rm', 'remove existing cap from user', 'succeeds' | |
897 | (err, out) = rgwadmin(ctx, client, ['caps', 'rm', '--uid', user1, '--caps', caps]) | |
898 | ||
899 | assert not out['caps'] | |
900 | ||
901 | # TESTCASE 'rm-user','user','rm','existing user','fails, still has buckets' | |
902 | bucket = connection.create_bucket(bucket_name) | |
181888fb | 903 | rl.log_and_clear("create_bucket", bucket_name, user1) |
7c673cae FG |
904 | key = boto.s3.key.Key(bucket) |
905 | ||
906 | (err, out) = rgwadmin(ctx, client, ['user', 'rm', '--uid', user1]) | |
907 | assert err | |
908 | ||
909 | # TESTCASE 'rm-user2', 'user', 'rm', 'user with data', 'succeeds' | |
910 | bucket = connection.create_bucket(bucket_name) | |
181888fb | 911 | rl.log_and_clear("create_bucket", bucket_name, user1) |
7c673cae FG |
912 | key = boto.s3.key.Key(bucket) |
913 | key.set_contents_from_string('twelve') | |
181888fb FG |
914 | rl.log_and_clear("put_obj", bucket_name, user1) |
915 | ||
916 | time.sleep(35) | |
917 | ||
918 | # need to wait for all usage data to get flushed, should take up to 30 seconds | |
919 | timestamp = time.time() | |
920 | while time.time() - timestamp <= (2 * 60): # wait up to 20 minutes | |
921 | (err, out) = rgwadmin(ctx, client, ['usage', 'show', '--categories', 'delete_obj']) # one of the operations we did is delete_obj, should be present. | |
922 | if get_user_successful_ops(out, user1) > 0: | |
923 | break | |
924 | time.sleep(1) | |
925 | ||
926 | assert time.time() - timestamp <= (20 * 60) | |
927 | ||
928 | # TESTCASE 'usage-show' 'usage' 'show' 'all usage' 'succeeds' | |
929 | (err, out) = rgwadmin(ctx, client, ['usage', 'show'], check_status=True) | |
930 | assert len(out['entries']) > 0 | |
931 | assert len(out['summary']) > 0 | |
932 | ||
933 | r = acc.compare_results(out) | |
934 | if len(r) != 0: | |
935 | sys.stderr.write(("\n".join(r))+"\n") | |
936 | assert(len(r) == 0) | |
937 | ||
938 | user_summary = get_user_summary(out, user1) | |
939 | ||
940 | total = user_summary['total'] | |
941 | assert total['successful_ops'] > 0 | |
942 | ||
943 | # TESTCASE 'usage-show2' 'usage' 'show' 'user usage' 'succeeds' | |
944 | (err, out) = rgwadmin(ctx, client, ['usage', 'show', '--uid', user1], | |
945 | check_status=True) | |
946 | assert len(out['entries']) > 0 | |
947 | assert len(out['summary']) > 0 | |
948 | user_summary = out['summary'][0] | |
949 | for entry in user_summary['categories']: | |
950 | assert entry['successful_ops'] > 0 | |
951 | assert user_summary['user'] == user1 | |
952 | ||
953 | # TESTCASE 'usage-show3' 'usage' 'show' 'user usage categories' 'succeeds' | |
954 | test_categories = ['create_bucket', 'put_obj', 'delete_obj', 'delete_bucket'] | |
955 | for cat in test_categories: | |
956 | (err, out) = rgwadmin(ctx, client, ['usage', 'show', '--uid', user1, '--categories', cat], | |
957 | check_status=True) | |
958 | assert len(out['summary']) > 0 | |
959 | user_summary = out['summary'][0] | |
960 | assert user_summary['user'] == user1 | |
961 | assert len(user_summary['categories']) == 1 | |
962 | entry = user_summary['categories'][0] | |
963 | assert entry['category'] == cat | |
964 | assert entry['successful_ops'] > 0 | |
965 | ||
9f95a23c TL |
966 | # TESTCASE 'user-rename', 'user', 'rename', 'existing user', 'new user', 'succeeds' |
967 | # create a new user user3 | |
968 | (err, out) = rgwadmin(ctx, client, [ | |
969 | 'user', 'create', | |
970 | '--uid', user3, | |
971 | '--display-name', display_name3, | |
972 | '--access-key', access_key3, | |
973 | '--secret', secret_key3, | |
974 | '--max-buckets', '4' | |
975 | ], | |
976 | check_status=True) | |
977 | ||
978 | # create a bucket | |
979 | bucket = connection3.create_bucket(bucket_name + '6') | |
980 | ||
981 | rl.log_and_clear("create_bucket", bucket_name + '6', user3) | |
982 | ||
983 | # create object | |
984 | object_name1 = 'thirteen' | |
985 | key1 = boto.s3.key.Key(bucket, object_name1) | |
986 | key1.set_contents_from_string(object_name1) | |
987 | rl.log_and_clear("put_obj", bucket_name + '6', user3) | |
988 | ||
989 | # rename user3 | |
990 | (err, out) = rgwadmin(ctx, client, ['user', 'rename', '--uid', user3, '--new-uid', user4], check_status=True) | |
991 | assert out['user_id'] == user4 | |
992 | assert out['keys'][0]['access_key'] == access_key3 | |
993 | assert out['keys'][0]['secret_key'] == secret_key3 | |
994 | ||
995 | time.sleep(5) | |
996 | ||
997 | # get bucket and object to test if user keys are preserved | |
998 | bucket = connection3.get_bucket(bucket_name + '6') | |
e306af50 | 999 | s = key1.get_contents_as_string(encoding='ascii') |
9f95a23c TL |
1000 | rl.log_and_clear("get_obj", bucket_name + '6', user4) |
1001 | assert s == object_name1 | |
1002 | ||
1003 | # TESTCASE 'user-rename', 'user', 'rename', 'existing user', 'another existing user', 'fails' | |
1004 | # create a new user user2 | |
1005 | (err, out) = rgwadmin(ctx, client, [ | |
1006 | 'user', 'create', | |
1007 | '--uid', user2, | |
1008 | '--display-name', display_name2, | |
1009 | '--access-key', access_key2, | |
1010 | '--secret', secret_key2, | |
1011 | '--max-buckets', '4' | |
1012 | ], | |
1013 | check_status=True) | |
1014 | ||
1015 | # create a bucket | |
1016 | bucket = connection2.create_bucket(bucket_name + '7') | |
1017 | ||
1018 | rl.log_and_clear("create_bucket", bucket_name + '7', user2) | |
1019 | ||
1020 | # create object | |
1021 | object_name2 = 'fourteen' | |
1022 | key2 = boto.s3.key.Key(bucket, object_name2) | |
1023 | key2.set_contents_from_string(object_name2) | |
1024 | rl.log_and_clear("put_obj", bucket_name + '7', user2) | |
1025 | ||
1026 | (err, out) = rgwadmin(ctx, client, ['user', 'rename', '--uid', user4, '--new-uid', user2]) | |
1027 | assert err | |
1028 | ||
1029 | # test if user 2 and user4 can still access their bucket and objects after rename fails | |
1030 | bucket = connection3.get_bucket(bucket_name + '6') | |
e306af50 | 1031 | s = key1.get_contents_as_string(encoding='ascii') |
9f95a23c TL |
1032 | rl.log_and_clear("get_obj", bucket_name + '6', user4) |
1033 | assert s == object_name1 | |
1034 | ||
1035 | bucket = connection2.get_bucket(bucket_name + '7') | |
e306af50 | 1036 | s = key2.get_contents_as_string(encoding='ascii') |
9f95a23c TL |
1037 | rl.log_and_clear("get_obj", bucket_name + '7', user2) |
1038 | assert s == object_name2 | |
1039 | ||
1040 | (err, out) = rgwadmin(ctx, client, | |
1041 | ['user', 'rm', '--uid', user4, '--purge-data' ], | |
1042 | check_status=True) | |
1043 | ||
1044 | (err, out) = rgwadmin(ctx, client, | |
1045 | ['user', 'rm', '--uid', user2, '--purge-data' ], | |
1046 | check_status=True) | |
1047 | ||
1048 | time.sleep(5) | |
1049 | ||
181888fb FG |
1050 | # should be all through with connection. (anything using connection |
1051 | # should be BEFORE the usage stuff above.) | |
1052 | rl.log_and_clear("(before-close)", '-', '-', ignore_this_entry) | |
1053 | connection.close() | |
1054 | connection = None | |
1055 | ||
1056 | # the usage flush interval is 30 seconds, wait that much an then some | |
1057 | # to make sure everything has been flushed | |
1058 | time.sleep(35) | |
1059 | ||
1060 | # TESTCASE 'usage-trim' 'usage' 'trim' 'user usage' 'succeeds, usage removed' | |
1061 | (err, out) = rgwadmin(ctx, client, ['usage', 'trim', '--uid', user1], | |
1062 | check_status=True) | |
1063 | (err, out) = rgwadmin(ctx, client, ['usage', 'show', '--uid', user1], | |
1064 | check_status=True) | |
1065 | assert len(out['entries']) == 0 | |
1066 | assert len(out['summary']) == 0 | |
7c673cae FG |
1067 | |
1068 | (err, out) = rgwadmin(ctx, client, | |
1069 | ['user', 'rm', '--uid', user1, '--purge-data' ], | |
1070 | check_status=True) | |
1071 | ||
1072 | # TESTCASE 'rm-user3','user','rm','deleted user','fails' | |
1073 | (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user1]) | |
1074 | assert err | |
1075 | ||
1076 | # TESTCASE 'zone-info', 'zone', 'get', 'get zone info', 'succeeds, has default placement rule' | |
31f18b77 | 1077 | (err, out) = rgwadmin(ctx, client, ['zone', 'get','--rgw-zone','default']) |
7c673cae FG |
1078 | orig_placement_pools = len(out['placement_pools']) |
1079 | ||
1080 | # removed this test, it is not correct to assume that zone has default placement, it really | |
1081 | # depends on how we set it up before | |
1082 | # | |
1083 | # assert len(out) > 0 | |
1084 | # assert len(out['placement_pools']) == 1 | |
1085 | ||
1086 | # default_rule = out['placement_pools'][0] | |
1087 | # assert default_rule['key'] == 'default-placement' | |
1088 | ||
1089 | rule={'key': 'new-placement', 'val': {'data_pool': '.rgw.buckets.2', 'index_pool': '.rgw.buckets.index.2'}} | |
1090 | ||
1091 | out['placement_pools'].append(rule) | |
1092 | ||
1093 | (err, out) = rgwadmin(ctx, client, ['zone', 'set'], | |
20effc67 | 1094 | stdin=StringIO(json.dumps(out)), |
7c673cae FG |
1095 | check_status=True) |
1096 | ||
b32b8144 | 1097 | (err, out) = rgwadmin(ctx, client, ['zone', 'get']) |
7c673cae FG |
1098 | assert len(out) > 0 |
1099 | assert len(out['placement_pools']) == orig_placement_pools + 1 | |
181888fb FG |
1100 | |
1101 | zonecmd = ['zone', 'placement', 'rm', | |
9f95a23c TL |
1102 | '--rgw-zone', 'default', |
1103 | '--placement-id', 'new-placement'] | |
181888fb FG |
1104 | |
1105 | (err, out) = rgwadmin(ctx, client, zonecmd, check_status=True) | |
1106 | ||
b32b8144 FG |
1107 | # TESTCASE 'zonegroup-info', 'zonegroup', 'get', 'get zonegroup info', 'succeeds' |
1108 | (err, out) = rgwadmin(ctx, client, ['zonegroup', 'get'], check_status=True) | |
1109 | ||
181888fb | 1110 | from teuthology.config import config |
f38dd50b | 1111 | from teuthology.orchestra import cluster, remote |
20effc67 | 1112 | |
181888fb FG |
1113 | import argparse; |
1114 | ||
1115 | def main(): | |
20effc67 TL |
1116 | parser = argparse.ArgumentParser() |
1117 | parser.add_argument('--uid') | |
1118 | parser.add_argument('--host', required=True) | |
1119 | parser.add_argument('--port', type=int) | |
1120 | ||
1121 | args = parser.parse_args() | |
1122 | host = args.host | |
1123 | if args.port: | |
1124 | port = args.port | |
181888fb | 1125 | else: |
20effc67 TL |
1126 | port = 80 |
1127 | ||
f38dd50b TL |
1128 | client0 = remote.Remote(host) |
1129 | #client0 = tasks.vstart_runner.LocalRemote() | |
1130 | ||
181888fb FG |
1131 | ctx = config |
1132 | ctx.cluster=cluster.Cluster(remotes=[(client0, | |
20effc67 | 1133 | [ 'ceph.client.rgw.%s' % (port), ]),]) |
181888fb FG |
1134 | ctx.rgw = argparse.Namespace() |
1135 | endpoints = {} | |
20effc67 TL |
1136 | endpoints['ceph.client.rgw.%s' % port] = RGWEndpoint( |
1137 | hostname=host, | |
1138 | port=port) | |
181888fb FG |
1139 | ctx.rgw.role_endpoints = endpoints |
1140 | ctx.rgw.realm = None | |
1141 | ctx.rgw.regions = {'region0': { 'api name': 'api1', | |
e306af50 TL |
1142 | 'is master': True, 'master zone': 'r0z0', |
1143 | 'zones': ['r0z0', 'r0z1'] }} | |
20effc67 TL |
1144 | ctx.rgw.omit_sudo = True |
1145 | ctx.rgw.omit_tdir = True | |
1146 | ctx.rgw.config = {'ceph.client.rgw.%s' % port: {'system user': {'name': '%s-system-user' % port}}} | |
181888fb FG |
1147 | task(config, None) |
1148 | exit() | |
1149 | ||
1150 | if __name__ == '__main__': | |
1151 | main() |