From e0362b0d0f8991e948d8f41d88ad2aab210247ef Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Mon, 28 Dec 2020 13:32:56 +0100 Subject: [PATCH] tape: correctly parse mtx import/export slots --- src/api2/tape/changer.rs | 8 ++++++-- src/api2/types/tape/changer.rs | 4 +++- src/bin/proxmox_tape/changer.rs | 2 ++ src/tape/changer/linux_tape.rs | 11 ++++++++--- src/tape/changer/mtx_wrapper.rs | 3 ++- src/tape/changer/parse_mtx_status.rs | 14 ++++++++------ 6 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/api2/tape/changer.rs b/src/api2/tape/changer.rs index f9653d44..a8092788 100644 --- a/src/api2/tape/changer.rs +++ b/src/api2/tape/changer.rs @@ -82,9 +82,13 @@ pub async fn get_status(name: String) -> Result, Error> { list.push(entry); } - for (id, slot_status) in status.slots.iter().enumerate() { + for (id, (import_export, slot_status)) in status.slots.iter().enumerate() { let entry = MtxStatusEntry { - entry_kind: MtxEntryKind::Slot, + entry_kind: if *import_export { + MtxEntryKind::ImportExport + } else { + MtxEntryKind::Slot + }, entry_id: id as u64 + 1, changer_id: match &slot_status { ElementStatus::Empty => None, diff --git a/src/api2/types/tape/changer.rs b/src/api2/types/tape/changer.rs index 349a1d25..b0f8600b 100644 --- a/src/api2/types/tape/changer.rs +++ b/src/api2/types/tape/changer.rs @@ -44,13 +44,15 @@ pub struct ScsiTapeChanger { #[api()] #[derive(Serialize,Deserialize)] -#[serde(rename_all = "lowercase")] +#[serde(rename_all = "kebab-case")] /// Mtx Entry Kind pub enum MtxEntryKind { /// Drive Drive, /// Slot Slot, + /// Import/Export Slot + ImportExport, } #[api( diff --git a/src/bin/proxmox_tape/changer.rs b/src/bin/proxmox_tape/changer.rs index 9db1644e..b5949bd6 100644 --- a/src/bin/proxmox_tape/changer.rs +++ b/src/bin/proxmox_tape/changer.rs @@ -207,6 +207,8 @@ async fn get_status( }; let options = default_table_format_options() + .sortby("entry-kind", false) + .sortby("entry-id", false) .column(ColumnConfig::new("entry-kind")) .column(ColumnConfig::new("entry-id")) .column(ColumnConfig::new("changer-id")) diff --git a/src/tape/changer/linux_tape.rs b/src/tape/changer/linux_tape.rs index 56983984..1c7c943a 100644 --- a/src/tape/changer/linux_tape.rs +++ b/src/tape/changer/linux_tape.rs @@ -27,7 +27,8 @@ fn unload_to_free_slot(drive_name: &str, path: &str, status: &MtxStatus, drivenu } else { let mut free_slot = None; for i in 0..status.slots.len() { - if let ElementStatus::Empty = status.slots[i] { + if status.slots[i].0 { continue; } // skip import/export slots + if let ElementStatus::Empty = status.slots[i].1 { free_slot = Some((i+1) as u64); break; } @@ -79,9 +80,12 @@ impl MediaChange for LinuxTapeDrive { } let mut slot = None; - for (i, element_status) in status.slots.iter().enumerate() { + for (i, (import_export, element_status)) in status.slots.iter().enumerate() { if let ElementStatus::VolumeTag(tag) = element_status { if *tag == changer_id { + if *import_export { + bail!("unable to load media '{}' - inside import/export slot", changer_id); + } slot = Some(i+1); break; } @@ -134,7 +138,8 @@ impl MediaChange for LinuxTapeDrive { } } - for element_status in status.slots.iter() { + for (import_export, element_status) in status.slots.iter() { + if *import_export { continue; } if let ElementStatus::VolumeTag(ref tag) = element_status { list.push(tag.clone()); } diff --git a/src/tape/changer/mtx_wrapper.rs b/src/tape/changer/mtx_wrapper.rs index ef0c3328..f3edca2c 100644 --- a/src/tape/changer/mtx_wrapper.rs +++ b/src/tape/changer/mtx_wrapper.rs @@ -87,7 +87,8 @@ pub fn mtx_status_to_online_set(status: &MtxStatus, inventory: &Inventory) -> Ha } } - for slot_status in status.slots.iter() { + for (import_export, slot_status) in status.slots.iter() { + if *import_export { continue; } if let ElementStatus::VolumeTag(ref changer_id) = slot_status { if let Some(media_id) = inventory.find_media_by_changer_id(changer_id) { online_set.insert(media_id.label.uuid.clone()); diff --git a/src/tape/changer/parse_mtx_status.rs b/src/tape/changer/parse_mtx_status.rs index 220a3141..438a7cb3 100644 --- a/src/tape/changer/parse_mtx_status.rs +++ b/src/tape/changer/parse_mtx_status.rs @@ -31,8 +31,8 @@ pub struct DriveStatus { pub struct MtxStatus { /// List of known drives pub drives: Vec, - /// List of known slots - pub slots: Vec, + /// List of known slots, the boolean attribute marks import/export slots + pub slots: Vec<(bool, ElementStatus)>, } // Recognizes one line @@ -122,17 +122,19 @@ fn parse_data_transfer_element(i: &str) -> IResult<&str, (u64, DriveStatus)> { Ok((i, (id, element_status))) } -fn parse_storage_element(i: &str) -> IResult<&str, (u64, ElementStatus)> { +fn parse_storage_element(i: &str) -> IResult<&str, (u64, bool, ElementStatus)> { let (i, _) = multispace1(i)?; let (i, _) = tag("Storage Element")(i)?; let (i, _) = multispace1(i)?; let (i, id) = parse_u64(i)?; + let (i, opt_ie) = nom::combinator::opt(tag(" IMPORT/EXPORT"))(i)?; + let import_export = opt_ie.is_some(); let (i, _) = nom::character::complete::char(':')(i)?; let (i, element_status) = parse_slot_status(i)?; let (i, _) = nom::character::complete::newline(i)?; - Ok((i, (id, element_status))) + Ok((i, (id, import_export, element_status))) } fn parse_status(i: &str) -> IResult<&str, MtxStatus> { @@ -149,12 +151,12 @@ fn parse_status(i: &str) -> IResult<&str, MtxStatus> { } let mut slots = Vec::new(); - while let Ok((n, (id, element_status))) = parse_storage_element(i) { + while let Ok((n, (id, import_export, element_status))) = parse_storage_element(i) { if id != (slots.len() as u64 + 1) { return Err(parse_failure(i, "unexpected slot number")); } i = n; - slots.push(element_status); + slots.push((import_export, element_status)); } let status = MtxStatus { drives, slots };