{ nixpkgs, services, system }: let pkgs = import nixpkgs { config = {}; inherit system; }; in with 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. The # result is a script that starts a QEMU instance for each virtual # machine. Each machine is given an arbitrary IP address in the # virtual network. buildVirtualNetwork = { nodes }: let nodes_ = lib.mapAttrs (n: buildVM nodes_) (assignIPAddresses nodes); in stdenv.mkDerivation { name = "vms"; buildCommand = '' ensureDir $out/vms ${ lib.concatMapStrings (vm: '' ln -sn ${vm.config.system.build.vm} $out/vms/${vm.config.networking.hostName} '' ) (lib.attrValues nodes_) } ensureDir $out/bin cat > $out/bin/run-vms < as the multicast address to # connect VMs on the same vlan, but allow it to # be overriden using the $QEMU_MCAST_ADDR_ # environment variable. The test driver sets # this variable to prevent collisions between # parallel builds. "-net socket,vlan=${toString second},mcast=" + "\${QEMU_MCAST_ADDR_${toString first}:-232.0.1.${toString first}:1234} " ); }; } ) (lib.getAttr m.first nodes) ] ); in lib.listToAttrs nodes_; # Zip two lists together. Should be moved to pkgs.lib. zip = xs: ys: if xs != [] && ys != [] then [ {first = lib.head xs; second = lib.head ys;} ] ++ zip (lib.tail xs) (lib.tail ys) else []; }