diff --git a/opentofu/vr1-dc0-maas/.terraform.lock.hcl b/opentofu/vr1-dc0-maas/.terraform.lock.hcl new file mode 100644 index 0000000..9e129c7 --- /dev/null +++ b/opentofu/vr1-dc0-maas/.terraform.lock.hcl @@ -0,0 +1,38 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/canonical/maas" { + version = "2.7.2" + constraints = "2.7.2" + hashes = [ + "h1:0/+f28bV5/BqmlBZdmQiTWmzVnjn8/3VNwU+7RLHi1E=", + "h1:0NQfNgN9iJEcuT3WK2+vC9Ss/C1cnyepVP6uahpvSSo=", + "h1:3LC/Yd6KHwKKUkeAOi0g6lRO3Aj6+vMwc5xGf6ARRcY=", + "h1:Be77+i/FQe/egck+r/Bi/qtUVTtB1+BXnwVS7rhQwGI=", + "h1:Cd7Ed7paJzuEhCpkcauEl18JkfRnvX7zK2KnbZfOeQ0=", + "h1:GcMMY3WdhRt6xJ6uXSoKRxs0tpmt43GL4a/a/gBlJV8=", + "h1:IdwSAz83vIz0gQvRt9VT+rs9F0+1MgLIi2IjU3U/8gA=", + "h1:JWEzos28aI09FfC9nW8Odb9h/J2KWnBwoOAsTz0OZ1g=", + "h1:JY1cOBhZyAYVKEWkM2TU/z+CgXI0GJ53HIdzIgmORRM=", + "h1:M4bq+7JZB9hf2hPzr1x85dAhbWcmMBDCoqGvYcSc/hk=", + "h1:PTbVBZc9uhi9zztYpAiWIRHc7zNr4Uwr5wR/atlbuI0=", + "h1:WNzlm/e2Rn6mVhLEgG5yBvMJEpcUCvSQxExvY77pAEo=", + "h1:jc8UQ6JbaFzi+zxpf8AzfZXs94sMIWYwu34adBDWvBk=", + "h1:u+mlHkUKpqQFmDB1zRtBFC7Nl+gMDvFw0edd71q5FH0=", + "zh:07de224747a55736794b771cfe42bcd7a84a0656120df73f3bba8fa5a7869fed", + "zh:0aa77c14a1e4826cc1b345b6dc61086a2d9c20a77b151b7677718544e275636e", + "zh:2a4a659601e97d10ff8d07871fa74dd895946f5e683fb7fb4a6050b78beb3012", + "zh:4627c138c5b36d36612bea1d6d5ed895b5edc082f15bdc2af3e3f6c1153d0568", + "zh:4a948b51b701b1e60794e7cee3f7f5183838fd2e1e53898ddd824a3d31e7b267", + "zh:54d987940d7e6c591a1d4b837adf01b6cace17698227649fa72da8113d8c3531", + "zh:5b111497a82b898478fbea60b244d7e932039bf95460df9d984d0f05e2567854", + "zh:68ed5d31ac46fb0e79b69e981021f83166600d222d7b2adecbea9393f8ff93b9", + "zh:7fd8f29946937cd2c2716603081fb5c71f524465cc4b0bfeeeacab13eb927515", + "zh:824e97b9b68192bf04cc56e94e7d279468d1c4d48c2a98d9f71f86b804053500", + "zh:ce5669c6279fa6cd72ab8e39ccffeb90be3f0d30d7b4077f154b8cb1fad710c0", + "zh:d508aa6858a9212e6b71924ec9e0ddeaada4bab74e4e040ce036ef4189e5076a", + "zh:db819ed07eaafbab90f8292b0a6bc4551c3bb7dcbd1006af67e68719f36720b0", + "zh:f42d9b7c7b0a8adcd1135f295b40425d5a47191d14468a5725f665d027aa9647", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} diff --git a/opentofu/vr1-dc0-maas/main.tf b/opentofu/vr1-dc0-maas/main.tf new file mode 100644 index 0000000..70b00f9 --- /dev/null +++ b/opentofu/vr1-dc0-maas/main.tf @@ -0,0 +1,56 @@ +# ===================================================================== +# vr1-dc0 MAAS registration root (Model B step D / runbook Step 9). +# +# WHY A THIRD ROOT, rather than adding `provider "maas"` to an existing one: +# DOCFIX-179 removed the maas provider block from the OUTER root after measuring +# that its mere PRESENCE forces every `tofu plan` to demand maas_api_url AND the +# SENSITIVE maas_api_key -- even for a plan that creates zero MAAS resources, +# which would bake a fake key into plan/state (the DOCFIX-175 plaintext-secret +# surface). That lesson applies verbatim to the INNER substrate root: coupling +# routine substrate plans to MAAS credential availability would be repeating the +# defect the repo already paid to learn. So MAAS registration gets its own small +# root with its own state, and the substrate roots stay credential-free. +# +# WHAT IT DOES: registers the DC's inner libvirt as a MAAS VM host (pod) so MAAS +# DISCOVERS the already-existing, OpenTofu-created node VMs. It deliberately does +# NOT compose machines -- see modules/maas-vm-host's header for the +# maas_vm_host vs maas_vm_host_machine reasoning (D-103). +# +# WHERE IT RUNS: from the Office1 headend (voffice1), the D-128 Plane-2 host -- +# same place the inner substrate root runs. +# +# SECRET HANDLING: maas_api_key comes ONLY from TF_VAR_maas_api_key in the +# environment, read from the operator-placed 0600 file. It is never written to a +# tfvars file. NOTE: it DOES land in this root's terraform.tfstate (unavoidable +# with this provider), so that state file inherits the same handling as any +# credential-bearing artifact -- 0600, on voffice1, never committed. +# ===================================================================== + +provider "maas" { + api_url = var.maas_api_url + api_key = var.maas_api_key +} + +module "vr1_dc0_vm_host" { + source = "../modules/maas-vm-host" + vm_host_name = var.vm_host_name + power_address = var.power_address + zone = var.zone + pool = var.pool +} + +output "vm_host_id" { + description = "MAAS id of the registered VM host -- the handle for a later teardown." + value = module.vr1_dc0_vm_host.id +} + +# MAAS's OWN view of the host's capacity. Not inputs -- a post-registration +# cross-check against the D-121/D-123 sizing math (vvr1-dc0 = 108 vCPU / 416 GiB): +# if MAAS reports something else, the nesting or the sizing is not what we think. +output "maas_reported_cores" { + value = module.vr1_dc0_vm_host.resources_cores_total +} + +output "maas_reported_memory" { + value = module.vr1_dc0_vm_host.resources_memory_total +} diff --git a/opentofu/vr1-dc0-maas/variables.tf b/opentofu/vr1-dc0-maas/variables.tf new file mode 100644 index 0000000..d863bc3 --- /dev/null +++ b/opentofu/vr1-dc0-maas/variables.tf @@ -0,0 +1,43 @@ +variable "maas_api_url" { + description = "Office1 MAAS region API endpoint, e.g. http://10.10.0.20:5240/MAAS. MEASURED (the rack enrolled against exactly this URL), never inferred." + type = string +} + +variable "maas_api_key" { + description = <<-EOT + MAAS API key (consumer:token:secret). SECRET -- supply ONLY via the + environment as TF_VAR_maas_api_key, sourced from the operator-placed 0600 + file (SEC-009 per-site creds convention). NEVER put it in a tfvars file, + never echo it, and never let it reach a plan file that gets committed. + EOT + type = string + sensitive = true +} + +variable "vm_host_name" { + description = "MAAS VM host (pod) name for this DC's inner libvirt." + type = string +} + +variable "power_address" { + description = <<-EOT + libvirt URI MAAS uses to reach this VM host. Under D-123 Model B this is + LOCAL to the rack (`qemu:///system`): vvr1-dc0 is BOTH the MAAS rack + controller AND the libvirt host holding the node VMs, so MAAS dials no + cross-fiber virsh. MEASURED prerequisite: the MAAS rack process must be + able to open that socket on the rack. + EOT + type = string +} + +variable "zone" { + description = "MAAS zone for the VM host. null = let MAAS compute it (the module's documented, provider-supported no-op)." + type = string + default = null +} + +variable "pool" { + description = "MAAS resource pool for the VM host. null = let MAAS compute it." + type = string + default = null +} diff --git a/opentofu/vr1-dc0-maas/versions.tf b/opentofu/vr1-dc0-maas/versions.tf new file mode 100644 index 0000000..0818fd1 --- /dev/null +++ b/opentofu/vr1-dc0-maas/versions.tf @@ -0,0 +1,18 @@ +# Pins mirror the outer root's versions.tf EXACTLY (canonical/maas 2.7.2) -- +# this root is a third entry point, not a different provider generation. If the +# outer root's pin is bumped, bump it here in the SAME change: two copies of one +# fact drift silently otherwise (the same caveat opentofu/variables.tf records +# about vr1_dc0_planes vs scripts/lib-net.sh). +# +# NO libvirt provider here ON PURPOSE. This root touches MAAS and nothing else. + +terraform { + required_version = ">= 1.6.0" + + required_providers { + maas = { + source = "canonical/maas" + version = "2.7.2" + } + } +}