2015-02-05 15:46:40 +01:00
|
|
|
class BackupTestsMixin(SystemTestsMixin):
|
|
|
|
def setUp(self):
|
|
|
|
super(BackupTestsMixin, self).setUp()
|
|
|
|
self.error_detected = multiprocessing.Queue()
|
|
|
|
self.verbose = False
|
|
|
|
|
|
|
|
if self.verbose:
|
|
|
|
print >>sys.stderr, "-> Creating backupvm"
|
|
|
|
|
2015-03-22 01:40:50 +01:00
|
|
|
# TODO: allow non-default template
|
2015-02-05 15:46:40 +01:00
|
|
|
self.backupvm = self.qc.add_new_vm("QubesAppVm",
|
|
|
|
name=self.make_vm_name('backupvm'),
|
|
|
|
template=self.qc.get_default_template())
|
|
|
|
self.backupvm.create_on_disk(verbose=self.verbose)
|
|
|
|
|
|
|
|
self.backupdir = os.path.join(os.environ["HOME"], "test-backup")
|
|
|
|
if os.path.exists(self.backupdir):
|
|
|
|
shutil.rmtree(self.backupdir)
|
|
|
|
os.mkdir(self.backupdir)
|
|
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
super(BackupTestsMixin, self).tearDown()
|
|
|
|
shutil.rmtree(self.backupdir)
|
|
|
|
|
|
|
|
|
|
|
|
def print_progress(self, progress):
|
|
|
|
if self.verbose:
|
|
|
|
print >> sys.stderr, "\r-> Backing up files: {0}%...".format(progress)
|
|
|
|
|
|
|
|
|
|
|
|
def error_callback(self, message):
|
|
|
|
self.error_detected.put(message)
|
|
|
|
if self.verbose:
|
|
|
|
print >> sys.stderr, "ERROR: {0}".format(message)
|
|
|
|
|
|
|
|
|
|
|
|
def print_callback(self, msg):
|
|
|
|
if self.verbose:
|
|
|
|
print msg
|
|
|
|
|
|
|
|
|
|
|
|
def fill_image(self, path, size=None, sparse=False):
|
|
|
|
block_size = 4096
|
|
|
|
|
|
|
|
if self.verbose:
|
|
|
|
print >>sys.stderr, "-> Filling %s" % path
|
|
|
|
f = open(path, 'w+')
|
|
|
|
if size is None:
|
|
|
|
f.seek(0, 2)
|
|
|
|
size = f.tell()
|
|
|
|
f.seek(0)
|
|
|
|
|
|
|
|
for block_num in xrange(size/block_size):
|
|
|
|
f.write('a' * block_size)
|
|
|
|
if sparse:
|
|
|
|
f.seek(block_size, 1)
|
|
|
|
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
|
|
|
# NOTE: this was create_basic_vms
|
|
|
|
def create_backup_vms(self):
|
|
|
|
template=self.qc.get_default_template()
|
|
|
|
|
|
|
|
vms = []
|
|
|
|
vmname = self.make_vm_name('test1')
|
|
|
|
if self.verbose:
|
|
|
|
print >>sys.stderr, "-> Creating %s" % vmname
|
|
|
|
testvm1 = self.qc.add_new_vm('QubesAppVm',
|
|
|
|
name=vmname, template=template)
|
|
|
|
testvm1.create_on_disk(verbose=self.verbose)
|
|
|
|
vms.append(testvm1)
|
|
|
|
self.fill_image(testvm1.private_img, 100*1024*1024)
|
|
|
|
|
|
|
|
vmname = self.make_vm_name('testhvm1')
|
|
|
|
if self.verbose:
|
|
|
|
print >>sys.stderr, "-> Creating %s" % vmname
|
|
|
|
testvm2 = self.qc.add_new_vm('QubesHVm', name=vmname)
|
|
|
|
testvm2.create_on_disk(verbose=self.verbose)
|
|
|
|
self.fill_image(testvm2.root_img, 1024*1024*1024, True)
|
|
|
|
vms.append(testvm2)
|
|
|
|
|
2015-02-21 00:25:50 +01:00
|
|
|
self.qc.save()
|
2015-02-19 03:52:35 +01:00
|
|
|
|
2015-02-05 15:46:40 +01:00
|
|
|
return vms
|
|
|
|
|
|
|
|
|
|
|
|
def make_backup(self, vms, prepare_kwargs=dict(), do_kwargs=dict(),
|
|
|
|
target=None):
|
|
|
|
# XXX: bakup_prepare and backup_do don't support host_collection
|
|
|
|
self.qc.unlock_db()
|
|
|
|
if target is None:
|
|
|
|
target = self.backupdir
|
|
|
|
try:
|
|
|
|
files_to_backup = \
|
|
|
|
qubes.backup.backup_prepare(vms,
|
|
|
|
print_callback=self.print_callback,
|
|
|
|
**prepare_kwargs)
|
2015-02-18 22:49:47 +01:00
|
|
|
except qubes.qubes.QubesException as e:
|
2015-02-05 15:46:40 +01:00
|
|
|
self.fail("QubesException during backup_prepare: %s" % str(e))
|
|
|
|
|
|
|
|
try:
|
|
|
|
qubes.backup.backup_do(target, files_to_backup, "qubes",
|
|
|
|
progress_callback=self.print_progress,
|
|
|
|
**do_kwargs)
|
2015-02-18 22:49:47 +01:00
|
|
|
except qubes.qubes.QubesException as e:
|
2015-02-05 15:46:40 +01:00
|
|
|
self.fail("QubesException during backup_do: %s" % str(e))
|
|
|
|
|
|
|
|
self.qc.lock_db_for_writing()
|
|
|
|
self.qc.load()
|
|
|
|
|
|
|
|
|
2015-02-11 13:15:35 +01:00
|
|
|
def restore_backup(self, source=None, appvm=None, options=None):
|
2015-02-05 15:46:40 +01:00
|
|
|
if source is None:
|
|
|
|
backupfile = os.path.join(self.backupdir,
|
|
|
|
sorted(os.listdir(self.backupdir))[-1])
|
|
|
|
else:
|
|
|
|
backupfile = source
|
|
|
|
|
|
|
|
with self.assertNotRaises(qubes.qubes.QubesException):
|
|
|
|
backup_info = qubes.backup.backup_restore_prepare(
|
|
|
|
backupfile, "qubes",
|
|
|
|
host_collection=self.qc,
|
|
|
|
print_callback=self.print_callback,
|
2015-02-11 13:15:35 +01:00
|
|
|
appvm=appvm,
|
|
|
|
options=options or {})
|
2015-02-05 15:46:40 +01:00
|
|
|
|
|
|
|
if self.verbose:
|
|
|
|
qubes.backup.backup_restore_print_summary(backup_info)
|
|
|
|
|
|
|
|
with self.assertNotRaises(qubes.qubes.QubesException):
|
|
|
|
qubes.backup.backup_restore_do(
|
|
|
|
backup_info,
|
|
|
|
host_collection=self.qc,
|
|
|
|
print_callback=self.print_callback if self.verbose else None,
|
|
|
|
error_callback=self.error_callback)
|
|
|
|
|
2015-02-11 13:15:35 +01:00
|
|
|
# maybe someone forgot to call .save()
|
|
|
|
self.qc.load()
|
|
|
|
|
2015-02-05 15:46:40 +01:00
|
|
|
errors = []
|
|
|
|
while not self.error_detected.empty():
|
|
|
|
errors.append(self.error_detected.get())
|
|
|
|
self.assertTrue(len(errors) == 0,
|
|
|
|
"Error(s) detected during backup_restore_do: %s" %
|
|
|
|
'\n'.join(errors))
|
2015-02-22 14:46:46 +01:00
|
|
|
if not appvm and not os.path.isdir(backupfile):
|
2015-02-05 15:46:40 +01:00
|
|
|
os.unlink(backupfile)
|
|
|
|
|
|
|
|
|
|
|
|
def create_sparse(self, path, size):
|
|
|
|
f = open(path, "w")
|
|
|
|
f.truncate(size)
|
|
|
|
f.close()
|