From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 606381FF09D for ; Sun, 01 Nov 2026 23:59:39 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 68980216EA; Sun, 01 Nov 2026 23:59:14 +0100 (CET) From: Thomas Lamprecht To: pve-devel@lists.proxmox.com Subject: [PATCH manager 06/19] vzdump: notification: capture guest logs right after each backup Date: Sun, 1 Nov 2026 23:58:33 +0100 Message-ID: <20261101225849.884587-7-t.lamprecht@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261101225849.884587-1-t.lamprecht@proxmox.com> References: <20261101225849.884587-1-t.lamprecht@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1793573948196 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.401 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) 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 Message-ID-Hash: H4VJRFZAAQ7ENKP6H3O26F4MHAW3EI4G X-Message-ID-Hash: H4VJRFZAAQ7ENKP6H3O26F4MHAW3EI4G X-MailFrom: t.lamprecht@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: The log of a guest backup is written to a path derived from the guest alone and was only read back when sending the notification at the end of the job. This relies on no other backup of the guest starting in the meantime, which no longer holds once backup jobs can run alongside each other. Read the log as the last step of each guest backup instead. Logs longer than the notification size limit are cut, as they would not be included anyway. Signed-off-by: Thomas Lamprecht --- PVE/VZDump.pm | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/PVE/VZDump.pm b/PVE/VZDump.pm index defe9e0a5..d07ced61b 100644 --- a/PVE/VZDump.pm +++ b/PVE/VZDump.pm @@ -368,24 +368,35 @@ sub read_vzdump_defaults { return $res; } -my sub read_backup_task_logs { +use constant MAX_LOG_SIZE => 1024 * 1024; + +my sub read_guest_log { + my ($path) = @_; + + open(my $fh, '<', $path) or return undef; + my $log = ''; + read($fh, $log, MAX_LOG_SIZE + 1); # anything longer is not sent anyway + close($fh); + + return $log; +} + +my sub format_backup_task_logs { my ($task_list) = @_; my $task_logs = ""; for my $task (@$task_list) { my $vmid = $task->{vmid}; - my $log_file = $task->{tmplog}; if (!$task->{tmplog}) { $task_logs .= "$vmid: no log available\n\n"; next; } - if (open(my $TMP, '<', "$log_file")) { - while (my $line = <$TMP>) { + if (defined(my $log = $task->{log})) { + for my $line (split(/^/m, $log)) { next if $line =~ /^status: \d+/; # not useful in mails $task_logs .= encode8bit("$vmid: $line"); } - close($TMP); } else { $task_logs .= "$vmid: Could not open log file\n\n"; } @@ -484,8 +495,6 @@ my sub get_hostname { return $hostname; } -use constant MAX_LOG_SIZE => 1024 * 1024; - sub send_notification { my ($self, $tasklist, $total_time, $err, $detail_pre, $detail_post) = @_; @@ -514,7 +523,7 @@ sub send_notification { my $text_log_part = "$cmdline\n\n"; $text_log_part .= $detail_pre . "\n" if defined($detail_pre); - $text_log_part .= read_backup_task_logs($tasklist); + $text_log_part .= format_backup_task_logs($tasklist); $text_log_part .= $detail_post if defined($detail_post); if (length($text_log_part) > MAX_LOG_SIZE) { @@ -1385,6 +1394,8 @@ sub exec_backup_task { eval { $self->run_hook_script('log-end', $task); }; debugmsg('warn', $@) if $@; # message already contains command with phase name + $task->{log} = read_guest_log($task->{tmplog}) if $task->{tmplog}; + die $err if $err && $err =~ m/^interrupted by signal$/; } -- 2.47.3