tape: improve MediaChange trait
We expose the whole MtxStatus, and we can load/store from/to specified slot numbers.
This commit is contained in:
@ -43,6 +43,30 @@ fn unload_to_free_slot(drive_name: &str, path: &str, status: &MtxStatus, drivenu
|
||||
|
||||
impl MediaChange for LinuxTapeDrive {
|
||||
|
||||
fn status(&mut self) -> Result<MtxStatus, Error> {
|
||||
let (config, _digest) = crate::config::drive::config()?;
|
||||
|
||||
let changer: ScsiTapeChanger = match self.changer {
|
||||
Some(ref changer) => config.lookup("changer", changer)?,
|
||||
None => bail!("drive '{}' has no associated changer", self.name),
|
||||
};
|
||||
|
||||
mtx_status(&changer)
|
||||
}
|
||||
|
||||
fn load_media_from_slot(&mut self, slot: u64) -> Result<(), Error> {
|
||||
let (config, _digest) = crate::config::drive::config()?;
|
||||
|
||||
let changer: ScsiTapeChanger = match self.changer {
|
||||
Some(ref changer) => config.lookup("changer", changer)?,
|
||||
None => bail!("drive '{}' has no associated changer", self.name),
|
||||
};
|
||||
|
||||
let drivenum = self.changer_drive_id.unwrap_or(0);
|
||||
|
||||
mtx_load(&changer.path, slot, drivenum as u64)
|
||||
}
|
||||
|
||||
fn load_media(&mut self, changer_id: &str) -> Result<(), Error> {
|
||||
|
||||
if changer_id.starts_with("CLN") {
|
||||
@ -97,11 +121,10 @@ impl MediaChange for LinuxTapeDrive {
|
||||
Some(slot) => slot,
|
||||
};
|
||||
|
||||
|
||||
mtx_load(&changer.path, slot as u64, drivenum as u64)
|
||||
}
|
||||
|
||||
fn unload_media(&mut self) -> Result<(), Error> {
|
||||
fn unload_media(&mut self, target_slot: Option<u64>) -> Result<(), Error> {
|
||||
let (config, _digest) = crate::config::drive::config()?;
|
||||
|
||||
let changer: ScsiTapeChanger = match self.changer {
|
||||
@ -111,40 +134,15 @@ impl MediaChange for LinuxTapeDrive {
|
||||
|
||||
let drivenum = self.changer_drive_id.unwrap_or(0);
|
||||
|
||||
let status = mtx_status(&changer)?;
|
||||
|
||||
unload_to_free_slot(&self.name, &changer.path, &status, drivenum)
|
||||
if let Some(target_slot) = target_slot {
|
||||
mtx_unload(&changer.path, target_slot, drivenum)
|
||||
} else {
|
||||
let status = mtx_status(&changer)?;
|
||||
unload_to_free_slot(&self.name, &changer.path, &status, drivenum)
|
||||
}
|
||||
}
|
||||
|
||||
fn eject_on_unload(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn list_media_changer_ids(&self) -> Result<Vec<String>, Error> {
|
||||
let (config, _digest) = crate::config::drive::config()?;
|
||||
|
||||
let changer: ScsiTapeChanger = match self.changer {
|
||||
Some(ref changer) => config.lookup("changer", changer)?,
|
||||
None => return Ok(Vec::new()),
|
||||
};
|
||||
|
||||
let status = mtx_status(&changer)?;
|
||||
|
||||
let mut list = Vec::new();
|
||||
|
||||
for drive_status in status.drives.iter() {
|
||||
if let ElementStatus::VolumeTag(ref tag) = drive_status.status {
|
||||
list.push(tag.clone());
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(list)
|
||||
}
|
||||
}
|
||||
|
@ -15,21 +15,52 @@ use anyhow::Error;
|
||||
/// Interface to media change devices
|
||||
pub trait MediaChange {
|
||||
|
||||
/// Load media into drive
|
||||
/// Returns the changer status
|
||||
fn status(&mut self) -> Result<MtxStatus, Error>;
|
||||
|
||||
/// Load media from storage slot into drive
|
||||
fn load_media_from_slot(&mut self, slot: u64) -> Result<(), Error>;
|
||||
|
||||
/// Load media by changer-id into drive
|
||||
///
|
||||
/// This unloads first if the drive is already loaded with another media.
|
||||
///
|
||||
/// Note: This refuses to load media inside import/export slots.
|
||||
fn load_media(&mut self, changer_id: &str) -> Result<(), Error>;
|
||||
|
||||
/// Unload media from drive
|
||||
///
|
||||
/// This is a nop on drives without autoloader.
|
||||
fn unload_media(&mut self) -> Result<(), Error>;
|
||||
fn unload_media(&mut self, target_slot: Option<u64>) -> Result<(), Error>;
|
||||
|
||||
/// Returns true if unload_media automatically ejects drive media
|
||||
fn eject_on_unload(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// List media changer IDs (barcodes)
|
||||
fn list_media_changer_ids(&self) -> Result<Vec<String>, Error>;
|
||||
/// List online media changer IDs (barcodes)
|
||||
///
|
||||
/// List acessible (online) changer IDs. This does not include
|
||||
/// media inside import-export slots or cleaning media.
|
||||
fn online_media_changer_ids(&mut self) -> Result<Vec<String>, Error> {
|
||||
let status = self.status()?;
|
||||
|
||||
let mut list = Vec::new();
|
||||
|
||||
for drive_status in status.drives.iter() {
|
||||
if let ElementStatus::VolumeTag(ref tag) = drive_status.status {
|
||||
list.push(tag.clone());
|
||||
}
|
||||
}
|
||||
|
||||
for (import_export, element_status) in status.slots.iter() {
|
||||
if *import_export { continue; }
|
||||
if let ElementStatus::VolumeTag(ref tag) = element_status {
|
||||
if !tag.starts_with("CLN") { continue; }
|
||||
list.push(tag.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(list)
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ use anyhow::Error;
|
||||
use serde_json::Value;
|
||||
|
||||
use proxmox::{
|
||||
tools::Uuid,
|
||||
api::schema::parse_property_string,
|
||||
};
|
||||
|
||||
@ -15,10 +14,8 @@ use crate::{
|
||||
ScsiTapeChanger,
|
||||
},
|
||||
tape::{
|
||||
Inventory,
|
||||
changer::{
|
||||
MtxStatus,
|
||||
ElementStatus,
|
||||
parse_mtx_status,
|
||||
},
|
||||
},
|
||||
@ -100,30 +97,3 @@ pub fn mtx_transfer(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Extract the list of online media from MtxStatus
|
||||
///
|
||||
/// Returns a HashSet containing all found media Uuid
|
||||
pub fn mtx_status_to_online_set(status: &MtxStatus, inventory: &Inventory) -> HashSet<Uuid> {
|
||||
|
||||
let mut online_set = HashSet::new();
|
||||
|
||||
for drive_status in status.drives.iter() {
|
||||
if let ElementStatus::VolumeTag(ref changer_id) = drive_status.status {
|
||||
if let Some(media_id) = inventory.find_media_by_changer_id(changer_id) {
|
||||
online_set.insert(media_id.label.uuid.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
online_set
|
||||
}
|
||||
|
Reference in New Issue
Block a user