]>
git.proxmox.com Git - pve-common.git/blob - src/PVE/Systemd.pm
6 use Net
::DBus
qw(dbus_uint32 dbus_uint64);
7 use Net
::DBus
::Callback
;
8 use Net
::DBus
::Reactor
;
10 # NOTE: This calls the dbus main loop and must not be used when another dbus
11 # main loop is being used as we need to wait for the JobRemoved signal.
12 # Polling the job status instead doesn't work because this doesn't give us the
13 # distinction between success and failure.
15 # Note that the description is mandatory for security reasons.
16 sub enter_systemd_scope
{
17 my ($unit, $description, %extra) = @_;
18 die "missing description\n" if !defined($description);
20 my $timeout = delete $extra{timeout
};
23 my $properties = [ [PIDs
=> [dbus_uint32
($$)]] ];
25 foreach my $key (keys %extra) {
26 if ($key eq 'Slice' || $key eq 'KillMode') {
27 push @{$properties}, [$key, $extra{$key}];
28 } elsif ($key eq 'CPUShares') {
29 push @{$properties}, [$key, dbus_uint64
($extra{$key})];
30 } elsif ($key eq 'CPUQuota') {
31 push @{$properties}, ['CPUQuotaPerSecUSec',
32 dbus_uint64
($extra{$key} * 10_000)];
34 die "Don't know how to encode $key for systemd scope\n";
41 my $bus = Net
::DBus-
>system();
42 my $reactor = Net
::DBus
::Reactor-
>main();
44 my $service = $bus->get_service('org.freedesktop.systemd1');
45 my $if = $service->get_object('/org/freedesktop/systemd1', 'org.freedesktop.systemd1.Manager');
46 # Connect to the JobRemoved signal since we want to wait for it to finish
50 my ($no_shutdown) = @_;
51 $if->disconnect_from_signal('JobRemoved', $sigid) if defined($if);
54 $reactor->remove_timeout($timer) if defined($timer);
56 return if $no_shutdown;
60 $sigid = $if->connect_to_signal('JobRemoved', sub {
61 my ($id, $removed_job, $signaled_unit, $result) = @_;
62 return if $signaled_unit ne $unit || $removed_job ne $job;
64 die "systemd job failed\n" if $result ne 'done';
68 my $on_timeout = sub {
70 die "systemd job timed out\n";
73 $timer = $reactor->add_timeout($timeout * 1000, Net
::DBus
::Callback-
>new(method => $on_timeout))
75 $job = $if->StartTransientUnit($unit, 'fail', $properties, []);
78 die "systemd job never completed\n" if !$done;