Add kexec support

You can now do a fast reboot (bypassing the BIOS, which may take
several minutes on servers) by running ‘systemctl kexec’.

Unfortunately the QEMU test for this is unreliable due to a QEMU bug
(it randomly crashes with a message like ‘Guest moved used index from
8 to 0’), so it's commented out.
This commit is contained in:
Eelco Dolstra 2013-09-16 17:15:42 +02:00
parent 5332480454
commit b825169404
7 changed files with 63 additions and 5 deletions

View File

@ -101,9 +101,25 @@ doing:
$ shutdown $ shutdown
</screen> </screen>
This is equivalent to running <command>systemctl poweroff</command>. This is equivalent to running <command>systemctl
Likewise, <command>reboot</command> (a.k.a. <command>systemctl poweroff</command>.</para>
reboot</command>) will reboot the system.</para>
<para>To reboot the system, run
<screen>
$ reboot
</screen>
which is equivalent to <command>systemctl reboot</command>.
Alternatively, you can quickly reboot the system using
<literal>kexec</literal>, which bypasses the BIOS by directly loading
the new kernel into memory:
<screen>
$ systemctl kexec
</screen>
</para>
<para>The machine can be suspended to RAM (if supported) using <para>The machine can be suspended to RAM (if supported) using
<command>systemctl suspend</command>, and suspended to disk using <command>systemctl suspend</command>, and suspended to disk using

View File

@ -232,9 +232,9 @@ sub connect {
$self->start; $self->start;
local $SIG{ALRM} = sub { die "timed out waiting for the guest to connect\n"; }; local $SIG{ALRM} = sub { die "timed out waiting for the VM to connect\n"; };
alarm 300; alarm 300;
readline $self->{socket} or die; readline $self->{socket} or die "the VM quit before connecting\n";
alarm 0; alarm 0;
$self->log("connected to guest root shell"); $self->log("connected to guest root shell");

View File

@ -235,6 +235,7 @@
./system/activation/activation-script.nix ./system/activation/activation-script.nix
./system/activation/top-level.nix ./system/activation/top-level.nix
./system/boot/kernel.nix ./system/boot/kernel.nix
./system/boot/kexec.nix
./system/boot/loader/efi-boot-stub/efi-boot-stub.nix ./system/boot/loader/efi-boot-stub/efi-boot-stub.nix
./system/boot/loader/efi.nix ./system/boot/loader/efi.nix
./system/boot/loader/generations-dir/generations-dir.nix ./system/boot/loader/generations-dir/generations-dir.nix

View File

@ -0,0 +1,21 @@
{ config, pkgs, ... }:
{
environment.systemPackages = [ pkgs.kexectools ];
systemd.services."prepare-kexec" =
{ description = "Preparation for kexec";
wantedBy = [ "kexec.target" ];
before = [ "systemd-kexec.service" ];
unitConfig.DefaultDependencies = false;
serviceConfig.Type = "oneshot";
path = [ pkgs.kexectools ];
script =
''
p=$(readlink -f /nix/var/nix/profiles/system)
if ! [ -d $p ]; then exit 1; fi
exec kexec --load $p/kernel --initrd=$p/initrd --append="$(cat $p/kernel-params) init=$p/init"
'';
};
}

View File

@ -129,6 +129,7 @@ let
"umount.target" "umount.target"
"final.target" "final.target"
"kexec.target" "kexec.target"
"systemd-kexec.service"
# Password entry. # Password entry.
"systemd-ask-password-console.path" "systemd-ask-password-console.path"

View File

@ -10,6 +10,7 @@ with import ../lib/testing.nix { inherit system minimal; };
installer = makeTests (import ./installer.nix); installer = makeTests (import ./installer.nix);
ipv6 = makeTest (import ./ipv6.nix); ipv6 = makeTest (import ./ipv6.nix);
kde4 = makeTest (import ./kde4.nix); kde4 = makeTest (import ./kde4.nix);
#kexec = makeTest (import ./kexec.nix);
login = makeTest (import ./login.nix {}); login = makeTest (import ./login.nix {});
latestKernel.login = makeTest (import ./login.nix ({ config, pkgs, ... }: { boot.kernelPackages = pkgs.linuxPackages_latest; })); latestKernel.login = makeTest (import ./login.nix ({ config, pkgs, ... }: { boot.kernelPackages = pkgs.linuxPackages_latest; }));
misc = makeTest (import ./misc.nix); misc = makeTest (import ./misc.nix);

18
tests/kexec.nix Normal file
View File

@ -0,0 +1,18 @@
# Test whether fast reboots via kexec work.
{ pkgs, ... }:
{
machine = { config, pkgs, ... }:
{ virtualisation.vlans = [ ]; };
testScript =
''
$machine->waitForUnit("multi-user.target");
$machine->execute("systemctl kexec &");
$machine->{connected} = 0;
$machine->waitForUnit("multi-user.target");
'';
}