mirror of
https://git.lapiole.org/dani/ansible-roles.git
synced 2025-07-29 18:55:34 +02:00
Update to 2021-12-01 19:13
This commit is contained in:
111
roles/pve/files/online_hook.pl
Executable file
111
roles/pve/files/online_hook.pl
Executable file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use File::Basename;
|
||||
use JSON;
|
||||
use Logger::Syslog;
|
||||
|
||||
$SIG{CHLD} = 'IGNORE';
|
||||
|
||||
info( "GUEST HOOK: " . join( ' ', @ARGV ) );
|
||||
|
||||
my $vmid = shift;
|
||||
my $phase = shift;
|
||||
|
||||
if ( not -l '/etc/pve/local' ) {
|
||||
error( "Can't find /etc/pve/local link" );
|
||||
die;
|
||||
} elsif ( not defined $vmid or not defined $phase ) {
|
||||
error( "Need to pass both vmid and phase arguments" );
|
||||
die;
|
||||
} elsif ( $vmid !~ m/^\d+$/ ) {
|
||||
error( "vmid must be only numerical" );
|
||||
die;
|
||||
}
|
||||
|
||||
# We must identify the local node
|
||||
my $local_node = basename( readlink( '/etc/pve/local' ) );
|
||||
|
||||
if ( $phase eq 'pre-start' ) {
|
||||
info( "Runing pre-start hook for guest $vmid" );
|
||||
} elsif ( $phase eq 'post-start' ) {
|
||||
info( "Running post-start hook for guest $vmid" );
|
||||
# A VM has just started. Let's check if it's already on the local node
|
||||
# If it's an incoming live migration, it might still be running on another node
|
||||
# All of this must run in the background because hooks are synchronous
|
||||
my $pid = fork();
|
||||
if ( $pid != 0 ) {
|
||||
# main script can stop now, everything will run in a forked process
|
||||
POSIX::_exit 0;
|
||||
} elsif ( defined $pid ) {
|
||||
# All those fh must be closed for the fork to be independant of its parent
|
||||
close STDOUT;
|
||||
close STDERR;
|
||||
close STDIN;
|
||||
POSIX::setsid();
|
||||
|
||||
my $i = 0;
|
||||
my $guest_found = 0;
|
||||
|
||||
# We'll loop for up to 30min, which should be sufficient. If migration takes longer than that,
|
||||
# something is probably wrong
|
||||
LOOP: while ( $i lt 1800 ) {
|
||||
# Here, we query the API for all the VM
|
||||
my $resources = from_json( qx(pvesh get /cluster/resources --type=vm --output-format=json) );
|
||||
# Then we loop through all the VM to find the one we're interested in
|
||||
foreach my $vm ( @{$resources} ){
|
||||
next if ( $vm->{id} !~ m{^(qemu|lxc)/$vmid$} );
|
||||
|
||||
# OK, we found the guest $vmid
|
||||
info("Found guest $vmid, running on node " . $vm->{node});
|
||||
$guest_found = 1;
|
||||
|
||||
# Is the guest running on local node ? If yes, it means migration is finished, and we
|
||||
# can redirect IP failover and routing table
|
||||
if ( $vm->{node} eq $local_node ) {
|
||||
|
||||
# pve-online use this env var to check if we must unplug/replug the WAN NIC
|
||||
$ENV{PVE_GUEST_TYPE} = $1;
|
||||
|
||||
# And here we go !
|
||||
qx(/bin/systemd-cat /usr/local/bin/pve-online --update-routes --update-gre --migrate-ipfo=$vmid);
|
||||
|
||||
# Update routing table of the other online nodes
|
||||
my $nodes = from_json( qx(pvesh get /nodes --output-format=json) );
|
||||
foreach my $node ( @{$nodes} ) {
|
||||
if ( $node->{status} eq 'online' and $node->{node} ne $local_node ) {
|
||||
info("Updating routing table of node $node->{node}");
|
||||
qx(ssh -o ConnectTimeout=3 -l root $node->{node} /usr/local/bin/pve-online --update-routes);
|
||||
}
|
||||
}
|
||||
|
||||
# And we're done, stop looping
|
||||
last LOOP;
|
||||
|
||||
# Guest is not running on the local node = migration is still running
|
||||
# Wait a bit and start again
|
||||
} else {
|
||||
info( "Guest $vmid is still running on node " . $vm->{node} . " not yet on $local_node. Waiting a bit more for migration to finish" );
|
||||
sleep 1;
|
||||
next LOOP;
|
||||
}
|
||||
}
|
||||
|
||||
# We looped through all the guests and couldn't find the one we're looking for, nothing more we can do
|
||||
if ( not $guest_found ) {
|
||||
error( "No such guest with id $vmid" );
|
||||
die;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elsif ( $phase eq 'pre-stop' ) {
|
||||
info( "Running pre-stop hook" );
|
||||
} elsif ( $phase eq 'post-stop' ) {
|
||||
info( "Running post-stop hook" );
|
||||
# Just remove routes if needed
|
||||
qx(/bin/systemd-cat /usr/local/bin/pve-online --update-routes)
|
||||
} else {
|
||||
error( "Unknown hook phase : $phase" );
|
||||
die;
|
||||
}
|
Reference in New Issue
Block a user