* Merged the Upstart 0.6 branch.

svn path=/nixos/trunk/; revision=18620
This commit is contained in:
Eelco Dolstra 2009-11-25 10:48:36 +00:00
commit 8c134a151c
85 changed files with 831 additions and 557 deletions

View File

@ -0,0 +1,75 @@
{ config, pkgs, ... }:
with pkgs.lib;
let
cfg = config.powerManagement;
sleepHook = pkgs.writeScript "sleep-hook.sh"
''
#! ${pkgs.stdenv.shell}
action="$1"
if [ "$action" = "resume" ]; then
${cfg.resumeCommands}
${cfg.powerUpCommands}
fi
'';
in
{
###### interface
options = {
powerManagement = {
enable = mkOption {
default = false;
description =
''
Whether to enable power management. This includes support
for suspend-to-RAM and powersave features on laptops.
'';
};
resumeCommands = mkOption {
default = "";
description = "Commands executed after the system resumes from suspend-to-RAM.";
};
powerUpCommands = mkOption {
default = "";
example = "${pkgs.hdparm}/sbin/hdparm -B 255 /dev/sda";
description =
''
Commands executed when the machine powers up. That is,
they're executed both when the system first boots and when
it resumes from suspend or hibernation.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
# Enable the ACPI daemon. Not sure whether this is essential.
services.acpid.enable = true;
environment.systemPackages = [ pkgs.pmutils ];
environment.etc = singleton
{ source = sleepHook;
target = "pm/sleep.d/00sleep-hook";
};
};
}

View File

@ -10,6 +10,7 @@ let
requiredPackages = requiredPackages =
[ config.system.sbin.modprobe # must take precedence over module_init_tools [ config.system.sbin.modprobe # must take precedence over module_init_tools
config.system.sbin.mount # must take precedence over util-linux config.system.sbin.mount # must take precedence over util-linux
config.system.build.upstart
config.environment.nix config.environment.nix
pkgs.acl pkgs.acl
pkgs.attr pkgs.attr
@ -53,7 +54,6 @@ let
pkgs.sysvtools pkgs.sysvtools
pkgs.time pkgs.time
pkgs.udev pkgs.udev
pkgs.upstart
pkgs.usbutils pkgs.usbutils
pkgs.utillinux pkgs.utillinux
]; ];

View File

@ -1,20 +1,22 @@
# This module contains the basic configuration for building a NixOS # This module contains the basic configuration for building a NixOS
# installation CD. # installation CD.
{config, pkgs, ...}: { config, pkgs, ... }:
with pkgs.lib;
let let
options = { options = {
system.nixosVersion = pkgs.lib.mkOption { system.nixosVersion = mkOption {
default = "${builtins.readFile ../../../VERSION}"; default = "${builtins.readFile ../../../VERSION}";
description = '' description = ''
NixOS version number. NixOS version number.
''; '';
}; };
installer.configModule = pkgs.lib.mkOption { installer.configModule = mkOption {
example = "./nixos/modules/installer/cd-dvd/installation-cd.nix"; example = "./nixos/modules/installer/cd-dvd/installation-cd.nix";
description = '' description = ''
Filename of the configuration module that builds the CD Filename of the configuration module that builds the CD
@ -38,10 +40,12 @@ let
''; '';
# Put the current directory in a tarball. # Put the current directory in a tarball.
nixosTarball = makeTarball "nixos.tar.bz2" (pkgs.lib.cleanSource ../../..); nixosTarball = makeTarball "nixos.tar.bz2" (cleanSource ../../..);
# Put Nixpkgs in a tarball. # Put Nixpkgs in a tarball.
nixpkgsTarball = makeTarball "nixpkgs.tar.bz2" (pkgs.lib.cleanSource pkgs.path); nixpkgsTarball = makeTarball "nixpkgs.tar.bz2" (cleanSource pkgs.path);
includeSources = true;
# A dummy /etc/nixos/configuration.nix in the booted CD that # A dummy /etc/nixos/configuration.nix in the booted CD that
@ -169,12 +173,14 @@ in
# Provide the NixOS/Nixpkgs sources in /etc/nixos. This is required # Provide the NixOS/Nixpkgs sources in /etc/nixos. This is required
# for nixos-install. # for nixos-install.
echo "unpacking the NixOS/Nixpkgs sources..." ${optionalString includeSources ''
mkdir -p /etc/nixos/nixos echo "unpacking the NixOS/Nixpkgs sources..."
tar xjf ${nixosTarball}/nixos.tar.bz2 -C /etc/nixos/nixos mkdir -p /etc/nixos/nixos
mkdir -p /etc/nixos/nixpkgs tar xjf ${nixosTarball}/nixos.tar.bz2 -C /etc/nixos/nixos
tar xjf ${nixpkgsTarball}/nixpkgs.tar.bz2 -C /etc/nixos/nixpkgs mkdir -p /etc/nixos/nixpkgs
chown -R root.root /etc/nixos tar xjf ${nixpkgsTarball}/nixpkgs.tar.bz2 -C /etc/nixos/nixpkgs
chown -R root.root /etc/nixos
''}
# Provide a configuration for the CD/DVD itself, to allow users # Provide a configuration for the CD/DVD itself, to allow users
# to run nixos-rebuild to change the configuration of the # to run nixos-rebuild to change the configuration of the

View File

@ -2,20 +2,22 @@
# configuration. The derivation for the ISO image will be placed in # configuration. The derivation for the ISO image will be placed in
# config.system.build.isoImage. # config.system.build.isoImage.
{config, pkgs, ...}: { config, pkgs, ... }:
with pkgs.lib;
let let
options = { options = {
isoImage.isoName = pkgs.lib.mkOption { isoImage.isoName = mkOption {
default = "cd.iso"; default = "cd.iso";
description = '' description = ''
Name of the generated ISO image file. Name of the generated ISO image file.
''; '';
}; };
isoImage.compressImage = pkgs.lib.mkOption { isoImage.compressImage = mkOption {
default = false; default = false;
description = '' description = ''
Whether the ISO image should be compressed using Whether the ISO image should be compressed using
@ -23,7 +25,7 @@ let
''; '';
}; };
isoImage.volumeID = pkgs.lib.mkOption { isoImage.volumeID = mkOption {
default = "NIXOS_BOOT_CD"; default = "NIXOS_BOOT_CD";
description = '' description = ''
Specifies the label or volume ID of the generated ISO image. Specifies the label or volume ID of the generated ISO image.
@ -32,7 +34,7 @@ let
''; '';
}; };
isoImage.contents = pkgs.lib.mkOption { isoImage.contents = mkOption {
example = example =
[ { source = pkgs.memtest86 + "/memtest.bin"; [ { source = pkgs.memtest86 + "/memtest.bin";
target = "boot/memtest.bin"; target = "boot/memtest.bin";
@ -44,7 +46,7 @@ let
''; '';
}; };
isoImage.storeContents = pkgs.lib.mkOption { isoImage.storeContents = mkOption {
example = [pkgs.stdenv]; example = [pkgs.stdenv];
description = '' description = ''
This option lists additional derivations to be included in the This option lists additional derivations to be included in the
@ -55,14 +57,38 @@ let
}; };
# The Grub image.
grubImage = pkgs.runCommand "grub_eltorito" {}
''
${pkgs.grub2}/bin/grub-mkimage -o tmp biosdisk iso9660 help linux linux16 sh chain gfxterm vbe png jpeg
cat ${pkgs.grub2}/lib/grub/*/cdboot.img tmp > $out
''; # */
# The configuration file for Grub. # The configuration file for Grub.
grubCfg = grubCfg =
'' ''
default 0 set default=0
timeout 10 set timeout=10
splashimage /boot/background.xpm.gz
${config.boot.extraGrubEntries} if loadfont /boot/grub/unicode.pf2; then
set gfxmode=640x480
insmod gfxterm
insmod vbe
terminal_output.gfxterm
insmod png
if background_image /boot/grub/splash.png; then
set color_normal=white/black
set color_highlight=black/white
else
set menu_color_normal=cyan/blue
set menu_color_highlight=white/blue
fi
fi
${config.boot.loader.grub.extraEntries}
''; '';
in in
@ -70,6 +96,17 @@ in
{ {
require = options; require = options;
boot.loader.grub.version = 2;
# Don't build the GRUB menu builder script, since we don't need it
# here and it causes a cyclic dependency.
boot.loader.grub.enable = false;
# !!! Hack - attributes expected by other modules.
system.build.menuBuilder = "true";
system.boot.loader.kernelFile = "vmlinuz";
environment.systemPackages = [ pkgs.grub2 ];
# In stage 1 of the boot, mount the CD/DVD as the root FS by label # In stage 1 of the boot, mount the CD/DVD as the root FS by label
# so that we don't need to know its device. # so that we don't need to know its device.
fileSystems = fileSystems =
@ -86,7 +123,7 @@ in
# We need squashfs in the initrd to mount the compressed Nix store, # We need squashfs in the initrd to mount the compressed Nix store,
# and aufs to make the root filesystem appear writable. # and aufs to make the root filesystem appear writable.
boot.extraModulePackages = (pkgs.lib.optional boot.extraModulePackages = (optional
(! config.boot.kernelPackages.kernel.features ? aufs) (! config.boot.kernelPackages.kernel.features ? aufs)
config.boot.kernelPackages.aufs); config.boot.kernelPackages.aufs);
boot.initrd.extraKernelModules = ["aufs" "squashfs"]; boot.initrd.extraKernelModules = ["aufs" "squashfs"];
@ -112,11 +149,11 @@ in
# Individual files to be included on the CD, outside of the Nix # Individual files to be included on the CD, outside of the Nix
# store on the CD. # store on the CD.
isoImage.contents = isoImage.contents =
[ { source = "${pkgs.grub}/lib/grub/${if pkgs.stdenv.system == "i686-linux" then "i386-pc" else "x86_64-unknown"}/stage2_eltorito"; [ { source = grubImage;
target = "/boot/grub/stage2_eltorito"; target = "/boot/grub/grub_eltorito";
} }
{ source = pkgs.writeText "menu.lst" grubCfg; { source = pkgs.writeText "grub.cfg" grubCfg;
target = "/boot/grub/menu.lst"; target = "/boot/grub/grub.cfg";
} }
{ source = config.boot.kernelPackages.kernel + "/vmlinuz"; { source = config.boot.kernelPackages.kernel + "/vmlinuz";
target = "/boot/vmlinuz"; target = "/boot/vmlinuz";
@ -124,8 +161,11 @@ in
{ source = config.system.build.initialRamdisk + "/initrd"; { source = config.system.build.initialRamdisk + "/initrd";
target = "/boot/initrd"; target = "/boot/initrd";
} }
{ source = config.boot.grubSplashImage; { source = "${pkgs.grub2}/share/grub/unicode.pf2";
target = "/boot/background.xpm.gz"; target = "/boot/grub/unicode.pf2";
}
{ source = config.boot.loader.grub.splashImage;
target = "/boot/grub/splash.png";
} }
{ source = config.system.build.squashfsStore; { source = config.system.build.squashfsStore;
target = "/nix-store.squashfs"; target = "/nix-store.squashfs";
@ -134,31 +174,20 @@ in
source = pkgs.runCommand "empty" {} "ensureDir $out"; source = pkgs.runCommand "empty" {} "ensureDir $out";
target = "/nix/store"; target = "/nix/store";
} }
{ # Another quick hack: the kernel needs a systemConfig
# parameter in menu.lst, but the system config depends on
# menu.lst. Break the cyclic dependency by having a /system
# symlink on the CD, and having menu.lst refer to /system.
source = pkgs.runCommand "system" {}
"ln -s ${config.system.build.toplevel} $out";
target = "/system";
}
{ # Idem for the stage-2 init script.
source = pkgs.runCommand "system" {}
"ln -s ${config.system.build.bootStage2} $out";
target = "/init";
}
]; ];
# The Grub menu. # The Grub menu.
boot.extraGrubEntries = boot.loader.grub.extraEntries =
'' ''
title Boot from hard disk menuentry "Boot from hard disk" {
root (hd0) set root=(hd0)
chainloader +1 chainloader +1
}
title NixOS Installer / Rescue menuentry "NixOS Installer / Rescue" {
kernel /boot/vmlinuz init=/init systemConfig=/system ${toString config.boot.kernelParams} linux /boot/vmlinuz init=${config.system.build.bootStage2} systemConfig=${config.system.build.toplevel} ${toString config.boot.kernelParams}
initrd /boot/initrd initrd /boot/initrd
}
''; '';
# Create the ISO image. # Create the ISO image.
@ -168,7 +197,7 @@ in
inherit (config.isoImage) isoName compressImage volumeID contents; inherit (config.isoImage) isoName compressImage volumeID contents;
bootable = true; bootable = true;
bootImage = "/boot/grub/stage2_eltorito"; bootImage = "/boot/grub/grub_eltorito";
}; };
boot.postBootCommands = boot.postBootCommands =

View File

@ -10,10 +10,11 @@ let
in in
{ {
boot.extraGrubEntries = boot.loader.grub.extraEntries =
'' ''
title Memtest86+ menuentry "Memtest86+" {
kernel ${memtestPath} linux16 ${memtestPath}
}
''; '';
isoImage.contents = isoImage.contents =

View File

@ -98,10 +98,7 @@ in
sha256 = "14kqdx2lfqvh40h6fjjzqgff1mwk74dmbjvmqphi6azzra7z8d59"; sha256 = "14kqdx2lfqvh40h6fjjzqgff1mwk74dmbjvmqphi6azzra7z8d59";
} }
# GRUB 1.97 doesn't support gzipped XPMs. # GRUB 1.97 doesn't support gzipped XPMs.
else pkgs.fetchurl { else ./winkler-gnu-blue-640x480.png;
url = http://www.gnu.org/graphics/winkler-gnu-blue.png;
sha256 = "0y8fvxalwxyid4k438k7c21bnv728qjsb92rqfapsmpv2bcj7f6k";
};
example = null; example = null;
description = '' description = ''
Background image used for GRUB. It must be a 640x480, Background image used for GRUB. It must be a 640x480,

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View File

@ -0,0 +1,6 @@
This is a resized version of
http://www.gnu.org/graphics/winkler-gnu-blue.png
by Kyle Winkler and released under the Free Art License
(http://artlibre.org/licence.php/lalgb.html).

View File

@ -5,6 +5,7 @@
./config/networking.nix ./config/networking.nix
./config/no-x-libs.nix ./config/no-x-libs.nix
./config/nsswitch.nix ./config/nsswitch.nix
./config/power-management.nix
./config/system-path.nix ./config/system-path.nix
./config/timezone.nix ./config/timezone.nix
./config/unix-odbc-drivers.nix ./config/unix-odbc-drivers.nix
@ -128,9 +129,9 @@
./system/boot/stage-1.nix ./system/boot/stage-1.nix
./system/boot/stage-2.nix ./system/boot/stage-2.nix
./system/etc/etc.nix ./system/etc/etc.nix
./system/upstart-events/ctrl-alt-delete.nix ./system/upstart-events/control-alt-delete.nix
./system/upstart-events/halt.nix ./system/upstart-events/runlevel.nix
./system/upstart-events/maintenance-shell.nix ./system/upstart-events/shutdown.nix
./system/upstart/upstart.nix ./system/upstart/upstart.nix
./tasks/filesystems.nix ./tasks/filesystems.nix
./tasks/kbd.nix ./tasks/kbd.nix

View File

@ -46,7 +46,7 @@ in
}; };
jobs.alsa = jobs.alsa =
{ startOn = "udev"; { startOn = "started udev";
preStart = preStart =
'' ''

View File

@ -66,7 +66,6 @@ in
{ description = "PulseAudio system-wide server"; { description = "PulseAudio system-wide server";
startOn = "startup"; startOn = "startup";
stopOn = "shutdown";
preStart = preStart =
'' ''

View File

@ -55,7 +55,15 @@ in
default = "/var/run/mysql"; default = "/var/run/mysql";
description = "Location of the file which stores the PID of the MySQL server"; description = "Location of the file which stores the PID of the MySQL server";
}; };
initialDatabases = mkOption {
default = [];
description = "List of database names and their initial schemas that should be used to create databases on the first startup of MySQL";
example = [
{ name = "foodatabase"; schema = ./foodatabase.sql; }
{ name = "bardatabase"; schema = ./bardatabase.sql; }
];
};
}; };
}; };
@ -75,8 +83,7 @@ in
jobs.mysql = jobs.mysql =
{ description = "MySQL server"; { description = "MySQL server";
startOn = "filesystems"; startOn = "started network-interfaces";
stopOn = "shutdown";
preStart = preStart =
'' ''
@ -90,14 +97,49 @@ in
chown -R ${cfg.user} ${cfg.pidDir} chown -R ${cfg.user} ${cfg.pidDir}
''; '';
exec = "${mysql}/bin/mysqld ${mysqldOptions}"; exec = "${mysql}/libexec/mysqld ${mysqldOptions}";
postStart =
''
# Wait until the MySQL server is available for use
count=0
while [ ! -e /tmp/mysql.sock ]
do
if [ $count -eq 30 ]
then
echo "Tried 30 times, giving up..."
exit 1
fi
postStop = echo "MySQL daemon not yet started. Waiting for 1 second..."
'' count=$((count++))
pid=$(cat ${pidFile}) sleep 1
kill "$pid" done
${mysql}/bin/mysql_waitpid "$pid" 1000
''; # Create initial databases
${concatMapStrings (database:
''
if ! test -e "${cfg.dataDir}/${database.name}"; then
echo "Creating initial database: ${database.name}"
( echo "create database ${database.name};"
echo "use ${database.name};"
if [ -f "${database.schema}" ]
then
cat ${database.schema}
elif [ -d "${database.schema}" ]
then
cat ${database.schema}/mysql-databases/*.sql
fi
) | ${mysql}/bin/mysql -u root -N
fi
'') cfg.initialDatabases}
'';
# !!! Need a postStart script to wait until mysqld is ready to
# accept connections.
extraConfig = "kill timeout 60";
}; };
}; };

View File

@ -116,20 +116,40 @@ in
jobs.postgresql = jobs.postgresql =
{ description = "PostgreSQL server"; { description = "PostgreSQL server";
startOn = "${startDependency}/started"; startOn = "started ${startDependency}";
stopOn = "shutdown";
environment =
{ TZ = config.time.timeZone;
PGDATA = cfg.dataDir;
};
preStart = preStart =
'' ''
# Initialise the database.
if ! test -e ${cfg.dataDir}; then if ! test -e ${cfg.dataDir}; then
mkdir -m 0700 -p ${cfg.dataDir} mkdir -m 0700 -p ${cfg.dataDir}
chown -R postgres ${cfg.dataDir} chown -R postgres ${cfg.dataDir}
${run} -c '${postgresql}/bin/initdb -D ${cfg.dataDir} -U root' ${run} -c '${postgresql}/bin/initdb -U root'
fi fi
cp -f ${pkgs.writeText "pg_hba.conf" cfg.authentication} ${cfg.dataDir}/pg_hba.conf cp -f ${pkgs.writeText "pg_hba.conf" cfg.authentication} ${cfg.dataDir}/pg_hba.conf
# We'd like to use the `-w' flag here to wait until the
# database is up, but it requires a `postgres' user to
# exist. And we can't call `createuser' before the
# database is running.
${run} -c '${postgresql}/bin/pg_ctl start -o "${toString flags}"'
# So wait until the server is running.
while ! ${run} -c '${postgresql}/bin/pg_ctl status'; do
sleep 1
done
''; '';
exec = "${run} -c '${postgresql}/bin/postgres -D ${cfg.dataDir} ${toString flags}'"; postStop =
''
${run} -c '${postgresql}/bin/pg_ctl stop -m fast'
'';
}; };
}; };

View File

@ -60,11 +60,11 @@ in
options = { options = {
powerManagement = { services.acpid = {
enable = mkOption { enable = mkOption {
default = false; default = false;
description = "Whether to enable power management (ACPI daemon)"; description = "Whether to enable the ACPI daemon.";
}; };
}; };
@ -74,13 +74,12 @@ in
###### implementation ###### implementation
config = mkIf config.powerManagement.enable { config = mkIf config.services.acpid.enable {
jobs.acpid = jobs.acpid =
{ description = "ACPI daemon"; { description = "ACPI daemon";
startOn = "udev"; startOn = "started udev";
stopOn = "shutdown";
exec = "${pkgs.acpid}/sbin/acpid --foreground --confdir ${acpiConfDir}"; exec = "${pkgs.acpid}/sbin/acpid --foreground --confdir ${acpiConfDir}";
}; };

View File

@ -48,10 +48,9 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
# !!! move pmutils somewhere else environment.systemPackages = [ hal ];
environment.systemPackages = [hal pkgs.pmutils];
services.hal.packages = [hal pkgs.hal_info]; services.hal.packages = [ hal pkgs.hal_info ];
users.extraUsers = singleton users.extraUsers = singleton
{ name = "haldaemon"; { name = "haldaemon";
@ -67,10 +66,7 @@ in
jobs.hal = jobs.hal =
{ description = "HAL daemon"; { description = "HAL daemon";
# !!! TODO: make sure that HAL starts after acpid, startOn = "started dbus" + optionalString config.services.acpid.enable " and started acpid";
# otherwise hald-addon-acpi will grab /proc/acpi/event.
startOn = if config.powerManagement.enable then "acpid" else "dbus";
stopOn = "shutdown";
environment = environment =
{ # !!! HACK? These environment variables manipulated inside { # !!! HACK? These environment variables manipulated inside
@ -99,23 +95,14 @@ in
mkdir -m 0755 -p /var/run/hald mkdir -m 0755 -p /var/run/hald
rm -f /var/cache/hald/fdi-cache rm -f /var/cache/hald/fdi-cache
# For some weird reason HAL sometimes fails to start at
# boot time, which seems to be timing-dependent. As a
# temporary workaround, sleep for a while here.
sleep 2
# !!! Hack: start the daemon here to make sure it's
# running when the Upstart job reaches the "running"
# state. Should be fixable in Upstart 0.6.
${hal}/sbin/hald --use-syslog # --verbose=yes
''; '';
postStop = daemonType = "fork";
''
pid=$(cat /var/run/hald/pid || true) # The `PATH=' works around a bug in HAL: it concatenates
test -n "$pid" && kill "$pid" # its libexec directory to $PATH, but using a 512-byte
''; # buffer. So if $PATH is too long it fails.
script = "PATH= exec ${hal}/sbin/hald --use-syslog";
}; };
services.udev.packages = [hal]; services.udev.packages = [hal];
@ -125,4 +112,4 @@ in
}; };
} }

View File

@ -159,7 +159,6 @@ in
jobs.udev = jobs.udev =
{ startOn = "startup"; { startOn = "startup";
stopOn = "shutdown";
environment = { UDEV_CONFIG_FILE = conf; }; environment = { UDEV_CONFIG_FILE = conf; };
@ -169,9 +168,6 @@ in
mkdir -p /var/lib/udev/rules.d mkdir -p /var/lib/udev/rules.d
# Get rid of possible old udev processes.
${procps}/bin/pkill -u root "^udevd$" || true
# Do the loading of additional stage 2 kernel modules. # Do the loading of additional stage 2 kernel modules.
# Maybe this isn't the best place... # Maybe this isn't the best place...
for i in ${toString config.boot.kernelModules}; do for i in ${toString config.boot.kernelModules}; do
@ -179,32 +175,24 @@ in
${modprobe}/sbin/modprobe $i || true ${modprobe}/sbin/modprobe $i || true
done done
# Start udev.
mkdir -p /dev/.udev # !!! bug in udev? mkdir -p /dev/.udev # !!! bug in udev?
${udev}/sbin/udevd --daemon '';
daemonType = "fork";
exec = "${udev}/sbin/udevd --daemon";
postStart =
''
# Let udev create device nodes for all modules that have already # Let udev create device nodes for all modules that have already
# been loaded into the kernel (or for which support is built into # been loaded into the kernel (or for which support is built into
# the kernel). # the kernel).
${udev}/sbin/udevadm trigger ${udev}/sbin/udevadm trigger
${udev}/sbin/udevadm settle # wait for udev to finish ${udev}/sbin/udevadm settle # wait for udev to finish
# Kill udev, let Upstart restart and monitor it. (This is nasty, initctl emit -n new-devices
# but we have to run `udevadm trigger' first. Maybe we can use
# Upstart's `binary' keyword, but it isn't implemented yet.)
if ! ${procps}/bin/pkill -u root "^udevd$"; then
echo "couldn't stop udevd"
fi
while ${procps}/bin/pgrep -u root "^udevd$"; do
sleep 1
done
initctl emit new-devices
''; '';
exec = "${udev}/sbin/udevd";
}; };
}; };

View File

@ -2,28 +2,16 @@
###### implementation ###### implementation
let
klogdCmd = "${pkgs.sysklogd}/sbin/klogd -c 1 -2 -k $(dirname $(readlink -f /var/run/booted-system/kernel))/System.map";
in
{ {
jobs.klogd = jobs.klogd =
{ description = "Kernel log daemon"; { description = "Kernel log daemon";
startOn = "syslogd"; startOn = "started syslogd";
stopOn = "shutdown";
preStart = exec =
'' "${pkgs.sysklogd}/sbin/klogd -c 1 -2 -n " +
# !!! this hangs for some reason (it blocks reading from "-k $(dirname $(readlink -f /var/run/booted-system/kernel))/System.map";
# /proc/kmsg).
#${klogdCmd} -o
'';
exec = "${klogdCmd} -n";
}; };
} }

View File

@ -50,12 +50,13 @@ in
jobs.syslogd = jobs.syslogd =
{ description = "Syslog daemon"; { description = "Syslog daemon";
startOn = "udev"; startOn = "started udev";
stopOn = "shutdown";
environment = { TZ = config.time.timeZone; }; environment = { TZ = config.time.timeZone; };
exec = "${pkgs.sysklogd}/sbin/syslogd -n -f ${syslogConf}"; daemonType = "fork";
exec = "${pkgs.sysklogd}/sbin/syslogd -f ${syslogConf}";
}; };
}; };

View File

@ -116,7 +116,7 @@ in
jobs.dovecot = jobs.dovecot =
{ description = "Dovecot IMAP/POP3 server"; { description = "Dovecot IMAP/POP3 server";
startOn = "${startingDependency}/started"; startOn = "started ${startingDependency}";
preStart = preStart =
'' ''

View File

@ -283,7 +283,7 @@ in
# accurate way is unlikely to be better. # accurate way is unlikely to be better.
{ description = "Postfix mail server"; { description = "Postfix mail server";
startOn = "${startingDependency}/started"; startOn = "started ${startingDependency}";
script = script =
'' ''

View File

@ -75,8 +75,8 @@ in
jobs.autofs = jobs.autofs =
{ description = "Filesystem automounter"; { description = "Filesystem automounter";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
environment = environment =
{ PATH = "${pkgs.nfsUtils}/sbin:${config.system.sbin.modprobe}/sbin"; { PATH = "${pkgs.nfsUtils}/sbin:${config.system.sbin.modprobe}/sbin";

View File

@ -39,8 +39,7 @@ in
jobs.disnix = jobs.disnix =
{ description = "Disnix server"; { description = "Disnix server";
startOn = "dbus"; startOn = "started dbus";
stopOn = "shutdown";
script = script =
'' ''

View File

@ -88,8 +88,8 @@ in
jobs.gpsd = jobs.gpsd =
{ description = "GPSD daemon"; { description = "GPSD daemon";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
exec = exec =
'' ''

View File

@ -78,8 +78,7 @@ in
description = "NixOS manual"; description = "NixOS manual";
startOn = "udev"; startOn = "started udev";
stopOn = "shutdown";
exec = exec =
'' ''

View File

@ -43,8 +43,7 @@ in
jobs.rogue = jobs.rogue =
{ description = "Rogue dungeon crawling game"; { description = "Rogue dungeon crawling game";
startOn = "udev"; startOn = "started udev";
stopOn = "shutdown";
extraConfig = "chdir /root"; extraConfig = "chdir /root";

View File

@ -76,8 +76,8 @@ in
description = "Synergy client"; description = "Synergy client";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stopped"; stopOn = "stopping network-interfaces";
exec = "${pkgs.synergy}/bin/synergyc ${if cfgS.screenName == "" then "" else "-n ${cfgS.screenName}" }"; exec = "${pkgs.synergy}/bin/synergyc ${if cfgS.screenName == "" then "" else "-n ${cfgS.screenName}" }";
}; };
@ -89,8 +89,8 @@ in
description = "Synergy server"; description = "Synergy server";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stopped"; stopOn = "stopping network-interfaces";
exec = exec =
'' ''

View File

@ -166,8 +166,8 @@ in
description = "Nagios monitoring daemon"; description = "Nagios monitoring daemon";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''

View File

@ -69,8 +69,8 @@ in
description = "Zabbix agent daemon"; description = "Zabbix agent daemon";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''

View File

@ -56,8 +56,8 @@ in
description = "Zabbix server daemon"; description = "Zabbix server daemon";
startOn = "postgresql"; startOn = "started postgresql";
stopOn = "shutdown"; stopOn = "stopping postgresql";
preStart = preStart =
'' ''

View File

@ -81,8 +81,8 @@ in
description = "Kernel NFS server"; description = "Kernel NFS server";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''
@ -111,8 +111,8 @@ in
description = "Kernel NFS server"; description = "Kernel NFS server";
startOn = "nfs-kernel-exports/started"; startOn = "started nfs-kernel-exports";
stopOn = "nfs-kernel-exports/stop"; stopOn = "stopping nfs-kernel-exports";
exec = "${pkgs.nfsUtils}/sbin/rpc.nfsd ${if cfg.hostName != null then "-H ${cfg.hostName}" else ""} ${builtins.toString cfg.nproc}"; exec = "${pkgs.nfsUtils}/sbin/rpc.nfsd ${if cfg.hostName != null then "-H ${cfg.hostName}" else ""} ${builtins.toString cfg.nproc}";
}; };
@ -122,8 +122,8 @@ in
description = "Kernel NFS server - mount daemon"; description = "Kernel NFS server - mount daemon";
startOn = "nfs-kernel-nfsd/started"; startOn = "started nfs-kernel-nfsd";
stopOn = "nfs-kernel-exports/stop"; stopOn = "stopping nfs-kernel-exports";
exec = "${pkgs.nfsUtils}/sbin/rpc.mountd -F -f ${exports}"; exec = "${pkgs.nfsUtils}/sbin/rpc.mountd -F -f ${exports}";
}; };
@ -133,8 +133,8 @@ in
description = "Kernel NFS server - Network Status Monitor"; description = "Kernel NFS server - Network Status Monitor";
startOn = "nfs-kernel-nfsd/started"; startOn = "started nfs-kernel-nfsd";
stopOn = "nfs-kernel-exports/stop"; stopOn = "stopping nfs-kernel-exports";
preStart = preStart =
'' ''

View File

@ -56,8 +56,8 @@ let
{ name = "samba-${appName}"; { name = "samba-${appName}";
description = "Samba Service daemon ${appName}"; description = "Samba Service daemon ${appName}";
startOn = "samba/started"; startOn = "started samba";
stopOn = "samba-control/stop"; stopOn = "stopping samba-control";
exec = "${samba}/sbin/${appName} ${args}"; exec = "${samba}/sbin/${appName} ${args}";
}; };
@ -168,8 +168,8 @@ in
{ name = "samba"; { name = "samba";
description = "Samba server"; description = "Samba server";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = setupScript; preStart = setupScript;
}; };

View File

@ -118,8 +118,8 @@ in
jobs.avahi_daemon = jobs.avahi_daemon =
{ name = "avahi-daemon"; { name = "avahi-daemon";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
script = script =
'' ''

View File

@ -67,8 +67,8 @@ in
jobs.bitlbee = jobs.bitlbee =
{ description = "BitlBee IRC to other chat networks gateway"; { description = "BitlBee IRC to other chat networks gateway";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''

View File

@ -114,7 +114,6 @@ in
{ name = "ddclient"; { name = "ddclient";
startOn = "startup"; startOn = "startup";
stopOn = "shutdown";
preStart = preStart =
'' ''

View File

@ -26,13 +26,13 @@ let
# hostnames in its config file, then it will never do # hostnames in its config file, then it will never do
# anything ever again ("couldn't resolve ..., giving up on # anything ever again ("couldn't resolve ..., giving up on
# it"), so we silently lose time synchronisation. # it"), so we silently lose time synchronisation.
${pkgs.upstart}/sbin/initctl stop ntpd ${config.system.build.upstart}/sbin/initctl stop ntpd
${pkgs.upstart}/sbin/initctl emit ip-up ${config.system.build.upstart}/sbin/initctl emit -n ip-up
fi fi
if test "$reason" = EXPIRE -o "$reason" = RELEASE; then if test "$reason" = EXPIRE -o "$reason" = RELEASE; then
${pkgs.upstart}/sbin/initctl emit ip-down ${config.system.build.upstart}/sbin/initctl emit -n ip-down
fi fi
''; '';
@ -62,8 +62,8 @@ in
config = mkIf config.networking.useDHCP { config = mkIf config.networking.useDHCP {
jobs.dhclient = jobs.dhclient =
{ startOn = "network-interfaces/started"; { startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''
@ -103,6 +103,22 @@ in
} }
]; ];
powerManagement.resumeCommands =
''
export PATH=${config.system.build.upstart}/sbin:$PATH
restart() {
local job="$1"
if initctl status "$job" 2> /dev/null | grep -q 'running'; then
initctl stop "$job"
initctl start "$job"
fi
}
restart wpa_supplicant
restart dhclient
'';
}; };
} }

View File

@ -111,8 +111,8 @@ in
jobs.dhcpd = jobs.dhcpd =
{ description = "DHCP server"; { description = "DHCP server";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
script = script =
'' ''

View File

@ -41,6 +41,11 @@ in
description = "Virtualhosts that ejabberd should host. Hostnames are surrounded with doublequotes and separated by commas"; description = "Virtualhosts that ejabberd should host. Hostnames are surrounded with doublequotes and separated by commas";
}; };
loadDumps = mkOption {
default = [];
description = "Configuration dump that should be loaded on the first startup";
example = [ ./myejabberd.dump ];
};
}; };
}; };
@ -54,8 +59,12 @@ in
jobs.ejabberd = jobs.ejabberd =
{ description = "EJabberd server"; { description = "EJabberd server";
startOn = "network-interface/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
environment = {
PATH = "$PATH:${pkgs.ejabberd}/sbin:${pkgs.ejabberd}/bin:${pkgs.coreutils}/bin:${pkgs.bash}/bin:${pkgs.gnused}/bin";
};
preStart = preStart =
'' ''
@ -64,6 +73,7 @@ in
if ! test -d ${cfg.spoolDir} if ! test -d ${cfg.spoolDir}
then then
initialize=1
cp -av ${pkgs.ejabberd}/var/lib/ejabberd /var/lib cp -av ${pkgs.ejabberd}/var/lib/ejabberd /var/lib
fi fi
@ -73,13 +83,50 @@ in
cp ${pkgs.ejabberd}/etc/ejabberd/* ${cfg.confDir} cp ${pkgs.ejabberd}/etc/ejabberd/* ${cfg.confDir}
sed -e 's|{hosts, \["localhost"\]}.|{hosts, \[${cfg.virtualHosts}\]}.|' ${pkgs.ejabberd}/etc/ejabberd/ejabberd.cfg > ${cfg.confDir}/ejabberd.cfg sed -e 's|{hosts, \["localhost"\]}.|{hosts, \[${cfg.virtualHosts}\]}.|' ${pkgs.ejabberd}/etc/ejabberd/ejabberd.cfg > ${cfg.confDir}/ejabberd.cfg
fi fi
'';
ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} start
${if cfg.loadDumps == [] then "" else
''
if [ "$initialize" = "1" ]
then
# Wait until the ejabberd server is available for use
count=0
while ! ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} status
do
if [ $count -eq 30 ]
then
echo "Tried 30 times, giving up..."
exit 1
fi
exec = "${pkgs.bash}/bin/sh -c 'export PATH=$PATH:${pkgs.ejabberd}/sbin:${pkgs.coreutils}/bin:${pkgs.bash}/bin; ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} start; sleep 1d'"; echo "Ejabberd daemon not yet started. Waiting for 1 second..."
count=$((count++))
sleep 1
done
${concatMapStrings (dump:
''
echo "Importing dump: ${dump}"
if [ -f ${dump} ]
then
ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} load ${dump}
elif [ -d ${dump} ]
then
for i in ${dump}/ejabberd-dump/*
do
ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} load $i
done
fi
'') cfg.loadDumps}
fi
''}
'';
postStop = postStop =
'' ''
${pkgs.ejabberd}/sbin/ejabberdctl stop ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} stop
''; '';
}; };

View File

@ -79,7 +79,7 @@ in
environment.systemPackages = [pkgs.iptables]; environment.systemPackages = [pkgs.iptables];
jobs.firewall = jobs.firewall =
{ startOn = "network-interfaces/started"; { startOn = "started network-interfaces";
preStart = preStart =
'' ''

View File

@ -194,8 +194,8 @@ in
jobs.gnunetd = jobs.gnunetd =
{ description = "The GNUnet Daemon"; { description = "The GNUnet Daemon";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''

View File

@ -56,13 +56,13 @@ in
''; '';
}; };
startOn = mkOption { startOn = mkOption {
default = "network-interfaces/started"; default = "started network-interfaces";
description = '' description = ''
Condition to start GVPE Condition to start GVPE
''; '';
}; };
stopOn = mkOption { stopOn = mkOption {
default = "network-interfaces/stop"; default = "stopping network-interfaces";
description = '' description = ''
Condition to stop GVPE Condition to stop GVPE
''; '';

View File

@ -6,10 +6,12 @@ let
cfg = config.services.gw6c; cfg = config.services.gw6c;
# !!! Move this from the services tree to the nixos tree.
gw6cService = import (servicesPath + /gw6c) { gw6cService = import (servicesPath + /gw6c) {
inherit (pkgs) stdenv gw6c coreutils inherit (pkgs) stdenv gw6c coreutils
procps upstart iputils gnused procps iputils gnused
gnugrep seccure writeScript; gnugrep seccure writeScript;
upstart = config.system.build.upstart;
username = cfg.username; username = cfg.username;
password = cfg.password; password = cfg.password;
server = cfg.server; server = cfg.server;
@ -132,8 +134,8 @@ in
jobs.gw6c = jobs.gw6c =
{ description = "Gateway6 client"; { description = "Gateway6 client";
startOn = if cfg.autorun then "network-interfaces/started" else ""; startOn = if cfg.autorun then "started network-interfaces" else "";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
exec = "${gw6cService}/bin/control start"; exec = "${gw6cService}/bin/control start";
}; };

View File

@ -16,7 +16,6 @@ let
#! ${pkgs.stdenv.shell} #! ${pkgs.stdenv.shell}
if test "$2" = up; then if test "$2" = up; then
initctl stop dhclient initctl stop dhclient
sleep 1
initctl start dhclient initctl start dhclient
fi fi
''; '';
@ -58,8 +57,8 @@ in
jobs.ifplugd = jobs.ifplugd =
{ description = "Network interface connectivity monitor"; { description = "Network interface connectivity monitor";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
exec = exec =
'' ''

View File

@ -122,8 +122,8 @@ in
description = "IRCD Hybrid server"; description = "IRCD Hybrid server";
startOn = "${startingDependency}/started"; startOn = "started ${startingDependency}";
stopOn = "${startingDependency}/stop"; stopOn = "stopping ${startingDependency}";
exec = "${ircdService}/bin/control start"; exec = "${ircdService}/bin/control start";
}; };

View File

@ -82,7 +82,7 @@ in
chown ${ntpUser} ${stateDir} chown ${ntpUser} ${stateDir}
# Needed to run ntpd as an unprivileged user. # Needed to run ntpd as an unprivileged user.
${modprobe}/sbin/modprobe capability || true ${modprobe}/sbin/modprobe --quiet capability || true
# !!! This can hang indefinitely if the network is down or # !!! This can hang indefinitely if the network is down or
# the servers are unreachable. This is particularly bad # the servers are unreachable. This is particularly bad

View File

@ -52,8 +52,7 @@ in
jobs.openfire = jobs.openfire =
{ description = "OpenFire XMPP server"; { description = "OpenFire XMPP server";
startOn = "${startDependency}/started"; startOn = "started ${startDependency}";
stopOn = "shutdown";
script = script =
'' ''

View File

@ -66,8 +66,8 @@ in
jobs.portmap = jobs.portmap =
{ description = "ONC RPC portmap"; { description = "ONC RPC portmap";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
exec = exec =
'' ''

View File

@ -81,7 +81,6 @@ in
{ name = "privoxy"; { name = "privoxy";
startOn = "startup"; startOn = "startup";
stopOn = "shutdown";
preStart = preStart =
'' ''

View File

@ -119,8 +119,8 @@ in
jobs.lshd = jobs.lshd =
{ description = "GNU lshd SSH2 daemon"; { description = "GNU lshd SSH2 daemon";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
environment = environment =
{ LD_LIBRARY_PATH = config.system.nssModules.path; }; { LD_LIBRARY_PATH = config.system.nssModules.path; };

View File

@ -112,8 +112,7 @@ in
description = "OpenSSH server"; description = "OpenSSH server";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop";
environment = { LD_LIBRARY_PATH = nssModulesPath; }; environment = { LD_LIBRARY_PATH = nssModulesPath; };
@ -126,7 +125,9 @@ in
fi fi
''; '';
exec = "${openssh}/sbin/sshd -D -h /etc/ssh/ssh_host_dsa_key -f ${sshdConfig}"; daemonType = "fork";
exec = "${openssh}/sbin/sshd -h /etc/ssh/ssh_host_dsa_key -f ${sshdConfig}";
}; };
networking.firewall.allowedTCPPorts = [22]; networking.firewall.allowedTCPPorts = [22];

View File

@ -102,8 +102,8 @@ in
jobs.vsftpd = jobs.vsftpd =
{ description = "vsftpd server"; { description = "vsftpd server";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''

View File

@ -38,8 +38,8 @@ in
environment.systemPackages = [pkgs.wpa_supplicant]; environment.systemPackages = [pkgs.wpa_supplicant];
jobs.wpa_supplicant = jobs.wpa_supplicant =
{ startOn = "network-interfaces/started"; { startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''

View File

@ -122,8 +122,8 @@ in
jobs.xinetd = jobs.xinetd =
{ description = "xinetd server"; { description = "xinetd server";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
exec = "${xinetd}/sbin/xinetd -syslog daemon -dontfork -stayalive -f ${configFile}"; exec = "${xinetd}/sbin/xinetd -syslog daemon -dontfork -stayalive -f ${configFile}";
}; };

View File

@ -160,8 +160,8 @@ in
jobs.cupsd = jobs.cupsd =
{ description = "CUPS printing daemon"; { description = "CUPS printing daemon";
startOn = "network-interfaces/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''

View File

@ -67,7 +67,6 @@ in
{ description = "at daemon (atd)"; { description = "at daemon (atd)";
startOn = "startup"; startOn = "startup";
stopOn = "shutdown";
preStart = preStart =
'' ''
@ -97,12 +96,12 @@ in
chown atd:atd "$jobdir"/.SEQ && \ chown atd:atd "$jobdir"/.SEQ && \
chmod 600 "$jobdir"/.SEQ chmod 600 "$jobdir"/.SEQ
fi fi
# `atd' doesn't have a no-fork flag, so start it here. !!!
# Fix this once we have Upstart 0.6.
${at}/sbin/atd
''; '';
daemonType = "fork";
exec = "${at}/sbin/atd";
postStop = postStop =
'' ''
test -e /var/run/atd.pid && kill $(cat /var/run/atd.pid) test -e /var/run/atd.pid && kill $(cat /var/run/atd.pid)

View File

@ -70,7 +70,6 @@ in
{ description = "Cron daemon"; { description = "Cron daemon";
startOn = "startup"; startOn = "startup";
stopOn = "shutdown";
# Needed to interpret times in the local timezone. # Needed to interpret times in the local timezone.
environment = { TZ = config.time.timeZone; }; environment = { TZ = config.time.timeZone; };

View File

@ -101,7 +101,6 @@ in
{ description = "fcron daemon"; { description = "fcron daemon";
startOn = "startup"; startOn = "startup";
stopOn = "shutdown";
environment = environment =
{ PATH = "/var/run/current-system/sw/bin"; { PATH = "/var/run/current-system/sw/bin";

View File

@ -113,8 +113,7 @@ in
}; };
jobs.dbus = jobs.dbus =
{ startOn = "udev"; { startOn = "started udev";
stopOn = "shutdown";
preStart = preStart =
'' ''
@ -125,24 +124,19 @@ in
${dbus.tools}/bin/dbus-uuidgen --ensure ${dbus.tools}/bin/dbus-uuidgen --ensure
rm -f ${homeDir}/pid rm -f ${homeDir}/pid
# !!! hack - dbus should be running once this job is
# considered "running"; should be fixable once we have
# Upstart 0.6.
${dbus}/bin/dbus-daemon --config-file=${configDir}/system.conf
''; '';
daemonType = "fork";
exec = "${dbus}/bin/dbus-daemon --config-file=${configDir}/system.conf";
postStop = postStop =
'' ''
pid=$(cat ${homeDir}/pid)
if test -n "$pid"; then
kill $pid
fi
# !!! Hack: doesn't belong here. # !!! Hack: doesn't belong here.
pid=$(cat /var/run/ConsoleKit/pid) pid=$(cat /var/run/ConsoleKit/pid || true)
if test -n "$pid"; then if test -n "$pid"; then
kill $pid kill $pid || true
rm /var/run/ConsoleKit/pid rm -f /var/run/ConsoleKit/pid
fi fi
''; '';
}; };

View File

@ -21,7 +21,6 @@ in
{ description = "Name Service Cache Daemon"; { description = "Name Service Cache Daemon";
startOn = "startup"; startOn = "startup";
stopOn = "shutdown";
environment = { LD_LIBRARY_PATH = nssModulesPath; }; environment = { LD_LIBRARY_PATH = nssModulesPath; };

View File

@ -53,7 +53,6 @@ in
{ description = "Uptimed daemon"; { description = "Uptimed daemon";
startOn = "startup"; startOn = "startup";
stopOn = "shutdown";
preStart = preStart =
'' ''

View File

@ -41,8 +41,7 @@ in
jobs.gpm = jobs.gpm =
{ description = "General purpose mouse"; { description = "General purpose mouse";
startOn = "udev"; startOn = "started udev";
stopOn = "shutdown";
exec = "${pkgs.gpm}/sbin/gpm -m /dev/input/mice -t ${cfg.protocol} -D &>/dev/null"; exec = "${pkgs.gpm}/sbin/gpm -m /dev/input/mice -t ${cfg.protocol} -D &>/dev/null";
}; };

View File

@ -55,7 +55,7 @@ with pkgs.lib;
# Generate a separate job for each tty. # Generate a separate job for each tty.
jobs = listToAttrs (map (tty: nameValuePair tty { jobs = listToAttrs (map (tty: nameValuePair tty {
startOn = "udev"; startOn = "started udev";
exec = "${pkgs.mingetty}/sbin/mingetty --loginprog=${pkgs.pam_login}/bin/login --noclear ${tty}"; exec = "${pkgs.mingetty}/sbin/mingetty --loginprog=${pkgs.pam_login}/bin/login --noclear ${tty}";

View File

@ -582,8 +582,7 @@ in
description = "Apache HTTPD"; description = "Apache HTTPD";
startOn = "${startingDependency}/started"; startOn = "started ${startingDependency}";
stopOn = "shutdown";
environment = environment =
{ # !!! This should be added in test-instrumentation.nix. It { # !!! This should be added in test-instrumentation.nix. It
@ -613,7 +612,14 @@ in
done done
''; '';
exec = "${httpd}/bin/httpd -f ${httpdConf} -DNO_DETACH"; daemonType = "fork";
exec = "${httpd}/bin/httpd -f ${httpdConf}";
preStop =
''
${httpd}/bin/httpd -f ${httpdConf} -k graceful-stop
'';
}; };
}; };

View File

@ -100,12 +100,12 @@ in
description = "Tomcat user"; description = "Tomcat user";
home = "/homeless-shelter"; home = "/homeless-shelter";
}; };
jobs.tomcat = jobs.tomcat =
{ description = "Apache Tomcat server"; { description = "Apache Tomcat server";
startOn = "network-interface/started"; startOn = "started network-interfaces";
stopOn = "network-interfaces/stop"; stopOn = "stopping network-interfaces";
preStart = preStart =
'' ''
@ -215,6 +215,7 @@ in
then then
for j in $i/conf/Catalina/* for j in $i/conf/Catalina/*
do do
mkdir -p ${cfg.baseDir}/conf/Catalina/localhost
ln -sfn $j ${cfg.baseDir}/conf/Catalina/localhost/`basename $j` ln -sfn $j ${cfg.baseDir}/conf/Catalina/localhost/`basename $j`
done done
fi fi
@ -251,6 +252,7 @@ in
then then
for j in $i/conf/Catalina/* for j in $i/conf/Catalina/*
do do
mkdir -p ${cfg.baseDir}/conf/Catalina/${virtualHost.name}
ln -sfn $j ${cfg.baseDir}/conf/Catalina/${virtualHost.name}/`basename $j` ln -sfn $j ${cfg.baseDir}/conf/Catalina/${virtualHost.name}/`basename $j`
done done
fi fi
@ -304,13 +306,10 @@ in
done done
'' ''
else ""} else ""}
''; # */
exec = ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${pkgs.tomcat6}/bin/startup.sh'
''
${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${pkgs.tomcat6}/bin/startup.sh; sleep 1000d'
''; '';
postStop = postStop =
'' ''
echo "Stopping tomcat..." echo "Stopping tomcat..."

View File

@ -12,8 +12,8 @@ let
defaultConfig = defaultConfig =
'' ''
[Shutdown] [Shutdown]
HaltCmd=${pkgs.upstart}/sbin/halt HaltCmd=${config.system.build.upstart}/sbin/halt
RebootCmd=${pkgs.upstart}/sbin/reboot RebootCmd=${config.system.build.upstart}/sbin/reboot
${optionalString (config.system.boot.loader.id == "grub") '' ${optionalString (config.system.boot.loader.id == "grub") ''
BootManager=Grub BootManager=Grub
''} ''}
@ -26,6 +26,8 @@ let
[X-:*-Core] [X-:*-Core]
ServerCmd=${dmcfg.xserverBin} ${dmcfg.xserverArgs} ServerCmd=${dmcfg.xserverBin} ${dmcfg.xserverArgs}
# The default timeout (15) is too short in a heavily loaded boot process.
ServerTimeout=60
# Needed to prevent the X server from dying on logout and not coming back: # Needed to prevent the X server from dying on logout and not coming back:
TerminateServer=true TerminateServer=true

View File

@ -14,8 +14,8 @@ let
xserver_arguments ${dmcfg.xserverArgs} xserver_arguments ${dmcfg.xserverArgs}
sessions ${pkgs.lib.concatStringsSep "," (dmcfg.session.names ++ ["custom"])} sessions ${pkgs.lib.concatStringsSep "," (dmcfg.session.names ++ ["custom"])}
login_cmd exec ${pkgs.stdenv.bash}/bin/sh ${dmcfg.session.script} "%session" login_cmd exec ${pkgs.stdenv.bash}/bin/sh ${dmcfg.session.script} "%session"
halt_cmd ${pkgs.upstart}/sbin/shutdown -h now halt_cmd ${config.system.build.upstart}/sbin/shutdown -h now
reboot_cmd ${pkgs.upstart}/sbin/shutdown -r now reboot_cmd ${config.system.build.upstart}/sbin/shutdown -r now
${if cfg.defaultUser != "" then "default_user " + cfg.defaultUser else ""} ${if cfg.defaultUser != "" then "default_user " + cfg.defaultUser else ""}
${if cfg.hideCursor then "hidecursor true" else ""} ${if cfg.hideCursor then "hidecursor true" else ""}
''; '';

View File

@ -43,8 +43,7 @@ in
jobs.xfs = jobs.xfs =
{ description = "X Font Server"; { description = "X Font Server";
startOn = "${startingDependency}/started"; startOn = "started ${startingDependency}";
stopOn = "shutdown";
exec = "${pkgs.xorg.xfs}/bin/xfs -config ${configFile}"; exec = "${pkgs.xorg.xfs}/bin/xfs -config ${configFile}";
}; };

View File

@ -385,7 +385,7 @@ in
optional (elem "virtualbox" driverNames) kernelPackages.virtualboxGuestAdditions; optional (elem "virtualbox" driverNames) kernelPackages.virtualboxGuestAdditions;
jobs.xserver = jobs.xserver =
{ startOn = if cfg.autorun then "hal" else "never"; { startOn = if cfg.autorun then "started udev and started hal" else "";
environment = environment =
{ FONTCONFIG_FILE = "/etc/fonts/fonts.conf"; # !!! cleanup { FONTCONFIG_FILE = "/etc/fonts/fonts.conf"; # !!! cleanup
@ -401,14 +401,6 @@ in
preStart = preStart =
'' ''
# Ugly hack: wait until udev has started since the X server
# needs various devices. This would more properly be
# expressed as an Upstart dependency, but AFAIK in "start
# on" we can't express a logical AND.
while ! initctl status udev 2>&1 | grep -q running; do
sleep 1
done
rm -f /var/run/opengl-driver rm -f /var/run/opengl-driver
${# !!! The OpenGL driver depends on what's detected at runtime. ${# !!! The OpenGL driver depends on what's detected at runtime.
if elem "nvidia" driverNames then '' if elem "nvidia" driverNames then ''

View File

@ -84,6 +84,16 @@ let
mkdir -m 0755 -p /var/run/nix/current-load # for distributed builds mkdir -m 0755 -p /var/run/nix/current-load # for distributed builds
mkdir -m 0700 -p /var/run/nix/remote-stores mkdir -m 0700 -p /var/run/nix/remote-stores
# Use a tmpfs for /var/run/nscd to ensure that / or /var can be
# unmounted or at least remounted read-only during shutdown.
# (Upstart 0.6 apparently uses nscd to do some name lookups,
# resulting in it holding some mmap mapping to deleted files in
# /var/run/nscd.)
if [ ! -e /var/run/nscd ]; then
mkdir -p /var/run/nscd
${pkgs.utillinux}/bin/mount -t tmpfs -o "mode=755" none /var/run/nscd
fi
mkdir -m 0755 -p /var/log mkdir -m 0755 -p /var/log
touch /var/log/wtmp # must exist touch /var/log/wtmp # must exist

View File

@ -54,27 +54,24 @@ EOF
exit 1 exit 1
fi fi
oldEvents=$(readlink -f /etc/event.d || true) oldJobs=$(readlink -f /etc/static/init)
newEvents=$(readlink -f @out@/etc/event.d) newJobs=$(readlink -f @out@/etc/init)
#echo "old: $oldEvents" echo "old: $oldJobs"
#echo "new: $newEvents" echo "new: $newJobs"
stopJob() { stopJob() {
local job=$1 local job=$1
initctl stop "$job" initctl stop "$job" || true
while ! initctl status "$job" 2>&1 | grep -q "(stop) waiting"; do
echo "waiting for $job to stop..."
sleep 1
done
} }
# Stop all services that are not in the new Upstart # Stop all services that are not in the new Upstart
# configuration. # configuration.
for event in $(cd $oldEvents && ls); do for job in $(cd $oldJobs && ls *.conf); do
if ! test -e "$newEvents/$event"; then job=$(basename $job .conf)
echo "stopping $event..." if ! test -e "$newJobs/$job.conf"; then
stopJob $event echo "stopping $job..."
stopJob $job
fi fi
done done
@ -83,26 +80,27 @@ EOF
echo "activating the configuration..." echo "activating the configuration..."
@out@/activate @out@ @out@/activate @out@
# Make Upstart reload its events. !!! Should wait until it has # Make Upstart reload its jobs.
# finished processing its stop events. initctl reload-configuration
kill -TERM 1
# Start all new services and restart all changed services. # Start all new services and restart all changed services.
for event in $(cd $newEvents && ls); do for job in $(cd $newJobs && ls *.conf); do
# Hack: skip the sys-* and ctrl-alt-delete events. job=$(basename $job .conf)
# Hack: skip the shutdown and control-alt-delete jobs.
# Another hack: don't restart the X server (that would kill all the clients). # Another hack: don't restart the X server (that would kill all the clients).
# And don't restart dbus, since that causes ConsoleKit to # And don't restart dbus, since that causes ConsoleKit to
# forget about current sessions. # forget about current sessions.
if echo "$event" | grep -q "^sys-\|^ctrl-\|^xserver$\|^dbus$"; then continue; fi if echo "$job" | grep -q "^shutdown$\|^control-alt-delete$\|^xserver$\|^dbus$"; then continue; fi
if ! test -e "$oldEvents/$event"; then if ! test -e "$oldJobs/$job.conf"; then
echo "starting $event..." echo "starting $job..."
initctl start "$event" initctl start "$job" || true
elif test "$(readlink "$oldEvents/$event")" != "$(readlink "$newEvents/$event")"; then elif test "$(readlink "$oldJobs/$job.conf")" != "$(readlink "$newJobs/$job.conf")"; then
echo "restarting $event..." echo "restarting $job..."
stopJob $event stopJob $job
initctl start "$event" initctl start "$job" || true
fi fi
done done
fi fi

View File

@ -76,11 +76,11 @@ let
ln -s ${config.system.activationScripts.script} $out/activate ln -s ${config.system.activationScripts.script} $out/activate
ln -s ${config.system.build.etc}/etc $out/etc ln -s ${config.system.build.etc}/etc $out/etc
ln -s ${config.system.path} $out/sw ln -s ${config.system.path} $out/sw
ln -s ${pkgs.upstart} $out/upstart ln -s ${config.system.build.upstart} $out/upstart
echo "$kernelParams" > $out/kernel-params echo "$kernelParams" > $out/kernel-params
echo "$configurationName" > $out/configuration-name echo "$configurationName" > $out/configuration-name
echo "${toString pkgs.upstart.interfaceVersion}" > $out/upstart-interface-version echo "${toString config.system.build.upstart.interfaceVersion}" > $out/upstart-interface-version
mkdir $out/fine-tune mkdir $out/fine-tune
childCount=0; childCount=0;
@ -114,7 +114,7 @@ let
pkgs.gnugrep pkgs.gnugrep
pkgs.findutils pkgs.findutils
pkgs.diffutils pkgs.diffutils
pkgs.upstart # for initctl config.system.build.upstart # for initctl
]; ];
# Boot loaders # Boot loaders

View File

@ -39,7 +39,7 @@ trap 'fail' ERR
# Print a greeting. # Print a greeting.
echo echo
echo "<<< NixOS Stage 1 >>>" echo "<<< NixOS Stage 1 >>>"
echo echo

View File

@ -5,7 +5,7 @@
# Print a greeting. # Print a greeting.
echo echo
echo "<<< NixOS Stage 2 >>>" echo -e "\e[1;32m<<< NixOS Stage 2 >>>\e[0m"
echo echo
@ -27,7 +27,7 @@ setPath "@path@"
# Mount special file systems. # Mount special file systems.
mkdir -m 0755 -p /etc mkdir -m 0755 -p /etc
test -e /etc/fstab || touch /etc/fstab # to shut up mount test -e /etc/fstab || touch /etc/fstab # to shut up mount
[ -s /etc/mtab ] && rm /etc/mtab # while installing a symlink is created (see man mount), if it's still there for whateever reason remove it test -s /etc/mtab && rm /etc/mtab # while installing a symlink is created (see man mount), if it's still there for whateever reason remove it
rm -f /etc/mtab* # not that we care about stale locks rm -f /etc/mtab* # not that we care about stale locks
mkdir -m 0755 -p /proc mkdir -m 0755 -p /proc
mount -n -t proc none /proc mount -n -t proc none /proc
@ -100,15 +100,12 @@ rm -rf /var/lock
# gone, of course. # gone, of course.
rm -rf /nix/var/nix/chroots # recreated in activate-configuration.sh rm -rf /nix/var/nix/chroots # recreated in activate-configuration.sh
if test -n "$safeMode"; then
mkdir -m 0755 -p /var/run
touch /var/run/safemode
fi
# Create the minimal device nodes needed for the activation scripts
# Create the minimal device nodes needed before we run udev. # and Upstart.
mknod -m 0666 /dev/null c 1 3 mknod -m 0666 /dev/null c 1 3
mknod -m 0644 /dev/urandom c 1 9 # needed for passwd mknod -m 0644 /dev/urandom c 1 9 # needed for passwd
mknod -m 0644 /dev/console c 5 1
# Clear the resume device. # Clear the resume device.
@ -136,12 +133,9 @@ export MODULE_DIR=@kernel@/lib/modules/
# Run any user-specified commands. # Run any user-specified commands.
@shell@ @postBootCommands@ @shell@ @postBootCommands@
echo "starting Upstart..." # For debugging Upstart.
#@shell@ --login < /dev/console > /dev/console 2>&1 &
# Start Upstart's init. We start it through the # Start Upstart's init.
# /var/run/current-system symlink indirection so that we can upgrade echo "starting Upstart..."
# init in a running system by changing the symlink and sending init a PATH=/var/run/current-system/upstart/sbin exec init
# HUP signal.
export UPSTART_CFG_DIR=/etc/event.d
setPath "@upstartPath@"
exec /var/run/current-system/upstart/sbin/init

View File

@ -15,30 +15,25 @@ let
}; };
inherit (pkgs) substituteAll writeText coreutils utillinux udev upstart; inherit (pkgs) substituteAll writeText coreutils utillinux udev;
kernel = config.boot.kernelPackages.kernel; kernel = config.boot.kernelPackages.kernel;
activateConfiguration = config.system.activationScripts.script; activateConfiguration = config.system.activationScripts.script;
# Path for Upstart jobs. Should be quite minimal.
upstartPath =
[ pkgs.coreutils
pkgs.findutils
pkgs.gnugrep
pkgs.gnused
pkgs.upstart
];
bootStage2 = substituteAll { bootStage2 = substituteAll {
src = ./stage-2-init.sh; src = ./stage-2-init.sh;
isExecutable = true; isExecutable = true;
inherit kernel upstart activateConfiguration upstartPath; inherit kernel activateConfiguration;
upstart = config.system.build.upstart;
path = path =
[ coreutils [ coreutils
utillinux utillinux
udev udev
upstart
]; ];
postBootCommands = writeText "local-cmds" config.boot.postBootCommands; postBootCommands = writeText "local-cmds"
''
${config.boot.postBootCommands}
${config.powerManagement.powerUpCommands}
'';
}; };
in in

View File

@ -3,10 +3,10 @@
###### implementation ###### implementation
{ {
jobs.ctrl_alt_delete = jobs.control_alt_delete =
{ name = "ctrl-alt-delete"; { name = "control-alt-delete";
startOn = "ctrlaltdel"; startOn = "control-alt-delete";
task = true; task = true;

View File

@ -1,22 +0,0 @@
{ config, pkgs, ... }:
###### implementation
{
jobs.maintenance_shell =
{ name = "maintenance-shell";
startOn = [ "maintenance" "stalled" ];
task = true;
script =
''
exec < /dev/tty1 > /dev/tty1 2>&1
echo \
echo "<<< MAINTENANCE SHELL >>>"
echo ""
exec ${pkgs.bash}/bin/sh
'';
};
}

View File

@ -0,0 +1,25 @@
{ config, pkgs, ... }:
with pkgs.lib;
{
jobs.runlevel =
{ name = "runlevel";
startOn = "runlevel [0123456S]";
task = true;
script =
''
case "$RUNLEVEL" in
0) initctl start shutdown MODE=poweroff;;
1) initctl start shutdown MODE=maintenance;;
6) initctl start shutdown MODE=reboot;;
*) echo "Unsupported runlevel: $RUNLEVEL";;
esac
'';
};
}

View File

@ -2,29 +2,33 @@
with pkgs.lib; with pkgs.lib;
###### implementation {
let jobs.shutdown =
{ name = "shutdown";
inherit (pkgs) bash utillinux;
jobFun = event:
{ startOn = event;
task = true; task = true;
environment = { MODE = "poweroff"; };
script = script =
'' ''
set +e # continue in case of errors set +e # continue in case of errors
${pkgs.kbd}/bin/chvt 1
exec < /dev/tty1 > /dev/tty1 2>&1 exec < /dev/console > /dev/console 2>&1
echo "" echo ""
echo "<<< SYSTEM SHUTDOWN >>>" if test "$MODE" = maintenance; then
echo "<<< Entering maintenance mode >>>"
else
echo "<<< System shutdown >>>"
fi
echo "" echo ""
export PATH=${utillinux}/bin:${utillinux}/sbin:$PATH export PATH=${pkgs.utillinux}/bin:${pkgs.utillinux}/sbin:$PATH
# Set the hardware clock to the system time. # Set the hardware clock to the system time.
echo "setting the hardware clock..." echo "setting the hardware clock..."
hwclock --systohc --utc hwclock --systohc --utc
@ -32,6 +36,15 @@ let
# Do an initial sync just in case. # Do an initial sync just in case.
sync sync
# Stop all Upstart jobs.
initctl list | while IFS=", " read jobName status rest; do
if test "$jobName" != shutdown -a "$status" != "stop/waiting"; then
echo "stopping $jobName..."
stop "$jobName"
fi
done
# Kill all remaining processes except init and this one. # Kill all remaining processes except init and this one.
@ -42,7 +55,20 @@ let
echo "sending the KILL signal to all processes..." echo "sending the KILL signal to all processes..."
kill -KILL -1 kill -KILL -1
# If maintenance mode is requested, start a root shell, and
# afterwards emit the "startup" event to bring everything
# back up.
if test "$MODE" = maintenance; then
echo ""
echo "<<< Maintenance shell >>>"
echo ""
while ! ${pkgs.bash}/bin/bash --login; do true; done
initctl emit -n startup
exit 0
fi
# Unmount helper functions. # Unmount helper functions.
getMountPoints() { getMountPoints() {
@ -99,9 +125,8 @@ let
sync sync
# Either reboot or power-off the system. Note that the "halt" # Either reboot or power-off the system.
# event also does a power-off. if test "$MODE" = reboot; then
if test ${event} = reboot; then
echo "rebooting..." echo "rebooting..."
sleep 1 sleep 1
exec reboot -f exec reboot -f
@ -113,9 +138,4 @@ let
''; '';
}; };
in }
{
jobs = listToAttrs (map (n: nameValuePair "sys-${n}" (jobFun n))
[ "reboot" "halt" "system-halt" "power-off" ] );
}

View File

@ -4,6 +4,19 @@ with pkgs.lib;
let let
upstart = pkgs.upstart06;
# Path for Upstart jobs. Should be quite minimal.
upstartPath =
[ pkgs.coreutils
pkgs.findutils
pkgs.gnugrep
pkgs.gnused
upstart
];
# From a job description, generate an Upstart job file. # From a job description, generate an Upstart job file.
makeJob = job: makeJob = job:
@ -15,23 +28,25 @@ let
description "${job.description}" description "${job.description}"
console output
${if isList job.startOn then ${if isList job.startOn then
# This is a hack to support or-dependencies on Upstart 0.3. "start on ${concatStringsSep " or " job.startOn}"
concatMapStrings (x: "start on ${x}\n") job.startOn
else if job.startOn != "" then else if job.startOn != "" then
"start on ${job.startOn}" "start on ${job.startOn}"
else "" else ""
} }
${if job.stopOn != "" then "stop on ${job.stopOn}" else ""} ${optionalString (job.stopOn != "") "stop on ${job.stopOn}"}
env PATH=${makeSearchPath "bin" upstartPath}:${makeSearchPath "sbin" upstartPath}
${concatMapStrings (n: "env ${n}=${getAttr n job.environment}\n") (attrNames job.environment)} ${concatMapStrings (n: "env ${n}=${getAttr n job.environment}\n") (attrNames job.environment)}
${if job.preStart != "" then '' ${optionalString (job.preStart != "") ''
start script pre-start script
${job.preStart} ${job.preStart}
end script end script
'' else ""} ''}
${if job.script != "" && job.exec != "" then ${if job.script != "" && job.exec != "" then
abort "Job ${job.name} has both a `script' and `exec' attribute." abort "Job ${job.name} has both a `script' and `exec' attribute."
@ -45,189 +60,218 @@ let
'' ''
exec ${job.exec} exec ${job.exec}
'' ''
else else ""
# Simulate jobs without a main process (which Upstart 0.3
# doesn't support) using a semi-infinite sleep.
''
exec sleep 1e100
''
} }
${if job.respawn && !job.task then "respawn" else ""} ${optionalString (job.postStart != "") ''
post-start script
${job.postStart}
end script
''}
${optionalString job.task "task"}
${optionalString job.respawn "respawn"}
${if job.postStop != "" then '' ${optionalString (job.preStop != "") ''
stop script pre-stop script
${job.preStop}
end script
''}
${optionalString (job.postStop != "") ''
post-stop script
${job.postStop} ${job.postStop}
end script end script
'' else ""} ''}
${optionalString (!job.task) (
if job.daemonType == "fork" then "expect fork" else
if job.daemonType == "daemon" then "expect daemon" else
if job.daemonType == "stop" then "expect stop" else
if job.daemonType == "none" then "" else
throw "invalid daemon type `${job.daemonType}'"
)}
${job.extraConfig} ${job.extraConfig}
''; '';
in in
pkgs.runCommand ("upstart-" + job.name) pkgs.runCommand ("upstart-" + job.name + ".conf")
{ inherit (job) buildHook; inherit jobText; } { inherit (job) buildHook; inherit jobText; }
'' ''
eval "$buildHook" eval "$buildHook"
ensureDir $out/etc/event.d echo "$jobText" > $out
echo "$jobText" > $out/etc/event.d/${job.name}
''; '';
jobs =
[pkgs.upstart] # for the built-in logd job
++ map (job: job.upstartPkg) (attrValues config.jobs);
# Create an etc/event.d directory containing symlinks to the
# specified list of Upstart job files.
jobsDir = pkgs.runCommand "upstart-jobs" {inherit jobs;}
''
ensureDir $out/etc/event.d
for i in $jobs; do
if ln -s $i . ; then
if test -d $i; then
ln -s $i/etc/event.d/* $out/etc/event.d/
fi
else
echo Duplicate entry: $i;
fi;
done
''; # */
# !! remove extra indentations.
jobOptions = { jobOptions = {
name = mkOption { name = mkOption {
# !!! The type should ensure that this could be a filename. # !!! The type should ensure that this could be a filename.
type = types.string; type = types.string;
example = "sshd"; example = "sshd";
description = '' description = ''
Name of the Upstart job. Name of the Upstart job.
''; '';
}; };
buildHook = mkOption { buildHook = mkOption {
type = types.string; type = types.string;
default = "true"; default = "true";
description = '' description = ''
Command run while building the Upstart job. Can be used Command run while building the Upstart job. Can be used
to perform simple regression tests (e.g., the Apache to perform simple regression tests (e.g., the Apache
Upstart job uses it to check the syntax of the generated Upstart job uses it to check the syntax of the generated
<filename>httpd.conf</filename>. <filename>httpd.conf</filename>.
''; '';
}; };
description = mkOption { description = mkOption {
type = types.string; type = types.string;
default = "(no description given)"; default = "(no description given)";
description = '' description = ''
A short description of this job. A short description of this job.
''; '';
}; };
startOn = mkOption { startOn = mkOption {
# !!! Re-enable this once we're on Upstart >= 0.6. # !!! Re-enable this once we're on Upstart >= 0.6.
#type = types.string; #type = types.string;
default = ""; default = "";
description = '' description = ''
The Upstart event that triggers this job to be started. The Upstart event that triggers this job to be started.
If empty, the job will not start automatically. If empty, the job will not start automatically.
''; '';
}; };
stopOn = mkOption { stopOn = mkOption {
type = types.string; type = types.string;
default = "shutdown"; default = "shutdown";
description = '' description = ''
The Upstart event that triggers this job to be stopped. The Upstart event that triggers this job to be stopped.
''; '';
}; };
preStart = mkOption { preStart = mkOption {
type = types.string; type = types.string;
default = ""; default = "";
description = '' description = ''
Shell commands executed before the job is started Shell commands executed before the job is started
(i.e. before the job's main process is started). (i.e. before the job's main process is started).
''; '';
}; };
postStop = mkOption { postStart = mkOption {
type = types.string; type = types.string;
default = ""; default = "";
description = '' description = ''
Shell commands executed after the job has stopped Shell commands executed after the job is started (i.e. after
(i.e. after the job's main process has terminated). the job's main process is started), but before the job is
''; considered running.
}; '';
};
exec = mkOption { preStop = mkOption {
type = types.string; type = types.string;
default = ""; default = "";
description = '' description = ''
Command to start the job's main process. If empty, the Shell commands executed before the job is stopped
job has no main process, but can still have pre/post-start (i.e. before Upstart kills the job's main process). This can
and pre/post-stop scripts, and is considered "running" be used to cleanly shut down a daemon.
until it is stopped. '';
''; };
};
script = mkOption { postStop = mkOption {
type = types.string; type = types.string;
default = ""; default = "";
description = '' description = ''
Shell commands executed as the job's main process. Can be Shell commands executed after the job has stopped
specified instead of the <varname>exec</varname> attribute. (i.e. after the job's main process has terminated).
''; '';
}; };
respawn = mkOption { exec = mkOption {
type = types.bool; type = types.string;
default = true; default = "";
description = '' description = ''
Whether to restart the job automatically if its process Command to start the job's main process. If empty, the
ends unexpectedly. job has no main process, but can still have pre/post-start
''; and pre/post-stop scripts, and is considered running
}; until it is stopped.
'';
};
task = mkOption { script = mkOption {
type = types.bool; type = types.string;
default = false; default = "";
description = '' description = ''
Whether this job is a task rather than a service. Tasks Shell commands executed as the job's main process. Can be
are executed only once, while services are restarted when specified instead of the <varname>exec</varname> attribute.
they exit. '';
''; };
};
environment = mkOption { respawn = mkOption {
type = types.attrs; type = types.bool;
default = {}; default = true;
example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; }; description = ''
description = '' Whether to restart the job automatically if its process
Environment variables passed to the job's processes. ends unexpectedly.
''; '';
}; };
extraConfig = mkOption { task = mkOption {
type = types.string; type = types.bool;
default = ""; default = false;
example = "limit nofile 4096 4096"; description = ''
description = '' Whether this job is a task rather than a service. Tasks
Additional Upstart stanzas not otherwise supported. are executed only once, while services are restarted when
''; they exit.
}; '';
};
}; environment = mkOption {
type = types.attrs;
default = {};
example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; };
description = ''
Environment variables passed to the job's processes.
'';
};
daemonType = mkOption {
type = types.string;
default = "none";
description = ''
Determines how Upstart detects when a daemon should be
considered running. The value <literal>none</literal> means
that the daemon is considered ready immediately. The value
<literal>fork</literal> means that the daemon will fork once.
The value <literal>daemon</literal> means that the daemon will
fork twice. The value <literal>stop</literal> means that the
daemon will raise the SIGSTOP signal to indicate readiness.
'';
};
extraConfig = mkOption {
type = types.string;
default = "";
example = "limit nofile 4096 4096";
description = ''
Additional Upstart stanzas not otherwise supported.
'';
};
};
upstartJob = {name, config, ...}: { upstartJob = {name, config, ...}: {
options = { options = {
upstartPkg = mkOption { jobDrv = mkOption {
default = makeJob config; default = makeJob config;
type = types.uniq types.package; type = types.uniq types.package;
description = '' description = ''
Upstart package which contains upstart events inside Derivation that builds the Upstart job file. The default
<filename>/etc/event.d/</filename>. The default value is value is generated from other options.
generated from other options.
''; '';
}; };
}; };
@ -275,19 +319,26 @@ in
config = { config = {
system.build.upstart = upstart;
environment.etc = environment.etc =
[ { # The Upstart events defined above. flip map (attrValues config.jobs) (job:
source = "${jobsDir}/etc/event.d"; { source = job.jobDrv;
target = "event.d"; target = "init/${job.name}.conf";
} } );
];
# Upstart can listen on the system bus, allowing normal users to
# do status queries.
services.dbus.packages = [ upstart ];
# !!! fix this # !!! fix this
/*
tests.upstartJobs = { recurseForDerivations = true; } // tests.upstartJobs = { recurseForDerivations = true; } //
builtins.listToAttrs (map (job: { builtins.listToAttrs (map (job: {
name = removePrefix "upstart-" job.name; name = removePrefix "upstart-" job.name;
value = job; value = job;
}) jobs); }) jobs);
*/
}; };

View File

@ -59,9 +59,11 @@ in
jobs.kbd = jobs.kbd =
{ description = "Keyboard / console initialisation"; { description = "Keyboard / console initialisation";
startOn = "udev"; startOn = "started udev";
preStart = '' task = true;
script = ''
export LANG=${defaultLocale} export LANG=${defaultLocale}
export LOCALE_ARCHIVE=/var/run/current-system/sw/lib/locale/locale-archive export LOCALE_ARCHIVE=/var/run/current-system/sw/lib/locale/locale-archive
export PATH=${pkgs.gzip}/bin:$PATH # Needed by setfont export PATH=${pkgs.gzip}/bin:$PATH # Needed by setfont

View File

@ -7,7 +7,7 @@
config = { config = {
jobs.lvm = jobs.lvm =
{ startOn = " udev"; # !!! or on new-devices { startOn = "started udev or new-devices";
script = script =
'' ''
@ -23,7 +23,7 @@
# make them appear in /dev. # make them appear in /dev.
${pkgs.lvm2}/sbin/vgchange --available y ${pkgs.lvm2}/sbin/vgchange --available y
initctl emit new-devices initctl emit -n new-devices
''; '';
task = true; task = true;

View File

@ -135,7 +135,7 @@ in
jobs.networkInterfaces = jobs.networkInterfaces =
{ name = "network-interfaces"; { name = "network-interfaces";
startOn = "udev"; startOn = "started udev";
preStart = preStart =
'' ''
@ -178,6 +178,11 @@ in
# Run any user-specified commands. # Run any user-specified commands.
${pkgs.stdenv.shell} ${pkgs.writeText "local-net-cmds" cfg.localCommands} || true ${pkgs.stdenv.shell} ${pkgs.writeText "local-net-cmds" cfg.localCommands} || true
# Emit the ip-up event (e.g. to start ntpd).
${optionalString (cfg.interfaces != []) ''
initctl emit -n ip-up
''}
''; '';
postStop = postStop =

View File

@ -13,7 +13,7 @@ in
{ {
jobs.swraid = jobs.swraid =
{ startOn = "udev"; # !!! or on "new-devices" { startOn = "started udev or new-devices";
script = script =
'' ''
@ -25,11 +25,13 @@ in
# Scan /proc/partitions for RAID devices. # Scan /proc/partitions for RAID devices.
${mdadm}/sbin/mdadm --examine --brief --scan -c partitions > ${tempConf} ${mdadm}/sbin/mdadm --examine --brief --scan -c partitions > ${tempConf}
if ! test -s ${tempConf}; then exit 0; fi
# Activate each device found. # Activate each device found.
${mdadm}/sbin/mdadm --assemble -c ${tempConf} --scan ${mdadm}/sbin/mdadm --assemble -c ${tempConf} --scan
initctl emit new-devices initctl emit -n new-devices
''; '';
task = true; task = true;

View File

@ -105,7 +105,7 @@ in
jobs.ttyBackgrounds = jobs.ttyBackgrounds =
{ name = "tty-backgrounds"; { name = "tty-backgrounds";
startOn = "udev"; startOn = "started udev";
preStart = preStart =
'' ''

View File

@ -9,6 +9,8 @@
{config, pkgs, ...}: {config, pkgs, ...}:
with pkgs.lib;
let let
vmName = config.networking.hostName; vmName = config.networking.hostName;
@ -16,7 +18,7 @@ let
options = { options = {
virtualisation.diskImage = virtualisation.diskImage =
pkgs.lib.mkOption { mkOption {
default = "./${vmName}.qcow2"; default = "./${vmName}.qcow2";
description = description =
'' ''
@ -90,7 +92,7 @@ in
# where the regular value for the `fileSystems' attribute should be # where the regular value for the `fileSystems' attribute should be
# disregarded for the purpose of building a VM test image (since # disregarded for the purpose of building a VM test image (since
# those filesystems don't exist in the VM). # those filesystems don't exist in the VM).
fileSystems = pkgs.lib.mkOverride 50 {} fileSystems = mkOverride 50 {}
[ { mountPoint = "/"; [ { mountPoint = "/";
device = "/dev/vda"; device = "/dev/vda";
} }
@ -119,6 +121,13 @@ in
networking.defaultGateway = "10.0.2.2"; networking.defaultGateway = "10.0.2.2";
networking.nameservers = [ "10.0.2.3" ];
networking.interfaces = singleton
{ name = "eth0";
ipAddress = "10.0.2.15";
};
system.build.vm = pkgs.runCommand "nixos-vm" {} system.build.vm = pkgs.runCommand "nixos-vm" {}
'' ''
ensureDir $out/bin ensureDir $out/bin
@ -135,11 +144,11 @@ in
# When building a regular system configuration, override whatever # When building a regular system configuration, override whatever
# video driver the host uses. # video driver the host uses.
services.xserver.videoDriver = pkgs.lib.mkOverride 50 {} null; services.xserver.videoDriver = mkOverride 50 {} null;
services.xserver.videoDrivers = pkgs.lib.mkOverride 50 {} [ "cirrus" "vesa" ]; services.xserver.videoDrivers = mkOverride 50 {} [ "cirrus" "vesa" ];
services.xserver.defaultDepth = pkgs.lib.mkOverride 50 {} 0; services.xserver.defaultDepth = mkOverride 50 {} 0;
services.xserver.resolutions = pkgs.lib.mkOverride 50 {} []; services.xserver.resolutions = mkOverride 50 {} [];
# Wireless won't work in the VM. # Wireless won't work in the VM.
networking.enableWLAN = pkgs.lib.mkOverride 50 {} false; networking.enableWLAN = mkOverride 50 {} false;
} }

View File

@ -30,10 +30,11 @@ let
description = "NixOS installation CD (${description}) - ISO image for ${system}"; description = "NixOS installation CD (${description}) - ISO image for ${system}";
maintainers = map (x: lib.getAttr x lib.maintainers) maintainers; maintainers = map (x: lib.getAttr x lib.maintainers) maintainers;
}; };
inherit iso;
} }
'' ''
ensureDir $out/nix-support ensureDir $out/nix-support
echo "file iso" ${iso}/iso/*.iso* >> $out/nix-support/hydra-build-products echo "file iso" $iso/iso/*.iso* >> $out/nix-support/hydra-build-products
''; # */ ''; # */