Introduces internal/provider/kvm with the side-effect-free pieces of the provider: providerID format/parse, the namespaced <metadata> element that carries the GC contract, q35 domain XML over pool volumes, volume XML for overlays and raw seeds, the NoCloud seed ISO built with kdomanski/iso9660, and config defaults. All unit-tested. Step 2 of docs/plans/2026-09-04-1404-kvm-provider.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
48 lines
1.4 KiB
Go
48 lines
1.4 KiB
Go
// Package kvm implements the provider contract on libvirt/KVM hypervisors.
|
|
// Each configured host is reached over SSH with the libvirt unix socket
|
|
// forwarded through the connection, so the hypervisors need no libvirtd TCP
|
|
// or TLS listener and the operator image needs no libvirt libraries. VMs
|
|
// boot a stock cloud image (fetched into the host's storage pool on first
|
|
// use) through a qcow2 overlay, with the Proxy's cloud-init delivered on a
|
|
// NoCloud seed ISO built in-process.
|
|
package kvm
|
|
|
|
import "gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/provider"
|
|
|
|
const (
|
|
defaultDiskSizeGB = 10
|
|
defaultSocket = "/var/run/libvirt/libvirt-sock"
|
|
defaultPool = "default"
|
|
formatQcow2 = "qcow2"
|
|
formatRaw = "raw"
|
|
)
|
|
|
|
func withDefaults(cfg provider.KVMConfig) provider.KVMConfig {
|
|
if cfg.DiskSizeGB == 0 {
|
|
cfg.DiskSizeGB = defaultDiskSizeGB
|
|
}
|
|
if cfg.VendorData == "" {
|
|
cfg.VendorData = defaultVendorData
|
|
}
|
|
images := make(map[string]provider.KVMImage, len(cfg.Images))
|
|
for k, img := range cfg.Images {
|
|
if img.Format == "" {
|
|
img.Format = formatQcow2
|
|
}
|
|
images[k] = img
|
|
}
|
|
cfg.Images = images
|
|
hosts := make([]provider.KVMHost, len(cfg.Hosts))
|
|
for i, h := range cfg.Hosts {
|
|
if h.Socket == "" {
|
|
h.Socket = defaultSocket
|
|
}
|
|
if h.Pool == "" {
|
|
h.Pool = defaultPool
|
|
}
|
|
hosts[i] = h
|
|
}
|
|
cfg.Hosts = hosts
|
|
return cfg
|
|
}
|