]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/API2/Qemu.pm
followup: refactor loop to use perls values
[qemu-server.git] / PVE / API2 / Qemu.pm
index fa8315e1d18f0572ba3cb6be381e6c5c541b2d6b..027bbf6fdcf49a4c597fa94d38170b9b752149e6 100644 (file)
@@ -404,7 +404,7 @@ __PACKAGE__->register_method({
 my $parse_restore_archive = sub {
     my ($storecfg, $archive) = @_;
 
-    my ($archive_storeid, $archive_volname) = PVE::Storage::parse_volume_id($archive);
+    my ($archive_storeid, $archive_volname) = PVE::Storage::parse_volume_id($archive, 1);
 
     if (defined($archive_storeid)) {
        my $scfg =  PVE::Storage::storage_config($storecfg, $archive_storeid);
@@ -2024,11 +2024,7 @@ __PACKAGE__->register_method({
                optional => 1,
            },
            machine => get_standard_option('pve-qemu-machine'),
-           targetstorage => {
-               description => "Target storage for the migration. (Can be '1' to use the same storage id as on the source node.)",
-               type => 'string',
-               optional => 1
-           },
+           targetstorage => get_standard_option('pve-targetstorage'),
            timeout => {
                description => "Wait maximal timeout seconds.",
                type => 'integer',
@@ -2067,12 +2063,20 @@ __PACKAGE__->register_method({
        my $migration_network = $get_root_param->('migration_network');
        my $targetstorage = $get_root_param->('targetstorage');
 
-       raise_param_exc({ targetstorage => "targetstorage can only by used with migratedfrom." })
-           if $targetstorage && !$migratedfrom;
+       my $storagemap;
+
+       if ($targetstorage) {
+           raise_param_exc({ targetstorage => "targetstorage can only by used with migratedfrom." })
+               if !$migratedfrom;
+           $storagemap = eval { PVE::JSONSchema::parse_idmap($targetstorage, 'pve-storage-id') };
+           raise_param_exc({ targetstorage => "failed to parse targetstorage map: $@" })
+               if $@;
+       }
 
        # read spice ticket from STDIN
        my $spice_ticket;
        my $nbd_protocol_version = 0;
+       my $replicated_volumes = {};
        if ($stateuri && ($stateuri eq 'tcp' || $stateuri eq 'unix') && $migratedfrom && ($rpcenv->{type} eq 'cli')) {
            while (defined(my $line = <STDIN>)) {
                chomp $line;
@@ -2080,6 +2084,8 @@ __PACKAGE__->register_method({
                    $spice_ticket = $1;
                } elsif ($line =~ m/^nbd_protocol_version: (\d+)$/) {
                    $nbd_protocol_version = $1;
+               } elsif ($line =~ m/^replicated_volume: (.*)$/) {
+                   $replicated_volumes->{$1} = 1;
                } else {
                    # fallback for old source node
                    $spice_ticket = $line;
@@ -2111,9 +2117,24 @@ __PACKAGE__->register_method({
 
                syslog('info', "start VM $vmid: $upid\n");
 
-               PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock, $migratedfrom, undef, $machine,
-                                         $spice_ticket, $migration_network, $migration_type, $targetstorage, $timeout,
-                                         $nbd_protocol_version);
+               my $migrate_opts = {
+                   migratedfrom => $migratedfrom,
+                   spice_ticket => $spice_ticket,
+                   network => $migration_network,
+                   type => $migration_type,
+                   storagemap => $storagemap,
+                   nbd_proto_version => $nbd_protocol_version,
+                   replicated_volumes => $replicated_volumes,
+               };
+
+               my $params = {
+                   statefile => $stateuri,
+                   skiplock => $skiplock,
+                   forcemachine => $machine,
+                   timeout => $timeout,
+               };
+
+               PVE::QemuServer::vm_start($storecfg, $vmid, $params, $migrate_opts);
                return;
            };
 
@@ -2581,7 +2602,7 @@ __PACKAGE__->register_method({
                PVE::QemuServer::vm_resume($vmid, $skiplock, $nocheck);
            } else {
                my $storecfg = PVE::Storage::config();
-               PVE::QemuServer::vm_start($storecfg, $vmid, undef, $skiplock);
+               PVE::QemuServer::vm_start($storecfg, $vmid, { skiplock => $skiplock });
            }
 
            return;
@@ -2947,7 +2968,7 @@ __PACKAGE__->register_method({
                    foreach my $opt (keys %$drives) {
                        my $drive = $drives->{$opt};
                        my $skipcomplete = ($total_jobs != $i); # finish after last drive
-                       my $completion = $skipcomplete ? 'skip' : 'wait';
+                       my $completion = $skipcomplete ? 'skip' : 'complete';
 
                        my $src_sid = PVE::Storage::parse_volume_id($drive->{file});
                        my $storage_list = [ $src_sid ];
@@ -2956,7 +2977,7 @@ __PACKAGE__->register_method({
 
                        my $newdrive = PVE::QemuServer::clone_disk($storecfg, $vmid, $running, $opt, $drive, $snapname,
                                                                   $newid, $storage, $format, $fullclone->{$opt}, $newvollist,
-                                                                  $jobs, $completion, $oldconf->{agent}, $clonelimit);
+                                                                  $jobs, $completion, $oldconf->{agent}, $clonelimit, $oldconf);
 
                        $newconf->{$opt} = PVE::QemuServer::print_drive($newdrive);
 
@@ -3143,7 +3164,7 @@ __PACKAGE__->register_method({
                    my $movelimit = PVE::Storage::get_bandwidth_limit('move', [$oldstoreid, $storeid], $bwlimit);
 
                    my $newdrive = PVE::QemuServer::clone_disk($storecfg, $vmid, $running, $disk, $drive, undef,
-                                                              $vmid, $storeid, $format, 1, $newvollist, undef, undef, undef, $movelimit);
+                                                              $vmid, $storeid, $format, 1, $newvollist, undef, undef, undef, $movelimit, $conf);
 
                    $conf->{$disk} = PVE::QemuServer::print_drive($newdrive);
 
@@ -3367,9 +3388,7 @@ __PACKAGE__->register_method({
                description => "Enable live storage migration for local disk",
                optional => 1,
            },
-            targetstorage => get_standard_option('pve-storage-id', {
-               description => "Default target storage.",
-               optional => 1,
+            targetstorage => get_standard_option('pve-targetstorage', {
                completion => \&PVE::QemuServer::complete_migration_storage,
             }),
            bwlimit => {
@@ -3433,8 +3452,34 @@ __PACKAGE__->register_method({
 
        my $storecfg = PVE::Storage::config();
 
-       if( $param->{targetstorage}) {
-           PVE::Storage::storage_check_node($storecfg, $param->{targetstorage}, $target);
+       if (my $targetstorage = $param->{targetstorage}) {
+           my $check_storage = sub {
+               my ($target_sid) = @_;
+               PVE::Storage::storage_check_node($storecfg, $target_sid, $target);
+               $rpcenv->check($authuser, "/storage/$target_sid", ['Datastore.AllocateSpace']);
+               my $scfg = PVE::Storage::storage_config($storecfg, $target_sid);
+               raise_param_exc({ targetstorage => "storage '$target_sid' does not support vm images"})
+                   if !$scfg->{content}->{images};
+           };
+
+           my $storagemap = eval { PVE::JSONSchema::parse_idmap($targetstorage, 'pve-storage-id') };
+           raise_param_exc({ targetstorage => "failed to parse targetstorage map: $@" })
+               if $@;
+
+           $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk'])
+               if !defined($storagemap->{identity});
+
+           foreach my $source (values %{$storagemap->{entries}}) {
+               $check_storage->($source);
+           }
+
+           $check_storage->($storagemap->{default})
+               if $storagemap->{default};
+
+           PVE::QemuServer::check_storage_availability($storecfg, $conf, $target)
+               if $storagemap->{identity};
+
+           $param->{storagemap} = $storagemap;
         } else {
            PVE::QemuServer::check_storage_availability($storecfg, $conf, $target);
        }