"""A minimal OVF 1.0 descriptor for importing one converted cloud image. vSphere builds the VM from this (``OvfManager.CreateImportSpec``) and then takes the disk contents over NFC. The descriptor only has to describe what the image does not: CPU, memory, one disk and the NICs. Devices are the ones VMware recommends for a 64-bit Linux guest -- PVSCSI and VMXNET3. Both drivers are in the mainline kernel; whether every distribution's *cloud* kernel carries them is one of the things #305 checks on real hardware. """ from __future__ import annotations from xml.sax.saxutils import escape, quoteattr _HW_VERSION = "vmx-13" # ESXi 6.5 and later _GUEST_OS = "otherLinux64Guest" _STREAM_OPTIMIZED = "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" def _item(**elements: str) -> str: # CIM requires the rasd elements in alphabetical order. body = "".join(f"{escape(v)}" for k, v in sorted(elements.items())) return f"{body}" def _nic_items(nic_count: int, first_instance: int) -> str: return "".join( _item( AutomaticAllocation="true", Connection=f"net{i}", ElementName=f"Network adapter {i + 1}", InstanceID=str(first_instance + i), ResourceSubType="VmxNet3", ResourceType="10", ) for i in range(nic_count) ) def ovf_descriptor( name: str, *, cpu: int, memory_mb: int, capacity_bytes: int, nic_count: int, firmware: str = "bios", ) -> str: networks = "".join( f'net{i}' for i in range(nic_count) ) hardware = "".join( [ _item( AllocationUnits="hertz * 10^6", ElementName=f"{cpu} virtual CPU(s)", InstanceID="1", ResourceType="3", VirtualQuantity=str(cpu), ), _item( AllocationUnits="byte * 2^20", ElementName=f"{memory_mb} MB of memory", InstanceID="2", ResourceType="4", VirtualQuantity=str(memory_mb), ), _item( Address="0", ElementName="SCSI controller 0", InstanceID="3", ResourceSubType="VirtualSCSI", ResourceType="6", ), _item( AddressOnParent="0", ElementName="Hard disk 1", HostResource="ovf:/disk/vmdisk1", InstanceID="4", Parent="3", ResourceType="17", ), _nic_items(nic_count, first_instance=5), ] ) firmware_config = ( '' if firmware == "efi" else "" ) return ( '' '' '' "Virtual disks" f'' "" f"Networks{networks}" f"" "A virtual machine" f"{escape(name)}" f'Guest OS' "" "Virtual hardware" "Virtual Hardware Family" "0" f"{escape(name)}" f"{_HW_VERSION}" f"{hardware}{firmware_config}" "" "" "" )