o
    b6                     @   sB  d dl Z d dlm  mZ d dlZddlmZ ddlm	Z	 ddl
mZmZmZ G dd deZG dd	 d	eZG d
d deZG dd deZdd ZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZd d! Zd"d# Zd$d% ZG d&d' d'eZdS )(    N   )	DomainCpu)log)
XMLBuilderXMLChildPropertyXMLPropertyc                   @      e Zd ZdZedZdS )_Valuevalue.N)__name__
__module____qualname__XML_NAMEr   r
    r   r   3/usr/share/virt-manager/virtinst/domcapabilities.pyr	          r	   c                   @   s$   e Zd ZeeZdd Zdd ZdS )
_HasValuesc                 C      dd | j D S )Nc                 S      g | ]}|j qS r   r
   ).0vr   r   r   
<listcomp>        z)_HasValues.get_values.<locals>.<listcomp>)valuesselfr   r   r   
get_values      z_HasValues.get_valuesc                 C      ||   v S N)r   )r   valr   r   r   	has_value"      z_HasValues.has_valueN)r   r   r   r   r	   r   r   r#   r   r   r   r   r      s    r   c                   @   r   )_Enumenum./@nameN)r   r   r   r   r   namer   r   r   r   r%   &   r   r%   c                   @   sL   e Zd ZedddZedZeeZe	dd Z
dd Zdd	 Zd
d ZdS )
_CapsBlock./@supportedTis_yesnoc                 C   s
   | j d uS r!   )_supported_presentr   r   r   r   present0   s   
z_CapsBlock.presentc                 C   r   )Nc                 S   r   r   )r(   )r   er   r   r   r   5   r   z)_CapsBlock.enum_names.<locals>.<listcomp>)enumsr   r   r   r   
enum_names4   r   z_CapsBlock.enum_namesc                 C   r    r!   )r1   )r   r(   r   r   r   has_enum7   r$   z_CapsBlock.has_enumc                 C   s(   | j D ]}|j|kr|  S qt| jS r!   )r0   r(   r%   conn)r   r(   r&   r   r   r   get_enum:   s
   


z_CapsBlock.get_enumN)r   r   r   r   	supportedr-   r   r%   r0   propertyr.   r1   r2   r4   r   r   r   r   r)   +   s    
r)   c                 C   s    G dd dt }t|d|  |S )a  
    Build a class object representing a list of <enum> in the XML. For
    example, domcapabilities may have a block like:

    <graphics supported='yes'>
      <enum name='type'>
        <value>sdl</value>
        <value>vnc</value>
        <value>spice</value>
      </enum>
    </graphics>

    To build a class that tracks that whole <graphics> block, call this
    like _make_capsblock("graphics")
    c                   @   s   e Zd ZdS )z!_make_capsblock.<locals>.TmpClassN)r   r   r   r   r   r   r   TmpClassS   s    r7   r   )r)   setattr)xml_root_namer7   r   r   r   _make_capsblockC   s   r:   c                   @   s   e Zd ZdZedddZdS )_SEVsevr*   Tr+   N)r   r   r   r   r   r5   r   r   r   r   r;   ]   s    r;   c                   @   s    e Zd ZdZeedddZdS )_OSosloaderT	is_singleN)r   r   r   r   r   r:   r?   r   r   r   r   r=   f   s    r=   c                   @   sp   e Zd ZdZeedddZeedddZeedddZeedddZ	eedddZ
eed	ddZd
S )_DevicesdeviceshostdevTr@   diskvideographicstpm
filesystemN)r   r   r   r   r   r:   rD   rE   rF   rG   rH   rI   r   r   r   r   rB   k   s    rB   c                   @   s,   e Zd ZdZeedddZeeddZdS )	_FeaturesfeaturesgicTr@   N)	r   r   r   r   r   r:   rL   r;   r<   r   r   r   r   rJ   u   s    rJ   c                   @   s   e Zd ZdZdS )_MemoryBackingmemoryBackingN)r   r   r   r   r   r   r   r   rM   {   s    rM   c                   @   s(   e Zd ZdZedZedZedZdS )	_CPUModelmodelr   z	./@usablez./@fallbackN)r   r   r   r   r   rP   usablefallbackr   r   r   r   rO      s
    rO   c                   @   s(   e Zd ZdZedZeeZdd Z	dS )_CPUModemoder'   c                 C   "   | j D ]}|j|kr|  S qd S r!   )modelsrP   )r   r(   rP   r   r   r   	get_model   
   

z_CPUMode.get_modelN)
r   r   r   r   r   r(   r   rO   rV   rW   r   r   r   r   rS      s
    rS   c                   @   s    e Zd ZdZeeZdd ZdS )_CPUcpuc                 C   rU   r!   )modesr(   )r   r(   rT   r   r   r   get_mode   rX   z_CPU.get_modeN)r   r   r   r   r   rS   r[   r\   r   r   r   r   rY      s    rY   c                 C   s6   t | }d|_i |_t |d}||_t j|ddS )NrZ   archunicode)encoding)ET
fromstringtagattrib
SubElementtexttostring)xmlr]   rootaelementr   r   r   _convert_mode_to_cpu   s   
rj   c              	   C   sz   t | | j}td| z| j| j| j| j| j	|gt
j}W n t
jtfy6   | j|gt
j}Y nw t| j|S )Nz0Generated CPU XML for security flag baseline:
%s)rj   get_xmlr]   r   debugr3   baselineHypervisorCPUpathmachinedomainlibvirt(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURESlibvirtErrorAttributeErrorbaselineCPUr   )domcapsrT   cpuXMLexpandedXMLr   r   r   _get_expanded_cpu   s   
ry   c                 C   s   g }g d}| j jD ]@}|jdks|jsq
zt| |}W n tjy8 } ztt	d| W Y d }~ nd }~ww |j
D ]}|j|v rI||j q<q
td| |S )N)z	spec-ctrlssbdibpbz	virt-ssbdzmd-clear
host-modelz"Failed to get expanded CPU XML: %sz&Found host-model security features: %s)rZ   r[   r(   r5   ry   rq   rs   r   warning_rK   appendrl   )rv   retsec_featuresmrZ   r/   featurer   r   r   _lookup_cpu_security_features   s&   

r   c                   @   s.  e Zd ZdZeeddZeeddZee	ddZ
eeddZeeddZedZedZedZedZedd	 Zed
d Zddgg dg dg ddZdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"Z d#d$ Z!d%d& Z"d'd( Z#d)d* Z$d+d, Z%d-d. Z&d/d0 Z'd1d2 Z(d3d4 Z)d"S )5DomainCapabilitiesdomainCapabilitiesTr@   z./archz./domainz	./machinez./pathc                 C   s\   d }| j  r"z
| ||||}W n ty!   tjddd Y nw |s(t| S t| |dS )Nz"Error fetching domcapabilities XMLT)exc_info)parsexml)supportconn_domain_capabilitiesgetDomainCapabilities	Exceptionr   rl   r   )r3   emulatorr]   ro   hvtyperg   r   r   r   build_from_params   s   

z$DomainCapabilities.build_from_paramsc                 C   s    t | j| j| jj| jj| jS r!   )r   r   r3   r   r>   r]   ro   type)guestr   r   r   build_from_guest   s   z#DomainCapabilities.build_from_guestz.*edk2-i386-.*\.fdz.*ovmf-ia32.*)z.*edk2-x86_64-.*\.fdz.*OVMF_CODE\.fdz.*ovmf-x64/OVMF.*\.fdz.*ovmf-x86_64-.*z.*ovmf.*z.*OVMF.*)z.*AAVMF_CODE\.fdz.*aarch64/QEMU_EFI.*z.*aarch64.*z.*edk2-aarch64-code\.fd)z.*AAVMF32_CODE\.fdz.*arm/QEMU_EFI.*z.*edk2-arm-code\.fd)i686x86_64aarch64armv7lc                 C   s   |   sdS dd | jjjD }| j r*|D ]
}d|v r!|  S q|r(|d p)dS | j| j}|D ]}|D ]}t	
||rE|    S q7q3dS )zN
        Search the loader paths for one that matches the passed arch
        Nc                 S   r   r   r   )r   fr   r   r   r   *  r   z>DomainCapabilities.find_uefi_path_for_arch.<locals>.<listcomp>zBHYVE_UEFI.fdr   )arch_can_uefir>   r?   r   r3   is_bhyve_uefi_arch_patternsgetr]   rematch)r   firmware_filesfirmware_filepatternspatternrn   r   r   r   find_uefi_path_for_arch#  s*   
z*DomainCapabilities.find_uefi_path_for_archc                 C   sr   |s| j dv rtdS tdS | j D ]\}}|D ]}t||r/td||d     S qqtdd|i S )zd
        Return a pretty label for passed path, based on if we know
        about it or not
        r   r   BIOSDefaultzUEFI %(arch)s: %(path)s)r]   rn   zCustom: %(path)srn   )r]   r~   r   itemsr   r   )r   rn   r]   r   r   r   r   r   label_for_firmware_path8  s   
z*DomainCapabilities.label_for_firmware_pathc                 C   s   | j t| j v S )zN
        Return True if we know how to setup UEFI for the passed arch
        )r]   listr   keysr   r   r   r   r   J     z DomainCapabilities.arch_can_uefic                 C      | j jddS )zK
        Return True if libvirt advertises support for UEFI loader
        readonlyyes)r>   r?   r4   r#   r   r   r   r   supports_uefi_loaderP  r   z'DomainCapabilities.supports_uefi_loaderc                 C      | j ddS )Nfirmwareefi)r>   r4   r#   r   r   r   r   supports_firmware_efiV  s   z(DomainCapabilities.supports_firmware_efic                 C   s&   | j d}|o|jo|jd jdkS )z
        Return True if domcaps reports support for cpu mode=host-model.
        host-model in fact predates this support, however it wasn't
        general purpose safe prior to domcaps advertisement.
        r|   r   forbid)rZ   r\   r5   rV   rR   r   r   r   r   r   supports_safe_host_model^  s   
z+DomainCapabilities.supports_safe_host_modelc                 C   s(   | j d}|o|jod|d v S )a$  
        Return True if host-passthrough is safe enough to use by default.
        We limit this to domcaps new enough to report whether host-passthrough
        is migratable or not, which also means libvirt is about new enough
        to not taint the VM for using host-passthrough
        zhost-passthroughonhostPassthroughMigratable)rZ   r\   r5   r4   r   r   r   r   r   supports_safe_host_passthroughh  s   
z1DomainCapabilities.supports_safe_host_passthroughc                 C   sH   g }| j jD ]}|jdkr!|jr!|jD ]}|jdkr ||j qq|S )Ncustomno)rZ   r[   r(   r5   rV   rQ   r   rP   )r   rV   r   rP   r   r   r   get_cpu_modelss  s   

z!DomainCapabilities.get_cpu_modelsNc                 C   s   | j d u rt| p
g | _ | j S r!   )	_featuresr   r   r   r   r   get_cpu_security_features  s   
z,DomainCapabilities.get_cpu_security_featuresc                 C   s   t | jjjS )z
        Returns False if either libvirt doesn't advertise support for SEV at
        all (< libvirt-4.5.0) or if it explicitly advertises it as unsupported
        on the platform
        )boolrK   r<   r5   r   r   r   r   supports_sev_launch_security  s   z/DomainCapabilities.supports_sev_launch_securityc                 C   r   )zj
        Returns False if either libvirt or qemu do not have support to bochs
        video type.
        	modelTypebochsrC   rF   r4   r#   r   r   r   r   supports_video_bochs  s   z'DomainCapabilities.supports_video_bochsc                 C   s*   | j jds|  S | j jddS )Nr   qxl)rC   rF   r2   supports_graphics_spicer4   r#   r   r   r   r   supports_video_qxl  s   z%DomainCapabilities.supports_video_qxlc                 C   r   )Nr   virtior   r   r   r   r   supports_video_virtio  s   z(DomainCapabilities.supports_video_virtioc                 C   s<   | j jd }| j jd }t|dkotd|v S )zj
        Returns False if either libvirt or qemu do not have support for
        emulating a TPM.
        rP   backendModelr   r   )rC   rH   r4   r   lenr   )r   rV   backendsr   r   r   supports_tpm_emulator  s   z(DomainCapabilities.supports_tpm_emulatorc                 C   sH   | j jjs| j s| j sdS | jjjjj	dv S | j j
ddS )NFr   r   spice)rC   rG   r5   r3   is_qemuis_testcapshostrZ   r]   r4   r#   r   r   r   r   r     s
   
z*DomainCapabilities.supports_graphics_spicec                 C   r   )zH
        Return True if libvirt advertises support for virtiofs
        
driverTypevirtiofs)rC   rI   r4   r#   r   r   r   r   supports_filesystem_virtiofs  s
   z/DomainCapabilities.supports_filesystem_virtiofsc                 C   r   )zT
        Return True if libvirt advertises support for memfd memory backend
        
sourceTypememfd)memorybackingr4   r#   r   r   r   r   supports_memorybacking_memfd  s   z/DomainCapabilities.supports_memorybacking_memfd)*r   r   r   r   r   r=   r>   rY   rZ   rB   rC   rJ   rK   rM   r   r   r]   rp   ro   rn   staticmethodr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      sP    



	
r   )r   xml.etree.ElementTreeetreeElementTreer`   rq   rp   r   loggerr   
xmlbuilderr   r   r   r	   r   r%   r)   r:   r;   r=   rB   rJ   rM   rO   rS   rY   rj   ry   r   r   r   r   r   r   <module>   s.   
	
	