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 C4E616C403 for ; Fri, 29 Jan 2021 16:12:22 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1DEE91128A for ; Fri, 29 Jan 2021 16:11:51 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (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 firstgate.proxmox.com (Proxmox) with ESMTPS id 208B1111FB for ; Fri, 29 Jan 2021 16:11:47 +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 DE05444D5F for ; Fri, 29 Jan 2021 16:11:46 +0100 (CET) From: Fabian Ebner To: pve-devel@lists.proxmox.com Date: Fri, 29 Jan 2021 16:11:32 +0100 Message-Id: <20210129151143.10014-3-f.ebner@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210129151143.10014-1-f.ebner@proxmox.com> References: <20210129151143.10014-1-f.ebner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.004 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust 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. [qemumigrate.pm] Subject: [pve-devel] [PATCH v2 qemu-server 02/13] migration: split sync_disks into two functions 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: Fri, 29 Jan 2021 15:12:22 -0000 by making local_volumes class-accessible. One functions is for scanning all local volumes and one is for actually syncing offline volumes via storage_migrate. The exception is replicated volumes, this still happens during the scan for now. Also introduce a filter_local_volumes helper, to makes life easier. Signed-off-by: Fabian Ebner --- Changes from v1: * rebase (include the deactivate_volumes block that didn't exist back then) PVE/QemuMigrate.pm | 108 +++++++++++++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 39 deletions(-) diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm index 5c019fc..0cc13df 100644 --- a/PVE/QemuMigrate.pm +++ b/PVE/QemuMigrate.pm @@ -9,6 +9,7 @@ use POSIX qw( WNOHANG ); use Time::HiRes qw( usleep ); use PVE::Cluster; +use PVE::GuestHelpers qw(safe_string_ne); use PVE::INotify; use PVE::RPCEnvironment; use PVE::Replication; @@ -357,7 +358,7 @@ sub prepare { return $running; } -sub sync_disks { +sub scan_local_volumes { my ($self, $vmid) = @_; my $conf = $self->{vmconf}; @@ -366,12 +367,13 @@ sub sync_disks { # and their old_id => new_id pairs $self->{volumes} = []; $self->{volume_map} = {}; + $self->{local_volumes} = {}; my $storecfg = $self->{storecfg}; eval { # found local volumes and their origin - my $local_volumes = {}; + my $local_volumes = $self->{local_volumes}; my $local_volumes_errors = {}; my $other_errors = []; my $abort = 0; @@ -608,11 +610,7 @@ sub sync_disks { PVE::QemuServer::update_efidisk_size($conf); } - $self->log('info', "copying local disk images") if scalar(%$local_volumes); - foreach my $volid (sort keys %$local_volumes) { - my ($sid, $volname) = PVE::Storage::parse_volume_id($volid); - my $targetsid = PVE::QemuServer::map_storage($self->{opts}->{storagemap}, $sid); my $ref = $local_volumes->{$volid}->{ref}; if ($self->{running} && $ref eq 'config') { push @{$self->{online_local_volumes}}, $volid; @@ -624,39 +622,70 @@ sub sync_disks { } else { next if $self->{replicated_volumes}->{$volid}; push @{$self->{volumes}}, $volid; - my $opts = $self->{opts}; - # use 'migrate' limit for transfer to other node - my $bwlimit = PVE::Storage::get_bandwidth_limit('migration', [$targetsid, $sid], $opts->{bwlimit}); - # JSONSchema and get_bandwidth_limit use kbps - storage_migrate bps - $bwlimit = $bwlimit * 1024 if defined($bwlimit); - - my $storage_migrate_opts = { - 'ratelimit_bps' => $bwlimit, - 'insecure' => $opts->{migration_type} eq 'insecure', - 'with_snapshots' => $local_volumes->{$volid}->{snapshots}, - 'allow_rename' => !$local_volumes->{$volid}->{is_vmstate}, - }; - - my $logfunc = sub { $self->log('info', $_[0]); }; - my $new_volid = eval { - PVE::Storage::storage_migrate($storecfg, $volid, $self->{ssh_info}, - $targetsid, $storage_migrate_opts, $logfunc); - }; - if (my $err = $@) { - die "storage migration for '$volid' to storage '$targetsid' failed - $err\n"; - } - - $self->{volume_map}->{$volid} = $new_volid; - $self->log('info', "volume '$volid' is '$new_volid' on the target\n"); - - eval { PVE::Storage::deactivate_volumes($storecfg, [$volid]); }; - if (my $err = $@) { - $self->log('warn', $err); - } + $local_volumes->{$volid}->{migration_mode} = 'offline'; } } }; - die "Failed to sync data - $@" if $@; + die "Problem found while scanning volumes - $@" if $@; +} + +sub filter_local_volumes { + my ($self, $migration_mode) = @_; + + my $volumes = $self->{local_volumes}; + my @filtered_volids; + + foreach my $volid (sort keys %{$volumes}) { + next if defined($migration_mode) && safe_string_ne($volumes->{$volid}->{migration_mode}, $migration_mode); + push @filtered_volids, $volid; + } + + return @filtered_volids; +} + +sub sync_offline_local_volumes { + my ($self) = @_; + + my $local_volumes = $self->{local_volumes}; + my @volids = $self->filter_local_volumes('offline'); + + my $storecfg = $self->{storecfg}; + my $opts = $self->{opts}; + + $self->log('info', "copying local disk images") if scalar(@volids); + + foreach my $volid (@volids) { + my ($sid, $volname) = PVE::Storage::parse_volume_id($volid); + my $targetsid = PVE::QemuServer::map_storage($self->{opts}->{storagemap}, $sid); + # use 'migration' limit for transfer to other node + my $bwlimit = PVE::Storage::get_bandwidth_limit('migration', [$targetsid, $sid], $opts->{bwlimit}); + # JSONSchema and get_bandwidth_limit use kbps - storage_migrate bps + $bwlimit = $bwlimit * 1024 if defined($bwlimit); + + my $storage_migrate_opts = { + 'ratelimit_bps' => $bwlimit, + 'insecure' => $opts->{migration_type} eq 'insecure', + 'with_snapshots' => $local_volumes->{$volid}->{snapshots}, + 'allow_rename' => !$local_volumes->{$volid}->{is_vmstate}, + }; + + my $logfunc = sub { $self->log('info', $_[0]); }; + my $new_volid = eval { + PVE::Storage::storage_migrate($storecfg, $volid, $self->{ssh_info}, + $targetsid, $storage_migrate_opts, $logfunc); + }; + if (my $err = $@) { + die "storage migration for '$volid' to storage '$targetsid' failed - $err\n"; + } + + $self->{volume_map}->{$volid} = $new_volid; + $self->log('info', "volume '$volid' is '$new_volid' on the target\n"); + + eval { PVE::Storage::deactivate_volumes($storecfg, [$volid]); }; + if (my $err = $@) { + $self->log('warn', $err); + } + } } sub cleanup_remotedisks { @@ -704,11 +733,12 @@ sub phase1 { $conf->{lock} = 'migrate'; PVE::QemuConfig->write_config($vmid, $conf); - sync_disks($self, $vmid); - - # sync_disks fixes disk sizes to match their actual size, write changes so + # scan_local_volumes fixes disk sizes to match their actual size, write changes so # target allocates correct volumes + $self->scan_local_volumes($vmid); PVE::QemuConfig->write_config($vmid, $conf); + + $self->sync_offline_local_volumes(); }; sub phase1_cleanup { -- 2.20.1