nixpkgs/nixos/lib/build-vms.nix
David Arnold 8bbdff4581
nixosTest: Force system.nixos.revision constant
nixos tests are blended with other system configurations, hence
their settings must be either enforced or defaulted.

This particular setting is set via lib.nixosSystem as
`system.nixos.revision = final.mkIf (self ? rev) self.rev;` which would
mean that without this change no flake generated nixos could be blended
with nixos testing.

This setting was made previously constant in 
169c6b4b14 in order to avoid pointless
rebuilds of the testing VMs, but was set without enforcing it.
2021-06-21 11:08:26 -05:00

106 lines
4 KiB
Nix

{ system
, # Use a minimal kernel?
minimal ? false
, # Ignored
config ? null
, # Nixpkgs, for qemu, lib and more
pkgs
, # !!! See comment about args in lib/modules.nix
specialArgs ? {}
, # NixOS configuration to add to the VMs
extraConfigurations ? []
}:
with pkgs.lib;
with import ../lib/qemu-flags.nix { inherit pkgs; };
rec {
inherit pkgs;
# Build a virtual network from an attribute set `{ machine1 =
# config1; ... machineN = configN; }', where `machineX' is the
# hostname and `configX' is a NixOS system configuration. Each
# machine is given an arbitrary IP address in the virtual network.
buildVirtualNetwork =
nodes: let nodesOut = mapAttrs (n: buildVM nodesOut) (assignIPAddresses nodes); in nodesOut;
buildVM =
nodes: configurations:
import ./eval-config.nix {
inherit system specialArgs;
modules = configurations ++ extraConfigurations;
baseModules = (import ../modules/module-list.nix) ++
[ ../modules/virtualisation/qemu-vm.nix
../modules/testing/test-instrumentation.nix # !!! should only get added for automated test runs
{ key = "no-manual"; documentation.nixos.enable = false; }
{ key = "no-revision";
# Make the revision metadata constant, in order to avoid needless retesting.
# The human version (e.g. 21.05-pre) is left as is, because it is useful
# for external modules that test with e.g. nixosTest and rely on that
# version number.
config.system.nixos.revision = mkForce "constant-nixos-revision";
}
{ key = "nodes"; _module.args.nodes = nodes; }
] ++ optional minimal ../modules/testing/minimal-kernel.nix;
};
# Given an attribute set { machine1 = config1; ... machineN =
# configN; }, sequentially assign IP addresses in the 192.168.1.0/24
# range to each machine, and set the hostname to the attribute name.
assignIPAddresses = nodes:
let
machines = attrNames nodes;
machinesNumbered = zipLists machines (range 1 254);
nodes_ = forEach machinesNumbered (m: nameValuePair m.fst
[ ( { config, nodes, ... }:
let
interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255);
interfaces = forEach interfacesNumbered ({ fst, snd }:
nameValuePair "eth${toString snd}" { ipv4.addresses =
[ { address = "192.168.${toString fst}.${toString m.snd}";
prefixLength = 24;
} ];
});
in
{ key = "ip-address";
config =
{ networking.hostName = mkDefault m.fst;
networking.interfaces = listToAttrs interfaces;
networking.primaryIPAddress =
optionalString (interfaces != []) (head (head interfaces).value.ipv4.addresses).address;
# 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 = flip concatMapStrings machines
(m': let config = (getAttr m' nodes).config; in
optionalString (config.networking.primaryIPAddress != "")
("${config.networking.primaryIPAddress} " +
optionalString (config.networking.domain != null)
"${config.networking.hostName}.${config.networking.domain} " +
"${config.networking.hostName}\n"));
virtualisation.qemu.options =
forEach interfacesNumbered
({ fst, snd }: qemuNICFlags snd fst m.snd);
};
}
)
(getAttr m.fst nodes)
] );
in listToAttrs nodes_;
}