qubes/backup: include LVM volumes content in backup

Use just introduced tar writer to archive content of LVM volumes (or
more generally: block devices). Place them as 'private.img' and
'root.img' files in the backup - just like in old format. This require
support for replacing file name in tar header - another thing trivially
supported with tar writer.
This commit is contained in:
Marek Marczykowski-Górecki 2016-10-05 01:55:30 +02:00
parent 36eb7f923f
commit 339c47480e
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -215,7 +215,7 @@ class SendWorker(Process):
class Backup(object): class Backup(object):
class FileToBackup(object): class FileToBackup(object):
def __init__(self, file_path, subdir=None): def __init__(self, file_path, subdir=None, name=None):
sz = qubes.storage.file.get_disk_usage(file_path) sz = qubes.storage.file.get_disk_usage(file_path)
if subdir is None: if subdir is None:
@ -230,9 +230,16 @@ class Backup(object):
if len(subdir) > 0 and not subdir.endswith('/'): if len(subdir) > 0 and not subdir.endswith('/'):
subdir += '/' subdir += '/'
#: real path to the file
self.path = file_path self.path = file_path
#: size of the file
self.size = sz self.size = sz
#: directory in backup archive where file should be placed
self.subdir = subdir self.subdir = subdir
#: use this name in the archive (aka rename)
self.name = os.path.basename(file_path)
if name is not None:
self.name = name
class VMToBackup(object): class VMToBackup(object):
def __init__(self, vm, files, subdir): def __init__(self, vm, files, subdir):
@ -341,11 +348,10 @@ class Backup(object):
subdir = None subdir = None
vm_files = [] vm_files = []
# TODO this is file pool specific. Change it to a more general
# solution
if vm.volumes['private'] is not None: if vm.volumes['private'] is not None:
path_to_private_img = vm.volumes['private'].path path_to_private_img = vm.storage.export('private')
vm_files.append(self.FileToBackup(path_to_private_img, subdir)) vm_files.append(self.FileToBackup(path_to_private_img, subdir,
'private.img'))
vm_files.append(self.FileToBackup(vm.icon_path, subdir)) vm_files.append(self.FileToBackup(vm.icon_path, subdir))
vm_files.extend(self.FileToBackup(i, subdir) vm_files.extend(self.FileToBackup(i, subdir)
@ -357,10 +363,9 @@ class Backup(object):
vm_files.append(self.FileToBackup(firewall_conf, subdir)) vm_files.append(self.FileToBackup(firewall_conf, subdir))
if vm.updateable: if vm.updateable:
# TODO this is file pool specific. Change it to a more general path_to_root_img = vm.storage.export('root')
# solution vm_files.append(self.FileToBackup(path_to_root_img, subdir,
path_to_root_img = vm.volumes['root'].path 'root.img'))
vm_files.append(self.FileToBackup(path_to_root_img, subdir))
files_to_backup[vm.qid] = self.VMToBackup(vm, vm_files, subdir) files_to_backup[vm.qid] = self.VMToBackup(vm, vm_files, subdir)
# Dom0 user home # Dom0 user home
@ -593,7 +598,7 @@ class Backup(object):
backup_tempfile = os.path.join( backup_tempfile = os.path.join(
self.tmpdir, file_info.subdir, self.tmpdir, file_info.subdir,
os.path.basename(file_info.path)) file_info.name)
self.log.debug("Using temporary location: {}".format( self.log.debug("Using temporary location: {}".format(
backup_tempfile)) backup_tempfile))
@ -610,13 +615,27 @@ class Backup(object):
'-C', os.path.dirname(file_info.path)] + '-C', os.path.dirname(file_info.path)] +
(['--dereference'] if (['--dereference'] if
file_info.subdir != "dom0-home/" else []) + file_info.subdir != "dom0-home/" else []) +
['--xform', 's:^%s:%s\\0:' % ( ['--xform=s:^%s:%s\\0:' % (
os.path.basename(file_info.path), os.path.basename(file_info.path),
file_info.subdir), file_info.subdir),
os.path.basename(file_info.path) os.path.basename(file_info.path)
]) ])
file_stat = os.stat(file_info.path)
if stat.S_ISBLK(file_stat.st_mode) or \
file_info.name != os.path.basename(file_info.path):
# tar doesn't handle content of block device, use our
# writer
# also use our tar writer when renaming file
assert not stat.S_ISDIR(file_stat.st_mode),\
"Renaming directories not supported"
tar_cmdline = ['python', '-m', 'qubes.tarwriter',
'--override-name=%s' % (
os.path.join(file_info.subdir, os.path.basename(
file_info.name))),
file_info.path,
backup_pipe]
if self.compressed: if self.compressed:
tar_cmdline.insert(-1, tar_cmdline.insert(-2,
"--use-compress-program=%s" % self.compression_filter) "--use-compress-program=%s" % self.compression_filter)
self.log.debug(" ".join(tar_cmdline)) self.log.debug(" ".join(tar_cmdline))