]> git.proxmox.com Git - proxmox-backup.git/blobdiff - src/tape/inventory.rs
typo fixes all over the place
[proxmox-backup.git] / src / tape / inventory.rs
index e8855f16f406601f3b356e05f7b80ad82288e4c6..7ae9d56504d8d6df32e02f9e6225379a904cbc51 100644 (file)
@@ -6,6 +6,7 @@
 
 use std::collections::{HashMap, BTreeMap};
 use std::path::{Path, PathBuf};
+use std::os::unix::io::AsRawFd;
 
 use anyhow::{bail, Error};
 use serde::{Serialize, Deserialize};
@@ -16,6 +17,7 @@ use proxmox::tools::{
     fs::{
         open_file_locked,
         replace_file,
+        fchown,
         file_get_json,
         CreateOptions,
     },
@@ -126,7 +128,16 @@ impl Inventory {
 
     /// Lock the database
     pub fn lock(&self) -> Result<std::fs::File, Error> {
-        open_file_locked(&self.lockfile_path, std::time::Duration::new(10, 0), true)
+        let file = open_file_locked(&self.lockfile_path, std::time::Duration::new(10, 0), true)?;
+        if cfg!(test) {
+            // We cannot use chown inside test environment (no permissions)
+            return Ok(file);
+        }
+
+        let backup_user = crate::backup::backup_user()?;
+        fchown(file.as_raw_fd(), Some(backup_user.uid), Some(backup_user.gid))?;
+
+        Ok(file)
     }
 
     fn load_media_db(path: &Path) -> Result<BTreeMap<Uuid, MediaStateEntry>, Error> {
@@ -146,12 +157,18 @@ impl Inventory {
         let list: Vec<&MediaStateEntry> = self.map.values().collect();
         let raw = serde_json::to_string_pretty(&serde_json::to_value(list)?)?;
 
-        let backup_user = crate::backup::backup_user()?;
         let mode = nix::sys::stat::Mode::from_bits_truncate(0o0640);
-        let options = CreateOptions::new()
-            .perm(mode)
-            .owner(backup_user.uid)
-            .group(backup_user.gid);
+
+        let options = if cfg!(test) {
+            // We cannot use chown inside test environment (no permissions)
+            CreateOptions::new().perm(mode)
+        } else {
+            let backup_user = crate::backup::backup_user()?;
+            CreateOptions::new()
+                .perm(mode)
+                .owner(backup_user.uid)
+                .group(backup_user.gid)
+        };
 
         replace_file(&self.inventory_path, raw.as_bytes(), options)?;
 
@@ -213,6 +230,11 @@ impl Inventory {
         self.map.get(uuid).map(|entry| &entry.id)
     }
 
+    /// List all media Uuids
+    pub fn media_list(&self) -> Vec<&Uuid> {
+        self.map.keys().collect()
+    }
+
     /// find media by label_text
     pub fn find_media_by_label_text(&self, label_text: &str) -> Option<&MediaId> {
         self.map.values().find_map(|entry| {
@@ -254,7 +276,7 @@ impl Inventory {
                         continue; // belong to another pool
                     }
 
-                    if set.uuid.as_ref() == [0u8;16] { // should we do this??
+                    if set.uuid.as_ref() == [0u8;16] {
                         list.push(MediaId {
                             label: entry.id.label.clone(),
                             media_set_label: None,
@@ -329,7 +351,7 @@ impl Inventory {
 
         match last_pool {
             Some(pool) => Ok(pool.to_string()),
-            None => bail!("media set {} is incomplete - unable to lookup pool"),
+            None => bail!("media set {} is incomplete - unable to lookup pool", media_set_uuid),
         }
     }
 
@@ -483,20 +505,27 @@ impl Inventory {
             Some(time) => time,
         };
 
-        let max_use_time = match media_set_policy {
-            MediaSetPolicy::ContinueCurrent => {
-                match self.media_set_next_start_time(&set.uuid) {
-                    Some(next_start_time) => next_start_time,
-                    None => return i64::MAX,
-                }
-            }
-            MediaSetPolicy::AlwaysCreate => {
-                set_start_time + 1
+        let max_use_time = match self.media_set_next_start_time(&set.uuid) {
+            Some(next_start_time) => {
+               match media_set_policy {
+                   MediaSetPolicy::AlwaysCreate => set_start_time,
+                   _ => next_start_time,
+               }
             }
-            MediaSetPolicy::CreateAt(ref event) => {
-                match compute_next_event(event, set_start_time, false) {
-                    Ok(Some(next)) => next,
-                    Ok(None) | Err(_) => return i64::MAX,
+            None => {
+                match media_set_policy {
+                    MediaSetPolicy::ContinueCurrent => {
+                        return i64::MAX;
+                    }
+                    MediaSetPolicy::AlwaysCreate => {
+                        set_start_time
+                    }
+                    MediaSetPolicy::CreateAt(ref event) => {
+                        match compute_next_event(event, set_start_time, false) {
+                            Ok(Some(next)) => next,
+                            Ok(None) | Err(_) => return i64::MAX,
+                        }
+                    }
                 }
             }
         };
@@ -532,7 +561,7 @@ impl Inventory {
 
     // Helpers to simplify testing
 
-    /// Genreate and insert a new free tape (test helper)
+    /// Generate and insert a new free tape (test helper)
     pub fn generate_free_tape(&mut self, label_text: &str, ctime: i64) -> Uuid {
 
         let label = MediaLabel {
@@ -547,7 +576,7 @@ impl Inventory {
         uuid
     }
 
-    /// Genreate and insert a new tape assigned to a specific pool
+    /// Generate and insert a new tape assigned to a specific pool
     /// (test helper)
     pub fn generate_assigned_tape(
         &mut self,
@@ -571,7 +600,7 @@ impl Inventory {
         uuid
     }
 
-    /// Genreate and insert a used tape (test helper)
+    /// Generate and insert a used tape (test helper)
     pub fn generate_used_tape(
         &mut self,
         label_text: &str,
@@ -637,6 +666,11 @@ impl Inventory {
         self.set_media_status(uuid, Some(MediaStatus::Damaged))
     }
 
+    /// Lock database, reload database, set status to Retired, store database
+    pub fn set_media_status_retired(&mut self, uuid: &Uuid) -> Result<(), Error> {
+        self.set_media_status(uuid, Some(MediaStatus::Retired))
+    }
+
     /// Lock database, reload database, set status to None, store database
     pub fn clear_media_status(&mut self, uuid: &Uuid) -> Result<(), Error> {
         self.set_media_status(uuid, None)