From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 1D45F1FF17E for ; Thu, 27 Nov 2025 11:44:51 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id CE7BF1FF28; Thu, 27 Nov 2025 11:45:06 +0100 (CET) From: Lukas Wagner To: pdm-devel@lists.proxmox.com Date: Thu, 27 Nov 2025 11:44:39 +0100 Message-ID: <20251127104447.162951-11-l.wagner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251127104447.162951-1-l.wagner@proxmox.com> References: <20251127104447.162951-1-l.wagner@proxmox.com> MIME-Version: 1.0 X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1764240257407 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.032 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pdm-devel] [PATCH datacenter-manager 05/13] remote updates: include repository status in node summary X-BeenThere: pdm-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Datacenter Manager development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Datacenter Manager development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pdm-devel-bounces@lists.proxmox.com Sender: "pdm-devel" Augment the per-node summary with a field that represents the APT repository configuration. Its value is an enum that can represent the most common issues, such as - missing product repo - unstable repos - missing subscription if the enterprise repo is enabled Signed-off-by: Lukas Wagner --- lib/pdm-api-types/src/remote_updates.rs | 22 +++++++ server/src/remote_updates.rs | 77 ++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/lib/pdm-api-types/src/remote_updates.rs b/lib/pdm-api-types/src/remote_updates.rs index 05ff3379..7b4bc112 100644 --- a/lib/pdm-api-types/src/remote_updates.rs +++ b/lib/pdm-api-types/src/remote_updates.rs @@ -114,6 +114,25 @@ pub struct PackageVersion { pub version: String, } +#[api] +#[derive(Default, Clone, Copy, Debug, Deserialize, Serialize, PartialEq, PartialOrd)] +#[serde(rename_all = "kebab-case")] +/// Product repository status. +pub enum ProductRepositoryStatus { + // NOTE: These are sorted in ascending severity. + /// Enterprise repository with a valid subscription. + Ok, + /// Non-production-ready (no-subscription, test) repository is enabled. + NonProductionReady, + /// Enterprise-repository is enabled, but there is no valid subscription. + MissingSubscriptionForEnterprise, + /// No product-specific repository is enabled. + NoProductRepository, + /// Other kind of error. + #[default] + Error, +} + #[api( properties: { versions: { @@ -140,4 +159,7 @@ pub struct NodeUpdateSummary { /// Versions of the most important packages. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub versions: Vec, + /// Repository status. + #[serde(default)] + pub repository_status: ProductRepositoryStatus, } diff --git a/server/src/remote_updates.rs b/server/src/remote_updates.rs index ad85ee85..d6fe352c 100644 --- a/server/src/remote_updates.rs +++ b/server/src/remote_updates.rs @@ -4,11 +4,11 @@ use std::io::ErrorKind; use anyhow::Error; use serde::{Deserialize, Serialize}; -use proxmox_apt_api_types::APTUpdateInfo; +use proxmox_apt_api_types::{APTRepositoriesResult, APTRepositoryHandle, APTUpdateInfo}; use pdm_api_types::remote_updates::{ NodeUpdateStatus, NodeUpdateSummary, NodeUpdateSummaryWrapper, PackageVersion, - RemoteUpdateStatus, RemoteUpdateSummary, UpdateSummary, + ProductRepositoryStatus, RemoteUpdateStatus, RemoteUpdateSummary, UpdateSummary, }; use pdm_api_types::remotes::{Remote, RemoteType}; use pdm_api_types::RemoteUpid; @@ -25,6 +25,7 @@ struct NodeUpdateInfo { updates: Vec, last_refresh: i64, versions: Vec, + repository_status: ProductRepositoryStatus, } impl From for NodeUpdateSummary { @@ -35,6 +36,7 @@ impl From for NodeUpdateSummary { status: NodeUpdateStatus::Success, status_message: None, versions: value.versions, + repository_status: value.repository_status, } } } @@ -227,6 +229,7 @@ pub async fn refresh_update_summary_cache(remotes: Vec) -> Result<(), Er status: NodeUpdateStatus::Error, status_message: Some(format!("{err:#}")), versions: Vec::new(), + repository_status: ProductRepositoryStatus::Error, }, ); log::error!( @@ -273,10 +276,19 @@ async fn fetch_available_updates( .map(map_pve_package_version) .collect(); + let repos = client.get_apt_repositories(&node).await?; + let subscription_info = client.get_subscription(&node).await?; + + let has_active_subscription = + subscription_info.status == pve_api_types::NodeSubscriptionInfoStatus::Active; + + let repository_status = check_repository_status(&repos, has_active_subscription); + Ok(NodeUpdateInfo { last_refresh: proxmox_time::epoch_i64(), updates, versions, + repository_status, }) } RemoteType::Pbs => { @@ -290,10 +302,19 @@ async fn fetch_available_updates( .map(map_pbs_package_version) .collect(); + let repos = client.get_apt_repositories().await?; + let subscription_info = client.get_subscription().await?; + + let has_active_subscription = + subscription_info.status == proxmox_subscription::SubscriptionStatus::Active; + + let repository_status = check_repository_status(&repos, has_active_subscription); + Ok(NodeUpdateInfo { last_refresh: proxmox_time::epoch_i64(), updates, versions, + repository_status, }) } } @@ -327,3 +348,55 @@ fn map_pbs_package_version(info: pbs_api_types::APTUpdateInfo) -> PackageVersion version: info.old_version.unwrap_or_default(), } } + +fn check_repository_status( + config: &APTRepositoriesResult, + active_subscription: bool, +) -> ProductRepositoryStatus { + if !config.errors.is_empty() { + return ProductRepositoryStatus::Error; + } + + let mut has_enterprise = false; + let mut has_no_subscription = false; + let mut has_test = false; + let mut has_ceph_enterprise = false; + let mut has_ceph_no_subscription = false; + let mut has_ceph_test = false; + + for repo in &config.standard_repos { + if repo.status != Some(true) { + continue; + } + match repo.handle { + APTRepositoryHandle::CephSquidEnterprise => has_ceph_enterprise = true, + APTRepositoryHandle::CephSquidNoSubscription => has_ceph_no_subscription = true, + APTRepositoryHandle::CephSquidTest => has_ceph_test = true, + APTRepositoryHandle::Enterprise => has_enterprise = true, + APTRepositoryHandle::NoSubscription => has_no_subscription = true, + APTRepositoryHandle::Test => has_test = true, + } + } + + if !(has_enterprise | has_no_subscription | has_test) { + return ProductRepositoryStatus::NoProductRepository; + } + + if has_enterprise && !active_subscription { + return ProductRepositoryStatus::MissingSubscriptionForEnterprise; + } + + if has_ceph_enterprise && !active_subscription { + return ProductRepositoryStatus::MissingSubscriptionForEnterprise; + } + + if has_test || has_no_subscription { + return ProductRepositoryStatus::NonProductionReady; + } + + if has_ceph_no_subscription || has_ceph_test { + return ProductRepositoryStatus::NonProductionReady; + } + + ProductRepositoryStatus::Ok +} -- 2.47.3 _______________________________________________ pdm-devel mailing list pdm-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel