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