Merge remote-tracking branch 'qubesos/pr/42'

* qubesos/pr/42:
  verify-only avoid dom0 handler
  Fix verify-only
  Issue #3303
This commit is contained in:
Marek Marczykowski-Górecki 2017-12-10 22:24:55 +01:00
commit 3541b7d883
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 45 additions and 29 deletions

View File

@ -70,6 +70,7 @@ _re_alphanum = re.compile(r'^[A-Za-z0-9-]*$')
_tar_msg_re = re.compile(r".*#[0-9].*restore_pipe") _tar_msg_re = re.compile(r".*#[0-9].*restore_pipe")
_tar_file_size_re = re.compile(r"^[^ ]+ [^ ]+/[^ ]+ *([0-9]+) .*") _tar_file_size_re = re.compile(r"^[^ ]+ [^ ]+/[^ ]+ *([0-9]+) .*")
class BackupCanceledError(QubesException): class BackupCanceledError(QubesException):
'''Exception raised when backup/restore was cancelled''' '''Exception raised when backup/restore was cancelled'''
def __init__(self, msg, tmpdir=None): def __init__(self, msg, tmpdir=None):
@ -1356,7 +1357,10 @@ class BackupRestore(object):
# This all means that if the file was correctly verified # This all means that if the file was correctly verified
# + decrypted, we will surely access the right file # + decrypted, we will surely access the right file
filename = self._verify_and_decrypt(filename) filename = self._verify_and_decrypt(filename)
to_extract.put(os.path.join(self.tmpdir, filename)) if not self.options.verify_only:
to_extract.put(os.path.join(self.tmpdir, filename))
else:
os.unlink(os.path.join(self.tmpdir, filename))
if self.canceled: if self.canceled:
raise BackupCanceledError("Restore canceled", raise BackupCanceledError("Restore canceled",
@ -1749,6 +1753,9 @@ class BackupRestore(object):
if vm and vm_info.subdir: if vm and vm_info.subdir:
vms_size += int(vm_info.size) vms_size += int(vm_info.size)
vms_dirs.append(vm_info.subdir) vms_dirs.append(vm_info.subdir)
if self.options.verify_only:
continue
for name, volume in vm.volumes.items(): for name, volume in vm.volumes.items():
if not volume.save_on_stop: if not volume.save_on_stop:
continue continue
@ -1768,7 +1775,8 @@ class BackupRestore(object):
restore_info['dom0'].good_to_go: restore_info['dom0'].good_to_go:
vms_dirs.append(os.path.dirname(restore_info['dom0'].subdir)) vms_dirs.append(os.path.dirname(restore_info['dom0'].subdir))
vms_size += restore_info['dom0'].size vms_size += restore_info['dom0'].size
handlers[restore_info['dom0'].subdir] = (self._handle_dom0, None) if not self.options.verify_only:
handlers[restore_info['dom0'].subdir] = (self._handle_dom0, None)
try: try:
self._restore_vm_data(vms_dirs=vms_dirs, vms_size=vms_size, self._restore_vm_data(vms_dirs=vms_dirs, vms_size=vms_size,
handlers=handlers) handlers=handlers)
@ -1777,20 +1785,18 @@ class BackupRestore(object):
raise raise
else: else:
self.log.error('Error extracting data: ' + str(err)) self.log.error('Error extracting data: ' + str(err))
self.log.warning( finally:
"Continuing anyway to restore at least some VMs") if self.log.getEffectiveLevel() > logging.DEBUG:
shutil.rmtree(self.tmpdir)
if self.options.verify_only:
shutil.rmtree(self.tmpdir)
return
if self.canceled: if self.canceled:
raise BackupCanceledError("Restore canceled", raise BackupCanceledError("Restore canceled",
tmpdir=self.tmpdir) tmpdir=self.tmpdir)
shutil.rmtree(self.tmpdir) self.log.info("-> Done.")
self.log.info("-> Done. Please install updates for all the restored " if not self.options.verify_only:
"templates.") self.log.info("-> Please install updates for all the restored "
"templates.")
def _restore_vms_metadata(self, restore_info): def _restore_vms_metadata(self, restore_info):
'''Restore VM metadata '''Restore VM metadata
@ -1811,7 +1817,10 @@ class BackupRestore(object):
for vm in self._templates_first(vms.values()): for vm in self._templates_first(vms.values()):
if self.canceled: if self.canceled:
return return
self.log.info("-> Restoring %s...", vm.name) if self.options.verify_only:
self.log.info("-> Verifying %s...", vm.name)
else:
self.log.info("-> Restoring %s...", vm.name)
kwargs = {} kwargs = {}
if vm.template: if vm.template:
template = restore_info[vm.name].template template = restore_info[vm.name].template
@ -1824,21 +1833,24 @@ class BackupRestore(object):
new_vm = None new_vm = None
vm_name = restore_info[vm.name].name vm_name = restore_info[vm.name].name
try: if self.options.verify_only:
# first only create VMs, later setting may require other VMs new_vm = self.backup_app.domains[vm_name]
# be already created else:
new_vm = self.app.add_new_vm( try:
vm.klass, # first only create VMs, later setting may require other VMs
name=vm_name, # be already created
label=vm.label, new_vm = self.app.add_new_vm(
pool=self.options.override_pool, vm.klass,
**kwargs) name=vm_name,
except Exception as err: # pylint: disable=broad-except label=vm.label,
self.log.error('Error restoring VM %s, skipping: %s', pool=self.options.override_pool,
vm.name, err) **kwargs)
if new_vm: except Exception as err: # pylint: disable=broad-except
del self.app.domains[new_vm.name] self.log.error('Error restoring VM %s, skipping: %s',
continue vm.name, err)
if new_vm:
del self.app.domains[new_vm.name]
continue
restore_info[vm.name].restored_vm = new_vm restore_info[vm.name].restored_vm = new_vm

View File

@ -134,8 +134,12 @@ def handle_broken(app, args, restore_info):
"Or use --rename-conflicting to restore those VMs under " "Or use --rename-conflicting to restore those VMs under "
"modified names (with numbers at the end).") "modified names (with numbers at the end).")
app.log.info("The above VMs will be copied and added to your system.") if args.verify_only:
app.log.info("Exisiting VMs will NOT be removed.") app.log.info("The above VM archive(s) will be verified.")
app.log.info("Existing VMs will NOT be removed or altered.")
else:
app.log.info("The above VMs will be copied and added to your system.")
app.log.info("Exisiting VMs will NOT be removed.")
if there_are_missing_templates: if there_are_missing_templates:
app.log.warning("*** One or more TemplateVMs are missing on the " app.log.warning("*** One or more TemplateVMs are missing on the "