[pdm-devel] [PATCH datacenter-manager 2/4] lib/server: pve: add api call to get the cached version info from remotes

Dominik Csapak d.csapak at proxmox.com
Tue Dec 2 11:00:03 CET 2025


this is useful when we e.g. want to feature gate some things in the ui.
This way we don't have to get the whole update information for all
remotes, and we don't have to query all nodes of the remotes for their
versions.

Should we need it in the future, we can do the analagous api call for
pbs too.

Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
 lib/pdm-client/src/lib.rs    |  6 ++++++
 server/src/api/pve/mod.rs    | 21 +++++++++++++++++++++
 server/src/remote_updates.rs | 22 +++++++++++++++++++++-
 3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/lib/pdm-client/src/lib.rs b/lib/pdm-client/src/lib.rs
index 11bedb64..f8d6062a 100644
--- a/lib/pdm-client/src/lib.rs
+++ b/lib/pdm-client/src/lib.rs
@@ -3,6 +3,7 @@
 use std::collections::HashMap;
 use std::time::Duration;
 
+use pdm_api_types::remote_updates::RemoteUpdateSummary;
 use pdm_api_types::remotes::{RemoteType, TlsProbeOutcome};
 use pdm_api_types::resource::{PveResource, RemoteResources, ResourceType, TopEntities};
 use pdm_api_types::rrddata::{
@@ -554,6 +555,11 @@ impl<T: HttpApiClient> PdmClient<T> {
         Ok(self.0.get(&query).await?.expect_json()?.data)
     }
 
+    pub async fn pve_cluster_updates(&self, remote: &str) -> Result<RemoteUpdateSummary, Error> {
+        let url = format!("/api2/extjs/pve/remotes/{remote}/updates");
+        Ok(self.0.get(&url).await?.expect_json()?.data)
+    }
+
     pub async fn pve_cluster_status(
         &self,
         remote: &str,
diff --git a/server/src/api/pve/mod.rs b/server/src/api/pve/mod.rs
index 310c6d08..97dc3970 100644
--- a/server/src/api/pve/mod.rs
+++ b/server/src/api/pve/mod.rs
@@ -13,6 +13,7 @@ use proxmox_schema::property_string::PropertyString;
 use proxmox_section_config::typed::SectionConfigData;
 use proxmox_sortable_macro::sortable;
 
+use pdm_api_types::remote_updates::RemoteUpdateSummary;
 use pdm_api_types::remotes::{
     NodeUrl, Remote, RemoteListEntry, RemoteType, TlsProbeOutcome, REMOTE_ID_SCHEMA,
 };
@@ -32,6 +33,7 @@ use super::resources::{map_pve_lxc, map_pve_node, map_pve_qemu, map_pve_storage}
 use crate::connection::PveClient;
 use crate::connection::{self, probe_tls_connection};
 use crate::remote_tasks;
+use crate::remote_updates::get_available_updates_for_remote;
 
 mod firewall;
 mod lxc;
@@ -75,6 +77,7 @@ const REMOTE_SUBDIRS: SubdirMap = &sorted!([
     ("resources", &RESOURCES_ROUTER),
     ("cluster-status", &STATUS_ROUTER),
     ("tasks", &tasks::ROUTER),
+    ("updates", &Router::new().get(&API_METHOD_GET_UPDATES)),
 ]);
 
 const NODES_ROUTER: Router = Router::new()
@@ -530,3 +533,21 @@ pub async fn get_options(remote: String) -> Result<serde_json::Value, Error> {
 
     Ok(options)
 }
+
+#[api(
+    input: {
+        properties: {
+            remote: { schema: REMOTE_ID_SCHEMA },
+        },
+    },
+    access: {
+        // correct permission?
+        permission: &Permission::Privilege(&["resource", "{remote}"], PRIV_RESOURCE_AUDIT, false),
+    },
+)]
+/// Return the cached update information about a remote.
+pub fn get_updates(remote: String) -> Result<RemoteUpdateSummary, Error> {
+    let update_summary = get_available_updates_for_remote(&remote)?;
+
+    Ok(update_summary)
+}
diff --git a/server/src/remote_updates.rs b/server/src/remote_updates.rs
index 7e57b56e..e772eef5 100644
--- a/server/src/remote_updates.rs
+++ b/server/src/remote_updates.rs
@@ -1,7 +1,7 @@
 use std::fs::File;
 use std::io::ErrorKind;
 
-use anyhow::Error;
+use anyhow::{bail, Error};
 use serde::{Deserialize, Serialize};
 
 use proxmox_apt_api_types::{APTRepositoriesResult, APTRepositoryHandle, APTUpdateInfo};
@@ -136,6 +136,26 @@ pub fn get_available_updates_summary() -> Result<UpdateSummary, Error> {
     Ok(summary)
 }
 
+/// Return cached update information from specific remote
+pub fn get_available_updates_for_remote(remote: &str) -> Result<RemoteUpdateSummary, Error> {
+    let (config, _digest) = pdm_config::remotes::config()?;
+
+    if let Some(remote) = config.get(remote) {
+        let cache_content = get_cached_summary_or_default()?;
+        Ok(cache_content
+            .remotes
+            .get(&remote.id)
+            .cloned()
+            .unwrap_or_else(|| RemoteUpdateSummary {
+                nodes: NodeUpdateSummaryWrapper::default(),
+                remote_type: remote.ty,
+                status: RemoteUpdateStatus::Unknown,
+            }))
+    } else {
+        bail!("no such remote '{remote}'");
+    }
+}
+
 fn get_cached_summary_or_default() -> Result<UpdateSummary, Error> {
     match File::open(UPDATE_CACHE) {
         Ok(file) => {
-- 
2.47.3





More information about the pdm-devel mailing list