From 02f02fd6c8cf235629014b8646980fd353800211 Mon Sep 17 00:00:00 2001 From: John Mulligan Date: Fri, 17 Nov 2023 14:34:24 -0500 Subject: [PATCH] cephadm: add support for systemd unit files for init/sidecar ctrs Signed-off-by: John Mulligan --- src/cephadm/cephadmlib/systemd_unit.py | 139 ++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 4 deletions(-) diff --git a/src/cephadm/cephadmlib/systemd_unit.py b/src/cephadm/cephadmlib/systemd_unit.py index 0c392c77bfe36..208bfba2706a1 100644 --- a/src/cephadm/cephadmlib/systemd_unit.py +++ b/src/cephadm/cephadmlib/systemd_unit.py @@ -1,16 +1,138 @@ # systemd_unit.py - creating/managing systemd unit files +import contextlib import os +import pathlib + +from typing import IO, List, Optional, Union from . import templating from .call_wrappers import call_throws from .container_engines import Docker, Podman from .context import CephadmContext -from .daemon_identity import DaemonIdentity +from .daemon_identity import DaemonIdentity, DaemonSubIdentity from .file_utils import write_new from .logging import write_cluster_logrotate_config +_DROP_IN_FILENAME = '99-cephadm.conf' + + +class PathInfo: + """Utility class to map basic service identities, to the paths used by + their corresponding systemd unit files. + """ + + def __init__( + self, + unit_dir: Union[str, pathlib.Path], + identity: DaemonIdentity, + sidecar_ids: Optional[List[DaemonSubIdentity]] = None, + ) -> None: + self.identity = identity + self.sidecar_ids = sidecar_ids or [] + + unit_dir = pathlib.Path(unit_dir) + self.default_unit_file = unit_dir / f'ceph-{identity.fsid}@.service' + self.init_ctr_unit_file = unit_dir / identity.init_service_name + self.sidecar_unit_files = { + si: unit_dir / si.sidecar_service_name for si in self.sidecar_ids + } + dname = f'{identity.service_name}.d' + self.drop_in_file = unit_dir / dname / _DROP_IN_FILENAME + + +def _write_drop_in( + dest: IO, + ctx: CephadmContext, + identity: DaemonIdentity, + enable_init_containers: bool, + sidecar_ids: List[DaemonSubIdentity], +) -> None: + templating.render_to_file( + dest, + ctx, + templating.Templates.dropin_service, + identity=identity, + enable_init_containers=enable_init_containers, + sidecar_ids=sidecar_ids, + ) + + +def _write_init_containers_unit_file( + dest: IO, ctx: CephadmContext, identity: DaemonIdentity +) -> None: + has_docker_engine = isinstance(ctx.container_engine, Docker) + has_podman_engine = isinstance(ctx.container_engine, Podman) + templating.render_to_file( + dest, + ctx, + templating.Templates.init_ctr_service, + identity=identity, + has_docker_engine=has_docker_engine, + has_podman_engine=has_podman_engine, + has_podman_split_version=( + has_podman_engine and ctx.container_engine.supports_split_cgroups + ), + ) + + +def _write_sidecar_unit_file( + dest: IO, ctx: CephadmContext, primary: DaemonIdentity, sidecar: DaemonSubIdentity +) -> None: + has_docker_engine = isinstance(ctx.container_engine, Docker) + has_podman_engine = isinstance(ctx.container_engine, Podman) + templating.render_to_file( + dest, + ctx, + templating.Templates.sidecar_service, + primary=primary, + sidecar=sidecar, + sidecar_script=sidecar.sidecar_script(ctx.data_dir), + has_docker_engine=has_docker_engine, + has_podman_engine=has_podman_engine, + has_podman_split_version=( + has_podman_engine and ctx.container_engine.supports_split_cgroups + ), + ) + + +def _install_extended_systemd_services( + ctx: CephadmContext, + pinfo: PathInfo, + identity: DaemonIdentity, + enable_init_containers: bool = False, +) -> None: + """Install the systemd unit files needed for more complex services + that have init containers and/or sidecars. + """ + with contextlib.ExitStack() as estack: + # install the unit file to handle running init containers + if enable_init_containers: + icfh = estack.enter_context( + write_new(pinfo.init_ctr_unit_file, perms=None) + ) + _write_init_containers_unit_file(icfh, ctx, identity) + + # install the unit files to handle running sidecars + sids = [] + for si, sup in pinfo.sidecar_unit_files.items(): + sufh = estack.enter_context(write_new(sup, perms=None)) + _write_sidecar_unit_file(sufh, ctx, identity, si) + sids.append(si) + + # create a drop-in to create a relationship between the primary + # service and the init- and sidecar-based services. + if enable_init_containers or sids: + pinfo.drop_in_file.parent.mkdir(parents=True, exist_ok=True) + difh = estack.enter_context( + write_new(pinfo.drop_in_file, perms=None) + ) + _write_drop_in( + difh, ctx, identity, enable_init_containers, sids + ) + + def _get_unit_file(ctx: CephadmContext, fsid: str) -> str: has_docker_engine = isinstance(ctx.container_engine, Docker) has_podman_engine = isinstance(ctx.container_engine, Podman) @@ -73,9 +195,18 @@ def _install_base_units(ctx: CephadmContext, fsid: str) -> None: write_cluster_logrotate_config(ctx, fsid) -def update_files(ctx: CephadmContext, ident: DaemonIdentity) -> None: +def update_files( + ctx: CephadmContext, + ident: DaemonIdentity, + *, + init_container_ids: Optional[List[DaemonSubIdentity]] = None, + sidecar_ids: Optional[List[DaemonSubIdentity]] = None, +) -> None: _install_base_units(ctx, ident.fsid) unit = _get_unit_file(ctx, ident.fsid) - unit_file = 'ceph-%s@.service' % (ident.fsid) - with write_new(ctx.unit_dir + '/' + unit_file, perms=None) as f: + pathinfo = PathInfo(ctx.unit_dir, ident, sidecar_ids=sidecar_ids) + with write_new(pathinfo.default_unit_file, perms=None) as f: f.write(unit) + _install_extended_systemd_services( + ctx, pathinfo, ident, bool(init_container_ids) + ) -- 2.39.5