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.
This commit is contained in:
Miguel Martín 2023-11-21 08:38:21 +01:00 committed by Simon de Vlieger
parent b3c6366135
commit 99af178c6d
7 changed files with 100 additions and 97 deletions

View file

@ -1,8 +1,10 @@
import os.path import os.path
import pathlib
import platform import platform
import shutil import shutil
import subprocess import subprocess
import sys import sys
from contextlib import contextmanager
def ldconfig(*dirs): def ldconfig(*dirs):
@ -31,6 +33,29 @@ def sysusers():
sys.exit(1) 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(): def tmpfiles():
# Allow systemd-tmpfiles to return non-0. Some packages want to create # Allow systemd-tmpfiles to return non-0. Some packages want to create
# directories owned by users that are not set up with systemd-sysusers. # directories owned by users that are not set up with systemd-sysusers.

View file

@ -10,9 +10,9 @@ if __name__ == "__main__":
with api.exception_handler(): with api.exception_handler():
runners.ldconfig() runners.ldconfig()
runners.sysusers() runners.sysusers()
runners.tmpfiles() with runners.create_machine_id_if_needed():
runners.nsswitch() runners.tmpfiles()
runners.nsswitch()
r = subprocess.run(sys.argv[1:], check=False) r = subprocess.run(sys.argv[1:], check=False)
sys.exit(r.returncode) sys.exit(r.returncode)

View file

@ -10,9 +10,9 @@ if __name__ == "__main__":
with api.exception_handler(): with api.exception_handler():
runners.ldconfig() runners.ldconfig()
runners.sysusers() runners.sysusers()
runners.tmpfiles() with runners.create_machine_id_if_needed():
runners.nsswitch() runners.tmpfiles()
runners.nsswitch()
r = subprocess.run(sys.argv[1:], check=False) r = subprocess.run(sys.argv[1:], check=False)
sys.exit(r.returncode) sys.exit(r.returncode)

View file

@ -10,9 +10,10 @@ if __name__ == "__main__":
with api.exception_handler(): with api.exception_handler():
runners.ldconfig() runners.ldconfig()
runners.sysusers() runners.sysusers()
runners.tmpfiles() with runners.create_machine_id_if_needed():
runners.nsswitch() runners.tmpfiles()
runners.sequoia() runners.nsswitch()
runners.sequoia()
r = subprocess.run(sys.argv[1:], check=False)
r = subprocess.run(sys.argv[1:], check=False)
sys.exit(r.returncode) sys.exit(r.returncode)

View file

@ -35,10 +35,11 @@ if __name__ == "__main__":
with api.exception_handler(): with api.exception_handler():
runners.ldconfig() runners.ldconfig()
runners.sysusers() runners.sysusers()
runners.tmpfiles() with runners.create_machine_id_if_needed():
runners.nsswitch() runners.tmpfiles()
os_release() runners.nsswitch()
runners.python_alternatives() 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) sys.exit(r.returncode)

View file

@ -10,12 +10,11 @@ if __name__ == "__main__":
with api.exception_handler(): with api.exception_handler():
runners.ldconfig() runners.ldconfig()
runners.sysusers() runners.sysusers()
runners.tmpfiles() with runners.create_machine_id_if_needed():
runners.nsswitch() runners.tmpfiles()
runners.python_alternatives() runners.nsswitch()
runners.python_alternatives()
env = runners.quirks() env = runners.quirks()
r = subprocess.run(sys.argv[1:], env=env, check=False)
r = subprocess.run(sys.argv[1:], env=env, check=False)
sys.exit(r.returncode) sys.exit(r.returncode)

View file

@ -35,7 +35,6 @@ This stage will return the following metadata via the osbuild API:
import contextlib import contextlib
import json import json
import os import os
import pathlib
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
@ -43,6 +42,7 @@ from operator import itemgetter
from osbuild import api from osbuild import api
from osbuild.util.mnt import mount from osbuild.util.mnt import mount
from osbuild.util.runners import create_machine_id_if_needed
SCHEMA = """ SCHEMA = """
"additionalProperties": false, "additionalProperties": false,
@ -263,21 +263,6 @@ def parse_input(inputs):
return path, files 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 # pylint: disable=too-many-branches
def main(tree, inputs, options): def main(tree, inputs, options):
pkgpath, packages = parse_input(inputs) pkgpath, packages = parse_input(inputs)
@ -322,69 +307,61 @@ def main(tree, inputs, options):
os.symlink("/proc/self/fd", f"{tree}/dev/fd") 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 extra_args = []
if options.get("ostree_booted", False): if options.get("exclude", {}).get("docs"):
os.makedirs(f"{tree}/run", exist_ok=True) extra_args += ["--excludedocs"]
ostree_booted = f"{tree}/{OSTREE_BOOTED_MARKER}"
with open(ostree_booted, "w", encoding="utf8") as f:
f.write("")
extra_args = [] # prevent dracut from running, if enabled
if options.get("exclude", {}).get("docs"): no_dracut = options.get("disable_dracut", False)
extra_args += ["--excludedocs"] if no_dracut:
masked_files = disable_dracut(tree)
# prevent dracut from running, if enabled langs = options.get("install_langs")
no_dracut = options.get("disable_dracut", False) if langs:
if no_dracut: macro = "%_install_langs " + ":".join(langs)
masked_files = disable_dracut(tree) print(f"using '{macro}'")
extra_args += [
"--define", macro,
]
langs = options.get("install_langs") with tempfile.NamedTemporaryFile(prefix="manifest.", mode='w') as manifest:
if langs: manifest.writelines(c + '\n' for c in packages)
macro = "%_install_langs " + ":".join(langs) manifest.flush()
print(f"using '{macro}'") subprocess.run([
extra_args += [ "rpm",
"--define", macro, "--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: for key in options.get("gpgkeys.fromtree", []):
manifest.writelines(c + '\n' for c in packages) path = os.path.join(tree, key.lstrip("/"))
manifest.flush() subprocess.run([
subprocess.run([ "rpmkeys",
"rpm", *rpm_args,
"--verbose", "--root", tree,
*rpm_args, "--import", path
"--root", tree, ], check=True)
*extra_args, print(f"imported gpg keys from '{key}'")
# 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", []): # re-enabled dracut
path = os.path.join(tree, key.lstrip("/")) if no_dracut:
subprocess.run([ enable_dracut(masked_files)
"rpmkeys", remove_unowned_etc_kernel(tree, rpm_args)
*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)
if ostree_booted: if ostree_booted:
os.unlink(ostree_booted) os.unlink(ostree_booted)