From: Lukas Wagner <l.wagner@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [pdm-devel] [PATCH datacenter-manager] ui: add task descriptions for PBS tasks
Date: Wed, 17 Dec 2025 15:39:43 +0100 [thread overview]
Message-ID: <20251217143943.273183-1-l.wagner@proxmox.com> (raw)
Tried to match the JS-implementation as exactly as possible. Some of the
definitions could definitely be improved, but this should be done in
tandem with the JS code. Maybe we could could even attempt to have a
canonical definition somewhere and then generate both the Rust and JS
implementations from that - but not sure if this is worth the effort.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
This patch requires
https://lore.proxmox.com/pdm-devel/20251216131518.241022-7-l.wagner@proxmox.com/T/#u
to be applied first. This patch is pretty much independent of the series
it is contained in, so it could be applied ahead of the rest.
ui/Cargo.toml | 2 +
ui/src/tasks.rs | 162 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 164 insertions(+)
diff --git a/ui/Cargo.toml b/ui/Cargo.toml
index 1b4f0a23..735a31ac 100644
--- a/ui/Cargo.toml
+++ b/ui/Cargo.toml
@@ -18,6 +18,7 @@ http = "1"
js-sys = "0.3.69"
log = "0.4.6"
percent-encoding = "2.1"
+regex = "1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
wasm-bindgen = "0.2.92"
@@ -42,6 +43,7 @@ proxmox-schema = "5"
proxmox-subscription = { version = "1.0.1", features = ["api-types"], default-features = false }
proxmox-rrd-api-types = "1"
proxmox-node-status = "1"
+proxmox-time = "2.1"
pbs-api-types = { version = "1.0.3", features = [ "enum-fallback" ] }
pdm-api-types = { version = "1.0", path = "../lib/pdm-api-types" }
diff --git a/ui/src/tasks.rs b/ui/src/tasks.rs
index 7e40863d..964ba47c 100644
--- a/ui/src/tasks.rs
+++ b/ui/src/tasks.rs
@@ -6,6 +6,7 @@ use yew::virtual_dom::Key;
pub fn register_tasks() {
register_pve_tasks();
+ register_pbs_tasks();
register_pdm_tasks();
}
@@ -112,6 +113,96 @@ fn register_pve_tasks() {
register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
}
+pub fn register_pbs_tasks() {
+ register_task_description("acme-deativate", |_ty, id: Option<String>| {
+ let id = id.unwrap_or_else(|| "default".to_string());
+ tr!("Deactivate ACME Account - {0}", id)
+ });
+ register_task_description("acme-register", |_ty, id: Option<String>| {
+ let id = id.unwrap_or_else(|| "default".to_string());
+ tr!("Register ACME Account - {0}", id)
+ });
+ register_task_description("acme-update", |_ty, id: Option<String>| {
+ let id = id.unwrap_or_else(|| "default".to_string());
+ tr!("Update ACME Account - {0}", id)
+ });
+ register_task_description("acme-new-cert", ("", tr!("Order Certificate")));
+ register_task_description("acme-renew-cert", ("", tr!("Renew Certificate")));
+ register_task_description("acme-revoke-cert", ("", tr!("Revoke Certificate")));
+ register_task_description("backup", |_ty, id: Option<String>| {
+ render_datastore_worker_id(&id.unwrap_or_default(), &tr!("Backup"))
+ });
+ register_task_description("barcode-label-media", ("Drive", tr!("Barcode-Label Media")));
+ register_task_description("catalog-media", ("Drive", tr!("Catalog Media")));
+ register_task_description(
+ "create-datastore",
+ (tr!("Datastore"), tr!("Create Datastore")),
+ );
+ register_task_description(
+ "delete-datastore",
+ (tr!("Datastore"), tr!("Remove Datastore")),
+ );
+ register_task_description(
+ "delete-namespace",
+ (tr!("Namespace"), tr!("Remove Namespace")),
+ );
+ register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
+ register_task_description("dirremove", (tr!("Directory Storage"), tr!("Remove")));
+ register_task_description("eject-media", (tr!("Drive"), tr!("Eject Media")));
+ register_task_description("format-media", (tr!("Drive"), tr!("Format Media")));
+ register_task_description("forget-group", (tr!("Group"), tr!("Remove Group")));
+ register_task_description(
+ "garbage_collection",
+ (tr!("Datastore"), tr!("Garbage Collect")),
+ );
+ register_task_description("realm-sync", ("Realm", tr!("User Sync")));
+ register_task_description("inventory-update", (tr!("Drive"), tr!("Inventory Update")));
+ register_task_description("label-media", (tr!("Drive"), tr!("Label Media")));
+ register_task_description("load-media", |_ty, id: Option<String>| {
+ render_drive_load_media_id(&id.unwrap_or_default(), &tr!("Load Media"))
+ });
+ register_task_description("logrotate", tr!("Log Rotation"));
+ register_task_description("mount-device", (tr!("Datastore"), tr!("Mount Device")));
+ register_task_description(
+ "mount-sync-jobs",
+ (
+ tr!("Datastore"),
+ tr!("sync jobs handler triggered by mount"),
+ ),
+ );
+ register_task_description("prune", |_ty, id: Option<String>| {
+ render_datastore_worker_id(&id.unwrap_or_default(), "Prune")
+ });
+ register_task_description("prunejob", |_ty, id: Option<String>| {
+ render_prune_job_worker_id(&id.unwrap_or_default(), &tr!("Prune Job"))
+ });
+ register_task_description("reader", |_ty, id: Option<String>| {
+ render_datastore_worker_id(&id.unwrap_or_default(), &tr!("Read Objects"))
+ });
+ register_task_description("rewind-media", (tr!("Drive"), tr!("Rewind Media")));
+ register_task_description("s3-refresh", (tr!("Datastore"), tr!("S3 Refresh")));
+ register_task_description("sync", (tr!("Datastore"), tr!("Remote Sync")));
+ register_task_description("syncjob", (tr!("Sync Job"), tr!("Remote Sync")));
+ register_task_description("tape-backup", |_ty, id: Option<String>| {
+ render_tape_backup_id(&id.unwrap_or_default(), &tr!("Tape Backup"))
+ });
+ register_task_description("tape-backup-job", |_ty, id: Option<String>| {
+ render_tape_backup_id(&id.unwrap_or_default(), &tr!("Tape Backup Job"))
+ });
+ register_task_description("tape-restore", (tr!("Datastore"), tr!("Tape Restore")));
+ register_task_description("unload-media", (tr!("Drive"), tr!("Unload Media")));
+ register_task_description("unmount-device", (tr!("Datastore"), tr!("Unmount Device")));
+ register_task_description(
+ "verificationjob",
+ (tr!("Verify Job"), tr!("Scheduled Verification")),
+ );
+ register_task_description("verify", (tr!("Datastore"), tr!("Verification")));
+ register_task_description("verify_group", (tr!("Group"), tr!("Verification")));
+ register_task_description("verify_snapshot", (tr!("Snapshot"), tr!("Verification")));
+ register_task_description("wipedisk", (tr!("Device"), tr!("Wipe Disk")));
+ register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
+}
+
fn register_pdm_tasks() {
register_task_description("logrotate", tr!("Log Rotation"));
register_task_description(
@@ -124,6 +215,77 @@ fn register_pdm_tasks() {
);
}
+proxmox_schema::const_regex! {
+ DATASTORE_WORKER_ID_REGEX = r"^(\S+?):(\S+?)/(\S+?)(/(.+))?$";
+}
+
+fn render_datastore_worker_id(id: &str, what: &str) -> String {
+ if let Some(caps) = DATASTORE_WORKER_ID_REGEX.captures(id) {
+ let datastore = &caps[1];
+ let backup_group = format!("{}/{}", &caps[2], &caps[3]);
+
+ if caps.get(4).is_some() {
+ if let Some(hex_ts) = caps.get(5) {
+ if let Ok(seconds) = u64::from_str_radix(hex_ts.as_str(), 16) {
+ let utctime =
+ proxmox_time::epoch_to_rfc3339_utc(seconds as i64).unwrap_or_default();
+
+ return format!("Datastore {datastore} {what} {backup_group}/{utctime}");
+ }
+ }
+ }
+
+ return format!("Datastore {datastore} {what} {backup_group}");
+ }
+
+ format!("Datastore {what} {id}")
+}
+
+proxmox_schema::const_regex! {
+ PRUNE_JOB_WORKER_ID_REGEX = r"^(\S+?):(\S+)$";
+}
+
+fn render_prune_job_worker_id(id: &str, what: &str) -> String {
+ if let Some(caps) = PRUNE_JOB_WORKER_ID_REGEX.captures(id) {
+ let datastore = &caps[1];
+ let namespace = &caps[2];
+
+ return format!("{what} on Datastore {datastore} Namespace {namespace}",);
+ }
+
+ format!("{what} on Datastore {id}")
+}
+
+proxmox_schema::const_regex! {
+ TAPE_WORKER_ID_REGEX = r"^(\S+?):(\S+?):(\S+?)(:(.+))?$";
+}
+
+fn render_tape_backup_id(id: &str, what: &str) -> String {
+ if let Some(caps) = TAPE_WORKER_ID_REGEX.captures(id) {
+ let datastore = &caps[1];
+ let pool = &caps[2];
+ let drive = &caps[3];
+
+ return format!("{what} {datastore} (pool {pool}, drive {drive})");
+ }
+
+ format!("{what} {id}")
+}
+
+proxmox_schema::const_regex! {
+ DRIVE_LOAD_WORKER_ID_REGEX = r"^(\S+?):(\S+?)$";
+}
+
+fn render_drive_load_media_id(id: &str, what: &str) -> String {
+ if let Some(caps) = DRIVE_LOAD_WORKER_ID_REGEX.captures(id) {
+ let drive = &caps[1];
+ let label = &caps[2];
+ return format!("{} {drive} - {what} '{label}'", tr!("Drive"));
+ }
+
+ format!("{what} {id}")
+}
+
/// Format a UPID that is either [`RemoteUpid`] or a [`UPID`]
/// If it's a [`RemoteUpid`], prefixes it with the remote name
pub fn format_optional_remote_upid(upid: &str, include_remote: bool) -> String {
--
2.47.3
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
reply other threads:[~2025-12-17 14:39 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251217143943.273183-1-l.wagner@proxmox.com \
--to=l.wagner@proxmox.com \
--cc=pdm-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox