public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Christoph Heiss <c.heiss@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [RFC PATCH v2 proxmox-backup-qemu 4/7] api: Supply `protected` parameter to the `finish` API call
Date: Wed, 25 Jan 2023 13:18:59 +0100	[thread overview]
Message-ID: <20230125121902.404950-5-c.heiss@proxmox.com> (raw)
In-Reply-To: <20230125121902.404950-1-c.heiss@proxmox.com>

This can be used to set backups as protected as soon as the transfer is
finished, to e.g. avoid races while trying to set it protected later on,
while the PBS might have locked it already for verification.

! This is a breaking API/ABI change !

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
Depends on the previous proxmox-backup patches (1-3 in the series).

RFC question: It would probably be sensible to issue a warning in
BackupTask::finish() - but what is the right way for that? A simple
eprintln!()?

Changes v1 -> v2:
* Use new server feature mechanism to detect support for API parameter

 current-api.h   |  3 ++-
 simpletest.c    |  2 +-
 src/backup.rs   | 24 ++++++++++++++++++++----
 src/commands.rs | 10 +++++++++-
 src/lib.rs      |  5 ++++-
 5 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/current-api.h b/current-api.h
index f38ad4b..729a3a3 100644
--- a/current-api.h
+++ b/current-api.h
@@ -271,7 +271,7 @@ void proxmox_backup_close_image_async(struct ProxmoxBackupHandle *handle,
 /**
  * Finish the backup (sync)
  */
-int proxmox_backup_finish(struct ProxmoxBackupHandle *handle, char **error);
+int proxmox_backup_finish(struct ProxmoxBackupHandle *handle, bool protected_, char **error);

 /**
  * Finish the backup
@@ -280,6 +280,7 @@ int proxmox_backup_finish(struct ProxmoxBackupHandle *handle, char **error);
  * All registered images have to be closed before calling this.
  */
 void proxmox_backup_finish_async(struct ProxmoxBackupHandle *handle,
+                                 bool protected_,
                                  void (*callback)(void*),
                                  void *callback_data,
                                  int *result,
diff --git a/simpletest.c b/simpletest.c
index ceb5afd..b061bde 100644
--- a/simpletest.c
+++ b/simpletest.c
@@ -77,7 +77,7 @@ void main(int argc, char **argv) {
   }

   printf("finish backup\n");
-  if (proxmox_backup_finish(pbs, &pbs_error) < 0) {
+  if (proxmox_backup_finish(pbs, false, &pbs_error) < 0) {
     fprintf(stderr, "proxmox_backup_finish failed - %s\n", pbs_error);
     proxmox_backup_free_error(pbs_error);
     exit(-1);
diff --git a/src/backup.rs b/src/backup.rs
index bbe4f00..60ec453 100644
--- a/src/backup.rs
+++ b/src/backup.rs
@@ -10,8 +10,10 @@ use tokio::runtime::Runtime;
 use proxmox_async::runtime::get_runtime_with_builder;
 use proxmox_sys::fs::file_get_contents;

-use pbs_api_types::{BackupType, CryptMode};
-use pbs_client::{BackupWriter, HttpClient, HttpClientOptions};
+use pbs_api_types::{BackupType, CryptMode, ServerFeature};
+use pbs_client::{
+    tools::get_supported_server_features, BackupWriter, HttpClient, HttpClientOptions,
+};
 use pbs_datastore::BackupManifest;
 use pbs_key_config::{load_and_decrypt_key, rsa_encrypt_key_config, KeyConfig};
 use pbs_tools::crypt_config::CryptConfig;
@@ -35,6 +37,7 @@ pub(crate) struct BackupTask {
     known_chunks: Arc<Mutex<HashSet<[u8; 32]>>>,
     abort: tokio::sync::broadcast::Sender<()>,
     aborted: OnceCell<String>, // set on abort, conatins abort reason
+    server_features: OnceCell<Vec<ServerFeature>>,
 }

 impl BackupTask {
@@ -92,6 +95,7 @@ impl BackupTask {
             writer: OnceCell::new(),
             last_manifest: OnceCell::new(),
             aborted: OnceCell::new(),
+            server_features: OnceCell::new(),
         })
     }

@@ -141,10 +145,15 @@ impl BackupTask {
                 &self.setup.auth_id,
                 options,
             )?;
+
+            self.server_features
+                .set(get_supported_server_features(&http).await)
+                .map_err(|_| format_err!("already connected!"))?;
+
             let mut backup_dir = self.setup.backup_dir.clone();
             backup_dir.group.ty = BackupType::Vm;
             let writer = BackupWriter::start(
-                http,
+                &http,
                 self.crypt_config.clone(),
                 &self.setup.store,
                 &self.setup.backup_ns,
@@ -286,14 +295,21 @@ impl BackupTask {
         abortable_command(command_future, abort_rx.recv()).await
     }

-    pub async fn finish(&self) -> Result<c_int, Error> {
+    pub async fn finish(&self, protected: bool) -> Result<c_int, Error> {
         self.check_aborted()?;

+        let protected_supported = self
+            .server_features
+            .get()
+            .map(|sf| sf.contains(&ServerFeature::FinishHasProtectedParam))
+            .unwrap_or(false);
+
         let command_future = finish_backup(
             self.need_writer()?,
             self.crypt_config.clone(),
             self.rsa_encrypted_key.clone(),
             Arc::clone(&self.manifest),
+            protected && protected_supported,
         );

         let mut abort_rx = self.abort.subscribe();
diff --git a/src/commands.rs b/src/commands.rs
index 37d653c..4258711 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -468,11 +468,15 @@ pub(crate) async fn write_data(
     Ok(if reused { 0 } else { size as c_int })
 }

+/// The caller must ensure that all used server features are actually supported by the server.
+/// Currently, this only applies to `protected`. If this is set to true, the server has to support
+/// the `FinishHasProtectedParam` feature flag.
 pub(crate) async fn finish_backup(
     client: Arc<BackupWriter>,
     crypt_config: Option<Arc<CryptConfig>>,
     rsa_encrypted_key: Option<Vec<u8>>,
     manifest: Arc<Mutex<BackupManifest>>,
+    protected: bool,
 ) -> Result<c_int, Error> {
     if let Some(rsa_encrypted_key) = rsa_encrypted_key {
         let target = ENCRYPTED_KEY_BLOB_NAME;
@@ -521,7 +525,11 @@ pub(crate) async fn finish_backup(
         .upload_blob_from_data(manifest.into_bytes(), MANIFEST_BLOB_NAME, options)
         .await?;

-    client.finish().await?;
+    let mut param = json!({});
+    if protected {
+        param["protected"] = json!(true);
+    }

+    client.finish(Some(param)).await?;
     Ok(0)
 }
diff --git a/src/lib.rs b/src/lib.rs
index b3c7b85..2fe234b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -703,6 +703,7 @@ pub extern "C" fn proxmox_backup_close_image_async(
 #[allow(clippy::not_unsafe_ptr_arg_deref)]
 pub extern "C" fn proxmox_backup_finish(
     handle: *mut ProxmoxBackupHandle,
+    protected: bool,
     error: *mut *mut c_char,
 ) -> c_int {
     let mut result: c_int = -1;
@@ -713,6 +714,7 @@ pub extern "C" fn proxmox_backup_finish(

     proxmox_backup_finish_async(
         handle,
+        protected,
         callback_info.callback,
         callback_info.callback_data,
         callback_info.result,
@@ -732,6 +734,7 @@ pub extern "C" fn proxmox_backup_finish(
 #[allow(clippy::not_unsafe_ptr_arg_deref)]
 pub extern "C" fn proxmox_backup_finish_async(
     handle: *mut ProxmoxBackupHandle,
+    protected: bool,
     callback: extern "C" fn(*mut c_void),
     callback_data: *mut c_void,
     result: *mut c_int,
@@ -746,7 +749,7 @@ pub extern "C" fn proxmox_backup_finish_async(
     };

     task.runtime().spawn(async move {
-        let result = task.finish().await;
+        let result = task.finish(protected).await;
         callback_info.send_result(result);
     });
 }
--
2.34.1





  parent reply	other threads:[~2023-01-25 12:20 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-25 12:18 [pbs-devel] [RFC PATCH v2 proxmox-backup{, -qemu}, pve-{qemu, manager}, qemu-server 0/7] fix #4289: Set protected flag on backup creation Christoph Heiss
2023-01-25 12:18 ` [pbs-devel] [RFC PATCH v2 proxmox-backup 1/7] api2: Introduce server features discovery mechanism Christoph Heiss
2023-01-25 15:56   ` Thomas Lamprecht
2023-01-26 12:33     ` Christoph Heiss
2023-01-25 12:18 ` [pbs-devel] [RFC PATCH v2 proxmox-backup 2/7] api2: Add `protected` parameter to `finish` endpoint Christoph Heiss
2023-01-25 12:18 ` [pbs-devel] [RFC PATCH v2 proxmox-backup 3/3] client: Add `--protected` CLI flag to backup command Christoph Heiss
2023-01-25 12:18 ` Christoph Heiss [this message]
2023-01-25 12:19 ` [pbs-devel] [RFC PATCH v2 pve-qemu 5/7] pve: Add patch to support new proxmox-backup-qemu API Christoph Heiss
2023-01-25 12:19 ` [pbs-devel] [RFC PATCH v2 qemu-server 6/7] vzdump: Set protected flag on backup start if supported Christoph Heiss
2023-01-25 12:19 ` [pbs-devel] [RFC PATCH v2 pve-manager 7/7] vzdump: Only set protected attribute if not already done Christoph Heiss
2023-01-25 16:00 ` [pbs-devel] [RFC PATCH v2 proxmox-backup{, -qemu}, pve-{qemu, manager}, qemu-server 0/7] fix #4289: Set protected flag on backup creation Thomas Lamprecht
2023-01-26 12:44   ` Christoph Heiss

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=20230125121902.404950-5-c.heiss@proxmox.com \
    --to=c.heiss@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