Skip to content

Commit 5b02db6

Browse files
committed
tests: add a test for no-revisions volume
This tests if volume works, but more importantly if all "unsafe" operations are blocked when its VM is running: - cloning to another volume - using as a source volume for snapshot The test has also commented out part about a backup - but that currently is blocked in the backup code directly. QubesOS/qubes-issues#8767
1 parent bc20def commit 5b02db6

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

qubes/tests/integ/storage.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,112 @@ async def _test_005_size_after_clone(self):
379379
await qubes.utils.coro_maybe(testvol2.import_volume(testvol))
380380
self.assertEqual(testvol2.size, size)
381381

382+
def test_006_no_revisions(self):
383+
"""Test if no-revisions volume persists data, and blocks parallel
384+
access"""
385+
return self.loop.run_until_complete(self._test_006_no_revisions())
386+
387+
async def _test_006_no_revisions(self):
388+
self.vm1.storage.set_revisions_to_keep("private", -1)
389+
dir_path = "/var/tmp/test-pool2"
390+
pool2 = await self.app.add_pool(
391+
dir_path=dir_path, name="test-pool2", driver="file"
392+
)
393+
self.addCleanup(shutil.rmtree, dir_path)
394+
395+
size = 32 * 1024 * 1024
396+
volume_config = {
397+
"pool": self.pool.name,
398+
"size": size,
399+
"save_on_stop": True,
400+
"rw": True,
401+
"revisions_to_keep": -1,
402+
}
403+
testvol = self.vm1.storage.init_volume("testvol", volume_config)
404+
await qubes.utils.coro_maybe(testvol.create())
405+
volume2_config = {
406+
"pool": self.pool.name,
407+
"size": size,
408+
"snap_on_start": True,
409+
"source": testvol.vid,
410+
"rw": True,
411+
}
412+
testvol2 = self.vm2.storage.init_volume("testvol2", volume2_config)
413+
await qubes.utils.coro_maybe(testvol2.create())
414+
del testvol
415+
del testvol2
416+
417+
volume3_config = {
418+
"pool": pool2.name,
419+
"size": size,
420+
"save_on_stop": True,
421+
"rw": True,
422+
}
423+
testvol3 = self.vm2.storage.init_volume("testvol3", volume3_config)
424+
await qubes.utils.coro_maybe(testvol3.create())
425+
426+
self.app.save()
427+
await self.vm1.start()
428+
await self.wait_for_session(self.vm1)
429+
# non-volatile image not clean
430+
await self.vm1.run_for_stdio(
431+
"head -c {} /dev/zero 2>&1 | diff -q /dev/xvde - 2>&1".format(size),
432+
user="root",
433+
)
434+
435+
await self.vm1.run_for_stdio("echo test123 > /dev/xvde", user="root")
436+
await self.vm1.shutdown(wait=True)
437+
await self.vm1.start()
438+
# non-volatile image volatile
439+
with self.assertRaises(subprocess.CalledProcessError):
440+
await self.vm1.run_for_stdio(
441+
"head -c {} /dev/zero 2>&1 | diff -q /dev/xvde - 2>&1".format(
442+
size
443+
),
444+
user="root",
445+
)
446+
447+
# should not work
448+
with self.assertRaises(qubes.exc.QubesException):
449+
await self.vm2.start()
450+
# clone within the same pool
451+
with self.assertRaises(qubes.exc.QubesException):
452+
await self.vm2.storage.import_volume(
453+
self.vm2.storage.get_volume("private"),
454+
self.vm1.storage.get_volume("private"),
455+
)
456+
# clone to a different pool
457+
with self.assertRaises(qubes.exc.QubesException):
458+
await self.vm2.storage.import_volume(
459+
self.vm2.storage.get_volume("testvol3"),
460+
self.vm1.storage.get_volume("testvol"),
461+
)
462+
# export is not blocked explicitly now, but its uses are (cross-pool
463+
# clone, backup)
464+
# with self.assertRaises(qubes.exc.QubesException):
465+
# path = await self.vm1.storage.export("testvol")
466+
# # just in case it was allowed...
467+
# await self.vm1.storage.export_end("testvol", path)
468+
469+
# now shutdown vm1 and the above operations should work
470+
await self.vm1.shutdown(wait=True)
471+
await self.vm2.storage.import_volume(
472+
self.vm2.storage.get_volume("private"),
473+
self.vm1.storage.get_volume("private"),
474+
)
475+
await self.vm2.storage.import_volume(
476+
self.vm2.storage.get_volume("testvol3"),
477+
self.vm1.storage.get_volume("testvol"),
478+
)
479+
path = await self.vm1.storage.export("testvol")
480+
await self.vm1.storage.export_end("testvol", path)
481+
482+
await self.vm2.start()
483+
stdout, stderr = await self.vm2.run_for_stdio(
484+
"head -c 7 /dev/xvde", user="root"
485+
)
486+
self.assertEqual(stdout, b"test123")
487+
382488

383489
class StorageFile(StorageTestMixin, qubes.tests.SystemTestCase):
384490
def init_pool(self):

0 commit comments

Comments
 (0)