]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/API2/Qemu.pm
vmconfig_cleanup_pending: new method to clenup setting in [PENDING]
[qemu-server.git] / PVE / API2 / Qemu.pm
index 066726dc1ae8b36e986563af5dfcdabd33773ac8..405ca383663b211e10343695111f8ceb35ac69f8 100644 (file)
@@ -37,6 +37,21 @@ my $resolve_cdrom_alias = sub {
     }
 };
 
+my $test_deallocate_drive = sub {
+    my ($storecfg, $vmid, $key, $drive, $force) = @_;
+
+    if (!PVE::QemuServer::drive_is_cdrom($drive)) {
+       my $volid = $drive->{file};
+       if ( PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $volid)) {
+           if ($force || $key =~ m/^unused/) {
+               my $sid = PVE::Storage::parse_volume_id($volid);
+               return $sid;
+           }
+       }
+    }
+
+    return undef;
+};
 
 my $check_storage_access = sub {
    my ($rpcenv, $authuser, $storecfg, $vmid, $settings, $default_storage) = @_;
@@ -639,43 +654,13 @@ __PACKAGE__->register_method({
        return $conf;
     }});
 
-my $vm_is_volid_owner = sub {
-    my ($storecfg, $vmid, $volid) =@_;
-
-    if ($volid !~  m|^/|) {
-       my ($path, $owner);
-       eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
-       if ($owner && ($owner == $vmid)) {
-           return 1;
-       }
-    }
-
-    return undef;
-};
-
-my $test_deallocate_drive = sub {
-    my ($storecfg, $vmid, $key, $drive, $force) = @_;
-
-    if (!PVE::QemuServer::drive_is_cdrom($drive)) {
-       my $volid = $drive->{file};
-       if (&$vm_is_volid_owner($storecfg, $vmid, $volid)) {
-           if ($force || $key =~ m/^unused/) {
-               my $sid = PVE::Storage::parse_volume_id($volid);
-               return $sid;
-           }
-       }
-    }
-
-    return undef;
-};
-
 my $delete_drive = sub {
     my ($conf, $storecfg, $vmid, $key, $drive, $force) = @_;
 
     if (!PVE::QemuServer::drive_is_cdrom($drive)) {
        my $volid = $drive->{file};
 
-       if (&$vm_is_volid_owner($storecfg, $vmid, $volid)) {
+       if (PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $volid)) {
            if ($force || $key =~ m/^unused/) {
                eval {
                    # check if the disk is really unused
@@ -961,8 +946,8 @@ my $update_vm_api  = sub {
        PVE::QemuServer::check_lock($conf) if !$skiplock;
 
        if ($param->{memory} || defined($param->{balloon})) {
-           my $maxmem = $param->{memory} || $conf->{memory} || $defaults->{memory};
-           my $balloon = defined($param->{balloon}) ?  $param->{balloon} : $conf->{balloon};
+           my $maxmem = $param->{memory} || $conf->{pending}->{memory} || $conf->{memory} || $defaults->{memory};
+           my $balloon = defined($param->{balloon}) ? $param->{balloon} : $conf->{pending}->{balloon} || $conf->{balloon};
 
            die "balloon value too large (must be smaller than assigned memory)\n"
                if $balloon && $balloon > $maxmem;
@@ -974,13 +959,68 @@ my $update_vm_api  = sub {
 
            print "update VM $vmid: " . join (' ', @paramarr) . "\n";
 
-           foreach my $opt (@delete) { # delete
+           # write updates to pending section
+
+           foreach my $opt (@delete) {
                $conf = PVE::QemuServer::load_config($vmid); # update/reload
-               &$vmconfig_delete_option($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $force);
+               if ($opt =~ m/^unused/) {
+                   $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
+                   my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
+                   if (my $sid = &$test_deallocate_drive($storecfg, $vmid, $opt, $drive, $force)) {
+                       $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
+                       &$delete_drive($conf, $storecfg, $vmid, $opt, $drive);
+                       PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+                   }
+               } elsif (PVE::QemuServer::valid_drivename($opt)) {
+                   $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
+                   PVE::QemuServer::vmconfig_register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
+                       if defined($conf->{pending}->{$opt});
+                   PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt);
+                   PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+               } else {
+                   PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt);
+                   PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+               }
            }
 
+           foreach my $opt (keys %$param) { # add/change
+               $conf = PVE::QemuServer::load_config($vmid); # update/reload
+               next if defined($conf->{pending}->{$opt}) && ($param->{$opt} eq $conf->{pending}->{$opt}); # skip if nothing changed
+
+               if (PVE::QemuServer::valid_drivename($opt)) {
+                   my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
+                   if (PVE::QemuServer::drive_is_cdrom($drive)) { # CDROM
+                       $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.CDROM']);
+                   } else {
+                       $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
+                   }
+                   PVE::QemuServer::vmconfig_register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
+                       if defined($conf->{pending}->{$opt});
+
+                   &$create_disks($rpcenv, $authuser, $conf->{pending}, $storecfg, $vmid, undef, {$opt => $param->{$opt}});
+               } else {
+                   $conf->{pending}->{$opt} = $param->{$opt};
+               }
+               PVE::QemuServer::vmconfig_undelete_pending_option($conf, $opt);
+               PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+           }
+
+           # remove pending changes when nothing changed
+           $conf = PVE::QemuServer::load_config($vmid); # update/reload
+           my $changes = PVE::QemuServer::vmconfig_cleanup_pending($conf);
+           PVE::QemuServer::update_config_nolock($vmid, $conf, 1) if $changes;
+
+           return if !scalar(keys %{$conf->{pending}});
+
            my $running = PVE::QemuServer::check_running($vmid);
 
+           # apply pending changes
+
+           $conf = PVE::QemuServer::load_config($vmid); # update/reload
+           PVE::QemuServer::vmconfig_apply_pending($vmid, $conf, $storecfg, $running);
+
+           return; # TODO: remove old code below
+
            foreach my $opt (keys %$param) { # add/change
 
                $conf = PVE::QemuServer::load_config($vmid); # update/reload