sam 6fc92541e9 router extension (dormant) + v2 redesign doc after OOM'd first run
Adds the real-router BMP extension code and a redesign doc capturing
what changed in the test's intent.

  scripts/router_bmp.py           push/dry-run/remove `bmp server 2`
                                  on all 18 lab routers via paramiko
                                  SSH shell. Inventory + cred pattern
                                  lifted from obmp-rib-poller/poller.py.
                                  Activation scope: bmp-activate server 2
                                  on the existing BMP-MONITORED
                                  neighbor-group -- mirrors production.

  terraform/router_bmp.tf         terraform_data resource with two-step
                                  safety (dry-run first, apply on
                                  confirm), triggers_replace on action
                                  change, destroy provisioner calls
                                  `remove` (idempotent, on_failure=
                                  continue so a stuck router doesn't
                                  block VM teardown).

  terraform/terraform.tfvars      enable_router_bmp / confirm_router_push
                                  both default false (dormant).

  docs/redesign-real-routers.md   captures the pivot from v1 "prove
                                  deploy.sh works" to v2 "canary
                                  collector receiving real router BMP".
                                  Documents that v1 store VM OOM'd at
                                  4 GB under the internal --profile
                                  test feed alone, proposes 32 GB /
                                  8 vCPU for v2 and dropping --profile
                                  test so the collector receives ONLY
                                  real router BMP.

State on prox940 as of this commit:
  - v1 VMs (9001 store, 9002 bmpgen) destroyed via PVE API
    (terraform destroy hung on the OOM'd guest agent)
  - Terraform state cleaned
  - Cached Ubuntu image kept for a fast next apply
  - Lab routers untouched (extension code dormant)

Not yet done, awaiting user input:
  - v2 sizing landed in terraform.tfvars
  - Compose scope decision (add --no-feeders to deploy.sh vs
    workaround in cloud-init)
  - Re-apply
  - Router extension dry-run + confirm

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-21 07:21:03 -07:00

92 lines
3.6 KiB
HCL

# Real-router extension: push `bmp server 2` to every lab router pointing
# at the test collector, so real-router BMP output flows into the test
# stack alongside the internal gobgp synthetic feed. Nothing touches
# `bmp server 1` (production).
#
# Two-step safety: first apply is a DRY RUN (prints per-router pending
# diffs, does not commit). Set `confirm_router_push=true` and re-apply
# to actually commit the config on all routers.
#
# Lifecycle:
# enable_router_bmp=false -> resource absent, no router-side changes
# enable=true, confirm=false -> dry-run provisioner (safe; abort at end)
# enable=true, confirm=true -> apply provisioner (commits + verifies)
# flip either back -> destroy provisioner runs `remove` (idempotent)
#
# The destroy provisioner uses `on_failure = continue` so a partial router
# outage never blocks the VM teardown in scripts/teardown.sh.
variable "enable_router_bmp" {
description = "Enable the real-router BMP extension (push bmp server 2 to lab routers)."
type = bool
default = false
}
variable "confirm_router_push" {
description = "Set to true on second apply to actually commit `bmp server 2` on routers. First apply (false) is a dry-run only."
type = bool
default = false
}
locals {
router_bmp_action = var.confirm_router_push ? "apply" : "dry-run"
router_bmp_script = abspath("${path.module}/../scripts/router_bmp.py")
# The collector's address on the routers' management path. With DHCP,
# this only becomes known after the store VM's guest-agent reports.
router_bmp_target = try(
proxmox_virtual_environment_vm.store.ipv4_addresses[1][0],
""
)
}
resource "terraform_data" "router_bmp" {
count = var.enable_router_bmp ? 1 : 0
# Any change to these values REPLACES the resource -- destroy provisioner
# runs first (removes any prior state on routers), then create provisioner
# runs (applies the new state). That gives us clean transitions:
# dry-run -> apply, or apply -> dry-run.
triggers_replace = [
local.router_bmp_action,
local.router_bmp_target,
var.router_facing_port,
]
# `input` is available to provisioners as `self.input`.
input = {
action = local.router_bmp_action
script = local.router_bmp_script
target_ip = local.router_bmp_target
target_port = tostring(var.router_facing_port)
}
# CREATE (or replace): push (or dry-run) `bmp server 2` to all routers.
provisioner "local-exec" {
command = "python3 ${self.input.script} ${self.input.action} --target-ip ${self.input.target_ip} --target-port ${self.input.target_port}"
}
# DESTROY: remove `bmp server 2` from all routers. Idempotent: routers
# without the config are no-ops. `on_failure = continue` so a single
# unreachable router does not block the VM teardown.
provisioner "local-exec" {
when = destroy
on_failure = continue
command = "python3 ${self.input.script} remove --target-ip ${self.input.target_ip} --target-port ${self.input.target_port}"
}
}
output "router_bmp_status" {
description = "Real-router BMP extension state."
value = var.enable_router_bmp ? {
enabled = true
action = local.router_bmp_action
confirm_needed = !var.confirm_router_push
target = "${local.router_bmp_target}:${var.router_facing_port}"
hint = var.confirm_router_push ? "committed on last apply; destroy will remove" : "set confirm_router_push=true and re-apply to commit"
} : {
enabled = false
hint = "set enable_router_bmp=true (and later confirm_router_push=true) to add bmp server 2 to lab routers"
}
}