Message ID | 20250112143141.1300189-3-arturkow2000@gmail.com |
---|---|
State | New |
Headers | show |
Series | Systemd user presets support | expand |
Can this patch be split up to make review easier? Particularly, separate adding new functions into their own commits, with justification for each, and introduce usage of those functions in separate commits as well if possible, again with justification for each. Alex On Sun, 12 Jan 2025 at 15:40, Artur Kowalski via lists.openembedded.org <arturkow2000=gmail.com@lists.openembedded.org> wrote: > > Previously user units were causing build erros when listed in > SYSTEMD_SERVICE and SYSTEMD_AUTO_ENABLE was set. > > Signed-off-by: Artur Kowalski <arturkow2000@gmail.com> > --- > meta/classes-recipe/systemd.bbclass | 120 +++++++++++++++++++++------- > 1 file changed, 93 insertions(+), 27 deletions(-) > > diff --git a/meta/classes-recipe/systemd.bbclass b/meta/classes-recipe/systemd.bbclass > index 4b4470b7b3..80f4da3bdf 100644 > --- a/meta/classes-recipe/systemd.bbclass > +++ b/meta/classes-recipe/systemd.bbclass > @@ -37,17 +37,29 @@ if systemctl >/dev/null 2>/dev/null; then > fi > > if [ "${SYSTEMD_AUTO_ENABLE}" = "enable" ]; then > - for service in ${SYSTEMD_SERVICE_ESCAPED}; do > + for service in ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)}; do > systemctl ${OPTS} enable "$service" > done > + > + for service in ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)}; do > + systemctl --global ${OPTS} enable "$service" > + done > fi > > if [ -z "$D" ]; then > + # Reload only system service manager > + # --global for daemon-reload is not supported: https://github.com/systemd/systemd/issues/19284 > systemctl daemon-reload > - systemctl preset ${SYSTEMD_SERVICE_ESCAPED} > + [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)}" ] && \ > + systemctl preset ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)} > + > + [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)}" ] && \ > + systemctl --global preset ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)} > > if [ "${SYSTEMD_AUTO_ENABLE}" = "enable" ]; then > - systemctl --no-block restart ${SYSTEMD_SERVICE_ESCAPED} > + # --global flag for restart is not supported by systemd (see above) > + [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)}" ] && \ > + systemctl --no-block restart ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)} > fi > fi > fi > @@ -56,9 +68,14 @@ fi > systemd_prerm() { > if systemctl >/dev/null 2>/dev/null; then > if [ -z "$D" ]; then > - systemctl stop ${SYSTEMD_SERVICE_ESCAPED} > + # same as above, --global flag is not supported for stop > + if [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)}" ]; then > + systemctl stop ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)} > + systemctl disable ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)} > + fi > > - systemctl disable ${SYSTEMD_SERVICE_ESCAPED} > + [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)}" ] && \ > + systemctl --global disable ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)} > fi > fi > } > @@ -67,6 +84,44 @@ fi > systemd_populate_packages[vardeps] += "systemd_prerm systemd_postinst" > systemd_populate_packages[vardepsexclude] += "OVERRIDES" > > +def systemd_service_path(service, searchpaths, d): > + path_found = '' > + > + # Deal with adding, for example, 'ifplugd@eth0.service' from > + # 'ifplugd@.service' > + base = None > + at = service.find('@') > + if at != -1: > + ext = service.rfind('.') > + base = service[:at] + '@' + service[ext:] > + > + for path in searchpaths: > + if os.path.lexists(oe.path.join(d.getVar("D"), path, service)): > + path_found = path > + break > + elif base is not None: > + if os.path.exists(oe.path.join(d.getVar("D"), path, base)): > + path_found = path > + break > + > + return path_found, base > + > +def systemd_service_exists(service, user, d): > + searchpaths = [ > + oe.path.join(d.getVar("sysconfdir"), "systemd", "user"), > + d.getVar("systemd_user_unitdir"), > + ] if user else [ > + oe.path.join(d.getVar("sysconfdir"), "systemd", "system"), > + d.getVar("systemd_system_unitdir"), > + ] > + > + path, _ = systemd_service_path(service, searchpaths, d) > + > + return path != '' > + > +def systemd_filter_services(services, user, d): > + return ' '.join(service for service in services.split() if systemd_service_exists(service, user, d)) > + > > python systemd_populate_packages() { > import re > @@ -147,7 +202,10 @@ python systemd_populate_packages() { > > # Check service-files and call systemd_add_files_and_parse for each entry > def systemd_check_services(): > - searchpaths = [oe.path.join(d.getVar("sysconfdir"), "systemd", "system"),] > + searchpaths = [ > + oe.path.join(d.getVar("sysconfdir"), "systemd", "system"), > + oe.path.join(d.getVar("sysconfdir"), "systemd", "user"), > + ] > searchpaths.append(d.getVar("systemd_system_unitdir")) > searchpaths.append(d.getVar("systemd_user_unitdir")) > systemd_packages = d.getVar('SYSTEMD_PACKAGES') > @@ -155,24 +213,7 @@ python systemd_populate_packages() { > # scan for all in SYSTEMD_SERVICE[] > for pkg_systemd in systemd_packages.split(): > for service in get_package_var(d, 'SYSTEMD_SERVICE', pkg_systemd).split(): > - path_found = '' > - > - # Deal with adding, for example, 'ifplugd@eth0.service' from > - # 'ifplugd@.service' > - base = None > - at = service.find('@') > - if at != -1: > - ext = service.rfind('.') > - base = service[:at] + '@' + service[ext:] > - > - for path in searchpaths: > - if os.path.lexists(oe.path.join(d.getVar("D"), path, service)): > - path_found = path > - break > - elif base is not None: > - if os.path.exists(oe.path.join(d.getVar("D"), path, base)): > - path_found = path > - break > + path_found, base = systemd_service_path(service, searchpaths, d) > > if path_found != '': > systemd_add_files_and_parse(pkg_systemd, path_found, service) > @@ -180,13 +221,38 @@ python systemd_populate_packages() { > bb.fatal("Didn't find service unit '{0}', specified in SYSTEMD_SERVICE:{1}. {2}".format( > service, pkg_systemd, "Also looked for service unit '{0}'.".format(base) if base is not None else "")) > > - def systemd_create_presets(pkg, action): > - presetf = oe.path.join(d.getVar("PKGD"), d.getVar("systemd_unitdir"), "system-preset/98-%s.preset" % pkg) > + def _systemd_create_presets(pkg, action, prefix, searchpaths): > + # Check there is at least one service of given type (system/user), don't > + # create empty files. > + needs_preset = False > + for service in d.getVar('SYSTEMD_SERVICE:%s' % pkg).split(): > + path_found, _ = systemd_service_path(service, searchpaths, d) > + if path_found != '': > + needs_preset = True > + break > + > + if not needs_preset: > + return > + > + presetf = oe.path.join(d.getVar("PKGD"), d.getVar("systemd_unitdir"), "%s-preset/98-%s.preset" % (prefix, pkg)) > bb.utils.mkdirhier(os.path.dirname(presetf)) > with open(presetf, 'a') as fd: > for service in d.getVar('SYSTEMD_SERVICE:%s' % pkg).split(): > + path_found, _ = systemd_service_path(service, searchpaths, d) > + if path_found == '': > + continue > fd.write("%s %s\n" % (action,service)) > - d.appendVar("FILES:%s" % pkg, ' ' + oe.path.join(d.getVar("systemd_unitdir"), "system-preset/98-%s.preset" % pkg)) > + d.appendVar("FILES:%s" % pkg, ' ' + oe.path.join(d.getVar("systemd_unitdir"), "%s-preset/98-%s.preset" % (prefix, pkg))) > + > + def systemd_create_presets(pkg, action): > + _systemd_create_presets(pkg, action, "system", [ > + oe.path.join(d.getVar("sysconfdir"), "systemd", "system"), > + d.getVar("systemd_system_unitdir"), > + ]) > + _systemd_create_presets(pkg, action, "user", [ > + oe.path.join(d.getVar("sysconfdir"), "systemd", "user"), > + d.getVar("systemd_user_unitdir"), > + ]) > > # Run all modifications once when creating package > if os.path.exists(d.getVar("D")): > -- > 2.47.0 > > > -=-=-=-=-=-=-=-=-=-=-=- > Links: You receive all messages sent to this group. > View/Reply Online (#209687): https://lists.openembedded.org/g/openembedded-core/message/209687 > Mute This Topic: https://lists.openembedded.org/mt/110569455/1686489 > Group Owner: openembedded-core+owner@lists.openembedded.org > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [alex.kanavin@gmail.com] > -=-=-=-=-=-=-=-=-=-=-=- >
diff --git a/meta/classes-recipe/systemd.bbclass b/meta/classes-recipe/systemd.bbclass index 4b4470b7b3..80f4da3bdf 100644 --- a/meta/classes-recipe/systemd.bbclass +++ b/meta/classes-recipe/systemd.bbclass @@ -37,17 +37,29 @@ if systemctl >/dev/null 2>/dev/null; then fi if [ "${SYSTEMD_AUTO_ENABLE}" = "enable" ]; then - for service in ${SYSTEMD_SERVICE_ESCAPED}; do + for service in ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)}; do systemctl ${OPTS} enable "$service" done + + for service in ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)}; do + systemctl --global ${OPTS} enable "$service" + done fi if [ -z "$D" ]; then + # Reload only system service manager + # --global for daemon-reload is not supported: https://github.com/systemd/systemd/issues/19284 systemctl daemon-reload - systemctl preset ${SYSTEMD_SERVICE_ESCAPED} + [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)}" ] && \ + systemctl preset ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)} + + [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)}" ] && \ + systemctl --global preset ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)} if [ "${SYSTEMD_AUTO_ENABLE}" = "enable" ]; then - systemctl --no-block restart ${SYSTEMD_SERVICE_ESCAPED} + # --global flag for restart is not supported by systemd (see above) + [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)}" ] && \ + systemctl --no-block restart ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)} fi fi fi @@ -56,9 +68,14 @@ fi systemd_prerm() { if systemctl >/dev/null 2>/dev/null; then if [ -z "$D" ]; then - systemctl stop ${SYSTEMD_SERVICE_ESCAPED} + # same as above, --global flag is not supported for stop + if [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)}" ]; then + systemctl stop ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)} + systemctl disable ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", False, d)} + fi - systemctl disable ${SYSTEMD_SERVICE_ESCAPED} + [ -n "${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)}" ] && \ + systemctl --global disable ${@systemd_filter_services("${SYSTEMD_SERVICE_ESCAPED}", True, d)} fi fi } @@ -67,6 +84,44 @@ fi systemd_populate_packages[vardeps] += "systemd_prerm systemd_postinst" systemd_populate_packages[vardepsexclude] += "OVERRIDES" +def systemd_service_path(service, searchpaths, d): + path_found = '' + + # Deal with adding, for example, 'ifplugd@eth0.service' from + # 'ifplugd@.service' + base = None + at = service.find('@') + if at != -1: + ext = service.rfind('.') + base = service[:at] + '@' + service[ext:] + + for path in searchpaths: + if os.path.lexists(oe.path.join(d.getVar("D"), path, service)): + path_found = path + break + elif base is not None: + if os.path.exists(oe.path.join(d.getVar("D"), path, base)): + path_found = path + break + + return path_found, base + +def systemd_service_exists(service, user, d): + searchpaths = [ + oe.path.join(d.getVar("sysconfdir"), "systemd", "user"), + d.getVar("systemd_user_unitdir"), + ] if user else [ + oe.path.join(d.getVar("sysconfdir"), "systemd", "system"), + d.getVar("systemd_system_unitdir"), + ] + + path, _ = systemd_service_path(service, searchpaths, d) + + return path != '' + +def systemd_filter_services(services, user, d): + return ' '.join(service for service in services.split() if systemd_service_exists(service, user, d)) + python systemd_populate_packages() { import re @@ -147,7 +202,10 @@ python systemd_populate_packages() { # Check service-files and call systemd_add_files_and_parse for each entry def systemd_check_services(): - searchpaths = [oe.path.join(d.getVar("sysconfdir"), "systemd", "system"),] + searchpaths = [ + oe.path.join(d.getVar("sysconfdir"), "systemd", "system"), + oe.path.join(d.getVar("sysconfdir"), "systemd", "user"), + ] searchpaths.append(d.getVar("systemd_system_unitdir")) searchpaths.append(d.getVar("systemd_user_unitdir")) systemd_packages = d.getVar('SYSTEMD_PACKAGES') @@ -155,24 +213,7 @@ python systemd_populate_packages() { # scan for all in SYSTEMD_SERVICE[] for pkg_systemd in systemd_packages.split(): for service in get_package_var(d, 'SYSTEMD_SERVICE', pkg_systemd).split(): - path_found = '' - - # Deal with adding, for example, 'ifplugd@eth0.service' from - # 'ifplugd@.service' - base = None - at = service.find('@') - if at != -1: - ext = service.rfind('.') - base = service[:at] + '@' + service[ext:] - - for path in searchpaths: - if os.path.lexists(oe.path.join(d.getVar("D"), path, service)): - path_found = path - break - elif base is not None: - if os.path.exists(oe.path.join(d.getVar("D"), path, base)): - path_found = path - break + path_found, base = systemd_service_path(service, searchpaths, d) if path_found != '': systemd_add_files_and_parse(pkg_systemd, path_found, service) @@ -180,13 +221,38 @@ python systemd_populate_packages() { bb.fatal("Didn't find service unit '{0}', specified in SYSTEMD_SERVICE:{1}. {2}".format( service, pkg_systemd, "Also looked for service unit '{0}'.".format(base) if base is not None else "")) - def systemd_create_presets(pkg, action): - presetf = oe.path.join(d.getVar("PKGD"), d.getVar("systemd_unitdir"), "system-preset/98-%s.preset" % pkg) + def _systemd_create_presets(pkg, action, prefix, searchpaths): + # Check there is at least one service of given type (system/user), don't + # create empty files. + needs_preset = False + for service in d.getVar('SYSTEMD_SERVICE:%s' % pkg).split(): + path_found, _ = systemd_service_path(service, searchpaths, d) + if path_found != '': + needs_preset = True + break + + if not needs_preset: + return + + presetf = oe.path.join(d.getVar("PKGD"), d.getVar("systemd_unitdir"), "%s-preset/98-%s.preset" % (prefix, pkg)) bb.utils.mkdirhier(os.path.dirname(presetf)) with open(presetf, 'a') as fd: for service in d.getVar('SYSTEMD_SERVICE:%s' % pkg).split(): + path_found, _ = systemd_service_path(service, searchpaths, d) + if path_found == '': + continue fd.write("%s %s\n" % (action,service)) - d.appendVar("FILES:%s" % pkg, ' ' + oe.path.join(d.getVar("systemd_unitdir"), "system-preset/98-%s.preset" % pkg)) + d.appendVar("FILES:%s" % pkg, ' ' + oe.path.join(d.getVar("systemd_unitdir"), "%s-preset/98-%s.preset" % (prefix, pkg))) + + def systemd_create_presets(pkg, action): + _systemd_create_presets(pkg, action, "system", [ + oe.path.join(d.getVar("sysconfdir"), "systemd", "system"), + d.getVar("systemd_system_unitdir"), + ]) + _systemd_create_presets(pkg, action, "user", [ + oe.path.join(d.getVar("sysconfdir"), "systemd", "user"), + d.getVar("systemd_user_unitdir"), + ]) # Run all modifications once when creating package if os.path.exists(d.getVar("D")):
Previously user units were causing build erros when listed in SYSTEMD_SERVICE and SYSTEMD_AUTO_ENABLE was set. Signed-off-by: Artur Kowalski <arturkow2000@gmail.com> --- meta/classes-recipe/systemd.bbclass | 120 +++++++++++++++++++++------- 1 file changed, 93 insertions(+), 27 deletions(-)