From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 61F7A94385 for ; Wed, 21 Sep 2022 13:04:26 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 5F34926C92 for ; Wed, 21 Sep 2022 13:04:26 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Wed, 21 Sep 2022 13:04:25 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 2937944345 for ; Wed, 21 Sep 2022 13:04:19 +0200 (CEST) From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= To: pve-devel@lists.proxmox.com Date: Wed, 21 Sep 2022 13:04:07 +0200 Message-Id: <20220921110407.2988743-2-f.gruenbichler@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220921110407.2988743-1-f.gruenbichler@proxmox.com> References: <20220921110407.2988743-1-f.gruenbichler@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.147 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% 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: [pve-devel] [PATCH proxmox-offline-mirror 2/2] helper: add status command X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2022 11:04:26 -0000 similar to `proxmox-offline-mirror medium status `, but limited to the information that is stored on the medium itself. this command can be used to get a quick overview over what's on a medium, or for automated setup of the contained repositories. Signed-off-by: Fabian Grünbichler --- src/bin/proxmox-offline-mirror-helper.rs | 98 +++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/src/bin/proxmox-offline-mirror-helper.rs b/src/bin/proxmox-offline-mirror-helper.rs index 4efb343..353973f 100644 --- a/src/bin/proxmox-offline-mirror-helper.rs +++ b/src/bin/proxmox-offline-mirror-helper.rs @@ -12,7 +12,10 @@ use proxmox_sys::{fs::file_get_contents, linux::tty}; use proxmox_time::epoch_to_rfc3339_utc; use serde_json::Value; -use proxmox_router::cli::{run_cli_command, CliCommand, CliCommandMap, CliEnvironment}; +use proxmox_router::cli::{ + format_and_print_result, get_output_format, run_cli_command, CliCommand, CliCommandMap, + CliEnvironment, OUTPUT_FORMAT, +}; use proxmox_schema::{api, param_bail}; use proxmox_offline_mirror::helpers::tty::{ @@ -319,11 +322,104 @@ async fn setup_offline_key( } } +#[api( + input: { + properties: { + mountpoint: { + type: String, + description: "Path to medium mountpoint", + }, + "output-format": { + schema: OUTPUT_FORMAT, + optional: true, + }, + }, + }, +)] +/// Prints status of medium +async fn status(mountpoint: String, param: Value) -> Result<(), Error> { + let output_format = get_output_format(¶m); + + 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"); + + let raw = file_get_contents(&statefile)?; + let state: MediumState = serde_json::from_slice(&raw)?; + + if output_format == "text" { + println!("Last sync: {}", epoch_to_rfc3339_utc(state.last_sync)?); + for (mirror, info) in &state.mirrors { + println!("\nMirror {mirror}:"); + match medium::list_snapshots(mountpoint, mirror) { + Ok(snapshots) => { + match (snapshots.first(), snapshots.last()) { + (Some(first), Some(last)) if first == last => { + println!("1 snapshot: {}", first); + } + (Some(first), Some(last)) => { + println!("{} snapshots: '{first}..{last}'", snapshots.len()); + } + _ => { + println!("No snapshots."); + } + }; + if let Some(last) = snapshots.last() { + println!( + "repository config: {}", + proxmox_offline_mirror::generate_repo_file_line( + mountpoint, mirror, info, last + )? + ); + } + } + Err(err) => { + println!("Failed to obtain snapshot list - {err}"); + } + } + } + } else { + let mut json: serde_json::value::Map = serde_json::json!(state) + .as_object() + .ok_or_else(|| format_err!("Failed to serialize state file"))? + .to_owned(); + for mirror in state.mirrors.keys() { + let mirror_json = json + .get_mut("mirrors") + .and_then(|v| v.as_object_mut()) + .and_then(|o| o.get_mut(mirror)) + .and_then(|v| v.as_object_mut()) + .ok_or_else(|| format_err!("Failed to obtain JSON field for mirror {mirror}"))?; + + match medium::list_snapshots(mountpoint, mirror) { + Ok(snapshots) => { + mirror_json.insert("snapshots".to_owned(), serde_json::json!(snapshots)); + } + Err(err) => { + mirror_json.insert( + "errors".to_owned(), + serde_json::json!(format!("Failed to obtain snapshot list - {err}")), + ); + } + } + } + json.remove("subscriptions"); + format_and_print_result(&json.into(), &output_format); + } + + Ok(()) +} + fn main() { let rpcenv = CliEnvironment::new(); let cmd_def = CliCommandMap::new() .insert("setup", CliCommand::new(&API_METHOD_SETUP)) + .insert("status", CliCommand::new(&API_METHOD_STATUS)) .insert( "offline-key", CliCommand::new(&API_METHOD_SETUP_OFFLINE_KEY), -- 2.30.2