diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs index bc5b97c8..016e3092 100644 --- a/src/api2/tape/drive.rs +++ b/src/api2/tape/drive.rs @@ -538,7 +538,7 @@ pub async fn read_label( let media_id = match media_id { Some(media_id) => { let mut flat = MediaIdFlat { - uuid: media_id.label.uuid.to_string(), + uuid: media_id.label.uuid.clone(), label_text: media_id.label.label_text.clone(), ctime: media_id.label.ctime, media_set_ctime: None, @@ -550,7 +550,7 @@ pub async fn read_label( if let Some(ref set) = media_id.media_set_label { flat.pool = Some(set.pool.clone()); flat.seq_nr = Some(set.seq_nr); - flat.media_set_uuid = Some(set.uuid.to_string()); + flat.media_set_uuid = Some(set.uuid.clone()); flat.media_set_ctime = Some(set.ctime); flat.encryption_key_fingerprint = set .encryption_key_fingerprint @@ -678,7 +678,7 @@ pub async fn inventory( let label_text = label_text.to_string(); if let Some(media_id) = inventory.find_media_by_label_text(&label_text) { - list.push(LabelUuidMap { label_text, uuid: Some(media_id.label.uuid.to_string()) }); + list.push(LabelUuidMap { label_text, uuid: Some(media_id.label.uuid.clone()) }); } else { list.push(LabelUuidMap { label_text, uuid: None }); } diff --git a/src/api2/tape/media.rs b/src/api2/tape/media.rs index cbbe80c5..3b2ea025 100644 --- a/src/api2/tape/media.rs +++ b/src/api2/tape/media.rs @@ -6,6 +6,7 @@ use serde::{Serialize, Deserialize}; use proxmox::{ api::{api, Router, SubdirMap}, list_subdirs_api_method, + tools::Uuid, }; use crate::{ @@ -17,6 +18,8 @@ use crate::{ BACKUP_TYPE_SCHEMA, MEDIA_POOL_NAME_SCHEMA, MEDIA_LABEL_SCHEMA, + MEDIA_UUID_SCHEMA, + MEDIA_SET_UUID_SCHEMA, MediaPoolConfig, MediaListEntry, MediaStatus, @@ -92,7 +95,7 @@ pub async fn list_media(pool: Option) -> Result, Err let expired = pool.media_is_expired(&media, current_time); let media_set_uuid = media.media_set_label() - .map(|set| set.uuid.to_string()); + .map(|set| set.uuid.clone()); let seq_nr = media.media_set_label() .map(|set| set.seq_nr); @@ -111,7 +114,7 @@ pub async fn list_media(pool: Option) -> Result, Err }; list.push(MediaListEntry { - uuid: media.uuid().to_string(), + uuid: media.uuid().clone(), label_text: media.label_text().to_string(), ctime: media.ctime(), pool: Some(pool_name.to_string()), @@ -140,7 +143,7 @@ pub async fn list_media(pool: Option) -> Result, Err } list.push(MediaListEntry { - uuid: media_id.label.uuid.to_string(), + uuid: media_id.label.uuid.clone(), ctime: media_id.label.ctime, label_text: media_id.label.label_text.to_string(), location, @@ -212,13 +215,11 @@ pub fn destroy_media(label_text: String, force: Option,) -> Result<(), Err optional: true, }, "media": { - description: "Filter by media UUID.", - type: String, + schema: MEDIA_UUID_SCHEMA, optional: true, }, "media-set": { - description: "Filter by media set UUID.", - type: String, + schema: MEDIA_SET_UUID_SCHEMA, optional: true, }, "backup-type": { @@ -237,8 +238,8 @@ pub fn destroy_media(label_text: String, force: Option,) -> Result<(), Err pub struct MediaContentListFilter { pub pool: Option, pub label_text: Option, - pub media: Option, - pub media_set: Option, + pub media: Option, + pub media_set: Option, pub backup_type: Option, pub backup_id: Option, } @@ -270,9 +271,6 @@ pub fn list_content( let status_path = Path::new(TAPE_STATUS_DIR); let inventory = Inventory::load(status_path)?; - let media_uuid = filter.media.and_then(|s| s.parse().ok()); - let media_set_uuid = filter.media_set.and_then(|s| s.parse().ok()); - let mut list = Vec::new(); for media_id in inventory.list_used_media() { @@ -286,11 +284,11 @@ pub fn list_content( if &set.pool != pool { continue; } } - if let Some(ref media_uuid) = media_uuid { + if let Some(ref media_uuid) = filter.media { if &media_id.label.uuid != media_uuid { continue; } } - if let Some(ref media_set_uuid) = media_set_uuid { + if let Some(ref media_set_uuid) = filter.media_set { if &set.uuid != media_set_uuid { continue; } } @@ -313,11 +311,11 @@ pub fn list_content( } list.push(MediaContentEntry { - uuid: media_id.label.uuid.to_string(), + uuid: media_id.label.uuid.clone(), label_text: media_id.label.label_text.to_string(), pool: set.pool.clone(), media_set_name: media_set_name.clone(), - media_set_uuid: set.uuid.to_string(), + media_set_uuid: set.uuid.clone(), seq_nr: set.seq_nr, snapshot: snapshot.to_owned(), backup_time: backup_dir.backup_time(), diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs index 93bc58df..546acace 100644 --- a/src/api2/types/mod.rs +++ b/src/api2/types/mod.rs @@ -316,7 +316,7 @@ pub const DATASTORE_SCHEMA: Schema = StringSchema::new("Datastore name.") .schema(); pub const MEDIA_SET_UUID_SCHEMA: Schema = - StringSchema::new("MediaSet Uuid.") + StringSchema::new("MediaSet Uuid (We use the all-zero Uuid to reseve an empty media for a specific pool).") .format(&UUID_FORMAT) .schema(); diff --git a/src/api2/types/tape/media.rs b/src/api2/types/tape/media.rs index 62f1a2b1..2da1849b 100644 --- a/src/api2/types/tape/media.rs +++ b/src/api2/types/tape/media.rs @@ -1,8 +1,13 @@ use ::serde::{Deserialize, Serialize}; -use proxmox::api::api; +use proxmox::{ + api::api, + tools::Uuid, +}; -use super::{ +use crate::api2::types::{ + MEDIA_UUID_SCHEMA, + MEDIA_SET_UUID_SCHEMA, MediaStatus, MediaLocation, }; @@ -15,6 +20,13 @@ use super::{ status: { type: MediaStatus, }, + uuid: { + schema: MEDIA_UUID_SCHEMA, + }, + "media-set-uuid": { + schema: MEDIA_SET_UUID_SCHEMA, + optional: true, + }, }, )] #[derive(Serialize,Deserialize)] @@ -23,8 +35,7 @@ use super::{ pub struct MediaListEntry { /// Media label text (or Barcode) pub label_text: String, - /// Media Uuid - pub uuid: String, + pub uuid: Uuid, /// Creation time stamp pub ctime: i64, pub location: MediaLocation, @@ -36,9 +47,8 @@ pub struct MediaListEntry { /// Media set name #[serde(skip_serializing_if="Option::is_none")] pub media_set_name: Option, - /// Media set uuid #[serde(skip_serializing_if="Option::is_none")] - pub media_set_uuid: Option, + pub media_set_uuid: Option, /// Media set seq_nr #[serde(skip_serializing_if="Option::is_none")] pub seq_nr: Option, @@ -50,13 +60,23 @@ pub struct MediaListEntry { pub pool: Option, } -#[api()] +#[api( + properties: { + uuid: { + schema: MEDIA_UUID_SCHEMA, + }, + "media-set-uuid": { + schema: MEDIA_SET_UUID_SCHEMA, + optional: true, + }, + }, +)] #[derive(Serialize,Deserialize)] #[serde(rename_all = "kebab-case")] /// Media label info pub struct MediaIdFlat { /// Unique ID - pub uuid: String, + pub uuid: Uuid, /// Media label text (or Barcode) pub label_text: String, /// Creation time stamp @@ -65,9 +85,8 @@ pub struct MediaIdFlat { /// MediaSet Pool #[serde(skip_serializing_if="Option::is_none")] pub pool: Option, - /// MediaSet Uuid. We use the all-zero Uuid to reseve an empty media for a specific pool #[serde(skip_serializing_if="Option::is_none")] - pub media_set_uuid: Option, + pub media_set_uuid: Option, /// MediaSet media sequence number #[serde(skip_serializing_if="Option::is_none")] pub seq_nr: Option, @@ -79,7 +98,14 @@ pub struct MediaIdFlat { pub encryption_key_fingerprint: Option, } -#[api()] +#[api( + properties: { + uuid: { + schema: MEDIA_UUID_SCHEMA, + optional: true, + }, + }, +)] #[derive(Serialize,Deserialize)] #[serde(rename_all = "kebab-case")] /// Label with optional Uuid @@ -87,10 +113,19 @@ pub struct LabelUuidMap { /// Changer label text (or Barcode) pub label_text: String, /// Associated Uuid (if any) - pub uuid: Option, + pub uuid: Option, } -#[api()] +#[api( + properties: { + uuid: { + schema: MEDIA_UUID_SCHEMA, + }, + "media-set-uuid": { + schema: MEDIA_SET_UUID_SCHEMA, + }, + }, +)] #[derive(Serialize,Deserialize)] #[serde(rename_all = "kebab-case")] /// Media content list entry @@ -98,11 +133,11 @@ pub struct MediaContentEntry { /// Media label text (or Barcode) pub label_text: String, /// Media Uuid - pub uuid: String, + pub uuid: Uuid, /// Media set name pub media_set_name: String, /// Media set uuid - pub media_set_uuid: String, + pub media_set_uuid: Uuid, /// Media set seq_nr pub seq_nr: u64, /// Media Pool