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
