[oe-commits] [openembedded-core] 02/12: systemd-systemctl: Restore support for enable command

git at git.openembedded.org git at git.openembedded.org
Wed May 8 22:12:24 UTC 2019


This is an automated email from the git hooks/post-receive script.

rpurdie pushed a commit to branch master-next
in repository openembedded-core.

commit 44690d76f9c79c9a9ddcce8cb251c14507a16ff8
Author: Alex Kiernan <alex.kiernan at gmail.com>
AuthorDate: Wed May 8 16:57:27 2019 +0100

    systemd-systemctl: Restore support for enable command
    
    Refactor so that SystemdUnit is its own class, then add support for the
    enable command. This restores the ability of systemd.bbclass to create
    instances using syntax such as:
    
      SYSTEMD_SERVICE_${PN} = "serial-getty at ttyAMA0.service"
    
    Signed-off-by: Alex Kiernan <alex.kiernan at gmail.com>
    Signed-off-by: Richard Purdie <richard.purdie at linuxfoundation.org>
---
 .../systemd/systemd-systemctl/systemctl            | 179 ++++++++++++---------
 1 file changed, 102 insertions(+), 77 deletions(-)

diff --git a/meta/recipes-core/systemd/systemd-systemctl/systemctl b/meta/recipes-core/systemd/systemd-systemctl/systemctl
index 7fdaf8c..8d7b3ba 100755
--- a/meta/recipes-core/systemd/systemd-systemctl/systemctl
+++ b/meta/recipes-core/systemd/systemd-systemctl/systemctl
@@ -20,6 +20,8 @@ SYSCONFDIR = Path("etc")
 BASE_LIBDIR = Path("lib")
 LIBDIR = Path("usr", "lib")
 
+locations = list()
+
 
 class SystemdFile():
     """Class representing a single systemd configuration file"""
@@ -111,12 +113,6 @@ class Presets():
 
     def _collect_presets(self, scope, root):
         """Collect list of preset files"""
-        locations = [SYSCONFDIR / "systemd"]
-        # Handle the usrmerge case by ignoring /lib when it's a symlink
-        if not BASE_LIBDIR.is_symlink():
-            locations.append(BASE_LIBDIR / "systemd")
-        locations.append(LIBDIR / "systemd")
-
         presets = dict()
         for location in locations:
             paths = (root / location / scope).glob("*.preset")
@@ -146,27 +142,6 @@ class Presets():
         return None
 
 
-def collect_services(root):
-    """Collect list of service files"""
-    locations = [SYSCONFDIR / "systemd"]
-    # Handle the usrmerge case by ignoring /lib when it's a symlink
-    if not BASE_LIBDIR.is_symlink():
-        locations.append(BASE_LIBDIR / "systemd")
-    locations.append(LIBDIR / "systemd")
-
-    services = dict()
-    for location in locations:
-        paths = (root / location / "system").glob("*")
-        for path in paths:
-            if path.is_dir():
-                continue
-            # implement earlier names override later ones
-            if path.name not in services:
-                services[path.name] = path
-
-    return services
-
-
 def add_link(path, target):
     try:
         path.parent.mkdir(parents=True)
@@ -177,69 +152,113 @@ def add_link(path, target):
         path.symlink_to(target)
 
 
-def process_deps(root, config, service, location, prop, dirstem):
-    systemdir = SYSCONFDIR / "systemd" / "system"
+class SystemdUnitNotFoundError(Exception):
+    pass
 
-    target = ROOT / location.relative_to(root)
-    try:
-        for dependent in config.get('Install', prop):
-            wants = root / systemdir / "{}.{}".format(dependent, dirstem) / service
-            add_link(wants, target)
 
-    except KeyError:
-        pass
+class SystemdUnit():
+    def __init__(self, root, unit):
+        self.root = root
+        self.unit = unit
+        self.config = None
+
+    def _path_for_unit(self, unit):
+        for location in locations:
+            path = self.root / location / "system" / unit
+            if path.exists():
+                return path
 
+        raise SystemdUnitNotFoundError(self.root, unit)
 
-def enable(root, service, location, services):
-    if location.is_symlink():
-        # ignore aliases
-        return
+    def _process_deps(self, config, service, location, prop, dirstem):
+        systemdir = self.root / SYSCONFDIR / "systemd" / "system"
+
+        target = ROOT / location.relative_to(self.root)
+        try:
+            for dependent in config.get('Install', prop):
+                wants = systemdir / "{}.{}".format(dependent, dirstem) / service
+                add_link(wants, target)
+
+        except KeyError:
+            pass
+
+    def enable(self):
+        # 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)
+        if template:
+            instance = template.group('instance')
+            unit = re.sub(r"@[^\.]*\.", "@.", self.unit, 1)
+        else:
+            instance = None
+            unit = self.unit
+
+        path = self._path_for_unit(unit)
+
+        if path.is_symlink():
+            # ignore aliases
+            return
 
-    config = SystemdFile(root, location)
-    template = re.match(r"[^@]+@(?P<instance>[^\.]*)\.", service)
-    if template:
-        instance = template.group('instance')
-        if not instance:
+        config = SystemdFile(self.root, path)
+        if instance == "":
             try:
-                instance = config.get('Install', 'DefaultInstance')[0]
-                service = service.replace("@.", "@{}.".format(instance))
+                default_instance = config.get('Install', 'DefaultInstance')[0]
             except KeyError:
-                pass
-        if instance is None:
-            return
-    else:
-        instance = None
+                # no default instance, so nothing to enable
+                return
 
-    process_deps(root, config, service, location, 'WantedBy', 'wants')
-    process_deps(root, config, service, location, 'RequiredBy', 'requires')
+            service = self.unit.replace("@.",
+                                        "@{}.".format(default_instance))
+        else:
+            service = self.unit
 
-    try:
-        for also in config.get('Install', 'Also'):
-            enable(root, also, services[also], services)
+        self._process_deps(config, service, path, 'WantedBy', 'wants')
+        self._process_deps(config, service, path, 'RequiredBy', 'requires')
 
-    except KeyError:
-        pass
+        try:
+            for also in config.get('Install', 'Also'):
+                SystemdUnit(self.root, also).enable()
 
-    systemdir = root / SYSCONFDIR / "systemd" / "system"
-    target = ROOT / location.relative_to(root)
-    try:
-        for dest in config.get('Install', 'Alias'):
-            alias = systemdir / dest
-            add_link(alias, target)
+        except KeyError:
+            pass
 
-    except KeyError:
-        pass
+        systemdir = self.root / SYSCONFDIR / "systemd" / "system"
+        target = ROOT / path.relative_to(self.root)
+        try:
+            for dest in config.get('Install', 'Alias'):
+                alias = systemdir / dest
+                add_link(alias, target)
+
+        except KeyError:
+            pass
+
+    def mask(self):
+        systemdir = self.root / SYSCONFDIR / "systemd" / "system"
+        add_link(systemdir / self.unit, "/dev/null")
+
+
+def collect_services(root):
+    """Collect list of service files"""
+    services = set()
+    for location in locations:
+        paths = (root / location / "system").glob("*")
+        for path in paths:
+            if path.is_dir():
+                continue
+            services.add(path.name)
+
+    return services
 
 
 def preset_all(root):
     presets = Presets('system-preset', root)
     services = collect_services(root)
 
-    for service, location in services.items():
+    for service in services:
         state = presets.state(service)
 
         if state == "enable" or state is None:
-            enable(root, service, location, services)
+            SystemdUnit(root, service).enable()
 
     # If we populate the systemd links we also create /etc/machine-id, which
     # allows systemd to boot with the filesystem read-only before generating
@@ -251,18 +270,13 @@ def preset_all(root):
     (root / SYSCONFDIR / "machine-id").touch()
 
 
-def mask(root, *services):
-    systemdir = root / SYSCONFDIR / "systemd" / "system"
-    for service in services:
-        add_link(systemdir / service, "/dev/null")
-
-
 def main():
     if sys.version_info < (3, 4, 0):
         sys.exit("Python 3.4 or greater is required")
 
     parser = argparse.ArgumentParser()
-    parser.add_argument('command', nargs=1, choices=['mask', 'preset-all'])
+    parser.add_argument('command', nargs=1, choices=['enable', 'mask',
+                                                     'preset-all'])
     parser.add_argument('service', nargs=argparse.REMAINDER)
     parser.add_argument('--root')
     parser.add_argument('--preset-mode',
@@ -272,9 +286,20 @@ def main():
     args = parser.parse_args()
 
     root = Path(args.root) if args.root else ROOT
+
+    locations.append(SYSCONFDIR / "systemd")
+    # Handle the usrmerge case by ignoring /lib when it's a symlink
+    if not (root / BASE_LIBDIR).is_symlink():
+        locations.append(BASE_LIBDIR / "systemd")
+    locations.append(LIBDIR / "systemd")
+
     command = args.command[0]
     if command == "mask":
-        mask(root, *args.service)
+        for service in args.service:
+            SystemdUnit(root, service).mask()
+    elif command == "enable":
+        for service in args.service:
+            SystemdUnit(root, service).enable()
     elif command == "preset-all":
         if len(args.service) != 0:
             sys.exit("Too many arguments.")

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Openembedded-commits mailing list