139 lines
4 KiB
Nix
139 lines
4 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.plasmacloud.network;
|
|
clusterCfg = config.plasmacloud.cluster;
|
|
|
|
# BGP peer type for FiberLB
|
|
bgpPeerType = types.submodule {
|
|
options = {
|
|
address = mkOption {
|
|
type = types.str;
|
|
description = "Peer IP address (ToR switch, upstream router)";
|
|
example = "192.168.1.1";
|
|
};
|
|
|
|
asn = mkOption {
|
|
type = types.int;
|
|
description = "Peer AS number";
|
|
example = 65001;
|
|
};
|
|
|
|
description = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = "Human-readable peer description";
|
|
example = "ToR switch rack1";
|
|
};
|
|
};
|
|
};
|
|
|
|
in {
|
|
options.plasmacloud.network = {
|
|
fiberlbBgp = {
|
|
enable = mkEnableOption "FiberLB BGP VIP advertisement";
|
|
|
|
vips = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [];
|
|
description = "VIPs to advertise via BGP (CIDR notation)";
|
|
example = [ "203.0.113.10/32" "203.0.113.11/32" ];
|
|
};
|
|
|
|
peers = mkOption {
|
|
type = types.listOf bgpPeerType;
|
|
default = [];
|
|
description = "BGP peers (ToR switches, upstream routers)";
|
|
example = literalExpression ''
|
|
[
|
|
{ address = "192.168.1.1"; asn = 65001; description = "ToR switch rack1"; }
|
|
{ address = "192.168.1.2"; asn = 65001; description = "ToR switch rack2"; }
|
|
]
|
|
'';
|
|
};
|
|
|
|
routerId = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = "BGP router ID (auto-detected from primary IP if null)";
|
|
};
|
|
};
|
|
|
|
prismnetIntegration = {
|
|
enable = mkEnableOption "PrismNET OVN integration";
|
|
};
|
|
};
|
|
|
|
config = mkMerge [
|
|
# FiberLB BGP configuration
|
|
(mkIf cfg.fiberlbBgp.enable {
|
|
# Assertions
|
|
assertions = [
|
|
{
|
|
assertion = clusterCfg.bgp.asn > 0;
|
|
message = "plasmacloud.cluster.bgp.asn must be configured for FiberLB BGP";
|
|
}
|
|
{
|
|
assertion = (length cfg.fiberlbBgp.vips) > 0;
|
|
message = "plasmacloud.network.fiberlbBgp.vips must contain at least one VIP";
|
|
}
|
|
{
|
|
assertion = (length cfg.fiberlbBgp.peers) > 0;
|
|
message = "plasmacloud.network.fiberlbBgp.peers must contain at least one BGP peer";
|
|
}
|
|
];
|
|
|
|
# Wire to nix-nos.bgp (Layer 1)
|
|
nix-nos.enable = true;
|
|
nix-nos.bgp = {
|
|
enable = true;
|
|
backend = "gobgp"; # FiberLB uses GoBGP
|
|
asn = clusterCfg.bgp.asn;
|
|
|
|
# Auto-detect router ID from primary IP or use configured value
|
|
routerId =
|
|
if cfg.fiberlbBgp.routerId != null
|
|
then cfg.fiberlbBgp.routerId
|
|
else
|
|
# Fallback to a simple IP extraction from node config
|
|
let
|
|
hostname = config.networking.hostName;
|
|
node = clusterCfg.nodes.${hostname} or null;
|
|
in
|
|
if node != null then node.ip else "127.0.0.1";
|
|
|
|
peers = cfg.fiberlbBgp.peers;
|
|
|
|
# Convert VIPs to BGP announcements
|
|
announcements = map (vip: { prefix = vip; }) cfg.fiberlbBgp.vips;
|
|
};
|
|
|
|
# FiberLB service configuration (if FiberLB is enabled)
|
|
# Note: This assumes fiberlb service is defined elsewhere
|
|
# services.fiberlb.bgp.gobgpAddress = mkIf (config.services.fiberlb.enable or false) "127.0.0.1:50051";
|
|
})
|
|
|
|
# PrismNET OVN integration
|
|
(mkIf cfg.prismnetIntegration.enable {
|
|
# Enable OVN Controller
|
|
virtualisation.switch.enable = true;
|
|
virtualisation.ovn = {
|
|
enable = true;
|
|
controller = {
|
|
enable = true;
|
|
# Use Geneve encapsulation to avoid VXLAN VNI limitations and allow richer metadata
|
|
encapType = "geneve";
|
|
# Auto-detect IP from cluster config
|
|
encapIp =
|
|
let
|
|
hostname = config.networking.hostName;
|
|
node = clusterCfg.nodes.${hostname} or null;
|
|
in
|
|
if node != null then node.ip else "127.0.0.1";
|
|
};
|
|
};
|
|
})
|
|
];
|
|
}
|