From 5b6e99de1e1a6cb7358e5d926247e70d4d85743a Mon Sep 17 00:00:00 2001 From: Redouane Kachach Date: Thu, 13 Oct 2022 10:06:33 +0200 Subject: [PATCH] Removing docs for unused commands + fixing style issues Adding logic to modify the master zonegroup endpoints Do no call pull realm when modifying zone Only update the endpoints if the modified zone is master Adding support to set custom endpoints when creating realm or zone Signed-off-by: Redouane Kachach --- doc/mgr/rgw.rst | 19 ------- src/pybind/mgr/cephadm/serve.py | 4 +- src/pybind/mgr/rgw/module.py | 12 +++-- .../ceph/deployment/service_spec.py | 2 + src/python-common/ceph/rgw/rgwam_core.py | 52 +++++++++++-------- src/python-common/ceph/rgw/types.py | 7 ++- 6 files changed, 46 insertions(+), 50 deletions(-) diff --git a/doc/mgr/rgw.rst b/doc/mgr/rgw.rst index 7e4d814e95d..7436833ba75 100644 --- a/doc/mgr/rgw.rst +++ b/doc/mgr/rgw.rst @@ -124,25 +124,6 @@ List the tokens of all the available realms Join an existing realm by creating a new secondary zone (using the realm token) -:: - - ceph rgw zone-creds create - -Create new credentials and return a token for new zone connection - -:: - - ceph rgw zone-creds remove - -Remove credentials and/or user that are associated with the specified -token - -:: - - ceph rgw realm reconcile - -Update the realm configuration to match the orchestrator deployment - :: ceph rgw admin [*] diff --git a/src/pybind/mgr/cephadm/serve.py b/src/pybind/mgr/cephadm/serve.py index 7e46fccb540..1e357d41cd5 100644 --- a/src/pybind/mgr/cephadm/serve.py +++ b/src/pybind/mgr/cephadm/serve.py @@ -573,7 +573,7 @@ class CephadmServe: for p in s.ports: ep.append(f'{protocol}://{s.hostname}:{p}') zone_update_cmd = { - 'prefix': 'rgw zone update', + 'prefix': 'rgw zone modify', 'realm_name': rgw_spec.rgw_realm, 'zonegroup_name': rgw_spec.rgw_zonegroup, 'zone_name': rgw_spec.rgw_zone, @@ -584,7 +584,7 @@ class CephadmServe: rc, out, err = self.mgr.mon_command(zone_update_cmd) rgw_spec.update_endpoints = (rc != 0) # keep trying on failure if rc != 0: - self.log.error(f'Error when trying to update rgw zone {err}') + self.log.error(f'Error when trying to update rgw zone: {err}') self.mgr.set_health_warning('CEPHADM_RGW', 'Cannot update rgw endpoints', 1, [f'Cannot update rgw endpoints for daemon {rgw_spec.service_name()}']) else: diff --git a/src/pybind/mgr/rgw/module.py b/src/pybind/mgr/rgw/module.py index 1595f791b18..d74426eeb6a 100644 --- a/src/pybind/mgr/rgw/module.py +++ b/src/pybind/mgr/rgw/module.py @@ -130,6 +130,7 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): zone_name: Optional[str] = None, port: Optional[int] = None, placement: Optional[str] = None, + endpoints: Optional[str] = None, start_radosgw: Optional[bool] = True, inbuf: Optional[str] = None): """Bootstrap new rgw realm, zonegroup, and zone""" @@ -145,7 +146,8 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): rgw_zonegroup=zonegroup_name, rgw_zone=zone_name, rgw_frontend_port=port, - placement=placement_spec)] + placement=placement_spec, + endpoints=endpoints)] else: err_msg = 'Invalid arguments: either pass a spec with -i or provide the realm, zonegroup and zone.' return HandleCommandResult(retval=-errno.EINVAL, stdout='', stderr=err_msg) @@ -224,7 +226,7 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): elif not (realm_info['access_key'] and realm_info['secret']): realms_info.append({'realm': realm_info['realm_name'], 'token': 'master zone has no access/secret keys'}) else: - keys = ['realm_name', 'realm_id', 'is_primary', 'endpoint', 'access_key', 'secret'] + keys = ['realm_name', 'realm_id', 'endpoint', 'access_key', 'secret'] realm_token = RealmToken(**{k: realm_info[k] for k in keys}) realm_token_b = realm_token.to_json().encode('utf-8') realm_token_s = base64.b64encode(realm_token_b).decode('utf-8') @@ -235,7 +237,7 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): return HandleCommandResult(retval=0, stdout=json.dumps(realms_info, indent=4), stderr='') - @CLICommand('rgw zone update', perm='rw') + @CLICommand('rgw zone modify', perm='rw') def update_zone_info(self, realm_name: str, zonegroup_name: str, zone_name: str, realm_token: str, endpoints: List[str]): try: retval, out, err = RGWAM(self.env).zone_modify(realm_name, @@ -256,6 +258,7 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): port: Optional[int] = None, placement: Optional[str] = None, start_radosgw: Optional[bool] = True, + endpoints: Optional[str] = None, inbuf: Optional[str] = None): """Bootstrap new rgw zone that syncs with zone on another cluster in the same realm""" @@ -271,7 +274,8 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): rgw_zone=zone_name, rgw_realm_token=realm_token, rgw_frontend_port=port, - placement=placement_spec)] + placement=placement_spec, + endpoints=endpoints)] else: err_msg = 'Invalid arguments: either pass a spec with -i or provide the zone_name and realm_token.' return HandleCommandResult(retval=-errno.EINVAL, stdout='', stderr=err_msg) diff --git a/src/python-common/ceph/deployment/service_spec.py b/src/python-common/ceph/deployment/service_spec.py index cfcc7ab83aa..b2a88bdc999 100644 --- a/src/python-common/ceph/deployment/service_spec.py +++ b/src/python-common/ceph/deployment/service_spec.py @@ -876,6 +876,7 @@ class RGWSpec(ServiceSpec): custom_configs: Optional[List[CustomConfig]] = None, rgw_realm_token: Optional[str] = None, update_endpoints: Optional[bool] = False, + endpoints: Optional[str] = None # commad separated endpoints list ): assert service_type == 'rgw', service_type @@ -911,6 +912,7 @@ class RGWSpec(ServiceSpec): self.ssl = ssl self.rgw_realm_token = rgw_realm_token self.update_endpoints = update_endpoints + self.endpoints = endpoints def get_port_start(self) -> List[int]: return [self.get_port()] diff --git a/src/python-common/ceph/rgw/rgwam_core.py b/src/python-common/ceph/rgw/rgwam_core.py index ae4d4452ad8..8506328ae0d 100644 --- a/src/python-common/ceph/rgw/rgwam_core.py +++ b/src/python-common/ceph/rgw/rgwam_core.py @@ -253,6 +253,12 @@ class ZonegroupOp: return json.loads(stdout) + def modify(self, realm: EntityKey, zg: EntityKey, endpoints=None): + ze = ZoneEnv(self.env, realm=realm, zg=zg) + params = ['zonegroup', 'modify'] + opt_arg(params, '--endpoints', endpoints) + return RGWAdminJSONCmd(ze).run(params) + class ZoneOp: def __init__(self, env: EnvArgs): @@ -292,8 +298,8 @@ class ZoneOp: return RGWAdminJSONCmd(ze).run(params) - def modify(self, zone: EntityKey, zg: EntityKey, endpoints=None, is_master=None, - access_key=None, secret=None): + def modify(self, zone: EntityKey, zg: EntityKey, is_master=None, + access_key=None, secret=None, endpoints=None): ze = ZoneEnv(self.env, zone=zone, zg=zg) params = ['zone', @@ -486,7 +492,8 @@ class RGWAM: uid_prefix='user-sys', is_system=True) sys_user = RGWUser(sys_user_info) - logging.info(f'Created system user: {sys_user.uid} on {realm.name}/{zonegroup.name}/{zone.name}') + logging.info(f'Created system user: {sys_user.uid} on' + '{realm.name}/{zonegroup.name}/{zone.name}') return sys_user except RGWAMException as e: raise RGWAMException('failed to create system user', e) @@ -495,7 +502,8 @@ class RGWAM: try: user_info = self.user_op().create(zone, zg, uid=uid, is_system=False) user = RGWUser(user_info) - logging.info('Created regular user {user.uid} on {realm.name}/{zonegroup.name}/{zone.name}') + logging.info('Created regular user {user.uid} on' + '{realm.name}/{zonegroup.name}/{zone.name}') return user except RGWAMException as e: raise RGWAMException('failed to create user', e) @@ -533,15 +541,15 @@ class RGWAM: rgw_acces_key = sys_user.get_key(0) access_key = rgw_acces_key.access_key if rgw_acces_key else '' secret = rgw_acces_key.secret_key if rgw_acces_key else '' - self.zone_op().modify(zone, zonegroup, None, None, access_key, secret) + self.zone_op().modify(zone, zonegroup, None, + access_key, secret, endpoints=rgw_spec.endpoints) self.update_period(realm, zonegroup) - if start_radosgw: + if start_radosgw and rgw_spec.endpoints is None: # Instruct the orchestrator to start RGW daemons, asynchronically, this will # call back the rgw module to update the master zone with the corresponding endpoints realm_token = RealmToken(realm_name, realm.id, - True, # primary cluster None, # no endpoint access_key, secret) realm_token_b = realm_token.to_json().encode('utf-8') @@ -678,14 +686,6 @@ class RGWAM: realm_token = RealmToken.from_base64_str(realm_token_b64) access_key = realm_token.access_key secret = realm_token.secret - try: - # We only pull the realm if we are on a secondary cluster - if not realm_token.is_primary and realm_token.endpoint is not None: - self.realm_op().pull(EntityName(realm_name), - realm_token.endpoint, access_key, secret) - except RGWAMException as e: - raise RGWAMException('failed to pull realm', e) - realm_name = realm_token.realm_name realm_id = realm_token.realm_id logging.info(f'Using realm {realm_name} {realm_id}') @@ -700,11 +700,16 @@ class RGWAM: zg = EntityName(zonegroup.name) zone = EntityName(zone_name) + master_zone_info = self.period_op().get_master_zone(realm, zg) success_message = f'Modified zone {realm_name} {zonegroup_name} {zone_name}' logging.info(success_message) try: - self.zone_op().modify(zone, zg, endpoints=','.join(endpoints), - access_key=access_key, secret=secret) + self.zone_op().modify(zone, zg, access_key=access_key, + secret=secret, endpoints=','.join(endpoints)) + # we only update the zonegroup endpoints if the zone being + # modified is a master zone + if zone_name == master_zone_info['name']: + self.zonegroup_op().modify(realm, zg, endpoints=','.join(endpoints)) except RGWAMException as e: raise RGWAMException('failed to modify zone', e) @@ -733,7 +738,6 @@ class RGWAM: secret = '' realms_info.append({"realm_name": realm_name, "realm_id": realm.id, - "is_primary": False, "master_zone_id": master_zone_inf['id'] if master_zone_inf else '', "endpoint": zone_ep[0] if zone_ep else None, "access_key": access_key, @@ -770,20 +774,21 @@ class RGWAM: period = RGWPeriod(period_info) logging.info('Period: ' + period.id) - zonegroup = period.find_zonegroup_by_name(rgw_spec.rgw_zonegroup) + zonegroup = period.get_master_zonegroup() if not zonegroup: - raise RGWAMException(f'zonegroup {rgw_spec.rgw_zonegroup}') + raise RGWAMException('Cannot find master zonegroup of realm {realm_name}') - zone = self.create_zone(realm, zonegroup, rgw_spec.rgw_zone, False, access_key, secret) + zone = self.create_zone(realm, zonegroup, rgw_spec.rgw_zone, + False, # secondary zone + access_key, secret, endpoints=rgw_spec.endpoints) self.update_period(realm, zonegroup, zone) period = RGWPeriod(period_info) logging.debug(period.to_json()) - if start_radosgw: + if start_radosgw and rgw_spec.endpoints is None: secondary_realm_token = RealmToken(realm_name, realm_id, - False, # is_primary None, # no endpoint realm_token.access_key, realm_token.secret) @@ -791,6 +796,7 @@ class RGWAM: realm_token_s = base64.b64encode(realm_token_b).decode('utf-8') rgw_spec.update_endpoints = True rgw_spec.rgw_token = realm_token_s + rgw_spec.rgw_zonegroup = zonegroup.name # master zonegroup is used self.env.mgr.apply_rgw(rgw_spec) def _get_daemon_eps(self, realm_name=None, zonegroup_name=None, zone_name=None): diff --git a/src/python-common/ceph/rgw/types.py b/src/python-common/ceph/rgw/types.py index c1c49df4ff5..4a69e6a7f88 100644 --- a/src/python-common/ceph/rgw/types.py +++ b/src/python-common/ceph/rgw/types.py @@ -50,10 +50,9 @@ class JSONObj: class RealmToken(JSONObj): - def __init__(self, realm_name, realm_id, is_primary, endpoint, access_key, secret): + def __init__(self, realm_name, realm_id, endpoint, access_key, secret): self.realm_name = realm_name self.realm_id = realm_id - self.is_primary = is_primary self.endpoint = endpoint self.access_key = access_key self.secret = secret @@ -68,6 +67,7 @@ class RealmToken(JSONObj): except binascii.Error: return None + class RGWZone(JSONObj): def __init__(self, zone_dict): self.id = zone_dict['id'] @@ -138,6 +138,9 @@ class RGWPeriod(JSONObj): return self.find_zonegroup_by_id(self.master_zonegroup) return self.zonegroups_by_name.get(zonegroup) + def get_master_zonegroup(self): + return self.find_zonegroup_by_id(self.master_zonegroup) + def find_zonegroup_by_id(self, zonegroup): return self.zonegroups_by_id.get(zonegroup)