Some checks failed
		
		
	
	Run Check Script / check (pull_request) Failing after 40s
				
			
		
			
				
	
	
		
			192 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env bash
 | 
						|
set -euo pipefail
 | 
						|
 | 
						|
# --- Configuration ---
 | 
						|
LAB_DIR="/var/lib/harmony_pxe_test"
 | 
						|
IMG_DIR="${LAB_DIR}/images"
 | 
						|
STATE_DIR="${LAB_DIR}/state"
 | 
						|
VM_OPN="opnsense-pxe"
 | 
						|
VM_PXE="pxe-node-1"
 | 
						|
NET_HARMONYLAN="harmonylan"
 | 
						|
 | 
						|
# Network settings for the isolated LAN
 | 
						|
VLAN_CIDR="192.168.150.0/24"
 | 
						|
VLAN_GW="192.168.150.1"
 | 
						|
VLAN_MASK="255.255.255.0"
 | 
						|
 | 
						|
# VM Specifications
 | 
						|
RAM_OPN="2048"
 | 
						|
VCPUS_OPN="2"
 | 
						|
DISK_OPN_GB="10"
 | 
						|
OS_VARIANT_OPN="freebsd14.0" # Updated to a more recent FreeBSD variant
 | 
						|
 | 
						|
RAM_PXE="4096"
 | 
						|
VCPUS_PXE="2"
 | 
						|
DISK_PXE_GB="40"
 | 
						|
OS_VARIANT_LINUX="centos-stream9"
 | 
						|
 | 
						|
OPN_IMG_URL="https://mirror.ams1.nl.leaseweb.net/opnsense/releases/25.7/OPNsense-25.7-serial-amd64.img.bz2"
 | 
						|
OPN_IMG_PATH="${IMG_DIR}/OPNsense-25.7-serial-amd64.img"
 | 
						|
CENTOS_ISO_URL="https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/os/images/boot.iso"
 | 
						|
CENTOS_ISO_PATH="${IMG_DIR}/CentOS-Stream-9-latest-boot.iso"
 | 
						|
 | 
						|
CONNECT_URI="qemu:///system"
 | 
						|
 | 
						|
download_if_missing() {
 | 
						|
  local url="$1"
 | 
						|
  local dest="$2"
 | 
						|
  if [[ ! -f "$dest" ]]; then
 | 
						|
    echo "Downloading $url to $dest"
 | 
						|
    mkdir -p "$(dirname "$dest")"
 | 
						|
    local tmp
 | 
						|
    tmp="$(mktemp)"
 | 
						|
    curl -L --progress-bar "$url" -o "$tmp"
 | 
						|
    case "$url" in
 | 
						|
      *.bz2) bunzip2 -c "$tmp" > "$dest" && rm -f "$tmp" ;;
 | 
						|
      *) mv "$tmp" "$dest" ;;
 | 
						|
    esac
 | 
						|
  else
 | 
						|
    echo "Already present: $dest"
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
# Ensures a libvirt network is defined and active
 | 
						|
ensure_network() {
 | 
						|
  local net_name="$1"
 | 
						|
  local net_xml_path="$2"
 | 
						|
  if virsh --connect "${CONNECT_URI}" net-info "${net_name}" >/dev/null 2>&1; then
 | 
						|
    echo "Network ${net_name} already exists."
 | 
						|
  else
 | 
						|
    echo "Defining network ${net_name} from ${net_xml_path}"
 | 
						|
    virsh --connect "${CONNECT_URI}" net-define "${net_xml_path}"
 | 
						|
  fi
 | 
						|
 | 
						|
  if ! virsh --connect "${CONNECT_URI}" net-info "${net_name}" | grep "Active: *yes"; then
 | 
						|
    echo "Starting network ${net_name}..."
 | 
						|
    virsh --connect "${CONNECT_URI}" net-start "${net_name}"
 | 
						|
    virsh --connect "${CONNECT_URI}" net-autostart "${net_name}"
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
# Destroys a VM completely
 | 
						|
destroy_vm() {
 | 
						|
  local vm_name="$1"
 | 
						|
  if virsh --connect "${CONNECT_URI}" dominfo "$vm_name" >/dev/null 2>&1; then
 | 
						|
    echo "Destroying and undefining VM: ${vm_name}"
 | 
						|
    virsh --connect "${CONNECT_URI}" destroy "$vm_name" || true
 | 
						|
    virsh --connect "${CONNECT_URI}" undefine "$vm_name" --nvram
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
# Destroys a libvirt network
 | 
						|
destroy_network() {
 | 
						|
  local net_name="$1"
 | 
						|
  if virsh --connect "${CONNECT_URI}" net-info "$net_name" >/dev/null 2>&1; then
 | 
						|
    echo "Destroying and undefining network: ${net_name}"
 | 
						|
    virsh --connect "${CONNECT_URI}" net-destroy "$net_name" || true
 | 
						|
    virsh --connect "${CONNECT_URI}" net-undefine "$net_name"
 | 
						|
  fi
 | 
						|
}
 | 
						|
 | 
						|
# --- Main Logic ---
 | 
						|
create_lab_environment() {
 | 
						|
  # Create network definition files
 | 
						|
  cat > "${STATE_DIR}/default.xml" <<EOF
 | 
						|
<network>
 | 
						|
  <name>default</name>
 | 
						|
  <forward mode='nat'/>
 | 
						|
  <bridge name='virbr0' stp='on' delay='0'/>
 | 
						|
  <ip address='192.168.122.1' netmask='255.255.255.0'>
 | 
						|
    <dhcp>
 | 
						|
      <range start='192.168.122.100' end='192.168.122.200'/>
 | 
						|
    </dhcp>
 | 
						|
  </ip>
 | 
						|
</network>
 | 
						|
EOF
 | 
						|
 | 
						|
  cat > "${STATE_DIR}/${NET_HARMONYLAN}.xml" <<EOF
 | 
						|
<network>
 | 
						|
  <name>${NET_HARMONYLAN}</name>
 | 
						|
  <bridge name='virbr1' stp='on' delay='0'/>
 | 
						|
</network>
 | 
						|
EOF
 | 
						|
 | 
						|
  # Ensure both networks exist and are active
 | 
						|
  ensure_network "default" "${STATE_DIR}/default.xml"
 | 
						|
  ensure_network "${NET_HARMONYLAN}" "${STATE_DIR}/${NET_HARMONYLAN}.xml"
 | 
						|
 | 
						|
  # --- Create OPNsense VM (MODIFIED SECTION) ---
 | 
						|
  local disk_opn="${IMG_DIR}/${VM_OPN}.qcow2"
 | 
						|
  if [[ ! -f "$disk_opn" ]]; then
 | 
						|
    qemu-img create -f qcow2 "$disk_opn" "${DISK_OPN_GB}G"
 | 
						|
  fi
 | 
						|
 | 
						|
  echo "Creating OPNsense VM using serial image..."
 | 
						|
  virt-install \
 | 
						|
    --connect "${CONNECT_URI}" \
 | 
						|
    --name "${VM_OPN}" \
 | 
						|
    --ram "${RAM_OPN}" \
 | 
						|
    --vcpus "${VCPUS_OPN}" \
 | 
						|
    --cpu host-passthrough \
 | 
						|
    --os-variant "${OS_VARIANT_OPN}" \
 | 
						|
    --graphics none \
 | 
						|
    --noautoconsole \
 | 
						|
    --disk path="${disk_opn}",device=disk,bus=virtio,boot.order=1 \
 | 
						|
    --disk path="${OPN_IMG_PATH}",device=disk,bus=usb,readonly=on,boot.order=2 \
 | 
						|
    --network network=default,model=virtio \
 | 
						|
    --network network="${NET_HARMONYLAN}",model=virtio \
 | 
						|
    --boot uefi,menu=on
 | 
						|
 | 
						|
  echo "OPNsense VM created. Connect with: sudo virsh console ${VM_OPN}"
 | 
						|
  echo "The VM will boot from the serial installation image."
 | 
						|
  echo "Login with user 'installer' and password 'opnsense' to start the installation."
 | 
						|
  echo "Install onto the VirtIO disk (vtbd0)."
 | 
						|
  echo "After installation, shutdown the VM, then run 'sudo virsh edit ${VM_OPN}' and remove the USB disk block to boot from the installed system."
 | 
						|
 | 
						|
  # --- Create PXE Client VM ---
 | 
						|
  local disk_pxe="${IMG_DIR}/${VM_PXE}.qcow2"
 | 
						|
  if [[ ! -f "$disk_pxe" ]]; then
 | 
						|
    qemu-img create -f qcow2 "$disk_pxe" "${DISK_PXE_GB}G"
 | 
						|
  fi
 | 
						|
 | 
						|
  echo "Creating PXE client VM..."
 | 
						|
  virt-install \
 | 
						|
    --connect "${CONNECT_URI}" \
 | 
						|
    --name "${VM_PXE}" \
 | 
						|
    --ram "${RAM_PXE}" \
 | 
						|
    --vcpus "${VCPUS_PXE}" \
 | 
						|
    --cpu host-passthrough \
 | 
						|
    --os-variant "${OS_VARIANT_LINUX}" \
 | 
						|
    --graphics none \
 | 
						|
    --noautoconsole \
 | 
						|
    --disk path="${disk_pxe}",format=qcow2,bus=virtio \
 | 
						|
    --network network="${NET_HARMONYLAN}",model=virtio \
 | 
						|
    --pxe \
 | 
						|
    --boot uefi,menu=on
 | 
						|
 | 
						|
  echo "PXE VM created. It will attempt to netboot on ${NET_HARMONYLAN}."
 | 
						|
}
 | 
						|
 | 
						|
# --- Script Entrypoint ---
 | 
						|
case "${1:-}" in
 | 
						|
  up)
 | 
						|
    mkdir -p "${IMG_DIR}" "${STATE_DIR}"
 | 
						|
    download_if_missing "$OPN_IMG_URL" "$OPN_IMG_PATH"
 | 
						|
    download_if_missing "$CENTOS_ISO_URL" "$CENTOS_ISO_PATH"
 | 
						|
    create_lab_environment
 | 
						|
    echo "Lab setup complete. Use 'sudo virsh list --all' to see VMs."
 | 
						|
    ;;
 | 
						|
  clean)
 | 
						|
    destroy_vm "${VM_PXE}"
 | 
						|
    destroy_vm "${VM_OPN}"
 | 
						|
    destroy_network "${NET_HARMONYLAN}"
 | 
						|
    # Optionally destroy the default network if you want a full reset
 | 
						|
    # destroy_network "default"
 | 
						|
    echo "Cleanup complete."
 | 
						|
    ;;
 | 
						|
  *)
 | 
						|
    echo "Usage: sudo $0 {up|clean}"
 | 
						|
    exit 1
 | 
						|
    ;;
 | 
						|
esac
 |