Unverified Commit 85c1c30f authored by Janne Heß's avatar Janne Heß
Browse files

nixos/switch-to-configuration: Never unmount / or /nix

Also adds a huge test for fstab handling
parent c3e64122
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -21,8 +21,9 @@ If the action is `switch` or `test`, the currently running system is inspected
and the actions to switch to the new system are calculated. This process takes
two data sources into account: `/etc/fstab` and the current systemd status.
Mounts and swaps are read from `/etc/fstab` and the corresponding actions are
generated. If a new mount is added, for example, the proper `.mount` unit is
marked to be started. The current systemd state is inspected, the difference
generated. If the options of a mount are modified, for example, the proper `.mount`
unit is reloaded (or restarted if anything else changed and it's neither the root
mount or the nix store). The current systemd state is inspected, the difference
between the current system and the desired configuration is calculated and
actions are generated to get to this state. There are a lot of nuances that can
be controlled by the units which are explained here.
+14 −4
Original line number Diff line number Diff line
@@ -661,10 +661,20 @@ foreach my $mount_point (keys(%{$cur_fss})) {
        # Filesystem entry disappeared, so unmount it.
        $units_to_stop{$unit} = 1;
    } elsif ($cur->{fsType} ne $new->{fsType} || $cur->{device} ne $new->{device}) {
        if ($mount_point eq '/' or $mount_point eq '/nix') {
            if ($cur->{options} ne $new->{options}) {
                # Mount options changed, so remount it.
                $units_to_reload{$unit} = 1;
                record_unit($reload_list_file, $unit);
            } else {
                # Don't unmount / or /nix if the device changed
                $units_to_skip{$unit} = 1;
            }
        } else {
            # Filesystem type or device changed, so unmount and mount it.
        $units_to_stop{$unit} = 1;
        $units_to_start{$unit} = 1;
        record_unit($start_list_file, $unit);
            $units_to_restart{$unit} = 1;
            record_unit($restart_list_file, $unit);
        }
    } elsif ($cur->{options} ne $new->{options}) {
        # Mount options changes, so remount it.
        $units_to_reload{$unit} = 1;
+69 −0
Original line number Diff line number Diff line
@@ -66,6 +66,25 @@ in {
          # Hello world!
        '';

        addedMount.configuration.virtualisation.fileSystems."/test" = {
          device = "tmpfs";
          fsType = "tmpfs";
        };

        addedMountOptsModified.configuration = {
          imports = [ addedMount.configuration ];
          virtualisation.fileSystems."/test".options = [ "x-test" ];
        };

        addedMountDevModified.configuration = {
          imports = [ addedMountOptsModified.configuration ];
          virtualisation.fileSystems."/test".device = lib.mkForce "ramfs";
        };

        storeMountModified.configuration = {
          virtualisation.fileSystems."/".device = lib.mkForce "auto";
        };

        simpleService.configuration = {
          systemd.services.test = {
            wantedBy = [ "multi-user.target" ];
@@ -672,6 +691,56 @@ in {
        out = switch_to_specialisation("${machine}", "modifiedSystemConf")
        assert_contains(out, "starting the following units: dbus.service\n")

    with subtest("fstab mounts"):
        switch_to_specialisation("${machine}", "")
        # add a mountpoint
        out = switch_to_specialisation("${machine}", "addedMount")
        assert_lacks(out, "stopping the following units:")
        assert_lacks(out, "NOT restarting the following changed units:")
        assert_lacks(out, "\nrestarting the following units:")
        assert_lacks(out, "\nstarting the following units:")
        assert_contains(out, "the following new units were started: test.mount\n")
        # modify the mountpoint's options
        out = switch_to_specialisation("${machine}", "addedMountOptsModified")
        assert_lacks(out, "stopping the following units:")
        assert_lacks(out, "NOT restarting the following changed units:")
        assert_contains(out, "reloading the following units: test.mount\n")
        assert_lacks(out, "\nrestarting the following units:")
        assert_lacks(out, "\nstarting the following units:")
        assert_lacks(out, "the following new units were started:")
        # modify the device
        out = switch_to_specialisation("${machine}", "addedMountDevModified")
        assert_lacks(out, "stopping the following units:")
        assert_lacks(out, "NOT restarting the following changed units:")
        assert_lacks(out, "reloading the following units:")
        assert_contains(out, "\nrestarting the following units: test.mount\n")
        assert_lacks(out, "\nstarting the following units:")
        assert_lacks(out, "the following new units were started:")
        # modify both
        out = switch_to_specialisation("${machine}", "addedMount")
        assert_lacks(out, "stopping the following units:")
        assert_lacks(out, "NOT restarting the following changed units:")
        assert_lacks(out, "reloading the following units:")
        assert_contains(out, "\nrestarting the following units: test.mount\n")
        assert_lacks(out, "\nstarting the following units:")
        assert_lacks(out, "the following new units were started:")
        # remove the mount
        out = switch_to_specialisation("${machine}", "")
        assert_contains(out, "stopping the following units: test.mount\n")
        assert_lacks(out, "NOT restarting the following changed units:")
        assert_contains(out, "reloading the following units: dbus.service\n")
        assert_lacks(out, "\nrestarting the following units:")
        assert_lacks(out, "\nstarting the following units:")
        assert_lacks(out, "the following new units were started:")
        # change something about the / mount
        out = switch_to_specialisation("${machine}", "storeMountModified")
        assert_lacks(out, "stopping the following units:")
        assert_contains(out, "NOT restarting the following changed units: -.mount")
        assert_contains(out, "reloading the following units: dbus.service\n")
        assert_lacks(out, "\nrestarting the following units:")
        assert_lacks(out, "\nstarting the following units:")
        assert_lacks(out, "the following new units were started:")

    with subtest("services"):
        switch_to_specialisation("${machine}", "")
        # Nothing happens when nothing is changed