For remote migration, we already check that the config can be parsed
on the target. Do the same for intra-cluster migration, to avoid
issues with future new settings unexpectedly being ignored if the
target is too old. For example, migrating a container with a
mountpoint with 'keepattrs' to a node with a too old pve-container
version, results in the mountpoint not being mounted on the target.

Signed-off-by: Fiona Ebner <[email protected]>
---

Dependency bump for guest-common needed!

New in v2.

 src/PVE/API2/LXC.pm    | 11 +++++++++++
 src/PVE/LXC/Migrate.pm | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 7841215..ec0b815 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -1618,6 +1618,14 @@ __PACKAGE__->register_method({
                 minimum => '0',
                 default => 'migrate limit from datacenter or storage config',
             },
+            force => {
+                type => 'boolean',
+                description =>
+                    "For intra-cluster migration: allow migration even if 
there are configuration"
+                    . " options not understood by the target. Only root may 
use this option.",
+                optional => 1,
+                default => 0,
+            },
         },
     },
     returns => {
@@ -1644,6 +1652,9 @@ __PACKAGE__->register_method({
 
         my $vmid = extract_param($param, 'vmid');
 
+        raise_param_exc({ force => "Only root may use this option." })
+            if $param->{force} && $authuser ne 'root@pam';
+
         # test if VM exists
         PVE::LXC::Config->load_config($vmid);
 
diff --git a/src/PVE/LXC/Migrate.pm b/src/PVE/LXC/Migrate.pm
index d243d90..1786e15 100644
--- a/src/PVE/LXC/Migrate.pm
+++ b/src/PVE/LXC/Migrate.pm
@@ -159,6 +159,43 @@ sub prepare {
         my $cmd = [@{ $self->{rem_ssh} }, '/bin/true'];
         eval { $self->cmd_quiet($cmd); };
         die "Can't connect to destination address using public key\n" if $@;
+
+        if (!$self->{opts}->{force}) {
+            my $skip;
+
+            # TODO PVE 10 - simplify by assuming that 'pct mtunnel' command is 
supported
+            my $log_and_check_supported = sub {
+                my ($level, $msg) = @_;
+                # Skip if the target is too old to support 'pct mtunnel' and 
avoid printing the
+                # whole 'pct' usage output
+                return if $skip;
+                if ($msg =~ m/unknown command 'pct mtunnel'/) {
+                    $skip = 1;
+                    return;
+                }
+                $self->log($level, $msg);
+            };
+
+            my $tunnel = eval {
+                PVE::Tunnel::fork_ssh_tunnel(
+                    $self->{rem_ssh}, ['pct', 'mtunnel'], undef, 
$log_and_check_supported);
+            };
+            my $err = $@;
+            if ($skip) {
+                $self->log('info', "skipping strict configuration check - 
target too old");
+            } else {
+                die $err if $err;
+
+                my $nodename = PVE::INotify::nodename();
+                eval { PVE::Tunnel::write_tunnel($tunnel, 10, "config $vmid 
$nodename"); };
+                if (my $err = $@) {
+                    chomp($err);
+                    die "$err - use --force to migrate regardless\n";
+                }
+                eval { PVE::Tunnel::finish_tunnel($tunnel); };
+                $self->log('warn', "failed to finish tunnel in prepare() - 
$@") if $@;
+            }
+        }
     }
 
     # in restart mode, we shutdown the container before migrating
-- 
2.47.3




Reply via email to