diff --git a/lib/build-vms.nix b/lib/build-vms.nix index 7505f6f49f3b..efd1ce3b8d3f 100644 --- a/lib/build-vms.nix +++ b/lib/build-vms.nix @@ -1,4 +1,4 @@ -{ nixpkgs, services, system }: +{ nixpkgs, services, system, useBackdoor ? false }: let pkgs = import nixpkgs { config = {}; inherit system; }; in @@ -58,7 +58,7 @@ rec { modules = configurations ++ [ ../modules/virtualisation/qemu-vm.nix ../modules/testing/test-instrumentation.nix # !!! should only get added for automated test runs - { key = "no-manual"; services.nixosManual.enable = false; } + { key = "no-manual"; services.nixosManual.enable = false; virtualisation.useBackdoor = useBackdoor; } ]; extraArgs = { inherit nodes; }; }; diff --git a/modules/installer/tools/nixos-build-vms/build-vms.nix b/modules/installer/tools/nixos-build-vms/build-vms.nix new file mode 100644 index 000000000000..bedabecad2d2 --- /dev/null +++ b/modules/installer/tools/nixos-build-vms/build-vms.nix @@ -0,0 +1,16 @@ +{ nixos +, nixpkgs +, services ? "/etc/nixos/services" +, system ? builtins.currentSystem +, networkExpr +, useBackdoor ? false +}: + +let nodes = import networkExpr; +in +(import "${nixos}/lib/build-vms.nix" { + inherit nixpkgs services system useBackdoor; +}) +.buildVirtualNetwork { + inherit nodes; +} diff --git a/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh b/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh new file mode 100644 index 000000000000..709b9051fc45 --- /dev/null +++ b/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh @@ -0,0 +1,66 @@ +#! @shell@ -e + +# Shows the usage of this command to the user + +showUsage() +{ + echo "Usage: $0 -n network_expr -i infrastructure_expr" + echo "Options:" + echo + echo "-n,--network Network Nix expression which captures properties of machines in the network" + echo "--use-backdoor Indicates that the backdoor must be enabled so that the VMs can be accessed through a UNIX domain socket" + echo "--show-trace Shows the output trace" + echo "-h,--help Shows the usage of this command" +} + +# Parse valid argument options + +PARAMS=`getopt -n $0 -o n:h -l network:,use-backdoor,show-trace,help -- "$@"` + +if [ $? != 0 ] +then + showUsage + exit 1 +fi + +eval set -- "$PARAMS" + +# Evaluate valid options + +while [ "$1" != "--" ] +do + case "$1" in + -n|--network) + networkExpr=`readlink -f $2` + ;; + --use-backdoor) + useBackdoorArg="--arg useBackdoor true" + ;; + --show-trace) + showTraceArg="--show-trace" + ;; + -h|--help) + showUsage + exit 0 + ;; + esac + + shift +done + +# Validate the given options + +if [ "$networkExpr" = "" ] +then + echo "ERROR: A network expression must be specified!" >&2 + exit 1 +fi + +if [ -z "$NIXOS" ] +then + NIXOS=/etc/nixos/nixos +fi + +# Build a network of VMs + +nix-build $NIXOS/modules/installer/tools/nixos-build-vms/build-vms.nix --argstr networkExpr $networkExpr --argstr nixos $NIXOS --argstr nixpkgs $NIXPKGS_ALL $useBackdoorArg $showTraceArg diff --git a/modules/installer/tools/nixos-deploy-network/nixos-deploy-network.sh b/modules/installer/tools/nixos-deploy-network/nixos-deploy-network.sh index 9b6d716f3433..08370a15dc86 100644 --- a/modules/installer/tools/nixos-deploy-network/nixos-deploy-network.sh +++ b/modules/installer/tools/nixos-deploy-network/nixos-deploy-network.sh @@ -9,6 +9,7 @@ showUsage() echo echo "-n,--network Network Nix expression which captures properties of machines in the network" echo "-i,--infrastructure Infrastructure Nix expression which captures properties of machines in the network" + echo "--show-trace Shows an output trace" echo "-h,--help Shows the usage of this command" } diff --git a/modules/installer/tools/tools.nix b/modules/installer/tools/tools.nix index 8dd07c67f916..b735863a34c3 100644 --- a/modules/installer/tools/tools.nix +++ b/modules/installer/tools/tools.nix @@ -11,6 +11,11 @@ let isExecutable = true; }); + nixosBuildVMS = makeProg { + name = "nixos-build-vms"; + src = ./nixos-build-vms/nixos-build-vms.sh; + }; + nixosDeployNetwork = makeProg { name = "nixos-deploy-network"; src = ./nixos-deploy-network/nixos-deploy-network.sh; @@ -131,7 +136,8 @@ in config = { environment.systemPackages = - [ nixosDeployNetwork + [ nixosBuildVMS + nixosDeployNetwork nixosInstall nixosRebuild nixosHardwareScan diff --git a/modules/virtualisation/qemu-vm.nix b/modules/virtualisation/qemu-vm.nix index 005e4ebfb54b..50b07435bdac 100644 --- a/modules/virtualisation/qemu-vm.nix +++ b/modules/virtualisation/qemu-vm.nix @@ -111,6 +111,17 @@ let description = "Options passed to QEMU."; }; + virtualisation.useBackdoor = + mkOption { + default = false; + description = + '' + If enabled, the virtual machine makes a connection through TCP port 23 + to a daemon running on the host system acting as a proxy. + This option makes it possible to connect to a VM through a socket file. + ''; + }; + virtualisation.useBootLoader = mkOption { default = false; @@ -145,6 +156,11 @@ let ${toString config.virtualisation.diskSize}M || exit 1 fi + ${pkgs.lib.optionalString cfg.useBackdoor '' + # Remember the current working directory + WORKDIR=$(pwd) + ''} + # Start Samba (which wants to put its socket and config files in TMPDIR). if [ -z "$TMPDIR" -o -z "$USE_TMPDIR" ]; then TMPDIR=$(mktemp -d nix-vm-smbd.XXXXXXXXXX --tmpdir) @@ -153,13 +169,24 @@ let ${pkgs.vmTools.startSamba} + ${pkgs.lib.optionalString cfg.useBackdoor '' + # Create a shell socket file to which the VM can connect and create in the + # current working directory a socket file which can be used to remotely access + # the VM through the shell interface + + ${pkgs.socat}/bin/socat UNIX-LISTEN:./shell UNIX-LISTEN:$WORKDIR/${vmName}.socket,fork & + + while [ ! -e ./shell ]; do sleep 0.1; done # Wait until the socket file is there + ''} + # Start QEMU. exec ${pkgs.qemu_kvm}/bin/qemu-system-x86_64 \ -name ${vmName} \ -m ${toString config.virtualisation.memorySize} \ -net nic,vlan=0,model=virtio \ -chardev socket,id=samba,path=./samba \ - -net user,vlan=0,guestfwd=tcp:10.0.2.4:139-chardev:samba''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS} \ + -net user,vlan=0,guestfwd=tcp:10.0.2.4:139-chardev:samba${if cfg.useBackdoor then ",guestfwd=tcp:10.0.2.6:23-chardev:shell" else ""}''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS} \ + ${if cfg.useBackdoor then "-chardev socket,id=shell,path=./shell" else ""} \ ${if cfg.useBootLoader then '' -drive index=0,file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \ -drive index=1,file=${bootDisk}/disk.img,if=virtio,boot=on \