* [pdm-devel] [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests
@ 2025-12-02 9:59 Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH yew-comp 1/2] qemu: options/hardware: prepare and use version feature gating Dominik Csapak
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Dominik Csapak @ 2025-12-02 9:59 UTC (permalink / raw)
To: pdm-devel
This adds some functionality so we can easily version guard specific features
for a pve node version.
Currently this is done for:
* env/entrypoint options for lxc
* intel-tdx options for qemu
We reuse the cached update information here, but we can easily change that out
if we want/need to.
proxmox-yew-comp:
Dominik Csapak (2):
qemu: options/hardware: prepare and use version feature gating
pve: lxc panels: prepare/add version feature gating
Cargo.toml | 1 +
src/configuration/pve/lxc_dns_panel.rs | 5 +++
src/configuration/pve/lxc_network_panel.rs | 5 +++
src/configuration/pve/lxc_options_panel.rs | 33 ++++++++++++++++---
.../pve/lxc_resources_panel/mod.rs | 5 +++
.../pve/qemu_hardware_panel/mod.rs | 5 +++
src/configuration/pve/qemu_options_panel.rs | 33 ++++++++++++++++---
src/form/pve/lxc_property/mod.rs | 11 +++++++
src/form/pve/mod.rs | 10 +++---
9 files changed, 94 insertions(+), 14 deletions(-)
proxmxo-datacenter-manager:
Dominik Csapak (4):
ui: subscription_info: add subscription counts
lib/server: pve: add api call to get the cached version info from
remotes
ui: pve: qemu: load and pass the pve-manager version to panels
ui: pve: lxc: pass the pve-manager version to panels
lib/pdm-client/src/lib.rs | 6 ++
server/src/api/pve/mod.rs | 21 +++++
server/src/remote_updates.rs | 22 +++++-
ui/src/dashboard/subscription_info.rs | 109 ++++++++++++++++++++++++--
ui/src/lib.rs | 14 ++++
ui/src/pve/lxc/mod.rs | 15 +++-
ui/src/pve/mod.rs | 63 ++++++++++-----
ui/src/pve/qemu/mod.rs | 12 ++-
8 files changed, 231 insertions(+), 31 deletions(-)
Summary over all repositories:
17 files changed, 325 insertions(+), 45 deletions(-)
--
Generated by git-murpp 0.8.1
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [pdm-devel] [PATCH yew-comp 1/2] qemu: options/hardware: prepare and use version feature gating
2025-12-02 9:59 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
@ 2025-12-02 10:00 ` Dominik Csapak
2025-12-02 10:32 ` Thomas Lamprecht
2025-12-02 10:00 ` [pdm-devel] [PATCH yew-comp 2/2] pve: lxc panels: prepare/add " Dominik Csapak
` (5 subsequent siblings)
6 siblings, 1 reply; 10+ messages in thread
From: Dominik Csapak @ 2025-12-02 10:00 UTC (permalink / raw)
To: pdm-devel
use the pve-manager version to feature gate the intel-tdx property for
now, but also prepare the hardware panel so we can already start passing
the version to it. If we need it there, we already have it then.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
Cargo.toml | 1 +
.../pve/qemu_hardware_panel/mod.rs | 5 +++
src/configuration/pve/qemu_options_panel.rs | 33 ++++++++++++++++---
3 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index 622bb09..600fafa 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -88,6 +88,7 @@ proxmox-node-status = { version = "1", features = [] }
pve-api-types = "8.1.2"
pbs-api-types = "1"
+proxmox-deb-version = "0.1.0"
[features]
default = []
diff --git a/src/configuration/pve/qemu_hardware_panel/mod.rs b/src/configuration/pve/qemu_hardware_panel/mod.rs
index 38bc6fd..c04c01f 100644
--- a/src/configuration/pve/qemu_hardware_panel/mod.rs
+++ b/src/configuration/pve/qemu_hardware_panel/mod.rs
@@ -38,6 +38,11 @@ pub struct QemuHardwarePanel {
vmid: u32,
node: AttrValue,
+ #[prop_or_default]
+ #[builder(IntoPropValue, into_prop_value)]
+ /// The nodes pve-manager version, used to feature gate some entries.
+ pve_manager_version: Option<String>,
+
/// Use Proxmox Datacenter Manager API endpoints
#[builder(IntoPropValue, into_prop_value)]
#[prop_or_default]
diff --git a/src/configuration/pve/qemu_options_panel.rs b/src/configuration/pve/qemu_options_panel.rs
index 4843ed9..b45d9bd 100644
--- a/src/configuration/pve/qemu_options_panel.rs
+++ b/src/configuration/pve/qemu_options_panel.rs
@@ -1,3 +1,4 @@
+use std::cmp::Ordering;
use std::rc::Rc;
use pwt::props::SubmitCallback;
@@ -13,16 +14,25 @@ use crate::pending_property_view::{pending_typed_load, PendingPropertyGrid, Pend
use crate::EditableProperty;
use crate::{http_put, percent_encoding::percent_encode_component};
+use proxmox_deb_version::cmp_versions;
use pve_api_types::QemuConfig;
use pwt_macros::builder;
+// newest known pve-manager version we care for
+const NEWEST_KNOWN_VERSION: &str = "9.1.2";
+
#[derive(Clone, PartialEq, Properties)]
#[builder]
pub struct QemuOptionsPanel {
vmid: u32,
node: AttrValue,
+ #[prop_or_default]
+ #[builder(IntoPropValue, into_prop_value)]
+ /// The nodes pve-manager version, used to feature gate some entries
+ pve_manager_version: Option<String>,
+
/// Use Proxmox Datacenter Manager API endpoints
#[builder(IntoPropValue, into_prop_value)]
#[prop_or_default]
@@ -52,8 +62,13 @@ pub struct PveQemuOptionsPanel {
properties: Rc<Vec<EditableProperty>>,
}
-fn properties(node: &str, vmid: u32, mobile: bool) -> Vec<EditableProperty> {
- vec![
+fn properties(
+ node: &str,
+ vmid: u32,
+ pve_manager_version: Option<&str>,
+ mobile: bool,
+) -> Vec<EditableProperty> {
+ let mut properties = vec![
crate::form::pve::qemu_name_property(vmid, mobile),
crate::form::pve::qemu_onboot_property(mobile),
crate::form::pve::qemu_startup_property(mobile),
@@ -72,8 +87,15 @@ fn properties(node: &str, vmid: u32, mobile: bool) -> Vec<EditableProperty> {
crate::form::pve::qemu_spice_enhancement_property(mobile),
crate::form::pve::qemu_vmstatestorage_property(node, mobile),
crate::form::pve::qemu_amd_sev_property(mobile),
- crate::form::pve::qemu_intel_tdx_property(mobile),
- ]
+ ];
+
+ let version = pve_manager_version.unwrap_or(NEWEST_KNOWN_VERSION);
+
+ if cmp_versions(version, "9.1") != Ok(Ordering::Less) {
+ properties.push(crate::form::pve::qemu_intel_tdx_property(mobile));
+ }
+
+ properties
}
impl Component for PveQemuOptionsPanel {
@@ -82,8 +104,9 @@ impl Component for PveQemuOptionsPanel {
fn create(ctx: &Context<Self>) -> Self {
let props = ctx.props();
+ let version = props.pve_manager_version.as_deref();
Self {
- properties: Rc::new(properties(&props.node, props.vmid, props.mobile)),
+ properties: Rc::new(properties(&props.node, props.vmid, version, props.mobile)),
}
}
--
2.47.3
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [pdm-devel] [PATCH yew-comp 2/2] pve: lxc panels: prepare/add version feature gating
2025-12-02 9:59 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH yew-comp 1/2] qemu: options/hardware: prepare and use version feature gating Dominik Csapak
@ 2025-12-02 10:00 ` Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 1/4] ui: subscription_info: add subscription counts Dominik Csapak
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Dominik Csapak @ 2025-12-02 10:00 UTC (permalink / raw)
To: pdm-devel
add the pve-manager version as property to the various lxc panels, and
use it on the options to display the new 'env' and 'entrypoint' options,
analogous to how we do it for the qemu panel.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
src/configuration/pve/lxc_dns_panel.rs | 5 +++
src/configuration/pve/lxc_network_panel.rs | 5 +++
src/configuration/pve/lxc_options_panel.rs | 33 ++++++++++++++++---
.../pve/lxc_resources_panel/mod.rs | 5 +++
src/form/pve/lxc_property/mod.rs | 11 +++++++
src/form/pve/mod.rs | 10 +++---
6 files changed, 60 insertions(+), 9 deletions(-)
diff --git a/src/configuration/pve/lxc_dns_panel.rs b/src/configuration/pve/lxc_dns_panel.rs
index 303843a..1e3a969 100644
--- a/src/configuration/pve/lxc_dns_panel.rs
+++ b/src/configuration/pve/lxc_dns_panel.rs
@@ -21,6 +21,11 @@ pub struct LxcDnsPanel {
vmid: u32,
node: AttrValue,
+ #[prop_or_default]
+ #[builder(IntoPropValue, into_prop_value)]
+ /// The nodes pve-manager version, used to feature gate some entries
+ pve_manager_version: Option<String>,
+
/// Use Proxmox Datacenter Manager API endpoints
#[builder(IntoPropValue, into_prop_value)]
#[prop_or_default]
diff --git a/src/configuration/pve/lxc_network_panel.rs b/src/configuration/pve/lxc_network_panel.rs
index 613448a..de78ff9 100644
--- a/src/configuration/pve/lxc_network_panel.rs
+++ b/src/configuration/pve/lxc_network_panel.rs
@@ -32,6 +32,11 @@ pub struct LxcNetworkPanel {
vmid: u32,
node: AttrValue,
+ #[prop_or_default]
+ #[builder(IntoPropValue, into_prop_value)]
+ /// The nodes pve-manager version, used to feature gate some entries
+ pve_manager_version: Option<String>,
+
/// Use Proxmox Datacenter Manager API endpoints
#[builder(IntoPropValue, into_prop_value)]
#[prop_or_default]
diff --git a/src/configuration/pve/lxc_options_panel.rs b/src/configuration/pve/lxc_options_panel.rs
index a2d9760..96edd00 100644
--- a/src/configuration/pve/lxc_options_panel.rs
+++ b/src/configuration/pve/lxc_options_panel.rs
@@ -1,5 +1,7 @@
+use std::cmp::Ordering;
use std::rc::Rc;
+use proxmox_deb_version::cmp_versions;
use pwt::props::SubmitCallback;
use serde_json::Value;
@@ -19,12 +21,20 @@ use pve_api_types::LxcConfig;
use pwt_macros::builder;
+// newest known pve-manager version we care for
+const NEWEST_KNOWN_VERSION: &str = "9.1.2";
+
#[derive(Clone, PartialEq, Properties)]
#[builder]
pub struct LxcOptionsPanel {
vmid: u32,
node: AttrValue,
+ #[prop_or_default]
+ #[builder(IntoPropValue, into_prop_value)]
+ /// The nodes pve-manager version, used to feature gate some entries
+ pve_manager_version: Option<String>,
+
/// Use Proxmox Datacenter Manager API endpoints
#[builder(IntoPropValue, into_prop_value)]
#[prop_or_default]
@@ -54,8 +64,13 @@ pub struct PveLxcOptionsPanel {
properties: Rc<Vec<EditableProperty>>,
}
-fn properties(_node: &str, _vmid: u32, mobile: bool) -> Vec<EditableProperty> {
- vec![
+fn properties(
+ _node: &str,
+ _vmid: u32,
+ pve_manager_version: Option<&str>,
+ mobile: bool,
+) -> Vec<EditableProperty> {
+ let mut properties = vec![
//crate::form::pve::Lxc_name_property(vmid, mobile),
crate::form::pve::qemu_onboot_property(mobile),
crate::form::pve::qemu_startup_property(mobile),
@@ -68,7 +83,16 @@ fn properties(_node: &str, _vmid: u32, mobile: bool) -> Vec<EditableProperty> {
crate::form::pve::lxc_unpriviledged_property(),
crate::form::pve::lxc_features_property(mobile),
crate::form::pve::lxc_hookscript_property(),
- ]
+ ];
+
+ let version = pve_manager_version.unwrap_or(NEWEST_KNOWN_VERSION);
+
+ if cmp_versions(version, "9.1") != Ok(Ordering::Less) {
+ properties.push(crate::form::pve::lxc_entrypoint_property());
+ properties.push(crate::form::pve::lxc_env_property());
+ }
+
+ properties
}
impl Component for PveLxcOptionsPanel {
@@ -77,8 +101,9 @@ impl Component for PveLxcOptionsPanel {
fn create(ctx: &Context<Self>) -> Self {
let props = ctx.props();
+ let version = props.pve_manager_version.as_deref();
Self {
- properties: Rc::new(properties(&props.node, props.vmid, props.mobile)),
+ properties: Rc::new(properties(&props.node, props.vmid, version, props.mobile)),
}
}
diff --git a/src/configuration/pve/lxc_resources_panel/mod.rs b/src/configuration/pve/lxc_resources_panel/mod.rs
index 54e66aa..31eb859 100644
--- a/src/configuration/pve/lxc_resources_panel/mod.rs
+++ b/src/configuration/pve/lxc_resources_panel/mod.rs
@@ -35,6 +35,11 @@ pub struct LxcResourcesPanel {
vmid: u32,
node: AttrValue,
+ #[prop_or_default]
+ #[builder(IntoPropValue, into_prop_value)]
+ /// The nodes pve-manager version, used to feature gate some entries
+ pve_manager_version: Option<String>,
+
/// Use Proxmox Datacenter Manager API endpoints
#[builder(IntoPropValue, into_prop_value)]
#[prop_or_default]
diff --git a/src/form/pve/lxc_property/mod.rs b/src/form/pve/lxc_property/mod.rs
index 2864359..54d175d 100644
--- a/src/form/pve/lxc_property/mod.rs
+++ b/src/form/pve/lxc_property/mod.rs
@@ -119,6 +119,17 @@ pub fn lxc_hookscript_property() -> EditableProperty {
EditableProperty::new("hookscript", tr!("Hookscript"))
}
+pub fn lxc_entrypoint_property() -> EditableProperty {
+ EditableProperty::new("entrypoint", tr!("Entrypoint"))
+}
+
+pub fn lxc_env_property() -> EditableProperty {
+ EditableProperty::new("env", tr!("Environment")).renderer(|_name, value, _data| match value {
+ Value::String(env) => env.split('\0').collect::<Vec<_>>().join(" ").into(),
+ _ => value.into(),
+ })
+}
+
pub fn lxc_tty_count_property(mobile: bool) -> EditableProperty {
let title = tr!("TTY count");
EditableProperty::new("tty", title.clone())
diff --git a/src/form/pve/mod.rs b/src/form/pve/mod.rs
index fc0e2c5..0be5e6f 100644
--- a/src/form/pve/mod.rs
+++ b/src/form/pve/mod.rs
@@ -54,11 +54,11 @@ pub use lxc_mount_options_selector::LxcMountOptionsSelector;
mod lxc_property;
pub use lxc_property::{
extract_used_mount_points, first_unused_mount_point, lxc_architecture_property,
- lxc_console_mode_property, lxc_console_property, lxc_cores_property, lxc_features_property,
- lxc_hookscript_property, lxc_hostname_property, lxc_memory_property, lxc_mount_point_property,
- lxc_nameserver_property, lxc_network_property, lxc_ostype_property, lxc_rootfs_property,
- lxc_searchdomain_property, lxc_swap_property, lxc_tty_count_property,
- lxc_unpriviledged_property, lxc_unused_volume_property,
+ lxc_console_mode_property, lxc_console_property, lxc_cores_property, lxc_entrypoint_property,
+ lxc_env_property, lxc_features_property, lxc_hookscript_property, lxc_hostname_property,
+ lxc_memory_property, lxc_mount_point_property, lxc_nameserver_property, lxc_network_property,
+ lxc_ostype_property, lxc_rootfs_property, lxc_searchdomain_property, lxc_swap_property,
+ lxc_tty_count_property, lxc_unpriviledged_property, lxc_unused_volume_property,
};
mod qemu_property;
--
2.47.3
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [pdm-devel] [PATCH datacenter-manager 1/4] ui: subscription_info: add subscription counts
2025-12-02 9:59 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH yew-comp 1/2] qemu: options/hardware: prepare and use version feature gating Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH yew-comp 2/2] pve: lxc panels: prepare/add " Dominik Csapak
@ 2025-12-02 10:00 ` Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 2/4] lib/server: pve: add api call to get the cached version info from remotes Dominik Csapak
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Dominik Csapak @ 2025-12-02 10:00 UTC (permalink / raw)
To: pdm-devel
count the subscriptions we know of and show them in a tabular style.
Showing each product as a single line with each subscription type as a
column.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
ui/src/dashboard/subscription_info.rs | 109 ++++++++++++++++++++++++--
1 file changed, 103 insertions(+), 6 deletions(-)
diff --git a/ui/src/dashboard/subscription_info.rs b/ui/src/dashboard/subscription_info.rs
index 6c94b8ef..f9e8c33f 100644
--- a/ui/src/dashboard/subscription_info.rs
+++ b/ui/src/dashboard/subscription_info.rs
@@ -1,3 +1,4 @@
+use std::collections::HashMap;
use std::rc::Rc;
use anyhow::Error;
@@ -7,16 +8,18 @@ use yew::{
};
use proxmox_yew_comp::Status;
+use pwt::css::{AlignItems, AlignSelf, Display, FlexFit, JustifyContent, TextAlign};
use pwt::prelude::*;
+use pwt::props::PwtSpace;
+use pwt::state::SharedState;
use pwt::widget::{Button, Column, Container, Dialog, Fa, Panel, Row};
-use pwt::{
- css::{AlignItems, FlexFit, JustifyContent, TextAlign},
- state::SharedState,
-};
-use pdm_api_types::subscription::{RemoteSubscriptionState, RemoteSubscriptions};
+use pdm_api_types::remotes::RemoteType;
+use pdm_api_types::subscription::{
+ NodeSubscriptionInfo, RemoteSubscriptionState, RemoteSubscriptions, SubscriptionLevel,
+};
-use crate::{dashboard::SubscriptionsList, LoadResult};
+use crate::{dashboard::SubscriptionsList, get_remote_list, LoadResult, RemoteList};
#[derive(Properties, PartialEq)]
pub struct SubscriptionInfo {
@@ -31,6 +34,97 @@ impl SubscriptionInfo {
struct PdmSubscriptionInfo;
+#[derive(Default)]
+struct SubCount {
+ community: u32,
+ basic: u32,
+ standard: u32,
+ premium: u32,
+ none: u32,
+}
+
+impl SubCount {
+ fn count_subs(&mut self, subscriptions: &HashMap<String, Option<NodeSubscriptionInfo>>) {
+ for info in subscriptions.values().flatten() {
+ match info.level {
+ SubscriptionLevel::None => self.none += 1,
+ SubscriptionLevel::Unknown => {}
+ SubscriptionLevel::Community => self.community += 1,
+ SubscriptionLevel::Basic => self.basic += 1,
+ SubscriptionLevel::Standard => self.standard += 1,
+ SubscriptionLevel::Premium => self.premium += 1,
+ }
+ }
+ }
+
+ fn total(&self) -> u32 {
+ self.community + self.basic + self.standard + self.none
+ }
+}
+
+fn render_subscription_list(remotes: RemoteList, subs: &[RemoteSubscriptions]) -> Container {
+ let mut pve = SubCount::default();
+ let mut pbs = SubCount::default();
+
+ for sub in subs {
+ if let Some(remote_type) = remotes
+ .iter()
+ .find_map(|remote| (remote.id == sub.remote).then_some(remote.ty))
+ {
+ if let Some(hash) = sub.node_status.as_ref() {
+ match remote_type {
+ RemoteType::Pve => pve.count_subs(hash),
+ RemoteType::Pbs => pbs.count_subs(hash),
+ }
+ }
+ }
+ }
+
+ fn render_right_aligned(text: impl Into<Html>) -> Container {
+ Container::new().class(TextAlign::Right).with_child(text)
+ }
+
+ fn render_product(count: SubCount, title: &str) -> Vec<Container> {
+ vec![
+ Container::new().with_child(title),
+ render_right_aligned(count.community),
+ render_right_aligned(count.basic),
+ render_right_aligned(count.standard),
+ render_right_aligned(count.premium),
+ render_right_aligned(count.none),
+ ]
+ }
+
+ let mut list = vec![
+ Container::new().with_child(tr!("Product")),
+ render_right_aligned("Community"),
+ render_right_aligned("Basic"),
+ render_right_aligned("Standard"),
+ render_right_aligned("Premium"),
+ render_right_aligned(tr!("None")),
+ ];
+
+ if pve.total() > 0 {
+ list.append(&mut render_product(pve, "Proxmox VE"));
+ }
+ if pbs.total() > 0 {
+ list.append(&mut render_product(pbs, "Proxmox Backup Server"));
+ }
+
+ if list.is_empty() {
+ return Container::new();
+ }
+
+ Container::new()
+ .padding_x(4)
+ .padding_bottom(4)
+ .class(Display::Grid)
+ .class(AlignSelf::Stretch)
+ .style("grid-template-columns", "1fr repeat(5, 100px)")
+ .style("gap", PwtSpace::Pwt(2))
+ .children(list.into_iter().map(|c| c.into()))
+}
+
fn render_subscription_status(subs: &[RemoteSubscriptions]) -> Row {
let mut none = 0;
let mut mixed = 0;
@@ -122,6 +216,9 @@ impl Component for PdmSubscriptionInfo {
.as_ref()
.map(|subs| render_subscription_status(subs)),
)
+ .with_optional_child(props.subs.as_ref().and_then(|subs| {
+ get_remote_list(ctx.link()).map(|remotes| render_subscription_list(remotes, subs))
+ }))
.into()
}
}
--
2.47.3
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [pdm-devel] [PATCH datacenter-manager 2/4] lib/server: pve: add api call to get the cached version info from remotes
2025-12-02 9:59 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
` (2 preceding siblings ...)
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 1/4] ui: subscription_info: add subscription counts Dominik Csapak
@ 2025-12-02 10:00 ` Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 3/4] ui: pve: qemu: load and pass the pve-manager version to panels Dominik Csapak
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Dominik Csapak @ 2025-12-02 10:00 UTC (permalink / raw)
To: pdm-devel
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@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
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [pdm-devel] [PATCH datacenter-manager 3/4] ui: pve: qemu: load and pass the pve-manager version to panels
2025-12-02 9:59 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
` (3 preceding siblings ...)
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 2/4] lib/server: pve: add api call to get the cached version info from remotes Dominik Csapak
@ 2025-12-02 10:00 ` Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 4/4] ui: pve: lxc: " Dominik Csapak
2025-12-02 11:18 ` [pdm-devel] superseded: [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
6 siblings, 0 replies; 10+ messages in thread
From: Dominik Csapak @ 2025-12-02 10:00 UTC (permalink / raw)
To: pdm-devel
this loads the cached update information when updating the resources
list and passes the pve-manager version to the qemu panels.
These can use that information to feature gate some information or
functionality.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
ui/src/lib.rs | 14 +++++++++++
ui/src/pve/mod.rs | 55 +++++++++++++++++++++++++++---------------
ui/src/pve/qemu/mod.rs | 12 +++++++--
3 files changed, 60 insertions(+), 21 deletions(-)
diff --git a/ui/src/lib.rs b/ui/src/lib.rs
index cf05c04d..2332002e 100644
--- a/ui/src/lib.rs
+++ b/ui/src/lib.rs
@@ -1,4 +1,5 @@
use js_sys::{Array, JsString, Object};
+use pdm_api_types::remote_updates::RemoteUpdateSummary;
use pdm_api_types::remotes::RemoteType;
use pdm_api_types::resource::{PveLxcResource, PveQemuResource};
use pdm_client::types::Resource;
@@ -241,3 +242,16 @@ pub async fn check_subscription() -> bool {
let data: Result<Value, _> = http_get("/nodes/localhost/subscription", None).await;
proxmox_yew_comp::subscription_is_active(&Some(data))
}
+
+/// Extract the version of a specific package from `RemoteUpdateSummary` for a specific node
+pub fn extract_package_version(
+ updates: &RemoteUpdateSummary,
+ node: &str,
+ package_name: &str,
+) -> Option<String> {
+ let entry = updates.nodes.get(node)?;
+ entry
+ .versions
+ .iter()
+ .find_map(|package| (package.package == package_name).then_some(package.version.clone()))
+}
diff --git a/ui/src/pve/mod.rs b/ui/src/pve/mod.rs
index 73632cd5..6ec323e5 100644
--- a/ui/src/pve/mod.rs
+++ b/ui/src/pve/mod.rs
@@ -18,9 +18,12 @@ use proxmox_yew_comp::{LoadableComponent, LoadableComponentContext, LoadableComp
use proxmox_client::Error;
-use pdm_api_types::resource::{PveResource, ResourceType};
+use pdm_api_types::{
+ remote_updates::RemoteUpdateSummary,
+ resource::{PveResource, ResourceType},
+};
-use crate::get_deep_url;
+use crate::{extract_package_version, get_deep_url, LoadResult};
pub mod lxc;
pub mod node;
@@ -131,13 +134,17 @@ impl GuestInfo {
pub enum Msg {
SelectedView(tree::PveTreeNode),
- ResourcesList(Result<Vec<PveResource>, Error>),
+ LoadFinished(
+ Result<Vec<PveResource>, Error>,
+ Result<RemoteUpdateSummary, Error>,
+ ),
}
pub struct PveRemoteComp {
view: tree::PveTreeNode,
resources: Rc<Vec<PveResource>>,
last_error: Option<String>,
+ updates: LoadResult<RemoteUpdateSummary, Error>,
}
impl LoadableComponent for PveRemoteComp {
@@ -151,6 +158,7 @@ impl LoadableComponent for PveRemoteComp {
view: PveTreeNode::Root,
resources: Rc::new(Vec::new()),
last_error: None,
+ updates: LoadResult::new(),
}
}
@@ -159,17 +167,20 @@ impl LoadableComponent for PveRemoteComp {
Msg::SelectedView(node) => {
self.view = node;
}
- Msg::ResourcesList(res) => match res {
- Ok(res) => {
- self.last_error = None;
- self.resources = Rc::new(res);
- }
- Err(err) => {
- self.last_error = Some(err.to_string());
- _ctx.link()
- .show_error(tr!("Load failed"), err.to_string(), false);
- }
- },
+ Msg::LoadFinished(resources, updates) => {
+ match resources {
+ Ok(res) => {
+ self.last_error = None;
+ self.resources = Rc::new(res);
+ }
+ Err(err) => {
+ self.last_error = Some(err.to_string());
+ _ctx.link()
+ .show_error(tr!("Load failed"), err.to_string(), false);
+ }
+ };
+ self.updates.update(updates);
+ }
}
true
}
@@ -185,7 +196,13 @@ impl LoadableComponent for PveRemoteComp {
node::PveNodePanel::new(remote.clone(), node.node.clone()).into()
}
PveTreeNode::Qemu(qemu) => {
- qemu::QemuPanel::new(remote.clone(), qemu.node.clone(), qemu.clone()).into()
+ let pve_manager = match &self.updates.data {
+ Some(updates) => extract_package_version(updates, &qemu.node, "pve-manager"),
+ None => None,
+ };
+ qemu::QemuPanel::new(remote.clone(), qemu.node.clone(), qemu.clone())
+ .pve_manager_version(pve_manager)
+ .into()
}
PveTreeNode::Lxc(lxc) => {
lxc::LxcPanel::new(remote.clone(), lxc.node.clone(), lxc.clone()).into()
@@ -275,10 +292,10 @@ impl LoadableComponent for PveRemoteComp {
let link = ctx.link();
let remote = ctx.props().remote.clone();
Box::pin(async move {
- let res = crate::pdm_client()
- .pve_cluster_resources(&remote, None)
- .await;
- link.send_message(Msg::ResourcesList(res));
+ let client = crate::pdm_client();
+ let resources = client.pve_cluster_resources(&remote, None).await;
+ let updates = client.pve_cluster_updates(&remote).await;
+ link.send_message(Msg::LoadFinished(resources, updates));
Ok(())
})
}
diff --git a/ui/src/pve/qemu/mod.rs b/ui/src/pve/qemu/mod.rs
index 562fb563..c14849ae 100644
--- a/ui/src/pve/qemu/mod.rs
+++ b/ui/src/pve/qemu/mod.rs
@@ -5,10 +5,10 @@ use std::rc::Rc;
use yew::virtual_dom::{VComp, VNode};
-use pwt::prelude::*;
-
use pwt::css::FlexFit;
+use pwt::prelude::*;
use pwt::widget::{Button, Column, Container, Fa, Row, TabBarItem, TabPanel, Tooltip};
+use pwt_macros::builder;
use proxmox_yew_comp::configuration::pve::{QemuHardwarePanel, QemuOptionsPanel};
@@ -18,11 +18,17 @@ use crate::pve::utils::render_qemu_name;
use crate::renderer::render_title_row;
#[derive(Clone, Debug, Properties, PartialEq)]
+#[builder]
pub struct QemuPanel {
remote: String,
node: String,
info: PveQemuResource,
+ #[prop_or_default]
+ #[builder]
+ /// The nodes pve-manager version, used to feature gate some entries.
+ pve_manager_version: Option<String>,
+
#[prop_or(60_000)]
/// The interval for refreshing the rrd data
pub rrd_interval: u32,
@@ -107,6 +113,7 @@ impl yew::Component for QemuPanelComp {
let remote = props.remote.clone();
let node = props.node.clone();
let vmid = props.info.vmid;
+ let pve_manager_version = props.pve_manager_version.clone();
move |_| {
Container::new()
.class(FlexFit)
@@ -127,6 +134,7 @@ impl yew::Component for QemuPanelComp {
.with_child(html! {<hr/>})
.with_child(
QemuOptionsPanel::new(node.clone(), vmid)
+ .pve_manager_version(pve_manager_version.clone())
.readonly(true)
.remote(remote.clone()),
),
--
2.47.3
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [pdm-devel] [PATCH datacenter-manager 4/4] ui: pve: lxc: pass the pve-manager version to panels
2025-12-02 9:59 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
` (4 preceding siblings ...)
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 3/4] ui: pve: qemu: load and pass the pve-manager version to panels Dominik Csapak
@ 2025-12-02 10:00 ` Dominik Csapak
2025-12-02 11:18 ` [pdm-devel] superseded: [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
6 siblings, 0 replies; 10+ messages in thread
From: Dominik Csapak @ 2025-12-02 10:00 UTC (permalink / raw)
To: pdm-devel
this will be used by the panels to feature gate by version.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
ui/src/pve/lxc/mod.rs | 15 +++++++++++++--
ui/src/pve/mod.rs | 8 +++++++-
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/ui/src/pve/lxc/mod.rs b/ui/src/pve/lxc/mod.rs
index 7429e07c..8a177a42 100644
--- a/ui/src/pve/lxc/mod.rs
+++ b/ui/src/pve/lxc/mod.rs
@@ -8,10 +8,10 @@ use std::rc::Rc;
use yew::virtual_dom::{VComp, VNode};
-use pwt::prelude::*;
-
use pwt::css::FlexFit;
+use pwt::prelude::*;
use pwt::widget::{Button, Column, Container, Fa, Row, TabBarItem, TabPanel, Tooltip};
+use pwt_macros::builder;
use pdm_api_types::resource::PveLxcResource;
@@ -19,11 +19,17 @@ use crate::pve::utils::render_lxc_name;
use crate::renderer::render_title_row;
#[derive(Clone, Debug, Properties, PartialEq)]
+#[builder]
pub struct LxcPanel {
remote: String,
node: String,
info: PveLxcResource,
+ #[prop_or_default]
+ #[builder]
+ /// The nodes pve-manager version, used to feature gate some entries.
+ pve_manager_version: Option<String>,
+
#[prop_or(60_000)]
/// The interval for refreshing the rrd data
pub rrd_interval: u32,
@@ -108,6 +114,7 @@ impl yew::Component for LxcPanelComp {
let remote = props.remote.clone();
let node = props.node.clone();
let vmid = props.info.vmid;
+ let pve_manager_version = props.pve_manager_version.clone();
move |_| {
Container::new()
.class(FlexFit)
@@ -119,6 +126,7 @@ impl yew::Component for LxcPanelComp {
.with_child(html! {<hr/>})
.with_child(
LxcResourcesPanel::new(node.clone(), vmid)
+ .pve_manager_version(pve_manager_version.clone())
.readonly(true)
.remote(remote.clone()),
)
@@ -128,6 +136,7 @@ impl yew::Component for LxcPanelComp {
.with_child(html! {<hr/>})
.with_child(
LxcNetworkPanel::new(node.clone(), vmid)
+ .pve_manager_version(pve_manager_version.clone())
.readonly(true)
.remote(remote.clone()),
)
@@ -135,6 +144,7 @@ impl yew::Component for LxcPanelComp {
.with_child(html! {<hr/>})
.with_child(
LxcDnsPanel::new(node.clone(), vmid)
+ .pve_manager_version(pve_manager_version.clone())
.readonly(true)
.remote(remote.clone()),
)
@@ -144,6 +154,7 @@ impl yew::Component for LxcPanelComp {
.with_child(html! {<hr/>})
.with_child(
LxcOptionsPanel::new(node.clone(), vmid)
+ .pve_manager_version(pve_manager_version.clone())
.readonly(true)
.remote(remote.clone()),
),
diff --git a/ui/src/pve/mod.rs b/ui/src/pve/mod.rs
index 6ec323e5..d0d038dd 100644
--- a/ui/src/pve/mod.rs
+++ b/ui/src/pve/mod.rs
@@ -205,7 +205,13 @@ impl LoadableComponent for PveRemoteComp {
.into()
}
PveTreeNode::Lxc(lxc) => {
- lxc::LxcPanel::new(remote.clone(), lxc.node.clone(), lxc.clone()).into()
+ let pve_manager = match &self.updates.data {
+ Some(updates) => extract_package_version(updates, &lxc.node, "pve-manager"),
+ None => None,
+ };
+ lxc::LxcPanel::new(remote.clone(), lxc.node.clone(), lxc.clone())
+ .pve_manager_version(pve_manager)
+ .into()
}
PveTreeNode::Storage(storage) => {
storage::StoragePanel::new(remote.clone(), storage.node.clone(), storage.clone())
--
2.47.3
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [pdm-devel] [PATCH yew-comp 1/2] qemu: options/hardware: prepare and use version feature gating
2025-12-02 10:00 ` [pdm-devel] [PATCH yew-comp 1/2] qemu: options/hardware: prepare and use version feature gating Dominik Csapak
@ 2025-12-02 10:32 ` Thomas Lamprecht
2025-12-02 10:53 ` Dominik Csapak
0 siblings, 1 reply; 10+ messages in thread
From: Thomas Lamprecht @ 2025-12-02 10:32 UTC (permalink / raw)
To: Proxmox Datacenter Manager development discussion, Dominik Csapak
Am 02.12.25 um 11:00 schrieb Dominik Csapak:
> use the pve-manager version to feature gate the intel-tdx property for
> now, but also prepare the hardware panel so we can already start passing
> the version to it. If we need it there, we already have it then.
>
> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
> ---
> Cargo.toml | 1 +
> .../pve/qemu_hardware_panel/mod.rs | 5 +++
> src/configuration/pve/qemu_options_panel.rs | 33 ++++++++++++++++---
> 3 files changed, 34 insertions(+), 5 deletions(-)
>
> diff --git a/Cargo.toml b/Cargo.toml
> index 622bb09..600fafa 100644
> --- a/Cargo.toml
> +++ b/Cargo.toml
> @@ -88,6 +88,7 @@ proxmox-node-status = { version = "1", features = [] }
>
> pve-api-types = "8.1.2"
> pbs-api-types = "1"
> +proxmox-deb-version = "0.1.0"
>
> [features]
> default = []
> diff --git a/src/configuration/pve/qemu_hardware_panel/mod.rs b/src/configuration/pve/qemu_hardware_panel/mod.rs
> index 38bc6fd..c04c01f 100644
> --- a/src/configuration/pve/qemu_hardware_panel/mod.rs
> +++ b/src/configuration/pve/qemu_hardware_panel/mod.rs
> @@ -38,6 +38,11 @@ pub struct QemuHardwarePanel {
> vmid: u32,
> node: AttrValue,
>
> + #[prop_or_default]
> + #[builder(IntoPropValue, into_prop_value)]
> + /// The nodes pve-manager version, used to feature gate some entries.
> + pve_manager_version: Option<String>,
FWIW, proxmox_deb_version::Version might be a better fit here, it's effectively
boiling down to using as much allocated memory as the string here, but should be
a bit more convenient to use.
I actually also want to change the usage I introduced in PDM directly to the
owned type, as after sleeping a night over that I noticed that if I assemble a
Vec of version String's, I might as well directly assemble a Vec of
proxmox_deb_version::Version.
Anyhow, can be also fine as is, just wanted to point it out in case you
overlooked this possibility initially the same way I did ^^
Looks OK to me in general.
> +
> /// Use Proxmox Datacenter Manager API endpoints
> #[builder(IntoPropValue, into_prop_value)]
> #[prop_or_default]
> diff --git a/src/configuration/pve/qemu_options_panel.rs b/src/configuration/pve/qemu_options_panel.rs
> index 4843ed9..b45d9bd 100644
> --- a/src/configuration/pve/qemu_options_panel.rs
> +++ b/src/configuration/pve/qemu_options_panel.rs
> @@ -1,3 +1,4 @@
> +use std::cmp::Ordering;
> use std::rc::Rc;
>
> use pwt::props::SubmitCallback;
> @@ -13,16 +14,25 @@ use crate::pending_property_view::{pending_typed_load, PendingPropertyGrid, Pend
> use crate::EditableProperty;
> use crate::{http_put, percent_encoding::percent_encode_component};
>
> +use proxmox_deb_version::cmp_versions;
> use pve_api_types::QemuConfig;
>
> use pwt_macros::builder;
>
> +// newest known pve-manager version we care for
> +const NEWEST_KNOWN_VERSION: &str = "9.1.2";
> +
> #[derive(Clone, PartialEq, Properties)]
> #[builder]
> pub struct QemuOptionsPanel {
> vmid: u32,
> node: AttrValue,
>
> + #[prop_or_default]
> + #[builder(IntoPropValue, into_prop_value)]
> + /// The nodes pve-manager version, used to feature gate some entries
> + pve_manager_version: Option<String>,
> +
> /// Use Proxmox Datacenter Manager API endpoints
> #[builder(IntoPropValue, into_prop_value)]
> #[prop_or_default]
> @@ -52,8 +62,13 @@ pub struct PveQemuOptionsPanel {
> properties: Rc<Vec<EditableProperty>>,
> }
>
> -fn properties(node: &str, vmid: u32, mobile: bool) -> Vec<EditableProperty> {
> - vec![
> +fn properties(
> + node: &str,
> + vmid: u32,
> + pve_manager_version: Option<&str>,
> + mobile: bool,
> +) -> Vec<EditableProperty> {
> + let mut properties = vec![
> crate::form::pve::qemu_name_property(vmid, mobile),
> crate::form::pve::qemu_onboot_property(mobile),
> crate::form::pve::qemu_startup_property(mobile),
> @@ -72,8 +87,15 @@ fn properties(node: &str, vmid: u32, mobile: bool) -> Vec<EditableProperty> {
> crate::form::pve::qemu_spice_enhancement_property(mobile),
> crate::form::pve::qemu_vmstatestorage_property(node, mobile),
> crate::form::pve::qemu_amd_sev_property(mobile),
> - crate::form::pve::qemu_intel_tdx_property(mobile),
> - ]
> + ];
> +
> + let version = pve_manager_version.unwrap_or(NEWEST_KNOWN_VERSION);
> +
> + if cmp_versions(version, "9.1") != Ok(Ordering::Less) {
> + properties.push(crate::form::pve::qemu_intel_tdx_property(mobile));
> + }
> +
> + properties
> }
>
> impl Component for PveQemuOptionsPanel {
> @@ -82,8 +104,9 @@ impl Component for PveQemuOptionsPanel {
>
> fn create(ctx: &Context<Self>) -> Self {
> let props = ctx.props();
> + let version = props.pve_manager_version.as_deref();
> Self {
> - properties: Rc::new(properties(&props.node, props.vmid, props.mobile)),
> + properties: Rc::new(properties(&props.node, props.vmid, version, props.mobile)),
> }
> }
>
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [pdm-devel] [PATCH yew-comp 1/2] qemu: options/hardware: prepare and use version feature gating
2025-12-02 10:32 ` Thomas Lamprecht
@ 2025-12-02 10:53 ` Dominik Csapak
0 siblings, 0 replies; 10+ messages in thread
From: Dominik Csapak @ 2025-12-02 10:53 UTC (permalink / raw)
To: Thomas Lamprecht, Proxmox Datacenter Manager development discussion
On 12/2/25 11:32 AM, Thomas Lamprecht wrote:
> Am 02.12.25 um 11:00 schrieb Dominik Csapak:
>> use the pve-manager version to feature gate the intel-tdx property for
>> now, but also prepare the hardware panel so we can already start passing
>> the version to it. If we need it there, we already have it then.
>>
>> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
>> ---
>> Cargo.toml | 1 +
>> .../pve/qemu_hardware_panel/mod.rs | 5 +++
>> src/configuration/pve/qemu_options_panel.rs | 33 ++++++++++++++++---
>> 3 files changed, 34 insertions(+), 5 deletions(-)
>>
>> diff --git a/Cargo.toml b/Cargo.toml
>> index 622bb09..600fafa 100644
>> --- a/Cargo.toml
>> +++ b/Cargo.toml
>> @@ -88,6 +88,7 @@ proxmox-node-status = { version = "1", features = [] }
>>
>> pve-api-types = "8.1.2"
>> pbs-api-types = "1"
>> +proxmox-deb-version = "0.1.0"
>>
>> [features]
>> default = []
>> diff --git a/src/configuration/pve/qemu_hardware_panel/mod.rs b/src/configuration/pve/qemu_hardware_panel/mod.rs
>> index 38bc6fd..c04c01f 100644
>> --- a/src/configuration/pve/qemu_hardware_panel/mod.rs
>> +++ b/src/configuration/pve/qemu_hardware_panel/mod.rs
>> @@ -38,6 +38,11 @@ pub struct QemuHardwarePanel {
>> vmid: u32,
>> node: AttrValue,
>>
>> + #[prop_or_default]
>> + #[builder(IntoPropValue, into_prop_value)]
>> + /// The nodes pve-manager version, used to feature gate some entries.
>> + pve_manager_version: Option<String>,
>
> FWIW, proxmox_deb_version::Version might be a better fit here, it's effectively
> boiling down to using as much allocated memory as the string here, but should be
> a bit more convenient to use.
>
> I actually also want to change the usage I introduced in PDM directly to the
> owned type, as after sleeping a night over that I noticed that if I assemble a
> Vec of version String's, I might as well directly assemble a Vec of
> proxmox_deb_version::Version.
>
> Anyhow, can be also fine as is, just wanted to point it out in case you
> overlooked this possibility initially the same way I did ^^
>
> Looks OK to me in general.
>
yes actually, i didn't see that, only the cmp_version function
i'll see if i can change this to a version here
>> +
>> /// Use Proxmox Datacenter Manager API endpoints
>> #[builder(IntoPropValue, into_prop_value)]
>> #[prop_or_default]
>> diff --git a/src/configuration/pve/qemu_options_panel.rs b/src/configuration/pve/qemu_options_panel.rs
>> index 4843ed9..b45d9bd 100644
>> --- a/src/configuration/pve/qemu_options_panel.rs
>> +++ b/src/configuration/pve/qemu_options_panel.rs
>> @@ -1,3 +1,4 @@
>> +use std::cmp::Ordering;
>> use std::rc::Rc;
>>
>> use pwt::props::SubmitCallback;
>> @@ -13,16 +14,25 @@ use crate::pending_property_view::{pending_typed_load, PendingPropertyGrid, Pend
>> use crate::EditableProperty;
>> use crate::{http_put, percent_encoding::percent_encode_component};
>>
>> +use proxmox_deb_version::cmp_versions;
>> use pve_api_types::QemuConfig;
>>
>> use pwt_macros::builder;
>>
>> +// newest known pve-manager version we care for
>> +const NEWEST_KNOWN_VERSION: &str = "9.1.2";
>> +
>> #[derive(Clone, PartialEq, Properties)]
>> #[builder]
>> pub struct QemuOptionsPanel {
>> vmid: u32,
>> node: AttrValue,
>>
>> + #[prop_or_default]
>> + #[builder(IntoPropValue, into_prop_value)]
>> + /// The nodes pve-manager version, used to feature gate some entries
>> + pve_manager_version: Option<String>,
>> +
>> /// Use Proxmox Datacenter Manager API endpoints
>> #[builder(IntoPropValue, into_prop_value)]
>> #[prop_or_default]
>> @@ -52,8 +62,13 @@ pub struct PveQemuOptionsPanel {
>> properties: Rc<Vec<EditableProperty>>,
>> }
>>
>> -fn properties(node: &str, vmid: u32, mobile: bool) -> Vec<EditableProperty> {
>> - vec![
>> +fn properties(
>> + node: &str,
>> + vmid: u32,
>> + pve_manager_version: Option<&str>,
>> + mobile: bool,
>> +) -> Vec<EditableProperty> {
>> + let mut properties = vec![
>> crate::form::pve::qemu_name_property(vmid, mobile),
>> crate::form::pve::qemu_onboot_property(mobile),
>> crate::form::pve::qemu_startup_property(mobile),
>> @@ -72,8 +87,15 @@ fn properties(node: &str, vmid: u32, mobile: bool) -> Vec<EditableProperty> {
>> crate::form::pve::qemu_spice_enhancement_property(mobile),
>> crate::form::pve::qemu_vmstatestorage_property(node, mobile),
>> crate::form::pve::qemu_amd_sev_property(mobile),
>> - crate::form::pve::qemu_intel_tdx_property(mobile),
>> - ]
>> + ];
>> +
>> + let version = pve_manager_version.unwrap_or(NEWEST_KNOWN_VERSION);
>> +
>> + if cmp_versions(version, "9.1") != Ok(Ordering::Less) {
>> + properties.push(crate::form::pve::qemu_intel_tdx_property(mobile));
>> + }
>> +
>> + properties
>> }
>>
>> impl Component for PveQemuOptionsPanel {
>> @@ -82,8 +104,9 @@ impl Component for PveQemuOptionsPanel {
>>
>> fn create(ctx: &Context<Self>) -> Self {
>> let props = ctx.props();
>> + let version = props.pve_manager_version.as_deref();
>> Self {
>> - properties: Rc::new(properties(&props.node, props.vmid, props.mobile)),
>> + properties: Rc::new(properties(&props.node, props.vmid, version, props.mobile)),
>> }
>> }
>>
>
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [pdm-devel] superseded: [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests
2025-12-02 9:59 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
` (5 preceding siblings ...)
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 4/4] ui: pve: lxc: " Dominik Csapak
@ 2025-12-02 11:18 ` Dominik Csapak
6 siblings, 0 replies; 10+ messages in thread
From: Dominik Csapak @ 2025-12-02 11:18 UTC (permalink / raw)
To: pdm-devel
superseded by v2:
https://lore.proxmox.com/pdm-devel/20251202111533.2068448-1-d.csapak@proxmox.com/T/#t
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-12-02 11:18 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-02 9:59 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH yew-comp 1/2] qemu: options/hardware: prepare and use version feature gating Dominik Csapak
2025-12-02 10:32 ` Thomas Lamprecht
2025-12-02 10:53 ` Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH yew-comp 2/2] pve: lxc panels: prepare/add " Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 1/4] ui: subscription_info: add subscription counts Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 2/4] lib/server: pve: add api call to get the cached version info from remotes Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 3/4] ui: pve: qemu: load and pass the pve-manager version to panels Dominik Csapak
2025-12-02 10:00 ` [pdm-devel] [PATCH datacenter-manager 4/4] ui: pve: lxc: " Dominik Csapak
2025-12-02 11:18 ` [pdm-devel] superseded: [PATCH datacenter-manager/yew-comp 0/6] add basic version guarding for pve guests Dominik Csapak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox