From 1917ea3ce1eaf34c85a5dc0bddd8e94d73faa34d Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Fri, 19 Feb 2021 09:50:25 +0100 Subject: [PATCH] cleanup: use serde(flatten) for VerificationJobStatus, improve code reuse --- src/api2/admin/verify.rs | 75 ++++++++++++++++++------------------- src/config/verify.rs | 80 +++++----------------------------------- 2 files changed, 45 insertions(+), 110 deletions(-) diff --git a/src/api2/admin/verify.rs b/src/api2/admin/verify.rs index 59f4c983..5734710a 100644 --- a/src/api2/admin/verify.rs +++ b/src/api2/admin/verify.rs @@ -1,24 +1,40 @@ //! Datastore Verify Job Management use anyhow::{format_err, Error}; +use serde_json::Value; use proxmox::api::router::SubdirMap; use proxmox::{list_subdirs_api_method, sortable}; use proxmox::api::{api, ApiMethod, Permission, Router, RpcEnvironment}; -use crate::api2::types::*; -use crate::server::do_verification_job; -use crate::server::jobstate::{Job, JobState}; -use crate::config::acl::{ - PRIV_DATASTORE_AUDIT, - PRIV_DATASTORE_VERIFY, +use crate::{ + api2::types::{ + DATASTORE_SCHEMA, + JOB_ID_SCHEMA, + Authid, + }, + server::{ + do_verification_job, + jobstate::{ + Job, + JobState, + compute_schedule_status, + }, + }, + config::{ + acl::{ + PRIV_DATASTORE_AUDIT, + PRIV_DATASTORE_VERIFY, + }, + cached_user_info::CachedUserInfo, + verify::{ + self, + VerificationJobConfig, + VerificationJobStatus, + }, + }, }; -use crate::config::cached_user_info::CachedUserInfo; -use crate::config::verify; -use crate::config::verify::{VerificationJobConfig, VerificationJobStatus}; -use serde_json::Value; -use crate::tools::systemd::time::{parse_calendar_event, compute_next_event}; -use crate::server::UPID; + #[api( input: { @@ -52,10 +68,10 @@ pub fn list_verification_jobs( let (config, digest) = verify::config()?; - let mut list: Vec = config + let job_config_iter = config .convert_to_typed_array("verification")? .into_iter() - .filter(|job: &VerificationJobStatus| { + .filter(|job: &VerificationJobConfig| { let privs = user_info.lookup_privs(&auth_id, &["datastore", &job.store]); if privs & required_privs == 0 { return false; @@ -66,36 +82,17 @@ pub fn list_verification_jobs( } else { true } - }).collect(); + }); - for job in &mut list { + let mut list = Vec::new(); + + for job in job_config_iter { let last_state = JobState::load("verificationjob", &job.id) .map_err(|err| format_err!("could not open statefile for {}: {}", &job.id, err))?; - let (upid, endtime, state, starttime) = match last_state { - JobState::Created { time } => (None, None, None, time), - JobState::Started { upid } => { - let parsed_upid: UPID = upid.parse()?; - (Some(upid), None, None, parsed_upid.starttime) - }, - JobState::Finished { upid, state } => { - let parsed_upid: UPID = upid.parse()?; - (Some(upid), Some(state.endtime()), Some(state.to_string()), parsed_upid.starttime) - }, - }; + let status = compute_schedule_status(&last_state, job.schedule.as_deref())?; - job.last_run_upid = upid; - job.last_run_state = state; - job.last_run_endtime = endtime; - - let last = job.last_run_endtime.unwrap_or(starttime); - - job.next_run = (|| -> Option { - let schedule = job.schedule.as_ref()?; - let event = parse_calendar_event(&schedule).ok()?; - // ignore errors - compute_next_event(&event, last, false).unwrap_or(None) - })(); + list.push(VerificationJobStatus { config: job, status }); } rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into(); diff --git a/src/config/verify.rs b/src/config/verify.rs index 81934270..07b5b7ee 100644 --- a/src/config/verify.rs +++ b/src/config/verify.rs @@ -70,88 +70,26 @@ pub struct VerificationJobConfig { pub schedule: Option, } - #[api( properties: { - id: { - schema: JOB_ID_SCHEMA, + config: { + type: VerificationJobConfig, }, - store: { - schema: DATASTORE_SCHEMA, + status: { + type: JobScheduleStatus, }, - "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: VERIFICATION_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 Verification Job pub struct VerificationJobStatus { - /// unique ID to address this job - pub id: String, - /// the datastore ID this verificaiton job affects - pub store: String, - #[serde(skip_serializing_if="Option::is_none")] - /// if not set to false, check the age of the last snapshot verification to filter - /// out recent ones, depending on 'outdated_after' configuration. - pub ignore_verified: Option, - #[serde(skip_serializing_if="Option::is_none")] - /// Reverify snapshots after X days, never if 0. Ignored if 'ignore_verified' is false. - pub outdated_after: Option, - #[serde(skip_serializing_if="Option::is_none")] - pub comment: Option, - #[serde(skip_serializing_if="Option::is_none")] - /// when to schedule this job in calendar event notation - pub schedule: Option, - #[serde(skip_serializing_if="Option::is_none")] - /// The timestamp when this job runs the next time. - pub next_run: Option, - #[serde(skip_serializing_if="Option::is_none")] - /// The state of the last scheduled run, if any - pub last_run_state: Option, - #[serde(skip_serializing_if="Option::is_none")] - /// The task UPID of the last scheduled run, if any - pub last_run_upid: Option, - #[serde(skip_serializing_if="Option::is_none")] - /// When the last run was finished, combined with UPID.starttime one can calculate the duration - pub last_run_endtime: Option, + #[serde(flatten)] + pub config: VerificationJobConfig, + #[serde(flatten)] + pub status: JobScheduleStatus, } - fn init() -> SectionConfig { let obj_schema = match VerificationJobConfig::API_SCHEMA { Schema::Object(ref obj_schema) => obj_schema,