Owns create/destroy of the "physical" layer per D-103: libvirt domains (node VMs), all virtual networks (dark-fiber mesh, per-DC planes, ISP-edge), the OPNsense edge VMs, and the Office1 service VMs. Runs from the Office1 operator VM against the vcloud host libvirt. See docs/dc-dc-buildout-design.md and docs/dc-dc-deployment-workflow.md (Stage 1-2, tooling gap register item 2) for the surrounding plan.
Status: SCAFFOLD, UNVALIDATED. No tofu/terraform binary was available in the session that authored this -- nothing here has been run through tofu init/validate/plan, let alone apply. Before trusting any of it:
bash scripts/opentofu-validate.sh
on a machine with the binary and network access to the provider registry, and read the result before proceeding.
Built:
modules/dc-planes -- the six per-DC plane segments (D-052/D-100) as isolated libvirt_network resources.modules/mesh-link -- one inter-site L2 segment per leg of the D-100 dark-fiber triangle (DC1<->DC2, DC1<->Office1, DC2<->Office1).modules/dc-storage-pool -- a directory-backed libvirt_pool per DC/Office1 for future node-VM disk images.Deliberately NOT built yet, and why:
libvirt_domain (the actual node VMs). The provider's current schema for this resource turned out to be a large (~40 top-level argument), deeply nested rewrite that closely mirrors raw libvirt domain XML (numa_tune, launch_security, memory_backing, a devices block containing disks, interfaces, filesystems, graphics, etc.) -- materially different from older, commonly-referenced examples of this provider. Doc-summarization tools available this session could not give high-confidence, verbatim field names for the nested devices.interfaces/devices.disks shape specifically. Authoring this blind risks exactly the "fabricated flag/value" failure mode this repo's operating discipline calls out as the cardinal sin. Next action: on a machine with the tofu binary, run tofu providers schema -json (after terraform init) and read the actual libvirt_domain schema directly, or start from the provider's own examples/ directory in its GitHub repo, before writing this module.libvirt_volume (per-VM disk images). Follows directly from the domain module above; deferred with it.main.tf has the DC2 module block written and commented out, ready to uncomment once NetBox assigns real CIDRs -- do not fill in a guessed default to make it "work" sooner.tc netem WAN simulation. libvirt_network has no netem-equivalent argument; this is an OS-level tc qdisc setting applied to the bridge interface a mesh-link module creates, which needs either a null_resource provisioner or a small companion script -- not yet written. The exact parameters are themselves a Phase-0 open item (D-100), so this was going to need a second pass regardless.modules/mesh-link, above); (b) the VM/image itself is blocked on the deferred domain module, and no image source (official OPNsense qcow2/ISO vs. a custom build) has been chosen; (c) OPNsense's own routing/firewall config is a config.xml the libvirt provider never touches -- pre-baked image vs. cloud-init first-boot vs. API/CLI-driven provisioner is an open choice, not started; (d) tc netem WAN simulation is a separate OS-level tc qdisc setting with no Terraform-native equivalent at all, needing its own provisioner/script, and whose parameters are still an unruled D-100 open item -- a decision, not just scripting, is needed first. Full breakdown in docs/dc-dc-deployment-workflow.md gap register item 4.Verified this session against the provider's actual current docs (docs/resources/*.md in dmacvicar/terraform-provider-libvirt, tag v0.9.8, fetched 2026-07-09) -- NOT from training-data memory of older provider versions, which would have been wrong:
libvirt_network's isolation control lives at forward.mode (a NESTED block field), not a top-level mode argument as older examples show. This scaffold OMITS the forward block entirely for isolated planes/links (documented native-libvirt behavior for a private, unforwarded switch) rather than guess a mode = "none" value this session could not confirm is still valid. Re-check this specific choice first if tofu validate objects.domain and mtu on libvirt_network are nested blocks (domain { name = ... }, mtu { size = ... }), not flat string/number arguments.libvirt_pool's target is a nested block (target { path = ... }), types like dir are native libvirt storage-pool vocabulary (stable, long-standing, not provider-specific) -- reasonably high confidence..tf files if this becomes a recurring class of finding -- not yet done, flag if it comes up).scripts/lib-net.sh's PLANE_CIDRS. Keep them in sync manually until a generator exists to derive one from the other (DOCFIX candidate, not actioned).