Files
box/bin/netvm-registry.py
T

78 lines
2.5 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""
netvm-registry.py — single source of truth for node -> CDP port mapping.
Parses NODES.md (the fleet registry). Every script that needs a node's
CDP port reads it from here instead of hardcoding — new nodes propagate
automatically.
Usage:
from netvm_registry import port_for, load
port_for("muse") # -> 9410 (int), None if unknown
CLI:
netvm-registry.py # prints "node:port" lines for active nodes
netvm-registry.py <node> # prints just the port (for bash)
"""
import os
import re
import sys
REGISTRY = os.path.join(os.path.dirname(os.path.dirname(
os.path.abspath(__file__))), "NODES.md")
def load(registry_path=None):
"""Return {node: {netns, egress_ip, cdp_port, status, agent}}."""
path = registry_path or REGISTRY
nodes = {}
try:
with open(path) as f:
for line in f:
line = line.rstrip("\n")
if not line.startswith("|"):
continue
cells = [c.strip() for c in line.strip("|").split("|")]
if len(cells) < 6:
continue
node, netns, egress, port, status, agent = cells[:6]
if node in ("node", "") or not re.fullmatch(r"[a-z0-9-]+",
node):
continue
if node.startswith("-"):
continue
try:
port_n = int(port)
except ValueError:
continue
nodes[node] = {"netns": netns, "egress_ip": egress,
"cdp_port": port_n, "status": status,
"agent": agent}
except FileNotFoundError:
pass
return nodes
def port_for(node, registry_path=None):
"""CDP port for a node, or None if the node isn't registered."""
rec = load(registry_path).get(node)
return rec["cdp_port"] if rec else None
def active_nodes(registry_path=None):
"""{node: port} for nodes with status == active."""
return {n: r["cdp_port"] for n, r in load(registry_path).items()
if r["status"] == "active"}
if __name__ == "__main__":
if len(sys.argv) == 2:
port = port_for(sys.argv[1])
if port is None:
print("unknown node: %s" % sys.argv[1], file=sys.stderr)
sys.exit(1)
print(port)
else:
for node, port in sorted(active_nodes().items()):
print("%s:%d" % (node, port))