diff --git a/default.nix b/default.nix index df69ee4c3e2..17a417306b2 100644 --- a/default.nix +++ b/default.nix @@ -23,11 +23,9 @@ in config.environment.checkConfigurationOptions optionDeclarations config; - nix = config.environment.nix; - + # The following are used by nixos-rebuild. nixFallback = pkgs.nixUnstable; - - manifests = config.installer.manifests; # exported here because nixos-rebuild uses it + manifests = config.installer.manifests; tests = config.tests; } diff --git a/etc/bashrc.sh b/etc/bashrc.sh index 55820a31a63..ea3f398c8f2 100644 --- a/etc/bashrc.sh +++ b/etc/bashrc.sh @@ -1,15 +1,10 @@ # Initialise a bunch of environment variables. export PATH=/var/run/current-system/sw/bin:/var/run/current-system/sw/sbin export LD_LIBRARY_PATH=/var/run/opengl-driver/lib -if test -n "@nssModulesPath@"; then - LD_LIBRARY_PATH=@nssModulesPath@:$LD_LIBRARY_PATH -fi export MODULE_DIR=@modulesTree@/lib/modules export NIXPKGS_CONFIG=/nix/etc/config.nix export NIXPKGS_ALL=/etc/nixos/nixpkgs export PAGER="less -R" -export TZ=@timeZone@ -export TZDIR=@glibc@/share/zoneinfo export FONTCONFIG_FILE=/etc/fonts/fonts.conf export LANG=@defaultLocale@ export EDITOR=nano @@ -18,6 +13,7 @@ export LOCATE_PATH=/var/cache/locatedb @shellInit@ export LOCALE_ARCHIVE=/var/run/current-system/sw/lib/locale/locale-archive + # Set up secure multi-user builds: non-root users build through the # Nix daemon. if test "$USER" != root; then diff --git a/etc/default.nix b/etc/default.nix index 6306dd4edaf..9326160955d 100644 --- a/etc/default.nix +++ b/etc/default.nix @@ -38,7 +38,6 @@ let shellInit = config.environment.shellInit; nixEnvVars = config.nix.envVars; modulesTree = config.system.modulesTree; - nssModulesPath = config.system.nssModules.path; wrapperDir = config.security.wrapperDir; systemPath = config.system.path; binsh = config.system.build.binsh; @@ -121,9 +120,7 @@ let { # Script executed when the shell starts as a non-login shell (system-wide version). source = pkgs.substituteAll { src = ./bashrc.sh; - inherit systemPath wrapperDir modulesTree nssModulesPath; - inherit (pkgs) glibc; - timeZone = config.time.timeZone; + inherit systemPath wrapperDir modulesTree; defaultLocale = config.i18n.defaultLocale; inherit nixEnvVars shellInit; }; diff --git a/maintainers/scripts/gen-module-list.sh b/maintainers/scripts/gen-module-list.sh index 5f40ee66bcf..b885fe58f32 100755 --- a/maintainers/scripts/gen-module-list.sh +++ b/maintainers/scripts/gen-module-list.sh @@ -34,7 +34,7 @@ generate_index(){ local path="$1" cd "$path" echo -n "$path: " 1>&2 - { echo "[ # This file have been generated by $(basename $prog)"; + { echo "[ # This file has been generated by $(basename $prog)"; for file in : $(find ./ -wholename '*.impl[./]*' -or -wholename './module-list.nix' -or -type f -name '*.nix' -print | sort); do [ "$file" = ':' ] && continue; echo -n . 1>&2 diff --git a/etc/nsswitch-mdns.conf b/modules/config/nsswitch-mdns.conf similarity index 100% rename from etc/nsswitch-mdns.conf rename to modules/config/nsswitch-mdns.conf diff --git a/etc/nsswitch.conf b/modules/config/nsswitch.conf similarity index 100% rename from etc/nsswitch.conf rename to modules/config/nsswitch.conf diff --git a/modules/config/nsswitch.nix b/modules/config/nsswitch.nix new file mode 100644 index 00000000000..2a37903f7f3 --- /dev/null +++ b/modules/config/nsswitch.nix @@ -0,0 +1,56 @@ +# Configuration for the Name Service Switch (/etc/nsswitch.conf). + +{config, pkgs, ...}: + +let + + options = { + + # NSS modules. Hacky! + system.nssModules = pkgs.lib.mkOption { + internal = true; + default = []; + description = " + Search path for NSS (Name Service Switch) modules. This allows + several DNS resolution methods to be specified via + /etc/nsswitch.conf. + "; + merge = pkgs.lib.mergeListOption; + apply = list: + let + list2 = + list + # !!! this should be in the LDAP module + ++ pkgs.lib.optional config.users.ldap.enable pkgs.nss_ldap; + in { + list = list2; + path = pkgs.lib.makeLibraryPath list2; + }; + }; + + }; + +in + +{ + require = [options]; + + environment.etc = + [ # Name Service Switch configuration file. Required by the C library. + # !!! Factor out the mdns stuff. The avahi module should define + # an option used by this module. + { source = + if config.services.avahi.nssmdns + then ./nsswitch-mdns.conf + else ./nsswitch.conf; + target = "nsswitch.conf"; + } + ]; + + environment.shellInit = + if config.system.nssModules.path != "" then + '' + LD_LIBRARY_PATH=${config.system.nssModules.path}:$LD_LIBRARY_PATH + '' + else ""; +} diff --git a/modules/config/timezone.nix b/modules/config/timezone.nix new file mode 100644 index 00000000000..b08712464a1 --- /dev/null +++ b/modules/config/timezone.nix @@ -0,0 +1,25 @@ +{pkgs, config, ...}: + +let + + options = { + + time.timeZone = pkgs.lib.mkOption { + default = "CET"; + example = "America/New_York"; + description = "The time zone used when displaying times and dates."; + }; + + }; + +in + +{ + require = [options]; + + environment.shellInit = + '' + export TZ=${config.time.timeZone} + export TZDIR=${pkgs.glibc}/share/zoneinfo + ''; +} diff --git a/modules/installer/grub/grub.nix b/modules/installer/grub/grub.nix index 45c8a1fb29b..eaef9521f33 100644 --- a/modules/installer/grub/grub.nix +++ b/modules/installer/grub/grub.nix @@ -77,6 +77,15 @@ let "; }; + copyKernels = mkOption { + default = false; + description = " + Whether the Grub menu builder should copy kernels and initial + ramdisks to /boot. This is necessary when /nix is on a + different file system than /boot. + "; + }; + }; }; in diff --git a/modules/module-list.nix b/modules/module-list.nix index 8d41318bf23..19fc5d10fbf 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -1,10 +1,13 @@ [ # This file have been generated by gen-module-list.sh ./config/fonts.nix ./config/i18n.nix + ./config/nsswitch.nix + ./config/system-path.nix + ./config/timezone.nix ./config/unix-odbc-drivers.nix ./config/users-groups.nix - ./config/system-path.nix ./installer/grub/grub.nix + ./legacy.nix ./security/setuid-wrappers.nix ./security/sudo.nix ./services/audio/alsa.nix @@ -59,27 +62,27 @@ ##### ./services/web-servers/apache-httpd/per-server-options.nix # error: while evaluating the attribute `' at `(string):2:8': # while evaluating the function at `(string):3:22': -# while evaluating the function at `/trace/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix:6:2': +# while evaluating the function at `/home/eelco/Dev/modular-nixos/modules/services/web-servers/apache-httpd/per-server-options.nix:6:2': # the argument named `forMainServer' required by the function is missing ##### ./services/web-servers/apache-httpd/subversion.nix # error: while evaluating the attribute `' at `(string):2:8': # while evaluating the function at `(string):3:22': -# while evaluating the function at `/trace/nixos/modules/services/web-servers/apache-httpd/subversion.nix:1:2': +# while evaluating the function at `/home/eelco/Dev/modular-nixos/modules/services/web-servers/apache-httpd/subversion.nix:1:2': # the argument named `serverInfo' required by the function is missing ##### ./services/web-servers/apache-httpd/tomcat-connector.nix # error: while evaluating the attribute `' at `(string):2:8': # while evaluating the function at `(string):3:22': -# while evaluating the function at `/trace/nixos/modules/services/web-servers/apache-httpd/tomcat-connector.nix:1:2': +# while evaluating the function at `/home/eelco/Dev/modular-nixos/modules/services/web-servers/apache-httpd/tomcat-connector.nix:1:2': # the argument named `serverInfo' required by the function is missing ##### ./services/web-servers/apache-httpd/twiki.nix # error: while evaluating the attribute `' at `(string):2:8': # while evaluating the function at `(string):3:22': -# while evaluating the function at `/trace/nixos/modules/services/web-servers/apache-httpd/twiki.nix:1:2': +# while evaluating the function at `/home/eelco/Dev/modular-nixos/modules/services/web-servers/apache-httpd/twiki.nix:1:2': # the argument named `serverInfo' required by the function is missing ##### ./services/web-servers/apache-httpd/zabbix.nix # error: while evaluating the attribute `' at `(string):2:8': # while evaluating the function at `(string):3:22': -# while evaluating the function at `/trace/nixos/modules/services/web-servers/apache-httpd/zabbix.nix:1:2': +# while evaluating the function at `/home/eelco/Dev/modular-nixos/modules/services/web-servers/apache-httpd/zabbix.nix:1:2': # the argument named `serverInfo' required by the function is missing ./services/web-servers/jboss.nix ./services/web-servers/tomcat.nix @@ -87,9 +90,9 @@ ./services/x11/xserver/default.nix ./services/x11/xserver/desktop-managers/default.nix ./services/x11/xserver/desktop-managers/gnome.nix + ./services/x11/xserver/desktop-managers/kde4.nix ./services/x11/xserver/desktop-managers/kde-environment.nix ./services/x11/xserver/desktop-managers/kde.nix - ./services/x11/xserver/desktop-managers/kde4.nix ./services/x11/xserver/desktop-managers/none.nix ./services/x11/xserver/desktop-managers/xterm.nix ./services/x11/xserver/display-managers/default.nix @@ -114,9 +117,8 @@ ##### ./system/upstart/make-job.nix # error: while evaluating the attribute `' at `(string):2:8': # while evaluating the function at `(string):3:22': -# while evaluating the function at `/trace/nixos/modules/system/upstart/make-job.nix:1:2': +# while evaluating the function at `/home/eelco/Dev/modular-nixos/modules/system/upstart/make-job.nix:1:2': # the argument named `runCommand' required by the function is missing ./system/upstart/tools.nix ./system/upstart/upstart.nix - ./legacy.nix ] diff --git a/modules/services/hardware/udev.nix b/modules/services/hardware/udev.nix index 51b11099ae1..63c4c77e1b3 100644 --- a/modules/services/hardware/udev.nix +++ b/modules/services/hardware/udev.nix @@ -5,6 +5,19 @@ let inherit (pkgs.lib) mkOption mkIf; options = { + + boot.hardwareScan = mkOption { + default = true; + description = " + Whether to try to load kernel modules for all detected hardware. + Usually this does a good job of providing you with the modules + you need, but sometimes it can crash the system or cause other + nasty effects. If the hardware scan is turned on, it can be + disabled at boot time by adding the safemode + parameter to the kernel command line. + "; + }; + services = { udev = { diff --git a/modules/services/networking/avahi-daemon.nix b/modules/services/networking/avahi-daemon.nix index a504bf9b6a0..9ba55f2076c 100644 --- a/modules/services/networking/avahi-daemon.nix +++ b/modules/services/networking/avahi-daemon.nix @@ -136,22 +136,6 @@ mkIf cfg.enable { environment = { extraPackages = [avahi]; - - # Name Service Switch configuration file. Required by the C library. - # !!! This should be done in some other way, e.g., this module - # should define an option used by the hypothetical module that - # generates nsswitch.conf. - etc = mkIf cfg.nssmdns (mkThenElse { - thenPart = [{ - source = ../../../etc/nsswitch-mdns.conf; - target = "nsswitch.conf"; - }]; - - elsePart = [{ - source = ../../../etc/nsswitch.conf; - target = "nsswitch.conf"; - }]; - }); }; users = { diff --git a/modules/system/boot/stage-1.nix b/modules/system/boot/stage-1.nix index ff8a37662f9..cb8bb7b3243 100644 --- a/modules/system/boot/stage-1.nix +++ b/modules/system/boot/stage-1.nix @@ -11,6 +11,16 @@ let options = { + boot.isLiveCD = mkOption { + default = false; + description = " + If set to true, the root device will be mounted read-only and + a ramdisk will be mounted on top of it using unionfs to + provide a writable root. This is used for the NixOS + Live-CD/DVD. + "; + }; + boot.resumeDevice = mkOption { default = ""; example = "0:0"; diff --git a/modules/system/boot/stage-2.nix b/modules/system/boot/stage-2.nix index c86570ad766..69c85d43bc5 100644 --- a/modules/system/boot/stage-2.nix +++ b/modules/system/boot/stage-2.nix @@ -1,10 +1,22 @@ {pkgs, config, ...}: let + + options = { + + boot.localCommands = pkgs.lib.mkOption { + default = ""; + example = "text=anything; echo You can put $text here."; + description = " + Shell commands to be executed just before Upstart is started. + "; + }; + + }; + inherit (pkgs) substituteAll writeText coreutils utillinux udev upstart; kernel = config.boot.kernelPackages.kernel; activateConfiguration = config.system.activationScripts.script; - inherit (config.boot) isLiveCD; # Path for Upstart jobs. Should be quite minimal. upstartPath = [ @@ -20,7 +32,7 @@ let bootStage2 = substituteAll { src = ./stage-2-init.sh; isExecutable = true; - inherit kernel upstart isLiveCD activateConfiguration upstartPath; + inherit kernel upstart activateConfiguration upstartPath; path = [ coreutils utillinux @@ -32,16 +44,7 @@ let in { - require = [ - # config.boot.localCommands - # config.boot.kernelPackages - - # config.system.activationScripts - # ../system/activate-configuration.nix - - # config.system.build - # ../system/system-options.nix - ]; + require = [options]; system = { build = { diff --git a/modules/system/upstart/upstart.nix b/modules/system/upstart/upstart.nix index 459b8a76e98..a5e431747fc 100644 --- a/modules/system/upstart/upstart.nix +++ b/modules/system/upstart/upstart.nix @@ -52,14 +52,6 @@ in ###### implementation let - # should be moved to the corresponding jobs. - nix = config.environment.nix; - nixEnvVars = config.nix.envVars; - kernelPackages = config.boot.kernelPackages; - nssModulesPath = config.system.nssModules.path; - modprobe = config.system.sbin.modprobe; - mount = config.system.sbin.mount; - makeJob = import ./make-job.nix { inherit (pkgs) runCommand; }; diff --git a/system/options.nix b/system/options.nix index 63ef9bc94a3..f070d867416 100644 --- a/system/options.nix +++ b/system/options.nix @@ -6,58 +6,8 @@ in { - time = { - - timeZone = mkOption { - default = "CET"; - example = "America/New_York"; - description = "The time zone used when displaying times and dates."; - }; - - }; - - boot = { - isLiveCD = mkOption { - default = false; - description = " - If set to true, the root device will be mounted read-only and - a ramdisk will be mounted on top of it using unionfs to - provide a writable root. This is used for the NixOS - Live-CD/DVD. - "; - }; - - hardwareScan = mkOption { - default = true; - description = " - Whether to try to load kernel modules for all detected hardware. - Usually this does a good job of providing you with the modules - you need, but sometimes it can crash the system or cause other - nasty effects. If the hardware scan is turned on, it can be - disabled at boot time by adding the safemode - parameter to the kernel command line. - "; - }; - - copyKernels = mkOption { - default = false; - description = " - Whether the Grub menu builder should copy kernels and initial - ramdisks to /boot. This is necessary when /nix is on a - different file system than /boot. - "; - }; - - localCommands = mkOption { - default = ""; - example = "text=anything; echo You can put $text here."; - description = " - Shell commands to be executed just before Upstart is started. - "; - }; - extraTTYs = mkOption { default = []; example = [8 9]; @@ -73,53 +23,6 @@ in }; - system = { - # NSS modules. Hacky! - nssModules = mkOption { - internal = true; - default = []; - description = " - Search path for NSS (Name Service Switch) modules. This allows - several DNS resolution methods to be specified via - /etc/nsswitch.conf. - "; - merge = pkgs.lib.mergeListOption; - apply = list: - let - list2 = - list - ++ pkgs.lib.optional config.users.ldap.enable pkgs.nss_ldap; - in { - list = list2; - path = pkgs.lib.makeLibraryPath list2; - }; - }; - - sbin = { - # !!! The mount option should not stay in /system/option.nix - mount = mkOption { - internal = true; - default = pkgs.utillinuxng.override { - buildMountOnly = true; - mountHelpers = pkgs.buildEnv { - name = "mount-helpers"; - paths = [ - pkgs.ntfs3g - pkgs.mount_cifs - pkgs.nfsUtils - ]; - pathsToLink = "/sbin"; - } + "/sbin"; - }; - description = " - A patched `mount' command that looks in a directory in the Nix - store instead of in /sbin for mount helpers (like mount.ntfs-3g or - mount.cifs). - "; - }; - }; - }; - networking = { @@ -239,61 +142,6 @@ in }; - fileSystems = mkOption { - default = null; - example = [ - { mountPoint = "/"; - device = "/dev/hda1"; - } - { mountPoint = "/data"; - device = "/dev/hda2"; - fsType = "ext3"; - options = "data=journal"; - } - { mountPoint = "/bigdisk"; - label = "bigdisk"; - } - ]; - description = " - The file systems to be mounted. It must include an entry for - the root directory (mountPoint = \"/\"). Each - entry in the list is an attribute set with the following fields: - mountPoint, device, - fsType (a file system type recognised by - mount; defaults to - \"auto\"), and options - (the mount options passed to mount using the - flag; defaults to \"defaults\"). - - Instead of specifying device, you can also - specify a volume label (label) for file - systems that support it, such as ext2/ext3 (see mke2fs - -L). - - autocreate forces mountPoint to be created with - mkdir -p . - "; - }; - - - swapDevices = mkOption { - default = []; - example = [ - { device = "/dev/hda7"; } - { device = "/var/swapfile"; } - { label = "bigswap"; } - ]; - description = " - The swap devices and swap files. These must have been - initialised using mkswap. Each element - should be an attribute set specifying either the path of the - swap device or file (device) or the label - of the swap device (label, see - mkswap -L). Using a label is - recommended. - "; - }; - nesting = { children = mkOption { default = []; @@ -304,14 +152,5 @@ in }; - passthru = mkOption { - default = {}; - description = " - Additional parameters. Ignored. When you want to be sure that - /etc/nixos/nixos -A config.passthru.* is that same thing the - system rebuild will use. - "; - }; - require = import ../modules/module-list.nix; } diff --git a/upstart-jobs/filesystems.nix b/upstart-jobs/filesystems.nix index 10673cce5f3..6ed59916ccd 100644 --- a/upstart-jobs/filesystems.nix +++ b/upstart-jobs/filesystems.nix @@ -1,11 +1,75 @@ {pkgs, config, ...}: +let + +###### interface + + options = { + + fileSystems = pkgs.lib.mkOption { + default = null; + example = [ + { mountPoint = "/"; + device = "/dev/hda1"; + } + { mountPoint = "/data"; + device = "/dev/hda2"; + fsType = "ext3"; + options = "data=journal"; + } + { mountPoint = "/bigdisk"; + label = "bigdisk"; + } + ]; + description = " + The file systems to be mounted. It must include an entry for + the root directory (mountPoint = \"/\"). Each + entry in the list is an attribute set with the following fields: + mountPoint, device, + fsType (a file system type recognised by + mount; defaults to + \"auto\"), and options + (the mount options passed to mount using the + flag; defaults to \"defaults\"). + + Instead of specifying device, you can also + specify a volume label (label) for file + systems that support it, such as ext2/ext3 (see mke2fs + -L). + + autocreate forces mountPoint to be created with + mkdir -p . + "; + }; + + system.sbin.mount = pkgs.lib.mkOption { + internal = true; + default = pkgs.utillinuxng.override { + buildMountOnly = true; + mountHelpers = pkgs.buildEnv { + name = "mount-helpers"; + paths = [ + pkgs.ntfs3g + pkgs.mount_cifs + pkgs.nfsUtils + ]; + pathsToLink = "/sbin"; + } + "/sbin"; + }; + description = " + A patched `mount' command that looks in a directory in the Nix + store instead of in /sbin for mount helpers (like mount.ntfs-3g or + mount.cifs). + "; + }; + + }; + ###### implementation -let inherit (pkgs) e2fsprogs; - mountPoints = map (fs: fs.mountPoint) fileSystems; fileSystems = config.fileSystems; + mountPoints = map (fs: fs.mountPoint) fileSystems; devices = map (fs: if fs ? device then fs.device else "LABEL=" + fs.label) fileSystems; fsTypes = map (fs: if fs ? fsType then fs.fsType else "auto") fileSystems; optionss = map (fs: if fs ? options then fs.options else "defaults") fileSystems; @@ -13,110 +77,111 @@ let mount = config.system.sbin.mount; job = '' - start on startup - start on new-devices - start on ip-up - - script - PATH=${e2fsprogs}/sbin:$PATH - - mountPoints=(${toString mountPoints}) - devices=(${toString devices}) - fsTypes=(${toString fsTypes}) - optionss=(${toString optionss}) - autocreates=(${toString autocreates}) - - newDevices=1 - - # If we mount any file system, we repeat this loop, because new - # mount opportunities may have become available (such as images - # for loopback mounts). - - while test -n "$newDevices"; do - - newDevices= - - for ((n = 0; n < ''${#mountPoints[*]}; n++)); do - mountPoint=''${mountPoints[$n]} - device=''${devices[$n]} - fsType=''${fsTypes[$n]} - options=''${optionss[$n]} - autocreate=''${autocreates[$n]} - - isLabel= - if echo "$device" | grep -q '^LABEL='; then isLabel=1; fi - - isPseudo= - if test "$fsType" = "nfs" || test "$fsType" = "tmpfs" || - test "$fsType" = "ext3cow"; then isPseudo=1; fi - - if ! test -n "$isLabel" -o -n "$isPseudo" -o -e "$device"; then - echo "skipping $device, doesn't exist (yet)" - continue - fi - - # !!! quick hack: if mount point already exists, try a - # remount to change the options but nothing else. - if cat /proc/mounts | grep -F -q " $mountPoint "; then - echo "remounting $device on $mountPoint" - ${mount}/bin/mount -t "$fsType" \ - -o remount,"$options" \ - "$device" "$mountPoint" || true - continue - fi - - # If $device is already mounted somewhere else, unmount it first. - # !!! Note: we use /etc/mtab, not /proc/mounts, because mtab - # contains more accurate info when using loop devices. - - # !!! not very smart about labels yet; should resolve the label somehow. - if test -z "$isLabel" -a -z "$isPseudo"; then - - device=$(readlink -f "$device") - - prevMountPoint=$( - cat /etc/mtab \ - | grep "^$device " \ - | sed 's|^[^ ]\+ \+\([^ ]\+\).*|\1|' \ - ) - - if test "$prevMountPoint" = "$mountPoint"; then + start on startup + start on new-devices + start on ip-up + + script + PATH=${e2fsprogs}/sbin:$PATH + + mountPoints=(${toString mountPoints}) + devices=(${toString devices}) + fsTypes=(${toString fsTypes}) + optionss=(${toString optionss}) + autocreates=(${toString autocreates}) + + newDevices=1 + + # If we mount any file system, we repeat this loop, because new + # mount opportunities may have become available (such as images + # for loopback mounts). + + while test -n "$newDevices"; do + + newDevices= + + for ((n = 0; n < ''${#mountPoints[*]}; n++)); do + mountPoint=''${mountPoints[$n]} + device=''${devices[$n]} + fsType=''${fsTypes[$n]} + options=''${optionss[$n]} + autocreate=''${autocreates[$n]} + + isLabel= + if echo "$device" | grep -q '^LABEL='; then isLabel=1; fi + + isPseudo= + if test "$fsType" = "nfs" || test "$fsType" = "tmpfs" || + test "$fsType" = "ext3cow"; then isPseudo=1; fi + + if ! test -n "$isLabel" -o -n "$isPseudo" -o -e "$device"; then + echo "skipping $device, doesn't exist (yet)" + continue + fi + + # !!! quick hack: if mount point already exists, try a + # remount to change the options but nothing else. + if cat /proc/mounts | grep -F -q " $mountPoint "; then echo "remounting $device on $mountPoint" ${mount}/bin/mount -t "$fsType" \ -o remount,"$options" \ "$device" "$mountPoint" || true continue fi - - if test -n "$prevMountPoint"; then - echo "unmount $device from $prevMountPoint" - ${mount}/bin/umount "$prevMountPoint" || true + + # If $device is already mounted somewhere else, unmount it first. + # !!! Note: we use /etc/mtab, not /proc/mounts, because mtab + # contains more accurate info when using loop devices. + + # !!! not very smart about labels yet; should resolve the label somehow. + if test -z "$isLabel" -a -z "$isPseudo"; then + + device=$(readlink -f "$device") + + prevMountPoint=$( + cat /etc/mtab \ + | grep "^$device " \ + | sed 's|^[^ ]\+ \+\([^ ]\+\).*|\1|' \ + ) + + if test "$prevMountPoint" = "$mountPoint"; then + echo "remounting $device on $mountPoint" + ${mount}/bin/mount -t "$fsType" \ + -o remount,"$options" \ + "$device" "$mountPoint" || true + continue + fi + + if test -n "$prevMountPoint"; then + echo "unmount $device from $prevMountPoint" + ${mount}/bin/umount "$prevMountPoint" || true + fi + fi - - fi - - echo "mounting $device on $mountPoint" - - # !!! should do something with the result; also prevent repeated fscks. - if test -z "$isPseudo"; then - fsck -a "$device" || true - fi - - if test "$autocreate" = 1; then mkdir -p "$mountPoint"; fi - - if ${mount}/bin/mount -t "$fsType" -o "$options" "$device" "$mountPoint"; then - newDevices=1 - fi - + + echo "mounting $device on $mountPoint" + + # !!! should do something with the result; also prevent repeated fscks. + if test -z "$isPseudo"; then + fsck -a "$device" || true + fi + + if test "$autocreate" = 1; then mkdir -p "$mountPoint"; fi + + if ${mount}/bin/mount -t "$fsType" -o "$options" "$device" "$mountPoint"; then + newDevices=1 + fi + + done + done - - done - - end script + + end script ''; in { + require = [options]; services = { extraJobs = [{ name = "filesystems"; diff --git a/upstart-jobs/swap.nix b/upstart-jobs/swap.nix index 5b6b70e362f..173b933d992 100644 --- a/upstart-jobs/swap.nix +++ b/upstart-jobs/swap.nix @@ -1,9 +1,34 @@ {pkgs, config, ...}: -###### implementation - let +###### interface + + options = { + + swapDevices = pkgs.lib.mkOption { + default = []; + example = [ + { device = "/dev/hda7"; } + { device = "/var/swapfile"; } + { label = "bigswap"; } + ]; + description = " + The swap devices and swap files. These must have been + initialised using mkswap. Each element + should be an attribute set specifying either the path of the + swap device or file (device) or the label + of the swap device (label, see + mkswap -L). Using a label is + recommended. + "; + }; + + }; + + +###### implementation + inherit (pkgs) utillinux lib; swapDevices = config.swapDevices; @@ -18,37 +43,37 @@ in { - services = { - extraJobs = [{ - name = "swap"; - - job = " - start on startup - start on new-devices - - script - for device in ${toString devicesByPath}; do - ${utillinux}/sbin/swapon \"$device\" || true - done - - for label in ${toString devicesByLabel}; do - ${utillinux}/sbin/swapon -L \"$label\" || true - done - - # Remove swap devices not listed in swapDevices. - # !!! disabled because it doesn't work with labels - #for used in $(cat /proc/swaps | grep '^/' | sed 's/ .*//'); do - # found= - # for device in $ {toString swapDevices}; do - # if test \"$used\" = \"$device\"; then found=1; fi - # done - # if test -z \"$found\"; then - # ${utillinux}/sbin/swapoff \"$used\" || true - # fi - #done - - end script - "; - }]; - }; + require = [options]; + + services.extraJobs = [{ + name = "swap"; + + job = '' + start on startup + start on new-devices + + script + for device in ${toString devicesByPath}; do + ${utillinux}/sbin/swapon "$device" || true + done + + for label in ${toString devicesByLabel}; do + ${utillinux}/sbin/swapon -L "$label" || true + done + + # Remove swap devices not listed in swapDevices. + # !!! disabled because it doesn't work with labels + #for used in $(cat /proc/swaps | grep '^/' | sed 's/ .*//'); do + # found= + # for device in $ {toString swapDevices}; do + # if test "$used" = "$device"; then found=1; fi + # done + # if test -z "$found"; then + # ${utillinux}/sbin/swapoff "$used" || true + # fi + #done + + end script + ''; + }]; }