2020-12-05 13:46:57 +00:00
|
|
|
mod email;
|
|
|
|
pub use email::*;
|
|
|
|
|
|
|
|
mod parse_mtx_status;
|
|
|
|
pub use parse_mtx_status::*;
|
|
|
|
|
|
|
|
mod mtx_wrapper;
|
|
|
|
pub use mtx_wrapper::*;
|
|
|
|
|
2021-01-10 09:06:24 +00:00
|
|
|
mod mtx;
|
|
|
|
pub use mtx::*;
|
2020-12-05 13:46:57 +00:00
|
|
|
|
2021-01-10 10:51:09 +00:00
|
|
|
use anyhow::{bail, Error};
|
2020-12-05 13:46:57 +00:00
|
|
|
|
|
|
|
/// Interface to media change devices
|
|
|
|
pub trait MediaChange {
|
|
|
|
|
2021-01-07 13:26:43 +00:00
|
|
|
/// Returns the changer status
|
|
|
|
fn status(&mut self) -> Result<MtxStatus, Error>;
|
|
|
|
|
2021-01-10 10:51:09 +00:00
|
|
|
/// Transfer media from on slot to another (storage or import export slots)
|
|
|
|
///
|
|
|
|
/// Target slot needs to be empty
|
|
|
|
fn transfer(&mut self, from: u64, to: u64) -> Result<(), Error>;
|
|
|
|
|
2021-01-07 13:26:43 +00:00
|
|
|
/// 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
|
2020-12-05 13:46:57 +00:00
|
|
|
///
|
|
|
|
/// This unloads first if the drive is already loaded with another media.
|
2021-01-07 13:26:43 +00:00
|
|
|
///
|
|
|
|
/// Note: This refuses to load media inside import/export slots.
|
2020-12-05 13:46:57 +00:00
|
|
|
fn load_media(&mut self, changer_id: &str) -> Result<(), Error>;
|
|
|
|
|
|
|
|
/// Unload media from drive
|
|
|
|
///
|
|
|
|
/// This is a nop on drives without autoloader.
|
2021-01-07 13:26:43 +00:00
|
|
|
fn unload_media(&mut self, target_slot: Option<u64>) -> Result<(), Error>;
|
2020-12-05 13:46:57 +00:00
|
|
|
|
|
|
|
/// Returns true if unload_media automatically ejects drive media
|
|
|
|
fn eject_on_unload(&self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2021-01-07 13:26:43 +00:00
|
|
|
/// 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 {
|
2021-01-08 08:16:42 +00:00
|
|
|
if tag.starts_with("CLN") { continue; }
|
2021-01-07 13:26:43 +00:00
|
|
|
list.push(tag.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(list)
|
|
|
|
}
|
2021-01-08 10:32:56 +00:00
|
|
|
|
|
|
|
/// Load/Unload cleaning cartridge
|
|
|
|
///
|
|
|
|
/// This fail if there is no cleaning cartridge online. Any media
|
|
|
|
/// inside the drive is automatically unloaded.
|
|
|
|
fn clean_drive(&mut self) -> Result<(), Error>;
|
2021-01-10 10:51:09 +00:00
|
|
|
|
|
|
|
/// Export media
|
|
|
|
///
|
|
|
|
/// By moving the media to an empty import-export slot. Returns
|
|
|
|
/// Some(slot) if the media was exported. Returns None if the media is
|
|
|
|
/// not online (already exported).
|
|
|
|
fn export_media(&mut self, changer_id: &str) -> Result<Option<u64>, Error> {
|
|
|
|
let status = self.status()?;
|
|
|
|
|
|
|
|
let mut from = None;
|
|
|
|
let mut to = None;
|
|
|
|
|
|
|
|
for (i, (import_export, element_status)) in status.slots.iter().enumerate() {
|
|
|
|
if *import_export {
|
|
|
|
if to.is_some() { continue; }
|
|
|
|
if let ElementStatus::Empty = element_status {
|
|
|
|
to = Some(i as u64 + 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if let ElementStatus::VolumeTag(ref tag) = element_status {
|
|
|
|
if tag == changer_id {
|
|
|
|
from = Some(i as u64 + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
match (from, to) {
|
|
|
|
(Some(from), Some(to)) => {
|
|
|
|
self.transfer(from, to);
|
|
|
|
Ok(Some(to))
|
|
|
|
}
|
|
|
|
(Some(from), None) => bail!("unable to find free export slot"),
|
|
|
|
(None, _) => Ok(None), // not online
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-05 13:46:57 +00:00
|
|
|
}
|