Hi everybody,

A few days ago I started playing with systemd user sessions[1] for a
distribution I'm setting up. I noticed that for system services
everything is setup correctly by using "inherit systemd", but there's
currently no much support for systemd user session services to be
installed easily.

As far as I understood and tested in my old (yocto-1.6) env, those
services files are supposed to be installed in /usr/lib/systemd/user/
instead of /lib/systemd/system/. Also, to enable or disable them with
systemctl one must explicitly declare so by using "--global"
parameter.

That means both FILES and postinst/prerm parts should be updated to
have that into account. After doing some tests, I arrived to the
conclusion that the best way to do that would be defining another env
var called SYSTEMD_USER_SERVICE used in recipes which does the same as
SYSTEMD_SERVICE, but meant to be used for user session systemd
services.

I did all the changes which should be needed and tested it with
pulseaudio, which is supposed to be used as a user session service. In
order to do that, I also needed to enable systemd support on the
recipe, which was not there.

I attach two patches implementing those changes, based on master-next.
Those patches are still not perfect though, and I need some advise on
that. It seems there's a problem currently with systemctl failing when
run with both "--root" and "--global" parameters at the same time. It
looks like usually the postinst script is run inside the OE env while
building, so the --root=$D is used, and so systemctl fails with
Invalid Argument. If I try to install the generated package once the
system is running, it works fine, because --root is not used.

I tried asking for help on #systemd IRC channel but I got no response so far.

I also opened a bug report in yocto related to this problem [2][3].

Any comments on this would be welcome.

By the way, if you try to run pulseaudio as user session you will
probably need also a session service to create a dbus session, as well
as some more black magic. If someone needs help on that please ask.
You may also want to check [1].

[1] https://wiki.archlinux.org/index.php/Systemd/User
[2] https://bugzilla.yoctoproject.org/show_bug.cgi?id=7800
[3] https://bugzilla.yoctoproject.org/show_bug.cgi?id=7801


Pau Espin Pedrol
From 1b223c86b88d29ce410c3f7220a9e4b6e7e6bde6 Mon Sep 17 00:00:00 2001
From: Pau Espin Pedrol <[email protected]>
Date: Thu, 21 May 2015 13:50:24 +0200
Subject: [PATCH 1/2] systemd.bbclass: Add code to enable user systemd services

* Some projects such as bluez/obex and pulseaudio install user session services in (/usr)/lib/systemd/user/.

* It still doesn't work completelly, because it seems systemctl returns "Operation failed: No such file" when using --global and --root params at the same time

Signed-off-by: Pau Espin Pedrol <[email protected]>

Conflicts:
	meta/classes/systemd.bbclass
---
 meta/classes/systemd.bbclass | 98 ++++++++++++++++++++++++++++++++------------
 1 file changed, 71 insertions(+), 27 deletions(-)

diff --git a/meta/classes/systemd.bbclass b/meta/classes/systemd.bbclass
index cfe1eb5..992869b 100644
--- a/meta/classes/systemd.bbclass
+++ b/meta/classes/systemd.bbclass
@@ -1,6 +1,7 @@
 # The list of packages that should have systemd packaging scripts added.  For
 # each entry, optionally have a SYSTEMD_SERVICE_[package] that lists the service
-# files in this package.  If this variable isn't set, [package].service is used.
+# files in this package. Same stands for SYSTEMD_USER_SERVICE_[package] for
+# systemd user session services.  If this variable isn't set, [package].service is used.
 SYSTEMD_PACKAGES ?= "${PN}"
 SYSTEMD_PACKAGES_class-native ?= ""
 SYSTEMD_PACKAGES_class-nativesdk ?= ""
@@ -29,11 +30,11 @@ if [ -n "$D" ]; then
 fi
 
 if type systemctl >/dev/null 2>/dev/null; then
-	systemctl $OPTS ${SYSTEMD_AUTO_ENABLE} ${SYSTEMD_SERVICE}
+    systemctl $OPTS ${SYSTEMD_AUTO_ENABLE} ${SYSTEMD_SERVICE}
 
-	if [ -z "$D" -a "${SYSTEMD_AUTO_ENABLE}" = "enable" ]; then
-		systemctl restart ${SYSTEMD_SERVICE}
-	fi
+    if [ -z "$D" -a "${SYSTEMD_AUTO_ENABLE}" = "enable" ]; then
+        systemctl restart ${SYSTEMD_SERVICE}
+    fi
 fi
 }
 
@@ -45,18 +46,48 @@ if [ -n "$D" ]; then
 fi
 
 if type systemctl >/dev/null 2>/dev/null; then
-	if [ -z "$D" ]; then
-		systemctl stop ${SYSTEMD_SERVICE}
-	fi
+    if [ -z "$D" ]; then
+        systemctl stop ${SYSTEMD_SERVICE}
+    fi
 
-	systemctl $OPTS disable ${SYSTEMD_SERVICE}
+    systemctl $OPTS disable ${SYSTEMD_SERVICE}
 fi
 }
 
+systemd_user_postinst() {
+OPTS=""
 
-systemd_populate_packages[vardeps] += "systemd_prerm systemd_postinst"
-systemd_populate_packages[vardepsexclude] += "OVERRIDES"
+if [ -n "$D" ]; then
+    OPTS="--root=$D"
+fi
+
+if type systemctl >/dev/null 2>/dev/null; then
+    systemctl --global $OPTS ${SYSTEMD_AUTO_ENABLE} ${SYSTEMD_USER_SERVICE}
+
+    if [ -z "$D" -a "${SYSTEMD_AUTO_ENABLE}" = "enable" ]; then
+        systemctl --user restart ${SYSTEMD_USER_SERVICE}
+    fi
+fi
+}
 
+systemd_user_prerm() {
+OPTS=""
+
+if [ -n "$D" ]; then
+    OPTS="--root=$D"
+fi
+
+if type systemctl >/dev/null 2>/dev/null; then
+    if [ -z "$D" ]; then
+        systemctl --user stop ${SYSTEMD_USER_SERVICE}
+    fi
+
+    systemctl --global $OPTS disable ${SYSTEMD_USER_SERVICE}
+fi
+}
+
+systemd_populate_packages[vardeps] += "systemd_prerm systemd_postinst systemd_user_prerm systemd_user_postinst"
+systemd_populate_packages[vardepsexclude] += "OVERRIDES"
 
 python systemd_populate_packages() {
     if not bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d):
@@ -75,11 +106,10 @@ python systemd_populate_packages() {
             bb.error('%s does not appear in package list, please add it' % pkg_systemd)
 
 
-    def systemd_generate_package_scripts(pkg):
-        bb.debug(1, 'adding systemd calls to postinst/postrm for %s' % pkg)
-
+    def systemd_generate_package_scripts(pkg, service_type):
+        bb.debug(1, 'adding systemd %s calls to postinst/prerm for %s' % (service_type, pkg))
         # Add pkg to the overrides so that it finds the SYSTEMD_SERVICE_pkg
-        # variable.
+        # and SYSTEMD_USER_SERVICE_pkg variables.
         localdata = d.createCopy()
         localdata.prependVar("OVERRIDES", pkg + ":")
         bb.data.update_data(localdata)
@@ -87,13 +117,19 @@ python systemd_populate_packages() {
         postinst = d.getVar('pkg_postinst_%s' % pkg, True)
         if not postinst:
             postinst = '#!/bin/sh\n'
-        postinst += localdata.getVar('systemd_postinst', True)
+        if service_type == 'system':
+            postinst += localdata.getVar('systemd_postinst', True)
+        elif service_type == 'user':
+            postinst += localdata.getVar('systemd_user_postinst', True)
         d.setVar('pkg_postinst_%s' % pkg, postinst)
 
         prerm = d.getVar('pkg_prerm_%s' % pkg, True)
         if not prerm:
             prerm = '#!/bin/sh\n'
-        prerm += localdata.getVar('systemd_prerm', True)
+        if service_type == 'system':
+            prerm += localdata.getVar('systemd_prerm', True)
+        elif service_type == 'user':
+            prerm += localdata.getVar('systemd_user_prerm', True)
         d.setVar('pkg_prerm_%s' % pkg, prerm)
 
 
@@ -134,16 +170,21 @@ python systemd_populate_packages() {
                 pipe.close()
 
     # Check service-files and call systemd_add_files_and_parse for each entry
-    def systemd_check_services():
-        searchpaths = [oe.path.join(d.getVar("sysconfdir", True), "systemd", "system"),]
-        searchpaths.append(oe.path.join(d.getVar("nonarch_base_libdir", True), "systemd", "system"))
-        searchpaths.append(oe.path.join(d.getVar("exec_prefix", True), d.getVar("nonarch_base_libdir", True), "systemd", "system"))
+    def systemd_check_services(service_type):
+        if service_type == 'system':
+            service_envvar = 'SYSTEMD_SERVICE'
+        elif service_type == 'user':
+            service_envvar = 'SYSTEMD_USER_SERVICE'
+
+        searchpaths = [oe.path.join(d.getVar("sysconfdir", True), "systemd", service_type),]
+        searchpaths.append(oe.path.join(d.getVar("nonarch_base_libdir", True), "systemd", service_type))
+        searchpaths.append(oe.path.join(d.getVar("exec_prefix", True), d.getVar("nonarch_base_libdir", True), "systemd", service_type))
         systemd_packages = d.getVar('SYSTEMD_PACKAGES', True)
 
         keys = 'Also'
-        # scan for all in SYSTEMD_SERVICE[]
+        # scan for all in SYSTEMD_SERVICE[] / SYSTEMD_USER_SERVICE[]
         for pkg_systemd in systemd_packages.split():
-            for service in get_package_var(d, 'SYSTEMD_SERVICE', pkg_systemd).split():
+            for service in get_package_var(d, service_envvar, pkg_systemd).split():
                 path_found = ''
                 for path in searchpaths:
                     if os.path.exists(oe.path.join(d.getVar("D", True), path, service)):
@@ -152,16 +193,19 @@ python systemd_populate_packages() {
                 if path_found != '':
                     systemd_add_files_and_parse(pkg_systemd, path_found, service, keys)
                 else:
-                    raise bb.build.FuncFailed("SYSTEMD_SERVICE_%s value %s does not exist" % \
-                        (pkg_systemd, service))
+                    raise bb.build.FuncFailed("%s_%s value %s does not exist" % \
+                        (service_envvar, pkg_systemd, service))
 
     # Run all modifications once when creating package
     if os.path.exists(d.getVar("D", True)):
         for pkg in d.getVar('SYSTEMD_PACKAGES', True).split():
             systemd_check_package(pkg)
             if d.getVar('SYSTEMD_SERVICE_' + pkg, True):
-                systemd_generate_package_scripts(pkg)
-        systemd_check_services()
+                systemd_generate_package_scripts(pkg, 'system')
+            if d.getVar('SYSTEMD_USER_SERVICE_' + pkg, True):
+                systemd_generate_package_scripts(pkg, 'user')
+        systemd_check_services('system')
+        systemd_check_services('user')
 }
 
 PACKAGESPLITFUNCS_prepend = "systemd_populate_packages "
-- 
1.9.1

From f304f4162a79040fa813eed90028b0fee10ef6fa Mon Sep 17 00:00:00 2001
From: Pau Espin Pedrol <[email protected]>
Date: Thu, 21 May 2015 14:09:05 +0200
Subject: [PATCH 2/2] pulseaudio.inc: enable systemd support if set in
 DISTRO_FEATURES

Signed-off-by: Pau Espin Pedrol <[email protected]>
---
 meta/recipes-multimedia/pulseaudio/pulseaudio.inc | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio.inc b/meta/recipes-multimedia/pulseaudio/pulseaudio.inc
index 30fe221..12c8b58 100644
--- a/meta/recipes-multimedia/pulseaudio/pulseaudio.inc
+++ b/meta/recipes-multimedia/pulseaudio/pulseaudio.inc
@@ -35,7 +35,9 @@ EXTRA_OECONF = "\
 PACKAGECONFIG ??= "${@bb.utils.contains('DISTRO_FEATURES', 'bluetooth', '${BLUEZ}', '', d)} \
                    ${@bb.utils.contains('DISTRO_FEATURES', 'zeroconf', 'avahi', '', d)} \
                    ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'x11', '', d)} \
-                   ${@bb.utils.contains('DISTRO_FEATURES', '3g', 'ofono', '', d)}"
+                   ${@bb.utils.contains('DISTRO_FEATURES', '3g', 'ofono', '', d)} \
+                   ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)} \
+                   "
 PACKAGECONFIG[bluez4] = "--enable-bluez4,--disable-bluez4,bluez4 sbc"
 PACKAGECONFIG[bluez5] = "--enable-bluez5,--disable-bluez5,bluez5 sbc"
 PACKAGECONFIG[ofono] = "--enable-bluez5-ofono-headset,--disable-bluez5-ofono-headset,ofono"
@@ -96,8 +98,8 @@ FILES_${PN}-conf = "${sysconfdir}"
 FILES_${PN}-bin += "${sysconfdir}/default/volatiles/volatiles.04_pulse"
 FILES_${PN}-server = "${bindir}/pulseaudio ${bindir}/start-* ${sysconfdir} ${bindir}/pactl */udev/rules.d/*.rules"
 
-#SYSTEMD_PACKAGES = "${PN}-server"
-SYSTEMD_SERVICE_${PN}-server = "pulseaudio.service"
+SYSTEMD_PACKAGES = "${PN}-server"
+SYSTEMD_USER_SERVICE_${PN}-server = "pulseaudio.socket"
 
 FILES_${PN}-misc = "${bindir}/* ${libdir}/pulseaudio/libpulsedsp.so"
 
-- 
1.9.1

-- 
_______________________________________________
Openembedded-devel mailing list
[email protected]
http://lists.openembedded.org/mailman/listinfo/openembedded-devel

Reply via email to