From: Yehuda Sadeh Date: Mon, 10 May 2021 23:43:46 +0000 (-0700) Subject: rgwam: rename file X-Git-Tag: v17.1.0~340^2~27 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ec2391f7f52a32c6b4e42f685bf40f4ec8df1943;p=ceph.git rgwam: rename file Signed-off-by: Yehuda Sadeh --- diff --git a/src/rgw/rgw_admin_multi.py b/src/rgw/rgw_admin_multi.py deleted file mode 100644 index b1c71a07fdab..000000000000 --- a/src/rgw/rgw_admin_multi.py +++ /dev/null @@ -1,637 +0,0 @@ -import subprocess -import random -import string -import json -import argparse -import sys -import socket -import base64 - -from urllib.parse import urlparse - -DEFAULT_PORT = 8000 - -def bool_str(x): - return 'true' if x else 'false' - -def rand_alphanum_lower(l): - return ''.join(random.choices(string.ascii_lowercase + string.digits, k=l)) - -def get_endpoints(endpoints, period = None): - if endpoints: - return endpoints - - hostname = socket.getfqdn() - - port = DEFAULT_PORT - - while True: - ep = 'http://%s:%d' % (hostname, port) - if not period or not period.endpoint_exists(ep): - return ep - port += 1 - -class JSONObj: - def to_json(self): - return json.dumps(self, default=lambda o: o.__dict__, indent=4) - -class RealmAccessConf(JSONObj): - def __init__(self, endpoint, uid, access_key, secret): - self.endpoint = endpoint - self.uid = uid - self.access_key = access_key - self.secret = secret - -class RGWZone(JSONObj): - def __init__(self, zone_dict): - self.id = zone_dict['id'] - self.name = zone_dict['name'] - self.endpoints = zone_dict['endpoints'] - -class RGWZoneGroup(JSONObj): - def __init__(self, zg_dict): - self.id = zg_dict['id'] - self.name = zg_dict['name'] - self.api_name = zg_dict['api_name'] - self.is_master = zg_dict['is_master'] - self.endpoints = zg_dict['endpoints'] - - self.zones_by_id = {} - self.zones_by_name = {} - self.all_endpoints = [] - - for zone in zg_dict['zones']: - z = RGWZone(zone) - self.zones_by_id[zone['id']] = z - self.zones_by_name[zone['name']] = z - self.all_endpoints += z.endpoints - - def endpoint_exists(self, endpoint): - for ep in self.all_endpoints: - if ep == endpoint: - return True - return False - -class RGWPeriod(JSONObj): - def __init__(self, period_dict): - self.id = period_dict['id'] - self.epoch = period_dict['epoch'] - pm = period_dict['period_map'] - self.zonegroups_by_id = {} - self.zonegroups_by_name = {} - - for zg in pm['zonegroups']: - self.zonegroups_by_id[zg['id']] = RGWZoneGroup(zg) - self.zonegroups_by_name[zg['name']] = RGWZoneGroup(zg) - - def endpoint_exists(self, endpoint): - for _, zg in self.zonegroups_by_id.items(): - if zg.endpoint_exists(endpoint): - return True - return False - - def find_zonegroup(self, zonegroup): - for _, zg in self.zonegroups_by_id.items(): - if not zonegroup or zg.name == zonegroup: - return zg.name - return None - -class RGWAccessKey(JSONObj): - def __init__(self, d): - self.uid = d['user'] - self.access_key = d['access_key'] - self.secret_key = d['secret_key'] - -class RGWUser(JSONObj): - def __init__(self, d): - self.uid = d['user_id'] - self.display_name = d['display_name'] - self.email = d['email'] - - self.keys = [] - - for k in d['keys']: - self.keys.append(RGWAccessKey(k)) - - is_system = d.get('system') or 'false' - self.system = (is_system == 'true') - - - -class RGWAMException(BaseException): - def __init__(self, message): - self.message = message - - -class RGWAdminCmd: - def __init__(self): - self.cmd_prefix = [ 'radosgw-admin' ] - - def run(self, cmd): - run_cmd = self.cmd_prefix + cmd - result = subprocess.run(run_cmd, stdout=subprocess.PIPE) - return (result.returncode, result.stdout) - -class RGWCmd: - def __init__(self): - self.cmd_prefix = [ 'radosgw' ] - - def run(self, cmd): - run_cmd = self.cmd_prefix + cmd - result = subprocess.run(run_cmd, stdout=subprocess.PIPE) - return (result.returncode, result.stdout) - -class RealmOp(RGWAdminCmd): - def __init__(self): - RGWAdminCmd.__init__(self) - - def create(self, name = None, is_default = True): - self.name = name - if not self.name: - self.name = 'realm-' + rand_alphanum_lower(8) - - params = [ 'realm', - 'create', - '--rgw-realm', self.name ] - - if is_default: - params += [ '--default' ] - - retcode, stdout = RGWAdminCmd.run(self, params) - if retcode != 0: - return None - - self.info = json.loads(stdout) - - return self.info - - def pull(self, url, access_key, secret, set_default = False): - params = [ 'realm', - 'pull', - '--url', url, - '--access-key', access_key, - '--secret', secret ] - - if set_default: - params += [ '--default' ] - - retcode, stdout = RGWAdminCmd.run(self, params) - if retcode != 0: - return None - - self.info = json.loads(stdout) - - self.name = self.info['name'] - - return self.info - -class ZonegroupOp(RGWAdminCmd): - def __init__(self): - RGWAdminCmd.__init__(self) - - def create(self, realm, name = None, endpoints = None, is_master = True, is_default = True): - self.name = name - if not self.name: - self.name = 'zg-' + rand_alphanum_lower(8) - - params = [ 'zonegroup', - 'create', - '--rgw-realm', realm, - '--rgw-zonegroup', self.name, - '--endpoints', endpoints ] - - if is_master: - params += [ '--master' ] - - if is_default: - params += [ '--default' ] - - retcode, stdout = RGWAdminCmd.run(self, params) - if retcode != 0: - return None - - self.info = json.loads(stdout) - - return self.info - -class ZoneOp(RGWAdminCmd): - def __init__(self): - RGWAdminCmd.__init__(self) - - def create(self, realm, zonegroup, name = None, endpoints = None, is_master = True, is_default = True, - access_key = None, secret = None): - self.name = name - if not self.name: - self.name = 'zg-' + rand_alphanum_lower(8) - - params = [ 'zone', - 'create', - '--rgw-realm', realm, - '--rgw-zonegroup', zonegroup, - '--rgw-zone', self.name, - '--endpoints', endpoints ] - - if is_master: - params += [ '--master' ] - - if is_default: - params += [ '--default' ] - - if access_key: - params += [ '--access-key', access_key ] - - if secret: - params += [ '--secret', secret ] - - retcode, stdout = RGWAdminCmd.run(self, params) - if retcode != 0: - return None - - self.info = json.loads(stdout) - - return self.info - - def modify(self, endpoints = None, is_master = None, is_default = None, access_key = None, secret = None): - params = [ 'zone', - 'modify' ] - - if endpoints: - params += [ '--endpoints', endpoints ] - - if is_master is not None: - params += [ '--master', bool_str(is_master) ] - - if is_default is not None: - params += [ '--default', bool_str(is_default) ] - - if access_key: - params += [ '--access-key', access_key ] - - if secret: - params += [ '--secret', secret ] - - retcode, stdout = RGWAdminCmd.run(self, params) - if retcode != 0: - return None - - self.info = json.loads(stdout) - - return self.info - -class PeriodOp(RGWAdminCmd): - def __init__(self): - RGWAdminCmd.__init__(self) - - def update(self, realm, commit = True): - - params = [ 'period', - 'update', - '--rgw-realm', realm ] - - if commit: - params += [ '--commit' ] - - retcode, stdout = RGWAdminCmd.run(self, params) - if retcode != 0: - return None - - self.info = json.loads(stdout) - - return self.info - - def get(self, realm = None): - params = [ 'period', - 'get' ] - - if realm: - params += [ '--rgw-realm', realm ] - - retcode, stdout = RGWAdminCmd.run(self, params) - if retcode != 0: - return None - - self.info = json.loads(stdout) - - return self.info - -class UserOp(RGWAdminCmd): - def __init__(self): - RGWAdminCmd.__init__(self) - - def create(self, uid = None, uid_prefix = None, display_name = None, email = None, is_system = False): - self.uid = uid - if not self.uid: - prefix = uid_prefix or 'user' - self.uid = prefix + '-' + rand_alphanum_lower(6) - - self.display_name = display_name - if not self.display_name: - self.display_name = self.uid - - params = [ 'user', - 'create', - '--uid', self.uid, - '--display-name', self.display_name ] - - if email: - params += [ '--email', email ] - - if is_system: - params += [ '--system' ] - - retcode, stdout = RGWAdminCmd.run(self, params) - if retcode != 0: - return None - - self.info = json.loads(stdout) - - return self.info - -class RGWAM: - def __init__(self): - pass - - def realm_bootstrap(self, realm, zonegroup, zone, endpoints, sys_uid, uid): - endpoints = get_endpoints(endpoints) - - realm_info = RealmOp().create(realm) - if not realm_info: - return - - realm_name = realm_info['name'] - realm_id = realm_info['id'] - print('Created realm %s (%s)' % (realm_name, realm_id)) - - zg_info = ZonegroupOp().create(realm_name, zonegroup, endpoints, True, True) - if not zg_info: - return - - zg_name = zg_info['name'] - zg_id = zg_info['id'] - print('Created zonegroup %s (%s)' % (zg_name, zg_id)) - - zone_info = ZoneOp().create(realm_name, zg_name, zone, endpoints, True, True) - if not zone_info: - return - - zone_name = zone_info['name'] - zone_id = zone_info['id'] - print('Created zone %s (%s)' % (zone_name, zone_id)) - - period_info = PeriodOp().update(realm_name, True) - if not period_info: - return - - period = RGWPeriod(period_info) - - print('Period: ' + period.id) - - sys_user_info = UserOp().create(uid = sys_uid, uid_prefix = 'user-sys', is_system = True) - - sys_user = RGWUser(sys_user_info) - - print('Created system user: %s' % sys_user.uid) - - sys_access_key = '' - sys_secret = '' - - if len(sys_user.keys) > 0: - sys_access_key = sys_user.keys[0].access_key - sys_secret = sys_user.keys[0].secret_key - - zone_info = ZoneOp().modify(endpoints, None, None, sys_access_key, sys_secret) - if not zone_info: - return - - user_info = UserOp().create(uid = uid, is_system = False) - - user = RGWUser(user_info) - - print('Created regular user: %s' % user.uid) - - eps = endpoints.split(',') - ep = '' - if len(eps) > 0: - ep = eps[0] - o = urlparse(ep) - self.run_radosgw(port = o.port) - - - realm_access = RealmAccessConf(ep, sys_user.uid, sys_access_key, sys_secret) - - print(realm_access.to_json()) - - realm_access_b = realm_access.to_json().encode('utf-8') - print('Realm Access Conf (b64): %s' % base64.b64encode(realm_access_b).decode('utf-8')) - - - def zone_create(self, realm_access_b64, zonegroup = None, zone = None, endpoints = None): - if not realm_access_b64: - print('ERROR: missing realm access config') - return - - realm_access_b = base64.b64decode(realm_access_b64) - realm_access_s = realm_access_b.decode('utf-8') - - realm_access = json.loads(realm_access_s) - - access_key = realm_access['access_key'] - secret = realm_access['secret'] - - realm_info = RealmOp().pull(realm_access['endpoint'], access_key, secret, set_default = True) - if not realm_info: - return - - realm_name = realm_info['name'] - realm_id = realm_info['id'] - print('Pulled realm %s (%s)' % (realm_name, realm_id)) - - period_info = PeriodOp().get() - - period = RGWPeriod(period_info) - - print('Period: ' + period.id) - endpoints = get_endpoints(endpoints, period) - - zg_name = period.find_zonegroup(zonegroup) - if not zg_name: - print("ERROR: zonegroup %s not found" % (zonegroup or '')) - return - - zone_info = ZoneOp().create(realm_name, zg_name, zone, endpoints, False, True, - access_key, secret) - if not zone_info: - return - - zone_name = zone_info['name'] - zone_id = zone_info['id'] - print('Created zone %s (%s)' % (zone_name, zone_id)) - - period_info = PeriodOp().update(realm_name, True) - if not period_info: - return - - period = RGWPeriod(period_info) - - print(period.to_json()) - - eps = endpoints.split(',') - ep = '' - if len(eps) > 0: - ep = eps[0] - o = urlparse(ep) - self.run_radosgw(port = o.port) - - def run_radosgw(self, port = None, log_file = None, debug_ms = None, debug_rgw = None): - - fe_cfg = 'beast' - if port: - fe_cfg += ' port=%s' % port - - - params = [ '--rgw-frontends', fe_cfg ] - - if log_file: - params += [ '--log-file', log_file ] - - if debug_ms: - params += [ '--debug-ms', debug_ms ] - - if debug_rgw: - params += [ '--debug-rgw', debug_rgw ] - - RGWCmd().run(params) - - -class RealmCommand: - def __init__(self, args): - self.args = args - - def parse(self): - parser = argparse.ArgumentParser( - description='S3 control tool', - usage='''rgwam realm - -The subcommands are: - bootstrap Manipulate bucket versioning -''') - parser.add_argument('subcommand', help='Subcommand to run') - # parse_args defaults to [1:] for args, but you need to - # exclude the rest of the args too, or validation will fail - args = parser.parse_args(self.args[0:1]) - if not hasattr(self, args.subcommand): - print('Unrecognized subcommand:', args.subcommand) - parser.print_help() - exit(1) - # use dispatch pattern to invoke method with same name - return getattr(self, args.subcommand) - - def bootstrap(self): - parser = argparse.ArgumentParser( - description='Bootstrap new realm', - usage='rgwam realm bootstrap []') - parser.add_argument('--realm') - parser.add_argument('--zonegroup') - parser.add_argument('--zone') - parser.add_argument('--endpoints') - parser.add_argument('--sys-uid') - parser.add_argument('--uid') - - args = parser.parse_args(self.args[1:]) - - RGWAM().realm_bootstrap(args.realm, args.zonegroup, args.zone, args.endpoints, - args.sys_uid, args.uid) - - -class ZoneCommand: - def __init__(self, args): - self.args = args - - def parse(self): - parser = argparse.ArgumentParser( - description='S3 control tool', - usage='''rgwam zone - -The subcommands are: - run run radosgw daemon in current zone -''') - parser.add_argument('subcommand', help='Subcommand to run') - # parse_args defaults to [1:] for args, but you need to - # exclude the rest of the args too, or validation will fail - args = parser.parse_args(self.args[0:1]) - if not hasattr(self, args.subcommand): - print('Unrecognized subcommand:', args.subcommand) - parser.print_help() - exit(1) - # use dispatch pattern to invoke method with same name - return getattr(self, args.subcommand) - - def run(self): - parser = argparse.ArgumentParser( - description='Run radosgw daemon', - usage='rgwam zone run []') - parser.add_argument('--port') - parser.add_argument('--log-file') - parser.add_argument('--debug-ms') - parser.add_argument('--debug-rgw') - - args = parser.parse_args(self.args[1:]) - - RGWAM().run_radosgw(port = args.port) - - def create(self): - parser = argparse.ArgumentParser( - description='Create new zone to join existing realm', - usage='rgwam zone create []') - parser.add_argument('--realm-access') - parser.add_argument('--zone') - parser.add_argument('--zonegroup') - parser.add_argument('--endpoints') - - args = parser.parse_args(self.args[1:]) - - RGWAM().zone_create(args.realm_access, args.zonegroup, args.zone, args.endpoints) - - -class TopLevelCommand: - - def _parse(self): - parser = argparse.ArgumentParser( - description='RGW assist for multisite tool', - usage='''rgwam [] - -The commands are: - realm bootstrap Bootstrap realm - zone run Run radosgw in current zone -''') - parser.add_argument('command', help='Subcommand to run') - # parse_args defaults to [1:] for args, but you need to - # exclude the rest of the args too, or validation will fail - args = parser.parse_args(sys.argv[1:2]) - if not hasattr(self, args.command) or args.command[0] == '_': - print('Unrecognized command:', args.command) - parser.print_help() - exit(1) - # use dispatch pattern to invoke method with same name - return getattr(self, args.command) - - def realm(self): - cmd = RealmCommand(sys.argv[2:]).parse() - cmd() - - def zone(self): - cmd = ZoneCommand(sys.argv[2:]).parse() - cmd() - - -def main(): - cmd = TopLevelCommand()._parse() - try: - cmd() - except RGWAMException as e: - print('ERROR: ' + e.message) - - -if __name__ == '__main__': - main() - diff --git a/src/rgw/rgwam.py b/src/rgw/rgwam.py new file mode 100644 index 000000000000..b1c71a07fdab --- /dev/null +++ b/src/rgw/rgwam.py @@ -0,0 +1,637 @@ +import subprocess +import random +import string +import json +import argparse +import sys +import socket +import base64 + +from urllib.parse import urlparse + +DEFAULT_PORT = 8000 + +def bool_str(x): + return 'true' if x else 'false' + +def rand_alphanum_lower(l): + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=l)) + +def get_endpoints(endpoints, period = None): + if endpoints: + return endpoints + + hostname = socket.getfqdn() + + port = DEFAULT_PORT + + while True: + ep = 'http://%s:%d' % (hostname, port) + if not period or not period.endpoint_exists(ep): + return ep + port += 1 + +class JSONObj: + def to_json(self): + return json.dumps(self, default=lambda o: o.__dict__, indent=4) + +class RealmAccessConf(JSONObj): + def __init__(self, endpoint, uid, access_key, secret): + self.endpoint = endpoint + self.uid = uid + self.access_key = access_key + self.secret = secret + +class RGWZone(JSONObj): + def __init__(self, zone_dict): + self.id = zone_dict['id'] + self.name = zone_dict['name'] + self.endpoints = zone_dict['endpoints'] + +class RGWZoneGroup(JSONObj): + def __init__(self, zg_dict): + self.id = zg_dict['id'] + self.name = zg_dict['name'] + self.api_name = zg_dict['api_name'] + self.is_master = zg_dict['is_master'] + self.endpoints = zg_dict['endpoints'] + + self.zones_by_id = {} + self.zones_by_name = {} + self.all_endpoints = [] + + for zone in zg_dict['zones']: + z = RGWZone(zone) + self.zones_by_id[zone['id']] = z + self.zones_by_name[zone['name']] = z + self.all_endpoints += z.endpoints + + def endpoint_exists(self, endpoint): + for ep in self.all_endpoints: + if ep == endpoint: + return True + return False + +class RGWPeriod(JSONObj): + def __init__(self, period_dict): + self.id = period_dict['id'] + self.epoch = period_dict['epoch'] + pm = period_dict['period_map'] + self.zonegroups_by_id = {} + self.zonegroups_by_name = {} + + for zg in pm['zonegroups']: + self.zonegroups_by_id[zg['id']] = RGWZoneGroup(zg) + self.zonegroups_by_name[zg['name']] = RGWZoneGroup(zg) + + def endpoint_exists(self, endpoint): + for _, zg in self.zonegroups_by_id.items(): + if zg.endpoint_exists(endpoint): + return True + return False + + def find_zonegroup(self, zonegroup): + for _, zg in self.zonegroups_by_id.items(): + if not zonegroup or zg.name == zonegroup: + return zg.name + return None + +class RGWAccessKey(JSONObj): + def __init__(self, d): + self.uid = d['user'] + self.access_key = d['access_key'] + self.secret_key = d['secret_key'] + +class RGWUser(JSONObj): + def __init__(self, d): + self.uid = d['user_id'] + self.display_name = d['display_name'] + self.email = d['email'] + + self.keys = [] + + for k in d['keys']: + self.keys.append(RGWAccessKey(k)) + + is_system = d.get('system') or 'false' + self.system = (is_system == 'true') + + + +class RGWAMException(BaseException): + def __init__(self, message): + self.message = message + + +class RGWAdminCmd: + def __init__(self): + self.cmd_prefix = [ 'radosgw-admin' ] + + def run(self, cmd): + run_cmd = self.cmd_prefix + cmd + result = subprocess.run(run_cmd, stdout=subprocess.PIPE) + return (result.returncode, result.stdout) + +class RGWCmd: + def __init__(self): + self.cmd_prefix = [ 'radosgw' ] + + def run(self, cmd): + run_cmd = self.cmd_prefix + cmd + result = subprocess.run(run_cmd, stdout=subprocess.PIPE) + return (result.returncode, result.stdout) + +class RealmOp(RGWAdminCmd): + def __init__(self): + RGWAdminCmd.__init__(self) + + def create(self, name = None, is_default = True): + self.name = name + if not self.name: + self.name = 'realm-' + rand_alphanum_lower(8) + + params = [ 'realm', + 'create', + '--rgw-realm', self.name ] + + if is_default: + params += [ '--default' ] + + retcode, stdout = RGWAdminCmd.run(self, params) + if retcode != 0: + return None + + self.info = json.loads(stdout) + + return self.info + + def pull(self, url, access_key, secret, set_default = False): + params = [ 'realm', + 'pull', + '--url', url, + '--access-key', access_key, + '--secret', secret ] + + if set_default: + params += [ '--default' ] + + retcode, stdout = RGWAdminCmd.run(self, params) + if retcode != 0: + return None + + self.info = json.loads(stdout) + + self.name = self.info['name'] + + return self.info + +class ZonegroupOp(RGWAdminCmd): + def __init__(self): + RGWAdminCmd.__init__(self) + + def create(self, realm, name = None, endpoints = None, is_master = True, is_default = True): + self.name = name + if not self.name: + self.name = 'zg-' + rand_alphanum_lower(8) + + params = [ 'zonegroup', + 'create', + '--rgw-realm', realm, + '--rgw-zonegroup', self.name, + '--endpoints', endpoints ] + + if is_master: + params += [ '--master' ] + + if is_default: + params += [ '--default' ] + + retcode, stdout = RGWAdminCmd.run(self, params) + if retcode != 0: + return None + + self.info = json.loads(stdout) + + return self.info + +class ZoneOp(RGWAdminCmd): + def __init__(self): + RGWAdminCmd.__init__(self) + + def create(self, realm, zonegroup, name = None, endpoints = None, is_master = True, is_default = True, + access_key = None, secret = None): + self.name = name + if not self.name: + self.name = 'zg-' + rand_alphanum_lower(8) + + params = [ 'zone', + 'create', + '--rgw-realm', realm, + '--rgw-zonegroup', zonegroup, + '--rgw-zone', self.name, + '--endpoints', endpoints ] + + if is_master: + params += [ '--master' ] + + if is_default: + params += [ '--default' ] + + if access_key: + params += [ '--access-key', access_key ] + + if secret: + params += [ '--secret', secret ] + + retcode, stdout = RGWAdminCmd.run(self, params) + if retcode != 0: + return None + + self.info = json.loads(stdout) + + return self.info + + def modify(self, endpoints = None, is_master = None, is_default = None, access_key = None, secret = None): + params = [ 'zone', + 'modify' ] + + if endpoints: + params += [ '--endpoints', endpoints ] + + if is_master is not None: + params += [ '--master', bool_str(is_master) ] + + if is_default is not None: + params += [ '--default', bool_str(is_default) ] + + if access_key: + params += [ '--access-key', access_key ] + + if secret: + params += [ '--secret', secret ] + + retcode, stdout = RGWAdminCmd.run(self, params) + if retcode != 0: + return None + + self.info = json.loads(stdout) + + return self.info + +class PeriodOp(RGWAdminCmd): + def __init__(self): + RGWAdminCmd.__init__(self) + + def update(self, realm, commit = True): + + params = [ 'period', + 'update', + '--rgw-realm', realm ] + + if commit: + params += [ '--commit' ] + + retcode, stdout = RGWAdminCmd.run(self, params) + if retcode != 0: + return None + + self.info = json.loads(stdout) + + return self.info + + def get(self, realm = None): + params = [ 'period', + 'get' ] + + if realm: + params += [ '--rgw-realm', realm ] + + retcode, stdout = RGWAdminCmd.run(self, params) + if retcode != 0: + return None + + self.info = json.loads(stdout) + + return self.info + +class UserOp(RGWAdminCmd): + def __init__(self): + RGWAdminCmd.__init__(self) + + def create(self, uid = None, uid_prefix = None, display_name = None, email = None, is_system = False): + self.uid = uid + if not self.uid: + prefix = uid_prefix or 'user' + self.uid = prefix + '-' + rand_alphanum_lower(6) + + self.display_name = display_name + if not self.display_name: + self.display_name = self.uid + + params = [ 'user', + 'create', + '--uid', self.uid, + '--display-name', self.display_name ] + + if email: + params += [ '--email', email ] + + if is_system: + params += [ '--system' ] + + retcode, stdout = RGWAdminCmd.run(self, params) + if retcode != 0: + return None + + self.info = json.loads(stdout) + + return self.info + +class RGWAM: + def __init__(self): + pass + + def realm_bootstrap(self, realm, zonegroup, zone, endpoints, sys_uid, uid): + endpoints = get_endpoints(endpoints) + + realm_info = RealmOp().create(realm) + if not realm_info: + return + + realm_name = realm_info['name'] + realm_id = realm_info['id'] + print('Created realm %s (%s)' % (realm_name, realm_id)) + + zg_info = ZonegroupOp().create(realm_name, zonegroup, endpoints, True, True) + if not zg_info: + return + + zg_name = zg_info['name'] + zg_id = zg_info['id'] + print('Created zonegroup %s (%s)' % (zg_name, zg_id)) + + zone_info = ZoneOp().create(realm_name, zg_name, zone, endpoints, True, True) + if not zone_info: + return + + zone_name = zone_info['name'] + zone_id = zone_info['id'] + print('Created zone %s (%s)' % (zone_name, zone_id)) + + period_info = PeriodOp().update(realm_name, True) + if not period_info: + return + + period = RGWPeriod(period_info) + + print('Period: ' + period.id) + + sys_user_info = UserOp().create(uid = sys_uid, uid_prefix = 'user-sys', is_system = True) + + sys_user = RGWUser(sys_user_info) + + print('Created system user: %s' % sys_user.uid) + + sys_access_key = '' + sys_secret = '' + + if len(sys_user.keys) > 0: + sys_access_key = sys_user.keys[0].access_key + sys_secret = sys_user.keys[0].secret_key + + zone_info = ZoneOp().modify(endpoints, None, None, sys_access_key, sys_secret) + if not zone_info: + return + + user_info = UserOp().create(uid = uid, is_system = False) + + user = RGWUser(user_info) + + print('Created regular user: %s' % user.uid) + + eps = endpoints.split(',') + ep = '' + if len(eps) > 0: + ep = eps[0] + o = urlparse(ep) + self.run_radosgw(port = o.port) + + + realm_access = RealmAccessConf(ep, sys_user.uid, sys_access_key, sys_secret) + + print(realm_access.to_json()) + + realm_access_b = realm_access.to_json().encode('utf-8') + print('Realm Access Conf (b64): %s' % base64.b64encode(realm_access_b).decode('utf-8')) + + + def zone_create(self, realm_access_b64, zonegroup = None, zone = None, endpoints = None): + if not realm_access_b64: + print('ERROR: missing realm access config') + return + + realm_access_b = base64.b64decode(realm_access_b64) + realm_access_s = realm_access_b.decode('utf-8') + + realm_access = json.loads(realm_access_s) + + access_key = realm_access['access_key'] + secret = realm_access['secret'] + + realm_info = RealmOp().pull(realm_access['endpoint'], access_key, secret, set_default = True) + if not realm_info: + return + + realm_name = realm_info['name'] + realm_id = realm_info['id'] + print('Pulled realm %s (%s)' % (realm_name, realm_id)) + + period_info = PeriodOp().get() + + period = RGWPeriod(period_info) + + print('Period: ' + period.id) + endpoints = get_endpoints(endpoints, period) + + zg_name = period.find_zonegroup(zonegroup) + if not zg_name: + print("ERROR: zonegroup %s not found" % (zonegroup or '')) + return + + zone_info = ZoneOp().create(realm_name, zg_name, zone, endpoints, False, True, + access_key, secret) + if not zone_info: + return + + zone_name = zone_info['name'] + zone_id = zone_info['id'] + print('Created zone %s (%s)' % (zone_name, zone_id)) + + period_info = PeriodOp().update(realm_name, True) + if not period_info: + return + + period = RGWPeriod(period_info) + + print(period.to_json()) + + eps = endpoints.split(',') + ep = '' + if len(eps) > 0: + ep = eps[0] + o = urlparse(ep) + self.run_radosgw(port = o.port) + + def run_radosgw(self, port = None, log_file = None, debug_ms = None, debug_rgw = None): + + fe_cfg = 'beast' + if port: + fe_cfg += ' port=%s' % port + + + params = [ '--rgw-frontends', fe_cfg ] + + if log_file: + params += [ '--log-file', log_file ] + + if debug_ms: + params += [ '--debug-ms', debug_ms ] + + if debug_rgw: + params += [ '--debug-rgw', debug_rgw ] + + RGWCmd().run(params) + + +class RealmCommand: + def __init__(self, args): + self.args = args + + def parse(self): + parser = argparse.ArgumentParser( + description='S3 control tool', + usage='''rgwam realm + +The subcommands are: + bootstrap Manipulate bucket versioning +''') + parser.add_argument('subcommand', help='Subcommand to run') + # parse_args defaults to [1:] for args, but you need to + # exclude the rest of the args too, or validation will fail + args = parser.parse_args(self.args[0:1]) + if not hasattr(self, args.subcommand): + print('Unrecognized subcommand:', args.subcommand) + parser.print_help() + exit(1) + # use dispatch pattern to invoke method with same name + return getattr(self, args.subcommand) + + def bootstrap(self): + parser = argparse.ArgumentParser( + description='Bootstrap new realm', + usage='rgwam realm bootstrap []') + parser.add_argument('--realm') + parser.add_argument('--zonegroup') + parser.add_argument('--zone') + parser.add_argument('--endpoints') + parser.add_argument('--sys-uid') + parser.add_argument('--uid') + + args = parser.parse_args(self.args[1:]) + + RGWAM().realm_bootstrap(args.realm, args.zonegroup, args.zone, args.endpoints, + args.sys_uid, args.uid) + + +class ZoneCommand: + def __init__(self, args): + self.args = args + + def parse(self): + parser = argparse.ArgumentParser( + description='S3 control tool', + usage='''rgwam zone + +The subcommands are: + run run radosgw daemon in current zone +''') + parser.add_argument('subcommand', help='Subcommand to run') + # parse_args defaults to [1:] for args, but you need to + # exclude the rest of the args too, or validation will fail + args = parser.parse_args(self.args[0:1]) + if not hasattr(self, args.subcommand): + print('Unrecognized subcommand:', args.subcommand) + parser.print_help() + exit(1) + # use dispatch pattern to invoke method with same name + return getattr(self, args.subcommand) + + def run(self): + parser = argparse.ArgumentParser( + description='Run radosgw daemon', + usage='rgwam zone run []') + parser.add_argument('--port') + parser.add_argument('--log-file') + parser.add_argument('--debug-ms') + parser.add_argument('--debug-rgw') + + args = parser.parse_args(self.args[1:]) + + RGWAM().run_radosgw(port = args.port) + + def create(self): + parser = argparse.ArgumentParser( + description='Create new zone to join existing realm', + usage='rgwam zone create []') + parser.add_argument('--realm-access') + parser.add_argument('--zone') + parser.add_argument('--zonegroup') + parser.add_argument('--endpoints') + + args = parser.parse_args(self.args[1:]) + + RGWAM().zone_create(args.realm_access, args.zonegroup, args.zone, args.endpoints) + + +class TopLevelCommand: + + def _parse(self): + parser = argparse.ArgumentParser( + description='RGW assist for multisite tool', + usage='''rgwam [] + +The commands are: + realm bootstrap Bootstrap realm + zone run Run radosgw in current zone +''') + parser.add_argument('command', help='Subcommand to run') + # parse_args defaults to [1:] for args, but you need to + # exclude the rest of the args too, or validation will fail + args = parser.parse_args(sys.argv[1:2]) + if not hasattr(self, args.command) or args.command[0] == '_': + print('Unrecognized command:', args.command) + parser.print_help() + exit(1) + # use dispatch pattern to invoke method with same name + return getattr(self, args.command) + + def realm(self): + cmd = RealmCommand(sys.argv[2:]).parse() + cmd() + + def zone(self): + cmd = ZoneCommand(sys.argv[2:]).parse() + cmd() + + +def main(): + cmd = TopLevelCommand()._parse() + try: + cmd() + except RGWAMException as e: + print('ERROR: ' + e.message) + + +if __name__ == '__main__': + main() +