]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
cephadm: add method for parsing a sub identity from a service name
authorJohn Mulligan <jmulligan@redhat.com>
Sat, 18 Nov 2023 18:58:33 +0000 (13:58 -0500)
committerJohn Mulligan <jmulligan@redhat.com>
Tue, 2 Jan 2024 14:30:21 +0000 (09:30 -0500)
This will become handy later when we need DaemonSubIdentity objects and
are not on the deploy path.

Signed-off-by: John Mulligan <jmulligan@redhat.com>
src/cephadm/cephadmlib/daemon_identity.py
src/cephadm/tests/test_util_funcs.py

index cbefa15041a0c42b51c0dc29bbf4b71db071f6ff..760401a3e5402923bf4a06bef430cabed9d9b396 100644 (file)
@@ -5,7 +5,7 @@ import os
 import pathlib
 import re
 
-from typing import Union, Optional
+from typing import Union, Optional, Tuple
 
 from .context import CephadmContext
 
@@ -177,6 +177,50 @@ class DaemonSubIdentity(DaemonIdentity):
             subcomponent,
         )
 
+    @classmethod
+    def from_service_name(
+        cls, service_name: str
+    ) -> Tuple['DaemonSubIdentity', str]:
+        """Return a DaemonSubIdentity and category value by parsing the
+        contents of a systemd service name for a sidecar container.
+        """
+        # ceph services always have the template@instance form
+        tpart, ipart = service_name.split('@', 1)
+        # drop the .service if it exists
+        if ipart.endswith('.service'):
+            ipart = ipart[:-8]
+        # verify the service name starts with 'ceph' -- our framework
+        framework, tpart = tpart.split('-', 1)
+        if framework != 'ceph':
+            raise ValueError(f'Invalid framework value: {service_name}')
+        # we're parsing only services for subcomponents. it must take the
+        # form <FSID>-<CATEGORY>. Where categories are sidecar or init.
+        fsid, category = tpart.rsplit('-', 1)
+        try:
+            Categories(category)
+        except ValueError:
+            raise ValueError(f'Invalid service category: {service_name}')
+        # if it is a sidecar it will have a subcomponent name following a colon
+        svcparts = ipart.split(':')
+        if len(svcparts) == 1:
+            subc = ''
+        elif len(svcparts) == 2:
+            subc = svcparts[1]
+        else:
+            raise ValueError(f'Unexpected instance value: {ipart}')
+        # only services based on sidecars currently have named subcomponents
+        # init subcomponents are all "hidden" within a single init service
+        if subc and not category == Categories.SIDECAR:
+            raise ValueError(
+                f'Unexpected subcomponent {subc!r} for category {category}'
+            )
+        elif not subc:
+            # because we return a DaemonSubIdentity we need some value for
+            # the subcomponent on init services. Just repeat the category
+            subc = str(category)
+        daemon_type, daemon_id = svcparts[0].split('.', 1)
+        return cls(fsid, daemon_type, daemon_id, subc), category
+
     @classmethod
     def must(cls, value: Optional[DaemonIdentity]) -> 'DaemonSubIdentity':
         """Helper to assert value is of the correct type.  Mostly to make mypy
index ffcf3909c4ee15f670278c1784aecb26815abe78..c52852db679ff46f00cb04d5461ede2a1791a505 100644 (file)
@@ -810,3 +810,65 @@ def test_apply_deploy_config_to_ctx(cc, monkeypatch):
     ctx = FakeContext()
     _cephadm.apply_deploy_config_to_ctx(cc.cfg_data, ctx)
     cc.check(ctx)
+
+
+def test_daemon_sub_identity_from_sidecar_service():
+    from cephadmlib.daemon_identity import DaemonSubIdentity
+
+    dsi = DaemonSubIdentity(
+        '244c9842-866b-11ee-80ad-3497f6318048', 'iscsi', 'rab.oof', 'tcmu'
+    )
+    service_name = dsi.sidecar_service_name
+    assert (
+        service_name
+        == 'ceph-244c9842-866b-11ee-80ad-3497f6318048-sidecar@iscsi.rab.oof:tcmu.service'
+    )
+    d2, category = DaemonSubIdentity.from_service_name(service_name)
+    assert category == 'sidecar'
+    assert d2.fsid == '244c9842-866b-11ee-80ad-3497f6318048'
+    assert d2.daemon_type == 'iscsi'
+    assert d2.daemon_id == 'rab.oof'
+    assert d2.subcomponent == 'tcmu'
+
+
+def test_daemon_sub_identity_from_init_service():
+    from cephadmlib.daemon_identity import DaemonIdentity, DaemonSubIdentity
+
+    di = DaemonIdentity(
+        '244c9842-866b-11ee-80ad-3497f6318048', 'putrats', 'wow',
+    )
+    service_name = di.init_service_name
+    assert (
+        service_name
+        == 'ceph-244c9842-866b-11ee-80ad-3497f6318048-init@putrats.wow.service'
+    )
+    d2, category = DaemonSubIdentity.from_service_name(service_name)
+    assert category == 'init'
+    assert d2.fsid == '244c9842-866b-11ee-80ad-3497f6318048'
+    assert d2.daemon_type == 'putrats'
+    assert d2.daemon_id == 'wow'
+    assert d2.subcomponent == 'init'
+
+
+def test_daemon_sub_identity_from_service_invalid():
+    from cephadmlib.daemon_identity import DaemonSubIdentity
+
+    service_name = 'ceph-244c9842-866b-11ee-80ad-3497f6318048-morbo@iscsi.rab.oof.tcmu.service'
+    with pytest.raises(ValueError):
+        DaemonSubIdentity.from_service_name(service_name)
+
+    service_name = 'ceph-244c9842-866b-11ee-80ad-3497f6318048@iscsi.rab.oof.service'
+    with pytest.raises(ValueError):
+        DaemonSubIdentity.from_service_name(service_name)
+
+    service_name = 'ceph-244c9842-866b-11ee-80ad-3497f6318048-sidecar@foo.bar.baz:acolon:toomany.service'
+    with pytest.raises(ValueError):
+        DaemonSubIdentity.from_service_name(service_name)
+
+    service_name = 'ceph-244c9842-866b-11ee-80ad-3497f6318048-init@foo.bar.baz:woops.service'
+    with pytest.raises(ValueError):
+        DaemonSubIdentity.from_service_name(service_name)
+
+    service_name = 'random-task@elsewise.service'
+    with pytest.raises(ValueError):
+        DaemonSubIdentity.from_service_name(service_name)