Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

live-iso: enable building with squashfs or erofs #4012

Merged
merged 6 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 41 additions & 43 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ fi
arch=$(uname -m)

if [ $# -gt 1 ]; then
echo Usage: "build.sh [CMD]"
echo "Supported commands:"
echo " configure_user"
echo " configure_yum_repos"
echo " install_rpms"
echo " make_and_makeinstall"
echo " patch_osbuild"
exit 1
echo Usage: "build.sh [CMD]"
echo "Supported commands:"
echo " configure_user"
echo " configure_yum_repos"
echo " install_rpms"
echo " make_and_makeinstall"
echo " patch_osbuild"
exit 1
fi

set -x
Expand Down Expand Up @@ -158,43 +158,41 @@ write_archive_info() {
}

patch_osbuild() {
return # we have no patches right now

## Add a few patches that either haven't made it into a release or
## that will be obsoleted with other work that will be done soon.

## To make it easier to apply patches we'll move around the osbuild
## code on the system first:
#rmdir /usr/lib/osbuild/osbuild
#mv /usr/lib/python3.13/site-packages/osbuild /usr/lib/osbuild/
#mkdir /usr/lib/osbuild/tools
#mv /usr/bin/osbuild-mpp /usr/lib/osbuild/tools/

## Now all the software is under the /usr/lib/osbuild dir and we can patch
#cat patch1.patch \
# patch2.patch \
# | patch -d /usr/lib/osbuild -p1

## And then move the files back; supermin appliance creation will need it back
## in the places delivered by the RPM.
#mv /usr/lib/osbuild/tools/osbuild-mpp /usr/bin/osbuild-mpp
#mv /usr/lib/osbuild/osbuild /usr/lib/python3.13/site-packages/osbuild
#mkdir /usr/lib/osbuild/osbuild
# Add a few patches that either haven't made it into a release or
# that will be obsoleted with other work that will be done soon.

# To make it easier to apply patches we'll move around the osbuild
# code on the system first:
rmdir /usr/lib/osbuild/osbuild
mv /usr/lib/python3.13/site-packages/osbuild /usr/lib/osbuild/
mkdir /usr/lib/osbuild/tools
mv /usr/bin/osbuild-mpp /usr/lib/osbuild/tools/

# Now all the software is under the /usr/lib/osbuild dir and we can patch
cat /usr/lib/coreos-assembler/0001-stages-coreos.live-artifacts-add-erofs-support.patch \
/usr/lib/coreos-assembler/0002-stages-coreos.live-artifacts-update-comments-names-t.patch \
| patch -d /usr/lib/osbuild -p1

# And then move the files back; supermin appliance creation will need it back
# in the places delivered by the RPM.
mv /usr/lib/osbuild/tools/osbuild-mpp /usr/bin/osbuild-mpp
mv /usr/lib/osbuild/osbuild /usr/lib/python3.13/site-packages/osbuild
mkdir /usr/lib/osbuild/osbuild
}

if [ $# -ne 0 ]; then
# Run the function specified by the calling script
${1}
# Run the function specified by the calling script
${1}
else
# Otherwise, just run all the steps. NOTE: This is presently not actually
# used in `Dockerfile`, so if you add a stage you'll need to do it both
# here and there.
configure_yum_repos
install_rpms
write_archive_info
make_and_makeinstall
install_ocp_tools
trust_redhat_gpg_keys
configure_user
patch_osbuild
# Otherwise, just run all the steps. NOTE: This is presently not actually
# used in `Dockerfile`, so if you add a stage you'll need to do it both
# here and there.
configure_yum_repos
install_rpms
write_archive_info
make_and_makeinstall
install_ocp_tools
trust_redhat_gpg_keys
configure_user
patch_osbuild
fi
9 changes: 9 additions & 0 deletions mantle/cmd/kola/testiso.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"io"
"os"
"path/filepath"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -391,6 +392,14 @@ func newBaseQemuBuilder(outdir string) (*platform.QemuBuilder, error) {
builder.ConsoleFile = filepath.Join(outdir, "console.txt")
}

if kola.QEMUOptions.Memory != "" {
parsedMem, err := strconv.ParseInt(kola.QEMUOptions.Memory, 10, 32)
if err != nil {
return nil, err
}
builder.MemoryMiB = int(parsedMem)
}

return builder, nil
}

Expand Down
149 changes: 149 additions & 0 deletions src/0001-stages-coreos.live-artifacts-add-erofs-support.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
From 2f26befc8213831950ca415b739c98eeb0d904bc Mon Sep 17 00:00:00 2001
From: Nikita Dubrovskii <[email protected]>
Date: Tue, 28 Jan 2025 12:20:40 +0100
Subject: [PATCH] stages/coreos.live-artifacts: add erofs support

---
stages/org.osbuild.coreos.live-artifacts.mono | 65 ++++++++++++-------
1 file changed, 42 insertions(+), 23 deletions(-)

diff --git a/stages/org.osbuild.coreos.live-artifacts.mono b/stages/org.osbuild.coreos.live-artifacts.mono
index ca5891cc..f3f7178f 100755
--- a/stages/org.osbuild.coreos.live-artifacts.mono
+++ b/stages/org.osbuild.coreos.live-artifacts.mono
@@ -83,13 +83,14 @@ def mkinitrd_pipe(tmproot, destf, compress=True):
files = subprocess.check_output(['find', '.', '-mindepth', '1', '-print0'],
cwd=tmproot)
file_list = files.split(b'\0')
- # If there's a root.squashfs, it _must_ be the first file in the cpio
+ # If there's a root.[squash|ero]fs, it _must_ be the first file in the cpio
# archive, since the dracut 20live module assumes its contents are at
# a fixed offset in the archive.
- squashfs = b'./root.squashfs'
- if squashfs in file_list:
- file_list.remove(squashfs)
- file_list.insert(0, squashfs)
+ for filename in [b'./root.squashfs', b'./root.erofs']:
+ if filename in file_list:
+ file_list.remove(filename)
+ file_list.insert(0, filename)
+ break
cpioproc = subprocess.Popen(['cpio', '-o', '-H', 'newc', '-R', 'root:root',
'--quiet', '--reproducible', '--force-local', '--null',
'-D', tmproot], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
@@ -544,14 +545,13 @@ boot
return "images/efiboot.img"


-def mksquashfs_metal(paths, workdir, img_metal, loop_client):
+def mkrootfs_metal(paths, workdir, img_metal, fstype, fsoptions, loop_client):
"""
- Mounts a copy of the metal image and modifies it accordingly to create a (squashfs) rootfs from its contents for the
- live ISO.
+ Mounts a copy of the metal image and modifies it accordingly to create a (fstype) rootfs from its contents for the
+ live ISO. fstype must be squashfs or erofs.

Returns the bls entry kernel arguments for the ISO bootloader.
"""
- squashfs_compression = 'zstd'
basearch = os.uname().machine
tmp_squashfs_dir = os.path.join(workdir, 'tmp-squashfs-dir')
os.mkdir(tmp_squashfs_dir)
@@ -601,17 +601,23 @@ def mksquashfs_metal(paths, workdir, img_metal, loop_client):
print(f"Kernel binary linked: {tmp_squashfs_dir}/boot/{kernel_binary_basename}")
print(f"Kernel HMAC linked: {tmp_squashfs_dir}/boot/{kernel_hmac_basename}")
# Generate root squashfs
- print(f'Compressing squashfs with {squashfs_compression}')
+ print(f'Creating {fstype} with {fsoptions}')

# Note the filename must be exactly "root.squashfs" because the 20live
# dracut module makes assumptions about the length of the name in sysroot.mount
# this matches the set of flags we implicitly passed when doing this
# through libguestfs' mksquashfs command
- subprocess.check_call(['mksquashfs', tmp_squashfs_dir,
- paths["initrd-rootfs/root.squashfs"],
- '-root-becomes', tmp_squashfs_dir,
- '-wildcards', '-no-recovery',
- '-comp', squashfs_compression])
+ if fstype == "erofs":
+ subprocess.check_call(['mkfs.erofs',
+ *fsoptions.split(' '),
+ paths["initrd-rootfs/root.erofs"],
+ tmp_squashfs_dir])
+ else:
+ subprocess.check_call(['mksquashfs', tmp_squashfs_dir,
+ paths["initrd-rootfs/root.squashfs"],
+ '-root-becomes', tmp_squashfs_dir,
+ '-wildcards', '-no-recovery',
+ *fsoptions.split(' ')])

# while it's mounted here, also get the kargs
blsentry = ensure_glob(os.path.join(tmp_squashfs_dir, 'boot/loader/entries/*.conf'), n=1)[0]
@@ -776,7 +782,7 @@ def mk_osmet_files(deployed_tree, img_metal, img_metal4k, loop_client, paths, os
chroot.run(cmd, check=True)


-def mk_paths(workdir):
+def mk_paths(workdir, fstype):
"""
Returns a dictionary with all the paths under workdir needed throughout multiple functions in the stage.
"""
@@ -808,7 +814,7 @@ def mk_paths(workdir):
"initrd/etc/coreos-live-want-rootfs": "",
"initrd/etc/coreos-live-initramfs": "",
"initrd-rootfs": "",
- "initrd-rootfs/root.squashfs": "",
+ f"initrd-rootfs/root.{fstype}": ""
}
for key in paths:
paths[key] = os.path.join(workdir, key)
@@ -864,7 +870,13 @@ def main(workdir, tree, inputs, options, loop_client):
os_release = osrelease.parse_files(os.path.join(deployed_tree, 'etc', 'os-release'))
version = os_release['OSTREE_VERSION']

- paths = mk_paths(workdir)
+ # Check whether live-rootfs options set
+ with open(os.path.join(deployed_tree, "usr/share/coreos-assembler", "image.json"), "r", encoding="utf8") as f:
+ parsed = json.load(f)
+ fstype = parsed.get("live-rootfs-fstype", "squashfs")
+ fsoptions = parsed.get("live-rootfs-fsoptions", "-comp zstd" if fstype == "squashfs" else "--quiet")
+
+ paths = mk_paths(workdir, fstype)
mk_workdirs(paths)

# Find the directory under `/usr/lib/modules/<kver>` where the
@@ -905,19 +917,26 @@ def main(workdir, tree, inputs, options, loop_client):

mk_osmet_files(deployed_tree, img_metal, img_metal4k, loop_client, paths, os_release)

- blsentry_kargs = mksquashfs_metal(paths, workdir, img_metal, loop_client)
+ blsentry_kargs = mkrootfs_metal(paths, workdir, img_metal, fstype, fsoptions, loop_client)

# Generate rootfs image
# The rootfs must be uncompressed because the ISO mounts root.squashfs
# directly from the middle of the file
extend_initramfs(initramfs=paths["iso/images/pxeboot/rootfs.img"],
tree=paths["initrd-rootfs"], compress=False)
- # Check that the root.squashfs magic number is in the offset hardcoded
+ # Check that the root.[squash|ero]fs magic number is in the offset hardcoded
# in sysroot.mount in 20live/live-generator
+ offset = 124
+ magic = b'hsqs' # squashfs magic
+ if fstype == "erofs":
+ # The erofs's superblock starts at an absolute offset 1024 bytes
+ # https://erofs.docs.kernel.org/en/latest/core_ondisk.html#superblock
+ offset += 1024
+ magic = bytes.fromhex("e2e1f5e0")
with open(paths["iso/images/pxeboot/rootfs.img"], 'rb') as fh:
- fh.seek(124)
- if fh.read(4) != b'hsqs':
- raise ValueError("root.squashfs not at expected offset in rootfs image")
+ fh.seek(offset)
+ if fh.read(4) != magic:
+ raise ValueError(f"root.{fstype} not at expected offset in rootfs image")
# Save stream hash of rootfs for verifying out-of-band fetches
os.makedirs(os.path.dirname(paths["initrd/etc/coreos-live-want-rootfs"]), exist_ok=True)
make_stream_hash(paths["iso/images/pxeboot/rootfs.img"],
--
2.48.1

104 changes: 104 additions & 0 deletions src/0002-stages-coreos.live-artifacts-update-comments-names-t.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
From 5cd28460d7c54cffb74990ddaab6bd62483433cb Mon Sep 17 00:00:00 2001
From: Nikita Dubrovskii <[email protected]>
Date: Wed, 12 Feb 2025 07:59:54 +0100
Subject: [PATCH 2/2] stages/coreos.live-artifacts: update comments/names to
reflect erofs related changes

---
stages/org.osbuild.coreos.live-artifacts.mono | 42 +++++++++----------
1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/stages/org.osbuild.coreos.live-artifacts.mono b/stages/org.osbuild.coreos.live-artifacts.mono
index f3f7178f..302b24d3 100755
--- a/stages/org.osbuild.coreos.live-artifacts.mono
+++ b/stages/org.osbuild.coreos.live-artifacts.mono
@@ -553,8 +553,8 @@ def mkrootfs_metal(paths, workdir, img_metal, fstype, fsoptions, loop_client):
Returns the bls entry kernel arguments for the ISO bootloader.
"""
basearch = os.uname().machine
- tmp_squashfs_dir = os.path.join(workdir, 'tmp-squashfs-dir')
- os.mkdir(tmp_squashfs_dir)
+ tmp_rootfs_dir = os.path.join(workdir, 'tmp-rootfs-dir')
+ os.mkdir(tmp_rootfs_dir)

# Since inputs are read-only and we want to modify it, we'll make a
# copy of the metal.raw image and then mount that.
@@ -569,13 +569,13 @@ def mkrootfs_metal(paths, workdir, img_metal, fstype, fsoptions, loop_client):
# If mounted via the manifest, the stage begins with mounts already in place,
# but osmet also performs a mount operation, leading to conflicts due to duplicate
# filesystem UUIDs. Perform the manual mount only after the osmet stage
- subprocess.check_call(['mount', '-o', 'rw', loopdev + 'p4', tmp_squashfs_dir])
- cm.callback(subprocess.run, ['umount', '-R', tmp_squashfs_dir], check=True)
+ subprocess.check_call(['mount', '-o', 'rw', loopdev + 'p4', tmp_rootfs_dir])
+ cm.callback(subprocess.run, ['umount', '-R', tmp_rootfs_dir], check=True)
subprocess.check_call(['mount', '-o', 'rw', loopdev + 'p3',
- os.path.join(tmp_squashfs_dir, 'boot')])
+ os.path.join(tmp_rootfs_dir, 'boot')])
if basearch in ['x86_64', 'aarch64']:
subprocess.check_call(['mount', '-o', 'rw', loopdev + 'p2',
- os.path.join(tmp_squashfs_dir, 'boot/efi')])
+ os.path.join(tmp_rootfs_dir, 'boot/efi')])

# Implements necessary CoreOS adjustments
# including creating hardlinks in the /boot/ filesystem
@@ -584,43 +584,41 @@ def mkrootfs_metal(paths, workdir, img_metal, fstype, fsoptions, loop_client):
# Make sure to create it, if it is not created yet.

# Remove the sysroot=readonly flag, see https://github.com/ostreedev/ostree/issues/1921
- subprocess.check_call(['sed', '-i', '/readonly=true/d', f'{tmp_squashfs_dir}/ostree/repo/config'])
+ subprocess.check_call(['sed', '-i', '/readonly=true/d', f'{tmp_rootfs_dir}/ostree/repo/config'])

# And ensure that the kernel binary and hmac file is in the place that dracut
# expects it to be; xref https://issues.redhat.com/browse/OCPBUGS-15843

- kernel_binary = glob.glob(f"{tmp_squashfs_dir}/boot/ostree/*/vmlinuz*")[0]
- kernel_hmac = glob.glob(f"{tmp_squashfs_dir}/boot/ostree/*/.*.hmac")[0]
+ kernel_binary = glob.glob(f"{tmp_rootfs_dir}/boot/ostree/*/vmlinuz*")[0]
+ kernel_hmac = glob.glob(f"{tmp_rootfs_dir}/boot/ostree/*/.*.hmac")[0]
kernel_binary_basename = os.path.basename(kernel_binary)
kernel_hmac_basename = os.path.basename(kernel_hmac)

# Create hard links in the /boot directory
- os.link(kernel_hmac, f"{tmp_squashfs_dir}/boot/{kernel_hmac_basename}")
- os.link(kernel_binary, f"{tmp_squashfs_dir}/boot/{kernel_binary_basename}")
+ os.link(kernel_hmac, f"{tmp_rootfs_dir}/boot/{kernel_hmac_basename}")
+ os.link(kernel_binary, f"{tmp_rootfs_dir}/boot/{kernel_binary_basename}")

- print(f"Kernel binary linked: {tmp_squashfs_dir}/boot/{kernel_binary_basename}")
- print(f"Kernel HMAC linked: {tmp_squashfs_dir}/boot/{kernel_hmac_basename}")
- # Generate root squashfs
+ print(f"Kernel binary linked: {tmp_rootfs_dir}/boot/{kernel_binary_basename}")
+ print(f"Kernel HMAC linked: {tmp_rootfs_dir}/boot/{kernel_hmac_basename}")
+ # Generate root squashfs/erofs
print(f'Creating {fstype} with {fsoptions}')

- # Note the filename must be exactly "root.squashfs" because the 20live
- # dracut module makes assumptions about the length of the name in sysroot.mount
- # this matches the set of flags we implicitly passed when doing this
- # through libguestfs' mksquashfs command
+ # Note the filename must be exactly "root.[squash|ero]fs"
+ # because the 35coreos-live dracut module requires it.
if fstype == "erofs":
subprocess.check_call(['mkfs.erofs',
*fsoptions.split(' '),
paths["initrd-rootfs/root.erofs"],
- tmp_squashfs_dir])
+ tmp_rootfs_dir])
else:
- subprocess.check_call(['mksquashfs', tmp_squashfs_dir,
+ subprocess.check_call(['mksquashfs', tmp_rootfs_dir,
paths["initrd-rootfs/root.squashfs"],
- '-root-becomes', tmp_squashfs_dir,
+ '-root-becomes', tmp_rootfs_dir,
'-wildcards', '-no-recovery',
*fsoptions.split(' ')])

# while it's mounted here, also get the kargs
- blsentry = ensure_glob(os.path.join(tmp_squashfs_dir, 'boot/loader/entries/*.conf'), n=1)[0]
+ blsentry = ensure_glob(os.path.join(tmp_rootfs_dir, 'boot/loader/entries/*.conf'), n=1)[0]
blsentry_kargs = []
with open(blsentry, encoding='utf8') as f:
for line in f:
--
2.48.1

Loading
Loading