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@xxxxxxxxxx> --- ...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 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list