Signed-off-by: Dietmar Maurer <diet...@proxmox.com>
---
 PVE/API2/Qemu.pm |   99 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 0787074..222c44f 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -951,6 +951,44 @@ my $update_vm_api  = sub {
 
     &$check_storage_access($rpcenv, $authuser, $storecfg, $vmid, $param);
 
+    my $pending_delete_option = sub {
+       my ($conf, $key) = @_;
+
+       delete $conf->{pending}->{$key};
+       my $pending_delete_hash = { $key => 1 };
+       foreach my $opt (PVE::Tools::split_list($conf->{pending}->{delete})) {
+           $pending_delete_hash->{$opt} = 1;
+       }
+       $conf->{pending}->{delete} = join(',', keys %$pending_delete_hash);
+    };
+
+    my $pending_undelete_option = sub {
+       my ($conf, $key) = @_;
+
+       my $pending_delete_hash = {};
+       foreach my $opt (PVE::Tools::split_list($conf->{pending}->{delete})) {
+           $pending_delete_hash->{$opt} = 1;
+       }
+       delete $pending_delete_hash->{$key};
+
+       my @keylist = keys %$pending_delete_hash;
+       if (scalar(@keylist)) {
+           $conf->{pending}->{delete} = join(',', @keylist);
+       } else {
+           delete $conf->{pending}->{delete};
+       }
+    };
+
+    my $register_unused_drive = sub {
+       my ($conf, $drive) = @_;
+       if (!PVE::QemuServer::drive_is_cdrom($drive)) {
+           my $volid = $drive->{file};
+           if (&$vm_is_volid_owner($storecfg, $vmid, $volid)) {
+               PVE::QemuServer::add_unused_volume($conf, $volid, $vmid);
+           }
+       }
+    };
+
     my $updatefn =  sub {
 
        my $conf = PVE::QemuServer::load_config($vmid);
@@ -960,6 +998,7 @@ my $update_vm_api  = sub {
 
        PVE::QemuServer::check_lock($conf) if !$skiplock;
 
+       # fixme: wrong place? howto handle pending changes? @delete ?
        if ($param->{memory} || defined($param->{balloon})) {
            my $maxmem = $param->{memory} || $conf->{memory} || 
$defaults->{memory};
            my $balloon = defined($param->{balloon}) ?  $param->{balloon} : 
$conf->{balloon};
@@ -974,11 +1013,67 @@ 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']);
+                   &$register_unused_drive($conf, 
PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
+                       if defined($conf->{pending}->{$opt});
+                   &$pending_delete_option($conf, $opt);
+                   PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+               } else {
+                   &$pending_delete_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']);
+                   }
+                   &$register_unused_drive($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};
+               }
+               &$pending_undelete_option($conf, $opt);
+               PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+           }
+
+           # remove pending changes when nothing changed
+           my $changes;
+           $conf = PVE::QemuServer::load_config($vmid); # update/reload
+           foreach my $opt (keys %{$conf->{pending}}) { # add/change
+               if (defined($conf->{$opt}) && ($conf->{pending}->{$opt} eq  
$conf->{$opt})) {
+                   $changes = 1;
+                   delete $conf->{pending}->{$opt};
+               }
+           }
+           PVE::QemuServer::update_config_nolock($vmid, $conf, 1) if $changes;
+
+           return if !scalar(keys %{$conf->{pending}});
+
+           return; # TODO: apply changes
+
            my $running = PVE::QemuServer::check_running($vmid);
 
            foreach my $opt (keys %$param) { # add/change
-- 
1.7.10.4

_______________________________________________
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to