public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Hannes Laimer <h.laimer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH proxmox-offline-mirror 1/2] helper: allow URL as source for offline key activation
Date: Fri, 17 Oct 2025 08:39:28 +0200	[thread overview]
Message-ID: <20251017063929.30890-2-h.laimer@proxmox.com> (raw)
In-Reply-To: <20251017063929.30890-1-h.laimer@proxmox.com>

If the HTTP server is setup like in our exmaple, `.mirror-state` is
accessible over HTTP. With this the `offline-key` subcommand also
accepts an URL as a source. So instead of reading the `.mirror-state`
file directly from the fs, we'd load it over HTTP if an URL specified.
This removes to need for mounting the medium directly just for key
activation.

Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
 src/bin/proxmox-offline-mirror-helper.rs | 63 ++++++++++++++++++------
 1 file changed, 49 insertions(+), 14 deletions(-)

diff --git a/src/bin/proxmox-offline-mirror-helper.rs b/src/bin/proxmox-offline-mirror-helper.rs
index 07537f0..849465c 100644
--- a/src/bin/proxmox-offline-mirror-helper.rs
+++ b/src/bin/proxmox-offline-mirror-helper.rs
@@ -5,6 +5,8 @@ use std::{collections::HashMap, path::Path};
 
 use anyhow::{Error, bail, format_err};
 
+use proxmox_http::client::sync::Client;
+use proxmox_http::{HttpClient, HttpOptions, ProxyConfig};
 use proxmox_offline_mirror::types::Snapshot;
 use proxmox_subscription::{ProductType, SubscriptionInfo};
 use proxmox_sys::command::run_command;
@@ -24,6 +26,48 @@ use proxmox_offline_mirror::helpers::tty::{
 };
 use proxmox_offline_mirror::medium::{self, MediumState, generate_repo_snippet};
 
+fn load_mirror_state(source: &str) -> Result<MediumState, Error> {
+    if source.starts_with("http://") || source.starts_with("https://") {
+        let state_url = if source.ends_with('/') {
+            format!("{}.mirror-state", source)
+        } else {
+            format!("{}/.mirror-state", source)
+        };
+
+        let options = HttpOptions {
+            user_agent: Some(
+                concat!("proxmox-offline-mirror-helper/", env!("CARGO_PKG_VERSION")).to_string(),
+            ),
+            proxy_config: ProxyConfig::from_proxy_env()?,
+            ..Default::default()
+        };
+        let client = Client::new(options);
+
+        let response = client.get(&state_url, None)?;
+        if !response.status().is_success() {
+            bail!(
+                "Failed to download mirror state from {}: {}",
+                state_url,
+                response.status()
+            );
+        }
+
+        let body: Vec<u8> = response.into_body();
+        serde_json::from_slice(&body).map_err(Error::from)
+    } else {
+        let mountpoint = Path::new(source);
+        if !mountpoint.exists() {
+            bail!("Medium mountpoint doesn't exist.");
+        }
+
+        let mut statefile = mountpoint.to_path_buf();
+        statefile.push(".mirror-state");
+
+        let raw = file_get_contents(&statefile)?;
+        serde_json::from_slice(&raw).map_err(Error::from)
+    }
+}
+
 fn set_subscription_key(
     product: &ProductType,
     subscription: &SubscriptionInfo,
@@ -264,9 +308,9 @@ async fn setup(_param: Value) -> Result<(), Error> {
 #[api(
     input: {
         properties: {
-            mountpoint: {
+            source: {
                 type: String,
-                description: "Path to medium mountpoint",
+                description: "Path to medium mountpoint or URL for key activation",
             },
             product: {
                 type: ProductType,
@@ -277,7 +321,7 @@ async fn setup(_param: Value) -> Result<(), Error> {
 )]
 /// Configures and offline subscription key
 async fn setup_offline_key(
-    mountpoint: String,
+    source: String,
     product: Option<ProductType>,
     _param: Value,
 ) -> Result<(), Error> {
@@ -288,17 +332,8 @@ async fn setup_offline_key(
         );
     }
 
-    let mountpoint = Path::new(&mountpoint);
-    if !mountpoint.exists() {
-        bail!("Medium mountpoint doesn't exist.");
-    }
-
-    let mut statefile = mountpoint.to_path_buf();
-    statefile.push(".mirror-state");
-
-    println!("Loading state from {statefile:?}..");
-    let raw = file_get_contents(&statefile)?;
-    let state: MediumState = serde_json::from_slice(&raw)?;
+    println!("Loading state from {}..", source);
+    let state = load_mirror_state(&source)?;
     println!(
         "Last sync timestamp: {}",
         epoch_to_rfc3339_utc(state.last_sync)?
-- 
2.47.3



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  reply	other threads:[~2025-10-17  6:39 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-17  6:39 [pve-devel] [PATCH proxmox-offline-mirror 0/2 RFC] allow key activation through URL Hannes Laimer
2025-10-17  6:39 ` Hannes Laimer [this message]
2025-10-17  6:39 ` [pve-devel] [PATCH proxmox-offline-mirror 2/2] docs: add section for activating key over HTTP Hannes Laimer

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=20251017063929.30890-2-h.laimer@proxmox.com \
    --to=h.laimer@proxmox.com \
    --cc=pve-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