]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/smb: Add RGWStorage resource class and update Share to support RGW
authorShweta Sodani <ssodani@redhat.com>
Mon, 20 Apr 2026 09:03:15 +0000 (14:33 +0530)
committerShweta Sodani <Shweta.Sodani@ibm.com>
Thu, 25 Jun 2026 16:19:45 +0000 (21:49 +0530)
- 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 <ssodani@redhat.com>
src/pybind/mgr/smb/resources.py

index 2956703e68e0218135344c8a9a2757a7f30713b8..118a40fa813df674fc693e3bd8b8f029cc7cb939 100644 (file)
@@ -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