api2/tape: add api call to list media sets

we want a 'media-set' selector in the gui, this makes it
very easy to do and is not as costly as reusing the media list,
since we do not need to iterate over all media (e.g. unassigned)

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
Dominik Csapak 2021-05-26 15:48:04 +02:00 committed by Thomas Lamprecht
parent 927ebc702c
commit 03380db560
2 changed files with 95 additions and 0 deletions

View File

@ -1,4 +1,5 @@
use std::path::Path; use std::path::Path;
use std::collections::HashSet;
use anyhow::{bail, format_err, Error}; use anyhow::{bail, format_err, Error};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
@ -28,6 +29,7 @@ use crate::{
CHANGER_NAME_SCHEMA, CHANGER_NAME_SCHEMA,
MediaPoolConfig, MediaPoolConfig,
MediaListEntry, MediaListEntry,
MediaSetListEntry,
MediaStatus, MediaStatus,
MediaContentEntry, MediaContentEntry,
VAULT_NAME_SCHEMA, VAULT_NAME_SCHEMA,
@ -44,6 +46,74 @@ use crate::{
}, },
}; };
#[api(
returns: {
description: "List of media sets.",
type: Array,
items: {
type: MediaSetListEntry,
},
},
access: {
description: "List of media sets filtered by Tape.Audit privileges on pool",
permission: &Permission::Anybody,
},
)]
/// List Media sets
pub async fn list_media_sets(
rpcenv: &mut dyn RpcEnvironment,
) -> Result<Vec<MediaSetListEntry>, Error> {
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let user_info = CachedUserInfo::new()?;
let (config, _digest) = config::media_pool::config()?;
let status_path = Path::new(TAPE_STATUS_DIR);
let mut media_sets: HashSet<Uuid> = HashSet::new();
let mut list = Vec::new();
for (_section_type, data) in config.sections.values() {
let pool_name = match data["name"].as_str() {
None => continue,
Some(name) => name,
};
let privs = user_info.lookup_privs(&auth_id, &["tape", "pool", pool_name]);
if (privs & PRIV_TAPE_AUDIT) == 0 {
continue;
}
let config: MediaPoolConfig = config.lookup("pool", pool_name)?;
let changer_name = None; // assume standalone drive
let pool = MediaPool::with_config(status_path, &config, changer_name, true)?;
for media in pool.list_media() {
if let Some(label) = media.media_set_label() {
if media_sets.contains(&label.uuid) {
continue;
}
let media_set_uuid = label.uuid.clone();
let media_set_ctime = label.ctime;
let media_set_name = pool
.generate_media_set_name(&media_set_uuid, config.template.clone())
.unwrap_or_else(|_| media_set_uuid.to_string());
media_sets.insert(media_set_uuid.clone());
list.push(MediaSetListEntry {
media_set_name,
media_set_uuid,
media_set_ctime,
pool: pool_name.to_string(),
});
}
}
}
Ok(list)
}
#[api( #[api(
input: { input: {
properties: { properties: {
@ -546,6 +616,11 @@ const SUBDIRS: SubdirMap = &[
.get(&API_METHOD_DESTROY_MEDIA) .get(&API_METHOD_DESTROY_MEDIA)
), ),
( "list", &MEDIA_LIST_ROUTER ), ( "list", &MEDIA_LIST_ROUTER ),
(
"media-sets",
&Router::new()
.get(&API_METHOD_LIST_MEDIA_SETS)
),
( (
"move", "move",
&Router::new() &Router::new()

View File

@ -12,6 +12,26 @@ use crate::api2::types::{
MediaLocation, MediaLocation,
}; };
#[api(
properties: {
"media-set-uuid": {
schema: MEDIA_SET_UUID_SCHEMA,
},
},
)]
#[derive(Serialize,Deserialize)]
#[serde(rename_all = "kebab-case")]
/// Media Set list entry
pub struct MediaSetListEntry {
/// Media set name
pub media_set_name: String,
pub media_set_uuid: Uuid,
/// MediaSet creation time stamp
pub media_set_ctime: i64,
/// Media Pool
pub pool: String,
}
#[api( #[api(
properties: { properties: {
location: { location: {