From 97f087cd447ef773cd15c6750df5aa24c633ea25 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 2 Nov 2012 17:08:11 +0100 Subject: [PATCH] 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. --- lib/build-vms.nix | 40 +++-- modules/programs/virtualbox.nix | 2 +- modules/services/networking/dhcpcd.nix | 3 +- modules/tasks/network-interfaces.nix | 228 ++++++++++++------------- modules/virtualisation/ec2-data.nix | 2 +- tests/bittorrent.nix | 4 +- tests/nat.nix | 2 +- 7 files changed, 138 insertions(+), 143 deletions(-) diff --git a/lib/build-vms.nix b/lib/build-vms.nix index aacd0e99cb1..59f05bfd104 100644 --- a/lib/build-vms.nix +++ b/lib/build-vms.nix @@ -2,7 +2,7 @@ let pkgs = import { 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_; } diff --git a/modules/programs/virtualbox.nix b/modules/programs/virtualbox.nix index 7bce11ab855..a7c41d915ec 100644 --- a/modules/programs/virtualbox.nix +++ b/modules/programs/virtualbox.nix @@ -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; }; } diff --git a/modules/services/networking/dhcpcd.nix b/modules/services/networking/dhcpcd.nix index 3abd77c8eeb..6c8194f0971 100644 --- a/modules/services/networking/dhcpcd.nix +++ b/modules/services/networking/dhcpcd.nix @@ -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"; }; }; diff --git a/modules/tasks/network-interfaces.nix b/modules/tasks/network-interfaces.nix index d36a1081de5..412e62bfe80 100644 --- a/modules/tasks/network-interfaces.nix +++ b/modules/tasks/network-interfaces.nix @@ -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 (24). + ''; + }; + + 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 + 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 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 (24). - ''; - }; - - 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 - 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 - 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; }; diff --git a/modules/virtualisation/ec2-data.nix b/modules/virtualisation/ec2-data.nix index 3f005d6eb2d..6ca89dd7ac5 100644 --- a/modules/virtualisation/ec2-data.nix +++ b/modules/virtualisation/ec2-data.nix @@ -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 ]; diff --git a/tests/bittorrent.nix b/tests/bittorrent.nix index 9e4ee2e0635..180da8267e0 100644 --- a/tests/bittorrent.nix +++ b/tests/bittorrent.nix @@ -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 = diff --git a/tests/nat.nix b/tests/nat.nix index 7b03739a9bc..55d87ed4fa1 100644 --- a/tests/nat.nix +++ b/tests/nat.nix @@ -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 =