]> git.proxmox.com Git - qemu-server.git/commitdiff
vmconfig_hotplug_pending : add update_net
authorDietmar Maurer <dietmar@proxmox.com>
Tue, 25 Nov 2014 05:58:33 +0000 (06:58 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Wed, 7 Jan 2015 05:43:11 +0000 (06:43 +0100)
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
PVE/API2/Qemu.pm
PVE/QemuServer.pm
pve-bridge

index c4f701426090dd5afcb819dd1be088b162cd2bf7..e400b6ece27ded7b3ad7821205383093284f362f 100644 (file)
@@ -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 {
 
index f914db5484ca82878daf70a1d9706f2cead43b2e..8ce42ca702f5f1672f806f32b85351f0c590b96f 100644 (file)
@@ -3153,6 +3153,7 @@ sub vm_devices_list {
     return $devices;
 }
 
+# fixme: this should raise exceptions on error!
 sub vm_deviceplug {
     my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
 
@@ -3194,7 +3195,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;
         }
@@ -3222,6 +3223,7 @@ sub vm_deviceplug {
     return 1;
 }
 
+# fixme: this should raise exceptions on error!
 sub vm_deviceunplug {
     my ($vmid, $conf, $deviceid) = @_;
 
@@ -3641,6 +3643,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";
            }
@@ -3675,6 +3680,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
            }
@@ -3735,6 +3743,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) = @_;
 
index d6c5eb8732a8a1a753307dff889259f744576ac9..1b9801d00e843205549eca9d41eb63aacaa24685 100755 (executable)
@@ -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});