tape: implement LTO userspace driver
This commit is contained in:
@ -27,7 +27,7 @@ use crate::{
|
||||
SLOT_ARRAY_SCHEMA,
|
||||
EXPORT_SLOT_LIST_SCHEMA,
|
||||
ScsiTapeChanger,
|
||||
LinuxTapeDrive,
|
||||
LtoTapeDrive,
|
||||
},
|
||||
tape::{
|
||||
linux_tape_changer_list,
|
||||
@ -303,7 +303,7 @@ pub fn delete_changer(name: String, _param: Value) -> Result<(), Error> {
|
||||
None => bail!("Delete changer '{}' failed - no such entry", name),
|
||||
}
|
||||
|
||||
let drive_list: Vec<LinuxTapeDrive> = config.convert_to_typed_array("linux")?;
|
||||
let drive_list: Vec<LtoTapeDrive> = config.convert_to_typed_array("lto")?;
|
||||
for drive in drive_list {
|
||||
if let Some(changer) = drive.changer {
|
||||
if changer == name {
|
||||
|
@ -19,12 +19,12 @@ use crate::{
|
||||
DRIVE_NAME_SCHEMA,
|
||||
CHANGER_NAME_SCHEMA,
|
||||
CHANGER_DRIVENUM_SCHEMA,
|
||||
LINUX_DRIVE_PATH_SCHEMA,
|
||||
LinuxTapeDrive,
|
||||
LTO_DRIVE_PATH_SCHEMA,
|
||||
LtoTapeDrive,
|
||||
ScsiTapeChanger,
|
||||
},
|
||||
tape::{
|
||||
linux_tape_device_list,
|
||||
lto_tape_device_list,
|
||||
check_drive_path,
|
||||
},
|
||||
};
|
||||
@ -37,7 +37,7 @@ use crate::{
|
||||
schema: DRIVE_NAME_SCHEMA,
|
||||
},
|
||||
path: {
|
||||
schema: LINUX_DRIVE_PATH_SCHEMA,
|
||||
schema: LTO_DRIVE_PATH_SCHEMA,
|
||||
},
|
||||
changer: {
|
||||
schema: CHANGER_NAME_SCHEMA,
|
||||
@ -60,13 +60,13 @@ pub fn create_drive(param: Value) -> Result<(), Error> {
|
||||
|
||||
let (mut config, _digest) = config::drive::config()?;
|
||||
|
||||
let item: LinuxTapeDrive = serde_json::from_value(param)?;
|
||||
let item: LtoTapeDrive = serde_json::from_value(param)?;
|
||||
|
||||
let linux_drives = linux_tape_device_list();
|
||||
let lto_drives = lto_tape_device_list();
|
||||
|
||||
check_drive_path(&linux_drives, &item.path)?;
|
||||
check_drive_path(<o_drives, &item.path)?;
|
||||
|
||||
let existing: Vec<LinuxTapeDrive> = config.convert_to_typed_array("linux")?;
|
||||
let existing: Vec<LtoTapeDrive> = config.convert_to_typed_array("lto")?;
|
||||
|
||||
for drive in existing {
|
||||
if drive.name == item.name {
|
||||
@ -77,7 +77,7 @@ pub fn create_drive(param: Value) -> Result<(), Error> {
|
||||
}
|
||||
}
|
||||
|
||||
config.set_data(&item.name, "linux", &item)?;
|
||||
config.set_data(&item.name, "lto", &item)?;
|
||||
|
||||
config::drive::save_config(&config)?;
|
||||
|
||||
@ -93,7 +93,7 @@ pub fn create_drive(param: Value) -> Result<(), Error> {
|
||||
},
|
||||
},
|
||||
returns: {
|
||||
type: LinuxTapeDrive,
|
||||
type: LtoTapeDrive,
|
||||
},
|
||||
access: {
|
||||
permission: &Permission::Privilege(&["tape", "device", "{name}"], PRIV_TAPE_AUDIT, false),
|
||||
@ -104,11 +104,11 @@ pub fn get_config(
|
||||
name: String,
|
||||
_param: Value,
|
||||
mut rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<LinuxTapeDrive, Error> {
|
||||
) -> Result<LtoTapeDrive, Error> {
|
||||
|
||||
let (config, digest) = config::drive::config()?;
|
||||
|
||||
let data: LinuxTapeDrive = config.lookup("linux", &name)?;
|
||||
let data: LtoTapeDrive = config.lookup("lto", &name)?;
|
||||
|
||||
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
|
||||
|
||||
@ -123,7 +123,7 @@ pub fn get_config(
|
||||
description: "The list of configured drives (with config digest).",
|
||||
type: Array,
|
||||
items: {
|
||||
type: LinuxTapeDrive,
|
||||
type: LtoTapeDrive,
|
||||
},
|
||||
},
|
||||
access: {
|
||||
@ -135,13 +135,13 @@ pub fn get_config(
|
||||
pub fn list_drives(
|
||||
_param: Value,
|
||||
mut rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<Vec<LinuxTapeDrive>, Error> {
|
||||
) -> Result<Vec<LtoTapeDrive>, Error> {
|
||||
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
|
||||
let user_info = CachedUserInfo::new()?;
|
||||
|
||||
let (config, digest) = config::drive::config()?;
|
||||
|
||||
let drive_list: Vec<LinuxTapeDrive> = config.convert_to_typed_array("linux")?;
|
||||
let drive_list: Vec<LtoTapeDrive> = config.convert_to_typed_array("lto")?;
|
||||
|
||||
let drive_list = drive_list
|
||||
.into_iter()
|
||||
@ -176,7 +176,7 @@ pub enum DeletableProperty {
|
||||
schema: DRIVE_NAME_SCHEMA,
|
||||
},
|
||||
path: {
|
||||
schema: LINUX_DRIVE_PATH_SCHEMA,
|
||||
schema: LTO_DRIVE_PATH_SCHEMA,
|
||||
optional: true,
|
||||
},
|
||||
changer: {
|
||||
@ -225,7 +225,7 @@ pub fn update_drive(
|
||||
crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
|
||||
}
|
||||
|
||||
let mut data: LinuxTapeDrive = config.lookup("linux", &name)?;
|
||||
let mut data: LtoTapeDrive = config.lookup("lto", &name)?;
|
||||
|
||||
if let Some(delete) = delete {
|
||||
for delete_prop in delete {
|
||||
@ -240,8 +240,8 @@ pub fn update_drive(
|
||||
}
|
||||
|
||||
if let Some(path) = path {
|
||||
let linux_drives = linux_tape_device_list();
|
||||
check_drive_path(&linux_drives, &path)?;
|
||||
let lto_drives = lto_tape_device_list();
|
||||
check_drive_path(<o_drives, &path)?;
|
||||
data.path = path;
|
||||
}
|
||||
|
||||
@ -261,7 +261,7 @@ pub fn update_drive(
|
||||
}
|
||||
}
|
||||
|
||||
config.set_data(&name, "linux", &data)?;
|
||||
config.set_data(&name, "lto", &data)?;
|
||||
|
||||
config::drive::save_config(&config)?;
|
||||
|
||||
@ -290,8 +290,8 @@ pub fn delete_drive(name: String, _param: Value) -> Result<(), Error> {
|
||||
|
||||
match config.sections.get(&name) {
|
||||
Some((section_type, _)) => {
|
||||
if section_type != "linux" {
|
||||
bail!("Entry '{}' exists, but is not a linux tape drive", name);
|
||||
if section_type != "lto" {
|
||||
bail!("Entry '{}' exists, but is not a lto tape drive", name);
|
||||
}
|
||||
config.sections.remove(&name);
|
||||
},
|
||||
|
@ -20,7 +20,7 @@ use crate::{
|
||||
Authid,
|
||||
CHANGER_NAME_SCHEMA,
|
||||
ChangerListEntry,
|
||||
LinuxTapeDrive,
|
||||
LtoTapeDrive,
|
||||
MtxEntryKind,
|
||||
MtxStatusEntry,
|
||||
ScsiTapeChanger,
|
||||
@ -88,7 +88,7 @@ pub async fn get_status(
|
||||
|
||||
inventory.update_online_status(&map)?;
|
||||
|
||||
let drive_list: Vec<LinuxTapeDrive> = config.convert_to_typed_array("linux")?;
|
||||
let drive_list: Vec<LtoTapeDrive> = config.convert_to_typed_array("lto")?;
|
||||
let mut drive_map: HashMap<u64, String> = HashMap::new();
|
||||
|
||||
for drive in drive_list {
|
||||
|
@ -42,11 +42,11 @@ use crate::{
|
||||
MEDIA_POOL_NAME_SCHEMA,
|
||||
Authid,
|
||||
DriveListEntry,
|
||||
LinuxTapeDrive,
|
||||
LtoTapeDrive,
|
||||
MediaIdFlat,
|
||||
LabelUuidMap,
|
||||
MamAttribute,
|
||||
LinuxDriveAndMediaStatus,
|
||||
LtoDriveAndMediaStatus,
|
||||
},
|
||||
tape::restore::{
|
||||
fast_catalog_restore,
|
||||
@ -62,7 +62,7 @@ use crate::{
|
||||
lock_media_set,
|
||||
lock_media_pool,
|
||||
lock_unassigned_media_pool,
|
||||
linux_tape_device_list,
|
||||
lto_tape_device_list,
|
||||
lookup_device_identification,
|
||||
file_formats::{
|
||||
MediaLabel,
|
||||
@ -70,9 +70,9 @@ use crate::{
|
||||
},
|
||||
drive::{
|
||||
TapeDriver,
|
||||
LinuxTapeHandle,
|
||||
LtoTapeHandle,
|
||||
Lp17VolumeStatistics,
|
||||
open_linux_tape_device,
|
||||
open_lto_tape_device,
|
||||
media_changer,
|
||||
required_media_changer,
|
||||
open_drive,
|
||||
@ -794,9 +794,9 @@ pub fn clean_drive(
|
||||
|
||||
changer.clean_drive()?;
|
||||
|
||||
if let Ok(drive_config) = config.lookup::<LinuxTapeDrive>("linux", &drive) {
|
||||
if let Ok(drive_config) = config.lookup::<LtoTapeDrive>("lto", &drive) {
|
||||
// Note: clean_drive unloads the cleaning media, so we cannot use drive_config.open
|
||||
let mut handle = LinuxTapeHandle::new(open_linux_tape_device(&drive_config.path)?);
|
||||
let mut handle = LtoTapeHandle::new(open_lto_tape_device(&drive_config.path)?)?;
|
||||
|
||||
// test for critical tape alert flags
|
||||
if let Ok(alert_flags) = handle.tape_alert_flags() {
|
||||
@ -1144,7 +1144,7 @@ pub async fn cartridge_memory(drive: String) -> Result<Vec<MamAttribute>, Error>
|
||||
drive.clone(),
|
||||
"reading cartridge memory".to_string(),
|
||||
move |config| {
|
||||
let drive_config: LinuxTapeDrive = config.lookup("linux", &drive)?;
|
||||
let drive_config: LtoTapeDrive = config.lookup("lto", &drive)?;
|
||||
let mut handle = drive_config.open()?;
|
||||
|
||||
handle.cartridge_memory()
|
||||
@ -1174,7 +1174,7 @@ pub async fn volume_statistics(drive: String) -> Result<Lp17VolumeStatistics, Er
|
||||
drive.clone(),
|
||||
"reading volume statistics".to_string(),
|
||||
move |config| {
|
||||
let drive_config: LinuxTapeDrive = config.lookup("linux", &drive)?;
|
||||
let drive_config: LtoTapeDrive = config.lookup("lto", &drive)?;
|
||||
let mut handle = drive_config.open()?;
|
||||
|
||||
handle.volume_statistics()
|
||||
@ -1192,24 +1192,24 @@ pub async fn volume_statistics(drive: String) -> Result<Lp17VolumeStatistics, Er
|
||||
},
|
||||
},
|
||||
returns: {
|
||||
type: LinuxDriveAndMediaStatus,
|
||||
type: LtoDriveAndMediaStatus,
|
||||
},
|
||||
access: {
|
||||
permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_AUDIT, false),
|
||||
},
|
||||
)]
|
||||
/// Get drive/media status
|
||||
pub async fn status(drive: String) -> Result<LinuxDriveAndMediaStatus, Error> {
|
||||
pub async fn status(drive: String) -> Result<LtoDriveAndMediaStatus, Error> {
|
||||
run_drive_blocking_task(
|
||||
drive.clone(),
|
||||
"reading drive status".to_string(),
|
||||
move |config| {
|
||||
let drive_config: LinuxTapeDrive = config.lookup("linux", &drive)?;
|
||||
let drive_config: LtoTapeDrive = config.lookup("lto", &drive)?;
|
||||
|
||||
// Note: use open_linux_tape_device, because this also works if no medium loaded
|
||||
let file = open_linux_tape_device(&drive_config.path)?;
|
||||
// Note: use open_lto_tape_device, because this also works if no medium loaded
|
||||
let file = open_lto_tape_device(&drive_config.path)?;
|
||||
|
||||
let mut handle = LinuxTapeHandle::new(file);
|
||||
let mut handle = LtoTapeHandle::new(file)?;
|
||||
|
||||
handle.get_drive_and_media_status()
|
||||
}
|
||||
@ -1382,9 +1382,9 @@ pub fn list_drives(
|
||||
|
||||
let (config, _) = config::drive::config()?;
|
||||
|
||||
let linux_drives = linux_tape_device_list();
|
||||
let lto_drives = lto_tape_device_list();
|
||||
|
||||
let drive_list: Vec<LinuxTapeDrive> = config.convert_to_typed_array("linux")?;
|
||||
let drive_list: Vec<LtoTapeDrive> = config.convert_to_typed_array("lto")?;
|
||||
|
||||
let mut list = Vec::new();
|
||||
|
||||
@ -1398,7 +1398,7 @@ pub fn list_drives(
|
||||
continue;
|
||||
}
|
||||
|
||||
let info = lookup_device_identification(&linux_drives, &drive.path);
|
||||
let info = lookup_device_identification(<o_drives, &drive.path);
|
||||
let state = get_tape_device_state(&config, &drive.name)?;
|
||||
let entry = DriveListEntry { config: drive, info, state };
|
||||
list.push(entry);
|
||||
|
@ -15,7 +15,7 @@ use proxmox::{
|
||||
use crate::{
|
||||
api2::types::TapeDeviceInfo,
|
||||
tape::{
|
||||
linux_tape_device_list,
|
||||
lto_tape_device_list,
|
||||
linux_tape_changer_list,
|
||||
},
|
||||
};
|
||||
@ -41,7 +41,7 @@ pub mod restore;
|
||||
/// Scan tape drives
|
||||
pub fn scan_drives(_param: Value) -> Result<Vec<TapeDeviceInfo>, Error> {
|
||||
|
||||
let list = linux_tape_device_list();
|
||||
let list = lto_tape_device_list();
|
||||
|
||||
Ok(list)
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ pub const DRIVE_NAME_SCHEMA: Schema = StringSchema::new("Drive Identifier.")
|
||||
.max_length(32)
|
||||
.schema();
|
||||
|
||||
pub const LINUX_DRIVE_PATH_SCHEMA: Schema = StringSchema::new(
|
||||
"The path to a LINUX non-rewinding SCSI tape device (i.e. '/dev/nst0')")
|
||||
pub const LTO_DRIVE_PATH_SCHEMA: Schema = StringSchema::new(
|
||||
"The path to a LTO SCSI-generic tape device (i.e. '/dev/sg0')")
|
||||
.schema();
|
||||
|
||||
pub const CHANGER_DRIVENUM_SCHEMA: Schema = IntegerSchema::new(
|
||||
@ -57,7 +57,7 @@ pub struct VirtualTapeDrive {
|
||||
schema: DRIVE_NAME_SCHEMA,
|
||||
},
|
||||
path: {
|
||||
schema: LINUX_DRIVE_PATH_SCHEMA,
|
||||
schema: LTO_DRIVE_PATH_SCHEMA,
|
||||
},
|
||||
changer: {
|
||||
schema: CHANGER_NAME_SCHEMA,
|
||||
@ -71,8 +71,8 @@ pub struct VirtualTapeDrive {
|
||||
)]
|
||||
#[derive(Serialize,Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
/// Linux SCSI tape driver
|
||||
pub struct LinuxTapeDrive {
|
||||
/// Lto SCSI tape driver
|
||||
pub struct LtoTapeDrive {
|
||||
pub name: String,
|
||||
pub path: String,
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
@ -84,7 +84,7 @@ pub struct LinuxTapeDrive {
|
||||
#[api(
|
||||
properties: {
|
||||
config: {
|
||||
type: LinuxTapeDrive,
|
||||
type: LtoTapeDrive,
|
||||
},
|
||||
info: {
|
||||
type: OptionalDeviceIdentification,
|
||||
@ -96,7 +96,7 @@ pub struct LinuxTapeDrive {
|
||||
/// Drive list entry
|
||||
pub struct DriveListEntry {
|
||||
#[serde(flatten)]
|
||||
pub config: LinuxTapeDrive,
|
||||
pub config: LtoTapeDrive,
|
||||
#[serde(flatten)]
|
||||
pub info: OptionalDeviceIdentification,
|
||||
/// the state of the drive if locked
|
||||
@ -169,11 +169,11 @@ impl TryFrom<u8> for TapeDensity {
|
||||
)]
|
||||
#[derive(Serialize,Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
/// Drive/Media status for Linux SCSI drives.
|
||||
/// Drive/Media status for Lto SCSI drives.
|
||||
///
|
||||
/// Media related data is optional - only set if there is a medium
|
||||
/// loaded.
|
||||
pub struct LinuxDriveAndMediaStatus {
|
||||
pub struct LtoDriveAndMediaStatus {
|
||||
/// Block size (0 is variable size)
|
||||
pub blocksize: u32,
|
||||
/// Tape density
|
||||
@ -181,17 +181,17 @@ pub struct LinuxDriveAndMediaStatus {
|
||||
pub density: Option<TapeDensity>,
|
||||
/// Status flags
|
||||
pub status: String,
|
||||
/// Linux Driver Options
|
||||
/// Lto Driver Options
|
||||
pub options: String,
|
||||
/// Tape Alert Flags
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub alert_flags: Option<String>,
|
||||
/// Current file number
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub file_number: Option<u32>,
|
||||
pub file_number: Option<u64>,
|
||||
/// Current block number
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub block_number: Option<u32>,
|
||||
pub block_number: Option<u64>,
|
||||
/// Medium Manufacture Date (epoch)
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub manufactured: Option<i64>,
|
||||
|
Reference in New Issue
Block a user