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

podvm-mkosi: support to build s390x fedora image #1753

Merged
merged 1 commit into from
Mar 21, 2024
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
85 changes: 85 additions & 0 deletions hack/build-s390x-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/bash

set -euo pipefail

pushd ../podvm-mkosi/build

workdir=.
tmp_img_path="${workdir}/tmp.qcow2"
tmp_nbd=/dev/nbd1
dst_mnt=./dst_mnt
disksize=100G

qemu-img create -f qcow2 "${tmp_img_path}" "${disksize}"

modprobe nbd
qemu-nbd --connect="${tmp_nbd}" "${tmp_img_path}"

# Partition and format
parted -a optimal "${tmp_nbd}" mklabel gpt \
mkpart boot ext4 1MiB 256MiB \
mkpart system 256MiB "${disksize}" \
set 1 boot on

echo "Waiting for the two nbd partitions to show up"
while true; do
sleep 1
[[ -e "${tmp_nbd}"p2 ]] && break
done

mke2fs -t ext4 -L boot "${tmp_nbd}"p1
boot_uuid=$(blkid "${tmp_nbd}"p1 -s PARTUUID -o value)

mke2fs -t ext4 -L system "${tmp_nbd}"p2
system_uuid=$(blkid "${tmp_nbd}"p2 -s PARTUUID -o value)

# Copy files
mkdir -p "${dst_mnt}"
mount "${tmp_nbd}p2" "${dst_mnt}"

mkdir -p "${dst_mnt}"/boot
mount -o norecovery "${tmp_nbd}"p1 "${dst_mnt}"/boot

cp initrd.cpio.zst "${dst_mnt}"/boot/initrd.img
cp system.vmlinuz "${dst_mnt}"/boot/vmlinuz

src_mnt=system
tar_opts=(--numeric-owner --preserve-permissions --acl --selinux --xattrs --xattrs-include='*' --sparse)
tar -cf - "${tar_opts[@]}" --sort=none -C "${src_mnt}" . | tar -xf - "${tar_opts[@]}" --preserve-order -C "${dst_mnt}"

cat <<END > "${dst_mnt}/etc/fstab"
#This file was auto-generated
PARTUUID=${system_uuid} / ext4 defaults 1 1
PARTUUID=${boot_uuid} /boot ext4 norecovery 1 2
END

mount -t sysfs sysfs "${dst_mnt}/sys"
mount -t proc proc "${dst_mnt}/proc"
mount --bind /dev "${dst_mnt}/dev"

# generate bootloader
chroot "${dst_mnt}" zipl -V --targetbase "${tmp_nbd}" \
--targettype scsi \
--targetblocksize 512 \
--targetoffset 2048 \
--target /boot \
--image /boot/vmlinuz \
--ramdisk /boot/initrd.img \
--parameters "root=LABEL=system selinux=0 enforcing=0 audit=0 systemd.firstboot=off"

umount "${dst_mnt}/dev"
umount "${dst_mnt}/proc"
umount "${dst_mnt}/sys"

umount "${dst_mnt}/boot"
umount "${dst_mnt}"

qemu-nbd --disconnect "${tmp_nbd}"

output_img_name="podvm-s390x.qcow2"
qemu-img convert -O qcow2 -c "${tmp_img_path}" "${output_img_name}"

output_img_path=$(realpath "${output_img_name}")
echo "podvm image is generated: ${output_img_path}"

popd
10 changes: 10 additions & 0 deletions podvm-mkosi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,25 @@ image:
rm -rf resources/buildDebugImage
rm -rf ./build
@echo "Building image..."
ifeq ($(ARCH),s390x)
mkosi --profile production.conf
../hack/build-s390x-image.sh
else
nix develop ..#podvm-mkosi --command mkosi --environment=VARIANT_ID=production
endif

PHONY: image-debug
image-debug:
@echo "Enabling debug preset..."
touch resources/buildDebugImage
rm -rf ./build
@echo "Building debug image..."
ifeq ($(ARCH),s390x)
mkosi --profile debug.conf
../hack/build-s390x-image.sh
else
nix develop ..#podvm-mkosi --command mkosi --environment=VARIANT_ID=debug
endif

PHONY: clean
clean:
Expand Down
24 changes: 24 additions & 0 deletions podvm-mkosi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,27 @@ reduce complexity of configuration and CI and shall not be seen as open to-dos.

- Deployed images cannot be customized with cloud-init. Runtime configuration data is retrieved
from IMDS via the project's `process-user-data` tool.

## Build s390x image
Since the [nix OS](https://nixos.org/download/#download-nix) does not support s390x, we can use the mkosi **ToolsTree** feature defined in `mkosi.conf` to download latest tools automatically:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ToolsTree is interesting. could this be replacement for the nix flake on all architectures? It would be good to have a common way, and if it supports reproducible builds that could be an option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into it, mkosi still needs certain tools to be present on the host, so a py virtualenv + ToolsTree cannot fully replace nix yet

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's doable, I like the idea to also use ToolsTree for x86 for alignment. Maybe worth to try.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried ToolsTree on ubuntu host to build the fedora image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On my side it was lacking the yum/rpm tools that are used to bootstrap a ToolsTree, but it might be due to an outdated local env. we should look into this, but it doesn't have to be in the scope of this PR.

```
[Host]
ToolsTree=default
```
And install **mkosi** from the repository:
```sh
git clone -b v21 https://github.com/systemd/mkosi
ln -s $PWD/mkosi/bin/mkosi /usr/local/bin/mkosi
mkosi --version
```
Another issue is s390x does not support UEFI. Instead, we can first use **mkosi** to build non-bootable system files, then use **zipl** to generate the bootloader and finally create the bootable image.

It requires a **s390x host** to build s390x image with make commands:
```
make fedora-binaries-builder
make binaries
make image
# make image-debug
```

The final output is `build/podvm-s390x.qcow2`, which can be used as the Pod VM image in libvirt environment.
10 changes: 10 additions & 0 deletions podvm-mkosi/mkosi.presets/initrd/mkosi.conf.d/fedora-s390x.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Match]
Distribution=fedora

Architecture=s390x

[Content]
Packages=kernel-core

[Host]
ToolsTree=default
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[Match]
Distribution=fedora

Architecture=!s390x

[Content]
Packages=systemd-boot
18 changes: 18 additions & 0 deletions podvm-mkosi/mkosi.presets/system/mkosi.conf.d/fedora-s390x.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[Match]
Distribution=fedora

Architecture=s390x

[Content]
Bootable=no
Packages=s390utils
dhclient
NetworkManager
cloud-init
cloud-utils-growpart

[Output]
Format=directory

[Host]
ToolsTree=default
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ Packages=
udev
util-linux
systemd
systemd-boot
systemd-networkd
systemd-resolved
dbus
Expand Down
14 changes: 14 additions & 0 deletions podvm-mkosi/mkosi.presets/system/mkosi.finalize.chroot
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

set -euxo pipefail

if [[ "${ARCHITECTURE}" == "s390x" ]]; then
# enable cloud-init services
systemctl enable cloud-init-local.service
systemctl enable cloud-init.service
systemctl enable cloud-config.service
systemctl enable cloud-final.service

# disable this service since we already have "NetworkManager-wait-online.service"
systemctl disable systemd-networkd-wait-online.service
fi
2 changes: 2 additions & 0 deletions podvm-mkosi/mkosi.profiles/debug.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Content]
Environment=VARIANT_ID=debug
2 changes: 2 additions & 0 deletions podvm-mkosi/mkosi.profiles/production.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Content]
Environment=VARIANT_ID=production
Loading