1 use anyhow
::{bail, Error}
;
3 use ::serde
::{Deserialize, Serialize}
;
5 use proxmox
::api
::{api, Permission, Router, RpcEnvironment}
;
6 use proxmox
::tools
::fs
::open_file_locked
;
8 use crate::api2
::types
::*;
10 use crate::config
::acl
::{
12 PRIV_DATASTORE_BACKUP
,
13 PRIV_DATASTORE_VERIFY
,
16 use crate::config
::verify
::{self, VerificationJobConfig}
;
23 description
: "List configured jobs.",
25 items
: { type: verify::VerificationJobConfig }
,
28 permission
: &Permission
::Privilege(
29 &["datastore", "{store}"],
30 PRIV_DATASTORE_AUDIT
| PRIV_DATASTORE_BACKUP
| PRIV_DATASTORE_VERIFY
,
34 /// List all verification jobs
35 pub fn list_verification_jobs(
37 mut rpcenv
: &mut dyn RpcEnvironment
,
38 ) -> Result
<Vec
<VerificationJobConfig
>, Error
> {
40 let (config
, digest
) = verify
::config()?
;
42 let list
= config
.convert_to_typed_array("verification")?
;
44 rpcenv
["digest"] = proxmox
::tools
::digest_to_hex(&digest
).into();
55 schema
: JOB_ID_SCHEMA
,
58 schema
: DATASTORE_SCHEMA
,
62 schema
: IGNORE_VERIFIED_BACKUPS_SCHEMA
,
66 schema
: VERIFICATION_OUTDATED_AFTER_SCHEMA
,
70 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
74 schema
: VERIFICATION_SCHEDULE_SCHEMA
,
79 permission
: &Permission
::Privilege(
80 &["datastore", "{store}"],
81 PRIV_DATASTORE_VERIFY
,
85 /// Create a new verification job.
86 pub fn create_verification_job(param
: Value
) -> Result
<(), Error
> {
88 let _lock
= open_file_locked(verify
::VERIFICATION_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0), true)?
;
90 let verification_job
: verify
::VerificationJobConfig
= serde_json
::from_value(param
.clone())?
;
92 let (mut config
, _digest
) = verify
::config()?
;
94 if let Some(_
) = config
.sections
.get(&verification_job
.id
) {
95 bail
!("job '{}' already exists.", verification_job
.id
);
98 config
.set_data(&verification_job
.id
, "verification", &verification_job
)?
;
100 verify
::save_config(&config
)?
;
102 crate::server
::jobstate
::create_state_file("verificationjob", &verification_job
.id
)?
;
111 schema
: JOB_ID_SCHEMA
,
116 description
: "The verification job configuration.",
117 type: verify
::VerificationJobConfig
,
120 permission
: &Permission
::Privilege(
121 &["datastore", "{store}"],
122 PRIV_DATASTORE_AUDIT
| PRIV_DATASTORE_BACKUP
| PRIV_DATASTORE_VERIFY
,
126 /// Read a verification job configuration.
127 pub fn read_verification_job(
129 mut rpcenv
: &mut dyn RpcEnvironment
,
130 ) -> Result
<VerificationJobConfig
, Error
> {
131 let (config
, digest
) = verify
::config()?
;
133 let verification_job
= config
.lookup("verification", &id
)?
;
134 rpcenv
["digest"] = proxmox
::tools
::digest_to_hex(&digest
).into();
140 #[derive(Serialize, Deserialize)]
141 #[serde(rename_all="kebab-case")]
142 /// Deletable property name
143 pub enum DeletableProperty
{
144 /// Delete the ignore verified property.
146 /// Delete the comment property.
148 /// Delete the job schedule.
150 /// Delete outdated after property.
159 schema
: JOB_ID_SCHEMA
,
163 schema
: DATASTORE_SCHEMA
,
167 schema
: IGNORE_VERIFIED_BACKUPS_SCHEMA
,
171 schema
: VERIFICATION_OUTDATED_AFTER_SCHEMA
,
175 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
179 schema
: VERIFICATION_SCHEDULE_SCHEMA
,
182 description
: "List of properties to delete.",
186 type: DeletableProperty
,
191 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
196 permission
: &Permission
::Privilege(
197 &["datastore", "{store}"],
198 PRIV_DATASTORE_VERIFY
,
202 /// Update verification job config.
203 pub fn update_verification_job(
205 store
: Option
<String
>,
206 ignore_verified
: Option
<bool
>,
207 outdated_after
: Option
<i64>,
208 comment
: Option
<String
>,
209 schedule
: Option
<String
>,
210 delete
: Option
<Vec
<DeletableProperty
>>,
211 digest
: Option
<String
>,
212 ) -> Result
<(), Error
> {
214 let _lock
= open_file_locked(verify
::VERIFICATION_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0), true)?
;
216 // pass/compare digest
217 let (mut config
, expected_digest
) = verify
::config()?
;
219 if let Some(ref digest
) = digest
{
220 let digest
= proxmox
::tools
::hex_to_digest(digest
)?
;
221 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
224 let mut data
: verify
::VerificationJobConfig
= config
.lookup("verification", &id
)?
;
226 if let Some(delete
) = delete
{
227 for delete_prop
in delete
{
229 DeletableProperty
::IgnoreVerified
=> { data.ignore_verified = None; }
,
230 DeletableProperty
::OutdatedAfter
=> { data.outdated_after = None; }
,
231 DeletableProperty
::Comment
=> { data.comment = None; }
,
232 DeletableProperty
::Schedule
=> { data.schedule = None; }
,
237 if let Some(comment
) = comment
{
238 let comment
= comment
.trim().to_string();
239 if comment
.is_empty() {
242 data
.comment
= Some(comment
);
246 if let Some(store
) = store { data.store = store; }
248 if ignore_verified
.is_some() { data.ignore_verified = ignore_verified; }
249 if outdated_after
.is_some() { data.outdated_after = outdated_after; }
250 if schedule
.is_some() { data.schedule = schedule; }
252 config
.set_data(&id
, "verification", &data
)?
;
254 verify
::save_config(&config
)?
;
264 schema
: JOB_ID_SCHEMA
,
268 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
273 permission
: &Permission
::Privilege(
274 &["datastore", "{store}"],
275 PRIV_DATASTORE_VERIFY
,
279 /// Remove a verification job configuration
280 pub fn delete_verification_job(id
: String
, digest
: Option
<String
>) -> Result
<(), Error
> {
282 let _lock
= open_file_locked(verify
::VERIFICATION_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0), true)?
;
284 let (mut config
, expected_digest
) = verify
::config()?
;
286 if let Some(ref digest
) = digest
{
287 let digest
= proxmox
::tools
::hex_to_digest(digest
)?
;
288 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
291 match config
.sections
.get(&id
) {
292 Some(_
) => { config.sections.remove(&id); }
,
293 None
=> bail
!("job '{}' does not exist.", id
),
296 verify
::save_config(&config
)?
;
298 crate::server
::jobstate
::remove_state_file("verificationjob", &id
)?
;
303 const ITEM_ROUTER
: Router
= Router
::new()
304 .get(&API_METHOD_READ_VERIFICATION_JOB
)
305 .put(&API_METHOD_UPDATE_VERIFICATION_JOB
)
306 .delete(&API_METHOD_DELETE_VERIFICATION_JOB
);
308 pub const ROUTER
: Router
= Router
::new()
309 .get(&API_METHOD_LIST_VERIFICATION_JOBS
)
310 .post(&API_METHOD_CREATE_VERIFICATION_JOB
)
311 .match_all("id", &ITEM_ROUTER
);