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 UTF8SMTPS id 2AE9F60691 for ; Thu, 8 Oct 2020 10:16:16 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with UTF8SMTP id 18CD8C18C for ; Thu, 8 Oct 2020 10:15:46 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (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 UTF8SMTPS id AC04CC17E for ; Thu, 8 Oct 2020 10:15:44 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with UTF8SMTP id 7007145C4E for ; Thu, 8 Oct 2020 10:15:44 +0200 (CEST) To: pbs-devel@lists.proxmox.com References: <20201007090324.42928-1-h.laimer@proxmox.com> <20201007090324.42928-3-h.laimer@proxmox.com> <20201008075001.ehfl3nstli3djlyq@olga.proxmox.com> From: Dominik Csapak Message-ID: Date: Thu, 8 Oct 2020 10:15:42 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Thunderbird/82.0 MIME-Version: 1.0 In-Reply-To: <20201008075001.ehfl3nstli3djlyq@olga.proxmox.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.504 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment NICE_REPLY_A -0.001 Looks like a legit reply (A) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [verify.rs, config.rs, proxmox.com] Subject: Re: [pbs-devel] [PATCH v2 proxmox-backup 02/15] add verify job config X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Oct 2020 08:16:16 -0000 On 10/8/20 9:50 AM, Wolfgang Bumiller wrote: > On Wed, Oct 07, 2020 at 11:03:11AM +0200, Hannes Laimer wrote: >> Signed-off-by: Hannes Laimer >> --- >> src/config.rs | 1 + >> src/config/verify.rs | 189 +++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 190 insertions(+) >> create mode 100644 src/config/verify.rs >> >> diff --git a/src/config.rs b/src/config.rs >> index c2ac6da1..ab7fc81a 100644 >> --- a/src/config.rs >> +++ b/src/config.rs >> @@ -23,6 +23,7 @@ pub mod network; >> pub mod remote; >> pub mod sync; >> pub mod user; >> +pub mod verify; >> >> /// Check configuration directory permissions >> /// >> diff --git a/src/config/verify.rs b/src/config/verify.rs >> new file mode 100644 >> index 00000000..7c92a16e >> --- /dev/null >> +++ b/src/config/verify.rs >> @@ -0,0 +1,189 @@ >> +use anyhow::{Error}; >> +use lazy_static::lazy_static; >> +use std::collections::HashMap; >> +use serde::{Serialize, Deserialize}; >> + >> +use proxmox::api::{ >> + api, >> + schema::*, >> + section_config::{ >> + SectionConfig, >> + SectionConfigData, >> + SectionConfigPlugin, >> + } >> +}; >> + >> +use proxmox::tools::{fs::replace_file, fs::CreateOptions}; >> + >> +use crate::api2::types::*; >> + >> +lazy_static! { >> + static ref CONFIG: SectionConfig = init(); >> +} >> + >> + >> +#[api( >> + properties: { >> + id: { >> + schema: JOB_ID_SCHEMA, >> + }, >> + store: { >> + schema: DATASTORE_SCHEMA, >> + }, >> + "ignore-verified": { >> + optional: true, >> + schema: IGNORE_VERIFIED_BACKUPS_SCHEMA, >> + }, >> + "outdated-after": { >> + optional: true, >> + schema: VERIFICATION_OUTDATED_AFTER_SCHEMA, >> + }, >> + comment: { >> + optional: true, >> + schema: SINGLE_LINE_COMMENT_SCHEMA, >> + }, >> + schedule: { >> + optional: true, >> + schema: VERIFY_SCHEDULE_SCHEMA, >> + }, >> + } >> +)] >> +#[serde(rename_all="kebab-case")] >> +#[derive(Serialize,Deserialize)] >> +/// Verify Job >> +pub struct VerifyJobConfig { > > First things first - can we name this `VerificationJobConfig`? I'm not a > fan of using a verb here... > >> + pub id: String, >> + pub store: String, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub ignore_verified: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub outdated_after: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub comment: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub schedule: Option, >> +} >> + >> +// FIXME: generate duplicate schemas/structs from one listing? > > Why though? > > So my question there is, what is this supposed to actually represent? > > It is a separate struct and it contains the keys from the other struct, > but how do they relate to each other? (And I mean apart from "we do this > in PVE, too", I do not consider that a good argument...) > > Do you really need all of these fields in there or really just the id? > > And if you want/need all the info as part of the state, what's stopping > you from simply using an actual struct member of type `VerifyJobConfig` > instead of flattening it out? > fyi, hannes probably copied it from our sync jobs the rationale here is that we need a list of all those properties below in a flat array (so no nested object) for easy use in the gui and we wanted to have a strict type (Vec) instead of Vec (or simply Value) to get some compile time guarantees but the additional fields do not belong in the config so we needed a second struct >> +#[api( >> + properties: { >> + id: { >> + schema: JOB_ID_SCHEMA, >> + }, >> + store: { >> + schema: DATASTORE_SCHEMA, >> + }, >> + "ignore-verified": { >> + optional: true, >> + schema: IGNORE_VERIFIED_BACKUPS_SCHEMA, >> + }, >> + "outdated-after": { >> + optional: true, >> + schema: VERIFICATION_OUTDATED_AFTER_SCHEMA, >> + }, >> + comment: { >> + optional: true, >> + schema: SINGLE_LINE_COMMENT_SCHEMA, >> + }, >> + schedule: { >> + optional: true, >> + schema: VERIFY_SCHEDULE_SCHEMA, >> + }, >> + "next-run": { >> + description: "Estimated time of the next run (UNIX epoch).", >> + optional: true, >> + type: Integer, >> + }, >> + "last-run-state": { >> + description: "Result of the last run.", >> + optional: true, >> + type: String, >> + }, >> + "last-run-upid": { >> + description: "Task UPID of the last run.", >> + optional: true, >> + type: String, >> + }, >> + "last-run-endtime": { >> + description: "Endtime of the last run.", >> + optional: true, >> + type: Integer, >> + }, >> + } >> +)] >> +#[serde(rename_all="kebab-case")] >> +#[derive(Serialize,Deserialize)] >> +/// Status of Verify Job >> +pub struct VerifyJobStatus { >> + pub id: String, >> + pub store: String, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub ignore_verified: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub outdated_after: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub comment: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub schedule: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub next_run: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub last_run_state: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub last_run_upid: Option, >> + #[serde(skip_serializing_if="Option::is_none")] >> + pub last_run_endtime: Option, >> +} >> + >> + >> +fn init() -> SectionConfig { >> + let obj_schema = match VerifyJobConfig::API_SCHEMA { >> + Schema::Object(ref obj_schema) => obj_schema, >> + _ => unreachable!(), >> + }; >> + >> + let plugin = SectionConfigPlugin::new("verify".to_string(), Some(String::from("id")), obj_schema); >> + let mut config = SectionConfig::new(&JOB_ID_SCHEMA); >> + config.register_plugin(plugin); >> + >> + config >> +} >> + >> +pub const VERIFY_CFG_FILENAME: &str = "/etc/proxmox-backup/verify.cfg"; >> +pub const VERIFY_CFG_LOCKFILE: &str = "/etc/proxmox-backup/.verify.lck"; >> + >> +pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> { >> + >> + let content = proxmox::tools::fs::file_read_optional_string(VERIFY_CFG_FILENAME)?; >> + let content = content.unwrap_or(String::from("")); > > Use `unwrap_or_else(String::new)`. > >> + >> + let digest = openssl::sha::sha256(content.as_bytes()); >> + let data = CONFIG.parse(VERIFY_CFG_FILENAME, &content)?; >> + Ok((data, digest)) >> +} >> + >> +pub fn save_config(config: &SectionConfigData) -> Result<(), Error> { >> + let raw = CONFIG.write(VERIFY_CFG_FILENAME, &config)?; >> + >> + let backup_user = crate::backup::backup_user()?; >> + let mode = nix::sys::stat::Mode::from_bits_truncate(0o0640); >> + // set the correct owner/group/permissions while saving file >> + // owner(rw) = root, group(r)= backup >> + >> + let options = CreateOptions::new() >> + .perm(mode) >> + .owner(nix::unistd::ROOT) >> + .group(backup_user.gid); >> + >> + replace_file(VERIFY_CFG_FILENAME, raw.as_bytes(), options)?; >> + >> + Ok(()) >> +} >> + >> +// shell completion helper >> +pub fn complete_verify_job_id(_arg: &str, _param: &HashMap) -> Vec { >> + match config() { >> + Ok((data, _digest)) => data.sections.iter().map(|(id, _)| id.to_string()).collect(), >> + Err(_) => return vec![], >> + } >> +} >> \ No newline at end of file >> -- >> 2.20.1 > > > _______________________________________________ > pbs-devel mailing list > pbs-devel@lists.proxmox.com > https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel > >