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