api2/tape/backup: include a summary on notification e-mails

for now only contains the list of included snapshots (if any),
as well as the backup duration

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
Dominik Csapak 2021-03-19 08:53:17 +01:00 committed by Dietmar Maurer
parent eac1beef3c
commit 4abd4dbe38
2 changed files with 47 additions and 6 deletions

View File

@ -33,6 +33,7 @@ use crate::{
}, },
server::{ server::{
lookup_user_email, lookup_user_email,
TapeBackupJobSummary,
jobstate::{ jobstate::{
Job, Job,
JobState, JobState,
@ -198,13 +199,16 @@ pub fn do_tape_backup_job(
let notify_user = setup.notify_user.as_ref().unwrap_or_else(|| &Userid::root_userid()); let notify_user = setup.notify_user.as_ref().unwrap_or_else(|| &Userid::root_userid());
let email = lookup_user_email(notify_user); let email = lookup_user_email(notify_user);
let job_result = backup_worker( let (job_result, summary) = match backup_worker(
&worker, &worker,
datastore, datastore,
&pool_config, &pool_config,
&setup, &setup,
email.clone(), email.clone(),
); ) {
Ok(summary) => (Ok(()), summary),
Err(err) => (Err(err), Default::default()),
};
let status = worker.create_state(&job_result); let status = worker.create_state(&job_result);
@ -214,6 +218,7 @@ pub fn do_tape_backup_job(
Some(job.jobname()), Some(job.jobname()),
&setup, &setup,
&job_result, &job_result,
summary,
) { ) {
eprintln!("send tape backup notification failed: {}", err); eprintln!("send tape backup notification failed: {}", err);
} }
@ -340,13 +345,17 @@ pub fn backup(
move |worker| { move |worker| {
let _drive_lock = drive_lock; // keep lock guard let _drive_lock = drive_lock; // keep lock guard
set_tape_device_state(&setup.drive, &worker.upid().to_string())?; set_tape_device_state(&setup.drive, &worker.upid().to_string())?;
let job_result = backup_worker(
let (job_result, summary) = match backup_worker(
&worker, &worker,
datastore, datastore,
&pool_config, &pool_config,
&setup, &setup,
email.clone(), email.clone(),
); ) {
Ok(summary) => (Ok(()), summary),
Err(err) => (Err(err), Default::default()),
};
if let Some(email) = email { if let Some(email) = email {
if let Err(err) = crate::server::send_tape_backup_status( if let Err(err) = crate::server::send_tape_backup_status(
@ -354,6 +363,7 @@ pub fn backup(
None, None,
&setup, &setup,
&job_result, &job_result,
summary,
) { ) {
eprintln!("send tape backup notification failed: {}", err); eprintln!("send tape backup notification failed: {}", err);
} }
@ -374,9 +384,11 @@ fn backup_worker(
pool_config: &MediaPoolConfig, pool_config: &MediaPoolConfig,
setup: &TapeBackupJobSetup, setup: &TapeBackupJobSetup,
email: Option<String>, email: Option<String>,
) -> Result<(), Error> { ) -> Result<TapeBackupJobSummary, Error> {
let status_path = Path::new(TAPE_STATUS_DIR); let status_path = Path::new(TAPE_STATUS_DIR);
let start = std::time::Instant::now();
let mut summary: TapeBackupJobSummary = Default::default();
let _lock = MediaPool::lock(status_path, &pool_config.name)?; let _lock = MediaPool::lock(status_path, &pool_config.name)?;
@ -422,8 +434,11 @@ fn backup_worker(
task_log!(worker, "skip snapshot {}", info.backup_dir); task_log!(worker, "skip snapshot {}", info.backup_dir);
continue; continue;
} }
let snapshot_name = info.backup_dir.to_string();
if !backup_snapshot(worker, &mut pool_writer, datastore.clone(), info.backup_dir)? { if !backup_snapshot(worker, &mut pool_writer, datastore.clone(), info.backup_dir)? {
errors = true; errors = true;
} else {
summary.snapshot_list.push(snapshot_name);
} }
progress.done_snapshots = 1; progress.done_snapshots = 1;
task_log!( task_log!(
@ -439,8 +454,11 @@ fn backup_worker(
task_log!(worker, "skip snapshot {}", info.backup_dir); task_log!(worker, "skip snapshot {}", info.backup_dir);
continue; continue;
} }
let snapshot_name = info.backup_dir.to_string();
if !backup_snapshot(worker, &mut pool_writer, datastore.clone(), info.backup_dir)? { if !backup_snapshot(worker, &mut pool_writer, datastore.clone(), info.backup_dir)? {
errors = true; errors = true;
} else {
summary.snapshot_list.push(snapshot_name);
} }
progress.done_snapshots = snapshot_number as u64 + 1; progress.done_snapshots = snapshot_number as u64 + 1;
task_log!( task_log!(
@ -478,7 +496,9 @@ fn backup_worker(
bail!("Tape backup finished with some errors. Please check the task log."); bail!("Tape backup finished with some errors. Please check the task log.");
} }
Ok(()) summary.duration = start.elapsed();
Ok(summary)
} }
// Try to update the the media online status // Try to update the the media online status

View File

@ -149,6 +149,14 @@ Datastore: {{job.store}}
Tape Pool: {{job.pool}} Tape Pool: {{job.pool}}
Tape Drive: {{job.drive}} Tape Drive: {{job.drive}}
{{#if snapshot-list ~}}
Snapshots included:
{{#each snapshot-list~}}
{{this}}
{{/each~}}
{{/if}}
Duration: {{duration}}
Tape Backup successful. Tape Backup successful.
@ -215,6 +223,15 @@ lazy_static::lazy_static!{
}; };
} }
/// Summary of a successful Tape Job
#[derive(Default)]
pub struct TapeBackupJobSummary {
/// The list of snaphots backed up
pub snapshot_list: Vec<String>,
/// The total time of the backup job
pub duration: std::time::Duration,
}
fn send_job_status_mail( fn send_job_status_mail(
email: &str, email: &str,
subject: &str, subject: &str,
@ -412,14 +429,18 @@ pub fn send_tape_backup_status(
id: Option<&str>, id: Option<&str>,
job: &TapeBackupJobSetup, job: &TapeBackupJobSetup,
result: &Result<(), Error>, result: &Result<(), Error>,
summary: TapeBackupJobSummary,
) -> Result<(), Error> { ) -> Result<(), Error> {
let (fqdn, port) = get_server_url(); let (fqdn, port) = get_server_url();
let duration: crate::tools::systemd::time::TimeSpan = summary.duration.into();
let mut data = json!({ let mut data = json!({
"job": job, "job": job,
"fqdn": fqdn, "fqdn": fqdn,
"port": port, "port": port,
"id": id, "id": id,
"snapshot-list": summary.snapshot_list,
"duration": duration.to_string(),
}); });
let text = match result { let text = match result {