tape: abort backup when we detect critical tape alert flags
This commit is contained in:
parent
7273ba3de2
commit
5843268c47
@ -23,6 +23,7 @@ use proxmox_backup::{
|
||||
LINUX_DRIVE_PATH_SCHEMA,
|
||||
},
|
||||
tape::{
|
||||
TapeDriver,
|
||||
linux_tape::{
|
||||
LinuxTapeHandle,
|
||||
open_linux_tape_device,
|
||||
|
@ -317,27 +317,6 @@ impl LinuxTapeHandle {
|
||||
result.map_err(|err| format_err!("{}", err))
|
||||
}
|
||||
|
||||
/// Read Tape Alert Flags
|
||||
///
|
||||
/// Note: Only 'root' user may run RAW SG commands, so we need to
|
||||
/// spawn setuid binary 'sg-tape-cmd'.
|
||||
pub fn tape_alert_flags(&mut self) -> Result<TapeAlertFlags, Error> {
|
||||
|
||||
if nix::unistd::Uid::effective().is_root() {
|
||||
return read_tape_alert_flags(&mut self.file);
|
||||
}
|
||||
|
||||
let mut command = std::process::Command::new(
|
||||
"/usr/lib/x86_64-linux-gnu/proxmox-backup/sg-tape-cmd");
|
||||
command.args(&["tape-alert-flags"]);
|
||||
command.stdin(unsafe { std::process::Stdio::from_raw_fd(self.file.as_raw_fd())});
|
||||
let output = run_command(command, None)?;
|
||||
let result: Result<u64, String> = serde_json::from_str(&output)?;
|
||||
result
|
||||
.map_err(|err| format_err!("{}", err))
|
||||
.map(|bits| TapeAlertFlags::from_bits_truncate(bits))
|
||||
}
|
||||
|
||||
/// Read Volume Statistics
|
||||
///
|
||||
/// Note: Only 'root' user may run RAW SG commands, so we need to
|
||||
@ -479,6 +458,27 @@ impl TapeDriver for LinuxTapeHandle {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Read Tape Alert Flags
|
||||
///
|
||||
/// Note: Only 'root' user may run RAW SG commands, so we need to
|
||||
/// spawn setuid binary 'sg-tape-cmd'.
|
||||
fn tape_alert_flags(&mut self) -> Result<TapeAlertFlags, Error> {
|
||||
|
||||
if nix::unistd::Uid::effective().is_root() {
|
||||
return read_tape_alert_flags(&mut self.file);
|
||||
}
|
||||
|
||||
let mut command = std::process::Command::new(
|
||||
"/usr/lib/x86_64-linux-gnu/proxmox-backup/sg-tape-cmd");
|
||||
command.args(&["tape-alert-flags"]);
|
||||
command.stdin(unsafe { std::process::Stdio::from_raw_fd(self.file.as_raw_fd())});
|
||||
let output = run_command(command, None)?;
|
||||
let result: Result<u64, String> = serde_json::from_str(&output)?;
|
||||
result
|
||||
.map_err(|err| format_err!("{}", err))
|
||||
.map(|bits| TapeAlertFlags::from_bits_truncate(bits))
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a single EOF mark without flushing buffers
|
||||
|
@ -151,6 +151,14 @@ pub trait TapeDriver {
|
||||
|
||||
/// Eject media
|
||||
fn eject_media(&mut self) -> Result<(), Error>;
|
||||
|
||||
/// Read Tape Alert Flags
|
||||
///
|
||||
/// This make only sense for real LTO drives. Virtual tape drives should
|
||||
/// simply return empty flags (default).
|
||||
fn tape_alert_flags(&mut self) -> Result<TapeAlertFlags, Error> {
|
||||
Ok(TapeAlertFlags::empty())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the media changer (MediaChange + name) associated with a tape drive.
|
||||
|
@ -25,6 +25,7 @@ use crate::{
|
||||
MediaSetCatalog,
|
||||
tape_write_snapshot_archive,
|
||||
request_and_load_media,
|
||||
tape_alert_flags_critical,
|
||||
file_formats::MediaSetLabel,
|
||||
},
|
||||
};
|
||||
@ -150,6 +151,15 @@ impl PoolWriter {
|
||||
let (mut drive, old_media_id) =
|
||||
request_and_load_media(worker, &drive_config, &self.drive_name, media.label())?;
|
||||
|
||||
// test for critical tape alert flags
|
||||
let alert_flags = drive.tape_alert_flags()?;
|
||||
if !alert_flags.is_empty() {
|
||||
worker.log(format!("TapeAlertFlags: {:?}", alert_flags));
|
||||
if tape_alert_flags_critical(alert_flags) {
|
||||
bail!("aborting due to critical tape alert flags: {:?}", alert_flags);
|
||||
}
|
||||
}
|
||||
|
||||
let catalog = update_media_set_label(
|
||||
worker,
|
||||
drive.as_mut(),
|
||||
|
Loading…
Reference in New Issue
Block a user