at 21.11-pre 4.0 kB view raw
1{ system 2, # Use a minimal kernel? 3 minimal ? false 4, # Ignored 5 config ? null 6, # Nixpkgs, for qemu, lib and more 7 pkgs 8, # !!! See comment about args in lib/modules.nix 9 specialArgs ? {} 10, # NixOS configuration to add to the VMs 11 extraConfigurations ? [] 12}: 13 14with pkgs.lib; 15with import ../lib/qemu-flags.nix { inherit pkgs; }; 16 17rec { 18 19 inherit pkgs; 20 21 # Build a virtual network from an attribute set `{ machine1 = 22 # config1; ... machineN = configN; }', where `machineX' is the 23 # hostname and `configX' is a NixOS system configuration. Each 24 # machine is given an arbitrary IP address in the virtual network. 25 buildVirtualNetwork = 26 nodes: let nodesOut = mapAttrs (n: buildVM nodesOut) (assignIPAddresses nodes); in nodesOut; 27 28 29 buildVM = 30 nodes: configurations: 31 32 import ./eval-config.nix { 33 inherit system specialArgs; 34 modules = configurations ++ extraConfigurations; 35 baseModules = (import ../modules/module-list.nix) ++ 36 [ ../modules/virtualisation/qemu-vm.nix 37 ../modules/testing/test-instrumentation.nix # !!! should only get added for automated test runs 38 { key = "no-manual"; documentation.nixos.enable = false; } 39 { key = "no-revision"; 40 # Make the revision metadata constant, in order to avoid needless retesting. 41 # The human version (e.g. 21.05-pre) is left as is, because it is useful 42 # for external modules that test with e.g. nixosTest and rely on that 43 # version number. 44 config.system.nixos.revision = "constant-nixos-revision"; 45 } 46 { key = "nodes"; _module.args.nodes = nodes; } 47 ] ++ optional minimal ../modules/testing/minimal-kernel.nix; 48 }; 49 50 51 # Given an attribute set { machine1 = config1; ... machineN = 52 # configN; }, sequentially assign IP addresses in the 192.168.1.0/24 53 # range to each machine, and set the hostname to the attribute name. 54 assignIPAddresses = nodes: 55 56 let 57 58 machines = attrNames nodes; 59 60 machinesNumbered = zipLists machines (range 1 254); 61 62 nodes_ = forEach machinesNumbered (m: nameValuePair m.fst 63 [ ( { config, nodes, ... }: 64 let 65 interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255); 66 interfaces = forEach interfacesNumbered ({ fst, snd }: 67 nameValuePair "eth${toString snd}" { ipv4.addresses = 68 [ { address = "192.168.${toString fst}.${toString m.snd}"; 69 prefixLength = 24; 70 } ]; 71 }); 72 in 73 { key = "ip-address"; 74 config = 75 { networking.hostName = mkDefault m.fst; 76 77 networking.interfaces = listToAttrs interfaces; 78 79 networking.primaryIPAddress = 80 optionalString (interfaces != []) (head (head interfaces).value.ipv4.addresses).address; 81 82 # Put the IP addresses of all VMs in this machine's 83 # /etc/hosts file. If a machine has multiple 84 # interfaces, use the IP address corresponding to 85 # the first interface (i.e. the first network in its 86 # virtualisation.vlans option). 87 networking.extraHosts = flip concatMapStrings machines 88 (m': let config = (getAttr m' nodes).config; in 89 optionalString (config.networking.primaryIPAddress != "") 90 ("${config.networking.primaryIPAddress} " + 91 optionalString (config.networking.domain != null) 92 "${config.networking.hostName}.${config.networking.domain} " + 93 "${config.networking.hostName}\n")); 94 95 virtualisation.qemu.options = 96 forEach interfacesNumbered 97 ({ fst, snd }: qemuNICFlags snd fst m.snd); 98 }; 99 } 100 ) 101 (getAttr m.fst nodes) 102 ] ); 103 104 in listToAttrs nodes_; 105 106}