Also enable iommu for virtio controllers and video in libvirt

Ie54fca066f33 added logic to libvirt/designer.py for enabling iommu
for certain devices where virtio is used.  This is required for AMD
SEV[0].  However it missed two cases.

Firstly, a SCSI controller can have the model as 'virtio-scsi', e.g.:

    <controller type='scsi' index='0' model='virtio-scsi'>

As with other virtio devices, here a child element needs to be added
to the config when SEV is enabled:

    <driver iommu="on" />

We do not need to cover the case of a controller with type
'virtio-serial' now, since even though it is supported by libvirt, it
is not currently used anywhere in Nova.

Secondly, a video device can be virtio, e.g. when vgpus are in use:

    <video>
        <model type='virtio'/>
    </video>

Also take this opportunity to clarify the corresponding documentation
around disk bus options.

[0] http://specs.openstack.org/openstack/nova-specs/specs/train/approved/amd-sev-libvirt-support.html#proposed-change

Partial-Bug: #1845986
Change-Id: I626c35d1653e6a25125320032d0a4a0c67ab8bcf
This commit is contained in:
Boris Bobrov 2019-11-29 13:40:00 +01:00 committed by Stephen Finucane
parent 2b0024c040
commit 1a88d35cb1
5 changed files with 42 additions and 9 deletions

View File

@ -699,10 +699,12 @@ features:
__ https://wiki.qemu.org/Features/VirtioVhostUser
- The boot disk of SEV-encrypted VMs can only be ``virtio-blk`` on
newer kernels which contain the necessary fixes. Using
``virtio-scsi`` or SATA for the boot disk works as expected, as does
``virtio-blk`` for non-boot disks.
- The boot disk of SEV-encrypted VMs can only be ``virtio``.
(``virtio-blk`` is typically the default for libvirt disks on x86,
but can also be explicitly set e.g. via the image property
``hw_disk_bus=virtio``). Valid alternatives for the disk
include using ``hw_disk_bus=scsi`` with
``hw_scsi_model=virtio-scsi`` , or ``hw_disk_bus=sata``.
- QEMU and libvirt cannot yet expose the number of slots available for
encrypted guests in the memory controller on SEV hardware. Until

View File

@ -134,7 +134,7 @@ def fake_kvm_guest():
# obj.devices[6]
video = config.LibvirtConfigGuestVideo()
video.type = 'qxl'
video.type = 'virtio'
obj.add_device(video)
# obj.devices[7]
@ -150,6 +150,13 @@ def fake_kvm_guest():
rng.rate_bytes = '34'
obj.add_device(rng)
# obj.devices[9]
controller = config.LibvirtConfigGuestController()
controller.type = 'scsi'
controller.model = 'virtio-scsi' # usually set from image meta
controller.index = 0
obj.add_device(controller)
return obj
@ -225,7 +232,7 @@ FAKE_KVM_GUEST = """
<input type="mouse" bus="virtio"/>
<graphics type="vnc" autoport="yes" keymap="en_US" listen="127.0.0.1"/>
<video>
<model type='qxl'/>
<model type='virtio'/>
</video>
<serial type="file">
<source path="/tmp/vm.log"/>
@ -234,6 +241,8 @@ FAKE_KVM_GUEST = """
<rate period='12' bytes='34'/>
<backend model='random'>/dev/urandom</backend>
</rng>
<controller type='scsi' index='0' model='virtio-scsi'>
</controller>
</devices>
<launchSecurity type="sev">
<policy>0x0033</policy>

View File

@ -3276,6 +3276,18 @@ class LibvirtConfigGuestVideoTest(LibvirtConfigBaseTest):
<model type='qxl'/>
</video>""")
def test_config_video_driver_virtio(self):
obj = config.LibvirtConfigGuestVideo()
obj.type = 'virtio'
self.assertTrue(obj.uses_virtio)
xml = obj.to_xml()
self.assertXmlEqual(xml, """
<video>
<model type='virtio'/>
</video>""")
def test_config_video_driver_vram_heads(self):
obj = config.LibvirtConfigGuestVideo()
obj.type = 'qxl'
@ -3357,6 +3369,8 @@ class LibvirtConfigGuestControllerTest(LibvirtConfigBaseTest):
obj.model = 'virtio-scsi'
obj.driver_iommu = True
self.assertTrue(obj.uses_virtio)
xml = obj.to_xml()
self.assertXmlEqual(xml, """
<controller type='scsi' index='0' model='virtio-scsi'>

View File

@ -232,15 +232,15 @@ class DesignerTestCase(test.NoDBTestCase):
# All disks/interfaces/memballoon are expected to be virtio,
# thus driver_iommu should be on
self.assertEqual(9, len(conf.devices))
for i in (0, 2, 3, 8):
self.assertEqual(10, len(conf.devices))
for i in (0, 2, 3, 6, 8, 9):
dev = conf.devices[i]
self.assertTrue(
dev.driver_iommu,
"expected device %d to have driver_iommu enabled\n%s" %
(i, dev.to_xml()))
for i in (1, 4, 6):
for i in (1, 4):
dev = conf.devices[i]
self.assertFalse(
dev.driver_iommu,

View File

@ -1873,6 +1873,10 @@ class LibvirtConfigGuestVideo(LibvirtConfigGuestDevice):
self.heads = None
self.driver_iommu = False
@property
def uses_virtio(self):
return 'virtio' == self.type
def format_dom(self):
dev = super(LibvirtConfigGuestVideo, self).format_dom()
@ -1927,6 +1931,10 @@ class LibvirtConfigGuestController(LibvirtConfigGuestDevice):
self.model = None
self.driver_iommu = False
@property
def uses_virtio(self):
return 'virtio-scsi' == self.model
def format_dom(self):
controller = super(LibvirtConfigGuestController, self).format_dom()
controller.set("type", self.type)