use anyhow::{format_err, Error}; use crate::{ server::WorkerTask, api2::types::*, server::jobstate::Job, config::verify::VerificationJobConfig, backup::{ DataStore, BackupManifest, verify_all_backups, }, task_log, }; /// Runs a verification job. pub fn do_verification_job( mut job: Job, verification_job: VerificationJobConfig, auth_id: &Authid, schedule: Option, ) -> Result { let datastore = DataStore::lookup_datastore(&verification_job.store)?; let outdated_after = verification_job.outdated_after; let ignore_verified_snapshots = verification_job.ignore_verified.unwrap_or(true); let filter = move |manifest: &BackupManifest| { if !ignore_verified_snapshots { return true; } let raw_verify_state = manifest.unprotected["verify_state"].clone(); match serde_json::from_value::(raw_verify_state) { Err(_) => true, // no last verification, always include Ok(last_verify) => { match outdated_after { None => false, // never re-verify if ignored and no max age Some(max_age) => { let now = proxmox::tools::time::epoch_i64(); let days_since_last_verify = (now - last_verify.upid.starttime) / 86400; days_since_last_verify > max_age } } } } }; let (email, notify) = crate::server::lookup_datastore_notify_settings(&verification_job.store); let job_id = format!("{}:{}", &verification_job.store, job.jobname()); let worker_type = job.jobtype().to_string(); let upid_str = WorkerTask::new_thread( &worker_type, Some(job_id.clone()), auth_id.clone(), false, move |worker| { job.start(&worker.upid().to_string())?; task_log!(worker,"Starting datastore verify job '{}'", job_id); if let Some(event_str) = schedule { task_log!(worker,"task triggered by schedule '{}'", event_str); } let verify_worker = crate::backup::VerifyWorker::new(worker.clone(), datastore); let result = verify_all_backups(&verify_worker, worker.upid(), None, Some(&filter)); let job_result = match result { Ok(ref failed_dirs) if failed_dirs.is_empty() => Ok(()), Ok(ref failed_dirs) => { worker.log("Failed to verify the following snapshots/groups:"); for dir in failed_dirs { worker.log(format!("\t{}", dir)); } Err(format_err!("verification failed - please check the log for details")) }, Err(_) => Err(format_err!("verification failed - job aborted")), }; let status = worker.create_state(&job_result); if let Err(err) = job.finish(status) { eprintln!( "could not finish job state for {}: {}", job.jobtype().to_string(), err ); } if let Some(email) = email { if let Err(err) = crate::server::send_verify_status(&email, notify, verification_job, &result) { eprintln!("send verify notification failed: {}", err); } } job_result }, )?; Ok(upid_str) }