summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrangé <berrange@redhat.com>2021-11-24 16:05:16 +0000
committerCole Robinson <crobinso@redhat.com>2022-01-21 17:49:15 -0500
commiteb58c09f488b0633ed1eea012cd311e48864401e (patch)
tree5cd8cda9b16d3c0c1198feedd234a7676954a952
parent7e1f886aa990ee462962b264cb412b749a23a9cb (diff)
downloadvirt-manager-master.tar.gz
virtinst/guest: enable a TPM by default if UEFI is presentmaster
The bare metal world is moving to a situation where UEFI is going to be the only supported firmware and there will be a strong expectation for TPM and SecureBoot support. With this in mind, if we're enabling UEFI on a VM, it makes sense to also provide a TPM alongside it. Since this requires swtpm to be installed we can't do this unconditionally. The forthcoming libvirt release expands the domain capabilities to report whether TPMs are supported, so we check that. The user can disable the default TPM by requesting --tpm none https://github.com/virt-manager/virt-manager/issues/310 Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
-rw-r--r--tests/data/capabilities/kvm-x86_64-domcaps-q35.xml10
-rw-r--r--tests/data/cli/compare/virt-install-boot-uefi-notpm.xml65
-rw-r--r--tests/data/cli/compare/virt-install-boot-uefi.xml3
-rw-r--r--tests/test_cli.py1
-rw-r--r--virtinst/cli.py5
-rw-r--r--virtinst/domcapabilities.py10
-rw-r--r--virtinst/guest.py21
7 files changed, 115 insertions, 0 deletions
diff --git a/tests/data/capabilities/kvm-x86_64-domcaps-q35.xml b/tests/data/capabilities/kvm-x86_64-domcaps-q35.xml
index b4300cfa..b66e2eb5 100644
--- a/tests/data/capabilities/kvm-x86_64-domcaps-q35.xml
+++ b/tests/data/capabilities/kvm-x86_64-domcaps-q35.xml
@@ -118,6 +118,16 @@
<value>vfio</value>
</enum>
</hostdev>
+ <tpm supported='yes'>
+ <enum name='model'>
+ <value>tpm-tis</value>
+ <value>tpm-crb</value>
+ </enum>
+ <enum name='backendModel'>
+ <value>passthrough</value>
+ <value>emulator</value>
+ </enum>
+ </tpm>
</devices>
<features>
<gic supported='no'/>
diff --git a/tests/data/cli/compare/virt-install-boot-uefi-notpm.xml b/tests/data/cli/compare/virt-install-boot-uefi-notpm.xml
new file mode 100644
index 00000000..301b09cc
--- /dev/null
+++ b/tests/data/cli/compare/virt-install-boot-uefi-notpm.xml
@@ -0,0 +1,65 @@
+<domain type="kvm">
+ <name>vm1</name>
+ <uuid>00000000-1111-2222-3333-444444444444</uuid>
+ <memory>65536</memory>
+ <currentMemory>65536</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch="x86_64" machine="q35">hvm</type>
+ <loader readonly="yes" secure="yes" type="pflash">/usr/share/ovmf/OVMF_CODE.secboot.fd</loader>
+ <boot dev="hd"/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <smm state="on"/>
+ <vmport state="off"/>
+ </features>
+ <cpu mode="host-model"/>
+ <clock offset="utc">
+ <timer name="rtc" tickpolicy="catchup"/>
+ <timer name="pit" tickpolicy="delay"/>
+ <timer name="hpet" present="no"/>
+ </clock>
+ <pm>
+ <suspend-to-mem enabled="no"/>
+ <suspend-to-disk enabled="no"/>
+ </pm>
+ <devices>
+ <emulator>/usr/bin/qemu-kvm</emulator>
+ <disk type="file" device="disk">
+ <driver name="qemu" type="qcow2"/>
+ <source file="/var/lib/libvirt/images/disk.qcow2"/>
+ <target dev="sda" bus="sata"/>
+ </disk>
+ <controller type="usb" model="ich9-ehci1"/>
+ <controller type="usb" model="ich9-uhci1">
+ <master startport="0"/>
+ </controller>
+ <controller type="usb" model="ich9-uhci2">
+ <master startport="2"/>
+ </controller>
+ <controller type="usb" model="ich9-uhci3">
+ <master startport="4"/>
+ </controller>
+ <interface type="bridge">
+ <source bridge="testsuitebr0"/>
+ <mac address="00:11:22:33:44:55"/>
+ <model type="e1000e"/>
+ </interface>
+ <console type="pty"/>
+ <channel type="spicevmc">
+ <target type="virtio" name="com.redhat.spice.0"/>
+ </channel>
+ <input type="tablet" bus="usb"/>
+ <graphics type="spice" port="-1" tlsPort="-1" autoport="yes">
+ <image compression="off"/>
+ </graphics>
+ <sound model="ich9"/>
+ <video>
+ <model type="qxl"/>
+ </video>
+ <redirdev bus="usb" type="spicevmc"/>
+ <redirdev bus="usb" type="spicevmc"/>
+ </devices>
+</domain>
diff --git a/tests/data/cli/compare/virt-install-boot-uefi.xml b/tests/data/cli/compare/virt-install-boot-uefi.xml
index 83e5c1dd..b598ddd0 100644
--- a/tests/data/cli/compare/virt-install-boot-uefi.xml
+++ b/tests/data/cli/compare/virt-install-boot-uefi.xml
@@ -47,6 +47,9 @@
<target type="virtio" name="com.redhat.spice.0"/>
</channel>
<input type="tablet" bus="usb"/>
+ <tpm model="tpm-tis">
+ <backend type="emulator"/>
+ </tpm>
<graphics type="spice" port="-1" tlsPort="-1" autoport="yes">
<image compression="off"/>
</graphics>
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 4d9070c2..996588c0 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -1076,6 +1076,7 @@ c.add_invalid("--boot uefi --machine q35 --launchSecurity sev,policy=0x0001 --co
c = vinst.add_category("kvm-q35", "--noautoconsole --connect " + utils.URIs.kvm_q35)
c.add_compare("--boot uefi --disk none", "boot-uefi")
+c.add_compare("--boot uefi --disk size=8 --tpm none", "boot-uefi-notpm")
c = vinst.add_category("kvm-arm", "--connect %(URI-KVM)s --noautoconsole", precompare_check="3.3.0") # required qemu-xhci from libvirt 3.3.0
diff --git a/virtinst/cli.py b/virtinst/cli.py
index 480e0b1e..681d5b87 100644
--- a/virtinst/cli.py
+++ b/virtinst/cli.py
@@ -4079,6 +4079,7 @@ class ParserTPM(VirtCLIParser):
cli_arg_name = "tpm"
guest_propname = "devices.tpm"
remove_first = "type"
+ stub_none = False
aliases = {
"backend.type": "type",
"backend.version": "version",
@@ -4086,6 +4087,10 @@ class ParserTPM(VirtCLIParser):
}
def _parse(self, inst):
+ if self.optstr == "none":
+ self.guest.skip_default_tpm = True
+ return
+
if (self.optdict.get("type", "").startswith("/")):
self.optdict["path"] = self.optdict.pop("type")
return super()._parse(inst)
diff --git a/virtinst/domcapabilities.py b/virtinst/domcapabilities.py
index 8a6ac66c..be4829d9 100644
--- a/virtinst/domcapabilities.py
+++ b/virtinst/domcapabilities.py
@@ -101,6 +101,7 @@ class _Devices(_CapsBlock):
disk = XMLChildProperty(_make_capsblock("disk"), is_single=True)
video = XMLChildProperty(_make_capsblock("video"), is_single=True)
graphics = XMLChildProperty(_make_capsblock("graphics"), is_single=True)
+ tpm = XMLChildProperty(_make_capsblock("tpm"), is_single=True)
class _Features(_CapsBlock):
@@ -351,6 +352,15 @@ class DomainCapabilities(XMLBuilder):
models = self.devices.video.get_enum("modelType").get_values()
return bool("bochs" in models)
+ def supports_tpm_emulator(self):
+ """
+ Returns False if either libvirt or qemu do not have support for
+ emulating a TPM.
+ """
+ models = self.devices.tpm.get_enum("model").get_values()
+ backends = self.devices.tpm.get_enum("backendModel").get_values()
+ return len(models) > 0 and bool("emulator" in backends)
+
def supports_graphics_spice(self):
if not self.devices.graphics.supported:
# domcaps is too old, or the driver doesn't advertise graphics
diff --git a/virtinst/guest.py b/virtinst/guest.py
index f11a105e..4e767dd0 100644
--- a/virtinst/guest.py
+++ b/virtinst/guest.py
@@ -199,6 +199,7 @@ class Guest(XMLBuilder):
self.skip_default_usbredir = False
self.skip_default_graphics = False
self.skip_default_rng = False
+ self.skip_default_tpm = False
self.x86_cpu_default = self.cpu.SPECIAL_MODE_APP_DEFAULT
self.skip_default_osinfo = False
@@ -724,6 +725,11 @@ class Guest(XMLBuilder):
self._add_default_channels()
self._add_default_rng()
self._add_default_memballoon()
+ if self.is_uefi():
+ # If the guest is using UEFI, we take that as a
+ # flag that the VM is targeting a modern platform
+ # and thus we should also provide an emulated TPM.
+ self._add_default_tpm()
self.clock.set_defaults(self)
self.cpu.set_defaults(self)
@@ -947,6 +953,21 @@ class Guest(XMLBuilder):
dev.device = "/dev/urandom"
self.add_device(dev)
+ def _add_default_tpm(self):
+ if self.skip_default_tpm:
+ return
+ if self.devices.tpm:
+ return
+
+ if not self.lookup_domcaps().supports_tpm_emulator():
+ log.debug("Domain caps doesn't report TPM support")
+ return
+
+ log.debug("Adding default TPM")
+ dev = DeviceTpm(self.conn)
+ dev.type = DeviceTpm.TYPE_EMULATOR
+ self.add_device(dev)
+
def _add_default_memballoon(self):
if self.devices.memballoon:
return