Turn networking.interfaces into an attribute set

Thus

  networking.interfaces = [ { name = "eth0"; ipAddress = "192.168.15.1"; } ];

can now be written as

  networking.interfaces.eth0.ipAddress = "192.168.15.1";

The old notation still works though.
This commit is contained in:
Eelco Dolstra 2012-11-02 17:08:11 +01:00
parent 93f82dfeef
commit 97f087cd44
7 changed files with 138 additions and 143 deletions

View File

@ -2,7 +2,7 @@
let pkgs = import <nixpkgs> { config = {}; inherit system; }; in
with pkgs;
with pkgs.lib;
with import ../lib/qemu-flags.nix;
rec {
@ -15,7 +15,7 @@ rec {
# hostname and `configX' is a NixOS system configuration. Each
# machine is given an arbitrary IP address in the virtual network.
buildVirtualNetwork =
nodes: let nodesOut = lib.mapAttrs (n: buildVM nodesOut) (assignIPAddresses nodes); in nodesOut;
nodes: let nodesOut = mapAttrs (n: buildVM nodesOut) (assignIPAddresses nodes); in nodesOut;
buildVM =
@ -27,7 +27,7 @@ rec {
[ ../modules/virtualisation/qemu-vm.nix
../modules/testing/test-instrumentation.nix # !!! should only get added for automated test runs
{ key = "no-manual"; services.nixosManual.enable = false; }
] ++ lib.optional minimal ../modules/testing/minimal-kernel.nix;
] ++ optional minimal ../modules/testing/minimal-kernel.nix;
extraArgs = { inherit nodes; };
};
@ -39,51 +39,49 @@ rec {
let
machines = lib.attrNames nodes;
machines = attrNames nodes;
machinesNumbered = lib.zipTwoLists machines (lib.range 1 254);
machinesNumbered = zipTwoLists machines (range 1 254);
nodes_ = lib.flip map machinesNumbered (m: lib.nameValuePair m.first
nodes_ = flip map machinesNumbered (m: nameValuePair m.first
[ ( { config, pkgs, nodes, ... }:
let
interfacesNumbered = lib.zipTwoLists config.virtualisation.vlans (lib.range 1 255);
interfaces =
lib.flip map interfacesNumbered ({ first, second }:
{ name = "eth${toString second}";
ipAddress = "192.168.${toString first}.${toString m.second}";
interfacesNumbered = zipTwoLists config.virtualisation.vlans (range 1 255);
interfaces = flip map interfacesNumbered ({ first, second }:
nameValuePair "eth${toString second}"
{ ipAddress = "192.168.${toString first}.${toString m.second}";
subnetMask = "255.255.255.0";
}
);
});
in
{ key = "ip-address";
config =
{ networking.hostName = m.first;
networking.interfaces = interfaces;
networking.interfaces = listToAttrs interfaces;
networking.primaryIPAddress =
lib.optionalString (interfaces != []) (lib.head interfaces).ipAddress;
optionalString (interfaces != []) (head interfaces).value.ipAddress;
# Put the IP addresses of all VMs in this machine's
# /etc/hosts file. If a machine has multiple
# interfaces, use the IP address corresponding to
# the first interface (i.e. the first network in its
# virtualisation.vlans option).
networking.extraHosts = lib.flip lib.concatMapStrings machines
(m: let config = (lib.getAttr m nodes).config; in
lib.optionalString (config.networking.primaryIPAddress != "")
networking.extraHosts = flip concatMapStrings machines
(m: let config = (getAttr m nodes).config; in
optionalString (config.networking.primaryIPAddress != "")
("${config.networking.primaryIPAddress} " +
"${config.networking.hostName}\n"));
virtualisation.qemu.options =
lib.flip map interfacesNumbered
flip map interfacesNumbered
({ first, second }: qemuNICFlags second first m.second);
};
}
)
(lib.getAttr m.first nodes)
(getAttr m.first nodes)
] );
in lib.listToAttrs nodes_;
in listToAttrs nodes_;
}

View File

@ -37,5 +37,5 @@ let virtualbox = config.boot.kernelPackages.virtualbox; in
'';
};
networking.interfaces = [ { name = "vboxnet0"; ipAddress = "192.168.56.1"; prefixLength = 24; } ];
networking.interfaces.vboxnet0 = { ipAddress = "192.168.56.1"; prefixLength = 24; };
}

View File

@ -9,7 +9,7 @@ let
# Don't start dhclient on explicitly configured interfaces or on
# interfaces that are part of a bridge.
ignoredInterfaces =
map (i: i.name) (filter (i: i ? ipAddress && i.ipAddress != "" ) config.networking.interfaces)
map (i: i.name) (filter (i: i.ipAddress != null) (attrValues config.networking.interfaces))
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
++ config.networking.dhcpcd.denyInterfaces;
@ -104,6 +104,7 @@ in
ExecStart = "@${dhcpcd}/sbin/dhcpcd dhcpcd --config ${dhcpcdConf}";
ExecReload = "${dhcpcd}/sbin/dhcpcd --rebind";
StandardError = "null";
Restart = "always";
};
};

View File

@ -5,7 +5,104 @@ with pkgs.lib;
let
cfg = config.networking;
hasVirtuals = any (i: i.virtual) cfg.interfaces;
interfaces = attrValues cfg.interfaces;
hasVirtuals = any (i: i.virtual) interfaces;
interfaceOpts = { name, ... }: {
options = {
name = mkOption {
example = "eth0";
type = types.string;
description = "Name of the interface.";
};
ipAddress = mkOption {
default = null;
example = "10.0.0.1";
type = types.nullOr types.string;
description = ''
IP address of the interface. Leave empty to configure the
interface using DHCP.
'';
};
prefixLength = mkOption {
default = null;
example = 24;
type = types.nullOr types.int;
description = ''
Subnet mask of the interface, specified as the number of
bits in the prefix (<literal>24</literal>).
'';
};
subnetMask = mkOption {
default = "";
example = "255.255.255.0";
type = types.string;
description = ''
Subnet mask of the interface, specified as a bitmask.
This is deprecated; use <option>prefixLength</option>
instead.
'';
};
macAddress = mkOption {
default = null;
example = "00:11:22:33:44:55";
type = types.nullOr types.string;
description = ''
MAC address of the interface. Leave empty to use the default.
'';
};
virtual = mkOption {
default = false;
type = types.bool;
description = ''
Whether this interface is virtual and should be created by tunctl.
This is mainly useful for creating bridges between a host a virtual
network such as VPN or a virtual machine.
Defaults to tap device, unless interface contains "tun" in its name.
'';
};
virtualOwner = mkOption {
default = "root";
type = types.uniq types.string;
description = ''
In case of a virtual device, the user who owns it.
'';
};
proxyARP = mkOption {
default = false;
type = types.bool;
description = ''
Turn on proxy_arp for this device (and proxy_ndp for ipv6).
This is mainly useful for creating pseudo-bridges between a real
interface and a virtual network such as VPN or a virtual machine for
interfaces that don't support real bridging (most wlan interfaces).
As ARP proxying acts slightly above the link-layer, below-ip traffic
isn't bridged, so things like DHCP won't work. The advantage above
using NAT lies in the fact that no IP addresses are shared, so all
hosts are reachable/routeable.
WARNING: turns on ip-routing, so if you have multiple interfaces, you
should think of the consequence and setup firewall rules to limit this.
'';
};
};
config = {
name = mkDefault name;
};
};
in
@ -66,121 +163,20 @@ in
};
networking.interfaces = mkOption {
default = [];
example = [
{ name = "eth0";
ipAddress = "131.211.84.78";
subnetMask = "255.255.255.128";
}
];
default = {};
example =
{ eth0 = {
ipAddress = "131.211.84.78";
subnetMask = "255.255.255.128";
};
};
description = ''
The configuration for each network interface. If
<option>networking.useDHCP</option> is true, then every
interface not listed here will be configured using DHCP.
'';
type = types.list types.optionSet;
options = {
name = mkOption {
example = "eth0";
type = types.string;
description = ''
Name of the interface.
'';
};
ipAddress = mkOption {
default = "";
example = "10.0.0.1";
type = types.string;
description = ''
IP address of the interface. Leave empty to configure the
interface using DHCP.
'';
};
prefixLength = mkOption {
default = null;
example = 24;
type = types.nullOr types.int;
description = ''
Subnet mask of the interface, specified as the number of
bits in the prefix (<literal>24</literal>).
'';
};
subnetMask = mkOption {
default = "";
example = "255.255.255.0";
type = types.string;
description = ''
Subnet mask of the interface, specified as a bitmask.
This is deprecated; use <option>prefixLength</option>
instead.
'';
};
macAddress = mkOption {
default = "";
example = "00:11:22:33:44:55";
type = types.string;
description = ''
MAC address of the interface. Leave empty to use the default.
'';
};
virtual = mkOption {
default = false;
type = types.bool;
description = ''
Whether this interface is virtual and should be created by tunctl.
This is mainly useful for creating bridges between a host a virtual
network such as VPN or a virtual machine.
Defaults to tap device, unless interface contains "tun" in its name.
'';
};
virtualOwner = mkOption {
default = "root";
type = types.uniq types.string;
description = ''
In case of a virtual device, the user who owns it.
'';
};
proxyARP = mkOption {
default = false;
type = types.bool;
description = ''
Turn on proxy_arp for this device (and proxy_ndp for ipv6).
This is mainly useful for creating pseudo-bridges between a real
interface and a virtual network such as VPN or a virtual machine for
interfaces that don't support real bridging (most wlan interfaces).
As ARP proxying acts slightly above the link-layer, below-ip traffic
isn't bridged, so things like DHCP won't work. The advantage above
using NAT lies in the fact that no IP addresses are shared, so all
hosts are reachable/routeable.
WARNING: turns on ip-routing, so if you have multiple interfaces, you
should think of the consequence and setup firewall rules to limit this.
'';
};
};
};
networking.ifaces = mkOption {
default = listToAttrs
(map (iface: { name = iface.name; value = iface; }) config.networking.interfaces);
internal = true;
description = ''
The network interfaces in <option>networking.interfaces</option>
as an attribute set keyed on the interface name.
'';
type = types.loaOf types.optionSet;
options = [ interfaceOpts ];
};
networking.bridges = mkOption {
@ -288,7 +284,7 @@ in
''}
# Turn on forwarding if any interface has enabled proxy_arp.
${optionalString (any (i: i.proxyARP) cfg.interfaces) ''
${optionalString (any (i: i.proxyARP) interfaces) ''
echo 1 > /proc/sys/net/ipv4/ip_forward
''}
@ -322,12 +318,12 @@ in
echo "bringing up interface..."
ip link set "${i.name}" up
''
+ optionalString (i.macAddress != "")
+ optionalString (i.macAddress != null)
''
echo "setting MAC address to ${i.macAddress}..."
ip link set "${i.name}" address "${i.macAddress}"
''
+ optionalString (i.ipAddress != "")
+ optionalString (i.ipAddress != null)
''
cur=$(ip -4 -o a show dev "${i.name}" | awk '{print $4}')
# Only do a flush/add if it's necessary. This is
@ -400,8 +396,8 @@ in
};
in listToAttrs (
map configureInterface cfg.interfaces ++
map createTunDevice (filter (i: i.virtual) cfg.interfaces))
map configureInterface interfaces ++
map createTunDevice (filter (i: i.virtual) interfaces))
// mapAttrs createBridgeDevice cfg.bridges
// { "network-setup" = networkSetup; };

View File

@ -13,7 +13,7 @@ with pkgs.lib;
wantedBy = [ "multi-user.target" ];
before = [ "sshd.service" ];
after = [ "dhcpcd.service" ];
after = [ "network.target" ];
path = [ pkgs.curl pkgs.iproute ];

View File

@ -16,7 +16,7 @@ let
miniupnpdConf = nodes: pkgs.writeText "miniupnpd.conf"
''
ext_ifname=eth1
listening_ip=${nodes.router.config.networking.ifaces.eth2.ipAddress}/24
listening_ip=${nodes.router.config.networking.interfaces.eth2.ipAddress}/24
allow 1024-65535 192.168.2.0/24 1024-65535
'';
@ -49,7 +49,7 @@ in
{ environment.systemPackages = [ pkgs.transmission ];
virtualisation.vlans = [ 2 ];
networking.defaultGateway =
nodes.router.config.networking.ifaces.eth2.ipAddress;
nodes.router.config.networking.interfaces.eth2.ipAddress;
};
client2 =

View File

@ -13,7 +13,7 @@
{ config, pkgs, nodes, ... }:
{ virtualisation.vlans = [ 1 ];
networking.defaultGateway =
nodes.router.config.networking.ifaces.eth2.ipAddress;
nodes.router.config.networking.interfaces.eth2.ipAddress;
};
router =