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 378109A4C9 for ; Mon, 8 May 2023 13:04:13 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1046DB881 for ; Mon, 8 May 2023 13:03:43 +0200 (CEST) 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 for ; Mon, 8 May 2023 13:03:42 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 3608647AB1 for ; Mon, 8 May 2023 13:03:42 +0200 (CEST) From: Dominik Csapak To: pbs-devel@lists.proxmox.com Date: Mon, 8 May 2023 13:03:41 +0200 Message-Id: <20230508110341.3590657-1-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.015 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record T_SCC_BODY_TEXT_LINE -0.01 - Subject: [pbs-devel] [PATCH proxmox-backup] fix #4719: wait for tape to be available in changer X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 May 2023 11:04:13 -0000 instead of aborting. If the tape is currently e.g. offline, in an import/export slot or in the wrong drive, this gives the user the chance to manually move it/insert it, so that the backup job can continue. Send an e-mail like we do on a standalone drive, but adapt the messages to contain the changer instead of the drive. This can help when not all tapes are currently available in the changer. Signed-off-by: Dominik Csapak --- src/server/email_notifications.rs | 19 ++++++---- src/tape/drive/mod.rs | 59 +++++++++++++++++++------------ 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/server/email_notifications.rs b/src/server/email_notifications.rs index 1224191c..27b638bb 100644 --- a/src/server/email_notifications.rs +++ b/src/server/email_notifications.rs @@ -540,27 +540,34 @@ pub fn send_tape_backup_status( /// Send email to a person to request a manual media change pub fn send_load_media_email( - drive: &str, + changer: bool, + device: &str, label_text: &str, to: &str, reason: Option, ) -> Result<(), Error> { use std::fmt::Write as _; - let subject = format!("Load Media '{label_text}' request for drive '{drive}'"); + let device_type = if changer { "changer" } else { "drive" }; + + let subject = format!("Load Media '{label_text}' request for {device_type} '{device}'"); let mut text = String::new(); if let Some(reason) = reason { let _ = write!( text, - "The drive has the wrong or no tape inserted. Error:\n{reason}\n\n" + "The {device_type} has the wrong or no tape(s) inserted. Error:\n{reason}\n\n" ); } - text.push_str("Please insert the requested media into the backup drive.\n\n"); - - let _ = writeln!(text, "Drive: {drive}"); + if changer { + text.push_str("Please insert the requested media into the changer.\n\n"); + let _ = writeln!(text, "Changer: {device}"); + } else { + text.push_str("Please insert the requested media into the backup drive.\n\n"); + let _ = writeln!(text, "Drive: {device}"); + } let _ = writeln!(text, "Media: {label_text}"); send_job_status_mail(to, &subject, &text) diff --git a/src/tape/drive/mod.rs b/src/tape/drive/mod.rs index c69ebc63..86f01201 100644 --- a/src/tape/drive/mod.rs +++ b/src/tape/drive/mod.rs @@ -298,6 +298,7 @@ enum TapeRequestError { OpenFailed(String), WrongLabel(String), ReadFailed(String), + LoadingFailed(String), } impl std::fmt::Display for TapeRequestError { @@ -321,6 +322,9 @@ impl std::fmt::Display for TapeRequestError { TapeRequestError::ReadFailed(reason) => { write!(f, "tape read failed - {}", reason) } + TapeRequestError::LoadingFailed(reason) => { + write!(f, "could not load tape into drive - {}", reason) + } } } } @@ -374,40 +378,31 @@ pub fn request_and_load_media( let label_text = label.label_text.clone(); - if drive_config.changer.is_some() { - task_log!( - worker, - "loading media '{}' into drive '{}'", - label_text, - drive - ); - - let mut changer = MtxMediaChanger::with_drive_config(&drive_config)?; - changer.load_media(&label_text)?; - - let mut handle: Box = - Box::new(open_lto_tape_drive(&drive_config)?); - - let media_id = check_label(handle.as_mut(), &label.uuid)?; - - return Ok((handle, media_id)); - } - let mut last_error = TapeRequestError::None; + let changer = &drive_config.changer; + let update_and_log_request_error = |old: &mut TapeRequestError, new: TapeRequestError| -> Result<(), Error> { if new != *old { task_log!(worker, "{}", new); + let (device_type, device) = if let Some(changer) = changer { + ("changer", changer.as_str()) + } else { + ("drive", drive) + }; + task_log!( worker, - "Please insert media '{}' into drive '{}'", + "Please insert media '{}' into {} '{}'", label_text, - drive + device_type, + device ); if let Some(to) = notify_email { send_load_media_email( - drive, + changer.is_some(), + device, &label_text, to, Some(new.to_string()), @@ -427,13 +422,31 @@ pub fn request_and_load_media( worker.check_abort()?; std::thread::sleep(std::time::Duration::from_millis(100)); } - } else { + } else if drive_config.changer.is_none() { task_log!( worker, "Checking for media '{}' in drive '{}'", label_text, drive ); + } else { + task_log!( + worker, + "trying to load media '{}' into drive '{}'", + label_text, + drive + ); + } + + if drive_config.changer.is_some() { + let mut changer = MtxMediaChanger::with_drive_config(&drive_config)?; + if let Err(err) = changer.load_media(&label_text) { + update_and_log_request_error( + &mut last_error, + TapeRequestError::LoadingFailed(err.to_string()), + )?; + continue; + } } let mut handle = match open_lto_tape_drive(&drive_config) { -- 2.30.2