terraform { required_providers { proxmox = { source = "bpg/proxmox" version = "0.83.1" } null = { source = "hashicorp/null" version = "3.2.4" } } } provider "proxmox" { endpoint = var.proxmox_api_url api_token = var.proxmox_api_token insecure = true } resource "null_resource" "stage_talos_image" { for_each = var.talos_image_update_mode == "download" ? local.image_target_nodes : [] triggers = { node_name = each.value image_url = local.talos_iso_download_url storage = var.talos_image_storage talos_version = var.talos_version filename = "talos-${trimprefix(var.talos_version, "v")}-${substr(var.talos_factory_schematic_id, 0, 12)}-${var.talos_image_architecture}.iso" } provisioner "local-exec" { interpreter = ["python", "-c"] command = "import subprocess; subprocess.run(['python', r'${path.module}/scripts/stage_talos_image.py', '--api-url', '${var.proxmox_api_url}', '--api-token', '${var.proxmox_api_token}', '--node', '${each.value}', '--storage', '${var.talos_image_storage}', '--image-url', '${local.talos_iso_download_url}', '--filename', '${self.triggers.filename}'], check=True)" } } # Create all required network bridges resource "proxmox_virtual_environment_network_linux_bridge" "cluster_bridge" { for_each = {} node_name = each.value.proxmox_node name = each.value.bridge_name comment = "Auto-created bridge for Talos VLAN ${each.value.vlan_id} on ${each.value.proxmox_node}" ports = var.create_vlan_interface ? ["${each.value.phys_iface}.${each.value.vlan_id}"] : [each.value.phys_iface] vlan_aware = false # The VLAN tagging is handled by the interface } # Create the Virtual Machines resource "proxmox_virtual_environment_vm" "vm" { for_each = local.all_nodes_transformed name = each.value.name node_name = each.value.proxmox_node description = local.node_configs[each.value.role].description tags = each.value.tags vm_id = each.value.vmid started = true bios = local.node_configs[each.value.role].bios # Enable QEMU Guest Agent for better VM management agent { enabled = true } # Boot the disk first, then the ISO as fallback boot_order = local.node_configs[each.value.role].boot_order cpu { cores = each.value.cores sockets = 1 type = local.node_configs[each.value.role].cpu_type } memory { dedicated = each.value.memory } # --- DYNAMIC NETWORK DEVICES --- # This block iterates over the network_devices list for each node dynamic "network_device" { for_each = each.value.network_devices content { bridge = network_device.value.bridge model = network_device.value.model mac_address = network_device.value.mac_address } } # Primary disk disk { interface = "scsi0" datastore_id = each.value.disk_storage size = tonumber(trimsuffix(each.value.disk_size, "G")) cache = "none" discard = "ignore" ssd = false } # Additional disk for Rook Ceph storage (only if specified) # This creates a raw passthrough disk that Rook can manage directly dynamic "disk" { for_each = each.value.additional_disk_size != null ? [1] : [] content { interface = "scsi1" datastore_id = each.value.additional_disk_storage size = tonumber(trimsuffix(each.value.additional_disk_size, "G")) cache = "none" discard = "ignore" ssd = false file_format = "raw" # Raw format for direct storage access } } # Attach Talos ISO cdrom { interface = "ide2" file_id = each.value.iso_file } # Ensure bridges are created before VMs depends_on = [ proxmox_virtual_environment_network_linux_bridge.cluster_bridge, null_resource.stage_talos_image, ] } # (Your output definitions should still work, but you may want to update # vm_details to show the list of MAC addresses and bridges)