backup: use vm.features to store backup-specific metadata
Do not keep them in system qubes.xml.
This commit is contained in:
parent
ed88b5a9a3
commit
424d3054f3
@ -514,15 +514,15 @@ class Backup(object):
|
|||||||
files_to_backup = self.get_files_to_backup()
|
files_to_backup = self.get_files_to_backup()
|
||||||
# make sure backup_content isn't set initially
|
# make sure backup_content isn't set initially
|
||||||
for vm in backup_app.domains:
|
for vm in backup_app.domains:
|
||||||
vm.backup_content = qubes.property.DEFAULT
|
vm.features['backup-content'] = False
|
||||||
|
|
||||||
for qid, vm_info in files_to_backup.iteritems():
|
for qid, vm_info in files_to_backup.iteritems():
|
||||||
if qid != 0 and vm_info.vm.is_running():
|
if qid != 0 and vm_info.vm.is_running():
|
||||||
raise qubes.exc.QubesVMNotHaltedError(vm_info.vm)
|
raise qubes.exc.QubesVMNotHaltedError(vm_info.vm)
|
||||||
# VM is included in the backup
|
# VM is included in the backup
|
||||||
backup_app.domains[qid].backup-content = True
|
backup_app.domains[qid].features['backup-content'] = True
|
||||||
backup_app.domains[qid].backup-path = vm_info.subdir
|
backup_app.domains[qid].features['backup-path'] = vm_info.subdir
|
||||||
backup_app.domains[qid].backup-size = vm_info.size
|
backup_app.domains[qid].features['backup-size'] = vm_info.size
|
||||||
backup_app.save()
|
backup_app.save()
|
||||||
|
|
||||||
passphrase = self.passphrase.encode('utf-8')
|
passphrase = self.passphrase.encode('utf-8')
|
||||||
@ -736,6 +736,9 @@ class Backup(object):
|
|||||||
self._done_vms_bytes += vm_info.size
|
self._done_vms_bytes += vm_info.size
|
||||||
self._current_vm_bytes = 0
|
self._current_vm_bytes = 0
|
||||||
self._send_progress_update()
|
self._send_progress_update()
|
||||||
|
# Save date of last backup
|
||||||
|
if vm_info.vm:
|
||||||
|
vm_info.vm.backup_timestamp = datetime.datetime.now()
|
||||||
|
|
||||||
self._queue_put_with_check(send_proc, vmproc, to_send, QUEUE_FINISHED)
|
self._queue_put_with_check(send_proc, vmproc, to_send, QUEUE_FINISHED)
|
||||||
send_proc.join()
|
send_proc.join()
|
||||||
@ -755,11 +758,6 @@ class Backup(object):
|
|||||||
tar_sparse.poll()))
|
tar_sparse.poll()))
|
||||||
vmproc.stdin.close()
|
vmproc.stdin.close()
|
||||||
|
|
||||||
# Save date of last backup
|
|
||||||
for vm in self.app.domains:
|
|
||||||
if vm.backup_content:
|
|
||||||
vm.backup_timestamp = datetime.datetime.now()
|
|
||||||
|
|
||||||
self.app.save()
|
self.app.save()
|
||||||
|
|
||||||
|
|
||||||
@ -1828,8 +1826,8 @@ class BackupRestore(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_vm_included_in_backup_v2(check_vm):
|
def _is_vm_included_in_backup_v2(check_vm):
|
||||||
if check_vm.backup_content:
|
if 'backup-content' in check_vm.features:
|
||||||
return True
|
return check_vm.features['backup-content']
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -1894,8 +1892,8 @@ class BackupRestore(object):
|
|||||||
self.backup_location, 'dom0-home'))[0]
|
self.backup_location, 'dom0-home'))[0]
|
||||||
vms_to_restore['dom0']['size'] = 0 # unknown
|
vms_to_restore['dom0']['size'] = 0 # unknown
|
||||||
else:
|
else:
|
||||||
vms_to_restore['dom0']['subdir'] = vm.backup_path
|
vms_to_restore['dom0']['subdir'] = vm.features['backup-path']
|
||||||
vms_to_restore['dom0']['size'] = vm.backup_size
|
vms_to_restore['dom0']['size'] = int(vm.features['backup-size'])
|
||||||
local_user = grp.getgrnam('qubes').gr_mem[0]
|
local_user = grp.getgrnam('qubes').gr_mem[0]
|
||||||
|
|
||||||
dom0_home = vms_to_restore['dom0']['subdir']
|
dom0_home = vms_to_restore['dom0']['subdir']
|
||||||
@ -2057,8 +2055,9 @@ class BackupRestore(object):
|
|||||||
continue
|
continue
|
||||||
vm = vm_info['vm']
|
vm = vm_info['vm']
|
||||||
if self.header_data.version >= 2:
|
if self.header_data.version >= 2:
|
||||||
vms_size += vm.backup_size
|
if vm.features['backup-size']:
|
||||||
vms_dirs.append(vm.backup_path)
|
vms_size += int(vm.features['backup-size'])
|
||||||
|
vms_dirs.append(vm.features['backup-path'])
|
||||||
vms[vm.name] = vm
|
vms[vm.name] = vm
|
||||||
|
|
||||||
if self.header_data.version >= 2:
|
if self.header_data.version >= 2:
|
||||||
@ -2148,8 +2147,9 @@ class BackupRestore(object):
|
|||||||
self._restore_vm_dir_v1(vm.dir_path,
|
self._restore_vm_dir_v1(vm.dir_path,
|
||||||
os.path.dirname(new_vm.dir_path))
|
os.path.dirname(new_vm.dir_path))
|
||||||
else:
|
else:
|
||||||
shutil.move(os.path.join(self.tmpdir, vm.backup_path),
|
shutil.move(os.path.join(self.tmpdir,
|
||||||
new_vm.dir_path)
|
vm.features['backup-path']),
|
||||||
|
new_vm.dir_path)
|
||||||
|
|
||||||
new_vm.verify_files()
|
new_vm.verify_files()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
@ -2169,6 +2169,11 @@ class BackupRestore(object):
|
|||||||
self.log.warning("Kernel %s not installed, "
|
self.log.warning("Kernel %s not installed, "
|
||||||
"using default one" % vm.kernel)
|
"using default one" % vm.kernel)
|
||||||
vm.kernel = qubes.property.DEFAULT
|
vm.kernel = qubes.property.DEFAULT
|
||||||
|
# remove no longer needed backup metadata
|
||||||
|
if 'backup-content' in vm.features:
|
||||||
|
del vm.features['backup-content']
|
||||||
|
del vm.features['backup-size']
|
||||||
|
del vm.features['backup-path']
|
||||||
try:
|
try:
|
||||||
# exclude VM references - handled manually according to
|
# exclude VM references - handled manually according to
|
||||||
# restore options
|
# restore options
|
||||||
|
@ -159,8 +159,7 @@ class Core2Qubes(qubes.Qubes):
|
|||||||
for attr in ['installed_by_rpm', 'include_in_backups',
|
for attr in ['installed_by_rpm', 'include_in_backups',
|
||||||
'qrexec_timeout', 'internal', 'label', 'name',
|
'qrexec_timeout', 'internal', 'label', 'name',
|
||||||
'vcpus', 'memory', 'maxmem', 'default_user',
|
'vcpus', 'memory', 'maxmem', 'default_user',
|
||||||
'debug', 'pci_strictreset', 'mac', 'autostart',
|
'debug', 'pci_strictreset', 'mac', 'autostart']:
|
||||||
'backup_content', 'backup_path', 'backup_size']:
|
|
||||||
value = element.get(attr)
|
value = element.get(attr)
|
||||||
if value:
|
if value:
|
||||||
kwargs[attr] = value
|
kwargs[attr] = value
|
||||||
@ -191,6 +190,10 @@ class Core2Qubes(qubes.Qubes):
|
|||||||
if repl_service == service:
|
if repl_service == service:
|
||||||
feature = repl_feature
|
feature = repl_feature
|
||||||
vm.features[feature] = value
|
vm.features[feature] = value
|
||||||
|
for attr in ['backup_content', 'backup_path',
|
||||||
|
'backup_size']:
|
||||||
|
value = element.get(attr)
|
||||||
|
vm.features[attr.replace('_', '-')] = value
|
||||||
pcidevs = element.get('pcidevs')
|
pcidevs = element.get('pcidevs')
|
||||||
if pcidevs:
|
if pcidevs:
|
||||||
pcidevs = eval(pcidevs)
|
pcidevs = eval(pcidevs)
|
||||||
|
@ -639,22 +639,6 @@ class TC_90_QubesVM(qubes.tests.QubesTestCase):
|
|||||||
vm = self.get_vm()
|
vm = self.get_vm()
|
||||||
self._test_generic_bool_property(vm, 'pci_strictreset')
|
self._test_generic_bool_property(vm, 'pci_strictreset')
|
||||||
|
|
||||||
def test_380_backup_size(self):
|
|
||||||
vm = self.get_vm()
|
|
||||||
self.assertPropertyDefaultValue(vm, 'backup_size', 0)
|
|
||||||
self.assertPropertyValue(vm, 'backup_size', 0, 0, '0')
|
|
||||||
del vm.backup_size
|
|
||||||
self.assertPropertyDefaultValue(vm, 'backup_size', 0)
|
|
||||||
self.assertPropertyValue(vm, 'backup_size', '0', 0, '0')
|
|
||||||
self.assertPropertyValue(vm, 'backup_size', 300, 300, '300')
|
|
||||||
|
|
||||||
def test_390_backup_path(self):
|
|
||||||
vm = self.get_vm()
|
|
||||||
self.assertPropertyDefaultValue(vm, 'backup_path', '')
|
|
||||||
self.assertPropertyValue(vm, 'backup_path', 'some/dir', 'some/dir')
|
|
||||||
del vm.backup_path
|
|
||||||
self.assertPropertyDefaultValue(vm, 'backup_path', '')
|
|
||||||
|
|
||||||
def test_400_backup_timestamp(self):
|
def test_400_backup_timestamp(self):
|
||||||
vm = self.get_vm()
|
vm = self.get_vm()
|
||||||
timestamp = datetime.datetime(2016, 1, 1, 12, 14, 2)
|
timestamp = datetime.datetime(2016, 1, 1, 12, 14, 2)
|
||||||
|
@ -267,17 +267,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
|
|||||||
type=bool, setter=qubes.property.bool,
|
type=bool, setter=qubes.property.bool,
|
||||||
doc='If this domain is to be included in default backup.')
|
doc='If this domain is to be included in default backup.')
|
||||||
|
|
||||||
backup_content = qubes.property('backup_content', default=False,
|
|
||||||
type=bool, setter=qubes.property.bool,
|
|
||||||
doc='FIXME')
|
|
||||||
|
|
||||||
backup_size = qubes.property('backup_size', type=int, default=0,
|
|
||||||
doc='FIXME')
|
|
||||||
|
|
||||||
# TODO default=None?
|
|
||||||
backup_path = qubes.property('backup_path', type=str, default='',
|
|
||||||
doc='FIXME')
|
|
||||||
|
|
||||||
# format got changed from %s to str(datetime.datetime)
|
# format got changed from %s to str(datetime.datetime)
|
||||||
backup_timestamp = qubes.property('backup_timestamp', default=None,
|
backup_timestamp = qubes.property('backup_timestamp', default=None,
|
||||||
setter=(lambda self, prop, value:
|
setter=(lambda self, prop, value:
|
||||||
|
Loading…
Reference in New Issue
Block a user