diff --git a/PVE/CLI/pvesm.pm b/PVE/CLI/pvesm.pm index 0432450..ae1bc3d 100755 --- a/PVE/CLI/pvesm.pm +++ b/PVE/CLI/pvesm.pm @@ -269,7 +269,9 @@ __PACKAGE__->register_method ({ enum => $KNOWN_EXPORT_FORMATS, }, filename => { - description => "Source file name", + description => "Source file name. For '-' stdin is used, the " . + "tcp:// format allows to use a TCP connection as input. " . + "Else, the file is treated as common file.", type => 'string', }, base => { @@ -304,6 +306,36 @@ __PACKAGE__->register_method ({ my $infh; if ($filename eq '-') { $infh = \*STDIN; + } elsif ($filename =~ m!^tcp://(([^/]+)(/\d+)?)$!) { + my ($cidr, $ip, $subnet) = ($1, $2, $3); + if ($subnet) { # got real CIDR notation, not just IP + $ip = PVE::Cluster::get_local_migration_ip($cidr); + } + my $family = PVE::Tools::get_host_address_family($ip); + my $port = PVE::Tools::next_migrate_port($family, $ip); + + my $sock_params = { + Listen => 1, + ReuseAddr => 1, + Proto => &Socket::IPPROTO_TCP, + GetAddrInfoFlags => 0, + LocalAddr => $ip, + LocalPort => $port, + }; + my $socket = IO::Socket::IP->new(%$sock_params) + or die "failed to open socket: $!\n"; + + print "$ip\n$port\n"; # tell remote where to connect + *STDOUT->flush(); + + my $prev_alarm = alarm 0; + local $SIG{ALRM} = sub { die "timed out waiting for client\n" }; + alarm 30; + my $client = $socket->accept; # Wait for a client + alarm $prev_alarm; + close($socket); + + $infh = \*$client; } else { sysopen($infh, $filename, O_RDONLY) or die "open($filename): $!\n"; diff --git a/PVE/Storage.pm b/PVE/Storage.pm index 0ce942a..5925c69 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -590,17 +590,15 @@ sub storage_migrate { die "cannot migrate from storage type '$scfg->{type}' to '$tcfg->{type}'\n" if !@formats; my $format = $formats[0]; - my @insecurecmd; + my $import_fn = '-'; # let pvesm import read from stdin per default if ($insecure) { - @insecurecmd = ('pvecm', 'mtunnel', '-run-command', 1); - if (my $network = $target_sshinfo->{network}) { - push @insecurecmd, '-migration_network', $network; - } + my $net = $target_sshinfo->{network} // $target_sshinfo->{ip}; + $import_fn = "tcp://$net"; } $with_snapshots = $with_snapshots ? 1 : 0; # sanitize for passing as cli parameter my $send = ['pvesm', 'export', $volid, $format, '-', '-with-snapshots', $with_snapshots]; - my $recv = [@$ssh, @insecurecmd, '--', 'pvesm', 'import', $volid, $format, '-', '-with-snapshots', $with_snapshots]; + my $recv = [@$ssh, '--', 'pvesm', 'import', $volid, $format, $import_fn, '-with-snapshots', $with_snapshots]; if (defined($snapshot)) { push @$send, '-snapshot', $snapshot }