[pbs-devel] [PATCH proxmox-backup v2] fix #4274: implement prune notifications
Dominik Csapak
d.csapak at proxmox.com
Thu Oct 6 11:08:12 CEST 2022
we converted the prune settings of datastores to prune-jobs, but did
not actually implement the notifications for them, even though
we had the notification options in the gui (they did not work).
implement the basic ok/error notification for prune jobs
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
changes from v1:
* include 'fix #' in the commit subject
* call lookup_datastore_notify_settings directly in the send helper
* fix compilation errors
* rebase on master
pbs-api-types/src/jobs.rs | 6 +++
src/api2/config/datastore.rs | 1 +
src/server/email_notifications.rs | 77 +++++++++++++++++++++++++++++++
src/server/prune_job.rs | 7 ++-
www/datastore/OptionView.js | 2 +-
www/window/NotifyOptions.js | 2 +-
6 files changed, 91 insertions(+), 4 deletions(-)
diff --git a/pbs-api-types/src/jobs.rs b/pbs-api-types/src/jobs.rs
index e4be03f0..7f029af7 100644
--- a/pbs-api-types/src/jobs.rs
+++ b/pbs-api-types/src/jobs.rs
@@ -128,6 +128,10 @@ pub enum Notify {
type: Notify,
optional: true,
},
+ prune: {
+ type: Notify,
+ optional: true,
+ },
},
)]
#[derive(Debug, Serialize, Deserialize)]
@@ -139,6 +143,8 @@ pub struct DatastoreNotify {
pub verify: Option<Notify>,
/// Sync job setting
pub sync: Option<Notify>,
+ /// Prune job setting
+ pub prune: Option<Notify>,
}
pub const DATASTORE_NOTIFY_STRING_SCHEMA: Schema =
diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs
index 2d769722..08adf7c9 100644
--- a/src/api2/config/datastore.rs
+++ b/src/api2/config/datastore.rs
@@ -331,6 +331,7 @@ pub fn update_datastore(
gc: None,
verify: None,
sync: None,
+ prune: None,
} = notify
{
data.notify = None;
diff --git a/src/server/email_notifications.rs b/src/server/email_notifications.rs
index f60acc64..8d97623a 100644
--- a/src/server/email_notifications.rs
+++ b/src/server/email_notifications.rs
@@ -113,6 +113,34 @@ Remote Store: {{job.remote-store}}
Synchronization failed: {{error}}
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
+
+"###;
+
+const PRUNE_OK_TEMPLATE: &str = r###"
+
+Job ID: {{jobname}}
+Datastore: {{store}}
+
+Pruning successful.
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#DataStore-{{store}}>
+
+"###;
+
+const PRUNE_ERR_TEMPLATE: &str = r###"
+
+Job ID: {{jobname}}
+Datastore: {{store}}
+
+Pruning failed: {{error}}
+
+
Please visit the web interface for further details:
<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
@@ -227,6 +255,9 @@ lazy_static::lazy_static! {
hb.register_template_string("sync_ok_template", SYNC_OK_TEMPLATE)?;
hb.register_template_string("sync_err_template", SYNC_ERR_TEMPLATE)?;
+ hb.register_template_string("prune_ok_template", PRUNE_OK_TEMPLATE)?;
+ hb.register_template_string("prune_err_template", PRUNE_ERR_TEMPLATE)?;
+
hb.register_template_string("tape_backup_ok_template", TAPE_BACKUP_OK_TEMPLATE)?;
hb.register_template_string("tape_backup_err_template", TAPE_BACKUP_ERR_TEMPLATE)?;
@@ -384,6 +415,51 @@ pub fn send_verify_status(
Ok(())
}
+pub fn send_prune_status(
+ store: &str,
+ jobname: &str,
+ result: &Result<(), Error>,
+) -> Result<(), Error> {
+ let (email, notify) = match lookup_datastore_notify_settings(&store) {
+ (Some(email), notify) => (email, notify),
+ (None, _) => return Ok(()),
+ };
+
+ match notify.prune {
+ None => { /* send notifications by default */ }
+ Some(notify) => {
+ if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
+ return Ok(());
+ }
+ }
+ }
+
+ let (fqdn, port) = get_server_url();
+ let mut data = json!({
+ "jobname": jobname,
+ "store": store,
+ "fqdn": fqdn,
+ "port": port,
+ });
+
+ let text = match result {
+ Ok(()) => HANDLEBARS.render("prune_ok_template", &data)?,
+ Err(err) => {
+ data["error"] = err.to_string().into();
+ HANDLEBARS.render("prune_err_template", &data)?
+ }
+ };
+
+ let subject = match result {
+ Ok(()) => format!("Pruning datastore '{}' successful", store,),
+ Err(_) => format!("Pruning datastore '{}' failed", store,),
+ };
+
+ send_job_status_mail(&email, &subject, &text)?;
+
+ Ok(())
+}
+
pub fn send_sync_status(
email: &str,
notify: DatastoreNotify,
@@ -584,6 +660,7 @@ pub fn lookup_datastore_notify_settings(store: &str) -> (Option<String>, Datasto
gc: None,
verify: None,
sync: None,
+ prune: None,
};
let (config, _digest) = match pbs_config::datastore::config() {
diff --git a/src/server/prune_job.rs b/src/server/prune_job.rs
index 4e261b48..0a8e1d19 100644
--- a/src/server/prune_job.rs
+++ b/src/server/prune_job.rs
@@ -164,9 +164,9 @@ pub fn do_prune_job(
let worker_type = job.jobtype().to_string();
let auth_id = auth_id.clone();
let worker_id = match &prune_options.ns {
- Some(ns) if ns.is_root() => store,
+ Some(ns) if ns.is_root() => store.clone(),
Some(ns) => format!("{store}:{ns}"),
- None => store,
+ None => store.clone(),
};
let upid_str = WorkerTask::new_thread(
@@ -191,6 +191,9 @@ pub fn do_prune_job(
eprintln!("could not finish job state for {}: {}", job.jobtype(), err);
}
+ if let Err(err) = crate::server::send_prune_status(&store, job.jobname(), &result) {
+ log::error!("send prune notification failed: {}", err);
+ }
result
},
)?;
diff --git a/www/datastore/OptionView.js b/www/datastore/OptionView.js
index 4cfafccf..eb335979 100644
--- a/www/datastore/OptionView.js
+++ b/www/datastore/OptionView.js
@@ -110,7 +110,7 @@ Ext.define('PBS.Datastore.Options', {
renderer: (value) => {
let notify = PBS.Utils.parsePropertyString(value);
let res = [];
- for (const k of ['Verify', 'Sync', 'GC']) {
+ for (const k of ['Verify', 'Sync', 'GC', 'Prune']) {
let v = Ext.String.capitalize(notify[k.toLowerCase()]) || 'Always';
res.push(`${k}=${v}`);
}
diff --git a/www/window/NotifyOptions.js b/www/window/NotifyOptions.js
index 924bbb8b..7c7e6489 100644
--- a/www/window/NotifyOptions.js
+++ b/www/window/NotifyOptions.js
@@ -36,7 +36,7 @@ Ext.define('PBS.window.NotifyOptions', {
xtype: 'inputpanel',
onGetValues: function(values) {
let notify = {};
- for (const k of ['verify', 'sync', 'gc']) {
+ for (const k of ['verify', 'sync', 'gc', 'prune']) {
notify[k] = values[k];
delete values[k];
}
--
2.30.2
More information about the pbs-devel
mailing list