public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Thomas Lamprecht <t.lamprecht@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH backup 1/2] save last verify result in snapshot manifest
Date: Tue, 25 Aug 2020 17:30:27 +0200	[thread overview]
Message-ID: <20200825153028.22466-1-t.lamprecht@proxmox.com> (raw)

Save the state ("ok" or "failed") and the UPID of the respective
verify task. With this we can easily allow to open  the relevant task
log and show when the last verify happened.

As we already load the manifest when listing the snapshots, just add
it there directly.

We need to make the verify API call protected to be able to save the manifest.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---

One thing I'm not 100% happy with is the serde_json::to_value(manifest) on
storing it again. But I did not wanted to introduce an extra method to store a
manifest derived from the BackupManifest type directly just for this.

 src/api2/admin/datastore.rs | 16 ++++++++++++++--
 src/api2/types/mod.rs       | 27 +++++++++++++++++++++++++++
 src/backup/verify.rs        | 17 +++++++++++++++--
 3 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs
index 7e811de9..6a1e0d63 100644
--- a/src/api2/admin/datastore.rs
+++ b/src/api2/admin/datastore.rs
@@ -361,7 +361,7 @@ pub fn list_snapshots (
 
         let mut size = None;
 
-        let (comment, files) = match get_all_snapshot_files(&datastore, &info) {
+        let (comment, verification, files) = match get_all_snapshot_files(&datastore, &info) {
             Ok((manifest, files)) => {
                 size = Some(files.iter().map(|x| x.size.unwrap_or(0)).sum());
                 // extract the first line from notes
@@ -370,11 +370,21 @@ pub fn list_snapshots (
                     .and_then(|notes| notes.lines().next())
                     .map(String::from);
 
-                (comment, files)
+                let verify = manifest.unprotected["verify_state"].clone();
+                let verify: Option<SnapshotVerifyState> = match serde_json::from_value(verify) {
+                    Ok(verify) => verify,
+                    Err(err) => {
+                        eprintln!("error parsing verification state : '{}'", err);
+                        None
+                    }
+                };
+
+                (comment, verify, files)
             },
             Err(err) => {
                 eprintln!("error during snapshot file listing: '{}'", err);
                 (
+                    None,
                     None,
                     info
                         .files
@@ -394,6 +404,7 @@ pub fn list_snapshots (
             backup_id: group.backup_id().to_string(),
             backup_time: info.backup_dir.backup_time().timestamp(),
             comment,
+            verification,
             files,
             size,
             owner: Some(owner),
@@ -453,6 +464,7 @@ pub fn status(
     returns: {
         schema: UPID_SCHEMA,
     },
+    protected: true,
     access: {
         permission: &Permission::Privilege(&["datastore", "{store}"], PRIV_DATASTORE_READ | PRIV_DATASTORE_BACKUP, true), // fixme
     },
diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs
index d3f20020..6854fdf0 100644
--- a/src/api2/types/mod.rs
+++ b/src/api2/types/mod.rs
@@ -6,6 +6,7 @@ use proxmox::const_regex;
 use proxmox::{IPRE, IPV4RE, IPV6RE, IPV4OCTET, IPV6H16, IPV6LS32};
 
 use crate::backup::CryptMode;
+use crate::server::UPID;
 
 #[macro_use]
 mod macros;
@@ -379,6 +380,25 @@ pub struct GroupListItem {
     pub owner: Option<Userid>,
 }
 
+#[api(
+    properties: {
+        upid: {
+            schema: UPID_SCHEMA
+        },
+        state: {
+            type: String
+        },
+    },
+)]
+#[derive(Serialize, Deserialize)]
+/// Task properties.
+pub struct SnapshotVerifyState {
+    /// UPID of the verify task
+    pub upid: UPID,
+    /// State of the verification. "failed" or "ok"
+    pub state: String,
+}
+
 #[api(
     properties: {
         "backup-type": {
@@ -394,6 +414,10 @@ pub struct GroupListItem {
             schema: SINGLE_LINE_COMMENT_SCHEMA,
             optional: true,
         },
+        verification: {
+            type: SnapshotVerifyState,
+            optional: true,
+        },
         files: {
             items: {
                 schema: BACKUP_ARCHIVE_NAME_SCHEMA
@@ -415,6 +439,9 @@ pub struct SnapshotListItem {
     /// The first line from manifest "notes"
     #[serde(skip_serializing_if="Option::is_none")]
     pub comment: Option<String>,
+    /// The result of the last run verify task
+    #[serde(skip_serializing_if="Option::is_none")]
+    pub verification: Option<SnapshotVerifyState>,
     /// List of contained archive files.
     pub files: Vec<BackupContent>,
     /// Overall snapshot size (sum of all archive sizes).
diff --git a/src/backup/verify.rs b/src/backup/verify.rs
index f9437ff0..dc8be22c 100644
--- a/src/backup/verify.rs
+++ b/src/backup/verify.rs
@@ -1,8 +1,9 @@
 use std::collections::HashSet;
 
-use anyhow::{bail, Error};
+use anyhow::{bail, format_err, Error};
 
 use crate::server::WorkerTask;
+use crate::api2::types::*;
 
 use super::{
     DataStore, BackupGroup, BackupDir, BackupInfo, IndexFile,
@@ -178,7 +179,7 @@ pub fn verify_backup_dir(
     worker: &WorkerTask
 ) -> Result<bool, Error> {
 
-    let manifest = match datastore.load_manifest(&backup_dir) {
+    let mut manifest = match datastore.load_manifest(&backup_dir) {
         Ok((manifest, _)) => manifest,
         Err(err) => {
             worker.log(format!("verify {}:{} - manifest load error: {}", datastore.name(), backup_dir, err));
@@ -190,6 +191,7 @@ pub fn verify_backup_dir(
 
     let mut error_count = 0;
 
+    let mut verify_result = "ok";
     for info in manifest.files() {
         let result = proxmox::try_block!({
             worker.log(format!("  check {}", info.filename));
@@ -221,9 +223,20 @@ pub fn verify_backup_dir(
         if let Err(err) = result {
             worker.log(format!("verify {}:{}/{} failed: {}", datastore.name(), backup_dir, info.filename, err));
             error_count += 1;
+            verify_result = "failed";
         }
+
     }
 
+    let verify_state = SnapshotVerifyState {
+        state: verify_result.to_string(),
+        upid: worker.upid().clone(),
+    };
+    manifest.unprotected["verify_state"] = serde_json::to_value(verify_state)?;
+    datastore.store_manifest(&backup_dir, serde_json::to_value(manifest)?)
+        .map_err(|err| format_err!("unable to store manifest blob - {}", err))?;
+
+
     Ok(error_count == 0)
 }
 
-- 
2.27.0





             reply	other threads:[~2020-08-25 15:30 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-25 15:30 Thomas Lamprecht [this message]
2020-08-25 15:30 ` [pbs-devel] [PATCH backup 2/2] ui: datastore content: show last verify result from a snapshot Thomas Lamprecht
2020-08-26  4:30 ` [pbs-devel] [PATCH backup 1/2] save last verify result in snapshot manifest Dietmar Maurer
2020-08-26  6:15   ` Thomas Lamprecht
2020-08-26  5:37 ` [pbs-devel] applied: " Dietmar Maurer

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=20200825153028.22466-1-t.lamprecht@proxmox.com \
    --to=t.lamprecht@proxmox.com \
    --cc=pbs-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