Patchwork [meta-oe,RFC,01/27] systemd.bbclass: rework

login
register
mail settings
Submitter Andreas Müller
Date Feb. 7, 2012, 3:12 p.m.
Message ID <1328627573-5217-2-git-send-email-schnitzeltony@googlemail.com>
Download mbox | patch
Permalink /patch/20827/
State Rejected
Headers show

Comments

Andreas Müller - Feb. 7, 2012, 3:12 p.m.
let systemd.bbclass do more for us and prepare support images without systemd

* introduce a global variable INIT_MANAGER. For images using systemd, this must
  contain 'systemd'. This varibale can e.g be set to default in local.conf and
  then overridden by distro.
* handle multiple entries in SYSTEMD_SERVICE. Currenly there are no use cases
  but networkmanager has potential requirements
* handle multiple entries in SYSTEMD_PACKAGES. Possible use cases are
  dhcp/dhcp-relay and ntp/ntpdate
* enhance the checks for SYSTEMD_PACKAGES and SYSTEMD_SERVICE. For package
  names only <name-of-an-existing-package>-systemd or ${PN} are allowed. In
  case of using ${PN} a warning is spitted. This was introduced to force recipe
  maintainers to separate out systemd to own package.
* all systemd packages are automatically created based on SYSTEMD_PACKAGES
* for systemd packets and their base packages RDEPENDS/RRECOMMENDS are
  automatically extended. Hereby it is ensured that all packets for proper
  systemd operation find their way into the image. Nice side effect:
  if in all tasks/images the base packets are include insted of *-systemd it is
  only a matter of INIT_MANAGER if systemd-packets are imaged.
* all *.socket and *.service files included by SRC_URI are automatically
  installed from WORKDIR.
* remove systemd from DEPENDS. Recipes requiring systemd at buildtime, should
  take care themselves.
Signed-off-by: Andreas Müller <schnitzeltony@googlemail.com>
---
 meta-oe/classes/systemd.bbclass |  173 +++++++++++++++++++++++++++++++++-----
 1 files changed, 150 insertions(+), 23 deletions(-)
Andreas Müller - Feb. 9, 2012, 8:14 a.m.
On Tue, Feb 7, 2012 at 4:12 PM, Andreas Müller
<schnitzeltony@googlemail.com> wrote:
Apart from the NAKed distro setting and automatic DEPENDS - are there
comments on the other:

let systemd.bbclass do more for us
>
> * handle multiple entries in SYSTEMD_SERVICE. Currenly there are no use cases
>  but networkmanager has potential requirements
> * handle multiple entries in SYSTEMD_PACKAGES. Possible use cases are
>  dhcp/dhcp-relay and ntp/ntpdate
> * enhance the checks for SYSTEMD_PACKAGES and SYSTEMD_SERVICE. For package
>  names only <name-of-an-existing-package>-systemd or ${PN} are allowed. In
>  case of using ${PN} a warning is spitted. This was introduced to force recipe
>  maintainers to separate out systemd to own package.
> * all systemd packages are automatically created based on SYSTEMD_PACKAGES
* for systemd packets  automatically add RDEPENDS to base packages
> * all *.socket and *.service files included by SRC_URI are automatically
>  installed from WORKDIR.
would it make sense to split this up and resend?

Andreas
Otavio Salvador - Feb. 9, 2012, 11:03 a.m.
On Thu, Feb 9, 2012 at 06:14, Andreas Müller
<schnitzeltony@googlemail.com>wrote:

> would it make sense to split this up and resend?


I'd love if you could split the changes so we can get those merged one by
one.

Specially about the multiple service support, the right place to fix it is
in the systemd-systemctl-native script adding support for it to deal with
one more service at time, as is supported by the real tool.

Patch

diff --git a/meta-oe/classes/systemd.bbclass b/meta-oe/classes/systemd.bbclass
index 094a12c..c843e66 100644
--- a/meta-oe/classes/systemd.bbclass
+++ b/meta-oe/classes/systemd.bbclass
@@ -1,5 +1,6 @@ 
-DEPENDS_append = " systemd systemd-systemctl-native"
+DEPENDS_append = " systemd-systemctl-native"
 
+# pre/post-inst/rm for each entry in SYSTEMD_SERVICE
 systemd_postinst() {
 OPTS=""
 
@@ -7,34 +8,95 @@  if [ -n "$D" ]; then
     OPTS="--root=$D"
 fi
 
-systemctl $OPTS enable ${SYSTEMD_SERVICE}
+for service in ${SYSTEMD_SERVICE} ; do
+    systemctl $OPTS enable $service
+done
 
 if [ -z "$D" ]; then
-    systemctl start ${SYSTEMD_SERVICE}
+    for service in ${SYSTEMD_SERVICE} ; do
+        systemctl start $service
+    done
 fi
 }
 
 systemd_prerm() {
 if [ -z "$D" ]; then
-    systemctl stop ${SYSTEMD_SERVICE}
+    for service in ${SYSTEMD_SERVICE} ; do
+        systemctl stop $service
+    done
 fi
 }
 
 systemd_postrm() {
-systemctl disable ${SYSTEMD_SERVICE}
+for service in ${SYSTEMD_SERVICE} ; do
+    systemctl disable $service
+done
 }
 
 def systemd_after_parse(d):
-    if bb.data.getVar('SYSTEMD_PACKAGES', d) == None:
-        if bb.data.getVar('SYSTEMD_SERVICE', d) == None:
-            raise bb.build.FuncFailed, "%s inherits systemd but doesn't set SYSTEMD_SERVICE" % bb.data.getVar('FILE', d)
+	def systemd_check_vars():
+		# not for native / only at parse time
+		if d.getVar('BPN', 1) + "-native" != d.getVar('PN', 1) and d.getVar('BB_WORKERCONTEXT', True) is None:
+			bb_filename = d.getVar('FILE')
+			packages = d.getVar('PACKAGES', 1)
+
+			# check SYSTEMD_PACKAGES
+			systemd_pkgs = d.getVar('SYSTEMD_PACKAGES', 1) or ""
+			if systemd_pkgs == "":
+				raise bb.build.FuncFailed, "\n\n%s inherits systemd but doesn't set SYSTEMD_PACKAGES" % bb_filename
+			for pkg_systemd in systemd_pkgs.split():
+				if pkg_systemd.find("-systemd") == -1:
+					if pkg_systemd != d.getVar('PN', 1):
+						raise (bb.build.FuncFailed,
+							"\n\n%s: %s in SYSTEMD_PACKAGES does not match <base-package-using-systemd>-systemd or ${PN} (deprecated)" %
+							(bb_filename, pkg_systemd))
+					else:
+						bb.warn("%s: it is recommended to set SYSTEMD_PACKAGES as <base-package-using-systemd>-systemd" % bb_filename)
+				else:
+					pkg_systemd_base = pkg_systemd.replace('-systemd', '')
+					if pkg_systemd_base not in packages:
+						raise (bb.build.FuncFailed,
+							"\n\n%s: %s in SYSTEMD_PACKAGES does not match <base-package-using-systemd>-systemd or ${PN} (deprecated)" %
+							( bb_filename, pkg_systemd))
+
+			# check SYSTEMD_SERVICE
+			for pkg_systemd in systemd_pkgs.split():
+				service_pkg = 'SYSTEMD_SERVICE' + "_" + pkg_systemd
+				systemd_services = d.getVar(service_pkg, 1) or d.getVar('SYSTEMD_SERVICE', 1) or ""
+				if systemd_services == "":
+					raise bb.build.FuncFailed, "\n\n%s inherits systemd but doesn't set SYSTEMD_SERVICE / %s" % (bb_filename, service_pkg)
+
+	# prepend packages not already included
+	def systemd_create_package(pkg_systemd):
+		packages = d.getVar('PACKAGES', 1)
+		if not pkg_systemd in packages:
+			packages = "%s %s" % (pkg_systemd, packages)
+			d.setVar('PACKAGES', packages)
+
+
+	systemd_check_vars()
+	systemd_pkgs = d.getVar('SYSTEMD_PACKAGES', 1)
+	for pkg_systemd in systemd_pkgs.split():
+		systemd_create_package(pkg_systemd)
+
 
 python __anonymous() {
-    systemd_after_parse(d)
+	systemd_after_parse(d)
+}
+
+# automatically install all *.service and *.socket supplied in SRC_URI
+do_install_append() {
+    install -d ${D}${base_libdir}/systemd/system
+    for service in `find ${WORKDIR} -maxdepth 1 -name '*.service' -o -name '*.socket'` ; do
+	# ensure installing systemd-files only (e.g not avahi *.service)
+	if grep -q '\[Unit\]' $service ; then
+	        install -m 644 $service ${D}${base_libdir}/systemd/system
+	fi
+    done
 }
 
 python populate_packages_prepend () {
-	def systemd_package(pkg):
+	def systemd_prepost_instrm(pkg):
 		bb.debug(1, 'adding systemd calls to postinst/postrm for %s' % pkg)
 		localdata = bb.data.createCopy(d)
 		overrides = bb.data.getVar("OVERRIDES", localdata, 1)
@@ -45,7 +107,7 @@  python populate_packages_prepend () {
 		systemd postinst is appended here because pkg_postinst may require to
 		execute on the target. Not doing so may cause systemd postinst invoked
 		twice to cause unwanted warnings.
-		""" 
+		"""
 		postinst = bb.data.getVar('pkg_postinst', localdata, 1)
 		if not postinst:
 			postinst = '#!/bin/sh\n'
@@ -58,23 +120,88 @@  python populate_packages_prepend () {
 		prerm += bb.data.getVar('systemd_prerm', localdata, 1)
 		bb.data.setVar('pkg_prerm_%s' % pkg, prerm, d)
 
-	        postrm = bb.data.getVar('pkg_postrm', localdata, 1)
-	        if not postrm:
-	                postrm = '#!/bin/sh\n'
-                postrm += bb.data.getVar('systemd_postrm', localdata, 1)
+		postrm = bb.data.getVar('pkg_postrm', localdata, 1)
+		if not postrm:
+			postrm = '#!/bin/sh\n'
+		postrm += bb.data.getVar('systemd_postrm', localdata, 1)
 		bb.data.setVar('pkg_postrm_%s' % pkg, postrm, d)
 
 		rdepends = explode_deps(bb.data.getVar('RDEPENDS_' + pkg, d, 0) or bb.data.getVar('RDEPENDS', d, 0) or "")
 		rdepends.append("systemd")
 		bb.data.setVar('RDEPENDS_' + pkg, " " + " ".join(rdepends), d)
 
+	"""	Setup rdepends / rrecommmends as:
+
+                  -----------------------------
+                  |  pkg_systemd_base:	'foo' |
+                  -----------------------------
+                             |    ^
+                             |    |                 --------------
+                 rrecommends |    | rdepends        | 'systemd'  |
+                             |    |               ->--------------
+                             V    |              / rdepends
+                  ------------------------------/
+                  | pkg_systemd: 'foo-systemd' |
+                  ------------------------------
+	"""
+	def systemd_rdepend_rrecommends(pkg_systemd):
+		pn_pkg = d.getVar('PN', 1)
+		# RDEPENDS_${pkg_systemd} += pkg_systemd_base systemd
+		rdepends = explode_deps(d.getVar('RDEPENDS_' + pkg_systemd, 1) or "")
+		if not 'systemd' in rdepends:
+			rdepends.append('systemd')
+		pkg_systemd_base = pkg_systemd.replace('-systemd', '')
+		# not rdepending myself / avoid double entries
+		if pkg_systemd != pn_pkg and not pkg_systemd_base in rdepends:
+			rdepends.append(pkg_systemd_base)
+		d.setVar('RDEPENDS_' + pkg_systemd, " " + " ".join(rdepends))
+		# default: just a suggestion - to be discussed?
+		initmanager = d.getVar('INIT_MANAGER', 1) or 'systemd'
+		# RRECOMMENDS_${pkg_systemd_base} += pkg_systemd systemd
+		if initmanager == 'systemd':
+			rrecommends = explode_deps(d.getVar('RRECOMMENDS_' + pkg_systemd_base, 1) or "")
+			# not rrecommending myself / avoid double entries
+			if pkg_systemd != pn_pkg and not pkg_systemd in rrecommends:
+				rrecommends.append(pkg_systemd)
+				d.setVar('RRECOMMENDS_' + pkg_systemd_base, " " + " ".join(rrecommends))
+
+	# append systemd files to FILES_*-systemd
+	def systemd_files(pkg_systemd):
+		systemd_services = d.getVar('SYSTEMD_SERVICE' + "_" + pkg_systemd, 1) or d.getVar('SYSTEMD_SERVICE', 1)
+		files_append = ""
+		if len(systemd_pkgs.split()) == 1:
+			# distribute complete ${base_libdir}/systemd/system/ to ${SYSTEMD_PACKAGES}
+			files_append = '${base_libdir}/systemd/system/'
+		else:
+			# distribute files set in SYSTEMD_SERVICE to ${SYSTEMD_PACKAGES}
+			for service in systemd_services.split():
+				files_append += " ${base_libdir}/systemd/system/" + service
+
+		var_name = "FILES_" + pkg_systemd
+		files = d.getVar(var_name, 0) or ""
+		d.setVar(var_name, "%s %s" % (files, files_append))
+
+
+	systemd_pkgs = d.getVar('SYSTEMD_PACKAGES', 1)
+	for pkg_systemd in systemd_pkgs.split():
+		systemd_prepost_instrm(pkg_systemd)
+		systemd_rdepend_rrecommends(pkg_systemd)
+		systemd_files(pkg_systemd)
 
-	pkgs = bb.data.getVar('SYSTEMD_PACKAGES', d, 1)
-	if pkgs == None:
-		pkgs = bb.data.getVar('PN', d, 1)
-		packages = (bb.data.getVar('PACKAGES', d, 1) or "").split()
-		if not pkgs in packages and packages != []:
-			pkgs = packages[0]
-	for pkg in pkgs.split():
-		systemd_package(pkg)
+	# temporary debug output found in do_package.log
+	pn_pkg = d.getVar('PN', 1)
+	print 'base-package info:'
+	print 'DEPENDS: %s' % d.getVar('DEPENDS', 1)
+	print 'PACKAGES: %s' % d.getVar('PACKAGES', 1)
+	print 'RDEPENDS_%s: %s' % (pn_pkg, d.getVar('RDEPENDS_' + pn_pkg, 1))
+	print 'RRECOMMENDS_%s: %s' % (pn_pkg, d.getVar('RRECOMMENDS_' + pn_pkg, 1))
+	print 'systemd-(base-)-packages info:'
+	for pkg_systemd in systemd_pkgs.split():
+		pkg_systemd_base = pkg_systemd.replace('-systemd', '')
+		print 'RDEPENDS_%s: %s' % (pkg_systemd_base, d.getVar('RDEPENDS_' + pkg_systemd_base, 1))
+		print 'RDEPENDS_%s: %s' % (pkg_systemd, d.getVar('RDEPENDS_' + pkg_systemd, 1))
+		print 'RRECOMMENDS_%s: %s' % (pkg_systemd_base, d.getVar('RRECOMMENDS_' + pkg_systemd_base, 1))
+		print 'RRECOMMENDS_%s: %s' % (pkg_systemd, d.getVar('RRECOMMENDS_' + pkg_systemd, 1))
+		print 'FILES_%s: %s' % (pkg_systemd_base, d.getVar('FILES_' + pkg_systemd_base, 1))
+		print 'FILES_%s: %s' % (pkg_systemd, d.getVar('FILES_' + pkg_systemd, 1))
 }