variable "libvirt_uri" {
description = "libvirt connection URI for the vcloud host (e.g. qemu+ssh://user@host/system). MUST be measured this session, never guessed -- no default."
type = string
}
# maas_api_url / maas_api_key variables are DEFERRED to Stage 3 (DOCFIX-179):
# removed from Stage 1's root because the provider "maas" block that consumed
# them is deferred (see main.tf's note). Re-add both here when Stage 3
# instantiates modules/maas-vm-host. The SENSITIVE maas_api_key MUST return via
# TF_VAR_maas_api_key only -- never a committed file (opentofu/README.md
# "State file handling", DOCFIX-175).
variable "domain_suffix" {
description = "Base domain for per-plane libvirt DNS domains. Anchor value per D-106's naming convention (<service>.omega.<dc>.vr1.cloud.neumatrix.local)."
type = string
default = "cloud.neumatrix.local"
}
variable "underlay_mtu" {
description = "Underlay MTU applied to every plane and mesh-link network. MUST be the Phase-0 MEASURED host L2 MTU (buildout-design Section 3 / D-102) -- do not assume jumbo (9000). No default -- pass explicitly, e.g. via a Phase-0-specific tfvars file once measured."
type = number
}
variable "vr1_dc0_pool_path" {
description = "Host filesystem path for DC1's libvirt storage pool. Measured, real path on the vcloud host -- no default."
type = string
}
variable "office1_pool_path" {
description = "Host filesystem path for Office1's libvirt storage pool (MAAS-region/NetBox/GitBucket service-VM disks). Measured, real path on the vcloud host -- no default."
type = string
}
variable "vr1_dc1_pool_path" {
description = "Host filesystem path for DC2's libvirt storage pool. Measured, real path on the vcloud host -- no default. NOTE: only DC2's STORAGE POOL is wired (operator ruling 2026-07-10, dc-dc-phase0 Step 5/7). DC2's PLANES stay deferred (Option B) pending NetBox assigning the D-101 supernet -- a storage pool has no address dependency, plane networks do."
type = string
}
variable "vr1_dc0_planes" {
description = <<-EOT
DC1's six planes. DC1 INHERITS the DC0 v4 layout UNCHANGED (D-101) --
these CIDRs are copied from scripts/lib-net.sh's PLANE_CIDRS array as it
stood 2026-07-09, not invented here. If lib-net.sh changes, update this
default in the SAME change (it is a second copy of the same fact, not an
independent source -- a future DOCFIX candidate is a generator that keeps
both in sync automatically instead of two hand-maintained copies).
EOT
type = map(object({
cidr = string
}))
default = {
provider-public = { cidr = "10.12.4.0/22" }
metal-admin = { cidr = "10.12.8.0/22" }
metal-internal = { cidr = "10.12.12.0/22" }
data-tenant = { cidr = "10.12.16.0/22" }
storage = { cidr = "10.12.32.0/22" }
replication = { cidr = "10.12.36.0/22" }
}
}
variable "vr1_dc1_planes" {
description = <<-EOT
vr1-dc1's six planes (D-124 AMENDMENT 2026-07-21, addressing RATIFIED;
supernet 10.12.64.0/19 per D-115). NOT a copy of dc0's layout: the six
/22s are CONTIGUOUS keeping dc0's role ORDER (dc0's 4/8/12/16/32/36
offsets cannot fit inside a /19 -- deliberate, documented divergence;
10.12.88+92.0/22 spare). These values are apex-VERIFIED, not invented:
all six exist in office1-netbox scoped dcim.site:vr1-dc1 with matching
roles (docs/audit/dc1-apex-confirm-20260721.txt). Under D-123 Model B
the planes are CREATED by the INNER root (opentofu/vr1-dc1-substrate/);
this default is the committed values-of-record the inner tfvars copies
(same relationship as vr1_dc0_planes above / lib-net.sh's vr1-dc1 arm --
change one, change all in the SAME commit).
EOT
type = map(object({
cidr = string
}))
default = {
provider-public = { cidr = "10.12.64.0/22" }
metal-admin = { cidr = "10.12.68.0/22" }
metal-internal = { cidr = "10.12.72.0/22" }
data-tenant = { cidr = "10.12.76.0/22" }
storage = { cidr = "10.12.80.0/22" }
replication = { cidr = "10.12.84.0/22" }
}
}
# D-119 NAMING: vr1-dc0 is VR1's FIRST DC, vr1-dc1 its SECOND -- matching the
# NetBox apex slugs exactly. Never write a bare "dcN" for a VR1 DC here: "dc0"
# means VR0's LIVE testcloud in scripts/lib-net.sh, and that collision is what
# D-119 exists to delete.
# ---- D-114: Office1 site containment VM (voffice1) ----------------------------
variable "office1_ssh_pubkey_path" {
description = <<-EOT
Path to the PUBLIC half of the Office1 service SSH key, injected into voffice1's
cloud-init. Read with file() at plan time so the key material never has to be pasted
into the repo or a command line. The PRIVATE half stays jumphost-local and is never
read (SEC-007 tracks its rotation). Public keys are not secret; the path is a var so
the location is not hardcoded.
EOT
type = string
}
variable "vr1_dc0_ssh_pubkey_path" {
description = <<-EOT
Path to the PUBLIC half of the DEDICATED vr1-dc0 service SSH key (D-126 per-env-key
ruling 2026-07-16, option a: the containment VM gets its OWN key, NOT office1's).
Injected into vvr1-dc0's cloud-init; the inner root's qemu+ssh authenticates with the
matching private half (jumphost-local at ~/vr1-dc0-creds/, never read). Read with file()
at plan time -- the .pub must exist. Per-env blast-radius isolation from Office1.
EOT
type = string
}
variable "voffice1_vcpu" {
description = "voffice1 vCPU count. Hosts MAAS-region + the LXD VM host and the service VMs MAAS composes into it (D-114)."
type = number
}
variable "voffice1_memory_mib" {
description = "voffice1 memory in MiB."
type = number
}
variable "voffice1_disk_bytes" {
description = "voffice1 boot disk size in bytes."
type = number
}
# ---- D-123 MODEL B (2026-07-16) + D-124 AMENDMENT: vvr1-dc0 is now the DC's node HOST,
# not a 4/8/80 rack. Sizing DERIVED (not invented, hard rule 2) from the ruled R-3 layout
# via scripts/dc-dc-whole-host-budget.py: one DC fleet (3 control + 2 compute + 4 storage)
# = 104 vCPU / 384 GiB / 2850 GiB thin, + containment overhead (4 vCPU / 32 GiB / ~150 GiB
# OS). Whole-host 2-DC total = 870/1024 GiB (85%), FIT. Defaults encode the derivation;
# override in tfvars only with a re-derived value. ----
variable "vvr1_dc0_vcpu" {
description = "vvr1-dc0 vCPU (Model B: hosts one DC's 9 node VMs). Derived: 104 node + 4 overhead."
type = number
default = 108
}
variable "vvr1_dc0_memory_mib" {
description = "vvr1-dc0 RAM in MiB (Model B). Derived: 384 GiB node fleet + 32 GiB overhead = 416 GiB."
type = number
default = 425984
}
variable "vvr1_dc0_disk_bytes" {
description = "vvr1-dc0 boot disk in bytes (Model B: holds the inner libvirt pool). Derived: ~2850 GiB node disks (thin) + ~150 GiB OS = ~3000 GiB."
type = number
default = 3221225472000
}
variable "vr1_dc1_ssh_pubkey_path" {
description = <<-EOT
Path to the PUBLIC half of the DEDICATED vr1-dc1 service SSH key (D-126 per-env-key
ruling, option a; dc1 row ratified in the D-124 amendment 2026-07-21:
~/vr1-dc1-creds/vr1-dc1_svc_ed25519). Injected into vvr1-dc1's cloud-init; the inner
root's qemu+ssh authenticates with the matching private half (jumphost-local, never
read). Read with file() at plan time -- the .pub must exist. Per-env blast-radius
isolation from Office1 AND from dc0.
EOT
type = string
}
# ---- vvr1-dc1 sizing: SAME derivation as vvr1-dc0 (D-121 Option C is per-DC --
# identical 3 control + 2 compute + 4 storage fleet), via
# scripts/dc-dc-whole-host-budget.py: 104 node vCPU / 384 GiB / ~2850 GiB thin +
# containment overhead. The whole-host 2-DC total (870/1024 GiB, 85%) was budgeted
# FIT when dc0's sizing was derived -- dc1 IS the second half of that budget. ----
variable "vvr1_dc1_vcpu" {
description = "vvr1-dc1 vCPU (Model B: hosts one DC's 9 node VMs). Derived: 104 node + 4 overhead."
type = number
default = 108
}
variable "vvr1_dc1_memory_mib" {
description = "vvr1-dc1 RAM in MiB (Model B). Derived: 384 GiB node fleet + 32 GiB overhead = 416 GiB."
type = number
default = 425984
}
variable "vvr1_dc1_disk_bytes" {
description = "vvr1-dc1 boot disk in bytes (Model B: holds the inner libvirt pool). Derived: ~2850 GiB node disks (thin) + ~150 GiB OS = ~3000 GiB."
type = number
default = 3221225472000
}
# ---- D-124 AMENDMENT (2026-07-21): vr1-dc1 MAAS rack controller (vvr1-dc1)
# addressing. NO defaults -- ratified values enter via tfvars ONLY AFTER the
# operator-gated apex --commit registers them in office1-netbox (dc0 precedent:
# rack_transit_ip=172.31.0.6, prefix=30, peer=172.31.0.5, metal_admin=10.12.68.2).
# Do NOT invent or pre-fill them here (hard rule 2). ----
variable "vr1_dc1_rack_metal_admin_ip" {
description = "vvr1-dc1 rack static IP in metal-admin (10.12.68.0/22), in the .2-.49 static band, not the .1 gateway. NetBox-assigned (D-124 amendment)."
type = string
}
variable "vr1_dc1_rack_transit_ip" {
description = "vvr1-dc1 rack IP on the office1<->dc1 mesh transit (D-124 Scheme A, next /30 in 172.31.0.0/24). NetBox-assigned."
type = string
}
variable "vr1_dc1_rack_transit_prefix" {
description = "office1<->dc1 transit link prefix length (30 or 31, D-124 Scheme A)."
type = number
}
variable "vr1_dc1_rack_transit_peer_ip" {
description = "Office1 region's IP on the office1<->dc1 transit link -- the rack's next-hop toward the MAAS region (10.10.0.0/22). NetBox-assigned (D-124 amendment)."
type = string
}
# ---- D-124: vr1-dc0 MAAS rack controller (vvr1-dc0) addressing. NO defaults --
# these come from office1-netbox (the IPAM apex) via the D-124 importer, then
# into a tfvars entry. Do NOT invent them here (hard rule 2). The rack straddles
# two legs: metal-admin (node-facing PXE/DHCP) + the office1<->dc0 mesh transit
# (region-facing, Scheme A). ----
variable "vr1_dc0_rack_metal_admin_ip" {
description = "vvr1-dc0 rack static IP in metal-admin (10.12.8.0/22), in the .2-.49 static band, not the .1 gateway. NetBox-assigned (D-124)."
type = string
}
variable "vr1_dc0_rack_transit_ip" {
description = "vvr1-dc0 rack IP on the office1<->dc0 mesh transit (D-124 Scheme A). NetBox-assigned."
type = string
}
variable "vr1_dc0_rack_transit_prefix" {
description = "Transit link prefix length (30 or 31, D-124 Scheme A)."
type = number
}
variable "vr1_dc0_rack_transit_peer_ip" {
description = "Office1 region's IP on the transit link -- the rack's next-hop toward the MAAS region (10.10.0.0/22). NetBox-assigned (D-124)."
type = string
}
# ---- D-125 (Model B bridge-in): the vr1-dc0 vcloud-level simulated-ISP uplink /24
# is NOT a HELD variable -- it is the SAME /24 D-115 already ruled for vr1-dc0's edge
# WAN (172.30.2.0/24), since bridge-in is single-NAT and the /24's IPAM identity is
# unchanged from Model A. It is therefore a RULED literal inlined in main.tf's
# `module "vr1_dc0_uplink"`, not a tfvar. (An earlier D-125 draft wrongly modeled it
# as a new NetBox-assigned HELD value; corrected 2026-07-16.) ----