# opnsense-edge: one OPNsense edge VM (D-100's per-site independent OPNsense
# edge with a simulated ISP uplink; D-103: OpenTofu owns creating it).
#
# NOT the cloud-init pattern (modules/cloudinit-vm) -- confirmed unreliable
# on OPNsense/FreeBSD this session (see opentofu/README.md's "OPNsense
# deployment research" section, fully sourced). This module instead uses
# OPNsense's own Configuration Importer: a plain ISO9660 volume containing
# /conf/config.xml, attached as a secondary cdrom disk -- mechanically
# IDENTICAL to cloudinit-vm's seed-volume shape (a libvirt_volume with
# create.content.url, attached as device="cdrom"), just a different payload
# and no libvirt_cloudinit_disk resource (that resource is NoCloud-specific;
# wrong format here). Both the base image and the config ISO are prepared
# OUTSIDE OpenTofu by scripts/opnsense-prep-image.sh and
# scripts/opnsense-build-config-iso.sh respectively -- see each variable's
# description for why.
#
# UNVERIFIED, flagged plainly (see opentofu/README.md for the full account):
# (a) whether the Configuration Importer's ISO9660 support actually behaves
# as described once booted for real -- the research is well-sourced but not
# independently tested this session (no real OPNsense boot, no
# genisoimage/xorriso available); (b) whether `devices.interfaces` list
# ORDER reliably maps to which NIC FreeBSD/OPNsense enumerates as its first
# vs. second interface (assumed here, consistent with libvirt XML ordering
# generally, but not independently confirmed for this specific guest OS).
# Confirm both on a real boot before trusting LAN/WAN role assignment.
#
# No PXE boot-order attribute is used here (unlike modules/node-vm): this VM
# boots from its own pre-installed disk, not over the network, so the
# UNVERIFIED `boot`-order shape noted in node-vm/main.tf does not need
# touching for this module at all.

resource "libvirt_volume" "disk" {
  name     = "${var.vm_name}-disk.qcow2"
  pool     = var.pool_name
  capacity = var.disk_size_bytes

  target = {
    format = {
      type = "qcow2"
    }
  }

  backing_store = {
    path = var.base_volume_path
    format = {
      type = "qcow2"
    }
  }
}

resource "libvirt_volume" "config_seed" {
  name = "${var.vm_name}-config.iso"
  pool = var.pool_name

  create = {
    content = {
      url = var.config_iso_path
    }
  }
}

resource "libvirt_domain" "vm" {
  name    = var.vm_name
  memory  = var.memory_mib
  vcpu    = var.vcpu
  type    = "kvm"
  running = true

  os = {
    type         = "hvm"
    type_arch    = "x86_64"
    type_machine = "q35"
  }

  devices = {
    disks = [
      {
        source = {
          volume = {
            pool   = libvirt_volume.disk.pool
            volume = libvirt_volume.disk.name
          }
        }
        target = {
          dev = "vda"
          bus = "virtio"
        }
        driver = {
          type = "qcow2"
        }
      },
      {
        device = "cdrom"
        source = {
          volume = {
            pool   = libvirt_volume.config_seed.pool
            volume = libvirt_volume.config_seed.name
          }
        }
        target = {
          dev = "sda"
          bus = "sata"
        }
      }
    ]

    # order matters: index 0 is LAN, index 1 is WAN, matching OPNsense's own
    # interface-1-is-LAN/interface-2-is-WAN default convention. See the
    # UNVERIFIED note above -- this ordering assumption is not independently
    # confirmed for this specific guest.
    interfaces = [
      {
        model = {
          type = "virtio"
        }
        source = {
          network = {
            network = var.lan_network_name
          }
        }
      },
      {
        model = {
          type = "virtio"
        }
        source = {
          network = {
            network = var.wan_network_name
          }
        }
      }
    ]
  }
}
