remove class APIDaemon

Moved last used sub into PVE::API2Tools.
This commit is contained in:
Dietmar Maurer 2015-01-01 16:54:21 +01:00
parent 5c173cc1df
commit 8208f7db2f
6 changed files with 47 additions and 257 deletions

View File

@ -2,6 +2,8 @@ package PVE::API2Tools;
use strict;
use warnings;
use Net::IP;
use PVE::Tools;
use Digest::MD5 qw(md5_hex);
use URI;
@ -195,4 +197,42 @@ sub run_spiceterm {
return $remote_viewer_config;
}
sub read_proxy_config {
my $conffile = "/etc/default/pveproxy";
# Note: evaluate with bash
my $shcmd = ". $conffile;\n";
$shcmd .= 'echo \"ALLOW_FROM:\$ALLOW_FROM\";';
$shcmd .= 'echo \"DENY_FROM:\$DENY_FROM\";';
$shcmd .= 'echo \"POLICY:\$POLICY\";';
$shcmd .= 'echo \"CIPHERS:\$CIPHERS\";';
my $data = -f $conffile ? `bash -c "$shcmd"` : '';
my $res = {};
while ($data =~ s/^(.*)\n//) {
my ($key, $value) = split(/:/, $1, 2);
next if !$value;
if ($key eq 'ALLOW_FROM' || $key eq 'DENY_FROM') {
my $ips = [];
foreach my $ip (split(/,/, $value)) {
$ip = "0/0" if $ip eq 'all';
push @$ips, Net::IP->new($ip) || die Net::IP::Error() . "\n";
}
$res->{$key} = $ips;
} elsif ($key eq 'POLICY') {
die "unknown policy '$value'\n" if $value !~ m/^(allow|deny)$/;
$res->{$key} = $value;
} elsif ($key eq 'CIPHERS') {
$res->{$key} = $value;
} else {
# silently skip everythin else?
}
}
return $res;
}
1;

View File

@ -1,252 +0,0 @@
package PVE::APIDaemon;
use strict;
use warnings;
use POSIX ":sys_wait_h";
use Socket qw(IPPROTO_TCP TCP_NODELAY SOMAXCONN);
use IO::Socket::INET;
use Net::IP;
use PVE::INotify;
use PVE::SafeSyslog;
use PVE::HTTPServer;
my $workers = {};
sub new {
my ($this, %args) = @_;
my $class = ref($this) || $this;
die "no lockfile" if !$args{lockfile};
die "no base_handler_class" if !$args{base_handler_class};
#require $args{base_handler_class};
my $lockfh = IO::File->new(">>$args{lockfile}") ||
die "unable to open lock file '$args{lockfile}' - $!\n";
my $socket = IO::Socket::INET->new(
LocalAddr => $args{host} || undef,
LocalPort => $args{port} || 80,
Listen => SOMAXCONN,
Proto => 'tcp',
ReuseAddr => 1) ||
die "unable to create socket - $@\n";
# we ofter observe delays when using Nagle algorithm,
# so we disable that to maximize performance
setsockopt($socket, IPPROTO_TCP, TCP_NODELAY, 1);
my $cfg = { %args };
my $self = bless { cfg => $cfg }, $class;
$cfg->{base_handler_class} = $args{base_handler_class};
$cfg->{socket} = $socket;
$cfg->{lockfh} = $lockfh;
$cfg->{max_workers} = 3 if !$cfg->{max_workers};
$cfg->{trusted_env} = 0 if !defined($cfg->{trusted_env});
return $self;
}
sub worker_finished {
my $cpid = shift;
syslog('info', "worker $cpid finished");
}
sub finish_workers {
local $!; local $?;
foreach my $cpid (keys %$workers) {
my $waitpid = waitpid ($cpid, WNOHANG);
if (defined($waitpid) && ($waitpid == $cpid)) {
delete ($workers->{$cpid});
worker_finished ($cpid);
}
}
}
sub test_workers {
foreach my $cpid (keys %$workers) {
if (!kill(0, $cpid)) {
waitpid($cpid, POSIX::WNOHANG());
delete $workers->{$cpid};
worker_finished ($cpid);
}
}
}
sub start_workers {
my ($self) = @_;
my $count = 0;
foreach my $cpid (keys %$workers) {
$count++;
}
my $need = $self->{cfg}->{max_workers} - $count;
return if $need <= 0;
syslog('info', "starting $need worker(s)");
while ($need > 0) {
my $pid = fork;
if (!defined ($pid)) {
syslog('err', "can't fork worker");
sleep (1);
} elsif ($pid) { #parent
$workers->{$pid} = 1;
syslog('info', "worker $pid started");
$need--;
} else {
$0 = "$0 worker";
PVE::INotify::inotify_close();
for my $sig (qw(CHLD HUP INT TERM QUIT)) {
$SIG{$sig} = 'DEFAULT'; # restore default handler
# AnyEvent signals only works if $SIG{XX} is
# undefined (perl event loop)
delete $SIG{$sig}; # so that we can handle events with AnyEvent
}
eval {
my $server = PVE::HTTPServer->new(%{$self->{cfg}});
$server->run();
};
if (my $err = $@) {
syslog('err', $err);
sleep(5); # avoid fast restarts
}
syslog('info', "worker exit");
exit (0);
}
}
}
sub terminate_server {
syslog('info', "received terminate request");
foreach my $cpid (keys %$workers) {
kill (15, $cpid); # TERM childs
}
# nicely shutdown childs (give them max 10 seconds to shut down)
my $previous_alarm = alarm (10);
eval {
local $SIG{ALRM} = sub { die "timeout\n" };
while ((my $pid = waitpid (-1, 0)) > 0) {
if (defined($workers->{$pid})) {
delete ($workers->{$pid});
worker_finished ($pid);
}
}
alarm(0); # avoid race condition
};
my $err = $@;
alarm ($previous_alarm);
if ($err) {
syslog('err', "error stopping workers (will kill them now) - $err");
foreach my $cpid (keys %$workers) {
# KILL childs still alive!
if (kill (0, $cpid)) {
delete ($workers->{$cpid});
syslog("err", "kill worker $cpid");
kill (9, $cpid);
}
}
}
}
sub start_server {
my $self = shift;
eval {
my $old_sig_chld = $SIG{CHLD};
local $SIG{CHLD} = sub {
finish_workers ();
&$old_sig_chld(@_) if $old_sig_chld;
};
my $old_sig_term = $SIG{TERM};
local $SIG{TERM} = sub {
terminate_server ();
&$old_sig_term(@_) if $old_sig_term;
};
local $SIG{QUIT} = sub {
terminate_server();
&$old_sig_term(@_) if $old_sig_term;
};
local $SIG{INT} = sub {
terminate_server();
&$old_sig_term(@_) if $old_sig_term;
};
local $SIG{HUP} = sub {
syslog("info", "received reload request");
foreach my $cpid (keys %$workers) {
kill (15, $cpid); # kill childs
}
};
for (;;) { # forever
$self->start_workers();
sleep (5);
$self->test_workers();
}
};
my $err = $@;
if ($err) {
syslog('err', "ERROR: $err");
}
}
sub read_proxy_config {
my $conffile = "/etc/default/pveproxy";
# Note: evaluate with bash
my $shcmd = ". $conffile;\n";
$shcmd .= 'echo \"ALLOW_FROM:\$ALLOW_FROM\";';
$shcmd .= 'echo \"DENY_FROM:\$DENY_FROM\";';
$shcmd .= 'echo \"POLICY:\$POLICY\";';
$shcmd .= 'echo \"CIPHERS:\$CIPHERS\";';
my $data = -f $conffile ? `bash -c "$shcmd"` : '';
my $res = {};
while ($data =~ s/^(.*)\n//) {
my ($key, $value) = split(/:/, $1, 2);
next if !$value;
if ($key eq 'ALLOW_FROM' || $key eq 'DENY_FROM') {
my $ips = [];
foreach my $ip (split(/,/, $value)) {
$ip = "0/0" if $ip eq 'all';
push @$ips, Net::IP->new($ip) || die Net::IP::Error() . "\n";
}
$res->{$key} = $ips;
} elsif ($key eq 'POLICY') {
die "unknown policy '$value'\n" if $value !~ m/^(allow|deny)$/;
$res->{$key} = $value;
} elsif ($key eq 'CIPHERS') {
$res->{$key} = $value;
} else {
# silently skip everythin else?
}
}
return $res;
}
1;

View File

@ -10,7 +10,6 @@ PERLSOURCE = \
TouchIndex.pm \
NoVncIndex.pm \
HTTPServer.pm \
APIDaemon.pm \
REST.pm \
OpenVZ.pm \
OpenVZMigrate.pm \

View File

@ -12,6 +12,7 @@ use PVE::Daemon;
use PVE::API2;
use PVE::API2::Formatter::Standard;
use PVE::API2::Formatter::HTML;
use PVE::HTTPServer;
use base qw(PVE::Daemon);

View File

@ -10,16 +10,17 @@ use English;
use PVE::SafeSyslog;
use PVE::Daemon;
use PVE::APIDaemon; # fixme: remove
use HTTP::Response;
use Encode;
use URI;
use URI::QueryParam;
use File::Find;
use Data::Dumper;
use PVE::API2Tools;
use PVE::API2;
use PVE::API2::Formatter::Standard;
use PVE::API2::Formatter::HTML;
use PVE::HTTPServer;
use PVE::ExtJSIndex;
use PVE::NoVncIndex;
@ -78,7 +79,7 @@ sub init {
my ($self) = @_;
# we use same ALLOW/DENY/POLICY as pveproxy
my $proxyconf = PVE::APIDaemon::read_proxy_config();
my $proxyconf = PVE::API2Tools::read_proxy_config();
my $accept_lock_fn = "/var/lock/pveproxy.lck";

View File

@ -14,8 +14,9 @@ use English;
use PVE::SafeSyslog;
use PVE::Daemon;
use PVE::APIDaemon; # fixme: remove
use PVE::API2Tools;
use PVE::API2;
use PVE::HTTPServer;
use base qw(PVE::Daemon);
@ -53,7 +54,7 @@ sub init {
my ($self) = @_;
# we use same ALLOW/DENY/POLICY as pveproxy
my $proxyconf = PVE::APIDaemon::read_proxy_config();
my $proxyconf = PVE::API2Tools::read_proxy_config();
my $accept_lock_fn = "/var/lock/spiceproxy.lck";