Skip to content

Commit

Permalink
podvm-mkosi: build s390x fedora image
Browse files Browse the repository at this point in the history
Package system with mkosi and generate bootloader
with zipl

Signed-off-by: Lei Li <[email protected]>
Signed-off-by: Lei Li <[email protected]>
  • Loading branch information
Lei Li authored and Qi Feng Huo committed Mar 21, 2024
1 parent e82aee5 commit 91f8d73
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 1 deletion.
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:
```
[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
1 change: 0 additions & 1 deletion podvm-mkosi/mkosi.presets/system/mkosi.conf.d/fedora.conf
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

0 comments on commit 91f8d73

Please sign in to comment.