Merging from trunk

svn path=/nixos/branches/stdenv-updates/; revision=25176
This commit is contained in:
Lluís Batlle i Rossell 2010-12-17 14:59:04 +00:00
commit 3f7751b9c2
31 changed files with 911 additions and 166 deletions

View File

@ -0,0 +1,148 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><command>nixos-build-vms</command></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><command>nixos-build-vms</command></refname>
<refpurpose>build a network of virtual machines from a network of NixOS configurations</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-build-vms</command>
<arg><option>--use-backdoor</option></arg>
<arg><option>--show-trace</option></arg>
<arg><option>--no-out-link</option></arg>
<arg><option>--help</option></arg>
<arg choice="plain"><replaceable>network.nix</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>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 <filename>bin/run-vms</filename> shell script that is generated by
this command. By default, a <filename>result</filename> symlink is produced that
points to the generated virtual network.
</para>
<para>This command also provides the <option>--use-backdoor</option> option,
which spawns UNIX domain sockets in the current working directory by using the
<command>socat</command> command. This allows
users to remotely script a generated virtual machine.</para>
<para>A network Nix expression has the following structure:
<screen>
{
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
};
}
</screen>
Each attribute in the expression represents a machine in the network
(e.g. <varname>test1</varname> and <varname>test2</varname>)
referring to a function defining a NixOS configuration.
In each NixOS configuration, two attributes have a special meaning.
The <varname>deployment.targetHost</varname> specifies the address
(domain name or IP address)
of the system which is used by <command>ssh</command> to perform
remote deployment operations. The <varname>nixpkgs.system</varname>
attribute can be used to specify an architecture for the target machine,
such as <varname>i686-linux</varname> which builds a 32-bit NixOS
configuration. Omitting this property will build the configuration
for the same architecture as the host system.
</para>
</refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>--use-backdoor</option></term>
<listitem>
<para>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.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--show-trace</option></term>
<listitem>
<para>Shows a trace of the output.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--no-out-link</option></term>
<listitem>
<para>Do not create a 'result' symlink.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option>, <option>--help</option></term>
<listitem>
<para>Shows the usage of this command to the user.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Environment variables</title>
<variablelist>
<varlistentry>
<term><envar>NIXOS</envar></term>
<listitem>
<para>Path to the NixOS source tree. Defaults to
<filename>/etc/nixos/nixos</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><envar>NIXPKGS_ALL</envar></term>
<listitem>
<para>Path to the Nixpkgs source tree. Defaults to
<filename>/etc/nixos/nixpkgs</filename>.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
</refentry>

View File

@ -0,0 +1,135 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><command>nixos-deploy-network</command></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><command>nixos-deploy-network</command></refname>
<refpurpose>deploy a network of NixOS configurations into a network of machines</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-deploy-network</command>
<arg><option>--show-trace</option></arg>
<arg><option>--no-out-link</option></arg>
<arg><option>--help</option></arg>
<arg choice="plain"><replaceable>network.nix</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>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.</para>
<para>A network Nix expression has the following structure:
<screen>
{
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
};
}
</screen>
Each attribute in the expression represents a machine in the network
(e.g. <varname>test1</varname> and <varname>test2</varname>)
referring to a function defining a NixOS configuration.
In each NixOS configuration, two attributes have a special meaning.
The <varname>deployment.targetHost</varname> specifies the address
(domain name or IP address)
of the system which is used by <command>ssh</command> to perform
remote deployment operations. The <varname>nixpkgs.system</varname>
attribute can be used to specify an architecture for the target machine,
such as <varname>i686-linux</varname> which builds a 32-bit NixOS
configuration. Omitting this property will build the configuration
for the same architecture as the host system.
</para>
</refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>--show-trace</option></term>
<listitem>
<para>Shows a trace of the output.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--no-out-link</option></term>
<listitem>
<para>Do not create a 'result' symlink.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option>, <option>--help</option></term>
<listitem>
<para>Shows the usage of this command to the user.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Environment variables</title>
<variablelist>
<varlistentry>
<term><envar>NIXOS</envar></term>
<listitem>
<para>Path to the NixOS source tree. Defaults to
<filename>/etc/nixos/nixos</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><envar>NIXPKGS_ALL</envar></term>
<listitem>
<para>Path to the Nixpkgs source tree. Defaults to
<filename>/etc/nixos/nixpkgs</filename>.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
</refentry>

View File

@ -26,5 +26,6 @@
<xi:include href="man-configuration.xml" />
<xi:include href="man-nixos-rebuild.xml" />
<xi:include href="man-nixos-option.xml" />
<xi:include href="man-nixos-deploy-network.xml" />
<xi:include href="man-nixos-build-vms.xml" />
</reference>

View File

@ -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);
};
}
)

View File

@ -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.<vlan> as the multicast address to connect VMs on
# the same vlan, but allow it to be overriden using the
# $QEMU_MCAST_ADDR_<vlan> environment variable. The test driver

View File

@ -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

View File

@ -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 (<STDIN>) {
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

View File

@ -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;
}

View File

@ -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.
'';
};
};

View File

@ -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

View File

@ -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
'';

View File

@ -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

View File

@ -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 <<EOF ;
@ -235,8 +250,12 @@ print <<EOF ;
"\${modulesPath}/installer/scan/not-detected.nix"
];
boot.initrd.kernelModules = [ $initrdKernelModules ];
boot.kernelModules = [ $kernelModules ];
boot = rec {
initrd.kernelModules = [ $initrdKernelModules ];
kernelModules = [ $kernelModules ];
kernelPackages = pkgs.linuxPackages;
extraModulePackages = [ $modulePackages ];
};
nix.maxJobs = $cpus;

View File

@ -4,20 +4,12 @@ with pkgs.lib;
{
options = {
deployment = mkOption {
deployment.targetHost = mkOption {
default = config.networking.hostName;
description = ''
This option captures various custom attributes related to the configuration of the system, which
are not directly used for building a system configuration. Usually these attributes
are used by external tooling, such as the nixos-deploy-network tool or the Disnix Avahi
publisher.
This option specifies a hostname or IP address which can be used by nixos-deploy-network
to execute remote deployment operations.
'';
default = {};
example = {
description = "My production machine";
hostname = "my.test.org";
country = "NL";
};
};
};
}

View File

@ -58,6 +58,8 @@ in
foldingAtHome = 37;
sabnzbd = 38;
kdm = 39;
ghostOne = 40;
git = 41;
# When adding a uid, make sure it doesn't match an existing gid.
nixbld = 30000; # start of range of uids
@ -98,6 +100,8 @@ in
privoxy = 32;
disnix = 33;
osgi = 34;
ghostOne = 40;
git = 41;
# When adding a gid, make sure it doesn't match an existing uid.
users = 100;

View File

@ -52,6 +52,7 @@
./services/backup/sitecopy-backup.nix
./services/databases/mysql.nix
./services/databases/postgresql.nix
./services/games/ghost-one.nix
./services/hardware/acpid.nix
./services/hardware/bluetooth.nix
./services/hardware/hal.nix
@ -91,6 +92,7 @@
./services/networking/dhcpd.nix
./services/networking/ejabberd.nix
./services/networking/firewall.nix
./services/networking/git-daemon.nix
./services/networking/gnunet.nix
./services/networking/gvpe.nix
./services/networking/gw6c.nix
@ -107,6 +109,7 @@
./services/networking/ssh/sshd.nix
./services/networking/tftpd.nix
./services/networking/vsftpd.nix
./services/networking/wakeonlan.nix
./services/networking/wicd.nix
./services/networking/wpa_supplicant.nix
./services/networking/xinetd.nix

View File

@ -79,7 +79,7 @@ in zipModules ([]
# OpenSSH
++ rename obsolete "services.sshd.ports" "services.openssh.ports"
++ rename obsolete "services.sshd.enable" "services.openssh.enable"
++ rename alias "services.sshd.enable" "services.openssh.enable"
++ rename obsolete "services.sshd.allowSFTP" "services.openssh.allowSFTP"
++ rename obsolete "services.sshd.forwardX11" "services.openssh.forwardX11"
++ rename obsolete "services.sshd.gatewayPorts" "services.openssh.gatewayPorts"

View File

@ -66,7 +66,7 @@ in
services.cron.systemCronJobs = map sitecopyCron config.services.sitecopy.backups;
system.activationScripts.sitecopyBackup = stringAfter [ "stdio" "systemConfig" "users" ]
system.activationScripts.sitecopyBackup = stringAfter [ "stdio" "users" ]
''
mkdir -m 0700 -p ${stateDir}
chown root ${stateDir}

View File

@ -0,0 +1,105 @@
{pkgs, config, ...}:
with pkgs.lib;
let
cfg = config.services.ghostOne;
ghostUser = "ghostone";
stateDir = "/var/lib/ghost-one";
in
{
###### interface
options = {
services.ghostOne = {
enable = mkOption {
default = false;
description = "Enable Ghost-One Warcraft3 game hosting server.";
};
language = mkOption {
default = "English";
check = lang: elem lang [ "English" "Spanish" "Russian" "Serbian" "Turkish" ];
description = "The language of bot messages: English, Spanish, Russian, Serbian or Turkish.";
};
war3path = mkOption {
default = "";
description = ''
The path to your local Warcraft III directory, which must contain war3.exe, storm.dll, and game.dll.
'';
};
mappath = mkOption {
default = "";
description = ''
The path to the directory where you keep your map files. GHost One doesn't require
map files but if it has access to them it can send them to players and automatically
calculate most map config values. GHost One will search [bot_mappath + map_localpath]
for the map file (map_localpath is set in each map's config file).
'';
};
config = mkOption {
default = "";
description = "Extra configuration options.";
};
};
};
###### implementation
config = mkIf cfg.enable {
users.extraUsers = singleton
{ name = ghostUser;
uid = config.ids.uids.ghostOne;
description = "Ghost One game server user";
home = stateDir;
};
users.extraGroups = singleton
{ name = ghostUser;
gid = config.ids.gids.ghostOne;
};
services.ghostOne.config = ''
# bot_log = /dev/stderr
bot_language = ${pkgs.ghostOne}/share/ghost-one/languages/${cfg.language}.cfg
bot_war3path = ${cfg.war3path}
bot_mapcfgpath = mapcfgs
bot_savegamepath = savegames
bot_mappath = ${cfg.mappath}
bot_replaypath = replays
'';
jobs.ghostOne = {
name = "ghost-one";
script = ''
mkdir -p ${stateDir}
cd ${stateDir}
chown ${ghostUser}:${ghostUser} .
mkdir -p mapcfgs
chown ${ghostUser}:${ghostUser} mapcfgs
mkdir -p replays
chown ${ghostUser}:${ghostUser} replays
mkdir -p savegames
chown ${ghostUser}:${ghostUser} savegames
ln -sf ${pkgs.writeText "ghost.cfg" cfg.config} ghost.cfg
ln -sf ${pkgs.ghostOne}/share/ghost-one/ip-to-country.csv
${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${ghostUser} \
-c "LANG=C ${pkgs.ghostOne}/bin/ghost++"
'';
};
};
}

View File

@ -34,6 +34,23 @@ in
description = "Whether to enable the DisnixWebService interface running on Apache Tomcat";
};
publishInfrastructure = {
enable = mkOption {
default = false;
description = "Whether to publish capabilities/properties of this machine in as attributes in the infrastructure option";
};
enableAuthentication = mkOption {
default = false;
description = "Whether to publish authentication credentials through the infrastructure attribute (not recommended in combination with Avahi)";
};
};
infrastructure = mkOption {
default = {};
description = "List of name value pairs containing properties for the infrastructure model";
};
publishAvahi = mkOption {
default = false;
description = "Whether to publish capabilities/properties as a Disnix service through Avahi";
@ -47,62 +64,79 @@ in
###### implementation
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.disnix ] ++ optional cfg.useWebServiceInterface pkgs.DisnixWebService;
services.dbus.enable = true;
services.dbus.packages = [ pkgs.disnix ];
services.avahi.enable = cfg.publishAvahi;
services.tomcat.enable = cfg.useWebServiceInterface;
services.tomcat.extraGroups = [ "disnix" ];
services.tomcat.javaOpts = "${optionalString cfg.useWebServiceInterface "-Djava.library.path=${pkgs.libmatthew_java}/lib/jni"} ";
services.tomcat.sharedLibs = []
++ optional cfg.useWebServiceInterface "${pkgs.DisnixWebService}/share/java/DisnixConnection.jar"
services.tomcat.sharedLibs = optional cfg.useWebServiceInterface "${pkgs.DisnixWebService}/share/java/DisnixConnection.jar"
++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar";
services.tomcat.webapps = [] ++ optional cfg.useWebServiceInterface pkgs.DisnixWebService;
services.tomcat.webapps = optional cfg.useWebServiceInterface pkgs.DisnixWebService;
users.extraGroups = singleton
{ name = "disnix";
gid = config.ids.gids.disnix;
};
jobs.disnix =
{ description = "Disnix server";
services.disnix.infrastructure =
optionalAttrs (cfg.publishInfrastructure.enable)
( { hostname = config.networking.hostName;
targetHost = config.deployment.targetHost;
system = if config.nixpkgs.system == "" then builtins.currentSystem else config.nixpkgs.system;
}
// optionalAttrs (cfg.useWebServiceInterface) { targetEPR = "http://${config.deployment.targetHost}:8080/DisnixWebService/services/DisnixWebService"; }
// optionalAttrs (config.services.httpd.enable) { documentRoot = config.services.httpd.documentRoot; }
// optionalAttrs (config.services.mysql.enable) { mysqlPort = config.services.mysql.port; }
// optionalAttrs (config.services.tomcat.enable) { tomcatPort = 8080; }
// optionalAttrs (cfg.publishInfrastructure.enableAuthentication) (
optionalAttrs (config.services.mysql.enable) { mysqlUsername = "root"; mysqlPassword = builtins.readFile config.services.mysql.rootPassword; })
)
;
services.disnix.publishInfrastructure.enable = cfg.publishAvahi;
jobs = {
disnix =
{ description = "Disnix server";
startOn = "started dbus";
startOn = "started dbus";
script =
script =
''
export PATH=/var/run/current-system/sw/bin:/var/run/current-system/sw/sbin
export HOME=/root
${pkgs.disnix}/bin/disnix-service --activation-modules-dir=${disnix_activation_scripts}/libexec/disnix/activation-scripts
'';
};
} //
mkIf cfg.publishAvahi {
services.avahi.enable = true;
jobs.disnixAvahi =
{ description = "Disnix Avahi publisher";
};
} // optionalAttrs cfg.publishAvahi {
disnixAvahi =
{ description = "Disnix Avahi publisher";
startOn = "started avahi-daemon";
startOn = "started avahi-daemon";
exec =
''
${pkgs.avahi}/bin/avahi-publish-service disnix-$(${pkgs.nettools}/bin/hostname) _disnix._tcp 22 \
"hostname=\"$(${pkgs.nettools}/bin/hostname)\"" \
"system=\"$(uname -m)-linux\"" \
"mem=$(grep 'MemTotal:' /proc/meminfo | sed -e 's/kB//' -e 's/MemTotal://' -e 's/ //g')" \
${optionalString (cfg.useWebServiceInterface) ''"targetEPR=\"http://(${pkgs.nettools}/bin/hostname):8080/DisnixWebService/services/DisnixWebService\""''} \
${optionalString (config.services.httpd.enable) ''"documentRoot=\"${config.services.httpd.documentRoot}\""''} \
${optionalString (config.services.mysql.enable) ''"mysqlPort=3306"''} \
${optionalString (config.services.tomcat.enable) ''"tomcatPort=8080"''} \
"supportedTypes=[$(for i in ${disnix_activation_scripts}/libexec/disnix/activation-scripts/*; do echo -n " \"$(basename $i)\""; done) ]" \
${concatMapStrings (deploymentAttrName: let deploymentAttrValue = getAttr deploymentAttrName (config.deployment); in ''${deploymentAttrName}=\"${deploymentAttrValue}\" '' ) (attrNames (config.deployment))}
'';
};
exec =
''
${pkgs.avahi}/bin/avahi-publish-service disnix-${config.networking.hostName} _disnix._tcp 22 \
"mem=$(grep 'MemTotal:' /proc/meminfo | sed -e 's/kB//' -e 's/MemTotal://' -e 's/ //g')" \
"supportedTypes=[$(for i in ${disnix_activation_scripts}/libexec/disnix/activation-scripts/*; do echo -n " \"$(basename $i)\""; done) ]" \
${concatMapStrings (infrastructureAttrName:
let infrastructureAttrValue = getAttr infrastructureAttrName (cfg.infrastructure);
in
if builtins.isInt infrastructureAttrValue then
''${infrastructureAttrName}=${infrastructureAttrValue} \
''
else
''${infrastructureAttrName}=\"${infrastructureAttrValue}\" \
''
) (attrNames (cfg.infrastructure))}
'';
};
};
};
}

View File

@ -5,6 +5,8 @@ with pkgs.lib;
let
cfg = config.services.zabbixServer;
stateDir = "/var/run/zabbix";
logDir = "/var/log/zabbix";
@ -19,9 +21,15 @@ let
PidFile = ${pidFile}
DBHost = ${cfg.dbServer}
DBName = zabbix
DBUser = zabbix
${optionalString (cfg.dbPassword != "") ''
DBPassword = ${cfg.dbPassword}
''}
'';
in
@ -39,11 +47,21 @@ in
'';
};
services.zabbixServer.dbServer = mkOption {
default = "localhost";
description = "Hostname or IP address of the database server.";
};
services.zabbixServer.dbPassword = mkOption {
default = "";
description = "Password used to connect to the database server.";
};
};
###### implementation
config = mkIf config.services.zabbixServer.enable {
config = mkIf cfg.enable {
services.postgresql.enable = true;

View File

@ -80,10 +80,10 @@ in
# Only run dhclient on interfaces of type ARPHRD_ETHER
# (1), i.e. Ethernet. Ignore peth* devices; on Xen,
# they're renamed physical Ethernet cards used for
# bridging.
# bridging. Likewise for vif* and tap*.
if [ "$(cat /sys/class/net/$i/type)" = 1 ]; then
if ! for j in ${toString ignoredInterfaces}; do echo $j; done | grep -F -x -q "$i" &&
! echo "$i" | grep -x -q "peth.*";
! echo "$i" | grep -x -q "peth.*\|vif.*\|tap.*";
then
echo "Running dhclient on $i"
interfaces="$interfaces $i"

View File

@ -0,0 +1,112 @@
{pkgs, config, ...}:
with pkgs.lib;
let
cfg = config.services.gitDaemon;
gitUser = "git";
in
{
###### interface
options = {
services.gitDaemon = {
enable = mkOption {
default = false;
description = ''
Enable Git daemon, which allows public hosting of git repositories
without any access controls. This is mostly intended for read-only access.
You can allow write access by setting daemon.receivepack configuration
item of the repository to true. This is solely meant for a closed LAN setting
where everybody is friendly.
If you need any access controls, use something else.
'';
};
basePath = mkOption {
default = "";
example = "/srv/git/";
description = ''
Remap all the path requests as relative to the given path. For example,
if you set base-path to /srv/git, then if you later try to pull
git://example.com/hello.git, Git daemon will interpret the path as /srv/git/hello.git.
'';
};
exportAll = mkOption {
default = false;
description = ''
Publish all directories that look like Git repositories (have the objects
and refs subdirectories), even if they do not have the git-daemon-export-ok file.
If disabled, you need to touch .git/git-daemon-export-ok in each repository
you want the daemon to publish.
Warning: enabling this without a repository whitelist or basePath
publishes every git repository you have.
'';
};
repositories = mkOption {
default = [];
example = [ "/srv/git" "/home/user/git/repo2" ];
description = ''
A whitelist of paths of git repositories, or directories containing repositories
all of which would be published. Paths must not end in "/".
Warning: leaving this empty and enabling exportAll publishes all
repositories in your filesystem or basePath if specified.
'';
};
listenAddress = mkOption {
default = "";
example = "example.com";
description = "Listen on a specific IP address or hostname.";
};
port = mkOption {
default = 9418;
description = "Port to listen on.";
};
options = mkOption {
default = "";
description = "Extra configuration options to be passed to Git daemon.";
};
};
};
###### implementation
config = mkIf cfg.enable {
users.extraUsers = singleton
{ name = gitUser;
uid = config.ids.uids.git;
description = "Git daemon user";
};
users.extraGroups = singleton
{ name = gitUser;
gid = config.ids.gids.git;
};
jobs.gitDaemon = {
name = "git-daemon";
startOn = "ip-up";
exec = "${pkgs.git}/bin/git daemon --reuseaddr "
+ (optionalString (cfg.basePath != "") "--basepath=${cfg.basePath} ")
+ (optionalString (cfg.listenAddress != "") "--listen=${cfg.listenAddress} ")
+ "--port=${toString cfg.port} --user=${gitUser} --group=${gitUser} ${cfg.options} "
+ "--verbose " + (optionalString cfg.exportAll "--export-all") + concatStringsSep " " cfg.repositories;
};
};
}

View File

@ -0,0 +1,56 @@
{ config, pkgs, ... }:
with pkgs.lib;
let
interfaces = config.services.wakeonlan.interfaces;
ethtool = "${pkgs.ethtool}/sbin/ethtool";
passwordParameter = password : if (password == "") then "" else
"sopass ${password}";
methodParameter = {method, password} :
if method == "magicpacket" then "wol g"
else if method == "password" then "wol s so ${passwordParameter password}"
else throw "Wake-On-Lan method not supported";
line = { interface, method ? "magicpacket", password ? "" }: ''
${ethtool} -s ${interface} ${methodParameter {inherit method password;}}
'';
concatStrings = fold (x: y: x + y) "";
lines = concatStrings (map (l: line l) interfaces);
in
{
###### interface
options = {
services.wakeonlan.interfaces = mkOption {
default = [ ];
example = [
{
interface = "eth0";
method = "password";
password = "00:11:22:33:44:55";
}
];
description = ''
Interfaces where to enable Wake-On-LAN, and how. Two methods available:
"magickey" and "password". The password has the shape of six bytes
in hexadecimal separated by a colon each. For more information,
check the ethtool manual.
'';
};
};
###### implementation
config.powerManagement.powerDownCommands = lines;
}

View File

@ -16,16 +16,16 @@ let
name = "additional-cups-backends";
builder = pkgs.writeScript "additional-backends-builder.sh" ''
PATH=${pkgs.coreutils}/bin
mkdir -p $out
mkdir -pv $out
if [ ! -e ${pkgs.samba}/lib/cups/backend/smb ]; then
mkdir -p $out/lib/cups/backend
ln -s ${pkgs.samba}/bin/smbspool $out/lib/cups/backend/smb
mkdir -pv $out/lib/cups/backend
ln -sv ${pkgs.samba}/bin/smbspool $out/lib/cups/backend/smb
fi
# Provide support for printing via HTTPS.
if [ ! -e ${pkgs.cups}/lib/cups/backend/https ]; then
mkdir -p $out/lib/cups/backend
ln -s ${pkgs.cups}/lib/cups/backend/ipp $out/lib/cups/backend/https
mkdir -pv $out/lib/cups/backend
ln -sv ${pkgs.cups}/lib/cups/backend/ipp $out/lib/cups/backend/https
fi
'';
};
@ -147,7 +147,7 @@ in
exec = "${cups}/sbin/cupsd -c ${pkgs.writeText "cupsd.conf" cfg.cupsdConf} -F";
};
services.printing.drivers = [ pkgs.cups pkgs.ghostscript additionalBackends ];
services.printing.drivers = [ pkgs.cups pkgs.cups_pdf_filter pkgs.ghostscript additionalBackends ];
services.printing.cupsdConf =
''
LogLevel info

View File

@ -57,17 +57,22 @@ let
$wgArticlePath = "${config.articleUrlPrefix}/$1";
''}
${optionalString config.enableUploads ''
$wgEnableUploads = true;
$wgUploadDirectory = "${config.uploadDir}";
''}
${config.extraConfig}
?>
'';
# 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}
<Directory ${config.uploadDir}>
Order allow,deny
Allow from all
Options -Indexes
</Directory>
''}
Alias ${config.urlPrefix} ${mediawikiRoot}
<Directory ${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 =

View File

@ -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

View File

@ -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 \

View File

@ -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";

View File

@ -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 ''

View File

@ -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";