208 lines
5.1 KiB
Text
208 lines
5.1 KiB
Text
# VM Hypervisor Detection System
|
|
#
|
|
# Detects available hypervisor capabilities on host system.
|
|
# Follows Rule 1 (single purpose) and Rule 2 (explicit types).
|
|
# Error handling: do/complete pattern (no try-catch)
|
|
|
|
export def "detect-hypervisors" []: table {
|
|
"""Detect all available hypervisors on the system"""
|
|
|
|
let kvm_available = (detect-kvm)
|
|
let libvirt_available = (detect-libvirt)
|
|
let qemu_available = (detect-qemu)
|
|
let docker_available = (detect-docker)
|
|
|
|
[
|
|
$kvm_available,
|
|
$libvirt_available,
|
|
$qemu_available,
|
|
$docker_available,
|
|
] | compact
|
|
}
|
|
|
|
def detect-kvm []: record {
|
|
"""Detect KVM kernel module and CPU support"""
|
|
|
|
# Check CPU support (vmx=Intel, svm=AMD)
|
|
let cpu_support = (
|
|
open /proc/cpuinfo
|
|
| grep -E "vmx|svm"
|
|
| length
|
|
) > 0
|
|
|
|
if not $cpu_support {
|
|
return null
|
|
}
|
|
|
|
# Check if module is loaded
|
|
let module_loaded = (
|
|
lsmod
|
|
| grep "^kvm "
|
|
| length
|
|
) > 0
|
|
|
|
# Check /dev/kvm device
|
|
let device_present = ("/dev/kvm" | path exists)
|
|
|
|
{
|
|
name: "kvm"
|
|
available: (if ($module_loaded and $device_present) { "ready" } else { "available" })
|
|
cpu_support: $cpu_support
|
|
module_loaded: $module_loaded
|
|
device_present: $device_present
|
|
description: "Kernel-based Virtual Machine"
|
|
}
|
|
}
|
|
|
|
def detect-libvirt []: record {
|
|
"""Detect libvirt daemon"""
|
|
|
|
# Check if package is installed (no try-catch)
|
|
let installed = (
|
|
let result = (do { virsh --version -q } | complete)
|
|
$result.exit_code == 0 and (($result.stdout | length) > 0)
|
|
)
|
|
|
|
if not $installed {
|
|
return null
|
|
}
|
|
|
|
# Check if service is running (no try-catch)
|
|
let running = (
|
|
let result = (do { systemctl is-active --quiet libvirtd } | complete)
|
|
$result.exit_code == 0
|
|
)
|
|
|
|
# Check libvirt socket
|
|
let socket_present = ("/var/run/libvirt/libvirt-sock" | path exists)
|
|
|
|
{
|
|
name: "libvirt"
|
|
available: (if $running { "ready" } else { "available" })
|
|
installed: $installed
|
|
running: $running
|
|
socket_present: $socket_present
|
|
description: "libvirt virtualization management"
|
|
}
|
|
}
|
|
|
|
def detect-qemu []: record {
|
|
"""Detect QEMU emulator"""
|
|
|
|
# Check if QEMU is installed (no try-catch)
|
|
let installed = (
|
|
let result = (do { qemu-system-x86_64 --version } | complete)
|
|
$result.exit_code == 0 and (($result.stdout | length) > 0)
|
|
)
|
|
|
|
if not $installed {
|
|
return null
|
|
}
|
|
|
|
# Get supported architectures
|
|
let archs = [
|
|
"x86_64",
|
|
"i386",
|
|
"aarch64",
|
|
"arm",
|
|
]
|
|
|
|
{
|
|
name: "qemu"
|
|
available: "available"
|
|
installed: $installed
|
|
architectures: $archs
|
|
description: "QEMU machine emulator"
|
|
}
|
|
}
|
|
|
|
def detect-docker []: record {
|
|
"""Detect Docker Desktop VM support (macOS/Windows)"""
|
|
|
|
# Check if Docker is installed (no try-catch)
|
|
let docker_installed = (
|
|
let result = (do { docker --version } | complete)
|
|
$result.exit_code == 0 and (($result.stdout | length) > 0)
|
|
)
|
|
|
|
if not $docker_installed {
|
|
return null
|
|
}
|
|
|
|
# Check Docker Desktop (via context) (no try-catch)
|
|
let is_desktop = (
|
|
let result = (do { docker context ls } | complete)
|
|
$result.exit_code == 0 and (($result.stdout | grep "desktop" | length) > 0)
|
|
)
|
|
|
|
{
|
|
name: "docker-vm"
|
|
available: (if $is_desktop { "ready" } else { "available" })
|
|
docker_installed: $docker_installed
|
|
is_desktop: $is_desktop
|
|
description: "Docker Desktop VM support"
|
|
}
|
|
}
|
|
|
|
export def "get-primary-hypervisor" []: string {
|
|
"""Get the best available hypervisor for VM creation"""
|
|
|
|
let hypervisors = (detect-hypervisors)
|
|
|
|
# Preference order: libvirt (ready) > kvm (ready) > qemu > docker
|
|
let ready_libvirt = (
|
|
$hypervisors
|
|
| where name == "libvirt" and available == "ready"
|
|
| length
|
|
) > 0
|
|
|
|
let ready_kvm = (
|
|
$hypervisors
|
|
| where name == "kvm" and available == "ready"
|
|
| length
|
|
) > 0
|
|
|
|
let available_qemu = (
|
|
$hypervisors
|
|
| where name == "qemu"
|
|
| length
|
|
) > 0
|
|
|
|
let available_docker = (
|
|
$hypervisors
|
|
| where name == "docker-vm"
|
|
| length
|
|
) > 0
|
|
|
|
if $ready_libvirt {
|
|
"libvirt"
|
|
} else if $ready_kvm {
|
|
"kvm"
|
|
} else if $available_qemu {
|
|
"qemu"
|
|
} else if $available_docker {
|
|
"docker-vm"
|
|
} else {
|
|
error make {msg: "No hypervisors detected on system"}
|
|
}
|
|
}
|
|
|
|
export def "check-vm-capability" [host: string]: record {
|
|
"""Check if host can run virtual machines"""
|
|
|
|
let hypervisors = (detect-hypervisors)
|
|
|
|
{
|
|
host: $host
|
|
can_run_vms: (($hypervisors | length) > 0)
|
|
available_hypervisors: $hypervisors
|
|
primary_backend: (
|
|
# Guard: Ensure at least one hypervisor detected before calling get-primary-hypervisor
|
|
if ($hypervisors | length) > 0 {
|
|
get-primary-hypervisor
|
|
} else {
|
|
"none"
|
|
}
|
|
)
|
|
}
|
|
}
|