about summary refs log tree commit diff
path: root/nixos/modules/system
diff options
context:
space:
mode:
authorOliver Charles <ollie@ocharles.org.uk>2014-02-02 14:41:26 +0000
committerOliver Charles <ollie@ocharles.org.uk>2014-02-02 14:41:26 +0000
commit41775167ac69a001f40c11e2ee9576887e17b8b4 (patch)
tree61669f43df76bc6e808e8319d6276ce3fdb06cb2 /nixos/modules/system
parentf3ac3a265b5c8e3f15e76c2261c9c2500c3493ba (diff)
downloadnixlib-41775167ac69a001f40c11e2ee9576887e17b8b4.tar
nixlib-41775167ac69a001f40c11e2ee9576887e17b8b4.tar.gz
nixlib-41775167ac69a001f40c11e2ee9576887e17b8b4.tar.bz2
nixlib-41775167ac69a001f40c11e2ee9576887e17b8b4.tar.lz
nixlib-41775167ac69a001f40c11e2ee9576887e17b8b4.tar.xz
nixlib-41775167ac69a001f40c11e2ee9576887e17b8b4.tar.zst
nixlib-41775167ac69a001f40c11e2ee9576887e17b8b4.zip
switch-to-configuration.pl: Interact via DBus
Currently switch-to-configuration.pl uses system() calls to interact
with DBus. This can be error prone, especially when we are parsing
output that could change. In this commit, almost all calls to the
systemctl binary have been replaced with equivalent operations via DBus.
Diffstat (limited to 'nixos/modules/system')
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl55
-rw-r--r--nixos/modules/system/activation/top-level.nix2
2 files changed, 36 insertions, 21 deletions
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index 33ae3aef9fca..91beed1130eb 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 use File::Basename;
 use File::Slurp;
+use Net::DBus;
 use Sys::Syslog qw(:standard :macros);
 use Cwd 'abs_path';
 
@@ -59,17 +60,18 @@ syslog(LOG_NOTICE, "switching to system configuration $out");
 # virtual console 1 and we restart the "tty1" unit.
 $SIG{PIPE} = "IGNORE";
 
+my $dbus = Net::DBus->find;
+my $systemdService = $dbus->get_service('org.freedesktop.systemd1');
+my $systemdManager = $systemdService->get_object('/org/freedesktop/systemd1');
+
 sub getActiveUnits {
-    # FIXME: use D-Bus or whatever to query this, since parsing the
-    # output of list-units is likely to break.
-    my $lines = `@systemd@/bin/systemctl list-units --full`;
     my $res = {};
-    foreach my $line (split '\n', $lines) {
-        chomp $line;
-        last if $line eq "";
-        $line =~ /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s/ or next;
-        next if $1 eq "UNIT";
-        $res->{$1} = { load => $2, state => $3, substate => $4 };
+    foreach my $unit (@{ $systemdManager->ListUnits() }) {
+        $res->{$unit->[0]} = {
+            load => $unit->[2],
+            state => $unit->[3],
+            substate => $unit->[4]
+        };
     }
     return $res;
 }
@@ -277,7 +279,7 @@ foreach my $device (keys %$prevSwaps) {
 if (scalar @unitsToStop > 0) {
     @unitsToStop = unique(@unitsToStop);
     print STDERR "stopping the following units: ", join(", ", sort(@unitsToStop)), "\n";
-    system("@systemd@/bin/systemctl", "stop", "--", @unitsToStop); # FIXME: ignore errors?
+    $systemdManager->StopUnit($_, "replace") for @unitsToStop;
 }
 
 print STDERR "NOT restarting the following units: ", join(", ", sort(@unitsToSkip)), "\n"
@@ -292,21 +294,22 @@ system("$out/activate", "$out") == 0 or $res = 2;
 # Restart systemd if necessary.
 if (abs_path("/proc/1/exe") ne abs_path("@systemd@/lib/systemd/systemd")) {
     print STDERR "restarting systemd...\n";
-    system("@systemd@/bin/systemctl", "daemon-reexec") == 0 or $res = 2;
+
+    $systemdManager->Reexecute();
 }
 
 # Forget about previously failed services.
-system("@systemd@/bin/systemctl", "reset-failed");
+$systemdManager->ResetFailed();
 
-# Make systemd reload its units.
-system("@systemd@/bin/systemctl", "daemon-reload") == 0 or $res = 3;
+# Make systemd reload its units
+$systemdManager->Reload();
 
 # Restart changed services (those that have to be restarted rather
 # than stopped and started).
 my @restart = unique(split('\n', read_file($restartListFile, err_mode => 'quiet') // ""));
 if (scalar @restart > 0) {
     print STDERR "restarting the following units: ", join(", ", sort(@restart)), "\n";
-    system("@systemd@/bin/systemctl", "restart", "--", @restart) == 0 or $res = 4;
+    $systemdManager->Restart($_, "replace") for @restart;
     unlink($restartListFile);
 }
 
@@ -318,7 +321,7 @@ if (scalar @restart > 0) {
 # systemd.
 my @start = unique("default.target", "timers.target", split('\n', read_file($startListFile, err_mode => 'quiet') // ""));
 print STDERR "starting the following units: ", join(", ", sort(@start)), "\n";
-system("@systemd@/bin/systemctl", "start", "--", @start) == 0 or $res = 4;
+$systemdManager->StartUnit($_, "replace") for @start;
 unlink($startListFile);
 
 # Reload units that need it.  This includes remounting changed mount
@@ -326,19 +329,31 @@ unlink($startListFile);
 my @reload = unique(split '\n', read_file($reloadListFile, err_mode => 'quiet') // "");
 if (scalar @reload > 0) {
     print STDERR "reloading the following units: ", join(", ", sort(@reload)), "\n";
-    system("@systemd@/bin/systemctl", "reload", "--", @reload) == 0 or $res = 4;
+    $systemdManager->ReloadUnit($_, "replace") for @reload;
     unlink($reloadListFile);
 }
 
 # Signal dbus to reload its configuration.
-system("@systemd@/bin/systemctl", "reload", "dbus.service");
+$systemdManager->ReloadUnit("dbus.service", "replace");
 
 # Print failed and new units.
 my (@failed, @new, @restarting);
 my $activeNew = getActiveUnits;
 while (my ($unit, $state) = each %{$activeNew}) {
-    push @failed, $unit if $state->{state} eq "failed" || $state->{substate} eq "auto-restart";
-    push @new, $unit if $state->{state} ne "failed" && !defined $activePrev->{$unit};
+    if ($state->{state} eq "failed") {
+        push @failed, $unit;
+    }
+    elsif ($state->{state} eq "auto-restart") {
+        # A unit in auto-restart state is a failure *if* it previously failed to start
+        my $unit = $systemdManager->GetUnit($unit);
+
+        if ($unit->ExecMainStatus ne '0') {
+            push @failed, $unit;
+        }
+    }
+    elsif ($state->{state} ne "failed" && !defined $activePrev->{$unit}) {
+        push @new, $unit;
+    }
 }
 
 print STDERR "the following new units were started: ", join(", ", sort(@new)), "\n"
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index d9891f434cc8..30a529988a96 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -108,7 +108,7 @@ let
     configurationName = config.boot.loader.grub.configurationName;
 
     # Needed by switch-to-configuration.
-    perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
+    perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.XMLTwig}/lib/perl5/site_perl -I${pkgs.perlPackages.XMLParser}/lib/perl5/site_perl -I${pkgs.perlPackages.NetDBus}/lib/perl5/site_perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
   };