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