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