]> git.proxmox.com Git - proxmox-backup.git/commitdiff
tape: backup - implement export-media-set option
authorDietmar Maurer <dietmar@proxmox.com>
Sun, 10 Jan 2021 10:59:55 +0000 (11:59 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Sun, 10 Jan 2021 10:59:55 +0000 (11:59 +0100)
src/api2/tape/backup.rs
src/bin/proxmox-tape.rs
src/tape/pool_writer.rs

index 4ae03059aec04a1b45680a452e4ea69076f453f7..c7b508c73c7509aab195486079c6acfaffb4b5c5 100644 (file)
@@ -56,6 +56,11 @@ use crate::{
                 type: bool,
                 optional: true,
             },
+            "export-media-set": {
+                description: "Export media set upon job completion.",
+                type: bool,
+                optional: true,
+            },
         },
     },
     returns: {
@@ -67,6 +72,7 @@ pub fn backup(
     store: String,
     pool: String,
     eject_media: Option<bool>,
+    export_media_set: Option<bool>,
     rpcenv: &mut dyn RpcEnvironment,
 ) -> Result<Value, Error> {
 
@@ -84,6 +90,7 @@ pub fn backup(
     let to_stdout = if rpcenv.env_type() == RpcEnvironmentType::CLI { true } else { false };
 
     let eject_media = eject_media.unwrap_or(false);
+    let export_media_set = export_media_set.unwrap_or(false);
 
     let upid_str = WorkerTask::new_thread(
         "tape-backup",
@@ -91,7 +98,7 @@ pub fn backup(
         auth_id,
         to_stdout,
         move |worker| {
-            backup_worker(&worker, datastore, &pool_config, eject_media)?;
+            backup_worker(&worker, datastore, &pool_config, eject_media, export_media_set)?;
             Ok(())
         }
     )?;
@@ -108,6 +115,7 @@ fn backup_worker(
     datastore: Arc<DataStore>,
     pool_config: &MediaPoolConfig,
     eject_media: bool,
+    export_media_set: bool,
 ) -> Result<(), Error> {
 
     let status_path = Path::new(TAPE_STATUS_DIR);
@@ -142,7 +150,10 @@ fn backup_worker(
 
     pool_writer.commit()?;
 
-    if eject_media {
+    if export_media_set {
+        worker.log(format!("exporting current media set"));
+        pool_writer.export_media_set(worker)?;
+    } else if eject_media {
         worker.log(format!("ejection backup media"));
         pool_writer.eject_media()?;
     }
index 76c40d769f14a32856f32aa438a4028f07541594..92ad157e52b30fe3668a06a5ef419ff8268aa3bd 100644 (file)
@@ -723,6 +723,11 @@ async fn clean_drive(
                 type: bool,
                 optional: true,
             },
+            "export-media-set": {
+                description: "Export media set upon job completion.",
+                type: bool,
+                optional: true,
+            },
         },
     },
 )]
index 616b0fcd1899a7966b9e9e2ffbafbe445d8dacfb..d8b9b09aaef4f676b21209ac4ac049bbd3879f80 100644 (file)
@@ -117,6 +117,7 @@ impl PoolWriter {
         let (drive_config, _digest) = crate::config::drive::config()?;
 
         if let Some((mut changer, _)) = media_changer(&drive_config, &self.drive_name)? {
+            drop(status); // close drive
             changer.unload_media(None)?;
         } else {
             status.drive.eject_media()?;
@@ -125,6 +126,37 @@ impl PoolWriter {
         Ok(())
     }
 
+    /// Export current media set and drop PoolWriterState (close drive)
+    pub fn export_media_set(&mut self, worker: &WorkerTask) -> Result<(), Error> {
+        let mut status = self.status.take();
+
+        let (drive_config, _digest) = crate::config::drive::config()?;
+
+        if let Some((mut changer, _)) = media_changer(&drive_config, &self.drive_name)? {
+            drop(status); // close drive
+
+            changer.unload_media(None)?;
+
+            for media_uuid in self.pool.current_media_list()? {
+                let media = self.pool.lookup_media(media_uuid)?;
+                let changer_id = media.changer_id();
+                if let Some(slot) = changer.export_media(changer_id)? {
+                    worker.log(format!("exported media '{}' to import/export slot {}", changer_id, slot));
+                } else {
+                    worker.warn(format!("export failed - media '{}' is not online", changer_id));
+                }
+            }
+
+        } else {
+            worker.log("standalone drive - ejecting media instead of export");
+            if let Some(mut status) = status {
+                status.drive.eject_media()?;
+            }
+        }
+
+        Ok(())
+    }
+
     /// commit changes to tape and catalog
     ///
     /// This is done automatically during a backupsession, but needs to