]> git.proxmox.com Git - proxmox-backup.git/blob - src/api2/config/media_pool.rs
56b296af3dad3a51e19609e38d65f8d78c0c9b28
[proxmox-backup.git] / src / api2 / config / media_pool.rs
1 use anyhow::{bail, Error};
2 use ::serde::{Deserialize, Serialize};
3
4 use proxmox::{
5 api::{
6 api,
7 Router,
8 RpcEnvironment,
9 Permission,
10 },
11 };
12
13 use crate::{
14 api2::types::{
15 Authid,
16 MEDIA_POOL_NAME_SCHEMA,
17 MediaPoolConfig,
18 MediaPoolConfigUpdater,
19 },
20 config::{
21 self,
22 cached_user_info::CachedUserInfo,
23 acl::{
24 PRIV_TAPE_AUDIT,
25 PRIV_TAPE_MODIFY,
26 },
27 },
28 };
29
30 #[api(
31 protected: true,
32 input: {
33 properties: {
34 config: {
35 type: MediaPoolConfig,
36 flatten: true,
37 },
38 },
39 },
40 access: {
41 permission: &Permission::Privilege(&["tape", "pool"], PRIV_TAPE_MODIFY, false),
42 },
43 )]
44 /// Create a new media pool
45 pub fn create_pool(
46 config: MediaPoolConfig,
47 ) -> Result<(), Error> {
48
49 let _lock = config::media_pool::lock()?;
50
51 let (mut section_config, _digest) = config::media_pool::config()?;
52
53 if section_config.sections.get(&config.name).is_some() {
54 bail!("Media pool '{}' already exists", config.name);
55 }
56
57 section_config.set_data(&config.name, "pool", &config)?;
58
59 config::media_pool::save_config(&section_config)?;
60
61 Ok(())
62 }
63
64 #[api(
65 returns: {
66 description: "The list of configured media pools (with config digest).",
67 type: Array,
68 items: {
69 type: MediaPoolConfig,
70 },
71 },
72 access: {
73 description: "List configured media pools filtered by Tape.Audit privileges",
74 permission: &Permission::Anybody,
75 },
76 )]
77 /// List media pools
78 pub fn list_pools(
79 mut rpcenv: &mut dyn RpcEnvironment,
80 ) -> Result<Vec<MediaPoolConfig>, Error> {
81 let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
82 let user_info = CachedUserInfo::new()?;
83
84 let (config, digest) = config::media_pool::config()?;
85
86 let list = config.convert_to_typed_array::<MediaPoolConfig>("pool")?;
87
88 let list = list
89 .into_iter()
90 .filter(|pool| {
91 let privs = user_info.lookup_privs(&auth_id, &["tape", "pool", &pool.name]);
92 privs & PRIV_TAPE_AUDIT != 0
93 })
94 .collect();
95
96 rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
97
98 Ok(list)
99 }
100
101 #[api(
102 input: {
103 properties: {
104 name: {
105 schema: MEDIA_POOL_NAME_SCHEMA,
106 },
107 },
108 },
109 returns: {
110 type: MediaPoolConfig,
111 },
112 access: {
113 permission: &Permission::Privilege(&["tape", "pool", "{name}"], PRIV_TAPE_AUDIT, false),
114 },
115 )]
116 /// Get media pool configuration
117 pub fn get_config(name: String) -> Result<MediaPoolConfig, Error> {
118
119 let (config, _digest) = config::media_pool::config()?;
120
121 let data: MediaPoolConfig = config.lookup("pool", &name)?;
122
123 Ok(data)
124 }
125
126 #[api()]
127 #[derive(Serialize, Deserialize)]
128 #[allow(non_camel_case_types)]
129 /// Deletable property name
130 pub enum DeletableProperty {
131 /// Delete media set allocation policy.
132 allocation,
133 /// Delete pool retention policy
134 retention,
135 /// Delete media set naming template
136 template,
137 /// Delete encryption fingerprint
138 encrypt,
139 /// Delete comment
140 comment,
141 }
142
143 #[api(
144 protected: true,
145 input: {
146 properties: {
147 name: {
148 schema: MEDIA_POOL_NAME_SCHEMA,
149 },
150 update: {
151 type: MediaPoolConfigUpdater,
152 flatten: true,
153 },
154 delete: {
155 description: "List of properties to delete.",
156 type: Array,
157 optional: true,
158 items: {
159 type: DeletableProperty,
160 }
161 },
162 },
163 },
164 access: {
165 permission: &Permission::Privilege(&["tape", "pool", "{name}"], PRIV_TAPE_MODIFY, false),
166 },
167 )]
168 /// Update media pool settings
169 pub fn update_pool(
170 name: String,
171 update: MediaPoolConfigUpdater,
172 delete: Option<Vec<DeletableProperty>>,
173 ) -> Result<(), Error> {
174
175 let _lock = config::media_pool::lock()?;
176
177 let (mut config, _digest) = config::media_pool::config()?;
178
179 let mut data: MediaPoolConfig = config.lookup("pool", &name)?;
180
181 if let Some(delete) = delete {
182 for delete_prop in delete {
183 match delete_prop {
184 DeletableProperty::allocation => { data.allocation = None; },
185 DeletableProperty::retention => { data.retention = None; },
186 DeletableProperty::template => { data.template = None; },
187 DeletableProperty::encrypt => { data.encrypt = None; },
188 DeletableProperty::comment => { data.comment = None; },
189 }
190 }
191 }
192
193 if update.allocation.is_some() { data.allocation = update.allocation; }
194 if update.retention.is_some() { data.retention = update.retention; }
195 if update.template.is_some() { data.template = update.template; }
196 if update.encrypt.is_some() { data.encrypt = update.encrypt; }
197
198 if let Some(comment) = update.comment {
199 let comment = comment.trim();
200 if comment.is_empty() {
201 data.comment = None;
202 } else {
203 data.comment = Some(comment.to_string());
204 }
205 }
206
207 config.set_data(&name, "pool", &data)?;
208
209 config::media_pool::save_config(&config)?;
210
211 Ok(())
212 }
213
214 #[api(
215 protected: true,
216 input: {
217 properties: {
218 name: {
219 schema: MEDIA_POOL_NAME_SCHEMA,
220 },
221 },
222 },
223 access: {
224 permission: &Permission::Privilege(&["tape", "pool", "{name}"], PRIV_TAPE_MODIFY, false),
225 },
226 )]
227 /// Delete a media pool configuration
228 pub fn delete_pool(name: String) -> Result<(), Error> {
229
230 let _lock = config::media_pool::lock()?;
231
232 let (mut config, _digest) = config::media_pool::config()?;
233
234 match config.sections.get(&name) {
235 Some(_) => { config.sections.remove(&name); },
236 None => bail!("delete pool '{}' failed - no such pool", name),
237 }
238
239 config::media_pool::save_config(&config)?;
240
241 Ok(())
242 }
243
244 const ITEM_ROUTER: Router = Router::new()
245 .get(&API_METHOD_GET_CONFIG)
246 .put(&API_METHOD_UPDATE_POOL)
247 .delete(&API_METHOD_DELETE_POOL);
248
249
250 pub const ROUTER: Router = Router::new()
251 .get(&API_METHOD_LIST_POOLS)
252 .post(&API_METHOD_CREATE_POOL)
253 .match_all("name", &ITEM_ROUTER);