Skip to content

Commit 848bc72

Browse files
authored
Merge pull request ceph#65480 from nzliu-dev/wip-admin-rest-api-for-setting-account-quota
rgw: Implement Admin REST APIs for Setting Account Quota Reviewed-by: Ville Ojamo <[email protected]> Reviewed-by: Casey Bodley <[email protected]>
2 parents a99c77a + 187573e commit 848bc72

File tree

8 files changed

+2010
-710
lines changed

8 files changed

+2010
-710
lines changed

doc/radosgw/adminops.rst

Lines changed: 721 additions & 5 deletions
Large diffs are not rendered by default.

qa/tasks/radosgw_admin_rest.py

Lines changed: 173 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,10 @@ def rgwadmin_rest(connection, cmd, params=None, headers=None, raw=False):
2929
"""
3030
log.info('radosgw-admin-rest: %s %s' % (cmd, params))
3131
put_cmds = ['create', 'link', 'add', 'set']
32-
post_cmds = ['unlink', 'modify']
32+
post_cmds = ['unlink', 'modify', 'post']
3333
delete_cmds = ['trim', 'rm', 'process']
3434
get_cmds = ['check', 'info', 'show', 'list', 'get', '']
3535

36-
bucket_sub_resources = ['object', 'policy', 'index']
37-
user_sub_resources = ['subuser', 'key', 'caps', 'quota']
38-
zone_sub_resources = ['pool', 'log', 'garbage']
39-
4036
def get_cmd_method_and_handler(cmd):
4137
"""
4238
Get the rest command and handler from information in cmd and
@@ -53,29 +49,21 @@ def get_cmd_method_and_handler(cmd):
5349

5450
def get_resource(cmd):
5551
"""
56-
Get the name of the resource from information in cmd.
52+
Always return (resource, subresource) as a 2-tuple.
53+
Accepts:
54+
['user','info'] -> ('user','')
55+
[('user','key'),'create'] -> ('user','key')
56+
['info',''] -> ('info','')
5757
"""
58-
if cmd[0] == 'bucket' or cmd[0] in bucket_sub_resources:
59-
if cmd[0] == 'bucket':
60-
return 'bucket', ''
61-
else:
62-
return 'bucket', cmd[0]
63-
elif cmd[0] == 'user' or cmd[0] in user_sub_resources:
64-
if cmd[0] == 'user':
65-
return 'user', ''
66-
else:
67-
return 'user', cmd[0]
68-
elif cmd[0] == 'usage':
69-
return 'usage', ''
70-
elif cmd[0] == 'info':
71-
return 'info', ''
72-
elif cmd[0] == 'ratelimit':
73-
return 'ratelimit', ''
74-
elif cmd[0] == 'zone' or cmd[0] in zone_sub_resources:
75-
if cmd[0] == 'zone':
76-
return 'zone', ''
58+
r = cmd[0]
59+
if isinstance(r, (list, tuple)):
60+
if len(r) == 1:
61+
return r[0], ''
7762
else:
78-
return 'zone', cmd[0]
63+
return r
64+
if isinstance(r, str):
65+
return r, ''
66+
raise TypeError(f'Unsupported resource type for {str(r)}')
7967

8068
def build_admin_request(conn, method, resource = '', headers=None, data='',
8169
query_args=None, params=None):
@@ -302,7 +290,7 @@ def task(ctx, config):
302290
admin_display_name = 'Ms. Admin User'
303291
admin_access_key = 'MH1WC2XQ1S8UISFDZC8W'
304292
admin_secret_key = 'dQyrTPA0s248YeN5bBv4ukvKU0kh54LWWywkrpoG'
305-
admin_caps = 'users=read, write; usage=read, write; buckets=read, write; zone=read, write; info=read;ratelimit=read, write'
293+
admin_caps = 'users=read, write; usage=read, write; buckets=read, write; zone=read, write; info=read; ratelimit=read, write; accounts=read, write'
306294

307295
user1 = 'foo'
308296
user2 = 'fud'
@@ -320,6 +308,7 @@ def task(ctx, config):
320308
swift_secret2 = 'ri2VJQcKSYATOY6uaDUX7pxgkW+W1YmC6OCxPHwy'
321309

322310
bucket_name = 'myfoo'
311+
account_id = 'RGW00000000000000001'
323312

324313
# legend (test cases can be easily grep-ed out)
325314
# TESTCASE 'testname','object','method','operation','assertion'
@@ -476,7 +465,7 @@ def task(ctx, config):
476465

477466
# TESTCASE 'add-keys','key','create','w/valid info','succeeds'
478467
(ret, out) = rgwadmin_rest(admin_conn,
479-
['key', 'create'],
468+
[('user', 'key'), 'create'],
480469
{'uid' : user1,
481470
'access-key' : access_key2,
482471
'secret-key' : secret_key2
@@ -494,7 +483,7 @@ def task(ctx, config):
494483

495484
# TESTCASE 'rm-key','key','rm','newly added key','succeeds, key is removed'
496485
(ret, out) = rgwadmin_rest(admin_conn,
497-
['key', 'rm'],
486+
[('user', 'key'), 'rm'],
498487
{'uid' : user1,
499488
'access-key' : access_key2
500489
})
@@ -509,7 +498,7 @@ def task(ctx, config):
509498

510499
# TESTCASE 'add-swift-key','key','create','swift key','succeeds'
511500
(ret, out) = rgwadmin_rest(admin_conn,
512-
['subuser', 'create'],
501+
[('user', 'subuser'), 'create'],
513502
{'subuser' : subuser1,
514503
'secret-key' : swift_secret1,
515504
'key-type' : 'swift'
@@ -526,7 +515,7 @@ def task(ctx, config):
526515

527516
# TESTCASE 'add-swift-subuser','key','create','swift sub-user key','succeeds'
528517
(ret, out) = rgwadmin_rest(admin_conn,
529-
['subuser', 'create'],
518+
[('user', 'subuser'), 'create'],
530519
{'subuser' : subuser2,
531520
'secret-key' : swift_secret2,
532521
'key-type' : 'swift'
@@ -543,7 +532,7 @@ def task(ctx, config):
543532

544533
# TESTCASE 'rm-swift-key1','key','rm','subuser','succeeds, one key is removed'
545534
(ret, out) = rgwadmin_rest(admin_conn,
546-
['key', 'rm'],
535+
[('user', 'key'), 'rm'],
547536
{'subuser' : subuser1,
548537
'key-type' :'swift'
549538
})
@@ -555,7 +544,7 @@ def task(ctx, config):
555544

556545
# TESTCASE 'rm-subuser','subuser','rm','subuser','success, subuser is removed'
557546
(ret, out) = rgwadmin_rest(admin_conn,
558-
['subuser', 'rm'],
547+
[('user', 'subuser'), 'rm'],
559548
{'subuser' : subuser1
560549
})
561550

@@ -566,7 +555,7 @@ def task(ctx, config):
566555

567556
# TESTCASE 'rm-subuser-with-keys','subuser','rm','subuser','succeeds, second subser and key is removed'
568557
(ret, out) = rgwadmin_rest(admin_conn,
569-
['subuser', 'rm'],
558+
[('user', 'subuser'), 'rm'],
570559
{'subuser' : subuser2,
571560
'key-type' : 'swift',
572561
'{purge-keys' :True
@@ -712,7 +701,7 @@ def task(ctx, config):
712701
key.set_contents_from_string(object_name)
713702

714703
# now delete it
715-
(ret, out) = rgwadmin_rest(admin_conn, ['object', 'rm'], {'bucket' : bucket_name, 'object' : object_name})
704+
(ret, out) = rgwadmin_rest(admin_conn, [('bucket', 'object'), 'rm'], {'bucket' : bucket_name, 'object' : object_name})
716705
assert ret == 200
717706

718707
# TESTCASE 'bucket-stats6','bucket','stats','after deleting key','succeeds, lists one no objects'
@@ -837,14 +826,14 @@ def task(ctx, config):
837826
# should be private already but guarantee it
838827
key.set_acl('private')
839828

840-
(ret, out) = rgwadmin_rest(admin_conn, ['policy', 'show'], {'bucket' : bucket.name, 'object' : key.key})
829+
(ret, out) = rgwadmin_rest(admin_conn, [('bucket', 'policy'), 'show'], {'bucket' : bucket.name, 'object' : key.key})
841830
assert ret == 200
842831
assert len(out['acl']['grant_map']) == 1
843832

844833
# add another grantee by making the object public read
845834
key.set_acl('public-read')
846835

847-
(ret, out) = rgwadmin_rest(admin_conn, ['policy', 'show'], {'bucket' : bucket.name, 'object' : key.key})
836+
(ret, out) = rgwadmin_rest(admin_conn, [('bucket', 'policy'), 'show'], {'bucket' : bucket.name, 'object' : key.key})
848837
assert ret == 200
849838
assert len(out['acl']['grant_map']) == 2
850839

@@ -865,12 +854,12 @@ def task(ctx, config):
865854

866855
# TESTCASE 'caps-add', 'caps', 'add', 'add user cap', 'succeeds'
867856
caps = 'usage=read'
868-
(ret, out) = rgwadmin_rest(admin_conn, ['caps', 'add'], {'uid' : user1, 'user-caps' : caps})
857+
(ret, out) = rgwadmin_rest(admin_conn, [('user', 'caps'), 'add'], {'uid' : user1, 'user-caps' : caps})
869858
assert ret == 200
870859
assert out[0]['perm'] == 'read'
871860

872861
# TESTCASE 'caps-rm', 'caps', 'rm', 'remove existing cap from user', 'succeeds'
873-
(ret, out) = rgwadmin_rest(admin_conn, ['caps', 'rm'], {'uid' : user1, 'user-caps' : caps})
862+
(ret, out) = rgwadmin_rest(admin_conn, [('user', 'caps'), 'rm'], {'uid' : user1, 'user-caps' : caps})
874863
assert ret == 200
875864
assert not out
876865

@@ -1053,3 +1042,148 @@ def task(ctx, config):
10531042
assert user_ratelimit['max_list_ops'] == 600
10541043
assert user_ratelimit['max_delete_ops'] == 400
10551044

1045+
# TESTCASE 'create account' 'account' 'post' 'creating a new account' 'succeeds'
1046+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'post'], {'id' : account_id, 'name': account_id})
1047+
assert ret == 200
1048+
1049+
# TESTCASE 'account-info' 'account' 'info' 'getting the account info, including its quota, and checking for default values' 'succeeds'
1050+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'info'], {'id' : account_id})
1051+
assert ret == 200
1052+
account_quota = out['quota']
1053+
assert not account_quota["enabled"]
1054+
assert account_quota["max_size"] == -1
1055+
assert account_quota["max_objects"] == -1
1056+
bucket_quota = out['bucket_quota']
1057+
assert not bucket_quota["enabled"]
1058+
assert bucket_quota["max_size"] == -1
1059+
assert bucket_quota["max_objects"] == -1
1060+
assert out["max_users"] == 1000
1061+
assert out["max_roles"] == 1000
1062+
assert out["max_groups"] == 1000
1063+
assert out["max_buckets"] == 1000
1064+
assert out["max_access_keys"] == 4
1065+
1066+
# TESTCASE 'bucket-level-account-quota-set' 'account-quota-set' 'setting account quota at the bucket level. Other values should remain the same' 'succeeds'
1067+
(ret, out) = rgwadmin_rest(admin_conn, [('account', 'quota'), 'set'], {'id': account_id, 'quota-type' : 'bucket', 'max-size': 12345, 'max-objects' : 54321, 'enabled': True})
1068+
assert ret == 200
1069+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'info'], {'id' : account_id})
1070+
assert ret == 200
1071+
# verifying bucket-level quota has been changed
1072+
bucket_quota = out['bucket_quota']
1073+
assert bucket_quota["enabled"]
1074+
assert bucket_quota["max_size"] == 12345
1075+
assert bucket_quota["max_objects"] == 54321
1076+
# verifying the rest of the values remain the same
1077+
account_quota = out['quota']
1078+
assert not account_quota["enabled"]
1079+
assert account_quota["max_size"] == -1
1080+
assert account_quota["max_objects"] == -1
1081+
assert out["max_users"] == 1000
1082+
assert out["max_roles"] == 1000
1083+
assert out["max_groups"] == 1000
1084+
assert out["max_buckets"] == 1000
1085+
assert out["max_access_keys"] == 4
1086+
# cleanup the account
1087+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'rm'], {'id' : account_id})
1088+
assert ret == 200
1089+
1090+
1091+
# TESTCASE 'account-level-quota-set' 'account-quota-set' 'setting account quota at the account level. Other values should remain the same' 'succeeds'
1092+
# re-create the account
1093+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'post'], {'id' : account_id, 'name': account_id})
1094+
assert ret == 200
1095+
(ret, out) = rgwadmin_rest(admin_conn, [('account', 'quota'), 'set'], {'id': account_id, 'quota-type' : 'account', 'max-size': 12345, 'max-objects' : 54321, 'enabled': True})
1096+
assert ret == 200
1097+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'info'], {'id' : account_id})
1098+
assert ret == 200
1099+
# verifying account-level quota has been changed
1100+
account_quota = out['quota']
1101+
assert account_quota["enabled"]
1102+
assert account_quota["max_size"] == 12345
1103+
assert account_quota["max_objects"] == 54321
1104+
# verifying the rest of the values remain the same
1105+
bucket_quota = out['bucket_quota']
1106+
assert not bucket_quota["enabled"]
1107+
assert bucket_quota["max_size"] == -1
1108+
assert bucket_quota["max_objects"] == -1
1109+
assert out["max_users"] == 1000
1110+
assert out["max_roles"] == 1000
1111+
assert out["max_groups"] == 1000
1112+
assert out["max_buckets"] == 1000
1113+
assert out["max_access_keys"] == 4
1114+
# cleanup the account
1115+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'rm'], {'id' : account_id})
1116+
assert ret == 200
1117+
1118+
# TESTCASE 'account-quota-set-invalid-args' 'account-quota-set' 'verify set quota requests with invalid args fail' 'fails'
1119+
# re-create the account
1120+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'post'], {'id' : account_id, 'name': account_id})
1121+
assert ret == 200
1122+
1123+
# verify invalid quota-type fails
1124+
(ret, out) = rgwadmin_rest(admin_conn, [('account', 'quota'), 'set'], {'id': account_id, 'quota-type' : 'invalid', 'max-size': 12345, 'max-objects' : 54321, 'enabled': True})
1125+
assert ret == 400
1126+
1127+
# verify empty quota-type fails
1128+
(ret, out) = rgwadmin_rest(admin_conn, [('account', 'quota'), 'set'], {'id': account_id, 'max-size': 12345, 'max-objects' : 54321, 'enabled': True})
1129+
assert ret == 400
1130+
1131+
# verify request with no account id fails
1132+
(ret, out) = rgwadmin_rest(admin_conn, [('account', 'quota'), 'set'], {'quota-type' : 'bucket', 'max-size': 12345, 'max-objects' : 54321, 'enabled': True})
1133+
assert ret == 400
1134+
1135+
# cleanup the account
1136+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'rm'], {'id' : account_id})
1137+
assert ret == 200
1138+
1139+
# TESTCASE 'rm account caps' 'user-caps-rm' 'verify access after removing user caps for account read and write' 'fails'
1140+
(err, out) = rgwadmin(ctx, client, [
1141+
'caps', 'rm',
1142+
'--uid', admin_user,
1143+
'--caps', 'accounts=read, write'
1144+
])
1145+
logging.error(out)
1146+
logging.error(err)
1147+
assert not err
1148+
1149+
# checking failed access to create account
1150+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'post'], {'id' : account_id, 'name': account_id})
1151+
assert ret == 403
1152+
1153+
# checking failed access to set quota
1154+
(ret, out) = rgwadmin_rest(admin_conn, [('account', 'quota'), 'set'], {'id': account_id, 'quota-type' : 'account', 'max-size': -1, 'max-objects' : -1, 'enabled': True})
1155+
assert ret == 403
1156+
1157+
# checking failed access to get account info
1158+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'info'], {'id' : account_id})
1159+
assert ret == 403
1160+
1161+
# checking failed access to remove account
1162+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'rm'], {'id' : account_id})
1163+
assert ret == 403
1164+
1165+
# TESTCASE 'add back account caps' 'user-caps-add' 'verify access after adding back user caps for account read and write' 'succeeds'
1166+
(err, out) = rgwadmin(ctx, client, [
1167+
'caps', 'add',
1168+
'--uid', admin_user,
1169+
'--caps', 'accounts=read, write'
1170+
])
1171+
logging.error(out)
1172+
logging.error(err)
1173+
assert not err
1174+
1175+
# checking create account access
1176+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'post'], {'id' : account_id, 'name': account_id})
1177+
assert ret == 200
1178+
1179+
# checking set quota access
1180+
(ret, out) = rgwadmin_rest(admin_conn, [('account', 'quota'), 'set'], {'id': account_id, 'quota-type' : 'account', 'max-size': -1, 'max-objects' : -1, 'enabled': True})
1181+
assert ret == 200
1182+
1183+
# checking get account info access
1184+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'info'], {'id' : account_id})
1185+
assert ret == 200
1186+
1187+
# checking remove account access
1188+
(ret, out) = rgwadmin_rest(admin_conn, ['account', 'rm'], {'id' : account_id})
1189+
assert ret == 200

0 commit comments

Comments
 (0)