use anyhow::{bail, Error};
use ::serde::{Deserialize, Serialize};
-use proxmox::{
- api::{
- api,
- Router,
- RpcEnvironment,
- },
-};
+use proxmox_router::{Router, RpcEnvironment, Permission};
+use proxmox_schema::api;
-use crate::{
- api2::types::{
- DRIVE_NAME_SCHEMA,
- MEDIA_POOL_NAME_SCHEMA,
- MEDIA_SET_NAMING_TEMPLATE_SCHEMA,
- MEDIA_SET_ALLOCATION_POLICY_SCHEMA,
- MEDIA_RETENTION_POLICY_SCHEMA,
- TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
- MediaPoolConfig,
- },
- config::{
- self,
- drive::{
- check_drive_exists,
- },
- },
+use pbs_api_types::{
+ Authid, MediaPoolConfig, MediaPoolConfigUpdater, MEDIA_POOL_NAME_SCHEMA,
+ PRIV_TAPE_AUDIT, PRIV_TAPE_MODIFY,
};
+use pbs_config::CachedUserInfo;
+
#[api(
protected: true,
input: {
properties: {
- name: {
- schema: MEDIA_POOL_NAME_SCHEMA,
- },
- drive: {
- schema: DRIVE_NAME_SCHEMA,
- },
- allocation: {
- schema: MEDIA_SET_ALLOCATION_POLICY_SCHEMA,
- optional: true,
- },
- retention: {
- schema: MEDIA_RETENTION_POLICY_SCHEMA,
- optional: true,
- },
- template: {
- schema: MEDIA_SET_NAMING_TEMPLATE_SCHEMA,
- optional: true,
- },
- encrypt: {
- schema: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
- optional: true,
+ config: {
+ type: MediaPoolConfig,
+ flatten: true,
},
},
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "pool"], PRIV_TAPE_MODIFY, false),
+ },
)]
/// Create a new media pool
pub fn create_pool(
- name: String,
- drive: String,
- allocation: Option<String>,
- retention: Option<String>,
- template: Option<String>,
- encrypt: Option<String>,
+ config: MediaPoolConfig,
) -> Result<(), Error> {
- let _lock = config::media_pool::lock()?;
+ let _lock = pbs_config::media_pool::lock()?;
- let (mut config, _digest) = config::media_pool::config()?;
+ let (mut section_config, _digest) = pbs_config::media_pool::config()?;
- if config.sections.get(&name).is_some() {
- bail!("Media pool '{}' already exists", name);
+ if section_config.sections.get(&config.name).is_some() {
+ bail!("Media pool '{}' already exists", config.name);
}
- let (drive_config, _) = config::drive::config()?;
- check_drive_exists(&drive_config, &drive)?;
+ section_config.set_data(&config.name, "pool", &config)?;
- let item = MediaPoolConfig {
- name: name.clone(),
- drive,
- allocation,
- retention,
- template,
- encrypt,
- };
-
- config.set_data(&name, "pool", &item)?;
-
- config::media_pool::save_config(&config)?;
+ pbs_config::media_pool::save_config(§ion_config)?;
Ok(())
}
type: MediaPoolConfig,
},
},
+ access: {
+ description: "List configured media pools filtered by Tape.Audit privileges",
+ permission: &Permission::Anybody,
+ },
)]
/// List media pools
pub fn list_pools(
mut rpcenv: &mut dyn RpcEnvironment,
) -> Result<Vec<MediaPoolConfig>, Error> {
+ let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
+ let user_info = CachedUserInfo::new()?;
- let (config, digest) = config::media_pool::config()?;
+ let (config, digest) = pbs_config::media_pool::config()?;
- let list = config.convert_to_typed_array("pool")?;
+ let list = config.convert_to_typed_array::<MediaPoolConfig>("pool")?;
+
+ let list = list
+ .into_iter()
+ .filter(|pool| {
+ let privs = user_info.lookup_privs(&auth_id, &["tape", "pool", &pool.name]);
+ privs & PRIV_TAPE_AUDIT != 0
+ })
+ .collect();
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
returns: {
type: MediaPoolConfig,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "pool", "{name}"], PRIV_TAPE_AUDIT, false),
+ },
)]
/// Get media pool configuration
pub fn get_config(name: String) -> Result<MediaPoolConfig, Error> {
- let (config, _digest) = config::media_pool::config()?;
+ let (config, _digest) = pbs_config::media_pool::config()?;
let data: MediaPoolConfig = config.lookup("pool", &name)?;
template,
/// Delete encryption fingerprint
encrypt,
+ /// Delete comment
+ comment,
}
#[api(
name: {
schema: MEDIA_POOL_NAME_SCHEMA,
},
- drive: {
- schema: DRIVE_NAME_SCHEMA,
- optional: true,
- },
- allocation: {
- schema: MEDIA_SET_ALLOCATION_POLICY_SCHEMA,
- optional: true,
- },
- retention: {
- schema: MEDIA_RETENTION_POLICY_SCHEMA,
- optional: true,
- },
- template: {
- schema: MEDIA_SET_NAMING_TEMPLATE_SCHEMA,
- optional: true,
- },
- encrypt: {
- schema: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
- optional: true,
+ update: {
+ type: MediaPoolConfigUpdater,
+ flatten: true,
},
delete: {
description: "List of properties to delete.",
},
},
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "pool", "{name}"], PRIV_TAPE_MODIFY, false),
+ },
)]
/// Update media pool settings
pub fn update_pool(
name: String,
- drive: Option<String>,
- allocation: Option<String>,
- retention: Option<String>,
- template: Option<String>,
- encrypt: Option<String>,
+ update: MediaPoolConfigUpdater,
delete: Option<Vec<DeletableProperty>>,
) -> Result<(), Error> {
- let _lock = config::media_pool::lock()?;
+ let _lock = pbs_config::media_pool::lock()?;
- let (mut config, _digest) = config::media_pool::config()?;
+ let (mut config, _digest) = pbs_config::media_pool::config()?;
let mut data: MediaPoolConfig = config.lookup("pool", &name)?;
DeletableProperty::retention => { data.retention = None; },
DeletableProperty::template => { data.template = None; },
DeletableProperty::encrypt => { data.encrypt = None; },
+ DeletableProperty::comment => { data.comment = None; },
}
}
}
- if let Some(drive) = drive { data.drive = drive; }
- if allocation.is_some() { data.allocation = allocation; }
- if retention.is_some() { data.retention = retention; }
- if template.is_some() { data.template = template; }
- if encrypt.is_some() { data.encrypt = encrypt; }
+ if update.allocation.is_some() { data.allocation = update.allocation; }
+ if update.retention.is_some() { data.retention = update.retention; }
+ if update.template.is_some() { data.template = update.template; }
+ if update.encrypt.is_some() { data.encrypt = update.encrypt; }
+
+ if let Some(comment) = update.comment {
+ let comment = comment.trim();
+ if comment.is_empty() {
+ data.comment = None;
+ } else {
+ data.comment = Some(comment.to_string());
+ }
+ }
config.set_data(&name, "pool", &data)?;
- config::media_pool::save_config(&config)?;
+ pbs_config::media_pool::save_config(&config)?;
Ok(())
}
},
},
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "pool", "{name}"], PRIV_TAPE_MODIFY, false),
+ },
)]
/// Delete a media pool configuration
pub fn delete_pool(name: String) -> Result<(), Error> {
- let _lock = config::media_pool::lock()?;
+ let _lock = pbs_config::media_pool::lock()?;
- let (mut config, _digest) = config::media_pool::config()?;
+ let (mut config, _digest) = pbs_config::media_pool::config()?;
match config.sections.get(&name) {
Some(_) => { config.sections.remove(&name); },
None => bail!("delete pool '{}' failed - no such pool", name),
}
- config::media_pool::save_config(&config)?;
+ pbs_config::media_pool::save_config(&config)?;
Ok(())
}