2021-03-20 02:34:13 +01:00
|
|
|
{ config, options, lib, ... }:
|
2021-02-24 23:44:23 +01:00
|
|
|
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
netOpts = { name, ... }: {
|
|
|
|
options = {
|
|
|
|
vlan = mkOption {
|
|
|
|
description = "VLAN tag number";
|
|
|
|
type = types.int;
|
|
|
|
};
|
|
|
|
subnet4 = mkOption {
|
|
|
|
description = "v.w.x.y/z";
|
2021-02-25 01:06:32 +01:00
|
|
|
type = with types; nullOr str;
|
2021-02-24 23:44:23 +01:00
|
|
|
default = null;
|
|
|
|
};
|
2021-03-25 00:46:46 +01:00
|
|
|
subnet4Len = mkOption {
|
|
|
|
type = with types; nullOr types.int;
|
|
|
|
default =
|
|
|
|
let
|
|
|
|
inherit (config.site.net.${name}) subnet4;
|
|
|
|
s = lib.splitString "/" subnet4;
|
|
|
|
in
|
|
|
|
if subnet4 != null && builtins.length s == 2
|
|
|
|
then lib.toInt (elemAt s 1)
|
|
|
|
else null;
|
|
|
|
};
|
2021-02-24 23:44:23 +01:00
|
|
|
subnets6 = mkOption {
|
|
|
|
description = "IPv6 subnets w/o prefixlen (always 64)";
|
2021-02-25 01:06:32 +01:00
|
|
|
type = with types; attrsOf str;
|
2021-02-24 23:44:23 +01:00
|
|
|
default = {};
|
|
|
|
};
|
2021-03-25 00:08:24 +01:00
|
|
|
hosts4 = mkOption {
|
|
|
|
description = "Attribute set of hostnames to IPv4 addresses";
|
|
|
|
type = with types; attrsOf str;
|
|
|
|
default = {};
|
|
|
|
};
|
|
|
|
hosts6 = mkOption {
|
|
|
|
description = "Attribute set of contexts to attribute sets of hostnames to IPv4 addresses";
|
|
|
|
type = with types; attrsOf (attrsOf str);
|
|
|
|
default = {};
|
|
|
|
};
|
2021-02-24 23:44:23 +01:00
|
|
|
};
|
|
|
|
};
|
2021-03-23 00:40:40 +01:00
|
|
|
interfaceOpts = { name, ... }: {
|
|
|
|
options = {
|
|
|
|
hwaddr = mkOption {
|
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
type = mkOption {
|
|
|
|
type = types.enum [ "veth" "phys" ];
|
|
|
|
};
|
2021-03-25 00:08:24 +01:00
|
|
|
gw4 = mkOption {
|
2021-03-23 00:40:40 +01:00
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
gw6 = mkOption {
|
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2021-02-25 01:06:32 +01:00
|
|
|
hostOpts = { name, ... }: {
|
|
|
|
options = {
|
|
|
|
role = mkOption {
|
2021-03-20 00:06:31 +01:00
|
|
|
type = types.enum [ "ap" "switch" "server" "container" "client" ];
|
2021-02-25 01:06:32 +01:00
|
|
|
default = "client";
|
|
|
|
};
|
|
|
|
model = mkOption {
|
|
|
|
type = types.str;
|
2021-03-20 00:06:31 +01:00
|
|
|
default = {
|
|
|
|
ap = "unknown";
|
|
|
|
switch = "unknown";
|
|
|
|
server = "pc";
|
|
|
|
container = "lxc";
|
|
|
|
client = "any";
|
|
|
|
}."${config.site.hosts.${name}.role}";
|
2021-02-25 01:06:32 +01:00
|
|
|
};
|
|
|
|
password = mkOption {
|
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
location = mkOption {
|
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
};
|
2021-03-23 00:40:40 +01:00
|
|
|
interfaces = mkOption {
|
|
|
|
default = {};
|
|
|
|
type = with types; attrsOf (submodule interfaceOpts);
|
|
|
|
};
|
2021-03-25 00:46:46 +01:00
|
|
|
isRouter = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = config.site.hosts.${name}.interfaces ? core;
|
|
|
|
};
|
2021-02-25 01:06:32 +01:00
|
|
|
};
|
|
|
|
};
|
2021-02-24 23:44:23 +01:00
|
|
|
in
|
|
|
|
{
|
|
|
|
options.site = {
|
|
|
|
net = mkOption {
|
|
|
|
default = {};
|
|
|
|
type = with types; attrsOf (submodule netOpts);
|
|
|
|
};
|
2021-02-25 01:06:32 +01:00
|
|
|
hosts = mkOption {
|
|
|
|
default = {};
|
|
|
|
type = with types; attrsOf (submodule hostOpts);
|
|
|
|
};
|
2021-02-24 23:44:23 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
config.warnings =
|
|
|
|
let
|
|
|
|
findCollisions = getter: xs:
|
|
|
|
(builtins.foldl' ({ known, dup }: k:
|
|
|
|
let
|
|
|
|
ks = builtins.toString k;
|
|
|
|
in
|
|
|
|
if known ? ${ks}
|
|
|
|
then { inherit known; dup = dup ++ [ks]; }
|
|
|
|
else { known = known // { ${ks} = true; }; inherit dup; }
|
|
|
|
) {
|
|
|
|
known = {}; dup = [];
|
|
|
|
} (
|
|
|
|
concatMap getter (builtins.attrValues xs)
|
|
|
|
)).dup;
|
|
|
|
reportCollisions = name: getter: xs:
|
|
|
|
map (k: "Duplicate ${name}: ${k}") (findCollisions getter xs);
|
|
|
|
in
|
|
|
|
(reportCollisions "VLAN tag" (x: [x.vlan]) config.site.net) ++
|
|
|
|
(reportCollisions "IPv4 subnet" (x: if x.subnet4 == null then [] else [x.subnet4]) config.site.net) ++
|
|
|
|
(reportCollisions "IPv6 subnet" (x: builtins.attrValues x.subnets6) config.site.net);
|
|
|
|
}
|