[pdm-devel] [PATCH proxmox-datacenter-manager v2 2/5] server: api: add resource-type parameter to list_resources

Stefan Hanreich s.hanreich at proxmox.com
Tue Sep 9 17:54:17 CEST 2025


Add a new parameter to the list_resources call that filters entities
based on their type. While this should already be possible with the
search function as well, filtering directly by enum is more efficient
than building the search filters and then doing matching based on
strings. The type parameter has precedence, so any search filters will
be applied only on entities that have the type specified in
resource-type.

In pdm-client add a separate method to not pollute existing call sites
with unnecessary parameters. In the future it might make sense to add
another method that takes all possible combinations of parameters.

Signed-off-by: Stefan Hanreich <s.hanreich at proxmox.com>
---
 lib/pdm-api-types/src/resource.rs | 15 ++++++++++++++-
 lib/pdm-client/src/lib.rs         | 15 ++++++++++++++-
 server/src/api/resources.rs       | 18 +++++++++++++++---
 server/src/resource_cache.rs      |  2 +-
 4 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/lib/pdm-api-types/src/resource.rs b/lib/pdm-api-types/src/resource.rs
index f274451..b219250 100644
--- a/lib/pdm-api-types/src/resource.rs
+++ b/lib/pdm-api-types/src/resource.rs
@@ -100,14 +100,27 @@ impl Resource {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[api]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
 /// Type of a PDM resource.
 pub enum ResourceType {
+    /// PVE Storage Resource
+    #[serde(rename = "storage")]
     PveStorage,
+    /// PVE Qemu Resource
+    #[serde(rename = "qemu")]
     PveQemu,
+    /// PVE LXC Resource
+    #[serde(rename = "lxc")]
     PveLxc,
+    /// PVE SDN Resource
+    #[serde(rename = "sdn-zone")]
     PveSdnZone,
+    /// PBS Datastore Resource
+    #[serde(rename = "datastore")]
     PbsDatastore,
+    /// Node resource
+    #[serde(rename = "node")]
     Node,
 }
 
diff --git a/lib/pdm-client/src/lib.rs b/lib/pdm-client/src/lib.rs
index 845738f..f2ff4d4 100644
--- a/lib/pdm-client/src/lib.rs
+++ b/lib/pdm-client/src/lib.rs
@@ -4,7 +4,7 @@ use std::collections::HashMap;
 use std::time::Duration;
 
 use pdm_api_types::remotes::TlsProbeOutcome;
-use pdm_api_types::resource::{PveResource, RemoteResources, TopEntities};
+use pdm_api_types::resource::{PveResource, RemoteResources, ResourceType, TopEntities};
 use pdm_api_types::rrddata::{
     LxcDataPoint, NodeDataPoint, PbsDatastoreDataPoint, PbsNodeDataPoint, PveStorageDataPoint,
     QemuDataPoint,
@@ -865,6 +865,19 @@ impl<T: HttpApiClient> PdmClient<T> {
         Ok(self.0.get(&path).await?.expect_json()?.data)
     }
 
+    pub async fn resources_by_type(
+        &self,
+        max_age: Option<u64>,
+        resource_type: ResourceType,
+    ) -> Result<Vec<RemoteResources>, Error> {
+        let path = ApiPathBuilder::new("/api2/extjs/resources/list")
+            .maybe_arg("max-age", &max_age)
+            .arg("resource-type", resource_type)
+            .build();
+
+        Ok(self.0.get(&path).await?.expect_json()?.data)
+    }
+
     pub async fn pve_list_networks(
         &self,
         remote: &str,
diff --git a/server/src/api/resources.rs b/server/src/api/resources.rs
index 736bfb9..dcdf0ea 100644
--- a/server/src/api/resources.rs
+++ b/server/src/api/resources.rs
@@ -150,6 +150,10 @@ fn remote_matches_search_term(remote_name: &str, online: Option<bool>, term: &Se
                 description: "Search term to filter for, uses special syntax e.g. <TODO>",
                 optional: true,
             },
+            "resource-type": {
+                type: ResourceType,
+                optional: true,
+            },
         }
     },
     returns: {
@@ -163,10 +167,11 @@ fn remote_matches_search_term(remote_name: &str, online: Option<bool>, term: &Se
 /// List all resources from remote nodes.
 pub async fn get_resources(
     max_age: u64,
+    resource_type: Option<ResourceType>,
     search: Option<String>,
     rpcenv: &mut dyn RpcEnvironment,
 ) -> Result<Vec<RemoteResources>, Error> {
-    get_resources_impl(max_age, search, Some(rpcenv)).await
+    get_resources_impl(max_age, search, resource_type, Some(rpcenv)).await
 }
 
 // helper to determine if the combination of search terms requires the results
@@ -208,6 +213,7 @@ fn is_remotes_only(filters: &Search) -> bool {
 pub(crate) async fn get_resources_impl(
     max_age: u64,
     search: Option<String>,
+    resource_type: Option<ResourceType>,
     rpcenv: Option<&mut dyn RpcEnvironment>,
 ) -> Result<Vec<RemoteResources>, Error> {
     let user_info = CachedUserInfo::new()?;
@@ -252,8 +258,14 @@ pub(crate) async fn get_resources_impl(
 
             if remotes_only {
                 resources.clear();
-            } else if !filter.is_empty() {
+            } else if resource_type.is_some() || !filter.is_empty() {
                 resources.retain(|resource| {
+                    if let Some(resource_type) = resource_type {
+                        if resource.resource_type() != resource_type {
+                            return false;
+                        }
+                    }
+
                     filter.matches(|filter| {
                         // if we get can't decide if it matches, don't filter it out
                         resource_matches_search_term(resource, filter).unwrap_or(true)
@@ -318,7 +330,7 @@ pub async fn get_status(
     max_age: u64,
     rpcenv: &mut dyn RpcEnvironment,
 ) -> Result<ResourcesStatus, Error> {
-    let remotes = get_resources(max_age, None, rpcenv).await?;
+    let remotes = get_resources(max_age, None, None, rpcenv).await?;
     let mut counts = ResourcesStatus::default();
     for remote in remotes {
         if remote.error.is_some() {
diff --git a/server/src/resource_cache.rs b/server/src/resource_cache.rs
index 0ae86ee..aa20c54 100644
--- a/server/src/resource_cache.rs
+++ b/server/src/resource_cache.rs
@@ -21,7 +21,7 @@ pub fn start_task() {
 async fn resource_caching_task() -> Result<(), Error> {
     loop {
         if let Err(err) =
-            crate::api::resources::get_resources_impl(METRIC_POLL_INTERVALL, None, None).await
+            crate::api::resources::get_resources_impl(METRIC_POLL_INTERVALL, None, None, None).await
         {
             log::error!("could not update resource cache: {err}");
         }
-- 
2.47.3




More information about the pdm-devel mailing list