From: John Mulligan Date: Mon, 23 Feb 2026 17:23:06 +0000 (-0500) Subject: cephadm: add support for a remote control local socket X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=bf3c77d0be2e68e5833e22be0d162dd4d9e9b513;p=ceph.git cephadm: add support for a remote control local socket It's not an oxymoron, it's Remote Control Local Socket (tm)! This allows processes on the ceph host to use a unix domain socket without mTLS to communicate with the remote control sidecar server in the samba service. At the higher level We treat the 2nd listener as a "feature" even though it really configures the same sidecar as "remote-contol". This way it's easy to have one of "remote-control", "remote-control-local" or both in the service spec configuring the smb service. NOTE: This service does have the ability to verify that the client has admin-ish access to ceph services by needing the client to pass the ceph user name and key over the grpc headers. Signed-off-by: John Mulligan --- diff --git a/src/cephadm/cephadmlib/daemons/smb.py b/src/cephadm/cephadmlib/daemons/smb.py index 6824df00164..bb2ab40cac4 100644 --- a/src/cephadm/cephadmlib/daemons/smb.py +++ b/src/cephadm/cephadmlib/daemons/smb.py @@ -58,6 +58,7 @@ class Features(enum.Enum): CLUSTERED = 'clustered' CEPHFS_PROXY = 'cephfs-proxy' REMOTE_CONTROL = 'remote-control' + REMOTE_CONTROL_LOCAL = 'remote-control-local' @classmethod def valid(cls, value: str) -> bool: @@ -136,6 +137,11 @@ class Ports(enum.Enum): return names[self] +class ListenTo(str, enum.Enum): + TCP = 'tcp' + UNIX = 'unix' + + @dataclasses.dataclass(frozen=True) class TLSFiles: cert: str = '' @@ -181,6 +187,42 @@ class TLSFiles: class RemoteControlConfig: port: int tls_files: TLSFiles + listen_to: Optional[List[ListenTo]] = None + unix_sock_path: str = '/run/remote-control.s' + + @property + def listen_to_tcp(self) -> bool: + return bool( + self.port + and (not self.listen_to or ListenTo.TCP in self.listen_to) + ) + + @property + def listen_to_unix(self) -> bool: + return bool( + self.unix_sock_path + and (self.listen_to and ListenTo.UNIX in self.listen_to) + ) + + @classmethod + def configure( + cls, + features: List[str], + service_ports: Dict, + tls_files: Dict[str, str], + ) -> Optional['RemoteControlConfig']: + listen_to = [] + if Features.REMOTE_CONTROL.value in features: + listen_to.append(ListenTo.TCP) + if Features.REMOTE_CONTROL_LOCAL.value in features: + listen_to.append(ListenTo.UNIX) + if not listen_to: + return None + return cls( + port=Ports.REMOTE_CONTROL.customized(service_ports), + tls_files=TLSFiles.match(tls_files, 'remote_control'), + listen_to=listen_to, + ) @dataclasses.dataclass(frozen=True) @@ -418,6 +460,16 @@ class RemoteControlContainer(SambaContainerCommon): assert self.cfg.remote_control, 'remote_control is not configured' args.append('serve') args.append('--grpc') + if self.cfg.remote_control.listen_to_tcp: + self._tcp_args(args) + if self.cfg.remote_control.listen_to_unix: + self._unix_extra_args(args) + elif self.cfg.remote_control.listen_to_unix: + self._unix_only_args(args) + return args + + def _tcp_args(self, args: List[str]) -> None: + assert self.cfg.remote_control address = self.cfg.bind_to[0].address if self.cfg.bind_to else '*' port = self.cfg.remote_control.port args.append(f'--address={address}:{port}') @@ -433,7 +485,17 @@ class RemoteControlContainer(SambaContainerCommon): args.append(f'--tls-key={key_path}') if ca_cert: args.append(f'--tls-ca-cert={ca_cert}') - return args + + def _unix_only_args(self, args: List[str]) -> None: + assert self.cfg.remote_control + sock_path = self.cfg.remote_control.unix_sock_path + args.append(f'--address=unix:{sock_path}') + args.append('--verification=rados-object') + + def _unix_extra_args(self, args: List[str]) -> None: + assert self.cfg.remote_control + sock_path = self.cfg.remote_control.unix_sock_path + args.append(f'--extra-listener=unix:{sock_path};rados-object') def container_args(self) -> List[str]: return super().container_args() + [ @@ -648,13 +710,11 @@ class SMB(ContainerDaemonForm): self._organize_files(files) - if Features.REMOTE_CONTROL.value in instance_features: - remote_control_cfg = RemoteControlConfig( - port=Ports.REMOTE_CONTROL.customized(service_ports), - tls_files=TLSFiles.match(self._tls_files, 'remote_control'), - ) - else: - remote_control_cfg = None + remote_control_cfg = RemoteControlConfig.configure( + instance_features, + service_ports, + self._tls_files, + ) rank, rank_gen = self._rank_info self._instance_cfg = Config(