How to run VM hooks asynchronously

For my need (see https://forum.proxmox.com/threads/running-hooks-when-incoming-migration-is-finished.54330 for some background), I need to run a hook script when a VM ends an incoming live migration. I'm trying to use the post-start hook. The idea : in the post-start hook, loop to see if the VM is running on the local node. If not, the migration is still running, if yes, it has finished the live migration and I can proceed with my custom script.

The problem is that hooks are blocking. Even post-start. As long as post-start has not returned, the migration won't proceed, as PVE consideres the VM is still starting. I tried to fork in my hook script, or to use a shell wrapper, calling the real one with &. But in both case it's the same. PVE dosn't start migration and juste blocks in the post-start hook. Not sure why, are hooks executed in a special cgroup which ensure even forks are ended ?

How can I fire a hook asynchronously ? I'd prefer not having to write a separate daemon which could receive signals from the hook script and do the async part
 

wolfgang

Proxmox Staff Member
Staff member
Oct 1, 2014
4,763
316
83
Hi,
You can do this with a fork of a new process.
 
This is where I'm lost. My hook is a perl script, and running in a simple fork() still blocks the hookThis is where it's getting strange. In my hook, I have something like this :


Code:
$SIG{CHLD} = 'IGNORE';

if ($phase eq 'post-start') {
  my $pid = fork();
  if ($pid) {
    print "Will run pre-start routine in the background\n";
  } elsif ( defined $pid ) {
    # Long running part which should be in the background
  }
}
Running this from the CLI, the script correctly detach itself. But when called but Proxmox as a hook, it's still blocking (in my case, it blocks the "Starting VM" part, and so the migration does not start. I'm probably doing it wrong, but I don't understand why it works from the CLI and not as a hook
 

wolfgang

Proxmox Staff Member
Staff member
Oct 1, 2014
4,763
316
83
Code:
#!/usr/bin/perl
use strict;
use warnings;
my $pid = fork();
if ($pid != 0) {
    exit;
} else {
    print "$$\n";
    sleep(1000);
    print "Done\n";
}
 

wolfgang

Proxmox Staff Member
Staff member
Oct 1, 2014
4,763
316
83
Code:
my $pid = fork();
if ($pid != 0) {
    POSIX::_exit 0;
} else {
close STDOUT;
close STDERR;
close STDIN;
POSIX::setsid();
#Do your things like 
sleep(100);
}
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE and Proxmox Mail Gateway. We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get your own in 60 seconds.

Buy now!