[pve-devel] [PATCH 2/7] vmconfig_hotplug_pending : add update_net

Alexandre Derumier aderumier at odiso.com
Tue Nov 18 13:39:47 CET 2014


Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 PVE/API2/Qemu.pm  |   44 ++-----------------------
 PVE/QemuServer.pm |   92 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 pve-bridge        |    4 +++
 3 files changed, 97 insertions(+), 43 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index a1f0f41..b87389f 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -813,46 +813,6 @@ my $vmconfig_update_disk = sub {
     }
 };
 
-my $vmconfig_update_net = sub {
-    my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $value) = @_;
-
-    if ($conf->{$opt} && PVE::QemuServer::check_running($vmid)) {
-	my $oldnet = PVE::QemuServer::parse_net($conf->{$opt});
-	my $newnet = PVE::QemuServer::parse_net($value);
-
-	if($oldnet->{model} ne $newnet->{model}){
-	    #if model change, we try to hot-unplug
-            die "error hot-unplug $opt for update" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
-	}else{
-
-	    if($newnet->{bridge} && $oldnet->{bridge}){
-		my $iface = "tap".$vmid."i".$1 if $opt =~ m/net(\d+)/;
-
-		if($newnet->{rate} ne $oldnet->{rate}){
-		    PVE::Network::tap_rate_limit($iface, $newnet->{rate});
-		}
-
-		if(($newnet->{bridge} ne $oldnet->{bridge}) || ($newnet->{tag} ne $oldnet->{tag}) || ($newnet->{firewall} ne $oldnet->{firewall})){
-		    PVE::Network::tap_unplug($iface);
-		    PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
-		}
-
-	    }else{
-		#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);
-	    }
-	}
-
-    }
-    $conf->{$opt} = $value;
-    PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
-    $conf = PVE::QemuServer::load_config($vmid); # update/reload
-
-    my $net = PVE::QemuServer::parse_net($conf->{$opt});
-
-    die "error hotplug $opt" if !PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt, $net);
-};
-
 # POST/PUT {vmid}/config implementation
 #
 # The original API used PUT (idempotent) an we assumed that all operations
@@ -1040,8 +1000,8 @@ my $update_vm_api  = sub {
 
 		} elsif ($opt =~ m/^net(\d+)$/) { #nics
 
-		    &$vmconfig_update_net($rpcenv, $authuser, $conf, $storecfg, $vmid,
-					  $opt, $param->{$opt});
+		   ## &$vmconfig_update_net($rpcenv, $authuser, $conf, $storecfg, $vmid,
+		##			  $opt, $param->{$opt});
 
 		} else {
 
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 015bb29..1d0d4a4 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3481,12 +3481,18 @@ sub vmconfig_hotplug_pending {
 	$conf = load_config($vmid); # update/reload
     }
 
-    return if !$conf->{hotplug};
+    #return if !$conf->{hotplug};  #some changes can't be done also without hotplug
 
     # fixme: implement disk/network hotplug here
+    foreach my $opt (keys %{$conf->{pending}}) {
+	if ($opt =~ m/^net(\d+)$/) { 
+	    vmconfig_update_net($storecfg, $conf, $vmid, $opt);
+	}
+    }
 
 }
 
+
 sub vmconfig_apply_pending {
     my ($vmid, $conf, $storecfg, $running) = @_;
 
@@ -3533,6 +3539,90 @@ sub vmconfig_apply_pending {
     }
 }
 
+my $safe_num_ne = sub {
+    my ($a, $b) = @_;
+
+    return 0 if !defined($a) && !defined($b);
+    return 1 if !defined($a);
+    return 1 if !defined($b);
+
+    return $a != $b;
+};
+
+my $safe_string_ne = sub {
+    my ($a, $b) = @_;
+
+    return 0 if !defined($a) && !defined($b);
+    return 1 if !defined($a);
+    return 1 if !defined($b);
+
+    return $a ne $b;
+};
+
+sub vmconfig_update_net {
+    my ($storecfg, $conf, $vmid, $opt) = @_;
+
+    if ($conf->{$opt}) {
+        my $running = PVE::QemuServer::check_running($vmid);
+
+        my $oldnet = PVE::QemuServer::parse_net($conf->{$opt});
+        my $newnet = PVE::QemuServer::parse_net($conf->{pending}->{$opt});
+
+        if(&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
+           &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
+           &$safe_num_ne($oldnet->{queues}, $newnet->{queues})){
+            #for non online change, we try to hot-unplug
+            if(!PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt)){
+                return;
+            }else{
+		delete $conf->{$opt};
+		PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+	    }
+        }else{
+
+            if($newnet->{bridge} && $oldnet->{bridge}){
+                my $iface = "tap".$vmid."i".$1 if $opt =~ m/net(\d+)/;
+
+                if(&$safe_num_ne($oldnet->{rate}, $newnet->{rate})){
+                    PVE::Network::tap_rate_limit($iface, $newnet->{rate});
+                }
+
+                if(&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
+                   &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
+                   &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})){
+                    PVE::Network::tap_unplug($iface);
+                    PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
+                }
+
+                $conf->{$opt} = $conf->{pending}->{$opt};
+                delete $conf->{pending}->{$opt};
+                PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+                return;
+
+            }else{
+
+                #if bridge/nat mode change, we try to hot-unplug
+
+                if(!PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt)){
+                    warn "error hot-unplug $opt for update";
+                    return;
+                }
+            }
+        }
+
+    }
+
+    if($conf->{pending}->{$opt}){
+        my $net = PVE::QemuServer::parse_net($conf->{pending}->{$opt});
+        if(PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt, $net, $conf->{pending}->{$opt})){
+	    $conf->{$opt} = $conf->{pending}->{$opt};
+	    delete $conf->{pending}->{$opt};
+	    PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+	}
+    }
+
+};
+
 sub vm_start {
     my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
 
diff --git a/pve-bridge b/pve-bridge
index d6c5eb8..caee33b 100755
--- a/pve-bridge
+++ b/pve-bridge
@@ -20,6 +20,10 @@ my $migratedfrom = $ENV{PVE_MIGRATED_FROM};
 
 my $conf = PVE::QemuServer::load_config($vmid, $migratedfrom);
 
+if ($conf->{pending}->{$netid}){
+    $conf = $conf->{pending};
+}
+
 die "unable to get network config '$netid'\n"
     if !$conf->{$netid};
 
-- 
1.7.10.4




More information about the pve-devel mailing list