fix #4719: wait for tape to be available in changer

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 <d.csapak@proxmox.com>
This commit is contained in:
Dominik Csapak 2023-05-08 13:03:41 +02:00 committed by Dietmar Maurer
parent 2ebe7bb54a
commit bdce7fa154
2 changed files with 49 additions and 29 deletions

View File

@ -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<String>,
) -> 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)

View File

@ -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<dyn TapeDriver> =
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) {