]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/API2/Qemu.pm
check also pending changes when reverting/deleting
[qemu-server.git] / PVE / API2 / Qemu.pm
index 3fb1ab245d44f0c193ce06703836ae289f27b8f8..54db5ab0caaf43255dcf8d73fb9262eddd31c32c 100644 (file)
@@ -15,6 +15,8 @@ use PVE::Exception qw(raise raise_param_exc raise_perm_exc);
 use PVE::Storage;
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::RESTHandler;
+use PVE::ReplicationConfig;
+use PVE::GuestHelpers;
 use PVE::QemuConfig;
 use PVE::QemuServer;
 use PVE::QemuMigrate;
@@ -24,7 +26,6 @@ use PVE::INotify;
 use PVE::Network;
 use PVE::Firewall;
 use PVE::API2::Firewall::VM;
-use PVE::ReplicationTools;
 
 BEGIN {
     if (!$ENV{PVE_GENERATING_DOCS}) {
@@ -120,7 +121,8 @@ my $create_disks = sub {
     my $vollist = [];
 
     my $res = {};
-    PVE::QemuServer::foreach_drive($settings, sub {
+
+    my $code = sub {
        my ($ds, $disk) = @_;
 
        my $volid = $disk->{file};
@@ -128,7 +130,7 @@ my $create_disks = sub {
        if (!$volid || $volid eq 'none' || $volid eq 'cdrom') {
            delete $disk->{size};
            $res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
-       } elsif ($volid =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
+       } elsif ($volid =~ m!^(([^/:\s]+):)?(\d+(\.\d+)?)$!) {
            my ($storeid, $size) = ($2 || $default_storage, $3);
            die "no storage ID specified (and no default storage)\n" if !$storeid;
            my $defformat = PVE::Storage::storage_default_format($storecfg, $storeid);
@@ -191,7 +193,9 @@ my $create_disks = sub {
 
            $res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
        }
-    });
+    };
+
+    eval { PVE::QemuServer::foreach_drive($settings, $code); };
 
     # free allocated images on error
     if (my $err = $@) {
@@ -1008,7 +1012,7 @@ my $update_vm_api  = sub {
            foreach my $opt (@delete) {
                $modified->{$opt} = 1;
                $conf = PVE::QemuConfig->load_config($vmid); # update/reload
-               if (!defined($conf->{$opt})) {
+               if (!defined($conf->{$opt}) && !defined($conf->{pending}->{$opt})) {
                    warn "cannot delete '$opt' - not set in current configuration!\n";
                    $modified->{$opt} = 0;
                    next;
@@ -1029,16 +1033,6 @@ my $update_vm_api  = sub {
                        if defined($conf->{pending}->{$opt});
                    PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force);
                    PVE::QemuConfig->write_config($vmid, $conf);
-               } elsif ($opt eq "replica" || $opt eq "replica_target") {
-                   delete $conf->{$opt};
-                   delete $conf->{replica} if $opt eq "replica_target";
-
-                   PVE::QemuConfig->write_config($vmid, $conf);
-                   PVE::ReplicationTools::job_remove($vmid);
-               } elsif ($opt eq "replica_interval" || $opt eq "replica_rate_limit") {
-                   delete $conf->{$opt};
-                   PVE::QemuConfig->write_config($vmid, $conf);
-                   PVE::ReplicationTools::update_conf($vmid, $opt, $param->{$opt});
                } else {
                    PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force);
                    PVE::QemuConfig->write_config($vmid, $conf);
@@ -1061,21 +1055,6 @@ my $update_vm_api  = sub {
                        if defined($conf->{pending}->{$opt});
 
                    &$create_disks($rpcenv, $authuser, $conf->{pending}, $storecfg, $vmid, undef, {$opt => $param->{$opt}});
-               } elsif ($opt eq "replica") {
-                   die "Not all volumes are syncable, please check your config\n"
-                       if !PVE::ReplicationTools::check_guest_volumes_syncable($conf, 'qemu');
-                   die "replica_target is required\n"
-                       if !$conf->{replica_target} && !$param->{replica_target};
-                   $conf->{$opt} = $param->{$opt};
-               } elsif ($opt eq "replica_interval" || $opt eq "replica_rate_limit") {
-                   $conf->{$opt} = $param->{$opt};
-                   PVE::ReplicationTools::update_conf($vmid, $opt, $param->{$opt});
-               } elsif ($opt eq "replica_target" ) {
-                   die "Node: $param->{$opt} does not exists in Cluster.\n"
-                       if !PVE::Cluster::check_node_exists($param->{$opt});
-                   PVE::ReplicationTools::update_conf($vmid, $opt, $param->{$opt})
-                       if defined($conf->{$opt});
-                   $conf->{$opt} = $param->{$opt};
                } else {
                    $conf->{pending}->{$opt} = $param->{$opt};
                }
@@ -1083,14 +1062,6 @@ my $update_vm_api  = sub {
                PVE::QemuConfig->write_config($vmid, $conf);
            }
 
-           if (defined($param->{replica})) {
-               if ($param->{replica}) {
-                   PVE::ReplicationTools::job_enable($vmid);
-               } else {
-                   PVE::ReplicationTools::job_disable($vmid);
-               }
-           }
-
            # remove pending changes when nothing changed
            $conf = PVE::QemuConfig->load_config($vmid); # update/reload
            my $changes = PVE::QemuServer::vmconfig_cleanup_pending($conf);
@@ -1310,6 +1281,10 @@ __PACKAGE__->register_method({
        die "unable to remove VM $vmid - used in HA resources\n"
            if PVE::HA::Config::vm_is_ha_managed($vmid);
 
+       # do not allow destroy if there are replication jobs
+       my $repl_conf = PVE::ReplicationConfig->new();
+       $repl_conf->check_for_existing_jobs($vmid);
+
        # early tests (repeat after locking)
        die "VM $vmid is running - destroy failed\n"
            if PVE::QemuServer::check_running($vmid);
@@ -1319,9 +1294,6 @@ __PACKAGE__->register_method({
 
            syslog('info', "destroy VM $vmid: $upid\n");
 
-           # return without error if vm has no replica job
-           PVE::ReplicationTools::destroy_replica($vmid);
-
            PVE::QemuServer::vm_destroy($storecfg, $vmid, $skiplock);
 
            PVE::AccessControl::remove_vm_access($vmid);
@@ -1461,6 +1433,7 @@ __PACKAGE__->register_method({
                $cmd = [@$remcmd, "/usr/sbin/qm", 'vncproxy', $vmid];
 
                my $sock = IO::Socket::IP->new(
+                   ReuseAddr => 1,
                    Listen => 1,
                    LocalPort => $port,
                    Proto => 'tcp',
@@ -1486,7 +1459,7 @@ __PACKAGE__->register_method({
            return;
        };
 
-       my $upid = $rpcenv->fork_worker('vncproxy', $vmid, $authuser, $realcmd);
+       my $upid = $rpcenv->fork_worker('vncproxy', $vmid, $authuser, $realcmd, 1);
 
        PVE::Tools::wait_for_vnc_port($port);
 
@@ -2475,12 +2448,12 @@ __PACKAGE__->register_method({
                        $newconf->{$opt} = $value; # simply copy configuration
                    } else {
                        if ($param->{full}) {
-                           die "Full clone feature is not available"
+                           die "Full clone feature is not supported for drive '$opt'\n"
                                if !PVE::Storage::volume_has_feature($storecfg, 'copy', $drive->{file}, $snapname, $running);
                            $fullclone->{$opt} = 1;
                        } else {
                            # not full means clone instead of copy
-                           die "Linked clone feature is not available"
+                           die "Linked clone feature is not supported for drive '$opt'\n"
                                if !PVE::Storage::volume_has_feature($storecfg, 'clone', $drive->{file}, $snapname, $running);
                        }
                        $drives->{$opt} = $drive;
@@ -2884,13 +2857,17 @@ __PACKAGE__->register_method({
 
        } else {
 
-           my $realcmd = sub {
-               my $upid = shift;
+           my $code = sub {
+               my $realcmd = sub {
+                   my $upid = shift;
+
+                   PVE::QemuMigrate->migrate($target, $targetip, $vmid, $param);
+               };
 
-               PVE::QemuMigrate->migrate($target, $targetip, $vmid, $param);
+               return $rpcenv->fork_worker('qmigrate', $vmid, $authuser, $realcmd);
            };
 
-           return $rpcenv->fork_worker('qmigrate', $vmid, $authuser, $realcmd);
+           return PVE::GuestHelpers::guest_migration_lock($vmid, 10, $code);
        }
 
     }});