lib/config/options: rewrite getHostLinkNetworks et al

This commit is contained in:
Astro 2021-11-06 03:38:01 +01:00
parent 7834d64e27
commit 001aaecf3a
1 changed files with 47 additions and 47 deletions

View File

@ -2,53 +2,49 @@
with lib; with lib;
let let
getHostNets = link: # A host needs to know a network if it
# - is a configured interface, or
# - is required behind at least two different links
getHostLinkNetworks = hostName: link:
let let
hostConfig = config.site.hosts.${link}; hostConfig = config.site.hosts.${hostName};
sort = nets: lib.unique ( # all the host's links
builtins.sort (net1: net2: hostLinkNetworks = builtins.mapAttrs (link: _:
config.site.net.${net1}.vlan < config.site.net.${net2}.vlan networksBehindLink hostName link
) nets ) hostConfig.links;
); # how many links have a net in networksBehindLink
networkLinkCount = net:
builtins.length (
builtins.filter (builtins.elem net)
(builtins.attrValues hostLinkNetworks)
);
in in
if config.site.hosts ? ${link} # access port
then if config.site.net ? ${link}
sort (
builtins.attrNames hostConfig.interfaces ++
getLinksNets link
)
else if config.site.net ? ${link}
then [ link ] then [ link ]
else builtins.trace "Don't know what nets to configure for link to \"${link}\"" []; # multiple vlans on this link
else
builtins.filter (net:
# this port and local interface
hostConfig.interfaces ? ${net}
||
# this port and another
networkLinkCount net > 1
) hostLinkNetworks.${link};
# breaks the getHostNets recursion for switches, networksBehindLink = hostName: name:
# requiring any net to be used by at >1 links networksBehindLink' {
getLinksNets = hostName: "${hostName}" = true;
let } [ name ];
linksNets = builtins.mapAttrs (link: _:
unique (
getLinkNets { "${hostName}" = true; } [ link ]
)
) config.site.hosts.${hostName}.links;
allNets = unique (
builtins.concatLists (builtins.attrValues linksNets)
);
netLinkCount = net:
builtins.foldl' (netLinkCount: nets:
if builtins.elem net nets
then netLinkCount + 1
else netLinkCount
) 0 (builtins.attrValues linksNets);
nets = builtins.filter (net:
netLinkCount net > 1
) allNets;
in nets;
getLinkNets = seen: links: networksBehindLink' = seen: links:
if links == [] if links == []
then [] then
# Done, result is the seen link names that are networks:
builtins.filter (name:
config.site.net ? ${name}
) (builtins.attrNames seen)
else else
let let
link = builtins.head links; link = builtins.head links;
@ -59,13 +55,17 @@ let
links' = builtins.tail links; links' = builtins.tail links;
in in
if config.site.hosts ? ${link} if config.site.hosts ? ${link}
then getLinkNets seen' ( then networksBehindLink' seen' (
links' ++ ( links' ++ (
builtins.attrNames config.site.hosts.${link}.interfaces
) ++ (
onlyUnseen (builtins.attrNames config.site.hosts.${link}.links) onlyUnseen (builtins.attrNames config.site.hosts.${link}.links)
) )
) )
else getHostNets link ++ else if config.site.net ? ${link}
getLinkNets seen' (onlyUnseen links'); then networksBehindLink' seen' links'
else throw "Link to invalid target ${link}";
dhcpOpts = { dhcpOpts = {
start = mkOption { start = mkOption {
@ -382,7 +382,7 @@ let
links = mkOption { links = mkOption {
description = "Which port is connected to what other device? Keys are either network names or known hostnames."; description = "Which port is connected to what other device? Keys are either network names or known hostnames.";
default = {}; default = {};
type = with types; attrsOf (submodule linkOpts); type = with types; attrsOf (submodule (linkOpts name));
}; };
wifi = mkOption { wifi = mkOption {
default = {}; default = {};
@ -433,7 +433,7 @@ let
}; };
}; };
linkOpts = { name, ... }: { linkOpts = hostName: { name, ... }: {
options = { options = {
ports = mkOption { ports = mkOption {
type = with types; listOf str; type = with types; listOf str;
@ -447,14 +447,14 @@ let
nets = mkOption { nets = mkOption {
type = with types; listOf str; type = with types; listOf str;
description = "Automatically generated"; description = "Automatically generated";
default = getHostNets name; default = getHostLinkNetworks hostName name;
}; };
vlans = mkOption { vlans = mkOption {
type = with types; listOf int; type = with types; listOf int;
description = "Automatically generated, do not set"; description = "Automatically generated, do not set";
default = map (net: default = map (net:
config.site.net.${net}.vlan config.site.net.${net}.vlan
) (getHostNets name); ) config.site.hosts.${hostName}.links.${name}.nets;
}; };
}; };
}; };