[pve-devel] r5707 - in pve-access-control/trunk: . PVE
svn-commits at proxmox.com
svn-commits at proxmox.com
Wed Mar 16 13:22:44 CET 2011
Author: dietmar
Date: 2011-03-16 13:22:44 +0100 (Wed, 16 Mar 2011)
New Revision: 5707
Modified:
pve-access-control/trunk/ChangeLog
pve-access-control/trunk/PVE/RPCEnvironment.pm
Log:
add code to simulate running in foreground (cli).
Modified: pve-access-control/trunk/ChangeLog
===================================================================
--- pve-access-control/trunk/ChangeLog 2011-03-16 12:19:42 UTC (rev 5706)
+++ pve-access-control/trunk/ChangeLog 2011-03-16 12:22:44 UTC (rev 5707)
@@ -1,3 +1,8 @@
+2011-03-16 Proxmox Support Team <support at proxmox.com>
+
+ * PVE/RPCEnvironment.pm (fork_worker): add code to simulate running
+ in foreground (cli).
+
2011-02-24 Proxmox Support Team <support at proxmox.com>
* PVE/AccessControl.pm (roles): fix group permission propagation
Modified: pve-access-control/trunk/PVE/RPCEnvironment.pm
===================================================================
--- pve-access-control/trunk/PVE/RPCEnvironment.pm 2011-03-16 12:19:42 UTC (rev 5706)
+++ pve-access-control/trunk/PVE/RPCEnvironment.pm 2011-03-16 12:22:44 UTC (rev 5707)
@@ -26,18 +26,37 @@
my $WORKER_PIDS;
+my $log_task_result = sub {
+ my ($upid, $user, $status) = @_;
+
+ my $msg = 'successful';
+ my $pri = 'info';
+ if ($status != 0) {
+ my $ec = $status >> 8;
+ my $ic = $status & 255;
+ $msg = $ec ? "failed ($ec)" : "interrupted ($ic)";
+ $pri = 'err';
+ }
+ PVE::Tools::upid_set_inactive($upid);
+ PVE::Cluster::log_msg($pri, $user, "end task $upid $msg");
+};
+
my $worker_reaper = sub {
local $!; local $?;
foreach my $pid (keys %$WORKER_PIDS) {
my $waitpid = waitpid ($pid, WNOHANG);
if (defined($waitpid) && ($waitpid == $pid)) {
+ my $info = $WORKER_PIDS->{$pid};
+ if ($info && $info->{upid} && $info->{user}) {
+ &$log_task_result($info->{upid}, $info->{user}, $?);
+ }
delete ($WORKER_PIDS->{$pid});
}
}
};
my $register_worker = sub {
- my $pid = shift;
+ my ($pid, $user, $upid) = @_;
return if !$pid;
@@ -48,7 +67,10 @@
return;
}
- $WORKER_PIDS->{$pid} = 1;
+ $WORKER_PIDS->{$pid} = {
+ user => $user,
+ upid => $upid,
+ };
};
# ACL cache
@@ -268,21 +290,31 @@
return $self->{user};
}
-
# start long running workers
# STDIN is redirected to /dev/null
# STDOUT,STDERR are redirected to the filename returned by upid_decode
-
+# NOTE: we simulate running in foreground if ($self->{type} eq 'cli')
sub fork_worker {
- my ($self, $dtype, $data, $function) = @_;
+ my ($self, $dtype, $user, $function) = @_;
$dtype = 'unknown' if !defined ($dtype);
- $data = '' if !defined ($data);
+ $user = 'root at pve' if !defined ($user);
+ my $sync = $self->{type} eq 'cli' ? 1 : 0;
+
+ local $SIG{INT} =
+ local $SIG{QUIT} =
+ local $SIG{PIPE} =
+ local $SIG{TERM} = 'IGNORE';
+
+ my $wwwid = getpwnam('www-data') ||
+ die "getpwnam failed";
+
my $starttime = time ();
my @psync = POSIX::pipe();
+ my @csync = POSIX::pipe();
my $node = $self->{nodename};
@@ -296,10 +328,14 @@
my $upid = PVE::Tools::upid_encode ({
node => $node, pid => $workerpuid, pstart => $pstart,
- starttime => $starttime, type => $dtype, data => $data });
+ starttime => $starttime, type => $dtype, user => $user });
- if ($cpid == 0) {
+ my $outfh;
+ if (!$cpid) { # child
+
+ $0 = "task $upid";
+
$SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { die "received interrupt\n"; };
$SIG{CHLD} = $SIG{PIPE} = 'DEFAULT';
@@ -309,8 +345,9 @@
POSIX::setsid();
POSIX::close ($psync[0]);
+ POSIX::close ($csync[1]);
- my $outfh;
+ $outfh = $sync ? $psync[1] : undef;
eval {
PVE::INotify::inotify_close();
@@ -320,7 +357,6 @@
}
# same algorythm as used inside SA
-
# STDIN = /dev/null
my $fd = fileno (STDIN);
close STDIN;
@@ -329,20 +365,13 @@
die "unable to redirect STDIN - $!"
if !open(STDIN, "</dev/null");
+ $outfh = PVE::Tools::upid_open($upid, $wwwid) if !$sync;
+
# redirect STDOUT
$fd = fileno(STDOUT);
close STDOUT;
POSIX::close (1) if $fd != 1;
- my $tmp = PVE::Tools::upid_decode($upid);
- my $filename = $tmp->{filename};
-
- $outfh = IO::File->new ($filename, O_WRONLY|O_CREAT|O_EXCL) ||
- die "unable to open output file - $!\n";
-
- my $wwwid = getpwnam('www-data');
- chown $wwwid, $outfh;
-
die "unable to redirect STDOUT - $!"
if !open(STDOUT, ">&", $outfh);
@@ -360,51 +389,142 @@
};
if (my $err = $@) {
my $msg = "ERROR: $err";
- print STDERR "$msg\n";
- STDERR->flush();
POSIX::write($psync[1], $msg, length ($msg));
POSIX::close($psync[1]);
POSIX::_exit(1);
kill('KILL', $$);
}
- # sync with parent
- POSIX::write($psync[1], $upid, length ($upid));
- POSIX::close($psync[1]);
+ # sync with parent (signal that we are read)
+ if ($sync) {
+ print "$upid\n";
+ } else {
+ POSIX::write($psync[1], $upid, length ($upid));
+ POSIX::close($psync[1]);
+ }
+ my $readbuf = '';
+ # sync with parent (wait until parent is ready)
+ POSIX::read($csync[0], $readbuf, 4096);
+ die "parent setup error\n" if $readbuf ne 'OK';
+
eval { &$function($upid); };
my $err = $@;
if ($err) {
- my $msg = "worker function failed: $err";
- syslog('err', $msg);
- print STDERR "$msg\n";
+ chomp $err;
+ $err =~ s/\n/ /mg;
+ syslog('err', $err);
+ print STDERR "TASK ERROR: $err\n";
POSIX::_exit(-1);
} else {
+ print STDERR "TASK OK\n";
POSIX::_exit (0);
}
kill('KILL', $$);
}
+ # parent
+
POSIX::close ($psync[1]);
+ POSIX::close ($csync[0]);
+ my $readbuf = '';
# sync with child (wait until child starts)
- my $readbuf = '';
POSIX::read($psync[0], $readbuf, 4096);
- POSIX::close ($psync[0]);
- &$register_worker($cpid);
+ if (!$sync) {
+ POSIX::close($psync[0]);
+ &$register_worker($cpid, $user, $upid);
+ } else {
+ chomp $readbuf;
+ }
- die "got no worker upid - start worker failed\n" if !$readbuf;
+ eval {
+ die "got no worker upid - start worker failed\n" if !$readbuf;
- if ($readbuf =~ m/^ERROR:\s*(.+)$/m) {
- die "starting worker failed: $1\n";
+ if ($readbuf =~ m/^ERROR:\s*(.+)$/m) {
+ die "starting worker failed: $1\n";
+ }
+
+ if ($readbuf ne $upid) {
+ die "got strange worker upid ('$readbuf' != '$upid') - start worker failed\n";
+ }
+
+ $outfh = PVE::Tools::upid_open($upid, $wwwid) if $sync;
+ };
+ my $err = $@;
+
+ if (!$err) {
+ my $msg = 'OK';
+ POSIX::write($csync[1], $msg, length ($msg));
+ POSIX::close($csync[1]);
+
+ } else {
+ POSIX::close($csync[1]);
+ kill (9, $cpid); # make sure it gets killed
+ die $err;
}
- if ($readbuf ne $upid) {
- die "got strange worker upid ('$readbuf' != '$upid') - start worker failed\n";
+ PVE::Cluster::log_msg('info', $user, "starting task $upid");
+
+ my $res = 0;
+
+ if ($sync) {
+ my $count;
+ my $outbuf = '';
+ eval {
+ local $SIG{INT} =
+ local $SIG{QUIT} =
+ local $SIG{TERM} = sub { die "got interrupt\n"; };
+ local $SIG{PIPE} = sub { die "broken pipe\n"; };
+
+ while (($count = POSIX::read($psync[0], $readbuf, 4096)) && ($count > 0)) {
+ $outbuf .= $readbuf;
+ while ($outbuf =~ s/^(([^\010\r\n]*)(\r|\n|(\010)+|\r\n))//s) {
+ my $line = $1;
+ my $data = $2;
+ if ($data =~ m/^TASK OK$/) {
+ # skip
+ } elsif ($data =~ m/^TASK ERROR: (.+)$/) {
+ print STDERR "$1\n";
+ } else {
+ print $line;
+ }
+ if ($outfh) {
+ print $outfh $line;
+ }
+ }
+ }
+ };
+ my $err = $@;
+
+ POSIX::close($psync[0]);
+
+ if ($outbuf) { # just to be sure
+ print $outbuf;
+ if ($outfh) {
+ print $outfh $outbuf;
+ }
+ }
+
+ if ($err) {
+ $err =~ s/\n/ /mg;
+ print STDERR "$err\n";
+ if ($outfh) {
+ print $outfh "TASK ERROR: $err\n";
+ }
+ kill (15, $cpid);
+
+ } else {
+ kill (9, $cpid); # make sure it gets killed
+ }
+
+ waitpid ($cpid, 0);
+ $res = $?;
+ &$log_task_result($upid, $user, $res);
}
- return $upid;
+ return wantarray ? ($upid, $res) : $upid;
}
1;
More information about the pve-devel
mailing list