mirror of
https://git.proxmox.com/git/pve-common
synced 2025-07-27 06:34:02 +00:00
add PVE::SystemD module
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
5a94ed9d9e
commit
f024a872c4
@ -29,6 +29,7 @@ LIB_SOURCES = \
|
||||
SectionConfig.pm \
|
||||
Subscription.pm \
|
||||
Syscall.pm \
|
||||
SystemD.pm \
|
||||
Ticket.pm \
|
||||
Tools.pm
|
||||
|
||||
|
81
src/PVE/SystemD.pm
Normal file
81
src/PVE/SystemD.pm
Normal file
@ -0,0 +1,81 @@
|
||||
package PVE::SystemD;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Net::DBus qw(dbus_uint32 dbus_uint64);
|
||||
use Net::DBus::Callback;
|
||||
use Net::DBus::Reactor;
|
||||
|
||||
# NOTE: This calls the dbus main loop and must not be used when another dbus
|
||||
# main loop is being used as we need to wait for the JobRemoved signal.
|
||||
# Polling the job status instead doesn't work because this doesn't give us the
|
||||
# distinction between success and failure.
|
||||
#
|
||||
# Note that the description is mandatory for security reasons.
|
||||
sub enter_systemd_scope {
|
||||
my ($unit, $description, %extra) = @_;
|
||||
die "missing description\n" if !defined($description);
|
||||
|
||||
my $timeout = delete $extra{timeout};
|
||||
|
||||
$unit .= '.scope';
|
||||
my $properties = [ [PIDs => [dbus_uint32($$)]] ];
|
||||
|
||||
foreach my $key (keys %extra) {
|
||||
if ($key eq 'Slice' || $key eq 'KillMode') {
|
||||
push @{$properties}, [$key, $extra{$key}];
|
||||
} elsif ($key eq 'CPUShares') {
|
||||
push @{$properties}, [$key, dbus_uint64($extra{$key})];
|
||||
} elsif ($key eq 'CPUQuota') {
|
||||
push @{$properties}, ['CPUQuotaPerSecUSec',
|
||||
dbus_uint64($extra{$key} * 10_000)];
|
||||
} else {
|
||||
die "Don't know how to encode $key for systemd scope\n";
|
||||
}
|
||||
}
|
||||
|
||||
my $job;
|
||||
my $done = 0;
|
||||
|
||||
my $bus = Net::DBus->system();
|
||||
my $reactor = Net::DBus::Reactor->main();
|
||||
|
||||
my $service = $bus->get_service('org.freedesktop.systemd1');
|
||||
my $if = $service->get_object('/org/freedesktop/systemd1', 'org.freedesktop.systemd1.Manager');
|
||||
# Connect to the JobRemoved signal since we want to wait for it to finish
|
||||
my $sigid;
|
||||
my $timer;
|
||||
my $cleanup = sub {
|
||||
my ($no_shutdown) = @_;
|
||||
$if->disconnect_from_signal('JobRemoved', $sigid) if defined($if);
|
||||
$if = undef;
|
||||
$sigid = undef;
|
||||
$reactor->remove_timeout($timer) if defined($timer);
|
||||
$timer = undef;
|
||||
return if $no_shutdown;
|
||||
$reactor->shutdown();
|
||||
};
|
||||
|
||||
$sigid = $if->connect_to_signal('JobRemoved', sub {
|
||||
my ($id, $removed_job, $signaled_unit, $result) = @_;
|
||||
return if $signaled_unit ne $unit || $removed_job ne $job;
|
||||
$cleanup->(0);
|
||||
die "systemd job failed\n" if $result ne 'done';
|
||||
$done = 1;
|
||||
});
|
||||
|
||||
my $on_timeout = sub {
|
||||
$cleanup->(0);
|
||||
die "systemd job timed out\n";
|
||||
};
|
||||
|
||||
$timer = $reactor->add_timeout($timeout * 1000, Net::DBus::Callback->new(method => $on_timeout))
|
||||
if defined($timeout);
|
||||
$job = $if->StartTransientUnit($unit, 'fail', $properties, []);
|
||||
$reactor->run();
|
||||
$cleanup->(1);
|
||||
die "systemd job never completed\n" if !$done;
|
||||
}
|
||||
|
||||
1;
|
@ -24,9 +24,6 @@ use JSON;
|
||||
use Text::ParseWords;
|
||||
use String::ShellQuote;
|
||||
use Time::HiRes qw(usleep gettimeofday tv_interval alarm);
|
||||
use Net::DBus qw(dbus_uint32 dbus_uint64);
|
||||
use Net::DBus::Callback;
|
||||
use Net::DBus::Reactor;
|
||||
use Scalar::Util 'weaken';
|
||||
use PVE::Syscall;
|
||||
|
||||
@ -1544,77 +1541,6 @@ sub mkdirat($$$) {
|
||||
return syscall(PVE::Syscall::mkdirat, $dirfd, $name, $mode) == 0;
|
||||
}
|
||||
|
||||
# NOTE: This calls the dbus main loop and must not be used when another dbus
|
||||
# main loop is being used as we need to wait for the JobRemoved signal.
|
||||
# Polling the job status instead doesn't work because this doesn't give us the
|
||||
# distinction between success and failure.
|
||||
#
|
||||
# Note that the description is mandatory for security reasons.
|
||||
sub enter_systemd_scope {
|
||||
my ($unit, $description, %extra) = @_;
|
||||
die "missing description\n" if !defined($description);
|
||||
|
||||
my $timeout = delete $extra{timeout};
|
||||
|
||||
$unit .= '.scope';
|
||||
my $properties = [ [PIDs => [dbus_uint32($$)]] ];
|
||||
|
||||
foreach my $key (keys %extra) {
|
||||
if ($key eq 'Slice' || $key eq 'KillMode') {
|
||||
push @$properties, [$key, $extra{$key}];
|
||||
} elsif ($key eq 'CPUShares') {
|
||||
push @$properties, [$key, dbus_uint64($extra{$key})];
|
||||
} elsif ($key eq 'CPUQuota') {
|
||||
push @$properties, ['CPUQuotaPerSecUSec',
|
||||
dbus_uint64($extra{$key} * 10000)];
|
||||
} else {
|
||||
die "Don't know how to encode $key for systemd scope\n";
|
||||
}
|
||||
}
|
||||
|
||||
my $job;
|
||||
my $done = 0;
|
||||
|
||||
my $bus = Net::DBus->system();
|
||||
my $reactor = Net::DBus::Reactor->main();
|
||||
|
||||
my $service = $bus->get_service('org.freedesktop.systemd1');
|
||||
my $if = $service->get_object('/org/freedesktop/systemd1', 'org.freedesktop.systemd1.Manager');
|
||||
# Connect to the JobRemoved signal since we want to wait for it to finish
|
||||
my $sigid;
|
||||
my $timer;
|
||||
my $cleanup = sub {
|
||||
my ($no_shutdown) = @_;
|
||||
$if->disconnect_from_signal('JobRemoved', $sigid) if defined($if);
|
||||
$if = undef;
|
||||
$sigid = undef;
|
||||
$reactor->remove_timeout($timer) if defined($timer);
|
||||
$timer = undef;
|
||||
return if $no_shutdown;
|
||||
$reactor->shutdown();
|
||||
};
|
||||
|
||||
$sigid = $if->connect_to_signal('JobRemoved', sub {
|
||||
my ($id, $removed_job, $signaled_unit, $result) = @_;
|
||||
return if $signaled_unit ne $unit || $removed_job ne $job;
|
||||
$cleanup->(0);
|
||||
die "systemd job failed\n" if $result ne 'done';
|
||||
$done = 1;
|
||||
});
|
||||
|
||||
my $on_timeout = sub {
|
||||
$cleanup->(0);
|
||||
die "systemd job timed out\n";
|
||||
};
|
||||
|
||||
$timer = $reactor->add_timeout($timeout * 1000, Net::DBus::Callback->new(method => $on_timeout))
|
||||
if defined($timeout);
|
||||
$job = $if->StartTransientUnit($unit, 'fail', $properties, []);
|
||||
$reactor->run();
|
||||
$cleanup->(1);
|
||||
die "systemd job never completed\n" if !$done;
|
||||
}
|
||||
|
||||
my $salt_starter = time();
|
||||
|
||||
sub encrypt_pw {
|
||||
|
Loading…
Reference in New Issue
Block a user