]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
Addressing adking review comments
authorRedouane Kachach <rkachach@redhat.com>
Tue, 11 Oct 2022 08:10:16 +0000 (10:10 +0200)
committerAdam King <adking@redhat.com>
Wed, 5 Apr 2023 17:30:59 +0000 (13:30 -0400)
Signed-off-by: Redouane Kachach <rkachach@redhat.com>
(cherry picked from commit b94c2b685a3e70daed0be7b83199b7183e3e1983)

doc/mgr/rgw.rst
src/pybind/mgr/cephadm/serve.py
src/pybind/mgr/rgw/module.py
src/python-common/ceph/deployment/service_spec.py
src/python-common/ceph/rgw/rgwam_core.py

index 5632fa64f7107c171561421dde4ad252b655d794..97624fcac62f540e9967a51a98a3f38a8c502b59 100644 (file)
@@ -77,9 +77,9 @@ the `ceph rgw realm tokens` output:
     }
   ]
 
-User can use the token to create and synchronize a secondary zones
-on another cluster with the master zone by using `ceph rgw zone create`
-command and proving the corresponding token.
+User can use the token to pull a realm to create secondary zone on a
+different cluster that syncs with the master zone on the primary cluster
+by using `ceph rgw zone create` command and providing the corresponding token.
 
 Following is an example of zone spec file:
 
@@ -101,9 +101,9 @@ Following is an example of zone spec file:
 
   ceph rgw zone create -i zone-spec.yaml
 
-.. note:: The spec file used by RGW has the same format as the one used by cephadm. Thus,
-          the user can provide any cephadm rgw supported parameter as any other advanced
-          configuration items such as SSL certificates etc.
+.. note:: The spec file used by RGW has the same format as the one used by the orchestrator. Thus,
+          the user can provide any orchestration supported rgw parameters including advanced
+          configuration features such as SSL certificates etc.
 
 Commands
 --------
index 1cf7ffaa45530a452f81620e6e5e22f78f875e7f..a6c663e644e2b46558b3f8ff6f9bd8fe8f7a3e7b 100644 (file)
@@ -563,6 +563,35 @@ class CephadmServe:
                 self.mgr.set_health_warning('CEPHADM_FAILED_SET_OPTION', f'Failed to set {len(options_failed_to_set)} option(s)', len(
                     options_failed_to_set), options_failed_to_set)
 
+    def _update_rgw_endpoints(self, rgw_spec: RGWSpec) -> None:
+
+        if not rgw_spec.update_endpoints or rgw_spec.rgw_realm_token is None:
+            return
+
+        ep = []
+        protocol = 'https' if rgw_spec.ssl else 'http'
+        for s in self.mgr.cache.get_daemons_by_service(rgw_spec.service_name()):
+            if s.ports:
+                for p in s.ports:
+                    ep.append(f'{protocol}://{s.hostname}:{p}')
+        zone_update_cmd = {
+            'prefix': 'rgw zone update',
+            'realm_name': rgw_spec.rgw_realm,
+            'zonegroup_name': rgw_spec.rgw_zonegroup,
+            'zone_name': rgw_spec.rgw_zone,
+            'realm_token': rgw_spec.rgw_realm_token,
+            'endpoints': ep,
+        }
+        self.log.debug(f'rgw cmd: {zone_update_cmd}')
+        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.mgr.set_health_warning('CEPHADM_RGW', 'Cannot update rgw endpoints', 1,
+                                        [f'Cannot update rgw endpoints for daemon {rgw_spec.service_name()}'])
+        else:
+            self.mgr.remove_health_warning('CEPHADM_RGW')
+
     def _apply_service(self, spec: ServiceSpec) -> bool:
         """
         Schedule a service.  Deploy new daemons or remove old ones, depending
@@ -822,26 +851,7 @@ class CephadmServe:
                     self.mgr._schedule_daemon_action(active_mgr.name(), 'restart')
 
             if service_type == 'rgw':
-                rgw_spec = cast(RGWSpec, spec)
-                if rgw_spec.update_endpoints and rgw_spec.rgw_realm_token is not None:
-                    ep = []
-                    for s in self.mgr.cache.get_daemons_by_service(rgw_spec.service_name()):
-                        if s.ports:
-                            for p in s.ports:
-                                ep.append(f'http://{s.hostname}:{p}')
-                    zone_update_cmd = {
-                        'prefix': 'rgw zone update',
-                        'realm_name': rgw_spec.rgw_realm,
-                        'zonegroup_name': rgw_spec.rgw_zonegroup,
-                        'zone_name': rgw_spec.rgw_zone,
-                        'realm_token': rgw_spec.rgw_realm_token,
-                        'endpoints': ep,
-                    }
-                    self.log.debug(f'rgw cmd: {zone_update_cmd}')
-                    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}.. keep trying')
+                self._update_rgw_endpoints(cast(RGWSpec, spec))
 
             # remove any?
             def _ok_to_stop(remove_daemons: List[orchestrator.DaemonDescription]) -> bool:
index b402b37f413674e4308056f36fbd4d7b18db21cd..e47b9b5a83b613a720cd8bc8c721c5259ca5765b 100644 (file)
@@ -128,29 +128,30 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
                                  start_radosgw: Optional[bool] = True,
                                  inbuf: Optional[str] = None):
         """Bootstrap new rgw realm, zonegroup, and zone"""
-        try:
-            if inbuf:
-                rgw_specs = self._parse_rgw_specs(inbuf)
-            elif (realm_name and zonegroup_name and zone_name):
-                placement_spec = PlacementSpec.from_string(placement) if placement else None
-                rgw_specs = [RGWSpec(rgw_realm=realm_name,
-                                     rgw_zonegroup=zonegroup_name,
-                                     rgw_zone=zone_name,
-                                     rgw_frontend_port=port,
-                                     placement=placement_spec)]
-            else:
-                return HandleCommandResult(retval=-errno.EINVAL, stdout='', stderr='Invalid arguments: -h or --help for usage')
 
+        if inbuf:
+            rgw_specs = self._parse_rgw_specs(inbuf)
+        elif (realm_name and zonegroup_name and zone_name):
+            placement_spec = PlacementSpec.from_string(placement) if placement else None
+            rgw_specs = [RGWSpec(rgw_realm=realm_name,
+                                 rgw_zonegroup=zonegroup_name,
+                                 rgw_zone=zone_name,
+                                 rgw_frontend_port=port,
+                                 placement=placement_spec)]
+        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)
+
+        try:
             for spec in rgw_specs:
                 RGWAM(self.env).realm_bootstrap(spec, start_radosgw)
-
         except RGWAMException as e:
             self.log.error('cmd run exception: (%d) %s' % (e.retcode, e.message))
             return (e.retcode, e.message, e.stderr)
 
         return HandleCommandResult(retval=0, stdout="Realm(s) created correctly. Please, use 'ceph rgw realm tokens' to get the token.", stderr='')
 
-    def _parse_rgw_specs(self, inbuf: Optional[str] = None):
+    def _parse_rgw_specs(self, inbuf: Optional[str] = None) -> List[RGWSpec]:
         """Parse RGW specs from a YAML file."""
         # YAML '---' document separator with no content generates
         # None entries in the output. Let's skip them silently.
@@ -158,7 +159,6 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
         specs = [o for o in yaml_objs if o is not None]
         rgw_specs = []
         for spec in specs:
-            # TODO(rkachach): should we use a new spec instead of RGWSpec here!
             rgw_spec = RGWSpec.from_json(spec)
             rgw_spec.validate()
             rgw_specs.append(rgw_spec)
@@ -193,22 +193,26 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
 
     @CLICommand('rgw realm tokens', perm='r')
     def list_realm_tokens(self):
-        realms_info = []
-        for realm_info in RGWAM(self.env).get_realms_info():
-            if not realm_info['master_zone_id']:
-                realms_info.append({'realm': realm_info['realm_name'], 'token': 'realm has no master zone'})
-            elif not realm_info['endpoint']:
-                realms_info.append({'realm': realm_info['realm_name'], 'token': 'master zone has no endpoint'})
-            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']
-                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')
-                realms_info.append({'realm': realm_info['realm_name'], 'token': realm_token_s})
-
-        return HandleCommandResult(retval=0, stdout=json.dumps(realms_info), stderr='')
+        try:
+            realms_info = []
+            for realm_info in RGWAM(self.env).get_realms_info():
+                if not realm_info['master_zone_id']:
+                    realms_info.append({'realm': realm_info['realm_name'], 'token': 'realm has no master zone'})
+                elif not realm_info['endpoint']:
+                    realms_info.append({'realm': realm_info['realm_name'], 'token': 'master zone has no endpoint'})
+                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']
+                    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')
+                    realms_info.append({'realm': realm_info['realm_name'], 'token': realm_token_s})
+        except RGWAMException as e:
+            self.log.error(f'cmd run exception: ({e.retcode}) {e.message}')
+            return (e.retcode, e.message, e.stderr)
+
+        return HandleCommandResult(retval=0, stdout=json.dumps(realms_info, indent=4), stderr='')
 
     @CLICommand('rgw zone update', perm='rw')
     def update_zone_info(self, realm_name: str, zonegroup_name: str, zone_name: str, realm_token: str, endpoints: List[str]):
@@ -233,23 +237,24 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
                              start_radosgw: Optional[bool] = True,
                              inbuf: Optional[str] = None):
         """Bootstrap new rgw zone that syncs with existing zone"""
-        try:
-            if inbuf:
-                rgw_specs = self._parse_rgw_specs(inbuf)
-            elif (zone_name and realm_token):
-                placement_spec = PlacementSpec.from_string(placement) if placement else None
-                rgw_specs = [RGWSpec(rgw_realm_token=realm_token,
-                                     rgw_zone=zone_name,
-                                     rgw_frontend_port=port,
-                                     placement=placement_spec)]
-            else:
-                return HandleCommandResult(retval=-errno.EINVAL, stdout='', stderr='Invalid arguments: -h or --help for usage')
 
+        if inbuf:
+            rgw_specs = self._parse_rgw_specs(inbuf)
+        elif (zone_name and realm_token):
+            placement_spec = PlacementSpec.from_string(placement) if placement else None
+            rgw_specs = [RGWSpec(rgw_realm_token=realm_token,
+                                 rgw_zone=zone_name,
+                                 rgw_frontend_port=port,
+                                 placement=placement_spec)]
+        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)
+
+        try:
             for rgw_spec in rgw_specs:
                 retval, out, err = RGWAM(self.env).zone_create(rgw_spec, start_radosgw)
                 if retval != 0:
                     break
-
         except RGWAMException as e:
             self.log.error('cmd run exception: (%d) %s' % (e.retcode, e.message))
             return (e.retcode, e.message, e.stderr)
index 33fff1c881f1e3a13df533e7b48c0c0e03cff96a..68f149aae7a97588e43c40cbe1080bfe9579513a 100644 (file)
@@ -892,10 +892,16 @@ class RGWSpec(ServiceSpec):
             custom_configs=custom_configs)
 
         #: The RGW realm associated with this service. Needs to be manually created
+        #: if the spec is being applied directly to cephdam. In case of rgw module
+        #: the realm is created automatically.
         self.rgw_realm: Optional[str] = rgw_realm
         #: The RGW zonegroup associated with this service. Needs to be manually created
+        #: if the spec is being applied directly to cephdam. In case of rgw module
+        #: the zonegroup is created automatically.
         self.rgw_zonegroup: Optional[str] = rgw_zonegroup
         #: The RGW zone associated with this service. Needs to be manually created
+        #: if the spec is being applied directly to cephdam. In case of rgw module
+        #: the zone is created automatically.
         self.rgw_zone: Optional[str] = rgw_zone
         #: Port of the RGW daemons
         self.rgw_frontend_port: Optional[int] = rgw_frontend_port
index 2bfaf97e55a335b379bc64d0d702648ab27de647..0f207b331be8ad33573de2bbeaa4b38cde4e6651 100644 (file)
@@ -195,7 +195,8 @@ class RealmOp:
             params = ['realm', 'list']
             output = RGWAdminJSONCmd(ze).run(params)
             return output.get('realms') or []
-        except RGWAMException:
+        except RGWAMException as e:
+            logging.info(f'Exception while listing realms {e.message}')
             # in case the realm list is empty an exception is raised
             return []
 
@@ -229,7 +230,8 @@ class ZonegroupOp:
             params = ['zonegroup', 'list']
             output = RGWAdminJSONCmd(ze).run(params)
             return output.get('zonegroups') or []
-        except RGWAMException:
+        except RGWAMException as e:
+            logging.info(f'Exception while listing zonegroups {e.message}')
             return []
 
     def get(self, zonegroup: EntityKey = None):
@@ -262,7 +264,8 @@ class ZoneOp:
             params = ['zone', 'list']
             output = RGWAdminJSONCmd(ze).run(params)
             return output.get('zones') or []
-        except RGWAMException:
+        except RGWAMException as e:
+            logging.info(f'Exception while listing zones {e.message}')
             return []
 
     def get(self, zone: EntityKey):
@@ -483,7 +486,7 @@ class RGWAM:
                                                   uid_prefix='user-sys',
                                                   is_system=True)
             sys_user = RGWUser(sys_user_info)
-            logging.info('Created system user: %s' % sys_user.uid)
+            logging.info(f'Created system user: {sys_user.uid} on {realm.name}/{zonegroup.name}/{zone.name}')
             access_key = sys_user.keys[0].access_key if sys_user and sys_user.keys else ''
             secret_key = sys_user.keys[0].secret_key if sys_user and sys_user.keys else ''
             sys_user.add_key(access_key, secret_key)
@@ -495,7 +498,7 @@ 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: %s' % user.uid)
+            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)