1{ system, minimal ? false }:
2
3let pkgs = import ../.. { config = {}; inherit system; }; in
4
5with pkgs.lib;
6with import ../lib/qemu-flags.nix;
7
8rec {
9
10 inherit pkgs;
11
12
13 # Build a virtual network from an attribute set `{ machine1 =
14 # config1; ... machineN = configN; }', where `machineX' is the
15 # hostname and `configX' is a NixOS system configuration. Each
16 # machine is given an arbitrary IP address in the virtual network.
17 buildVirtualNetwork =
18 nodes: let nodesOut = mapAttrs (n: buildVM nodesOut) (assignIPAddresses nodes); in nodesOut;
19
20
21 buildVM =
22 nodes: configurations:
23
24 import ./eval-config.nix {
25 inherit system;
26 modules = configurations ++
27 [ ../modules/virtualisation/qemu-vm.nix
28 ../modules/testing/test-instrumentation.nix # !!! should only get added for automated test runs
29 { key = "no-manual"; services.nixosManual.enable = false; }
30 ] ++ optional minimal ../modules/testing/minimal-kernel.nix;
31 extraArgs = { inherit nodes; };
32 };
33
34
35 # Given an attribute set { machine1 = config1; ... machineN =
36 # configN; }, sequentially assign IP addresses in the 192.168.1.0/24
37 # range to each machine, and set the hostname to the attribute name.
38 assignIPAddresses = nodes:
39
40 let
41
42 machines = attrNames nodes;
43
44 machinesNumbered = zipLists machines (range 1 254);
45
46 nodes_ = flip map machinesNumbered (m: nameValuePair m.fst
47 [ ( { config, pkgs, nodes, ... }:
48 let
49 interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255);
50 interfaces = flip map interfacesNumbered ({ fst, snd }:
51 nameValuePair "eth${toString snd}" { ip4 =
52 [ { address = "192.168.${toString fst}.${toString m.snd}";
53 prefixLength = 24;
54 } ];
55 });
56 in
57 { key = "ip-address";
58 config =
59 { networking.hostName = m.fst;
60
61 networking.interfaces = listToAttrs interfaces;
62
63 networking.primaryIPAddress =
64 optionalString (interfaces != []) (head (head interfaces).value.ip4).address;
65
66 # Put the IP addresses of all VMs in this machine's
67 # /etc/hosts file. If a machine has multiple
68 # interfaces, use the IP address corresponding to
69 # the first interface (i.e. the first network in its
70 # virtualisation.vlans option).
71 networking.extraHosts = flip concatMapStrings machines
72 (m': let config = (getAttr m' nodes).config; in
73 optionalString (config.networking.primaryIPAddress != "")
74 ("${config.networking.primaryIPAddress} " +
75 "${config.networking.hostName}\n"));
76
77 virtualisation.qemu.options =
78 flip map interfacesNumbered
79 ({ fst, snd }: qemuNICFlags snd fst m.snd);
80 };
81 }
82 )
83 (getAttr m.fst nodes)
84 ] );
85
86 in listToAttrs nodes_;
87
88}