[pve-devel] [PATCH 7/8] add socat and unix socket for storage migration
Wolfgang Bumiller
w.bumiller at proxmox.com
Tue Jan 3 16:05:20 CET 2017
On Tue, Jan 03, 2017 at 03:03:18PM +0100, Alexandre Derumier wrote:
> This is a workaround for nbd infinite timeout connect
>
> Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
> ---
> PVE/QemuServer.pm | 52 ++++++++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 48 insertions(+), 4 deletions(-)
>
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index a2acf0c..9585832 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -5913,13 +5913,36 @@ sub qemu_drive_mirror {
>
> my $qemu_target;
> my $format;
> + $jobs->{"drive-$drive"} = {};
>
> - if($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+)/) {
> - $qemu_target = $dst_volid;
> + if($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+):exportname=(\S+)/) {
> my $server = $1;
> my $port = $2;
> + my $exportname = $3;
> +
> $format = "nbd";
> - die "can't connect remote nbd server $server:$port" if !PVE::Network::tcp_ping($server, $port, 2);
> + my $unixsocket = "/run/qemu-server/$vmid.mirror-drive-$drive";
> + $qemu_target = "nbd+unix:///$exportname?socket=$unixsocket";
> + my $cmd = ['socat', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=1"];
> +
> + my $pid = fork();
> + if (!defined($pid)) {
> + die "forking socat tunnel failed";
> + } elsif ($pid == 0) {
> + exec(@$cmd);
> + exit(-1);
Should be POSIX::_exit(-1);
> + } else {
The rest of this code doesn't need to be in an else block, that just
adds extra indentation and makes it look more nested than it is.
> +
> + $jobs->{"drive-$drive"}->{pid} = $pid;
> +
> + my $timeout = 0;
> + while (1) {
> + last if -S $unixsocket;
> + die if $timeout > 5;
This die has no error message?
> + $timeout++;
> + sleep 1;
> + }
> + }
> } else {
>
> my $storecfg = PVE::Storage::config();
> @@ -5940,12 +5963,12 @@ sub qemu_drive_mirror {
> print "drive mirror is starting for drive-$drive\n";
>
> eval { vm_mon_cmd($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
> +
> if (my $err = $@) {
> eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
> die "mirroring error: $err";
> }
>
> - $jobs->{"drive-$drive"} = {};
>
> qemu_drive_mirror_monitor ($vmid, $vmiddst, $jobs, $skipcomplete);
> }
> @@ -6016,6 +6039,7 @@ sub qemu_drive_mirror_monitor {
> }else {
> print "$job : complete ok : flushing pending writes\n";
> $jobs->{$job}->{complete} = 1;
> + eval { qemu_blockjobs_finish_tunnel($vmid, $job, $jobs->{$job}->{pid}) } ;
> }
> }
> }
> @@ -6053,6 +6077,7 @@ sub qemu_blockjobs_cancel {
>
> if(defined($jobs->{$job}->{cancel}) && !defined($running_jobs->{$job})) {
> print "$job : finished\n";
> + eval { qemu_blockjobs_finish_tunnel($vmid, $job, $jobs->{$job}->{pid}) } ;
> delete $jobs->{$job};
> }
> }
> @@ -6063,6 +6088,25 @@ sub qemu_blockjobs_cancel {
> }
> }
>
> +sub qemu_blockjobs_finish_tunnel {
> + my ($vmid, $job, $cpid) = @_;
> +
> + return if !$cpid;
> +
> + for (my $i = 1; $i < 20; $i++) {
> + my $waitpid = waitpid($cpid, WNOHANG);
> + last if (defined($waitpid) && ($waitpid == $cpid));
> +
> + if ($i == 10) {
> + kill(15, $cpid);
> + } elsif ($i >= 15) {
> + kill(9, $cpid);
> + }
> + sleep (1);
> + }
> + unlink "/run/qemu-server/$vmid.mirror-$job";
> +}
> +
> sub clone_disk {
> my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
> $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete) = @_;
> --
> 2.1.4
>
> _______________________________________________
> pve-devel mailing list
> pve-devel at pve.proxmox.com
> http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
More information about the pve-devel
mailing list