From 1c4c37d21abad3cfdb78bd2a09881722e7c7d160 Mon Sep 17 00:00:00 2001 From: Fabian Pflug Date: Tue, 8 Sep 2026 13:24:43 +0200 Subject: [PATCH] systemd-systemctl: enable templated services The wrapper script previously did not allow to instantiate templated services without DefaultInstance defined. This change allows foo@.service be installed and therefor be in enabled state. In real systemd land, templated units without a specified instance are valid, but we restrict it here a bit in order to not have a foo@.service with: [Install] WantedBy=bar.service # bar.service starts -> start foo@???.service In this case, system can never resolve the specific instance of foo@.service when bar.service is started. It is fixed by adding the template_only variable, which restricts the dependents of generic template units to template-only ones. This means the following is still legal for the above foo@.service: [Install] WantedBy=bar@.service # bar@1.service starts -> start foo@1.service # bar@2.service starts -> start foo@2.service # etc... WantedBy=bas@1.service # bas@1.service starts -> start foo@1.service # bas@2.service starts -> no dependency here # etc... Signed-off-by: Fabian Pflug Signed-off-by: Khem Raj --- .../systemd/systemd-systemctl/systemctl | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/meta-oe/recipes-devtools/systemd/systemd-systemctl/systemctl b/meta-oe/recipes-devtools/systemd/systemd-systemctl/systemctl index 07d24fd175..a9785e8b4b 100755 --- a/meta-oe/recipes-devtools/systemd/systemd-systemctl/systemctl +++ b/meta-oe/recipes-devtools/systemd/systemd-systemctl/systemctl @@ -179,12 +179,18 @@ class SystemdUnit(): raise SystemdUnitNotFoundError(self.root, unit) - def _process_deps(self, config, service, location, prop, dirstem): + def _process_deps(self, config, service, location, prop, dirstem, + template_only): systemdir = self.root / SYSCONFDIR / "systemd" / "system" target = ROOT / location.relative_to(self.root) try: for dependent in config.get('Install', prop): + # template-only dependencies means either foo@.unit or foo@bar.unit, + # but not foo.unit, as then systemd cannot resolve the instance + if template_only and not re.match(r"[^@]+@[^\.]*\.", dependent): + continue + wants = systemdir / "{}.{}".format(dependent, dirstem) / service add_link(wants, target) @@ -209,20 +215,24 @@ class SystemdUnit(): return config = SystemdFile(self.root, path) + service = self.unit + template_only = False + + # handle enabling a template unit with unspecified instance if instance == "": try: default_instance = config.get('Install', 'DefaultInstance')[0] except KeyError: - # no default instance, so nothing to enable - return + # no default instance, allow template only dependencies + template_only = True + else: + # otherwise rewrite the service name with the default instance + service = self.unit.replace("@.", "@{}.".format(default_instance)) - service = self.unit.replace("@.", - "@{}.".format(default_instance)) - else: - service = self.unit - - self._process_deps(config, service, path, 'WantedBy', 'wants') - self._process_deps(config, service, path, 'RequiredBy', 'requires') + self._process_deps(config, service, path, 'WantedBy', 'wants', + template_only) + self._process_deps(config, service, path, 'RequiredBy', 'requires', + template_only) try: for also in config.get('Install', 'Also'):