tests/backup: check restored disk images

This commit is contained in:
Marek Marczykowski-Górecki 2016-09-25 20:29:18 +02:00
parent e499b529ad
commit 016c3d8e88
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -22,6 +22,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# #
import hashlib
import logging import logging
import multiprocessing import multiprocessing
@ -36,7 +37,7 @@ import qubes.tests
import qubes.vm import qubes.vm
import qubes.vm.appvm import qubes.vm.appvm
import qubes.vm.templatevm import qubes.vm.templatevm
import qubes.vm.qubesvm
# noinspection PyAttributeOutsideInit # noinspection PyAttributeOutsideInit
class BackupTestsMixin(qubes.tests.SystemTestsMixin): class BackupTestsMixin(qubes.tests.SystemTestsMixin):
@ -224,14 +225,31 @@ class BackupTestsMixin(qubes.tests.SystemTestsMixin):
f.truncate(size) f.truncate(size)
f.close() f.close()
def vm_checksum(self, vms):
class TC_00_Backup(BackupTestsMixin, qubes.tests.QubesTestCase): hashes = {}
def test_000_basic_backup(self):
vms = self.create_backup_vms()
self.make_backup(vms)
self.remove_vms(reversed(vms))
self.restore_backup()
for vm in vms: for vm in vms:
assert isinstance(vm, qubes.vm.qubesvm.QubesVM)
hashes[vm.name] = {}
for name, volume in vm.volumes.items():
if not volume.rw or not volume.save_on_stop:
continue
vol_path = vm.storage.get_pool(volume).export(volume)
hasher = hashlib.sha1()
with open(vol_path) as afile:
for buf in iter(lambda: afile.read(4096000), b''):
hasher.update(buf)
hashes[vm.name][name] = hasher.hexdigest()
return hashes
def assertCorrectlyRestored(self, orig_vms, orig_hashes):
''' Verify if restored VMs are identical to those before backup.
:param orig_vms: collection of original QubesVM objects
:param orig_hashes: result of :py:meth:`vm_checksum` on original VMs,
before backup
:return:
'''
for vm in orig_vms:
self.assertIn(vm.name, self.app.domains) self.assertIn(vm.name, self.app.domains)
restored_vm = self.app.domains[vm.name] restored_vm = self.app.domains[vm.name]
for prop in ('name', 'kernel', for prop in ('name', 'kernel',
@ -261,35 +279,50 @@ class TC_00_Backup(BackupTestsMixin, qubes.tests.QubesTestCase):
vm.name, prop)) vm.name, prop))
for dev_class in vm.devices.keys(): for dev_class in vm.devices.keys():
for dev in vm.devices[dev_class]: for dev in vm.devices[dev_class]:
self.assertIn(dev, restored_vm.devices[dev_class]) self.assertIn(dev, restored_vm.devices[dev_class],
"VM {} - {} device not restored".format(
vm.name, dev_class))
# TODO: compare disk images if orig_hashes:
hashes = self.vm_checksum([restored_vm])[restored_vm.name]
self.assertEqual(orig_hashes[vm.name], hashes,
"VM {} - disk images are not properly restored".format(
vm.name))
class TC_00_Backup(BackupTestsMixin, qubes.tests.QubesTestCase):
def test_000_basic_backup(self):
vms = self.create_backup_vms()
orig_hashes = self.vm_checksum(vms)
self.make_backup(vms)
self.remove_vms(reversed(vms))
self.restore_backup()
self.assertCorrectlyRestored(vms, orig_hashes)
self.remove_vms(reversed(vms)) self.remove_vms(reversed(vms))
def test_001_compressed_backup(self): def test_001_compressed_backup(self):
vms = self.create_backup_vms() vms = self.create_backup_vms()
orig_hashes = self.vm_checksum(vms)
self.make_backup(vms, compressed=True) self.make_backup(vms, compressed=True)
self.remove_vms(reversed(vms)) self.remove_vms(reversed(vms))
self.restore_backup() self.restore_backup()
for vm in vms: self.assertCorrectlyRestored(vms, orig_hashes)
self.assertIn(vm.name, self.app.domains)
def test_002_encrypted_backup(self): def test_002_encrypted_backup(self):
vms = self.create_backup_vms() vms = self.create_backup_vms()
orig_hashes = self.vm_checksum(vms)
self.make_backup(vms, encrypted=True) self.make_backup(vms, encrypted=True)
self.remove_vms(reversed(vms)) self.remove_vms(reversed(vms))
self.restore_backup() self.restore_backup()
for vm in vms: self.assertCorrectlyRestored(vms, orig_hashes)
self.assertIn(vm.name, self.app.domains)
def test_003_compressed_encrypted_backup(self): def test_003_compressed_encrypted_backup(self):
vms = self.create_backup_vms() vms = self.create_backup_vms()
orig_hashes = self.vm_checksum(vms)
self.make_backup(vms, compressed=True, encrypted=True) self.make_backup(vms, compressed=True, encrypted=True)
self.remove_vms(reversed(vms)) self.remove_vms(reversed(vms))
self.restore_backup() self.restore_backup()
for vm in vms: self.assertCorrectlyRestored(vms, orig_hashes)
self.assertIn(vm.name, self.app.domains)
def test_004_sparse_multipart(self): def test_004_sparse_multipart(self):
vms = [] vms = []
@ -310,21 +343,22 @@ class TC_00_Backup(BackupTestsMixin, qubes.tests.QubesTestCase):
sparse=True) sparse=True)
vms.append(hvmtemplate) vms.append(hvmtemplate)
self.app.save() self.app.save()
orig_hashes = self.vm_checksum(vms)
self.make_backup(vms) self.make_backup(vms)
self.remove_vms(reversed(vms)) self.remove_vms(reversed(vms))
self.restore_backup() self.restore_backup()
for vm in vms: self.assertCorrectlyRestored(vms, orig_hashes)
self.assertIn(vm.name, self.app.domains)
# TODO check vm.backup_timestamp # TODO check vm.backup_timestamp
def test_005_compressed_custom(self): def test_005_compressed_custom(self):
vms = self.create_backup_vms() vms = self.create_backup_vms()
orig_hashes = self.vm_checksum(vms)
self.make_backup(vms, compression_filter="bzip2") self.make_backup(vms, compression_filter="bzip2")
self.remove_vms(reversed(vms)) self.remove_vms(reversed(vms))
self.restore_backup() self.restore_backup()
for vm in vms: self.assertCorrectlyRestored(vms, orig_hashes)
self.assertIn(vm.name, self.app.domains)
def test_100_backup_dom0_no_restore(self): def test_100_backup_dom0_no_restore(self):
# do not write it into dom0 home itself... # do not write it into dom0 home itself...
@ -339,6 +373,7 @@ class TC_00_Backup(BackupTestsMixin, qubes.tests.QubesTestCase):
:return: :return:
""" """
vms = self.create_backup_vms() vms = self.create_backup_vms()
orig_hashes = self.vm_checksum(vms)
self.make_backup(vms) self.make_backup(vms)
self.remove_vms(reversed(vms)) self.remove_vms(reversed(vms))
test_dir = vms[0].dir_path test_dir = vms[0].dir_path
@ -350,6 +385,7 @@ class TC_00_Backup(BackupTestsMixin, qubes.tests.QubesTestCase):
'*** Directory {} already exists! It has been moved'.format( '*** Directory {} already exists! It has been moved'.format(
test_dir) test_dir)
]) ])
self.assertCorrectlyRestored(vms, orig_hashes)
def test_210_auto_rename(self): def test_210_auto_rename(self):
""" """