]> git.proxmox.com Git - proxmox-backup.git/blob - src/api2/admin/verify.rs
6bdfdeded176efa33969a25a3792ef49c14958bd
[proxmox-backup.git] / src / api2 / admin / verify.rs
1 //! Datastore Verify Job Management
2
3 use anyhow::{format_err, Error};
4 use serde_json::Value;
5
6 use proxmox::api::router::SubdirMap;
7 use proxmox::{list_subdirs_api_method, sortable};
8 use proxmox::api::{api, ApiMethod, Permission, Router, RpcEnvironment, RpcEnvironmentType};
9
10 use pbs_api_types::{
11 VerificationJobConfig, VerificationJobStatus, JOB_ID_SCHEMA, Authid,
12 PRIV_DATASTORE_AUDIT, PRIV_DATASTORE_VERIFY, DATASTORE_SCHEMA,
13 };
14 use pbs_config::verify;
15 use pbs_config::CachedUserInfo;
16
17 use crate::{
18 server::{
19 do_verification_job,
20 jobstate::{
21 Job,
22 JobState,
23 compute_schedule_status,
24 },
25 },
26 };
27
28 #[api(
29 input: {
30 properties: {
31 store: {
32 schema: DATASTORE_SCHEMA,
33 optional: true,
34 },
35 },
36 },
37 returns: {
38 description: "List configured jobs and their status (filtered by access)",
39 type: Array,
40 items: { type: VerificationJobStatus },
41 },
42 access: {
43 permission: &Permission::Anybody,
44 description: "Requires Datastore.Audit or Datastore.Verify on datastore.",
45 },
46 )]
47 /// List all verification jobs
48 pub fn list_verification_jobs(
49 store: Option<String>,
50 _param: Value,
51 mut rpcenv: &mut dyn RpcEnvironment,
52 ) -> Result<Vec<VerificationJobStatus>, Error> {
53 let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
54 let user_info = CachedUserInfo::new()?;
55
56 let required_privs = PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_VERIFY;
57
58 let (config, digest) = verify::config()?;
59
60 let job_config_iter = config
61 .convert_to_typed_array("verification")?
62 .into_iter()
63 .filter(|job: &VerificationJobConfig| {
64 let privs = user_info.lookup_privs(&auth_id, &["datastore", &job.store]);
65 if privs & required_privs == 0 {
66 return false;
67 }
68
69 if let Some(store) = &store {
70 &job.store == store
71 } else {
72 true
73 }
74 });
75
76 let mut list = Vec::new();
77
78 for job in job_config_iter {
79 let last_state = JobState::load("verificationjob", &job.id)
80 .map_err(|err| format_err!("could not open statefile for {}: {}", &job.id, err))?;
81
82 let status = compute_schedule_status(&last_state, job.schedule.as_deref())?;
83
84 list.push(VerificationJobStatus { config: job, status });
85 }
86
87 rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
88
89 Ok(list)
90 }
91
92 #[api(
93 input: {
94 properties: {
95 id: {
96 schema: JOB_ID_SCHEMA,
97 }
98 }
99 },
100 access: {
101 permission: &Permission::Anybody,
102 description: "Requires Datastore.Verify on job's datastore.",
103 },
104 )]
105 /// Runs a verification job manually.
106 pub fn run_verification_job(
107 id: String,
108 _info: &ApiMethod,
109 rpcenv: &mut dyn RpcEnvironment,
110 ) -> Result<String, Error> {
111 let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
112 let user_info = CachedUserInfo::new()?;
113
114 let (config, _digest) = verify::config()?;
115 let verification_job: VerificationJobConfig = config.lookup("verification", &id)?;
116
117 user_info.check_privs(&auth_id, &["datastore", &verification_job.store], PRIV_DATASTORE_VERIFY, true)?;
118
119 let job = Job::new("verificationjob", &id)?;
120 let to_stdout = rpcenv.env_type() == RpcEnvironmentType::CLI;
121
122 let upid_str = do_verification_job(job, verification_job, &auth_id, None, to_stdout)?;
123
124 Ok(upid_str)
125 }
126
127 #[sortable]
128 const VERIFICATION_INFO_SUBDIRS: SubdirMap = &[("run", &Router::new().post(&API_METHOD_RUN_VERIFICATION_JOB))];
129
130 const VERIFICATION_INFO_ROUTER: Router = Router::new()
131 .get(&list_subdirs_api_method!(VERIFICATION_INFO_SUBDIRS))
132 .subdirs(VERIFICATION_INFO_SUBDIRS);
133
134 pub const ROUTER: Router = Router::new()
135 .get(&API_METHOD_LIST_VERIFICATION_JOBS)
136 .match_all("id", &VERIFICATION_INFO_ROUTER);