tape: implement drive clean
This commit is contained in:
parent
25d3965769
commit
df69a4fc59
@ -480,6 +480,53 @@ pub async fn read_label(drive: String) -> Result<MediaIdFlat, Error> {
|
|||||||
}).await?
|
}).await?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
drive: {
|
||||||
|
schema: DRIVE_NAME_SCHEMA,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
schema: UPID_SCHEMA,
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Clean drive
|
||||||
|
pub fn clean_drive(
|
||||||
|
drive: String,
|
||||||
|
rpcenv: &mut dyn RpcEnvironment,
|
||||||
|
) -> Result<Value, Error> {
|
||||||
|
|
||||||
|
let (config, _digest) = config::drive::config()?;
|
||||||
|
|
||||||
|
check_drive_exists(&config, &drive)?; // early check before starting worker
|
||||||
|
|
||||||
|
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
|
||||||
|
|
||||||
|
let to_stdout = if rpcenv.env_type() == RpcEnvironmentType::CLI { true } else { false };
|
||||||
|
|
||||||
|
let upid_str = WorkerTask::new_thread(
|
||||||
|
"clean-drive",
|
||||||
|
Some(drive.clone()),
|
||||||
|
auth_id,
|
||||||
|
to_stdout,
|
||||||
|
move |worker| {
|
||||||
|
|
||||||
|
let (mut changer, _changer_name) = required_media_changer(&config, &drive)?;
|
||||||
|
|
||||||
|
worker.log("Starting drive clean");
|
||||||
|
|
||||||
|
changer.clean_drive()?;
|
||||||
|
|
||||||
|
worker.log("Drive cleaned sucessfully");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(upid_str.into())
|
||||||
|
}
|
||||||
|
|
||||||
#[api(
|
#[api(
|
||||||
input: {
|
input: {
|
||||||
properties: {
|
properties: {
|
||||||
@ -643,6 +690,7 @@ pub fn update_inventory(
|
|||||||
inventory.store(media_id, false)?;
|
inventory.store(media_id, false)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
changer.unload_media(None)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -940,6 +988,11 @@ pub const SUBDIRS: SubdirMap = &sorted!([
|
|||||||
&Router::new()
|
&Router::new()
|
||||||
.put(&API_METHOD_CATALOG_MEDIA)
|
.put(&API_METHOD_CATALOG_MEDIA)
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"clean",
|
||||||
|
&Router::new()
|
||||||
|
.put(&API_METHOD_CLEAN_DRIVE)
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"eject-media",
|
"eject-media",
|
||||||
&Router::new()
|
&Router::new()
|
||||||
|
@ -677,6 +677,38 @@ fn status(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
drive: {
|
||||||
|
schema: DRIVE_NAME_SCHEMA,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Clean drive
|
||||||
|
async fn clean_drive(
|
||||||
|
mut param: Value,
|
||||||
|
rpcenv: &mut dyn RpcEnvironment,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let (config, _digest) = config::drive::config()?;
|
||||||
|
|
||||||
|
param["drive"] = lookup_drive_name(¶m, &config)?.into();
|
||||||
|
|
||||||
|
let info = &api2::tape::drive::API_METHOD_CLEAN_DRIVE;
|
||||||
|
|
||||||
|
let result = match info.handler {
|
||||||
|
ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
wait_for_local_worker(result.as_str().unwrap()).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[api(
|
#[api(
|
||||||
input: {
|
input: {
|
||||||
properties: {
|
properties: {
|
||||||
@ -856,6 +888,11 @@ fn main() {
|
|||||||
CliCommand::new(&API_METHOD_CARTRIDGE_MEMORY)
|
CliCommand::new(&API_METHOD_CARTRIDGE_MEMORY)
|
||||||
.completion_cb("drive", complete_drive_name)
|
.completion_cb("drive", complete_drive_name)
|
||||||
)
|
)
|
||||||
|
.insert(
|
||||||
|
"clean",
|
||||||
|
CliCommand::new(&API_METHOD_CLEAN_DRIVE)
|
||||||
|
.completion_cb("drive", complete_drive_name)
|
||||||
|
)
|
||||||
.insert(
|
.insert(
|
||||||
"label",
|
"label",
|
||||||
CliCommand::new(&API_METHOD_LABEL_MEDIA)
|
CliCommand::new(&API_METHOD_LABEL_MEDIA)
|
||||||
|
@ -145,4 +145,47 @@ impl MediaChange for LinuxTapeDrive {
|
|||||||
fn eject_on_unload(&self) -> bool {
|
fn eject_on_unload(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clean_drive(&mut self) -> Result<(), Error> {
|
||||||
|
let (config, _digest) = crate::config::drive::config()?;
|
||||||
|
|
||||||
|
let changer: ScsiTapeChanger = match self.changer {
|
||||||
|
Some(ref changer) => config.lookup("changer", changer)?,
|
||||||
|
None => bail!("unable to load cleaning cartridge - no associated changer device"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let drivenum = self.changer_drive_id.unwrap_or(0);
|
||||||
|
|
||||||
|
let status = mtx_status(&changer)?;
|
||||||
|
|
||||||
|
let mut cleaning_cartridge_slot = None;
|
||||||
|
|
||||||
|
for (i, (import_export, element_status)) in status.slots.iter().enumerate() {
|
||||||
|
if *import_export { continue; }
|
||||||
|
if let ElementStatus::VolumeTag(ref tag) = element_status {
|
||||||
|
if tag.starts_with("CLN") {
|
||||||
|
cleaning_cartridge_slot = Some(i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cleaning_cartridge_slot = match cleaning_cartridge_slot {
|
||||||
|
None => bail!("clean failed - unable to find cleaning cartridge"),
|
||||||
|
Some(cleaning_cartridge_slot) => cleaning_cartridge_slot as u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(drive_status) = status.drives.get(drivenum as usize) {
|
||||||
|
match drive_status.status {
|
||||||
|
ElementStatus::Empty => { /* OK */ },
|
||||||
|
_ => unload_to_free_slot(&self.name, &changer.path, &status, drivenum)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mtx_load(&changer.path, cleaning_cartridge_slot, drivenum)?;
|
||||||
|
|
||||||
|
mtx_unload(&changer.path, cleaning_cartridge_slot, drivenum)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,4 +63,10 @@ pub trait MediaChange {
|
|||||||
|
|
||||||
Ok(list)
|
Ok(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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>;
|
||||||
}
|
}
|
||||||
|
@ -439,6 +439,10 @@ impl MediaChange for VirtualTapeHandle {
|
|||||||
fn eject_on_unload(&self) -> bool {
|
fn eject_on_unload(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clean_drive(&mut self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaChange for VirtualTapeDrive {
|
impl MediaChange for VirtualTapeDrive {
|
||||||
@ -472,4 +476,9 @@ impl MediaChange for VirtualTapeDrive {
|
|||||||
let handle = self.open()?;
|
let handle = self.open()?;
|
||||||
handle.online_media_changer_ids()
|
handle.online_media_changer_ids()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clean_drive(&mut self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user