From f41d5230fe23b2a4417ec3a829ecc453c94518af Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Fri, 14 Jul 2023 08:58:42 -0700 Subject: [PATCH 1/5] imgutils: Split part DracutChroot into ProcMount In some cases we need to just mount /proc and /dev so this moves the mount and cleanup code for that into ProcMount, leaving the dracut specific code in DracutChroot (which uses ProcMount). --- src/pylorax/imgutils.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/pylorax/imgutils.py b/src/pylorax/imgutils.py index fe80a8fc8..08428822e 100644 --- a/src/pylorax/imgutils.py +++ b/src/pylorax/imgutils.py @@ -473,20 +473,20 @@ def __exit__(self, exc_type, exc_value, tracebk): execWithRedirect("kpartx", ["-d", "-s", self.disk_img]) -class DracutChroot(object): - """Setup the chroot for running dracut inside it, cleanup when done +class ProcMount(object): + """Setup /proc, /dev, and optional bind mounts. Cleanup when done. - This mount /proc, /dev, and /var/tmp plus optional bind mounted directories + This mount /proc, /dev, and optional bind mounted directories as a list of (source, destination) tuples where destination is relative to the chroot. """ def __init__(self, root, bind=None): self.root = root - self.bind = [("/var/tmp", "/var/tmp")] + (bind if bind else []) + self.bind = bind if bind else [] def __enter__(self): - for d in [d for _, d in self.bind] + ["/proc", "/dev", "/etc/dracut.conf.d"]: + for d in [d for _, d in self.bind] + ["/proc", "/dev"]: if not os.path.exists(self.root + d): - logger.warning("Making missing dracut chroot directory: %s", d) + logger.warning("Making missing mount directory: %s", d) os.makedirs(self.root + d) runcmd(["mount", "-t", "proc", "-o", "nosuid,noexec,nodev", "proc", self.root + "/proc" ]) @@ -507,6 +507,13 @@ def __exit__(self, exc_type, exc_value, tracebk): # some mounts in /var/tmp/lorax can be busy at the moment of unmounting umount(self.root + d, maxretry=10, retrysleep=5, delete=False) +class DracutChroot(ProcMount): + def __init__(self, root, bind=None): + super(DracutChroot, self).__init__(root, [("/var/tmp", "/var/tmp")] + (bind if bind else [])) + + if not os.path.exists(self.root + "/etc/dracut.conf.d/"): + os.makedirs(self.root + "/etc/dracut.conf.d/") + def _copy_conf(self, args): """Check the arguments for --conf, copy the file into the chroot under /etc/dracut.conf.d/, and rewrite the file path to point to the new location. From 20c66641f4713ce2c7c583f54748bacd9e99e6ad Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Fri, 14 Jul 2023 09:00:20 -0700 Subject: [PATCH 2/5] ltmpl: Use ProcMount while running the dnf transaction Some packages expect a filesystem that looks more like a real system. So this mounts /proc and /dev inside the dnf installroot while packages are being installed. This was prompted by a systemd change which has been fixed (https://github.com/systemd/systemd/pull/28388) but as noted, it may happen again. Also update tests to adjust for this. Sadly the run_pkg_transaction test can now only be run as root. And when it doesn't run there is no /etc in the installroot so make the directory just to be sure it is present. --- src/pylorax/ltmpl.py | 15 ++++++++------- tests/pylorax/templates/install-cmd.tmpl | 1 + tests/pylorax/test_ltmpl.py | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/pylorax/ltmpl.py b/src/pylorax/ltmpl.py index d51dbc1ad..71218ba5c 100644 --- a/src/pylorax/ltmpl.py +++ b/src/pylorax/ltmpl.py @@ -32,7 +32,7 @@ from pylorax.dnfhelper import LoraxDownloadCallback, LoraxRpmCallback from pylorax.base import DataHolder from pylorax.executils import runcmd, runcmd_output -from pylorax.imgutils import mkcpio +from pylorax.imgutils import mkcpio, ProcMount from mako.lookup import TemplateLookup from mako.exceptions import text_error_template @@ -719,12 +719,13 @@ def run_pkg_transaction(self): raise logger.info("Preparing transaction from installation source") - try: - display = LoraxRpmCallback() - self.dbo.do_transaction(display=display) - except BaseException as e: - logger.error("The transaction process has ended abruptly: %s", e) - raise + with ProcMount(self.outroot): + try: + display = LoraxRpmCallback() + self.dbo.do_transaction(display=display) + except BaseException as e: + logger.error("The transaction process has ended abruptly: %s", e) + raise # Reset the package sack to pick up the installed packages self.dbo.reset(repos=False) diff --git a/tests/pylorax/templates/install-cmd.tmpl b/tests/pylorax/templates/install-cmd.tmpl index 1ecefda6a..a52eff018 100644 --- a/tests/pylorax/templates/install-cmd.tmpl +++ b/tests/pylorax/templates/install-cmd.tmpl @@ -1,3 +1,4 @@ <%page /> +mkdir /etc append /etc/lorax-test "TESTING LORAX TEMPLATES" install /etc/lorax-test /etc/lorax-test-dest diff --git a/tests/pylorax/test_ltmpl.py b/tests/pylorax/test_ltmpl.py index bc21a9d0c..c6d2bb41f 100644 --- a/tests/pylorax/test_ltmpl.py +++ b/tests/pylorax/test_ltmpl.py @@ -213,6 +213,7 @@ def nevra(pkg): else: self.assertEqual(r, [], t[0]) + @unittest.skipUnless(os.geteuid() == 0 and not os.path.exists("/.in-container"), "requires root privileges, and no containers") def test_01_runner_multi_repo(self): """Test installing packages with updates in a 2nd repo""" # If this does not raise an error it means that: From 4b6d0e872275eba963fa336b043537d261feea81 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Fri, 14 Jul 2023 09:23:44 -0700 Subject: [PATCH 3/5] tests: Fix HFS test to work with new get_file_magic output Macintosh HFS changed to Apple HFS. Accept either one. --- tests/pylorax/test_imgutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pylorax/test_imgutils.py b/tests/pylorax/test_imgutils.py index 0f23243d3..e50381787 100644 --- a/tests/pylorax/test_imgutils.py +++ b/tests/pylorax/test_imgutils.py @@ -311,7 +311,7 @@ def test_mkhfsimg(self): mkhfsimg(work_dir, disk_img.name, label="test") self.assertTrue(os.path.exists(disk_img.name)) file_details = get_file_magic(disk_img.name) - self.assertTrue("Macintosh HFS" in file_details, file_details) + self.assertTrue(any(s in file_details for s in ("Macintosh HFS", "Apple HFS")), file_details) def test_default_image_name(self): """Test default_image_name function""" From 371a928feb5b73adaf1276be494e702f97df660e Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Fri, 14 Jul 2023 09:43:33 -0700 Subject: [PATCH 4/5] tests: Fix image_minimizer test dnf usage --releasever=/ isn't setting $releasever when using dnf5. --- tests/image-minimizer/test_minimizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/image-minimizer/test_minimizer.py b/tests/image-minimizer/test_minimizer.py index 0fe0dfd46..554efaa80 100644 --- a/tests/image-minimizer/test_minimizer.py +++ b/tests/image-minimizer/test_minimizer.py @@ -8,7 +8,7 @@ class MinimizerTestCase(unittest.TestCase): def test_minimizer_ok(self): with tempfile.TemporaryDirectory(prefix="minimize.test.") as rootdir: - check_call(["dnf", "--releasever=/", "--use-host-config", "--installroot", rootdir, "install", "-y", \ + check_call(["dnf", "--use-host-config", "--installroot", rootdir, "install", "-y", \ "filesystem", "tzdata"]) im = ImageMinimizer("./tests/image-minimizer/im-script.txt", rootdir, False, False) From b48c57a43301c31d6adb14181f5b03870ce7db73 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Fri, 14 Jul 2023 10:09:16 -0700 Subject: [PATCH 5/5] pylint: Ignore false positive from pylint on rawhide The new pylint/astroid on rawhide doesn't know how to deal with datetime. Ignore the false positive error until it is fixed. --- tests/pylint/runpylint.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/pylint/runpylint.py b/tests/pylint/runpylint.py index 9d11c3226..a08b23dd1 100755 --- a/tests/pylint/runpylint.py +++ b/tests/pylint/runpylint.py @@ -16,6 +16,9 @@ def __init__(self): FalsePositive(r"raise-missing-from"), FalsePositive(r"redundant-u-string-prefix"), FalsePositive(r"unspecified-encoding"), + # Python 3.12 problems with pylint/astroid + # see https://github.com/pylint-dev/pylint/issues/8852 + FalsePositive(r"Class 'datetime' has no '(now|utcfromtimestamp)' member"), ] @property