}
};
+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) = @_;
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
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;
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