allow dedicated migration network, bug #1177

Without this patch we use the network were the cluster traffic runs
for sending migration traffic. This is not ideal as it may hinder
cluster traffic. Further some users have a powerful network which
would be perfect for migrations, with this patch they can run the
migration traffic over such a network without having the corosync
traffic on the same network.

The network is configurable through /etc/pve/datacenter.cfg which
got a new property, namely migration. migration has two
subproperties: type (replaces the old migration_unsecure property)
and network.

For the case of a network failure or that a VM has to be moved over
another network for arbitrary other reasons I added the
migration_type and migration_network parameters to qm migrate (and
respectively vm_start as this gets used on migration).
They allow overwriting the datacenter.cfg settings.

Fixes bug #1177

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2016-10-31 09:42:31 +01:00 committed by Dietmar Maurer
parent 613d76a179
commit 2de2d6f74e
3 changed files with 69 additions and 7 deletions

View File

@ -1626,6 +1626,20 @@ __PACKAGE__->register_method({
skiplock => get_standard_option('skiplock'), skiplock => get_standard_option('skiplock'),
stateuri => get_standard_option('pve-qm-stateuri'), stateuri => get_standard_option('pve-qm-stateuri'),
migratedfrom => get_standard_option('pve-node',{ optional => 1 }), migratedfrom => get_standard_option('pve-node',{ optional => 1 }),
migration_type => {
type => 'string',
enum => ['secure', 'insecure'],
description => "Migration traffic is encrypted using an SSH " .
"tunnel by default. On secure, completely private networks " .
"this can be disabled to increase performance.",
optional => 1,
},
migration_network => {
type => 'string',
format => 'CIDR',
description => "CIDR of the (sub) network that is used for migration.",
optional => 1,
},
machine => get_standard_option('pve-qm-machine'), machine => get_standard_option('pve-qm-machine'),
}, },
}, },
@ -1657,6 +1671,14 @@ __PACKAGE__->register_method({
raise_param_exc({ migratedfrom => "Only root may use this option." }) raise_param_exc({ migratedfrom => "Only root may use this option." })
if $migratedfrom && $authuser ne 'root@pam'; if $migratedfrom && $authuser ne 'root@pam';
my $migration_type = extract_param($param, 'migration_type');
raise_param_exc({ migration_type => "Only root may use this option." })
if $migration_type && $authuser ne 'root@pam';
my $migration_network = extract_param($param, 'migration_network');
raise_param_exc({ migration_network => "Only root may use this option." })
if $migration_network && $authuser ne 'root@pam';
# read spice ticket from STDIN # read spice ticket from STDIN
my $spice_ticket; my $spice_ticket;
if ($stateuri && ($stateuri eq 'tcp') && $migratedfrom && ($rpcenv->{type} eq 'cli')) { if ($stateuri && ($stateuri eq 'tcp') && $migratedfrom && ($rpcenv->{type} eq 'cli')) {
@ -1697,7 +1719,7 @@ __PACKAGE__->register_method({
syslog('info', "start VM $vmid: $upid\n"); syslog('info', "start VM $vmid: $upid\n");
PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock, $migratedfrom, undef, PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock, $migratedfrom, undef,
$machine, $spice_ticket); $machine, $spice_ticket, $migration_network, $migration_type);
return; return;
}; };
@ -2648,6 +2670,20 @@ __PACKAGE__->register_method({
description => "Allow to migrate VMs which use local devices. Only root may use this option.", description => "Allow to migrate VMs which use local devices. Only root may use this option.",
optional => 1, optional => 1,
}, },
migration_type => {
type => 'string',
enum => ['secure', 'insecure'],
description => "Migration traffic is encrypted using an SSH " .
"tunnel by default. On secure, completely private networks " .
"this can be disabled to increase performance.",
optional => 1,
},
migration_network => {
type => 'string',
format => 'CIDR',
description => "CIDR of the (sub) network that is used for migration.",
optional => 1,
},
}, },
}, },
returns => { returns => {
@ -2677,6 +2713,13 @@ __PACKAGE__->register_method({
raise_param_exc({ force => "Only root may use this option." }) raise_param_exc({ force => "Only root may use this option." })
if $param->{force} && $authuser ne 'root@pam'; if $param->{force} && $authuser ne 'root@pam';
raise_param_exc({ migration_type => "Only root may use this option." })
if $param->{migration_type} && $authuser ne 'root@pam';
# allow root only until better network permissions are available
raise_param_exc({ migration_network => "Only root may use this option." })
if $param->{migration_network} && $authuser ne 'root@pam';
# test if VM exists # test if VM exists
my $conf = PVE::QemuConfig->load_config($vmid); my $conf = PVE::QemuConfig->load_config($vmid);

View File

@ -459,9 +459,20 @@ sub phase2 {
# secure migration use UNIX sockets now, this *breaks* compatibilty when trying # secure migration use UNIX sockets now, this *breaks* compatibilty when trying
# to migrate from new to old but *not* from old to new. # to migrate from new to old but *not* from old to new.
my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg'); my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
my $secure_migration = ($datacenterconf->{migration_unsecure}) ? 0 : 1;
if (!$secure_migration) { my $migration_type = 'secure';
if (defined($self->{opts}->{migration_type})) {
$migration_type = $self->{opts}->{migration_type};
} elsif (defined($datacenterconf->{migration}->{type})) {
$migration_type = $datacenterconf->{migration}->{type};
}
push @$cmd, '--migration_type', $migration_type;
push @$cmd, '--migration_network', $self->{opts}->{migration_network}
if $self->{opts}->{migration_network};
if ($migration_type eq 'insecure') {
push @$cmd, '--stateuri', 'tcp'; push @$cmd, '--stateuri', 'tcp';
} else { } else {
push @$cmd, '--stateuri', 'unix'; push @$cmd, '--stateuri', 'unix';
@ -503,7 +514,7 @@ sub phase2 {
die "unable to detect remote migration address\n" if !$raddr; die "unable to detect remote migration address\n" if !$raddr;
if ($secure_migration) { if ($migration_type eq 'secure') {
$self->log('info', "start remote tunnel"); $self->log('info', "start remote tunnel");
if ($ruri =~ /^unix:/) { if ($ruri =~ /^unix:/) {

View File

@ -4429,7 +4429,7 @@ sub vmconfig_update_disk {
sub vm_start { sub vm_start {
my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
$forcemachine, $spice_ticket) = @_; $forcemachine, $spice_ticket, $migration_network, $migration_type) = @_;
PVE::QemuConfig->lock_config($vmid, sub { PVE::QemuConfig->lock_config($vmid, sub {
my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom); my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
@ -4459,10 +4459,18 @@ sub vm_start {
my $localip = "localhost"; my $localip = "localhost";
my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg'); my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
my $nodename = PVE::INotify::nodename(); my $nodename = PVE::INotify::nodename();
if ($datacenterconf->{migration_unsecure}) {
if ($migration_type eq 'insecure') {
my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
if ($migrate_network_addr) {
$localip = $migrate_network_addr;
} else {
$localip = PVE::Cluster::remote_node_ip($nodename, 1); $localip = PVE::Cluster::remote_node_ip($nodename, 1);
}
$localip = "[$localip]" if Net::IP::ip_is_ipv6($localip); $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
} }
my $pfamily = PVE::Tools::get_host_address_family($nodename); my $pfamily = PVE::Tools::get_host_address_family($nodename);
$migrate_port = PVE::Tools::next_migrate_port($pfamily); $migrate_port = PVE::Tools::next_migrate_port($pfamily);
$migrate_uri = "tcp:${localip}:${migrate_port}"; $migrate_uri = "tcp:${localip}:${migrate_port}";