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;
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
hostConfig = config.site.hosts.${link};
sort = nets: lib.unique (
builtins.sort (net1: net2:
config.site.net.${net1}.vlan < config.site.net.${net2}.vlan
) nets
);
hostConfig = config.site.hosts.${hostName};
# all the host's links
hostLinkNetworks = builtins.mapAttrs (link: _:
networksBehindLink hostName link
) hostConfig.links;
# how many links have a net in networksBehindLink
networkLinkCount = net:
builtins.length (
builtins.filter (builtins.elem net)
(builtins.attrValues hostLinkNetworks)
);
in
if config.site.hosts ? ${link}
then
sort (
builtins.attrNames hostConfig.interfaces ++
getLinksNets link
)
else if config.site.net ? ${link}
# access port
if config.site.net ? ${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,
# requiring any net to be used by at >1 links
getLinksNets = hostName:
let
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;
networksBehindLink = hostName: name:
networksBehindLink' {
"${hostName}" = true;
} [ name ];
getLinkNets = seen: links:
networksBehindLink' = seen: 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
let
link = builtins.head links;
@ -59,13 +55,17 @@ let
links' = builtins.tail links;
in
if config.site.hosts ? ${link}
then getLinkNets seen' (
then networksBehindLink' seen' (
links' ++ (
builtins.attrNames config.site.hosts.${link}.interfaces
) ++ (
onlyUnseen (builtins.attrNames config.site.hosts.${link}.links)
)
)
else getHostNets link ++
getLinkNets seen' (onlyUnseen links');
else if config.site.net ? ${link}
then networksBehindLink' seen' links'
else throw "Link to invalid target ${link}";
dhcpOpts = {
start = mkOption {
@ -382,7 +382,7 @@ let
links = mkOption {
description = "Which port is connected to what other device? Keys are either network names or known hostnames.";
default = {};
type = with types; attrsOf (submodule linkOpts);
type = with types; attrsOf (submodule (linkOpts name));
};
wifi = mkOption {
default = {};
@ -433,7 +433,7 @@ let
};
};
linkOpts = { name, ... }: {
linkOpts = hostName: { name, ... }: {
options = {
ports = mkOption {
type = with types; listOf str;
@ -447,14 +447,14 @@ let
nets = mkOption {
type = with types; listOf str;
description = "Automatically generated";
default = getHostNets name;
default = getHostLinkNetworks hostName name;
};
vlans = mkOption {
type = with types; listOf int;
description = "Automatically generated, do not set";
default = map (net:
config.site.net.${net}.vlan
) (getHostNets name);
) config.site.hosts.${hostName}.links.${name}.nets;
};
};
};