Signed-off-by: Alexandre Derumier <aderum...@odiso.com>
---
 PVE/API2/Qemu.pm  |   44 ++-------------------------
 PVE/QemuServer.pm |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 pve-bridge        |    4 +++
 3 files changed, 91 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 141a21c..b948de8 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3521,12 +3521,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) = @_;
 
@@ -3573,6 +3579,84 @@ 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)){
+                warn "error hot-unplug $opt for update";
+                return;
+            }
+        }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});
+        warn "error hotplug $opt" 
if(!PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt, $net, 
$conf->{pending}->{$opt}));
+    }
+
+};
+
 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

_______________________________________________
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to