]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/radosgw_admin.py
2 Rgw admin testing against a running instance
4 # The test cases in this file have been annotated for inventory.
5 # To extract the inventory (in csv format) use the command:
7 # grep '^ *# TESTCASE' | sed 's/^ *# TESTCASE //'
16 from cStringIO
import StringIO
19 import boto
.s3
.connection
24 import util
.rgw
as rgw_utils
26 from util
.rgw
import rgwadmin
, get_user_summary
, get_user_successful_ops
28 log
= logging
.getLogger(__name__
)
30 def create_presigned_url(conn
, method
, bucket_name
, key_name
, expiration
):
31 return conn
.generate_url(expires_in
=expiration
,
38 def send_raw_http_request(conn
, method
, bucket_name
, key_name
, follow_redirects
= False):
39 url
= create_presigned_url(conn
, method
, bucket_name
, key_name
, 3600)
42 h
.follow_redirects
= follow_redirects
43 return h
.request(url
, method
)
48 Helper function to get the xml acl from a key, ensuring that the xml
49 version tag is removed from the acl response
51 raw_acl
= key
.get_xml_acl()
53 def remove_version(string
):
55 '<?xml version="1.0" encoding="UTF-8"?>'
58 def remove_newlines(string
):
59 return string
.strip('\n')
61 return remove_version(
62 remove_newlines(raw_acl
)
65 def task(ctx
, config
):
67 Test radosgw-admin functionality against a running rgw instance.
71 # regions and config found from rgw task
72 assert ctx
.rgw
.regions
is not None, \
73 "radosgw_admin task needs region(s) declared from the rgw task"
74 regions
= ctx
.rgw
.regions
75 log
.debug('regions are: %r', regions
)
77 assert ctx
.rgw
.config
, \
78 "radosgw_admin task needs a config passed from the rgw task"
79 config
= ctx
.rgw
.config
80 log
.debug('config is: %r', config
)
82 clients_from_config
= config
.keys()
84 # choose first client as default
85 client
= clients_from_config
[0]
87 multi_region_run
= rgw_utils
.multi_region_enabled(ctx
)
89 client
= rgw_utils
.get_config_master_client(ctx
, config
, regions
)
91 log
.debug('multi_region_run is: %r', multi_region_run
)
92 log
.debug('master_client is: %r', client
)
94 # once the client is chosen, pull the host name and assigned port out of
95 # the role_endpoints that were assigned by the rgw task
96 (remote_host
, remote_port
) = ctx
.rgw
.role_endpoints
[client
]
99 log
.debug('radosgw-admin: realm %r', realm
)
110 access_key
='9te6NH5mcdcq0Tc5i8i1'
111 secret_key
='Ny4IOauQoL18Gp2zM7lC1vLmoawgqcYP/YGcWfXu'
112 access_key2
='p5YnriCv1nAtykxBrupQ'
113 secret_key2
='Q8Tk6Q/27hfbFSYdSkPtUqhqx1GgzvpXa4WARozh'
114 swift_secret1
='gpS2G9RREMrnbqlp29PP2D36kgPR1tm72n5fPYfL'
115 swift_secret2
='ri2VJQcKSYATOY6uaDUX7pxgkW+W1YmC6OCxPHwy'
121 connection
= boto
.s3
.connection
.S3Connection(
122 aws_access_key_id
=access_key
,
123 aws_secret_access_key
=secret_key
,
127 calling_format
=boto
.s3
.connection
.OrdinaryCallingFormat(),
129 connection2
= boto
.s3
.connection
.S3Connection(
130 aws_access_key_id
=access_key2
,
131 aws_secret_access_key
=secret_key2
,
135 calling_format
=boto
.s3
.connection
.OrdinaryCallingFormat(),
138 # legend (test cases can be easily grep-ed out)
139 # TESTCASE 'testname','object','method','operation','assertion'
140 # TESTCASE 'info-nosuch','user','info','non-existent user','fails'
141 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user1
])
144 # TESTCASE 'create-ok','user','create','w/all valid info','succeeds'
145 (err
, out
) = rgwadmin(ctx
, client
, [
148 '--display-name', display_name1
,
150 '--access-key', access_key
,
151 '--secret', secret_key
,
156 # TESTCASE 'duplicate email','user','create','existing user email','fails'
157 (err
, out
) = rgwadmin(ctx
, client
, [
160 '--display-name', display_name2
,
165 # TESTCASE 'info-existing','user','info','existing user','returns correct info'
166 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user1
], check_status
=True)
167 assert out
['user_id'] == user1
168 assert out
['email'] == email
169 assert out
['display_name'] == display_name1
170 assert len(out
['keys']) == 1
171 assert out
['keys'][0]['access_key'] == access_key
172 assert out
['keys'][0]['secret_key'] == secret_key
173 assert not out
['suspended']
175 # this whole block should only be run if regions have been configured
177 rgw_utils
.radosgw_agent_sync_all(ctx
)
178 # post-sync, validate that user1 exists on the sync destination host
179 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
180 dest_client
= c_config
['dest']
181 (err
, out
) = rgwadmin(ctx
, dest_client
, ['metadata', 'list', 'user'])
182 (err
, out
) = rgwadmin(ctx
, dest_client
, ['user', 'info', '--uid', user1
], check_status
=True)
183 assert out
['user_id'] == user1
184 assert out
['email'] == email
185 assert out
['display_name'] == display_name1
186 assert len(out
['keys']) == 1
187 assert out
['keys'][0]['access_key'] == access_key
188 assert out
['keys'][0]['secret_key'] == secret_key
189 assert not out
['suspended']
191 # compare the metadata between different regions, make sure it matches
192 log
.debug('compare the metadata between different regions, make sure it matches')
193 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
194 source_client
= c_config
['src']
195 dest_client
= c_config
['dest']
196 (err1
, out1
) = rgwadmin(ctx
, source_client
,
197 ['metadata', 'get', 'user:{uid}'.format(uid
=user1
)], check_status
=True)
198 (err2
, out2
) = rgwadmin(ctx
, dest_client
,
199 ['metadata', 'get', 'user:{uid}'.format(uid
=user1
)], check_status
=True)
202 # suspend a user on the master, then check the status on the destination
203 log
.debug('suspend a user on the master, then check the status on the destination')
204 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
205 source_client
= c_config
['src']
206 dest_client
= c_config
['dest']
207 (err
, out
) = rgwadmin(ctx
, source_client
, ['user', 'suspend', '--uid', user1
])
208 rgw_utils
.radosgw_agent_sync_all(ctx
)
209 (err
, out
) = rgwadmin(ctx
, dest_client
, ['user', 'info', '--uid', user1
], check_status
=True)
210 assert out
['suspended']
212 # delete a user on the master, then check that it's gone on the destination
213 log
.debug('delete a user on the master, then check that it\'s gone on the destination')
214 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
215 source_client
= c_config
['src']
216 dest_client
= c_config
['dest']
217 (err
, out
) = rgwadmin(ctx
, source_client
, ['user', 'rm', '--uid', user1
], check_status
=True)
218 rgw_utils
.radosgw_agent_sync_all(ctx
)
219 (err
, out
) = rgwadmin(ctx
, source_client
, ['user', 'info', '--uid', user1
])
221 (err
, out
) = rgwadmin(ctx
, dest_client
, ['user', 'info', '--uid', user1
])
224 # then recreate it so later tests pass
225 (err
, out
) = rgwadmin(ctx
, client
, [
228 '--display-name', display_name1
,
230 '--access-key', access_key
,
231 '--secret', secret_key
,
236 # now do the multi-region bucket tests
237 log
.debug('now do the multi-region bucket tests')
239 # Create a second user for the following tests
240 log
.debug('Create a second user for the following tests')
241 (err
, out
) = rgwadmin(ctx
, client
, [
244 '--display-name', display_name2
,
246 '--access-key', access_key2
,
247 '--secret', secret_key2
,
251 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user2
], check_status
=True)
252 assert out
is not None
254 # create a bucket and do a sync
255 log
.debug('create a bucket and do a sync')
256 bucket
= connection
.create_bucket(bucket_name2
)
257 rgw_utils
.radosgw_agent_sync_all(ctx
)
259 # compare the metadata for the bucket between different regions, make sure it matches
260 log
.debug('compare the metadata for the bucket between different regions, make sure it matches')
261 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
262 source_client
= c_config
['src']
263 dest_client
= c_config
['dest']
264 (err1
, out1
) = rgwadmin(ctx
, source_client
,
265 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
267 (err2
, out2
) = rgwadmin(ctx
, dest_client
,
268 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
270 log
.debug('metadata 1 %r', out1
)
271 log
.debug('metadata 2 %r', out2
)
274 # get the bucket.instance info and compare that
275 src_bucket_id
= out1
['data']['bucket']['bucket_id']
276 dest_bucket_id
= out2
['data']['bucket']['bucket_id']
277 (err1
, out1
) = rgwadmin(ctx
, source_client
, ['metadata', 'get',
278 'bucket.instance:{bucket_name}:{bucket_instance}'.format(
279 bucket_name
=bucket_name2
,bucket_instance
=src_bucket_id
)],
281 (err2
, out2
) = rgwadmin(ctx
, dest_client
, ['metadata', 'get',
282 'bucket.instance:{bucket_name}:{bucket_instance}'.format(
283 bucket_name
=bucket_name2
,bucket_instance
=dest_bucket_id
)],
288 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
289 source_client
= c_config
['src']
290 dest_client
= c_config
['dest']
292 source_region
= rgw_utils
.region_for_client(ctx
, source_client
)
293 dest_region
= rgw_utils
.region_for_client(ctx
, dest_client
)
295 # 301 is only returned for requests to something in a different region
296 if source_region
== dest_region
:
297 log
.debug('301 is only returned for requests to something in a different region')
301 # Attempt to create a new connection with user1 to the destination RGW
302 log
.debug('Attempt to create a new connection with user1 to the destination RGW')
303 # and use that to attempt a delete (that should fail)
305 (dest_remote_host
, dest_remote_port
) = ctx
.rgw
.role_endpoints
[dest_client
]
306 connection_dest
= boto
.s3
.connection
.S3Connection(
307 aws_access_key_id
=access_key
,
308 aws_secret_access_key
=secret_key
,
310 port
=dest_remote_port
,
311 host
=dest_remote_host
,
312 calling_format
=boto
.s3
.connection
.OrdinaryCallingFormat(),
316 r
, content
= send_raw_http_request(connection_dest
, 'DELETE', bucket_name2
, '', follow_redirects
= False)
317 assert r
.status
== 301
319 # now delete the bucket on the source RGW and do another sync
320 log
.debug('now delete the bucket on the source RGW and do another sync')
322 rgw_utils
.radosgw_agent_sync_all(ctx
)
324 if same_region
== len(ctx
.radosgw_agent
.config
):
326 rgw_utils
.radosgw_agent_sync_all(ctx
)
328 # make sure that the bucket no longer exists in either region
329 log
.debug('make sure that the bucket no longer exists in either region')
330 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
331 source_client
= c_config
['src']
332 dest_client
= c_config
['dest']
333 (err1
, out1
) = rgwadmin(ctx
, source_client
, ['metadata', 'get',
334 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)])
335 (err2
, out2
) = rgwadmin(ctx
, dest_client
, ['metadata', 'get',
336 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)])
337 # Both of the previous calls should have errors due to requesting
338 # metadata for non-existent buckets
342 # create a bucket and then sync it
343 log
.debug('create a bucket and then sync it')
344 bucket
= connection
.create_bucket(bucket_name2
)
345 rgw_utils
.radosgw_agent_sync_all(ctx
)
347 # compare the metadata for the bucket between different regions, make sure it matches
348 log
.debug('compare the metadata for the bucket between different regions, make sure it matches')
349 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
350 source_client
= c_config
['src']
351 dest_client
= c_config
['dest']
352 (err1
, out1
) = rgwadmin(ctx
, source_client
,
353 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
355 (err2
, out2
) = rgwadmin(ctx
, dest_client
,
356 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
360 # Now delete the bucket and recreate it with a different user
361 log
.debug('Now delete the bucket and recreate it with a different user')
362 # within the same window of time and then sync.
364 bucket
= connection2
.create_bucket(bucket_name2
)
365 rgw_utils
.radosgw_agent_sync_all(ctx
)
367 # compare the metadata for the bucket between different regions, make sure it matches
368 log
.debug('compare the metadata for the bucket between different regions, make sure it matches')
369 # user2 should own the bucket in both regions
370 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
371 source_client
= c_config
['src']
372 dest_client
= c_config
['dest']
373 (err1
, out1
) = rgwadmin(ctx
, source_client
,
374 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
376 (err2
, out2
) = rgwadmin(ctx
, dest_client
,
377 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
380 assert out1
['data']['owner'] == user2
381 assert out1
['data']['owner'] != user1
383 # now we're going to use this bucket to test meta-data update propagation
384 log
.debug('now we\'re going to use this bucket to test meta-data update propagation')
385 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
386 source_client
= c_config
['src']
387 dest_client
= c_config
['dest']
389 # get the metadata so we can tweak it
390 log
.debug('get the metadata so we can tweak it')
391 (err
, orig_data
) = rgwadmin(ctx
, source_client
,
392 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
395 # manually edit mtime for this bucket to be 300 seconds in the past
396 log
.debug('manually edit mtime for this bucket to be 300 seconds in the past')
397 new_data
= copy
.deepcopy(orig_data
)
398 mtime
= datetime
.datetime
.strptime(orig_data
['mtime'], "%Y-%m-%d %H:%M:%S.%fZ") - datetime
.timedelta(300)
399 new_data
['mtime'] = unicode(mtime
.strftime("%Y-%m-%d %H:%M:%S.%fZ"))
400 log
.debug("new mtime ", mtime
)
401 assert new_data
!= orig_data
402 (err
, out
) = rgwadmin(ctx
, source_client
,
403 ['metadata', 'put', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
404 stdin
=StringIO(json
.dumps(new_data
)),
407 # get the metadata and make sure that the 'put' worked
408 log
.debug('get the metadata and make sure that the \'put\' worked')
409 (err
, out
) = rgwadmin(ctx
, source_client
,
410 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
412 assert out
== new_data
414 # sync to propagate the new metadata
415 log
.debug('sync to propagate the new metadata')
416 rgw_utils
.radosgw_agent_sync_all(ctx
)
418 # get the metadata from the dest and compare it to what we just set
419 log
.debug('get the metadata from the dest and compare it to what we just set')
420 # and what the source region has.
421 (err1
, out1
) = rgwadmin(ctx
, source_client
,
422 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
424 (err2
, out2
) = rgwadmin(ctx
, dest_client
,
425 ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name
=bucket_name2
)],
427 # yeah for the transitive property
429 assert out1
== new_data
431 # now we delete the bucket
432 log
.debug('now we delete the bucket')
435 log
.debug('sync to propagate the deleted bucket')
436 rgw_utils
.radosgw_agent_sync_all(ctx
)
438 # Delete user2 as later tests do not expect it to exist.
439 # Verify that it is gone on both regions
440 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
441 source_client
= c_config
['src']
442 dest_client
= c_config
['dest']
443 (err
, out
) = rgwadmin(ctx
, source_client
,
444 ['user', 'rm', '--uid', user2
], check_status
=True)
445 rgw_utils
.radosgw_agent_sync_all(ctx
)
446 # The two 'user info' calls should fail and not return any data
447 # since we just deleted this user.
448 (err
, out
) = rgwadmin(ctx
, source_client
, ['user', 'info', '--uid', user2
])
450 (err
, out
) = rgwadmin(ctx
, dest_client
, ['user', 'info', '--uid', user2
])
455 # First create a bucket for data sync test purpose
456 bucket
= connection
.create_bucket(bucket_name
+ 'data')
458 # Create a tiny file and check if in sync
459 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
460 if c_config
.get('metadata-only'):
463 for full
in (True, False):
464 source_client
= c_config
['src']
465 dest_client
= c_config
['dest']
466 k
= boto
.s3
.key
.Key(bucket
)
468 k
.set_contents_from_string("123456789")
469 safety_window
= rgw_utils
.radosgw_data_log_window(ctx
, source_client
)
470 time
.sleep(safety_window
)
471 rgw_utils
.radosgw_agent_sync_all(ctx
, data
=True, full
=full
)
472 (dest_host
, dest_port
) = ctx
.rgw
.role_endpoints
[dest_client
]
473 dest_connection
= boto
.s3
.connection
.S3Connection(
474 aws_access_key_id
=access_key
,
475 aws_secret_access_key
=secret_key
,
479 calling_format
=boto
.s3
.connection
.OrdinaryCallingFormat(),
481 dest_k
= dest_connection
.get_bucket(bucket_name
+ 'data').get_key('tiny_file')
482 assert k
.get_contents_as_string() == dest_k
.get_contents_as_string()
484 # check that deleting it removes it from the dest zone
486 time
.sleep(safety_window
)
487 # full sync doesn't handle deleted objects yet
488 rgw_utils
.radosgw_agent_sync_all(ctx
, data
=True, full
=False)
490 dest_bucket
= dest_connection
.get_bucket(bucket_name
+ 'data')
491 dest_k
= dest_bucket
.get_key('tiny_file')
492 assert dest_k
== None, 'object not deleted from destination zone'
494 # finally we delete the bucket
497 bucket
= connection
.create_bucket(bucket_name
+ 'data2')
498 for agent_client
, c_config
in ctx
.radosgw_agent
.config
.iteritems():
499 if c_config
.get('metadata-only'):
502 for full
in (True, False):
503 source_client
= c_config
['src']
504 dest_client
= c_config
['dest']
505 (dest_host
, dest_port
) = ctx
.rgw
.role_endpoints
[dest_client
]
506 dest_connection
= boto
.s3
.connection
.S3Connection(
507 aws_access_key_id
=access_key
,
508 aws_secret_access_key
=secret_key
,
512 calling_format
=boto
.s3
.connection
.OrdinaryCallingFormat(),
515 k
= boto
.s3
.key
.Key(bucket
)
516 k
.key
= 'tiny_file_' + str(i
)
517 k
.set_contents_from_string(str(i
) * 100)
519 safety_window
= rgw_utils
.radosgw_data_log_window(ctx
, source_client
)
520 time
.sleep(safety_window
)
521 rgw_utils
.radosgw_agent_sync_all(ctx
, data
=True, full
=full
)
524 dest_k
= dest_connection
.get_bucket(bucket_name
+ 'data2').get_key('tiny_file_' + str(i
))
525 assert (str(i
) * 100) == dest_k
.get_contents_as_string()
526 k
= boto
.s3
.key
.Key(bucket
)
527 k
.key
= 'tiny_file_' + str(i
)
530 # check that deleting removes the objects from the dest zone
531 time
.sleep(safety_window
)
532 # full sync doesn't delete deleted objects yet
533 rgw_utils
.radosgw_agent_sync_all(ctx
, data
=True, full
=False)
536 dest_bucket
= dest_connection
.get_bucket(bucket_name
+ 'data2')
537 dest_k
= dest_bucket
.get_key('tiny_file_' + str(i
))
538 assert dest_k
== None, 'object %d not deleted from destination zone' % i
541 # end of 'if multi_region_run:'
543 # TESTCASE 'suspend-ok','user','suspend','active user','succeeds'
544 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'suspend', '--uid', user1
],
547 # TESTCASE 'suspend-suspended','user','suspend','suspended user','succeeds w/advisory'
548 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user1
], check_status
=True)
549 assert out
['suspended']
551 # TESTCASE 're-enable','user','enable','suspended user','succeeds'
552 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'enable', '--uid', user1
], check_status
=True)
554 # TESTCASE 'info-re-enabled','user','info','re-enabled user','no longer suspended'
555 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user1
], check_status
=True)
556 assert not out
['suspended']
558 # TESTCASE 'add-keys','key','create','w/valid info','succeeds'
559 (err
, out
) = rgwadmin(ctx
, client
, [
560 'key', 'create', '--uid', user1
,
561 '--access-key', access_key2
, '--secret', secret_key2
,
562 ], check_status
=True)
564 # TESTCASE 'info-new-key','user','info','after key addition','returns all keys'
565 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user1
],
567 assert len(out
['keys']) == 2
568 assert out
['keys'][0]['access_key'] == access_key2
or out
['keys'][1]['access_key'] == access_key2
569 assert out
['keys'][0]['secret_key'] == secret_key2
or out
['keys'][1]['secret_key'] == secret_key2
571 # TESTCASE 'rm-key','key','rm','newly added key','succeeds, key is removed'
572 (err
, out
) = rgwadmin(ctx
, client
, [
573 'key', 'rm', '--uid', user1
,
574 '--access-key', access_key2
,
575 ], check_status
=True)
576 assert len(out
['keys']) == 1
577 assert out
['keys'][0]['access_key'] == access_key
578 assert out
['keys'][0]['secret_key'] == secret_key
580 # TESTCASE 'add-swift-key','key','create','swift key','succeeds'
581 subuser_access
= 'full'
582 subuser_perm
= 'full-control'
584 (err
, out
) = rgwadmin(ctx
, client
, [
585 'subuser', 'create', '--subuser', subuser1
,
586 '--access', subuser_access
587 ], check_status
=True)
589 # TESTCASE 'add-swift-key','key','create','swift key','succeeds'
590 (err
, out
) = rgwadmin(ctx
, client
, [
591 'subuser', 'modify', '--subuser', subuser1
,
592 '--secret', swift_secret1
,
593 '--key-type', 'swift',
594 ], check_status
=True)
596 # TESTCASE 'subuser-perm-mask', 'subuser', 'info', 'test subuser perm mask durability', 'succeeds'
597 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user1
])
599 assert out
['subusers'][0]['permissions'] == subuser_perm
601 # TESTCASE 'info-swift-key','user','info','after key addition','returns all keys'
602 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user1
], check_status
=True)
603 assert len(out
['swift_keys']) == 1
604 assert out
['swift_keys'][0]['user'] == subuser1
605 assert out
['swift_keys'][0]['secret_key'] == swift_secret1
607 # TESTCASE 'add-swift-subuser','key','create','swift sub-user key','succeeds'
608 (err
, out
) = rgwadmin(ctx
, client
, [
609 'subuser', 'create', '--subuser', subuser2
,
610 '--secret', swift_secret2
,
611 '--key-type', 'swift',
612 ], check_status
=True)
614 # TESTCASE 'info-swift-subuser','user','info','after key addition','returns all sub-users/keys'
615 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user1
], check_status
=True)
616 assert len(out
['swift_keys']) == 2
617 assert out
['swift_keys'][0]['user'] == subuser2
or out
['swift_keys'][1]['user'] == subuser2
618 assert out
['swift_keys'][0]['secret_key'] == swift_secret2
or out
['swift_keys'][1]['secret_key'] == swift_secret2
620 # TESTCASE 'rm-swift-key1','key','rm','subuser','succeeds, one key is removed'
621 (err
, out
) = rgwadmin(ctx
, client
, [
622 'key', 'rm', '--subuser', subuser1
,
623 '--key-type', 'swift',
624 ], check_status
=True)
625 assert len(out
['swift_keys']) == 1
627 # TESTCASE 'rm-subuser','subuser','rm','subuser','success, subuser is removed'
628 (err
, out
) = rgwadmin(ctx
, client
, [
629 'subuser', 'rm', '--subuser', subuser1
,
630 ], check_status
=True)
631 assert len(out
['subusers']) == 1
633 # TESTCASE 'rm-subuser-with-keys','subuser','rm','subuser','succeeds, second subser and key is removed'
634 (err
, out
) = rgwadmin(ctx
, client
, [
635 'subuser', 'rm', '--subuser', subuser2
,
636 '--key-type', 'swift', '--purge-keys',
637 ], check_status
=True)
638 assert len(out
['swift_keys']) == 0
639 assert len(out
['subusers']) == 0
641 # TESTCASE 'bucket-stats','bucket','stats','no session/buckets','succeeds, empty list'
642 (err
, out
) = rgwadmin(ctx
, client
, ['bucket', 'stats', '--uid', user1
],
647 rgw_utils
.radosgw_agent_sync_all(ctx
)
649 # TESTCASE 'bucket-stats2','bucket','stats','no buckets','succeeds, empty list'
650 (err
, out
) = rgwadmin(ctx
, client
, ['bucket', 'list', '--uid', user1
], check_status
=True)
653 # create a first bucket
654 bucket
= connection
.create_bucket(bucket_name
)
656 # TESTCASE 'bucket-list','bucket','list','one bucket','succeeds, expected list'
657 (err
, out
) = rgwadmin(ctx
, client
, ['bucket', 'list', '--uid', user1
], check_status
=True)
659 assert out
[0] == bucket_name
661 # TESTCASE 'bucket-list-all','bucket','list','all buckets','succeeds, expected list'
662 (err
, out
) = rgwadmin(ctx
, client
, ['bucket', 'list'], check_status
=True)
664 assert bucket_name
in out
;
666 # TESTCASE 'max-bucket-limit,'bucket','create','4 buckets','5th bucket fails due to max buckets == 4'
667 bucket2
= connection
.create_bucket(bucket_name
+ '2')
668 bucket3
= connection
.create_bucket(bucket_name
+ '3')
669 bucket4
= connection
.create_bucket(bucket_name
+ '4')
670 # the 5th should fail.
673 connection
.create_bucket(bucket_name
+ '5')
683 # TESTCASE 'bucket-stats3','bucket','stats','new empty bucket','succeeds, empty list'
684 (err
, out
) = rgwadmin(ctx
, client
, [
685 'bucket', 'stats', '--bucket', bucket_name
], check_status
=True)
686 assert out
['owner'] == user1
687 bucket_id
= out
['id']
689 # TESTCASE 'bucket-stats4','bucket','stats','new empty bucket','succeeds, expected bucket ID'
690 (err
, out
) = rgwadmin(ctx
, client
, ['bucket', 'stats', '--uid', user1
], check_status
=True)
692 assert out
[0]['id'] == bucket_id
# does it return the same ID twice in a row?
695 key
= boto
.s3
.key
.Key(bucket
)
696 key
.set_contents_from_string('one')
698 # TESTCASE 'bucket-stats5','bucket','stats','after creating key','succeeds, lists one non-empty object'
699 (err
, out
) = rgwadmin(ctx
, client
, [
700 'bucket', 'stats', '--bucket', bucket_name
], check_status
=True)
701 assert out
['id'] == bucket_id
702 assert out
['usage']['rgw.main']['num_objects'] == 1
703 assert out
['usage']['rgw.main']['size_kb'] > 0
708 # TESTCASE 'bucket unlink', 'bucket', 'unlink', 'unlink bucket from user', 'fails', 'access denied error'
709 (err
, out
) = rgwadmin(ctx
, client
,
710 ['bucket', 'unlink', '--uid', user1
, '--bucket', bucket_name
],
713 # create a second user to link the bucket to
714 (err
, out
) = rgwadmin(ctx
, client
, [
717 '--display-name', display_name2
,
718 '--access-key', access_key2
,
719 '--secret', secret_key2
,
720 '--max-buckets', '1',
724 # try creating an object with the first user before the bucket is relinked
726 key
= boto
.s3
.key
.Key(bucket
)
729 key
.set_contents_from_string('two')
730 except boto
.exception
.S3ResponseError
:
738 # link the bucket to another user
739 (err
, out
) = rgwadmin(ctx
, client
, ['metadata', 'get', 'bucket:{n}'.format(n
=bucket_name
)],
742 bucket_data
= out
['data']
743 assert bucket_data
['bucket']['name'] == bucket_name
745 bucket_id
= bucket_data
['bucket']['bucket_id']
747 # link the bucket to another user
748 (err
, out
) = rgwadmin(ctx
, client
, ['bucket', 'link', '--uid', user2
, '--bucket', bucket_name
, '--bucket-id', bucket_id
],
751 # try to remove user, should fail (has a linked bucket)
752 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'rm', '--uid', user2
])
755 # TESTCASE 'bucket unlink', 'bucket', 'unlink', 'unlink bucket from user', 'succeeds, bucket unlinked'
756 (err
, out
) = rgwadmin(ctx
, client
, ['bucket', 'unlink', '--uid', user2
, '--bucket', bucket_name
],
759 # relink the bucket to the first user and delete the second user
760 (err
, out
) = rgwadmin(ctx
, client
,
761 ['bucket', 'link', '--uid', user1
, '--bucket', bucket_name
, '--bucket-id', bucket_id
],
764 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'rm', '--uid', user2
],
767 # TESTCASE 'object-rm', 'object', 'rm', 'remove object', 'succeeds, object is removed'
771 key
= boto
.s3
.key
.Key(bucket
, object_name
)
772 key
.set_contents_from_string(object_name
)
775 (err
, out
) = rgwadmin(ctx
, client
,
776 ['object', 'rm', '--bucket', bucket_name
, '--object', object_name
],
779 # TESTCASE 'bucket-stats6','bucket','stats','after deleting key','succeeds, lists one no objects'
780 (err
, out
) = rgwadmin(ctx
, client
, [
781 'bucket', 'stats', '--bucket', bucket_name
],
783 assert out
['id'] == bucket_id
784 assert out
['usage']['rgw.main']['num_objects'] == 0
787 # TESTCASE 'log-list','log','list','after activity','succeeds, lists one no objects'
788 (err
, out
) = rgwadmin(ctx
, client
, ['log', 'list'], check_status
=True)
792 # TESTCASE 'log-show','log','show','after activity','returns expected info'
793 if obj
[:4] == 'meta' or obj
[:4] == 'data' or obj
[:18] == 'obj_delete_at_hint':
796 (err
, rgwlog
) = rgwadmin(ctx
, client
, ['log', 'show', '--object', obj
],
798 assert len(rgwlog
) > 0
800 # exempt bucket_name2 from checking as it was only used for multi-region tests
801 assert rgwlog
['bucket'].find(bucket_name
) == 0 or rgwlog
['bucket'].find(bucket_name2
) == 0
802 assert rgwlog
['bucket'] != bucket_name
or rgwlog
['bucket_id'] == bucket_id
803 assert rgwlog
['bucket_owner'] == user1
or rgwlog
['bucket'] == bucket_name
+ '5' or rgwlog
['bucket'] == bucket_name2
804 for entry
in rgwlog
['log_entries']:
805 log
.debug('checking log entry: ', entry
)
806 assert entry
['bucket'] == rgwlog
['bucket']
807 possible_buckets
= [bucket_name
+ '5', bucket_name2
]
809 assert user
== user1
or user
.endswith('system-user') or \
810 rgwlog
['bucket'] in possible_buckets
812 # TESTCASE 'log-rm','log','rm','delete log objects','succeeds'
813 (err
, out
) = rgwadmin(ctx
, client
, ['log', 'rm', '--object', obj
],
816 # TODO: show log by bucket+date
818 # need to wait for all usage data to get flushed, should take up to 30 seconds
819 timestamp
= time
.time()
820 while time
.time() - timestamp
<= (20 * 60): # wait up to 20 minutes
821 (err
, out
) = rgwadmin(ctx
, client
, ['usage', 'show', '--categories', 'delete_obj']) # last operation we did is delete obj, wait for it to flush
822 if get_user_successful_ops(out
, user1
) > 0:
826 assert time
.time() - timestamp
<= (20 * 60)
828 # TESTCASE 'usage-show' 'usage' 'show' 'all usage' 'succeeds'
829 (err
, out
) = rgwadmin(ctx
, client
, ['usage', 'show'], check_status
=True)
830 assert len(out
['entries']) > 0
831 assert len(out
['summary']) > 0
833 user_summary
= get_user_summary(out
, user1
)
835 total
= user_summary
['total']
836 assert total
['successful_ops'] > 0
838 # TESTCASE 'usage-show2' 'usage' 'show' 'user usage' 'succeeds'
839 (err
, out
) = rgwadmin(ctx
, client
, ['usage', 'show', '--uid', user1
],
841 assert len(out
['entries']) > 0
842 assert len(out
['summary']) > 0
843 user_summary
= out
['summary'][0]
844 for entry
in user_summary
['categories']:
845 assert entry
['successful_ops'] > 0
846 assert user_summary
['user'] == user1
848 # TESTCASE 'usage-show3' 'usage' 'show' 'user usage categories' 'succeeds'
849 test_categories
= ['create_bucket', 'put_obj', 'delete_obj', 'delete_bucket']
850 for cat
in test_categories
:
851 (err
, out
) = rgwadmin(ctx
, client
, ['usage', 'show', '--uid', user1
, '--categories', cat
],
853 assert len(out
['summary']) > 0
854 user_summary
= out
['summary'][0]
855 assert user_summary
['user'] == user1
856 assert len(user_summary
['categories']) == 1
857 entry
= user_summary
['categories'][0]
858 assert entry
['category'] == cat
859 assert entry
['successful_ops'] > 0
861 # the usage flush interval is 30 seconds, wait that much an then some
862 # to make sure everything has been flushed
865 # TESTCASE 'usage-trim' 'usage' 'trim' 'user usage' 'succeeds, usage removed'
866 (err
, out
) = rgwadmin(ctx
, client
, ['usage', 'trim', '--uid', user1
],
868 (err
, out
) = rgwadmin(ctx
, client
, ['usage', 'show', '--uid', user1
],
870 assert len(out
['entries']) == 0
871 assert len(out
['summary']) == 0
873 # TESTCASE 'user-suspend2','user','suspend','existing user','succeeds'
874 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'suspend', '--uid', user1
],
877 # TESTCASE 'user-suspend3','user','suspend','suspended user','cannot write objects'
879 key
= boto
.s3
.key
.Key(bucket
)
880 key
.set_contents_from_string('five')
881 except boto
.exception
.S3ResponseError
as e
:
882 assert e
.status
== 403
884 # TESTCASE 'user-renable2','user','enable','suspended user','succeeds'
885 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'enable', '--uid', user1
],
888 # TESTCASE 'user-renable3','user','enable','reenabled user','can write objects'
889 key
= boto
.s3
.key
.Key(bucket
)
890 key
.set_contents_from_string('six')
892 # TESTCASE 'gc-list', 'gc', 'list', 'get list of objects ready for garbage collection'
894 # create an object large enough to be split into multiple parts
895 test_string
= 'foo'*10000000
897 big_key
= boto
.s3
.key
.Key(bucket
)
898 big_key
.set_contents_from_string(test_string
)
900 # now delete the head
903 # wait a bit to give the garbage collector time to cycle
906 (err
, out
) = rgwadmin(ctx
, client
, ['gc', 'list'])
910 # TESTCASE 'gc-process', 'gc', 'process', 'manually collect garbage'
911 (err
, out
) = rgwadmin(ctx
, client
, ['gc', 'process'], check_status
=True)
914 (err
, out
) = rgwadmin(ctx
, client
, ['gc', 'list'])
918 # TESTCASE 'rm-user-buckets','user','rm','existing user','fails, still has buckets'
919 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'rm', '--uid', user1
])
922 # delete should fail because ``key`` still exists
925 except boto
.exception
.S3ResponseError
as e
:
926 assert e
.status
== 409
931 # TESTCASE 'policy', 'bucket', 'policy', 'get bucket policy', 'returns S3 policy'
932 bucket
= connection
.create_bucket(bucket_name
)
935 key
= boto
.s3
.key
.Key(bucket
)
936 key
.set_contents_from_string('seven')
938 # should be private already but guarantee it
939 key
.set_acl('private')
941 (err
, out
) = rgwadmin(ctx
, client
,
942 ['policy', '--bucket', bucket
.name
, '--object', key
.key
],
943 check_status
=True, format
='xml')
947 assert acl
== out
.strip('\n')
949 # add another grantee by making the object public read
950 key
.set_acl('public-read')
952 (err
, out
) = rgwadmin(ctx
, client
,
953 ['policy', '--bucket', bucket
.name
, '--object', key
.key
],
954 check_status
=True, format
='xml')
958 assert acl
== out
.strip('\n')
960 # TESTCASE 'rm-bucket', 'bucket', 'rm', 'bucket with objects', 'succeeds'
961 bucket
= connection
.create_bucket(bucket_name
)
962 key_name
= ['eight', 'nine', 'ten', 'eleven']
964 key
= boto
.s3
.key
.Key(bucket
)
965 key
.set_contents_from_string(key_name
[i
])
967 (err
, out
) = rgwadmin(ctx
, client
,
968 ['bucket', 'rm', '--bucket', bucket_name
, '--purge-objects'],
971 # TESTCASE 'caps-add', 'caps', 'add', 'add user cap', 'succeeds'
973 (err
, out
) = rgwadmin(ctx
, client
, ['caps', 'add', '--uid', user1
, '--caps', caps
])
975 assert out
['caps'][0]['perm'] == 'read'
977 # TESTCASE 'caps-rm', 'caps', 'rm', 'remove existing cap from user', 'succeeds'
978 (err
, out
) = rgwadmin(ctx
, client
, ['caps', 'rm', '--uid', user1
, '--caps', caps
])
980 assert not out
['caps']
982 # TESTCASE 'rm-user','user','rm','existing user','fails, still has buckets'
983 bucket
= connection
.create_bucket(bucket_name
)
984 key
= boto
.s3
.key
.Key(bucket
)
986 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'rm', '--uid', user1
])
989 # TESTCASE 'rm-user2', 'user', 'rm', 'user with data', 'succeeds'
990 bucket
= connection
.create_bucket(bucket_name
)
991 key
= boto
.s3
.key
.Key(bucket
)
992 key
.set_contents_from_string('twelve')
994 (err
, out
) = rgwadmin(ctx
, client
,
995 ['user', 'rm', '--uid', user1
, '--purge-data' ],
998 # TESTCASE 'rm-user3','user','rm','deleted user','fails'
999 (err
, out
) = rgwadmin(ctx
, client
, ['user', 'info', '--uid', user1
])
1002 # TESTCASE 'zone-info', 'zone', 'get', 'get zone info', 'succeeds, has default placement rule'
1006 (err
, out
) = rgwadmin(ctx
, client
, ['zone', 'get','--rgw-zone','default'])
1008 (err
, out
) = rgwadmin(ctx
, client
, ['zone', 'get'])
1009 orig_placement_pools
= len(out
['placement_pools'])
1011 # removed this test, it is not correct to assume that zone has default placement, it really
1012 # depends on how we set it up before
1014 # assert len(out) > 0
1015 # assert len(out['placement_pools']) == 1
1017 # default_rule = out['placement_pools'][0]
1018 # assert default_rule['key'] == 'default-placement'
1020 rule
={'key': 'new-placement', 'val': {'data_pool': '.rgw.buckets.2', 'index_pool': '.rgw.buckets.index.2'}}
1022 out
['placement_pools'].append(rule
)
1024 (err
, out
) = rgwadmin(ctx
, client
, ['zone', 'set'],
1025 stdin
=StringIO(json
.dumps(out
)),
1029 (err
, out
) = rgwadmin(ctx
, client
, ['zone', 'get','--rgw-zone','default'])
1031 (err
, out
) = rgwadmin(ctx
, client
, ['zone', 'get'])
1033 assert len(out
['placement_pools']) == orig_placement_pools
+ 1