From: Shweta Sodani Date: Mon, 20 Apr 2026 09:03:15 +0000 (+0530) Subject: mgr/smb: Add RGWStorage resource class and update Share to support RGW X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6da208dec17c6f325f5d2711d7ca2dd3a34f7d86;p=ceph.git mgr/smb: Add RGWStorage resource class and update Share to support RGW - Add RGWStorage component class for RGW bucket storage backend - Include fields: bucket, user_id, access_key_id, secret_access_key - Add password conversion support for credentials - Update Share class to accept optional rgw field and added convert defination - Update Share validation to support both cephfs and rgw backends - Ensure exactly one storage backend (cephfs or rgw) is specified This is the first step in implementing RGW storage support for SMB shares, similar to the existing NFS RGW export functionality. Signed-off-by: Shweta Sodani --- diff --git a/src/pybind/mgr/smb/resources.py b/src/pybind/mgr/smb/resources.py index 2956703e68e..118a40fa813 100644 --- a/src/pybind/mgr/smb/resources.py +++ b/src/pybind/mgr/smb/resources.py @@ -400,6 +400,44 @@ class LoginAccessEntry(_RBase): validation.check_access_name(self.name) +@resourcelib.component() +class RGWStorage(_RBase): + """Description of where in an RGW bucket a share is located.""" + + bucket: str + user_id: Optional[str] = None + access_key_id: Optional[str] = None + secret_access_key: Optional[str] = None + + def validate(self) -> None: + if not self.bucket: + raise ValueError('bucket requires a value') + + def convert(self, operation: ConversionOp) -> Self: + """Convert password fields based on the operation.""" + return self.__class__( + bucket=self.bucket, + user_id=self.user_id, + access_key_id=( + _password_convert(self.access_key_id, operation) + if self.access_key_id + else None + ), + secret_access_key=( + _password_convert(self.secret_access_key, operation) + if self.secret_access_key + else None + ), + ) + + @resourcelib.customize + def _customize_resource(rc: resourcelib.Resource) -> resourcelib.Resource: + rc.user_id.quiet = True + rc.access_key_id.quiet = True + rc.secret_access_key.quiet = True + return rc + + @resourcelib.component() class HostAccessEntry(_RBase): access: HostAccess @@ -461,6 +499,7 @@ class Share(_RBase): comment: Optional[str] = None max_connections: Optional[int] = None cephfs: Optional[CephFSStorage] = None + rgw: Optional[RGWStorage] = None custom_smb_share_options: Optional[Dict[str, str]] = None login_control: Optional[List[LoginAccessEntry]] = None restrict_access: bool = False @@ -481,9 +520,14 @@ class Share(_RBase): validation.check_share_name(self.name) if self.intent != Intent.PRESENT: raise ValueError('Share must have present intent') - # currently only cephfs is supported - if self.cephfs is None: - raise ValueError('a cephfs configuration is required') + # Ensure exactly one storage backend is specified + storage_count = len([b for b in (self.cephfs, self.rgw) if b]) + if storage_count == 0: + raise ValueError( + 'a storage configuration is required (cephfs or rgw)' + ) + if storage_count > 1: + raise ValueError('only one storage backend can be specified') if self.max_connections is not None and self.max_connections < 0: raise ValueError( 'max_connections must be 0 or a non-negative integer' @@ -501,6 +545,25 @@ class Share(_RBase): """Return the .cephfs storage object or raise ValueError if None.""" return checked(self.cephfs) + def convert(self, operation: ConversionOp) -> Self: + """Convert password fields in nested storage components.""" + return self.__class__( + cluster_id=self.cluster_id, + share_id=self.share_id, + intent=self.intent, + name=self.name, + readonly=self.readonly, + browseable=self.browseable, + comment=self.comment, + max_connections=self.max_connections, + cephfs=self.cephfs.convert(operation) if self.cephfs else None, + rgw=self.rgw.convert(operation) if self.rgw else None, + custom_smb_share_options=self.custom_smb_share_options, + login_control=self.login_control, + restrict_access=self.restrict_access, + hosts_access=self.hosts_access, + ) + @resourcelib.customize def _customize_resource(rc: resourcelib.Resource) -> resourcelib.Resource: rc.restrict_access.quiet = True