tape: API type cleanup, use serde flatten to derive types

This commit is contained in:
Dietmar Maurer 2021-01-30 09:36:54 +01:00
parent 9586ce2f46
commit b5b99a52cd
8 changed files with 97 additions and 81 deletions

View File

@ -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()]

View File

@ -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)
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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")]

View File

@ -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")]

View File

@ -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()]

View File

@ -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(())