[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