1 use anyhow
::{format_err, Error}
;
3 use proxmox
::api
::router
::SubdirMap
;
4 use proxmox
::{list_subdirs_api_method, sortable}
;
5 use proxmox
::api
::{api, ApiMethod, Permission, Router, RpcEnvironment}
;
7 use crate::api2
::types
::*;
8 use crate::server
::do_verification_job
;
9 use crate::server
::jobstate
::{Job, JobState}
;
10 use crate::config
::acl
::{
12 PRIV_DATASTORE_VERIFY
,
14 use crate::config
::cached_user_info
::CachedUserInfo
;
15 use crate::config
::verify
;
16 use crate::config
::verify
::{VerificationJobConfig, VerificationJobStatus}
;
17 use serde_json
::Value
;
18 use crate::tools
::systemd
::time
::{parse_calendar_event, compute_next_event}
;
19 use crate::server
::UPID
;
25 schema
: DATASTORE_SCHEMA
,
31 description
: "List configured jobs and their status (filtered by access)",
33 items
: { type: verify::VerificationJobStatus }
,
36 permission
: &Permission
::Anybody
,
37 description
: "Requires Datastore.Audit or Datastore.Verify on datastore.",
40 /// List all verification jobs
41 pub fn list_verification_jobs(
42 store
: Option
<String
>,
44 mut rpcenv
: &mut dyn RpcEnvironment
,
45 ) -> Result
<Vec
<VerificationJobStatus
>, Error
> {
46 let auth_id
: Authid
= rpcenv
.get_auth_id().unwrap().parse()?
;
47 let user_info
= CachedUserInfo
::new()?
;
49 let required_privs
= PRIV_DATASTORE_AUDIT
| PRIV_DATASTORE_VERIFY
;
51 let (config
, digest
) = verify
::config()?
;
53 let mut list
: Vec
<VerificationJobStatus
> = config
54 .convert_to_typed_array("verification")?
56 .filter(|job
: &VerificationJobStatus
| {
57 let privs
= user_info
.lookup_privs(&auth_id
, &["datastore", &job
.store
]);
58 if privs
& required_privs
== 0 {
62 if let Some(store
) = &store
{
69 for job
in &mut list
{
70 let last_state
= JobState
::load("verificationjob", &job
.id
)
71 .map_err(|err
| format_err
!("could not open statefile for {}: {}", &job
.id
, err
))?
;
73 let (upid
, endtime
, state
, starttime
) = match last_state
{
74 JobState
::Created { time }
=> (None
, None
, None
, time
),
75 JobState
::Started { upid }
=> {
76 let parsed_upid
: UPID
= upid
.parse()?
;
77 (Some(upid
), None
, None
, parsed_upid
.starttime
)
79 JobState
::Finished { upid, state }
=> {
80 let parsed_upid
: UPID
= upid
.parse()?
;
81 (Some(upid
), Some(state
.endtime()), Some(state
.to_string()), parsed_upid
.starttime
)
85 job
.last_run_upid
= upid
;
86 job
.last_run_state
= state
;
87 job
.last_run_endtime
= endtime
;
89 let last
= job
.last_run_endtime
.unwrap_or(starttime
);
91 job
.next_run
= (|| -> Option
<i64> {
92 let schedule
= job
.schedule
.as_ref()?
;
93 let event
= parse_calendar_event(&schedule
).ok()?
;
95 compute_next_event(&event
, last
, false).unwrap_or(None
)
99 rpcenv
["digest"] = proxmox
::tools
::digest_to_hex(&digest
).into();
108 schema
: JOB_ID_SCHEMA
,
113 permission
: &Permission
::Anybody
,
114 description
: "Requires Datastore.Verify on job's datastore.",
117 /// Runs a verification job manually.
118 fn run_verification_job(
121 rpcenv
: &mut dyn RpcEnvironment
,
122 ) -> Result
<String
, Error
> {
123 let auth_id
: Authid
= rpcenv
.get_auth_id().unwrap().parse()?
;
124 let user_info
= CachedUserInfo
::new()?
;
126 let (config
, _digest
) = verify
::config()?
;
127 let verification_job
: VerificationJobConfig
= config
.lookup("verification", &id
)?
;
129 user_info
.check_privs(&auth_id
, &["datastore", &verification_job
.store
], PRIV_DATASTORE_VERIFY
, true)?
;
131 let job
= Job
::new("verificationjob", &id
)?
;
133 let upid_str
= do_verification_job(job
, verification_job
, &auth_id
, None
)?
;
139 const VERIFICATION_INFO_SUBDIRS
: SubdirMap
= &[("run", &Router
::new().post(&API_METHOD_RUN_VERIFICATION_JOB
))];
141 const VERIFICATION_INFO_ROUTER
: Router
= Router
::new()
142 .get(&list_subdirs_api_method
!(VERIFICATION_INFO_SUBDIRS
))
143 .subdirs(VERIFICATION_INFO_SUBDIRS
);
145 pub const ROUTER
: Router
= Router
::new()
146 .get(&API_METHOD_LIST_VERIFICATION_JOBS
)
147 .match_all("id", &VERIFICATION_INFO_ROUTER
);