]> git.proxmox.com Git - pve-qemu.git/blame - debian/patches/pve/0030-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch
update submodule and patches to 7.1.0
[pve-qemu.git] / debian / patches / pve / 0030-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch
CommitLineData
6402d961
TL
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Dietmar Maurer <dietmar@proxmox.com>
83faa3fe
TL
3Date: Mon, 6 Apr 2020 12:17:01 +0200
4Subject: [PATCH] PVE-Backup: pbs-restore - new command to restore from proxmox
5 backup server
6402d961 6
bce72611 7Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
6402d961 8---
817b7667 9 meson.build | 4 +
5b15e2ec
FE
10 pbs-restore.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++
11 2 files changed, 227 insertions(+)
6402d961
TL
12 create mode 100644 pbs-restore.c
13
817b7667 14diff --git a/meson.build b/meson.build
5b15e2ec 15index 0bc2fb5b10..f48d2e0457 100644
817b7667
SR
16--- a/meson.build
17+++ b/meson.build
5b15e2ec 18@@ -3613,6 +3613,10 @@ if have_tools
c5e8e7c9 19 vma = executable('vma', files('vma.c', 'vma-reader.c') + genh,
817b7667 20 dependencies: [authz, block, crypto, io, qom], install: true)
6402d961 21
c5e8e7c9 22+ pbs_restore = executable('pbs-restore', files('pbs-restore.c') + genh,
817b7667
SR
23+ dependencies: [authz, block, crypto, io, qom,
24+ libproxmox_backup_qemu], install: true)
25+
26 subdir('storage-daemon')
27 subdir('contrib/rdmacm-mux')
28 subdir('contrib/elf2dmp')
6402d961
TL
29diff --git a/pbs-restore.c b/pbs-restore.c
30new file mode 100644
5b15e2ec 31index 0000000000..2f834cf42e
6402d961
TL
32--- /dev/null
33+++ b/pbs-restore.c
5b15e2ec 34@@ -0,0 +1,223 @@
6402d961
TL
35+/*
36+ * Qemu image restore helper for Proxmox Backup
37+ *
38+ * Copyright (C) 2019 Proxmox Server Solutions
39+ *
40+ * Authors:
41+ * Dietmar Maurer (dietmar@proxmox.com)
42+ *
43+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
44+ * See the COPYING file in the top-level directory.
45+ *
46+ */
47+
48+#include "qemu/osdep.h"
49+#include <glib.h>
50+#include <getopt.h>
51+#include <string.h>
52+
6402d961
TL
53+#include "qemu/module.h"
54+#include "qemu/error-report.h"
55+#include "qemu/main-loop.h"
56+#include "qemu/cutils.h"
57+#include "qapi/error.h"
58+#include "qapi/qmp/qdict.h"
59+#include "sysemu/block-backend.h"
60+
61+#include <proxmox-backup-qemu.h>
62+
63+static void help(void)
64+{
65+ const char *help_msg =
66+ "usage: pbs-restore [--repository <repo>] snapshot archive-name target [command options]\n"
67+ ;
68+
69+ printf("%s", help_msg);
70+ exit(1);
71+}
72+
73+typedef struct CallbackData {
74+ BlockBackend *target;
75+ uint64_t last_offset;
76+ bool skip_zero;
77+} CallbackData;
78+
79+static int write_callback(
80+ void *callback_data_ptr,
81+ uint64_t offset,
82+ const unsigned char *data,
83+ uint64_t data_len)
84+{
85+ int res = -1;
86+
87+ CallbackData *callback_data = (CallbackData *)callback_data_ptr;
88+
89+ uint64_t last_offset = callback_data->last_offset;
90+ if (offset > last_offset) callback_data->last_offset = offset;
91+
92+ if (data == NULL) {
93+ if (callback_data->skip_zero && offset > last_offset) {
94+ return 0;
95+ }
96+ res = blk_pwrite_zeroes(callback_data->target, offset, data_len, 0);
97+ } else {
5b15e2ec 98+ res = blk_pwrite(callback_data->target, offset, data_len, data, 0);
6402d961
TL
99+ }
100+
101+ if (res < 0) {
102+ fprintf(stderr, "blk_pwrite failed at offset %ld length %ld (%d) - %s\n", offset, data_len, res, strerror(-res));
103+ return res;
104+ }
105+
106+ return 0;
107+}
108+
109+int main(int argc, char **argv)
110+{
111+ Error *main_loop_err = NULL;
112+ const char *format = "raw";
113+ const char *repository = NULL;
114+ const char *keyfile = NULL;
115+ int verbose = false;
116+ bool skip_zero = false;
117+
118+ error_init(argv[0]);
119+
c6979241 120+ for (;;) {
6402d961
TL
121+ static const struct option long_options[] = {
122+ {"help", no_argument, 0, 'h'},
123+ {"skip-zero", no_argument, 0, 'S'},
124+ {"verbose", no_argument, 0, 'v'},
125+ {"format", required_argument, 0, 'f'},
126+ {"repository", required_argument, 0, 'r'},
127+ {"keyfile", required_argument, 0, 'k'},
128+ {0, 0, 0, 0}
129+ };
130+ int c = getopt_long(argc, argv, "hvf:r:k:", long_options, NULL);
131+ if (c == -1) {
132+ break;
133+ }
c6979241
TL
134+ switch (c) {
135+ case ':':
136+ fprintf(stderr, "missing argument for option '%s'\n", argv[optind - 1]);
137+ return -1;
138+ case '?':
139+ fprintf(stderr, "unrecognized option '%s'\n", argv[optind - 1]);
140+ return -1;
141+ case 'f':
142+ format = g_strdup(argv[optind - 1]);
143+ break;
144+ case 'r':
145+ repository = g_strdup(argv[optind - 1]);
146+ break;
147+ case 'k':
148+ keyfile = g_strdup(argv[optind - 1]);
149+ break;
150+ case 'v':
151+ verbose = true;
152+ break;
153+ case 'S':
154+ skip_zero = true;
155+ break;
156+ case 'h':
157+ help();
158+ return 0;
6402d961
TL
159+ }
160+ }
161+
162+ if (optind >= argc - 2) {
163+ fprintf(stderr, "missing arguments\n");
164+ help();
165+ return -1;
166+ }
167+
168+ if (repository == NULL) {
169+ repository = getenv("PBS_REPOSITORY");
170+ }
171+
172+ if (repository == NULL) {
173+ fprintf(stderr, "no repository specified\n");
174+ help();
175+ return -1;
176+ }
177+
178+ char *snapshot = argv[optind++];
179+ char *archive_name = argv[optind++];
180+ char *target = argv[optind++];
181+
182+ const char *password = getenv("PBS_PASSWORD");
183+ const char *fingerprint = getenv("PBS_FINGERPRINT");
184+ const char *key_password = getenv("PBS_ENCRYPTION_PASSWORD");
185+
186+ if (qemu_init_main_loop(&main_loop_err)) {
187+ g_error("%s", error_get_pretty(main_loop_err));
188+ }
189+
190+ bdrv_init();
191+ module_call_init(MODULE_INIT_QOM);
192+
bce72611
TL
193+ if (verbose) {
194+ fprintf(stderr, "connecting to repository '%s'\n", repository);
195+ }
6402d961 196+ char *pbs_error = NULL;
0c893fd8 197+ ProxmoxRestoreHandle *conn = proxmox_restore_new(
6402d961
TL
198+ repository, snapshot, password, keyfile, key_password, fingerprint, &pbs_error);
199+ if (conn == NULL) {
200+ fprintf(stderr, "restore failed: %s\n", pbs_error);
201+ return -1;
202+ }
203+
0c893fd8
SR
204+ int res = proxmox_restore_connect(conn, &pbs_error);
205+ if (res < 0 || pbs_error) {
206+ fprintf(stderr, "restore failed (connection error): %s\n", pbs_error);
207+ return -1;
208+ }
209+
6402d961 210+ QDict *options = qdict_new();
6402d961
TL
211+
212+ if (format) {
213+ qdict_put_str(options, "driver", format);
214+ }
215+
bce72611
TL
216+
217+ if (verbose) {
218+ fprintf(stderr, "open block backend for target '%s'\n", target);
219+ }
6402d961
TL
220+ Error *local_err = NULL;
221+ int flags = BDRV_O_RDWR;
6402d961
TL
222+ BlockBackend *blk = blk_new_open(target, NULL, options, flags, &local_err);
223+ if (!blk) {
224+ fprintf(stderr, "%s\n", error_get_pretty(local_err));
225+ return -1;
226+ }
227+
c6979241 228+ CallbackData *callback_data = calloc(sizeof(CallbackData), 1);
6402d961
TL
229+
230+ callback_data->target = blk;
231+ callback_data->skip_zero = skip_zero;
232+ callback_data->last_offset = 0;
233+
234+ // blk_set_enable_write_cache(blk, !writethrough);
235+
bce72611
TL
236+ if (verbose) {
237+ fprintf(stderr, "starting to restore snapshot '%s'\n", snapshot);
fff7e250 238+ fflush(stderr); // ensure we do not get printed after the progress log
bce72611 239+ }
0c893fd8 240+ res = proxmox_restore_image(
6402d961
TL
241+ conn,
242+ archive_name,
243+ write_callback,
244+ callback_data,
245+ &pbs_error,
246+ verbose);
247+
248+ proxmox_restore_disconnect(conn);
41941247 249+ blk_unref(blk);
6402d961
TL
250+
251+ if (res < 0) {
252+ fprintf(stderr, "restore failed: %s\n", pbs_error);
253+ return -1;
254+ }
255+
256+ return 0;
257+}