config: make notify a property string

For example "gc=never,verify=always,sync=error".
This commit is contained in:
Dietmar Maurer 2020-11-05 11:32:59 +01:00
parent 9e45e03aef
commit c26c9390ff
4 changed files with 87 additions and 21 deletions

View File

@ -5,6 +5,7 @@ use serde_json::Value;
use ::serde::{Deserialize, Serialize}; use ::serde::{Deserialize, Serialize};
use proxmox::api::{api, Router, RpcEnvironment, Permission}; use proxmox::api::{api, Router, RpcEnvironment, Permission};
use proxmox::api::schema::parse_property_string;
use proxmox::tools::fs::open_file_locked; use proxmox::tools::fs::open_file_locked;
use crate::api2::types::*; use crate::api2::types::*;
@ -74,7 +75,7 @@ pub fn list_datastores(
}, },
"notify": { "notify": {
optional: true, optional: true,
type: Notify, schema: DATASTORE_NOTIFY_STRING_SCHEMA,
}, },
"gc-schedule": { "gc-schedule": {
optional: true, optional: true,
@ -218,7 +219,7 @@ pub enum DeletableProperty {
}, },
"notify": { "notify": {
optional: true, optional: true,
type: Notify, schema: DATASTORE_NOTIFY_STRING_SCHEMA,
}, },
"gc-schedule": { "gc-schedule": {
optional: true, optional: true,
@ -282,7 +283,7 @@ pub fn update_datastore(
keep_weekly: Option<u64>, keep_weekly: Option<u64>,
keep_monthly: Option<u64>, keep_monthly: Option<u64>,
keep_yearly: Option<u64>, keep_yearly: Option<u64>,
notify: Option<Notify>, notify: Option<String>,
notify_user: Option<Userid>, notify_user: Option<Userid>,
delete: Option<Vec<DeletableProperty>>, delete: Option<Vec<DeletableProperty>>,
digest: Option<String>, digest: Option<String>,
@ -346,7 +347,15 @@ pub fn update_datastore(
if keep_monthly.is_some() { data.keep_monthly = keep_monthly; } if keep_monthly.is_some() { data.keep_monthly = keep_monthly; }
if keep_yearly.is_some() { data.keep_yearly = keep_yearly; } if keep_yearly.is_some() { data.keep_yearly = keep_yearly; }
if notify.is_some() { data.notify = notify; } if let Some(notify_str) = notify {
let value = parse_property_string(&notify_str, &DatastoreNotify::API_SCHEMA)?;
let notify: DatastoreNotify = serde_json::from_value(value)?;
if let DatastoreNotify { gc: None, verify: None, sync: None } = notify {
data.notify = None;
} else {
data.notify = Some(notify_str);
}
}
if notify_user.is_some() { data.notify_user = notify_user; } if notify_user.is_some() { data.notify_user = notify_user; }
config.set_data(&name, "datastore", &data)?; config.set_data(&name, "datastore", &data)?;

View File

@ -1167,3 +1167,35 @@ pub enum Notify {
/// Send notifications for failed jobs only /// Send notifications for failed jobs only
Error, Error,
} }
#[api(
properties: {
gc: {
type: Notify,
optional: true,
},
verify: {
type: Notify,
optional: true,
},
sync: {
type: Notify,
optional: true,
},
},
)]
#[derive(Debug, Serialize, Deserialize)]
/// Datastore notify settings
pub struct DatastoreNotify {
/// Garbage collection settings
pub gc: Option<Notify>,
/// Verify job setting
pub verify: Option<Notify>,
/// Sync job setting
pub sync: Option<Notify>,
}
pub const DATASTORE_NOTIFY_STRING_SCHEMA: Schema = StringSchema::new(
"Datastore notification setting")
.format(&ApiStringFormat::PropertyString(&DatastoreNotify::API_SCHEMA))
.schema();

View File

@ -38,7 +38,7 @@ pub const DIR_NAME_SCHEMA: Schema = StringSchema::new("Directory name").schema()
}, },
"notify": { "notify": {
optional: true, optional: true,
type: Notify, schema: DATASTORE_NOTIFY_STRING_SCHEMA,
}, },
comment: { comment: {
optional: true, optional: true,
@ -114,7 +114,7 @@ pub struct DataStoreConfig {
pub notify_user: Option<Userid>, pub notify_user: Option<Userid>,
/// Send notification only for job errors /// Send notification only for job errors
#[serde(skip_serializing_if="Option::is_none")] #[serde(skip_serializing_if="Option::is_none")]
pub notify: Option<Notify>, pub notify: Option<String>,
} }
fn init() -> SectionConfig { fn init() -> SectionConfig {

View File

@ -4,6 +4,7 @@ use serde_json::json;
use handlebars::{Handlebars, Helper, Context, RenderError, RenderContext, Output, HelperResult}; use handlebars::{Handlebars, Helper, Context, RenderError, RenderContext, Output, HelperResult};
use proxmox::tools::email::sendmail; use proxmox::tools::email::sendmail;
use proxmox::api::schema::parse_property_string;
use crate::{ use crate::{
config::datastore::DataStoreConfig, config::datastore::DataStoreConfig,
@ -14,6 +15,7 @@ use crate::{
GarbageCollectionStatus, GarbageCollectionStatus,
Userid, Userid,
Notify, Notify,
DatastoreNotify,
}, },
tools::format::HumanByte, tools::format::HumanByte,
}; };
@ -190,15 +192,20 @@ fn send_job_status_mail(
pub fn send_gc_status( pub fn send_gc_status(
email: &str, email: &str,
notify: Notify, notify: DatastoreNotify,
datastore: &str, datastore: &str,
status: &GarbageCollectionStatus, status: &GarbageCollectionStatus,
result: &Result<(), Error>, result: &Result<(), Error>,
) -> Result<(), Error> { ) -> Result<(), Error> {
match notify.gc {
None => { /* send notifications by default */ },
Some(notify) => {
if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) { if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
return Ok(()); return Ok(());
} }
}
}
let (fqdn, port) = get_server_url(); let (fqdn, port) = get_server_url();
let mut data = json!({ let mut data = json!({
@ -244,15 +251,11 @@ pub fn send_gc_status(
pub fn send_verify_status( pub fn send_verify_status(
email: &str, email: &str,
notify: Notify, notify: DatastoreNotify,
job: VerificationJobConfig, job: VerificationJobConfig,
result: &Result<Vec<String>, Error>, result: &Result<Vec<String>, Error>,
) -> Result<(), Error> { ) -> Result<(), Error> {
if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
return Ok(());
}
let (fqdn, port) = get_server_url(); let (fqdn, port) = get_server_url();
let mut data = json!({ let mut data = json!({
"job": job, "job": job,
@ -260,8 +263,11 @@ pub fn send_verify_status(
"port": port, "port": port,
}); });
let mut result_is_ok = false;
let text = match result { let text = match result {
Ok(errors) if errors.is_empty() => { Ok(errors) if errors.is_empty() => {
result_is_ok = true;
HANDLEBARS.render("verify_ok_template", &data)? HANDLEBARS.render("verify_ok_template", &data)?
} }
Ok(errors) => { Ok(errors) => {
@ -274,6 +280,15 @@ pub fn send_verify_status(
} }
}; };
match notify.verify {
None => { /* send notifications by default */ },
Some(notify) => {
if notify == Notify::Never || (result_is_ok && notify == Notify::Error) {
return Ok(());
}
}
}
let subject = match result { let subject = match result {
Ok(errors) if errors.is_empty() => format!( Ok(errors) if errors.is_empty() => format!(
"Verify Datastore '{}' successful", "Verify Datastore '{}' successful",
@ -292,14 +307,19 @@ pub fn send_verify_status(
pub fn send_sync_status( pub fn send_sync_status(
email: &str, email: &str,
notify: Notify, notify: DatastoreNotify,
job: &SyncJobConfig, job: &SyncJobConfig,
result: &Result<(), Error>, result: &Result<(), Error>,
) -> Result<(), Error> { ) -> Result<(), Error> {
match notify.sync {
None => { /* send notifications by default */ },
Some(notify) => {
if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) { if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
return Ok(()); return Ok(());
} }
}
}
let (fqdn, port) = get_server_url(); let (fqdn, port) = get_server_url();
let mut data = json!({ let mut data = json!({
@ -399,11 +419,12 @@ fn lookup_user_email(userid: &Userid) -> Option<String> {
/// Lookup Datastore notify settings /// Lookup Datastore notify settings
pub fn lookup_datastore_notify_settings( pub fn lookup_datastore_notify_settings(
store: &str, store: &str,
) -> (Option<String>, Notify) { ) -> (Option<String>, DatastoreNotify) {
let mut notify = Notify::Always;
let mut email = None; let mut email = None;
let notify = DatastoreNotify { gc: None, verify: None, sync: None };
let (config, _digest) = match crate::config::datastore::config() { let (config, _digest) = match crate::config::datastore::config() {
Ok(result) => result, Ok(result) => result,
Err(_) => return (email, notify), Err(_) => return (email, notify),
@ -419,8 +440,12 @@ pub fn lookup_datastore_notify_settings(
None => lookup_user_email(Userid::backup_userid()), None => lookup_user_email(Userid::backup_userid()),
}; };
if let Some(value) = config.notify { let notify_str = config.notify.unwrap_or(String::new());
notify = value;
if let Ok(value) = parse_property_string(&notify_str, &DatastoreNotify::API_SCHEMA) {
if let Ok(notify) = serde_json::from_value(value) {
return (email, notify);
}
} }
(email, notify) (email, notify)