From: Shwetha K Acharya Date: Fri, 20 Jun 2025 12:03:52 +0000 (+0530) Subject: mgr/smb: Add configurable options to share X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=2e8cb970d8cfd84366da4853e64ccb7930a8a64b;p=ceph.git mgr/smb: Add configurable options to share Introduced comment and max_connections fields as configurable options in the Share resource to support Microsoft Management Console (MMC) integration. Added appropriate validations and tests. Signed-off-by: Shwetha K Acharya --- diff --git a/src/pybind/mgr/smb/handler.py b/src/pybind/mgr/smb/handler.py index e5e2dbea707a1..f190de9dc3809 100644 --- a/src/pybind/mgr/smb/handler.py +++ b/src/pybind/mgr/smb/handler.py @@ -1196,11 +1196,15 @@ def _generate_share( 'browseable': ynbool(share.browseable), 'kernel share modes': 'no', 'x:ceph:id': f'{share.cluster_id}.{share.share_id}', - 'comment': '', - 'max connections': '0', 'smbd profiling share': 'yes', } } + if share.comment is not None: + cfg['options']['comment'] = share.comment + + if share.max_connections is not None: + cfg['options']['max connections'] = str(share.max_connections) + if proxy_val: cfg['options'][f'{ceph_vfs}:proxy'] = proxy_val # extend share with user+group login access lists diff --git a/src/pybind/mgr/smb/resources.py b/src/pybind/mgr/smb/resources.py index e93822b188abf..9ec3694baa78c 100644 --- a/src/pybind/mgr/smb/resources.py +++ b/src/pybind/mgr/smb/resources.py @@ -194,6 +194,8 @@ class Share(_RBase): name: str = '' readonly: bool = False browseable: bool = True + comment: Optional[str] = None + max_connections: Optional[int] = None cephfs: Optional[CephFSStorage] = None custom_smb_share_options: Optional[Dict[str, str]] = None login_control: Optional[List[LoginAccessEntry]] = None @@ -217,6 +219,12 @@ class Share(_RBase): # currently only cephfs is supported if self.cephfs is None: raise ValueError('a cephfs configuration is required') + if self.max_connections is not None and self.max_connections < 0: + raise ValueError( + 'max_connections must be 0 or a non-negative integer' + ) + if self.comment is not None and '\n' in self.comment: + raise ValueError('Comment cannot contain newlines') validation.check_custom_options(self.custom_smb_share_options) if self.restrict_access and not self.login_control: raise ValueError( diff --git a/src/pybind/mgr/smb/tests/test_handler.py b/src/pybind/mgr/smb/tests/test_handler.py index f8c389dbdf598..f1aac1cc3967b 100644 --- a/src/pybind/mgr/smb/tests/test_handler.py +++ b/src/pybind/mgr/smb/tests/test_handler.py @@ -85,6 +85,8 @@ def test_internal_apply_cluster_and_share(thandler): cluster_id='foo', share_id='s1', name='Ess One', + comment='This is a test share', + max_connections=5, cephfs=_cephfs( volume='cephfs', path='/', @@ -99,6 +101,10 @@ def test_internal_apply_cluster_and_share(thandler): assert len(shares) == 1 assert ('foo', 's1') in shares + share_dict = thandler.internal_store.data[('shares', 'foo.s1')] + assert share_dict['comment'] == 'This is a test share' + assert share_dict['max_connections'] == 5 + def test_internal_apply_remove_cluster(thandler): thandler.internal_store.overwrite( diff --git a/src/pybind/mgr/smb/tests/test_resources.py b/src/pybind/mgr/smb/tests/test_resources.py index d8edfafe5d400..5f2b03d691251 100644 --- a/src/pybind/mgr/smb/tests/test_resources.py +++ b/src/pybind/mgr/smb/tests/test_resources.py @@ -838,3 +838,67 @@ def test_load_text(params): else: with pytest.raises(params['exc_type'], match=params['error']): smb.resources.load_text(params['txt']) + + +@pytest.mark.parametrize("max_conn", [0, 25]) +def test_share_with_comment_and_max_connections(max_conn): + import yaml + + yaml_str = f""" +resource_type: ceph.smb.share +cluster_id: rhumba +share_id: goodshare +name: Good Share +cephfs: + volume: myvol + path: /good +comment: This is a test share +max_connections: {max_conn} +""" + + data = yaml.safe_load_all(yaml_str) + loaded = smb.resources.load(data) + assert loaded + + share = loaded[0] + assert share.comment == "This is a test share" + assert share.max_connections == max_conn + + +def test_share_with_invalid_max_connections(): + import yaml + + yaml_str = """ +resource_type: ceph.smb.share +cluster_id: rhumba +share_id: badshare +name: Bad Share +cephfs: + volume: myvol + path: /bad +max_connections: -10 +""" + data = yaml.safe_load_all(yaml_str) + with pytest.raises( + ValueError, + match="max_connections must be 0 or a non-negative integer", + ): + smb.resources.load(data) + + +def test_share_with_invalid_comment(): + import yaml + + yaml_str = """ +resource_type: ceph.smb.share +cluster_id: rhumba +share_id: weirdshare +name: Weird Share +cephfs: + volume: myvol + path: /weird +comment: "Invalid\\nComment" +""" + data = yaml.safe_load_all(yaml_str) + with pytest.raises(ValueError, match="Comment cannot contain newlines"): + smb.resources.load(data)