diff options
Diffstat (limited to 'meta/recipes-core/systemd/systemd-systemctl/systemctl')
-rwxr-xr-x | meta/recipes-core/systemd/systemd-systemctl/systemctl | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/meta/recipes-core/systemd/systemd-systemctl/systemctl b/meta/recipes-core/systemd/systemd-systemctl/systemctl index de733e255b..2229bc7b6d 100755 --- a/meta/recipes-core/systemd/systemd-systemctl/systemctl +++ b/meta/recipes-core/systemd/systemd-systemctl/systemctl @@ -11,6 +11,7 @@ import re import sys from collections import namedtuple +from itertools import chain from pathlib import Path version = 1.0 @@ -25,12 +26,19 @@ locations = list() class SystemdFile(): """Class representing a single systemd configuration file""" - def __init__(self, root, path): + + _clearable_keys = ['WantedBy'] + + def __init__(self, root, path, instance_unit_name): self.sections = dict() self._parse(root, path) dirname = os.path.basename(path.name) + ".d" for location in locations: - for path2 in sorted((root / location / "system" / dirname).glob("*.conf")): + files = (root / location / "system" / dirname).glob("*.conf") + if instance_unit_name: + inst_dirname = instance_unit_name + ".d" + files = chain(files, (root / location / "system" / inst_dirname).glob("*.conf")) + for path2 in sorted(files): self._parse(root, path2) def _parse(self, root, path): @@ -75,6 +83,14 @@ class SystemdFile(): v = m.group('value') if k not in section: section[k] = list() + + # If we come across a "key=" line for a "clearable key", then + # forget all preceding assignments. This works because we are + # processing files in correct parse order. + if k in self._clearable_keys and not v: + del section[k] + continue + section[k].extend(v.split()) def get(self, section, prop): @@ -160,7 +176,9 @@ def add_link(path, target): class SystemdUnitNotFoundError(Exception): - pass + def __init__(self, path, unit): + self.path = path + self.unit = unit class SystemdUnit(): @@ -177,24 +195,29 @@ 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, instance): systemdir = self.root / SYSCONFDIR / "systemd" / "system" target = ROOT / location.relative_to(self.root) try: for dependent in config.get('Install', prop): + # expand any %i to instance (ignoring escape sequence %%) + dependent = re.sub("([^%](%%)*)%i", "\\g<1>{}".format(instance), dependent) wants = systemdir / "{}.{}".format(dependent, dirstem) / service add_link(wants, target) except KeyError: pass - def enable(self): + def enable(self, units_enabled=[]): # if we're enabling an instance, first extract the actual instance # then figure out what the template unit is template = re.match(r"[^@]+@(?P<instance>[^\.]*)\.", self.unit) + instance_unit_name = None if template: instance = template.group('instance') + if instance != "": + instance_unit_name = self.unit unit = re.sub(r"@[^\.]*\.", "@.", self.unit, 1) else: instance = None @@ -206,7 +229,7 @@ class SystemdUnit(): # ignore aliases return - config = SystemdFile(self.root, path) + config = SystemdFile(self.root, path, instance_unit_name) if instance == "": try: default_instance = config.get('Install', 'DefaultInstance')[0] @@ -219,12 +242,17 @@ class SystemdUnit(): 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', instance) + self._process_deps(config, service, path, 'RequiredBy', 'requires', instance) try: for also in config.get('Install', 'Also'): - SystemdUnit(self.root, also).enable() + try: + units_enabled.append(unit) + if also not in units_enabled: + SystemdUnit(self.root, also).enable(units_enabled) + except SystemdUnitNotFoundError as e: + sys.exit("Error: Systemctl also enable issue with %s (%s)" % (service, e.unit)) except KeyError: pass @@ -265,7 +293,10 @@ def preset_all(root): state = presets.state(service) if state == "enable" or state is None: - SystemdUnit(root, service).enable() + try: + SystemdUnit(root, service).enable() + except SystemdUnitNotFoundError: + sys.exit("Error: Systemctl preset_all issue in %s" % service) # If we populate the systemd links we also create /etc/machine-id, which # allows systemd to boot with the filesystem read-only before generating @@ -307,10 +338,16 @@ def main(): if command == "mask": for service in args.service: - SystemdUnit(root, service).mask() + try: + SystemdUnit(root, service).mask() + except SystemdUnitNotFoundError as e: + sys.exit("Error: Systemctl main mask issue in %s (%s)" % (service, e.unit)) elif command == "enable": for service in args.service: - SystemdUnit(root, service).enable() + try: + SystemdUnit(root, service).enable() + except SystemdUnitNotFoundError as e: + sys.exit("Error: Systemctl main enable issue in %s (%s)" % (service, e.unit)) elif command == "preset-all": if len(args.service) != 0: sys.exit("Too many arguments.") |