[pve-devel] [PATCH] implement config change checks to check for vm running, hotplug enabled ...
Stefan Priebe
s.priebe at profihost.ag
Thu Feb 20 09:53:21 CET 2014
Signed-off-by: Stefan Priebe <s.priebe at profihost.ag>
---
PVE/API2/Qemu.pm | 104 ++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 81 insertions(+), 23 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 903f1fb..c47ccbb 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,6 +770,9 @@ 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
}
@@ -802,6 +807,9 @@ my $vmconfig_update_disk = sub {
}
}
+ 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});
PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
@@ -810,7 +818,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 {
@@ -856,6 +864,10 @@ my $vmconfig_update_net = sub {
}
}
+ } 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 +984,96 @@ 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, map {$_ => undef} @delete };
+ 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)) {
+ my $need_hotplug = 0;
+ my $need_offlinevm = 0;
- &$vmconfig_update_disk($rpcenv, $authuser, $conf, $storecfg, $vmid,
- $opt, $param->{$opt}, $force);
+ 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;
+
+ } 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});
+ }
+
+
+ if ($running && $need_hotplug && !$conf->{hotplug}) {
+ die "Changing '$opt' not possible while VM is running and hotplug disabled.\n";
+ }
+ if ($running && $need_offlinevm) {
+ die "Changing '$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
More information about the pve-devel
mailing list