Fix starting VM with kernel=None
When dom0 do not provide the kernel, it should also not set kernel command line in libvirt config. Otherwise qemu in stubdom fails to start because it get -append option without -kernel, which is illegal configuration. Fixes QubesOS/qubes-issues#3339
This commit is contained in:
parent
fd45378041
commit
466bf89aae
@ -28,6 +28,8 @@ import datetime
|
|||||||
import lxml.etree
|
import lxml.etree
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
|
||||||
import qubes
|
import qubes
|
||||||
import qubes.exc
|
import qubes.exc
|
||||||
import qubes.config
|
import qubes.config
|
||||||
@ -147,6 +149,7 @@ class QubesVMTestsMixin(object):
|
|||||||
super(QubesVMTestsMixin, self).setUp()
|
super(QubesVMTestsMixin, self).setUp()
|
||||||
self.app = qubes.tests.vm.TestApp()
|
self.app = qubes.tests.vm.TestApp()
|
||||||
self.app.vmm.offline_mode = True
|
self.app.vmm.offline_mode = True
|
||||||
|
self.app.default_kernel = None
|
||||||
# when full test run is called, extensions are loaded by earlier
|
# when full test run is called, extensions are loaded by earlier
|
||||||
# tests, but if just this test class is run, load them manually here,
|
# tests, but if just this test class is run, load them manually here,
|
||||||
# to have the same behaviour
|
# to have the same behaviour
|
||||||
@ -583,6 +586,14 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
|
|||||||
vm = self.get_vm(uuid=my_uuid)
|
vm = self.get_vm(uuid=my_uuid)
|
||||||
vm.netvm = None
|
vm.netvm = None
|
||||||
vm.virt_mode = 'pv'
|
vm.virt_mode = 'pv'
|
||||||
|
with unittest.mock.patch('qubes.config.qubes_base_dir',
|
||||||
|
'/tmp/qubes-test'):
|
||||||
|
kernel_dir = '/tmp/qubes-test/vm-kernels/dummy'
|
||||||
|
os.makedirs(kernel_dir, exist_ok=True)
|
||||||
|
open(os.path.join(kernel_dir, 'vmlinuz'), 'w').close()
|
||||||
|
open(os.path.join(kernel_dir, 'initramfs'), 'w').close()
|
||||||
|
self.addCleanup(shutil.rmtree, '/tmp/qubes-test')
|
||||||
|
vm.kernel = 'dummy'
|
||||||
# tests for storage are later
|
# tests for storage are later
|
||||||
vm.volumes['kernel'] = unittest.mock.Mock(**{
|
vm.volumes['kernel'] = unittest.mock.Mock(**{
|
||||||
'kernels_dir': '/tmp/kernel',
|
'kernels_dir': '/tmp/kernel',
|
||||||
@ -620,8 +631,6 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
|
|||||||
<loader type="rom">hvmloader</loader>
|
<loader type="rom">hvmloader</loader>
|
||||||
<boot dev="cdrom" />
|
<boot dev="cdrom" />
|
||||||
<boot dev="hd" />
|
<boot dev="hd" />
|
||||||
<!-- server_ip is the address of stubdomain. It hosts it's own DNS server. -->
|
|
||||||
<cmdline>root=/dev/mapper/dmroot ro nomodeset console=hvc0 rd_NO_PLYMOUTH rd.plymouth.enable=0 plymouth.enable=0 nopat</cmdline>
|
|
||||||
</os>
|
</os>
|
||||||
<features>
|
<features>
|
||||||
<pae/>
|
<pae/>
|
||||||
@ -634,6 +643,7 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
|
|||||||
<on_reboot>destroy</on_reboot>
|
<on_reboot>destroy</on_reboot>
|
||||||
<on_crash>destroy</on_crash>
|
<on_crash>destroy</on_crash>
|
||||||
<devices>
|
<devices>
|
||||||
|
<!-- server_ip is the address of stubdomain. It hosts it's own DNS server. -->
|
||||||
<emulator type="stubdom-linux" />
|
<emulator type="stubdom-linux" />
|
||||||
<input type="tablet" bus="usb"/>
|
<input type="tablet" bus="usb"/>
|
||||||
<video>
|
<video>
|
||||||
@ -651,6 +661,69 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
|
|||||||
self.assertXMLEqual(lxml.etree.XML(libvirt_xml),
|
self.assertXMLEqual(lxml.etree.XML(libvirt_xml),
|
||||||
lxml.etree.XML(expected))
|
lxml.etree.XML(expected))
|
||||||
|
|
||||||
|
def test_600_libvirt_xml_hvm_dom0_kernel(self):
|
||||||
|
expected = '''<domain type="xen">
|
||||||
|
<name>test-inst-test</name>
|
||||||
|
<uuid>7db78950-c467-4863-94d1-af59806384ea</uuid>
|
||||||
|
<memory unit="MiB">500</memory>
|
||||||
|
<currentMemory unit="MiB">400</currentMemory>
|
||||||
|
<vcpu placement="static">2</vcpu>
|
||||||
|
<cpu mode='host-passthrough'>
|
||||||
|
<!-- disable nested HVM -->
|
||||||
|
<feature name='vmx' policy='disable'/>
|
||||||
|
<feature name='svm' policy='disable'/>
|
||||||
|
<!-- disable SMAP inside VM, because of Linux bug -->
|
||||||
|
<feature name='smap' policy='disable'/>
|
||||||
|
</cpu>
|
||||||
|
<os>
|
||||||
|
<type arch="x86_64" machine="xenfv">hvm</type>
|
||||||
|
<!--
|
||||||
|
For the libxl backend libvirt switches between OVMF (UEFI)
|
||||||
|
and SeaBIOS based on the loader type. This has nothing to
|
||||||
|
do with the hvmloader binary.
|
||||||
|
-->
|
||||||
|
<loader type="rom">hvmloader</loader>
|
||||||
|
<boot dev="cdrom" />
|
||||||
|
<boot dev="hd" />
|
||||||
|
<cmdline>root=/dev/mapper/dmroot ro nomodeset console=hvc0 rd_NO_PLYMOUTH rd.plymouth.enable=0 plymouth.enable=0 nopat</cmdline>
|
||||||
|
</os>
|
||||||
|
<features>
|
||||||
|
<pae/>
|
||||||
|
<acpi/>
|
||||||
|
<apic/>
|
||||||
|
<viridian/>
|
||||||
|
</features>
|
||||||
|
<clock offset="variable" adjustment="0" basis="localtime" />
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>destroy</on_reboot>
|
||||||
|
<on_crash>destroy</on_crash>
|
||||||
|
<devices>
|
||||||
|
<!-- server_ip is the address of stubdomain. It hosts it's own DNS server. -->
|
||||||
|
<emulator type="stubdom-linux" />
|
||||||
|
<input type="tablet" bus="usb"/>
|
||||||
|
<video>
|
||||||
|
<model type="vga"/>
|
||||||
|
</video>
|
||||||
|
<graphics type="qubes"/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
||||||
|
'''
|
||||||
|
my_uuid = '7db78950-c467-4863-94d1-af59806384ea'
|
||||||
|
vm = self.get_vm(uuid=my_uuid)
|
||||||
|
vm.netvm = None
|
||||||
|
vm.virt_mode = 'hvm'
|
||||||
|
with unittest.mock.patch('qubes.config.qubes_base_dir',
|
||||||
|
'/tmp/qubes-test'):
|
||||||
|
kernel_dir = '/tmp/qubes-test/vm-kernels/dummy'
|
||||||
|
os.makedirs(kernel_dir, exist_ok=True)
|
||||||
|
open(os.path.join(kernel_dir, 'vmlinuz'), 'w').close()
|
||||||
|
open(os.path.join(kernel_dir, 'initramfs'), 'w').close()
|
||||||
|
self.addCleanup(shutil.rmtree, '/tmp/qubes-test')
|
||||||
|
vm.kernel = 'dummy'
|
||||||
|
libvirt_xml = vm.create_config_file()
|
||||||
|
self.assertXMLEqual(lxml.etree.XML(libvirt_xml),
|
||||||
|
lxml.etree.XML(expected))
|
||||||
|
|
||||||
def test_600_libvirt_xml_pvh(self):
|
def test_600_libvirt_xml_pvh(self):
|
||||||
expected = '''<domain type="xen">
|
expected = '''<domain type="xen">
|
||||||
<name>test-inst-test</name>
|
<name>test-inst-test</name>
|
||||||
@ -701,6 +774,14 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
|
|||||||
vm = self.get_vm(uuid=my_uuid)
|
vm = self.get_vm(uuid=my_uuid)
|
||||||
vm.netvm = None
|
vm.netvm = None
|
||||||
vm.virt_mode = 'pvh'
|
vm.virt_mode = 'pvh'
|
||||||
|
with unittest.mock.patch('qubes.config.qubes_base_dir',
|
||||||
|
'/tmp/qubes-test'):
|
||||||
|
kernel_dir = '/tmp/qubes-test/vm-kernels/dummy'
|
||||||
|
os.makedirs(kernel_dir, exist_ok=True)
|
||||||
|
open(os.path.join(kernel_dir, 'vmlinuz'), 'w').close()
|
||||||
|
open(os.path.join(kernel_dir, 'initramfs'), 'w').close()
|
||||||
|
self.addCleanup(shutil.rmtree, '/tmp/qubes-test')
|
||||||
|
vm.kernel = 'dummy'
|
||||||
# tests for storage are later
|
# tests for storage are later
|
||||||
vm.volumes['kernel'] = unittest.mock.Mock(**{
|
vm.volumes['kernel'] = unittest.mock.Mock(**{
|
||||||
'kernels_dir': '/tmp/kernel',
|
'kernels_dir': '/tmp/kernel',
|
||||||
@ -738,8 +819,6 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
|
|||||||
<loader type="rom">hvmloader</loader>
|
<loader type="rom">hvmloader</loader>
|
||||||
<boot dev="cdrom" />
|
<boot dev="cdrom" />
|
||||||
<boot dev="hd" />
|
<boot dev="hd" />
|
||||||
<!-- server_ip is the address of stubdomain. It hosts it's own DNS server. -->
|
|
||||||
<cmdline>root=/dev/mapper/dmroot ro nomodeset console=hvc0 rd_NO_PLYMOUTH rd.plymouth.enable=0 plymouth.enable=0 nopat</cmdline>
|
|
||||||
</os>
|
</os>
|
||||||
<features>
|
<features>
|
||||||
<pae/>
|
<pae/>
|
||||||
@ -759,6 +838,7 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
|
|||||||
<backenddomain name="test-inst-netvm" />
|
<backenddomain name="test-inst-netvm" />
|
||||||
<script path="vif-route-qubes" />
|
<script path="vif-route-qubes" />
|
||||||
</interface>
|
</interface>
|
||||||
|
<!-- server_ip is the address of stubdomain. It hosts it's own DNS server. -->
|
||||||
<emulator type="stubdom-linux" />
|
<emulator type="stubdom-linux" />
|
||||||
<input type="tablet" bus="usb"/>
|
<input type="tablet" bus="usb"/>
|
||||||
<video>
|
<video>
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
<loader type="{{ "pflash" if vm.features.check_with_template('uefi', False) else "rom" }}">hvmloader</loader>
|
<loader type="{{ "pflash" if vm.features.check_with_template('uefi', False) else "rom" }}">hvmloader</loader>
|
||||||
<boot dev="cdrom" />
|
<boot dev="cdrom" />
|
||||||
<boot dev="hd" />
|
<boot dev="hd" />
|
||||||
<!-- server_ip is the address of stubdomain. It hosts it's own DNS server. -->
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if vm.virt_mode == 'pvh' %}
|
{% if vm.virt_mode == 'pvh' %}
|
||||||
<type arch="x86_64" machine="xenfv">hvm</type>
|
<type arch="x86_64" machine="xenfv">hvm</type>
|
||||||
@ -43,7 +42,9 @@
|
|||||||
<kernel>{{ vm.storage.kernels_dir }}/vmlinuz</kernel>
|
<kernel>{{ vm.storage.kernels_dir }}/vmlinuz</kernel>
|
||||||
<initrd>{{ vm.storage.kernels_dir }}/initramfs</initrd>
|
<initrd>{{ vm.storage.kernels_dir }}/initramfs</initrd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<cmdline>root=/dev/mapper/dmroot ro nomodeset console=hvc0 rd_NO_PLYMOUTH rd.plymouth.enable=0 plymouth.enable=0 {{ vm.kernelopts }}</cmdline>
|
{% if vm.kernel %}
|
||||||
|
<cmdline>root=/dev/mapper/dmroot ro nomodeset console=hvc0 rd_NO_PLYMOUTH rd.plymouth.enable=0 plymouth.enable=0 {{ vm.kernelopts }}</cmdline>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</os>
|
</os>
|
||||||
|
|
||||||
@ -145,6 +146,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if vm.virt_mode == 'hvm' %}
|
{% if vm.virt_mode == 'hvm' %}
|
||||||
|
<!-- server_ip is the address of stubdomain. It hosts it's own DNS server. -->
|
||||||
<emulator
|
<emulator
|
||||||
{% if vm.features.check_with_template('linux-stubdom', True) %}
|
{% if vm.features.check_with_template('linux-stubdom', True) %}
|
||||||
type="stubdom-linux"
|
type="stubdom-linux"
|
||||||
|
@ -9,7 +9,8 @@ added as needed.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
class libvirtError(Exception):
|
class libvirtError(Exception):
|
||||||
pass
|
def get_error_code(self):
|
||||||
|
return VIR_ERR_NO_DOMAIN
|
||||||
|
|
||||||
class virConnect:
|
class virConnect:
|
||||||
pass
|
pass
|
||||||
@ -30,3 +31,5 @@ VIR_DOMAIN_SHUTDOWN = 4
|
|||||||
VIR_DOMAIN_SHUTOFF = 5
|
VIR_DOMAIN_SHUTOFF = 5
|
||||||
VIR_DOMAIN_CRASHED = 6
|
VIR_DOMAIN_CRASHED = 6
|
||||||
VIR_DOMAIN_PMSUSPENDED = 7
|
VIR_DOMAIN_PMSUSPENDED = 7
|
||||||
|
|
||||||
|
VIR_ERR_NO_DOMAIN = 0
|
||||||
|
Loading…
Reference in New Issue
Block a user