commit 3e43e432cea1a7eafa5592752ca62906278ed9a5
Author: Marc Weber <marco-oweber@gmx.de>
Date:   Thu Jun 2 04:38:10 2011 +0200

    nix2/job-switch-actions
    
    Some jobs should not be restarted even if their derivation changes.
    
    The declaration which jobs should not be started, stopped or restarted on
    nixos-switch is now a job option.
    
    The most famous example is X, you don't want to restart X just because its
    derivation changed. All clients would be killed.
    
    Second (new) example: All samba jobs are not restarted by switch cause upstart
    should do so.
    
    Signed-off-by: Marc Weber <marco-oweber@gmx.de>

diff --git a/modules/services/misc/disnix.nix b/modules/services/misc/disnix.nix
index d0ef5d3..7985651 100644
--- a/modules/services/misc/disnix.nix
+++ b/modules/services/misc/disnix.nix
@@ -107,6 +107,8 @@ in
       disnix =
         { description = "Disnix server";
 
+          switchActions = ["start" "stop"]; # why ?
+
           startOn = "started dbus"
 	  + optionalString config.services.httpd.enable " and started httpd"
 	  + optionalString config.services.mysql.enable " and started mysql"
diff --git a/modules/services/network-filesystems/samba.nix b/modules/services/network-filesystems/samba.nix
index e42316b..881c792 100644
--- a/modules/services/network-filesystems/samba.nix
+++ b/modules/services/network-filesystems/samba.nix
@@ -62,10 +62,12 @@ let
   # This may include nss_ldap, needed for samba if it has to use ldap.
   nssModulesPath = config.system.nssModules.path;
 
-  daemonJob = appName: args:
+  daemonJob = appName:
     { name = "samba-${appName}";
       description = "Samba Service daemon ${appName}";
 
+      switchActions = []; # they are controlled by job "samba"
+
       startOn = "started samba";
       stopOn = "stopping samba";
 
@@ -75,9 +77,7 @@ let
         LOCALE_ARCHIVE = "/var/run/current-system/sw/lib/locale/locale-archive";
       };
   
-      daemonType = "fork";
-
-      exec = "${samba}/sbin/${appName} ${args}";
+      exec = "${samba}/sbin/${appName} --no-process-group -F";
     };
 
 in
@@ -156,23 +156,23 @@ in
 
       defaultShare = {
         enable = mkOption {
-	  description = "Whether to share /home/smbd as 'default'.";
-	  default = false;
-	};
+          description = "Whether to share /home/smbd as 'default'.";
+          default = false;
+        };
         writeable = mkOption {
-	  description = "Whether to allow write access to default share.";
-	  default = false;
-	};
+          description = "Whether to allow write access to default share.";
+          default = false;
+        };
         guest = mkOption {
-	  description = "Whether to allow guest access to default share.";
-	  default = true;
-	};
+          description = "Whether to allow guest access to default share.";
+          default = true;
+        };
       };
 
       securityType = mkOption {
         description = "Samba security type";
-	default = "user";
-	example = "share";
+        default = "user";
+        example = "share";
       };
 
     };
@@ -213,11 +213,11 @@ in
         preStart = setupScript;
       };
 
-    jobs.nmbd = daemonJob "nmbd" "-D";
+    jobs.nmbd = daemonJob "nmbd";
 
-    jobs.smbd = daemonJob "smbd" "-D";
+    jobs.smbd = daemonJob "smbd";
 
-    jobs.winbindd = daemonJob "winbindd" "-D";
+    jobs.winbindd = daemonJob "winbindd";
 
   };
   
diff --git a/modules/services/system/dbus.nix b/modules/services/system/dbus.nix
index e083707..78d9b0e 100644
--- a/modules/services/system/dbus.nix
+++ b/modules/services/system/dbus.nix
@@ -120,6 +120,10 @@ in
     jobs.dbus =
       { startOn = "started udev and started syslogd";
 
+        # don't restart dbus, since that causes ConsoleKit to
+        # forget about current sessions.
+        switchActions = ["start" "stop"];
+
         preStart =
           ''
             mkdir -m 0755 -p ${homeDir}
diff --git a/modules/services/x11/xserver.nix b/modules/services/x11/xserver.nix
index 0eb19fc..b5da0bf 100644
--- a/modules/services/x11/xserver.nix
+++ b/modules/services/x11/xserver.nix
@@ -387,6 +387,8 @@ in
     jobs.xserver =
       { startOn = if cfg.autorun then "filesystem and stopped udevtrigger and started hal" else "";
  
+        switchActions = [ "start" ];
+
         environment =
           { FONTCONFIG_FILE = "/etc/fonts/fonts.conf"; # !!! cleanup
             XKB_BINDIR = "${xorg.xkbcomp}/bin"; # Needed for the Xkb extension.
diff --git a/modules/system/activation/switch-to-configuration.sh b/modules/system/activation/switch-to-configuration.sh
index 3249ee3..39d1057 100644
--- a/modules/system/activation/switch-to-configuration.sh
+++ b/modules/system/activation/switch-to-configuration.sh
@@ -81,11 +81,18 @@ EOF
         initctl stop "$job" || true
     }
 
+    switchActionAllowed(){
+      file=$1
+      action=$2
+      # \b is word boundary
+      grep -q -e "# switch actions: .*\\b$2\\b" "$1" 
+    }
+
     # Stop all services that are not in the new Upstart
     # configuration.
     for job in $(cd $oldJobs && ls *.conf); do
         job=$(basename $job .conf)
-        if ! test -e "$newJobs/$job.conf"; then
+        if ! test -e "$newJobs/$job.conf" && switchActionAllowed $oldJobs/$job.conf "stop"; then
             echo "stopping $job..."
             stopJob $job
         fi
@@ -104,22 +111,16 @@ EOF
 
         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).
-        # And don't restart dbus, since that causes ConsoleKit to
-        # forget about current sessions.
-        # Idem for the emergeny-shell, because its `console owner'
-        # line screws up the X server.
-        # Idem for xendomains because we don't want to save/restore
-	# Xen domains unless we have to.
-        # TODO: Jobs should be able to declare that they should not be
-	# auto-restarted.
-        if echo "$job" | grep -q "^shutdown$\|^control-alt-delete$\|^xserver$\|^dbus$\|^disnix$\|^emergency-shell$\|^xendomains$"; then continue; fi
-
+        # continue if job should not be restarted
         if ! test -e "$oldJobs/$job.conf"; then
+            switchActionAllowed $newJobs/$job.conf "start" || continue
             echo "starting $job..."
             initctl start "$job" || true
         elif test "$(readlink "$oldJobs/$job.conf")" != "$(readlink "$newJobs/$job.conf")"; then
+
+            switchActionAllowed $oldJobs/$job.conf "restart" || continue
+            switchActionAllowed $newJobs/$job.conf "restart" || continue
+
             echo "restarting $job..."
             stopJob $job
             initctl start "$job" || true
diff --git a/modules/system/upstart-events/control-alt-delete.nix b/modules/system/upstart-events/control-alt-delete.nix
index f0f1461..1f8f06f 100644
--- a/modules/system/upstart-events/control-alt-delete.nix
+++ b/modules/system/upstart-events/control-alt-delete.nix
@@ -6,6 +6,8 @@
   jobs.control_alt_delete =
     { name = "control-alt-delete";
 
+      switchActions = [];
+
       startOn = "control-alt-delete";
 
       task = true;
diff --git a/modules/system/upstart-events/shutdown.nix b/modules/system/upstart-events/shutdown.nix
index 85ad601..78c6e9c 100644
--- a/modules/system/upstart-events/shutdown.nix
+++ b/modules/system/upstart-events/shutdown.nix
@@ -7,6 +7,8 @@ with pkgs.lib;
   jobs.shutdown =
     { name = "shutdown";
 
+      switchActions = [];
+
       task = true;
 
       stopOn = ""; # must override the default ("starting shutdown")
diff --git a/modules/system/upstart/upstart.nix b/modules/system/upstart/upstart.nix
index 7373bed..b798666 100644
--- a/modules/system/upstart/upstart.nix
+++ b/modules/system/upstart/upstart.nix
@@ -29,6 +29,8 @@ let
         let log = "/var/log/upstart/${job.name}"; in
         ''
           # Upstart job `${job.name}'.  This is a generated file.  Do not edit.
+          # switch actions: ${concatStringsSep "," (maybeAttr "switchActions" ["start" "restart" "stop"] job) }
+          # ^ this comment line is read by switch-to-configuration.sh
         
           description "${job.description}"
 
@@ -165,6 +167,15 @@ let
       '';
     };
 
+    switchActions = mkOption {
+      default = ["start" "stop" "restart"];
+      description = ''
+        list of actions which may be run by switch-to-configuration.sh.
+        Eg xserver should never be restarted or stopped - because this would
+        kill all clients.
+      '';
+    };
+
     preStart = mkOption {
       type = types.string;
       default = "";
diff --git a/modules/tasks/filesystems.nix b/modules/tasks/filesystems.nix
index 699e9b3..02ba77f 100644
--- a/modules/tasks/filesystems.nix
+++ b/modules/tasks/filesystems.nix
@@ -210,6 +210,8 @@ in
     jobs.emergency_shell =
       { name = "emergency-shell";
 
+        switchActions = []; # cause its `console owner' line screws up X (?), don't restart
+
         task = true;
 
         extraConfig = "console owner";
diff --git a/modules/virtualisation/xen-dom0.nix b/modules/virtualisation/xen-dom0.nix
index cb71f41..6c11044 100644
--- a/modules/virtualisation/xen-dom0.nix
+++ b/modules/virtualisation/xen-dom0.nix
@@ -136,6 +136,11 @@ in
     jobs.xendomains =
       { description = "Automatically starts, saves and restores Xen domains on startup/shutdown";
 
+        # don't restart because we don't want
+        # to save/restore Xen domains unless we have to.
+        switchActions = ["start" "stop"]; 
+
+
         startOn = "started xend";
 
         stopOn = "starting shutdown and stopping xend";
