]>
git.proxmox.com Git - pve-manager.git/blob - PVE/APIDaemon.pm
041b7ed2be262496b38de9afd996c5bdb8a008d6
1 package PVE
::APIDaemon
;
5 use POSIX
":sys_wait_h";
6 use Socket
qw(IPPROTO_TCP TCP_NODELAY SOMAXCONN);
16 my ($this, %args) = @_;
18 my $class = ref($this) || $this;
20 die "no lockfile" if !$args{lockfile
};
22 my $lockfh = IO
::File-
>new(">>$args{lockfile}") ||
23 die "unable to open lock file '$args{lockfile}' - $!\n";
25 my $socket = IO
::Socket
::INET-
>new(
26 LocalAddr
=> $args{host
} || undef,
27 LocalPort
=> $args{port
} || 80,
31 die "unable to create socket - $@\n";
33 # we ofter observe delays when using Nagle algorithm,
34 # so we disable that to maximize performance
35 setsockopt($socket, IPPROTO_TCP
, TCP_NODELAY
, 1);
38 my $self = bless { cfg
=> $cfg }, $class;
40 $cfg->{socket} = $socket;
41 $cfg->{lockfh
} = $lockfh;
42 $cfg->{max_workers
} = 3 if !$cfg->{max_workers
};
43 $cfg->{trusted_env
} = 0 if !defined($cfg->{trusted_env
});
51 syslog
('info', "worker $cpid finished");
56 foreach my $cpid (keys %$workers) {
57 my $waitpid = waitpid ($cpid, WNOHANG
);
58 if (defined($waitpid) && ($waitpid == $cpid)) {
59 delete ($workers->{$cpid});
60 worker_finished
($cpid);
66 foreach my $cpid (keys %$workers) {
67 if (!kill(0, $cpid)) {
68 waitpid($cpid, POSIX
::WNOHANG
());
69 delete $workers->{$cpid};
70 worker_finished
($cpid);
79 foreach my $cpid (keys %$workers) {
83 my $need = $self->{cfg
}->{max_workers
} - $count;
87 syslog
('info', "starting $need worker(s)");
92 if (!defined ($pid)) {
93 syslog
('err', "can't fork worker");
95 } elsif ($pid) { #parent
97 syslog
('info', "worker $pid started");
102 $SIG{TERM
} = $SIG{QUIT
} = 'DEFAULT'; # we handle that with AnyEvent
105 my $server = PVE
::HTTPServer-
>new(%{$self->{cfg
}});
110 sleep(5); # avoid fast restarts
117 sub terminate_server
{
119 syslog
('info', "received terminate request");
121 foreach my $cpid (keys %$workers) {
122 kill (15, $cpid); # TERM childs
125 # nicely shutdown childs (give them max 10 seconds to shut down)
126 my $previous_alarm = alarm (10);
128 local $SIG{ALRM
} = sub { die "timeout\n" };
130 while ((my $pid = waitpid (-1, 0)) > 0) {
131 if (defined($workers->{$pid})) {
132 delete ($workers->{$pid});
133 worker_finished
($pid);
136 alarm(0); # avoid race condition
140 alarm ($previous_alarm);
143 syslog
('err', "error stopping workers (will kill them now) - $err");
144 foreach my $cpid (keys %$workers) {
145 # KILL childs still alive!
146 if (kill (0, $cpid)) {
147 delete ($workers->{$cpid});
148 syslog
("err", "kill worker $cpid");
159 my $old_sig_chld = $SIG{CHLD
};
160 local $SIG{CHLD
} = sub {
162 &$old_sig_chld(@_) if $old_sig_chld;
165 my $old_sig_term = $SIG{TERM
};
166 local $SIG{TERM
} = sub {
168 &$old_sig_term(@_) if $old_sig_term;
170 local $SIG{QUIT
} = sub {
172 &$old_sig_term(@_) if $old_sig_term;
175 local $SIG{HUP
} = sub {
176 syslog
("info", "received reload request");
177 foreach my $cpid (keys %$workers) {
178 kill (15, $cpid); # kill childs
183 $self->start_workers();
185 $self->test_workers();
191 syslog
('err', "ERROR: $err");
195 sub read_proxy_config
{
197 my $conffile = "/etc/default/pveproxy";
199 # Note: evaluate with bash
200 my $shcmd = ". $conffile;\n";
201 $shcmd .= 'echo \"ALLOW_FROM:\$ALLOW_FROM\";';
202 $shcmd .= 'echo \"DENY_FROM:\$DENY_FROM\";';
203 $shcmd .= 'echo \"POLICY:\$POLICY\";';
204 $shcmd .= 'echo \"CIPHERS:\$CIPHERS\";';
206 my $data = -f
$conffile ?
`bash -c "$shcmd"` : '';
210 while ($data =~ s/^(.*)\n//) {
211 my ($key, $value) = split(/:/, $1, 2);
213 if ($key eq 'ALLOW_FROM' || $key eq 'DENY_FROM') {
215 foreach my $ip (split(/,/, $value)) {
216 $ip = "0/0" if $ip eq 'all';
217 push @$ips, Net
::IP-
>new($ip) || die Net
::IP
::Error
() . "\n";
220 } elsif ($key eq 'POLICY') {
221 die "unknown policy '$value'\n" if $value !~ m/^(allow|deny)$/;
222 $res->{$key} = $value;
223 } elsif ($key eq 'CIPHERS') {
224 $res->{$key} = $value;
226 # silently skip everythin else?