From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id B49CA881BB for ; Wed, 5 Jan 2022 10:59:05 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id A561D2598A for ; Wed, 5 Jan 2022 10:59:05 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id BF1882597F for ; Wed, 5 Jan 2022 10:59:04 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 965D3453B2 for ; Wed, 5 Jan 2022 10:59:04 +0100 (CET) Message-ID: <794ef6ee-7061-4b07-d91a-783fbfe19688@proxmox.com> Date: Wed, 5 Jan 2022 10:59:03 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.4.1 Content-Language: en-US To: pve-devel@lists.proxmox.com, =?UTF-8?Q?Fabian_Gr=c3=bcnbichler?= References: <20211222135257.3242938-1-f.gruenbichler@proxmox.com> <20211222135257.3242938-21-f.gruenbichler@proxmox.com> From: Fabian Ebner In-Reply-To: <20211222135257.3242938-21-f.gruenbichler@proxmox.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.671 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment NICE_REPLY_A -1.057 Looks like a legit reply (A) SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [storage.pm] Subject: Re: [pve-devel] [PATCH v3 storage 3/4] storage_migrate: pull out import/export_prepare X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Jan 2022 09:59:05 -0000 Am 22.12.21 um 14:52 schrieb Fabian Grünbichler: > for re-use with remote migration, where import and export happen on > different clusters connected via a websocket instead of SSH tunnel. > > no semantic changes intended. > > Signed-off-by: Fabian Grünbichler > --- > new in v3 > > using $opts across the board in storage_migrate to prevent future bugs > where options get out of sync between helper calls.. > > PVE/Storage.pm | 113 ++++++++++++++++++++++++++++++------------------- > 1 file changed, 70 insertions(+), 43 deletions(-) > > diff --git a/PVE/Storage.pm b/PVE/Storage.pm > index 4f3a44a..976bd63 100755 > --- a/PVE/Storage.pm > +++ b/PVE/Storage.pm > @@ -651,16 +651,70 @@ sub storage_migrate_snapshot { > return $scfg->{type} eq 'zfspool' || $scfg->{type} eq 'btrfs'; > } > > -sub storage_migrate { > - my ($cfg, $volid, $target_sshinfo, $target_storeid, $opts, $logfunc) = @_; > +my $volume_import_prepare = sub { > + my ($volid, $format, $path, $apiver, $opts) = @_; > > my $base_snapshot = $opts->{base_snapshot}; > my $snapshot = $opts->{snapshot}; > - my $ratelimit_bps = $opts->{ratelimit_bps}; > - my $insecure = $opts->{insecure}; > my $with_snapshots = $opts->{with_snapshots} ? 1 : 0; > + my $migration_snapshot = $opts->{migration_snapshot} ? 1 : 0; > my $allow_rename = $opts->{allow_rename} ? 1 : 0; > > + my $recv = ['pvesm', 'import', $volid, $format, $path, '-with-snapshots', $with_snapshots]; > + if (defined($snapshot)) { > + push @$recv, '-snapshot', $snapshot; > + } > + if ($migration_snapshot) { > + push @$recv, '-delete-snapshot', $snapshot; > + } > + push @$recv, '-allow-rename', $allow_rename if $apiver >= 5; > + > + if (defined($base_snapshot)) { > + # Check if the snapshot exists on the remote side: > + push @$recv, '-base', $base_snapshot if $apiver >= 9; > + } > + > + return $recv; > +}; > + > +my $volume_export_prepare = sub { > + my ($cfg, $volid, $format, $logfunc, $opts) = @_; > + my $base_snapshot = $opts->{base_snapshot}; > + my $snapshot = $opts->{snapshot}; > + my $with_snapshots = $opts->{with_snapshots} ? 1 : 0; > + my $migration_snapshot = $opts->{migration_snapshot} ? 1 : 0; > + my $ratelimit_bps = $opts->{ratelimit_bps}; > + > + my $send = ['pvesm', 'export', $volid, $format, '-', '-with-snapshots', $with_snapshots]; > + if (defined($snapshot)) { > + push @$send, '-snapshot', $snapshot; > + } > + if (defined($base_snapshot)) { > + push @$send, '-base', $base_snapshot; > + } > + > + my @cstream; > + if (defined($ratelimit_bps)) { > + @cstream = [ '/usr/bin/cstream', '-t', $ratelimit_bps ]; Nit: It's Perl I guess and it seems to work, but assigning an array ref to an array looks weird to me. Why not keep the surrounding ( )? Or better, can't we just avoid wrapping the ref in an array altogether? > + $logfunc->("using a bandwidth limit of $ratelimit_bps bps for transferring '$volid'") if $logfunc; > + } > + > + volume_snapshot($cfg, $volid, $snapshot) if $migration_snapshot; > + > + if (defined($snapshot)) { > + activate_volumes($cfg, [$volid], $snapshot); > + } else { > + activate_volumes($cfg, [$volid]); > + } > + > + return [ $send, @cstream ]; > +}; > + > +sub storage_migrate { > + my ($cfg, $volid, $target_sshinfo, $target_storeid, $opts, $logfunc) = @_; > + > + my $insecure = $opts->{insecure}; > + > my ($storeid, $volname) = parse_volume_id($volid); > > my $scfg = storage_config($cfg, $storeid); > @@ -688,19 +742,12 @@ sub storage_migrate { > my $ssh_base = PVE::SSHInfo::ssh_info_to_command_base($target_sshinfo); > local $ENV{RSYNC_RSH} = PVE::Tools::cmd2string($ssh_base); > > - my @cstream; > - if (defined($ratelimit_bps)) { > - @cstream = ([ '/usr/bin/cstream', '-t', $ratelimit_bps ]); > - $logfunc->("using a bandwidth limit of $ratelimit_bps bps for transferring '$volid'") if $logfunc; > + if (!defined($opts->{snapshot})) { > + $opts->{migration_snapshot} = storage_migrate_snapshot($cfg, $target_storeid); > + $opts->{snapshot} = '__migration__' if $opts->{migration_snapshot}; > } > > - my $migration_snapshot; > - if (!defined($snapshot)) { > - $migration_snapshot = storage_migrate_snapshot->($cfg, $target_storeid); > - $snapshot = '__migration__' if $migration_snapshot; > - } > - > - my @formats = volume_transfer_formats($cfg, $volid, $target_volid, $snapshot, $base_snapshot, $with_snapshots); > + my @formats = volume_transfer_formats($cfg, $volid, $target_volid, $opts->{snapshot}, $opts->{base_snapshot}, $opts->{with_snapshots}); > die "cannot migrate from storage type '$scfg->{type}' to '$tcfg->{type}'\n" if !@formats; > my $format = $formats[0]; > > @@ -715,22 +762,7 @@ sub storage_migrate { > my $match_api_version = sub { $target_apiver = $1 if $_[0] =~ m!^APIVER (\d+)$!; }; > eval { run_command($get_api_version, logfunc => $match_api_version); }; > > - my $send = ['pvesm', 'export', $volid, $format, '-', '-with-snapshots', $with_snapshots]; > - my $recv = [@$ssh, '--', 'pvesm', 'import', $target_volid, $format, $import_fn, '-with-snapshots', $with_snapshots]; > - if (defined($snapshot)) { > - push @$send, '-snapshot', $snapshot; > - push @$recv, '-snapshot', $snapshot; > - } > - if ($migration_snapshot) { > - push @$recv, '-delete-snapshot', $snapshot; > - } > - push @$recv, '-allow-rename', $allow_rename if $target_apiver >= 5; > - > - if (defined($base_snapshot)) { > - # Check if the snapshot exists on the remote side: > - push @$send, '-base', $base_snapshot; > - push @$recv, '-base', $base_snapshot if $target_apiver >= 9; > - } > + my $recv = [ @$ssh, '--', $volume_import_prepare->($target_volid, $format, $import_fn, $target_apiver, $opts)->@* ]; > > my $new_volid; > my $pattern = volume_imported_message(undef, 1); > @@ -745,19 +777,13 @@ sub storage_migrate { > } > }; > > - volume_snapshot($cfg, $volid, $snapshot) if $migration_snapshot; > - > - if (defined($snapshot)) { > - activate_volumes($cfg, [$volid], $snapshot); > - } else { > - activate_volumes($cfg, [$volid]); > - } > + my $cmds = [ $volume_export_prepare->($cfg, $volid, $format, $logfunc, $opts)->@* ]; > > eval { > if ($insecure) { > my $input = IO::File->new(); > my $info = IO::File->new(); > - open3($input, $info, $info, @{$recv}) > + open3($input, $info, $info, @$recv) > or die "receive command failed: $!\n"; > close($input); > > @@ -774,7 +800,7 @@ sub storage_migrate { > # we won't be reading from the socket > shutdown($socket, 0); > > - eval { run_command([$send, @cstream], output => '>&'.fileno($socket), errfunc => $logfunc); }; > + eval { run_command($cmds, output => '>&'.fileno($socket), errfunc => $logfunc); }; > my $send_error = $@; > > # don't close the connection entirely otherwise the receiving end > @@ -795,7 +821,8 @@ sub storage_migrate { > > die $send_error if $send_error; > } else { > - run_command([$send, @cstream, $recv], logfunc => $match_volid_and_log); > + push @$cmds, $recv; > + run_command($cmds, logfunc => $match_volid_and_log); > } > > die "unable to get ID of the migrated volume\n" > @@ -803,8 +830,8 @@ sub storage_migrate { > }; > my $err = $@; > warn "send/receive failed, cleaning up snapshot(s)..\n" if $err; > - if ($migration_snapshot) { > - eval { volume_snapshot_delete($cfg, $volid, $snapshot, 0) }; > + if ($opts->{migration_snapshot}) { > + eval { volume_snapshot_delete($cfg, $volid, $opts->{snapshot}, 0) }; > warn "could not remove source snapshot: $@\n" if $@; > } > die $err if $err;