public inbox for pdm-devel@lists.proxmox.com
 help / color / mirror / Atom feed
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
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal