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