]> git.proxmox.com Git - proxmox-backup.git/blame - src/server/verify_job.rs
verify: introduce & use new Datastore.Verify privilege
[proxmox-backup.git] / src / server / verify_job.rs
CommitLineData
a4915dfc 1use anyhow::{format_err, Error};
acc3d9df
DM
2
3use crate::{
4 server::WorkerTask,
5 api2::types::*,
6 server::jobstate::Job,
7 config::verify::VerificationJobConfig,
8 backup::{
9 DataStore,
d771a608 10 BackupManifest,
a4915dfc 11 verify_all_backups,
acc3d9df
DM
12 },
13 task_log,
14};
15
16/// Runs a verification job.
17pub fn do_verification_job(
18 mut job: Job,
19 verification_job: VerificationJobConfig,
e6dc35ac 20 auth_id: &Authid,
acc3d9df
DM
21 schedule: Option<String>,
22) -> Result<String, Error> {
a4915dfc 23
acc3d9df
DM
24 let datastore = DataStore::lookup_datastore(&verification_job.store)?;
25
a4915dfc 26 let outdated_after = verification_job.outdated_after.clone();
b4b14dc1 27 let ignore_verified_snapshots = verification_job.ignore_verified.unwrap_or(true);
a4915dfc 28
d771a608 29 let filter = move |manifest: &BackupManifest| {
b4b14dc1 30 if !ignore_verified_snapshots {
a4915dfc
DM
31 return true;
32 }
a4915dfc
DM
33
34 let raw_verify_state = manifest.unprotected["verify_state"].clone();
b4b14dc1
TL
35 match serde_json::from_value::<SnapshotVerifyState>(raw_verify_state) {
36 Err(_) => return true, // no last verification, always include
37 Ok(last_verify) => {
38 match outdated_after {
39 None => false, // never re-verify if ignored and no max age
40 Some(max_age) => {
41 let now = proxmox::tools::time::epoch_i64();
42 let days_since_last_verify = (now - last_verify.upid.starttime) / 86400;
a4915dfc 43
b4b14dc1
TL
44 days_since_last_verify > max_age
45 }
46 }
47 }
48 }
a4915dfc 49 };
acc3d9df 50
e6dc35ac 51 let email = crate::server::lookup_user_email(auth_id.user());
b9e7bcc2 52
acc3d9df
DM
53 let job_id = job.jobname().to_string();
54 let worker_type = job.jobtype().to_string();
55 let upid_str = WorkerTask::new_thread(
56 &worker_type,
57 Some(job.jobname().to_string()),
e6dc35ac 58 auth_id.clone(),
acc3d9df
DM
59 false,
60 move |worker| {
61 job.start(&worker.upid().to_string())?;
62
63 task_log!(worker,"Starting datastore verify job '{}'", job_id);
acc3d9df
DM
64 if let Some(event_str) = schedule {
65 task_log!(worker,"task triggered by schedule '{}'", event_str);
66 }
67
09f6a240 68 let result = verify_all_backups(datastore, worker.clone(), worker.upid(), None, Some(&filter));
a4915dfc
DM
69 let job_result = match result {
70 Ok(ref errors) if errors.is_empty() => Ok(()),
71 Ok(_) => Err(format_err!("verification failed - please check the log for details")),
72 Err(_) => Err(format_err!("verification failed - job aborted")),
73 };
acc3d9df 74
a4915dfc 75 let status = worker.create_state(&job_result);
acc3d9df
DM
76
77 match job.finish(status) {
78 Err(err) => eprintln!(
79 "could not finish job state for {}: {}",
80 job.jobtype().to_string(),
81 err
82 ),
83 Ok(_) => (),
84 }
85
b9e7bcc2
DM
86 if let Some(email) = email {
87 if let Err(err) = crate::server::send_verify_status(&email, verification_job, &result) {
88 eprintln!("send verify notification failed: {}", err);
89 }
90 }
91
a4915dfc 92 job_result
acc3d9df
DM
93 },
94 )?;
95 Ok(upid_str)
96}