Integrate zosstorage build path and runtime orchestration

Summary:

* add openssh-client to the builder image and mount host SSH keys into the dev container when available

* switch RFS to git builds, register the zosstorage source, and document the extra Rust component

* wire zosstorage into the build: add build_zosstorage(), ship the binary in the initramfs, and extend component validation

* refresh kernel configuration to 6.12.49 while dropping Xen guest selections and enabling counted-by support

* tighten runtime configs: use cached mycelium key path, add zosstorage zinit unit, bootstrap ovsdb-server, and enable openvswitch module

* adjust the network health check ping invocation and fix the RFS pack-tree --debug flag order

* update NOTES changelog, README component list, and introduce a runit helper for qemu/cloud-hypervisor testing

* add ovsdb init script wiring under config/zinit/init and ensure zosstorage is available before mycelium
This commit is contained in:
2025-10-14 17:47:13 +02:00
parent cf05e0ca5b
commit 334821dacf
16 changed files with 441 additions and 95 deletions

263
runit.sh Executable file
View File

@@ -0,0 +1,263 @@
#!/bin/bash
set -e
# Default configuration
HYPERVISOR="${HYPERVISOR:-qemu}" # qemu or ch (cloud-hypervisor)
NUM_DISKS="${NUM_DISKS:-3}"
DISK_SIZE="${DISK_SIZE:-10G}"
DISK_PREFIX="zosvol"
KERNEL="dist/vmlinuz.efi"
MEMORY="2048"
BRIDGE="${BRIDGE:-zosbr}"
TAP_INTERFACE="${TAP_INTERFACE:-zos-tap0}"
# Parse command line arguments
RESET_VOLUMES=false
usage() {
cat <<EOF
Usage: $0 [OPTIONS]
Options:
-H, --hypervisor <qemu|ch> Choose hypervisor (default: qemu)
-d, --disks <N> Number of disks to create (default: 3)
-s, --disk-size <SIZE> Size of each disk (default: 10G)
-r, --reset Delete and recreate all volumes
-m, --memory <MB> Memory in MB (default: 2048)
-b, --bridge <NAME> Network bridge name (default: zosbr)
-h, --help Show this help message
Environment variables:
HYPERVISOR Same as --hypervisor
NUM_DISKS Same as --disks
DISK_SIZE Same as --disk-size
BRIDGE Same as --bridge
Examples:
$0 -H qemu -d 5
$0 --hypervisor ch --reset
$0 -d 4 -r
HYPERVISOR=ch NUM_DISKS=4 $0
EOF
exit 0
}
# Parse arguments using getopt
TEMP=$(getopt -o 'H:d:s:rm:b:h' --long 'hypervisor:,disks:,disk-size:,reset,memory:,bridge:,help' -n "$0" -- "$@")
if [ $? -ne 0 ]; then
echo "Error parsing arguments. Try '$0 --help' for more information."
exit 1
fi
eval set -- "$TEMP"
unset TEMP
while true; do
case "$1" in
'-H' | '--hypervisor')
HYPERVISOR="$2"
shift 2
;;
'-d' | '--disks')
NUM_DISKS="$2"
shift 2
;;
'-s' | '--disk-size')
DISK_SIZE="$2"
shift 2
;;
'-r' | '--reset')
RESET_VOLUMES=true
shift
;;
'-m' | '--memory')
MEMORY="$2"
shift 2
;;
'-b' | '--bridge')
BRIDGE="$2"
shift 2
;;
'-h' | '--help')
usage
;;
'--')
shift
break
;;
*)
echo "Internal error!"
exit 1
;;
esac
done
# Validate hypervisor choice
if [[ "$HYPERVISOR" != "qemu" && "$HYPERVISOR" != "ch" ]]; then
echo "Error: Invalid hypervisor '$HYPERVISOR'. Must be 'qemu' or 'ch'"
exit 1
fi
if [[ "$HYPERVISOR" == "qemu" ]]; then
DISK_SUFFIX="qcow"
DISK_FORMAT="qcow2"
else
DISK_SUFFIX="raw"
DISK_FORMAT="raw"
fi
# Validate kernel exists
if [[ ! -f "$KERNEL" ]]; then
echo "Error: Kernel not found at $KERNEL"
echo "Run the build first: ./scripts/build.sh"
exit 1
fi
# Setup TAP interface for cloud-hypervisor
setup_tap_interface() {
local tap="$1"
local bridge="$2"
echo "Setting up TAP interface $tap for cloud-hypervisor..."
if [[ -z "${CH_TAP_IP:-}" && -z "${CH_TAP_MASK:-}" ]]; then
echo " Reminder: set CH_TAP_IP and CH_TAP_MASK to configure $tap and silence cloud-hypervisor IP warnings."
fi
# Check if bridge exists
if ! ip link show "$bridge" &>/dev/null; then
echo "Warning: Bridge $bridge does not exist. Create it with:"
echo " sudo ip link add name $bridge type bridge"
echo " sudo ip link set $bridge up"
echo ""
read -p "Continue anyway? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
# Check if TAP already exists
if ip link show "$tap" &>/dev/null; then
echo " TAP interface $tap already exists"
# Check if it's already attached to bridge
if bridge link show | grep -q "$tap"; then
echo " $tap is already attached to bridge"
return 0
else
echo " Attaching $tap to bridge $bridge"
sudo ip link set dev "$tap" master "$bridge" 2>/dev/null || true
return 0
fi
fi
# Create new TAP interface
echo " Creating TAP interface $tap"
sudo ip tuntap add "$tap" mode tap user "$(whoami)"
# Bring it up
echo " Bringing up $tap"
sudo ip link set "$tap" up
# Attach to bridge
echo " Attaching $tap to bridge $bridge"
sudo ip link set dev "$tap" master "$bridge"
echo " TAP interface setup complete"
}
# Cleanup TAP interface on exit (for cloud-hypervisor)
cleanup_tap_interface() {
local tap="$1"
if [[ -n "$tap" ]] && ip link show "$tap" &>/dev/null; then
echo "Cleaning up TAP interface $tap"
sudo ip link delete "$tap" 2>/dev/null || true
fi
}
# Reset volumes if requested
if [[ "$RESET_VOLUMES" == "true" ]]; then
echo "Resetting volumes..."
for i in $(seq 0 $((NUM_DISKS - 1))); do
for suffix in qcow raw; do
vol="${DISK_PREFIX}${i}.${suffix}"
if [[ -f "$vol" ]]; then
echo " Removing $vol"
rm -f "$vol"
fi
done
done
fi
# Create disk volumes if they don't exist
echo "Ensuring $NUM_DISKS disk volume(s) exist..."
for i in $(seq 0 $((NUM_DISKS - 1))); do
vol="${DISK_PREFIX}${i}.${DISK_SUFFIX}"
if [[ ! -f "$vol" ]]; then
echo " Creating $vol (size: $DISK_SIZE, format: $DISK_FORMAT)"
qemu-img create -f "$DISK_FORMAT" "$vol" "$DISK_SIZE" >/dev/null
else
echo " $vol already exists"
fi
done
# Build disk arguments based on hypervisor
DISK_ARGS=()
if [[ "$HYPERVISOR" == "qemu" ]]; then
for i in $(seq 0 $((NUM_DISKS - 1))); do
vol="${DISK_PREFIX}${i}.${DISK_SUFFIX}"
DISK_ARGS+=("-drive" "file=$vol,format=$DISK_FORMAT,if=virtio")
done
elif [[ "$HYPERVISOR" == "ch" ]]; then
# cloud-hypervisor requires comma-separated disk list in single --disk argument
# Use raw format (no compression)
CH_DISKS=""
for i in $(seq 0 $((NUM_DISKS - 1))); do
vol="${DISK_PREFIX}${i}.${DISK_SUFFIX}"
if [[ -z "$CH_DISKS" ]]; then
CH_DISKS="path=$vol,iommu=on"
else
CH_DISKS="${CH_DISKS},path=$vol,iommu=on"
fi
done
if [[ -n "$CH_DISKS" ]]; then
DISK_ARGS+=("--disk" "$CH_DISKS")
fi
fi
# Launch the appropriate hypervisor
echo "Launching with $HYPERVISOR hypervisor..."
echo ""
if [[ "$HYPERVISOR" == "qemu" ]]; then
exec qemu-system-x86_64 \
-kernel "$KERNEL" \
-m "$MEMORY" \
-enable-kvm \
-cpu host \
-net nic,model=virtio \
-net bridge,br="$BRIDGE" \
"${DISK_ARGS[@]}" \
-chardev stdio,id=char0,mux=on,logfile=serial.log \
-serial chardev:char0 \
-mon chardev=char0 \
-append "console=ttyS0,115200n8 console=tty"
elif [[ "$HYPERVISOR" == "ch" ]]; then
# Setup TAP interface for cloud-hypervisor
setup_tap_interface "$TAP_INTERFACE" "$BRIDGE"
# Cleanup on exit
trap "cleanup_tap_interface '$TAP_INTERFACE'" EXIT
exec cloud-hypervisor \
--kernel "$KERNEL" \
--memory size="${MEMORY}M" \
--cpus boot=2 \
--net "tap=$TAP_INTERFACE" \
"${DISK_ARGS[@]}" \
--console off \
--serial tty \
--cmdline "console=ttyS0,115200n8"
fi