diff --git a/doc/manual/man-nixos-build-vms.xml b/doc/manual/man-nixos-build-vms.xml new file mode 100644 index 000000000000..1650f33064fb --- /dev/null +++ b/doc/manual/man-nixos-build-vms.xml @@ -0,0 +1,148 @@ + + + + nixos-build-vms + 8 + NixOS + + + + + nixos-build-vms + build a network of virtual machines from a network of NixOS configurations + + + + + nixos-build-vms + + + + + network.nix + + + +Description + +This command builds a network of QEMU-KVM virtual machines of a Nix expression +specifying a network of NixOS machines. The virtual network can be started by +executing the bin/run-vms shell script that is generated by +this command. By default, a result symlink is produced that +points to the generated virtual network. + + +This command also provides the option, +which spawns UNIX domain sockets in the current working directory by using the +socat command. This allows +users to remotely script a generated virtual machine. + +A network Nix expression has the following structure: + + +{ + test1 = {pkgs, config, ...}: + { + services.openssh.enable = true; + nixpkgs.system = "i686-linux"; + deployment.targetHost = "test1.example.net"; + + # Other NixOS options + }; + + test2 = {pkgs, config, ...}: + { + services.openssh.enable = true; + services.httpd.enable = true; + environment.systemPackages = [ pkgs.lynx ]; + nixpkgs.system = "x86_64-linux"; + deployment.targetHost = "test2.example.net"; + + # Other NixOS options + }; +} + + +Each attribute in the expression represents a machine in the network +(e.g. test1 and test2) +referring to a function defining a NixOS configuration. +In each NixOS configuration, two attributes have a special meaning. +The deployment.targetHost specifies the address +(domain name or IP address) +of the system which is used by ssh to perform +remote deployment operations. The nixpkgs.system +attribute can be used to specify an architecture for the target machine, +such as i686-linux which builds a 32-bit NixOS +configuration. Omitting this property will build the configuration +for the same architecture as the host system. + + + + +Options + +This command accepts the following options: + + + + + + + Indicates that the backdoor must be enabled so that the VMs can be + accessed through a UNIX domain socket. The UNIX domain sockets are + created in the current working directory. + + + + + + + Shows a trace of the output. + + + + + + + Do not create a 'result' symlink. + + + + + , + + Shows the usage of this command to the user. + + + + + + + + +Environment variables + + + + + NIXOS + + Path to the NixOS source tree. Defaults to + /etc/nixos/nixos. + + + + + NIXPKGS_ALL + + Path to the Nixpkgs source tree. Defaults to + /etc/nixos/nixpkgs. + + + + + + + diff --git a/doc/manual/man-nixos-deploy-network.xml b/doc/manual/man-nixos-deploy-network.xml new file mode 100644 index 000000000000..2a1f78f6ff8b --- /dev/null +++ b/doc/manual/man-nixos-deploy-network.xml @@ -0,0 +1,135 @@ + + + + nixos-deploy-network + 8 + NixOS + + + + + nixos-deploy-network + deploy a network of NixOS configurations into a network of machines + + + + + nixos-deploy-network + + + + network.nix + + + +Description + +This command automatically deploys a network of NixOS +configurations into a network of machines. +First, it tries to build all the system derivations defined +in the network expression. Then it efficiently transfers +the closures to the machines in the network. Finally, the configurations +are activated. In case of a failure, a rollback is performed, +which brings all the updated configurations back into the previous +state. + +A network Nix expression has the following structure: + + +{ + test1 = {pkgs, config, ...}: + { + services.openssh.enable = true; + nixpkgs.system = "i686-linux"; + deployment.targetHost = "test1.example.net"; + + # Other NixOS options + }; + + test2 = {pkgs, config, ...}: + { + services.openssh.enable = true; + services.httpd.enable = true; + environment.systemPackages = [ pkgs.lynx ]; + nixpkgs.system = "x86_64-linux"; + deployment.targetHost = "test2.example.net"; + + # Other NixOS options + }; +} + + +Each attribute in the expression represents a machine in the network +(e.g. test1 and test2) +referring to a function defining a NixOS configuration. +In each NixOS configuration, two attributes have a special meaning. +The deployment.targetHost specifies the address +(domain name or IP address) +of the system which is used by ssh to perform +remote deployment operations. The nixpkgs.system +attribute can be used to specify an architecture for the target machine, +such as i686-linux which builds a 32-bit NixOS +configuration. Omitting this property will build the configuration +for the same architecture as the host system. + + + + +Options + +This command accepts the following options: + + + + + + + Shows a trace of the output. + + + + + + + Do not create a 'result' symlink. + + + + + , + + Shows the usage of this command to the user. + + + + + + + + +Environment variables + + + + + NIXOS + + Path to the NixOS source tree. Defaults to + /etc/nixos/nixos. + + + + + NIXPKGS_ALL + + Path to the Nixpkgs source tree. Defaults to + /etc/nixos/nixpkgs. + + + + + + + diff --git a/doc/manual/man-pages.xml b/doc/manual/man-pages.xml index e3b3a5bc2899..ffe0100c5ed3 100644 --- a/doc/manual/man-pages.xml +++ b/doc/manual/man-pages.xml @@ -26,5 +26,6 @@ - + + diff --git a/lib/build-vms.nix b/lib/build-vms.nix index efd1ce3b8d3f..2c867a0985ba 100644 --- a/lib/build-vms.nix +++ b/lib/build-vms.nix @@ -108,7 +108,7 @@ rec { virtualisation.qemu.options = lib.flip lib.concatMapStrings interfacesNumbered - ({ first, second }: qemuNICFlags second first ); + ({ first, second }: qemuNICFlags second first m.second); }; } ) diff --git a/lib/qemu-flags.nix b/lib/qemu-flags.nix index 05edc1d2cc6c..7831c8f149ab 100644 --- a/lib/qemu-flags.nix +++ b/lib/qemu-flags.nix @@ -2,8 +2,8 @@ { - qemuNICFlags = nic: net: - "-net nic,vlan=${toString nic},model=virtio " + + qemuNICFlags = nic: net: machine: + "-net nic,vlan=${toString nic},macaddr=52:54:00:12:${toString net}:${toString machine},model=virtio " + # Use 232.0.1. 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 diff --git a/lib/test-driver/Machine.pm b/lib/test-driver/Machine.pm index daa40f78f9f2..abf08c7fcf24 100644 --- a/lib/test-driver/Machine.pm +++ b/lib/test-driver/Machine.pm @@ -19,11 +19,20 @@ for (my $n = 0; $n < 256; $n++) { $ENV{"QEMU_MCAST_ADDR_$n"} = "$mcastPrefix.$n.$mcastSuffix"; } +my $showGraphics = defined $ENV{'DISPLAY'}; + sub new { my ($class, $args) = @_; my $startCommand = $args->{startCommand}; + + my $name = $args->{name}; + if (!$name) { + $startCommand =~ /run-(.*)-vm$/; + $name = $1 || "machine"; + } + if (!$startCommand) { # !!! merge with qemu-vm.nix. $startCommand = @@ -34,12 +43,8 @@ sub new { $startCommand .= "-cdrom $args->{cdrom} " if defined $args->{cdrom}; $startCommand .= $args->{qemuFlags} || ""; - } - - my $name = $args->{name}; - if (!$name) { - $startCommand =~ /run-(.*)-vm$/; - $name = $1 || "machine"; + } else { + $startCommand = Cwd::abs_path $startCommand; } my $tmpDir = $ENV{'TMPDIR'} || "/tmp"; @@ -51,7 +56,7 @@ sub new { pid => 0, connected => 0, socket => undef, - stateDir => "$tmpDir/$name", + stateDir => "$tmpDir/vm-state-$name", monitor => undef, }; @@ -121,12 +126,14 @@ sub start { dup2(fileno($serialC), fileno(STDERR)); $ENV{TMPDIR} = $self->{stateDir}; $ENV{USE_TMPDIR} = 1; - $ENV{QEMU_OPTS} = "-nographic -no-reboot -monitor unix:./monitor -chardev socket,id=shell,path=./shell"; + $ENV{QEMU_OPTS} = + "-no-reboot -monitor unix:./monitor -chardev socket,id=shell,path=./shell " . + ($showGraphics ? "-serial stdio" : "-nographic"); $ENV{QEMU_NET_OPTS} = "guestfwd=tcp:10.0.2.6:23-chardev:shell"; $ENV{QEMU_KERNEL_PARAMS} = "hostTmpDir=$ENV{TMPDIR}"; chdir $self->{stateDir} or die; exec $self->{startCommand}; - die; + die "running VM script: $!"; } # Process serial line output. @@ -248,7 +255,8 @@ sub execute { my $out = ""; while (1) { - my $line = readline($self->{socket}) or die "connection to VM lost unexpectedly"; + my $line = readline($self->{socket}); + die "connection to VM lost unexpectedly" unless defined $line; #$self->log("got line: $line"); if ($line =~ /^(.*)\|\!\=EOF\s+(\d+)$/) { $out .= $1; @@ -267,7 +275,7 @@ sub succeed { my ($status, $out) = $self->execute($command); if ($status != 0) { $self->log("output: $out"); - die "command `$command' did not succeed (exit code $status)"; + die "command `$command' did not succeed (exit code $status)\n"; } $res .= $out; } @@ -404,7 +412,8 @@ sub unblock { # Take a screenshot of the X server on :0.0. sub screenshot { my ($self, $filename) = @_; - $filename = "$ENV{'out'}/${filename}.png" if $filename =~ /^\w+$/; + my $dir = $ENV{'out'} || Cwd::abs_path("."); + $filename = "$dir/${filename}.png" if $filename =~ /^\w+$/; my $tmp = "${filename}.ppm"; $self->sendMonitorCommand("screendump $tmp"); system("convert $tmp ${filename}") == 0 diff --git a/lib/test-driver/test-driver.pl b/lib/test-driver/test-driver.pl index ad1af5a6fbf4..6735b52dd695 100644 --- a/lib/test-driver/test-driver.pl +++ b/lib/test-driver/test-driver.pl @@ -1,8 +1,13 @@ +#! @perl@ -w -I@libDir@ -I@readline@ + use strict; use Machine; +use Term::ReadLine; $SIG{PIPE} = 'IGNORE'; # because Unix domain sockets may die unexpectedly +$ENV{PATH} = "@extraPath@:$ENV{PATH}"; + STDERR->autoflush(1); my %vms; @@ -26,10 +31,13 @@ sub runTests { eval "$context $ENV{tests}"; die $@ if $@; } else { - while () { + my $term = Term::ReadLine->new('nixos-vm-test'); + $term->ReadHistory; + while (defined ($_ = $term->readline("> "))) { eval "$context $_\n"; warn $@ if $@; } + $term->WriteHistory; } # Copy the kernel coverage data for each machine, if the kernel diff --git a/lib/testing.nix b/lib/testing.nix index 02c011c5bc83..6c7a9edac696 100644 --- a/lib/testing.nix +++ b/lib/testing.nix @@ -8,6 +8,27 @@ rec { inherit pkgs; + testDriver = stdenv.mkDerivation { + name = "nixos-test-driver"; + buildCommand = + '' + mkdir -p $out/bin + cp ${./test-driver/test-driver.pl} $out/bin/nixos-test-driver + chmod u+x $out/bin/nixos-test-driver + + libDir=$out/lib/perl5/site_perl + mkdir -p $libDir + cp ${./test-driver/Machine.pm} $libDir/Machine.pm + + substituteInPlace $out/bin/nixos-test-driver \ + --subst-var-by perl "${perl}/bin/perl" \ + --subst-var-by readline "${perlPackages.TermReadLineGnu}/lib/perl5/site_perl" \ + --subst-var-by extraPath "${imagemagick}/bin" \ + --subst-var libDir + ''; + }; + + # Run an automated test suite in the given virtual network. # `network' must be the result of a call to the # `buildVirtualNetwork' function. `tests' is a Perl fragment @@ -20,15 +41,13 @@ rec { inherit tests; - buildInputs = [ pkgs.qemu_kvm pkgs.imagemagick ]; + buildInputs = [ pkgs.qemu_kvm ]; buildCommand = '' - mkdir $out - cp ${./test-driver/Machine.pm} Machine.pm ensureDir $out/nix-support - - ${perl}/bin/perl ${./test-driver/test-driver.pl} ${network}/vms/*/bin/run-*-vm + + ${testDriver}/bin/nixos-test-driver ${network}/vms/*/bin/run-*-vm for i in */coverage-data; do ensureDir $out/coverage-data @@ -98,13 +117,38 @@ rec { if t ? nodes then t.nodes else if t ? machine then { machine = t.machine; } else { }; + vms = buildVirtualNetwork { inherit nodes; }; - test = runTests vms + + testScript = # Call the test script with the computed nodes. - (if builtins.isFunction t.testScript then t.testScript { inherit (vms) nodes; } else t.testScript); + if builtins.isFunction t.testScript + then t.testScript { inherit (vms) nodes; } + else t.testScript; + + test = runTests vms testScript; + report = makeReport test; + + # Generate a convenience wrapper for running the test driver + # interactively with the specified network. + driver = runCommand "nixos-test-driver" + { buildInputs = [ makeWrapper]; + inherit testScript; + } + '' + mkdir -p $out/bin + ln -s ${vms}/bin/* $out/bin/ + ln -s ${testDriver}/bin/* $out/bin/ + wrapProgram $out/bin/nixos-test-driver \ + --add-flags "${vms}/vms/*/bin/run-*-vm" \ + --run "testScript=\"\$(cat $out/test-script)\"" \ + --set testScript '"$testScript"' + echo "$testScript" > $out/test-script + ''; # " }; + runInMachine = { drv , machine @@ -140,7 +184,7 @@ rec { export PATH=${qemu_kvm}/bin:${coreutils}/bin cp ${./test-driver/Machine.pm} Machine.pm export tests='${testscript}' - ${perl}/bin/perl ${./test-driver/test-driver.pl} ${vms}/vms/*/bin/run-*-vm + ${testDriver}/bin/nixos-test-driver ${vms}/vms/*/bin/run-*-vm ''; # */ in @@ -152,6 +196,7 @@ rec { origBuilder = attrs.builder; }); + runInMachineWithX = { require ? [], ...}@args : let client = @@ -174,6 +219,7 @@ rec { '' ; } // args ); + simpleTest = as: (makeTest ({ ... }: as)).test; } diff --git a/modules/config/power-management.nix b/modules/config/power-management.nix index ce67285140e4..97b7f61c4737 100644 --- a/modules/config/power-management.nix +++ b/modules/config/power-management.nix @@ -10,10 +10,15 @@ let '' #! ${pkgs.stdenv.shell} action="$1" - if [ "$action" = "resume" ]; then - ${cfg.resumeCommands} - ${cfg.powerUpCommands} - fi + case "$action" in + hibernate|suspend) + ${cfg.powerDownCommands} + ;; + thaw|resume) + ${cfg.resumeCommands} + ${cfg.powerUpCommands} + ;; + esac ''; in @@ -50,6 +55,17 @@ in it resumes from suspend or hibernation. ''; }; + + powerDownCommands = mkOption { + default = ""; + example = "${pkgs.hdparm}/sbin/hdparm -B 255 /dev/sda"; + description = + '' + Commands executed when the machine powers down. That is, + they're executed both when the system shuts down and when + it goes to suspend or hibernation. + ''; + }; }; diff --git a/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh b/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh index 709b9051fc45..681ec0387c89 100644 --- a/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh +++ b/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh @@ -4,18 +4,18 @@ showUsage() { - echo "Usage: $0 -n network_expr -i infrastructure_expr" + echo "Usage: $0 network_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" + echo "--use-backdoor Indicates that the backdoor must be enabled so that the VMs can be accessed through a UNIX domain socket" + echo "--no-out-link Do not create a 'result' symlink" + 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 -- "$@"` +PARAMS=`getopt -n $0 -o h -l use-backdoor,no-out-link,show-trace,help -- "$@"` if [ $? != 0 ] then @@ -30,12 +30,12 @@ eval set -- "$PARAMS" while [ "$1" != "--" ] do case "$1" in - -n|--network) - networkExpr=`readlink -f $2` - ;; --use-backdoor) useBackdoorArg="--arg useBackdoor true" ;; + --no-out-link) + noOutLinkArg="--no-out-link" + ;; --show-trace) showTraceArg="--show-trace" ;; @@ -48,19 +48,23 @@ do shift done -# Validate the given options +shift -if [ "$networkExpr" = "" ] -then - echo "ERROR: A network expression must be specified!" >&2 - exit 1 -fi +# Validate the given options if [ -z "$NIXOS" ] then NIXOS=/etc/nixos/nixos fi +if [ "$@" = "" ] +then + echo "ERROR: A network expression must be specified!" >&2 + exit 1 +else + networkExpr=$(readlink -f $@) +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 +nix-build $NIXOS/modules/installer/tools/nixos-build-vms/build-vms.nix --argstr networkExpr $networkExpr --argstr nixos $NIXOS --argstr nixpkgs $NIXPKGS_ALL $useBackdoorArg $noOutLinkArg $showTraceArg diff --git a/modules/installer/tools/nixos-deploy-network/deploy.nix b/modules/installer/tools/nixos-deploy-network/deploy.nix index 10210fb0bea6..c060ce417562 100644 --- a/modules/installer/tools/nixos-deploy-network/deploy.nix +++ b/modules/installer/tools/nixos-deploy-network/deploy.nix @@ -1,8 +1,7 @@ { nixos ? /etc/nixos/nixos , nixpkgs ? /etc/nixos/nixpkgs , networkExpr -, infrastructureExpr -, targetProperty ? "hostname" +, targetProperty ? "targetHost" }: let @@ -12,19 +11,17 @@ let inherit (pkgs.lib) concatMapStrings; network = import networkExpr; - infrastructure = import infrastructureExpr; - generateRollbackSucceededPhase = network: infrastructure: configs: + generateRollbackSucceededPhase = network: configs: concatMapStrings (configurationName: let - infrastructureElement = getAttr configurationName infrastructure; config = getAttr configurationName configs; in '' if [ "$rollback" != "$succeeded" ] then - ssh $NIX_SSHOPTS ${getAttr targetProperty infrastructureElement} nix-env -p /nix/var/nix/profiles/system --rollback - ssh $NIX_SSHOPTS ${getAttr targetProperty infrastructureElement} /nix/var/nix/profiles/bin/switch-to-configuration switch + ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} nix-env -p /nix/var/nix/profiles/system --rollback + ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} /nix/var/nix/profiles/system/bin/switch-to-configuration switch rollback=$((rollback + 1)) fi @@ -32,33 +29,31 @@ let ) (attrNames network) ; - generateDistributionPhase = network: infrastructure: configs: + generateDistributionPhase = network: configs: concatMapStrings (configurationName: let - infrastructureElement = getAttr configurationName infrastructure; config = getAttr configurationName configs; in '' - echo "=== copy system closure to ${getAttr targetProperty infrastructureElement} ===" - nix-copy-closure --to ${getAttr targetProperty infrastructureElement} ${config.system.build.toplevel} + echo "=== copy system closure to ${getAttr targetProperty (config.deployment)} ===" + nix-copy-closure --to ${getAttr targetProperty (config.deployment)} ${config.system.build.toplevel} '' ) (attrNames network) ; - generateActivationPhase = network: infrastructure: configs: + generateActivationPhase = network: configs: concatMapStrings (configurationName: let - infrastructureElement = getAttr configurationName infrastructure; config = getAttr configurationName configs; in '' - echo "=== activating system configuration on ${getAttr targetProperty infrastructureElement} ===" - ssh $NIX_SSHOPTS ${getAttr targetProperty infrastructureElement} nix-env -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} || - (ssh $NIX_SSHOPTS ${getAttr targetProperty infrastructureElement} nix-env -p /nix/var/nix/profiles/system --rollback; rollbackSucceeded) + echo "=== activating system configuration on ${getAttr targetProperty (config.deployment)} ===" + ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} nix-env -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} || + (ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} nix-env -p /nix/var/nix/profiles/system --rollback; rollbackSucceeded) - ssh $NIX_SSHOPTS ${getAttr targetProperty infrastructureElement} /nix/var/nix/profiles/bin/switch-to-configuration switch || - ( ssh $NIX_SSHOPTS ${getAttr targetProperty infrastructureElement} nix-env -p /nix/var/nix/profiles/system --rollback - ssh $NIX_SSHOPTS ${getAttr targetProperty infrastructureElement} /nix/var/nix/profiles/bin/switch-to-configuration switch + ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} /nix/var/nix/profiles/system/bin/switch-to-configuration switch || + ( ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} nix-env -p /nix/var/nix/profiles/system --rollback + ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} /nix/var/nix/profiles/system/bin/switch-to-configuration switch rollbackSucceeded ) @@ -67,25 +62,36 @@ let ) (attrNames network) ; - evaluateMachines = network: infrastructure: + evaluateMachines = network: listToAttrs (map (configurationName: let configuration = getAttr configurationName network; - system = (getAttr configurationName infrastructure).system; in { name = configurationName; value = (import "${nixos}/lib/eval-config.nix" { - inherit nixpkgs system; - modules = [ configuration ]; - extraArgs = evaluateMachines network infrastructure; + inherit nixpkgs; + modules = + [ configuration + # Provide a default hostname and deployment target equal + # to the attribute name of the machine in the model. + { key = "set-default-hostname"; + networking.hostName = pkgs.lib.mkOverride 900 configurationName; + deployment.targetHost = pkgs.lib.mkOverride 900 configurationName; + } + ]; + extraArgs = evaluateMachines network; }).config; } - ) (attrNames (network))) - ; + ) (attrNames (network))); - configs = evaluateMachines network infrastructure; + configs = evaluateMachines network; in pkgs.stdenv.mkDerivation { name = "deploy-script"; + + # This script has a zillion dependencies and is trivial to build, so + # we don't want to build it remotely. + preferLocalBuild = true; + buildCommand = '' ensureDir $out/bin @@ -95,18 +101,18 @@ pkgs.stdenv.mkDerivation { rollbackSucceeded() { rollback=0 - ${generateRollbackSucceededPhase network infrastructure configs} + ${generateRollbackSucceededPhase network configs} } # Distribution phase - ${generateDistributionPhase network infrastructure configs} + ${generateDistributionPhase network configs} # Activation phase succeeded=0 - ${generateActivationPhase network infrastructure configs} + ${generateActivationPhase network configs} EOF chmod +x $out/bin/deploy-systems ''; 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 08370a15dc86..dc2b2198cfc7 100644 --- a/modules/installer/tools/nixos-deploy-network/nixos-deploy-network.sh +++ b/modules/installer/tools/nixos-deploy-network/nixos-deploy-network.sh @@ -4,18 +4,17 @@ showUsage() { - echo "Usage: $0 -n network_expr -i infrastructure_expr" + echo "Usage: $0 network_expr" echo "Options:" 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" + echo "--show-trace Shows an output trace" + echo "--no-out-link Do not create a 'result' symlink" + echo "-h,--help Shows the usage of this command" } # Parse valid argument options -PARAMS=`getopt -n $0 -o n:i:h -l network:,infrastructure:,show-trace,help -- "$@"` +PARAMS=`getopt -n $0 -o h -l show-trace,no-out-link,help -- "$@"` if [ $? != 0 ] then @@ -30,15 +29,12 @@ eval set -- "$PARAMS" while [ "$1" != "--" ] do case "$1" in - -n|--network) - networkExpr=`readlink -f $2` - ;; - -i|--infrastructure) - infrastructureExpr=`readlink -f $2` - ;; --show-trace) showTraceArg="--show-trace" ;; + --no-out-link) + noOutLinkArg="--no-out-link" + ;; -h|--help) showUsage exit 0 @@ -48,27 +44,24 @@ do shift done +shift + # Validate the given options -if [ "$infrastructureExpr" = "" ] -then - echo "ERROR: A infrastructure expression must be specified!" >&2 - exit 1 -fi - -if [ "$networkExpr" = "" ] -then - echo "ERROR: A network expression must be specified!" >&2 - exit 1 -fi - if [ -z "$NIXOS" ] then NIXOS=/etc/nixos/nixos fi +if [ "$@" = "" ] +then + echo "ERROR: A network Nix expression must be specified!" >&2 + exit 1 +else + networkExpr=$(readlink -f $@) +fi + # Deploy the network -nix-build $NIXOS/modules/installer/tools/nixos-deploy-network/deploy.nix --argstr networkExpr $networkExpr --argstr infrastructureExpr $infrastructureExpr $showTraceArg -./result/bin/deploy-systems -rm -f result +vms=`nix-build $NIXOS/modules/installer/tools/nixos-deploy-network/deploy.nix --argstr networkExpr $networkExpr $showTraceArg $noOutLinkArg` +$vms/bin/deploy-systems diff --git a/modules/installer/tools/nixos-hardware-scan.pl b/modules/installer/tools/nixos-hardware-scan.pl index 56549f99235d..b26358e10786 100644 --- a/modules/installer/tools/nixos-hardware-scan.pl +++ b/modules/installer/tools/nixos-hardware-scan.pl @@ -7,6 +7,7 @@ use File::Basename; my @attrs = (); my @kernelModules = (); my @initrdKernelModules = (); +my @modulePackages = (); sub debug { @@ -93,6 +94,19 @@ sub pciCheck { } } + # broadcom STA driver (wl.ko) + # list taken from http://www.broadcom.com/docs/linux_sta/README.txt + if ($vendor eq "0x14e4" && + ($device eq "0x4311" || $device eq "0x4312" || $device eq "0x4313" || + $device eq "0x4315" || $device eq "0x4327" || $device eq "0x4328" || + $device eq "0x4329" || $device eq "0x432a" || $device eq "0x432b" || + $device eq "0x432c" || $device eq "0x432d" || $device eq "0x4353" || + $device eq "0x4357") ) + { + push @modulePackages, "kernelPackages.broadcom_sta"; + push @kernelModules, "wl"; + } + # Can't rely on $module here, since the module may not be loaded # due to missing firmware. Ideally we would check modules.pcimap # here. @@ -222,6 +236,7 @@ sub multiLineList { my $initrdKernelModules = toNixExpr(removeDups @initrdKernelModules); my $kernelModules = toNixExpr(removeDups @kernelModules); +my $modulePackages = toNixExpr(removeDups @modulePackages); my $attrs = multiLineList(" ", removeDups @attrs); print < ''; # Unpack Mediawiki and put the config file in its root directory. mediawikiRoot = pkgs.stdenv.mkDerivation rec { - name= "mediawiki-1.15.4"; + name= "mediawiki-1.15.5"; src = pkgs.fetchurl { url = "http://download.wikimedia.org/mediawiki/1.15/${name}.tar.gz"; - sha256 = "1blf79lhnaxixc8z96f9z4xi2jlg906ps3kd4x8b9ipg2dgl3vy9"; + sha256 = "1d8afbdh3lsg54b69mnh6a47psb3lg978xpp277qs08yz15cjf7q"; }; buildPhase = "true"; @@ -96,6 +101,16 @@ in extraConfig = '' + ${optionalString config.enableUploads '' + Alias ${config.urlPrefix}/images ${config.uploadDir} + + + Order allow,deny + Allow from all + Options -Indexes + + ''} + Alias ${config.urlPrefix} ${mediawikiRoot} @@ -205,6 +220,17 @@ in ''; }; + enableUploads = mkOption { + default = false; + description = "Whether to enable file uploads."; + }; + + uploadDir = mkOption { + default = throw "You must specify `uploadDir'."; + example = "/data/mediawiki-upload"; + description = "The directory that stores uploaded files."; + }; + extraConfig = mkOption { default = ""; example = diff --git a/modules/system/upstart-events/shutdown.nix b/modules/system/upstart-events/shutdown.nix index 51b741d54e0a..85ad601914d8 100644 --- a/modules/system/upstart-events/shutdown.nix +++ b/modules/system/upstart-events/shutdown.nix @@ -29,9 +29,11 @@ with pkgs.lib; echo "<<< System shutdown >>>" fi echo "" + + ${config.powerManagement.powerDownCommands} export PATH=${pkgs.utillinux}/bin:${pkgs.utillinux}/sbin:$PATH - + # Do an initial sync just in case. sync diff --git a/modules/virtualisation/qemu-vm.nix b/modules/virtualisation/qemu-vm.nix index 50b07435bdac..4aef6848ac8a 100644 --- a/modules/virtualisation/qemu-vm.nix +++ b/modules/virtualisation/qemu-vm.nix @@ -185,7 +185,7 @@ let -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${if cfg.useBackdoor then ",guestfwd=tcp:10.0.2.6:23-chardev:shell" else ""}''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS} \ + -net user,vlan=0,guestfwd=tcp:10.0.2.4:445-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 \ diff --git a/modules/virtualisation/xen-dom0.nix b/modules/virtualisation/xen-dom0.nix index 18fbf7bc62b2..7b8c5f3dd90b 100644 --- a/modules/virtualisation/xen-dom0.nix +++ b/modules/virtualisation/xen-dom0.nix @@ -79,6 +79,14 @@ in # as it's loaded, so don't load it. boot.blacklistedKernelModules = [ "radeonfb" ]; + # Increase the number of loopback devices from the default (8), + # which is way too small because every VM virtual disk requires a + # loopback device. + boot.extraModprobeConfig = + '' + options loop max_loop=64 + ''; + virtualisation.xen.bootParams = [ "loglvl=all" "guest_loglvl=all" ] ++ optional (cfg.domain0MemorySize != 0) "dom0_mem=${toString cfg.domain0MemorySize}M"; diff --git a/tests/installer.nix b/tests/installer.nix index 4dcb08f70766..eead83053ed0 100644 --- a/tests/installer.nix +++ b/tests/installer.nix @@ -93,7 +93,7 @@ let '' createDisk("harddisk", 4 * 1024); - my $machine = Machine->new({ hda => "harddisk", cdrom => glob("${iso}/iso/*.iso"), qemuFlags => '${qemuNICFlags 1 1}' }); + my $machine = Machine->new({ hda => "harddisk", cdrom => glob("${iso}/iso/*.iso"), qemuFlags => '${qemuNICFlags 1 1 1}' }); $machine->start; ${optionalString testChannel '' diff --git a/tests/nfs.nix b/tests/nfs.nix index db91179aca2a..c8ead3d89309 100644 --- a/tests/nfs.nix +++ b/tests/nfs.nix @@ -4,7 +4,7 @@ let client = { config, pkgs, ... }: - { fileSystems = pkgs.lib.mkOverrideTemplate 50 {} + { fileSystems = pkgs.lib.mkOverride 50 [ { mountPoint = "/data"; device = "server:/data"; fsType = "nfs";