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>
This commit is contained in:
parent
33f9f4daf7
commit
d0b82c4973
@ -119,10 +119,10 @@ assert_routers_row() {
|
|||||||
}
|
}
|
||||||
assert "routers table has >= 1 row" assert_routers_row
|
assert "routers table has >= 1 row" assert_routers_row
|
||||||
|
|
||||||
# 4: at least 1 UP BGP peer
|
# 4: at least 1 UP BGP peer. bgp_peers.state uses lowercase 'up' (opstate enum).
|
||||||
assert_bgp_peer_up() {
|
assert_bgp_peer_up() {
|
||||||
local n
|
local n
|
||||||
n=$(ssh_store "docker exec -i obmp-psql psql -U openbmp -d openbmp -tAc \"SELECT count(*) FROM bgp_peers WHERE state='UP'\"")
|
n=$(ssh_store "docker exec -i obmp-psql psql -U openbmp -d openbmp -tAc \"SELECT count(*) FROM bgp_peers WHERE state='up'\"")
|
||||||
[ "${n:-0}" -ge 1 ]
|
[ "${n:-0}" -ge 1 ]
|
||||||
}
|
}
|
||||||
assert "bgp_peers has >= 1 UP session" assert_bgp_peer_up
|
assert "bgp_peers has >= 1 UP session" assert_bgp_peer_up
|
||||||
|
|||||||
@ -1,20 +1,25 @@
|
|||||||
# VM B -- GoBGP standing in for a real BGP router. Cloud-init installs
|
# 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.
|
# docker and runs a gobgp container configured to BMP-report to VM A.
|
||||||
#
|
#
|
||||||
# `depends_on` on the store VM's cloud-init snippet, not the store VM
|
# Ordering: bmpgen's cloud-init needs VM-A's IP. With a static CIDR it's
|
||||||
# itself -- we don't want to wait for the store's cloud-init to finish
|
# known at plan time; with DHCP we defer to store.ipv4_addresses (populated
|
||||||
# before launching B (cloud-init on B will retry the BMP session until A
|
# only after the store VM boots and its qemu-guest-agent reports). That
|
||||||
# is ready).
|
# reference creates an implicit dependency, so bmpgen's snippet upload +
|
||||||
|
# VM creation both wait until the store's address is known.
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
bmpgen_hostname = "obmp-bmpgen-test"
|
bmpgen_hostname = "obmp-bmpgen-test"
|
||||||
|
|
||||||
# If DHCP, we don't know VM-A's address at plan time and cloud-init on
|
# Resolve store's address: static CIDR var wins; otherwise fall back to
|
||||||
# VM-B will need it. We handle both cases in the template:
|
# the store VM's guest-agent-reported IPv4. ipv4_addresses is a list of
|
||||||
# - static: pass store_ip_addr directly
|
# lists (one per interface); index [1][0] is the first NIC's first non-
|
||||||
# - DHCP: cloud-init on B does an ARP scan + hostname lookup at boot
|
# loopback address. try() keeps plan output tidy when the attribute
|
||||||
# (kept out-of-scope here; DHCP + this test is best-effort)
|
# doesn't exist yet.
|
||||||
bmpgen_store_addr = var.store_vm_ip_cidr != "" ? split("/", var.store_vm_ip_cidr)[0] : ""
|
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", {
|
bmpgen_user_data = templatefile("${path.module}/cloud-init/bmpgen.cloud-init.yaml.tftpl", {
|
||||||
hostname = local.bmpgen_hostname
|
hostname = local.bmpgen_hostname
|
||||||
|
|||||||
@ -36,6 +36,11 @@ write_files:
|
|||||||
[global.config]
|
[global.config]
|
||||||
as = ${local_asn}
|
as = ${local_asn}
|
||||||
router-id = "10.99.99.99"
|
router-id = "10.99.99.99"
|
||||||
|
# Non-privileged BGP listener port. Default 179 requires root+cap_net_bind_service
|
||||||
|
# inside the container; Ubuntu 24.04 + docker denies this even with
|
||||||
|
# --network host despite the default cap set including NET_BIND_SERVICE.
|
||||||
|
# We're not accepting BGP peers here anyway -- only the BMP session out.
|
||||||
|
port = 1179
|
||||||
|
|
||||||
[[bmp-servers]]
|
[[bmp-servers]]
|
||||||
[bmp-servers.config]
|
[bmp-servers.config]
|
||||||
|
|||||||
@ -22,11 +22,18 @@ provider "proxmox" {
|
|||||||
api_token = var.pve_api_token
|
api_token = var.pve_api_token
|
||||||
insecure = var.pve_insecure
|
insecure = var.pve_insecure
|
||||||
|
|
||||||
# SSH is used by the provider for a few operations (snippet uploads, etc).
|
# SSH is used by the provider for snippet uploads (SCP, not the API --
|
||||||
# Optional -- if omitted the provider falls back to API-only paths where
|
# a known bpg quirk). Point it at the same address as the API endpoint
|
||||||
# possible. Set node -> address so the provider doesn't have to resolve.
|
# rather than letting the provider guess from cluster metadata (which
|
||||||
|
# may return a bridge address that's unreachable from here).
|
||||||
ssh {
|
ssh {
|
||||||
agent = true
|
agent = false
|
||||||
username = var.pve_ssh_username
|
username = var.pve_ssh_username
|
||||||
|
private_key = file(var.pve_ssh_private_key_path)
|
||||||
|
|
||||||
|
node {
|
||||||
|
name = var.pve_node
|
||||||
|
address = var.pve_ssh_address != "" ? var.pve_ssh_address : replace(replace(var.pve_endpoint, "https://", ""), ":8006/", "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,18 @@ variable "pve_ssh_username" {
|
|||||||
default = "root"
|
default = "root"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "pve_ssh_private_key_path" {
|
||||||
|
description = "Path to the SSH private key the provider uses to reach the PVE host. Its matching pubkey must be in /root/.ssh/authorized_keys on the PVE node."
|
||||||
|
type = string
|
||||||
|
default = "~/.ssh/id_ed25519"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "pve_ssh_address" {
|
||||||
|
description = "Address the provider uses for SSH to the PVE node. Defaults to the endpoint host. Set explicitly if the PVE cluster returns a different bridge/hostname than the one that's reachable from here."
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
variable "pve_node" {
|
variable "pve_node" {
|
||||||
description = "PVE node name to schedule VMs on (as shown in the PVE cluster tree)"
|
description = "PVE node name to schedule VMs on (as shown in the PVE cluster tree)"
|
||||||
type = string
|
type = string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user