backup/restore: add option to ignore size limit

Allow to restore backup which have miscalculated VMs size, but otherwise
is good.
This commit is contained in:
Marek Marczykowski-Górecki 2017-07-29 04:49:14 +02:00
parent 213760f263
commit 9210048673
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
3 changed files with 29 additions and 4 deletions

View File

@ -70,6 +70,13 @@ Options
Ignore dom0 username mismatch while restoring homedir Ignore dom0 username mismatch while restoring homedir
.. option:: --ignore-size-limit
Backup metadata contains expected size of each VM. By default if backup
contains more data than expected, it is rejected. Use this option to ignore
this limit and restore such (broken, or potentially malicious) backup
anyway.
.. option:: --dest-vm=APPVM, -d APPVM .. option:: --dest-vm=APPVM, -d APPVM
Restore from a backup located in a specific AppVM Restore from a backup located in a specific AppVM

View File

@ -731,6 +731,8 @@ class BackupRestoreOptions(object):
self.exclude = [] self.exclude = []
#: restore VMs into selected storage pool #: restore VMs into selected storage pool
self.override_pool = None self.override_pool = None
#: ignore size limit calculated from backup metadata
self.ignore_size_limit = False
class BackupRestore(object): class BackupRestore(object):
"""Usage: """Usage:
@ -859,6 +861,7 @@ class BackupRestore(object):
self.processes_to_kill_on_cancel.append(vmproc) self.processes_to_kill_on_cancel.append(vmproc)
backup_stdin = vmproc.stdout backup_stdin = vmproc.stdout
# FIXME use /usr/lib/qubes/qfile-unpacker in non-dom0
tar1_command = ['/usr/libexec/qubes/qfile-dom0-unpacker', tar1_command = ['/usr/libexec/qubes/qfile-dom0-unpacker',
str(os.getuid()), self.tmpdir, '-v'] str(os.getuid()), self.tmpdir, '-v']
else: else:
@ -1252,6 +1255,9 @@ class BackupRestore(object):
limit_count = str(2 * (10 * len(vms_dirs) + limit_count = str(2 * (10 * len(vms_dirs) +
int(vms_size / (100 * 1024 * 1024)))) int(vms_size / (100 * 1024 * 1024))))
if self.options.ignore_size_limit:
limit_count = '0'
vms_size = 0
self.log.debug("Working in temporary dir: %s", self.tmpdir) self.log.debug("Working in temporary dir: %s", self.tmpdir)
self.log.info("Extracting data: %s to restore", size_to_human(vms_size)) self.log.info("Extracting data: %s to restore", size_to_human(vms_size))
@ -1352,9 +1358,15 @@ class BackupRestore(object):
tmpdir=self.tmpdir) tmpdir=self.tmpdir)
if retrieve_proc.wait() != 0: if retrieve_proc.wait() != 0:
if retrieve_proc.returncode == errno.EDQUOT:
raise QubesException( raise QubesException(
"unable to read the qubes backup file {0}: {1}" 'retrieved backup size exceed expected size, if you '
.format(self.backup_location, error_pipe.read( 'believe this is ok, use --ignore-size-limit option')
else:
raise QubesException(
"unable to read the qubes backup file {} ({}): {}"
.format(self.backup_location,
retrieve_proc.returncode, error_pipe.read(
MAX_STDERR_BYTES))) MAX_STDERR_BYTES)))
# wait for other processes (if any) # wait for other processes (if any)
for proc in self.processes_to_kill_on_cancel: for proc in self.processes_to_kill_on_cancel:

View File

@ -74,6 +74,10 @@ parser.add_argument("--ignore-username-mismatch", action="store_true",
help="Ignore dom0 username mismatch when restoring home " help="Ignore dom0 username mismatch when restoring home "
"directory") "directory")
parser.add_argument("--ignore-size-limit", action="store_true",
dest="ignore_size_limit", default=False,
help="Ignore size limit calculated from backup metadata")
parser.add_argument("-d", "--dest-vm", action="store", dest="appvm", parser.add_argument("-d", "--dest-vm", action="store", dest="appvm",
help="Specify VM containing the backup to be restored") help="Specify VM containing the backup to be restored")
@ -229,6 +233,8 @@ def main(args=None, app=None):
backup.options.dom0_home = False backup.options.dom0_home = False
if args.ignore_username_mismatch: if args.ignore_username_mismatch:
backup.options.ignore_username_mismatch = True backup.options.ignore_username_mismatch = True
if args.ignore_size_limit:
backup.options.ignore_size_limit = True
if args.exclude: if args.exclude:
backup.options.exclude = args.exclude backup.options.exclude = args.exclude
if args.verify_only: if args.verify_only: