[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