From a753fb18cd4748934f92e404d0ee788e74f61e6f Mon Sep 17 00:00:00 2001 From: John Mulligan Date: Tue, 17 Jun 2025 19:07:56 -0400 Subject: [PATCH] mgr/smb: add bind_addrs field to cluster resource type Add bind_addrs, which is largely a wrapper around the service spec's bind_addrs to the smb cluster resource. Signed-off-by: John Mulligan --- src/pybind/mgr/smb/handler.py | 1 + src/pybind/mgr/smb/resources.py | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/pybind/mgr/smb/handler.py b/src/pybind/mgr/smb/handler.py index 98e079ed612e4..11e95c9ad18a7 100644 --- a/src/pybind/mgr/smb/handler.py +++ b/src/pybind/mgr/smb/handler.py @@ -887,6 +887,7 @@ def _generate_smb_service_spec( include_ceph_users=user_entities, cluster_public_addrs=cluster.service_spec_public_addrs(), custom_ports=cluster.custom_ports, + bind_addrs=cluster.service_spec_bind_addrs(), ) diff --git a/src/pybind/mgr/smb/resources.py b/src/pybind/mgr/smb/resources.py index 9ec3694baa78c..5351e9d4d41ad 100644 --- a/src/pybind/mgr/smb/resources.py +++ b/src/pybind/mgr/smb/resources.py @@ -8,6 +8,7 @@ import yaml from ceph.deployment.service_spec import ( PlacementSpec, + SMBClusterBindIPSpec, SMBClusterPublicIPSpec, SpecValidationError, ) @@ -404,6 +405,40 @@ class ClusterPublicIPAssignment(_RBase): raise ValueError(str(err)) from err +# A resource component wrapper around the service spec class +# SMBClusterBindIPSpec +@resourcelib.component() +class ClusterBindIP(_RBase): + """Cluster Bind IP address or network. + Restricts what addresses SMB services and/or containers will bind + to when run on a cluster node. + """ + + address: str = '' + network: str = '' + + def to_spec(self) -> SMBClusterBindIPSpec: + if self.address: + kwargs = {'address': self.address} + elif self.network: + kwargs = {'network': self.network} + else: + raise ValueError('ClusterBindIP has no values') + return SMBClusterBindIPSpec(**kwargs) + + def validate(self) -> None: + try: + self.to_spec().validate() + except SpecValidationError as err: + raise ValueError(str(err)) from err + + @resourcelib.customize + def _customize_resource(rc: resourcelib.Resource) -> resourcelib.Resource: + rc.address.quiet = True + rc.network.quiet = True + return rc + + @resourcelib.resource('ceph.smb.cluster') class Cluster(_RBase): """Represents a cluster (instance) that is / should be present.""" @@ -421,6 +456,9 @@ class Cluster(_RBase): clustering: Optional[SMBClustering] = None public_addrs: Optional[List[ClusterPublicIPAssignment]] = None custom_ports: Optional[Dict[str, int]] = None + # bind_addrs are used to restrict what IP addresses instances of this + # cluster will use + bind_addrs: Optional[List[ClusterBindIP]] = None def validate(self) -> None: if not self.cluster_id: @@ -448,6 +486,10 @@ class Cluster(_RBase): ) validation.check_custom_options(self.custom_smb_global_options) validation.check_custom_ports(self.custom_ports) + if self.bind_addrs is not None and not self.bind_addrs: + raise ValueError( + 'bind_addrs must have at least one value or not be set' + ) @resourcelib.customize def _customize_resource(rc: resourcelib.Resource) -> resourcelib.Resource: @@ -483,6 +525,11 @@ class Cluster(_RBase): return None return [a.to_spec() for a in self.public_addrs] + def service_spec_bind_addrs(self) -> Optional[List[SMBClusterBindIPSpec]]: + if self.bind_addrs is None: + return None + return [b.to_spec() for b in self.bind_addrs] + @resourcelib.resource('ceph.smb.join.auth') class JoinAuth(_RBase): -- 2.39.5