[pbs-devel] [RFC proxmox-backup 6/8] api: admin: add sanity check job api endpoints

Christian Ebner c.ebner at proxmox.com
Wed Dec 13 16:38:17 CET 2023


Implements the api endpoints required to perform administration tasks
for sanity check jobs.

Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
---
 src/api2/admin/mod.rs          |   2 +
 src/api2/admin/sanity_check.rs | 111 +++++++++++++++++++++++++++++++++
 2 files changed, 113 insertions(+)
 create mode 100644 src/api2/admin/sanity_check.rs

diff --git a/src/api2/admin/mod.rs b/src/api2/admin/mod.rs
index 168dc038..8577fc56 100644
--- a/src/api2/admin/mod.rs
+++ b/src/api2/admin/mod.rs
@@ -8,6 +8,7 @@ pub mod datastore;
 pub mod metrics;
 pub mod namespace;
 pub mod prune;
+pub mod sanity_check;
 pub mod sync;
 pub mod traffic_control;
 pub mod verify;
@@ -17,6 +18,7 @@ const SUBDIRS: SubdirMap = &sorted!([
     ("datastore", &datastore::ROUTER),
     ("metrics", &metrics::ROUTER),
     ("prune", &prune::ROUTER),
+    ("sanity-check", &sanity_check::ROUTER),
     ("sync", &sync::ROUTER),
     ("traffic-control", &traffic_control::ROUTER),
     ("verify", &verify::ROUTER),
diff --git a/src/api2/admin/sanity_check.rs b/src/api2/admin/sanity_check.rs
new file mode 100644
index 00000000..990ce6f2
--- /dev/null
+++ b/src/api2/admin/sanity_check.rs
@@ -0,0 +1,111 @@
+//! Sanity Check Job Management
+
+use anyhow::{format_err, Error};
+use serde_json::Value;
+
+use proxmox_router::{
+    list_subdirs_api_method, ApiMethod, Permission, Router, RpcEnvironment, SubdirMap,
+};
+use proxmox_schema::api;
+use proxmox_sortable_macro::sortable;
+
+use pbs_api_types::{
+    Authid, SanityCheckJobConfig, SanityCheckJobStatus, JOB_ID_SCHEMA, PRIV_SYS_AUDIT,
+    PRIV_SYS_MODIFY,
+};
+use pbs_config::{sanity_check, CachedUserInfo};
+
+use crate::server::{
+    do_sanity_check_job,
+    jobstate::{compute_schedule_status, Job, JobState},
+};
+
+#[api(
+    returns: {
+        description: "List configured jobs and their status",
+        type: Array,
+        items: { type: SanityCheckJobStatus },
+    },
+    access: {
+        permission: &Permission::Anybody,
+        description: "Requires Sys.Audit or Sys.Modify.",
+    },
+)]
+/// List all sanity check jobs
+pub fn list_sanity_check_jobs(
+    _param: Value,
+    rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<SanityCheckJobStatus>, Error> {
+    let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
+    let user_info = CachedUserInfo::new()?;
+    user_info.check_privs(&auth_id, &["/"], PRIV_SYS_AUDIT | PRIV_SYS_MODIFY, true)?;
+
+    let (config, digest) = sanity_check::config()?;
+    let sanity_check_job_config: Vec<SanityCheckJobConfig> =
+        config.convert_to_typed_array("sanity-check")?;
+
+    let mut list = Vec::new();
+    for job in sanity_check_job_config {
+        let last_state = JobState::load("sanitycheckjob", &job.id)
+            .map_err(|err| format_err!("could not open statefile for {}: {err}", &job.id))?;
+
+        let mut status = compute_schedule_status(&last_state, Some(&job.schedule))?;
+        if job.disable {
+            status.next_run = None;
+        }
+
+        list.push(SanityCheckJobStatus {
+            config: job,
+            status,
+        });
+    }
+
+    rpcenv["digest"] = hex::encode(digest).into();
+
+    Ok(list)
+}
+
+#[api(
+    input: {
+        properties: {
+            id: {
+                schema: JOB_ID_SCHEMA,
+            }
+        }
+    },
+    access: {
+        permission: &Permission::Anybody,
+        description: "Requires Sys.Modify.",
+    },
+)]
+/// Runs a sanity check job manually.
+pub fn run_sanity_check_job(
+    id: String,
+    _info: &ApiMethod,
+    rpcenv: &mut dyn RpcEnvironment,
+) -> Result<String, Error> {
+    let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
+    let user_info = CachedUserInfo::new()?;
+    user_info.check_privs(&auth_id, &["/"], PRIV_SYS_MODIFY, true)?;
+
+    let (config, _digest) = sanity_check::config()?;
+    let sanity_check_job: SanityCheckJobConfig = config.lookup("sanity-check", &id)?;
+
+    let job = Job::new("sanitycheckjob", &id)?;
+
+    let upid_str = do_sanity_check_job(job, sanity_check_job.options, &auth_id, None)?;
+
+    Ok(upid_str)
+}
+
+#[sortable]
+const SANITY_CHECK_INFO_SUBDIRS: SubdirMap =
+    &[("run", &Router::new().post(&API_METHOD_RUN_SANITY_CHECK_JOB))];
+
+const SANITY_CHECK_INFO_ROUTER: Router = Router::new()
+    .get(&list_subdirs_api_method!(SANITY_CHECK_INFO_SUBDIRS))
+    .subdirs(SANITY_CHECK_INFO_SUBDIRS);
+
+pub const ROUTER: Router = Router::new()
+    .get(&API_METHOD_LIST_SANITY_CHECK_JOBS)
+    .match_all("id", &SANITY_CHECK_INFO_ROUTER);
-- 
2.39.2





More information about the pbs-devel mailing list