diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs index b7ccb2cc..32b92750 100644 --- a/src/api2/tape/drive.rs +++ b/src/api2/tape/drive.rs @@ -17,6 +17,7 @@ use crate::{ mtx_load, mtx_unload, linux_tape_device_list, + open_drive, }, }; @@ -113,7 +114,39 @@ pub fn scan_drives(_param: Value) -> Result, Error> { Ok(list) } +#[api( + input: { + properties: { + drive: { + schema: DRIVE_ID_SCHEMA, + }, + fast: { + description: "Use fast erase.", + type: bool, + optional: true, + default: true, + }, + }, + }, +)] +/// Erase media +pub fn erase_media(drive: String, fast: Option) -> Result<(), Error> { + + let (config, _digest) = config::drive::config()?; + + let mut drive = open_drive(&config, &drive)?; + + drive.erase_media(fast.unwrap_or(true))?; + + Ok(()) +} + pub const SUBDIRS: SubdirMap = &[ + ( + "erase-media", + &Router::new() + .put(&API_METHOD_ERASE_MEDIA) + ), ( "load-slot", &Router::new() diff --git a/src/bin/proxmox-tape.rs b/src/bin/proxmox-tape.rs index bb5684c3..1c24aa73 100644 --- a/src/bin/proxmox-tape.rs +++ b/src/bin/proxmox-tape.rs @@ -1,16 +1,106 @@ +use anyhow::{format_err, Error}; +use serde_json::Value; + use proxmox::{ api::{ + api, cli::*, + ApiHandler, RpcEnvironment, + section_config::SectionConfigData, + }, +}; + +use proxmox_backup::{ + api2::{ + self, + types::{ + DRIVE_ID_SCHEMA, + }, + }, + config::{ + self, + drive::complete_drive_name, }, }; mod proxmox_tape; use proxmox_tape::*; +fn lookup_drive_name( + param: &Value, + config: &SectionConfigData, +) -> Result { + + let drive = param["drive"] + .as_str() + .map(String::from) + .or_else(|| std::env::var("PROXMOX_TAPE_DRIVE").ok()) + .or_else(|| { + + let mut drive_names = Vec::new(); + + for (name, (section_type, _)) in config.sections.iter() { + + if !(section_type == "linux" || section_type == "virtual") { continue; } + drive_names.push(name); + } + + if drive_names.len() == 1 { + Some(drive_names[0].to_owned()) + } else { + None + } + }) + .ok_or_else(|| format_err!("unable to get (default) drive name"))?; + + Ok(drive) +} + +#[api( + input: { + properties: { + drive: { + schema: DRIVE_ID_SCHEMA, + optional: true, + }, + fast: { + description: "Use fast erase.", + type: bool, + optional: true, + default: true, + }, + }, + }, +)] +/// Erase media +fn erase_media( + 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_ERASE_MEDIA; + + match info.handler { + ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?, + _ => unreachable!(), + }; + + Ok(()) +} + fn main() { let cmd_def = CliCommandMap::new() + .insert( + "erase", + CliCommand::new(&API_METHOD_ERASE_MEDIA) + .completion_cb("drive", complete_drive_name) + ) .insert("changer", changer_commands()) .insert("drive", drive_commands()) ;