tape: cleanup MediaLocation type for direct use with API
This commit is contained in:
parent
7680525eec
commit
c1c2c8f635
|
@ -17,32 +17,16 @@ use crate::{
|
|||
MediaPoolConfig,
|
||||
MediaListEntry,
|
||||
MediaStatus,
|
||||
MediaLocationKind,
|
||||
},
|
||||
tape::{
|
||||
TAPE_STATUS_DIR,
|
||||
Inventory,
|
||||
MediaStateDatabase,
|
||||
MediaLocation,
|
||||
MediaPool,
|
||||
update_online_status,
|
||||
},
|
||||
};
|
||||
|
||||
fn split_location(location: &MediaLocation) -> (MediaLocationKind, Option<String>) {
|
||||
match location {
|
||||
MediaLocation::Online(changer_name) => {
|
||||
(MediaLocationKind::Online, Some(changer_name.to_string()))
|
||||
}
|
||||
MediaLocation::Offline => {
|
||||
(MediaLocationKind::Offline, None)
|
||||
}
|
||||
MediaLocation::Vault(vault) => {
|
||||
(MediaLocationKind::Vault, Some(vault.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[api(
|
||||
input: {
|
||||
properties: {
|
||||
|
@ -94,8 +78,6 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
|
|||
let current_time = proxmox::tools::time::epoch_i64();
|
||||
|
||||
for media in pool.list_media() {
|
||||
let (location, location_hint) = split_location(&media.location());
|
||||
|
||||
let expired = pool.media_is_expired(&media, current_time);
|
||||
|
||||
let media_set_uuid = media.media_set_label().as_ref()
|
||||
|
@ -114,8 +96,7 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
|
|||
uuid: media.uuid().to_string(),
|
||||
changer_id: media.changer_id().to_string(),
|
||||
pool: Some(pool_name.to_string()),
|
||||
location,
|
||||
location_hint,
|
||||
location: media.location().clone(),
|
||||
status: *media.status(),
|
||||
expired,
|
||||
media_set_uuid,
|
||||
|
@ -133,7 +114,6 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
|
|||
for media_id in inventory.list_unassigned_media() {
|
||||
|
||||
let (mut status, location) = state_db.status_and_location(&media_id.label.uuid);
|
||||
let (location, location_hint) = split_location(&location);
|
||||
|
||||
if status == MediaStatus::Unknown {
|
||||
status = MediaStatus::Writable;
|
||||
|
@ -143,7 +123,6 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
|
|||
uuid: media_id.label.uuid.to_string(),
|
||||
changer_id: media_id.label.changer_id.to_string(),
|
||||
location,
|
||||
location_hint,
|
||||
status,
|
||||
expired: false,
|
||||
media_set_uuid: None,
|
||||
|
|
|
@ -4,26 +4,13 @@ use proxmox::api::api;
|
|||
|
||||
use super::{
|
||||
MediaStatus,
|
||||
MediaLocation,
|
||||
};
|
||||
|
||||
#[api()]
|
||||
#[derive(Serialize,Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
/// Media location
|
||||
pub enum MediaLocationKind {
|
||||
/// Ready for use (inside tape library)
|
||||
Online,
|
||||
/// Local available, but need to be mounted (insert into tape
|
||||
/// drive)
|
||||
Offline,
|
||||
/// Media is inside a Vault
|
||||
Vault,
|
||||
}
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
location: {
|
||||
type: MediaLocationKind,
|
||||
type: MediaLocation,
|
||||
},
|
||||
status: {
|
||||
type: MediaStatus,
|
||||
|
@ -38,9 +25,7 @@ pub struct MediaListEntry {
|
|||
pub changer_id: String,
|
||||
/// Media Uuid
|
||||
pub uuid: String,
|
||||
pub location: MediaLocationKind,
|
||||
/// Media location hint (vault name, changer name)
|
||||
pub location_hint: Option<String>,
|
||||
pub location: MediaLocation,
|
||||
pub status: MediaStatus,
|
||||
/// Expired flag
|
||||
pub expired: bool,
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
use anyhow::{bail, Error};
|
||||
|
||||
use proxmox::api::{
|
||||
schema::{
|
||||
Schema,
|
||||
StringSchema,
|
||||
ApiStringFormat,
|
||||
parse_simple_value,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::api2::types::{
|
||||
PROXMOX_SAFE_ID_FORMAT,
|
||||
CHANGER_NAME_SCHEMA,
|
||||
};
|
||||
|
||||
pub const VAULT_NAME_SCHEMA: Schema = StringSchema::new("Vault name.")
|
||||
.format(&PROXMOX_SAFE_ID_FORMAT)
|
||||
.min_length(3)
|
||||
.max_length(32)
|
||||
.schema();
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
/// Media location
|
||||
pub enum MediaLocation {
|
||||
/// Ready for use (inside tape library)
|
||||
Online(String),
|
||||
/// Local available, but need to be mounted (insert into tape
|
||||
/// drive)
|
||||
Offline,
|
||||
/// Media is inside a Vault
|
||||
Vault(String),
|
||||
}
|
||||
|
||||
proxmox::forward_deserialize_to_from_str!(MediaLocation);
|
||||
proxmox::forward_serialize_to_display!(MediaLocation);
|
||||
|
||||
impl MediaLocation {
|
||||
pub const API_SCHEMA: Schema = StringSchema::new(
|
||||
"Media location (e.g. 'offline', 'online-<changer_name>', 'vault-<vault_name>')")
|
||||
.format(&ApiStringFormat::VerifyFn(|text| {
|
||||
let location: MediaLocation = text.parse()?;
|
||||
match location {
|
||||
MediaLocation::Online(ref changer) => {
|
||||
parse_simple_value(changer, &CHANGER_NAME_SCHEMA)?;
|
||||
}
|
||||
MediaLocation::Vault(ref vault) => {
|
||||
parse_simple_value(vault, &VAULT_NAME_SCHEMA)?;
|
||||
}
|
||||
MediaLocation::Offline => { /* OK */}
|
||||
}
|
||||
Ok(())
|
||||
}))
|
||||
.schema();
|
||||
}
|
||||
|
||||
|
||||
impl std::fmt::Display for MediaLocation {
|
||||
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MediaLocation::Offline => {
|
||||
write!(f, "offline")
|
||||
}
|
||||
MediaLocation::Online(changer) => {
|
||||
write!(f, "online-{}", changer)
|
||||
}
|
||||
MediaLocation::Vault(vault) => {
|
||||
write!(f, "vault-{}", vault)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for MediaLocation {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s == "offline" {
|
||||
return Ok(MediaLocation::Offline);
|
||||
}
|
||||
if let Some(changer) = s.strip_prefix("online-") {
|
||||
return Ok(MediaLocation::Online(changer.to_string()));
|
||||
}
|
||||
if let Some(vault) = s.strip_prefix("vault-") {
|
||||
return Ok(MediaLocation::Online(vault.to_string()));
|
||||
}
|
||||
|
||||
bail!("MediaLocation parse error");
|
||||
}
|
||||
}
|
|
@ -15,5 +15,8 @@ pub use media_pool::*;
|
|||
mod media_status;
|
||||
pub use media_status::*;
|
||||
|
||||
mod media_location;
|
||||
pub use media_location::*;
|
||||
|
||||
mod media;
|
||||
pub use media::*;
|
||||
|
|
|
@ -15,7 +15,6 @@ use proxmox_backup::{
|
|||
self,
|
||||
types::{
|
||||
MEDIA_POOL_NAME_SCHEMA,
|
||||
MediaLocationKind,
|
||||
MediaStatus,
|
||||
MediaListEntry,
|
||||
},
|
||||
|
@ -72,19 +71,6 @@ async fn list_media(
|
|||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
fn render_location(_value: &Value, record: &Value) -> Result<String, Error> {
|
||||
let record: MediaListEntry = serde_json::from_value(record.clone())?;
|
||||
Ok(match record.location {
|
||||
MediaLocationKind::Online => {
|
||||
record.location_hint.unwrap_or(String::from("-"))
|
||||
}
|
||||
MediaLocationKind::Offline => String::from("offline"),
|
||||
MediaLocationKind::Vault => {
|
||||
format!("V({})", record.location_hint.unwrap_or(String::from("-")))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn render_status(_value: &Value, record: &Value) -> Result<String, Error> {
|
||||
let record: MediaListEntry = serde_json::from_value(record.clone())?;
|
||||
Ok(match record.status {
|
||||
|
@ -115,7 +101,7 @@ async fn list_media(
|
|||
.column(ColumnConfig::new("media-set-name"))
|
||||
.column(ColumnConfig::new("seq-nr"))
|
||||
.column(ColumnConfig::new("status").renderer(render_status))
|
||||
.column(ColumnConfig::new("location").renderer(render_location))
|
||||
.column(ColumnConfig::new("location"))
|
||||
.column(ColumnConfig::new("uuid"))
|
||||
.column(ColumnConfig::new("media-set-uuid"))
|
||||
;
|
||||
|
|
|
@ -16,6 +16,7 @@ use proxmox::tools::Uuid;
|
|||
use crate::{
|
||||
api2::types::{
|
||||
MediaStatus,
|
||||
MediaLocation,
|
||||
MediaSetPolicy,
|
||||
RetentionPolicy,
|
||||
MediaPoolConfig,
|
||||
|
@ -24,7 +25,6 @@ use crate::{
|
|||
tape::{
|
||||
MediaId,
|
||||
MediaSet,
|
||||
MediaLocation,
|
||||
Inventory,
|
||||
MediaStateDatabase,
|
||||
file_formats::{
|
||||
|
|
|
@ -21,21 +21,10 @@ use crate::{
|
|||
},
|
||||
api2::types::{
|
||||
MediaStatus,
|
||||
MediaLocation,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
/// Media location
|
||||
pub enum MediaLocation {
|
||||
/// Ready for use (inside tape library)
|
||||
Online(String),
|
||||
/// Local available, but need to be mounted (insert into tape
|
||||
/// drive)
|
||||
Offline,
|
||||
/// Media is inside a Vault
|
||||
Vault(String),
|
||||
}
|
||||
|
||||
#[derive(Serialize,Deserialize)]
|
||||
struct MediaStateEntry {
|
||||
u: Uuid,
|
||||
|
|
Loading…
Reference in New Issue