[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