backup: use simple classes instead of hashes, use events for appmenus
This makes typo errors much easier to find (also using pylint or so). While at it, also removed explicit appmenus backup, as it should be provided by appmenus extension.
This commit is contained in:
parent
c01f43a5d3
commit
b4227f7581
140
qubes/backup.py
140
qubes/backup.py
@ -212,6 +212,36 @@ class SendWorker(Process):
|
||||
|
||||
|
||||
class Backup(object):
|
||||
class FileToBackup(object):
|
||||
def __init__(self, file_path, subdir=None):
|
||||
sz = qubes.storage.get_disk_usage(file_path)
|
||||
|
||||
if subdir is None:
|
||||
abs_file_path = os.path.abspath(file_path)
|
||||
abs_base_dir = os.path.abspath(
|
||||
qubes.config.system_path["qubes_base_dir"]) + '/'
|
||||
abs_file_dir = os.path.dirname(abs_file_path) + '/'
|
||||
(nothing, directory, subdir) = abs_file_dir.partition(abs_base_dir)
|
||||
assert nothing == ""
|
||||
assert directory == abs_base_dir
|
||||
else:
|
||||
if len(subdir) > 0 and not subdir.endswith('/'):
|
||||
subdir += '/'
|
||||
|
||||
self.path = file_path
|
||||
self.size = sz
|
||||
self.subdir = subdir
|
||||
|
||||
class VMToBackup(object):
|
||||
def __init__(self, vm, files, subdir):
|
||||
self.vm = vm
|
||||
self.files = files
|
||||
self.subdir = subdir
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return reduce(lambda x, y: x + y.size, self.files, 0)
|
||||
|
||||
def __init__(self, app, vms_list=None, exclude_list=None, **kwargs):
|
||||
"""
|
||||
If vms = None, include all (sensible) VMs;
|
||||
@ -307,27 +337,9 @@ class Backup(object):
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def _file_to_backup(file_path, subdir=None):
|
||||
sz = qubes.storage.get_disk_usage(file_path)
|
||||
|
||||
if subdir is None:
|
||||
abs_file_path = os.path.abspath(file_path)
|
||||
abs_base_dir = os.path.abspath(
|
||||
qubes.config.system_path["qubes_base_dir"]) + '/'
|
||||
abs_file_dir = os.path.dirname(abs_file_path) + '/'
|
||||
(nothing, directory, subdir) = abs_file_dir.partition(abs_base_dir)
|
||||
assert nothing == ""
|
||||
assert directory == abs_base_dir
|
||||
else:
|
||||
if len(subdir) > 0 and not subdir.endswith('/'):
|
||||
subdir += '/'
|
||||
return [{"path": file_path, "size": sz, "subdir": subdir}]
|
||||
|
||||
|
||||
def get_files_to_backup(self):
|
||||
files_to_backup = {}
|
||||
total_backup_sz = 0
|
||||
for vm in self.vms_for_backup:
|
||||
if vm.qid == 0:
|
||||
# handle dom0 later
|
||||
@ -340,43 +352,20 @@ class Backup(object):
|
||||
|
||||
vm_files = []
|
||||
if vm.private_img is not None:
|
||||
vm_files += self._file_to_backup(vm.private_img, subdir)
|
||||
vm_files.append(self.FileToBackup(vm.private_img, subdir))
|
||||
|
||||
vm_files += self._file_to_backup(vm.icon_path, subdir)
|
||||
if vm.updateable:
|
||||
if os.path.exists(vm.dir_path + "/apps.templates"):
|
||||
# template
|
||||
vm_files += self._file_to_backup(
|
||||
vm.dir_path + "/apps.templates", subdir)
|
||||
else:
|
||||
# standaloneVM
|
||||
vm_files += self._file_to_backup(
|
||||
vm.dir_path + "/apps", subdir)
|
||||
vm_files.append(self.FileToBackup(vm.icon_path, subdir))
|
||||
vm_files.extend(self.FileToBackup(i, subdir)
|
||||
for i in vm.fire_event('backup-get-files'))
|
||||
|
||||
# TODO: drop after merging firewall.xml into qubes.xml
|
||||
firewall_conf = os.path.join(vm.dir_path, vm.firewall_conf)
|
||||
if os.path.exists(firewall_conf):
|
||||
vm_files += self._file_to_backup(
|
||||
firewall_conf, subdir)
|
||||
if 'appmenus_whitelist' in qubes.config.vm_files and \
|
||||
os.path.exists(os.path.join(vm.dir_path,
|
||||
qubes.config.vm_files[
|
||||
'appmenus_whitelist'])):
|
||||
vm_files += self._file_to_backup(
|
||||
os.path.join(vm.dir_path, qubes.config.vm_files[
|
||||
'appmenus_whitelist']),
|
||||
subdir)
|
||||
vm_files.append(self.FileToBackup(firewall_conf, subdir))
|
||||
|
||||
if vm.updateable:
|
||||
vm_files += self._file_to_backup(vm.root_img, subdir)
|
||||
vm_size = reduce(lambda x, y: x + y['size'], vm_files, 0)
|
||||
files_to_backup[vm.qid] = {
|
||||
'vm': vm,
|
||||
'files': vm_files,
|
||||
'subdir': subdir,
|
||||
'size': vm_size,
|
||||
}
|
||||
total_backup_sz += vm_size
|
||||
vm_files.append(self.FileToBackup(vm.root_img, subdir))
|
||||
files_to_backup[vm.qid] = self.VMToBackup(vm, vm_files, subdir)
|
||||
|
||||
# Dom0 user home
|
||||
if 0 in [vm.qid for vm in self.vms_for_backup]:
|
||||
@ -387,20 +376,16 @@ class Backup(object):
|
||||
# left after 'sudo bash' and similar commands
|
||||
subprocess.check_call(['sudo', 'chown', '-R', local_user, home_dir])
|
||||
|
||||
home_sz = qubes.storage.get_disk_usage(home_dir)
|
||||
home_to_backup = [
|
||||
{"path": home_dir, "size": home_sz, "subdir": 'dom0-home/'}]
|
||||
self.FileToBackup(home_dir, 'dom0-home/')]
|
||||
vm_files = home_to_backup
|
||||
|
||||
files_to_backup[0] = {
|
||||
'vm': self.app.domains[0],
|
||||
'files': vm_files,
|
||||
'subdir': os.path.join('dom0-home', os.path.basename(home_dir)),
|
||||
'size': home_sz,
|
||||
}
|
||||
total_backup_sz += home_sz
|
||||
files_to_backup[0] = self.VMToBackup(self.app.domains[0],
|
||||
vm_files,
|
||||
os.path.join('dom0-home', os.path.basename(home_dir)))
|
||||
|
||||
self.total_backup_bytes = total_backup_sz
|
||||
self.total_backup_bytes = reduce(
|
||||
lambda x, y: x + y.size, files_to_backup.values(), 0)
|
||||
return files_to_backup
|
||||
|
||||
|
||||
@ -541,12 +526,12 @@ class Backup(object):
|
||||
vm.backup_content = qubes.property.DEFAULT
|
||||
|
||||
for qid, vm_info in files_to_backup.iteritems():
|
||||
if qid != 0 and vm_info['vm'].is_running():
|
||||
raise qubes.exc.QubesVMNotHaltedError(vm_info['vm'])
|
||||
if qid != 0 and vm_info.vm.is_running():
|
||||
raise qubes.exc.QubesVMNotHaltedError(vm_info.vm)
|
||||
# VM is included in the backup
|
||||
backup_app.domains[qid].backup_content = True
|
||||
backup_app.domains[qid].backup_path = vm_info['subdir']
|
||||
backup_app.domains[qid].backup_size = vm_info['size']
|
||||
backup_app.domains[qid].backup-content = True
|
||||
backup_app.domains[qid].backup-path = vm_info.subdir
|
||||
backup_app.domains[qid].backup-size = vm_info.size
|
||||
backup_app.save()
|
||||
|
||||
passphrase = self.passphrase.encode('utf-8')
|
||||
@ -603,21 +588,20 @@ class Backup(object):
|
||||
to_send.put(f)
|
||||
|
||||
vm_files_to_backup = self.get_files_to_backup()
|
||||
qubes_xml_info = {
|
||||
'files': self._file_to_backup(qubes_xml, ''),
|
||||
'vm': None,
|
||||
'size': 0,
|
||||
'subdir': '',
|
||||
}
|
||||
qubes_xml_info = self.VMToBackup(
|
||||
None,
|
||||
[self.FileToBackup(qubes_xml, '')],
|
||||
''
|
||||
)
|
||||
for vm_info in itertools.chain([qubes_xml_info],
|
||||
vm_files_to_backup.itervalues()):
|
||||
for file_info in vm_info['files']:
|
||||
for file_info in vm_info.files:
|
||||
|
||||
self.log.debug("Backing up {}".format(file_info))
|
||||
|
||||
backup_tempfile = os.path.join(
|
||||
self.tmpdir, file_info["subdir"],
|
||||
os.path.basename(file_info["path"]))
|
||||
self.tmpdir, file_info.subdir,
|
||||
os.path.basename(file_info.path))
|
||||
self.log.debug("Using temporary location: {}".format(
|
||||
backup_tempfile))
|
||||
|
||||
@ -631,13 +615,13 @@ class Backup(object):
|
||||
# verified during untar
|
||||
tar_cmdline = (["tar", "-Pc", '--sparse',
|
||||
"-f", backup_pipe,
|
||||
'-C', os.path.dirname(file_info["path"])] +
|
||||
'-C', os.path.dirname(file_info.path)] +
|
||||
(['--dereference'] if
|
||||
file_info["subdir"] != "dom0-home/" else []) +
|
||||
file_info.subdir != "dom0-home/" else []) +
|
||||
['--xform', 's:^%s:%s\\0:' % (
|
||||
os.path.basename(file_info["path"]),
|
||||
file_info["subdir"]),
|
||||
os.path.basename(file_info["path"])
|
||||
os.path.basename(file_info.path),
|
||||
file_info.subdir),
|
||||
os.path.basename(file_info.path)
|
||||
])
|
||||
if self.compressed:
|
||||
tar_cmdline.insert(-1,
|
||||
@ -760,7 +744,7 @@ class Backup(object):
|
||||
pipe.close()
|
||||
|
||||
# This VM done, update progress
|
||||
self._done_vms_bytes += vm_info['size']
|
||||
self._done_vms_bytes += vm_info.size
|
||||
self._current_vm_bytes = 0
|
||||
self._send_progress_update()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user