currently it is allowed to change all configuration settings for a VM. But may be some are only allowed if VM is offline or if hotplug is enabled
Signed-off-by: Stefan Priebe <[email protected]> --- PVE/API2/Qemu.pm | 127 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 102 insertions(+), 25 deletions(-) diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index 903f1fb..3a23912 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -757,6 +757,8 @@ my $vmconfig_update_disk = sub { $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']); } + my $running = PVE::QemuServer::check_running($vmid); + if ($conf->{$opt}) { if (my $old_drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt})) { @@ -768,10 +770,20 @@ my $vmconfig_update_disk = sub { if (!PVE::QemuServer::drive_is_cdrom($old_drive) && ($drive->{file} ne $old_drive->{file})) { # delete old disks + die "Deleting drive '$drive->{file}' not possible while VM is running and hotplug disabled.\n" + if $running && !$conf->{hotplug}; + &$vmconfig_delete_option($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $force); $conf = PVE::QemuServer::load_config($vmid); # update/reload } + if ((defined $old_drive->{cache} && defined $drive->{cache} && $old_drive->{cache} ne $drive->{cache}) || + (!defined $drive->{cache} && defined $old_drive->{cache}) || + (!defined $old_drive->{cache} && defined $drive->{cache})) { + die "Changing cache mode for drive '$opt' not possible while VM is running and hotplug disabled.\n" + if ($running && !PVE::QemuServer::drive_is_cdrom($drive) && !$conf->{hotplug}); + } + if(&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) || &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) || &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) || @@ -800,6 +812,9 @@ my $vmconfig_update_disk = sub { if !PVE::QemuServer::drive_is_cdrom($drive); } } + } else { + die "Adding drive '$opt' not possible while VM is running and hotplug disabled.\n" + if ($running && !PVE::QemuServer::drive_is_cdrom($drive) && !$conf->{hotplug}); } &$create_disks($rpcenv, $authuser, $conf, $storecfg, $vmid, undef, {$opt => $value}); @@ -810,7 +825,7 @@ my $vmconfig_update_disk = sub { if (PVE::QemuServer::drive_is_cdrom($drive)) { # cdrom - if (PVE::QemuServer::check_running($vmid)) { + if ($running) { if ($drive->{file} eq 'none') { PVE::QemuServer::vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt"); } else { @@ -834,8 +849,10 @@ my $vmconfig_update_net = sub { my $newnet = PVE::QemuServer::parse_net($value); if($oldnet->{model} ne $newnet->{model}){ + die "Changing model is not possible while VM is running and hotplug disabled.\n" + if PVE::QemuServer::check_running($vmid) && !$conf->{hotplug}; #if model change, we try to hot-unplug - die "error hot-unplug $opt for update" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt); + die "error hot-unplug $opt for update\n" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt); }else{ if($newnet->{bridge} && $oldnet->{bridge}){ @@ -851,11 +868,17 @@ my $vmconfig_update_net = sub { } }else{ + die "Changing bridged/nat mode is not possible while VM is running and hotplug disabled.\n" + if PVE::QemuServer::check_running($vmid) && !$conf->{hotplug}; #if bridge/nat mode change, we try to hot-unplug - die "error hot-unplug $opt for update" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt); + die "error hot-unplug $opt for update\n" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt); } } + } else { + # new device + die "Adding new net device '$opt' not possible while VM is running and hotplug disabled.\n" + if PVE::QemuServer::check_running($vmid) && !$conf->{hotplug}; } $conf->{$opt} = $value; PVE::QemuServer::update_config_nolock($vmid, $conf, 1); @@ -972,50 +995,104 @@ my $update_vm_api = sub { print "update VM $vmid: " . join (' ', @paramarr) . "\n"; - foreach my $opt (@delete) { # delete - $conf = PVE::QemuServer::load_config($vmid); # update/reload - &$vmconfig_delete_option($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $force); - } - my $running = PVE::QemuServer::check_running($vmid); - foreach my $opt (keys %$param) { # add/change + my $conf_param = $param; + foreach my $del (@delete) { + die "You cannot update/add and delete at the same time '$del'\n" if exists $conf_param->{$del}; + $conf_param->{$del} = undef; + } + + foreach my $opt (keys %$conf_param) { # add/change/delete $conf = PVE::QemuServer::load_config($vmid); # update/reload - next if $conf->{$opt} && ($param->{$opt} eq $conf->{$opt}); # skip if nothing changed + next if ((defined $conf->{$opt} && defined $conf_param->{$opt} && $conf_param->{$opt} eq $conf->{$opt}) || + (!defined $conf->{$opt} && !defined $conf_param->{$opt})); # skip if nothing changed - if (PVE::QemuServer::valid_drivename($opt)) { + # ignore sockets setting if maxcpu is set + next if ($opt eq "sockets" && $conf->{maxcpus}); + + my $need_hotplug = 0; + my $need_offlinevm = 0; + + if ($opt eq 'tablet') { + # special handling for tablet option + + if ($conf_param->{$opt}) { + PVE::QemuServer::vm_deviceplug(undef, $conf, $vmid, $opt); + } else { + PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt); + } + next; - &$vmconfig_update_disk($rpcenv, $authuser, $conf, $storecfg, $vmid, - $opt, $param->{$opt}, $force); + } elsif (PVE::QemuServer::valid_drivename($opt)) { + + if (defined $conf_param->{$opt}) { + &$vmconfig_update_disk($rpcenv, $authuser, $conf, $storecfg, $vmid, + $opt, $conf_param->{$opt}, $force); + next; + } + $need_hotplug = 1; # for delete / remove } elsif ($opt =~ m/^net(\d+)$/) { #nics - &$vmconfig_update_net($rpcenv, $authuser, $conf, $storecfg, $vmid, - $opt, $param->{$opt}); + if (defined $conf_param->{$opt}) { + &$vmconfig_update_net($rpcenv, $authuser, $conf, $storecfg, $vmid, + $opt, $conf_param->{$opt}); + next; + } + $need_hotplug = 1; # for delete / remove } else { + # all options which do not update config on their own - if($opt eq 'tablet' && $param->{$opt} == 1){ - PVE::QemuServer::vm_deviceplug(undef, $conf, $vmid, $opt); - } elsif($opt eq 'tablet' && $param->{$opt} == 0){ - PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt); + if ($opt =~ /^(cores)$/) { + # options only possible to change if hotplug is enabled + $need_hotplug = 1; + + } elsif ($opt =~ /^(balloon)$/ && length $conf->{$opt}) { + + # options always beeing able to change IF they already exist config + + } elsif ($opt =~ /^(onboot|name|boot|shares)$/) { + + # options always beeing able to change + + } else { + + # options only possible to change if the vm isn't running + $need_offlinevm = 1; } - - if($opt eq 'cores' && $conf->{maxcpus}){ - PVE::QemuServer::qemu_cpu_hotplug($vmid, $conf, $param->{$opt}); + } + + my $type = (!defined $conf_param->{$opt}) ? "Removing" : "Changing"; + if ($running && $need_hotplug && !$conf->{hotplug}) { + die "$type '$opt' not possible while VM is running and hotplug disabled.\n"; + } + if ($running && $need_offlinevm) { + die "$type '$opt' not possible while VM is running.\n"; + } + + if (!defined $conf_param->{$opt}) { + + # undefined values are "delete" values + &$vmconfig_delete_option($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $force); + } else { + + if ($opt eq 'cores' && $conf->{maxcpus}){ + PVE::QemuServer::qemu_cpu_hotplug($vmid, $conf, $conf_param->{$opt}); } - $conf->{$opt} = $param->{$opt}; + $conf->{$opt} = $conf_param->{$opt}; PVE::QemuServer::update_config_nolock($vmid, $conf, 1); } } # allow manual ballooning if shares is set to zero - if ($running && defined($param->{balloon}) && + if ($running && defined($conf_param->{balloon}) && defined($conf->{shares}) && ($conf->{shares} == 0)) { - my $balloon = $param->{'balloon'} || $conf->{memory} || $defaults->{memory}; + my $balloon = $conf_param->{'balloon'} || $conf->{memory} || $defaults->{memory}; PVE::QemuServer::vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024); } }; -- 1.7.10.4 _______________________________________________ pve-devel mailing list [email protected] http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
