]>
git.proxmox.com Git - pmg-api.git/blob - PMG/Service/pmgtunnel.pm
1 package PMG
::Service
::pmgtunnel
;
6 use Time
::HiRes qw
(gettimeofday
);
9 use PVE
::Tools
qw(extract_param);
13 use PMG
::RESTEnvironment
;
17 use PMG
::ClusterConfig
;
20 use base
qw(PVE::Daemon);
22 my $cmdline = [$0, @ARGV];
24 my %daemon_options = (restart_on_error
=> 5, stop_wait_time
=> 5);
26 my $daemon = __PACKAGE__-
>new('pmgtunnel', $cmdline, %daemon_options);
28 my $restart_request = 0;
35 my $delayed_exec = {};
38 my $socketdir = "/var/run/pmgtunnel";
40 my $socketfile = sub {
42 return "$socketdir/.s.PGSQL.$cid";
46 while ((my $cpid = waitpid(-1, POSIX
::WNOHANG
())) > 0) {
47 if (defined($workers->{$cpid})) {
48 my $ip = $workers->{$cpid}->{ip
};
49 my $cid = $workers->{$cpid}->{cid
};
50 syslog
('err', "tunnel finished $cpid $ip");
51 unlink $socketfile->($cid);
52 $delayed_exec->{$cid} = time + ($startcount->{$cid} > 5 ?
60 : 10);
53 delete $workers->{$cpid};
59 my ($self, $cinfo) = @_;
61 my $role = $cinfo->{local}->{type
} // '-';
62 return if $role eq '-';
64 foreach my $cid (keys %{$cinfo->{ids
}}) {
65 my $ni = $cinfo->{ids
}->{$cid};
66 next if $ni->{ip
} eq $cinfo->{local}->{ip
}; # just to be sure
69 foreach my $cpid (keys %$workers) {
70 $running = 1 if $workers->{$cpid}->{ip
} eq $ni->{ip
};
74 if ($delayed_exec->{$cid} && (time < $delayed_exec->{$cid})) {
77 $delayed_exec->{$cid} = 0;
78 $startcount->{$cid}++;
82 if (!defined ($pid)) {
84 syslog
('err', "can't fork tunnel");
86 } elsif($pid) { # parent
88 $workers->{$pid}->{ip
} = $ni->{ip
};
89 $workers->{$pid}->{cid
} = $cid;
91 if ($startcount->{$cid} > 1) {
92 syslog
('info', "restarting crashed tunnel $pid $ni->{ip}");
94 syslog
('info', "starting tunnel $pid $ni->{ip}");
99 $self->after_fork_cleanup();
102 my $sock = $socketfile->($cid);
104 exec('/usr/bin/ssh', '-N', '-o', 'BatchMode=yes',
105 '-o', "HostKeyAlias=$ni->{name}",
106 '-L', "$sock:/var/run/postgresql/.s.PGSQL.5432",
114 my ($self, $cinfo) = @_;
116 foreach my $cpid (keys %$workers) {
117 my $ip = $workers->{$cpid}->{ip
};
118 my $cid = $workers->{$cpid}->{cid
};
121 foreach my $ni (values %{$cinfo->{ids
}}) {
122 $found = 1 if ($ni->{ip
} eq $ip) && ($ni->{cid
} eq $cid);
125 my $role = $cinfo->{local}->{type
} // '-';
126 $found = 0 if $role eq '-';
129 syslog
('info', "trying to finish tunnel $cpid $ip");
131 $delayed_exec->{$cid} = time + ($startcount->{$cid} > 5 ?
60 : 10);
132 delete $workers->{$cpid};
144 syslog
('info' , "server closing");
146 foreach my $cpid (keys %$workers) {
147 if (kill (15, $cpid) || ! kill(0, $cpid)) {
148 my $ip = $workers->{$cpid}->{ip
};
149 delete $workers->{$cpid};
150 syslog
('info', "successfully deleted tunnel $cpid $ip");
155 1 while (waitpid(-1, POSIX
::WNOHANG
()) > 0);
157 # $self->exit_daemon(0);
163 $restart_request = 1;
171 local $SIG{CHLD
} = \
&finish_children
;
175 $next_update = time() + $updatetime;
178 my $cinfo = PMG
::ClusterConfig-
>new(); # reload
179 $self->purge_tunnels($cinfo);
180 $self->start_tunnels($cinfo);
185 syslog
('err', "status update error: $err");
189 while ((time() < $next_update) &&
190 ($wcount < $updatetime) && # protect against time wrap
191 !$restart_request && !$self->{terminate
}) {
195 $wcount++; sleep (1);
198 last if $self->{terminate
};
200 $self->restart_daemon() if $restart_request;
204 __PACKAGE__-
>register_method ({
208 description
=> "Print cluster tunnel status.",
210 additionalProperties
=> 0,
213 returns
=> { type
=> 'null' },
217 my $status = $daemon->running() ?
'running' : 'stopped';
224 $daemon->register_start_command("Start the Cluster Tunnel Daemon");
225 $daemon->register_stop_command("Stop the Cluster Tunnel Daemon");
226 $daemon->register_restart_command(1, "Restart the Cluster Tunnel Daemon");
229 start
=> [ __PACKAGE__
, 'start', []],
230 restart
=> [ __PACKAGE__
, 'restart', []],
231 stop
=> [ __PACKAGE__
, 'stop', []],
232 status
=> [ __PACKAGE__
, 'status', []]