2020-10-28 11:58:15 +00:00
|
|
|
use anyhow::{format_err, Error};
|
2020-10-28 06:58:07 +00:00
|
|
|
|
|
|
|
use crate::{
|
|
|
|
server::WorkerTask,
|
|
|
|
api2::types::*,
|
|
|
|
server::jobstate::Job,
|
|
|
|
config::verify::VerificationJobConfig,
|
|
|
|
backup::{
|
|
|
|
DataStore,
|
2020-10-29 06:59:19 +00:00
|
|
|
BackupManifest,
|
2020-10-28 11:58:15 +00:00
|
|
|
verify_all_backups,
|
2020-10-28 06:58:07 +00:00
|
|
|
},
|
|
|
|
task_log,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Runs a verification job.
|
|
|
|
pub fn do_verification_job(
|
|
|
|
mut job: Job,
|
|
|
|
verification_job: VerificationJobConfig,
|
2020-10-23 11:33:21 +00:00
|
|
|
auth_id: &Authid,
|
2020-10-28 06:58:07 +00:00
|
|
|
schedule: Option<String>,
|
|
|
|
) -> Result<String, Error> {
|
2020-10-28 11:58:15 +00:00
|
|
|
|
2020-10-28 06:58:07 +00:00
|
|
|
let datastore = DataStore::lookup_datastore(&verification_job.store)?;
|
|
|
|
|
2020-10-28 11:58:15 +00:00
|
|
|
let outdated_after = verification_job.outdated_after.clone();
|
do_verification_job: fix "never-reverify" and refactor/comment
commit a4915dfc2bc7bef03354f97f5bbce9fe2df4e0d6 made a wrong fix, as
it did not observed that the last expressions was done under the
invariant that we had a last verification result, because if none
could be loaded we already returned true (include).
It thus broke the case for "never re-verify", which is important when
using multiple schedules, a more high frequent one for new,
unverified snapshots, and a low frequency to re-verify older snapshots,
e.g., monthly.
Fix this case again, rework the code to avoid this easy to oversee
invariant. Use a nested match to better express the implication of
each setting, and add some comments.
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2020-10-28 14:33:04 +00:00
|
|
|
let ignore_verified_snapshots = verification_job.ignore_verified.unwrap_or(true);
|
2020-10-28 11:58:15 +00:00
|
|
|
|
2020-10-29 06:59:19 +00:00
|
|
|
let filter = move |manifest: &BackupManifest| {
|
do_verification_job: fix "never-reverify" and refactor/comment
commit a4915dfc2bc7bef03354f97f5bbce9fe2df4e0d6 made a wrong fix, as
it did not observed that the last expressions was done under the
invariant that we had a last verification result, because if none
could be loaded we already returned true (include).
It thus broke the case for "never re-verify", which is important when
using multiple schedules, a more high frequent one for new,
unverified snapshots, and a low frequency to re-verify older snapshots,
e.g., monthly.
Fix this case again, rework the code to avoid this easy to oversee
invariant. Use a nested match to better express the implication of
each setting, and add some comments.
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2020-10-28 14:33:04 +00:00
|
|
|
if !ignore_verified_snapshots {
|
2020-10-28 11:58:15 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
let raw_verify_state = manifest.unprotected["verify_state"].clone();
|
do_verification_job: fix "never-reverify" and refactor/comment
commit a4915dfc2bc7bef03354f97f5bbce9fe2df4e0d6 made a wrong fix, as
it did not observed that the last expressions was done under the
invariant that we had a last verification result, because if none
could be loaded we already returned true (include).
It thus broke the case for "never re-verify", which is important when
using multiple schedules, a more high frequent one for new,
unverified snapshots, and a low frequency to re-verify older snapshots,
e.g., monthly.
Fix this case again, rework the code to avoid this easy to oversee
invariant. Use a nested match to better express the implication of
each setting, and add some comments.
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2020-10-28 14:33:04 +00:00
|
|
|
match serde_json::from_value::<SnapshotVerifyState>(raw_verify_state) {
|
|
|
|
Err(_) => return 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;
|
2020-10-28 11:58:15 +00:00
|
|
|
|
do_verification_job: fix "never-reverify" and refactor/comment
commit a4915dfc2bc7bef03354f97f5bbce9fe2df4e0d6 made a wrong fix, as
it did not observed that the last expressions was done under the
invariant that we had a last verification result, because if none
could be loaded we already returned true (include).
It thus broke the case for "never re-verify", which is important when
using multiple schedules, a more high frequent one for new,
unverified snapshots, and a low frequency to re-verify older snapshots,
e.g., monthly.
Fix this case again, rework the code to avoid this easy to oversee
invariant. Use a nested match to better express the implication of
each setting, and add some comments.
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2020-10-28 14:33:04 +00:00
|
|
|
days_since_last_verify > max_age
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-28 11:58:15 +00:00
|
|
|
};
|
2020-10-28 06:58:07 +00:00
|
|
|
|
2020-11-04 10:27:57 +00:00
|
|
|
let (email, notify) = crate::server::lookup_datastore_notify_settings(&verification_job.store);
|
2020-10-27 12:36:56 +00:00
|
|
|
|
2020-11-06 10:23:09 +00:00
|
|
|
let job_id = format!("{}:{}",
|
|
|
|
&verification_job.store,
|
|
|
|
job.jobname());
|
2020-10-28 06:58:07 +00:00
|
|
|
let worker_type = job.jobtype().to_string();
|
|
|
|
let upid_str = WorkerTask::new_thread(
|
|
|
|
&worker_type,
|
2020-11-06 10:23:09 +00:00
|
|
|
Some(job_id.clone()),
|
2020-10-23 11:33:21 +00:00
|
|
|
auth_id.clone(),
|
2020-10-28 06:58:07 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-10-30 11:36:39 +00:00
|
|
|
let result = verify_all_backups(datastore, worker.clone(), worker.upid(), None, Some(&filter));
|
2020-10-28 11:58:15 +00:00
|
|
|
let job_result = match result {
|
2020-11-23 09:57:15 +00:00
|
|
|
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"))
|
|
|
|
},
|
2020-10-28 11:58:15 +00:00
|
|
|
Err(_) => Err(format_err!("verification failed - job aborted")),
|
|
|
|
};
|
2020-10-28 06:58:07 +00:00
|
|
|
|
2020-10-28 11:58:15 +00:00
|
|
|
let status = worker.create_state(&job_result);
|
2020-10-28 06:58:07 +00:00
|
|
|
|
|
|
|
match job.finish(status) {
|
|
|
|
Err(err) => eprintln!(
|
|
|
|
"could not finish job state for {}: {}",
|
|
|
|
job.jobtype().to_string(),
|
|
|
|
err
|
|
|
|
),
|
|
|
|
Ok(_) => (),
|
|
|
|
}
|
|
|
|
|
2020-10-27 12:36:56 +00:00
|
|
|
if let Some(email) = email {
|
2020-11-04 10:27:57 +00:00
|
|
|
if let Err(err) = crate::server::send_verify_status(&email, notify, verification_job, &result) {
|
2020-10-27 12:36:56 +00:00
|
|
|
eprintln!("send verify notification failed: {}", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-28 11:58:15 +00:00
|
|
|
job_result
|
2020-10-28 06:58:07 +00:00
|
|
|
},
|
|
|
|
)?;
|
|
|
|
Ok(upid_str)
|
|
|
|
}
|