]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
cephadm: run smbmetrics as side-car container
authorShachar Sharon <ssharon@redhat.com>
Wed, 24 Jul 2024 09:30:31 +0000 (12:30 +0300)
committerShachar Sharon <ssharon@redhat.com>
Fri, 30 Aug 2024 09:02:55 +0000 (12:02 +0300)
When samba metrics-exporter image is provided and it is not an empty
string, run the smbmetrics as side-car container along-side main
samba-server. This metrics-exporter uses 'smbstatus' to convert SMB
stats into standard Prometheus metrics (via port 9922 by default).

This commit defines ContainerCommon as base of SambaContainerCommon and
SMBMetricsContainer. It defines the basic APIs of smb containers with
empty defaults. It also allows passing explicit image URL to samba's
sidecar containers. If no alternative image is provided (which is the
typical case), use the one provided by context or default one.

Signed-off-by: Shachar Sharon <ssharon@redhat.com>
src/cephadm/cephadmlib/daemons/smb.py

index 0aecd418b1bc477bfddb4b2d8738d35b2bd80b05..ae9acbc9c45845564c38e9fb5718ee2b75e1ddc5 100644 (file)
@@ -81,6 +81,8 @@ class Config:
     smb_port: int
     ceph_config_entity: str
     vhostname: str
+    metrics_image: str
+    metrics_port: int
     # clustering related values
     rank: int
     rank_generation: int
@@ -103,6 +105,8 @@ class Config:
         smb_port: int = 0,
         ceph_config_entity: str = 'client.admin',
         vhostname: str = '',
+        metrics_image: str = '',
+        metrics_port: int = 0,
         rank: int = -1,
         rank_generation: int = -1,
         cluster_meta_uri: str = '',
@@ -122,6 +126,8 @@ class Config:
         self.smb_port = smb_port
         self.ceph_config_entity = ceph_config_entity
         self.vhostname = vhostname
+        self.metrics_image = metrics_image
+        self.metrics_port = metrics_port
         self.rank = rank
         self.rank_generation = rank_generation
         self.cluster_meta_uri = cluster_meta_uri
@@ -155,15 +161,34 @@ def _container_dns_args(cfg: Config) -> List[str]:
     return cargs
 
 
-class SambaContainerCommon:
-    def __init__(
-        self,
-        cfg: Config,
-    ) -> None:
+class ContainerCommon:
+    def __init__(self, cfg: Config, image: str = '') -> None:
         self.cfg = cfg
+        self.image = image
 
     def name(self) -> str:
-        raise NotImplementedError('samba container name')
+        raise NotImplementedError('container name')
+
+    def envs(self) -> Dict[str, str]:
+        return {}
+
+    def envs_list(self) -> List[str]:
+        return []
+
+    def args(self) -> List[str]:
+        return []
+
+    def container_args(self) -> List[str]:
+        return []
+
+    def container_image(self) -> str:
+        return self.image
+
+
+class SambaContainerCommon(ContainerCommon):
+    def __init__(self, cfg: Config, image: str = '') -> None:
+        self.cfg = cfg
+        self.image = image
 
     def envs(self) -> Dict[str, str]:
         environ = {
@@ -196,9 +221,6 @@ class SambaContainerCommon:
             args.append(f'--debug-delay={self.cfg.debug_delay}')
         return args
 
-    def container_args(self) -> List[str]:
-        return []
-
 
 class SambaNetworkedInitContainer(SambaContainerCommon):
     """SambaContainerCommon subclass that enables additional networking
@@ -233,6 +255,9 @@ class SMBDContainer(SambaContainerCommon):
         cargs = []
         if self.cfg.smb_port:
             cargs.append(f'--publish={self.cfg.smb_port}:{self.cfg.smb_port}')
+        if self.cfg.metrics_port:
+            metrics_port = self.cfg.metrics_port
+            cargs.append(f'--publish={metrics_port}:{metrics_port}')
         cargs.extend(_container_dns_args(self.cfg))
         return cargs
 
@@ -284,6 +309,17 @@ class ConfigWatchContainer(SambaContainerCommon):
         return super().args() + ['update-config', '--watch']
 
 
+class SMBMetricsContainer(ContainerCommon):
+    def name(self) -> str:
+        return 'smbmetrics'
+
+    def args(self) -> List[str]:
+        args = []
+        if self.cfg.metrics_port > 0:
+            args.append(f'--port={self.cfg.metrics_port}')
+        return args
+
+
 class CTDBMigrateInitContainer(SambaContainerCommon):
     def name(self) -> str:
         return 'ctdbMigrate'
@@ -358,13 +394,13 @@ class CTDBNodeMonitorContainer(SambaContainerCommon):
 class ContainerLayout:
     init_containers: List[SambaContainerCommon]
     primary: SambaContainerCommon
-    supplemental: List[SambaContainerCommon]
+    supplemental: List[ContainerCommon]
 
     def __init__(
         self,
         init_containers: List[SambaContainerCommon],
         primary: SambaContainerCommon,
-        supplemental: List[SambaContainerCommon],
+        supplemental: List[ContainerCommon],
     ) -> None:
         self.init_containers = init_containers
         self.primary = primary
@@ -393,6 +429,7 @@ class SMB(ContainerDaemonForm):
         self._cached_layout: Optional[ContainerLayout] = None
         self._rank_info = context_getters.fetch_rank_info(ctx)
         self.smb_port = 445
+        self.metrics_port = 9922
         self._network_mapper = _NetworkMapper(ctx)
         logger.debug('Created SMB ContainerDaemonForm instance')
 
@@ -431,6 +468,8 @@ class SMB(ContainerDaemonForm):
         files = data_utils.dict_get(configs, 'files', {})
         ceph_config_entity = configs.get('config_auth_entity', '')
         vhostname = configs.get('virtual_hostname', '')
+        metrics_image = configs.get('metrics_image', '')
+        metrics_port = int(configs.get('metrics_port', '0'))
         cluster_meta_uri = configs.get('cluster_meta_uri', '')
         cluster_lock_uri = configs.get('cluster_lock_uri', '')
         cluster_public_addrs = configs.get('cluster_public_addrs', [])
@@ -470,6 +509,8 @@ class SMB(ContainerDaemonForm):
             smb_port=self.smb_port,
             ceph_config_entity=ceph_config_entity,
             vhostname=vhostname,
+            metrics_image=metrics_image,
+            metrics_port=metrics_port,
             cluster_meta_uri=cluster_meta_uri,
             cluster_lock_uri=cluster_lock_uri,
             cluster_public_addrs=_public_addrs,
@@ -517,7 +558,7 @@ class SMB(ContainerDaemonForm):
         if self._cached_layout:
             return self._cached_layout
         init_ctrs: List[SambaContainerCommon] = []
-        ctrs: List[SambaContainerCommon] = []
+        ctrs: List[ContainerCommon] = []
 
         init_ctrs.append(ConfigInitContainer(self._cfg))
         ctrs.append(ConfigWatchContainer(self._cfg))
@@ -526,6 +567,11 @@ class SMB(ContainerDaemonForm):
             init_ctrs.append(MustJoinContainer(self._cfg))
             ctrs.append(WinbindContainer(self._cfg))
 
+        metrics_image = self._cfg.metrics_image.strip()
+        metrics_port = self._cfg.metrics_port
+        if metrics_image and metrics_port > 0:
+            ctrs.append(SMBMetricsContainer(self._cfg, metrics_image))
+
         if self._cfg.clustered:
             init_ctrs += [
                 CTDBMigrateInitContainer(self._cfg),
@@ -564,7 +610,7 @@ class SMB(ContainerDaemonForm):
         )
 
     def _to_sidecar_container(
-        self, ctx: CephadmContext, smb_ctr: SambaContainerCommon
+        self, ctx: CephadmContext, smb_ctr: ContainerCommon
     ) -> SidecarContainer:
         volume_mounts: Dict[str, str] = {}
         container_args: List[str] = smb_ctr.container_args()
@@ -587,10 +633,11 @@ class SMB(ContainerDaemonForm):
         identity = DaemonSubIdentity.from_parent(
             self.identity, smb_ctr.name()
         )
+        img = smb_ctr.container_image() or ctx.image or self.default_image
         return SidecarContainer(
             ctx,
             entrypoint='',
-            image=ctx.image or self.default_image,
+            image=img,
             identity=identity,
             container_args=container_args,
             args=smb_ctr.args(),
@@ -673,6 +720,9 @@ class SMB(ContainerDaemonForm):
     ) -> None:
         if not any(ep.port == self.smb_port for ep in endpoints):
             endpoints.append(EndPoint('0.0.0.0', self.smb_port))
+        if self.metrics_port > 0:
+            if not any(ep.port == self.metrics_port for ep in endpoints):
+                endpoints.append(EndPoint('0.0.0.0', self.metrics_port))
 
     def prepare_data_dir(self, data_dir: str, uid: int, gid: int) -> None:
         self.validate()