]> git.proxmox.com Git - proxmox-backup.git/commitdiff
tape: abort backup when we detect critical tape alert flags
authorDietmar Maurer <dietmar@proxmox.com>
Sat, 9 Jan 2021 11:34:00 +0000 (12:34 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Sat, 9 Jan 2021 11:34:00 +0000 (12:34 +0100)
src/bin/sg-tape-cmd.rs
src/tape/drive/linux_tape.rs
src/tape/drive/mod.rs
src/tape/pool_writer.rs

index 7a16642d13835511314e8ee71bb375b17a3c8e22..769b5c1b4f63591c71b009b919e710820dc91146 100644 (file)
@@ -23,6 +23,7 @@ use proxmox_backup::{
         LINUX_DRIVE_PATH_SCHEMA,
     },
     tape::{
+        TapeDriver,
         linux_tape::{
             LinuxTapeHandle,
             open_linux_tape_device,
index 28527ee54818a220a71f2e0cbc601b8e9f2ae2b8..0fb7e67af6aa33bcc60c84be98d0b23d9567fdb4 100644 (file)
@@ -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
index db1a89a3956351d252263de82ed71aa76960e1a1..7f0593132dd4e9af768d324afeb2ea97731df166 100644 (file)
@@ -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.
index 88e2c2a3afb248911d6cd7ba1f4f60c591833422..13b6caf8d28da5f29fd36baed7f8b2dafdfc2e1a 100644 (file)
@@ -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(),