1
0
mirror of https://github.com/coreos/fedora-coreos-config.git synced 2026-02-05 09:45:30 +01:00

tree: import changes from testing-devel at 8594e0c045

This commit is contained in:
CoreOS Bot
2025-11-07 13:17:47 +00:00
parent 342a387552
commit 6a28008a2f
2 changed files with 68 additions and 57 deletions

View File

@@ -17,3 +17,7 @@
!/overlay.d/
!/overrides/
!/platforms.yaml
# Useful for testing development versions.
!/bootc-base-imagectl
!/rpm-ostree

View File

@@ -55,12 +55,16 @@ def main():
overlays = gather_overlays(manifest)
nodocs = (manifest.get('documentation') is False)
recommends = manifest.get('recommends')
# We generate the initramfs using dracut ourselves later after our
# CoreOS postprocess scripts have run. If this version of rpm-ostree
# supports it we'll tell it to not run dracut in the initial compose.
no_initramfs = True if no_initramfs_arg_supported() else False
if version != "":
dracut_tmpd = inject_dracut_version(manifest['mutate-os-release'], version)
overlays += [dracut_tmpd.name]
build_rootfs(target_rootfs, manifest_path, packages, locked_nevras, overlays, repos, nodocs)
build_rootfs(
target_rootfs, manifest_path, packages, locked_nevras,
overlays, repos, nodocs, recommends, no_initramfs
)
inject_live(target_rootfs)
inject_image_json(target_rootfs, manifest_path)
@@ -68,14 +72,13 @@ def main():
inject_content_manifest(target_rootfs, manifest)
if version != "":
overlays.remove(dracut_tmpd.name)
cleanup_dracut_version(target_rootfs, dracut_tmpd)
inject_version_info(target_rootfs, manifest['mutate-os-release'], version)
strict_mode = os.getenv('STRICT_MODE')
if strict_mode == '1':
verify_strict_mode(target_rootfs, locked_nevras)
run_postprocess_scripts(target_rootfs, manifest)
run_dracut(target_rootfs)
cleanup_extraneous_files(target_rootfs)
calculate_inputhash(target_rootfs, overlays, manifest)
@@ -111,7 +114,10 @@ def inject_yumrepos():
shutil.copy(repo, "/etc/yum.repos.d")
def build_rootfs(target_rootfs, manifest_path, packages, locked_nevras, overlays, repos, nodocs):
def build_rootfs(
target_rootfs, manifest_path, packages, locked_nevras,
overlays, repos, nodocs, recommends, no_initramfs
):
passwd_group_dir = os.getenv('PASSWD_GROUP_DIR')
if passwd_group_dir is not None:
inject_passwd_group(os.path.join(SRCDIR, passwd_group_dir))
@@ -124,6 +130,12 @@ def build_rootfs(target_rootfs, manifest_path, packages, locked_nevras, overlays
argsfile.write("--no-docs\n")
# temporarily work around https://issues.redhat.com/browse/RHEL-97826
tmpd = workaround_rhel_97826(argsfile)
if recommends:
if not recommends_arg_supported():
raise Exception(f"Need to set recommends: true but --recommends is unsupported")
argsfile.write("--recommends\n")
if no_initramfs:
argsfile.write("--no-initramfs\n")
if repos and repo_arg_supported():
for repo in repos:
argsfile.write(f"--repo={repo}\n")
@@ -141,22 +153,47 @@ def build_rootfs(target_rootfs, manifest_path, packages, locked_nevras, overlays
if nodocs and tmpd is not None:
del tmpd
def get_bootc_base_imagectl_help():
return subprocess.check_output(['/usr/libexec/bootc-base-imagectl', 'build-rootfs', '-h'], encoding='utf-8')
def repo_arg_supported():
# Detect if we have https://gitlab.com/fedora/bootc/base-images/-/merge_requests/248.
# If not, then we can't use `--repo`. That's OK because that should only
# happen on RHEL, where we don't have any default repos anyway and only rely on
# the mounted secret repo file.
help = subprocess.check_output(['/usr/libexec/bootc-base-imagectl', 'build-rootfs', '-h'], encoding='utf-8')
return '--repo REPO' in help
return '--repo REPO' in get_bootc_base_imagectl_help()
def lock_arg_supported():
# Detect if we have https://gitlab.com/fedora/bootc/base-images/-/merge_requests/279.
# If not, then we can't use `--lock`. That should only happen in RHCOS,
# where we only use this for autolocking and not base lockfile management.
help = subprocess.check_output(['/usr/libexec/bootc-base-imagectl', 'build-rootfs', '-h'], encoding='utf-8')
return '--lock NEVRA' in help
return '--lock NEVRA' in get_bootc_base_imagectl_help()
def recommends_arg_supported():
# Detect if we have https://gitlab.com/fedora/bootc/base-images/-/merge_requests/314.
# If not, then we can't use `--recommends` and should error.
return '--recommends' in get_bootc_base_imagectl_help()
def no_initramfs_arg_supported():
# Detect if we have # https://gitlab.com/fedora/bootc/base-images/-/merge_requests/320.
# If not, then we can't use `--no-initramfs`, but that's OK because it's just
# an optimization to prevent building the initramfs twice.
if not '--no-initramfs' in get_bootc_base_imagectl_help():
return False
# Detect if we have https://github.com/coreos/rpm-ostree/commit/481fbb034292666578780bacfdbf3dae9d10e6c3
# At the time of this writing it's unreleased in rpm-ostree but it
# should be in the next release (2025.13 or 2026.1).
out = subprocess.check_output(['rpm-ostree', '--version'], encoding='utf-8')
data = yaml.safe_load(out)
version_str = data['rpm-ostree']['Version']
# ideally, we could use `packaging.version`, but that's not in centos-bootc
# but conveniently, Python list comparisons do the right thing here
version = [int(c) for c in version_str.split('.')]
return version >= [2025, 13]
def workaround_rhel_97826(argsfile):
@@ -217,6 +254,15 @@ def run_postprocess_scripts(rootfs, manifest):
os.unlink(os.path.join(rootfs, name))
def run_dracut(rootfs):
print(f"Running dracut to generate the initramfs", flush=True)
# https://docs.fedoraproject.org/en-US/bootc/initramfs/#_modifying_and_regenerating_the_initrd
kver = bwrap(rootfs, ['ls', '/usr/lib/modules'], capture=True).strip()
bwrap(rootfs, ['env', 'DRACUT_NO_XATTR=1',
'dracut', '--verbose', '--force', '--reproducible',
'--no-hostonly', f"/usr/lib/modules/{kver}/initramfs.img", kver])
def prepare_local_rpm_overrides(rootfs):
overrides_repo = os.path.join(SRCDIR, 'overrides/rpm')
if not os.path.isdir(f'{overrides_repo}/repodata'):
@@ -252,8 +298,9 @@ priority=1
# Could upstream this as e.g. `bootc-base-imagectl runroot /rootfs <cmd>` maybe?
# But we'd need to carry it anyway at least for RHCOS 9.6.
def bwrap(rootfs, args, capture=False):
args = ['bwrap', '--bind', f'{rootfs}', '/', '--dev', '/dev', '--proc',
'/proc', '--tmpfs', '/tmp', '--tmpfs', '/var', '--tmpfs', '/run',
args = ['bwrap', '--bind', f'{rootfs}', '/', '--dev', '/dev',
'--proc', '/proc', '--tmpfs', '/tmp', '--tmpfs', '/var',
'--tmpfs', '/var/tmp', '--tmpfs', '/run',
'--bind', '/run/.containerenv', '/run/.containerenv', '--'] + args
if capture:
return subprocess.check_output(args, encoding='utf-8')
@@ -310,8 +357,6 @@ def inject_version_info(rootfs, base_version, version):
(k, v) = line.split('=', 1)
os_release[k] = v
# The fields modified here match those in inject_dracut_version below. Keep
# them in sync.
for key in ['VERSION', 'PRETTY_NAME']:
os_release[key] = os_release[key].replace(base_version, version)
os_release['OSTREE_VERSION'] = f"'{version}'"
@@ -322,46 +367,6 @@ def inject_version_info(rootfs, base_version, version):
f.write(f'{k}={v}\n')
# This dynamically generates a dracut module which doesn't actually install
# anything in the initrd. It just mutates the initrd-release installed by
# dracut-systemd in the same way we mutate os-release above. Normally, we'd
# only need inject_version_info above and dracut would create its initrd-release
# based on that. But injection happens after the rpm-ostree compose and we want
# to avoid regenerating the initramfs just for that.
def inject_dracut_version(base_version, version):
tmpd = tempfile.TemporaryDirectory()
# we use 99 here so we run last, i.e. after initrd-release exists
module_setup = os.path.join(tmpd.name, 'usr/lib/dracut/modules.d/99dracut-coreos-version/module-setup.sh')
os.makedirs(os.path.dirname(module_setup), exist_ok=True)
with open(module_setup, 'w', encoding='utf-8') as f:
# The fields modified here match those in inject_version_info above.
# Keep them in sync.
f.write(f'''
check() {{ return 0; }}
install() {{
sed -i -E -e '/^(PRETTY_NAME|VERSION)=/ s/{base_version}/{version}/' $initdir/usr/lib/initrd-release
echo "OSTREE_VERSION='{version}'" >> $initdir/usr/lib/initrd-release
echo "IMAGE_VERSION='{version}'" >> $initdir/usr/lib/initrd-release
# XXX SUPER HACK to stamp out the systemd-gpt-auto-generator in the
# initramfs. The rm of the file in a postprocess we do runs after
# the initramfs is generated so we need something like this
# delivered via a dracut module that gets into an overlay in the
# original rpm-ostree compose.
rm -v $initdir/usr/lib/systemd/system-generators/systemd-gpt-auto-generator
}}
''')
return tmpd
def cleanup_dracut_version(rootfs, tmpd):
# we can nuke this from the rootfs now; any dracut regeneration from this
# point on (e.g. in derived builds, or client side) will be able to see the
# os-release changes done by inject_version_info
shutil.rmtree(f'{rootfs}/usr/lib/dracut/modules.d/99dracut-coreos-version')
del tmpd
# This re-implements cosa's overlay logic.
def gather_overlays(manifest):
overlays = []
@@ -463,7 +468,9 @@ def calculate_inputhash(rootfs, overlays, manifest):
all_files = sorted(all_files)
for file in all_files:
with open(file, 'rb') as f:
h.update(hashlib.file_digest(f, 'sha256').digest())
# When python3.11+ is the minimal version we can use hashlib.file_digest
# h.update(hashlib.file_digest(f, 'sha256').digest())
h.update(hashlib.sha256(f.read()).digest())
has_x_bit = os.stat(f.fileno()).st_mode & 0o111 != 0
h.update(bytes([has_x_bit]))