feat(#2363): full-DHCP for all agents — drop static agent_network_ip
All agent containers now receive their bridge IP dynamically via DHCP from the dnsmasq pool instead of a hash-derived static address: - nix/templates/harness-base.nix: networking.useDHCP = true - nix/modules/hive-gateway.nix: expand DHCP pool to full usable range (.2 to .254 on /24) — was last-14-IPs-only - hive-sh4re/src/priv_proto.rs: remove agent_ip from NetworkIsolation - hive-c0re/src/lifecycle/mod.rs: drop agent_network_ip + DHCP_POOL_SIZE - hive-c0re/src/lifecycle/host_config.rs: remove agent_network_ip call - hive-priv/src/main.rs: LOCAL_ADDRESS= empty (DHCP assigns IP); HOST_ADDRESS still set so nixos-container installs default route before the DHCP lease arrives - nix/dhcp-pool-size: deleted (no longer needed) The nix/dhcp-pool-size single-source-of-truth file and all associated Rust/Nix dual-constant plumbing are gone — there is no static map. bridge_gateway_ip() is retained (still needed for HOST_ADDRESS). Closes #2363
This commit is contained in:
parent
eb94b2aae6
commit
4cdbbafc44
8 changed files with 37 additions and 244 deletions
|
|
@ -37,80 +37,6 @@ async fn setup_proposed_seeds_flake_nix() {
|
|||
assert!(tracked.contains("flake.nix"), "flake.nix not committed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_network_ip_is_in_subnet() {
|
||||
// Default subnet 10.42.0.0/24 — agents get .2 to .240 (last 14 are DHCP pool).
|
||||
// agent_slots = usable(253) - DHCP_POOL_SIZE(14) = 239 → offsets in [2, 240].
|
||||
let ip = agent_network_ip("alice", "10.42.0.0/24").expect("should produce an IP");
|
||||
let octets: Vec<u8> = ip.split('.').map(|o| o.parse().unwrap()).collect();
|
||||
assert_eq!(&octets[..3], &[10, 42, 0], "wrong /24 prefix");
|
||||
assert!(
|
||||
octets[3] >= 2 && octets[3] <= 240,
|
||||
"host byte {} — expected in agent-only range [2,240]",
|
||||
octets[3]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_network_ip_never_in_dhcp_pool() {
|
||||
// No agent should be assigned an address in the DHCP pool
|
||||
// (.241-.254 on a /24 with DHCP_POOL_SIZE=14).
|
||||
// agent_slots = usable(253) - DHCP_POOL_SIZE(14) = 239 → offsets in [2, 240].
|
||||
let subnet = "10.42.0.0/24";
|
||||
let names = [
|
||||
"alice",
|
||||
"bob",
|
||||
"carol",
|
||||
"damocles",
|
||||
"iris",
|
||||
"argus",
|
||||
"atlas",
|
||||
"ruth",
|
||||
"dmatrix",
|
||||
"bitburner",
|
||||
"lexis",
|
||||
"sock",
|
||||
"triage",
|
||||
"janet",
|
||||
"eve",
|
||||
"frank",
|
||||
"grace",
|
||||
"heidi",
|
||||
];
|
||||
for name in names {
|
||||
let ip = agent_network_ip(name, subnet).unwrap_or_else(|| panic!("{name} returned None"));
|
||||
let last: u8 = ip.rsplit('.').next().unwrap().parse().unwrap();
|
||||
assert!(
|
||||
last < 241,
|
||||
"{name} got .{last} — inside the DHCP pool [.241-.254]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_network_ip_stable() {
|
||||
// Same name + subnet must always produce the same IP.
|
||||
let a = agent_network_ip("damocles", "10.42.0.0/24");
|
||||
let b = agent_network_ip("damocles", "10.42.0.0/24");
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_network_ip_different_agents() {
|
||||
// Different agent names very likely produce different IPs (not guaranteed,
|
||||
// but for these two names the hashes don't collide).
|
||||
let alice = agent_network_ip("alice", "10.42.0.0/24").unwrap();
|
||||
let bob = agent_network_ip("bob", "10.42.0.0/24").unwrap();
|
||||
assert_ne!(alice, bob, "alice and bob collide — rename one");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_network_ip_different_subnet() {
|
||||
let ip = agent_network_ip("alice", "192.168.5.0/24").expect("should produce an IP");
|
||||
let octets: Vec<u8> = ip.split('.').map(|o| o.parse().unwrap()).collect();
|
||||
assert_eq!(&octets[..3], &[192, 168, 5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bridge_gateway_ip_extracts_verbatim_address() {
|
||||
// HIVE_NETWORK_SUBNET carries the bridge IP verbatim, not the
|
||||
|
|
@ -139,31 +65,6 @@ fn bridge_gateway_ip_rejects_bad_input() {
|
|||
assert!(bridge_gateway_ip("10.42.0/24").is_none()); // 3 octets
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_network_ip_rejects_bad_input() {
|
||||
assert!(agent_network_ip("alice", "notanip/24").is_none());
|
||||
assert!(agent_network_ip("alice", "10.0.0.0/33").is_none()); // prefix > 32
|
||||
assert!(agent_network_ip("alice", "10.0.0.0/31").is_none()); // too small
|
||||
assert!(agent_network_ip("alice", "10.0.0.0").is_none()); // no prefix
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_network_ip_normalizes_bridge_ip_subnet() {
|
||||
// HIVE_NETWORK_SUBNET carries the bridge IP (10.42.0.1/24), not
|
||||
// canonical network (10.42.0.0/24). Both must produce the same result
|
||||
// after host-bit masking.
|
||||
let from_bridge = agent_network_ip("alice", "10.42.0.1/24");
|
||||
let from_canonical = agent_network_ip("alice", "10.42.0.0/24");
|
||||
assert_eq!(
|
||||
from_bridge, from_canonical,
|
||||
"bridge-IP and canonical-network form should normalize to the same result"
|
||||
);
|
||||
// Result must be in .2-.240 (DHCP pool .241-.254 is excluded).
|
||||
let ip = from_bridge.unwrap();
|
||||
let last: u8 = ip.rsplit('.').next().unwrap().parse().unwrap();
|
||||
assert!((2..=240).contains(&last), "host byte {last}");
|
||||
}
|
||||
|
||||
/// `setup_proposed` is idempotent: calling it on an existing repo is a
|
||||
/// no-op (the fresh guard skips all writes).
|
||||
#[tokio::test]
|
||||
|
|
|
|||
Loading…
Reference in a new issue