1# The list of packages that should have systemd packaging scripts added. For 2# each entry, optionally have a SYSTEMD_SERVICE:[package] that lists the service 3# files in this package. If this variable isn't set, [package].service is used. 4SYSTEMD_PACKAGES ?= "${PN}" 5SYSTEMD_PACKAGES:class-native ?= "" 6SYSTEMD_PACKAGES:class-nativesdk ?= "" 7 8# Whether to enable or disable the services on installation. 9SYSTEMD_AUTO_ENABLE ??= "enable" 10 11# This class will be included in any recipe that supports systemd init scripts, 12# even if systemd is not in DISTRO_FEATURES. As such don't make any changes 13# directly but check the DISTRO_FEATURES first. 14python __anonymous() { 15 # If the distro features have systemd but not sysvinit, inhibit update-rcd 16 # from doing any work so that pure-systemd images don't have redundant init 17 # files. 18 if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d): 19 d.appendVar("DEPENDS", " systemd-systemctl-native") 20 d.appendVar("PACKAGE_WRITE_DEPS", " systemd-systemctl-native") 21 if not bb.utils.contains('DISTRO_FEATURES', 'sysvinit', True, False, d): 22 d.setVar("INHIBIT_UPDATERCD_BBCLASS", "1") 23} 24 25systemd_postinst() { 26if systemctl >/dev/null 2>/dev/null; then 27 OPTS="" 28 29 if [ -n "$D" ]; then 30 OPTS="--root=$D" 31 fi 32 33 if [ "${SYSTEMD_AUTO_ENABLE}" = "enable" ]; then 34 for service in ${SYSTEMD_SERVICE_ESCAPED}; do 35 systemctl ${OPTS} enable "$service" 36 done 37 fi 38 39 if [ -z "$D" ]; then 40 systemctl daemon-reload 41 systemctl preset ${SYSTEMD_SERVICE_ESCAPED} 42 43 if [ "${SYSTEMD_AUTO_ENABLE}" = "enable" ]; then 44 systemctl --no-block restart ${SYSTEMD_SERVICE_ESCAPED} 45 fi 46 fi 47fi 48} 49 50systemd_prerm() { 51if systemctl >/dev/null 2>/dev/null; then 52 if [ -z "$D" ]; then 53 systemctl stop ${SYSTEMD_SERVICE_ESCAPED} 54 55 systemctl disable ${SYSTEMD_SERVICE_ESCAPED} 56 fi 57fi 58} 59 60 61systemd_populate_packages[vardeps] += "systemd_prerm systemd_postinst" 62systemd_populate_packages[vardepsexclude] += "OVERRIDES" 63 64 65python systemd_populate_packages() { 66 import re 67 import shlex 68 69 if not bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d): 70 return 71 72 def get_package_var(d, var, pkg): 73 val = (d.getVar('%s:%s' % (var, pkg)) or "").strip() 74 if val == "": 75 val = (d.getVar(var) or "").strip() 76 return val 77 78 # Check if systemd-packages already included in PACKAGES 79 def systemd_check_package(pkg_systemd): 80 packages = d.getVar('PACKAGES') 81 if not pkg_systemd in packages.split(): 82 bb.error('%s does not appear in package list, please add it' % pkg_systemd) 83 84 85 def systemd_generate_package_scripts(pkg): 86 bb.debug(1, 'adding systemd calls to postinst/postrm for %s' % pkg) 87 88 paths_escaped = ' '.join(shlex.quote(s) for s in d.getVar('SYSTEMD_SERVICE:' + pkg).split()) 89 d.setVar('SYSTEMD_SERVICE_ESCAPED:' + pkg, paths_escaped) 90 91 # Add pkg to the overrides so that it finds the SYSTEMD_SERVICE:pkg 92 # variable. 93 localdata = d.createCopy() 94 localdata.prependVar("OVERRIDES", pkg + ":") 95 96 postinst = d.getVar('pkg_postinst:%s' % pkg) 97 if not postinst: 98 postinst = '#!/bin/sh\n' 99 postinst += localdata.getVar('systemd_postinst') 100 d.setVar('pkg_postinst:%s' % pkg, postinst) 101 102 prerm = d.getVar('pkg_prerm:%s' % pkg) 103 if not prerm: 104 prerm = '#!/bin/sh\n' 105 prerm += localdata.getVar('systemd_prerm') 106 d.setVar('pkg_prerm:%s' % pkg, prerm) 107 108 109 # Add files to FILES:*-systemd if existent and not already done 110 def systemd_append_file(pkg_systemd, file_append): 111 appended = False 112 if os.path.exists(oe.path.join(d.getVar("D"), file_append)): 113 var_name = "FILES:" + pkg_systemd 114 files = d.getVar(var_name, False) or "" 115 if file_append not in files.split(): 116 d.appendVar(var_name, " " + file_append) 117 appended = True 118 return appended 119 120 # Add systemd files to FILES:*-systemd, parse for Also= and follow recursive 121 def systemd_add_files_and_parse(pkg_systemd, path, service, keys): 122 # avoid infinite recursion 123 if systemd_append_file(pkg_systemd, oe.path.join(path, service)): 124 fullpath = oe.path.join(d.getVar("D"), path, service) 125 if service.find('.service') != -1: 126 # for *.service add *@.service 127 service_base = service.replace('.service', '') 128 systemd_add_files_and_parse(pkg_systemd, path, service_base + '@.service', keys) 129 if service.find('.socket') != -1: 130 # for *.socket add *.service and *@.service 131 service_base = service.replace('.socket', '') 132 systemd_add_files_and_parse(pkg_systemd, path, service_base + '.service', keys) 133 systemd_add_files_and_parse(pkg_systemd, path, service_base + '@.service', keys) 134 for key in keys.split(): 135 # recurse all dependencies found in keys ('Also';'Conflicts';..) and add to files 136 cmd = "grep %s %s | sed 's,%s=,,g' | tr ',' '\\n'" % (key, shlex.quote(fullpath), key) 137 pipe = os.popen(cmd, 'r') 138 line = pipe.readline() 139 while line: 140 line = line.replace('\n', '') 141 systemd_add_files_and_parse(pkg_systemd, path, line, keys) 142 line = pipe.readline() 143 pipe.close() 144 145 # Check service-files and call systemd_add_files_and_parse for each entry 146 def systemd_check_services(): 147 searchpaths = [oe.path.join(d.getVar("sysconfdir"), "systemd", "system"),] 148 searchpaths.append(d.getVar("systemd_system_unitdir")) 149 searchpaths.append(d.getVar("systemd_user_unitdir")) 150 systemd_packages = d.getVar('SYSTEMD_PACKAGES') 151 152 keys = 'Also' 153 # scan for all in SYSTEMD_SERVICE[] 154 for pkg_systemd in systemd_packages.split(): 155 for service in get_package_var(d, 'SYSTEMD_SERVICE', pkg_systemd).split(): 156 path_found = '' 157 158 # Deal with adding, for example, 'ifplugd@eth0.service' from 159 # 'ifplugd@.service' 160 base = None 161 at = service.find('@') 162 if at != -1: 163 ext = service.rfind('.') 164 base = service[:at] + '@' + service[ext:] 165 166 for path in searchpaths: 167 if os.path.exists(oe.path.join(d.getVar("D"), path, service)): 168 path_found = path 169 break 170 elif base is not None: 171 if os.path.exists(oe.path.join(d.getVar("D"), path, base)): 172 path_found = path 173 break 174 175 if path_found != '': 176 systemd_add_files_and_parse(pkg_systemd, path_found, service, keys) 177 else: 178 bb.fatal("Didn't find service unit '{0}', specified in SYSTEMD_SERVICE:{1}. {2}".format( 179 service, pkg_systemd, "Also looked for service unit '{0}'.".format(base) if base is not None else "")) 180 181 def systemd_create_presets(pkg, action): 182 presetf = oe.path.join(d.getVar("PKGD"), d.getVar("systemd_unitdir"), "system-preset/98-%s.preset" % pkg) 183 bb.utils.mkdirhier(os.path.dirname(presetf)) 184 with open(presetf, 'a') as fd: 185 for service in d.getVar('SYSTEMD_SERVICE:%s' % pkg).split(): 186 fd.write("%s %s\n" % (action,service)) 187 d.appendVar("FILES:%s" % pkg, ' ' + oe.path.join(d.getVar("systemd_unitdir"), "system-preset/98-%s.preset" % pkg)) 188 189 # Run all modifications once when creating package 190 if os.path.exists(d.getVar("D")): 191 for pkg in d.getVar('SYSTEMD_PACKAGES').split(): 192 systemd_check_package(pkg) 193 if d.getVar('SYSTEMD_SERVICE:' + pkg): 194 systemd_generate_package_scripts(pkg) 195 action = get_package_var(d, 'SYSTEMD_AUTO_ENABLE', pkg) 196 if action in ("enable", "disable"): 197 systemd_create_presets(pkg, action) 198 elif action not in ("mask", "preset"): 199 bb.fatal("SYSTEMD_AUTO_ENABLE:%s '%s' is not 'enable', 'disable', 'mask' or 'preset'" % (pkg, action)) 200 systemd_check_services() 201} 202 203PACKAGESPLITFUNCS:prepend = "systemd_populate_packages " 204 205python rm_systemd_unitdir (){ 206 import shutil 207 if not bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d): 208 systemd_unitdir = oe.path.join(d.getVar("D"), d.getVar('systemd_unitdir')) 209 if os.path.exists(systemd_unitdir): 210 shutil.rmtree(systemd_unitdir) 211 systemd_libdir = os.path.dirname(systemd_unitdir) 212 if (os.path.exists(systemd_libdir) and not os.listdir(systemd_libdir)): 213 os.rmdir(systemd_libdir) 214} 215 216python rm_sysvinit_initddir (){ 217 import shutil 218 sysv_initddir = oe.path.join(d.getVar("D"), (d.getVar('INIT_D_DIR') or "/etc/init.d")) 219 220 if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d) and \ 221 not bb.utils.contains('DISTRO_FEATURES', 'sysvinit', True, False, d) and \ 222 os.path.exists(sysv_initddir): 223 systemd_system_unitdir = oe.path.join(d.getVar("D"), d.getVar('systemd_system_unitdir')) 224 225 # If systemd_system_unitdir contains anything, delete sysv_initddir 226 if (os.path.exists(systemd_system_unitdir) and os.listdir(systemd_system_unitdir)): 227 shutil.rmtree(sysv_initddir) 228} 229 230do_install[postfuncs] += "${RMINITDIR} " 231RMINITDIR:class-target = " rm_sysvinit_initddir rm_systemd_unitdir " 232RMINITDIR:class-nativesdk = " rm_sysvinit_initddir rm_systemd_unitdir " 233RMINITDIR = "" 234 235