public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pbs-devel] [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name
@ 2021-02-11 13:11 Dominik Csapak
  2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 2/4] api2/tape/media: add 'move' api call Dominik Csapak
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Dominik Csapak @ 2021-02-11 13:11 UTC (permalink / raw)
  To: pbs-devel

in most uses, we want to remove the drive from the param afterwards
where we don't, we already overwrite it with the result of this function

this fixes some commands (like 'proxmox-tape read-label --drive foo')
that failed with:

parameter 'drive': duplicate parameter.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/bin/proxmox-tape.rs                | 84 ++++++++++++++------------
 src/bin/proxmox_tape/changer.rs        |  4 +-
 src/bin/proxmox_tape/encryption_key.rs |  2 +-
 3 files changed, 48 insertions(+), 42 deletions(-)

diff --git a/src/bin/proxmox-tape.rs b/src/bin/proxmox-tape.rs
index 69db8f3f..5a6ee06f 100644
--- a/src/bin/proxmox-tape.rs
+++ b/src/bin/proxmox-tape.rs
@@ -57,8 +57,8 @@ use proxmox_backup::{
 mod proxmox_tape;
 use proxmox_tape::*;
 
-pub fn lookup_drive_name(
-    param: &Value,
+pub fn extract_drive_name(
+    param: &mut Value,
     config: &SectionConfigData,
 ) -> Result<String, Error> {
 
@@ -84,6 +84,10 @@ pub fn lookup_drive_name(
         })
         .ok_or_else(|| format_err!("unable to get (default) drive name"))?;
 
+    if let Some(map) = param.as_object_mut() {
+        map.remove("drive");
+    }
+
     Ok(drive)
 }
 
@@ -108,13 +112,13 @@ pub fn lookup_drive_name(
     },
 )]
 /// Erase media
-async fn erase_media(param: Value) -> Result<(), Error> {
+async fn erase_media(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -141,13 +145,13 @@ async fn erase_media(param: Value) -> Result<(), Error> {
     },
 )]
 /// Rewind tape
-async fn rewind(param: Value) -> Result<(), Error> {
+async fn rewind(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -174,13 +178,13 @@ async fn rewind(param: Value) -> Result<(), Error> {
     },
 )]
 /// Eject/Unload drive media
-async fn eject_media(param: Value) -> Result<(), Error> {
+async fn eject_media(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -206,11 +210,11 @@ async fn eject_media(param: Value) -> Result<(), Error> {
     },
 )]
 /// Load media with specified label
-async fn load_media(param: Value) -> Result<(), Error> {
+async fn load_media(mut param: Value) -> Result<(), Error> {
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -234,11 +238,11 @@ async fn load_media(param: Value) -> Result<(), Error> {
     },
 )]
 /// Export media with specified label
-async fn export_media(param: Value) -> Result<(), Error> {
+async fn export_media(mut param: Value) -> Result<(), Error> {
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -264,11 +268,11 @@ async fn export_media(param: Value) -> Result<(), Error> {
     },
 )]
 /// Load media from the specified slot
-async fn load_media_from_slot(param: Value) -> Result<(), Error> {
+async fn load_media_from_slot(mut param: Value) -> Result<(), Error> {
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -295,11 +299,11 @@ async fn load_media_from_slot(param: Value) -> Result<(), Error> {
     },
 )]
 /// Unload media via changer
-async fn unload_media(param: Value) -> Result<(), Error> {
+async fn unload_media(mut param: Value) -> Result<(), Error> {
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -331,13 +335,13 @@ async fn unload_media(param: Value) -> Result<(), Error> {
     },
 )]
 /// Label media
-async fn label_media(param: Value) -> Result<(), Error> {
+async fn label_media(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -369,13 +373,13 @@ async fn label_media(param: Value) -> Result<(), Error> {
     },
 )]
 /// Read media label
-async fn read_label(param: Value) -> Result<(), Error> {
+async fn read_label(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let client = connect_to_localhost()?;
 
@@ -428,13 +432,13 @@ async fn read_label(param: Value) -> Result<(), Error> {
 async fn inventory(
     read_labels: Option<bool>,
     read_all_labels: Option<bool>,
-    param: Value,
+    mut param: Value,
 ) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let do_read = read_labels.unwrap_or(false) || read_all_labels.unwrap_or(false);
 
@@ -487,13 +491,13 @@ async fn inventory(
     },
 )]
 /// Label media with barcodes from changer device
-async fn barcode_label_media(param: Value) -> Result<(), Error> {
+async fn barcode_label_media(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -516,11 +520,11 @@ async fn barcode_label_media(param: Value) -> Result<(), Error> {
     },
 )]
 /// Move to end of media (MTEOM, used to debug)
-fn move_to_eom(param: Value) -> Result<(), Error> {
+fn move_to_eom(mut param: Value) -> Result<(), Error> {
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let _lock = lock_tape_device(&config, &drive)?;
 
@@ -545,11 +549,11 @@ fn move_to_eom(param: Value) -> Result<(), Error> {
 ///
 /// Note: This reads unless the driver returns an IO Error, so this
 /// method is expected to fails when we reach EOT.
-fn debug_scan(param: Value) -> Result<(), Error> {
+fn debug_scan(mut param: Value) -> Result<(), Error> {
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let _lock = lock_tape_device(&config, &drive)?;
 
@@ -610,13 +614,13 @@ fn debug_scan(param: Value) -> Result<(), Error> {
     },
 )]
 /// Read Cartridge Memory (Medium auxiliary memory attributes)
-async fn cartridge_memory(param: Value) -> Result<(), Error> {
+async fn cartridge_memory(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let client = connect_to_localhost()?;
 
@@ -651,13 +655,13 @@ async fn cartridge_memory(param: Value) -> Result<(), Error> {
     },
 )]
 /// Read Volume Statistics (SCSI log page 17h)
-async fn volume_statistics(param: Value) -> Result<(), Error> {
+async fn volume_statistics(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let client = connect_to_localhost()?;
 
@@ -689,13 +693,13 @@ async fn volume_statistics(param: Value) -> Result<(), Error> {
     },
 )]
 /// Get drive/media status
-async fn status(param: Value) -> Result<(), Error> {
+async fn status(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let client = connect_to_localhost()?;
 
@@ -748,13 +752,13 @@ async fn status(param: Value) -> Result<(), Error> {
     },
 )]
 /// Clean drive
-async fn clean_drive(param: Value) -> Result<(), Error> {
+async fn clean_drive(mut param: Value) -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
@@ -803,7 +807,7 @@ async fn backup(mut param: Value) -> Result<(), Error> {
 
     let (config, _digest) = config::drive::config()?;
 
-    param["drive"] = lookup_drive_name(&param, &config)?.into();
+    param["drive"] = extract_drive_name(&mut param, &config)?.into();
 
     let mut client = connect_to_localhost()?;
 
@@ -842,7 +846,7 @@ async fn restore(mut param: Value) -> Result<(), Error> {
 
     let (config, _digest) = config::drive::config()?;
 
-    param["drive"] = lookup_drive_name(&param, &config)?.into();
+    param["drive"] = extract_drive_name(&mut param, &config)?.into();
 
     let mut client = connect_to_localhost()?;
 
@@ -878,13 +882,13 @@ async fn restore(mut param: Value) -> Result<(), Error> {
     },
 )]
 /// Scan media and record content
-async fn catalog_media(param: Value)  -> Result<(), Error> {
+async fn catalog_media(mut param: Value)  -> Result<(), Error> {
 
     let output_format = get_output_format(&param);
 
     let (config, _digest) = config::drive::config()?;
 
-    let drive = lookup_drive_name(&param, &config)?;
+    let drive = extract_drive_name(&mut param, &config)?;
 
     let mut client = connect_to_localhost()?;
 
diff --git a/src/bin/proxmox_tape/changer.rs b/src/bin/proxmox_tape/changer.rs
index e3bb7bb3..d5b6ede1 100644
--- a/src/bin/proxmox_tape/changer.rs
+++ b/src/bin/proxmox_tape/changer.rs
@@ -42,7 +42,9 @@ pub fn lookup_changer_name(
         return Ok(String::from(name));
     }
 
-    if let Ok(drive) = crate::lookup_drive_name(&Value::Null, config) {
+    let mut empty = Value::Null;
+
+    if let Ok(drive) = crate::extract_drive_name(&mut empty, config) {
         if let Ok(Some((_, name))) = media_changer(config, &drive) {
             return Ok(name);
         }
diff --git a/src/bin/proxmox_tape/encryption_key.rs b/src/bin/proxmox_tape/encryption_key.rs
index 5587d352..9177a377 100644
--- a/src/bin/proxmox_tape/encryption_key.rs
+++ b/src/bin/proxmox_tape/encryption_key.rs
@@ -214,7 +214,7 @@ async fn restore_key(
 ) -> Result<(), Error> {
 
     let (config, _digest) = config::drive::config()?;
-    param["drive"] = crate::lookup_drive_name(&param, &config)?.into();
+    param["drive"] = crate::extract_drive_name(&mut param, &config)?.into();
 
     if !tty::stdin_isatty() {
         bail!("no password input mechanism available");
-- 
2.20.1





^ permalink raw reply	[flat|nested] 5+ messages in thread

* [pbs-devel] [PATCH proxmox-backup 2/4] api2/tape/media: add 'move' api call
  2021-02-11 13:11 [pbs-devel] [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name Dominik Csapak
@ 2021-02-11 13:11 ` Dominik Csapak
  2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 3/4] api2/types/tape/media_location: fix deserialization of MediaLocation::Vault Dominik Csapak
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Dominik Csapak @ 2021-02-11 13:11 UTC (permalink / raw)
  To: pbs-devel

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/api2/tape/media.rs | 43 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/src/api2/tape/media.rs b/src/api2/tape/media.rs
index 27ed37c9..647cc755 100644
--- a/src/api2/tape/media.rs
+++ b/src/api2/tape/media.rs
@@ -24,6 +24,7 @@ use crate::{
         MediaListEntry,
         MediaStatus,
         MediaContentEntry,
+        VAULT_NAME_SCHEMA,
     },
     backup::{
         BackupDir,
@@ -162,6 +163,43 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
     Ok(list)
 }
 
+#[api(
+    input: {
+        properties: {
+            "label-text": {
+                schema: MEDIA_LABEL_SCHEMA,
+            },
+            "vault-name": {
+                schema: VAULT_NAME_SCHEMA,
+                optional: true,
+            },
+        },
+    },
+)]
+/// Change Tape location to vault (if given), or offline.
+pub fn move_tape(
+    label_text: String,
+    vault_name: Option<String>,
+) -> Result<(), Error> {
+
+    let status_path = Path::new(TAPE_STATUS_DIR);
+    let mut inventory = Inventory::load(status_path)?;
+
+    let uuid = inventory.find_media_by_label_text(&label_text)
+        .ok_or_else(|| format_err!("no such media '{}'", label_text))?
+        .label
+        .uuid
+        .clone();
+
+    if let Some(vault_name) = vault_name {
+        inventory.set_media_location_vault(&uuid, &vault_name)?;
+    } else {
+        inventory.set_media_location_offline(&uuid)?;
+    }
+
+    Ok(())
+}
+
 #[api(
     input: {
         properties: {
@@ -342,6 +380,11 @@ const SUBDIRS: SubdirMap = &[
         &Router::new()
             .get(&API_METHOD_LIST_MEDIA)
     ),
+    (
+        "move",
+        &Router::new()
+            .post(&API_METHOD_MOVE_TAPE)
+    ),
 ];
 
 
-- 
2.20.1





^ permalink raw reply	[flat|nested] 5+ messages in thread

* [pbs-devel] [PATCH proxmox-backup 3/4] api2/types/tape/media_location: fix deserialization of MediaLocation::Vault
  2021-02-11 13:11 [pbs-devel] [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name Dominik Csapak
  2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 2/4] api2/tape/media: add 'move' api call Dominik Csapak
@ 2021-02-11 13:11 ` Dominik Csapak
  2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 4/4] ui: tape/TapeInventory: add 'Set Tape Location' button Dominik Csapak
  2021-02-11 13:24 ` [pbs-devel] applied: [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name Dietmar Maurer
  3 siblings, 0 replies; 5+ messages in thread
From: Dominik Csapak @ 2021-02-11 13:11 UTC (permalink / raw)
  To: pbs-devel

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/api2/types/tape/media_location.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/api2/types/tape/media_location.rs b/src/api2/types/tape/media_location.rs
index 31a15c65..031369e3 100644
--- a/src/api2/types/tape/media_location.rs
+++ b/src/api2/types/tape/media_location.rs
@@ -83,7 +83,7 @@ impl std::str::FromStr for MediaLocation {
             return Ok(MediaLocation::Online(changer.to_string()));
         }
         if let Some(vault) = s.strip_prefix("vault-") {
-            return Ok(MediaLocation::Online(vault.to_string()));
+            return Ok(MediaLocation::Vault(vault.to_string()));
         }
 
         bail!("MediaLocation parse error");
-- 
2.20.1





^ permalink raw reply	[flat|nested] 5+ messages in thread

* [pbs-devel] [PATCH proxmox-backup 4/4] ui: tape/TapeInventory: add 'Set Tape Location' button
  2021-02-11 13:11 [pbs-devel] [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name Dominik Csapak
  2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 2/4] api2/tape/media: add 'move' api call Dominik Csapak
  2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 3/4] api2/types/tape/media_location: fix deserialization of MediaLocation::Vault Dominik Csapak
@ 2021-02-11 13:11 ` Dominik Csapak
  2021-02-11 13:24 ` [pbs-devel] applied: [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name Dietmar Maurer
  3 siblings, 0 replies; 5+ messages in thread
From: Dominik Csapak @ 2021-02-11 13:11 UTC (permalink / raw)
  To: pbs-devel

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/tape/TapeInventory.js | 54 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/www/tape/TapeInventory.js b/www/tape/TapeInventory.js
index ed45ab88..4bac4072 100644
--- a/www/tape/TapeInventory.js
+++ b/www/tape/TapeInventory.js
@@ -28,6 +28,48 @@ Ext.define('PBS.TapeManagement.TapeInventory', {
     controller: {
 	xclass: 'Ext.app.ViewController',
 
+	moveToVault: function() {
+	    let me = this;
+	    let view = me.getView();
+	    let selection = view.getSelection();
+	    if (!selection || selection.length < 1) {
+		return;
+	    }
+	    let label = selection[0].data['label-text'];
+	    let inVault = selection[0].data.location.startsWith('vault-');
+	    let vault = "";
+	    if (inVault) {
+		vault = selection[0].data.location.slice("vault-".length);
+	    }
+	    Ext.create('Proxmox.window.Edit', {
+		title: gettext('Set Tape Location'),
+		url: `/api2/extjs/tape/media/move`,
+		method: 'POST',
+		items: [
+		    {
+			xtype: 'displayfield',
+			name: 'label-text',
+			value: label,
+			submitValue: true,
+			fieldLabel: gettext('Media'),
+		    },
+		    {
+			xtype: 'proxmoxtextfield',
+			fieldLabel: gettext('Vault'),
+			name: 'vault-name',
+			value: vault,
+			emptyText: gettext('On-site'),
+			skipEmpty: true,
+		    },
+		],
+		listeners: {
+		    destroy: function() {
+			me.reload();
+		    },
+		},
+	    }).show();
+	},
+
 	reload: function() {
 	    this.getView().getStore().rstore.load();
 	},
@@ -57,6 +99,16 @@ Ext.define('PBS.TapeManagement.TapeInventory', {
 	sorters: 'label-text',
     },
 
+    tbar: [
+	{
+	    xtype: 'proxmoxButton',
+	    text: gettext('Set Tape Location'),
+	    disabled: true,
+	    handler: 'moveToVault',
+	    enableFn: (rec) => !rec.data.location.startsWith('online-'),
+	},
+    ],
+
     columns: [
 	{
 	    text: gettext('Label'),
@@ -83,7 +135,7 @@ Ext.define('PBS.TapeManagement.TapeInventory', {
 	    flex: 1,
 	    renderer: function(value) {
 		if (value === 'offline') {
-		    return `<i class="fa fa-circle-o"></i> ${gettext("Offline")}`;
+		    return `<i class="fa fa-circle-o"></i> ${gettext("Offline")} (${gettext('On-site')})`;
 		} else if (value.startsWith('online-')) {
 		    let location = value.substring(value.indexOf('-') + 1);
 		    return `<i class="fa fa-dot-circle-o"></i> ${gettext("Online")} - ${location}`;
-- 
2.20.1





^ permalink raw reply	[flat|nested] 5+ messages in thread

* [pbs-devel] applied: [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name
  2021-02-11 13:11 [pbs-devel] [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name Dominik Csapak
                   ` (2 preceding siblings ...)
  2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 4/4] ui: tape/TapeInventory: add 'Set Tape Location' button Dominik Csapak
@ 2021-02-11 13:24 ` Dietmar Maurer
  3 siblings, 0 replies; 5+ messages in thread
From: Dietmar Maurer @ 2021-02-11 13:24 UTC (permalink / raw)
  To: Proxmox Backup Server development discussion, Dominik Csapak

applied all 4 patches




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-02-11 13:24 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-11 13:11 [pbs-devel] [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name Dominik Csapak
2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 2/4] api2/tape/media: add 'move' api call Dominik Csapak
2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 3/4] api2/types/tape/media_location: fix deserialization of MediaLocation::Vault Dominik Csapak
2021-02-11 13:11 ` [pbs-devel] [PATCH proxmox-backup 4/4] ui: tape/TapeInventory: add 'Set Tape Location' button Dominik Csapak
2021-02-11 13:24 ` [pbs-devel] applied: [PATCH proxmox-backup 1/4] proxmox-tape: change lookup_drive_name to extract_drive_name Dietmar Maurer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal