vmconfig_hotplug_pending : add update_net

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
This commit is contained in:
Dietmar Maurer 2014-11-25 06:58:33 +01:00
parent e56beedaba
commit 3eec576714
3 changed files with 75 additions and 46 deletions

View 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 # POST/PUT {vmid}/config implementation
# #
# The original API used PUT (idempotent) an we assumed that all operations # 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 } elsif ($opt =~ m/^net(\d+)$/) { #nics
&$vmconfig_update_net($rpcenv, $authuser, $conf, $storecfg, $vmid, # &$vmconfig_update_net($rpcenv, $authuser, $conf, $storecfg, $vmid,
$opt, $param->{$opt}); # $opt, $param->{$opt});
} else { } else {

View File

@ -3153,6 +3153,7 @@ sub vm_devices_list {
return $devices; return $devices;
} }
# fixme: this should raise exceptions on error!
sub vm_deviceplug { sub vm_deviceplug {
my ($storecfg, $conf, $vmid, $deviceid, $device) = @_; 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_findorcreatescsihw($storecfg,$conf, $vmid, $device);
return undef if !qemu_driveadd($storecfg, $vmid, $device); return undef if !qemu_driveadd($storecfg, $vmid, $device);
my $devicefull = print_drivedevice_full($storecfg, $conf, $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); qemu_drivedel($vmid, $deviceid);
return undef; return undef;
} }
@ -3222,6 +3223,7 @@ sub vm_deviceplug {
return 1; return 1;
} }
# fixme: this should raise exceptions on error!
sub vm_deviceunplug { sub vm_deviceunplug {
my ($vmid, $conf, $deviceid) = @_; my ($vmid, $conf, $deviceid) = @_;
@ -3641,6 +3643,9 @@ sub vmconfig_hotplug_pending {
} elsif ($opt eq 'cores') { } elsif ($opt eq 'cores') {
die "skip\n" if !$hotplug; die "skip\n" if !$hotplug;
qemu_cpu_hotplug($vmid, $conf, 1); qemu_cpu_hotplug($vmid, $conf, 1);
} elsif ($opt =~ m/^net(\d+)$/) {
die "skip\n" if !$hotplug;
vm_deviceunplug($vmid, $conf, $opt);
} else { } else {
die "skip\n"; die "skip\n";
} }
@ -3675,6 +3680,9 @@ sub vmconfig_hotplug_pending {
# allow manual ballooning if shares is set to zero # allow manual ballooning if shares is set to zero
my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory}; my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024); 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 { } else {
die "skip\n"; # skip non-hot-pluggable options 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 { sub vm_start {
my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_; my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;

View File

@ -20,10 +20,14 @@ my $migratedfrom = $ENV{PVE_MIGRATED_FROM};
my $conf = PVE::QemuServer::load_config($vmid, $migratedfrom); my $conf = PVE::QemuServer::load_config($vmid, $migratedfrom);
die "unable to get network config '$netid'\n" my $netconf = $conf->{$netid};
if !$conf->{$netid};
my $net = PVE::QemuServer::parse_net($conf->{$netid}); $netconf = $conf->{pending}->{$netid} if !$migratedfrom && defined($conf->{pending}->{$netid});
die "unable to get network config '$netid'\n"
if !defined($netconf);
my $net = PVE::QemuServer::parse_net($netconf);
die "unable to parse network config '$netid'\n" if !$net; die "unable to parse network config '$netid'\n" if !$net;
PVE::Network::tap_create($iface, $net->{bridge}); PVE::Network::tap_create($iface, $net->{bridge});