Skip to content
Snippets Groups Projects
Commit 2fde577a authored by Daniel Salzman's avatar Daniel Salzman
Browse files

Merge branch 'backup_byteorder' into 'master'

mark the CPU architecture in the backup, in restore, make sure that the data is compatible

See merge request !1675
parents 07800fbe 50b696e9
No related branches found
No related tags found
1 merge request!1675mark the CPU architecture in the backup, in restore, make sure that the data is compatible
Pipeline #126861 passed
Showing with 112 additions and 2 deletions
......@@ -85,6 +85,7 @@ int zone_backup_init(bool restore_mode, knot_backup_params_t filters, bool force
ctx->restore_mode = restore_mode;
ctx->backup_params = filters;
ctx->in_backup = 0; // Just to be sure.
ctx->arch_match = true;
ctx->forced = forced;
ctx->backup_format = BACKUP_VERSION;
ctx->backup_global = false;
......@@ -105,6 +106,11 @@ int zone_backup_init(bool restore_mode, knot_backup_params_t filters, bool force
// For restore, check that there are all required data components in the backup.
if (restore_mode) {
if (!ctx->arch_match && filters & BACKUP_PARAM_DB) {
free(ctx);
return KNOT_ECPUCOMPAT;
}
// '+kaspdb' in backup provides data also for '+keysonly' restore.
knot_backup_params_t available = ctx->in_backup |
((bool)(ctx->in_backup & BACKUP_PARAM_KASPDB) * BACKUP_PARAM_KEYSONLY);
......
......@@ -57,6 +57,11 @@ typedef enum {
BACKUP_PARAM_TIMERS | BACKUP_PARAM_KASPDB | \
BACKUP_PARAM_CATALOG)
/*! \bref Backup components using LMDB databases. */
#define BACKUP_PARAM_DB (BACKUP_PARAM_JOURNAL | BACKUP_PARAM_TIMERS | \
BACKUP_PARAM_KASPDB | BACKUP_PARAM_KEYSONLY | \
BACKUP_PARAM_CATALOG)
typedef struct {
const char *name;
knot_backup_params_t param;
......@@ -70,6 +75,7 @@ typedef struct zone_backup_ctx {
bool forced; // if true, the force flag has been set
knot_backup_params_t backup_params; // bit-mapped list of backup components
knot_backup_params_t in_backup; // bit-mapped list of components available in backup
bool arch_match; // match of the system and the backup architectures
bool backup_global; // perform global backup for all zones
ssize_t readers; // when decremented to 0, all zones done, free this context
pthread_mutex_t readers_mutex; // mutex covering readers counter
......
......@@ -28,11 +28,21 @@
#include "contrib/getline.h"
#include "knot/common/log.h"
#ifdef ENDIANITY_LITTLE
#define ENDIAN_STR "LE"
#else
#define ENDIAN_STR "BE"
#endif
#define _STR(x) #x
#define STR(x) _STR(x)
#define KNOT_ARCH STR(__LONG_WIDTH__) ENDIAN_STR
#define LABEL_FILE "knot_backup.label"
#define LOCK_FILE "lock.knot_backup"
#define LABEL_FILE_HEAD "label: Knot DNS Backup\n"
#define LABEL_FILE_FORMAT "backup_format: %d\n"
#define LABEL_FILE_ARCH "architecture: "
#define LABEL_FILE_PARAMS "parameters: "
#define LABEL_FILE_BACKUPDIR "backupdir "
#define LABEL_FILE_TIME_FORMAT "%Y-%m-%d %H:%M:%S %Z"
......@@ -49,6 +59,7 @@
static const char *label_file_name = LABEL_FILE;
static const char *lock_file_name = LOCK_FILE;
static const char *label_file_head = LABEL_FILE_HEAD;
static const char *label_file_arch = KNOT_ARCH;
static void get_full_path(zone_backup_ctx_t *ctx, const char *filename,
char *full_path, size_t full_path_size)
......@@ -125,6 +136,9 @@ static int make_label_file(zone_backup_ctx_t *ctx)
localtime_r(&now, &tm);
strftime(finished_time, sizeof(finished_time), LABEL_FILE_TIME_FORMAT, &tm);
int lmdb_major, lmdb_minor, lmdb_patch;
(void)mdb_version(&lmdb_major, &lmdb_minor, &lmdb_patch);
// Print the label contents.
char params_str[PARAMS_MAX_LENGTH];
print_params(params_str, ctx->backup_params);
......@@ -135,10 +149,14 @@ static int make_label_file(zone_backup_ctx_t *ctx)
"started_time: %s\n"
"finished_time: %s\n"
"knot_version: %s\n"
"lmdb_version: %d.%d.%d\n"
LABEL_FILE_ARCH "%s\n"
LABEL_FILE_PARAMS "%s+" LABEL_FILE_BACKUPDIR "%s\n"
"zone_count: %d\n",
label_file_head,
ctx->backup_format, ident, started_time, finished_time, PACKAGE_VERSION,
ctx->backup_format, ident, started_time, finished_time,
PACKAGE_VERSION,
lmdb_major, lmdb_minor, lmdb_patch, label_file_arch,
params_str, ctx->backup_dir,
ctx->zone_count);
......@@ -199,6 +217,7 @@ static int get_backup_format(zone_backup_ctx_t *ctx)
unsigned int remain = 3; // Bit-mapped "punch card" for lines to get data from.
while (remain > 0 && knot_getline(&line, &line_size, file) != -1) {
int value;
char str[8];
if (sscanf(line, LABEL_FILE_FORMAT, &value) != 0) {
if (value >= BACKUP_FORMAT_TERM) {
ret = KNOT_ENOTSUP;
......@@ -212,6 +231,11 @@ static int get_backup_format(zone_backup_ctx_t *ctx)
continue;
}
}
if (sscanf(line, LABEL_FILE_ARCH "%7s\n", str) != 0 &&
strcmp(str, label_file_arch) != 0) {
ctx->arch_match = false;
continue;
}
if (strncmp(line, LABEL_FILE_PARAMS, sizeof(LABEL_FILE_PARAMS) - 1) == 0) {
ctx->in_backup = parse_params(line + sizeof(LABEL_FILE_PARAMS) - 1);
remain &= ~2;
......
......@@ -109,6 +109,7 @@ enum knot_error {
KNOT_EBADCERTKEY,
KNOT_EFACCES,
KNOT_EBACKUPDATA,
KNOT_ECPUCOMPAT,
KNOT_GENERAL_ERROR = -900,
......
......@@ -108,6 +108,7 @@ static const struct error errors[] = {
{ KNOT_EBADCERTKEY, "unknown certificate key" },
{ KNOT_EFACCES, "file permission denied" },
{ KNOT_EBACKUPDATA, "requested data not in backup" },
{ KNOT_ECPUCOMPAT, "incompatible CPU architecture" },
{ KNOT_GENERAL_ERROR, "unknown general error" },
......
label: Knot DNS Backup
backup_format: 2
identity: tester.knot-dns.cz
started_time: 2021-07-07 14:39:48 CEST
finished_time: 2021-07-07 14:39:48 CEST
knot_version: 3.1.dev.1625122029.e48145931
architecture: 64BE
parameters: +zonefile +nojournal +timers +kaspdb +catalog +backupdir backup_for_tests
zone_count: 3
File added
File added
;; Zone dump (Knot DNS 3.1.dev.1625122029.e48145931)
example1. 10 SOA a.ns.example1. admin.example1. 1 10 10 120 10
example1. 10 NS a.ns.example1.
example1. 10 NS b.ns.example1.
example1. 10 NS ns.out.
deleg.example1. 10 NS a.ns.deleg.example1.
deleg.example1. 10 NS ns.out.
a.ns.deleg.example1. 10 A 10.0.1.1
a.ns.deleg.example1. 10 AAAA fd00::1:1
a.mail.example1. 10 A 10.0.1.1
b.mail.example1. 10 AAAA fd00::1:1
cname.mail.example1. 10 CNAME a.mail.example1.
mx.example1. 10 MX 10 a.mail.example1.
mx.example1. 10 MX 20 b.mail.example1.
mx.example1. 10 MX 30 mail.out.
mx-cname.example1. 10 MX 10 cname.mail.example1.
a.ns.example1. 10 A 10.0.0.1
a.ns.example1. 10 AAAA fd00::a1
b.ns.example1. 10 AAAA fd00::b1
b.ns.example1. 10 AAAA fd00::b2
ptr.example1. 10 PTR target.example1.
a.service.example1. 10 TXT "no address"
b.service.example1. 10 AAAA fd00::2:1
b.service.example1. 10 AAAA fd00::2:2
b.service.example1. 10 AAAA fd00::2:3
srv.example1. 10 SRV 10 0 1000 a.service.example1.
srv.example1. 10 SRV 10 0 1000 b.service.example1.
srv.example1. 10 SRV 10 0 1000 service.out.
target.example1. 10 A 10.0.3.1
target.example1. 10 AAAA fd00::3:1
;; Written 29 records
;; Time 2021-07-07 14:39:48 CEST
;; Zone dump (Knot DNS 3.1.dev.1625122029.e48145931)
example2. 3600 SOA dns1.example2. hostmaster.example2. 1 1 1 10 600
example2. 3600 NS dns1.example2.
dns1.example2. 3600 A 192.0.2.1
;; Written 3 records
;; Time 2021-07-07 14:39:48 CEST
;; Zone dump (Knot DNS 3.1.dev.1625122029.e48145931)
example3. 3600 SOA dns1.example3. hostmaster.example3. 2010111213 10800 3600 1209600 7200
example3. 3600 NS dns1.example3.
example3. 3600 NS dns2.example3.
added.example3. 3600 A 1.2.3.4
dns1.example3. 3600 A 192.0.2.1
dns1.example3. 3600 AAAA 2001:db8::1
dns2.example3. 3600 A 192.0.2.2
dns2.example3. 3600 AAAA 2001:db8::2
;; Written 8 records
;; Time 2021-07-07 14:39:48 CEST
......@@ -47,7 +47,7 @@ zones2 = t.zone("example1.", file_name="example1.file", storage=".") \
+ t.zone("example2.", file_name="example2.file", storage=".") \
+ t.zone("example3.", file_name="example3.file", storage=".")
t.link(zones2, master2)
for i in range(2, 8):
for i in range(2, 9):
dir_from = os.path.join(t.data_dir, "backup%d" % i)
dir_to = os.path.join(master2.dir, "backup%d" % i)
shutil.copytree(dir_from, dir_to)
......@@ -204,4 +204,18 @@ except:
pass
check_log_err(master2, "malformed data")
# Attempt to restore from a backup made by incompatible CPU architecture (incompatible CPU architecture).
try:
master2.ctl("zone-restore +backupdir %s" % backup8_dir, wait=True)
set_err("RESTORE FROM INCOMPATIBLE ARCHITECTURE ALLOWED")
except:
pass
check_log_err(master2, "incompatible CPU architecture")
# Attempt to restore a zonefile from a backup made by incompatible CPU architecture, expected OK.
try:
master2.ctl("zone-restore +zonefile +notimers +nokaspdb +nojournal +nocatalog +backupdir %s" % backup8_dir, wait=True)
except:
set_err("ZONEFILE RESTORE FROM INCOMPATIBLE CPU FAILED")
t.stop()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment