[virt-tools-list] [virt-install PATCH 2/7] virtinst: cli: Introduce parser support for SEV launch security

Erik Skultety eskultet at redhat.com
Thu Jun 6 10:00:40 UTC 2019


Introduce both the launchSecurity XML and parser classes. While at it,
add launchSecurity as a property instance to the Guest class too.

The parser requires the 'type' argument to be mandatory since in the
future it will determine different code paths, therefore
'--launch-security foo=bar' is incorrect.

Signed-off-by: Erik Skultety <eskultet at redhat.com>
---
 ...nstall-x86_64-launch-security-sev-full.xml | 63 +++++++++++++++++++
 tests/clitest.py                              |  5 ++
 virtinst/cli.py                               | 39 ++++++++++++
 virtinst/domain/__init__.py                   |  1 +
 virtinst/domain/launch_security.py            | 24 +++++++
 virtinst/guest.py                             |  3 +-
 6 files changed, 134 insertions(+), 1 deletion(-)
 create mode 100644 tests/cli-test-xml/compare/virt-install-x86_64-launch-security-sev-full.xml
 create mode 100644 virtinst/domain/launch_security.py

diff --git a/tests/cli-test-xml/compare/virt-install-x86_64-launch-security-sev-full.xml b/tests/cli-test-xml/compare/virt-install-x86_64-launch-security-sev-full.xml
new file mode 100644
index 00000000..5b87a621
--- /dev/null
+++ b/tests/cli-test-xml/compare/virt-install-x86_64-launch-security-sev-full.xml
@@ -0,0 +1,63 @@
+<domain type="kvm">
+  <name>foobar</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" type="pflash">/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
+    <boot dev="hd"/>
+  </os>
+  <features>
+    <acpi/>
+    <apic/>
+    <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>
+    <controller type="usb" index="0" model="ich9-ehci1"/>
+    <controller type="usb" index="0" model="ich9-uhci1">
+      <master startport="0"/>
+    </controller>
+    <controller type="usb" index="0" model="ich9-uhci2">
+      <master startport="2"/>
+    </controller>
+    <controller type="usb" index="0" model="ich9-uhci3">
+      <master startport="4"/>
+    </controller>
+    <interface type="bridge">
+      <source bridge="eth0"/>
+      <mac address="00:11:22:33:44:55"/>
+      <model type="e1000e"/>
+    </interface>
+    <console type="pty"/>
+    <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>
+  <launchSecurity type="sev">
+    <cbitpos>47</cbitpos>
+    <reducedPhysBits>1</reducedPhysBits>
+    <policy>0x0001</policy>
+    <session>BASE64SESSION</session>
+    <dhCert>BASE64CERT</dhCert>
+  </launchSecurity>
+</domain>
diff --git a/tests/clitest.py b/tests/clitest.py
index 01f76b8a..c0efabf7 100644
--- a/tests/clitest.py
+++ b/tests/clitest.py
@@ -874,6 +874,11 @@ c.add_invalid("--nodisks --boot network --arch mips --virt-type kvm")  # Invalid
 c.add_invalid("--nodisks --boot network --paravirt --arch mips")  # Invalid arch/virt combo
 c.add_invalid("--disk none --location nfs:example.com/fake --nonetworks")  # Using --location nfs, no longer supported
 
+
+c = vinst.add_category("kvm-x86_64-launch-security", "--disk none --noautoconsole")
+c.add_compare("--boot uefi --machine q35 --launch-security type=sev,reduced_phys_bits=1,policy=0x0001,cbitpos=47,dh_cert=BASE64CERT,session=BASE64SESSION --connect " + utils.URIs.kvm_amd_q35, "x86_64-launch-security-sev-full")  # Full cmdline
+c.add_invalid("--launch-security policy=0x0001 --connect " + utils.URIs.kvm_amd_q35)  # Missing launch-security 'type'
+
 c = vinst.add_category("kvm-q35", "--noautoconsole --connect " + utils.URIs.kvm_q35)
 c.add_compare("--boot uefi --disk none", "boot-uefi")
 
diff --git a/virtinst/cli.py b/virtinst/cli.py
index 7ba6b211..0a76b074 100644
--- a/virtinst/cli.py
+++ b/virtinst/cli.py
@@ -827,6 +827,12 @@ def add_guest_xml_options(geng):
                "--qemu-commandline='-display gtk,gl=on'\n"
                "--qemu-commandline env=DISPLAY=:0.1"))
 
+    ParserLaunchSecurity.register()
+    geng.add_argument("--launch-security", action="append",
+        help=_("Configure VM launch security (e.g. SEV memory encryption). Ex:\n"
+               "--launch-security type=sev,cbitpos=47,reduced_phys_bits=1,policy=0x0001,dh_cert=BASE64CERT\n"
+               "--launch-security sev"))
+
 
 def add_boot_options(insg):
     ParserBoot.register()
@@ -3832,6 +3838,39 @@ class ParserHostdev(VirtCLIParser):
         cls.add_arg("rom.bar", "rom_bar", is_onoff=True)
 
 
+#############################
+# --launch-security parsing #
+#############################
+
+class ParserLaunchSecurity(VirtCLIParser):
+    cli_arg_name = "launch_security"
+    guest_propname = "launchSecurity"
+    remove_first = "type"
+
+    @classmethod
+    def _init_class(cls, **kwargs):
+        VirtCLIParser._init_class(**kwargs)
+        cls.add_arg("type", "type_")
+        cls.add_arg("cbitpos", "cbitpos")
+        cls.add_arg("reduced_phys_bits", "reduced_phys_bits")
+        cls.add_arg("policy", "policy")
+        cls.add_arg("session", "session")
+        cls.add_arg("dh_cert", "dh_cert")
+
+    def _check_required_opts(self):
+        type_ = self.optdict.get("type", None)
+
+        if not type_:
+            fail(_("Missing mandatory attribute 'type' for --launch-security"))
+
+    def _parse(self, inst):
+        if not inst.conn.is_qemu():
+            logging.warning("--launch-security is only supported with QEMU")
+
+        self._check_required_opts()
+        return super()._parse(inst)
+
+
 ###########################
 # Public virt parser APIs #
 ###########################
diff --git a/virtinst/domain/__init__.py b/virtinst/domain/__init__.py
index f942ee59..b7157c9c 100644
--- a/virtinst/domain/__init__.py
+++ b/virtinst/domain/__init__.py
@@ -19,5 +19,6 @@ from .seclabel import DomainSeclabel
 from .sysinfo import DomainSysinfo
 from .vcpus import DomainVCPUs
 from .xmlnsqemu import DomainXMLNSQemu
+from .launch_security import DomainLaunchSecurity
 
 __all__ = [l for l in locals() if l.startswith("Domain")]
diff --git a/virtinst/domain/launch_security.py b/virtinst/domain/launch_security.py
new file mode 100644
index 00000000..a911712c
--- /dev/null
+++ b/virtinst/domain/launch_security.py
@@ -0,0 +1,24 @@
+from ..xmlbuilder import XMLBuilder, XMLProperty
+
+
+class DomainLaunchSecurity(XMLBuilder):
+    """
+    Class for generating <launchSecurity> XML element
+    """
+
+    XML_NAME = "launchSecurity"
+    _XML_PROP_ORDER = ["type_", "cbitpos", "reduced_phys_bits", "policy",
+            "session", "dh_cert"]
+
+    type_ = XMLProperty("./@type")
+    cbitpos = XMLProperty("./cbitpos", is_int=True)
+    reduced_phys_bits = XMLProperty("./reducedPhysBits", is_int=True)
+    policy = XMLProperty("./policy")
+    session = XMLProperty("./session")
+    dh_cert = XMLProperty("./dhCert")
+
+    def enabled(self):
+        return self.type_ is not None
+
+    def is_sev(self):
+        return self.type_ == "sev"
diff --git a/virtinst/guest.py b/virtinst/guest.py
index 98893fa6..474afc7a 100644
--- a/virtinst/guest.py
+++ b/virtinst/guest.py
@@ -159,7 +159,7 @@ class Guest(XMLBuilder):
         "vcpu_cpuset", "vcpulist", "numatune", "resource", "sysinfo",
         "bootloader", "os", "idmap", "features", "cpu", "clock",
         "on_poweroff", "on_reboot", "on_crash",
-        "pm", "emulator", "devices", "seclabels"]
+        "pm", "emulator", "devices", "launchSecurity", "seclabels"]
 
     def __init__(self, *args, **kwargs):
         XMLBuilder.__init__(self, *args, **kwargs)
@@ -250,6 +250,7 @@ class Guest(XMLBuilder):
     idmap = XMLChildProperty(DomainIdmap, is_single=True)
     resource = XMLChildProperty(DomainResource, is_single=True)
     sysinfo = XMLChildProperty(DomainSysinfo, is_single=True)
+    launchSecurity = XMLChildProperty(DomainLaunchSecurity, is_single=True)
     _metadata = XMLChildProperty(DomainMetadata, is_single=True)
 
     xmlns_qemu = XMLChildProperty(DomainXMLNSQemu, is_single=True)
-- 
2.20.1




More information about the virt-tools-list mailing list