From 99af178c6d50bf203f804ebaa5994dec850538d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Mart=C3=ADn?= Date: Tue, 21 Nov 2023 08:38:21 +0100 Subject: [PATCH] runners: create fake machine id when needed Create fake machine before executing the runner command to avoid the "Failed to resolve specifiers in '/var/log/journal/%m'" errors. --- osbuild/util/runners.py | 25 +++++++ runners/org.osbuild.centos9 | 8 +-- runners/org.osbuild.fedora30 | 8 +-- runners/org.osbuild.fedora38 | 9 +-- runners/org.osbuild.rhel81 | 11 ++-- runners/org.osbuild.rhel82 | 13 ++-- stages/org.osbuild.rpm | 123 ++++++++++++++--------------------- 7 files changed, 100 insertions(+), 97 deletions(-) diff --git a/osbuild/util/runners.py b/osbuild/util/runners.py index 3688a867..99f5de91 100644 --- a/osbuild/util/runners.py +++ b/osbuild/util/runners.py @@ -1,8 +1,10 @@ import os.path +import pathlib import platform import shutil import subprocess import sys +from contextlib import contextmanager def ldconfig(*dirs): @@ -31,6 +33,29 @@ def sysusers(): sys.exit(1) +@contextmanager +def create_machine_id_if_needed(tree="", keep_empty=False): + """Create a machine-id with a fake machine id if it does not exist. + The machine-id file will be delete at context exit unless specified + with 'keep_empty' variable. In that case an empty machine-id will + be kept. + """ + path = pathlib.Path(f"{tree}/etc/machine-id") + try: + if not path.exists(): + path.parent.mkdir(mode=0o755, exist_ok=True) + with path.open(mode="w", encoding="utf8") as f: + # create a fake machine ID to improve reproducibility + f.write("ffffffffffffffffffffffffffffffff\n") + path.chmod(0o444) + yield + finally: + path.unlink() + if keep_empty: + path.touch() + path.chmod(0o444) + + def tmpfiles(): # Allow systemd-tmpfiles to return non-0. Some packages want to create # directories owned by users that are not set up with systemd-sysusers. diff --git a/runners/org.osbuild.centos9 b/runners/org.osbuild.centos9 index a6a7b7c2..3e0f60f0 100755 --- a/runners/org.osbuild.centos9 +++ b/runners/org.osbuild.centos9 @@ -10,9 +10,9 @@ if __name__ == "__main__": with api.exception_handler(): runners.ldconfig() runners.sysusers() - runners.tmpfiles() - runners.nsswitch() - - r = subprocess.run(sys.argv[1:], check=False) + with runners.create_machine_id_if_needed(): + runners.tmpfiles() + runners.nsswitch() + r = subprocess.run(sys.argv[1:], check=False) sys.exit(r.returncode) diff --git a/runners/org.osbuild.fedora30 b/runners/org.osbuild.fedora30 index a6a7b7c2..3e0f60f0 100755 --- a/runners/org.osbuild.fedora30 +++ b/runners/org.osbuild.fedora30 @@ -10,9 +10,9 @@ if __name__ == "__main__": with api.exception_handler(): runners.ldconfig() runners.sysusers() - runners.tmpfiles() - runners.nsswitch() - - r = subprocess.run(sys.argv[1:], check=False) + with runners.create_machine_id_if_needed(): + runners.tmpfiles() + runners.nsswitch() + r = subprocess.run(sys.argv[1:], check=False) sys.exit(r.returncode) diff --git a/runners/org.osbuild.fedora38 b/runners/org.osbuild.fedora38 index 92fb55eb..2d0b8198 100755 --- a/runners/org.osbuild.fedora38 +++ b/runners/org.osbuild.fedora38 @@ -10,9 +10,10 @@ if __name__ == "__main__": with api.exception_handler(): runners.ldconfig() runners.sysusers() - runners.tmpfiles() - runners.nsswitch() - runners.sequoia() + with runners.create_machine_id_if_needed(): + runners.tmpfiles() + runners.nsswitch() + runners.sequoia() + r = subprocess.run(sys.argv[1:], check=False) - r = subprocess.run(sys.argv[1:], check=False) sys.exit(r.returncode) diff --git a/runners/org.osbuild.rhel81 b/runners/org.osbuild.rhel81 index d00399e7..db7fe78c 100755 --- a/runners/org.osbuild.rhel81 +++ b/runners/org.osbuild.rhel81 @@ -35,10 +35,11 @@ if __name__ == "__main__": with api.exception_handler(): runners.ldconfig() runners.sysusers() - runners.tmpfiles() - runners.nsswitch() - os_release() - runners.python_alternatives() + with runners.create_machine_id_if_needed(): + runners.tmpfiles() + runners.nsswitch() + os_release() + runners.python_alternatives() + r = subprocess.run(sys.argv[1:], check=False) - r = subprocess.run(sys.argv[1:], check=False) sys.exit(r.returncode) diff --git a/runners/org.osbuild.rhel82 b/runners/org.osbuild.rhel82 index 71e6841b..101c5771 100755 --- a/runners/org.osbuild.rhel82 +++ b/runners/org.osbuild.rhel82 @@ -10,12 +10,11 @@ if __name__ == "__main__": with api.exception_handler(): runners.ldconfig() runners.sysusers() - runners.tmpfiles() - runners.nsswitch() - runners.python_alternatives() - - env = runners.quirks() - - r = subprocess.run(sys.argv[1:], env=env, check=False) + with runners.create_machine_id_if_needed(): + runners.tmpfiles() + runners.nsswitch() + runners.python_alternatives() + env = runners.quirks() + r = subprocess.run(sys.argv[1:], env=env, check=False) sys.exit(r.returncode) diff --git a/stages/org.osbuild.rpm b/stages/org.osbuild.rpm index bdc33779..80b8bf86 100755 --- a/stages/org.osbuild.rpm +++ b/stages/org.osbuild.rpm @@ -35,7 +35,6 @@ This stage will return the following metadata via the osbuild API: import contextlib import json import os -import pathlib import subprocess import sys import tempfile @@ -43,6 +42,7 @@ from operator import itemgetter from osbuild import api from osbuild.util.mnt import mount +from osbuild.util.runners import create_machine_id_if_needed SCHEMA = """ "additionalProperties": false, @@ -263,21 +263,6 @@ def parse_input(inputs): return path, files -def create_machine_id_if_needed(tree): - """Create a machine-id with a fake machine id if it does not exist""" - path = f"{tree}/etc/machine-id" - if os.path.exists(path): - return False - - os.makedirs(f"{tree}/etc", exist_ok=True) - with open(path, "w", encoding="utf8") as f: - # create a fake machine ID to improve reproducibility - f.write("ffffffffffffffffffffffffffffffff\n") - os.fchmod(f.fileno(), 0o400) - - return True - - # pylint: disable=too-many-branches def main(tree, inputs, options): pkgpath, packages = parse_input(inputs) @@ -322,69 +307,61 @@ def main(tree, inputs, options): os.symlink("/proc/self/fd", f"{tree}/dev/fd") - machine_id_created = create_machine_id_if_needed(tree) + with create_machine_id_if_needed(tree, keep_empty=True): + ostree_booted = None + if options.get("ostree_booted", False): + os.makedirs(f"{tree}/run", exist_ok=True) + ostree_booted = f"{tree}/{OSTREE_BOOTED_MARKER}" + with open(ostree_booted, "w", encoding="utf8") as f: + f.write("") - ostree_booted = None - if options.get("ostree_booted", False): - os.makedirs(f"{tree}/run", exist_ok=True) - ostree_booted = f"{tree}/{OSTREE_BOOTED_MARKER}" - with open(ostree_booted, "w", encoding="utf8") as f: - f.write("") + extra_args = [] + if options.get("exclude", {}).get("docs"): + extra_args += ["--excludedocs"] - extra_args = [] - if options.get("exclude", {}).get("docs"): - extra_args += ["--excludedocs"] + # prevent dracut from running, if enabled + no_dracut = options.get("disable_dracut", False) + if no_dracut: + masked_files = disable_dracut(tree) - # prevent dracut from running, if enabled - no_dracut = options.get("disable_dracut", False) - if no_dracut: - masked_files = disable_dracut(tree) + langs = options.get("install_langs") + if langs: + macro = "%_install_langs " + ":".join(langs) + print(f"using '{macro}'") + extra_args += [ + "--define", macro, + ] - langs = options.get("install_langs") - if langs: - macro = "%_install_langs " + ":".join(langs) - print(f"using '{macro}'") - extra_args += [ - "--define", macro, - ] + with tempfile.NamedTemporaryFile(prefix="manifest.", mode='w') as manifest: + manifest.writelines(c + '\n' for c in packages) + manifest.flush() + subprocess.run([ + "rpm", + "--verbose", + *rpm_args, + "--root", tree, + *extra_args, + # All digests and signatures of the rpms has been verified, + # default to not verifying package or header signatures when + # reading. + "--nosignature", + "--install", manifest.name + ], cwd=pkgpath, check=True) - with tempfile.NamedTemporaryFile(prefix="manifest.", mode='w') as manifest: - manifest.writelines(c + '\n' for c in packages) - manifest.flush() - subprocess.run([ - "rpm", - "--verbose", - *rpm_args, - "--root", tree, - *extra_args, - # All digests and signatures of the rpms has been verified, - # default to not verifying package or header signatures when - # reading. - "--nosignature", - "--install", manifest.name - ], cwd=pkgpath, check=True) + for key in options.get("gpgkeys.fromtree", []): + path = os.path.join(tree, key.lstrip("/")) + subprocess.run([ + "rpmkeys", + *rpm_args, + "--root", tree, + "--import", path + ], check=True) + print(f"imported gpg keys from '{key}'") - for key in options.get("gpgkeys.fromtree", []): - path = os.path.join(tree, key.lstrip("/")) - subprocess.run([ - "rpmkeys", - *rpm_args, - "--root", tree, - "--import", path - ], check=True) - print(f"imported gpg keys from '{key}'") - - # re-enabled dracut - if no_dracut: - enable_dracut(masked_files) - remove_unowned_etc_kernel(tree, rpm_args) - - # remove temporary machine ID if it was created by us - if machine_id_created: - print("deleting the fake machine id") - machine_id_file = pathlib.Path(f"{tree}/etc/machine-id") - machine_id_file.unlink() - machine_id_file.touch(mode=0o444) + # re-enabled dracut + if no_dracut: + enable_dracut(masked_files) + remove_unowned_etc_kernel(tree, rpm_args) if ostree_booted: os.unlink(ostree_booted)