tape: API type cleanup, use serde flatten to derive types
This commit is contained in:
parent
9586ce2f46
commit
b5b99a52cd
@ -17,7 +17,6 @@ use crate::{
|
|||||||
LINUX_DRIVE_PATH_SCHEMA,
|
LINUX_DRIVE_PATH_SCHEMA,
|
||||||
SLOT_ARRAY_SCHEMA,
|
SLOT_ARRAY_SCHEMA,
|
||||||
EXPORT_SLOT_LIST_SCHEMA,
|
EXPORT_SLOT_LIST_SCHEMA,
|
||||||
DriveListEntry,
|
|
||||||
ScsiTapeChanger,
|
ScsiTapeChanger,
|
||||||
LinuxTapeDrive,
|
LinuxTapeDrive,
|
||||||
},
|
},
|
||||||
@ -121,7 +120,7 @@ pub fn get_config(
|
|||||||
description: "The list of configured changers (with config digest).",
|
description: "The list of configured changers (with config digest).",
|
||||||
type: Array,
|
type: Array,
|
||||||
items: {
|
items: {
|
||||||
type: DriveListEntry,
|
type: ScsiTapeChanger,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)]
|
)]
|
||||||
@ -129,27 +128,14 @@ pub fn get_config(
|
|||||||
pub fn list_changers(
|
pub fn list_changers(
|
||||||
_param: Value,
|
_param: Value,
|
||||||
mut rpcenv: &mut dyn RpcEnvironment,
|
mut rpcenv: &mut dyn RpcEnvironment,
|
||||||
) -> Result<Vec<DriveListEntry>, Error> {
|
) -> Result<Vec<ScsiTapeChanger>, Error> {
|
||||||
|
|
||||||
let (config, digest) = config::drive::config()?;
|
let (config, digest) = config::drive::config()?;
|
||||||
|
|
||||||
let changer_list: Vec<ScsiTapeChanger> = config.convert_to_typed_array("changer")?;
|
let list: Vec<ScsiTapeChanger> = config.convert_to_typed_array("changer")?;
|
||||||
|
|
||||||
let mut list = Vec::new();
|
|
||||||
|
|
||||||
for changer in changer_list {
|
|
||||||
list.push(DriveListEntry {
|
|
||||||
name: changer.name,
|
|
||||||
path: changer.path.clone(),
|
|
||||||
changer: None,
|
|
||||||
changer_drivenum: None,
|
|
||||||
vendor: None,
|
|
||||||
model: None,
|
|
||||||
serial: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
|
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
|
||||||
|
|
||||||
Ok(list)
|
Ok(list)
|
||||||
}
|
}
|
||||||
#[api()]
|
#[api()]
|
||||||
|
@ -12,7 +12,6 @@ use crate::{
|
|||||||
CHANGER_NAME_SCHEMA,
|
CHANGER_NAME_SCHEMA,
|
||||||
CHANGER_DRIVENUM_SCHEMA,
|
CHANGER_DRIVENUM_SCHEMA,
|
||||||
LINUX_DRIVE_PATH_SCHEMA,
|
LINUX_DRIVE_PATH_SCHEMA,
|
||||||
DriveListEntry,
|
|
||||||
LinuxTapeDrive,
|
LinuxTapeDrive,
|
||||||
ScsiTapeChanger,
|
ScsiTapeChanger,
|
||||||
},
|
},
|
||||||
@ -110,7 +109,7 @@ pub fn get_config(
|
|||||||
description: "The list of configured drives (with config digest).",
|
description: "The list of configured drives (with config digest).",
|
||||||
type: Array,
|
type: Array,
|
||||||
items: {
|
items: {
|
||||||
type: DriveListEntry,
|
type: LinuxTapeDrive,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)]
|
)]
|
||||||
@ -125,6 +124,7 @@ pub fn list_drives(
|
|||||||
let drive_list: Vec<LinuxTapeDrive> = config.convert_to_typed_array("linux")?;
|
let drive_list: Vec<LinuxTapeDrive> = config.convert_to_typed_array("linux")?;
|
||||||
|
|
||||||
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
|
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
|
||||||
|
|
||||||
Ok(drive_list)
|
Ok(drive_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use crate::{
|
|||||||
config,
|
config,
|
||||||
api2::types::{
|
api2::types::{
|
||||||
CHANGER_NAME_SCHEMA,
|
CHANGER_NAME_SCHEMA,
|
||||||
DriveListEntry,
|
ChangerListEntry,
|
||||||
MtxEntryKind,
|
MtxEntryKind,
|
||||||
MtxStatusEntry,
|
MtxStatusEntry,
|
||||||
ScsiTapeChanger,
|
ScsiTapeChanger,
|
||||||
@ -25,7 +25,7 @@ use crate::{
|
|||||||
ScsiMediaChange,
|
ScsiMediaChange,
|
||||||
mtx_status_to_online_set,
|
mtx_status_to_online_set,
|
||||||
},
|
},
|
||||||
lookup_drive,
|
lookup_device_identification,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,14 +144,14 @@ pub async fn transfer(
|
|||||||
description: "The list of configured changers with model information.",
|
description: "The list of configured changers with model information.",
|
||||||
type: Array,
|
type: Array,
|
||||||
items: {
|
items: {
|
||||||
type: DriveListEntry,
|
type: ChangerListEntry,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)]
|
)]
|
||||||
/// List changers
|
/// List changers
|
||||||
pub fn list_changers(
|
pub fn list_changers(
|
||||||
_param: Value,
|
_param: Value,
|
||||||
) -> Result<Vec<DriveListEntry>, Error> {
|
) -> Result<Vec<ChangerListEntry>, Error> {
|
||||||
|
|
||||||
let (config, _digest) = config::drive::config()?;
|
let (config, _digest) = config::drive::config()?;
|
||||||
|
|
||||||
@ -162,21 +162,8 @@ pub fn list_changers(
|
|||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
|
|
||||||
for changer in changer_list {
|
for changer in changer_list {
|
||||||
let mut entry = DriveListEntry {
|
let info = lookup_device_identification(&linux_changers, &changer.path);
|
||||||
name: changer.name,
|
let entry = ChangerListEntry { config: changer, info };
|
||||||
path: changer.path.clone(),
|
|
||||||
changer: None,
|
|
||||||
changer_drivenum: None,
|
|
||||||
vendor: None,
|
|
||||||
model: None,
|
|
||||||
serial: None,
|
|
||||||
};
|
|
||||||
if let Some(info) = lookup_drive(&linux_changers, &changer.path) {
|
|
||||||
entry.vendor = Some(info.vendor.clone());
|
|
||||||
entry.model = Some(info.model.clone());
|
|
||||||
entry.serial = Some(info.serial.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
list.push(entry);
|
list.push(entry);
|
||||||
}
|
}
|
||||||
Ok(list)
|
Ok(list)
|
||||||
|
@ -49,7 +49,7 @@ use crate::{
|
|||||||
MediaCatalog,
|
MediaCatalog,
|
||||||
MediaId,
|
MediaId,
|
||||||
linux_tape_device_list,
|
linux_tape_device_list,
|
||||||
lookup_drive,
|
lookup_device_identification,
|
||||||
file_formats::{
|
file_formats::{
|
||||||
MediaLabel,
|
MediaLabel,
|
||||||
MediaSetLabel,
|
MediaSetLabel,
|
||||||
@ -1133,21 +1133,8 @@ pub fn list_drives(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut entry = DriveListEntry {
|
let info = lookup_device_identification(&linux_drives, &drive.path);
|
||||||
name: drive.name,
|
let entry = DriveListEntry { config: drive, info };
|
||||||
path: drive.path.clone(),
|
|
||||||
changer: drive.changer,
|
|
||||||
changer_drivenum: drive.changer_drivenum,
|
|
||||||
vendor: None,
|
|
||||||
model: None,
|
|
||||||
serial: None,
|
|
||||||
};
|
|
||||||
if let Some(info) = lookup_drive(&linux_drives, &drive.path) {
|
|
||||||
entry.vendor = Some(info.vendor.clone());
|
|
||||||
entry.model = Some(info.model.clone());
|
|
||||||
entry.serial = Some(info.serial.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
list.push(entry);
|
list.push(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,10 @@ use proxmox::api::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::api2::types::PROXMOX_SAFE_ID_FORMAT;
|
use crate::api2::types::{
|
||||||
|
PROXMOX_SAFE_ID_FORMAT,
|
||||||
|
OptionalDeviceIdentification,
|
||||||
|
};
|
||||||
|
|
||||||
pub const CHANGER_NAME_SCHEMA: Schema = StringSchema::new("Tape Changer Identifier.")
|
pub const CHANGER_NAME_SCHEMA: Schema = StringSchema::new("Tape Changer Identifier.")
|
||||||
.format(&PROXMOX_SAFE_ID_FORMAT)
|
.format(&PROXMOX_SAFE_ID_FORMAT)
|
||||||
@ -69,6 +72,26 @@ pub struct ScsiTapeChanger {
|
|||||||
pub export_slots: Option<String>,
|
pub export_slots: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
properties: {
|
||||||
|
config: {
|
||||||
|
type: ScsiTapeChanger,
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
type: OptionalDeviceIdentification,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
#[derive(Serialize,Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
/// Changer config with optional device identification attributes
|
||||||
|
pub struct ChangerListEntry {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub config: ScsiTapeChanger,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub info: OptionalDeviceIdentification,
|
||||||
|
}
|
||||||
|
|
||||||
#[api()]
|
#[api()]
|
||||||
#[derive(Serialize,Deserialize)]
|
#[derive(Serialize,Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
@ -2,6 +2,22 @@ use ::serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use proxmox::api::api;
|
use proxmox::api::api;
|
||||||
|
|
||||||
|
#[api()]
|
||||||
|
#[derive(Serialize,Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
/// Optional Device Identification Attributes
|
||||||
|
pub struct OptionalDeviceIdentification {
|
||||||
|
/// Vendor (autodetected)
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
pub vendor: Option<String>,
|
||||||
|
/// Model (autodetected)
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
pub model: Option<String>,
|
||||||
|
/// Serial number (autodetected)
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
pub serial: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[api()]
|
#[api()]
|
||||||
#[derive(Debug,Serialize,Deserialize)]
|
#[derive(Debug,Serialize,Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
@ -12,6 +12,7 @@ use proxmox::api::{
|
|||||||
use crate::api2::types::{
|
use crate::api2::types::{
|
||||||
PROXMOX_SAFE_ID_FORMAT,
|
PROXMOX_SAFE_ID_FORMAT,
|
||||||
CHANGER_NAME_SCHEMA,
|
CHANGER_NAME_SCHEMA,
|
||||||
|
OptionalDeviceIdentification,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DRIVE_NAME_SCHEMA: Schema = StringSchema::new("Drive Identifier.")
|
pub const DRIVE_NAME_SCHEMA: Schema = StringSchema::new("Drive Identifier.")
|
||||||
@ -80,30 +81,24 @@ pub struct LinuxTapeDrive {
|
|||||||
pub changer_drivenum: Option<u64>,
|
pub changer_drivenum: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[api()]
|
#[api(
|
||||||
|
properties: {
|
||||||
|
config: {
|
||||||
|
type: LinuxTapeDrive,
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
type: OptionalDeviceIdentification,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
#[derive(Serialize,Deserialize)]
|
#[derive(Serialize,Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
/// Drive list entry
|
/// Drive list entry
|
||||||
pub struct DriveListEntry {
|
pub struct DriveListEntry {
|
||||||
/// Drive name
|
#[serde(flatten)]
|
||||||
pub name: String,
|
pub config: LinuxTapeDrive,
|
||||||
/// Path to the linux device node
|
#[serde(flatten)]
|
||||||
pub path: String,
|
pub info: OptionalDeviceIdentification,
|
||||||
/// Associated changer device
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
pub changer: Option<String>,
|
|
||||||
/// Drive number in associated changer device
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
pub changer_drivenum: Option<u64>,
|
|
||||||
/// Vendor (autodetected)
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
pub vendor: Option<String>,
|
|
||||||
/// Model (autodetected)
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
pub model: Option<String>,
|
|
||||||
/// Serial number (autodetected)
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
pub serial: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[api()]
|
#[api()]
|
||||||
|
@ -6,6 +6,7 @@ use anyhow::{bail, Error};
|
|||||||
use crate::{
|
use crate::{
|
||||||
api2::types::{
|
api2::types::{
|
||||||
DeviceKind,
|
DeviceKind,
|
||||||
|
OptionalDeviceIdentification,
|
||||||
TapeDeviceInfo,
|
TapeDeviceInfo,
|
||||||
},
|
},
|
||||||
tools::fs::scan_subdir,
|
tools::fs::scan_subdir,
|
||||||
@ -191,9 +192,9 @@ pub fn linux_tape_device_list() -> Vec<TapeDeviceInfo> {
|
|||||||
list
|
list
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test if path is a linux tape device
|
/// Test if a device exists, and returns associated `TapeDeviceInfo`
|
||||||
pub fn lookup_drive<'a>(
|
pub fn lookup_device<'a>(
|
||||||
drives: &'a[TapeDeviceInfo],
|
devices: &'a[TapeDeviceInfo],
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Option<&'a TapeDeviceInfo> {
|
) -> Option<&'a TapeDeviceInfo> {
|
||||||
|
|
||||||
@ -202,18 +203,39 @@ pub fn lookup_drive<'a>(
|
|||||||
let major = unsafe { libc::major(stat.st_rdev) };
|
let major = unsafe { libc::major(stat.st_rdev) };
|
||||||
let minor = unsafe { libc::minor(stat.st_rdev) };
|
let minor = unsafe { libc::minor(stat.st_rdev) };
|
||||||
|
|
||||||
drives.iter().find(|d| d.major == major && d.minor == minor)
|
devices.iter().find(|d| d.major == major && d.minor == minor)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lookup optional drive identification attributes
|
||||||
|
pub fn lookup_device_identification<'a>(
|
||||||
|
devices: &'a[TapeDeviceInfo],
|
||||||
|
path: &str,
|
||||||
|
) -> OptionalDeviceIdentification {
|
||||||
|
|
||||||
|
if let Some(info) = lookup_device(devices, path) {
|
||||||
|
OptionalDeviceIdentification {
|
||||||
|
vendor: Some(info.vendor.clone()),
|
||||||
|
model: Some(info.model.clone()),
|
||||||
|
serial: Some(info.serial.clone()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OptionalDeviceIdentification {
|
||||||
|
vendor: None,
|
||||||
|
model: None,
|
||||||
|
serial: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Make sure path is a linux tape device
|
/// Make sure path is a linux tape device
|
||||||
pub fn check_drive_path(
|
pub fn check_drive_path(
|
||||||
drives: &[TapeDeviceInfo],
|
drives: &[TapeDeviceInfo],
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if lookup_drive(drives, path).is_none() {
|
if lookup_device(drives, path).is_none() {
|
||||||
bail!("path '{}' is not a linux (non-rewinding) tape device", path);
|
bail!("path '{}' is not a linux (non-rewinding) tape device", path);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user