mirror of
https://git.proxmox.com/git/proxmox-backup
synced 2025-08-04 14:38:58 +00:00
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:
parent
2ebe7bb54a
commit
bdce7fa154
@ -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)
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user