]> git.proxmox.com Git - qemu-server.git/commitdiff
implement copy_vm
authorDietmar Maurer <dietmar@proxmox.com>
Mon, 29 Apr 2013 08:42:35 +0000 (10:42 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Mon, 29 Apr 2013 08:53:03 +0000 (10:53 +0200)
This is based on patches from Alexandre Derumier <aderumier@odiso.com>.

It just implements copy/clone for stopped VMs and Templates. Copying
running VMs or copy from snapshots is not implemented.

PVE/API2/Qemu.pm

index 82d3a7f9e29a4852cb13738a07a4e88bf7d4e7f9..04106b83a9017e68a3f398e4b1a5803bb430bb18 100644 (file)
@@ -1867,20 +1867,22 @@ __PACKAGE__->register_method({
                if -f $conffile;
 
            # create empty/temp config - this fails if VM already exists on other node
-           PVE::Tools::file_set_contents($conffile, "# qmcopy temporary file\n");
+           PVE::Tools::file_set_contents($conffile, "# qmcopy temporary file\nlock: copy\n");
 
            my $realcmd = sub {
                my $upid = shift;
 
-               eval {
-                   print "COPY VM $vmid start\n";
+               my $newvollist = [];
 
-                   my $newconf = {};
+               eval {
+                   my $newconf = { lock => 'copy' };
                    my $drives = {};
                    my $vollist = [];
                    foreach my $opt (keys %$conf) {
                        my $value = $conf->{$opt};
 
+                       next if $opt eq 'snapshots'; #  do not copy snapshot info
+
                        # always change MAC! address
                        if ($opt =~ m/^net(\d+)$/) {
                            my $net = PVE::QemuServer::parse_net($value);
@@ -1903,21 +1905,51 @@ __PACKAGE__->register_method({
                    
                    PVE::Storage::activate_volumes($storecfg, $vollist);
 
-                   foreach my $opt (keys %$drives) {
-                       my $drive = $drives->{$opt};
-                       print "COPY  drive $opt: $drive->{file}\n";
+                   eval {
+                       local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub { die "interrupted by signal\n"; };
 
-                   }
+                       foreach my $opt (keys %$drives) {
+                           my $drive = $drives->{$opt};
 
-                   sleep(10);
-                   PVE::QemuServer::update_config_nolock($newid, $newconf, 1);
+                           my $newvolid;
+                           if (!$param->{full} && PVE::Storage::volume_is_base($storecfg,  $drive->{file})) {
+                               print "clone drive $opt ($drive->{file})\n";
+                               $newvolid = PVE::Storage::vdisk_clone($storecfg,  $drive->{file}, $newid);
+                           } else {
+                               my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
+                               my $defformat = PVE::Storage::storage_default_format($storecfg, $storeid);
+                               my $fmt = $drive->{format} || $defformat;
+
+                               my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3);
+
+                               print "copy drive $opt ($drive->{file})\n";
+                               $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newid, $fmt, undef, ($size/1024));
+
+                               PVE::QemuServer::qemu_img_convert($drive->{file}, $newvolid, $size);
+                           }
+
+                           my ($size) = PVE::Storage::volume_size_info($storecfg, $newvolid, 3);
+                           my $disk = { file => $newvolid, size => $size };
+                           $newconf->{$opt} = PVE::QemuServer::print_drive($vmid, $disk); 
+                           push @$newvollist, $newvolid;
 
-                   print "COPY VM $vmid end\n";
+                           PVE::QemuServer::update_config_nolock($newid, $newconf, 1);
+                       }
+                   };
+                   die $@ if $@;
+
+                   delete $newconf->{lock};
+                   PVE::QemuServer::update_config_nolock($newid, $newconf, 1);
                };
                if (my $err = $@) { 
-                   # fixme: remove all created files
                    unlink $conffile;
 
+                   sleep 1; # some storage like rbd need to wait before release volume - really?
+
+                   foreach my $volid (@$newvollist) {
+                       eval { PVE::Storage::vdisk_free($storecfg, $volid); };
+                       warn $@ if $@;
+                   }
                    die "copy failed: $err";
                }