tests: booting VM from ISO image
Check two cases: if ISO image is in dom0 and if its in a VM. QubesOS/qubes-issues#3339
This commit is contained in:
parent
96bd734852
commit
9a4d2abf1f
@ -1061,6 +1061,37 @@ class SystemTestCase(QubesTestCase):
|
||||
shutil.rmtree(mountpoint)
|
||||
subprocess.check_call(['sudo', 'losetup', '-d', loopdev])
|
||||
|
||||
def create_bootable_iso(self):
|
||||
'''Create simple bootable ISO image.
|
||||
Type 'poweroff' to it to terminate that VM.
|
||||
'''
|
||||
isolinux_cfg = (
|
||||
'prompt 1\n'
|
||||
'label poweroff\n'
|
||||
' kernel poweroff.c32\n'
|
||||
)
|
||||
output_fd, output_path = tempfile.mkstemp('.iso')
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
try:
|
||||
shutil.copy('/usr/share/syslinux/isolinux.bin', tmp_dir)
|
||||
shutil.copy('/usr/share/syslinux/ldlinux.c32', tmp_dir)
|
||||
shutil.copy('/usr/share/syslinux/poweroff.c32', tmp_dir)
|
||||
with open(os.path.join(tmp_dir, 'isolinux.cfg'), 'w') as cfg:
|
||||
cfg.write(isolinux_cfg)
|
||||
subprocess.check_call(['genisoimage', '-o', output_path,
|
||||
'-c', 'boot.cat',
|
||||
'-b', 'isolinux.bin',
|
||||
'-no-emul-boot',
|
||||
'-boot-load-size', '4',
|
||||
'-boot-info-table',
|
||||
'-q',
|
||||
tmp_dir])
|
||||
except FileNotFoundError:
|
||||
self.skipTest('syslinux or genisoimage not installed')
|
||||
os.close(output_fd)
|
||||
self.addCleanup(os.unlink, output_path)
|
||||
return output_path
|
||||
|
||||
def create_local_file(self, filename, content, mode='w'):
|
||||
with open(filename, mode) as file:
|
||||
file.write(content)
|
||||
|
@ -32,6 +32,8 @@ import unittest
|
||||
|
||||
import collections
|
||||
|
||||
import pkg_resources
|
||||
|
||||
import qubes
|
||||
import qubes.firewall
|
||||
import qubes.tests
|
||||
@ -82,6 +84,30 @@ class TC_00_Basic(qubes.tests.SystemTestCase):
|
||||
self.loop.run_until_complete(asyncio.sleep(0.1))
|
||||
self.assertTrue(flag)
|
||||
|
||||
@unittest.skipUnless(
|
||||
spawn.find_executable('xdotool'), "xdotool not installed")
|
||||
def test_120_start_standalone_with_cdrom_dom0(self):
|
||||
vmname = self.make_vm_name('appvm')
|
||||
self.vm = self.app.add_new_vm('StandaloneVM', label='red', name=vmname)
|
||||
self.loop.run_until_complete(self.vm.create_on_disk())
|
||||
self.vm.kernel = None
|
||||
|
||||
iso_path = self.create_bootable_iso()
|
||||
# start the VM using qvm-start tool, to test --cdrom option there
|
||||
p = self.loop.run_until_complete(asyncio.create_subprocess_exec(
|
||||
'qvm-start', '--cdrom=dom0:' + iso_path, self.vm.name,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||
(stdout, _) = self.loop.run_until_complete(p.communicate())
|
||||
self.assertEqual(p.returncode, 0, stdout)
|
||||
# check if VM do not crash instantly
|
||||
self.loop.run_until_complete(asyncio.sleep(5))
|
||||
self.assertTrue(self.vm.is_running())
|
||||
# Type 'poweroff'
|
||||
subprocess.check_call(['xdotool', 'search', '--name', self.vm.name,
|
||||
'type', 'poweroff\r'])
|
||||
self.loop.run_until_complete(asyncio.sleep(1))
|
||||
self.assertFalse(self.vm.is_running())
|
||||
|
||||
def _test_200_on_domain_start(self, vm, event, **_kwargs):
|
||||
'''Simulate domain crash just after startup'''
|
||||
vm.libvirt_domain.destroy()
|
||||
@ -649,6 +675,48 @@ class TC_05_StandaloneVMMixin(object):
|
||||
# some safety margin for FS metadata
|
||||
self.assertGreater(int(new_size.strip()), 19 * 1024 ** 2)
|
||||
|
||||
class TC_06_AppVMMixin(object):
|
||||
template = None
|
||||
|
||||
def setUp(self):
|
||||
super(TC_06_AppVMMixin, self).setUp()
|
||||
self.init_default_template(self.template)
|
||||
|
||||
@unittest.skipUnless(
|
||||
spawn.find_executable('xdotool'), "xdotool not installed")
|
||||
def test_121_start_standalone_with_cdrom_vm(self):
|
||||
cdrom_vmname = self.make_vm_name('cdrom')
|
||||
self.cdrom_vm = self.app.add_new_vm('AppVM', label='red',
|
||||
name=cdrom_vmname)
|
||||
self.loop.run_until_complete(self.cdrom_vm.create_on_disk())
|
||||
self.loop.run_until_complete(self.cdrom_vm.start())
|
||||
iso_path = self.create_bootable_iso()
|
||||
with open(iso_path, 'rb') as iso_f:
|
||||
self.loop.run_until_complete(
|
||||
self.cdrom_vm.run_for_stdio('cat > /home/user/boot.iso',
|
||||
stdin=iso_f))
|
||||
|
||||
vmname = self.make_vm_name('appvm')
|
||||
self.vm = self.app.add_new_vm('StandaloneVM', label='red', name=vmname)
|
||||
self.loop.run_until_complete(self.vm.create_on_disk())
|
||||
self.vm.kernel = None
|
||||
|
||||
# start the VM using qvm-start tool, to test --cdrom option there
|
||||
p = self.loop.run_until_complete(asyncio.create_subprocess_exec(
|
||||
'qvm-start', '--cdrom=' + cdrom_vmname + ':/home/user/boot.iso',
|
||||
self.vm.name,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||
(stdout, _) = self.loop.run_until_complete(p.communicate())
|
||||
self.assertEqual(p.returncode, 0, stdout)
|
||||
# check if VM do not crash instantly
|
||||
self.loop.run_until_complete(asyncio.sleep(5))
|
||||
self.assertTrue(self.vm.is_running())
|
||||
# Type 'poweroff'
|
||||
subprocess.check_call(['xdotool', 'search', '--name', self.vm.name,
|
||||
'type', 'poweroff\r'])
|
||||
self.loop.run_until_complete(asyncio.sleep(1))
|
||||
self.assertFalse(self.vm.is_running())
|
||||
|
||||
|
||||
def load_tests(loader, tests, pattern):
|
||||
for template in qubes.tests.list_templates():
|
||||
@ -657,6 +725,11 @@ def load_tests(loader, tests, pattern):
|
||||
'TC_05_StandaloneVM_' + template,
|
||||
(TC_05_StandaloneVMMixin, qubes.tests.SystemTestCase),
|
||||
{'template': template})))
|
||||
tests.addTests(loader.loadTestsFromTestCase(
|
||||
type(
|
||||
'TC_06_AppVM_' + template,
|
||||
(TC_06_AppVMMixin, qubes.tests.SystemTestCase),
|
||||
{'template': template})))
|
||||
|
||||
return tests
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user