#!/bin/bash # Define the pxetest network, volumes and VMs. Idempotent: existing # pxetest-* objects are kept (run destroy.sh first to rebuild them). # # pxetest-imaging isolated libvirt network: no , no , so the # host has no address on it and libvirt runs no DHCP. # Bridge virbr-pxetest holds only the VMs' tap devices. # pxetest-server 2 vCPU, 4 GiB, OVMF (Secure Boot, MS keys), 60G thin # qcow2 + the USB image as a USB disk. # NIC1 52:54:00:9e:10:01 on 'default' NAT ("GE/corp") # NIC2 52:54:00:9e:10:02 on pxetest-imaging ("imaging") # pxetest-client 2 vCPU, 2 GiB, OVMF Secure Boot with MS keys, 1G blank # disk, one NIC 52:54:00:9e:10:03 on pxetest-imaging, # network boot first (UEFI IPv4 PXE). # # Usage: tests/vm/create.sh source "$(dirname "$0")/common.sh" TMP=$(mktemp -d) trap 'rm -rf "$TMP"' EXIT # --- isolated imaging network --- if ! net_exists "$IMAGING_NET"; then cat >"$TMP/net.xml" < $IMAGING_NET XML virsh net-define "$TMP/net.xml" >/dev/null log "defined network $IMAGING_NET (isolated, no forward, no ip)" fi virsh net-autostart --disable "$IMAGING_NET" >/dev/null 2>&1 || true if ! net_active "$IMAGING_NET"; then virsh net-start "$IMAGING_NET" >/dev/null fi assert_imaging_isolated net_exists "$GE_NET" || die "libvirt network '$GE_NET' (NAT) does not exist" net_active "$GE_NET" || virsh net-start "$GE_NET" >/dev/null # --- volumes --- if ! vol_exists "$SERVER_DISK_VOL"; then virsh vol-create-as "$POOL" "$SERVER_DISK_VOL" "$SERVER_DISK_SIZE" --format qcow2 >/dev/null log "created $SERVER_DISK_VOL ($SERVER_DISK_SIZE thin qcow2)" fi if ! vol_exists "$CLIENT_DISK_VOL"; then virsh vol-create-as "$POOL" "$CLIENT_DISK_VOL" 1G --format qcow2 >/dev/null log "created $CLIENT_DISK_VOL (1G blank)" fi vol_exists "$USB_VOL" || log "WARNING: no $USB_VOL volume yet; run build-image.sh before start.sh" # Disks are type='file' with the pool's path: with type='volume' sources # qemu got "Permission denied" opening them (AppArmor profile). POOL_DIR=$(virsh pool-dumpxml "$POOL" | sed -n 's|.*\(.*\).*|\1|p' | head -1) [ -n "$POOL_DIR" ] || die "cannot read the path of pool $POOL" # Secure Boot with Microsoft keys enrolled: libvirt picks the edk2 # descriptor (40-edk2-x86_64-secure-enrolled.json) and copies its # OVMF_VARS_4M.ms.fd template into a per-VM nvram. efi_os() { cat < hvm XML } # --- server VM --- # Boot order: the installed disk first, the USB second. A blank disk falls # through to the USB; after the install the disk boots, so autoinstall does # not loop. CIDATA stays attached for the first-boot playbook. if ! dom_exists "$SERVER_VM"; then cat >"$TMP/server.xml" < $SERVER_VM $SERVER_MEM_MIB 2 $(efi_os) restart /dev/urandom XML virsh define "$TMP/server.xml" >/dev/null log "defined $SERVER_VM" fi # --- client VM --- if ! dom_exists "$CLIENT_VM"; then cat >"$TMP/client.xml" < $CLIENT_VM $CLIENT_MEM_MIB 2 $(efi_os) XML virsh define "$TMP/client.xml" >/dev/null log "defined $CLIENT_VM" fi # Never attach a pxetest VM anywhere but default NAT / pxetest-imaging. for vm in "$SERVER_VM" "$CLIENT_VM"; do while read -r _ type src _ _; do case "$type:$src" in network:"$GE_NET") [ "$vm" = "$SERVER_VM" ] || die "$vm is on $GE_NET" ;; network:"$IMAGING_NET") ;; *) die "$vm has an interface on $type:$src (only $GE_NET / $IMAGING_NET allowed)" ;; esac done < <(virsh domiflist "$vm" | tail -n +3 | grep -v '^$') done log "ready. Playbook NIC pins for this site:" log " pxe_imaging_mac: \"$SERVER_IMAGING_MAC\" (pxe_nic_mac)" log " pxe_ge_mac: \"$SERVER_GE_MAC\" (corp_nic_mac)"