tape: improve export media to directly export from drive, add CLI

This commit is contained in:
Dietmar Maurer
2021-01-10 13:44:44 +01:00
parent c92e3832bf
commit 483da89d03
5 changed files with 135 additions and 32 deletions

View File

@ -10,7 +10,7 @@ pub use mtx_wrapper::*;
mod mtx;
pub use mtx::*;
use anyhow::{bail, Error};
use anyhow::Error;
/// Interface to media change devices
pub trait MediaChange {
@ -80,34 +80,5 @@ pub trait MediaChange {
/// 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_media(from, to)?;
Ok(Some(to))
}
(Some(_from), None) => bail!("unable to find free export slot"),
(None, _) => Ok(None), // not online
}
}
fn export_media(&mut self, changer_id: &str) -> Result<Option<u64>, Error>;
}

View File

@ -48,6 +48,7 @@ fn unload_to_free_slot(drive_name: &str, path: &str, status: &MtxStatus, drivenu
}
let drive_status = &status.drives[drivenum as usize];
if let Some(slot) = drive_status.loaded_slot {
// fixme: check if slot is free
mtx_unload(path, slot, drivenum)
} else {
let mut free_slot = None;
@ -174,4 +175,54 @@ impl MediaChange for MtxMediaChanger {
Ok(())
}
fn export_media(&mut self, changer_id: &str) -> Result<Option<u64>, Error> {
let status = self.status()?;
let mut from_drive = None;
if let Some(drive_status) = status.drives.get(self.drivenum as usize) {
if let ElementStatus::VolumeTag(ref tag) = drive_status.status {
if tag == changer_id {
from_drive = Some(self.drivenum);
}
}
}
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);
}
}
}
}
if let Some(drivenum) = from_drive {
match to {
Some(to) => {
mtx_unload(&self.config.path, to, drivenum)?;
Ok(Some(to))
}
None => bail!("unable to find free export slot"),
}
} else {
match (from, to) {
(Some(from), Some(to)) => {
self.transfer_media(from, to)?;
Ok(Some(to))
}
(Some(_from), None) => bail!("unable to find free export slot"),
(None, _) => Ok(None), // not online
}
}
}
}

View File

@ -394,7 +394,11 @@ impl MediaChange for VirtualTapeHandle {
}
fn transfer_media(&mut self, _from: u64, _to: u64) -> Result<(), Error> {
bail!("medfia tranfer is not implemented!");
bail!("media tranfer is not implemented!");
}
fn export_media(&mut self, _changer_id: &str) -> Result<Option<u64>, Error> {
bail!("media export is not implemented!");
}
fn load_media_from_slot(&mut self, slot: u64) -> Result<(), Error> {
@ -461,6 +465,11 @@ impl MediaChange for VirtualTapeDrive {
handle.transfer_media(from, to)
}
fn export_media(&mut self, changer_id: &str) -> Result<Option<u64>, Error> {
let mut handle = self.open()?;
handle.export_media(changer_id)
}
fn load_media_from_slot(&mut self, slot: u64) -> Result<(), Error> {
let mut handle = self.open()?;
handle.load_media_from_slot(slot)