[OE-core] [PATCH 22/36] package.bbclass: add support for pkg_postinst_ontarget()

Alexander Kanavin alexander.kanavin at linux.intel.com
Mon Feb 13 15:05:52 UTC 2017


All commands that cannot be executed during cross-install and can only be run on target
should go into this function. They will only be executed on first boot (if package was
cross-installed) or immediately during package installation on target.

The previous approach was to check if we are cross-installing before executing these commands,
and if so, exit the script with an error. This was not optimal for two reasons:

1) Code is hard to read; it is not obvious that 'exit 1' means 'defer what follows to first boot'.
2) Worse, this hides actual errors in the scriptlets; there is no difference between scriptlet
failing because it's intended to be run on target and scriptlet failing because there's a bug or
a regression somewhere.

Plain pkg_postinst() works as before: it is run during cross-install, if it fails, it's deferred to first boot
(but from now on, the deferral produces a deprecation warning).

Signed-off-by: Alexander Kanavin <alexander.kanavin at linux.intel.com>
---
 .../recipes-test/postinst/postinst_1.0.bb          | 99 ++++++++--------------
 meta/classes/package.bbclass                       | 20 +++++
 meta/lib/oe/rootfs.py                              | 39 +++++----
 scripts/postinst-intercepts/delay_to_first_boot    |  2 +
 4 files changed, 82 insertions(+), 78 deletions(-)
 create mode 100644 scripts/postinst-intercepts/delay_to_first_boot

diff --git a/meta-selftest/recipes-test/postinst/postinst_1.0.bb b/meta-selftest/recipes-test/postinst/postinst_1.0.bb
index 6d497342779..1c2d46c3d28 100644
--- a/meta-selftest/recipes-test/postinst/postinst_1.0.bb
+++ b/meta-selftest/recipes-test/postinst/postinst_1.0.bb
@@ -23,88 +23,68 @@ RDEPENDS_${PN}-delayed-t = "${PN}-delayed-p"
 
 # Main recipe post-install
 pkg_postinst_${PN}-at-rootfs () {
-    tfile="/etc/postinsta-test"
-    touch "$D"/this-was-created-at-rootfstime
-    if test "x$D" != "x" then
-        # Need to run on first boot
-        exit 1
-    else
-        echo "lets write postinst" > $tfile
+    if test "x$D" != "x" ; then
+        touch "$D"/this-was-created-at-rootfstime
     fi
 }
 
+pkg_postinst_ontarget_${PN}-at-rootfs () {
+    tfile="/etc/postinsta-test"
+    echo "lets write postinst" > $tfile
+}
+
 # Dependency recipes post-installs
-pkg_postinst_${PN}-delayed-a () {
+pkg_postinst_ontarget_${PN}-delayed-a () {
     efile="/etc/postinst-test"
     tfile="/etc/postinsta-test"
     rdeps="postinst"
 
-    if test "x$D" != "x"; then
-      # Need to run on first boot
-      exit 1
+    touch /etc/this-was-created-at-first-boot
+    if test -e $efile ; then
+      echo 'success' > $tfile
     else
-      touch /etc/this-was-created-at-first-boot
-      if test -e $efile ; then
-        echo 'success' > $tfile
-      else
-        echo 'fail to install $rdeps first!' >&2
-        exit 1
-      fi
-   fi
+      echo 'fail to install $rdeps first!' >&2
+      exit 1
+    fi
 }
 
-pkg_postinst_${PN}-delayed-b () {
+pkg_postinst_ontarget_${PN}-delayed-b () {
     efile="/etc/postinsta-test"
     tfile="/etc/postinstb-test"
     rdeps="postinsta"
 
-    if test "x$D" != "x"; then
-      # Need to run on first boot
-      exit 1
+    if test -e $efile ; then
+      echo 'success' > $tfile
     else
-      if test -e $efile ; then
-        echo 'success' > $tfile
-      else
-        echo 'fail to install $rdeps first!' >&2
-        exit 1
-      fi
-   fi
+      echo 'fail to install $rdeps first!' >&2
+      exit 1
+    fi
 }
 
-pkg_postinst_${PN}-delayed-d () {
+pkg_postinst_ontarget_${PN}-delayed-d () {
     efile="/etc/postinstb-test"
     tfile="/etc/postinstd-test"
     rdeps="postinstb"
 
-    if test "x$D" != "x"; then
-      # Need to run on first boot
-      exit 1
+    if test -e $efile ; then
+      echo 'success' > $tfile
     else
-      if test -e $efile ; then
-        echo 'success' > $tfile
-      else
-        echo 'fail to install $rdeps first!' >&2
-        exit 1
-      fi
-   fi
+      echo 'fail to install $rdeps first!' >&2
+      exit 1
+    fi
 }
 
-pkg_postinst_${PN}-delayed-p () {
+pkg_postinst_ontarget_${PN}-delayed-p () {
     efile="/etc/postinstd-test"
     tfile="/etc/postinstp-test"
     rdeps="postinstd"
 
-    if test "x$D" != "x"; then
-      # Need to run on first boot
-      exit 1
+    if test -e $efile ; then
+      echo 'success' > $tfile
     else
-      if test -e $efile ; then
-        echo 'success' > $tfile
-      else
-        echo 'fail to install $rdeps first!' >&2
-        exit 1
-      fi
-   fi
+      echo 'fail to install $rdeps first!' >&2
+      exit 1
+    fi
 }
 
 pkg_postinst_${PN}-delayed-t () {
@@ -112,15 +92,10 @@ pkg_postinst_${PN}-delayed-t () {
     tfile="/etc/postinstt-test"
     rdeps="postinstp"
 
-    if test "x$D" != "x"; then
-      # Need to run on first boot
-      exit 1
+    if test -e $efile ; then
+        echo 'success' > $tfile
     else
-      if test -e $efile ; then
-          echo 'success' > $tfile
-      else
-          echo 'fail to install $rdeps first!' >&2
-          exit 1
-      fi
-   fi
+        echo 'fail to install $rdeps first!' >&2
+        exit 1
+    fi
 }
diff --git a/meta/classes/package.bbclass b/meta/classes/package.bbclass
index 17029451e36..169c8d98b1d 100644
--- a/meta/classes/package.bbclass
+++ b/meta/classes/package.bbclass
@@ -1289,6 +1289,25 @@ python emit_pkgdata() {
     from glob import glob
     import json
 
+    def process_postinst_on_target(pkg, mlprefix):
+        defer_fragment = """
+if [ -n "$D" ]; then
+    $INTERCEPT_DIR/postinst_intercept delay_to_first_boot %s mlprefix=%s
+    exit 0
+fi
+""" % (pkg, mlprefix)
+
+        postinst = d.getVar('pkg_postinst_%s' % pkg)
+        postinst_ontarget = d.getVar('pkg_postinst_ontarget_%s' % pkg)
+
+        if postinst_ontarget:
+            bb.debug(1, 'adding deferred pkg_postinst_ontarget() to pkg_postinst() for %s' % pkg)
+            if not postinst:
+                postinst = '#!/bin/sh\n'
+            postinst += defer_fragment
+            postinst += postinst_ontarget
+            d.setVar('pkg_postinst_%s' % pkg, postinst)
+
     def write_if_exists(f, pkg, var):
         def encode(str):
             import codecs
@@ -1383,6 +1402,7 @@ python emit_pkgdata() {
         write_if_exists(sf, pkg, 'PKG')
         write_if_exists(sf, pkg, 'ALLOW_EMPTY')
         write_if_exists(sf, pkg, 'FILES')
+        process_postinst_on_target(pkg, d.getVar("MLPREFIX"))
         write_if_exists(sf, pkg, 'pkg_postinst')
         write_if_exists(sf, pkg, 'pkg_postrm')
         write_if_exists(sf, pkg, 'pkg_preinst')
diff --git a/meta/lib/oe/rootfs.py b/meta/lib/oe/rootfs.py
index c8ab421fe21..abcc852ba45 100644
--- a/meta/lib/oe/rootfs.py
+++ b/meta/lib/oe/rootfs.py
@@ -290,6 +290,24 @@ class Rootfs(object, metaclass=ABCMeta):
             # Remove the package manager data files
             self.pm.remove_packaging_data()
 
+    def _postpone_to_first_boot(self, postinst_intercept_hook):
+        with open(postinst_intercept_hook) as intercept:
+            registered_pkgs = None
+            for line in intercept.read().split("\n"):
+                m = re.match("^##PKGS:(.*)", line)
+                if m is not None:
+                    registered_pkgs = m.group(1).strip()
+                    break
+
+            if registered_pkgs is not None:
+                bb.warn("The postinstalls for the following packages "
+                        "will be postponed for first boot: %s" %
+                        registered_pkgs)
+
+                # call the backend dependent handler
+                self._handle_intercept_failure(registered_pkgs)
+
+
     def _run_intercepts(self):
         intercepts_dir = os.path.join(self.d.getVar('WORKDIR'),
                                       "intercept_scripts")
@@ -303,6 +321,10 @@ class Rootfs(object, metaclass=ABCMeta):
             if script == "postinst_intercept" or not os.access(script_full, os.X_OK):
                 continue
 
+            if script == "delay_to_first_boot":
+                self._postpone_to_first_boot(script_full)
+                continue
+
             bb.note("> Executing %s intercept ..." % script)
 
             try:
@@ -310,22 +332,7 @@ class Rootfs(object, metaclass=ABCMeta):
             except subprocess.CalledProcessError as e:
                 bb.warn("The postinstall intercept hook '%s' failed (exit code: %d)! See log for details! (Output: %s)" %
                         (script, e.returncode, e.output))
-
-                with open(script_full) as intercept:
-                    registered_pkgs = None
-                    for line in intercept.read().split("\n"):
-                        m = re.match("^##PKGS:(.*)", line)
-                        if m is not None:
-                            registered_pkgs = m.group(1).strip()
-                            break
-
-                    if registered_pkgs is not None:
-                        bb.warn("The postinstalls for the following packages "
-                                "will be postponed for first boot: %s" %
-                                registered_pkgs)
-
-                        # call the backend dependent handler
-                        self._handle_intercept_failure(registered_pkgs)
+                self._postpone_to_first_boot(script_full)
 
     def _run_ldconfig(self):
         if self.d.getVar('LDCONFIGDEPEND'):
diff --git a/scripts/postinst-intercepts/delay_to_first_boot b/scripts/postinst-intercepts/delay_to_first_boot
new file mode 100644
index 00000000000..ecdbef95dde
--- /dev/null
+++ b/scripts/postinst-intercepts/delay_to_first_boot
@@ -0,0 +1,2 @@
+#!/bin/sh
+exit 1
-- 
2.11.0




More information about the Openembedded-core mailing list