diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index ac04dffe..66dc69a2 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -1626,6 +1626,20 @@ __PACKAGE__->register_method({ skiplock => get_standard_option('skiplock'), stateuri => get_standard_option('pve-qm-stateuri'), 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'), }, }, @@ -1657,6 +1671,14 @@ __PACKAGE__->register_method({ raise_param_exc({ migratedfrom => "Only root may use this option." }) 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 my $spice_ticket; if ($stateuri && ($stateuri eq 'tcp') && $migratedfrom && ($rpcenv->{type} eq 'cli')) { @@ -1697,7 +1719,7 @@ __PACKAGE__->register_method({ syslog('info', "start VM $vmid: $upid\n"); PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock, $migratedfrom, undef, - $machine, $spice_ticket); + $machine, $spice_ticket, $migration_network, $migration_type); return; }; @@ -2648,6 +2670,20 @@ __PACKAGE__->register_method({ description => "Allow to migrate VMs which use local devices. Only root may use this option.", 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 => { @@ -2677,6 +2713,13 @@ __PACKAGE__->register_method({ raise_param_exc({ force => "Only root may use this option." }) 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 my $conf = PVE::QemuConfig->load_config($vmid); diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm index 22a49ef5..8a65fe6d 100644 --- a/PVE/QemuMigrate.pm +++ b/PVE/QemuMigrate.pm @@ -459,9 +459,20 @@ sub phase2 { # secure migration use UNIX sockets now, this *breaks* compatibilty when trying # to migrate from new to old but *not* from old to new. 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'; } else { push @$cmd, '--stateuri', 'unix'; @@ -503,7 +514,7 @@ sub phase2 { die "unable to detect remote migration address\n" if !$raddr; - if ($secure_migration) { + if ($migration_type eq 'secure') { $self->log('info', "start remote tunnel"); if ($ruri =~ /^unix:/) { diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 7cb5ffc2..9999b83e 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -4429,7 +4429,7 @@ sub vmconfig_update_disk { sub vm_start { my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, - $forcemachine, $spice_ticket) = @_; + $forcemachine, $spice_ticket, $migration_network, $migration_type) = @_; PVE::QemuConfig->lock_config($vmid, sub { my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom); @@ -4459,10 +4459,18 @@ sub vm_start { my $localip = "localhost"; my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg'); 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 = "[$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); $migrate_port = PVE::Tools::next_migrate_port($pfamily); $migrate_uri = "tcp:${localip}:${migrate_port}";