sam d0b82c4973 first successful two-VM run + fixes surfaced by it
The initial two-VM run against a real Proxmox host found three real
bugs in the obmp-docker stack, plus one design issue in this test:

  Fixed in obmp-docker (deploy-refinement branch):
    - 745f066  deploy.sh: probe sudo with `sudo -n true` instead of
               `sudo -v` / `sudo -n -v`; the latter demands a credential
               timestamp that NOPASSWD never produces, so both fail on
               cloud-init / CI even with NOPASSWD:ALL configured.
    - 6df67a7  .env.example: quote GNMI_ADDRESSES with single quotes so
               docker compose's .env parser doesn't choke on the mid-line
               comma in the double-quoted list form.

  Fixed here:
    - bmpgen cloud-init: add `port = 1179` under [global.config] to
      avoid gobgpd's 179 listener bind failing under Ubuntu 24.04 +
      Docker even with --network host and default NET_BIND_SERVICE cap.
      We don't accept BGP peers on bmpgen so the port value doesn't
      matter as long as it's unprivileged.
    - run-test.sh: fix column name for bgp_peers.state -- the opstate
      enum uses lowercase 'up', not uppercase 'UP'.

  Verified against the live run: 6/6 assertions pass, ip_rib landed
  251,760 routes from the store VM's own gobgp connecting to Bromirski's
  public full-table feed via --profile test.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-20 23:38:43 -07:00

95 lines
2.8 KiB
HCL

# VM B -- GoBGP standing in for a real BGP router. Cloud-init installs
# docker and runs a gobgp container configured to BMP-report to VM A.
#
# Ordering: bmpgen's cloud-init needs VM-A's IP. With a static CIDR it's
# known at plan time; with DHCP we defer to store.ipv4_addresses (populated
# only after the store VM boots and its qemu-guest-agent reports). That
# reference creates an implicit dependency, so bmpgen's snippet upload +
# VM creation both wait until the store's address is known.
locals {
bmpgen_hostname = "obmp-bmpgen-test"
# Resolve store's address: static CIDR var wins; otherwise fall back to
# the store VM's guest-agent-reported IPv4. ipv4_addresses is a list of
# lists (one per interface); index [1][0] is the first NIC's first non-
# loopback address. try() keeps plan output tidy when the attribute
# doesn't exist yet.
bmpgen_store_addr = (
var.store_vm_ip_cidr != ""
? split("/", var.store_vm_ip_cidr)[0]
: try(proxmox_virtual_environment_vm.store.ipv4_addresses[1][0], "")
)
bmpgen_user_data = templatefile("${path.module}/cloud-init/bmpgen.cloud-init.yaml.tftpl", {
hostname = local.bmpgen_hostname
ssh_username = var.ssh_username
ssh_public_key = trimspace(file(var.ssh_public_key_path))
store_ip_addr = local.bmpgen_store_addr
router_facing_port = var.router_facing_port
local_asn = var.test_local_asn
})
}
resource "proxmox_virtual_environment_file" "bmpgen_cloud_init" {
content_type = "snippets"
datastore_id = var.snippet_storage
node_name = var.pve_node
source_raw {
file_name = "obmp-bmpgen-user-data.yaml"
data = local.bmpgen_user_data
}
}
resource "proxmox_virtual_environment_vm" "bmpgen" {
name = local.bmpgen_hostname
description = "OpenBMP portability-test BMPGEN VM (managed by terraform)"
tags = ["obmp", "portability-test", "bmpgen"]
node_name = var.pve_node
vm_id = var.bmpgen_vm_id
agent { enabled = true }
cpu {
cores = 2
type = "host"
}
memory {
dedicated = 2048
}
disk {
datastore_id = var.vm_storage_pool
file_id = proxmox_download_file.ubuntu_noble.id
interface = "scsi0"
size = 16
ssd = true
discard = "on"
}
network_device {
bridge = var.vm_bridge
model = "virtio"
vlan_id = var.vm_vlan_tag != 0 ? var.vm_vlan_tag : null
}
operating_system { type = "l26" }
initialization {
datastore_id = var.vm_storage_pool
ip_config {
ipv4 {
address = var.bmpgen_vm_ip_cidr != "" ? var.bmpgen_vm_ip_cidr : "dhcp"
gateway = var.bmpgen_vm_ip_cidr != "" ? var.vm_gateway : null
}
}
dns {
servers = var.vm_dns_servers
}
user_data_file_id = proxmox_virtual_environment_file.bmpgen_cloud_init.id
}
}