all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Stefan Hanreich <s.hanreich@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH v2 pve-container 2/2] add migration hooks to container migration process
Date: Thu,  6 Oct 2022 14:44:42 +0200	[thread overview]
Message-ID: <20221006124447.120701-4-s.hanreich@proxmox.com> (raw)
In-Reply-To: <20221006124447.120701-1-s.hanreich@proxmox.com>

Using the pct commands implemented in the previous commit, this commit
adds running the migration-hooks during the container migration process.

I am redirecting STDERR from the pct mtunnel to /dev/null since it is
not captured by the current fork_ssh_tunnel function and can then
pollute the output of the migration task. The STDERR of the
migrate-hookscript is not affected, since it is captured by the remote
mtunnel command and gets transferred via the query-migrate-hook command.

Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
 src/PVE/LXC/Migrate.pm | 119 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 119 insertions(+)

diff --git a/src/PVE/LXC/Migrate.pm b/src/PVE/LXC/Migrate.pm
index 2ef1cce..fdde180 100644
--- a/src/PVE/LXC/Migrate.pm
+++ b/src/PVE/LXC/Migrate.pm
@@ -89,6 +89,8 @@ sub prepare {
 	    if !$target_scfg->{content}->{rootdir};
     });
 
+    $self->migration_hook($vmid, 'pre');
+
     # todo: test if VM uses local resources
 
     # test ssh connection
@@ -384,6 +386,15 @@ sub phase3 {
     }
 }
 
+#  only called when phase1 was successful
+sub phase3_cleanup {
+    my ($self, $vmid, $err) = @_;
+
+    if (!$self->{errors}) {
+	$self->migration_hook($vmid, 'post');
+    }
+}
+
 sub final_cleanup {
     my ($self, $vmid) = @_;
 
@@ -413,7 +424,115 @@ sub final_cleanup {
 	    $self->cmd($cmd);
 	}
     }
+}
+
+sub fork_tunnel {
+    my ($self, $ssh_forward_info) = @_;
+
+    my $cmd = ['/usr/sbin/pct', 'mtunnel', '2>', '/dev/null'];
+    my $log = sub {
+	my ($level, $msg) = @_;
+	$self->log($level, $msg);
+    };
+
+    return PVE::Tunnel::fork_ssh_tunnel($self->{rem_ssh}, $cmd, $ssh_forward_info, $log);
+}
+
+sub migration_hook {
+    my ($self, $vmid, $phase) = @_;
+
+    if (!$self->{vmconf}->{hookscript}) {
+	return;
+    }
+
+    my $stop_on_error = $phase eq 'pre';
+
+    PVE::GuestHelpers::exec_hookscript(
+	$self->{vmconf},
+	$vmid,
+	"$phase-migrate",
+	$stop_on_error,
+    );
+
+    my $tunnel;
+
+    eval {
+	$tunnel = $self->{tunnel} // $self->fork_tunnel();
+    };
+    if ($@ =~ /can't open tunnel/) {
+	$self->log('warn', 'Target node does not support mtunnel. Not running hookscript on target, but still continuing with migration.');
+	return;
+    } elsif ($@) {
+	die $@;
+    }
+
+    my $close_tunnel = sub {
+	if (!$self->{tunnel}) {
+	    eval {
+		$self->log('info', "closing tunnel for migration hook");
+		PVE::Tunnel::finish_tunnel($tunnel);
+	    };
+	    if ($@) {
+		$self->log('warn', 'could not close tunnel to remote host');
+	    }
+	}
+    };
+
+    my $result;
+
+    eval {
+	$self->log('info', "starting hook $phase-migrate on target");
+
+	$result = PVE::Tunnel::write_tunnel($tunnel, 30, "migrate-hook", {
+	    vmid => $vmid,
+	    phase => $phase,
+	    source => PVE::INotify::nodename(),
+	    target => $self->{node},
+	});
+    };
+    my $err = $@;
+
+    if ($err) {
+	$close_tunnel->();
+	die $err;
+    }
+
+    $self->log('info', "successfully started hook $phase-migrate on target");
+
+    my $running = 1;
+
+    while ($running) {
+	eval {
+	    $result = PVE::Tunnel::write_tunnel($tunnel, 30, "query-migrate-hook");
+
+	    if (!exists $result->{status}) {
+		die "Invalid response!";
+	    } elsif ($result->{status} eq 'running') {
+		sleep(5);
+	    } elsif ($result->{status} eq 'finished') {
+		$self->log('info', "$phase-migrate hook ran successfully on target:\n$result->{output}");
+	    } elsif ($result->{status} eq 'error') {
+		my $msg = "An error occured during running the hookscript:\n" . $result->{output};
+
+		if ($stop_on_error) {
+		    die $msg;
+		} else {
+		    $self->log('warn', $msg)
+		}
+	    } else {
+		die "Invalid response!";
+	    }
+
+	    $running = $result->{status} eq 'running';
+	};
+	if ($@) {
+	    $err = $@;
+	    last;
+	}
+    }
 
+    $close_tunnel->();
+    die $err if $err;
 }
 
 1;
-- 
2.30.2




  parent reply	other threads:[~2022-10-06 12:45 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-06 12:44 [pve-devel] [PATCH v2 pve-container/qemu-server/pve-docs/pve-guest-common 0/8] Add pre/post-migrate hooks Stefan Hanreich
2022-10-06 12:44 ` [pve-devel] [PATCH v2 pve-guest-common 1/1] Add run_params to exec_hookscript function Stefan Hanreich
2022-10-06 12:44 ` [pve-devel] [PATCH v2 pve-container 1/2] add pct mtunnel command to the CLI Stefan Hanreich
2022-10-06 12:44 ` Stefan Hanreich [this message]
2022-10-06 12:44 ` [pve-devel] [PATCH v2 pve-docs 1/3] Add pre/post-migrate events to hookscript example Stefan Hanreich
2022-10-06 12:44 ` [pve-devel] [PATCH v2 pve-docs 2/3] Add hookscript section to container documentation Stefan Hanreich
2022-10-06 12:44 ` [pve-devel] [PATCH v2 pve-docs 3/3] Add pre/post-migrate section to VM hookscript documentation Stefan Hanreich
2022-10-06 12:44 ` [pve-devel] [PATCH v2 qemu-server 1/2] add migrate-hook and query-migrate-hook commands to CLI Stefan Hanreich
2022-10-06 12:44 ` [pve-devel] [PATCH v2 qemu-server 2/2] add migration hooks to VM migration process Stefan Hanreich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221006124447.120701-4-s.hanreich@proxmox.com \
    --to=s.hanreich@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal