diff mbox series

[v1,1/3] image.bbclass/rootfs: archive and deploy opkg package database

Message ID 20240213085658.170917-2-johannes.schneider@leica-geosystems.com
State New
Headers show
Series pkg-database and systemd-sysext image | expand

Commit Message

SCHNEIDER Johannes Feb. 13, 2024, 8:56 a.m. UTC
archive the package database after the rootfs has been put together as
*rootfs-pkdbfs.tar.gz, and put it into the deploy folder.

This creates a snapshot of the package mangers state at the point in time when
all dependencies have been resolved and installed; which can be used by "follow
up" images to be built upon.

Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 meta/classes/image.bbclass                | 44 +++++++++++++++++++++--
 meta/classes/image_types.bbclass          |  1 +
 meta/conf/bitbake.conf                    |  1 +
 meta/lib/oe/package_manager/deb/rootfs.py |  1 +
 meta/lib/oe/package_manager/ipk/rootfs.py |  1 +
 meta/lib/oe/package_manager/rpm/rootfs.py |  1 +
 meta/lib/oe/rootfs.py                     | 35 ++++++++++++++++++
 7 files changed, 82 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass
index 00413d56d1..c8919a4857 100644
--- a/meta/classes/image.bbclass
+++ b/meta/classes/image.bbclass
@@ -36,6 +36,9 @@  IMAGE_FEATURES ?= ""
 IMAGE_FEATURES[type] = "list"
 IMAGE_FEATURES[validitems] += "debug-tweaks read-only-rootfs read-only-rootfs-delayed-postinsts stateless-rootfs empty-root-password allow-empty-password allow-root-login post-install-logging overlayfs-etc"
 
+# Generate snapshot of the package database?
+IMAGE_GEN_PKGDBFS ?= "0"
+
 # Generate companion debugfs?
 IMAGE_GEN_DEBUGFS ?= "0"
 
@@ -125,7 +128,7 @@  def rootfs_variables(d):
                  'IMAGE_ROOTFS_MAXSIZE','IMAGE_NAME','IMAGE_LINK_NAME','IMAGE_MANIFEST','DEPLOY_DIR_IMAGE','IMAGE_FSTYPES','IMAGE_INSTALL_COMPLEMENTARY','IMAGE_LINGUAS', 'IMAGE_LINGUAS_COMPLEMENTARY', 'IMAGE_LOCALES_ARCHIVE',
                  'MULTILIBRE_ALLOW_REP','MULTILIB_TEMP_ROOTFS','MULTILIB_VARIANTS','MULTILIBS','ALL_MULTILIB_PACKAGE_ARCHS','MULTILIB_GLOBAL_VARIANTS','BAD_RECOMMENDATIONS','NO_RECOMMENDATIONS',
                  'PACKAGE_ARCHS','PACKAGE_CLASSES','TARGET_VENDOR','TARGET_ARCH','TARGET_OS','OVERRIDES','BBEXTENDVARIANT','FEED_DEPLOYDIR_BASE_URI','INTERCEPT_DIR','USE_DEVFS',
-                 'CONVERSIONTYPES', 'IMAGE_GEN_DEBUGFS', 'ROOTFS_RO_UNNEEDED', 'IMGDEPLOYDIR', 'PACKAGE_EXCLUDE_COMPLEMENTARY', 'REPRODUCIBLE_TIMESTAMP_ROOTFS', 'IMAGE_INSTALL_DEBUGFS']
+                 'CONVERSIONTYPES', 'IMAGE_GEN_PKGDBFS', 'IMAGE_GEN_DEBUGFS', 'ROOTFS_RO_UNNEEDED', 'IMGDEPLOYDIR', 'PACKAGE_EXCLUDE_COMPLEMENTARY', 'REPRODUCIBLE_TIMESTAMP_ROOTFS', 'IMAGE_INSTALL_DEBUGFS']
     variables.extend(rootfs_command_variables(d))
     variables.extend(variable_depends(d))
     return " ".join(variables)
@@ -330,6 +333,19 @@  python do_image_qa_setscene () {
 }
 addtask do_image_qa_setscene
 
+def setup_pkgdbfs_variables(d):
+    d.appendVar('IMAGE_ROOTFS', '-pkgdb')
+    if d.getVar('IMAGE_LINK_NAME'):
+        d.appendVar('IMAGE_LINK_NAME', '-pkgdb')
+    d.appendVar('IMAGE_NAME','-pkgdb')
+    pkgdbfs_image_fstypes = d.getVar('IMAGE_FSTYPES_PKGDBFS')
+    if pkgdbfs_image_fstypes:
+        d.setVar('IMAGE_FSTYPES', pkgdbfs_image_fstypes)
+
+python setup_pkgdbfs () {
+    setup_pkgdbfs_variables(d)
+}
+
 def setup_debugfs_variables(d):
     d.appendVar('IMAGE_ROOTFS', '-dbg')
     if d.getVar('IMAGE_LINK_NAME'):
@@ -374,6 +390,11 @@  python () {
     alltypes = d.getVar('IMAGE_FSTYPES').split()
     typedeps = {}
 
+    if d.getVar('IMAGE_GEN_PKGDBFS') == "1":
+        pkgdbfs_fstypes = d.getVar('IMAGE_FSTYPES_PKGDBFS').split()
+        for t in pkgdbfs_fstypes:
+            alltypes.append("pkgdbfs_" + t)
+
     if d.getVar('IMAGE_GEN_DEBUGFS') == "1":
         debugfs_fstypes = d.getVar('IMAGE_FSTYPES_DEBUGFS').split()
         for t in debugfs_fstypes:
@@ -386,6 +407,10 @@  python () {
             basetypes[baset]= []
         if t not in basetypes[baset]:
             basetypes[baset].append(t)
+        pkgdb = ""
+        if t.startswith("pkgdbfs_"):
+            t = t[8:]
+            pkgdb = "pkgdbfs_"
         debug = ""
         if t.startswith("debugfs_"):
             t = t[8:]
@@ -394,6 +419,13 @@  python () {
         vardeps.add('IMAGE_TYPEDEP:' + t)
         if baset not in typedeps:
             typedeps[baset] = set()
+        deps = [pkgdb + dep for dep in deps]
+        for dep in deps:
+            if dep not in alltypes:
+                alltypes.append(dep)
+            _add_type(dep)
+            basedep = _image_base_type(dep)
+            typedeps[baset].add(basedep)
         deps = [debug + dep for dep in deps]
         for dep in deps:
             if dep not in alltypes:
@@ -412,6 +444,7 @@  python () {
 
     maskedtypes = (d.getVar('IMAGE_TYPES_MASKED') or "").split()
     maskedtypes = [dbg + t for t in maskedtypes for dbg in ("", "debugfs_")]
+    maskedtypes = [pkgdb + t for t in maskedtypes for pkgdb in ("", "pkgdbfs_")]
 
     for t in basetypes:
         vardeps = set()
@@ -423,6 +456,11 @@  python () {
             continue
 
         localdata = bb.data.createCopy(d)
+        pkgdb = ""
+        if t.startswith("pkgdbfs_"):
+            setup_pkgdbfs_variables(localdata)
+            pkgdb = "setup_pkgdbfs "
+            realt = t[8:]
         debug = ""
         if t.startswith("debugfs_"):
             setup_debugfs_variables(localdata)
@@ -461,6 +499,8 @@  python () {
             for ctype in sorted(ctypes):
                 if bt.endswith("." + ctype):
                     type = bt[0:-len(ctype) - 1]
+                    if type.startswith("pkgdbfs_"):
+                        type = type[8:]
                     if type.startswith("debugfs_"):
                         type = type[8:]
                     # Create input image first.
@@ -501,7 +541,7 @@  python () {
         d.setVarFlag(task, 'func', '1')
         d.setVarFlag(task, 'fakeroot', '1')
 
-        d.appendVarFlag(task, 'prefuncs', ' ' + debug + ' set_image_size')
+        d.appendVarFlag(task, 'prefuncs', ' ' + debug + pkgdb + ' set_image_size')
         d.prependVarFlag(task, 'postfuncs', 'create_symlinks ')
         d.appendVarFlag(task, 'subimages', ' ' + ' '.join(subimages))
         d.appendVarFlag(task, 'vardeps', ' ' + ' '.join(vardeps))
diff --git a/meta/classes/image_types.bbclass b/meta/classes/image_types.bbclass
index 9d5f8c68a4..cae8abd47e 100644
--- a/meta/classes/image_types.bbclass
+++ b/meta/classes/image_types.bbclass
@@ -19,6 +19,7 @@  def imagetypes_getdepends(d):
 
     fstypes = set((d.getVar('IMAGE_FSTYPES') or "").split())
     fstypes |= set((d.getVar('IMAGE_FSTYPES_DEBUGFS') or "").split())
+    fstypes |= set((d.getVar('IMAGE_FSTYPES_PKGDBFS') or "").split())
 
     deprecated = set()
     deps = set()
diff --git a/meta/conf/bitbake.conf b/meta/conf/bitbake.conf
index 290dfda6c8..80607567c1 100644
--- a/meta/conf/bitbake.conf
+++ b/meta/conf/bitbake.conf
@@ -830,6 +830,7 @@  require conf/sanity.conf
 DL_DIR ?= "${TOPDIR}/downloads"
 SSTATE_DIR ?= "${TOPDIR}/sstate-cache"
 IMAGE_FSTYPES ?= "tar.gz"
+IMAGE_FSTYPES_PKGDBFS ?= "tar.gz"
 IMAGE_FSTYPES_DEBUGFS ?= "tar.gz"
 
 INITRAMFS_FSTYPES ?= "cpio.gz"
diff --git a/meta/lib/oe/package_manager/deb/rootfs.py b/meta/lib/oe/package_manager/deb/rootfs.py
index 8fbaca11d6..08d8aa9813 100644
--- a/meta/lib/oe/package_manager/deb/rootfs.py
+++ b/meta/lib/oe/package_manager/deb/rootfs.py
@@ -176,6 +176,7 @@  class PkgRootfs(DpkgOpkgRootfs):
         if self.progress_reporter:
             self.progress_reporter.next_stage()
 
+        self._setup_pkg_db_rootfs(['/var/lib/dpkg'])
         self._setup_dbg_rootfs(['/var/lib/dpkg'])
 
         self.pm.fix_broken_dependencies()
diff --git a/meta/lib/oe/package_manager/ipk/rootfs.py b/meta/lib/oe/package_manager/ipk/rootfs.py
index 10a831994e..14bf6cac98 100644
--- a/meta/lib/oe/package_manager/ipk/rootfs.py
+++ b/meta/lib/oe/package_manager/ipk/rootfs.py
@@ -317,6 +317,7 @@  class PkgRootfs(DpkgOpkgRootfs):
 
         opkg_lib_dir = self.d.getVar('OPKGLIBDIR')
         opkg_dir = os.path.join(opkg_lib_dir, 'opkg')
+        self._setup_pkg_db_rootfs([opkg_dir])
         self._setup_dbg_rootfs([opkg_dir])
 
         execute_pre_post_process(self.d, opkg_post_process_cmds)
diff --git a/meta/lib/oe/package_manager/rpm/rootfs.py b/meta/lib/oe/package_manager/rpm/rootfs.py
index a120092b83..cdf9c228f5 100644
--- a/meta/lib/oe/package_manager/rpm/rootfs.py
+++ b/meta/lib/oe/package_manager/rpm/rootfs.py
@@ -108,6 +108,7 @@  class PkgRootfs(Rootfs):
         if self.progress_reporter:
             self.progress_reporter.next_stage()
 
+        self._setup_pkg_db_rootfs(['/etc/rpm', '/etc/rpmrc', '/etc/dnf', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
         self._setup_dbg_rootfs(['/etc/rpm', '/etc/rpmrc', '/etc/dnf', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
 
         execute_pre_post_process(self.d, rpm_post_process_cmds)
diff --git a/meta/lib/oe/rootfs.py b/meta/lib/oe/rootfs.py
index 2824d4f037..f24c2697b4 100644
--- a/meta/lib/oe/rootfs.py
+++ b/meta/lib/oe/rootfs.py
@@ -104,6 +104,41 @@  class Rootfs(object, metaclass=ABCMeta):
     def _cleanup(self):
         pass
 
+    def _setup_pkg_db_rootfs(self, package_paths):
+        gen_pkg_db_fs = self.d.getVar('IMAGE_GEN_PKGDBFS') or '0'
+        if gen_pkg_db_fs != '1':
+           return
+
+        bb.note("  Renaming the original rootfs...")
+        try:
+            shutil.rmtree(self.image_rootfs + '-orig')
+        except:
+            pass
+        bb.utils.rename(self.image_rootfs, self.image_rootfs + '-orig')
+
+        bb.note("  Creating pkg-db rootfs...")
+        bb.utils.mkdirhier(self.image_rootfs)
+
+        bb.note("  Copying back package database...")
+        for path in package_paths:
+            bb.utils.mkdirhier(self.image_rootfs + os.path.dirname(path))
+            if os.path.isdir(self.image_rootfs + '-orig' + path):
+                shutil.copytree(self.image_rootfs + '-orig' + path, self.image_rootfs + path, symlinks=True)
+            elif os.path.isfile(self.image_rootfs + '-orig' + path):
+                shutil.copyfile(self.image_rootfs + '-orig' + path, self.image_rootfs + path)
+
+        ####
+
+        bb.note("  Rename pkg-db rootfs...")
+        try:
+            shutil.rmtree(self.image_rootfs + '-pkgdb')
+        except:
+            pass
+        bb.utils.rename(self.image_rootfs, self.image_rootfs + '-pkgdb')
+
+        bb.note("  Restoring original rootfs...")
+        bb.utils.rename(self.image_rootfs + '-orig', self.image_rootfs)
+
     def _setup_dbg_rootfs(self, package_paths):
         gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS') or '0'
         if gen_debugfs != '1':