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,
|
||||
SLOT_ARRAY_SCHEMA,
|
||||
EXPORT_SLOT_LIST_SCHEMA,
|
||||
DriveListEntry,
|
||||
ScsiTapeChanger,
|
||||
LinuxTapeDrive,
|
||||
},
|
||||
@ -121,7 +120,7 @@ pub fn get_config(
|
||||
description: "The list of configured changers (with config digest).",
|
||||
type: Array,
|
||||
items: {
|
||||
type: DriveListEntry,
|
||||
type: ScsiTapeChanger,
|
||||
},
|
||||
},
|
||||
)]
|
||||
@ -129,27 +128,14 @@ pub fn get_config(
|
||||
pub fn list_changers(
|
||||
_param: Value,
|
||||
mut rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<Vec<DriveListEntry>, Error> {
|
||||
) -> Result<Vec<ScsiTapeChanger>, Error> {
|
||||
|
||||
let (config, digest) = config::drive::config()?;
|
||||
|
||||
let changer_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,
|
||||
});
|
||||
}
|
||||
let list: Vec<ScsiTapeChanger> = config.convert_to_typed_array("changer")?;
|
||||
|
||||
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
|
||||
|
||||
Ok(list)
|
||||
}
|
||||
#[api()]
|
||||
|
@ -12,7 +12,6 @@ use crate::{
|
||||
CHANGER_NAME_SCHEMA,
|
||||
CHANGER_DRIVENUM_SCHEMA,
|
||||
LINUX_DRIVE_PATH_SCHEMA,
|
||||
DriveListEntry,
|
||||
LinuxTapeDrive,
|
||||
ScsiTapeChanger,
|
||||
},
|
||||
@ -110,7 +109,7 @@ pub fn get_config(
|
||||
description: "The list of configured drives (with config digest).",
|
||||
type: Array,
|
||||
items: {
|
||||
type: DriveListEntry,
|
||||
type: LinuxTapeDrive,
|
||||
},
|
||||
},
|
||||
)]
|
||||
@ -125,6 +124,7 @@ pub fn list_drives(
|
||||
let drive_list: Vec<LinuxTapeDrive> = config.convert_to_typed_array("linux")?;
|
||||
|
||||
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
|
||||
|
||||
Ok(drive_list)
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
config,
|
||||
api2::types::{
|
||||
CHANGER_NAME_SCHEMA,
|
||||
DriveListEntry,
|
||||
ChangerListEntry,
|
||||
MtxEntryKind,
|
||||
MtxStatusEntry,
|
||||
ScsiTapeChanger,
|
||||
@ -25,7 +25,7 @@ use crate::{
|
||||
ScsiMediaChange,
|
||||
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.",
|
||||
type: Array,
|
||||
items: {
|
||||
type: DriveListEntry,
|
||||
type: ChangerListEntry,
|
||||
},
|
||||
},
|
||||
)]
|
||||
/// List changers
|
||||
pub fn list_changers(
|
||||
_param: Value,
|
||||
) -> Result<Vec<DriveListEntry>, Error> {
|
||||
) -> Result<Vec<ChangerListEntry>, Error> {
|
||||
|
||||
let (config, _digest) = config::drive::config()?;
|
||||
|
||||
@ -162,21 +162,8 @@ pub fn list_changers(
|
||||
let mut list = Vec::new();
|
||||
|
||||
for changer in changer_list {
|
||||
let mut entry = DriveListEntry {
|
||||
name: changer.name,
|
||||
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());
|
||||
}
|
||||
|
||||
let info = lookup_device_identification(&linux_changers, &changer.path);
|
||||
let entry = ChangerListEntry { config: changer, info };
|
||||
list.push(entry);
|
||||
}
|
||||
Ok(list)
|
||||
|
@ -49,7 +49,7 @@ use crate::{
|
||||
MediaCatalog,
|
||||
MediaId,
|
||||
linux_tape_device_list,
|
||||
lookup_drive,
|
||||
lookup_device_identification,
|
||||
file_formats::{
|
||||
MediaLabel,
|
||||
MediaSetLabel,
|
||||
@ -1133,21 +1133,8 @@ pub fn list_drives(
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut entry = DriveListEntry {
|
||||
name: drive.name,
|
||||
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());
|
||||
}
|
||||
|
||||
let info = lookup_device_identification(&linux_drives, &drive.path);
|
||||
let entry = DriveListEntry { config: drive, info };
|
||||
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.")
|
||||
.format(&PROXMOX_SAFE_ID_FORMAT)
|
||||
@ -69,6 +72,26 @@ pub struct ScsiTapeChanger {
|
||||
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()]
|
||||
#[derive(Serialize,Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
|
@ -2,6 +2,22 @@ use ::serde::{Deserialize, Serialize};
|
||||
|
||||
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()]
|
||||
#[derive(Debug,Serialize,Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
|
@ -12,6 +12,7 @@ use proxmox::api::{
|
||||
use crate::api2::types::{
|
||||
PROXMOX_SAFE_ID_FORMAT,
|
||||
CHANGER_NAME_SCHEMA,
|
||||
OptionalDeviceIdentification,
|
||||
};
|
||||
|
||||
pub const DRIVE_NAME_SCHEMA: Schema = StringSchema::new("Drive Identifier.")
|
||||
@ -80,30 +81,24 @@ pub struct LinuxTapeDrive {
|
||||
pub changer_drivenum: Option<u64>,
|
||||
}
|
||||
|
||||
#[api()]
|
||||
#[api(
|
||||
properties: {
|
||||
config: {
|
||||
type: LinuxTapeDrive,
|
||||
},
|
||||
info: {
|
||||
type: OptionalDeviceIdentification,
|
||||
},
|
||||
},
|
||||
)]
|
||||
#[derive(Serialize,Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
/// Drive list entry
|
||||
pub struct DriveListEntry {
|
||||
/// Drive name
|
||||
pub name: String,
|
||||
/// Path to the linux device node
|
||||
pub path: String,
|
||||
/// 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>,
|
||||
#[serde(flatten)]
|
||||
pub config: LinuxTapeDrive,
|
||||
#[serde(flatten)]
|
||||
pub info: OptionalDeviceIdentification,
|
||||
}
|
||||
|
||||
#[api()]
|
||||
|
@ -6,6 +6,7 @@ use anyhow::{bail, Error};
|
||||
use crate::{
|
||||
api2::types::{
|
||||
DeviceKind,
|
||||
OptionalDeviceIdentification,
|
||||
TapeDeviceInfo,
|
||||
},
|
||||
tools::fs::scan_subdir,
|
||||
@ -191,9 +192,9 @@ pub fn linux_tape_device_list() -> Vec<TapeDeviceInfo> {
|
||||
list
|
||||
}
|
||||
|
||||
/// Test if path is a linux tape device
|
||||
pub fn lookup_drive<'a>(
|
||||
drives: &'a[TapeDeviceInfo],
|
||||
/// Test if a device exists, and returns associated `TapeDeviceInfo`
|
||||
pub fn lookup_device<'a>(
|
||||
devices: &'a[TapeDeviceInfo],
|
||||
path: &str,
|
||||
) -> Option<&'a TapeDeviceInfo> {
|
||||
|
||||
@ -202,18 +203,39 @@ pub fn lookup_drive<'a>(
|
||||
let major = unsafe { libc::major(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 {
|
||||
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
|
||||
pub fn check_drive_path(
|
||||
drives: &[TapeDeviceInfo],
|
||||
path: &str,
|
||||
) -> 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);
|
||||
}
|
||||
Ok(())
|
||||
|
Loading…
Reference in New Issue
Block a user