* [pbs-devel] [PATCH many v2 00/43] integrate notification system
@ 2024-04-17 14:34 Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 01/43] notify: expose `config` module Lukas Wagner
` (42 more replies)
0 siblings, 43 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
These patches integrate the notification system which was introduced in Proxmox VE
in 8.1 into Proxmox Backup Server.
Some highlights/noteworthy details from the series:
- notification template files are installed in /usr/share/proxmox-backup/templates/default
and are rendered when a notification is sent
- since sending notifications needs to be done from a privileged context
(to read protected passwords/tokens from the priv config file),
we queue notifications to be sent in /var/lib/proxmox-backup/notifications
and periodically send any queued notifications via a worker in the
privileged process
- The API endpoint paths are prefixed with /config/notifications
- API endpoints which read/modify notification system config require
Sys.Audit (read) or Sys.Modify (modify/test endpoint) permissions
on /system/notifications
- tape-{backup,restore} settings and datastore options now have a
'notification-mode' parameter, which allows to choose between the
'legacy' behavior (sendmail to a selected user's email address) and
the event-based notification system. If the parameter is not set, we
default to the legacy behavior in order to keep existing behavior
as is for now. For new datastores/tape backup jobs created
interactively from the UI, we set the parameter to 'notification-system'
and opt in into the new system by default. For the CLI/API we don't
so that we don't cause problems with any automations/scripts -
there I'd change the default to the new system with the next major release
Rough edges:
- Datastore option view in UI could be improved. When 'notification-mode' is
set to 'notification-system', we should indicate that 'mailto-user' and the
other notification settings have no effect. Already did that in the edit
window, but in the grid panel I did not find a quick way to do that.
Prerequisites:
- This patch series requires the patches for 'proxmox' from
https://lists.proxmox.com/pipermail/pve-devel/2024-April/062708.html
to be applied first
- The dependency for proxmox-widget-toolkit should be bumped to at least
4.1.4 (we need: "utils: add mechanism to add and override translatable notification event
descriptions in the product specific UIs")
Also, while not strictly needed, the patches for widget-toolkit from
https://lists.proxmox.com/pipermail/pve-devel/2024-February/061992.html
make creating matchers much easier - the required API endpoints were
already implemented by this series.
Changes since v1:
- proxmox_notify: Change default-matcher to exclude 'prune success' notifications
- proxmox_notify: Move sendmail/forward functions from proxmox_sys
- proxmox_notify: Improve docs for API types
- proxmox-widget-toolkit: allow to override default mail author
- Add documentation, man pages, etc. (mostly copied from PVE, some
stylistic touchups, some rephrasing)
- Add additional matchable metadata fields, allowing to match on
individual jobs:
- verification-job
- prune-job
- sync-job
- tape-job
- Sort queued notifications by timestamp before sending
- Fix missing hostname in package-update notification
- Change default mail author in the UI from Proxmox VE to Proxmox Backup Server ($hostname)
proxmox:
Lukas Wagner (6):
notify: expose `config` module
notify: use std::sync::OnceCell instead of lazy_static!
notify: pbs-context: exclude successful prunes in default matcher
notify: endpoints: matcher: improve descriptions for API types
notify: sys: move 'email' module from proxmox_sys to proxmox_notify
notify: add getter for notification timestamp
proxmox-notify/Cargo.toml | 4 +--
proxmox-notify/src/config.rs | 23 +++++++++------
proxmox-notify/src/context/pbs.rs | 5 +++-
proxmox-notify/src/endpoints/common/mod.rs | 3 ++
.../src/endpoints/common/sendmail_impl.rs | 10 ++++---
proxmox-notify/src/endpoints/gotify.rs | 6 ++--
proxmox-notify/src/endpoints/sendmail.rs | 20 ++++++++-----
proxmox-notify/src/endpoints/smtp.rs | 28 ++++++++++++-------
proxmox-notify/src/lib.rs | 11 +++++---
proxmox-notify/src/matcher.rs | 18 ++++++------
proxmox-sys/src/lib.rs | 1 -
11 files changed, 80 insertions(+), 49 deletions(-)
rename proxmox-sys/src/email.rs => proxmox-notify/src/endpoints/common/sendmail_impl.rs (96%)
proxmox-widget-toolkit:
Lukas Wagner (1):
sendmail: smtp: allow to overide default mail author
src/Schema.js | 9 +++++++++
src/panel/SendmailEditPanel.js | 2 +-
src/panel/SmtpEditPanel.js | 2 +-
src/window/EndpointEditBase.js | 1 +
4 files changed, 12 insertions(+), 2 deletions(-)
proxmox-backup:
Lukas Wagner (36):
pbs-config: add module for loading notification config
server: rename email_notifications module to notifications
notifications: allow sending notifications via proxmox_notify
buildsys: install templates for test notifications
pbs-config: acl: add /system/notifications as known ACL path
api: add endpoints for querying/testing notification targets
api: add endpoints for notification matchers
api: add endpoints for sendmail targets
api: add endpoints for smtp targets
api: add endpoints for gotify targets
api: add endpoints for querying known notification values/fields
api-types: api: datatore: add notification-mode parameter
api-types: api: tape: add notification-mode parameter
server: notifications: send GC notifications via notification system
server: notifications: send prune notifications via notification
system
server: notifications: send verify notifications via notification
system
server: notifications: send sync notifications via notification system
server: notifications: send update notifications via notification
system
server: notifications: send acme notifications via notification system
server: notifications: send tape notifications via notification system
ui: add notification config panel
ui: tape backup job: add selector for notification-mode
ui: tape backup: add selector for 'notification-mode'
ui: tape restore: add 'notification-mode' parameter
ui: datastore options: add 'notification-mode' parameter
ui: utils: add overrides for known notification metadata fields/values
ui: datastore edit: make new stores use notification system by default
ui: permissions paths: add /system/notifications to combobox
proxmox-backup-manager: add CLI for notification targets
proxmox-backup-manager: add CLI for notification matchers
proxmox-backup-manager: add CLI for gotify endpoints
proxmox-backup-manager: add CLI for sendmail endpoints
proxmox-backup-manager: add CLI for SMTP endpoints
docgen: generate synopsis for notifications{-priv,}.cfg
docs: add documentation for notification system
ui: util: override default mail author for sendmail/smtp targets
Cargo.toml | 3 +
Makefile | 5 +-
debian/proxmox-backup-server.install | 31 +
docs/Makefile | 6 +-
docs/conf.py | 2 +
docs/config/notifications-priv/format.rst | 1 +
docs/config/notifications-priv/man5.rst | 24 +
docs/config/notifications/format.rst | 28 +
docs/config/notifications/man5.rst | 24 +
docs/configuration-files.rst | 30 +
docs/index.rst | 1 +
docs/notifications.rst | 213 +++++
pbs-api-types/src/datastore.rs | 22 +
pbs-api-types/src/jobs.rs | 8 +-
pbs-config/Cargo.toml | 1 +
pbs-config/src/acl.rs | 3 +-
pbs-config/src/lib.rs | 1 +
pbs-config/src/notifications.rs | 41 +
src/api2/config/datastore.rs | 9 +
src/api2/config/mod.rs | 2 +
src/api2/config/notifications/gotify.rs | 190 +++++
src/api2/config/notifications/matchers.rs | 170 ++++
src/api2/config/notifications/mod.rs | 224 +++++
src/api2/config/notifications/sendmail.rs | 178 ++++
src/api2/config/notifications/smtp.rs | 191 +++++
src/api2/config/notifications/targets.rs | 63 ++
src/api2/config/tape_backup_job.rs | 8 +
src/api2/pull.rs | 10 +-
src/api2/tape/backup.rs | 62 +-
src/api2/tape/restore.rs | 46 +-
src/bin/docgen.rs | 4 +
src/bin/proxmox-backup-api.rs | 11 +
src/bin/proxmox-backup-manager.rs | 2 +
src/bin/proxmox-backup-proxy.rs | 1 +
src/bin/proxmox_backup_manager/mod.rs | 2 +
.../notifications/gotify.rs | 93 +++
.../notifications/matchers.rs | 93 +++
.../notifications/mod.rs | 21 +
.../notifications/sendmail.rs | 94 +++
.../notifications/smtp.rs | 96 +++
.../notifications/targets.rs | 51 ++
src/server/email_notifications.rs | 763 ------------------
src/server/gc_job.rs | 10 +-
src/server/mod.rs | 4 +-
src/server/notifications.rs | 566 +++++++++++++
src/server/verify_job.rs | 10 +-
src/tape/drive/mod.rs | 22 +-
src/tape/mod.rs | 27 +
src/tape/pool_writer/mod.rs | 11 +-
templates/Makefile | 41 +
templates/default/acme-err-body.txt.hbs | 7 +
templates/default/acme-err-subject.txt.hbs | 1 +
templates/default/gc-err-body.txt.hbs | 8 +
templates/default/gc-err-subject.txt.hbs | 1 +
templates/default/gc-ok-body.txt.hbs | 23 +
templates/default/gc-ok-subject.txt.hbs | 1 +
.../default/package-updates-body.txt.hbs | 8 +
.../default/package-updates-subject.txt.hbs | 1 +
templates/default/prune-err-body.txt.hbs | 10 +
templates/default/prune-err-subject.txt.hbs | 1 +
templates/default/prune-ok-body.txt.hbs | 10 +
templates/default/prune-ok-subject.txt.hbs | 1 +
templates/default/sync-err-body.txt.hbs | 14 +
templates/default/sync-err-subject.txt.hbs | 5 +
templates/default/sync-ok-body.txt.hbs | 14 +
templates/default/sync-ok-subject.txt.hbs | 5 +
.../default/tape-backup-err-body.txt.hbs | 26 +
.../default/tape-backup-err-subject.txt.hbs | 5 +
templates/default/tape-backup-ok-body.txt.hbs | 27 +
.../default/tape-backup-ok-subject.txt.hbs | 5 +
templates/default/tape-load-body.txt.hbs | 15 +
templates/default/tape-load-subject.txt.hbs | 1 +
templates/default/test-body.html.hbs | 1 +
templates/default/test-body.txt.hbs | 1 +
templates/default/test-subject.txt.hbs | 1 +
templates/default/verify-err-body.txt.hbs | 14 +
templates/default/verify-err-subject.txt.hbs | 1 +
templates/default/verify-ok-body.txt.hbs | 10 +
templates/default/verify-ok-subject.txt.hbs | 1 +
www/Makefile | 1 +
www/NavigationTree.js | 6 +
www/OnlineHelpInfo.js | 24 +
www/Utils.js | 40 +
www/config/NotificationConfigView.js | 11 +
www/datastore/OptionView.js | 15 +
www/form/PermissionPathSelector.js | 1 +
www/tape/window/TapeBackup.js | 25 +
www/tape/window/TapeBackupJob.js | 24 +
www/tape/window/TapeRestore.js | 17 +
www/window/DataStoreEdit.js | 13 +
www/window/NotifyOptions.js | 38 +
91 files changed, 3083 insertions(+), 869 deletions(-)
create mode 100644 docs/config/notifications-priv/format.rst
create mode 100644 docs/config/notifications-priv/man5.rst
create mode 100644 docs/config/notifications/format.rst
create mode 100644 docs/config/notifications/man5.rst
create mode 100644 docs/notifications.rst
create mode 100644 pbs-config/src/notifications.rs
create mode 100644 src/api2/config/notifications/gotify.rs
create mode 100644 src/api2/config/notifications/matchers.rs
create mode 100644 src/api2/config/notifications/mod.rs
create mode 100644 src/api2/config/notifications/sendmail.rs
create mode 100644 src/api2/config/notifications/smtp.rs
create mode 100644 src/api2/config/notifications/targets.rs
create mode 100644 src/bin/proxmox_backup_manager/notifications/gotify.rs
create mode 100644 src/bin/proxmox_backup_manager/notifications/matchers.rs
create mode 100644 src/bin/proxmox_backup_manager/notifications/mod.rs
create mode 100644 src/bin/proxmox_backup_manager/notifications/sendmail.rs
create mode 100644 src/bin/proxmox_backup_manager/notifications/smtp.rs
create mode 100644 src/bin/proxmox_backup_manager/notifications/targets.rs
delete mode 100644 src/server/email_notifications.rs
create mode 100644 src/server/notifications.rs
create mode 100644 templates/Makefile
create mode 100644 templates/default/acme-err-body.txt.hbs
create mode 100644 templates/default/acme-err-subject.txt.hbs
create mode 100644 templates/default/gc-err-body.txt.hbs
create mode 100644 templates/default/gc-err-subject.txt.hbs
create mode 100644 templates/default/gc-ok-body.txt.hbs
create mode 100644 templates/default/gc-ok-subject.txt.hbs
create mode 100644 templates/default/package-updates-body.txt.hbs
create mode 100644 templates/default/package-updates-subject.txt.hbs
create mode 100644 templates/default/prune-err-body.txt.hbs
create mode 100644 templates/default/prune-err-subject.txt.hbs
create mode 100644 templates/default/prune-ok-body.txt.hbs
create mode 100644 templates/default/prune-ok-subject.txt.hbs
create mode 100644 templates/default/sync-err-body.txt.hbs
create mode 100644 templates/default/sync-err-subject.txt.hbs
create mode 100644 templates/default/sync-ok-body.txt.hbs
create mode 100644 templates/default/sync-ok-subject.txt.hbs
create mode 100644 templates/default/tape-backup-err-body.txt.hbs
create mode 100644 templates/default/tape-backup-err-subject.txt.hbs
create mode 100644 templates/default/tape-backup-ok-body.txt.hbs
create mode 100644 templates/default/tape-backup-ok-subject.txt.hbs
create mode 100644 templates/default/tape-load-body.txt.hbs
create mode 100644 templates/default/tape-load-subject.txt.hbs
create mode 100644 templates/default/test-body.html.hbs
create mode 100644 templates/default/test-body.txt.hbs
create mode 100644 templates/default/test-subject.txt.hbs
create mode 100644 templates/default/verify-err-body.txt.hbs
create mode 100644 templates/default/verify-err-subject.txt.hbs
create mode 100644 templates/default/verify-ok-body.txt.hbs
create mode 100644 templates/default/verify-ok-subject.txt.hbs
create mode 100644 www/config/NotificationConfigView.js
Summary over all repositories:
106 files changed, 3175 insertions(+), 920 deletions(-)
--
Generated by git-murpp 0.7.1
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox v2 01/43] notify: expose `config` module
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 02/43] notify: use std::sync::OnceCell instead of lazy_static! Lukas Wagner
` (41 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
This is needed because we want to access CONFIG and PRIVATE_CONFIG
from the docgen helper in PBS.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
proxmox-notify/src/lib.rs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/proxmox-notify/src/lib.rs b/proxmox-notify/src/lib.rs
index 8d4dc63..68aa753 100644
--- a/proxmox-notify/src/lib.rs
+++ b/proxmox-notify/src/lib.rs
@@ -18,14 +18,13 @@ use matcher::{MatcherConfig, MATCHER_TYPENAME};
pub mod api;
pub mod context;
+pub mod config;
pub mod endpoints;
pub mod filter;
pub mod group;
pub mod renderer;
pub mod schema;
-mod config;
-
#[derive(Debug)]
pub enum Error {
/// There was an error serializing the config
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox v2 02/43] notify: use std::sync::OnceCell instead of lazy_static!
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 01/43] notify: expose `config` module Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 03/43] notify: pbs-context: exclude successful prunes in default matcher Lukas Wagner
` (40 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
proxmox-notify/Cargo.toml | 1 -
proxmox-notify/src/config.rs | 23 +++++++++++++++--------
proxmox-notify/src/lib.rs | 5 ++---
3 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/proxmox-notify/Cargo.toml b/proxmox-notify/Cargo.toml
index 797b1ac..3a97847 100644
--- a/proxmox-notify/Cargo.toml
+++ b/proxmox-notify/Cargo.toml
@@ -11,7 +11,6 @@ exclude.workspace = true
anyhow.workspace = true
const_format.workspace = true
handlebars = { workspace = true }
-lazy_static.workspace = true
lettre = { workspace = true, optional = true }
log.workspace = true
mail-parser = { workspace = true, optional = true }
diff --git a/proxmox-notify/src/config.rs b/proxmox-notify/src/config.rs
index fe25ea7..4445371 100644
--- a/proxmox-notify/src/config.rs
+++ b/proxmox-notify/src/config.rs
@@ -1,4 +1,4 @@
-use lazy_static::lazy_static;
+use std::sync::OnceLock;
use proxmox_schema::{ApiType, ObjectSchema};
use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin};
@@ -9,9 +9,16 @@ use crate::matcher::{MatcherConfig, MATCHER_TYPENAME};
use crate::schema::BACKEND_NAME_SCHEMA;
use crate::Error;
-lazy_static! {
- pub static ref CONFIG: SectionConfig = config_init();
- pub static ref PRIVATE_CONFIG: SectionConfig = private_config_init();
+/// Section config schema for the public config file.
+pub fn config_parser() -> &'static SectionConfig {
+ static CONFIG: OnceLock<SectionConfig> = OnceLock::new();
+ CONFIG.get_or_init(|| config_init())
+}
+
+/// Section config schema for the private config file.
+pub fn private_config_parser() -> &'static SectionConfig {
+ static CONFIG: OnceLock<SectionConfig> = OnceLock::new();
+ CONFIG.get_or_init(|| private_config_init())
}
fn config_init() -> SectionConfig {
@@ -108,7 +115,7 @@ fn private_config_init() -> SectionConfig {
pub fn config(raw_config: &str) -> Result<(SectionConfigData, [u8; 32]), Error> {
let digest = openssl::sha::sha256(raw_config.as_bytes());
- let mut data = CONFIG
+ let mut data = config_parser()
.parse("notifications.cfg", raw_config)
.map_err(|err| Error::ConfigDeserialization(err.into()))?;
@@ -139,20 +146,20 @@ pub fn config(raw_config: &str) -> Result<(SectionConfigData, [u8; 32]), Error>
pub fn private_config(raw_config: &str) -> Result<(SectionConfigData, [u8; 32]), Error> {
let digest = openssl::sha::sha256(raw_config.as_bytes());
- let data = PRIVATE_CONFIG
+ let data = private_config_parser()
.parse("priv/notifications.cfg", raw_config)
.map_err(|err| Error::ConfigDeserialization(err.into()))?;
Ok((data, digest))
}
pub fn write(config: &SectionConfigData) -> Result<String, Error> {
- CONFIG
+ config_parser()
.write("notifications.cfg", config)
.map_err(|err| Error::ConfigSerialization(err.into()))
}
pub fn write_private(config: &SectionConfigData) -> Result<String, Error> {
- PRIVATE_CONFIG
+ private_config_parser()
.write("priv/notifications.cfg", config)
.map_err(|err| Error::ConfigSerialization(err.into()))
}
diff --git a/proxmox-notify/src/lib.rs b/proxmox-notify/src/lib.rs
index 68aa753..b5829fd 100644
--- a/proxmox-notify/src/lib.rs
+++ b/proxmox-notify/src/lib.rs
@@ -13,12 +13,11 @@ use proxmox_section_config::SectionConfigData;
use proxmox_uuid::Uuid;
pub mod matcher;
-use crate::config::CONFIG;
use matcher::{MatcherConfig, MATCHER_TYPENAME};
pub mod api;
-pub mod context;
pub mod config;
+pub mod context;
pub mod endpoints;
pub mod filter;
pub mod group;
@@ -279,7 +278,7 @@ impl Config {
let default_config = context().default_config();
- let builtin_config = CONFIG
+ let builtin_config = config::config_parser()
.parse("<builtin>", default_config)
.map_err(|err| Error::ConfigDeserialization(err.into()))?;
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox v2 03/43] notify: pbs-context: exclude successful prunes in default matcher
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 01/43] notify: expose `config` module Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 02/43] notify: use std::sync::OnceCell instead of lazy_static! Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 04/43] notify: endpoints: matcher: improve descriptions for API types Lukas Wagner
` (39 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
PBS sends notifications for all events but successful prune jobs.
There we only care about errors.
This commit adapts the 'default-matcher' to reflect that behavior
as well.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
proxmox-notify/src/context/pbs.rs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/proxmox-notify/src/context/pbs.rs b/proxmox-notify/src/context/pbs.rs
index 299f685..2de305f 100644
--- a/proxmox-notify/src/context/pbs.rs
+++ b/proxmox-notify/src/context/pbs.rs
@@ -66,8 +66,11 @@ sendmail: mail-to-root
matcher: default-matcher
mode all
+ invert-match true
+ match-field exact:type=prune
+ match-severity info
target mail-to-root
- comment Route all notifications to mail-to-root
+ comment Route everything but successful prune job notifications to mail-to-root
";
#[derive(Debug)]
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox v2 04/43] notify: endpoints: matcher: improve descriptions for API types
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (2 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 03/43] notify: pbs-context: exclude successful prunes in default matcher Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 05/43] notify: sys: move 'email' module from proxmox_sys to proxmox_notify Lukas Wagner
` (38 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
proxmox-schema will automatically append text (e.g. 'Can be specified
more than once'), so we should end every comment with a '.'.
Also copy over some text from PVE docs, since these doc comments will
now be visible in the PBS documentation.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
proxmox-notify/src/endpoints/gotify.rs | 6 ++---
proxmox-notify/src/endpoints/sendmail.rs | 15 ++++++++-----
proxmox-notify/src/endpoints/smtp.rs | 28 +++++++++++++++---------
proxmox-notify/src/matcher.rs | 18 +++++++--------
4 files changed, 40 insertions(+), 27 deletions(-)
diff --git a/proxmox-notify/src/endpoints/gotify.rs b/proxmox-notify/src/endpoints/gotify.rs
index 70675c8..dc8326a 100644
--- a/proxmox-notify/src/endpoints/gotify.rs
+++ b/proxmox-notify/src/endpoints/gotify.rs
@@ -40,12 +40,12 @@ pub(crate) const GOTIFY_TYPENAME: &str = "gotify";
#[serde(rename_all = "kebab-case")]
/// Config for Gotify notification endpoints
pub struct GotifyConfig {
- /// Name of the endpoint
+ /// Name of the endpoint.
#[updater(skip)]
pub name: String,
- /// Gotify Server URL
+ /// Gotify Server URL.
pub server: String,
- /// Comment
+ /// Comment.
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
/// Deprecated.
diff --git a/proxmox-notify/src/endpoints/sendmail.rs b/proxmox-notify/src/endpoints/sendmail.rs
index 47901ef..da0c0cc 100644
--- a/proxmox-notify/src/endpoints/sendmail.rs
+++ b/proxmox-notify/src/endpoints/sendmail.rs
@@ -43,21 +43,26 @@ pub struct SendmailConfig {
/// Name of the endpoint
#[updater(skip)]
pub name: String,
- /// Mail recipients
+ /// Mail address to send a mail to.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[updater(serde(skip_serializing_if = "Option::is_none"))]
pub mailto: Vec<String>,
- /// Mail recipients
+ /// Users to send a mail to. The email address of the user
+ /// will be looked up in users.cfg.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[updater(serde(skip_serializing_if = "Option::is_none"))]
pub mailto_user: Vec<String>,
- /// `From` address for the mail
+ /// `From` address for sent E-Mails.
+ /// If the parameter is not set, the plugin will fall back to the
+ /// email-from setting from node.cfg (PBS).
+ /// If that is also not set, the plugin will default to root@$hostname,
+ /// where $hostname is the hostname of the node.
#[serde(skip_serializing_if = "Option::is_none")]
pub from_address: Option<String>,
- /// Author of the mail
+ /// Author of the mail. Defaults to 'Proxmox Backup Server ($hostname)'
#[serde(skip_serializing_if = "Option::is_none")]
pub author: Option<String>,
- /// Comment
+ /// Comment.
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
/// Deprecated.
diff --git a/proxmox-notify/src/endpoints/smtp.rs b/proxmox-notify/src/endpoints/smtp.rs
index f04583a..27afeba 100644
--- a/proxmox-notify/src/endpoints/smtp.rs
+++ b/proxmox-notify/src/endpoints/smtp.rs
@@ -66,33 +66,41 @@ pub enum SmtpMode {
#[serde(rename_all = "kebab-case")]
/// Config for Sendmail notification endpoints
pub struct SmtpConfig {
- /// Name of the endpoint
+ /// Name of the endpoint.
#[updater(skip)]
pub name: String,
- /// Host name or IP of the SMTP relay
+ /// Host name or IP of the SMTP relay.
pub server: String,
- /// Port to use when connecting to the SMTP relay
+ /// The port to connect to.
+ /// If not set, the used port defaults to 25 (insecure), 465 (tls)
+ /// or 587 (starttls), depending on the value of mode
#[serde(skip_serializing_if = "Option::is_none")]
pub port: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mode: Option<SmtpMode>,
- /// Username for authentication
+ /// Username to use during authentication.
+ /// If no username is set, no authentication will be performed.
+ /// The PLAIN and LOGIN authentication methods are supported
#[serde(skip_serializing_if = "Option::is_none")]
pub username: Option<String>,
- /// Mail recipients
+ /// Mail address to send a mail to.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[updater(serde(skip_serializing_if = "Option::is_none"))]
pub mailto: Vec<String>,
- /// Mail recipients
+ /// Users to send a mail to. The email address of the user
+ /// will be looked up in users.cfg.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[updater(serde(skip_serializing_if = "Option::is_none"))]
pub mailto_user: Vec<String>,
- /// `From` address for the mail
+ /// `From` address for the mail.
+ /// SMTP relays might require that this address is owned by the user
+ /// in order to avoid spoofing. The `From` header in the email will be
+ /// set to `$author <$from-address>`.
pub from_address: String,
- /// Author of the mail
+ /// Author of the mail. Defaults to 'Proxmox Backup Server ($hostname)'
#[serde(skip_serializing_if = "Option::is_none")]
pub author: Option<String>,
- /// Comment
+ /// Comment.
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
/// Disable this target.
@@ -136,7 +144,7 @@ pub struct SmtpPrivateConfig {
/// Name of the endpoint
#[updater(skip)]
pub name: String,
- /// Authentication token
+ /// The password to use during authentication.
#[serde(skip_serializing_if = "Option::is_none")]
pub password: Option<String>,
}
diff --git a/proxmox-notify/src/matcher.rs b/proxmox-notify/src/matcher.rs
index 2d30378..986deee 100644
--- a/proxmox-notify/src/matcher.rs
+++ b/proxmox-notify/src/matcher.rs
@@ -108,42 +108,42 @@ pub const MATCH_FIELD_ENTRY_SCHEMA: Schema = StringSchema::new("Match metadata f
#[serde(rename_all = "kebab-case")]
/// Config for Sendmail notification endpoints
pub struct MatcherConfig {
- /// Name of the matcher
+ /// Name of the matcher.
#[updater(skip)]
pub name: String,
- /// List of matched metadata fields
+ /// List of matched metadata fields.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[updater(serde(skip_serializing_if = "Option::is_none"))]
pub match_field: Vec<FieldMatcher>,
- /// List of matched severity levels
+ /// List of matched severity levels.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[updater(serde(skip_serializing_if = "Option::is_none"))]
pub match_severity: Vec<SeverityMatcher>,
- /// List of matched severity levels
+ /// List of matched severity levels.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[updater(serde(skip_serializing_if = "Option::is_none"))]
pub match_calendar: Vec<CalendarMatcher>,
- /// Decide if 'all' or 'any' match statements must match
+ /// Decide if 'all' or 'any' match statements must match.
#[serde(skip_serializing_if = "Option::is_none")]
pub mode: Option<MatchModeOperator>,
- /// Invert match of the whole filter
+ /// Invert match of the whole filter.
#[serde(skip_serializing_if = "Option::is_none")]
pub invert_match: Option<bool>,
- /// Targets to notify
+ /// Targets to notify.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[updater(serde(skip_serializing_if = "Option::is_none"))]
pub target: Vec<String>,
- /// Comment
+ /// Comment.
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
- /// Disable this matcher
+ /// Disable this matcher.
#[serde(skip_serializing_if = "Option::is_none")]
pub disable: Option<bool>,
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox v2 05/43] notify: sys: move 'email' module from proxmox_sys to proxmox_notify
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (3 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 04/43] notify: endpoints: matcher: improve descriptions for API types Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 06/43] notify: add getter for notification timestamp Lukas Wagner
` (37 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
Now that PBS stopped using the proxmox_sys::email module due to the
switch to proxmox_notify, we can move the email module to
proxmox_notify to make the proxmox_sys crate a bit leaner.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
proxmox-notify/Cargo.toml | 3 ++-
proxmox-notify/src/endpoints/common/mod.rs | 3 +++
.../src/endpoints/common/sendmail_impl.rs | 10 ++++++----
proxmox-notify/src/endpoints/sendmail.rs | 5 +++--
proxmox-sys/src/lib.rs | 1 -
5 files changed, 14 insertions(+), 8 deletions(-)
rename proxmox-sys/src/email.rs => proxmox-notify/src/endpoints/common/sendmail_impl.rs (96%)
diff --git a/proxmox-notify/Cargo.toml b/proxmox-notify/Cargo.toml
index 3a97847..0156fe6 100644
--- a/proxmox-notify/Cargo.toml
+++ b/proxmox-notify/Cargo.toml
@@ -9,6 +9,7 @@ exclude.workspace = true
[dependencies]
anyhow.workspace = true
+base64 = { workspace = true, optional = true }
const_format.workspace = true
handlebars = { workspace = true }
lettre = { workspace = true, optional = true }
@@ -32,7 +33,7 @@ proxmox-uuid = { workspace = true, features = ["serde"] }
[features]
default = ["sendmail", "gotify", "smtp"]
mail-forwarder = ["dep:mail-parser", "dep:proxmox-sys"]
-sendmail = ["dep:proxmox-sys"]
+sendmail = ["dep:base64"]
gotify = ["dep:proxmox-http"]
pve-context = ["dep:proxmox-sys"]
pbs-context = ["dep:proxmox-sys"]
diff --git a/proxmox-notify/src/endpoints/common/mod.rs b/proxmox-notify/src/endpoints/common/mod.rs
index 60e0761..561b138 100644
--- a/proxmox-notify/src/endpoints/common/mod.rs
+++ b/proxmox-notify/src/endpoints/common/mod.rs
@@ -1,2 +1,5 @@
#[cfg(any(feature = "sendmail", feature = "smtp"))]
pub(crate) mod mail;
+
+#[cfg(feature = "sendmail")]
+pub(crate) mod sendmail_impl;
diff --git a/proxmox-sys/src/email.rs b/proxmox-notify/src/endpoints/common/sendmail_impl.rs
similarity index 96%
rename from proxmox-sys/src/email.rs
rename to proxmox-notify/src/endpoints/common/sendmail_impl.rs
index 85d171d..1499400 100644
--- a/proxmox-sys/src/email.rs
+++ b/proxmox-notify/src/endpoints/common/sendmail_impl.rs
@@ -3,14 +3,14 @@
use std::io::Write;
use std::process::{Command, Stdio};
-use anyhow::{bail, format_err, Error};
+use anyhow::{bail, Error};
/// Sends multi-part mail with text and/or html to a list of recipients
///
/// Includes the header `Auto-Submitted: auto-generated`, so that auto-replies
/// (i.e. OOO replies) won't trigger.
/// ``sendmail`` is used for sending the mail.
-pub fn sendmail(
+pub(crate) fn sendmail(
mailto: &[&str],
subject: &str,
text: Option<&str>,
@@ -114,12 +114,14 @@ pub fn sendmail(
///
/// ``sendmail`` is used for sending the mail, thus `message` must be
/// compatible with that (the message is piped into stdin unmodified).
-pub fn forward(
+#[cfg(feature = "mail-forwarder")]
+pub(crate) fn forward(
mailto: &[&str],
mailfrom: &str,
message: &[u8],
uid: Option<u32>,
) -> Result<(), Error> {
+ use anyhow::format_err;
use std::os::unix::process::CommandExt;
if mailto.is_empty() {
@@ -162,7 +164,7 @@ pub fn forward(
#[cfg(test)]
mod test {
- use crate::email::sendmail;
+ use super::*;
#[test]
fn email_without_recipients() {
diff --git a/proxmox-notify/src/endpoints/sendmail.rs b/proxmox-notify/src/endpoints/sendmail.rs
index da0c0cc..a8efd32 100644
--- a/proxmox-notify/src/endpoints/sendmail.rs
+++ b/proxmox-notify/src/endpoints/sendmail.rs
@@ -4,6 +4,7 @@ use proxmox_schema::api_types::COMMENT_SCHEMA;
use proxmox_schema::{api, Updater};
use crate::context;
+use crate::endpoints::common;
use crate::endpoints::common::mail;
use crate::renderer::TemplateType;
use crate::schema::{EMAIL_SCHEMA, ENTITY_NAME_SCHEMA, USER_SCHEMA};
@@ -133,7 +134,7 @@ impl Endpoint for SendmailEndpoint {
.clone()
.unwrap_or_else(|| context().default_sendmail_author());
- proxmox_sys::email::sendmail(
+ common::sendmail_impl::sendmail(
&recipients_str,
&subject,
Some(&text_part),
@@ -145,7 +146,7 @@ impl Endpoint for SendmailEndpoint {
}
#[cfg(feature = "mail-forwarder")]
Content::ForwardedMail { raw, uid, .. } => {
- proxmox_sys::email::forward(&recipients_str, &mailfrom, raw, *uid)
+ common::sendmail_impl::forward(&recipients_str, &mailfrom, raw, *uid)
.map_err(|err| Error::NotifyFailed(self.config.name.clone(), err.into()))
}
}
diff --git a/proxmox-sys/src/lib.rs b/proxmox-sys/src/lib.rs
index 8ea7073..e0c14ba 100644
--- a/proxmox-sys/src/lib.rs
+++ b/proxmox-sys/src/lib.rs
@@ -4,7 +4,6 @@ pub mod boot_mode;
pub mod command;
#[cfg(feature = "crypt")]
pub mod crypt;
-pub mod email;
pub mod error;
pub mod fd;
pub mod fs;
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox v2 06/43] notify: add getter for notification timestamp
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (4 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 05/43] notify: sys: move 'email' module from proxmox_sys to proxmox_notify Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH widget-toolkit v2 07/43] sendmail: smtp: allow to overide default mail author Lukas Wagner
` (36 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
proxmox-notify/src/lib.rs | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/proxmox-notify/src/lib.rs b/proxmox-notify/src/lib.rs
index b5829fd..a5caee3 100644
--- a/proxmox-notify/src/lib.rs
+++ b/proxmox-notify/src/lib.rs
@@ -260,6 +260,11 @@ impl Notification {
pub fn id(&self) -> &Uuid {
&self.id
}
+
+ /// Return the notification's timestamp
+ pub fn timestamp(&self) -> i64 {
+ self.metadata.timestamp
+ }
}
/// Notification configuration
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH widget-toolkit v2 07/43] sendmail: smtp: allow to overide default mail author
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (5 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 06/43] notify: add getter for notification timestamp Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 08/43] pbs-config: add module for loading notification config Lukas Wagner
` (35 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
In PBS, we obviously don't have "Proxmox VE" as a default sender, so
we need a mechanism to change the default author.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/Schema.js | 9 +++++++++
src/panel/SendmailEditPanel.js | 2 +-
src/panel/SmtpEditPanel.js | 2 +-
src/window/EndpointEditBase.js | 1 +
4 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/Schema.js b/src/Schema.js
index 7833fc0..42541e0 100644
--- a/src/Schema.js
+++ b/src/Schema.js
@@ -52,11 +52,13 @@ Ext.define('Proxmox.Schema', { // a singleton
name: 'Sendmail',
ipanel: 'pmxSendmailEditPanel',
iconCls: 'fa-envelope-o',
+ defaultMailAuthor: 'Proxmox VE',
},
smtp: {
name: 'SMTP',
ipanel: 'pmxSmtpEditPanel',
iconCls: 'fa-envelope-o',
+ defaultMailAuthor: 'Proxmox VE',
},
gotify: {
name: 'Gotify',
@@ -65,6 +67,13 @@ Ext.define('Proxmox.Schema', { // a singleton
},
},
+ // to add or change existing for product specific ones
+ overrideEndpointTypes: function(extra) {
+ for (const [key, value] of Object.entries(extra)) {
+ Proxmox.Schema.notificationEndpointTypes[key] = value;
+ }
+ },
+
pxarFileTypes: {
b: { icon: 'cube', label: gettext('Block Device') },
c: { icon: 'tty', label: gettext('Character Device') },
diff --git a/src/panel/SendmailEditPanel.js b/src/panel/SendmailEditPanel.js
index 5a154c1..ccdfe98 100644
--- a/src/panel/SendmailEditPanel.js
+++ b/src/panel/SendmailEditPanel.js
@@ -58,8 +58,8 @@ Ext.define('Proxmox.panel.SendmailEditPanel', {
fieldLabel: gettext('Author'),
name: 'author',
allowBlank: true,
- emptyText: 'Proxmox VE',
cbind: {
+ emptyText: '{defaultMailAuthor}',
deleteEmpty: '{!isCreate}',
},
},
diff --git a/src/panel/SmtpEditPanel.js b/src/panel/SmtpEditPanel.js
index 8b258e0..edb6344 100644
--- a/src/panel/SmtpEditPanel.js
+++ b/src/panel/SmtpEditPanel.js
@@ -161,8 +161,8 @@ Ext.define('Proxmox.panel.SmtpEditPanel', {
fieldLabel: gettext('Author'),
name: 'author',
allowBlank: true,
- emptyText: gettext('Proxmox VE'),
cbind: {
+ emptyText: '{defaultMailAuthor}',
deleteEmpty: '{!isCreate}',
},
},
diff --git a/src/window/EndpointEditBase.js b/src/window/EndpointEditBase.js
index f42d0ea..993fa16 100644
--- a/src/window/EndpointEditBase.js
+++ b/src/window/EndpointEditBase.js
@@ -45,6 +45,7 @@ Ext.define('Proxmox.window.EndpointEditBase', {
isCreate: me.isCreate,
baseUrl: me.baseUrl,
type: me.type,
+ defaultMailAuthor: endpointConfig.defaultMailAuthor,
}],
});
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 08/43] pbs-config: add module for loading notification config
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (6 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH widget-toolkit v2 07/43] sendmail: smtp: allow to overide default mail author Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 09/43] server: rename email_notifications module to notifications Lukas Wagner
` (34 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
Cargo.toml | 3 +++
pbs-config/Cargo.toml | 1 +
pbs-config/src/lib.rs | 1 +
pbs-config/src/notifications.rs | 41 +++++++++++++++++++++++++++++++++
4 files changed, 46 insertions(+)
create mode 100644 pbs-config/src/notifications.rs
diff --git a/Cargo.toml b/Cargo.toml
index 4616e476..f06aeba3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -65,6 +65,7 @@ proxmox-io = "1.0.1" # tools and client use "tokio" feature
proxmox-lang = "1.1"
proxmox-ldap = "0.2.1"
proxmox-metrics = "0.3"
+proxmox-notify = "0.3"
proxmox-openid = "0.10.0"
proxmox-rest-server = { version = "0.5.1", features = [ "templates" ] }
# some use "cli", some use "cli" and "server", pbs-config uses nothing
@@ -211,6 +212,7 @@ proxmox-io.workspace = true
proxmox-lang.workspace = true
proxmox-ldap.workspace = true
proxmox-metrics.workspace = true
+proxmox-notify = { workspace = true, features = [ "pbs-context" ] }
proxmox-openid.workspace = true
proxmox-rest-server = { workspace = true, features = [ "rate-limited-stream" ] }
proxmox-router = { workspace = true, features = [ "cli", "server"] }
@@ -257,6 +259,7 @@ proxmox-rrd.workspace = true
#proxmox-lang = { path = "../proxmox/proxmox-lang" }
#proxmox-ldap = { path = "../proxmox/proxmox-ldap" }
#proxmox-metrics = { path = "../proxmox/proxmox-metrics" }
+#proxmox-notify = { path = "../proxmox/proxmox-notify" }
#proxmox-openid = { path = "../proxmox/proxmox-openid" }
#proxmox-rest-server = { path = "../proxmox/proxmox-rest-server" }
#proxmox-router = { path = "../proxmox/proxmox-router" }
diff --git a/pbs-config/Cargo.toml b/pbs-config/Cargo.toml
index d11cd41e..ac639a8e 100644
--- a/pbs-config/Cargo.toml
+++ b/pbs-config/Cargo.toml
@@ -17,6 +17,7 @@ regex.workspace = true
serde.workspace = true
serde_json.workspace = true
+proxmox-notify.workspace = true
proxmox-router = { workspace = true, default-features = false }
proxmox-schema.workspace = true
proxmox-section-config.workspace = true
diff --git a/pbs-config/src/lib.rs b/pbs-config/src/lib.rs
index 3cfdb2a1..20a8238d 100644
--- a/pbs-config/src/lib.rs
+++ b/pbs-config/src/lib.rs
@@ -7,6 +7,7 @@ pub mod drive;
pub mod media_pool;
pub mod metrics;
pub mod network;
+pub mod notifications;
pub mod prune;
pub mod remote;
pub mod sync;
diff --git a/pbs-config/src/notifications.rs b/pbs-config/src/notifications.rs
new file mode 100644
index 00000000..df327346
--- /dev/null
+++ b/pbs-config/src/notifications.rs
@@ -0,0 +1,41 @@
+use anyhow::Error;
+
+use proxmox_notify::Config;
+
+use pbs_buildcfg::configdir;
+
+use crate::{open_backup_lockfile, BackupLockGuard};
+
+/// Configuration file location for notification targets/matchers.
+pub const NOTIFICATION_CONFIG_PATH: &str = configdir!("/notifications.cfg");
+
+/// Private configuration file location for secrets - only readable by `root`.
+pub const NOTIFICATION_PRIV_CONFIG_PATH: &str = configdir!("/notifications-priv.cfg");
+
+/// Lockfile to prevent concurrent write access.
+pub const NOTIFICATION_LOCK_FILE: &str = configdir!("/.notifications.lck");
+
+/// Get exclusive lock for `notifications.cfg`
+pub fn lock_config() -> Result<BackupLockGuard, Error> {
+ open_backup_lockfile(NOTIFICATION_LOCK_FILE, None, true)
+}
+
+/// Load notification config.
+pub fn config() -> Result<Config, Error> {
+ let content =
+ proxmox_sys::fs::file_read_optional_string(NOTIFICATION_CONFIG_PATH)?.unwrap_or_default();
+
+ let priv_content = proxmox_sys::fs::file_read_optional_string(NOTIFICATION_PRIV_CONFIG_PATH)?
+ .unwrap_or_default();
+
+ Ok(Config::new(&content, &priv_content)?)
+}
+
+/// Save notification config.
+pub fn save_config(config: Config) -> Result<(), Error> {
+ let (cfg, priv_cfg) = config.write()?;
+ crate::replace_backup_config(NOTIFICATION_CONFIG_PATH, cfg.as_bytes())?;
+ crate::replace_secret_config(NOTIFICATION_PRIV_CONFIG_PATH, priv_cfg.as_bytes())?;
+
+ Ok(())
+}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 09/43] server: rename email_notifications module to notifications
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (7 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 08/43] pbs-config: add module for loading notification config Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 10/43] notifications: allow sending notifications via proxmox_notify Lukas Wagner
` (33 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
The module will be extended to interact with the proxmox_notify crate,
hence the name change seems to be in order.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
src/server/mod.rs | 4 ++--
src/server/{email_notifications.rs => notifications.rs} | 0
2 files changed, 2 insertions(+), 2 deletions(-)
rename src/server/{email_notifications.rs => notifications.rs} (100%)
diff --git a/src/server/mod.rs b/src/server/mod.rs
index 4e3b68ac..d2cbc931 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -25,8 +25,8 @@ pub use gc_job::*;
mod realm_sync_job;
pub use realm_sync_job::*;
-mod email_notifications;
-pub use email_notifications::*;
+pub mod notifications;
+pub use notifications::*;
mod report;
pub use report::*;
diff --git a/src/server/email_notifications.rs b/src/server/notifications.rs
similarity index 100%
rename from src/server/email_notifications.rs
rename to src/server/notifications.rs
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 10/43] notifications: allow sending notifications via proxmox_notify
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (8 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 09/43] server: rename email_notifications module to notifications Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 11/43] buildsys: install templates for test notifications Lukas Wagner
` (32 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
- Set the context in proxmox_notify
- Add helper function which queues notifications to a spool
directory
- Set up a worker task, running in the privileged process, which
periodically checks the spool directory for queued notifications
The queuing is needed because on PBS we send most if not all
notifications from the proxy-process running as the `backup` user.
However, to have access to the protected passwords/tokens for various
notification endpoints, we need to read the notification config as
root.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/bin/proxmox-backup-api.rs | 11 ++++
src/bin/proxmox-backup-proxy.rs | 1 +
src/server/notifications.rs | 107 +++++++++++++++++++++++++++++++-
3 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/src/bin/proxmox-backup-api.rs b/src/bin/proxmox-backup-api.rs
index e46557a0..d5ce9f3b 100644
--- a/src/bin/proxmox-backup-api.rs
+++ b/src/bin/proxmox-backup-api.rs
@@ -56,6 +56,7 @@ async fn run() -> Result<(), Error> {
proxmox_backup::server::create_state_dir()?;
proxmox_backup::server::create_active_operations_dir()?;
proxmox_backup::server::jobstate::create_jobstate_dir()?;
+ proxmox_backup::server::notifications::create_spool_dir()?;
proxmox_backup::tape::create_tape_status_dir()?;
proxmox_backup::tape::create_drive_state_dir()?;
proxmox_backup::tape::create_changer_state_dir()?;
@@ -72,6 +73,7 @@ async fn run() -> Result<(), Error> {
let _ = csrf_secret(); // load with lazy_static
proxmox_backup::auth_helpers::setup_auth_context(true);
+ proxmox_backup::server::notifications::init()?;
let backup_user = pbs_config::backup_user()?;
let mut command_sock = proxmox_rest_server::CommandSocket::new(
@@ -153,6 +155,8 @@ async fn run() -> Result<(), Error> {
std::thread::sleep(std::time::Duration::from_secs(3));
});
+ start_notification_worker();
+
server.await?;
log::info!("server shutting down, waiting for active workers to complete");
proxmox_rest_server::last_worker_future().await?;
@@ -161,3 +165,10 @@ async fn run() -> Result<(), Error> {
Ok(())
}
+
+fn start_notification_worker() {
+ let abort_future = proxmox_rest_server::shutdown_future();
+ let future = Box::pin(proxmox_backup::server::notifications::notification_worker());
+ let task = futures::future::select(future, abort_future);
+ tokio::spawn(task);
+}
diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs
index f79ec2f5..15444685 100644
--- a/src/bin/proxmox-backup-proxy.rs
+++ b/src/bin/proxmox-backup-proxy.rs
@@ -198,6 +198,7 @@ async fn run() -> Result<(), Error> {
}
proxmox_backup::auth_helpers::setup_auth_context(false);
+ proxmox_backup::server::notifications::init()?;
let rrd_cache = initialize_rrd_cache()?;
rrd_cache.apply_journal()?;
diff --git a/src/server/notifications.rs b/src/server/notifications.rs
index 43b55656..9fb202d8 100644
--- a/src/server/notifications.rs
+++ b/src/server/notifications.rs
@@ -1,20 +1,29 @@
use anyhow::Error;
-use serde_json::json;
+use const_format::concatcp;
+use serde_json::{json, Value};
+use std::collections::HashMap;
+use std::path::Path;
+use std::time::{Duration, Instant};
use handlebars::{
Context, Handlebars, Helper, HelperResult, Output, RenderContext, RenderError, TemplateError,
};
+use nix::unistd::Uid;
use proxmox_human_byte::HumanByte;
use proxmox_lang::try_block;
+use proxmox_notify::context::pbs::PBS_CONTEXT;
use proxmox_schema::ApiType;
use proxmox_sys::email::sendmail;
+use proxmox_sys::fs::{create_path, CreateOptions};
use pbs_api_types::{
APTUpdateInfo, DataStoreConfig, DatastoreNotify, GarbageCollectionStatus, Notify,
SyncJobConfig, TapeBackupJobSetup, User, Userid, VerificationJobConfig,
};
+use proxmox_notify::{Notification, Severity};
+const SPOOL_DIR: &str = concatcp!(pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR, "/notifications");
const GC_OK_TEMPLATE: &str = r###"
Datastore: {{datastore}}
@@ -283,6 +292,102 @@ lazy_static::lazy_static! {
};
}
+/// Initialize the notification system by setting context in proxmox_notify
+pub fn init() -> Result<(), Error> {
+ proxmox_notify::context::set_context(&PBS_CONTEXT);
+ Ok(())
+}
+
+/// Create the directory which will be used to temporarily store notifications
+/// which were sent from an unprivileged process.
+pub fn create_spool_dir() -> Result<(), Error> {
+ let backup_user = pbs_config::backup_user()?;
+ let opts = CreateOptions::new()
+ .owner(backup_user.uid)
+ .group(backup_user.gid);
+
+ create_path(SPOOL_DIR, None, Some(opts))?;
+ Ok(())
+}
+
+async fn send_queued_notifications() -> Result<(), Error> {
+ let mut read_dir = tokio::fs::read_dir(SPOOL_DIR).await?;
+
+ let mut notifications = Vec::new();
+
+ while let Some(entry) = read_dir.next_entry().await? {
+ let path = entry.path();
+
+ if let Some(ext) = path.extension() {
+ if ext == "json" {
+ let p = path.clone();
+
+ let bytes = tokio::fs::read(p).await?;
+ let notification: Notification = serde_json::from_slice(&bytes)?;
+ notifications.push(notification);
+
+ // Currently, there is no retry-mechanism in case of failure...
+ // For retries, we'd have to keep track of which targets succeeded/failed
+ // to send, so we do not retry notifying a target which succeeded before.
+ tokio::fs::remove_file(path).await?;
+ }
+ }
+ }
+
+ // Make sure that we send the oldest notification first
+ notifications.sort_unstable_by_key(|n| n.timestamp());
+
+ let res = tokio::task::spawn_blocking(move || {
+ let config = pbs_config::notifications::config()?;
+ for notification in notifications {
+ if let Err(err) = proxmox_notify::api::common::send(&config, ¬ification) {
+ log::error!("failed to send notification: {err}");
+ }
+ }
+
+ Ok::<(), Error>(())
+ })
+ .await?;
+
+ if let Err(e) = res {
+ log::error!("could not read notification config: {e}");
+ }
+
+ Ok::<(), Error>(())
+}
+
+/// Worker task to periodically send any queued notifications.
+pub async fn notification_worker() {
+ loop {
+ let delay_target = Instant::now() + Duration::from_secs(5);
+
+ if let Err(err) = send_queued_notifications().await {
+ log::error!("notification worker task error: {err}");
+ }
+
+ tokio::time::sleep_until(tokio::time::Instant::from_std(delay_target)).await;
+ }
+}
+
+fn send_notification(notification: Notification) -> Result<(), Error> {
+ if nix::unistd::ROOT == Uid::current() {
+ let config = pbs_config::notifications::config()?;
+ proxmox_notify::api::common::send(&config, ¬ification)?;
+ } else {
+ let ser = serde_json::to_vec(¬ification)?;
+ let path = Path::new(SPOOL_DIR).join(format!("{id}.json", id = notification.id()));
+
+ let backup_user = pbs_config::backup_user()?;
+ let opts = CreateOptions::new()
+ .owner(backup_user.uid)
+ .group(backup_user.gid);
+ proxmox_sys::fs::replace_file(path, &ser, opts, true)?;
+ log::info!("queued notification (id={id})", id = notification.id())
+ }
+
+ Ok(())
+}
+
/// Summary of a successful Tape Job
#[derive(Default)]
pub struct TapeBackupJobSummary {
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 11/43] buildsys: install templates for test notifications
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (9 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 10/43] notifications: allow sending notifications via proxmox_notify Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 12/43] pbs-config: acl: add /system/notifications as known ACL path Lukas Wagner
` (31 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
The notification stack loads handlebar templates for notifications
from /usr/share/proxmox-backup-server/templates/default/. This commit
modifies the build system to install template files from the
'templates' directory at that location. First, we only have templates
for test notifications.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
Makefile | 5 +++--
debian/proxmox-backup-server.install | 3 +++
templates/Makefile | 15 +++++++++++++++
templates/default/test-body.html.hbs | 1 +
templates/default/test-body.txt.hbs | 1 +
templates/default/test-subject.txt.hbs | 1 +
6 files changed, 24 insertions(+), 2 deletions(-)
create mode 100644 templates/Makefile
create mode 100644 templates/default/test-body.html.hbs
create mode 100644 templates/default/test-body.txt.hbs
create mode 100644 templates/default/test-subject.txt.hbs
diff --git a/Makefile b/Makefile
index 0317dd5e..03e93876 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ include defines.mk
PACKAGE := proxmox-backup
ARCH := $(DEB_BUILD_ARCH)
-SUBDIRS := etc www docs
+SUBDIRS := etc www docs templates
# Binaries usable by users
USR_BIN := \
@@ -93,7 +93,7 @@ build:
cp -a debian \
Cargo.toml src \
$(SUBCRATES) \
- docs etc examples tests www zsh-completions \
+ docs etc examples tests www zsh-completions templates \
defines.mk Makefile \
./build/
rm -f build/Cargo.lock
@@ -211,6 +211,7 @@ install: $(COMPILED_BINS)
install -m755 $(COMPILEDIR)/$(i) $(DESTDIR)$(LIBEXECDIR)/proxmox-backup/ ;)
$(MAKE) -C www install
$(MAKE) -C docs install
+ $(MAKE) -C templates install
.PHONY: upload
upload: UPLOAD_DIST ?= $(DEB_DISTRIBUTION)
diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install
index ee114ea3..6aff594d 100644
--- a/debian/proxmox-backup-server.install
+++ b/debian/proxmox-backup-server.install
@@ -41,3 +41,6 @@ usr/share/zsh/vendor-completions/_pmtx
usr/share/zsh/vendor-completions/_proxmox-backup-debug
usr/share/zsh/vendor-completions/_proxmox-backup-manager
usr/share/zsh/vendor-completions/_proxmox-tape
+usr/share/proxmox-backup/templates/default/test-body.txt.hbs
+usr/share/proxmox-backup/templates/default/test-body.html.hbs
+usr/share/proxmox-backup/templates/default/test-subject.txt.hbs
diff --git a/templates/Makefile b/templates/Makefile
new file mode 100644
index 00000000..b35a8bb3
--- /dev/null
+++ b/templates/Makefile
@@ -0,0 +1,15 @@
+include ../defines.mk
+
+NOTIFICATION_TEMPLATES= \
+ default/test-body.txt.hbs \
+ default/test-body.html.hbs \
+ default/test-subject.txt.hbs \
+
+all:
+
+clean:
+
+install:
+ install -dm755 $(DESTDIR)$(DATAROOTDIR)/proxmox-backup/templates/default
+ $(foreach i,$(NOTIFICATION_TEMPLATES), \
+ install -m644 $(i) $(DESTDIR)$(DATAROOTDIR)/proxmox-backup/templates/$(i) ;)
diff --git a/templates/default/test-body.html.hbs b/templates/default/test-body.html.hbs
new file mode 100644
index 00000000..26a43dde
--- /dev/null
+++ b/templates/default/test-body.html.hbs
@@ -0,0 +1 @@
+This is a test of the notification target '{{ target }}'.
diff --git a/templates/default/test-body.txt.hbs b/templates/default/test-body.txt.hbs
new file mode 100644
index 00000000..26a43dde
--- /dev/null
+++ b/templates/default/test-body.txt.hbs
@@ -0,0 +1 @@
+This is a test of the notification target '{{ target }}'.
diff --git a/templates/default/test-subject.txt.hbs b/templates/default/test-subject.txt.hbs
new file mode 100644
index 00000000..cb8e1320
--- /dev/null
+++ b/templates/default/test-subject.txt.hbs
@@ -0,0 +1 @@
+Test notification
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 12/43] pbs-config: acl: add /system/notifications as known ACL path
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (10 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 11/43] buildsys: install templates for test notifications Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 13/43] api: add endpoints for querying/testing notification targets Lukas Wagner
` (30 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
This one will be used for configuring the new notification stack.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
pbs-config/src/acl.rs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pbs-config/src/acl.rs b/pbs-config/src/acl.rs
index a0354a05..f78d69cd 100644
--- a/pbs-config/src/acl.rs
+++ b/pbs-config/src/acl.rs
@@ -100,7 +100,8 @@ pub fn check_acl_path(path: &str) -> Result<(), Error> {
return Ok(());
}
match components[1] {
- "certificates" | "disks" | "log" | "status" | "tasks" | "time" => {
+ "certificates" | "disks" | "log" | "notifications" | "status" | "tasks"
+ | "time" => {
if components_len == 2 {
return Ok(());
}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 13/43] api: add endpoints for querying/testing notification targets
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (11 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 12/43] pbs-config: acl: add /system/notifications as known ACL path Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 14/43] api: add endpoints for notification matchers Lukas Wagner
` (29 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
These endpoints require Sys.Audit permissions on
/system/notifications.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
src/api2/config/mod.rs | 2 +
src/api2/config/notifications/mod.rs | 12 +++++
src/api2/config/notifications/targets.rs | 63 ++++++++++++++++++++++++
3 files changed, 77 insertions(+)
create mode 100644 src/api2/config/notifications/mod.rs
create mode 100644 src/api2/config/notifications/targets.rs
diff --git a/src/api2/config/mod.rs b/src/api2/config/mod.rs
index 6cfeaea1..15dc5db9 100644
--- a/src/api2/config/mod.rs
+++ b/src/api2/config/mod.rs
@@ -11,6 +11,7 @@ pub mod datastore;
pub mod drive;
pub mod media_pool;
pub mod metrics;
+pub mod notifications;
pub mod prune;
pub mod remote;
pub mod sync;
@@ -28,6 +29,7 @@ const SUBDIRS: SubdirMap = &sorted!([
("drive", &drive::ROUTER),
("media-pool", &media_pool::ROUTER),
("metrics", &metrics::ROUTER),
+ ("notifications", ¬ifications::ROUTER),
("prune", &prune::ROUTER),
("remote", &remote::ROUTER),
("sync", &sync::ROUTER),
diff --git a/src/api2/config/notifications/mod.rs b/src/api2/config/notifications/mod.rs
new file mode 100644
index 00000000..f75e3910
--- /dev/null
+++ b/src/api2/config/notifications/mod.rs
@@ -0,0 +1,12 @@
+use proxmox_router::list_subdirs_api_method;
+use proxmox_router::{Router, SubdirMap};
+use proxmox_sortable_macro::sortable;
+
+mod targets;
+
+#[sortable]
+const SUBDIRS: SubdirMap = &sorted!([("targets", &targets::ROUTER),]);
+
+pub const ROUTER: Router = Router::new()
+ .get(&list_subdirs_api_method!(SUBDIRS))
+ .subdirs(SUBDIRS);
diff --git a/src/api2/config/notifications/targets.rs b/src/api2/config/notifications/targets.rs
new file mode 100644
index 00000000..6c5017b0
--- /dev/null
+++ b/src/api2/config/notifications/targets.rs
@@ -0,0 +1,63 @@
+use anyhow::Error;
+use serde_json::Value;
+
+use proxmox_notify::api::Target;
+use proxmox_notify::schema::ENTITY_NAME_SCHEMA;
+use proxmox_router::{list_subdirs_api_method, Permission, Router, RpcEnvironment, SubdirMap};
+use proxmox_schema::api;
+use proxmox_sortable_macro::sortable;
+
+use pbs_api_types::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
+
+#[api(
+ protected: true,
+ input: {
+ properties: {},
+ },
+ returns: {
+ description: "List of all entities which can be used as notification targets.",
+ type: Array,
+ items: { type: Target },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// List all notification targets.
+pub fn list_targets(_param: Value, _rpcenv: &mut dyn RpcEnvironment) -> Result<Vec<Target>, Error> {
+ let config = pbs_config::notifications::config()?;
+ let targets = proxmox_notify::api::get_targets(&config)?;
+
+ Ok(targets)
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ },
+ }
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Test a given notification target.
+pub fn test_target(name: String, _rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
+ let config = pbs_config::notifications::config()?;
+ proxmox_notify::api::common::test_target(&config, &name)?;
+ Ok(())
+}
+
+#[sortable]
+const SUBDIRS: SubdirMap = &sorted!([("test", &TEST_ROUTER),]);
+const TEST_ROUTER: Router = Router::new().post(&API_METHOD_TEST_TARGET);
+const ITEM_ROUTER: Router = Router::new()
+ .get(&list_subdirs_api_method!(SUBDIRS))
+ .subdirs(SUBDIRS);
+
+pub const ROUTER: Router = Router::new()
+ .get(&API_METHOD_LIST_TARGETS)
+ .match_all("name", &ITEM_ROUTER);
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 14/43] api: add endpoints for notification matchers
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (12 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 13/43] api: add endpoints for querying/testing notification targets Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 15/43] api: add endpoints for sendmail targets Lukas Wagner
` (28 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
These endpoints require Sys.Audit/Sys.Modify permissions on
/system/notifications.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
src/api2/config/notifications/matchers.rs | 170 ++++++++++++++++++++++
src/api2/config/notifications/mod.rs | 6 +-
2 files changed, 175 insertions(+), 1 deletion(-)
create mode 100644 src/api2/config/notifications/matchers.rs
diff --git a/src/api2/config/notifications/matchers.rs b/src/api2/config/notifications/matchers.rs
new file mode 100644
index 00000000..fba1859c
--- /dev/null
+++ b/src/api2/config/notifications/matchers.rs
@@ -0,0 +1,170 @@
+use anyhow::Error;
+use serde_json::Value;
+
+use proxmox_notify::matcher::{DeleteableMatcherProperty, MatcherConfig, MatcherConfigUpdater};
+use proxmox_notify::schema::ENTITY_NAME_SCHEMA;
+use proxmox_router::{Permission, Router, RpcEnvironment};
+use proxmox_schema::api;
+
+use pbs_api_types::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, PROXMOX_CONFIG_DIGEST_SCHEMA};
+
+#[api(
+ protected: true,
+ input: {
+ properties: {},
+ },
+ returns: {
+ description: "List of matchers.",
+ type: Array,
+ items: { type: MatcherConfig },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// List all notification matchers.
+pub fn list_matchers(
+ _param: Value,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<MatcherConfig>, Error> {
+ let config = pbs_config::notifications::config()?;
+
+ let matchers = proxmox_notify::api::matcher::get_matchers(&config)?;
+
+ Ok(matchers)
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ }
+ },
+ },
+ returns: { type: MatcherConfig },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// Get a notification matcher.
+pub fn get_matcher(name: String, rpcenv: &mut dyn RpcEnvironment) -> Result<MatcherConfig, Error> {
+ let config = pbs_config::notifications::config()?;
+ let matcher = proxmox_notify::api::matcher::get_matcher(&config, &name)?;
+
+ rpcenv["digest"] = hex::encode(config.digest()).into();
+
+ Ok(matcher)
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ matcher: {
+ type: MatcherConfig,
+ flatten: true,
+ }
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Add a new notification matcher.
+pub fn add_matcher(matcher: MatcherConfig, _rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+
+ proxmox_notify::api::matcher::add_matcher(&mut config, matcher)?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ },
+ updater: {
+ type: MatcherConfigUpdater,
+ flatten: true,
+ },
+ delete: {
+ description: "List of properties to delete.",
+ type: Array,
+ optional: true,
+ items: {
+ type: DeleteableMatcherProperty,
+ }
+ },
+ digest: {
+ optional: true,
+ schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
+ },
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Update notification matcher.
+pub fn update_matcher(
+ name: String,
+ updater: MatcherConfigUpdater,
+ delete: Option<Vec<DeleteableMatcherProperty>>,
+ digest: Option<String>,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ let digest = digest.map(hex::decode).transpose()?;
+
+ proxmox_notify::api::matcher::update_matcher(
+ &mut config,
+ &name,
+ updater,
+ delete.as_deref(),
+ digest.as_deref(),
+ )?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ }
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Delete notification matcher.
+pub fn delete_matcher(name: String, _rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ proxmox_notify::api::matcher::delete_matcher(&mut config, &name)?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+const ITEM_ROUTER: Router = Router::new()
+ .get(&API_METHOD_GET_MATCHER)
+ .put(&API_METHOD_UPDATE_MATCHER)
+ .delete(&API_METHOD_DELETE_MATCHER);
+
+pub const ROUTER: Router = Router::new()
+ .get(&API_METHOD_LIST_MATCHERS)
+ .post(&API_METHOD_ADD_MATCHER)
+ .match_all("name", &ITEM_ROUTER);
diff --git a/src/api2/config/notifications/mod.rs b/src/api2/config/notifications/mod.rs
index f75e3910..361dc593 100644
--- a/src/api2/config/notifications/mod.rs
+++ b/src/api2/config/notifications/mod.rs
@@ -2,10 +2,14 @@ use proxmox_router::list_subdirs_api_method;
use proxmox_router::{Router, SubdirMap};
use proxmox_sortable_macro::sortable;
+mod matchers;
mod targets;
#[sortable]
-const SUBDIRS: SubdirMap = &sorted!([("targets", &targets::ROUTER),]);
+const SUBDIRS: SubdirMap = &sorted!([
+ ("targets", &targets::ROUTER),
+ ("matchers", &matchers::ROUTER),
+]);
pub const ROUTER: Router = Router::new()
.get(&list_subdirs_api_method!(SUBDIRS))
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 15/43] api: add endpoints for sendmail targets
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (13 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 14/43] api: add endpoints for notification matchers Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 16/43] api: add endpoints for smtp targets Lukas Wagner
` (27 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
These endpoints require Sys.Audit/Sys.Modify permissions on
/system/notifications.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
src/api2/config/notifications/mod.rs | 9 ++
src/api2/config/notifications/sendmail.rs | 178 ++++++++++++++++++++++
2 files changed, 187 insertions(+)
create mode 100644 src/api2/config/notifications/sendmail.rs
diff --git a/src/api2/config/notifications/mod.rs b/src/api2/config/notifications/mod.rs
index 361dc593..76233b6c 100644
--- a/src/api2/config/notifications/mod.rs
+++ b/src/api2/config/notifications/mod.rs
@@ -3,10 +3,12 @@ use proxmox_router::{Router, SubdirMap};
use proxmox_sortable_macro::sortable;
mod matchers;
+mod sendmail;
mod targets;
#[sortable]
const SUBDIRS: SubdirMap = &sorted!([
+ ("endpoints", &ENDPOINT_ROUTER),
("targets", &targets::ROUTER),
("matchers", &matchers::ROUTER),
]);
@@ -14,3 +16,10 @@ const SUBDIRS: SubdirMap = &sorted!([
pub const ROUTER: Router = Router::new()
.get(&list_subdirs_api_method!(SUBDIRS))
.subdirs(SUBDIRS);
+
+#[sortable]
+const ENDPOINT_SUBDIRS: SubdirMap = &sorted!([("sendmail", &sendmail::ROUTER),]);
+
+const ENDPOINT_ROUTER: Router = Router::new()
+ .get(&list_subdirs_api_method!(ENDPOINT_SUBDIRS))
+ .subdirs(ENDPOINT_SUBDIRS);
diff --git a/src/api2/config/notifications/sendmail.rs b/src/api2/config/notifications/sendmail.rs
new file mode 100644
index 00000000..b8ce6b2b
--- /dev/null
+++ b/src/api2/config/notifications/sendmail.rs
@@ -0,0 +1,178 @@
+use anyhow::Error;
+use serde_json::Value;
+
+use proxmox_notify::endpoints::sendmail::{
+ DeleteableSendmailProperty, SendmailConfig, SendmailConfigUpdater,
+};
+use proxmox_notify::schema::ENTITY_NAME_SCHEMA;
+use proxmox_router::{Permission, Router, RpcEnvironment};
+use proxmox_schema::api;
+
+use pbs_api_types::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, PROXMOX_CONFIG_DIGEST_SCHEMA};
+
+#[api(
+ protected: true,
+ input: {
+ properties: {},
+ },
+ returns: {
+ description: "List of sendmail endpoints.",
+ type: Array,
+ items: { type: SendmailConfig },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// List all sendmail endpoints.
+pub fn list_endpoints(
+ _param: Value,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<SendmailConfig>, Error> {
+ let config = pbs_config::notifications::config()?;
+
+ let endpoints = proxmox_notify::api::sendmail::get_endpoints(&config)?;
+
+ Ok(endpoints)
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ }
+ },
+ },
+ returns: { type: SendmailConfig },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// Get a sendmail endpoint.
+pub fn get_endpoint(
+ name: String,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<SendmailConfig, Error> {
+ let config = pbs_config::notifications::config()?;
+ let endpoint = proxmox_notify::api::sendmail::get_endpoint(&config, &name)?;
+
+ rpcenv["digest"] = hex::encode(config.digest()).into();
+
+ Ok(endpoint)
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ endpoint: {
+ type: SendmailConfig,
+ flatten: true,
+ }
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Add a new sendmail endpoint.
+pub fn add_endpoint(
+ endpoint: SendmailConfig,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+
+ proxmox_notify::api::sendmail::add_endpoint(&mut config, endpoint)?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ },
+ updater: {
+ type: SendmailConfigUpdater,
+ flatten: true,
+ },
+ delete: {
+ description: "List of properties to delete.",
+ type: Array,
+ optional: true,
+ items: {
+ type: DeleteableSendmailProperty,
+ }
+ },
+ digest: {
+ optional: true,
+ schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
+ },
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Update sendmail endpoint.
+pub fn update_endpoint(
+ name: String,
+ updater: SendmailConfigUpdater,
+ delete: Option<Vec<DeleteableSendmailProperty>>,
+ digest: Option<String>,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ let digest = digest.map(hex::decode).transpose()?;
+
+ proxmox_notify::api::sendmail::update_endpoint(
+ &mut config,
+ &name,
+ updater,
+ delete.as_deref(),
+ digest.as_deref(),
+ )?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ }
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Delete sendmail endpoint.
+pub fn delete_endpoint(name: String, _rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ proxmox_notify::api::sendmail::delete_endpoint(&mut config, &name)?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+const ITEM_ROUTER: Router = Router::new()
+ .get(&API_METHOD_GET_ENDPOINT)
+ .put(&API_METHOD_UPDATE_ENDPOINT)
+ .delete(&API_METHOD_DELETE_ENDPOINT);
+
+pub const ROUTER: Router = Router::new()
+ .get(&API_METHOD_LIST_ENDPOINTS)
+ .post(&API_METHOD_ADD_ENDPOINT)
+ .match_all("name", &ITEM_ROUTER);
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 16/43] api: add endpoints for smtp targets
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (14 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 15/43] api: add endpoints for sendmail targets Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 17/43] api: add endpoints for gotify targets Lukas Wagner
` (26 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
These endpoints require Sys.Audit/Sys.Modify permissions on
/system/notifications.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
src/api2/config/notifications/mod.rs | 4 +-
src/api2/config/notifications/smtp.rs | 191 ++++++++++++++++++++++++++
2 files changed, 194 insertions(+), 1 deletion(-)
create mode 100644 src/api2/config/notifications/smtp.rs
diff --git a/src/api2/config/notifications/mod.rs b/src/api2/config/notifications/mod.rs
index 76233b6c..75b96ce1 100644
--- a/src/api2/config/notifications/mod.rs
+++ b/src/api2/config/notifications/mod.rs
@@ -4,6 +4,7 @@ use proxmox_sortable_macro::sortable;
mod matchers;
mod sendmail;
+mod smtp;
mod targets;
#[sortable]
@@ -18,7 +19,8 @@ pub const ROUTER: Router = Router::new()
.subdirs(SUBDIRS);
#[sortable]
-const ENDPOINT_SUBDIRS: SubdirMap = &sorted!([("sendmail", &sendmail::ROUTER),]);
+const ENDPOINT_SUBDIRS: SubdirMap =
+ &sorted!([("sendmail", &sendmail::ROUTER), ("smtp", &smtp::ROUTER),]);
const ENDPOINT_ROUTER: Router = Router::new()
.get(&list_subdirs_api_method!(ENDPOINT_SUBDIRS))
diff --git a/src/api2/config/notifications/smtp.rs b/src/api2/config/notifications/smtp.rs
new file mode 100644
index 00000000..8df2ab18
--- /dev/null
+++ b/src/api2/config/notifications/smtp.rs
@@ -0,0 +1,191 @@
+use anyhow::Error;
+use serde_json::Value;
+
+use proxmox_notify::endpoints::smtp::{
+ DeleteableSmtpProperty, SmtpConfig, SmtpConfigUpdater, SmtpPrivateConfig,
+ SmtpPrivateConfigUpdater,
+};
+use proxmox_notify::schema::ENTITY_NAME_SCHEMA;
+use proxmox_router::{Permission, Router, RpcEnvironment};
+use proxmox_schema::api;
+
+use pbs_api_types::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, PROXMOX_CONFIG_DIGEST_SCHEMA};
+
+#[api(
+ protected: true,
+ input: {
+ properties: {},
+ },
+ returns: {
+ description: "List of smtp endpoints.",
+ type: Array,
+ items: { type: SmtpConfig },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// List all smtp endpoints.
+pub fn list_endpoints(
+ _param: Value,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<SmtpConfig>, Error> {
+ let config = pbs_config::notifications::config()?;
+
+ let endpoints = proxmox_notify::api::smtp::get_endpoints(&config)?;
+
+ Ok(endpoints)
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ }
+ },
+ },
+ returns: { type: SmtpConfig },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// Get a smtp endpoint.
+pub fn get_endpoint(name: String, rpcenv: &mut dyn RpcEnvironment) -> Result<SmtpConfig, Error> {
+ let config = pbs_config::notifications::config()?;
+ let endpoint = proxmox_notify::api::smtp::get_endpoint(&config, &name)?;
+
+ rpcenv["digest"] = hex::encode(config.digest()).into();
+
+ Ok(endpoint)
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ endpoint: {
+ type: SmtpConfig,
+ flatten: true,
+ },
+ password: {
+ optional: true,
+ description: "SMTP authentication password"
+ }
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Add a new smtp endpoint.
+pub fn add_endpoint(
+ endpoint: SmtpConfig,
+ password: Option<String>,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ let private_endpoint_config = SmtpPrivateConfig {
+ name: endpoint.name.clone(),
+ password,
+ };
+
+ proxmox_notify::api::smtp::add_endpoint(&mut config, endpoint, private_endpoint_config)?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ },
+ updater: {
+ type: SmtpConfigUpdater,
+ flatten: true,
+ },
+ password: {
+ description: "SMTP authentication password",
+ optional: true,
+ },
+ delete: {
+ description: "List of properties to delete.",
+ type: Array,
+ optional: true,
+ items: {
+ type: DeleteableSmtpProperty,
+ }
+ },
+ digest: {
+ optional: true,
+ schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
+ },
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Update smtp endpoint.
+pub fn update_endpoint(
+ name: String,
+ updater: SmtpConfigUpdater,
+ password: Option<String>,
+ delete: Option<Vec<DeleteableSmtpProperty>>,
+ digest: Option<String>,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ let digest = digest.map(hex::decode).transpose()?;
+
+ proxmox_notify::api::smtp::update_endpoint(
+ &mut config,
+ &name,
+ updater,
+ SmtpPrivateConfigUpdater { password },
+ delete.as_deref(),
+ digest.as_deref(),
+ )?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ }
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Delete smtp endpoint.
+pub fn delete_endpoint(name: String, _rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ proxmox_notify::api::smtp::delete_endpoint(&mut config, &name)?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+const ITEM_ROUTER: Router = Router::new()
+ .get(&API_METHOD_GET_ENDPOINT)
+ .put(&API_METHOD_UPDATE_ENDPOINT)
+ .delete(&API_METHOD_DELETE_ENDPOINT);
+
+pub const ROUTER: Router = Router::new()
+ .get(&API_METHOD_LIST_ENDPOINTS)
+ .post(&API_METHOD_ADD_ENDPOINT)
+ .match_all("name", &ITEM_ROUTER);
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 17/43] api: add endpoints for gotify targets
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (15 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 16/43] api: add endpoints for smtp targets Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 18/43] api: add endpoints for querying known notification values/fields Lukas Wagner
` (25 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
These endpoints require Sys.Audit/Sys.Modify permissions on
/system/notifications.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
src/api2/config/notifications/gotify.rs | 190 ++++++++++++++++++++++++
src/api2/config/notifications/mod.rs | 8 +-
2 files changed, 196 insertions(+), 2 deletions(-)
create mode 100644 src/api2/config/notifications/gotify.rs
diff --git a/src/api2/config/notifications/gotify.rs b/src/api2/config/notifications/gotify.rs
new file mode 100644
index 00000000..1f14b377
--- /dev/null
+++ b/src/api2/config/notifications/gotify.rs
@@ -0,0 +1,190 @@
+use anyhow::Error;
+use serde_json::Value;
+
+use proxmox_notify::endpoints::gotify::{
+ DeleteableGotifyProperty, GotifyConfig, GotifyConfigUpdater, GotifyPrivateConfig,
+ GotifyPrivateConfigUpdater,
+};
+use proxmox_notify::schema::ENTITY_NAME_SCHEMA;
+use proxmox_router::{Permission, Router, RpcEnvironment};
+use proxmox_schema::api;
+
+use pbs_api_types::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, PROXMOX_CONFIG_DIGEST_SCHEMA};
+
+#[api(
+ protected: true,
+ input: {
+ properties: {},
+ },
+ returns: {
+ description: "List of gotify endpoints.",
+ type: Array,
+ items: { type: GotifyConfig },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// List all gotify endpoints.
+pub fn list_endpoints(
+ _param: Value,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<GotifyConfig>, Error> {
+ let config = pbs_config::notifications::config()?;
+
+ let endpoints = proxmox_notify::api::gotify::get_endpoints(&config)?;
+
+ Ok(endpoints)
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ }
+ },
+ },
+ returns: { type: GotifyConfig },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// Get a gotify endpoint.
+pub fn get_endpoint(name: String, rpcenv: &mut dyn RpcEnvironment) -> Result<GotifyConfig, Error> {
+ let config = pbs_config::notifications::config()?;
+ let endpoint = proxmox_notify::api::gotify::get_endpoint(&config, &name)?;
+
+ rpcenv["digest"] = hex::encode(config.digest()).into();
+
+ Ok(endpoint)
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ endpoint: {
+ type: GotifyConfig,
+ flatten: true,
+ },
+ token: {
+ description: "Authentication token",
+ }
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Add a new gotify endpoint.
+pub fn add_endpoint(
+ endpoint: GotifyConfig,
+ token: String,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ let private_endpoint_config = GotifyPrivateConfig {
+ name: endpoint.name.clone(),
+ token,
+ };
+
+ proxmox_notify::api::gotify::add_endpoint(&mut config, endpoint, private_endpoint_config)?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ },
+ updater: {
+ type: GotifyConfigUpdater,
+ flatten: true,
+ },
+ token: {
+ description: "Authentication token",
+ optional: true,
+ },
+ delete: {
+ description: "List of properties to delete.",
+ type: Array,
+ optional: true,
+ items: {
+ type: DeleteableGotifyProperty,
+ }
+ },
+ digest: {
+ optional: true,
+ schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
+ },
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Update gotify endpoint.
+pub fn update_endpoint(
+ name: String,
+ updater: GotifyConfigUpdater,
+ token: Option<String>,
+ delete: Option<Vec<DeleteableGotifyProperty>>,
+ digest: Option<String>,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ let digest = digest.map(hex::decode).transpose()?;
+
+ proxmox_notify::api::gotify::update_endpoint(
+ &mut config,
+ &name,
+ updater,
+ GotifyPrivateConfigUpdater { token },
+ delete.as_deref(),
+ digest.as_deref(),
+ )?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ }
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Delete gotify endpoint.
+pub fn delete_endpoint(name: String, _rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
+ let _lock = pbs_config::notifications::lock_config()?;
+ let mut config = pbs_config::notifications::config()?;
+ proxmox_notify::api::gotify::delete_gotify_endpoint(&mut config, &name)?;
+
+ pbs_config::notifications::save_config(config)?;
+ Ok(())
+}
+
+const ITEM_ROUTER: Router = Router::new()
+ .get(&API_METHOD_GET_ENDPOINT)
+ .put(&API_METHOD_UPDATE_ENDPOINT)
+ .delete(&API_METHOD_DELETE_ENDPOINT);
+
+pub const ROUTER: Router = Router::new()
+ .get(&API_METHOD_LIST_ENDPOINTS)
+ .post(&API_METHOD_ADD_ENDPOINT)
+ .match_all("name", &ITEM_ROUTER);
diff --git a/src/api2/config/notifications/mod.rs b/src/api2/config/notifications/mod.rs
index 75b96ce1..9c4a0cd9 100644
--- a/src/api2/config/notifications/mod.rs
+++ b/src/api2/config/notifications/mod.rs
@@ -2,6 +2,7 @@ use proxmox_router::list_subdirs_api_method;
use proxmox_router::{Router, SubdirMap};
use proxmox_sortable_macro::sortable;
+mod gotify;
mod matchers;
mod sendmail;
mod smtp;
@@ -19,8 +20,11 @@ pub const ROUTER: Router = Router::new()
.subdirs(SUBDIRS);
#[sortable]
-const ENDPOINT_SUBDIRS: SubdirMap =
- &sorted!([("sendmail", &sendmail::ROUTER), ("smtp", &smtp::ROUTER),]);
+const ENDPOINT_SUBDIRS: SubdirMap = &sorted!([
+ ("gotify", &gotify::ROUTER),
+ ("sendmail", &sendmail::ROUTER),
+ ("smtp", &smtp::ROUTER),
+]);
const ENDPOINT_ROUTER: Router = Router::new()
.get(&list_subdirs_api_method!(ENDPOINT_SUBDIRS))
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 18/43] api: add endpoints for querying known notification values/fields
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (16 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 17/43] api: add endpoints for gotify targets Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 19/43] api-types: api: datatore: add notification-mode parameter Lukas Wagner
` (24 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
These endpoints require Sys.Audit/Sys.Modify permissions on
/system/notifications.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/api2/config/notifications/mod.rs | 195 ++++++++++++++++++++++++++-
1 file changed, 194 insertions(+), 1 deletion(-)
diff --git a/src/api2/config/notifications/mod.rs b/src/api2/config/notifications/mod.rs
index 9c4a0cd9..05a51f24 100644
--- a/src/api2/config/notifications/mod.rs
+++ b/src/api2/config/notifications/mod.rs
@@ -1,7 +1,22 @@
-use proxmox_router::list_subdirs_api_method;
+use anyhow::Error;
+use serde::Serialize;
+use serde_json::Value;
+use std::cmp::Ordering;
+
+use proxmox_router::{list_subdirs_api_method, Permission, RpcEnvironment};
use proxmox_router::{Router, SubdirMap};
+use proxmox_schema::api;
use proxmox_sortable_macro::sortable;
+use pbs_api_types::PRIV_SYS_AUDIT;
+
+use crate::api2::admin::prune::list_prune_jobs;
+use crate::api2::admin::sync::list_sync_jobs;
+use crate::api2::admin::verify::list_verification_jobs;
+use crate::api2::config::datastore::list_datastores;
+use crate::api2::config::media_pool::list_pools;
+use crate::api2::tape::backup::list_tape_backup_jobs;
+
mod gotify;
mod matchers;
mod sendmail;
@@ -11,6 +26,8 @@ mod targets;
#[sortable]
const SUBDIRS: SubdirMap = &sorted!([
("endpoints", &ENDPOINT_ROUTER),
+ ("fields", &FIELD_ROUTER),
+ ("values", &VALUE_ROUTER),
("targets", &targets::ROUTER),
("matchers", &matchers::ROUTER),
]);
@@ -29,3 +46,179 @@ const ENDPOINT_SUBDIRS: SubdirMap = &sorted!([
const ENDPOINT_ROUTER: Router = Router::new()
.get(&list_subdirs_api_method!(ENDPOINT_SUBDIRS))
.subdirs(ENDPOINT_SUBDIRS);
+
+const FIELD_ROUTER: Router = Router::new().get(&API_METHOD_GET_FIELDS);
+const VALUE_ROUTER: Router = Router::new().get(&API_METHOD_GET_VALUES);
+
+#[api]
+#[derive(Serialize)]
+/// A matchable field.
+pub struct MatchableField {
+ /// Name of the field
+ name: String,
+}
+
+#[api]
+#[derive(Serialize)]
+/// A matchable metadata field value.
+pub struct MatchableValue {
+ /// Field this value belongs to.
+ field: String,
+ /// Notification metadata value known by the system.
+ value: String,
+ /// Additional comment for this value.
+ comment: Option<String>,
+ /// Set if `value` was generated by the system and can safely be used
+ /// as a base for translations.
+ internal: Option<bool>,
+}
+
+#[api(
+ protected: false,
+ input: {
+ properties: {},
+ },
+ returns: {
+ description: "List of known metadata fields.",
+ type: Array,
+ items: { type: MatchableField },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// Get all known metadata fields.
+pub fn get_fields() -> Result<Vec<MatchableField>, Error> {
+ let fields = [
+ "datastore",
+ "hostname",
+ "media-pool",
+ "prune-job",
+ "sync-job",
+ "type",
+ "tape-job",
+ "verification-job",
+ ]
+ .into_iter()
+ .map(Into::into)
+ .map(|name| MatchableField { name })
+ .collect();
+
+ Ok(fields)
+}
+
+#[api(
+ protected: false,
+ input: {
+ properties: {},
+ },
+ returns: {
+ description: "List of known metadata field values.",
+ type: Array,
+ items: { type: MatchableValue },
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// List all known, matchable metadata field values.
+pub fn get_values(
+ param: Value,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<MatchableValue>, Error> {
+ let mut values = Vec::new();
+
+ let datastores = list_datastores(param.clone(), rpcenv)?;
+
+ for datastore in datastores {
+ values.push(MatchableValue {
+ field: "datastore".into(),
+ value: datastore.name.clone(),
+ comment: datastore.comment.clone(),
+ internal: Some(false),
+ });
+ }
+
+ let pools = list_pools(rpcenv)?;
+ for pool in pools {
+ values.push(MatchableValue {
+ field: "media-pool".into(),
+ value: pool.name.clone(),
+ comment: None,
+ internal: Some(false),
+ });
+ }
+
+ let tape_backup_jobs = list_tape_backup_jobs(param.clone(), rpcenv)?;
+ for job in tape_backup_jobs {
+ values.push(MatchableValue {
+ field: "tape-job".into(),
+ value: job.config.id,
+ comment: job.config.comment,
+ internal: Some(false),
+ });
+ }
+
+ let prune_jobs = list_prune_jobs(None, param.clone(), rpcenv)?;
+ for job in prune_jobs {
+ values.push(MatchableValue {
+ field: "prune-job".into(),
+ value: job.config.id,
+ comment: job.config.comment,
+ internal: Some(false),
+ });
+ }
+
+ let sync_jobs = list_sync_jobs(None, param.clone(), rpcenv)?;
+ for job in sync_jobs {
+ values.push(MatchableValue {
+ field: "sync-job".into(),
+ value: job.config.id,
+ comment: job.config.comment,
+ internal: Some(false),
+ });
+ }
+
+ let verify_jobs = list_verification_jobs(None, param.clone(), rpcenv)?;
+ for job in verify_jobs {
+ values.push(MatchableValue {
+ field: "verification-job".into(),
+ value: job.config.id,
+ comment: job.config.comment,
+ internal: Some(false),
+ });
+ }
+
+ values.push(MatchableValue {
+ field: "hostname".into(),
+ value: proxmox_sys::nodename().into(),
+ comment: None,
+ internal: Some(false),
+ });
+
+ for ty in [
+ "acme",
+ "gc",
+ "package-updates",
+ "prune",
+ "sync",
+ "system-mail",
+ "tape-backup",
+ "tape-load",
+ "verify",
+ ] {
+ values.push(MatchableValue {
+ field: "type".into(),
+ value: ty.into(),
+ comment: None,
+ internal: Some(true),
+ });
+ }
+
+ values.sort_by(|a, b| match a.field.cmp(&b.field) {
+ Ordering::Equal => a.value.cmp(&b.value),
+ ord => ord,
+ });
+
+ Ok(values)
+}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 19/43] api-types: api: datatore: add notification-mode parameter
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (17 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 18/43] api: add endpoints for querying known notification values/fields Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 20/43] api-types: api: tape: " Lukas Wagner
` (23 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
This one lets the user choose between the old notification behavior
(selecting an email address/user and always/error/never behavior per
datastore) and the new one (emit notification events to the
notification system)
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
pbs-api-types/src/datastore.rs | 22 ++++++++++++++++++++++
src/api2/config/datastore.rs | 9 +++++++++
2 files changed, 31 insertions(+)
diff --git a/pbs-api-types/src/datastore.rs b/pbs-api-types/src/datastore.rs
index 5e13c157..76b6ef43 100644
--- a/pbs-api-types/src/datastore.rs
+++ b/pbs-api-types/src/datastore.rs
@@ -309,6 +309,10 @@ pub struct DataStoreConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub notify: Option<String>,
+ /// Opt in to the new notification system
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub notification_mode: Option<NotificationMode>,
+
/// Datastore tuning options
#[serde(skip_serializing_if = "Option::is_none")]
pub tuning: Option<String>,
@@ -318,6 +322,23 @@ pub struct DataStoreConfig {
pub maintenance_mode: Option<String>,
}
+#[api]
+#[derive(Serialize, Deserialize, Updater, Clone, PartialEq, Default)]
+#[serde(rename_all = "kebab-case")]
+/// Configure how notifications for this datastore should be sent.
+/// `legacy-sendmail` sends email notifications to the user configured
+/// in `notify-user` via the system's `sendmail` executable.
+/// `notification-system` emits matchable notification events to the
+/// notification system.
+pub enum NotificationMode {
+ /// Send notifications via the system's sendmail command to the user
+ /// configured in `notify-user`
+ #[default]
+ LegacySendmail,
+ /// Emit notification events to the notification system
+ NotificationSystem,
+}
+
impl DataStoreConfig {
pub fn new(name: String, path: String) -> Self {
Self {
@@ -330,6 +351,7 @@ impl DataStoreConfig {
verify_new: None,
notify_user: None,
notify: None,
+ notification_mode: None,
tuning: None,
maintenance_mode: None,
}
diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs
index 3081e1f4..9a64c6a6 100644
--- a/src/api2/config/datastore.rs
+++ b/src/api2/config/datastore.rs
@@ -222,6 +222,8 @@ pub enum DeletableProperty {
NotifyUser,
/// Delete the notify property
Notify,
+ /// Delete the notification-mode property
+ NotificationMode,
/// Delete the tuning property
Tuning,
/// Delete the maintenance-mode property
@@ -315,6 +317,9 @@ pub fn update_datastore(
DeletableProperty::NotifyUser => {
data.notify_user = None;
}
+ DeletableProperty::NotificationMode => {
+ data.notification_mode = None;
+ }
DeletableProperty::Tuning => {
data.tuning = None;
}
@@ -385,6 +390,10 @@ pub fn update_datastore(
data.notify_user = update.notify_user;
}
+ if update.notification_mode.is_some() {
+ data.notification_mode = update.notification_mode;
+ }
+
if update.tuning.is_some() {
data.tuning = update.tuning;
}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 20/43] api-types: api: tape: add notification-mode parameter
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (18 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 19/43] api-types: api: datatore: add notification-mode parameter Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 21/43] server: notifications: send GC notifications via notification system Lukas Wagner
` (22 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
Same as with datastores, this option determines whether we send
notifications the old way (send email via sendmail to a user's email
address) or the new way (emit matchable notification events to the
notification stack).
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
pbs-api-types/src/jobs.rs | 8 +++++---
src/api2/config/tape_backup_job.rs | 8 ++++++++
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/pbs-api-types/src/jobs.rs b/pbs-api-types/src/jobs.rs
index 6fb9b187..868702bc 100644
--- a/pbs-api-types/src/jobs.rs
+++ b/pbs-api-types/src/jobs.rs
@@ -8,9 +8,9 @@ use serde::{Deserialize, Serialize};
use proxmox_schema::*;
use crate::{
- Authid, BackupNamespace, BackupType, RateLimitConfig, Userid, BACKUP_GROUP_SCHEMA,
- BACKUP_NAMESPACE_SCHEMA, BACKUP_NS_RE, DATASTORE_SCHEMA, DRIVE_NAME_SCHEMA,
- MEDIA_POOL_NAME_SCHEMA, NS_MAX_DEPTH_REDUCED_SCHEMA, PROXMOX_SAFE_ID_FORMAT,
+ Authid, BackupNamespace, BackupType, NotificationMode, RateLimitConfig, Userid,
+ BACKUP_GROUP_SCHEMA, BACKUP_NAMESPACE_SCHEMA, BACKUP_NS_RE, DATASTORE_SCHEMA,
+ DRIVE_NAME_SCHEMA, MEDIA_POOL_NAME_SCHEMA, NS_MAX_DEPTH_REDUCED_SCHEMA, PROXMOX_SAFE_ID_FORMAT,
PROXMOX_SAFE_ID_REGEX_STR, REMOTE_ID_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA,
};
@@ -325,6 +325,8 @@ pub struct TapeBackupJobSetup {
#[serde(skip_serializing_if = "Option::is_none")]
pub notify_user: Option<Userid>,
#[serde(skip_serializing_if = "Option::is_none")]
+ pub notification_mode: Option<NotificationMode>,
+ #[serde(skip_serializing_if = "Option::is_none")]
pub group_filter: Option<Vec<GroupFilter>>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub ns: Option<BackupNamespace>,
diff --git a/src/api2/config/tape_backup_job.rs b/src/api2/config/tape_backup_job.rs
index 386ff530..e425cbb5 100644
--- a/src/api2/config/tape_backup_job.rs
+++ b/src/api2/config/tape_backup_job.rs
@@ -132,6 +132,8 @@ pub enum DeletableProperty {
LatestOnly,
/// Delete the 'notify-user' property
NotifyUser,
+ /// Delete the 'notification-mode' property
+ NotificationMode,
/// Delete the 'group_filter' property
GroupFilter,
/// Delete the 'max-depth' property
@@ -202,6 +204,9 @@ pub fn update_tape_backup_job(
DeletableProperty::NotifyUser => {
data.setup.notify_user = None;
}
+ DeletableProperty::NotificationMode => {
+ data.setup.notification_mode = None;
+ }
DeletableProperty::Schedule => {
data.schedule = None;
}
@@ -243,6 +248,9 @@ pub fn update_tape_backup_job(
if update.setup.notify_user.is_some() {
data.setup.notify_user = update.setup.notify_user;
}
+ if update.setup.notification_mode.is_some() {
+ data.setup.notification_mode = update.setup.notification_mode;
+ }
if update.setup.group_filter.is_some() {
data.setup.group_filter = update.setup.group_filter;
}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 21/43] server: notifications: send GC notifications via notification system
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (19 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 20/43] api-types: api: tape: " Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 22/43] server: notifications: send prune " Lukas Wagner
` (21 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
If the `notification-mode` parameter is set to `legacy-sendmail`, then
we still use the new infrastructure, but don't consider the
notification config and use a hard-coded sendmail endpoint directly.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
debian/proxmox-backup-server.install | 4 +
src/api2/pull.rs | 2 +-
src/server/gc_job.rs | 10 +-
src/server/notifications.rs | 184 +++++++----------------
src/server/verify_job.rs | 3 +-
templates/Makefile | 4 +
templates/default/gc-err-body.txt.hbs | 8 +
templates/default/gc-err-subject.txt.hbs | 1 +
templates/default/gc-ok-body.txt.hbs | 23 +++
templates/default/gc-ok-subject.txt.hbs | 1 +
10 files changed, 102 insertions(+), 138 deletions(-)
create mode 100644 templates/default/gc-err-body.txt.hbs
create mode 100644 templates/default/gc-err-subject.txt.hbs
create mode 100644 templates/default/gc-ok-body.txt.hbs
create mode 100644 templates/default/gc-ok-subject.txt.hbs
diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install
index 6aff594d..197c070f 100644
--- a/debian/proxmox-backup-server.install
+++ b/debian/proxmox-backup-server.install
@@ -41,6 +41,10 @@ usr/share/zsh/vendor-completions/_pmtx
usr/share/zsh/vendor-completions/_proxmox-backup-debug
usr/share/zsh/vendor-completions/_proxmox-backup-manager
usr/share/zsh/vendor-completions/_proxmox-tape
+usr/share/proxmox-backup/templates/default/gc-err-body.txt.hbs
+usr/share/proxmox-backup/templates/default/gc-ok-body.txt.hbs
+usr/share/proxmox-backup/templates/default/gc-err-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/gc-ok-subject.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.html.hbs
usr/share/proxmox-backup/templates/default/test-subject.txt.hbs
diff --git a/src/api2/pull.rs b/src/api2/pull.rs
index 59db3660..7fe2267a 100644
--- a/src/api2/pull.rs
+++ b/src/api2/pull.rs
@@ -114,7 +114,7 @@ pub fn do_sync_job(
bail!("can't sync to same datastore");
}
- let (email, notify) = crate::server::lookup_datastore_notify_settings(&sync_job.store);
+ let (email, notify, _) = crate::server::lookup_datastore_notify_settings(&sync_job.store);
let upid_str = WorkerTask::spawn(
&worker_type,
diff --git a/src/server/gc_job.rs b/src/server/gc_job.rs
index 41375d72..ff5bdccf 100644
--- a/src/server/gc_job.rs
+++ b/src/server/gc_job.rs
@@ -19,8 +19,6 @@ pub fn do_garbage_collection_job(
) -> Result<String, Error> {
let store = datastore.name().to_string();
- let (email, notify) = crate::server::lookup_datastore_notify_settings(&store);
-
let worker_type = job.jobtype().to_string();
let upid_str = WorkerTask::new_thread(
&worker_type,
@@ -43,11 +41,9 @@ pub fn do_garbage_collection_job(
eprintln!("could not finish job state for {}: {err}", job.jobtype());
}
- if let Some(email) = email {
- let gc_status = datastore.last_gc_status();
- if let Err(err) = send_gc_status(&email, notify, &store, &gc_status, &result) {
- eprintln!("send gc notification failed: {err}");
- }
+ let gc_status = datastore.last_gc_status();
+ if let Err(err) = send_gc_status(&store, &gc_status, &result) {
+ eprintln!("send gc notification failed: {err}");
}
result
diff --git a/src/server/notifications.rs b/src/server/notifications.rs
index 9fb202d8..a9b79cc8 100644
--- a/src/server/notifications.rs
+++ b/src/server/notifications.rs
@@ -1,16 +1,13 @@
use anyhow::Error;
use const_format::concatcp;
-use serde_json::{json, Value};
+use serde_json::json;
use std::collections::HashMap;
use std::path::Path;
use std::time::{Duration, Instant};
-use handlebars::{
- Context, Handlebars, Helper, HelperResult, Output, RenderContext, RenderError, TemplateError,
-};
+use handlebars::{Handlebars, TemplateError};
use nix::unistd::Uid;
-use proxmox_human_byte::HumanByte;
use proxmox_lang::try_block;
use proxmox_notify::context::pbs::PBS_CONTEXT;
use proxmox_schema::ApiType;
@@ -18,52 +15,13 @@ use proxmox_sys::email::sendmail;
use proxmox_sys::fs::{create_path, CreateOptions};
use pbs_api_types::{
- APTUpdateInfo, DataStoreConfig, DatastoreNotify, GarbageCollectionStatus, Notify,
- SyncJobConfig, TapeBackupJobSetup, User, Userid, VerificationJobConfig,
+ APTUpdateInfo, DataStoreConfig, DatastoreNotify, GarbageCollectionStatus, NotificationMode,
+ Notify, SyncJobConfig, TapeBackupJobSetup, User, Userid, VerificationJobConfig,
};
-use proxmox_notify::{Notification, Severity};
+use proxmox_notify::endpoints::sendmail::{SendmailConfig, SendmailEndpoint};
+use proxmox_notify::{Endpoint, Notification, Severity};
const SPOOL_DIR: &str = concatcp!(pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR, "/notifications");
-const GC_OK_TEMPLATE: &str = r###"
-
-Datastore: {{datastore}}
-Task ID: {{status.upid}}
-Index file count: {{status.index-file-count}}
-
-Removed garbage: {{human-bytes status.removed-bytes}}
-Removed chunks: {{status.removed-chunks}}
-Removed bad chunks: {{status.removed-bad}}
-
-Leftover bad chunks: {{status.still-bad}}
-Pending removals: {{human-bytes status.pending-bytes}} (in {{status.pending-chunks}} chunks)
-
-Original Data usage: {{human-bytes status.index-data-bytes}}
-On-Disk usage: {{human-bytes status.disk-bytes}} ({{relative-percentage status.disk-bytes status.index-data-bytes}})
-On-Disk chunks: {{status.disk-chunks}}
-
-Deduplication Factor: {{deduplication-factor}}
-
-Garbage collection successful.
-
-
-Please visit the web interface for further details:
-
-<https://{{fqdn}}:{{port}}/#DataStore-{{datastore}}>
-
-"###;
-
-const GC_ERR_TEMPLATE: &str = r###"
-
-Datastore: {{datastore}}
-
-Garbage collection failed: {{error}}
-
-
-Please visit the web interface for further details:
-
-<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
-
-"###;
const VERIFY_OK_TEMPLATE: &str = r###"
@@ -259,12 +217,6 @@ lazy_static::lazy_static! {
hb.set_strict_mode(true);
hb.register_escape_fn(handlebars::no_escape);
- hb.register_helper("human-bytes", Box::new(handlebars_humam_bytes_helper));
- hb.register_helper("relative-percentage", Box::new(handlebars_relative_percentage_helper));
-
- hb.register_template_string("gc_ok_template", GC_OK_TEMPLATE)?;
- hb.register_template_string("gc_err_template", GC_ERR_TEMPLATE)?;
-
hb.register_template_string("verify_ok_template", VERIFY_OK_TEMPLATE)?;
hb.register_template_string("verify_err_template", VERIFY_ERR_TEMPLATE)?;
@@ -388,6 +340,19 @@ fn send_notification(notification: Notification) -> Result<(), Error> {
Ok(())
}
+fn send_sendmail_legacy_notification(notification: Notification, email: &str) -> Result<(), Error> {
+ let endpoint = SendmailEndpoint {
+ config: SendmailConfig {
+ mailto: vec![email.into()],
+ ..Default::default()
+ },
+ };
+
+ endpoint.send(¬ification)?;
+
+ Ok(())
+}
+
/// Summary of a successful Tape Job
#[derive(Default)]
pub struct TapeBackupJobSummary {
@@ -424,21 +389,10 @@ fn send_job_status_mail(email: &str, subject: &str, text: &str) -> Result<(), Er
}
pub fn send_gc_status(
- email: &str,
- notify: DatastoreNotify,
datastore: &str,
status: &GarbageCollectionStatus,
result: &Result<(), Error>,
) -> Result<(), Error> {
- match notify.gc {
- 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!({
"datastore": datastore,
@@ -446,7 +400,7 @@ pub fn send_gc_status(
"port": port,
});
- let text = match result {
+ let (severity, template) = match result {
Ok(()) => {
let deduplication_factor = if status.disk_bytes > 0 {
(status.index_data_bytes as f64) / (status.disk_bytes as f64)
@@ -457,20 +411,38 @@ pub fn send_gc_status(
data["status"] = json!(status);
data["deduplication-factor"] = format!("{:.2}", deduplication_factor).into();
- HANDLEBARS.render("gc_ok_template", &data)?
+ (Severity::Info, "gc-ok")
}
Err(err) => {
data["error"] = err.to_string().into();
- HANDLEBARS.render("gc_err_template", &data)?
+ (Severity::Error, "gc-err")
}
};
+ let metadata = HashMap::from([
+ ("datastore".into(), datastore.into()),
+ ("hostname".into(), proxmox_sys::nodename().into()),
+ ("type".into(), "gc".into()),
+ ]);
- let subject = match result {
- Ok(()) => format!("Garbage Collect Datastore '{datastore}' successful"),
- Err(_) => format!("Garbage Collect Datastore '{datastore}' failed"),
- };
+ let notification = Notification::from_template(severity, template, data, metadata);
- send_job_status_mail(email, &subject, &text)?;
+ let (email, notify, mode) = lookup_datastore_notify_settings(datastore);
+ match mode {
+ NotificationMode::LegacySendmail => {
+ let notify = notify.gc.unwrap_or(Notify::Always);
+
+ if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
+ return Ok(());
+ }
+
+ if let Some(email) = email {
+ send_sendmail_legacy_notification(notification, &email)?;
+ }
+ }
+ NotificationMode::NotificationSystem => {
+ send_notification(notification)?;
+ }
+ }
Ok(())
}
@@ -530,8 +502,8 @@ pub fn send_prune_status(
result: &Result<(), Error>,
) -> Result<(), Error> {
let (email, notify) = match lookup_datastore_notify_settings(store) {
- (Some(email), notify) => (email, notify),
- (None, _) => return Ok(()),
+ (Some(email), notify, _) => (email, notify),
+ (None, _, _) => return Ok(()),
};
let notify_prune = notify.prune.unwrap_or(Notify::Error);
@@ -766,7 +738,9 @@ pub fn lookup_user_email(userid: &Userid) -> Option<String> {
}
/// Lookup Datastore notify settings
-pub fn lookup_datastore_notify_settings(store: &str) -> (Option<String>, DatastoreNotify) {
+pub fn lookup_datastore_notify_settings(
+ store: &str,
+) -> (Option<String>, DatastoreNotify, NotificationMode) {
let mut email = None;
let notify = DatastoreNotify {
@@ -778,12 +752,12 @@ pub fn lookup_datastore_notify_settings(store: &str) -> (Option<String>, Datasto
let (config, _digest) = match pbs_config::datastore::config() {
Ok(result) => result,
- Err(_) => return (email, notify),
+ Err(_) => return (email, notify, NotificationMode::default()),
};
let config: DataStoreConfig = match config.lookup("datastore", store) {
Ok(result) => result,
- Err(_) => return (email, notify),
+ Err(_) => return (email, notify, NotificationMode::default()),
};
email = match config.notify_user {
@@ -791,68 +765,20 @@ pub fn lookup_datastore_notify_settings(store: &str) -> (Option<String>, Datasto
None => lookup_user_email(Userid::root_userid()),
};
+ let notification_mode = config.notification_mode.unwrap_or_default();
let notify_str = config.notify.unwrap_or_default();
if let Ok(value) = DatastoreNotify::API_SCHEMA.parse_property_string(¬ify_str) {
if let Ok(notify) = serde_json::from_value(value) {
- return (email, notify);
+ return (email, notify, notification_mode);
}
}
- (email, notify)
-}
-
-// Handlerbar helper functions
-
-fn handlebars_humam_bytes_helper(
- h: &Helper,
- _: &Handlebars,
- _: &Context,
- _rc: &mut RenderContext,
- out: &mut dyn Output,
-) -> HelperResult {
- let param = h
- .param(0)
- .and_then(|v| v.value().as_u64())
- .ok_or_else(|| RenderError::new("human-bytes: param not found"))?;
-
- out.write(&HumanByte::from(param).to_string())?;
-
- Ok(())
-}
-
-fn handlebars_relative_percentage_helper(
- h: &Helper,
- _: &Handlebars,
- _: &Context,
- _rc: &mut RenderContext,
- out: &mut dyn Output,
-) -> HelperResult {
- let param0 = h
- .param(0)
- .and_then(|v| v.value().as_f64())
- .ok_or_else(|| RenderError::new("relative-percentage: param0 not found"))?;
- let param1 = h
- .param(1)
- .and_then(|v| v.value().as_f64())
- .ok_or_else(|| RenderError::new("relative-percentage: param1 not found"))?;
-
- if param1 == 0.0 {
- out.write("-")?;
- } else {
- out.write(&format!("{:.2}%", (param0 * 100.0) / param1))?;
- }
- Ok(())
+ (email, notify, notification_mode)
}
#[test]
fn test_template_register() {
- HANDLEBARS.get_helper("human-bytes").unwrap();
- HANDLEBARS.get_helper("relative-percentage").unwrap();
-
- assert!(HANDLEBARS.has_template("gc_ok_template"));
- assert!(HANDLEBARS.has_template("gc_err_template"));
-
assert!(HANDLEBARS.has_template("verify_ok_template"));
assert!(HANDLEBARS.has_template("verify_err_template"));
diff --git a/src/server/verify_job.rs b/src/server/verify_job.rs
index 8bf2a0c9..fed80e5c 100644
--- a/src/server/verify_job.rs
+++ b/src/server/verify_job.rs
@@ -23,7 +23,8 @@ pub fn do_verification_job(
let outdated_after = verification_job.outdated_after;
let ignore_verified_snapshots = verification_job.ignore_verified.unwrap_or(true);
- let (email, notify) = crate::server::lookup_datastore_notify_settings(&verification_job.store);
+ let (email, notify, _) =
+ crate::server::lookup_datastore_notify_settings(&verification_job.store);
// FIXME encode namespace here for filter/ACL check?
let job_id = format!("{}:{}", &verification_job.store, job.jobname());
diff --git a/templates/Makefile b/templates/Makefile
index b35a8bb3..7d4cb19f 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -1,6 +1,10 @@
include ../defines.mk
NOTIFICATION_TEMPLATES= \
+ default/gc-err-body.txt.hbs \
+ default/gc-ok-body.txt.hbs \
+ default/gc-err-subject.txt.hbs \
+ default/gc-ok-subject.txt.hbs \
default/test-body.txt.hbs \
default/test-body.html.hbs \
default/test-subject.txt.hbs \
diff --git a/templates/default/gc-err-body.txt.hbs b/templates/default/gc-err-body.txt.hbs
new file mode 100644
index 00000000..d6c2d0bc
--- /dev/null
+++ b/templates/default/gc-err-body.txt.hbs
@@ -0,0 +1,8 @@
+Datastore: {{datastore}}
+
+Garbage collection failed: {{error}}
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
diff --git a/templates/default/gc-err-subject.txt.hbs b/templates/default/gc-err-subject.txt.hbs
new file mode 100644
index 00000000..ebf49f3b
--- /dev/null
+++ b/templates/default/gc-err-subject.txt.hbs
@@ -0,0 +1 @@
+Garbage Collect Datastore '{{ datastore }}' failed
diff --git a/templates/default/gc-ok-body.txt.hbs b/templates/default/gc-ok-body.txt.hbs
new file mode 100644
index 00000000..d2f7cd81
--- /dev/null
+++ b/templates/default/gc-ok-body.txt.hbs
@@ -0,0 +1,23 @@
+Datastore: {{datastore}}
+Task ID: {{status.upid}}
+Index file count: {{status.index-file-count}}
+
+Removed garbage: {{human-bytes status.removed-bytes}}
+Removed chunks: {{status.removed-chunks}}
+Removed bad chunks: {{status.removed-bad}}
+
+Leftover bad chunks: {{status.still-bad}}
+Pending removals: {{human-bytes status.pending-bytes}} (in {{status.pending-chunks}} chunks)
+
+Original Data usage: {{human-bytes status.index-data-bytes}}
+On-Disk usage: {{human-bytes status.disk-bytes}} ({{relative-percentage status.disk-bytes status.index-data-bytes}})
+On-Disk chunks: {{status.disk-chunks}}
+
+Deduplication Factor: {{deduplication-factor}}
+
+Garbage collection successful.
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#DataStore-{{datastore}}>
diff --git a/templates/default/gc-ok-subject.txt.hbs b/templates/default/gc-ok-subject.txt.hbs
new file mode 100644
index 00000000..538e3700
--- /dev/null
+++ b/templates/default/gc-ok-subject.txt.hbs
@@ -0,0 +1 @@
+Garbage Collect Datastore '{{ datastore }}' successful
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 22/43] server: notifications: send prune notifications via notification system
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (20 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 21/43] server: notifications: send GC notifications via notification system Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 23/43] server: notifications: send verify " Lukas Wagner
` (20 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
If the `notification-mode` parameter is set to `legacy-sendmail`, then
we still use the new infrastructure, but don't consider the
notification config and use a hard-coded sendmail endpoint directly.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
debian/proxmox-backup-server.install | 4 ++
src/server/notifications.rs | 76 ++++++++-------------
templates/Makefile | 4 ++
templates/default/prune-err-body.txt.hbs | 10 +++
templates/default/prune-err-subject.txt.hbs | 1 +
templates/default/prune-ok-body.txt.hbs | 10 +++
templates/default/prune-ok-subject.txt.hbs | 1 +
7 files changed, 57 insertions(+), 49 deletions(-)
create mode 100644 templates/default/prune-err-body.txt.hbs
create mode 100644 templates/default/prune-err-subject.txt.hbs
create mode 100644 templates/default/prune-ok-body.txt.hbs
create mode 100644 templates/default/prune-ok-subject.txt.hbs
diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install
index 197c070f..7b8183dd 100644
--- a/debian/proxmox-backup-server.install
+++ b/debian/proxmox-backup-server.install
@@ -45,6 +45,10 @@ usr/share/proxmox-backup/templates/default/gc-err-body.txt.hbs
usr/share/proxmox-backup/templates/default/gc-ok-body.txt.hbs
usr/share/proxmox-backup/templates/default/gc-err-subject.txt.hbs
usr/share/proxmox-backup/templates/default/gc-ok-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/prune-err-body.txt.hbs
+usr/share/proxmox-backup/templates/default/prune-ok-body.txt.hbs
+usr/share/proxmox-backup/templates/default/prune-err-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/prune-ok-subject.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.html.hbs
usr/share/proxmox-backup/templates/default/test-subject.txt.hbs
diff --git a/src/server/notifications.rs b/src/server/notifications.rs
index a9b79cc8..4dcde943 100644
--- a/src/server/notifications.rs
+++ b/src/server/notifications.rs
@@ -87,34 +87,6 @@ Local Source 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>
@@ -223,9 +195,6 @@ 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)?;
@@ -501,16 +470,6 @@ pub fn send_prune_status(
jobname: &str,
result: &Result<(), Error>,
) -> Result<(), Error> {
- let (email, notify) = match lookup_datastore_notify_settings(store) {
- (Some(email), notify, _) => (email, notify),
- (None, _, _) => return Ok(()),
- };
-
- let notify_prune = notify.prune.unwrap_or(Notify::Error);
- if notify_prune == Notify::Never || (result.is_ok() && notify_prune == Notify::Error) {
- return Ok(());
- }
-
let (fqdn, port) = get_server_url();
let mut data = json!({
"jobname": jobname,
@@ -519,20 +478,39 @@ pub fn send_prune_status(
"port": port,
});
- let text = match result {
- Ok(()) => HANDLEBARS.render("prune_ok_template", &data)?,
+ let (template, severity) = match result {
+ Ok(()) => ("prune-ok", Severity::Info),
Err(err) => {
data["error"] = err.to_string().into();
- HANDLEBARS.render("prune_err_template", &data)?
+ ("prune-err", Severity::Error)
}
};
- let subject = match result {
- Ok(()) => format!("Pruning datastore '{store}' successful"),
- Err(_) => format!("Pruning datastore '{store}' failed"),
- };
+ let metadata = HashMap::from([
+ ("datastore".into(), store.into()),
+ ("hostname".into(), proxmox_sys::nodename().into()),
+ ("type".into(), "prune".into()),
+ ]);
- send_job_status_mail(&email, &subject, &text)?;
+ let notification = Notification::from_template(severity, template, data, metadata);
+
+ let (email, notify, mode) = lookup_datastore_notify_settings(store);
+ match mode {
+ NotificationMode::LegacySendmail => {
+ let notify = notify.prune.unwrap_or(Notify::Error);
+
+ if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
+ return Ok(());
+ }
+
+ if let Some(email) = email {
+ send_sendmail_legacy_notification(notification, &email)?;
+ }
+ }
+ NotificationMode::NotificationSystem => {
+ send_notification(notification)?;
+ }
+ }
Ok(())
}
diff --git a/templates/Makefile b/templates/Makefile
index 7d4cb19f..1f556aba 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -5,6 +5,10 @@ NOTIFICATION_TEMPLATES= \
default/gc-ok-body.txt.hbs \
default/gc-err-subject.txt.hbs \
default/gc-ok-subject.txt.hbs \
+ default/prune-err-body.txt.hbs \
+ default/prune-ok-body.txt.hbs \
+ default/prune-err-subject.txt.hbs \
+ default/prune-ok-subject.txt.hbs \
default/test-body.txt.hbs \
default/test-body.html.hbs \
default/test-subject.txt.hbs \
diff --git a/templates/default/prune-err-body.txt.hbs b/templates/default/prune-err-body.txt.hbs
new file mode 100644
index 00000000..0973c3d9
--- /dev/null
+++ b/templates/default/prune-err-body.txt.hbs
@@ -0,0 +1,10 @@
+
+Job ID: {{jobname}}
+Datastore: {{store}}
+
+Pruning failed: {{error}}
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
diff --git a/templates/default/prune-err-subject.txt.hbs b/templates/default/prune-err-subject.txt.hbs
new file mode 100644
index 00000000..836ae722
--- /dev/null
+++ b/templates/default/prune-err-subject.txt.hbs
@@ -0,0 +1 @@
+Pruning datastore '{{ store }}' failed
diff --git a/templates/default/prune-ok-body.txt.hbs b/templates/default/prune-ok-body.txt.hbs
new file mode 100644
index 00000000..b7e449e3
--- /dev/null
+++ b/templates/default/prune-ok-body.txt.hbs
@@ -0,0 +1,10 @@
+
+Job ID: {{jobname}}
+Datastore: {{store}}
+
+Pruning successful.
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#DataStore-{{store}}>
diff --git a/templates/default/prune-ok-subject.txt.hbs b/templates/default/prune-ok-subject.txt.hbs
new file mode 100644
index 00000000..3227a062
--- /dev/null
+++ b/templates/default/prune-ok-subject.txt.hbs
@@ -0,0 +1 @@
+Pruning datastore '{{ store }}' successful
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 23/43] server: notifications: send verify notifications via notification system
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (21 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 22/43] server: notifications: send prune " Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 24/43] server: notifications: send sync " Lukas Wagner
` (19 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
If the `notification-mode` parameter is set to `legacy-sendmail`, then
we still use the new infrastructure, but don't consider the
notification config and use a hard-coded sendmail endpoint directly.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
debian/proxmox-backup-server.install | 4 +
src/server/notifications.rs | 87 ++++++--------------
src/server/verify_job.rs | 11 +--
templates/Makefile | 4 +
templates/default/verify-err-body.txt.hbs | 14 ++++
templates/default/verify-err-subject.txt.hbs | 1 +
templates/default/verify-ok-body.txt.hbs | 10 +++
templates/default/verify-ok-subject.txt.hbs | 1 +
8 files changed, 63 insertions(+), 69 deletions(-)
create mode 100644 templates/default/verify-err-body.txt.hbs
create mode 100644 templates/default/verify-err-subject.txt.hbs
create mode 100644 templates/default/verify-ok-body.txt.hbs
create mode 100644 templates/default/verify-ok-subject.txt.hbs
diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install
index 7b8183dd..dfe671a6 100644
--- a/debian/proxmox-backup-server.install
+++ b/debian/proxmox-backup-server.install
@@ -52,3 +52,7 @@ usr/share/proxmox-backup/templates/default/prune-ok-subject.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.html.hbs
usr/share/proxmox-backup/templates/default/test-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/verify-err-body.txt.hbs
+usr/share/proxmox-backup/templates/default/verify-ok-body.txt.hbs
+usr/share/proxmox-backup/templates/default/verify-err-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/verify-ok-subject.txt.hbs
diff --git a/src/server/notifications.rs b/src/server/notifications.rs
index 4dcde943..b9b57160 100644
--- a/src/server/notifications.rs
+++ b/src/server/notifications.rs
@@ -23,38 +23,6 @@ use proxmox_notify::{Endpoint, Notification, Severity};
const SPOOL_DIR: &str = concatcp!(pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR, "/notifications");
-const VERIFY_OK_TEMPLATE: &str = r###"
-
-Job ID: {{job.id}}
-Datastore: {{job.store}}
-
-Verification successful.
-
-
-Please visit the web interface for further details:
-
-<https://{{fqdn}}:{{port}}/#DataStore-{{job.store}}>
-
-"###;
-
-const VERIFY_ERR_TEMPLATE: &str = r###"
-
-Job ID: {{job.id}}
-Datastore: {{job.store}}
-
-Verification failed on these snapshots/groups:
-
-{{#each errors}}
- {{this~}}
-{{/each}}
-
-
-Please visit the web interface for further details:
-
-<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
-
-"###;
-
const SYNC_OK_TEMPLATE: &str = r###"
Job ID: {{job.id}}
@@ -189,9 +157,6 @@ lazy_static::lazy_static! {
hb.set_strict_mode(true);
hb.register_escape_fn(handlebars::no_escape);
- hb.register_template_string("verify_ok_template", VERIFY_OK_TEMPLATE)?;
- hb.register_template_string("verify_err_template", VERIFY_ERR_TEMPLATE)?;
-
hb.register_template_string("sync_ok_template", SYNC_OK_TEMPLATE)?;
hb.register_template_string("sync_err_template", SYNC_ERR_TEMPLATE)?;
@@ -417,8 +382,6 @@ pub fn send_gc_status(
}
pub fn send_verify_status(
- email: &str,
- notify: DatastoreNotify,
job: VerificationJobConfig,
result: &Result<Vec<String>, Error>,
) -> Result<(), Error> {
@@ -429,39 +392,45 @@ pub fn send_verify_status(
"port": port,
});
- let mut result_is_ok = false;
-
- let text = match result {
- Ok(errors) if errors.is_empty() => {
- result_is_ok = true;
- HANDLEBARS.render("verify_ok_template", &data)?
- }
+ let (template, severity) = match result {
+ Ok(errors) if errors.is_empty() => ("verify-ok", Severity::Info),
Ok(errors) => {
data["errors"] = json!(errors);
- HANDLEBARS.render("verify_err_template", &data)?
+ ("verify-err", Severity::Error)
}
Err(_) => {
- // aborted job - do not send any email
+ // aborted job - do not send any notification
return Ok(());
}
};
- match notify.verify {
- None => { /* send notifications by default */ }
- Some(notify) => {
- if notify == Notify::Never || (result_is_ok && notify == Notify::Error) {
+ let metadata = HashMap::from([
+ ("verification-job".into(), job.id.clone()),
+ ("datastore".into(), job.store.clone()),
+ ("hostname".into(), proxmox_sys::nodename().into()),
+ ("type".into(), "verify".into()),
+ ]);
+
+ let notification = Notification::from_template(severity, template, data, metadata);
+
+ let (email, notify, mode) = lookup_datastore_notify_settings(&job.store);
+ match mode {
+ NotificationMode::LegacySendmail => {
+ let notify = notify.verify.unwrap_or(Notify::Always);
+
+ if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
return Ok(());
}
+
+ if let Some(email) = email {
+ send_sendmail_legacy_notification(notification, &email)?;
+ }
+ }
+ NotificationMode::NotificationSystem => {
+ send_notification(notification)?;
}
}
- let subject = match result {
- Ok(errors) if errors.is_empty() => format!("Verify Datastore '{}' successful", job.store),
- _ => format!("Verify Datastore '{}' failed", job.store),
- };
-
- send_job_status_mail(email, &subject, &text)?;
-
Ok(())
}
@@ -487,6 +456,7 @@ pub fn send_prune_status(
};
let metadata = HashMap::from([
+ ("prune-job".into(), jobname.to_string()),
("datastore".into(), store.into()),
("hostname".into(), proxmox_sys::nodename().into()),
("type".into(), "prune".into()),
@@ -757,9 +727,6 @@ pub fn lookup_datastore_notify_settings(
#[test]
fn test_template_register() {
- assert!(HANDLEBARS.has_template("verify_ok_template"));
- assert!(HANDLEBARS.has_template("verify_err_template"));
-
assert!(HANDLEBARS.has_template("sync_ok_template"));
assert!(HANDLEBARS.has_template("sync_err_template"));
diff --git a/src/server/verify_job.rs b/src/server/verify_job.rs
index fed80e5c..f3cf2277 100644
--- a/src/server/verify_job.rs
+++ b/src/server/verify_job.rs
@@ -23,9 +23,6 @@ pub fn do_verification_job(
let outdated_after = verification_job.outdated_after;
let ignore_verified_snapshots = verification_job.ignore_verified.unwrap_or(true);
- let (email, notify, _) =
- crate::server::lookup_datastore_notify_settings(&verification_job.store);
-
// FIXME encode namespace here for filter/ACL check?
let job_id = format!("{}:{}", &verification_job.store, job.jobname());
let worker_type = job.jobtype().to_string();
@@ -79,12 +76,8 @@ pub fn do_verification_job(
eprintln!("could not finish job state for {}: {}", job.jobtype(), 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);
- }
+ if let Err(err) = crate::server::send_verify_status(verification_job, &result) {
+ eprintln!("send verify notification failed: {err}");
}
job_result
diff --git a/templates/Makefile b/templates/Makefile
index 1f556aba..f1adda9f 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -12,6 +12,10 @@ NOTIFICATION_TEMPLATES= \
default/test-body.txt.hbs \
default/test-body.html.hbs \
default/test-subject.txt.hbs \
+ default/verify-err-body.txt.hbs \
+ default/verify-ok-body.txt.hbs \
+ default/verify-err-subject.txt.hbs \
+ default/verify-ok-subject.txt.hbs \
all:
diff --git a/templates/default/verify-err-body.txt.hbs b/templates/default/verify-err-body.txt.hbs
new file mode 100644
index 00000000..d07b5ce0
--- /dev/null
+++ b/templates/default/verify-err-body.txt.hbs
@@ -0,0 +1,14 @@
+
+Job ID: {{job.id}}
+Datastore: {{job.store}}
+
+Verification failed on these snapshots/groups:
+
+{{#each errors}}
+ {{this~}}
+{{/each}}
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
diff --git a/templates/default/verify-err-subject.txt.hbs b/templates/default/verify-err-subject.txt.hbs
new file mode 100644
index 00000000..00a2d07f
--- /dev/null
+++ b/templates/default/verify-err-subject.txt.hbs
@@ -0,0 +1 @@
+Verify Datastore '{{ job.store }}' failed
diff --git a/templates/default/verify-ok-body.txt.hbs b/templates/default/verify-ok-body.txt.hbs
new file mode 100644
index 00000000..7560582e
--- /dev/null
+++ b/templates/default/verify-ok-body.txt.hbs
@@ -0,0 +1,10 @@
+
+Job ID: {{job.id}}
+Datastore: {{job.store}}
+
+Verification successful.
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#DataStore-{{job.store}}>
diff --git a/templates/default/verify-ok-subject.txt.hbs b/templates/default/verify-ok-subject.txt.hbs
new file mode 100644
index 00000000..6020874c
--- /dev/null
+++ b/templates/default/verify-ok-subject.txt.hbs
@@ -0,0 +1 @@
+Verify Datastore '{{ job.store }}' successful
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 24/43] server: notifications: send sync notifications via notification system
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (22 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 23/43] server: notifications: send verify " Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 25/43] server: notifications: send update " Lukas Wagner
` (18 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
If the `notification-mode` parameter is set to `legacy-sendmail`, then
we still use the new infrastructure, but don't consider the
notification config and use a hard-coded sendmail endpoint directly.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
debian/proxmox-backup-server.install | 4 +
src/api2/pull.rs | 10 +-
src/server/notifications.rs | 102 ++++++---------------
templates/Makefile | 4 +
templates/default/sync-err-body.txt.hbs | 14 +++
templates/default/sync-err-subject.txt.hbs | 5 +
templates/default/sync-ok-body.txt.hbs | 14 +++
templates/default/sync-ok-subject.txt.hbs | 5 +
8 files changed, 76 insertions(+), 82 deletions(-)
create mode 100644 templates/default/sync-err-body.txt.hbs
create mode 100644 templates/default/sync-err-subject.txt.hbs
create mode 100644 templates/default/sync-ok-body.txt.hbs
create mode 100644 templates/default/sync-ok-subject.txt.hbs
diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install
index dfe671a6..86e2b543 100644
--- a/debian/proxmox-backup-server.install
+++ b/debian/proxmox-backup-server.install
@@ -49,6 +49,10 @@ usr/share/proxmox-backup/templates/default/prune-err-body.txt.hbs
usr/share/proxmox-backup/templates/default/prune-ok-body.txt.hbs
usr/share/proxmox-backup/templates/default/prune-err-subject.txt.hbs
usr/share/proxmox-backup/templates/default/prune-ok-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/sync-err-body.txt.hbs
+usr/share/proxmox-backup/templates/default/sync-ok-body.txt.hbs
+usr/share/proxmox-backup/templates/default/sync-err-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/sync-ok-subject.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.html.hbs
usr/share/proxmox-backup/templates/default/test-subject.txt.hbs
diff --git a/src/api2/pull.rs b/src/api2/pull.rs
index 7fe2267a..5d02510c 100644
--- a/src/api2/pull.rs
+++ b/src/api2/pull.rs
@@ -114,8 +114,6 @@ pub fn do_sync_job(
bail!("can't sync to same datastore");
}
- let (email, notify, _) = crate::server::lookup_datastore_notify_settings(&sync_job.store);
-
let upid_str = WorkerTask::spawn(
&worker_type,
Some(job_id.clone()),
@@ -194,12 +192,8 @@ pub fn do_sync_job(
}
}
- if let Some(email) = email {
- if let Err(err) =
- crate::server::send_sync_status(&email, notify, &sync_job2, &result)
- {
- eprintln!("send sync notification failed: {}", err);
- }
+ if let Err(err) = crate::server::send_sync_status(&sync_job2, &result) {
+ eprintln!("send sync notification failed: {err}");
}
result
diff --git a/src/server/notifications.rs b/src/server/notifications.rs
index b9b57160..3e5c9ae4 100644
--- a/src/server/notifications.rs
+++ b/src/server/notifications.rs
@@ -23,44 +23,6 @@ use proxmox_notify::{Endpoint, Notification, Severity};
const SPOOL_DIR: &str = concatcp!(pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR, "/notifications");
-const SYNC_OK_TEMPLATE: &str = r###"
-
-Job ID: {{job.id}}
-Datastore: {{job.store}}
-{{#if job.remote~}}
-Remote: {{job.remote}}
-Remote Store: {{job.remote-store}}
-{{else~}}
-Local Source Store: {{job.remote-store}}
-{{/if}}
-Synchronization successful.
-
-
-Please visit the web interface for further details:
-
-<https://{{fqdn}}:{{port}}/#DataStore-{{job.store}}>
-
-"###;
-
-const SYNC_ERR_TEMPLATE: &str = r###"
-
-Job ID: {{job.id}}
-Datastore: {{job.store}}
-{{#if job.remote~}}
-Remote: {{job.remote}}
-Remote Store: {{job.remote-store}}
-{{else~}}
-Local Source Store: {{job.remote-store}}
-{{/if}}
-Synchronization failed: {{error}}
-
-
-Please visit the web interface for further details:
-
-<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
-
-"###;
-
const PACKAGE_UPDATES_TEMPLATE: &str = r###"
Proxmox Backup Server has the following updates available:
{{#each updates }}
@@ -157,9 +119,6 @@ lazy_static::lazy_static! {
hb.set_strict_mode(true);
hb.register_escape_fn(handlebars::no_escape);
- hb.register_template_string("sync_ok_template", SYNC_OK_TEMPLATE)?;
- hb.register_template_string("sync_err_template", SYNC_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)?;
@@ -485,21 +444,7 @@ pub fn send_prune_status(
Ok(())
}
-pub fn send_sync_status(
- email: &str,
- notify: DatastoreNotify,
- job: &SyncJobConfig,
- result: &Result<(), Error>,
-) -> Result<(), Error> {
- match notify.sync {
- None => { /* send notifications by default */ }
- Some(notify) => {
- if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
- return Ok(());
- }
- }
- }
-
+pub fn send_sync_status(job: &SyncJobConfig, result: &Result<(), Error>) -> Result<(), Error> {
let (fqdn, port) = get_server_url();
let mut data = json!({
"job": job,
@@ -507,28 +452,40 @@ pub fn send_sync_status(
"port": port,
});
- let text = match result {
- Ok(()) => HANDLEBARS.render("sync_ok_template", &data)?,
+ let (template, severity) = match result {
+ Ok(()) => ("sync-ok", Severity::Info),
Err(err) => {
data["error"] = err.to_string().into();
- HANDLEBARS.render("sync_err_template", &data)?
+ ("sync-err", Severity::Error)
}
};
- let tmp_src_string;
- let source_str = if let Some(remote) = &job.remote {
- tmp_src_string = format!("Sync remote '{}'", remote);
- &tmp_src_string
- } else {
- "Sync local"
- };
+ let metadata = HashMap::from([
+ ("sync-job".into(), job.id.clone()),
+ ("datastore".into(), job.store.clone()),
+ ("hostname".into(), proxmox_sys::nodename().into()),
+ ("type".into(), "sync".into()),
+ ]);
- let subject = match result {
- Ok(()) => format!("{} datastore '{}' successful", source_str, job.remote_store,),
- Err(_) => format!("{} datastore '{}' failed", source_str, job.remote_store,),
- };
+ let notification = Notification::from_template(severity, template, data, metadata);
- send_job_status_mail(email, &subject, &text)?;
+ let (email, notify, mode) = lookup_datastore_notify_settings(&job.store);
+ match mode {
+ NotificationMode::LegacySendmail => {
+ let notify = notify.prune.unwrap_or(Notify::Error);
+
+ if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
+ return Ok(());
+ }
+
+ if let Some(email) = email {
+ send_sendmail_legacy_notification(notification, &email)?;
+ }
+ }
+ NotificationMode::NotificationSystem => {
+ send_notification(notification)?;
+ }
+ }
Ok(())
}
@@ -727,9 +684,6 @@ pub fn lookup_datastore_notify_settings(
#[test]
fn test_template_register() {
- assert!(HANDLEBARS.has_template("sync_ok_template"));
- assert!(HANDLEBARS.has_template("sync_err_template"));
-
assert!(HANDLEBARS.has_template("tape_backup_ok_template"));
assert!(HANDLEBARS.has_template("tape_backup_err_template"));
diff --git a/templates/Makefile b/templates/Makefile
index f1adda9f..41cdd2da 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -9,6 +9,10 @@ NOTIFICATION_TEMPLATES= \
default/prune-ok-body.txt.hbs \
default/prune-err-subject.txt.hbs \
default/prune-ok-subject.txt.hbs \
+ default/sync-err-body.txt.hbs \
+ default/sync-ok-body.txt.hbs \
+ default/sync-err-subject.txt.hbs \
+ default/sync-ok-subject.txt.hbs \
default/test-body.txt.hbs \
default/test-body.html.hbs \
default/test-subject.txt.hbs \
diff --git a/templates/default/sync-err-body.txt.hbs b/templates/default/sync-err-body.txt.hbs
new file mode 100644
index 00000000..a56d9d22
--- /dev/null
+++ b/templates/default/sync-err-body.txt.hbs
@@ -0,0 +1,14 @@
+Job ID: {{job.id}}
+Datastore: {{job.store}}
+{{#if job.remote~}}
+Remote: {{job.remote}}
+Remote Store: {{job.remote-store}}
+{{else~}}
+Local Source Store: {{job.remote-store}}
+{{/if}}
+Synchronization failed: {{error}}
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
diff --git a/templates/default/sync-err-subject.txt.hbs b/templates/default/sync-err-subject.txt.hbs
new file mode 100644
index 00000000..a1464802
--- /dev/null
+++ b/templates/default/sync-err-subject.txt.hbs
@@ -0,0 +1,5 @@
+{{#if job.remote~}}
+Sync remote '{{ job.remote }}' datastore '{{ job.remote-store }}' failed
+{{else~}}
+Sync local datastore '{{ job.remote-store }}' failed
+{{/if}}
diff --git a/templates/default/sync-ok-body.txt.hbs b/templates/default/sync-ok-body.txt.hbs
new file mode 100644
index 00000000..25c4b33b
--- /dev/null
+++ b/templates/default/sync-ok-body.txt.hbs
@@ -0,0 +1,14 @@
+Job ID: {{job.id}}
+Datastore: {{job.store}}
+{{#if job.remote~}}
+Remote: {{job.remote}}
+Remote Store: {{job.remote-store}}
+{{else~}}
+Local Source Store: {{job.remote-store}}
+{{/if}}
+Synchronization successful.
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#DataStore-{{job.store}}>
diff --git a/templates/default/sync-ok-subject.txt.hbs b/templates/default/sync-ok-subject.txt.hbs
new file mode 100644
index 00000000..76616b5c
--- /dev/null
+++ b/templates/default/sync-ok-subject.txt.hbs
@@ -0,0 +1,5 @@
+{{#if job.remote~}}
+Sync remote '{{ job.remote }}' datastore '{{ job.remote-store }}' successful
+{{else~}}
+Sync local datastore '{{ job.remote-store }}' successful
+{{/if}}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 25/43] server: notifications: send update notifications via notification system
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (23 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 24/43] server: notifications: send sync " Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 26/43] server: notifications: send acme " Lukas Wagner
` (17 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
debian/proxmox-backup-server.install | 2 +
src/server/notifications.rs | 47 +++++++------------
templates/Makefile | 2 +
.../default/package-updates-body.txt.hbs | 8 ++++
.../default/package-updates-subject.txt.hbs | 1 +
5 files changed, 29 insertions(+), 31 deletions(-)
create mode 100644 templates/default/package-updates-body.txt.hbs
create mode 100644 templates/default/package-updates-subject.txt.hbs
diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install
index 86e2b543..52a01ca5 100644
--- a/debian/proxmox-backup-server.install
+++ b/debian/proxmox-backup-server.install
@@ -45,6 +45,8 @@ usr/share/proxmox-backup/templates/default/gc-err-body.txt.hbs
usr/share/proxmox-backup/templates/default/gc-ok-body.txt.hbs
usr/share/proxmox-backup/templates/default/gc-err-subject.txt.hbs
usr/share/proxmox-backup/templates/default/gc-ok-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/package-updates-body.txt.hbs
+usr/share/proxmox-backup/templates/default/package-updates-subject.txt.hbs
usr/share/proxmox-backup/templates/default/prune-err-body.txt.hbs
usr/share/proxmox-backup/templates/default/prune-ok-body.txt.hbs
usr/share/proxmox-backup/templates/default/prune-err-subject.txt.hbs
diff --git a/src/server/notifications.rs b/src/server/notifications.rs
index 3e5c9ae4..991ee11e 100644
--- a/src/server/notifications.rs
+++ b/src/server/notifications.rs
@@ -23,18 +23,6 @@ use proxmox_notify::{Endpoint, Notification, Severity};
const SPOOL_DIR: &str = concatcp!(pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR, "/notifications");
-const PACKAGE_UPDATES_TEMPLATE: &str = r###"
-Proxmox Backup Server has the following updates available:
-{{#each updates }}
- {{Package}}: {{OldVersion}} -> {{Version~}}
-{{/each }}
-
-To upgrade visit the web interface:
-
-<https://{{fqdn}}:{{port}}/#pbsServerAdministration:updates>
-
-"###;
-
const TAPE_BACKUP_OK_TEMPLATE: &str = r###"
{{#if id ~}}
@@ -122,8 +110,6 @@ lazy_static::lazy_static! {
hb.register_template_string("tape_backup_ok_template", TAPE_BACKUP_OK_TEMPLATE)?;
hb.register_template_string("tape_backup_err_template", TAPE_BACKUP_ERR_TEMPLATE)?;
- hb.register_template_string("package_update_template", PACKAGE_UPDATES_TEMPLATE)?;
-
hb.register_template_string("certificate_renewal_err_template", ACME_CERTIFICATE_ERR_RENEWAL)?;
Ok(())
@@ -583,24 +569,25 @@ fn get_server_url() -> (String, usize) {
}
pub fn send_updates_available(updates: &[&APTUpdateInfo]) -> Result<(), Error> {
- // update mails always go to the root@pam configured email..
- if let Some(email) = lookup_user_email(Userid::root_userid()) {
- let nodename = proxmox_sys::nodename();
- let subject = format!("New software packages available ({nodename})");
+ let (fqdn, port) = get_server_url();
+ let hostname = proxmox_sys::nodename().to_string();
- let (fqdn, port) = get_server_url();
+ let data = json!({
+ "fqdn": fqdn,
+ "hostname": &hostname,
+ "port": port,
+ "updates": updates,
+ });
- let text = HANDLEBARS.render(
- "package_update_template",
- &json!({
- "fqdn": fqdn,
- "port": port,
- "updates": updates,
- }),
- )?;
+ let metadata = HashMap::from([
+ ("hostname".into(), hostname),
+ ("type".into(), "package-updates".into()),
+ ]);
- send_job_status_mail(&email, &subject, &text)?;
- }
+ let notification =
+ Notification::from_template(Severity::Info, "package-updates", data, metadata);
+
+ send_notification(notification)?;
Ok(())
}
@@ -687,7 +674,5 @@ fn test_template_register() {
assert!(HANDLEBARS.has_template("tape_backup_ok_template"));
assert!(HANDLEBARS.has_template("tape_backup_err_template"));
- assert!(HANDLEBARS.has_template("package_update_template"));
-
assert!(HANDLEBARS.has_template("certificate_renewal_err_template"));
}
diff --git a/templates/Makefile b/templates/Makefile
index 41cdd2da..56965400 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -5,6 +5,8 @@ NOTIFICATION_TEMPLATES= \
default/gc-ok-body.txt.hbs \
default/gc-err-subject.txt.hbs \
default/gc-ok-subject.txt.hbs \
+ default/package-updates-body.txt.hbs \
+ default/package-updates-subject.txt.hbs \
default/prune-err-body.txt.hbs \
default/prune-ok-body.txt.hbs \
default/prune-err-subject.txt.hbs \
diff --git a/templates/default/package-updates-body.txt.hbs b/templates/default/package-updates-body.txt.hbs
new file mode 100644
index 00000000..62f9c7c4
--- /dev/null
+++ b/templates/default/package-updates-body.txt.hbs
@@ -0,0 +1,8 @@
+Proxmox Backup Server has the following updates available:
+{{#each updates }}
+ {{Package}}: {{OldVersion}} -> {{Version~}}
+{{/each }}
+
+To upgrade visit the web interface:
+
+<https://{{fqdn}}:{{port}}/#pbsServerAdministration:updates>
diff --git a/templates/default/package-updates-subject.txt.hbs b/templates/default/package-updates-subject.txt.hbs
new file mode 100644
index 00000000..c8a775d5
--- /dev/null
+++ b/templates/default/package-updates-subject.txt.hbs
@@ -0,0 +1 @@
+New software packages available ({{ hostname }})
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 26/43] server: notifications: send acme notifications via notification system
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (24 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 25/43] server: notifications: send update " Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 27/43] server: notifications: send tape " Lukas Wagner
` (16 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
debian/proxmox-backup-server.install | 2 ++
src/server/notifications.rs | 41 +++++++---------------
templates/Makefile | 24 +++++++------
templates/default/acme-err-body.txt.hbs | 7 ++++
templates/default/acme-err-subject.txt.hbs | 1 +
5 files changed, 35 insertions(+), 40 deletions(-)
create mode 100644 templates/default/acme-err-body.txt.hbs
create mode 100644 templates/default/acme-err-subject.txt.hbs
diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install
index 52a01ca5..17951780 100644
--- a/debian/proxmox-backup-server.install
+++ b/debian/proxmox-backup-server.install
@@ -41,6 +41,8 @@ usr/share/zsh/vendor-completions/_pmtx
usr/share/zsh/vendor-completions/_proxmox-backup-debug
usr/share/zsh/vendor-completions/_proxmox-backup-manager
usr/share/zsh/vendor-completions/_proxmox-tape
+usr/share/proxmox-backup/templates/default/acme-err-body.txt.hbs
+usr/share/proxmox-backup/templates/default/acme-err-subject.txt.hbs
usr/share/proxmox-backup/templates/default/gc-err-body.txt.hbs
usr/share/proxmox-backup/templates/default/gc-ok-body.txt.hbs
usr/share/proxmox-backup/templates/default/gc-err-subject.txt.hbs
diff --git a/src/server/notifications.rs b/src/server/notifications.rs
index 991ee11e..306c228d 100644
--- a/src/server/notifications.rs
+++ b/src/server/notifications.rs
@@ -86,18 +86,6 @@ Please visit the web interface for further details:
"###;
-const ACME_CERTIFICATE_ERR_RENEWAL: &str = r###"
-
-Proxmox Backup Server was not able to renew a TLS certificate.
-
-Error: {{error}}
-
-Please visit the web interface for further details:
-
-<https://{{fqdn}}:{{port}}/#pbsCertificateConfiguration>
-
-"###;
-
lazy_static::lazy_static! {
static ref HANDLEBARS: Handlebars<'static> = {
@@ -110,8 +98,6 @@ lazy_static::lazy_static! {
hb.register_template_string("tape_backup_ok_template", TAPE_BACKUP_OK_TEMPLATE)?;
hb.register_template_string("tape_backup_err_template", TAPE_BACKUP_ERR_TEMPLATE)?;
- hb.register_template_string("certificate_renewal_err_template", ACME_CERTIFICATE_ERR_RENEWAL)?;
-
Ok(())
});
@@ -598,23 +584,22 @@ pub fn send_certificate_renewal_mail(result: &Result<(), Error>) -> Result<(), E
_ => return Ok(()),
};
- if let Some(email) = lookup_user_email(Userid::root_userid()) {
- let (fqdn, port) = get_server_url();
+ let (fqdn, port) = get_server_url();
- let text = HANDLEBARS.render(
- "certificate_renewal_err_template",
- &json!({
- "fqdn": fqdn,
- "port": port,
- "error": error,
- }),
- )?;
+ let data = json!({
+ "fqdn": fqdn,
+ "port": port,
+ "error": error,
+ });
- let subject = "Could not renew certificate";
+ let metadata = HashMap::from([
+ ("hostname".into(), proxmox_sys::nodename().into()),
+ ("type".into(), "acme".into()),
+ ]);
- send_job_status_mail(&email, subject, &text)?;
- }
+ let notification = Notification::from_template(Severity::Info, "acme-err", data, metadata);
+ send_notification(notification)?;
Ok(())
}
@@ -673,6 +658,4 @@ pub fn lookup_datastore_notify_settings(
fn test_template_register() {
assert!(HANDLEBARS.has_template("tape_backup_ok_template"));
assert!(HANDLEBARS.has_template("tape_backup_err_template"));
-
- assert!(HANDLEBARS.has_template("certificate_renewal_err_template"));
}
diff --git a/templates/Makefile b/templates/Makefile
index 56965400..824d28d9 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -1,12 +1,14 @@
include ../defines.mk
-NOTIFICATION_TEMPLATES= \
- default/gc-err-body.txt.hbs \
- default/gc-ok-body.txt.hbs \
- default/gc-err-subject.txt.hbs \
- default/gc-ok-subject.txt.hbs \
- default/package-updates-body.txt.hbs \
- default/package-updates-subject.txt.hbs \
+NOTIFICATION_TEMPLATES= \
+ default/acme-err-body.txt.hbs \
+ default/acme-err-subject.txt.hbs \
+ default/gc-err-body.txt.hbs \
+ default/gc-ok-body.txt.hbs \
+ default/gc-err-subject.txt.hbs \
+ default/gc-ok-subject.txt.hbs \
+ default/package-updates-body.txt.hbs \
+ default/package-updates-subject.txt.hbs \
default/prune-err-body.txt.hbs \
default/prune-ok-body.txt.hbs \
default/prune-err-subject.txt.hbs \
@@ -14,10 +16,10 @@ NOTIFICATION_TEMPLATES= \
default/sync-err-body.txt.hbs \
default/sync-ok-body.txt.hbs \
default/sync-err-subject.txt.hbs \
- default/sync-ok-subject.txt.hbs \
- default/test-body.txt.hbs \
- default/test-body.html.hbs \
- default/test-subject.txt.hbs \
+ default/sync-ok-subject.txt.hbs \
+ default/test-body.txt.hbs \
+ default/test-body.html.hbs \
+ default/test-subject.txt.hbs \
default/verify-err-body.txt.hbs \
default/verify-ok-body.txt.hbs \
default/verify-err-subject.txt.hbs \
diff --git a/templates/default/acme-err-body.txt.hbs b/templates/default/acme-err-body.txt.hbs
new file mode 100644
index 00000000..3cbfea4a
--- /dev/null
+++ b/templates/default/acme-err-body.txt.hbs
@@ -0,0 +1,7 @@
+Proxmox Backup Server was not able to renew a TLS certificate.
+
+Error: {{error}}
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#pbsCertificateConfiguration>
diff --git a/templates/default/acme-err-subject.txt.hbs b/templates/default/acme-err-subject.txt.hbs
new file mode 100644
index 00000000..3cf4fe45
--- /dev/null
+++ b/templates/default/acme-err-subject.txt.hbs
@@ -0,0 +1 @@
+Could not renew certificate
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 27/43] server: notifications: send tape notifications via notification system
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (25 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 26/43] server: notifications: send acme " Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 28/43] ui: add notification config panel Lukas Wagner
` (15 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
If the `notification-mode` parameter is set to `legacy-sendmail`, then
we still use the new infrastructure, but don't consider the
notification config and use a hard-coded sendmail endpoint directly.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
debian/proxmox-backup-server.install | 6 +
src/api2/tape/backup.rs | 62 ++---
src/api2/tape/restore.rs | 46 ++--
src/server/notifications.rs | 213 +++++-------------
src/tape/drive/mod.rs | 22 +-
src/tape/mod.rs | 27 +++
src/tape/pool_writer/mod.rs | 11 +-
templates/Makefile | 6 +
.../default/tape-backup-err-body.txt.hbs | 26 +++
.../default/tape-backup-err-subject.txt.hbs | 5 +
templates/default/tape-backup-ok-body.txt.hbs | 27 +++
.../default/tape-backup-ok-subject.txt.hbs | 5 +
templates/default/tape-load-body.txt.hbs | 15 ++
templates/default/tape-load-subject.txt.hbs | 1 +
14 files changed, 244 insertions(+), 228 deletions(-)
create mode 100644 templates/default/tape-backup-err-body.txt.hbs
create mode 100644 templates/default/tape-backup-err-subject.txt.hbs
create mode 100644 templates/default/tape-backup-ok-body.txt.hbs
create mode 100644 templates/default/tape-backup-ok-subject.txt.hbs
create mode 100644 templates/default/tape-load-body.txt.hbs
create mode 100644 templates/default/tape-load-subject.txt.hbs
diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install
index 17951780..df7d68ee 100644
--- a/debian/proxmox-backup-server.install
+++ b/debian/proxmox-backup-server.install
@@ -57,6 +57,12 @@ usr/share/proxmox-backup/templates/default/sync-err-body.txt.hbs
usr/share/proxmox-backup/templates/default/sync-ok-body.txt.hbs
usr/share/proxmox-backup/templates/default/sync-err-subject.txt.hbs
usr/share/proxmox-backup/templates/default/sync-ok-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/tape-backup-err-body.txt.hbs
+usr/share/proxmox-backup/templates/default/tape-backup-err-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/tape-backup-ok-body.txt.hbs
+usr/share/proxmox-backup/templates/default/tape-backup-ok-subject.txt.hbs
+usr/share/proxmox-backup/templates/default/tape-load-body.txt.hbs
+usr/share/proxmox-backup/templates/default/tape-load-subject.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.txt.hbs
usr/share/proxmox-backup/templates/default/test-body.html.hbs
usr/share/proxmox-backup/templates/default/test-subject.txt.hbs
diff --git a/src/api2/tape/backup.rs b/src/api2/tape/backup.rs
index 28d7e720..896e809b 100644
--- a/src/api2/tape/backup.rs
+++ b/src/api2/tape/backup.rs
@@ -10,7 +10,7 @@ use proxmox_sys::{task_log, task_warn, WorkerTaskContext};
use pbs_api_types::{
print_ns_and_snapshot, print_store_and_ns, Authid, MediaPoolConfig, Operation,
- TapeBackupJobConfig, TapeBackupJobSetup, TapeBackupJobStatus, Userid, JOB_ID_SCHEMA,
+ TapeBackupJobConfig, TapeBackupJobSetup, TapeBackupJobStatus, JOB_ID_SCHEMA,
PRIV_DATASTORE_READ, PRIV_TAPE_AUDIT, PRIV_TAPE_WRITE, UPID_SCHEMA,
};
@@ -19,10 +19,11 @@ use pbs_datastore::backup_info::{BackupDir, BackupInfo};
use pbs_datastore::{DataStore, StoreProgress};
use proxmox_rest_server::WorkerTask;
+use crate::tape::TapeNotificationMode;
use crate::{
server::{
jobstate::{compute_schedule_status, Job, JobState},
- lookup_user_email, TapeBackupJobSummary,
+ TapeBackupJobSummary,
},
tape::{
changer::update_changer_online_status,
@@ -162,12 +163,6 @@ pub fn do_tape_backup_job(
Some(lock_tape_device(&drive_config, &setup.drive)?)
};
- let notify_user = setup
- .notify_user
- .as_ref()
- .unwrap_or_else(|| Userid::root_userid());
- let email = lookup_user_email(notify_user);
-
let upid_str = WorkerTask::new_thread(
&worker_type,
Some(job_id.clone()),
@@ -206,7 +201,6 @@ pub fn do_tape_backup_job(
datastore,
&pool_config,
&setup,
- email.clone(),
&mut summary,
false,
)
@@ -214,16 +208,13 @@ pub fn do_tape_backup_job(
let status = worker.create_state(&job_result);
- if let Some(email) = email {
- if let Err(err) = crate::server::send_tape_backup_status(
- &email,
- Some(job.jobname()),
- &setup,
- &job_result,
- summary,
- ) {
- eprintln!("send tape backup notification failed: {}", err);
- }
+ if let Err(err) = crate::server::send_tape_backup_status(
+ Some(job.jobname()),
+ &setup,
+ &job_result,
+ summary,
+ ) {
+ eprintln!("send tape backup notification failed: {err}");
}
if let Err(err) = job.finish(status) {
@@ -328,12 +319,6 @@ pub fn backup(
let job_id = format!("{}:{}:{}", setup.store, setup.pool, setup.drive);
- let notify_user = setup
- .notify_user
- .as_ref()
- .unwrap_or_else(|| Userid::root_userid());
- let email = lookup_user_email(notify_user);
-
let upid_str = WorkerTask::new_thread(
"tape-backup",
Some(job_id),
@@ -349,21 +334,14 @@ pub fn backup(
datastore,
&pool_config,
&setup,
- email.clone(),
&mut summary,
force_media_set,
);
- if let Some(email) = email {
- if let Err(err) = crate::server::send_tape_backup_status(
- &email,
- None,
- &setup,
- &job_result,
- summary,
- ) {
- eprintln!("send tape backup notification failed: {}", err);
- }
+ if let Err(err) =
+ crate::server::send_tape_backup_status(None, &setup, &job_result, summary)
+ {
+ eprintln!("send tape backup notification failed: {err}");
}
// ignore errors
@@ -386,7 +364,6 @@ fn backup_worker(
datastore: Arc<DataStore>,
pool_config: &MediaPoolConfig,
setup: &TapeBackupJobSetup,
- email: Option<String>,
summary: &mut TapeBackupJobSummary,
force_media_set: bool,
) -> Result<(), Error> {
@@ -399,9 +376,16 @@ fn backup_worker(
let ns_magic = !root_namespace.is_root() || setup.max_depth != Some(0);
let pool = MediaPool::with_config(TAPE_STATUS_DIR, pool_config, changer_name, false)?;
+ let notification_mode = TapeNotificationMode::from(setup);
- let mut pool_writer =
- PoolWriter::new(pool, &setup.drive, worker, email, force_media_set, ns_magic)?;
+ let mut pool_writer = PoolWriter::new(
+ pool,
+ &setup.drive,
+ worker,
+ notification_mode,
+ force_media_set,
+ ns_magic,
+ )?;
let mut group_list = Vec::new();
let namespaces = datastore.recursive_iter_backup_ns_ok(root_namespace, setup.max_depth)?;
diff --git a/src/api2/tape/restore.rs b/src/api2/tape/restore.rs
index 8273c867..84557bce 100644
--- a/src/api2/tape/restore.rs
+++ b/src/api2/tape/restore.rs
@@ -18,9 +18,10 @@ use proxmox_uuid::Uuid;
use pbs_api_types::{
parse_ns_and_snapshot, print_ns_and_snapshot, Authid, BackupDir, BackupNamespace, CryptMode,
- Operation, TapeRestoreNamespace, Userid, DATASTORE_MAP_ARRAY_SCHEMA, DATASTORE_MAP_LIST_SCHEMA,
- DRIVE_NAME_SCHEMA, MAX_NAMESPACE_DEPTH, PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_MODIFY,
- PRIV_TAPE_READ, TAPE_RESTORE_NAMESPACE_SCHEMA, TAPE_RESTORE_SNAPSHOT_SCHEMA, UPID_SCHEMA,
+ NotificationMode, Operation, TapeRestoreNamespace, Userid, DATASTORE_MAP_ARRAY_SCHEMA,
+ DATASTORE_MAP_LIST_SCHEMA, DRIVE_NAME_SCHEMA, MAX_NAMESPACE_DEPTH, PRIV_DATASTORE_BACKUP,
+ PRIV_DATASTORE_MODIFY, PRIV_TAPE_READ, TAPE_RESTORE_NAMESPACE_SCHEMA,
+ TAPE_RESTORE_SNAPSHOT_SCHEMA, UPID_SCHEMA,
};
use pbs_config::CachedUserInfo;
use pbs_datastore::dynamic_index::DynamicIndexReader;
@@ -34,8 +35,8 @@ use pbs_tape::{
use proxmox_rest_server::WorkerTask;
use crate::backup::check_ns_modification_privs;
+use crate::tape::TapeNotificationMode;
use crate::{
- server::lookup_user_email,
tape::{
drive::{lock_tape_device, request_and_load_media, set_tape_device_state, TapeDriver},
file_formats::{
@@ -289,6 +290,10 @@ pub const ROUTER: Router = Router::new().post(&API_METHOD_RESTORE);
type: Userid,
optional: true,
},
+ "notification-mode": {
+ type: NotificationMode,
+ optional: true,
+ },
"snapshots": {
description: "List of snapshots.",
type: Array,
@@ -322,6 +327,7 @@ pub fn restore(
namespaces: Option<Vec<String>>,
media_set: String,
notify_user: Option<Userid>,
+ notification_mode: Option<NotificationMode>,
snapshots: Option<Vec<String>>,
owner: Option<Authid>,
rpcenv: &mut dyn RpcEnvironment,
@@ -329,6 +335,8 @@ pub fn restore(
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let user_info = CachedUserInfo::new()?;
+ let notification_mode = TapeNotificationMode::from((notify_user, notification_mode));
+
let mut store_map = DataStoreMap::try_from(store)
.map_err(|err| format_err!("cannot parse store mapping: {err}"))?;
let namespaces = if let Some(maps) = namespaces {
@@ -394,11 +402,6 @@ pub fn restore(
let restore_owner = owner.as_ref().unwrap_or(&auth_id);
- let email = notify_user
- .as_ref()
- .and_then(lookup_user_email)
- .or_else(|| lookup_user_email(&auth_id.clone().into()));
-
task_log!(worker, "Mediaset '{media_set}'");
task_log!(worker, "Pool: {pool}");
@@ -412,7 +415,7 @@ pub fn restore(
&drive,
store_map,
restore_owner,
- email,
+ ¬ification_mode,
user_info,
&auth_id,
)
@@ -425,7 +428,7 @@ pub fn restore(
&drive,
store_map,
restore_owner,
- email,
+ ¬ification_mode,
&auth_id,
)
};
@@ -452,7 +455,7 @@ fn restore_full_worker(
drive_name: &str,
store_map: DataStoreMap,
restore_owner: &Authid,
- email: Option<String>,
+ notification_mode: &TapeNotificationMode,
auth_id: &Authid,
) -> Result<(), Error> {
let members = inventory.compute_media_set_members(&media_set_uuid)?;
@@ -519,7 +522,7 @@ fn restore_full_worker(
&store_map,
&mut checked_chunks_map,
restore_owner,
- &email,
+ notification_mode,
auth_id,
)?;
}
@@ -635,7 +638,7 @@ fn restore_list_worker(
drive_name: &str,
store_map: DataStoreMap,
restore_owner: &Authid,
- email: Option<String>,
+ notification_mode: &TapeNotificationMode,
user_info: Arc<CachedUserInfo>,
auth_id: &Authid,
) -> Result<(), Error> {
@@ -779,7 +782,7 @@ fn restore_list_worker(
&drive_config,
drive_name,
&media_id.label,
- &email,
+ notification_mode,
)?;
file_list.sort_unstable();
@@ -833,7 +836,7 @@ fn restore_list_worker(
&drive_config,
drive_name,
&media_id.label,
- &email,
+ notification_mode,
)?;
restore_file_chunk_map(worker.clone(), &mut drive, &store_map, file_chunk_map)?;
}
@@ -1241,7 +1244,7 @@ pub fn request_and_restore_media(
store_map: &DataStoreMap,
checked_chunks_map: &mut HashMap<String, HashSet<[u8; 32]>>,
restore_owner: &Authid,
- email: &Option<String>,
+ notification_mode: &TapeNotificationMode,
auth_id: &Authid,
) -> Result<(), Error> {
let media_set_uuid = match media_id.media_set_label {
@@ -1249,8 +1252,13 @@ pub fn request_and_restore_media(
Some(ref set) => &set.uuid,
};
- let (mut drive, info) =
- request_and_load_media(&worker, drive_config, drive_name, &media_id.label, email)?;
+ let (mut drive, info) = request_and_load_media(
+ &worker,
+ drive_config,
+ drive_name,
+ &media_id.label,
+ notification_mode,
+ )?;
match info.media_set_label {
None => {
diff --git a/src/server/notifications.rs b/src/server/notifications.rs
index 306c228d..65cb871b 100644
--- a/src/server/notifications.rs
+++ b/src/server/notifications.rs
@@ -1,19 +1,17 @@
-use anyhow::Error;
-use const_format::concatcp;
-use serde_json::json;
use std::collections::HashMap;
use std::path::Path;
use std::time::{Duration, Instant};
-use handlebars::{Handlebars, TemplateError};
+use anyhow::Error;
+use const_format::concatcp;
use nix::unistd::Uid;
+use serde_json::json;
-use proxmox_lang::try_block;
use proxmox_notify::context::pbs::PBS_CONTEXT;
use proxmox_schema::ApiType;
-use proxmox_sys::email::sendmail;
use proxmox_sys::fs::{create_path, CreateOptions};
+use crate::tape::TapeNotificationMode;
use pbs_api_types::{
APTUpdateInfo, DataStoreConfig, DatastoreNotify, GarbageCollectionStatus, NotificationMode,
Notify, SyncJobConfig, TapeBackupJobSetup, User, Userid, VerificationJobConfig,
@@ -23,92 +21,6 @@ use proxmox_notify::{Endpoint, Notification, Severity};
const SPOOL_DIR: &str = concatcp!(pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR, "/notifications");
-const TAPE_BACKUP_OK_TEMPLATE: &str = r###"
-
-{{#if id ~}}
-Job ID: {{id}}
-{{/if~}}
-Datastore: {{job.store}}
-Tape Pool: {{job.pool}}
-Tape Drive: {{job.drive}}
-
-{{#if snapshot-list ~}}
-Snapshots included:
-
-{{#each snapshot-list~}}
-{{this}}
-{{/each~}}
-{{/if}}
-Duration: {{duration}}
-{{#if used-tapes }}
-Used Tapes:
-{{#each used-tapes~}}
-{{this}}
-{{/each~}}
-{{/if}}
-Tape Backup successful.
-
-
-Please visit the web interface for further details:
-
-<https://{{fqdn}}:{{port}}/#DataStore-{{job.store}}>
-
-"###;
-
-const TAPE_BACKUP_ERR_TEMPLATE: &str = r###"
-
-{{#if id ~}}
-Job ID: {{id}}
-{{/if~}}
-Datastore: {{job.store}}
-Tape Pool: {{job.pool}}
-Tape Drive: {{job.drive}}
-
-{{#if snapshot-list ~}}
-Snapshots included:
-
-{{#each snapshot-list~}}
-{{this}}
-{{/each~}}
-{{/if}}
-{{#if used-tapes }}
-Used Tapes:
-{{#each used-tapes~}}
-{{this}}
-{{/each~}}
-{{/if}}
-Tape Backup failed: {{error}}
-
-
-Please visit the web interface for further details:
-
-<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
-
-"###;
-
-lazy_static::lazy_static! {
-
- static ref HANDLEBARS: Handlebars<'static> = {
- let mut hb = Handlebars::new();
- let result: Result<(), TemplateError> = try_block!({
-
- hb.set_strict_mode(true);
- hb.register_escape_fn(handlebars::no_escape);
-
- hb.register_template_string("tape_backup_ok_template", TAPE_BACKUP_OK_TEMPLATE)?;
- hb.register_template_string("tape_backup_err_template", TAPE_BACKUP_ERR_TEMPLATE)?;
-
- Ok(())
- });
-
- if let Err(err) = result {
- eprintln!("error during template registration: {err}");
- }
-
- hb
- };
-}
-
/// Initialize the notification system by setting context in proxmox_notify
pub fn init() -> Result<(), Error> {
proxmox_notify::context::set_context(&PBS_CONTEXT);
@@ -229,30 +141,6 @@ pub struct TapeBackupJobSummary {
pub used_tapes: Option<Vec<String>>,
}
-fn send_job_status_mail(email: &str, subject: &str, text: &str) -> Result<(), Error> {
- let (config, _) = crate::config::node::config()?;
- let from = config.email_from;
-
- // NOTE: some (web)mailers have big problems displaying text mails, so include html as well
- let escaped_text = handlebars::html_escape(text);
- let html = format!("<html><body><pre>\n{escaped_text}\n<pre>");
-
- let nodename = proxmox_sys::nodename();
-
- let author = format!("Proxmox Backup Server - {nodename}");
-
- sendmail(
- &[email],
- subject,
- Some(text),
- Some(&html),
- from.as_deref(),
- Some(&author),
- )?;
-
- Ok(())
-}
-
pub fn send_gc_status(
datastore: &str,
status: &GarbageCollectionStatus,
@@ -463,7 +351,6 @@ pub fn send_sync_status(job: &SyncJobConfig, result: &Result<(), Error>) -> Resu
}
pub fn send_tape_backup_status(
- email: &str,
id: Option<&str>,
job: &TapeBackupJobSetup,
result: &Result<(), Error>,
@@ -478,62 +365,86 @@ pub fn send_tape_backup_status(
"id": id,
"snapshot-list": summary.snapshot_list,
"used-tapes": summary.used_tapes,
- "duration": duration.to_string(),
+ "job-duration": duration.to_string(),
});
- let text = match result {
- Ok(()) => HANDLEBARS.render("tape_backup_ok_template", &data)?,
+ let (template, severity) = match result {
+ Ok(()) => ("tape-backup-ok", Severity::Info),
Err(err) => {
data["error"] = err.to_string().into();
- HANDLEBARS.render("tape_backup_err_template", &data)?
+ ("tape-backup-err", Severity::Error)
}
};
- let subject = match (result, id) {
- (Ok(()), Some(id)) => format!("Tape Backup '{id}' datastore '{}' successful", job.store,),
- (Ok(()), None) => format!("Tape Backup datastore '{}' successful", job.store,),
- (Err(_), Some(id)) => format!("Tape Backup '{id}' datastore '{}' failed", job.store,),
- (Err(_), None) => format!("Tape Backup datastore '{}' failed", job.store,),
- };
+ let mut metadata = HashMap::from([
+ ("datastore".into(), job.store.clone()),
+ ("media-pool".into(), job.pool.clone()),
+ ("hostname".into(), proxmox_sys::nodename().into()),
+ ("type".into(), "tape-backup".into()),
+ ]);
- send_job_status_mail(email, &subject, &text)?;
+ if let Some(id) = id {
+ metadata.insert("tape-job".into(), id.into());
+ }
+
+ let notification = Notification::from_template(severity, template, data, metadata);
+
+ let mode = TapeNotificationMode::from(job);
+
+ match &mode {
+ TapeNotificationMode::LegacySendmail { notify_user } => {
+ let email = lookup_user_email(notify_user);
+
+ if let Some(email) = email {
+ send_sendmail_legacy_notification(notification, &email)?;
+ }
+ }
+ TapeNotificationMode::NotificationSystem => {
+ send_notification(notification)?;
+ }
+ }
Ok(())
}
/// Send email to a person to request a manual media change
-pub fn send_load_media_email(
+pub fn send_load_media_notification(
+ mode: &TapeNotificationMode,
changer: bool,
device: &str,
label_text: &str,
- to: &str,
reason: Option<String>,
) -> Result<(), Error> {
- use std::fmt::Write as _;
-
let device_type = if changer { "changer" } else { "drive" };
- let subject = format!("Load Media '{label_text}' request for {device_type} '{device}'");
+ let data = json!({
+ "device-type": device_type,
+ "device": device,
+ "label-text": label_text,
+ "reason": reason,
+ "is-changer": changer,
+ });
- let mut text = String::new();
+ let metadata = HashMap::from([
+ ("hostname".into(), proxmox_sys::nodename().into()),
+ ("type".into(), "tape-load".into()),
+ ]);
+ let notification = Notification::from_template(Severity::Notice, "tape-load", data, metadata);
- if let Some(reason) = reason {
- let _ = write!(
- text,
- "The {device_type} has the wrong or no tape(s) inserted. Error:\n{reason}\n\n"
- );
- }
+ match mode {
+ TapeNotificationMode::LegacySendmail { notify_user } => {
+ let email = lookup_user_email(notify_user);
- if changer {
- text.push_str("Please insert the requested media into the changer.\n\n");
- let _ = writeln!(text, "Changer: {device}");
- } else {
- text.push_str("Please insert the requested media into the backup drive.\n\n");
- let _ = writeln!(text, "Drive: {device}");
+ if let Some(email) = email {
+ send_sendmail_legacy_notification(notification, &email)?;
+ }
+ }
+ TapeNotificationMode::NotificationSystem => {
+ send_notification(notification)?;
+ }
}
- let _ = writeln!(text, "Media: {label_text}");
- send_job_status_mail(to, &subject, &text)
+ Ok(())
}
fn get_server_url() -> (String, usize) {
@@ -653,9 +564,3 @@ pub fn lookup_datastore_notify_settings(
(email, notify, notification_mode)
}
-
-#[test]
-fn test_template_register() {
- assert!(HANDLEBARS.has_template("tape_backup_ok_template"));
- assert!(HANDLEBARS.has_template("tape_backup_err_template"));
-}
diff --git a/src/tape/drive/mod.rs b/src/tape/drive/mod.rs
index 8607d64b..39602461 100644
--- a/src/tape/drive/mod.rs
+++ b/src/tape/drive/mod.rs
@@ -27,8 +27,9 @@ use pbs_key_config::KeyConfig;
use pbs_tape::{sg_tape::TapeAlertFlags, BlockReadError, MediaContentHeader, TapeRead, TapeWrite};
+use crate::tape::TapeNotificationMode;
use crate::{
- server::send_load_media_email,
+ server::send_load_media_notification,
tape::{
changer::{MediaChange, MtxMediaChanger},
drive::virtual_tape::open_virtual_tape_drive,
@@ -368,7 +369,7 @@ pub fn request_and_load_media(
config: &SectionConfigData,
drive: &str,
label: &MediaLabel,
- notify_email: &Option<String>,
+ notification_mode: &TapeNotificationMode,
) -> Result<(Box<dyn TapeDriver>, MediaId), Error> {
let check_label = |handle: &mut dyn TapeDriver, uuid: &proxmox_uuid::Uuid| {
if let Ok((Some(media_id), _)) = handle.read_label() {
@@ -428,15 +429,14 @@ pub fn request_and_load_media(
device_type,
device
);
- if let Some(to) = notify_email {
- send_load_media_email(
- changer.is_some(),
- device,
- &label_text,
- to,
- Some(new.to_string()),
- )?;
- }
+ send_load_media_notification(
+ notification_mode,
+ changer.is_some(),
+ device,
+ &label_text,
+ Some(new.to_string()),
+ )?;
+
*old = new;
}
Ok(())
diff --git a/src/tape/mod.rs b/src/tape/mod.rs
index 7a928884..f276f948 100644
--- a/src/tape/mod.rs
+++ b/src/tape/mod.rs
@@ -1,6 +1,7 @@
//! Magnetic tape backup
use anyhow::{format_err, Error};
+use proxmox_auth_api::types::Userid;
use proxmox_sys::fs::{create_path, CreateOptions};
@@ -29,6 +30,7 @@ pub use media_catalog::*;
mod media_catalog_cache;
pub use media_catalog_cache::*;
+use pbs_api_types::{NotificationMode, TapeBackupJobSetup};
mod pool_writer;
pub use pool_writer::*;
@@ -128,3 +130,28 @@ pub fn create_changer_state_dir() -> Result<(), Error> {
Ok(())
}
+
+#[derive(Clone)]
+pub enum TapeNotificationMode {
+ LegacySendmail { notify_user: Userid },
+ NotificationSystem,
+}
+
+impl From<&TapeBackupJobSetup> for TapeNotificationMode {
+ fn from(value: &TapeBackupJobSetup) -> Self {
+ Self::from((value.notify_user.clone(), value.notification_mode.clone()))
+ }
+}
+
+impl From<(Option<Userid>, Option<NotificationMode>)> for TapeNotificationMode {
+ fn from(value: (Option<Userid>, Option<NotificationMode>)) -> Self {
+ match value.1.as_ref().unwrap_or(&Default::default()) {
+ NotificationMode::LegacySendmail => {
+ let notify_user = value.0.as_ref().unwrap_or(Userid::root_userid()).clone();
+
+ Self::LegacySendmail { notify_user }
+ }
+ NotificationMode::NotificationSystem => Self::NotificationSystem,
+ }
+ }
+}
diff --git a/src/tape/pool_writer/mod.rs b/src/tape/pool_writer/mod.rs
index a6ba4a1d..21426080 100644
--- a/src/tape/pool_writer/mod.rs
+++ b/src/tape/pool_writer/mod.rs
@@ -25,7 +25,8 @@ use crate::tape::{
file_formats::{
tape_write_catalog, tape_write_snapshot_archive, ChunkArchiveWriter, MediaSetLabel,
},
- MediaCatalog, MediaId, MediaPool, COMMIT_BLOCK_SIZE, MAX_CHUNK_ARCHIVE_SIZE, TAPE_STATUS_DIR,
+ MediaCatalog, MediaId, MediaPool, TapeNotificationMode, COMMIT_BLOCK_SIZE,
+ MAX_CHUNK_ARCHIVE_SIZE, TAPE_STATUS_DIR,
};
use super::file_formats::{
@@ -52,7 +53,7 @@ pub struct PoolWriter {
drive_name: String,
status: Option<PoolWriterState>,
catalog_set: Arc<Mutex<CatalogSet>>,
- notify_email: Option<String>,
+ notification_mode: TapeNotificationMode,
ns_magic: bool,
used_tapes: HashSet<Uuid>,
}
@@ -62,7 +63,7 @@ impl PoolWriter {
mut pool: MediaPool,
drive_name: &str,
worker: &WorkerTask,
- notify_email: Option<String>,
+ notification_mode: TapeNotificationMode,
force_media_set: bool,
ns_magic: bool,
) -> Result<Self, Error> {
@@ -90,7 +91,7 @@ impl PoolWriter {
drive_name: drive_name.to_string(),
status: None,
catalog_set: Arc::new(Mutex::new(catalog_set)),
- notify_email,
+ notification_mode,
ns_magic,
used_tapes: HashSet::new(),
})
@@ -248,7 +249,7 @@ impl PoolWriter {
&drive_config,
&self.drive_name,
media.label(),
- &self.notify_email,
+ &self.notification_mode,
)?;
// test for critical tape alert flags
diff --git a/templates/Makefile b/templates/Makefile
index 824d28d9..0f8ad72c 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -17,6 +17,12 @@ NOTIFICATION_TEMPLATES= \
default/sync-ok-body.txt.hbs \
default/sync-err-subject.txt.hbs \
default/sync-ok-subject.txt.hbs \
+ default/tape-backup-err-body.txt.hbs \
+ default/tape-backup-err-subject.txt.hbs \
+ default/tape-backup-ok-body.txt.hbs \
+ default/tape-backup-ok-subject.txt.hbs \
+ default/tape-load-body.txt.hbs \
+ default/tape-load-subject.txt.hbs \
default/test-body.txt.hbs \
default/test-body.html.hbs \
default/test-subject.txt.hbs \
diff --git a/templates/default/tape-backup-err-body.txt.hbs b/templates/default/tape-backup-err-body.txt.hbs
new file mode 100644
index 00000000..cc45c882
--- /dev/null
+++ b/templates/default/tape-backup-err-body.txt.hbs
@@ -0,0 +1,26 @@
+{{#if id ~}}
+Job ID: {{id}}
+{{/if~}}
+Datastore: {{job.store}}
+Tape Pool: {{job.pool}}
+Tape Drive: {{job.drive}}
+
+{{#if snapshot-list ~}}
+Snapshots included:
+
+{{#each snapshot-list~}}
+{{this}}
+{{/each~}}
+{{/if}}
+{{#if used-tapes }}
+Used Tapes:
+{{#each used-tapes~}}
+{{this}}
+{{/each~}}
+{{/if}}
+Tape Backup failed: {{error}}
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#pbsServerAdministration:tasks>
diff --git a/templates/default/tape-backup-err-subject.txt.hbs b/templates/default/tape-backup-err-subject.txt.hbs
new file mode 100644
index 00000000..b52d338a
--- /dev/null
+++ b/templates/default/tape-backup-err-subject.txt.hbs
@@ -0,0 +1,5 @@
+{{#if id~}}
+Tape Backup '{{ id }}' datastore '{{ job.store }}' failed
+{{else~}}
+Tape Backup datastore '{{ job.store }}' failed
+{{/if}}
diff --git a/templates/default/tape-backup-ok-body.txt.hbs b/templates/default/tape-backup-ok-body.txt.hbs
new file mode 100644
index 00000000..ede51d05
--- /dev/null
+++ b/templates/default/tape-backup-ok-body.txt.hbs
@@ -0,0 +1,27 @@
+{{#if id ~}}
+Job ID: {{id}}
+{{/if~}}
+Datastore: {{job.store}}
+Tape Pool: {{job.pool}}
+Tape Drive: {{job.drive}}
+
+{{#if snapshot-list ~}}
+Snapshots included:
+
+{{#each snapshot-list~}}
+{{this}}
+{{/each~}}
+{{/if}}
+Duration: {{job-duration}}
+{{#if used-tapes }}
+Used Tapes:
+{{#each used-tapes~}}
+{{this}}
+{{/each~}}
+{{/if}}
+Tape Backup successful.
+
+
+Please visit the web interface for further details:
+
+<https://{{fqdn}}:{{port}}/#DataStore-{{job.store}}>
diff --git a/templates/default/tape-backup-ok-subject.txt.hbs b/templates/default/tape-backup-ok-subject.txt.hbs
new file mode 100644
index 00000000..c475c05b
--- /dev/null
+++ b/templates/default/tape-backup-ok-subject.txt.hbs
@@ -0,0 +1,5 @@
+{{#if id~}}
+Tape Backup '{{ id }}' datastore '{{ job.store }}' successful
+{{else~}}
+Tape Backup datastore '{{ job.store }}' successful
+{{/if}}
diff --git a/templates/default/tape-load-body.txt.hbs b/templates/default/tape-load-body.txt.hbs
new file mode 100644
index 00000000..ddc8a9e1
--- /dev/null
+++ b/templates/default/tape-load-body.txt.hbs
@@ -0,0 +1,15 @@
+{{#if reason~}}
+The {{ device-type }} has the wrong or no tape(s) inserted. Error:
+{{ reason }}
+
+{{/if~}}
+{{#if is-changer~}}
+Please insert the requested media into the changer.
+
+Changer: {{ device }}
+{{else}}
+Please insert the requested media into the backup drive.
+
+Drive: {{ device }}
+{{/if}}
+Media: {{ label-text }}
diff --git a/templates/default/tape-load-subject.txt.hbs b/templates/default/tape-load-subject.txt.hbs
new file mode 100644
index 00000000..10f6a02e
--- /dev/null
+++ b/templates/default/tape-load-subject.txt.hbs
@@ -0,0 +1 @@
+Load Media '{{ label-text }}' request for {{ device-type }} '{{ device }}'
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 28/43] ui: add notification config panel
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (26 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 27/43] server: notifications: send tape " Lukas Wagner
@ 2024-04-17 14:34 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 29/43] ui: tape backup job: add selector for notification-mode Lukas Wagner
` (14 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:34 UTC (permalink / raw)
To: pbs-devel
This commit adds the same notification configuration panel that we
already use in Proxmox VE.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
www/Makefile | 1 +
www/NavigationTree.js | 6 ++++++
www/config/NotificationConfigView.js | 11 +++++++++++
3 files changed, 18 insertions(+)
create mode 100644 www/config/NotificationConfigView.js
diff --git a/www/Makefile b/www/Makefile
index 79cb4c04..f3d90bc4 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -67,6 +67,7 @@ JSSRC= \
config/CertificateView.js \
config/NodeOptionView.js \
config/MetricServerView.js \
+ config/NotificationConfigView.js \
window/ACLEdit.js \
window/BackupGroupChangeOwner.js \
window/CreateDirectory.js \
diff --git a/www/NavigationTree.js b/www/NavigationTree.js
index 3e0040f7..a5ea390f 100644
--- a/www/NavigationTree.js
+++ b/www/NavigationTree.js
@@ -68,6 +68,12 @@ Ext.define('PBS.store.NavigationStore', {
path: 'pbsCertificateConfiguration',
leaf: true,
},
+ {
+ text: gettext('Notifications'),
+ iconCls: 'fa fa-bell-o',
+ path: 'pbsNotificationConfigView',
+ leaf: true,
+ },
{
text: gettext('Subscription'),
iconCls: 'fa fa-support',
diff --git a/www/config/NotificationConfigView.js b/www/config/NotificationConfigView.js
new file mode 100644
index 00000000..904cee71
--- /dev/null
+++ b/www/config/NotificationConfigView.js
@@ -0,0 +1,11 @@
+Ext.define('PBS.config.NotificationConfigView', {
+ extend: 'Proxmox.panel.NotificationConfigView',
+ alias: ['widget.pbsNotificationConfigView'],
+ mixins: ['Proxmox.Mixin.CBind'],
+
+ cbindData: function(_initialConfig) {
+ return {
+ baseUrl: '/config/notifications',
+ };
+ },
+});
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 29/43] ui: tape backup job: add selector for notification-mode
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (27 preceding siblings ...)
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 28/43] ui: add notification config panel Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 30/43] ui: tape backup: add selector for 'notification-mode' Lukas Wagner
` (13 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
www/tape/window/TapeBackupJob.js | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/www/tape/window/TapeBackupJob.js b/www/tape/window/TapeBackupJob.js
index abbbaa0b..309dda0b 100644
--- a/www/tape/window/TapeBackupJob.js
+++ b/www/tape/window/TapeBackupJob.js
@@ -46,6 +46,15 @@ Ext.define('PBS.TapeManagement.BackupJobEdit', {
},
},
+ viewModel: {
+ data: {
+ notificationMode: 'notification-system',
+ },
+ formulas: {
+ notificationSystemSelected: (get) => get('notificationMode') === 'notification-system',
+ },
+ },
+
items: {
xtype: 'tabpanel',
bodyPadding: 10,
@@ -109,6 +118,18 @@ Ext.define('PBS.TapeManagement.BackupJobEdit', {
fieldLabel: gettext('Drive'),
name: 'drive',
},
+ {
+ xtype: 'proxmoxKVComboBox',
+ comboItems: [
+ ['legacy-sendmail', gettext('Email (legacy)')],
+ ['notification-system', gettext('Notification system')],
+ ],
+ fieldLabel: gettext('Notification mode'),
+ name: 'notification-mode',
+ bind: {
+ value: '{notificationMode}',
+ },
+ },
{
xtype: 'pmxUserSelector',
name: 'notify-user',
@@ -117,6 +138,9 @@ Ext.define('PBS.TapeManagement.BackupJobEdit', {
allowBlank: true,
value: null,
renderer: Ext.String.htmlEncode,
+ bind: {
+ disabled: "{notificationSystemSelected}",
+ },
},
],
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 30/43] ui: tape backup: add selector for 'notification-mode'
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (28 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 29/43] ui: tape backup job: add selector for notification-mode Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 31/43] ui: tape restore: add 'notification-mode' parameter Lukas Wagner
` (12 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
www/tape/window/TapeBackup.js | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/www/tape/window/TapeBackup.js b/www/tape/window/TapeBackup.js
index 941b6b83..a8385339 100644
--- a/www/tape/window/TapeBackup.js
+++ b/www/tape/window/TapeBackup.js
@@ -8,6 +8,15 @@ Ext.define('PBS.TapeManagement.TapeBackupWindow', {
showTaskViewer: true,
isCreate: true,
+ viewModel: {
+ data: {
+ notificationMode: 'notification-system',
+ },
+ formulas: {
+ notificationSystemSelected: (get) => get('notificationMode') === 'notification-system',
+ },
+ },
+
items: [
{
xtype: 'inputpanel',
@@ -81,6 +90,19 @@ Ext.define('PBS.TapeManagement.TapeBackupWindow', {
name: 'eject-media',
fieldLabel: gettext('Eject Media'),
},
+ {
+ xtype: 'proxmoxKVComboBox',
+ labelWidth: 150,
+ comboItems: [
+ ['legacy-sendmail', gettext('Email (legacy)')],
+ ['notification-system', gettext('Notification system')],
+ ],
+ fieldLabel: gettext('Notification mode'),
+ name: 'notification-mode',
+ bind: {
+ value: '{notificationMode}',
+ },
+ },
{
xtype: 'pmxUserSelector',
labelWidth: 150,
@@ -90,6 +112,9 @@ Ext.define('PBS.TapeManagement.TapeBackupWindow', {
value: null,
allowBlank: true,
skipEmptyText: true,
+ bind: {
+ disabled: "{notificationSystemSelected}",
+ },
renderer: Ext.String.htmlEncode,
},
],
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 31/43] ui: tape restore: add 'notification-mode' parameter
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (29 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 30/43] ui: tape backup: add selector for 'notification-mode' Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 32/43] ui: datastore options: " Lukas Wagner
` (11 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
www/tape/window/TapeRestore.js | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/www/tape/window/TapeRestore.js b/www/tape/window/TapeRestore.js
index c686c958..61a2fcd7 100644
--- a/www/tape/window/TapeRestore.js
+++ b/www/tape/window/TapeRestore.js
@@ -33,6 +33,7 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
data: {
uuid: "",
singleDatastore: true,
+ notificationMode: 'notification-system',
},
formulas: {
singleSelectorLabel: get =>
@@ -40,6 +41,7 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
singleSelectorEmptyText: get => get('singleDatastore') ? '' : Proxmox.Utils.NoneText,
singleSelectorLabelNs: get =>
get('singleDatastore') ? gettext('Target Namespace') : gettext('Default Namespace'),
+ notificationSystemSelected: (get) => get('notificationMode') === 'notification-system',
},
},
@@ -428,6 +430,18 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
return values;
},
column1: [
+ {
+ xtype: 'proxmoxKVComboBox',
+ comboItems: [
+ ['legacy-sendmail', gettext('Email (legacy)')],
+ ['notification-system', gettext('Notification system')],
+ ],
+ fieldLabel: gettext('Notification mode'),
+ name: 'notification-mode',
+ bind: {
+ value: '{notificationMode}',
+ },
+ },
{
xtype: 'pmxUserSelector',
name: 'notify-user',
@@ -437,6 +451,9 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
allowBlank: true,
skipEmptyText: true,
renderer: Ext.String.htmlEncode,
+ bind: {
+ disabled: "{notificationSystemSelected}",
+ },
},
{
xtype: 'pbsAuthidSelector',
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 32/43] ui: datastore options: add 'notification-mode' parameter
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (30 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 31/43] ui: tape restore: add 'notification-mode' parameter Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 33/43] ui: utils: add overrides for known notification metadata fields/values Lukas Wagner
` (10 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
www/datastore/OptionView.js | 15 +++++++++++++++
www/window/NotifyOptions.js | 38 +++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/www/datastore/OptionView.js b/www/datastore/OptionView.js
index 6f1be969..e1f38af6 100644
--- a/www/datastore/OptionView.js
+++ b/www/datastore/OptionView.js
@@ -159,6 +159,21 @@ Ext.define('PBS.Datastore.Options', {
},
rows: {
+ "notification-mode": {
+ required: true,
+ defaultValue: 'legacy-sendmail',
+ header: gettext('Notification mode'),
+ renderer: function(value) {
+ if (value === 'notification-system') {
+ return gettext('Notification system');
+ } else {
+ return gettext('Email (legacy)');
+ }
+ },
+ editor: {
+ xtype: 'pbsNotifyOptionEdit',
+ },
+ },
"notify": {
required: true,
header: gettext('Notify'),
diff --git a/www/window/NotifyOptions.js b/www/window/NotifyOptions.js
index 11765b43..95323486 100644
--- a/www/window/NotifyOptions.js
+++ b/www/window/NotifyOptions.js
@@ -44,6 +44,15 @@ Ext.define('PBS.window.NotifyOptions', {
labelWidth: 120,
},
+ viewModel: {
+ data: {
+ notificationMode: 'notification-system',
+ },
+ formulas: {
+ notificationSystemSelected: (get) => get('notificationMode') === 'notification-system',
+ },
+ },
+
items: {
xtype: 'inputpanel',
onGetValues: function(values) {
@@ -60,6 +69,18 @@ Ext.define('PBS.window.NotifyOptions', {
return values;
},
items: [
+ {
+ xtype: 'proxmoxKVComboBox',
+ comboItems: [
+ ['legacy-sendmail', gettext('Email (legacy)')],
+ ['notification-system', gettext('Notification system')],
+ ],
+ fieldLabel: gettext('Notification mode'),
+ name: 'notification-mode',
+ bind: {
+ value: '{notificationMode}',
+ },
+ },
{
xtype: 'pmxUserSelector',
name: 'notify-user',
@@ -69,6 +90,9 @@ Ext.define('PBS.window.NotifyOptions', {
allowBlank: true,
renderer: Ext.String.htmlEncode,
deleteEmpty: true,
+ bind: {
+ disabled: "{notificationSystemSelected}",
+ },
},
{
xtype: 'pbsNotifyType',
@@ -76,6 +100,9 @@ Ext.define('PBS.window.NotifyOptions', {
fieldLabel: gettext('Verification Jobs'),
value: '__default__',
deleteEmpty: false,
+ bind: {
+ disabled: "{notificationSystemSelected}",
+ },
},
{
xtype: 'pbsNotifyType',
@@ -83,6 +110,9 @@ Ext.define('PBS.window.NotifyOptions', {
fieldLabel: gettext('Sync Jobs'),
value: '__default__',
deleteEmpty: false,
+ bind: {
+ disabled: "{notificationSystemSelected}",
+ },
},
{
xtype: 'pbsNotifyErrorDefaultType',
@@ -90,6 +120,9 @@ Ext.define('PBS.window.NotifyOptions', {
fieldLabel: gettext('Prune Jobs'),
value: '__default__',
deleteEmpty: false,
+ bind: {
+ disabled: "{notificationSystemSelected}",
+ },
},
{
xtype: 'pbsNotifyType',
@@ -97,6 +130,9 @@ Ext.define('PBS.window.NotifyOptions', {
fieldLabel: gettext('Garbage Collection'),
value: '__default__',
deleteEmpty: false,
+ bind: {
+ disabled: "{notificationSystemSelected}",
+ },
},
],
},
@@ -107,6 +143,8 @@ Ext.define('PBS.window.NotifyOptions', {
let options = {
'notify-user': values['notify-user'],
'verify-new': values['verify-new'],
+ 'notification-mode':
+ values['notification-mode'] ? values['notification-mode'] : 'legacy-sendmail',
};
let notify = {};
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 33/43] ui: utils: add overrides for known notification metadata fields/values
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (31 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 32/43] ui: datastore options: " Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 34/43] ui: datastore edit: make new stores use notification system by default Lukas Wagner
` (9 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
This mechanism allows having nice, translatable notification event
types and fields.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
www/Utils.js | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/www/Utils.js b/www/Utils.js
index 5357949b..ae8d8ed3 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -429,6 +429,26 @@ Ext.define('PBS.Utils', {
zfscreate: [gettext('ZFS Storage'), gettext('Create')],
});
+ Proxmox.Utils.overrideNotificationFieldName({
+ 'datastore': gettext('Datastore'),
+ 'tape-job': gettext('Tape Backup Job ID'),
+ 'verification-job': gettext('Verification Job ID'),
+ 'prune-job': gettext('Prune Job ID'),
+ 'sync-job': gettext('Sync Job ID'),
+ 'media-pool': gettext('Media Pool'),
+ });
+
+ Proxmox.Utils.overrideNotificationFieldValue({
+ 'acme': gettext('ACME certificate renewal'),
+ 'gc': gettext('Garbage collection'),
+ 'package-updates': gettext('Package updates are available'),
+ 'prune': gettext('Prune job'),
+ 'sync': gettext('Sync job'),
+ 'tape-backup': gettext('Tape backup notifications'),
+ 'tape-load': gettext('Tape loading request'),
+ 'verify': gettext('Verification job'),
+ });
+
Proxmox.Schema.overrideAuthDomains({
pbs: {
name: 'Proxmox Backup authentication server',
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 34/43] ui: datastore edit: make new stores use notification system by default
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (32 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 33/43] ui: utils: add overrides for known notification metadata fields/values Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 35/43] ui: permissions paths: add /system/notifications to combobox Lukas Wagner
` (8 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
www/window/DataStoreEdit.js | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/www/window/DataStoreEdit.js b/www/window/DataStoreEdit.js
index aecf6b8d..b6115460 100644
--- a/www/window/DataStoreEdit.js
+++ b/www/window/DataStoreEdit.js
@@ -39,6 +39,9 @@ Ext.define('PBS.DataStoreEdit', {
title: gettext('General'),
xtype: 'inputpanel',
onlineHelp: 'datastore_intro',
+ cbind: {
+ isCreate: '{isCreate}',
+ },
column1: [
{
xtype: 'pmxDisplayEditField',
@@ -90,6 +93,16 @@ Ext.define('PBS.DataStoreEdit', {
fieldLabel: gettext('Comment'),
},
],
+
+ onGetValues: function(values) {
+ let me = this;
+
+ if (me.isCreate) {
+ // New datastores default to using the notification system
+ values['notification-mode'] = 'notification-system';
+ }
+ return values;
+ },
},
{
title: gettext('Prune Options'),
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 35/43] ui: permissions paths: add /system/notifications to combobox
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (33 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 34/43] ui: datastore edit: make new stores use notification system by default Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 36/43] proxmox-backup-manager: add CLI for notification targets Lukas Wagner
` (7 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
The /system/notifications ACL path is used for configuring the
notification system.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
www/form/PermissionPathSelector.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/www/form/PermissionPathSelector.js b/www/form/PermissionPathSelector.js
index 3f8b5376..8dcea195 100644
--- a/www/form/PermissionPathSelector.js
+++ b/www/form/PermissionPathSelector.js
@@ -19,6 +19,7 @@ Ext.define('PBS.data.PermissionPathsStore', {
{ 'value': '/system/network' },
{ 'value': '/system/network/dns' },
{ 'value': '/system/network/interfaces' },
+ { 'value': '/system/notifications' },
{ 'value': '/system/services' },
{ 'value': '/system/status' },
{ 'value': '/system/tasks' },
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 36/43] proxmox-backup-manager: add CLI for notification targets
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (34 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 35/43] ui: permissions paths: add /system/notifications to combobox Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 37/43] proxmox-backup-manager: add CLI for notification matchers Lukas Wagner
` (6 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
src/api2/config/notifications/mod.rs | 10 ++--
src/bin/proxmox-backup-manager.rs | 2 +
src/bin/proxmox_backup_manager/mod.rs | 2 +
.../notifications/mod.rs | 9 ++++
.../notifications/targets.rs | 51 +++++++++++++++++++
5 files changed, 69 insertions(+), 5 deletions(-)
create mode 100644 src/bin/proxmox_backup_manager/notifications/mod.rs
create mode 100644 src/bin/proxmox_backup_manager/notifications/targets.rs
diff --git a/src/api2/config/notifications/mod.rs b/src/api2/config/notifications/mod.rs
index 05a51f24..ad9fd0c8 100644
--- a/src/api2/config/notifications/mod.rs
+++ b/src/api2/config/notifications/mod.rs
@@ -17,11 +17,11 @@ use crate::api2::config::datastore::list_datastores;
use crate::api2::config::media_pool::list_pools;
use crate::api2::tape::backup::list_tape_backup_jobs;
-mod gotify;
-mod matchers;
-mod sendmail;
-mod smtp;
-mod targets;
+pub mod gotify;
+pub mod matchers;
+pub mod sendmail;
+pub mod smtp;
+pub mod targets;
#[sortable]
const SUBDIRS: SubdirMap = &sorted!([
diff --git a/src/bin/proxmox-backup-manager.rs b/src/bin/proxmox-backup-manager.rs
index 115207f3..132de290 100644
--- a/src/bin/proxmox-backup-manager.rs
+++ b/src/bin/proxmox-backup-manager.rs
@@ -430,6 +430,7 @@ async fn get_versions(verbose: bool, param: Value) -> Result<Value, Error> {
async fn run() -> Result<(), Error> {
init_cli_logger("PBS_LOG", "info");
+ proxmox_backup::server::notifications::init()?;
let cmd_def = CliCommandMap::new()
.insert("acl", acl_commands())
@@ -439,6 +440,7 @@ async fn run() -> Result<(), Error> {
.insert("ldap", ldap_commands())
.insert("network", network_commands())
.insert("node", node_commands())
+ .insert("notification", notification_commands())
.insert("user", user_commands())
.insert("openid", openid_commands())
.insert("remote", remote_commands())
diff --git a/src/bin/proxmox_backup_manager/mod.rs b/src/bin/proxmox_backup_manager/mod.rs
index 8a1c140c..8992a7a7 100644
--- a/src/bin/proxmox_backup_manager/mod.rs
+++ b/src/bin/proxmox_backup_manager/mod.rs
@@ -28,6 +28,8 @@ mod disk;
pub use disk::*;
mod node;
pub use node::*;
+mod notifications;
+pub use notifications::*;
mod openid;
pub use openid::*;
mod traffic_control;
diff --git a/src/bin/proxmox_backup_manager/notifications/mod.rs b/src/bin/proxmox_backup_manager/notifications/mod.rs
new file mode 100644
index 00000000..fdd5abe3
--- /dev/null
+++ b/src/bin/proxmox_backup_manager/notifications/mod.rs
@@ -0,0 +1,9 @@
+use proxmox_router::cli::{CliCommandMap, CommandLineInterface};
+
+mod targets;
+
+pub fn notification_commands() -> CommandLineInterface {
+ let cmd_def = CliCommandMap::new().insert("target", targets::commands());
+
+ cmd_def.into()
+}
diff --git a/src/bin/proxmox_backup_manager/notifications/targets.rs b/src/bin/proxmox_backup_manager/notifications/targets.rs
new file mode 100644
index 00000000..37603a92
--- /dev/null
+++ b/src/bin/proxmox_backup_manager/notifications/targets.rs
@@ -0,0 +1,51 @@
+use anyhow::Error;
+use serde_json::Value;
+
+use proxmox_router::{cli::*, ApiHandler, RpcEnvironment};
+use proxmox_schema::api;
+
+use proxmox_backup::api2;
+
+#[api(
+ input: {
+ properties: {
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// List targets.
+fn list_targets(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::config::notifications::targets::API_METHOD_LIST_TARGETS;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options()
+ .column(ColumnConfig::new("disable"))
+ .column(ColumnConfig::new("name"))
+ .column(ColumnConfig::new("type"))
+ .column(ColumnConfig::new("origin"))
+ .column(ColumnConfig::new("comment"));
+
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
+pub fn commands() -> CommandLineInterface {
+ let cmd_def = CliCommandMap::new()
+ .insert("list", CliCommand::new(&API_METHOD_LIST_TARGETS))
+ .insert(
+ "test",
+ CliCommand::new(&api2::config::notifications::targets::API_METHOD_TEST_TARGET)
+ .arg_param(&["name"]),
+ );
+
+ cmd_def.into()
+}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 37/43] proxmox-backup-manager: add CLI for notification matchers
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (35 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 36/43] proxmox-backup-manager: add CLI for notification targets Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 38/43] proxmox-backup-manager: add CLI for gotify endpoints Lukas Wagner
` (5 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
.../notifications/matchers.rs | 93 +++++++++++++++++++
.../notifications/mod.rs | 5 +-
2 files changed, 97 insertions(+), 1 deletion(-)
create mode 100644 src/bin/proxmox_backup_manager/notifications/matchers.rs
diff --git a/src/bin/proxmox_backup_manager/notifications/matchers.rs b/src/bin/proxmox_backup_manager/notifications/matchers.rs
new file mode 100644
index 00000000..cfa3aaa4
--- /dev/null
+++ b/src/bin/proxmox_backup_manager/notifications/matchers.rs
@@ -0,0 +1,93 @@
+use anyhow::Error;
+use proxmox_notify::schema::ENTITY_NAME_SCHEMA;
+use serde_json::Value;
+
+use proxmox_router::{cli::*, ApiHandler, RpcEnvironment};
+use proxmox_schema::api;
+
+use proxmox_backup::api2;
+
+#[api(
+ input: {
+ properties: {
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// List notification matchers.
+fn list_matchers(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::config::notifications::matchers::API_METHOD_LIST_MATCHERS;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options()
+ .column(ColumnConfig::new("disable"))
+ .column(ColumnConfig::new("name"))
+ .column(ColumnConfig::new("origin"))
+ .column(ColumnConfig::new("comment"));
+
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
+#[api(
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ },
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// Show a single matcher.
+fn show_matcher(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::config::notifications::matchers::API_METHOD_GET_MATCHER;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options();
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
+pub fn commands() -> CommandLineInterface {
+ let cmd_def = CliCommandMap::new()
+ .insert("list", CliCommand::new(&API_METHOD_LIST_MATCHERS))
+ .insert(
+ "show",
+ CliCommand::new(&API_METHOD_SHOW_MATCHER).arg_param(&["name"]),
+ )
+ .insert(
+ "create",
+ CliCommand::new(&api2::config::notifications::matchers::API_METHOD_ADD_MATCHER)
+ .arg_param(&["name"]),
+ )
+ .insert(
+ "update",
+ CliCommand::new(&api2::config::notifications::matchers::API_METHOD_UPDATE_MATCHER)
+ .arg_param(&["name"]),
+ )
+ .insert(
+ "delete",
+ CliCommand::new(&api2::config::notifications::matchers::API_METHOD_DELETE_MATCHER)
+ .arg_param(&["name"]),
+ );
+ cmd_def.into()
+}
diff --git a/src/bin/proxmox_backup_manager/notifications/mod.rs b/src/bin/proxmox_backup_manager/notifications/mod.rs
index fdd5abe3..d83563f5 100644
--- a/src/bin/proxmox_backup_manager/notifications/mod.rs
+++ b/src/bin/proxmox_backup_manager/notifications/mod.rs
@@ -1,9 +1,12 @@
use proxmox_router::cli::{CliCommandMap, CommandLineInterface};
+mod matchers;
mod targets;
pub fn notification_commands() -> CommandLineInterface {
- let cmd_def = CliCommandMap::new().insert("target", targets::commands());
+ let cmd_def = CliCommandMap::new()
+ .insert("target", targets::commands())
+ .insert("matcher", matchers::commands());
cmd_def.into()
}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 38/43] proxmox-backup-manager: add CLI for gotify endpoints
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (36 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 37/43] proxmox-backup-manager: add CLI for notification matchers Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 39/43] proxmox-backup-manager: add CLI for sendmail endpoints Lukas Wagner
` (4 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
.../notifications/gotify.rs | 93 +++++++++++++++++++
.../notifications/mod.rs | 8 +-
2 files changed, 99 insertions(+), 2 deletions(-)
create mode 100644 src/bin/proxmox_backup_manager/notifications/gotify.rs
diff --git a/src/bin/proxmox_backup_manager/notifications/gotify.rs b/src/bin/proxmox_backup_manager/notifications/gotify.rs
new file mode 100644
index 00000000..541df82e
--- /dev/null
+++ b/src/bin/proxmox_backup_manager/notifications/gotify.rs
@@ -0,0 +1,93 @@
+use anyhow::Error;
+use proxmox_notify::schema::ENTITY_NAME_SCHEMA;
+use serde_json::Value;
+
+use proxmox_router::{cli::*, ApiHandler, RpcEnvironment};
+use proxmox_schema::api;
+
+use proxmox_backup::api2;
+
+#[api(
+ input: {
+ properties: {
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// List all endpoints.
+fn list_endpoints(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::config::notifications::gotify::API_METHOD_LIST_ENDPOINTS;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options()
+ .column(ColumnConfig::new("disable"))
+ .column(ColumnConfig::new("name"))
+ .column(ColumnConfig::new("server"))
+ .column(ColumnConfig::new("comment"));
+
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
+#[api(
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ },
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// Show a single endpoint.
+fn show_endpoint(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::config::notifications::gotify::API_METHOD_GET_ENDPOINT;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options();
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
+pub fn commands() -> CommandLineInterface {
+ let cmd_def = CliCommandMap::new()
+ .insert("list", CliCommand::new(&API_METHOD_LIST_ENDPOINTS))
+ .insert(
+ "show",
+ CliCommand::new(&API_METHOD_SHOW_ENDPOINT).arg_param(&["name"]),
+ )
+ .insert(
+ "create",
+ CliCommand::new(&api2::config::notifications::gotify::API_METHOD_ADD_ENDPOINT)
+ .arg_param(&["name"]),
+ )
+ .insert(
+ "update",
+ CliCommand::new(&api2::config::notifications::gotify::API_METHOD_UPDATE_ENDPOINT)
+ .arg_param(&["name"]),
+ )
+ .insert(
+ "delete",
+ CliCommand::new(&api2::config::notifications::gotify::API_METHOD_DELETE_ENDPOINT)
+ .arg_param(&["name"]),
+ );
+ cmd_def.into()
+}
diff --git a/src/bin/proxmox_backup_manager/notifications/mod.rs b/src/bin/proxmox_backup_manager/notifications/mod.rs
index d83563f5..798d0066 100644
--- a/src/bin/proxmox_backup_manager/notifications/mod.rs
+++ b/src/bin/proxmox_backup_manager/notifications/mod.rs
@@ -1,12 +1,16 @@
use proxmox_router::cli::{CliCommandMap, CommandLineInterface};
+mod gotify;
mod matchers;
mod targets;
pub fn notification_commands() -> CommandLineInterface {
+ let endpoint_def = CliCommandMap::new().insert("gotify", gotify::commands());
+
let cmd_def = CliCommandMap::new()
- .insert("target", targets::commands())
- .insert("matcher", matchers::commands());
+ .insert("endpoint", endpoint_def)
+ .insert("matcher", matchers::commands())
+ .insert("target", targets::commands());
cmd_def.into()
}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 39/43] proxmox-backup-manager: add CLI for sendmail endpoints
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (37 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 38/43] proxmox-backup-manager: add CLI for gotify endpoints Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 40/43] proxmox-backup-manager: add CLI for SMTP endpoints Lukas Wagner
` (3 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
.../notifications/mod.rs | 5 +-
.../notifications/sendmail.rs | 94 +++++++++++++++++++
2 files changed, 98 insertions(+), 1 deletion(-)
create mode 100644 src/bin/proxmox_backup_manager/notifications/sendmail.rs
diff --git a/src/bin/proxmox_backup_manager/notifications/mod.rs b/src/bin/proxmox_backup_manager/notifications/mod.rs
index 798d0066..19a9dd0d 100644
--- a/src/bin/proxmox_backup_manager/notifications/mod.rs
+++ b/src/bin/proxmox_backup_manager/notifications/mod.rs
@@ -2,10 +2,13 @@ use proxmox_router::cli::{CliCommandMap, CommandLineInterface};
mod gotify;
mod matchers;
+mod sendmail;
mod targets;
pub fn notification_commands() -> CommandLineInterface {
- let endpoint_def = CliCommandMap::new().insert("gotify", gotify::commands());
+ let endpoint_def = CliCommandMap::new()
+ .insert("gotify", gotify::commands())
+ .insert("sendmail", sendmail::commands());
let cmd_def = CliCommandMap::new()
.insert("endpoint", endpoint_def)
diff --git a/src/bin/proxmox_backup_manager/notifications/sendmail.rs b/src/bin/proxmox_backup_manager/notifications/sendmail.rs
new file mode 100644
index 00000000..202e15b0
--- /dev/null
+++ b/src/bin/proxmox_backup_manager/notifications/sendmail.rs
@@ -0,0 +1,94 @@
+use anyhow::Error;
+use proxmox_notify::schema::ENTITY_NAME_SCHEMA;
+use serde_json::Value;
+
+use proxmox_router::{cli::*, ApiHandler, RpcEnvironment};
+use proxmox_schema::api;
+
+use proxmox_backup::api2;
+
+#[api(
+ input: {
+ properties: {
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// List all endpoints.
+fn list_endpoints(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::config::notifications::sendmail::API_METHOD_LIST_ENDPOINTS;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options()
+ .column(ColumnConfig::new("disable"))
+ .column(ColumnConfig::new("name"))
+ .column(ColumnConfig::new("mailto"))
+ .column(ColumnConfig::new("mailto-user"))
+ .column(ColumnConfig::new("comment"));
+
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
+#[api(
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ },
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// Show a single endpoint.
+fn show_endpoint(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::config::notifications::sendmail::API_METHOD_GET_ENDPOINT;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options();
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
+pub fn commands() -> CommandLineInterface {
+ let cmd_def = CliCommandMap::new()
+ .insert("list", CliCommand::new(&API_METHOD_LIST_ENDPOINTS))
+ .insert(
+ "show",
+ CliCommand::new(&API_METHOD_SHOW_ENDPOINT).arg_param(&["name"]),
+ )
+ .insert(
+ "create",
+ CliCommand::new(&api2::config::notifications::sendmail::API_METHOD_ADD_ENDPOINT)
+ .arg_param(&["name"]),
+ )
+ .insert(
+ "update",
+ CliCommand::new(&api2::config::notifications::sendmail::API_METHOD_UPDATE_ENDPOINT)
+ .arg_param(&["name"]),
+ )
+ .insert(
+ "delete",
+ CliCommand::new(&api2::config::notifications::sendmail::API_METHOD_DELETE_ENDPOINT)
+ .arg_param(&["name"]),
+ );
+ cmd_def.into()
+}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 40/43] proxmox-backup-manager: add CLI for SMTP endpoints
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (38 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 39/43] proxmox-backup-manager: add CLI for sendmail endpoints Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 41/43] docgen: generate synopsis for notifications{-priv, }.cfg Lukas Wagner
` (2 subsequent siblings)
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Gabriel Goller <g.goller@proxmox.com>
Reviewed-by: Gabriel Goller <g.goller@proxmox.com>
---
.../notifications/mod.rs | 4 +-
.../notifications/smtp.rs | 96 +++++++++++++++++++
2 files changed, 99 insertions(+), 1 deletion(-)
create mode 100644 src/bin/proxmox_backup_manager/notifications/smtp.rs
diff --git a/src/bin/proxmox_backup_manager/notifications/mod.rs b/src/bin/proxmox_backup_manager/notifications/mod.rs
index 19a9dd0d..678f9c54 100644
--- a/src/bin/proxmox_backup_manager/notifications/mod.rs
+++ b/src/bin/proxmox_backup_manager/notifications/mod.rs
@@ -3,12 +3,14 @@ use proxmox_router::cli::{CliCommandMap, CommandLineInterface};
mod gotify;
mod matchers;
mod sendmail;
+mod smtp;
mod targets;
pub fn notification_commands() -> CommandLineInterface {
let endpoint_def = CliCommandMap::new()
.insert("gotify", gotify::commands())
- .insert("sendmail", sendmail::commands());
+ .insert("sendmail", sendmail::commands())
+ .insert("smtp", smtp::commands());
let cmd_def = CliCommandMap::new()
.insert("endpoint", endpoint_def)
diff --git a/src/bin/proxmox_backup_manager/notifications/smtp.rs b/src/bin/proxmox_backup_manager/notifications/smtp.rs
new file mode 100644
index 00000000..3a2b15ef
--- /dev/null
+++ b/src/bin/proxmox_backup_manager/notifications/smtp.rs
@@ -0,0 +1,96 @@
+use anyhow::Error;
+use proxmox_notify::schema::ENTITY_NAME_SCHEMA;
+use serde_json::Value;
+
+use proxmox_router::{cli::*, ApiHandler, RpcEnvironment};
+use proxmox_schema::api;
+
+use proxmox_backup::api2;
+
+#[api(
+ input: {
+ properties: {
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// List all endpoints.
+fn list_endpoints(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::config::notifications::smtp::API_METHOD_LIST_ENDPOINTS;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options()
+ .column(ColumnConfig::new("disable"))
+ .column(ColumnConfig::new("name"))
+ .column(ColumnConfig::new("server"))
+ .column(ColumnConfig::new("from-address"))
+ .column(ColumnConfig::new("mailto"))
+ .column(ColumnConfig::new("mailto-user"))
+ .column(ColumnConfig::new("comment"));
+
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
+#[api(
+ input: {
+ properties: {
+ name: {
+ schema: ENTITY_NAME_SCHEMA,
+ },
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// Show a single endpoint.
+fn show_endpoint(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::config::notifications::smtp::API_METHOD_GET_ENDPOINT;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options();
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
+pub fn commands() -> CommandLineInterface {
+ let cmd_def = CliCommandMap::new()
+ .insert("list", CliCommand::new(&API_METHOD_LIST_ENDPOINTS))
+ .insert(
+ "show",
+ CliCommand::new(&API_METHOD_SHOW_ENDPOINT).arg_param(&["name"]),
+ )
+ .insert(
+ "create",
+ CliCommand::new(&api2::config::notifications::smtp::API_METHOD_ADD_ENDPOINT)
+ .arg_param(&["name"]),
+ )
+ .insert(
+ "update",
+ CliCommand::new(&api2::config::notifications::smtp::API_METHOD_UPDATE_ENDPOINT)
+ .arg_param(&["name"]),
+ )
+ .insert(
+ "delete",
+ CliCommand::new(&api2::config::notifications::smtp::API_METHOD_DELETE_ENDPOINT)
+ .arg_param(&["name"]),
+ );
+ cmd_def.into()
+}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 41/43] docgen: generate synopsis for notifications{-priv, }.cfg
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (39 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 40/43] proxmox-backup-manager: add CLI for SMTP endpoints Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 42/43] docs: add documentation for notification system Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 43/43] ui: util: override default mail author for sendmail/smtp targets Lukas Wagner
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/bin/docgen.rs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/bin/docgen.rs b/src/bin/docgen.rs
index 7ee991a0..66d71423 100644
--- a/src/bin/docgen.rs
+++ b/src/bin/docgen.rs
@@ -31,6 +31,10 @@ fn main() -> Result<(), Error> {
"apidata.js" => generate_api_tree(),
"datastore.cfg" => dump_section_config(&pbs_config::datastore::CONFIG),
"domains.cfg" => dump_section_config(&pbs_config::domains::CONFIG),
+ "notifications.cfg" => dump_section_config(proxmox_notify::config::config_parser()),
+ "notifications-priv.cfg" => {
+ dump_section_config(proxmox_notify::config::private_config_parser())
+ }
"tape.cfg" => dump_section_config(&pbs_config::drive::CONFIG),
"tape-job.cfg" => dump_section_config(&pbs_config::tape_job::CONFIG),
"user.cfg" => dump_section_config(&pbs_config::user::CONFIG),
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 42/43] docs: add documentation for notification system
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (40 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 41/43] docgen: generate synopsis for notifications{-priv, }.cfg Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 43/43] ui: util: override default mail author for sendmail/smtp targets Lukas Wagner
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Mostly copied from PVE and adapted where it makes sense.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
debian/proxmox-backup-server.install | 2 +
docs/Makefile | 6 +-
docs/conf.py | 2 +
docs/config/notifications-priv/format.rst | 1 +
docs/config/notifications-priv/man5.rst | 24 +++
docs/config/notifications/format.rst | 28 +++
docs/config/notifications/man5.rst | 24 +++
docs/configuration-files.rst | 30 +++
docs/index.rst | 1 +
docs/notifications.rst | 213 ++++++++++++++++++++++
www/OnlineHelpInfo.js | 24 +++
11 files changed, 354 insertions(+), 1 deletion(-)
create mode 100644 docs/config/notifications-priv/format.rst
create mode 100644 docs/config/notifications-priv/man5.rst
create mode 100644 docs/config/notifications/format.rst
create mode 100644 docs/config/notifications/man5.rst
create mode 100644 docs/notifications.rst
diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install
index df7d68ee..ef1e9ba1 100644
--- a/debian/proxmox-backup-server.install
+++ b/debian/proxmox-backup-server.install
@@ -30,6 +30,8 @@ usr/share/man/man5/acl.cfg.5
usr/share/man/man5/datastore.cfg.5
usr/share/man/man5/domains.cfg.5
usr/share/man/man5/media-pool.cfg.5
+usr/share/man/man5/notifications.cfg.5
+usr/share/man/man5/notifications-priv.cfg.5
usr/share/man/man5/remote.cfg.5
usr/share/man/man5/sync.cfg.5
usr/share/man/man5/tape-job.cfg.5
diff --git a/docs/Makefile b/docs/Makefile
index 0d0963f3..a617fc91 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -11,6 +11,8 @@ GENERATED_SYNOPSIS := \
pmtx/synopsis.rst \
pmt/synopsis.rst \
config/media-pool/config.rst \
+ config/notifications/config.rst \
+ config/notifications-priv/config.rst \
config/tape/config.rst \
config/tape-job/config.rst \
config/user/config.rst \
@@ -43,7 +45,9 @@ MAN5_PAGES := \
sync.cfg.5 \
verification.cfg.5 \
datastore.cfg.5 \
- domains.cfg.5
+ domains.cfg.5 \
+ notifications.cfg.5 \
+ notifications-priv.cfg.5 \
PRUNE_SIMULATOR_FILES := \
prune-simulator/index.html \
diff --git a/docs/conf.py b/docs/conf.py
index f85cd187..fec234b9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -114,6 +114,8 @@ man_pages = [
('config/tape/man5', 'tape.cfg', 'Tape Drive and Changer Configuration', [author], 5),
('config/user/man5', 'user.cfg', 'User Configuration', [author], 5),
('config/verification/man5', 'verification.cfg', 'Verification Job Configuration', [author], 5),
+ ('config/notifications/man5', 'notifications.cfg', 'Notification target/matcher configuration', [author], 5),
+ ('config/notifications-priv/man5', 'notifications-priv.cfg', 'Notification target secrets', [author], 5),
]
diff --git a/docs/config/notifications-priv/format.rst b/docs/config/notifications-priv/format.rst
new file mode 100644
index 00000000..7d92c979
--- /dev/null
+++ b/docs/config/notifications-priv/format.rst
@@ -0,0 +1 @@
+This file contains protected credentials for notification targets.
diff --git a/docs/config/notifications-priv/man5.rst b/docs/config/notifications-priv/man5.rst
new file mode 100644
index 00000000..827c8ac7
--- /dev/null
+++ b/docs/config/notifications-priv/man5.rst
@@ -0,0 +1,24 @@
+:orphan:
+
+======================
+notifications-priv.cfg
+======================
+
+Description
+===========
+
+The file /etc/proxmox-backup/notifications-priv.cfg is a configuration file
+for Proxmox Backup Server. It contains the configration for the
+notification system configuration.
+
+File Format
+===========
+
+.. include:: format.rst
+
+Options
+=======
+
+.. include:: config.rst
+
+.. include:: ../../pbs-copyright.rst
diff --git a/docs/config/notifications/format.rst b/docs/config/notifications/format.rst
new file mode 100644
index 00000000..e29facb5
--- /dev/null
+++ b/docs/config/notifications/format.rst
@@ -0,0 +1,28 @@
+This file contains configuration for notification targets and notification
+matchers.
+
+.. Each user configuration section starts with the header ``<realm-type>: <name>``,
+.. followed by the realm's configuration options.
+..
+.. For LDAP realms, the LDAP bind password is stored in ``ldap_passwords.json``.
+..
+.. ::
+..
+.. openid: master
+.. client-id pbs
+.. comment
+.. issuer-url http://192.168.0.10:8080/realms/master
+.. username-claim username
+..
+.. ldap: ldap-server
+.. base-dn OU=People,DC=ldap-server,DC=example,DC=com
+.. mode ldaps
+.. server1 192.168.0.10
+.. sync-attributes email=mail
+.. sync-defaults-options enable-new=0,remove-vanished=acl;entry
+.. user-attr uid
+.. user-classes inetorgperson,posixaccount,person,user
+..
+..
+.. You can use the ``proxmox-backup-manager openid`` and ``proxmox-backup-manager ldap`` commands to manipulate
+.. this file.
diff --git a/docs/config/notifications/man5.rst b/docs/config/notifications/man5.rst
new file mode 100644
index 00000000..96844162
--- /dev/null
+++ b/docs/config/notifications/man5.rst
@@ -0,0 +1,24 @@
+:orphan:
+
+==================
+notifications.cfg
+==================
+
+Description
+===========
+
+The file /etc/proxmox-backup/notifications.cfg is a configuration file
+for Proxmox Backup Server. It contains the configration for the
+notification system configuration.
+
+File Format
+===========
+
+.. include:: format.rst
+
+Options
+=======
+
+.. include:: config.rst
+
+.. include:: ../../pbs-copyright.rst
diff --git a/docs/configuration-files.rst b/docs/configuration-files.rst
index ba54a7b0..ee8367e5 100644
--- a/docs/configuration-files.rst
+++ b/docs/configuration-files.rst
@@ -67,6 +67,36 @@ Options
.. include:: config/media-pool/config.rst
+.. _notifications.cfg:
+
+``notifications.cfg``
+~~~~~~~~~~~~~~~~~~~~~
+
+File Format
+^^^^^^^^^^^
+
+.. include:: config/notifications/format.rst
+
+
+Options
+^^^^^^^
+
+.. include:: config/notifications/config.rst
+
+``notifications-priv.cfg``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+File Format
+^^^^^^^^^^^
+
+.. include:: config/notifications-priv/format.rst
+
+
+Options
+^^^^^^^
+
+.. include:: config/notifications-priv/config.rst
+
``tape.cfg``
~~~~~~~~~~~~
diff --git a/docs/index.rst b/docs/index.rst
index 8e13c24f..86add2d7 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -34,6 +34,7 @@ in the section entitled "GNU Free Documentation License".
maintenance.rst
sysadmin.rst
network-management.rst
+ notifications.rst
technical-overview.rst
faq.rst
diff --git a/docs/notifications.rst b/docs/notifications.rst
new file mode 100644
index 00000000..d8367b68
--- /dev/null
+++ b/docs/notifications.rst
@@ -0,0 +1,213 @@
+Notifications
+=============
+
+Overview
+--------
+
+Proxmox Backup Server will send notifications if case of noteworthy
+events.
+
+There are a number of different :ref:`Notification Events`,
+each with their own set of metadata fields that can be used in
+notification matchers.
+
+A notification matcher determines *which* notifications shall be sent *where*.
+A matcher has *match rules*, that can be used to
+match on certain notification properties (e.g. timestamp, severity,
+metadata fields).
+If a matcher matches a notification, the notification will be routed
+to a configured set of notification targets.
+
+A notification target is an abstraction for a destination where a
+notification should be sent to - for instance a Gotify server instance,
+or a set of email addresses.
+There are multiple types of notification targets, including
+sendmail, which uses the system's sendmail command to send emails,
+or gotify, which sends a notification to a Gotify instance.
+
+The notification system can be configured in the GUI under
+``Configuration -> Notifications``. The configuration is stored in
+``/etc/proxmox-backup/notifications.cfg`` and
+``/etc/proxmox-backup/notifications-priv.cfg`` -
+the latter contains sensitive configuration options such as
+passwords or authentication tokens for notification targets and
+can only be read by ``root``.
+
+
+Notification Targets
+--------------------
+
+Proxmox Backup Server offers multiple types of notification targets.
+
+.. _notification_targets_sendmail:
+
+Sendmail
+^^^^^^^^
+The sendmail binary is a program commonly found on Unix-like operating systems
+that handles the sending of email messages.
+It is a command-line utility that allows users and applications to send emails
+directly from the command line or from within scripts.
+
+The sendmail notification target uses the ``sendmail`` binary to send emails to a
+list of configured users or email addresses. If a user is selected as a recipient,
+the email address configured in user's settings will be used.
+For the ``root@pam`` user, this is the email address entered during installation.
+A user's email address can be configured in ``Configuration -> Access Control -> User Management``.
+If a user has no associated email address, no email will be sent.
+
+.. NOTE:: In standard Proxmox Backup Server installations, the ``sendmail`` binary is provided by
+ Postfix. It may be necessary to configure Postfix so that it can deliver
+ mails correctly - for example by setting an external mail relay (smart host).
+ In case of failed delivery, check the system logs for messages logged by
+ the Postfix daemon.
+
+See :ref:`notifications.cfg` for all configuration options.
+
+.. _notification_targets_smtp:
+
+SMTP
+^^^^
+SMTP notification targets can send emails directly to an SMTP mail relay.
+This target does not use the system's MTA to deliver emails.
+Similar to sendmail targets, if a user is selected as a recipient, the user's configured
+email address will be used.
+
+.. NOTE:: Unlike sendmail targets, SMTP targets do not have any queuing/retry mechanism
+ in case of a failed mail delivery.
+
+See :ref:`notifications.cfg` for all configuration options.
+
+.. _notification_targets_gotify:
+
+Gotify
+^^^^^^
+`Gotify <http://gotify.net>`_ is an open-source self-hosted notification server that
+allows you to send push notifications to various devices and
+applications. It provides a simple API and web interface, making it easy to
+integrate with different platforms and services.
+
+See :ref:`notifications.cfg` for all configuration options.
+
+.. _notification_matchers:
+
+Notification Matchers
+---------------------
+
+Notification matchers route notifications to notification targets based
+on their matching rules. These rules can match certain properties of a
+notification, such as the timestamp (``match-calendar``), the severity of
+the notification (``match-severity``) or metadata fields (``match-field``).
+If a notification is matched by a matcher, all targets configured for the
+matcher will receive the notification.
+
+An arbitrary number of matchers can be created, each with with their own
+matching rules and targets to notify.
+Every target is notified at most once for every notification, even if
+the target is used in multiple matchers.
+
+A matcher without rules matches any notification; the configured targets
+will always be notified.
+
+See :ref:`notifications.cfg` for all configuration options.
+
+Calendar Matching Rules
+^^^^^^^^^^^^^^^^^^^^^^^
+A calendar matcher matches a notification's timestamp.
+
+Examples:
+
+* ``match-calendar 8-12``
+* ``match-calendar 8:00-15:30``
+* ``match-calendar mon-fri 9:00-17:00``
+* ``match-calendar sun,tue-wed,fri 9-17``
+
+Field Matching Rules
+^^^^^^^^^^^^^^^^^^^^
+Notifications have a selection of metadata fields that can be matched.
+When using ``exact`` as a matching mode, a ``,`` can be used as a separator.
+The matching rule then matches if the metadata field has **any** of the specified
+values.
+
+Examples:
+
+* ``match-field exact:type=gc`` Only match notifications for garbage collection jobs
+* ``match-field exact:type=prune,verify`` Match prune job and verification job notifications.
+* ``match-field regex:datastore=^backup-.*$`` Match any datastore starting with ``backup``.
+
+If a notification does not have the matched field, the rule will **not** match.
+For instance, a ``match-field regex:datastore=.*`` directive will match any notification that has
+a ``datastore`` metadata field, but will not match if the field does not exist.
+
+Severity Matching Rules
+^^^^^^^^^^^^^^^^^^^^^^^
+A notification has a associated severity that can be matched.
+
+Examples:
+
+* ``match-severity error``: Only match errors
+* ``match-severity warning,error``: Match warnings and error
+
+The following severities are in use:
+``info``, ``notice``, ``warning``, ``error``, ``unknown``.
+
+.. _Notification Events:
+
+Notification Events
+-------------------
+
+The following table contains a list of all notification events in Proxmox Backup server, their
+type, severity and additional metadata fields. ``type`` as well as any other metadata field
+may be used in ``match-field`` match rules.
+
+================================ ==================== ========== ==============================================================
+Event ``type`` Severity Metadata fields (in addition to ``type``)
+================================ ==================== ========== ==============================================================
+ACME certificate renewal failed ``acme`` ``error`` ``hostname``
+Garbage collection failure ``gc`` ``error`` ``datastore``, ``hostname``
+Garbage collection success ``gc`` ``info`` ``datastore``, ``hostname``
+Package updates available ``package-updates`` ``info`` ``hostname``
+Prune job failure ``prune`` ``error`` ``datastore``, ``hostname``, ``prune-job``
+Prune job success ``prune`` ``info`` ``datastore``, ``hostname``, ``prune-job``
+Remote sync failure ``sync`` ``error`` ``datastore``, ``hostname``, ``sync-job``
+Remote sync success ``sync`` ``info`` ``datastore``, ``hostname``, ``sync-job``
+Tape backup job failure ``tape-backup`` ``error`` ``datastore``, ``hostname``, ``media-pool``, ``tape-job``
+Tape backup job success ``tape-backup`` ``info`` ``datastore``, ``hostname``, ``media-pool``, ``tape-job``
+Tape loading request ``tape-load`` ``notice`` ``hostname``
+Verification job failure ``verification`` ``error`` ``datastore``, ``hostname``, ``verification-job``
+Verification job success ``verification`` ``info`` ``datastore``, ``hostname``, ``verification-job``
+================================ ==================== ========== ==============================================================
+
+The following table contains a description of all use metadata fields. All of these
+can be used in ``match-field`` match rules.
+
+==================== ===================================
+Metadata field Description
+==================== ===================================
+``datastore`` The name of the datastore
+``hostname`` The hostname of the backup server
+``media-pool`` The name of the tape media pool
+``prune-job`` Prune job ID
+``sync-job`` Sync job ID
+``tape-job`` Tape backup job ID
+``type`` Notification event type
+``verification-job`` Verification job ID
+==================== ===================================
+
+System Mail Forwarding
+----------------------
+Certain local system daemons, such as ``smartd``, send notification emails
+to the local ``root`` user. Proxmox Backup Server will feed these mails
+into the notification system as a notification of type ``system-mail``
+and with severity ``unknown``.
+
+When the email is forwarded to a sendmail target, the mail's content and headers
+are forwarded as-is. For all other targets,
+the system tries to extract both a subject line and the main text body
+from the email content. In instances where emails solely consist of HTML
+content, they will be transformed into plain text format during this process.
+
+Permissions
+-----------
+In order to modify/view the configuration for notification targets,
+the ``Sys.Modify/Sys.Audit`` permissions are required for the
+``/system/notifications`` ACL node.
diff --git a/www/OnlineHelpInfo.js b/www/OnlineHelpInfo.js
index 2402c11d..639408b1 100644
--- a/www/OnlineHelpInfo.js
+++ b/www/OnlineHelpInfo.js
@@ -35,6 +35,10 @@ const proxmoxOnlineHelpInfo = {
"link": "/docs/configuration-files.html#domains-cfg",
"title": "``domains.cfg``"
},
+ "notifications-cfg": {
+ "link": "/docs/configuration-files.html#notifications-cfg",
+ "title": "``notifications.cfg``"
+ },
"faq-support-table": {
"link": "/docs/faq.html#faq-support-table",
"title": "How long will my Proxmox Backup Server version be supported?"
@@ -139,6 +143,26 @@ const proxmoxOnlineHelpInfo = {
"link": "/docs/network-management.html#sysadmin-traffic-control",
"title": "Traffic Control"
},
+ "notification-targets-sendmail": {
+ "link": "/docs/notifications.html#notification-targets-sendmail",
+ "title": "Sendmail"
+ },
+ "notification-targets-smtp": {
+ "link": "/docs/notifications.html#notification-targets-smtp",
+ "title": "SMTP"
+ },
+ "notification-targets-gotify": {
+ "link": "/docs/notifications.html#notification-targets-gotify",
+ "title": "Gotify"
+ },
+ "notification-matchers": {
+ "link": "/docs/notifications.html#notification-matchers",
+ "title": "Notification Matchers"
+ },
+ "notification-events": {
+ "link": "/docs/notifications.html#notification-events",
+ "title": "Notification Events"
+ },
"pve-integration": {
"link": "/docs/pve-integration.html#pve-integration",
"title": "`Proxmox VE`_ Integration"
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v2 43/43] ui: util: override default mail author for sendmail/smtp targets
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
` (41 preceding siblings ...)
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 42/43] docs: add documentation for notification system Lukas Wagner
@ 2024-04-17 14:35 ` Lukas Wagner
42 siblings, 0 replies; 44+ messages in thread
From: Lukas Wagner @ 2024-04-17 14:35 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
www/Utils.js | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/www/Utils.js b/www/Utils.js
index ae8d8ed3..f5ffa704 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -458,6 +458,26 @@ Ext.define('PBS.Utils', {
sync: false,
},
});
+
+ Proxmox.Schema.overrideEndpointTypes({
+ sendmail: {
+ name: 'Sendmail',
+ ipanel: 'pmxSendmailEditPanel',
+ iconCls: 'fa-envelope-o',
+ defaultMailAuthor: 'Proxmox Backup Server ($hostname)',
+ },
+ smtp: {
+ name: 'SMTP',
+ ipanel: 'pmxSmtpEditPanel',
+ iconCls: 'fa-envelope-o',
+ defaultMailAuthor: 'Proxmox Backup Server ($hostname)',
+ },
+ gotify: {
+ name: 'Gotify',
+ ipanel: 'pmxGotifyEditPanel',
+ iconCls: 'fa-bell-o',
+ },
+ });
},
// Convert an ArrayBuffer to a base64url encoded string.
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 44+ messages in thread
end of thread, other threads:[~2024-04-17 14:45 UTC | newest]
Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-17 14:34 [pbs-devel] [PATCH many v2 00/43] integrate notification system Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 01/43] notify: expose `config` module Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 02/43] notify: use std::sync::OnceCell instead of lazy_static! Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 03/43] notify: pbs-context: exclude successful prunes in default matcher Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 04/43] notify: endpoints: matcher: improve descriptions for API types Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 05/43] notify: sys: move 'email' module from proxmox_sys to proxmox_notify Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox v2 06/43] notify: add getter for notification timestamp Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH widget-toolkit v2 07/43] sendmail: smtp: allow to overide default mail author Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 08/43] pbs-config: add module for loading notification config Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 09/43] server: rename email_notifications module to notifications Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 10/43] notifications: allow sending notifications via proxmox_notify Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 11/43] buildsys: install templates for test notifications Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 12/43] pbs-config: acl: add /system/notifications as known ACL path Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 13/43] api: add endpoints for querying/testing notification targets Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 14/43] api: add endpoints for notification matchers Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 15/43] api: add endpoints for sendmail targets Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 16/43] api: add endpoints for smtp targets Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 17/43] api: add endpoints for gotify targets Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 18/43] api: add endpoints for querying known notification values/fields Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 19/43] api-types: api: datatore: add notification-mode parameter Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 20/43] api-types: api: tape: " Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 21/43] server: notifications: send GC notifications via notification system Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 22/43] server: notifications: send prune " Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 23/43] server: notifications: send verify " Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 24/43] server: notifications: send sync " Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 25/43] server: notifications: send update " Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 26/43] server: notifications: send acme " Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 27/43] server: notifications: send tape " Lukas Wagner
2024-04-17 14:34 ` [pbs-devel] [PATCH proxmox-backup v2 28/43] ui: add notification config panel Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 29/43] ui: tape backup job: add selector for notification-mode Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 30/43] ui: tape backup: add selector for 'notification-mode' Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 31/43] ui: tape restore: add 'notification-mode' parameter Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 32/43] ui: datastore options: " Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 33/43] ui: utils: add overrides for known notification metadata fields/values Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 34/43] ui: datastore edit: make new stores use notification system by default Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 35/43] ui: permissions paths: add /system/notifications to combobox Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 36/43] proxmox-backup-manager: add CLI for notification targets Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 37/43] proxmox-backup-manager: add CLI for notification matchers Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 38/43] proxmox-backup-manager: add CLI for gotify endpoints Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 39/43] proxmox-backup-manager: add CLI for sendmail endpoints Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 40/43] proxmox-backup-manager: add CLI for SMTP endpoints Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 41/43] docgen: generate synopsis for notifications{-priv, }.cfg Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 42/43] docs: add documentation for notification system Lukas Wagner
2024-04-17 14:35 ` [pbs-devel] [PATCH proxmox-backup v2 43/43] ui: util: override default mail author for sendmail/smtp targets Lukas Wagner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox