X-Git-Url: https://git.proxmox.com/?p=pve-qemu.git;a=blobdiff_plain;f=debian%2Fpatches%2Fpve%2F0029-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch;fp=debian%2Fpatches%2Fpve%2F0029-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch;h=0000000000000000000000000000000000000000;hp=f1c77cbbf1ffc656ee07617274fd4e193505b42d;hb=5b15e2ecaf054107200a49c7d2509053fb91c9fe;hpb=2775b2e3788bfed64345046ce6a669bcdf28eb43 diff --git a/debian/patches/pve/0029-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch b/debian/patches/pve/0029-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch deleted file mode 100644 index f1c77cb..0000000 --- a/debian/patches/pve/0029-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch +++ /dev/null @@ -1,258 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dietmar Maurer -Date: Mon, 6 Apr 2020 12:17:01 +0200 -Subject: [PATCH] PVE-Backup: pbs-restore - new command to restore from proxmox - backup server - -Signed-off-by: Thomas Lamprecht ---- - meson.build | 4 + - pbs-restore.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 228 insertions(+) - create mode 100644 pbs-restore.c - -diff --git a/meson.build b/meson.build -index 76fcb23299..9476ccbe07 100644 ---- a/meson.build -+++ b/meson.build -@@ -3365,6 +3365,10 @@ if have_tools - vma = executable('vma', files('vma.c', 'vma-reader.c') + genh, - dependencies: [authz, block, crypto, io, qom], install: true) - -+ pbs_restore = executable('pbs-restore', files('pbs-restore.c') + genh, -+ dependencies: [authz, block, crypto, io, qom, -+ libproxmox_backup_qemu], install: true) -+ - subdir('storage-daemon') - subdir('contrib/rdmacm-mux') - subdir('contrib/elf2dmp') -diff --git a/pbs-restore.c b/pbs-restore.c -new file mode 100644 -index 0000000000..4d3f925a1b ---- /dev/null -+++ b/pbs-restore.c -@@ -0,0 +1,224 @@ -+/* -+ * Qemu image restore helper for Proxmox Backup -+ * -+ * Copyright (C) 2019 Proxmox Server Solutions -+ * -+ * Authors: -+ * Dietmar Maurer (dietmar@proxmox.com) -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ * -+ */ -+ -+#include "qemu/osdep.h" -+#include -+#include -+#include -+ -+#include "qemu-common.h" -+#include "qemu/module.h" -+#include "qemu/error-report.h" -+#include "qemu/main-loop.h" -+#include "qemu/cutils.h" -+#include "qapi/error.h" -+#include "qapi/qmp/qdict.h" -+#include "sysemu/block-backend.h" -+ -+#include -+ -+static void help(void) -+{ -+ const char *help_msg = -+ "usage: pbs-restore [--repository ] snapshot archive-name target [command options]\n" -+ ; -+ -+ printf("%s", help_msg); -+ exit(1); -+} -+ -+typedef struct CallbackData { -+ BlockBackend *target; -+ uint64_t last_offset; -+ bool skip_zero; -+} CallbackData; -+ -+static int write_callback( -+ void *callback_data_ptr, -+ uint64_t offset, -+ const unsigned char *data, -+ uint64_t data_len) -+{ -+ int res = -1; -+ -+ CallbackData *callback_data = (CallbackData *)callback_data_ptr; -+ -+ uint64_t last_offset = callback_data->last_offset; -+ if (offset > last_offset) callback_data->last_offset = offset; -+ -+ if (data == NULL) { -+ if (callback_data->skip_zero && offset > last_offset) { -+ return 0; -+ } -+ res = blk_pwrite_zeroes(callback_data->target, offset, data_len, 0); -+ } else { -+ res = blk_pwrite(callback_data->target, offset, data, data_len, 0); -+ } -+ -+ if (res < 0) { -+ fprintf(stderr, "blk_pwrite failed at offset %ld length %ld (%d) - %s\n", offset, data_len, res, strerror(-res)); -+ return res; -+ } -+ -+ return 0; -+} -+ -+int main(int argc, char **argv) -+{ -+ Error *main_loop_err = NULL; -+ const char *format = "raw"; -+ const char *repository = NULL; -+ const char *keyfile = NULL; -+ int verbose = false; -+ bool skip_zero = false; -+ -+ error_init(argv[0]); -+ -+ for (;;) { -+ static const struct option long_options[] = { -+ {"help", no_argument, 0, 'h'}, -+ {"skip-zero", no_argument, 0, 'S'}, -+ {"verbose", no_argument, 0, 'v'}, -+ {"format", required_argument, 0, 'f'}, -+ {"repository", required_argument, 0, 'r'}, -+ {"keyfile", required_argument, 0, 'k'}, -+ {0, 0, 0, 0} -+ }; -+ int c = getopt_long(argc, argv, "hvf:r:k:", long_options, NULL); -+ if (c == -1) { -+ break; -+ } -+ switch (c) { -+ case ':': -+ fprintf(stderr, "missing argument for option '%s'\n", argv[optind - 1]); -+ return -1; -+ case '?': -+ fprintf(stderr, "unrecognized option '%s'\n", argv[optind - 1]); -+ return -1; -+ case 'f': -+ format = g_strdup(argv[optind - 1]); -+ break; -+ case 'r': -+ repository = g_strdup(argv[optind - 1]); -+ break; -+ case 'k': -+ keyfile = g_strdup(argv[optind - 1]); -+ break; -+ case 'v': -+ verbose = true; -+ break; -+ case 'S': -+ skip_zero = true; -+ break; -+ case 'h': -+ help(); -+ return 0; -+ } -+ } -+ -+ if (optind >= argc - 2) { -+ fprintf(stderr, "missing arguments\n"); -+ help(); -+ return -1; -+ } -+ -+ if (repository == NULL) { -+ repository = getenv("PBS_REPOSITORY"); -+ } -+ -+ if (repository == NULL) { -+ fprintf(stderr, "no repository specified\n"); -+ help(); -+ return -1; -+ } -+ -+ char *snapshot = argv[optind++]; -+ char *archive_name = argv[optind++]; -+ char *target = argv[optind++]; -+ -+ const char *password = getenv("PBS_PASSWORD"); -+ const char *fingerprint = getenv("PBS_FINGERPRINT"); -+ const char *key_password = getenv("PBS_ENCRYPTION_PASSWORD"); -+ -+ if (qemu_init_main_loop(&main_loop_err)) { -+ g_error("%s", error_get_pretty(main_loop_err)); -+ } -+ -+ bdrv_init(); -+ module_call_init(MODULE_INIT_QOM); -+ -+ if (verbose) { -+ fprintf(stderr, "connecting to repository '%s'\n", repository); -+ } -+ char *pbs_error = NULL; -+ ProxmoxRestoreHandle *conn = proxmox_restore_new( -+ repository, snapshot, password, keyfile, key_password, fingerprint, &pbs_error); -+ if (conn == NULL) { -+ fprintf(stderr, "restore failed: %s\n", pbs_error); -+ return -1; -+ } -+ -+ int res = proxmox_restore_connect(conn, &pbs_error); -+ if (res < 0 || pbs_error) { -+ fprintf(stderr, "restore failed (connection error): %s\n", pbs_error); -+ return -1; -+ } -+ -+ QDict *options = qdict_new(); -+ -+ if (format) { -+ qdict_put_str(options, "driver", format); -+ } -+ -+ -+ if (verbose) { -+ fprintf(stderr, "open block backend for target '%s'\n", target); -+ } -+ Error *local_err = NULL; -+ int flags = BDRV_O_RDWR; -+ BlockBackend *blk = blk_new_open(target, NULL, options, flags, &local_err); -+ if (!blk) { -+ fprintf(stderr, "%s\n", error_get_pretty(local_err)); -+ return -1; -+ } -+ -+ CallbackData *callback_data = calloc(sizeof(CallbackData), 1); -+ -+ callback_data->target = blk; -+ callback_data->skip_zero = skip_zero; -+ callback_data->last_offset = 0; -+ -+ // blk_set_enable_write_cache(blk, !writethrough); -+ -+ if (verbose) { -+ fprintf(stderr, "starting to restore snapshot '%s'\n", snapshot); -+ fflush(stderr); // ensure we do not get printed after the progress log -+ } -+ res = proxmox_restore_image( -+ conn, -+ archive_name, -+ write_callback, -+ callback_data, -+ &pbs_error, -+ verbose); -+ -+ proxmox_restore_disconnect(conn); -+ blk_unref(blk); -+ -+ if (res < 0) { -+ fprintf(stderr, "restore failed: %s\n", pbs_error); -+ return -1; -+ } -+ -+ return 0; -+}