[pve-devel] [PATCH pve-container 1/2] clone: implement target parameter

Dietmar Maurer dietmar at proxmox.com
Tue Mar 20 12:19:12 CET 2018


Signed-off-by: Dietmar Maurer <dietmar at proxmox.com>
---
 src/PVE/API2/LXC.pm | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 9205215..128a89b 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -1229,10 +1229,10 @@ __PACKAGE__->register_method({
 	        description => "Create a full copy of all disks. This is always done when " .
 		    "you clone a normal CT. For CT templates, we try to create a linked clone by default.",
 	    },
-#	    target => get_standard_option('pve-node', {
-#		description => "Target node. Only allowed if the original VM is on shared storage.",
-#		optional => 1,
-#	    }),
+	    target => get_standard_option('pve-node', {
+		description => "Target node. Only allowed if the original VM is on shared storage.",
+		optional => 1,
+	    }),
         },
     },
     returns => {
@@ -1261,13 +1261,26 @@ __PACKAGE__->register_method({
 
 	my $storage = extract_param($param, 'storage');
 
+	my $target = extract_param($param, 'target');
+
         my $localnode = PVE::INotify::nodename();
 
+        undef $target if $target && ($target eq $localnode || $target eq 'localhost');
+
+	PVE::Cluster::check_node_exists($target) if $target;
+
 	my $storecfg = PVE::Storage::config();
 
 	if ($storage) {
 	    # check if storage is enabled on local node
 	    PVE::Storage::storage_check_enabled($storecfg, $storage);
+	    if ($target) {
+		# check if storage is available on target node
+		PVE::Storage::storage_check_node($storecfg, $storage, $target);
+		# clone only works if target storage is shared
+		my $scfg = PVE::Storage::storage_config($storecfg, $storage);
+		die "can't clone to non-shared storage '$storage'\n" if !$scfg->{shared};
+	    }
 	}
 
 	PVE::Cluster::check_cfs_quorum();
@@ -1277,10 +1290,13 @@ __PACKAGE__->register_method({
 	my $mountpoints = {};
 	my $fullclone = {};
 	my $vollist = [];
+	my $running;
 
 	PVE::LXC::Config->lock_config($vmid, sub {
 	    my $src_conf = PVE::LXC::Config->set_lock($vmid, 'disk');
 
+	    $running = PVE::LXC::check_running($vmid) || 0;
+
 	    my $full = extract_param($param, 'full');
 	    if (!defined($full)) {
 		$full = !PVE::LXC::Config->is_template($src_conf);
@@ -1291,7 +1307,6 @@ __PACKAGE__->register_method({
 		die "snapshot '$snapname' does not exist\n"
 		    if $snapname && !defined($src_conf->{snapshots}->{$snapname});
 
-		my $running = PVE::LXC::check_running($vmid) || 0;
 
 		my $src_conf = $snapname ? $src_conf->{snapshots}->{$snapname} : $src_conf;
 
@@ -1372,6 +1387,9 @@ __PACKAGE__->register_method({
 
 	    my $newvollist = [];
 
+	    my $verify_running = PVE::LXC::check_running($vmid) || 0;
+	    die "unexpected state change\n" if $verify_running != $running;
+
 	    eval {
 		local $SIG{INT} =
 		    local $SIG{TERM} =
@@ -1402,6 +1420,16 @@ __PACKAGE__->register_method({
 
 		PVE::AccessControl::add_vm_to_pool($newid, $pool) if $pool;
 		PVE::LXC::Config->remove_lock($newid, 'create');
+
+		if ($target) {
+		    # always deactivate volumes - avoid lvm LVs to be active on several nodes
+		    PVE::Storage::deactivate_volumes($storecfg, $vollist, $snapname) if !$running;
+		    PVE::Storage::deactivate_volumes($storecfg, $newvollist);
+
+		    my $newconffile = PVE::LXC::Config->config_file($newid, $target);
+		    die "Failed to move config to node '$target' - rename failed: $!\n"
+			if !rename($conffile, $newconffile);
+		}
 	    };
 	    my $err = $@;
 
-- 
2.11.0



More information about the pve-devel mailing list