Signed-off-by: Alexandre Derumier <aderum...@odiso.com> Signed-off-by: Dietmar Maurer <diet...@proxmox.com> --- PVE/API2/Qemu.pm | 44 ++--------------------------------- PVE/QemuServer.pm | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++- pve-bridge | 8 +++++-- 3 files changed, 74 insertions(+), 45 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index 98a42fe..ea045c9 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -897,46 +897,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 @@ -1128,8 +1088,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 6642928..c568dfd 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -3032,6 +3032,7 @@ sub vm_devices_list { return $devices; } +# fixme: this should raise exceptions on error! sub vm_deviceplug { my ($storecfg, $conf, $vmid, $deviceid, $device) = @_; @@ -3073,7 +3074,7 @@ sub vm_deviceplug { return undef if !qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device); return undef if !qemu_driveadd($storecfg, $vmid, $device); my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device); - if(!qemu_deviceadd($vmid, $devicefull)) { + if(!qemu_deviceadd($vmid, $devicefull)) { # fixme: use qemu_deviceaddverify? qemu_drivedel($vmid, $deviceid); return undef; } @@ -3101,6 +3102,7 @@ sub vm_deviceplug { return 1; } +# fixme: this should raise exceptions on error! sub vm_deviceunplug { my ($vmid, $conf, $deviceid) = @_; @@ -3532,6 +3534,9 @@ sub vmconfig_hotplug_pending { } elsif ($opt eq 'cores') { die "skip\n" if !$hotplug; qemu_cpu_hotplug($vmid, $conf, 1); + } elsif ($opt =~ m/^net(\d+)$/) { + die "skip\n" if !$hotplug; + vm_deviceunplug($vmid, $conf, $opt); } else { die "skip\n"; } @@ -3566,6 +3571,9 @@ sub vmconfig_hotplug_pending { # allow manual ballooning if shares is set to zero my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory}; vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024); + } elsif ($opt =~ m/^net(\d+)$/) { + # some changes can be done without hotplug + vmconfig_update_net($storecfg, $conf, $vmid, $opt, $value); } else { die "skip\n"; # skip non-hot-pluggable options } @@ -3626,6 +3634,63 @@ 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, $value) = @_; + + my $newnet = parse_net($value); + + if ($conf->{$opt}) { + my $oldnet = parse_net($conf->{$opt}); + + if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) || + &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) || + &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) || + !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change + + # for non online change, we try to hot-unplug + die "skip\n" if !$conf->{hotplug}; + vm_deviceunplug($vmid, $conf, $opt); + } else { + + die "internal error" if $opt !~ m/net(\d+)/; + my $iface = "tap${vmid}i$1"; + + 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}); + } + } + } + + vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet); +} + sub vm_start { my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_; diff --git a/pve-bridge b/pve-bridge index d6c5eb8..1b9801d 100755 --- a/pve-bridge +++ b/pve-bridge @@ -20,10 +20,14 @@ my $migratedfrom = $ENV{PVE_MIGRATED_FROM}; my $conf = PVE::QemuServer::load_config($vmid, $migratedfrom); +my $netconf = $conf->{$netid}; + +$netconf = $conf->{pending}->{$netid} if !$migratedfrom && defined($conf->{pending}->{$netid}); + die "unable to get network config '$netid'\n" - if !$conf->{$netid}; + if !defined($netconf); -my $net = PVE::QemuServer::parse_net($conf->{$netid}); +my $net = PVE::QemuServer::parse_net($netconf); die "unable to parse network config '$netid'\n" if !$net; PVE::Network::tap_create($iface, $net->{bridge}); -- 1.7.10.4 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel