Kaynağa Gözat

backup/restore: add option to ignore size limit

Allow to restore backup which have miscalculated VMs size, but otherwise
is good.
Marek Marczykowski-Górecki 6 yıl önce
ebeveyn
işleme
9210048673

+ 7 - 0
doc/manpages/qvm-backup-restore.rst

@@ -70,6 +70,13 @@ Options
 
     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
 
     Restore from a backup located in a specific AppVM

+ 16 - 4
qubesadmin/backup/restore.py

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

+ 6 - 0
qubesadmin/tools/qvm_backup_restore.py

@@ -74,6 +74,10 @@ parser.add_argument("--ignore-username-mismatch", action="store_true",
     help="Ignore dom0 username mismatch when restoring home "
          "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",
     help="Specify VM containing the backup to be restored")
 
@@ -229,6 +233,8 @@ def main(args=None, app=None):
         backup.options.dom0_home = False
     if args.ignore_username_mismatch:
         backup.options.ignore_username_mismatch = True
+    if args.ignore_size_limit:
+        backup.options.ignore_size_limit = True
     if args.exclude:
         backup.options.exclude = args.exclude
     if args.verify_only: