HEX
Server: Apache
System: Linux server2.voipitup.com.au 4.18.0-553.104.1.lve.el8.x86_64 #1 SMP Tue Feb 10 20:07:30 UTC 2026 x86_64
User: posscale (1027)
PHP: 8.2.29
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/__pycache__/virt.cpython-310.pyc
o

�N�g<~�@s2	dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
ZddlmZddlmZddlZddlZddlZddlZddlZddlZddlZddlZddlmmZddl Zddl!m"Z"ddl#m$Z$m%Z%zddl&Z&ddl&m'Z'dZ(Wne)y�d	Z(Ynwe�*e+�Z,ej-e�.ej/�0ejj1j2d
��d�Z3dZ4d
d
d
ddddd�Z5dd�Z6dd�Z7dd�Z8dd�Z9dd�Z:dd�Z;dd�Z<d d!�Z=d"d#�Z>d$d%�Z?d&d'�Z@d(d)�ZAd*d+�ZBd,d-�ZCd.d/�ZDd0d1�ZEd2d3�ZF�ded5d6�ZG�dfd7d8�ZH											�dgd9d:�ZI							�dhd;d<�ZJ									�did=d>�ZK										�djd?d@�ZLdAdB�ZMdCdD�ZNdEdF�ZO�dkdHdI�ZPdJdK�ZQ�dldLdM�ZRdNdO�ZSdPdQ�ZTdRdS�ZUdTdU�ZV�dfdVdW�ZWdXdY�ZXdZd[�ZY	\				\		G					]													�dmd^d_�ZZd`da�Z[dbdc�Z\ddde�Z]dfdg�Z^dhdi�Z_djdk�Z`dldm�Zadndo�Zbdpdq�Zcdrds�Zddtdu�Zedvdw�Zfdxdy�Zgdzd{�Zhd|d}�Zid~d�Zjd�d��Zkd�d��Zld�d��Zmd�d��Znd�d��Zo																						�dnd�d��Zpd�d��Zqd�d��Zrd�d��Zs�dfd�d��Zt�dfd�d��Zud�d��Zvd�d��Zwd�d��Zxd�d��Zyd�d��Zzd�d��Z{d�d��Z|d�d��Z}d�d��Z~�dod�d��Z�dod�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z��dfd�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�dʄZ�d�d̄Z�d�d΄Z�d�dЄZ��dfd�d҄Z�	�dfd�dԄZ��dfd�dքZ�d�d؄Z�d�dڄZ��dod�d܄Z��dpd�d߄Z�d�d�Z��dqd�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z�d�d�Z��dfd�d�Z��dfd�d�Z��dfd�d��Z��dod�d��Z��dfd�d��Z��drd�d��Z�d�d��Z��dsd�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�d�Z��d�d�Z��d�d�Z��d�d�Z��dt�d�d�Z��d�d�Z��du�d�d�Z�													�dv�d�d �Z��d!�d"�Z�													�dw�d#�d$�Z��d%�d&�Z��df�d'�d(�Z��d)�d*�Z��d+�d,�Z��d-�d.�Z��d/�d0�Zdp�d1�d2�ZÐd3�d4�ZĐd5�d6�ZŐd7�d8�Z�													�dx�d9�d:�Z�		�dy�d;�d<�Z�												�dz�d=�d>�Zɐd?�d@�Zʐdf�dA�dB�ZːdC�dD�Z̐dE�dF�Z͐dG�dH�ZΐdI�dJ�ZϐdK�dL�ZАdM�dN�ZѐdO�dP�ZҐdp�dQ�dR�ZӐdS�dT�ZԐdU�dV�ZՐdW�dX�Z֐dY�dZ�Zאdr�d[�d\�Zؐd]�d^�Z�							�d{�d_�d`�Zڐd|�da�db�Zېd|�dc�dd�Z�dS(}aJ

Work with virtual machines managed by libvirt

:depends:
    * libvirt Python module
    * libvirt client
    * qemu-img
    * grep

Connection
==========

The connection to the virtualization host can be either setup in the minion configuration,
pillar data or overridden for each individual call.

By default, the libvirt connection URL will be guessed: the first available libvirt
hypervisor driver will be used. This can be overridden like this:

.. code-block:: yaml

    virt:
      connection:
        uri: lxc:///

If the connection requires an authentication like for ESXi, this can be defined in the
minion pillar data like this:

.. code-block:: yaml

    virt:
      connection:
        uri: esx://10.1.1.101/?no_verify=1&auto_answer=1
        auth:
          username: user
          password: secret

Connecting with SSH protocol
----------------------------

Libvirt can connect to remote hosts using SSH using one of the ``ssh``, ``libssh`` and
``libssh2`` transports. Note that ``libssh2`` is likely to fail as it doesn't read the
``known_hosts`` file. Libvirt may also have been built without ``libssh`` or ``libssh2``
support.

To use the SSH transport, on the minion setup an SSH agent with a key authorized on
the remote libvirt machine.

Per call connection setup
-------------------------

.. versionadded:: 2019.2.0

All the calls requiring the libvirt connection configuration as mentioned above can
override this configuration using ``connection``, ``username`` and ``password`` parameters.

This means that the following will list the domains on the local LXC libvirt driver,
whatever the ``virt:connection`` is.

.. code-block:: bash

    salt 'hypervisor' virt.list_domains connection=lxc:///

The calls not using the libvirt connection setup are:

- ``seed_non_shared_migrate``
- ``virt_type``
- ``is_*hyper``
- all migration functions

- `libvirt ESX URI format <http://libvirt.org/drvesx.html#uriformat>`_
- `libvirt URI format <http://libvirt.org/uri.html#URI_config>`_
- `libvirt authentication configuration <http://libvirt.org/auth.html#Auth_client_config>`_

Units
==========
.. _virt-units:
.. rubric:: Units specification
.. versionadded:: 3002

The string should contain a number optionally followed
by a unit. The number may have a decimal fraction. If
the unit is not given then MiB are set by default.
Units can optionally be given in IEC style (such as MiB),
although the standard single letter style (such as M) is
more convenient.

Valid units include:

========== =====    ==========  ==========  ======
Standard   IEC      Standard    IEC
  Unit     Unit     Name        Name        Factor
========== =====    ==========  ==========  ======
    B               Bytes                   1
    K       KiB     Kilobytes   Kibibytes   2**10
    M       MiB     Megabytes   Mebibytes   2**20
    G       GiB     Gigabytes   Gibibytes   2**30
    T       TiB     Terabytes   Tebibytes   2**40
    P       PiB     Petabytes   Pebibytes   2**50
    E       EiB     Exabytes    Exbibytes   2**60
    Z       ZiB     Zettabytes  Zebibytes   2**70
    Y       YiB     Yottabytes  Yobibytes   2**80
========== =====    ==========  ==========  ======

Additional decimal based units:

======  =======
Unit     Factor
======  =======
KB      10**3
MB      10**6
GB      10**9
TB      10**12
PB      10**15
EB      10**18
ZB      10**21
YB      10**24
======  =======
�N)�ElementTree)�saxutils)�	ipaddress)�CommandExecutionError�SaltInvocationError)�libvirtErrorTF�virt)�loaderz/var/lib/libvirt/saltinst�runningZpaused�shutdownZcrashed)r������cCstsdSdS)N)Fz2Unable to locate or import python libvirt library.r)�HAS_LIBVIRT�rr�E/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/virt.py�__virtual__�srcs��fdd�}dS)zm
    Get libvirt.openAuth callback with username, password values overriding
    the configuration ones.
    csz|D]8}|dtjkr�r�ntdd|d�|d<q|dtjkr2�r&�ntdd|d�|d<qt�d|d�qdS)a0Callback method passed to libvirt.openAuth().

        The credentials argument is a list of credentials that libvirt
        would like to request. An element of this list is a list containing
        5 items (4 inputs, 1 output):
          - the credential type, e.g. libvirt.VIR_CRED_AUTHNAME
          - a prompt to be displayed to the user
          - a challenge
          - a default result for the request
          - a place to store the actual result for the request

        The user_data argument is currently not set in the openAuth call.
        r�
config.getzvirt:connection:auth:usernamerrzvirt:connection:auth:passwordzUnhandled credential type: %s)�libvirt�VIR_CRED_AUTHNAME�__salt__�VIR_CRED_NOECHOPROMPT�log�info)ZcredentialsZ	user_dataZ
credential��password�usernamerr�__request_auth�s"������z*__get_request_auth.<locals>.__request_authNr)rrr rrr�__get_request_auth�sr!cKs�|�dd�}|�dd�}|�dd�}|stdd|�}ztjtjtjtjtjg}t�||t	||�dgd�}W|St
yHtd�t
d	|���w)
a=
    Detects what type of dom this node is and attempts to connect to the
    correct hypervisor via libvirt.

    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    rNr�
connectionrzvirt:connection:urirzFSorry, {} failed to open a connection to the hypervisor software at {}Zfqdn)�getrrrrZVIR_CRED_ECHOPROMPTZVIR_CRED_PASSPHRASEZVIR_CRED_EXTERNALZopenAuthr!�	Exceptionr�format�
__grains__)�kwargsrrZconn_str�
auth_types�connrrr�
__get_conn�s,�����r*cOs�t�}t�}g}|�dd�r|��D]}|�|�|����q|�dd�r1|��D]}|�|�q)|r9|s9td��|rR|D]}||vrKtd|�d���|�|�q=nt|�}|D]
}|�|�|��qXt	|�dkrs|�d�rs|d	pt|S)
z�
    Return a domain object for the named VM or return domain object for all VMs.

    :params conn: libvirt connection object
    :param vms: list of domain names to look for
    :param iterable: True to return an array in all cases
    �activeT�inactivezNo virtual machines found.zThe VM "z" is not presentr�iterabler)
�listr#Z
listDomainsID�appendZ
lookupByID�nameZlistDefinedDomainsrZlookupByName�len)r)�vmsr'�retZ
lookup_vmsZall_vms�id_r0rrr�_get_domains*�$r5cs�tjj�|�}g}|D]>}|d|d|d|dd|vr!|dndd��d|��vr3t|d��d	<d
|��vrDdd�|d
D��d
<|���q|D]�d	���vre�fd
d�|D�}|re|d�d	<qL|dS)zD
    Parse qemu-img info JSON output into disk infos dictionary
    �filenamer%zactual-sizezvirtual-sizezcluster-sizeN)�file�file format�	disk size�virtual sizezcluster sizezfull-backing-filename�backing file�	snapshotscSslg|]2}|d|d|dtj�td�|d|d�����tj�td�|d|d�������d��qS)	�idr0z
vm-state-size�{}.{}zdate-secz	date-nseczvm-clock-secz
vm-clock-nsec)r=�tagZvmsize�dateZvmclock)�datetime�
fromtimestamp�floatr%�	isoformat�utcfromtimestamp�time)�.0�snapshotrrr�
<listcomp>Os,��������z(_parse_qemu_img_info.<locals>.<listcomp>cs,g|]}d|��vr|d�dkr|�qS)r7r;��keys)rGr��diskrrrIis
�r)�salt�utils�json�loadsrKr%r/)rZ	raw_infos�disksZ
disk_infosZ
candidatesrrLr�_parse_qemu_img_info:s2�

�
��rScCst�t|���d�jS)z~
    Return a uuid from the named vm

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_uuid <domain>
    �uuid�r�
fromstring�get_xml�find�text)�domrrr�	_get_uuidts
r[cC�&t�t|���d�}|dur|jSdS)z�
    Return `on_poweroff` setting from the named vm

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_on_restart <domain>
    �on_poweroffN�rU�rZ�noderrr�_get_on_poweroff��
racCr\)z�
    Return `on_reboot` setting from the named vm

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_on_reboot <domain>
    �	on_rebootNr^rUr_rrr�_get_on_reboot�rbrdcCr\)z�
    Return `on_crash` setting from the named vm

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_on_crash <domain>
    �on_crashNr^rUr_rrr�
_get_on_crash�rbrfc	Csi}t�|�tj��}|�d�D]{}i}|�d�|d<|D]b}|jdkr+|�d�|d<|jdkr7|�d�|d<|jdkrC|�d�|d<t�	d|j�r_i}|j
��D]\}}|||<qQ|||j<|jd	kri}|�d�|d<|j
��D]\}}|||<qr||d	<qd|vr�q|||d<q|S)
zE
    Get domain network interfaces from a libvirt domain object.
    �devices/interface�type�mac�address�model�target�devz(driver|source|address)Zvirtualport)rrV�XMLDescr�VIR_DOMAIN_XML_INACTIVE�findallr#r?�re�match�attrib�items)	rZ�nics�docZ
iface_node�nicZv_nodeZtemp�key�valuerrr�	_get_nics�s8






�rzcCsPdddddd�}t�|�d��}|�d�D]}|j��D]\}}|||<qq|S)z;
    Get domain graphics from a libvirt domain object.
    �None)ZautoportZkeymap�listen�portrhrzdevices/graphics)rrVrnrprsrt�rZ�outrvZg_noderxryrrr�
_get_graphics�s�
�r�cCsRddi}t�|�d��}|�d�D]}|j|d<|j��D]\}}|||<qq|S)z9
    Get domain loader from a libvirt domain object.
    �pathr{r�	os/loader)rrVrnrprYrsrtr~rrr�_get_loader�s

�r�c
sbi}t�|�d��}t��}|�d�D�]����d�}|dur q��d�}��d�}|dur/qd}d}	d|jv�r���d�}
��fd	d
�}|
dkr�|�dd�}|�d
�r_|dd�||�d�<q||vrt||}||d|d�\}}	�n
��dd�dkr�z1t	j
dddddd|gdt	jt	jd�}
|
��\}}|
j
dkr�tjj�|�}t|�}|}	nd|i}	Wn�ty�ddi}	Yn�wn�|
dkr�|�dd�}||vr�||}||d|d�\}}	n�|
d k�rk|�d!�}|�d�}|r�|�d"|��}|�d!�d#v�r-���D].}t�|���}|�d$�}|du�r,|�|j�d%���r,d&�|��|t|j�d��}nq���dd�dk�rj|�d'�}|du�rj|�d�}|�d(�}tj�|�d!�|�r[|�d"|��n||dt�|�d)d��df�}n|
d*k�r�|�d�}|�d*�}|||�\}}	|�s�q|��d�d+�}|du�r�d|jv�r�|�d�|d,<|	�r�|�|	�|||�d�<q|S)-z8
    Get domain disks from a libvirt domain object.
    rzdevices/disk�sourceNrl�driverrmrhcs0|�d|��}��|�}i}zw|�|�}|��}|d|dd�}��d�}dd�|D�}|rI|d|d	<|d	}	|dd�D]}
|
|	d	<|
}	q?n3t�|���}|�d
�}|�d�}
|durwd|ji|d	<|
dur�|
�	d
�|d	d<W||fSW||fSW||fSW||fSt
jy�t�d�Y||fSw)N�/rr
)r:r9z.//backingStore[source]cSs.g|]}|�d��d�|�d��d�d��qS)r�r7r%rh)r7r8)rXr#�rGr`rrrrIs���z=_get_disks.<locals>._get_disk_volume_data.<locals>.<listcomp>rr;�./backingStore/path�./backingStore/formatr7rhr8zQCouldn't extract all volume informations: pool is likely not running or refreshed)
�storagePoolLookupByName�storageVolLookupByNamerrprrVrnrXrYr#rrr)�	pool_name�volume_name�qemu_target�pool�extra_properties�volZvol_infoZ_nodesZ
backing_files�parentZsub_backing_fileZvol_desc�backing_path�backing_format�r)�elemrr�_get_disk_volume_datasX

����

��	���
���z)_get_disks.<locals>._get_disk_volume_datar7r^�
/dev/zvol/T)r7�zfsr�r0�devicerM�cdrom�qemu-imgrz-Uz--outputrPz--backing-chainF)�shell�stdout�stderr�errorzqemu-img not found�block�network�protocol�:)�rbd�glusterzsource/namer��{}{}�hostr}�query�volume)r7rhr8)rrVrn�_get_all_volumes_pathsrprXrsr#�
startswith�
subprocess�Popen�PIPE�communicate�
returncoderNrO�stringutils�to_strrS�FileNotFoundError�listAllStoragePoolsrYr%r0r1�urllib�parse�
urlunparserZunescape�update)r)rZrRrv�all_volumesr�rlr�r�r�Z	disk_typer�r��processr�r�Zqemu_output�output�source_nameZpool_iZ
pool_i_xml�	name_nodeZ	host_node�hostnamer}r�r�rMrr�r�
_get_disks�s�



5
��	�
�����




���



���



��
�r�cCs�gd�}gd�}ztj|tjd���d}tjj�|��d�d}Wnt	y-d}Ynwztj|tjd���d}tjj�|��d�d}Wnt	ySd}Ynw||d�S)	zL
    Returns the user and group that the disk images should be owned by
    )�grepz	^\s*group�/etc/libvirt/qemu.conf)r�z^\s*userr��r�r�"r�root)�user�group)
r�r�r�r�rNrOr�r��split�
IndexError)Zg_cmdZu_cmdr�r�r�rrr�_libvirt_creds�s��
r�c
Ks&d}i}tj}|�dd�r|tjO}|�dd�r|tjO}|�dd�r(|tjO}|�d�}|rIzt|�}WntyCtd|����w|�	|�|�d�}|rjzt|�}	Wntydtd	|����w|�
|	�|�d
�dury|tjO}tj}|�d�dur�|tj
O}|�d�}
|
r�|
�d
�|tj<tjtjtjtjd�}|��D]#\}}
|�|�}|r�zt|�||
<Wq�ty�td|�d���wq�|�d�}|r�z	t|�|tj<Wnty�td��w|tjO}tdd�r�|r�td��|tjO}|tjO}|�d�du�r|tjO}|�d�}|�r.zt|�}Wnt�y%td��w|j	|tjd�|�d�}|�rP|dk�rA|tjO}n|dv�rL|tjO}ntd��z*d}t||�d�|�d �d!�}|j|||d"�}|�ro|� �}|�!�|�oy||vWStj"�y�}z
|�!�t#|�$���d#}~ww)$aL	
    Migrate the domain object from its current host to the destination
    host given by URI.

    :param dom: domain object to migrate
    :param dst_uri: destination URI
    :param kwargs:
        - live:            Use live migration. Default value is True.
        - persistent:      Leave the domain persistent on destination host.
                           Default value is True.
        - undefinesource:  Undefine the domain on the source host.
                           Default value is True.
        - offline:         If set to True it will migrate the domain definition
                           without starting the domain on destination and without
                           stopping it on source host. Default value is False.
        - max_bandwidth:   The maximum bandwidth (in MiB/s) that will be used.
        - max_downtime:    Set maximum tolerable downtime for live-migration.
                           The value represents a number of milliseconds the guest
                           is allowed to be down at the end of live migration.
        - parallel_connections: Specify a number of parallel network connections
                           to be used to send memory pages to the destination host.
        - compressed:      Activate compression.
        - comp_methods:    A comma-separated list of compression methods. Supported
                           methods are "mt" and "xbzrle" and can be  used in any
                           combination. QEMU defaults to "xbzrle".
        - comp_mt_level:   Set compression level. Values are in range from 0 to 9,
                           where 1 is maximum speed and 9 is  maximum compression.
        - comp_mt_threads: Set number of compress threads on source host.
        - comp_mt_dthreads: Set number of decompress threads on target host.
        - comp_xbzrle_cache: Set the size of page cache for xbzrle compression in bytes.
        - copy_storage:    Migrate non-shared storage. It must be one of the following
                           values: all (full disk copy) or incremental (Incremental copy)
        - postcopy:        Enable the use of post-copy migration.
        - postcopy_bandwidth: The maximum bandwidth allowed in post-copy phase. (MiB/s)
        - username:        Username to connect with target host
        - password:        Password to connect with target host
    r�liveT�
persistentZundefinesource�
max_bandwidthzInvalid max_bandwidth value: �max_downtimezInvalid max_downtime value: Zoffline�
compressed�comp_methods�,)Z
comp_mt_levelZcomp_mt_threadsZcomp_mt_dthreadsZcomp_xbzrle_cachezInvalid z value�parallel_connectionsz"Invalid parallel_connections valuerzvirt:tunnelz;Parallel migration isn't compatible with tunneled migrationZpostcopy�postcopy_bandwidthz Invalid postcopy_bandwidth value)�flags�copy_storage�all)ZincZincrementalzinvalid copy_storage valueFrr)r"rr)Zdconn�paramsr�N)%rZVIR_DOMAIN_RUNNING_MIGRATEDr#ZVIR_MIGRATE_LIVEZVIR_MIGRATE_PERSIST_DESTZVIR_MIGRATE_UNDEFINE_SOURCE�int�
ValueErrorrZmigrateSetMaxSpeedZmigrateSetMaxDowntimeZVIR_MIGRATE_OFFLINEZVIR_DOMAIN_RUNNING_UNPAUSEDZVIR_MIGRATE_COMPRESSEDr�ZVIR_MIGRATE_PARAM_COMPRESSIONZ&VIR_MIGRATE_PARAM_COMPRESSION_MT_LEVELZ(VIR_MIGRATE_PARAM_COMPRESSION_MT_THREADSZ)VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADSZ*VIR_MIGRATE_PARAM_COMPRESSION_XBZRLE_CACHErtZ&VIR_MIGRATE_PARAM_PARALLEL_CONNECTIONSZVIR_MIGRATE_PARALLELrZVIR_MIGRATE_PEER2PEERZVIR_MIGRATE_TUNNELLEDZVIR_MIGRATE_POSTCOPYZ%VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPYZVIR_MIGRATE_NON_SHARED_DISKZVIR_MIGRATE_NON_SHARED_INCr*Zmigrate3�state�closerr�get_error_message)rZ�dst_urir'r�r�Zmigrated_stater�Zbandwidth_valuer�Zdowntime_valuer�Zcomp_optionsZcomp_optionZ	param_keyZcomp_option_valuer�r�Zpostcopy_bandwidth_valuer�r�Zdst_connZnew_dom�errrrr�_migrate�s�&



�

�



�
��
��
�



��


���r�cCsV||��vr|�|�}t�|���}|�d�jSt�|���}|�d�j}|d|S)zd
    Get the path to a volume. If the volume doesn't exist, compute its path from the pool one.
    z
./target/pathr�)�listVolumesr�rrVrnrXrY)r�r�r�Z
volume_xml�pool_xmlZ	pool_pathrrr�_get_volume_pathJs
r�c
Cs|�d�}i}|dvrd|d<t||�|d<|S|dvr-d|d<d|d<t||�|d<|S|d	vr�d
|d<||d<dd
�|�d�D�|d<|�d�}|�d�}|dur]|j�d|��|d<|�d�}|dur�|�d�}	|�d�}
|
�d�}|s�|
�d�}|�|���}d|	|d�|d<|S)z�
    Create a disk definition out of the pool XML and volume name.
    The aim of this function is to replace the volume-based definition when not handled by libvirt.
    It returns the disk Jinja context to be used when creating the VM
    rh)�dir�netfs�fsr7�source_file)�logicalrM�iscsi�scsir��rawr%�r�r��sheepdogr�r�cSs"g|]
}|�d�|�d�d��qS)r0r}�r0r}�r#�rGr�rrrrIqs��z#_disk_from_pool.<locals>.<listcomp>z.//host�hostsz./source/dirz
./source/nameNr�r�z
./source/authrz./secret�usagerT�ceph)rhrr��auth)r#r�rprXrY�secretLookupByUUIDStringZusageID)
r)r�r�r��	pool_type�disk_contextZdir_noder��	auth_noder�secret_noder�rTrrr�_disk_from_poolYsD
%� �
�







�r��mcCs(tjjj||dd�}|dkrtd��|S)z?
    Handle the unit conversion, return the value in bytes
    T)Zdefault_unitZ
handle_metricrzinvalid number or unit)rNrOr�Zhuman_to_bytesr)�sZdef_unitr3rrr�_handle_unit�s�r�cCst�t|pi�S)zD
    create default dict that allows arbitrary level of nesting
    )�collections�defaultdict�nesthash)ryrrrr��sr�c2Ks||||
pi|pi|rdndd�}dd�|d<dd�|d<t�|d	<t|t�r3||d	d
<||d	d<nt|t�r>t|�|d	<t�|d<t�|d
<t|t�rVt|�|dd<nt|t�rat|�|d<|ry|�dd�rkdnd}d|vrsd}||dd<|dvr�|r�|ni|d<d|d<n|dkr�d|d<|	r�d|	vr�ddd�|	d<nd|	dvr�|	dddkr�d|	dd<|	�dd �d kr�d!}	|	|d"<|d!ur�|��nd#g|d$<|
r�|
ni|d
<|
r�|d
�d%d!�nd!}|dur�d&|d
d'<n
|d!ur�t|t�s�td(��|d)k�r-t	d*d+k�r-|
�r|
�d,d!��s-d-d.�d/D�}|�st
d0��|d1d2|d
d,<g|d$<d3}d4}d5d6g}|D]E}g||d7<t�|d7}|d!u�r{|D]-}|}|�d|�|d<|dd4k�rp|�d8|�|d8<|�d9d:�|d9<||d7�|��qM�q7g|d;<d<d=d>d#d?�}g} t
|�D]�\}!}"|�|"d@dA�}#|"�dBdC�t| t|�|#�|"d@|"�dDdE�t|!�|"�dFdG�|"�dHd!�dI�}$| �|$dJ�|"�dK��r
tj�|"dK�}%|%j�r�|%j�s�|"dK|$dK<dL|$d<nu|%jdMv�rdN|$d<|%j|$d9<|%j|$dO<t�|%j�|$dP<|%j|%jdQ�g|$dR<nN|"�dS��rW|"dT|$dO<|�|"dS�}&t�|&���}'|'�d�}(|d)k�s6|(dUv�rC|$�t||&|'|$dO��n|(dVv�rLdE|$dD<dO|$d<|"dS|$dS<ndL|$d<|dWv�rid|$d<d|$dX<n
|dYv�rvd|$d<d|$dX<|d;�|$��q�||dZ<g})zm|�p�gD]e}*|� |*�}+t�|+���},d[|+�!�v�r�|)�d[d\�"t|,�#d]�j$��d^�"t|,�#d_�j$��d^�"t|,�#d`�j$��da�"|,�#db�j$�dc���q�dd|+�!�v�r�|,�#de��df�}-|,�#dg��df�}.|)�dh|-|.di���q�Wnt%j&�y}/z|�'�t
dj|/�(���d!}/~/ww|)|dk<||dl<||dm<dn}0zt)�*|0�}1Wnt+j,j-�y5t.�/do|0�YdpSw|1j0dqi|��S)rz8
    Generate the XML string to define a libvirt VM
    �destroy�restart)�
hypervisorr0�hypervisor_features�clockrccSstt|�d�S)N�)r�r���vrrr�<lambda>��z_gen_xml.<locals>.<lambda>Zto_kibcS�|rdSdS�N�yes�norrrrrr���yesno�mem�boot�current�cpuZcputune�maximum�utcT�	localtime�timezoner�offset��qemu�kvm�numatuneFZcontroller_model�vmwareZlsilogicr|rjz0.0.0.0)rhrjrh�noneN�graphics�hd�boot_dev�efizfirmware='efi'�	os_attrib�Invalid efi value�xenZ	os_familyZSuse�kernelcSs g|]}tj�|d�r|�qS)�/grub2/x86_64-xen/grub.xen)�osr��exists�rGr�rrrrI�s��z_gen_xml.<locals>.<listcomp>)z
/usr/sharez/usr/libz%grub-x86_64-xen needs to be installedrr'i�YZtcp�serial�consoler�r}r��telnetrR�vd�xvd�fd)�virtior%Zfdc�iderk�sdr�rMr%r��io�nativeZiothread_id)r��
target_devZdisk_busr%�indexr4�iothreadr6r�r7)�http�https�ftpZftps�tftpr�r�r�r�r�r�r6r�)rMr�)rr�bhyver%r���esxirru�pciz0x{:04x}z ./capability[@type='pci']/domainz0x{:02x}z./capability[@type='pci']/busz./capability[@type='pci']/slotz0x{}z"./capability[@type='pci']/function)rh�domain�bus�slot�function�
usb_device�	.//vendorr=�
.//product�usb)rh�vendor�productzFailed to get host devices: Zhostdevs�os_type�archzlibvirt_domain.jinja�Could not load template %sr^r)1r��
isinstancer��dict�strr#r��boolrr&r�localsr/�	enumerate�_get_disk_targetr1r�r��urlparse�schemer�r�r�escaper�r}r�rrVrnr�r�ZnodeDeviceLookupByName�listCapsr%rXrYrrr�r��JINJA�get_template�jinja2�
exceptions�TemplateNotFoundrr��render)2r)r0rr�diskp�nicprrKrLrrr!rrr�serials�consoles�stop_on_reboot�host_devicesr'�contextr�	efi_value�paths�default_portZdefault_chardev_typeZ
chardev_typesZchardev_typeZparameter_valueZchardevZchardev_contextZdisk_bus_map�targets�irM�prefixr��urlr�r�r�Zhostdev_contextZhostdev_nameZ
hostdevicerv�	vendor_id�
product_idr��fn_�templaterrr�_gen_xml�sN
�








�
�



�	


�
�




���
���
���
����rqcCs~t|�d}||||d�|t|�tt|�d�|d�}d}	zt�|	�}
Wntjjy6t�d|	�YdSw|
j	di|��S)	zD
    Generate the XML string to define a libvirt storage volume
    r)�permissions�nocow)rhr0rlr%�size�
allocationZbackingStorezlibvirt_volume.jinjarMr^Nr)
r�rPrYrZr[r\r]rr�r^)r0rtr%rurhrr�
backing_storersrerorprrr�_gen_vol_xml�s"
�	�rwc
Cs�t|t�r
d|i}
n|}
t|ttf�rdd|igi}n|}g}|
r4dd�|
���d�D�}dd�|D�}|||||||	rA|	�d�ng|||
||dd�|pMgD�d	d
�d�}d}zt�|�}Wntjj	ypt
�d
|�YdSw|jdi|��S)z=
    Generate the XML string to define a libvirt network
    rh�tagsr=cSsg|]}t�d|��qS)z/([0-9]+):([0-9A-Fa-f]+):([0-9A-Fa-f]+)\.([0-9]))rq�	fullmatch)rG�addrrrrrI�s
��z _gen_net_xml.<locals>.<listcomp>� cSs6g|]}|r|�d�|�d�|�d�|�d�d��qS)rr
rr�rArBrCrD)r�)rGr�rrrrI�s���c	SsDg|]}t�|d�|�dg�|�di�|�di�|�d�d��qS)Zcidr�dhcp_rangesr��bootpr<)rjr}r�r~r<)r�
ip_networkr#�rG�configrrrrI�s�


��cSr
rrrrrrr�rz_gen_net_xml.<locals>.<lambda>)r0�bridge�mturA�forward�nat�
interfaces�	addresses�pf�vportZvlan�dns�
ip_configsrzlibvirt_network.jinjarMr^Nr)
rNrPr��lowerr�rYrZr[r\r]rr�r^)r0r�r�r�r?r�r�rAr�r�r��physical_functionr�Z
vport_contextZtag_contextZaddresses_context�matchesrerorprrr�_gen_net_xml�sN

���
��r�c	Cs�dd�|pgD�}d}
t||||||	|
|g�r4|pg|
dks |s"|n|�d�|dd�|D�||	|
|d�}
||||d�|
d	�}d
}zt�|�}WntjjyYt�d|�YdSw|j	d
i|��S)zB
    Generate the XML string to define a libvirt storage pool
    cS�g|]}|�d��qS)r�)r�r�rrrrI�z!_gen_pool_xml.<locals>.<listcomp>N�cifsr�cSs.g|]}|dt|�dkr|dndd��qS)rrNr�)r1r�rrrrIs ��)�devicesr�Zadapterr�r�r0r%Z	initiator)r�rr)r0�ptyperlr�zlibvirt_pool.jinjarMr^r)
�any�lstriprYrZr[r\r]rr�r^)r0r�rlrr�source_devices�
source_dir�source_adapter�source_hosts�source_authr��
source_format�source_initiatorr�r�rerorprrr�
_gen_pool_xml�sN��
�����r�cCsT|||d�}d}zt�|�}Wntjjy!t�d|�YdSw|jdi|��S)z2
    Generate a libvirt secret definition XML
    )rhr��descriptionzlibvirt_secret.jinjarMr^Nr)rYrZr[r\r]rr�r^)Z	auth_typer�r�rerorprrr�_gen_secret_xml4s��r�cCstdd�}t�d|�|S)z
    Extract the images dir from the configuration. First attempts to
    find legacy virt.images, then tries virt:images.
    rzvirt:imagesz6Image directory from config option `virt:images` is %s)rr�debug)�img_dirrrr�_get_images_dirFsr�cCs|s|std�|���|std�|���tj�||�d|���}t�d|�td|d�}d|vr;td�||d���||vrOt�d	|�tj�d
||�}	|	Si}
|rW||
|<|rctd|||
d�n|rotd
||
||d�tj�d
||�d|���}	t�d|	�|	S)a�
    Clones an existing image, or creates a new one.

    When cloning an image, disk_image_name refers to the source
    of the clone. If not specified, disk_size is used for creating
    a new zvol, and sparse_volume determines whether to create
    a thin provisioned volume.

    The cloned or new volume can have a ZFS property set containing
    the vm_name. Use hostname_property_name for specifying the key
    of this ZFS property.
    zVUnable to create new disk {}, please specify the disk image name or disk size argumentz?Unable to create new disk {}, please specify the disk pool name�.�Image destination will be %szzfs.list�r0r�z Unable to create new disk {}. {}z3ZFS filesystem %s already exists. Skipping creation�	/dev/zvolz	zfs.clone)Zname_aZname_b�
propertiesz
zfs.create)r0r�Zvolume_size�sparsezImage path will be %s)	rr%r(r��joinrr�rr)�vm_namer��	disk_name�hostname_property_name�
sparse_volume�	disk_size�disk_image_nameZdestination_fsZ
existing_diskZblockdevice_pathr�rrr�_zfs_image_createPsR�������r��basec
CsP|�dd�}|�dd�}|s|std�|d���|d}t�d|�tj�|�}t�d|�tj�|�s:t�	|�|r�t�d	|�t
d
||�}d}tjj�
d�rit
d
d|�d��}	tjj�|	�}
|
ddk}zW|r�|r�t�d|�t
d
d�||����nt�d||�tjj�||�tjj��}|r�|r�t�d|�t
d
d|�d|�d��t�d�d|Ad@}t�||�W|Sty�}
z
td|�d|
����d}
~
wwz9tjj��}|r�t�d|�t
d
d�|�d d�||��ntd!�|���t�d�d|Ad@}t�||�W|St�y'}
z
td"|�d|
����d}
~
ww)#zv
    Create the image file using specified disk_size or/and disk_image

    Return path to the created image file
    rtN�imagezQUnable to create new disk {}, please specify disk size and/or disk image argumentr6r�r�z!Image destination directory is %sz#Create disk from specified image %s�
cp.cache_fileFr��cmd.runzqemu-img info "r�r8�qcow2z*Cloning qcow2 image %s using copy on writez2qemu-img create -f qcow2 -o backing_file="{}" "{}"zCopying %s to %szResize qcow2 image to %sMzqemu-img resize "z" �MzApply umask and remove exec biti�i�zProblem while copying image. z - z Create empty image with size %sMzqemu-img create -f {} "{}" {}Mr%z<Unable to create new disk {}, please specify <size> argumentzProblem while creating volume )r#rr%rr�r(r��dirnamer)�makedirsrrNrO�which�yaml�	safe_loadrr��files�copyfileZ	get_umask�chmod�OSError)rM�create_overlay�saltenvr�Z
disk_image�img_destr�Zsfnr��resZ	imageinfo�mask�moder�rrr�_qemu_image_create�s�
�
��
"�������
����r�cCs&t�d�t|||||||d�dS)z_
    Helper function to seed an existing image. Note that this doesn't
    handle volumes.
    z
Seeding image)r4r��install�pub_key�priv_keyN)rr�r)�seed_cmdZimg_pathr0r�r�r�r�rrr�_seed_image�s

�r�cCs:|�d�r	td��|�|d�}|d|��vrdSt�|����d�}|�d�}|�d�}d}|rD|rD|�d	�d
ks?|dkrD||d�}|rO|�d
�rOtd��t|d|�dd�|�d	�|d�}	t||	|�d��|�d
�r�t	�
d|�d
��td|�d
�|�}
|r�||
�t||d|d|
|�d	�d
kd�dSdS)z.
    Create a disk volume for use in a VM
    �
overlay_imagez{Disk overlay_image property is not supported when creating volumes,use backing_store_path and backing_store_format instead.r�r6Nrh�backing_store_path�backing_store_formatr%r�r��r�r%r�zSUsing a template image with a backing store is not possible, choose either of them.rtr)r%rvzCaching disk template image: %sr�)r�)
r#rr�r�rrVrnrw�_define_vol_xml_strrr�r�_volume_upload)r)rM�seederr�r�r�r�r�rv�vol_xmlZcached_pathrrr�_disk_volume_create�sR
�

��
�
�

��r�c
s�dddiig}|dkrdddd�}n!|d	vrdd
d�}n|dkr&ddd�}n
|d
kr1dd
dd�}ni}g}|rLt�tddi��||��}dd�|D�}|ro|D]�d�vrn�fdd�|D�}|ri|d���qP|���qPt|�}	|D]`}
|
�dd�dkr�d|
vr�d|
d<|��D]\}}||
vr�||
|<q�|
�d�r�tj	�
|
d�r�tj	�|
d�|
d<|
�d�s�|
�dd�dkr�dnd|
d<qu|r�|
�dd�dkr�t|||
||	�qu|S) a�
    Gather the disk profile from the config or apply the default based
    on the active hypervisor

    This is the ``default`` profile for KVM/QEMU, which can be
    overridden in the configuration:

    .. code-block:: yaml

        virt:
          disk:
            default:
              - system:
                  size: 8192
                  format: qcow2
                  model: virtio

    Example profile for KVM/QEMU with two disks, first is created
    from specified image, the second is empty:

    .. code-block:: yaml

        virt:
          disk:
            two_disks:
              - system:
                  size: 8192
                  format: qcow2
                  model: virtio
                  image: http://path/to/image.qcow2
              - lvm:
                  size: 32768
                  format: qcow2
                  model: virtio

    The ``format`` and ``model`` parameters are optional, and will
    default to whatever is best suitable for the active hypervisor.
    �systemrti r�vmdkr�rM)r%rkr�rr1)r�rkr%r=r�F)r%rkr�rz	virt:diskcSs*g|]}|��D]
\}}t||d��qqS)r�)rtrO)rGrMr0�drrrrIss*z!_disk_profile.<locals>.<listcomp>r0cs g|]}�d|dkr|�qSr�r)rGrM�ZudiskrrrIy� rr�r�rkr2r�r6r%r�)
�copy�deepcopyrr#r�r/�_pool_capabilitiesrtr(r�r)�basename�_fill_disk_filename)
r)�profilerrRr��defaultZoverlayZdisklist�found�	pool_capsrMrx�valrr�r�
_disk_profile8sT'�
��
���r�csnd�||d�|d<|�dd�}|dvr�|st�}||��vrA|�d�s(d|d<d	�|d|d�|d<tj�||d�|d
<dSd|vrI||d<|�|�}t�	|�
��}|�d���dkr�|�d
��d�}|��}	|�d
�|	vr�dd�|	D�pzdg�t
�fdd�tdt��d�D��}
tj�|��|
��|d<|�d
�r�|�d
�|��vr�td�|�d
�|���|d
|d<|d
=|�d�s�fdd�|�d�D�p�igd}d|�dg�vr�d|d<dS|�dd�|d<dSdS|dk�r|�rd	�||d�|d<tj�d|�pd|d�|d
<dS|dv�r5|�stdd d!�}d	�|d|d�|d<d"�||d�|d
<dSdS)#zE
    Compute the disk file name and update it in the disk value.
    z{}_{}r0r6r�N�rrr%r%r�r>r�rhrMz./source/devicer�cSsg|]}tt�dd|���qS)z[a-z]+r^)r�rq�sub)rGZvol_namerrrrI�s�z'_fill_disk_filename.<locals>.<listcomp>rc3s�|]	}|�vr|VqdS�Nr)rG�idx)�indexesrr�	<genexpr>�s��z&_fill_disk_filename.<locals>.<genexpr>rr
z"{} volume doesn't exist in pool {}cs,g|]}|d�kr|�di��di��qS)r0�optionsr�r�)rGZ	type_caps)r�rrrI�s
��
pool_types�targetFormatType�default_formatr=r�r^r>r�virt:storagepoolz[0] r�)r%r#r��listStoragePoolsr(r�r�r�rrVrnrXr��min�range�maxr�rr)r)r�rMrr��base_dir�pool_objr�r�r�r7Zvolume_optionsr)r�r�rr��sv


���

��

��	��
�r�c	s|dddd�}dddd�}dddd�}dddd�}|||||d	��d
d�}��fdd
�}|D]}||���vr;||�q-|S)z7
    Complete missing data for network interfaces.
    r�ZDEFAULTZe1000�rhr�rkZbr0r1NZbridge0)r%rrrr=cSsLdD]}||vr||d<|�|�|d<q|�dd�|d<|�dd�|d<dS)z�
        Guess which style of definition:

            bridge: br0

             or

            network: net0

             or

            type: network
            source: net0
        )r�r�rhr�N)�popr#)�
attributes�type_rrr�_normalize_net_types�s�z,_complete_nics.<locals>._normalize_net_typescs2����D]\}}||vs||s|||<qdS)z9
        Apply the default overlay to attributes
        N)rt)r�rxry�rZoverlaysrr�_apply_default_overlays
��z._complete_nics.<locals>._apply_default_overlayr)	r�rZvmware_overlayZkvm_overlayZxen_overlayZ
bhyve_overlayr�r��	interfacerr�r�_complete_nics�s$��r�cs�tddi��|diig�}g��fdd�}t|t�r ||�nt|t�r?|D]}t|t�r>t|�dkr9||�q'��|�q't�|�S)z+
    Compute NIC data based on profile
    rzvirt:nicZeth0cs(|��D]
\}}||d<��|�qdS)zC
        Append dictionary profile data to interfaces list
        r0N)rtr/)Zprofile_dictZinterface_namer��r�rr�%append_dict_profile_to_interface_list/s�z;_nic_profile.<locals>.append_dict_profile_to_interface_listr)rr#rNrOr.r1r/r�)Zprofile_namerZconfig_datarr�rrr�_nic_profile$s
�





�
rcsv|rt||�ng}t�d|�|r9t||�}|D]��fdd�|D�}|r-|d���q|���qt�d|�|S)zT
    Get network devices from the profile and merge uer defined ones with them.
    zNIC profile is %scs g|]}|d�dkr|�qSr�r)rGrw�ZunicrrrIer�z$_get_merged_nics.<locals>.<listcomp>rzMerged NICs: %s)rrr�r�r�r/)rr�r�r`Z
users_nicsr�rrr�_get_merged_nics\s
rc	Cs�d}|��}|��}dhhd�hd�ddhddhhd	�hd
�hd�g}||vrl|D]@}|dkr@t|�|��tkr@|�|�||<q)|�|�duritjj�|�|��ri|dur\t	�
t�t}tjj�|�|�|�||<q)|St
d��)
ah
    Checks if the boot parameters contain a remote path. If so, it will copy
    the parameters, download the files specified in the remote path, and return
    a new dictionary with updated paths containing the canonical path to the
    kernel and/or initrd

    :param orig_boot: The original boot parameters passed to the init or update
    functions.
    Nr">�initrdr"r&>r�cmdliner"r&r	�nvramr&r>rrr&>r	rrr&>r	rrrr&z|Invalid boot parameters,It has to follow this combination: [(kernel, initrd) or/and cmdline] or/and [(loader, nvram) or efi])r�rKrhr#rQrNrOrZcheck_remoter(r��	CACHE_DIRZdownload_remoter)Z	orig_bootZsaltinst_dirZnew_bootrK�casesrxrrr�_handle_remote_boot_paramsns<
��

���r
cCs�|r|�dd�nd}|�d�}|j}|dur#|ikr#|j�dd�dSt|t�r^|ikr^|dur?|�d�dur?|�dd�dS|dur\|�d�dur\|�|�d��|�|�d��dSdSt|t�sgtd	��dS)
a
    Checks if boot parameter contains efi boolean value, if so, handles the firmware attribute.
    :param boot: The boot parameters passed to the init or update functions.
    :param desc: The XML description of that domain.
    :return: A boolean value.
    r"Nr(FZfirmwareTr	rr$)	r#rXrsr�rNrQ�set�remover)r�descrfZ
parent_tagr#rrr�_handle_efi_param�s$

�rr��
seed.applyc.sf�z�td/i���}t|�}tdd�|dD��}tdd�|dD��}|} | sKtdd�dd�|dD�D��}!t|!�dkrAtd	��d
|!vrGd
n|!d} | dkrQdn| } t�d
| �t| ||�}"t||| |��}#|#D]�}$|$�	dd�dkrtqit�d�|$�| dkr�d|$vr�td��t�d|$�d�
�|$d�}%d�
|%|$d�}&t|&|$d|$dd�}'t||'|$�	d�d�qi| dv�r������fdd�}(|$�	d d!�})|$�	d�}*|$�	d"�r�t
j�|$d"�r�|$d"}+nt|$|)|	�}+n
t||$|
r�|(nd#|	�d#}+|
�r|+�r|$�	dd#��r|(|+�qi|d$v�r)t�|$�	d�|$�	d�|$�	d�|$�	d�|$�	d%�|$�	d&�d'�}+qitd(�
| ���t�d)�|d#u�rEd*|v�rAd*n|d}|d#u�rUd+|v�rQd+n|d}|d#u�r^t|�}t|�|||#|"| ||||||||||||fi���},t�d,|,�|�|,�Wntj�y�}-z
|��t|-����d#}-~-ww|�r�t�d-��t|����|��d.S)0a2v
    Initialize a new vm

    :param name: name of the virtual machine to create
    :param cpu:
        Number of virtual CPUs to assign to the virtual machine or a dictionary with detailed information to configure
        cpu model and topology, numa node tuning, cpu tuning and iothreads allocation. The structure of the dictionary is
        documented in :ref:`init-cpu-def`.

        .. code-block:: yaml

             cpu:
               placement: static
               cpuset: 0-11
               current: 5
               maximum: 12
               vcpus:
                 0:
                   enabled: True
                   hotpluggable: False
                   order: 1
                 1:
                   enabled: False
                   hotpluggable: True
               match: minimum
               mode: custom
               check: full
               vendor: Intel
               model:
                 name: core2duo
                 fallback: allow
                 vendor_id: GenuineIntel
               topology:
                 sockets: 1
                 cores: 12
                 threads: 1
               cache:
                 level: 3
                 mode: emulate
               features:
                 lahf: optional
                 pcid: require
               numa:
                 0:
                    cpus: 0-3
                    memory: 1g
                    discard: True
                    distances:
                      0: 10     # sibling id : value
                      1: 21
                      2: 31
                      3: 41
                 1:
                    cpus: 4-6
                    memory: 1g
                    memAccess: shared
                    distances:
                      0: 21
                      1: 10
                      2: 21
                      3: 31
               tuning:
                    vcpupin:
                      0: 1-4,^2  # vcpuid : cpuset
                      1: 0,1
                      2: 2,3
                      3: 0,4
                    emulatorpin: 1-3
                    iothreadpin:
                      1: 5,6    # iothread id: cpuset
                      2: 7,8
                    shares: 2048
                    period: 1000000
                    quota: -1
                    global_period: 1000000
                    global_quota: -1
                    emulator_period: 1000000
                    emulator_quota: -1
                    iothread_period: 1000000
                    iothread_quota: -1
                    vcpusched:
                      - scheduler: fifo
                        priority: 1
                        vcpus: 0,3-5
                      - scheduler: rr
                        priority: 3
                    iothreadsched:
                      - scheduler: idle
                      - scheduler: batch
                        iothreads: 2,3
                    emulatorsched:
                      - scheduler: batch
                    cachetune:
                      0-3:      # vcpus set
                        0:      # cache id
                          level: 3
                          type: both
                          size: 4
                        1:
                          level: 3
                          type: both
                          size: 6
                        monitor:
                          1: 3
                          0-3: 3
                      4-5:
                        monitor:
                          4: 3  # vcpus: level
                          5: 3
                    memorytune:
                      0-3:      # vcpus set
                        0: 60   # node id: bandwidth
                      4-5:
                        0: 60
               iothreads: 4

        .. versionadded:: 3003

    :param mem: Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to
        contain detailed configuration which support memory allocation or tuning. Supported parameters are ``boot``,
        ``current``, ``max``, ``slots``, ``hard_limit``, ``soft_limit``, ``swap_hard_limit``, ``min_guarantee``,
        ``hugepages`` ,  ``nosharepages``, ``locked``, ``source``, ``access``, ``allocation`` and ``discard``. The structure
        of the dictionary is documented in  :ref:`init-mem-def`. Both decimal and binary base are supported. Detail unit
        specification is documented  in :ref:`virt-units`. Please note that the value for ``slots`` must be an integer.

        .. code-block:: python

            {
                'boot': 1g,
                'current': 1g,
                'max': 1g,
                'slots': 10,
                'hard_limit': '1024',
                'soft_limit': '512m',
                'swap_hard_limit': '1g',
                'min_guarantee': '512mib',
                'hugepages': [{'nodeset': '0-3,^2', 'size': '1g'}, {'nodeset': '2', 'size': '2m'}],
                'nosharepages': True,
                'locked': True,
                'source': 'file',
                'access': 'shared',
                'allocation': 'immediate',
                'discard': True
            }

        .. versionchanged:: 3002

    :param nic: NIC profile to use (Default: ``'default'``).
                The profile interfaces can be customized / extended with the interfaces parameter.
                If set to ``None``, no profile will be used.
    :param interfaces:
        List of dictionaries providing details on the network interfaces to create.
        These data are merged with the ones from the nic profile. The structure of
        each dictionary is documented in :ref:`init-nic-def`.

        .. versionadded:: 2019.2.0
    :param hypervisor: the virtual machine type. By default the value will be computed according
                       to the virtual host capabilities.
    :param start: ``True`` to start the virtual machine after having defined it (Default: ``True``)
    :param disk: Disk profile to use (Default: ``'default'``). If set to ``None``, no profile will be used.
    :param disks: List of dictionaries providing details on the disk devices to create.
                  These data are merged with the ones from the disk profile. The structure of
                  each dictionary is documented in :ref:`init-disk-def`.

                  .. versionadded:: 2019.2.0
    :param saltenv: Fileserver environment (Default: ``'base'``).
                    See :mod:`cp module for more details <salt.modules.cp>`
    :param seed: ``True`` to seed the disk image. Only used when the ``image`` parameter is provided.
                 (Default: ``True``)
    :param install: install salt minion if absent (Default: ``True``)
    :param pub_key: public key to seed with (Default: ``None``)
    :param priv_key: public key to seed with (Default: ``None``)
    :param seed_cmd: Salt command to execute to seed the image. (Default: ``'seed.apply'``)
    :param graphics:
        Dictionary providing details on the graphics device to create. (Default: ``None``)
        See :ref:`init-graphics-def` for more details on the possible values.

        .. versionadded:: 2019.2.0
    :param os_type:
        type of virtualization as found in the ``//os/type`` element of the libvirt definition.
        The default value is taken from the host capabilities, with a preference for ``hvm``.

        .. versionadded:: 2019.2.0
    :param arch:
        architecture of the virtual machine. The default value is taken from the host capabilities,
        but ``x86_64`` is prefed over ``i686``.

        .. versionadded:: 2019.2.0
    :param config: minion configuration to use when seeding.
                   See :mod:`seed module for more details <salt.modules.seed>`
    :param boot_dev: String of space-separated devices to boot from (Default: ``'hd'``)
    :param connection: libvirt connection URI, overriding defaults

                       .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

                     .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

                     .. versionadded:: 2019.2.0

    :param stop_on_reboot:
        If set to ``True`` the guest will stop instead of rebooting.
        This is specially useful when creating a virtual machine with an installation cdrom or
        an autoinstallation needing a special first boot configuration.
        Defaults to ``False``

        .. versionadded:: 3003

    :param boot:
        Specifies kernel, initial ramdisk and kernel command line parameters for the virtual machine.
        This is an optional parameter, all of the keys are optional within the dictionary. The structure of
        the dictionary is documented in :ref:`init-boot-def`. If a remote path is provided to kernel or initrd,
        salt will handle the downloading of the specified remote file and modify the XML accordingly.
        To boot VM with UEFI, specify loader and nvram path or specify 'efi': ``True`` if your libvirtd version
        is >= 5.2.0 and QEMU >= 3.0.0.

        .. versionadded:: 3000

        .. code-block:: python

            {
                'kernel': '/root/f8-i386-vmlinuz',
                'initrd': '/root/f8-i386-initrd',
                'cmdline': 'console=ttyS0 ks=http://example.com/f8-i386/os/',
                'loader': '/usr/share/OVMF/OVMF_CODE.fd',
                'nvram': '/usr/share/OVMF/OVMF_VARS.ms.fd'
            }

    :param boot_dev:
        Space separated list of devices to boot from sorted by decreasing priority.
        Values can be ``hd``, ``fd``, ``cdrom`` or ``network``.

        By default, the value will ``"hd"``.

    :param numatune:
        The optional numatune element provides details of how to tune the performance of a NUMA host via controlling NUMA
        policy for domain process. The optional ``memory`` element specifies how to allocate memory for the domain process
        on a NUMA host. ``memnode`` elements can specify memory allocation policies per each guest NUMA node. The definition
        used in the dictionary can be found at :ref:`init-cpu-def`.

        .. versionadded:: 3003

        .. code-block:: python

            {
                'memory': {'mode': 'strict', 'nodeset': '0-11'},
                'memnodes': {0: {'mode': 'strict', 'nodeset': 1}, 1: {'mode': 'preferred', 'nodeset': 2}}
            }

    :param hypervisor_features:
        Enable or disable hypervisor-specific features on the virtual machine.

        .. versionadded:: 3003

        .. code-block:: yaml

            hypervisor_features:
              kvm-hint-dedicated: True

    :param clock:
        Configure the guest clock.
        The value is a dictionary with the following keys:

        adjustment
            time adjustment in seconds or ``reset``

        utc
            set to ``False`` to use the host local time as the guest clock. Defaults to ``True``.

        timezone
            synchronize the guest to the correspding timezone

        timers
            a dictionary associating the timer name with its configuration.
            This configuration is a dictionary with the properties ``track``, ``tickpolicy``,
            ``catchup``, ``frequency``, ``mode``, ``present``, ``slew``, ``threshold`` and ``limit``.
            See `libvirt time keeping documentation <https://libvirt.org/formatdomain.html#time-keeping>`_ for the possible values.

        .. versionadded:: 3003

        Set the clock to local time using an offset in seconds
        .. code-block:: yaml

            clock:
              adjustment: 3600
              utc: False

        Set the clock to a specific time zone:

        .. code-block:: yaml

            clock:
              timezone: CEST

        Tweak guest timers:

        .. code-block:: yaml

            clock:
              timers:
                tsc:
                  frequency: 3504000000
                  mode: native
                rtc:
                  track: wall
                  tickpolicy: catchup
                  slew: 4636
                  threshold: 123
                  limit: 2342
                hpet:
                  present: False

    :param serials:
        Dictionary providing details on the serials connection to create. (Default: ``None``)
        See :ref:`init-chardevs-def` for more details on the possible values.

        .. versionadded:: 3003

    :param consoles:
        Dictionary providing details on the consoles device to create. (Default: ``None``)
        See :ref:`init-chardevs-def` for more details on the possible values.

        .. versionadded:: 3003

    :param host_devices:
        List of host devices to passthrough to the guest.
        The value is a list of device names as provided by the :py:func:`~salt.modules.virt.node_devices` function.
        (Default: ``None``)

        .. versionadded:: 3003

    .. _init-cpu-def:

    .. rubric:: cpu parameters definition

    The cpu parameters dictionary can contain the following properties:

    cpuset
        a comma-separated list of physical CPU numbers that domain process and virtual CPUs can be pinned to by default.
        eg. ``1-4,^3`` cpuset 3 is excluded.

    current
        the number of virtual cpus available at startup

    placement
        indicate the CPU placement mode for domain process. the value can be either ``static`` or ``auto``

    vcpus
        specify the state of individual vcpu. Possible attribute for each individual vcpu include: ``id``, ``enabled``,
        ``hotpluggable`` and ``order``. Valid ``ids`` are from 0 to the maximum vCPU count minus 1. ``enabled`` takes
        boolean values which controls the state of the vcpu. ``hotpluggable`` take boolean value which controls whether
        given vCPU can be hotplugged and hotunplugged. ``order`` takes an integer value which specifies the order to add
        the online vCPUs.

    match
        The cpu attribute ``match`` attribute specifies how strictly the virtual CPU provided to the guest matches the CPU
        requirements, possible values are ``minimum``, ``exact`` or ``strict``.

    check
        Optional cpu attribute ``check`` attribute can be used to request a specific way of checking whether the virtual
        CPU matches the specification, possible values are ``none``, ``partial`` and ``full``.

    mode
        Optional cpu attribute ``mode`` attribute may be used to make it easier to configure a guest CPU to be as close
        to host CPU as possible, possible values are ``custom``, ``host-model`` and ``host-passthrough``.

    model
        specifies CPU model requested by the guest. An optional ``fallback`` attribute can be used to forbid libvirt falls
        back to the closest model supported by the hypervisor, possible values are ``allow`` or ``forbid``. ``vendor_id``
        attribute can be used to set the vendor id seen by the guest, the length must be exactly 12 characters long.

    vendor
        specifies CPU vendor requested by the guest.

    topology
        specifies requested topology of virtual CPU provided to the guest. Four possible attributes , ``sockets``, ``dies``,
        ``cores``, and ``threads``, accept non-zero positive integer values. They refer to the number of CPU sockets per
        NUMA node, number of dies per socket, number of cores per die, and number of threads per core, respectively.

    features
        A dictionary contains a set of cpu features to fine-tune features provided by the selected CPU model. Use cpu
        feature ``name`` as the key and the ``policy`` as the value. ``policy`` Attribute takes ``force``, ``require``,
        ``optional``, ``disable`` or ``forbid``.

    cache
        describes the virtual CPU cache. Optional attribute ``level`` takes an integer value which describes cache level
        ``mode`` attribute supported three possible values: ``emulate``, ``passthrough``, ``disable``

    numa
        specify the guest numa topology. ``cell`` element specifies a NUMA cell or a NUMA node, ``cpus`` specifies the
        CPU or range of CPUs that are part of the node, ``memory`` specifies the size of the node memory. All cells
        should have ``id`` attribute in case referring to some cell is necessary in the code. optional attribute
        ``memAccess`` control whether the memory is to be mapped as ``shared`` or ``private``, ``discard`` attribute which
        fine tunes the discard feature for given numa node, possible values are ``True`` or ``False``.  ``distances``
        element define the distance between NUMA cells and ``sibling`` sub-element is used to specify the distance value
        between sibling NUMA cells.

    vcpupin
        The optional vcpupin element specifies which of host's physical CPUs the domain vCPU will be pinned to.

    emulatorpin
        The optional emulatorpin element specifies which of host physical CPUs the "emulator", a subset of a domain not
        including vCPU or iothreads will be pinned to.

    iothreadpin
        The optional iothreadpin element specifies which of host physical CPUs the IOThreads will be pinned to.

    shares
        The optional shares element specifies the proportional weighted share for the domain.

    period
        The optional period element specifies the enforcement interval (unit: microseconds).

    quota
        The optional quota element specifies the maximum allowed bandwidth (unit: microseconds).

    global_period
        The optional global_period element specifies the enforcement CFS scheduler interval (unit: microseconds) for the
        whole domain in contrast with period which enforces the interval per vCPU.

    global_quota
        The optional global_quota element specifies the maximum allowed bandwidth (unit: microseconds) within a period
        for the whole domain.

    emulator_period
        The optional emulator_period element specifies the enforcement interval (unit: microseconds).

    emulator_quota
        The optional emulator_quota element specifies the maximum allowed bandwidth (unit: microseconds) for domain's
        emulator threads (those excluding vCPUs).

    iothread_period
        The optional iothread_period element specifies the enforcement interval (unit: microseconds) for IOThreads.

    iothread_quota
        The optional iothread_quota element specifies the maximum allowed bandwidth (unit: microseconds) for IOThreads.

    vcpusched
        specify the scheduler type for vCPUs.
        The value is a list of dictionaries with the ``scheduler`` key (values ``batch``, ``idle``, ``fifo``, ``rr``)
        and the optional ``priority`` and ``vcpus`` keys. The ``priority`` value usually is a positive integer and the
        ``vcpus`` value is a cpu set like ``1-4,^3,6`` or simply the vcpu id.

    iothreadsched
        specify the scheduler type for IO threads.
        The value is a list of dictionaries with the ``scheduler`` key (values ``batch``, ``idle``, ``fifo``, ``rr``)
        and the optional ``priority`` and ``vcpus`` keys. The ``priority`` value usually is a positive integer and the
        ``vcpus`` value is a cpu set like ``1-4,^3,6`` or simply the vcpu id.

    emulatorsched
        specify the scheduler type (values batch, idle, fifo, rr) for particular the emulator.
        The value is a dictionary with the ``scheduler`` key (values ``batch``, ``idle``, ``fifo``, ``rr``)
        and the optional ``priority`` and ``vcpus`` keys. The ``priority`` value usually is a positive integer.

    cachetune
        Optional cachetune element can control allocations for CPU caches using the resctrl on the host.

    monitor
        The optional element monitor creates the cache monitor(s) for current cache allocation.

    memorytune
        Optional memorytune element can control allocations for memory bandwidth using the resctrl on the host.

    iothreads
        Number of threads for supported disk devices to perform I/O requests. iothread id will be numbered from 1 to
        the provided number (Default: None).

    .. _init-boot-def:

    .. rubric:: Boot parameters definition

    The boot parameters dictionary can contains the following properties:

    kernel
        The URL or path to the kernel to run the virtual machine with.

    initrd
        The URL or path to the initrd file to run the virtual machine with.

    cmdline
        The parameters to pass to the kernel provided in the `kernel` property.

    loader
        The path to the UEFI binary loader to use.

        .. versionadded:: 3001

    nvram
        The path to the UEFI data template. The file will be copied when creating the virtual machine.

        .. versionadded:: 3001

    efi
       A boolean value.

       .. versionadded:: 3001

    .. _init-mem-def:

    .. rubric:: Memory parameter definition

    Memory parameter can contain the following properties:

    boot
        The maximum allocation of memory for the guest at boot time

    current
        The actual allocation of memory for the guest

    max
        The run time maximum memory allocation of the guest

    slots
         specifies the number of slots available for adding memory to the guest

    hard_limit
        the maximum memory the guest can use

    soft_limit
        memory limit to enforce during memory contention

    swap_hard_limit
        the maximum memory plus swap the guest can use

    min_guarantee
        the guaranteed minimum memory allocation for the guest

    hugepages
        memory allocated using ``hugepages`` instead of the normal native page size. It takes a list of
        dictionaries with ``nodeset`` and ``size`` keys.
        For example ``"hugepages": [{"nodeset": "1-4,^3", "size": "2m"}, {"nodeset": "3", "size": "1g"}]``.

    nosharepages
        boolean value to instruct hypervisor to disable shared pages (memory merge, KSM) for this domain

    locked
        boolean value that allows memory pages belonging to the domain will be locked in host's memory and the host will
        not be allowed to swap them out, which might be required for some workloads such as real-time.

    source
        possible values are ``file`` which utilizes file memorybacking, ``anonymous`` by default and ``memfd`` backing.
        (QEMU/KVM only)

    access
        specify if the memory is to be ``shared`` or ``private``. This can be overridden per numa node by memAccess.

    allocation
        specify when to allocate the memory by supplying either ``immediate`` or ``ondemand``.

    discard
        boolean value to ensure the memory content is discarded just before guest shuts down (or when DIMM module is
        unplugged). Please note that this is just an optimization and is not guaranteed to work in all cases
        (e.g. when hypervisor crashes). (QEMU/KVM only)

    .. _init-nic-def:

    .. rubric:: Network Interfaces Definitions

    Network interfaces dictionaries can contain the following properties:

    name
        Name of the network interface. This is only used as a key to merge with the profile data

    type
        Network type. One of ``'bridge'``, ``'network'``

    source
        The network source, typically the bridge or network name

    mac
        The desired mac address, computed if ``None`` (Default: ``None``).

    model
        The network card model (Default: depends on the hypervisor)

    .. _init-disk-def:

    .. rubric:: Disks Definitions

    Disk dictionaries can contain the following properties:

    name
        Name of the disk. This is mostly used in the name of the disk image and as a key to merge
        with the profile data.

    format
        Format of the disk image, like ``'qcow2'``, ``'raw'``, ``'vmdk'``.
        (Default: depends on the hypervisor)

    size
        Disk size in MiB

    pool
        Path to the folder or name of the pool where disks should be created.
        (Default: depends on hypervisor and the virt:storagepool configuration)

        .. versionchanged:: 3001

        If the value contains no '/', it is considered a pool name where to create a volume.
        Using volumes will be mandatory for some pools types like rdb, iscsi, etc.

    model
        One of the disk busses allowed by libvirt (Default: depends on hypervisor)

        See the libvirt `disk element`_ documentation for the allowed bus types.

    image
        Path to the image to use for the disk. If no image is provided, an empty disk will be created
        (Default: ``None``)

        Note that some pool types do not support uploading an image. This list can evolve with libvirt
        versions.

    overlay_image
        ``True`` to create a QCOW2 disk image with ``image`` as backing file. If ``False``
        the file pointed to by the ``image`` property will simply be copied. (Default: ``False``)

        .. versionchanged:: 3001

        This property is only valid on path-based disks, not on volumes. To create a volume with a
        backing store, set the ``backing_store_path`` and ``backing_store_format`` properties.

    backing_store_path
        Path to the backing store image to use. This can also be the name of a volume to use as
        backing store within the same pool.

        .. versionadded:: 3001

    backing_store_format
        Image format of the disk or volume to use as backing store. This property is mandatory when
        using ``backing_store_path`` to avoid `problems <https://libvirt.org/kbase/backing_chains.html#troubleshooting>`_

        .. versionadded:: 3001

    source_file
        Absolute path to the disk image to use. Not to be confused with ``image`` parameter. This
        parameter is useful to use disk images that are created outside of this module. Can also
        be ``None`` for devices that have no associated image like cdroms.

        .. versionchanged:: 3001

        For volume disks, this can be the name of a volume already existing in the storage pool.

    device
        Type of device of the disk. Can be one of 'disk', 'cdrom', 'floppy' or 'lun'.
        (Default: ``'disk'``)

    hostname_property
        When using ZFS volumes, setting this value to a ZFS property ID will make Salt store the name of the
        virtual machine inside this property. (Default: ``None``)

    sparse_volume
        Boolean to specify whether to use a thin provisioned ZFS volume.

        Example profile for a bhyve VM with two ZFS disks. The first is
        cloned from the specified image. The second disk is a thin
        provisioned volume.

        .. code-block:: yaml

            virt:
              disk:
                two_zvols:
                  - system:
                      image: zroot/bhyve/CentOS-7-x86_64-v1@v1.0.5
                      hostname_property: virt:hostname
                      pool: zroot/bhyve/guests
                  - data:
                      pool: tank/disks
                      size: 20G
                      hostname_property: virt:hostname
                      sparse_volume: True

    io
        I/O control policy. String value amongst ``native``, ``threads`` and ``io_uring``.
        (Default: ``native``)

        .. versionadded:: 3003

    iothread_id
        I/O thread id to assign the disk to.
        (Default: none assigned)

        .. versionadded:: 3003

    .. _init-graphics-def:

    .. rubric:: Graphics Definition

    The graphics dictionary can have the following properties:

    type
        Graphics type. The possible values are ``none``, ``'spice'``, ``'vnc'`` and other values
        allowed as a libvirt graphics type (Default: ``None``)

        See the libvirt `graphics element`_ documentation for more details on the possible types.

    port
        Port to export the graphics on for ``vnc``, ``spice`` and ``rdp`` types.

    tls_port
        Port to export the graphics over a secured connection for ``spice`` type.

    listen
        Dictionary defining on what address to listen on for ``vnc``, ``spice`` and ``rdp``.
        It has a ``type`` property with ``address`` and ``None`` as possible values, and an
        ``address`` property holding the IP or hostname to listen on.

        By default, not setting the ``listen`` part of the dictionary will default to
        listen on all addresses.

    .. _init-chardevs-def:

    .. rubric:: Serials and Consoles Definitions

    Serial dictionaries can contain the following properties:

    type
        Type of the serial connection, like ``'tcp'``, ``'pty'``, ``'file'``, ``'udp'``, ``'dev'``,
        ``'pipe'``, ``'unix'``.

    path
        Path to the source device. Can be a log file, a host character device to pass through,
        a unix socket, a named pipe path.

    host
        The serial UDP or TCP host name.
        (Default: 23023)

    port
        The serial UDP or TCP port number.
        (Default: 23023)

    protocol
        Name of the TCP connection protocol.
        (Default: telnet)

    tls
        Boolean value indicating whether to use hypervisor TLS certificates environment for TCP devices.

    target_port
        The guest device port number starting from 0

    target_type
        The guest device type. Common values are ``serial``, ``virtio`` or ``usb-serial``, but more are documented in
        `the libvirt documentation <https://libvirt.org/formatdomain.html#consoles-serial-parallel-channel-devices>`_.

    .. rubric:: CLI Example

    .. code-block:: bash

        salt 'hypervisor' virt.init vm_name 4 512 salt://path/to/image.raw
        salt 'hypervisor' virt.init vm_name 4 512 /var/lib/libvirt/images/img.raw
        salt 'hypervisor' virt.init vm_name 4 512 nic=profile disk=profile

    The disk images will be created in an image folder within the directory
    defined by the ``virt:images`` option. Its default value is
    ``/srv/salt-images/`` but this can changed with such a configuration:

    .. code-block:: yaml

        virt:
            images: /data/my/vm/images/

    .. _disk element: https://libvirt.org/formatdomain.html#elementsDisks
    .. _graphics element: https://libvirt.org/formatdomain.html#elementsGraphics
    cSsh|]}|d�qS)rKr�rG�guestrrr�	<setcomp>�
�zinit.<locals>.<setcomp>�guestscSsh|]}|dd�qS)rLr0rrrrrr�
scS�h|]	}|D]}|�qqSrr�rG�y�xrrrr�
s���cS�g|]
}|dd���qS�rL�domainsrJrrrrrI�
s�zinit.<locals>.<listcomp>r�#No supported hypervisors were foundrr?rzUsing hypervisor %sr�rMr�zCreating disk for VM [ %s ]: %sr�zMvirt.init does not support image template in conjunction with esxi hypervisorzGenerating libvirt XML for %s�{}/{}r0r>r%rt)r%r��r�r�cst�|���d�����dS)Nr�)r�r#�r��r�r'r0r�r�r�rrr�s�zinit.<locals>.seederr�Fr�N)r=Zhostname_propertyr�)r�r�r�r�r�r�r�z3Unsupported hypervisor when handling disk image: {}zGenerating VM XMLZhvm�x86_64z"New virtual machine definition: %szStarting VM %sTr)r*�
_capabilities�sortedr1rrr�rr�r#r%rwr�r(r�r)r�r�r�r
rq�	defineXMLrrr�rr�r5�create).r0rrrwr�r�startrMrRr��seedr�r�r�r�rrKrLrr!rrrrarbrcrdr'r)�capsZos_types�archesZvirt_hypervisor�hypervisorsr`r_Z_diskr�r6r�r�r�r%r�Zvm_xmlr�rr r�init�s�$���	��



�
���



����r+c
Cs�|�d�}|�d�}t�|d�}t�|d�}|�di�}|�di�}|�di��dd�}|�di��dd�}	|r>|�dd�|rF|�dd�||kou|duou|duou|�d	�|�d	�kou|�d
d�|�d
d�kou|�d�|�d�kou||	kS)
zM
    Test if two disk elements should be considered like the same device
    rlTr�r�r4r5r7NrBr�rMrm)rX�xmlutil�to_dictr#r�)
Zdisk1Zdisk2Ztarget1Ztarget2Z
disk1_dictZ
disk2_dictZsource1_dictZsource2_dictZio1Zio2rrr�_disks_equalos2

������r.cCsHdd�}dd�}||�}||�}|p|p||k}||�||�ko#|S)zR
    Test if two interface elements should be considered like the same device
    cSs�|�d�}|dur|jni}d|vrdn|jd}dd�dd�dd�d	d�d
�}||dur3|||�nd|�d�durE|�d�jdd�Sdd�S)
zC
        Filter out elements to ignore when comparing nics
        r�Nr�rhcS�
|�d�S)Nr�r���nrrrr��
z2_nics_equal.<locals>._filter_nic.<locals>.<lambda>cSr/)Nr�r�r0rrrr�r2cSr/)Nrmr�r0rrrr�r2cSst|�d��S)Nrj)�_format_pci_addressrXr0rrrr�s)r�r�Zdirect�hostdevrkr�)rXrs)rw�source_nodeZ
source_attribZsource_typeZsource_gettersrrr�_filter_nic�s"
����
�z _nics_equal.<locals>._filter_niccSs&|�d�dur|�d�jd��SdS)Nrirj)rXrsr�)rwrrr�_get_mac�s
���z_nics_equal.<locals>._get_macr)Znic1Znic2r6r7Zmac1Zmac2Z
macs_equalrrr�_nics_equal�sr8cCs(dd�}t�||�d�t�||�d�kS)zK
    Test if two graphics devices should be considered the same device
    cSs�t�|�}ddddgd�dddgd�dddgd�g}|D]%}|�|d	�}|d
}|durA||jvrA|j||dvrA|j�|�q|S)
z�
        When the domain is running, the graphics element may contain additional properties
        with the default values. This function will strip down the default values.
        r�r}Z5900z-1)r`rs�valuesrjz	127.0.0.1r|r`rsNr9)r�r�rXrsr�)ZgfxZgfx_copy�defaultsr�r`rsrrr�_filter_graphics�s
��z)_graphics_equal.<locals>._filter_graphicsT)r,r-)Zgfx1Zgfx2r;rrr�_graphics_equal�s�r<cC�dd�}||�||�kS)zK
    Test if two hostdevs devices should be considered the same device
    cSsn|�d�}d|i}|dkr |�d�}dD]	}|�|�||<q|S|dkr5dD]}|�d|��d�||<q&|S)	z�
        When the domain is running, the hostdevs element may contain additional properties.
        This function will only keep the ones we care about
        rhr@z./source/addressr|rH)rIrJz	./source/r=�r#rX)rmr��
definitionZaddress_node�attrrrr�_filter_hostdevs�s
�
�z)_hostdevs_equal.<locals>._filter_hostdevsr)�dev1�dev2rArrr�_hostdevs_equal�srDcs�dd��ggggd�}t�|�}|D]7����fdd�|D�}|r;|�|d�|d�|d�|d�|d�q|d	���|d���q||d
<|S)a,
    Compare lists to extract the changes

    :param old: old list
    :param new: new list
    :return: a dictionary with ``unchanged``, ``new``, ``deleted`` and ``sorted`` keys

    The sorted list is the union of unchanged and new lists, but keeping the original
    order from the new list.
    cSs(t�|�}d|_|��D]}d|_q|S)zM
        Remove the XML indentation to compare XML trees more easily
        N)r�r�rY�iter�tail)r`Z	node_copy�itemrrr�_remove_indents

z#_diff_lists.<locals>._remove_indent)�	unchanged�new�deletedr#cs"g|]
}��|�����r|�qSrr�rGrG�rH�
comparator�new_itemrrrIs��z_diff_lists.<locals>.<listcomp>rrIr#rJrK)r�r�rr/)�oldrJrN�diffZold_devicesr�rrMr�_diff_lists�s

�rRcCs4t|�D]}|�tj|��}||vr|SqdS)z�
    Compute the disk target name for a given prefix.

    :param targets: the list of already computed targets
    :param disks: the number of disks
    :param prefix: the prefix of the target name, i.e. "hd"
    N)r��string�ascii_lowercase)riZdisks_countrkrjr3rrrrT"s�rTcsrg}gd�}|D]*}|�d�}|�d���fdd�|D�d}t|t|�|�}|�d|�|�|�qt||t�S)z�
    Compare disk definitions to extract the changes and fix target devices

    :param old: list of ElementTree nodes representing the old disks
    :param new: list of ElementTree nodes representing the new disks
    )r0r r.r3r/Zubdrlrmcsg|]	}��|�r|�qSr)r�rL�rlrrrI@�z$_diff_disk_lists.<locals>.<listcomp>r)rXr#rTr1rr/rRr.)rPrJri�prefixesrMZtarget_noderk�
new_targetrrUr�_diff_disk_lists1s


rYcC�t||t�S)z�
    Compare network interface definitions to extract the changes

    :param old: list of ElementTree nodes representing the old interfaces
    :param new: list of ElementTree nodes representing the new interfaces
    )rRr8�rPrJrrr�_diff_interface_listsH�r\cCrZ)z�
    Compare graphic devices definitions to extract the changes

    :param old: list of ElementTree nodes representing the old graphic devices
    :param new: list of ElementTree nodes representing the new graphic devices
    )rRr<r[rrr�_diff_graphics_listsRr]r^cCrZ)z�
    Compare hostdev devices definitions to extract the changes

    :param old: list of ElementTree nodes representing the old hostdev devices
    :param new: list of ElementTree nodes representing the new hostdev devices
    )rRrDr[rrr�_diff_hostdev_lists\r]r_c	Cs�|durdSt|t�rt|�St�}t�}|�d�D]8}t�d|�}|r:|ttt|�d��t|�d��d��O}q|�	d�rK|�
t|dd���q|�
t|��qt||�}|��dd�|D�}d�
|�S)	zR
    Expand the libvirt cpuset and nodeset values into a list of cpu/node IDs
    Nr�z([0-9]+)-([0-9]+)rr
�^cS�g|]}t|��qSr)rP)rGrrrrrI|rz"_expand_cpuset.<locals>.<listcomp>)rNr�rPrr�rqrrr�r�r��addr.�sortr�)�cpuset�resultZtoremove�partr��cpusrrr�_expand_cpusetfs"
,

rhc	Cs�gd�}|D]}|�|�}|D]
}|�dt|�d���qqt|�d�t�s(dS|d�di�}dD]5}|�|�rgt�}||��D] \}	}
|dkr\|
�d�r\d	d
�|
d��D�|
d<|
|t|	�<qB|||<q2dS)z�
    Expand the cpusets that can't be expanded by the change_xml() function,
    namely the ones that are used as keys and in the middle of the XPath expressions.
    )zcputune/cachetunezcputune/cachetune/monitorzcputune/memorytune�vcpusrN�tuning)�	cachetuneZ
memorytunerk�monitorcSsi|]	\}}t|�|�qSr)rh)rGZmonitor_cpusrlrrr�
<dictcomp>�s��z&_normalize_cpusets.<locals>.<dictcomp>)rprrhr#rNrOrt)r
�dataZxpaths�xpathZnodesr`rj�childrOrdryrrr�_normalize_cpusets�s*
�


���rqcCr=)NcSsR|jd|�d�dur|�d��d�nd|�d�dur%|�d��d�d�Sdd�S)zD
        Filter out elements to ignore when comparing items
        rhr�NZservicer�)rhr}r�)rsrXr#�rGrrr�_filter_serial_or_concole�s���
�z;_serial_or_concole_equal.<locals>._filter_serial_or_concoler)rPrJrsrrr�_serial_or_concole_equal�srtcCrZ)z�
    Compare serial definitions to extract the changes

    :param old: list of ElementTree nodes representing the old serials
    :param new: list of ElementTree nodes representing the new serials
    �rRrtr[rrr�_diff_serial_lists�r]rvcCrZ)z�
    Compare console definitions to extract the changes

    :param old: list of ElementTree nodes representing the old consoles
    :param new: list of ElementTree nodes representing the new consoles
    rur[rrr�_diff_console_lists�r]rwc	CsHd�|�d��dd�|�d��dd�|�d��dd�|�d��dd��S)Nz{}:{}:{}.{}rA�0xr^rBrCrD)r%r#�replace�r`rrrr3�s�r3cCs(|dus|dur
dSt||�|dkS)zC
    return True if the parameters are numbers that are almost
    NFg����MbP?)�abs)rrJrrr�
_almost_equal�sr|cCsb|�d�}i}|D]%}i||<||s.|�|�}|�d|���}t�d|�d�||�||<q	|S)zH
    Compute the device changes between two domain XML definitions.
    r�zdevices/Z_diff_Z_lists)rXrp�globals)�old_xml�new_xml�to_skip�devices_node�changes�dev_typerPrJrrr�_compute_device_changes�s

�r�cCsdd�|�d�D�S)zD
    Get all the pci addresses in the node in 0000:00:00.0 form
    cSsh|]}t|��qSr�r3)rGrjrrrr�rz%_get_pci_addresses.<locals>.<setcomp>�
.//address�rprzrrr�_get_pci_addresses�sr�cs�dd�|��D�}|�d�}i}|D]9}|�d�dkrKt|�d����fdd�|D�}|rKt�|�}|�dd�|�d��d|d	�d
�j�|||<q|S)z�
    Adjust the interface devices matching existing networks.
    Returns the network interfaces XML definition as string mapped to the new device node.
    cSsg|]	}t�|����qSr)rrVrn�rG�netrrrrI�rVz%_correct_networks.<locals>.<listcomp>rgrhr4r�cs0g|]}|�d��d�dkr�t|�@r|�qS)r�r�r4)rXr#r�r��rzrrrI�s
��r�rr0)	�listAllNetworksrpr#r�rXr�tostringrrY)r)r
ZnetworksruZ
device_maprwZ
matching_netsr~rr�r�_correct_networks�s 

�
�r�c#s�i}g}	|��s||	fSg}
|r?t|t�st|t�r?|�d�r?t|t�r)|�d�n|}||kr?|dur?|
�dd|tjgd��|rxt|t�rXd|vrUtt|�d��d�nd}nt|t�rct|d�}t	||�sx|durx|
�dd	|tjgd��t
�|�d
��}
dt
|��|
�i}t|
||�}g}g}|d�d
g�D]v}|�dd���dvr�|�|�q�|�d��d����fdd�|d�dg�D�}|s�|�|�q�|d
}|dd�|�|�|�|�d�}|�d�}|dur�|�d�nd}|�dd�|du�r|�|�|�rt
j|dd|id�q�||dd
<dD]D}||�d
g�D]}|
�|dt�|�gd���q$||�dg�D]}|�|i��|t
�|��}|
�|dtjj�|�gd���q=�q|D]}|
�ddt�|�gd���qa|
D]_}zA|�r|d
n
t||d�|d�}|d}|dv�r�|||<nd d!d"d#�}|�|i�} | �||dg�}!|!�|dd
�W�qttj�y�}"z|	�t|"��WYd}"~"�qtd}"~"ww||	fS)$z.
    Perform the live update of a domain.
    rNr�
setVcpusFlags)r��cmd�argsrrr�setMemoryFlagsrr�rMrJr��r�Zfloppyrlrmcs4g|]}|�dd��kr|�d��d��kr|�qS)r�rMrlrmr>)rGZold_disk�r�r6rrrIH
s�z _update_live.<locals>.<listcomp>rKr�r7rh)rs)rMr�r4�attachDevice�detachDevice�updateDeviceFlagsr�r�)rr�attached�detached�updated)r�r�r�)�isActiverNr�rOr#r/rZVIR_DOMAIN_AFFECT_LIVEr�r|rrVrnr��connectr�rXrr�
SubElementr,�element_to_strr�rNrOr�r��getattr�
setdefaultrrP)#rA�new_descrr�old_mem�old_cpur��test�status�errorsZcommandsZnew_cpuZnew_memZold_descZchanged_devicesr�Zremovable_changesZ	new_disksZnew_diskZmatchingZupdated_diskr5Znew_source_noder�r�ZaddedZremovedZremoved_defr�r3Zdevice_type�actionsZ
device_statusZ
cmd_statusr�rr�r�_update_live

s�"��
��
��	
�


�


��
��
����
�� 
����r�c<sN
dgggd�ggd�d�}t�di|��}t||�}t�|�tj��}d}|�d�}t|||||�}|	durGt	|	�}	|	�dd�durGt
|	|�}t�t||||pPd|t|||�||�
�|�d	��d
�||	||
f
||||d�|���}t||rwdnd
�|r�|�dd�r�dnd}d|vr�d}||d<dd�}dd�}�d
dd��dd��dd�} t�|�d��d�}!t|�d�j�}"�d
d d!�}#�d��fd"d#�	}$�dd$d%�}%d&d'�t���D�}&||&d(<|r�|��|&d)<gd*�}'|&�d+i��d,��r'gd-�}(|&d+d,��D]})|(D]}*|*|)v�r
d|)|*<�qq�|'D]}+|+|&d+d,v�r%d|&d+d,|+<�qt||&�gd(d.d/d0�d1��d2d3d4��d5d6d4��d7d8d4��d9d:|d;��d<d=|d;��|$d>d��|$d>d?��|$d@dA��|$dBd��|$dCd?��t�dDdAdEdFg��|$dGdH��|$dIdJ��|$dKdL��|$dMdN��t�dOdPdQ��|$dRdSdTdFdUg��|%dVdSdU��dWdXdYd0�dZd0�d[��d\d]d^d0�d_d0�d[��t�d`dad��t�dbdcdd��t�dedfdd��dgdhd4��didjdkd0�| d[��dldjdmd0�dn��t�dodjdp��|%dqdjdr��t�dsdjdt��t�dudidv��t�dwdidd��t�dxdidy��dzd{d4��t�d|d{d}��t�d~d{d��d�d�d4��t�d�d�d���t�d�d�d���t�d�d�d���t�d�d�d���t�d�d�dd��t�d�d�d�d�g��|#d�d�d�d�g��|#d�d�d�d�g��t�d�d�d�d�g��|%d�d�d�d�g��|$d�d�dd�g��|#d�d�d�d�g��t�d�d�d�d�g��t�d�d�d�d�g��d�d�d4��d�d�d4��d�d�d4��d�d�d4��d�d�d4��d�d�d4��d�d�d4��d�d�d4��d�d�d4��d�d�d4��|%d�d�drdjg��|%d�d�dr��|%d�d�drd�g��t�d�d�d�d�d�g��t�d�d�d¡�|%d�d�dÃ�t�d�d�d�d�d�g��t�d�d�d¡�|%d�d�d���t�d�d�d�d�g��t�d�d�d¡�t�d�d�d�d�g��t�d�d�d�d�d�g��t�d�d+d��tjd�d+d�tdՍ�t�d�d+d��},|'D]p})|,t�d�|)�d؝d�|)�dڝd�d�g�t�d�|)�dܝd�|)�dڝd�d�g�t�d�|)�dޝd�|)�dڝd�d�g�t�d�|)�d�d�|)�dڝddd�g�|#d�|)�d�d�|)�dڝd�d�g�g7},d�D]}-|,�t�d�|)�d�|-��d�|)�d�|-���q��q@d�D]}-|,�t�d�|-d�|-gd����q�|d�v�r�|,t�d�d�dd�|%d�d�dU�t�d�d�ddd�g�|%d�d�dUd�g�tjd�d�d�d�d0�dՍg7},tjj�||&|,��p�|}|�d��}.t���fd�d��}/|/d�d�g�|/d�d�g�|/d�g�|/d�g�|/d�g�|/�dg��d�}0t|||0�}1|1D]6}2|0|2�si|.� |2�}3|1|2��d��sR|1|2��d��ri|3D]}4|.�!|4��qT|.�"|1|2�d�d}�q4|�r�z{|1�d�r�t#|1�d�d�D]O\}5}4||5��d�}6||5��d�d��dk�r��q|4|1�d�dv�r�|6�r�t$j%�&|6��s�t'||5��q|4|1�d�dv�r�|6�s�t(|||5��q|�s�t�)|�}7t*�+�d	|7�|�,|7�d|�d
<Wntj-�y�}8z|�.�|8�d}8~8ww|�r!t/|||||!|"|0|�\}9}:|�0|9�|:�r!|�1�dg�};|;|:7};|�.�|S(aJ"
    Update the definition of an existing domain.

    :param name: Name of the domain to update
    :param cpu:
        Number of virtual CPUs to assign to the virtual machine or a dictionary with detailed information to configure
        cpu model and topology, numa node tuning, cpu tuning and iothreads allocation. The structure of the dictionary is
        documented in :ref:`init-cpu-def`.

        To update any cpu parameters specify the new values to the corresponding tag. To remove any element or attribute,
        specify ``None`` object. Please note that ``None`` object is mapped to ``null`` in yaml, use ``null`` in sls file
        instead.
    :param mem: Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to
        contain detailed configuration which support memory allocation or tuning. Supported parameters are ``boot``,
        ``current``, ``max``, ``slots``, ``hard_limit``, ``soft_limit``, ``swap_hard_limit``, ``min_guarantee``,
        ``hugepages`` ,  ``nosharepages``, ``locked``, ``source``, ``access``, ``allocation`` and ``discard``. The structure
        of the dictionary is documented in  :ref:`init-mem-def`. Both decimal and binary base are supported. Detail unit
        specification is documented  in :ref:`virt-units`. Please note that the value for ``slots`` must be an integer.

        To remove any parameters, pass a None object, for instance: 'soft_limit': ``None``. Please note  that ``None``
        is mapped to ``null`` in sls file, pass ``null`` in sls file instead.

        .. code-block:: yaml

            - mem:
                hard_limit: null
                soft_limit: null

        .. versionchanged:: 3002

    :param disk_profile: disk profile to use
    :param disks:
        Disk definitions as documented in the :func:`init` function.
        If neither the profile nor this parameter are defined, the disk devices
        will not be changed. However to clear disks set this parameter to empty list.

    :param nic_profile: network interfaces profile to use
    :param interfaces:
        Network interface definitions as documented in the :func:`init` function.
        If neither the profile nor this parameter are defined, the interface devices
        will not be changed. However to clear network interfaces set this parameter
        to empty list.

    :param graphics:
        The new graphics definition as defined in :ref:`init-graphics-def`. If not set,
        the graphics will not be changed. To remove a graphics device, set this parameter
        to ``{'type': 'none'}``.

    :param live:
        ``False`` to avoid trying to live update the definition. In such a case, the
        new definition is applied at the next start of the virtual machine. If ``True``,
        not all aspects of the definition can be live updated, but as much as possible
        will be attempted. (Default: ``True``)

    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    :param boot:
        Specifies kernel, initial ramdisk and kernel command line parameters for the virtual machine.
        This is an optional parameter, all of the keys are optional within the dictionary.

        Refer to :ref:`init-boot-def` for the complete boot parameter description.

        To update any boot parameters, specify the new path for each. To remove any boot parameters, pass ``None`` object,
        for instance: 'kernel': ``None``. To switch back to BIOS boot, specify ('loader': ``None`` and 'nvram': ``None``)
        or 'efi': ``False``. Please note that ``None`` is mapped to ``null`` in sls file, pass ``null`` in sls file instead.

        SLS file Example:

        .. code-block:: yaml

            - boot:
                loader: null
                nvram: null

        .. versionadded:: 3000

    :param boot_dev:
        Space separated list of devices to boot from sorted by decreasing priority.
        Values can be ``hd``, ``fd``, ``cdrom`` or ``network``.

        By default, the value will ``"hd"``.

        .. versionadded:: 3002

    :param numatune:
        The optional numatune element provides details of how to tune the performance of a NUMA host via controlling NUMA
        policy for domain process. The optional ``memory`` element specifies how to allocate memory for the domain process
        on a NUMA host. ``memnode`` elements can specify memory allocation policies per each guest NUMA node. The definition
        used in the dictionary can be found at :ref:`init-cpu-def`.

        To update any numatune parameters, specify the new value. To remove any ``numatune`` parameters, pass a None object,
        for instance: 'numatune': ``None``. Please note that ``None`` is mapped to ``null`` in sls file, pass ``null`` in
        sls file instead.

        .. versionadded:: 3003

    :param serials:
        Dictionary providing details on the serials connection to create. (Default: ``None``)
        See :ref:`init-chardevs-def` for more details on the possible values.

        .. versionadded:: 3003

    :param consoles:
        Dictionary providing details on the consoles device to create. (Default: ``None``)
        See :ref:`init-chardevs-def` for more details on the possible values.

        .. versionadded:: 3003

    :param stop_on_reboot:
        If set to ``True`` the guest will stop instead of rebooting.
        This is specially useful when creating a virtual machine with an installation cdrom or
        an autoinstallation needing a special first boot configuration.
        Defaults to ``False``

        .. versionadded:: 3003

    :param test: run in dry-run mode if set to True

        .. versionadded:: 3001

    :param hypervisor_features:
        Enable or disable hypervisor-specific features on the virtual machine.

        .. versionadded:: 3003

        .. code-block:: yaml

            hypervisor_features:
              kvm-hint-dedicated: True

    :param clock:
        Configure the guest clock.
        The value is a dictionary with the following keys:

        adjustment
            time adjustment in seconds or ``reset``

        utc
            set to ``False`` to use the host local time as the guest clock. Defaults to ``True``.

        timezone
            synchronize the guest to the correspding timezone

        timers
            a dictionary associating the timer name with its configuration.
            This configuration is a dictionary with the properties ``track``, ``tickpolicy``,
            ``catchup``, ``frequency``, ``mode``, ``present``, ``slew``, ``threshold`` and ``limit``.
            See `libvirt time keeping documentation <https://libvirt.org/formatdomain.html#time-keeping>`_ for the possible values.

        .. versionadded:: 3003

        Set the clock to local time using an offset in seconds
        .. code-block:: yaml

            clock:
              adjustment: 3600
              utc: False

        Set the clock to a specific time zone:

        .. code-block:: yaml

            clock:
              timezone: CEST

        Tweak guest timers:

        .. code-block:: yaml

            clock:
              timers:
                tsc:
                  frequency: 3504000000
                  mode: native
                rtc:
                  track: wall
                  tickpolicy: catchup
                  slew: 4636
                  threshold: 123
                  limit: 2342
                hpet:
                  present: False

    :param host_devices:
        List of host devices to passthrough to the guest.
        The value is a list of device names as provided by the :py:func:`~salt.modules.virt.node_devices` function.
        (Default: ``None``)

        .. versionadded:: 3003

    :param autostart:
        If set to ``True`` the host will start the guest after boot.
        (Default: ``False``)

    :return:

        Returns a dictionary indicating the status of what has been done. It is structured in
        the following way:

        .. code-block:: python

            {
              'definition': True,
              'cpu': True,
              'mem': True,
              'disks': {'attached': [list of actually attached disks],
                        'detached': [list of actually detached disks]},
              'nics': {'attached': [list of actually attached nics],
                       'detached': [list of actually detached nics]},
              'errors': ['error messages for failures']
            }

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.update domain cpu=2 mem=1024

    F)r�r�r�)r�r�)r?rMr�rhNr"rz
.//os/typerL)rarbrcrd�on�offrTrrrcSs8tjj�||�|dur|�dd�|�dd�dSdS)N�readonlyrrhZpflash)rNrOr,Z
set_node_textr�r`ryrrr�_set_loader�s
�zupdate.<locals>._set_loadercSs|�d|�dS)Nrp)rr�rrr�
_set_nvram��zupdate.<locals>._set_nvramcs�fdd�}|S)Ncs0�r|��t|��nt|�|_|�dd�dS)N�unit�bytes)rrPrYr���	attr_namerr�_setter�s
z4update.<locals>._set_with_byte_unit.<locals>._setterr)r�r�rr�r�_set_with_byte_unit�sz#update.<locals>._set_with_byte_unitcSsN|�dd�}|dkr|nd}|�d�p|�d�p|j}|r%t|�|���SdS)Nr��KiBr��b�memoryrt)r#rYr�)r`r�ryrrr�_get_with_unit�szupdate.<locals>._get_with_unitcSst|�|_|�dt|��dS)Nr)rPrYrr�rrr�	_set_vcpu�s
zupdate.<locals>._set_vcpur�rz./vcpucSst�||||dd��S)NcSr
rrrrrrr�rz2update.<locals>._yesno_attribute.<locals>.<lambda>)r,�	attribute)r�ror��ignoredrrr�_yesno_attribute�s�z update.<locals>._yesno_attributecs2||t��|�td�}|rtjj�||�|d<|S)N)r�ro�convertr#r�equals�del)r�r|rNrOr,�
del_attribute)r�ror�r��entry)r�r�rr�_memory_parameter�s�z!update.<locals>._memory_parametercs@�fdd�}||t�fdd�|d�}�rtjj��|�|d<|S)Ncs�r
|��|�dS||_dSr�)rrYr�r�rr�_set_cpuset�s
z6update.<locals>._cpuset_parameter.<locals>._set_cpusetcst�r	|����S|j�Sr�)rhr#rYr0r�rrrrVz3update.<locals>._cpuset_parameter.<locals>.<lambda>)r�ror�r#rr�)rhrNrOr,r�)r�ror�r�r�r�rr�r�_cpuset_parameter�s
�z!update.<locals>._cpuset_parametercSsi|]\}}t|�r||�qSr)rQ)rG�krrrrrm	szupdate.<locals>.<dictcomp>rcr!)�platformZhpetZkvmclockZpitZrtcZtscZhypervclockZ	armvtimerrZtimers)�track�
tickpolicy�	frequencyr��present�slew�	threshold�limitrccSr
)Nrrrrrrrr3rzupdate.<locals>.<lambda>)r�ror�zboot:kernelz	os/kernel)r�rozboot:initrdz	os/initrdzboot:cmdlinez
os/cmdlinezboot:loaderr�)r�rorz
boot:nvramzos/nvramrZ
currentMemoryzmem:maxZ	maxMemoryzmem:bootzmem:currentz	mem:slots�slotsr�zmem:hard_limitzmemtune/hard_limitzmem:soft_limitzmemtune/soft_limitzmem:swap_hard_limitzmemtune/swap_hard_limitzmem:min_guaranteezmemtune/min_guaranteezboot_dev:{dev}z
os/boot[$dev]rmzmem:hugepages:{id}:sizez!memoryBacking/hugepages/page[$id]rtZnodesetzmem:hugepages:{id}:nodesetzmem:nosharepageszmemoryBacking/nosharepagescS�|duSr�rr0rrrrR�cS�dSr�r�r1rrrrrS�)r�ror#rz
mem:lockedzmemoryBacking/lockedcSr�r�rr0rrrrXr�cSr�r�rr�rrrrYr�z
mem:sourcezmemoryBacking/sourcez
mem:accesszmemoryBacking/accessr�zmem:allocationzmemoryBacking/allocationzmem:discardzmemoryBacking/discardr�vcpucS�
t|j�Sr��r�rYr0rrrrbr2zcpu:maximumcSr�r�r�r0rrrrer2)r�ror#z
cpu:placementZ	placementz
cpu:cpusetrdzcpu:currentrz	cpu:matchrrzcpu:modez	cpu:check�checkzcpu:model:namez	cpu/modelzcpu:model:fallback�fallbackzcpu:model:vendor_idrmz
cpu:vendorz
cpu/vendorzcpu:topology:socketszcpu/topology�socketszcpu:topology:cores�coreszcpu:topology:threads�threadszcpu:cache:levelz	cpu/cache�levelzcpu:cache:modezcpu:features:{id}zcpu/feature[@name='$id']�policyr0zcpu:vcpus:{id}:enabledzvcpus/vcpu[@id='$id']�enabledr=zcpu:vcpus:{id}:hotpluggableZhotpluggablezcpu:vcpus:{id}:order�orderzcpu:numa:{id}:cpuszcpu/numa/cell[@id='$id']rgzcpu:numa:{id}:memoryzcpu:numa:{id}:discard�discardzcpu:numa:{id}:memAccessZ	memAccesszcpu:numa:{id}:distances:{sid}z6cpu/numa/cell[@id='$id']/distances/sibling[@id='$sid']ryz
cpu:iothreads�	iothreadszcpu:tuning:shareszcputune/shareszcpu:tuning:periodzcputune/periodzcpu:tuning:quotaz
cputune/quotazcpu:tuning:global_periodzcputune/global_periodzcpu:tuning:global_quotazcputune/global_quotazcpu:tuning:emulator_periodzcputune/emulator_periodzcpu:tuning:emulator_quotazcputune/emulator_quotazcpu:tuning:iothread_periodzcputune/iothread_periodzcpu:tuning:iothread_quotazcputune/iothread_quotazcpu:tuning:vcpupin:{id}zcputune/vcpupin[@vcpu='$id']zcpu:tuning:emulatorpinzcputune/emulatorpinzcpu:tuning:iothreadpin:{id}z$cputune/iothreadpin[@iothread='$id']r8z#cpu:tuning:vcpusched:{id}:schedulerzcputune/vcpusched[$id]Z	scheduler�priorityriz"cpu:tuning:vcpusched:{id}:priorityzcpu:tuning:vcpusched:{id}:vcpusz'cpu:tuning:iothreadsched:{id}:schedulerzcputune/iothreadsched[$id]z&cpu:tuning:iothreadsched:{id}:priorityz'cpu:tuning:iothreadsched:{id}:iothreadsz"cpu:tuning:emulatorsched:schedulerzcputune/emulatorschedz!cpu:tuning:emulatorsched:priorityz'cpu:tuning:cachetune:{id}:monitor:{sid}z6cputune/cachetune[@vcpus='$id']/monitor[@vcpus='$sid']z cpu:tuning:memorytune:{id}:{sid}z1cputune/memorytune[@vcpus='$id']/node[@id='$sid']Z	bandwidthzclock:offsetzclock:adjustmentZ
adjustment)r�zclock:timezonez
clock:timers:z:trackzclock/timer[@name='z']r�z:tickpolicyr�z
:frequencyr�z:modez:presentr�)r�r�r�r�z
']/catchup)r�rhrtz cpu:tuning:cachetune:{id}:{sid}:z1cputune/cachetune[@vcpus='$id']/cache[@id='$sid'])r=r�rirznumatune:memory:modeznumatune/memoryznumatune:memory:nodesetznumatune:memnodes:{id}:modeznumatune/memnode[@cellid='$id']Zcellidznumatune:memnodes:{id}:nodesetz&hypervisor_features:kvm-hint-dedicatedzfeatures/kvm/hint-dedicatedr�cSr
)Nr�r�rrrrrr,rr�cst�fdd�|D��S)Nc3s�|]
}��|�duVqdSr�r�)rGr1��func_localsrrr�9s�z/update.<locals>._skip_update.<locals>.<genexpr>)r�)�namesr�rr�_skip_update8szupdate.<locals>._skip_updaterR�disk_profiler��nic_profilerrarbrd)rMr�rr+r,r4rKrJr#rMr�r�r�z%Update virtual machine definition: %sr?r�rr��NN)2r*r5rrVrnrror#r�r
rrqrZOSTyperX�
set_autostartr�rYrRrtr�r9rqr,r�Z
int_attributerPr/rNrOZ
change_xmlr�rpr�extendrSr(r�r)r�r�r�rr�r$rr�r�r�r�)<r0rrr�rRr�r�rr�rrr�r!rrrarbrcrd�	autostartr'r�r)rAr
Zneed_updaterZ	all_disksr�rr�r�r�r�r�r�r�r�rnZtimer_namesr�Ztimerr�Z
timer_nameZparams_mappingr@r�r�r�r�r�rPrGr�r��xml_descr�Zlive_statusr�Z
status_errorsr)r�r�r�rr��
s�x
�



����




���
�����
	�

��
��������������!��'��,�-�.�/�1��6�7�
8�9�:�;�<�=�>�?�@�A�B�C�D�E�F
��I
��L��R
��U
��X
��[
��^
��a��g�h�i�j�k�l�m�n�o�p�q��
w�x��~��������������������!���$���*���0��1��2��5

�

�

�

�

�� 
���	��


�����



�

$��
��

���
r�cKs>g}tdi|��}t|dd�D]	}|�|���q|��|S)a�
    Return a list of available domains.

    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.list_domains
    T�r-Nr�r*r5r/r0r��r'r2r)rZrrr�list_domainsusr�cK�@g}tdi|��}t|ddd�D]	}|�|���q|��|S)a�
    Return a list of names for active virtual machine on the minion

    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.list_active_vms
    TF�r-r,Nrr�r�rrr�list_active_vms��r�cKr�)a�
    Return a list of names for inactive virtual machine on the minion

    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.list_inactive_vms
    TF)r-r+Nrr�r�rrr�list_inactive_vms�r�r�cKsddd�}i}tdi|��}|r||t||��||<nt|dd�D]}|||�||��<q |��|S)a�
    Return detailed information about the vms on this hyper in a
    list of dicts:

    :param vm_: name of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    .. code-block:: python

        [
            'your-vm': {
                'cpu': <int>,
                'maxMem': <int>,
                'mem': <int>,
                'state': '<state>',
                'cputime' <int>
                },
            ...
            ]

    If you pass a VM name in as an argument then it will return info
    for just the named VM, otherwise it will return all VMs.

    CLI Example:

    .. code-block:: bash

        salt '*' virt.vm_info
    cSsr|��}|dt|d�t||�t|�t|�t|�t|�t|�t|�t	|�t|d�t|d�t
�|dd�d�
S)z/
        Compute the infos of a domain
        rrrr
r�unknown)
r�cputimerRrrurTr	rercr]ZmaxMemrr�)rr�r�r�rzr[r�rfrdra�VIRT_STATE_NAME_MAPr#)r)rZr�rrr�_info�s


�zvm_info.<locals>._infoTr�Nr�r*r5r0r���vm_r'r�rr)rArrr�vm_info�s'r�cK�`dd�}i}tdi|��}|r|t||��||<nt|dd�D]
}||�||��<q|��|S)af
    Return list of all the vms and their state.

    If you pass a VM name in as an argument then it will return info
    for just the named VM, otherwise it will return all VMs.

    :param vm_: name of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.vm_state <domain>
    cSs d}|��}t�|dd�}|S)z&
        Compute domain state
        r^rr�)rr�r#)rZr�r�rrrr�)szvm_state.<locals>._infoTr�Nrr�r�rrr�vm_states	rc	CsF|��}|d|dt|d�|d|d|d|d|dd	�}|S)
zP
    Internal variant of node_info taking a libvirt connection as parameter
    rrrr
�rrr)ZcpucoresZcpumhzZcpumodelrgZ
cputhreadsZ	numanodesZ	phymemoryr�)�getInforP)r)r�rrrr�
_node_info=s
�
rcK�"tdi|��}t|�}|��|S)a�
    Return a dict with information about this node

    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.node_info
    Nr)r*rr��r'r)rrrr�	node_infoOsrc	Cs"|��}g}|D�]}t�|���}t|���hd�@sqdd�|���i}d|��vrU|�d�j}|dkr7q|�	|�d�j|�d�j||�d	��
d
�d��|�|�q|�d�}|�
d
���}|�d�}	|	�
d
���}
|�	|�
�||
d��|jr�|j|d<|	jr�|	j|d<d|��vr�d�t|�d�j�t|�d�j�t|�d�j�|�d�j�|d<|�d�}|dur�|j|d<dd�|�d�D�}|r�||d<|�d �}
|
dur�t|
�|d!<nd"|��vr�d#�t|�d�j�t|�d$�j��|d<|d%ko�|
d&v}|�d'�du�r|�s|�|�q|S)(z�
    List the host available devices, using an established connection.

    :param conn: the libvirt connection handle to use.

    .. versionadded:: 3003
    >r�rEr@r(r{r�z	.//parentZcomputerz.//interfacer�z.//linkr�)r0rjzdevice namer�rFr=rG)r0rmrnrIrJr@z{:04x}:{:02x}:{:02x}.{}z	.//domainz.//busz.//slotz.//functionrjz.//classNz	PCI classcSrarr�)rGZvfrrrrI����z!_node_devices.<locals>.<listcomp>zD./capability[@type='pci']/capability[@type='virt_functions']/addresszvirtual functionszC./capability[@type='pci']/capability[@type='phys_function']/addresszphysical functionrEz{:03}:{:03}z	.//deviceZ0x1d6b)Z0x0001Z0x0002Z0x0003z!.//capability[@type='pci-bridge'])ZlistAllDevicesrrVrnrrXr�rXrYr�r#r/r�r0r%r�rpr3)r)r�Z
devices_infosrmr��infosr�Zvendor_nodermZproduct_nodernZ
class_nodeZvf_addressesr�Zlinux_usb_hostrrr�
_node_devicesis�
�

��


�


�

������
�r
cKr)a
    List the host available devices.

    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 3003
    Nr)r*r
r�)r'r)Zdevsrrr�node_devices�s
rcK�(tdi|��}tt||��}|��|S)a�
    Return info about the network interfaces of a named vm

    :param vm_: name of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_nics <domain>
    Nr)r*rzr5r�)r�r'r)rurrr�get_nics��r
cKs*t�t|fi|���}dd�|�d�D�S)a�
    Return a list off MAC addresses from the named vm

    :param vm_: name of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_macs <domain>
    cSr�)rjr�r�rrrrI
r�zget_macs.<locals>.<listcomp>zdevices/interface/mac�rrVrWrp)r�r'rvrrr�get_macs�srcKr)a�
    Returns the information on vnc for a given vm

    :param vm_: name of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_graphics <domain>
    Nr)r*r�r5r�)r�r'r)rrrr�get_graphicsrrcKs6tdi|��}ztt||��}|W|��S|��w)a�
    Returns the information on the loader for a given vm

    :param vm_: name of the domain
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_loader <domain>

    .. versionadded:: 2019.2.0
    Nr)r*r�r5r�)r�r'r)r	rrr�
get_loader+s
rcKs*tdi|��}t|t||��}|��|S)a�
    Return the disks of a named vm

    :param vm_: name of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_disks <domain>
    Nr)r*r�r5r�)r�r'r)rRrrr�	get_disksD�rc	Ks�tdi|��}t||�}t�|��dd�dkrdStj}|r$|tjB}|�|d|�}|�|dtj	�}|�
�||koBdkSS)a�
    Changes the amount of memory allocated to VM. The VM must be shutdown
    for this to work.

    :param vm_: name of the domain
    :param memory: memory amount to set in MB
    :param config: if True then libvirt will be asked to modify the config as well
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.setmem <domain> <size>
        salt '*' virt.setmem my_domain 768
    rr�rFrNr)r*r5r�r#rrZVIR_DOMAIN_MEM_MAXIMUM�VIR_DOMAIN_AFFECT_CONFIGr��VIR_DOMAIN_AFFECT_CURRENTr�)	r�r�r�r'r)rZr��ret1�ret2rrr�setmem_s

rc	Ks�tdi|��}t||�}t�|��dd�dkrdStj}|r$|tjB}|�||�}|�|tj	�}|�
�||ko>dkSS)a*
    Changes the amount of vcpus allocated to VM. The VM must be shutdown
    for this to work.

    If config is True then we ask libvirt to modify the config as well

    :param vm_: name of the domain
    :param vcpus: integer representing the number of CPUs to be assigned
    :param config: if True then libvirt will be asked to modify the config as well
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.setvcpus <domain> <amount>
        salt '*' virt.setvcpus my_domain 4
    rr�rFNr)r*r5r�r#rrZVIR_DOMAIN_VCPU_MAXIMUMrr�rr�)	r�rir�r'r)rZr�rrrrr�setvcpus�s

rcCsJ|��d}|d8}t|dd�D]}|��dkr"||��dd8}q|S)zN
    Internal variant of freemem taking a libvirt connection as parameter
    r�Tr�rr
r�rr5�IDr)r)rrZrrr�_freemem�s�rcKr)a�
    Return an int representing the amount of memory (in MB) that has not
    been given to virtual machines on this node

    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.freemem
    Nr)r*rr�)r'r)rrrr�freemem��rcCs>|��d}t|dd�D]}|��dkr||��d8}q|S)zN
    Internal variant of freecpu taking a libvirt connection as parameter
    r
Tr�rrr)r)rgrZrrr�_freecpu�s�r!cKr)a�
    Return an int representing the number of unallocated cpus on this
    hypervisor

    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.freecpu
    Nr)r*r!r�)r'r)rgrrr�freecpu�r r"cKs6tdi|��}t|�t|�t|�t�d�}|��|S)a�
    Return the node_info, vm_info and freemem

    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.full_info
    )r"rrr�Nr)r*r!rrr�r�rrrr�	full_info
s�r#cKs@tdi|��}t|tj�r|�d�nt||��d�}|��|S)a�
    Returns the XML for a given vm

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_xml <domain>
    rNr)r*rNrZ	virDomainrnr5r�)r�r'r)r�rrrrW)s
��rWcKs�tdi|��}t|�}tdd�dd�|dD�D��}t|�dkr%td��|s1d|vr-dn|d}d	t|d	|gd
�id	td	|�id�}tdd
i�}|�dg�D]}t|||gd
�|d|<qP|�dg�D]}t||�|d|<qe|S)ad
    Return the virt profiles for hypervisor.

    Currently there are profiles for:

    - nic
    - disk

    :param hypervisor: override the default machine type.
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_profiles
        salt '*' virt.get_profiles hypervisor=vmware
    cSrrrrrrrrhs���zget_profiles.<locals>.<setcomp>cSrrrJrrrrrIjsz get_profiles.<locals>.<listcomp>rrrrr�N)rMrwrrrMrwr)	r*r"r#r1rr�rrr#)rr'r)r(r*r3Zvirtconfr�rrr�get_profilesHs(���r$cK�0tdi|��}t||�}|��dk}|��|S)a�
    Send a soft shutdown signal to the named vm

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.shutdown <domain>
    rNr)r*r5rr��r�r'r)rZr3rrrr��

cKr%)a�
    Pause the named vm

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pause <domain>
    rNr)r*r5Zsuspendr�r&rrr�pause�r'r(cKr%)a�
    Resume the named vm

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.resume <domain>
    rNr)r*r5�resumer�r&rrrr)�r'r)cK�,tdi|��}t||���dk}|��|S)a�
    Start a defined domain

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.start <domain>
    rNr)r*r5r%r��r0r'r)r3rrrr&��r&cKr*)a�
    Hard power down the virtual machine, this is equivalent to pulling the power.

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.stop <domain>
    rNr)r*r5rr�r+rrr�stop�r,r-cKs0tdi|��}t||��tj�dk}|��|S)a�
    Reboot a domain via ACPI request

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.reboot <domain>
    rNr)r*r5�rebootrZVIR_DOMAIN_REBOOT_DEFAULTr�r+rrrr.
sr.cKs2tdi|��}t||�}|�d�dk}|��|S)a�
    Reset a VM by emulating the reset button on a physical machine

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.reset <domain>
    rNr)r*r5�resetr�r&rrrr/(s

r/cKs>tdi|��}t||�}|�ddgd�dd�dk}|��|S)a�
    Sends CTRL+ALT+DEL to a VM

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.ctrl_alt_del <domain>
    r)��8�orNr)r*r5ZsendKeyr�r&rrr�ctrl_alt_delHs

r3cKs*tdi|��}|�|d�du}|��|S)a
    Start a transient domain based on the XML passed to the function

    :param xml: libvirt XML definition of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.create_xml_str <XML in string format>
    rNr)r*�	createXMLr���xmlr'r)r3rrr�create_xml_strdrr7cK�lz+tjj�|d��}ttjj�|���fi|��Wd�WS1s$wYWdSty5YdSw)aP
    Start a transient domain based on the XML-file path passed to the function

    :param path: path to a file containing the libvirt XML definition of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.create_xml_path <path to XML file on the node>
    �rNF)	rNrOr��fopenr7r��
to_unicode�readr��r�r'�fp_rrr�create_xml_paths��(��r?cKs(tdi|��}|�|�du}|��|S)a 
    Define a persistent domain based on the XML passed to the function

    :param xml: libvirt XML definition of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.define_xml_str <XML in string format>
    Nr)r*r$r�r5rrr�define_xml_str�rr@cKr8)aS
    Define a persistent domain based on the XML-file path passed to the function

    :param path: path to a file containing the libvirt XML definition of the domain
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.define_xml_path <path to XML file on the node>

    r9NF)	rNrOr�r:r@r�r;r<r�r=rrr�define_xml_path�s��(��rAcCsL|��dkrdnd}|r|ntdd|�}|�t|��}|�|d�du}|S)z^
    Same function than define_vml_xml_str but using an already opened libvirt connection
    ZESXr��0rr�rN)ZgetTyperr�rPr4)r)r6r�Zdefault_poolZpoolnamer3rrrr��s�r�c
Ksdtdi|��}d}z#z	t|||d�}Wnty%}zt|����d}~wwW|��|S|��w)a�
    Define a volume based on the XML passed to the function

    :param xml: libvirt XML definition of the storage volume
    :param pool:
        storage pool name to define the volume in.
        If defined, this parameter will override the configuration setting.

        .. versionadded:: 3001
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.define_vol_xml_str <XML in string format>

    The storage pool where the disk image will be defined is ``default``
    unless changed with the pool parameter or a configuration like this:

    .. code-block:: yaml

        virt:
            storagepool: mine
    FrNr)r*r�rrr�r�)r6r�r'r)r3r�rrr�define_vol_xml_str�s$���
�rCcKspz-tjj�|d��}ttjj�|���fd|i|��Wd�WS1s&wYWdSty7YdSw)a�
    Define a volume based on the XML-file path passed to the function

    :param path: path to a file containing the libvirt XML definition of the volume
    :param pool:
        storage pool name to define the volume in.
        If defined, this parameter will override the configuration setting.

        .. versionadded:: 3001
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.define_vol_xml_path <path to XML file on the node>

    r9r�NF)	rNrOr�r:rCr�r;r<r�)r�r�r'r>rrr�define_vol_xml_paths���(��rDcKsVt�}t||�}tj�|�jsd}|�d|�d�}n|}t||fi|��}|��|S)aW
    Shared storage migration

    :param vm_: domain name
    :param target: target libvirt URI or host name

    :param kwargs:
        - live:            Use live migration. Default value is True.
        - persistent:      Leave the domain persistent on destination host.
                           Default value is True.
        - undefinesource:  Undefine the domain on the source host.
                           Default value is True.
        - offline:         If set to True it will migrate the domain definition
                           without starting the domain on destination and without
                           stopping it on source host. Default value is False.
        - max_bandwidth:   The maximum bandwidth (in MiB/s) that will be used.
        - max_downtime:    Set maximum tolerable downtime for live-migration.
                           The value represents a number of milliseconds the guest
                           is allowed to be down at the end of live migration.
        - parallel_connections: Specify a number of parallel network connections
                           to be used to send memory pages to the destination host.
        - compressed:      Activate compression.
        - comp_methods:    A comma-separated list of compression methods. Supported
                           methods are "mt" and "xbzrle" and can be  used in any
                           combination. QEMU defaults to "xbzrle".
        - comp_mt_level:   Set compression level. Values are in range from 0 to 9,
                           where 1 is maximum speed and 9 is  maximum compression.
        - comp_mt_threads: Set number of compress threads on source host.
        - comp_mt_dthreads: Set number of decompress threads on target host.
        - comp_xbzrle_cache: Set the size of page cache for xbzrle compression in bytes.
        - copy_storage:    Migrate non-shared storage. It must be one of the following
                           values: all (full disk copy) or incremental (Incremental copy)
        - postcopy:        Enable the use of post-copy migration.
        - postcopy_bandwidth: The maximum bandwidth allowed in post-copy phase. (MiB/s)
        - username:        Username to connect with target host
        - password:        Password to connect with target host

        .. versionadded:: 3002

    CLI Example:

    .. code-block:: bash

        salt '*' virt.migrate <domain> <target hypervisor URI>
        salt src virt.migrate guest qemu+ssh://dst/system
        salt src virt.migrate guest qemu+tls://dst/system
        salt src virt.migrate guest qemu+tcp://dst/system

    A tunnel data migration can be performed by setting this in the
    configuration:

    .. code-block:: yaml

        virt:
            tunnel: True

    For more details on tunnelled data migrations, report to
    https://libvirt.org/migration.html#transporttunnel
    rz://z/system)r*r5r�r�rUrVr�r�)r�rlr'r)rZ�protor�r3rrr�migrate7s=
rFc
CsXt�}t||�}z|��Wntjy%}z
|��t|����d}~ww|��dS)a
    Starts post-copy migration. This function has to be called
    while live migration is in progress and it has been initiated
    with the `postcopy=True` option.

    CLI Example:

    .. code-block:: bash

        salt '*' virt.migrate_start_postcopy <domain>
    N)r*r5ZmigrateStartPostCopyrrr�rr�)r�r)rZr�rrr�migrate_start_postcopy�s
��rGc		Cs|��D]�\}}|d}|d}|d��ddd�}tj�|�rJ|sJtjj�t	j
gd�t	jd���d�}|d|dkrJ|d|dkrJd	Stj�
tj�|��s]t�tj�|��tj�|�rht�|�t	�d
dd|||g�t�}t	�d
djdi|��|g�qdS)a�
    Non shared migration requires that the disks be present on the migration
    destination, pass the disks information via this function, to the
    migration destination before executing the migration.

    :param disks: the list of disk data as provided by virt.get_disks
    :param force: skip checking the compatibility of source and target disk
                  images if True. (default: False)

    CLI Example:

    .. code-block:: bash

        salt '*' virt.seed_non_shared_migrate <disks>
    r7r8r:rN)r�rrLr�rFr�r%z-f�chownz{user}:{group}Tr)rtr�r(r��isfilerNrOr�r�r�r�r�r��isdirr�r�r�callr�r%)	rR�force�_rnroZformrtZpreZcredsrrr�seed_non_shared_migrate�s.
���
rNr�cKsVtdi|��}t||�}d}|dkr|�d�dk}n|dkr%|�d�dk}|��|S)a�
    Set the autostart flag on a VM so that the VM will start with the host
    system on reboot.

    :param vm_: domain name
    :param state: 'on' to auto start the VM, 'off' to mark the VM not to be
                  started when the host boots
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt "*" virt.set_autostart <domain> <on | off>
    Fr�rrr�Nr)r*r5�setAutostartr�)r�r�r'r)rZr3rrrr��s
r�cKsNtdi|��}t||�}ttdd�r|�tj�dk}n|��dk}|��|S)a&
    Remove a defined vm, this does not purge the virtual machine image, and
    this only works if the vm is powered down

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.undefine <domain>
    �VIR_DOMAIN_UNDEFINE_NVRAMFrNr)r*r5r�r�
undefineFlagsrP�undefiner�r&rrrrR�s
rRcKs�tdi|��}t||�}t||�}t�|��dd�dkr%|��dkr%dSt�}|D]�}|s7||ddvr7q*||�dd�r_t�	d�||d	t
d
�d�}	t�d|	�td
|	dd�q*t
j�||d	�r�t
�||d	�|�t
j�||d	��q*t�d||d	�}
|
r�|
�d�}d}||��vr�|�|�}|r�|
�d�|��vr�|�|
�d��}
|
��q*|r�|D]}t�|�q�ttdd�r�z|�tj �Wnt!y�|�"�Ynw|�"�|�#�dS)a	
    Recursively destroy and delete a persistent virtual machine, pass True for
    dir's to also delete the directories containing the virtual machine disk
    images - USE WITH EXTREME CAUTION!

    :param vm_: domain name
    :param dirs: pass True to remove containing directories
    :param removables: pass True to remove removable devices

        .. versionadded:: 2019.2.0
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.purge <domain>
    rr�rFrhr�r�rr7r�NzDestroying VM ZFS volume %szzfs.destroyT)r0rLz ^(?P<pool>[^/]+)/(?P<volume>.*)$r�r�rPr)$r*r5r�r�r#rrrrF�sleepr1rrr(r�r)rrbr�rqrrr�r�r�r�r��delete�shutil�rmtreer�rrQrPr$rRr�)r��dirsZ
removablesr'r)rZrR�directoriesrMZfs_name�matcherr�r�r�Zdir_rrr�purgesP




��rZcCstdS)z�
    Returns the virtual machine type as a string

    CLI Example:

    .. code-block:: bash

        salt '*' virt.virt_type
    Zvirtual)r&rrrr�	virt_typeWs
r[cCs$tj�d�sdSdtdtd�vS)zE
    Returns a bool whether or not this node is a KVM hypervisor
    z/dev/kvmF�libvirtdr��ps)r(r�r)rr&rrrr�
_is_kvm_hyperdsr^cCs�ztddkr
WdSWn
tyYdSwz.tjj�d��}dtjj�|���vr4	Wd�WdSWd�n1s>wYWn
t	yNYdSwdt
dtd	�vS)
zE
    Returns a bool whether or not this node is a XEN hypervisor
    Zvirtual_subtypezXen Dom0Fz
/proc/modulesZxen_Nr\r�r])r&�KeyErrorrNrOr�r:r�r;r<r�r)r>rrr�
_is_xen_hyperms&������r`cCs&gd�}dd�|D�}|r|dSdS)aL
    Returns the name of the hypervisor running on this node or ``None``.

    Detected hypervisors:

    - kvm
    - xen
    - bhyve

    CLI Example:

    .. code-block:: bash

        salt '*' virt.get_hypervisor

    .. versionadded:: 2019.2.0
        the function and the ``kvm``, ``xen`` and ``bhyve`` hypervisors support
    )rr%r=cSs*g|]}ttjtd|�d���r|�qS)Z_is_Z_hyper)r��sys�modules�__name__)rGZhyperrrrrI�s��z"get_hypervisor.<locals>.<listcomp>rNr)r*rerrr�get_hypervisor�s
�rdcCs\d}z!tjddgtjd���d}ttjj�|��	d�d�dk}W|St
y-Y|Sw)NFZsysctlz
hw.vmm.creater�rr�r)r�r�r�r�r1rNrOr�r�r�r�)Zvmm_enabledr�rrr�_is_bhyve_hyper�s
��"��recCstrt�p
t�p
t�SdS)z�
    Returns a bool whether or not this node is a hypervisor of any kind

    CLI Example:

    .. code-block:: bash

        salt '*' virt.is_hyper
    F)rr`r^rerrrr�is_hyper�s
rfcsptdi|��}|��d��fdd�}i}|r!|t||��||<nt|dd�D]
}||�||��<q'|��|S)a*
    Return cputime used by the vms on this hyper in a
    list of dicts:

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    .. code-block:: python

        [
            'your-vm': {
                'cputime' <int>
                'cputime_percent' <int>
                },
            ...
            ]

    If you pass a VM name in as an argument then it will return info
    for just the named VM, otherwise it will return all VMs.

    CLI Example:

    .. code-block:: bash

        salt '*' virt.vm_cputime
    r
csR|��}t|d�}t|d�}d}|rd|�|}t|d�t|d��d�S)z2
        Compute cputime info of a domain
        rrrgH�����z>z.0f)r��cputime_percent)rr�)rZr�rir�rg�Z	host_cpusrrr��s

�zvm_cputime.<locals>._infoTr�Nr)r*rr5r0r�)r�r'r)r�rrArrhr�
vm_cputime�s#ricKr)a
    Return combined network counters used by the vms on this hyper in a
    list of dicts:

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    .. code-block:: python

        [
            'your-vm': {
                'rx_bytes'   : 0,
                'rx_packets' : 0,
                'rx_errs'    : 0,
                'rx_drop'    : 0,
                'tx_bytes'   : 0,
                'tx_packets' : 0,
                'tx_errs'    : 0,
                'tx_drop'    : 0
                },
            ...
            ]

    If you pass a VM name in as an argument then it will return info
    for just the named VM, otherwise it will return all VMs.

    CLI Example:

    .. code-block:: bash

        salt '*' virt.vm_netstats
    c	Ss�t|�}ddddddddd�}|��D]_}d|vrr|d}|�|�}|d|d7<|d|d7<|d|d7<|d	|d
7<|d|d7<|d
|d7<|d|d7<|d|d7<q|S)z3
        Compute network stats of a domain
        r)�rx_bytes�
rx_packets�rx_errs�rx_drop�tx_bytes�
tx_packets�tx_errs�tx_droprlrjrkrrlr
rmrrnrrorrprrqr)rzr9ZinterfaceStats)rZrur3Zattrsrm�statsrrrr�$s0�

�zvm_netstats.<locals>._infoTr�Nrr�r�rrr�vm_netstats�s*rscsr�fdd���fdd�}i}td	i���}|r!|t||��||<nt|ddd�D]
}||�||��<q(|��|S)
a�
    Return disk usage counters used by the vms on this hyper in a
    list of dicts:

    :param vm_: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    .. code-block:: python

        [
            'your-vm': {
                'rd_req'   : 0,
                'rd_bytes' : 0,
                'wr_req'   : 0,
                'wr_bytes' : 0,
                'errs'     : 0
                },
            ...
            ]

    If you pass a VM name in as an argument then it will return info
    for just the named VM, otherwise it will return all VMs.

    CLI Example:

    .. code-block:: bash

        salt '*' virt.vm_blockstats
    cs*t�t|fi����}dd�|�d�D�S)zO
        Extract the disk devices names from the domain XML definition
        cSr�)rmr�)rGrlrrrrIyr�z7vm_diskstats.<locals>.get_disk_devs.<locals>.<listcomp>zdevices/disk/targetr)rZrv)r'rr�
get_disk_devstsz#vm_diskstats.<locals>.get_disk_devscs��|�}dddddd�}|D]9}|�|�}|d|d7<|d|d7<|d|d7<|d|d	7<|d
|d7<q|S)z4
        Compute the disk stats of a domain
        r)�rd_req�rd_bytes�wr_req�wr_bytes�errsrurvrrwr
rxrryr)Z
blockStats)rZrRr3rMrr)rtrrr�{s
zvm_diskstats.<locals>._infoTFr�Nrr�r�r)rtr'r�vm_diskstatsMs'rzcCs�t�}t�|���}|D]4}|jdkr|j|d<q|jdkr4|s,tj�t|j���	d�nt|j�|d<q|jdkr@|jdk|d<q|�
�dk|d<|S)	zb
    Parse XML doc and return a dict with the status values.

    :param xmldoc:
    :return:
    r0ZcreationTimer{�createdr�r
rr)rOrrVZ
getXMLDescr?rYrArBrCrD�	isCurrent)�vm_snapshot�	unix_timer3Ztreer`rrr�_parse_snapshot_description�s

��
�rcKsft�}tdi|��}t|g|r|gpt��Rddi�D]}dd�|��D�p'd||��<q|��|S)a2
    List available snapshots for certain vm or for all.

    :param domain: domain name
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    .. versionadded:: 2016.3.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.list_snapshots
        salt '*' virt.list_snapshots <domain>
    r-TcSrar�r�rG�snaprrrrI���z"list_snapshots.<locals>.<listcomp>�N/ANr)rOr*r5r.�listAllSnapshotsr0r�)rAr'r3r)Z	vm_domainrrr�list_snapshots�s&��r�cKs�|r|��|��krtdj|d���|s!dj|t�dt���d�}|r*|�d|��}t�d�}t�|d�}||_	t
d
i|��}t||��t
�|��|��d|iS)a
    Create a snapshot of a VM.

    :param domain: domain name
    :param name: Name of the snapshot. If the name is omitted, then will be used original domain
                 name with ISO 8601 time as a suffix.

    :param suffix: Add suffix for the new name. Useful in states, where such snapshots
                   can be distinguished from manually created.
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    .. versionadded:: 2016.3.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.snapshot <domain>
    zVVirtual Machine {name} is already defined. Please choose another name for the snapshotr�z{domain}-{tsnap}z
%Y%m%d-%H%M%S)rAZtsnap�-Zdomainsnapshotr0Nr)r�rr%rF�strftimerrZElementr�rYr*r5ZsnapshotCreateXMLr,r�r�)rAr0�suffixr'rvZn_namer)rrrrH�s&���
rHcOs�t�}tdi|��}t||�}|��D]}|��|vs|s)t|�||��<|��q|��|dd�|��D�p9di}||d�S)a�
    Delete one or more snapshots of the given VM.

    :param name: domain name
    :param names: names of the snapshots to remove
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    .. versionadded:: 2016.3.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.delete_snapshots <domain> all=True
        salt '*' virt.delete_snapshots <domain> <snapshot>
        salt '*' virt.delete_snapshots <domain> <snapshot1> <snapshot2> ...
    cSrarr�r�rrrrI.rz$delete_snapshots.<locals>.<listcomp>r�)�	availablerKNr)rOr*r5r��getNamerrTr�)r0r�r'rKr)rAr�r�rrr�delete_snapshots
s
��
r�c
Ks�t�}tdi|��}t||�}|��}t�}|D]}	|�t|	dd�d|	d��qdd�t|dd�dd	�D�}~|sB|��t	d
��t
|�dkrP|��t	d��d
}
|D]-}|sw|��rv||�|�dd
�rv||�|�dd
�d}
nqT|�
�|kr�|}
nqT|
s�|��t	tr�d|�d�p�d��|
��r�|��t	d��|�|
�|
�
�|d<|r�t�}|D]}|�
�|
�
�kr�|�|�
��|��q�||d<nd|d<|��|S)a�
    Revert snapshot to the previous from current (if available) or to the specific.

    :param name: domain name
    :param vm_snapshot: name of the snapshot to revert
    :param cleanup: Remove all newer than reverted snapshots. Values: True or False (default False).
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    .. versionadded:: 2016.3.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.revert <domain>
        salt '*' virt.revert <domain> <snapshot>
    T)r~r{)r��ptrcSsg|]}|d�qS)r�r)rGZw_ptrrrrrI\rz#revert_snapshot.<locals>.<listcomp>cSs|dS)Nr�rrrrrrr^r�z!revert_snapshot.<locals>.<lambda>)rx�reversezNo snapshots foundrz8Cannot revert to itself: only one snapshot is available.Nrz
Snapshot "z" not foundz$No more previous snapshots availablez0Cannot revert to the currently running snapshot.ZrevertedrKr�r)rOr*r5r�r.r/rr#r�rr1r|r7r�rHZrevertToSnapshotrT)
r0r}Zcleanupr'r3r)rAr<Z
_snapshotsZsnap_objr�Zp_snaprTrrr�revert_snapshot5st
������
��


r�cCsr|�d�}|�d�}|j}d}|r|}|}|�|�}|s,dgi}|r(t|�|d<|||<|r7|d�|�dSdS)zc
    Parse the <machine> element of the host capabilities and add it
    to the machines list.
    ZmaxCpus�	canonicalr^Zalternate_names�maxcpusN)r#rYr�r/)�machinesr`r�r�r0Zalternate_name�machinerrr�_caps_add_machine�s 


�r�c	Cs&|�d�}|�d�j|�d�iid�d�}d}|D]a}|jdkr*t|j�|dd<q|jdkr7|j|dd<q|jd	krFt|dd
|�q|jdkrz|�d�}did
�}|�d�}|durc|j|d<|�d	�D]	}t|d
|�qh||dd|<q|�d�}|dur�|dur�dd�|D�|d<|S)zF
    Parse the <guest> element of the connection capabilities XML
    rLrKr0)r0r�r)rKrLNZwordsize�emulatorr�r�rArh)r�r�r�featurescSs2i|]}|j|�dd�dk|�dd�dkd��qS)�toggler
rr�r�)r�r�)r?r#�rGrprrrrm�s���z%_parse_caps_guest.<locals>.<dictcomp>)rXrYr#r?r�r�rp)	rZ	arch_nodererpZdomain_typerAZ
emulator_noder�Zfeatures_nodesrrr�_parse_caps_guest�s8

�







�

�r�c
Csdt|�d��i}|�d�}|dur$|�dd�}|j}|�d|��|d<dd�|�d	�D�}|r4||d	<d
d�|�d�D�}|rD||d
<g}|�d�D]5}dt|�d��i}	|�d�}
|
rct|
�|	d<|�d�}|rpt|�|	d<|�d�}|r{||	d<|�|	�qK|r�||d<|S)zK
    Parse the <cell> nodes of the connection capabilities XML output.
    r=r�Nr�r�r{c	Ss2g|]}d�|�d�|�dd��t|j�d��qS)�{} {}rtr�r�)rtr�)r%r#r�rY�rGZpagerrrrI�s���z$_parse_caps_cell.<locals>.<listcomp>�pagescSs&i|]}t|�d��t|�d���qS)r=ry)r�r#)rGZdistancerrrrm�s��z$_parse_caps_cell.<locals>.<dictcomp>zdistances/sibling�	distanceszcpus/cpu�	socket_id�core_id�siblingsrg)r�r#rXrYrpr/)
�cellreZmem_noder�r�r�r�rgZcpu_noderr�r�r�rrr�_parse_caps_cell�s@
��


r�c	Cs�t|�d��t|�d��|�d�d�|�d�|�d��|�d�d�}g}|�d	�D]1}|�d�}d�|�d
�|�|�d�t|�d��d�}|�d
�}|rU|�d|��|d
<|�|�q)|ra||d<|S)zF
    Parse the <bank> element of the connection capabilities XML.
    r=r�rhr�rtr�rg)r=r�rhrtrg�control�granularity�	maxAllocs)r�rhr�r�r{�controls)r�r#r%rpr/)�bankrer�r�r�Zresult_controlZminimumrrr�_parse_caps_bank	s(�
�
r�c	Cs�i}|D]�}|jdkr|j|d<q|jdkr�|�d�dur#|�d�jnd|�d�dur1|�d�jnd|�d�dur?|�d�jnddd�|�d	�D�d
d�|�d�D�d�}|�d
�}|dure|�d�|d
<|�d�}|dur�t|�d��|d<t|�d��|d<t|�d��|d<||d<q|jdkr�dd�|D�|d<q|jdkr�|�d�dudd�|�d�D�d�|d<q|jdkr�ddd�|�d�D�i|d<q|jdkr�dd d�|�d!�D�i|d<qd"d�|�d#�D�|d$<|S)%zF
    Parse the <host> element of the connection capabilities XML.
    rTrrLNrkrIcSr�r�r��rG�featurerrrrIAs
�z$_parse_caps_host.<locals>.<listcomp>r�c
Ss*g|]}dd�|�d�|�dd��i�qS)rtr�r�r�)r%r#r�rrrrIDs��r�)rLrkrIr�r��	microcode�version�topologyr�r�r�Zpower_managementcS�g|]}|j�qSr)r?r�rrrrIV�Zmigration_featuresr�cSr�r�rYr�rrrrI[s�zuri_transports/uri_transport)r�Z
transportsZ	migrationZcellscSrar)r�)rGr�rrrrIbr�z
cells/cell�cacheZbankscSrar)r�)rGr�rrrrIirr�cSs\g|]*}|�d�dur|�d�jnd|�d�dur|�d�jnddd�|�d�D�d��qS)rkN�doicSsg|]}|�d�|jd��qS)rh)rh�label)r#rY)rGr�rrrrIv���z/_parse_caps_host.<locals>.<listcomp>.<listcomp>Z	baselabel)rkr�Z
baselabels)rXrYrp)rG�secmodelrrrrIls�����r�Zsecurity)r?rYrXrpr#r�)r�rerprr�r�rrr�_parse_caps_host(sb

�����




��
�
�
��
�r�cCs2t�|���}t|�d��dd�|�d�D�d�S)zk
    Return the hypervisor connection capabilities.

    :param conn: opened libvirt connection to use
    r�cSrar�r�rrrrrI�rz!_capabilities.<locals>.<listcomp>r�r�r)rrV�getCapabilitiesr�rXrp)r)r(rrrr"�s�r"c
Ks\tdi|��}z!zt|�}Wntjy!}ztt|���d}~wwW|��|S|��w)ar
    Return the hypervisor connection capabilities.

    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.capabilities
    Nr)r*r"rrrrPr�)r'r)r(r�rrr�capabilities�s���
�r�cCs|�d�dd�|�d�D�fS)zP
    Return a tuple containing the name of the enum and the possible values
    r0cSr�rr��rGryrrrrI�r�z$_parse_caps_enum.<locals>.<listcomp>ry�r#rprzrrr�_parse_caps_enum�sr�c
Cs(i}|�d�D]�}|�d�dksq|�d�}|dkrd||<q|dkrwi}|�d�}|d	urMd|ji}|�d
�}|r>||d
<|�d�}|rI||d<||d<|�d�d	urZ|�d�jnd	}	|	rb|	|d<d
d�|�d�D�}
|
rr|
|d<|||<q|dkr�i}dd�|�d�D�}|r�||d<|||<q|S)z<
    Parse the <cpu> element of the domain capabilities
    r��	supportedrr0zhost-passthroughTz
host-modelrkNrmr�rIcSsi|]}|�d�|�d��qS)r0r�r�r�rrrrm�r�z#_parse_caps_cpu.<locals>.<dictcomp>r�r�ZcustomcSsi|]	}|j|�d��qS)Zusable)rYr#)rGrkrrrrm�s��models)rpr#rXrY)
r`rer�r0Z
host_model�
model_noderkrmr�rIr�Zcustom_modelr�rrr�_parse_caps_cpu�sN





��
��r�cCsHi}|D]}|�d�dkr!dd�|�d�D�}dd�|D�||j<q|S)zG
    Parse the devices or features list of the domain capatilities
    r�rcSrar�r�r�rrrrI�rz0_parse_caps_devices_features.<locals>.<listcomp>�enumcS�"i|]
}|dr|d|d�qS�rrrrLrrrrm��"z0_parse_caps_devices_features.<locals>.<dictcomp>)r#rpr?)r`rerp�enumsrrr�_parse_caps_devices_features�s�r�cCsFdd�|�d�D�}dd�|D�}dd�|�d�D�}|r!||d<|S)	z@
    Parse the <loader> element of the domain capabilities.
    cSrarr��rGr�rrrrI�rz&_parse_caps_loader.<locals>.<listcomp>r�cSr�r�rrLrrrrm�r�z&_parse_caps_loader.<locals>.<dictcomp>cSr�rr�r�rrrrI�r�ryr9r�)r`r�rer9rrr�_parse_caps_loader�sr�cCsp|�d�dur
|�d�jnd|�d�dur|�d�jnd|�d�dur)|�d�jnd|�d�dur7|�d�jndd�}|D]x}|jdkrS|�d�rSt|�d��|d	<q=|jd
krb|�d�dk|d
<q=|jd
kr�i|d
<|�d�}|dur�|�d�dkr�t|�}||d
d<q=|jdkr�t|�}|r�||d<q=|jdkr�t|�}|r�||d<q=|jdkr�t|�}|r�||d<q=|S)zI
    Parse the XML document of domain capabilities into a structure.
    r�NrAr�rL)r�rAr�rLr�r�Z	max_vcpusr�r�rr(r	rr�r�)rXrYr?r#r�r�r�r�)r(rerpZloader_noder	rr�r�rrr�_parse_domain_capssB�	


�
�
�
�r�c	KsLtdi|��}g}zt�|�||||d��}t|�}W|��|S|��w)a�
    Return the domain capabilities given an emulator, architecture, machine or virtualization type.

    .. versionadded:: 2019.2.0

    :param emulator: return the capabilities for the given emulator binary
    :param arch: return the capabilities for the given CPU architecture
    :param machine: return the capabilities for the given emulated machine type
    :param domain: return the capabilities for the given virtualization type.
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    The list of the possible emulator, arch, machine and domain can be found in
    the host capabilities output.

    If none of the parameters is provided, the libvirt default one is returned.

    CLI Example:

    .. code-block:: bash

        salt '*' virt.domain_capabilities arch='x86_64' domain='kvm'

    rNr)r*rrV�getDomainCapabilitiesr�r�)r�rLr�rAr'r)rer(rrr�domain_capabilities/s�

�r�cs�tdi|���zEt�����}dd�dd�|�d�D�D�}dd�dd�|D�D�}t|�d��d	d�|�d�D�d
��fdd�|D�d�}|W���S���w)a~
    Return the host and domain capabilities in a single call.

    .. versionadded:: 3001

    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    CLI Example:

    .. code-block:: bash

        salt '*' virt.all_capabilities

    cs2g|]��fdd���di��di���D��qS)cs6g|]}��di��dd�|��di��dd�f�qS)rLr0Nr�r�)rGrx�rrrrIks���z/all_capabilities.<locals>.<listcomp>.<listcomp>rLr)r#rK)rGrr�rrIjs	
���z$all_capabilities.<locals>.<listcomp>cSrarr�rrrrrIsr�rcSsg|]	}|D]}|�qqSrr)rGrG�pairrrrrIwrVcss�|]}|VqdSr�r)rGrrrrr�ws�z#all_capabilities.<locals>.<genexpr>r�cSrarr�rrrrrI{r�r�cs,g|]\}}}tt���||d|����qSr�)r�rrVr�)rGrLrAr��r)rrrIs����)r�rNr)r*rrVr�rpr�rXr�)r'Z	host_capsrZ	flattenedrerr�r�all_capabilitiesVs(	��
��
��r�rc
s�tdi|��}t�|���}|�d�}t�|�}t�d|�d}|r4t	t
dd�r.|t
j7}n|��t
�|rAt	t
dd�rA|t
j7}t�|�|g|��}|��|r�t	t
dd�s�tjj�dd��
}	t�|	�}	Wd	�n1sowY|�d
�j��r�|	�d�}
�fdd
�|
D�}|s�t
d��d���t|�dkr�t
d��d���|d}|�d
�}|d	ur�d	�n|�d��|�dd
�|�d�D���s||dkr�|�d
�j|�d�jdd
�|�d�D�d�St�|�S)a
    Return the optimal 'custom' CPU baseline config for VM's on this minion

    .. versionadded:: 2016.3.0

    :param full: Return all CPU features rather than the ones on top of the closest CPU model
    :param migratable: Exclude CPU features that are unmigratable (libvirt 2.13+)
    :param out: 'libvirt' (default) for usable libvirt XML definition, 'salt' for nice dict
    :param connection: libvirt connection URI, overriding defaults

        .. versionadded:: 2019.2.0
    :param username: username to connect with, overriding defaults

        .. versionadded:: 2019.2.0
    :param password: password to connect with, overriding defaults

        .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.cpu_baseline

    zhost/cpuzHost CPU model definition: %sr�#VIR_CONNECT_BASELINE_CPU_MIGRATABLEF�(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURESz/usr/share/libvirt/cpu_map.xmlr9Nrkz
arch/modelcs*g|]}|�d��krtt|��r|�qSr�)r#rQr1)rG�el�Z	cpu_modelrrrI�s
�z cpu_baseline.<locals>.<listcomp>zModel z not found in CPU maprzMultiple models z found in CPU mapr0cSsg|]}|�qSrrr�rrrrI�r	r�rNrIcSr�r�r�r�rrrrI�r�)rkrIr�r)r*rrVr�rXr,r�rr�r�rr�r�r�r�ZbaselineCPUrNrOr�r:r�rYrpr1r#r�r�)
�fullZ
migratablerr'r)r(rZhost_cpu_defr�Zcpu_mapZcpu_map_modelsZ	cpu_specsr�rr�r�cpu_baseline�sT


�

�

�

�
r�cKsPtd
i|��}|�dd�}|�dd�}t|||||dd�||fD�|	|
|||
||d�
}z|�|�WntjyJ}zt�|�|��|�d}~wwz|�	|�}Wntjyj}zt�|�|��|�d}~ww|duru|��dS|sy|r�|�
�dkr�|��|r�|��dkr�|�
t|��n|s�|��dkr�|�
t|��|��d	S)ac
    Create libvirt network.

    :param name: Network name.
    :param bridge: Bridge name.
    :param forward: Forward mode (bridge, router, nat).

        .. versionchanged:: 3003
           a ``None`` value creates an isolated network with no forwarding at all

    :param vport: Virtualport type.
        The value can also be a dictionary with ``type`` and ``parameters`` keys.
        The ``parameters`` value is a dictionary of virtual port parameters.

        .. code-block:: yaml

          - vport:
              type: openvswitch
              parameters:
                interfaceid: 09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f

        .. versionchanged:: 3003
           possible dictionary value

    :param tag: Vlan tag.
        The value can also be a dictionary with the ``tags`` and optional ``trunk`` keys.
        ``trunk`` is a boolean value indicating whether to use VLAN trunking.
        ``tags`` is a list of dictionaries with keys ``id`` and ``nativeMode``.
        The ``nativeMode`` value can be one of ``tagged`` or ``untagged``.

        .. code-block:: yaml

          - tag:
              trunk: True
              tags:
                - id: 42
                  nativeMode: untagged
                - id: 47

        .. versionchanged:: 3003
           possible dictionary value

    :param autostart: Network autostart (default True).
    :param start: Network start (default True).
    :param ipv4_config: IP v4 configuration.
        Dictionary describing the IP v4 setup like IP range and
        a possible DHCP configuration. The structure is documented
        in net-define-ip_.

        .. versionadded:: 3000
    :type ipv4_config: dict or None

    :param ipv6_config: IP v6 configuration.
        Dictionary describing the IP v6 setup like IP range and
        a possible DHCP configuration. The structure is documented
        in net-define-ip_.

        .. versionadded:: 3000
    :type ipv6_config: dict or None

    :param connection: libvirt connection URI, overriding defaults.
    :param username: username to connect with, overriding defaults.
    :param password: password to connect with, overriding defaults.

    :param mtu: size of the Maximum Transmission Unit (MTU) of the network.
        (default ``None``)

        .. versionadded:: 3003

    :param domain: DNS domain name of the DHCP server.
        The value is a dictionary with a mandatory ``name`` property and an optional ``localOnly`` boolean one.
        (default ``None``)

        .. code-block:: yaml

          - domain:
              name: lab.acme.org
              localOnly: True

        .. versionadded:: 3003

    :param nat: addresses and ports to route in NAT forward mode.
        The value is a dictionary with optional keys ``address`` and ``port``.
        Both values are a dictionary with ``start`` and ``end`` values.
        (default ``None``)

        .. code-block:: yaml

          - forward: nat
          - nat:
              address:
                start: 1.2.3.4
                end: 1.2.3.10
              port:
                start: 500
                end: 1000

        .. versionadded:: 3003

    :param interfaces: whitespace separated list of network interfaces devices that can be used for this network.
        (default ``None``)

        .. code-block:: yaml

          - forward: passthrough
          - interfaces: "eth10 eth11 eth12"

        .. versionadded:: 3003

    :param addresses: whitespace separated list of addresses of PCI devices that can be used for this network in `hostdev` forward mode.
        (default ``None``)

        .. code-block:: yaml

          - forward: hostdev
          - interfaces: "0000:04:00.1 0000:e3:01.2"

        .. versionadded:: 3003

    :param physical_function: device name of the physical interface to use in ``hostdev`` forward mode.
        (default ``None``)

        .. code-block:: yaml

          - forward: hostdev
          - physical_function: "eth0"

        .. versionadded:: 3003

    :param dns: virtual network DNS configuration.
        The value is a dictionary described in net-define-dns_.
        (default ``None``)

        .. code-block:: yaml

          - dns:
              forwarders:
                - domain: example.com
                  addr: 192.168.1.1
                - addr: 8.8.8.8
                - domain: www.example.com
              txt:
                example.com: "v=spf1 a -all"
                _http.tcp.example.com: "name=value,paper=A4"
              hosts:
                192.168.1.2:
                  - mirror.acme.lab
                  - test.acme.lab
              srvs:
                - name: ldap
                  protocol: tcp
                  domain: ldapserver.example.com
                  target: .
                  port: 389
                  priority: 1
                  weight: 10

        .. versionadded:: 3003

    .. _net-define-ip:

    .. rubric:: IP configuration definition

    Both the IPv4 and IPv6 configuration dictionaries can contain the following properties:

    cidr
        CIDR notation for the network. For example '192.168.124.0/24'

    dhcp_ranges
        A list of dictionaries with ``'start'`` and ``'end'`` properties.

    hosts
        A list of dictionaries with ``ip`` property and optional ``name``, ``mac`` and ``id`` properties.

        .. versionadded:: 3003

    bootp
        A dictionary with a ``file`` property and an optional ``server`` one.

        .. versionadded:: 3003

    tftp
        The path to the TFTP root directory to serve.

        .. versionadded:: 3003

    .. _net-define-dns:

    .. rubric:: DNS configuration definition

    The DNS configuration dictionary contains the following optional properties:

    forwarders
        List of alternate DNS forwarders to use.
        Each item is a dictionary with the optional ``domain`` and ``addr`` keys.
        If both are provided, the requests to the domain are forwarded to the server at the ``addr``.
        If only ``domain`` is provided the requests matching this domain will be resolved locally.
        If only ``addr`` is provided all requests will be forwarded to this DNS server.

    txt:
        Dictionary of TXT fields to set.

    hosts:
        Dictionary of host DNS entries.
        The key is the IP of the host, and the value is a list of hostnames for it.

    srvs:
        List of SRV DNS entries.
        Each entry is a dictionary with the mandatory ``name`` and ``protocol`` keys.
        Entries can also have ``target``, ``port``, ``priority``, ``domain`` and ``weight`` optional properties.

    CLI Example:

    .. code-block:: bash

        salt '*' virt.network_define network main bridge openvswitch

    .. versionadded:: 2019.2.0
    r�Nr?cS�g|]}|r|�qSrrr�rrrrI�rz"network_define.<locals>.<listcomp>�	r?r�r�rAr�r�r�r�r�FrTr)r*r#r��networkDefineXMLrrr�warningr��networkLookupByNamer�r%r�rOr�)r0r�r��ipv4_config�ipv6_configr�r?r�r&r�rAr�r�r�r�r�r'r)Znet_xmlr�r�rrr�network_define�s\o�
��
��r�cCs:|D]}|js|js|��s|s|�|�qt|�q|S)zE
    Remove the nodes with no children, no text and no attribute
    )rFrYrtr�_remove_empty_xml_node)r`rprrrr�s

r�c%Ks�tdi|��}d}�z:|�|�}t�|���}t�t|||||dd�||fD�|||	|
|||
d�
�}ddg}|D]}|�|�}|durI|�d|�q8|j�	d	d�|�d
�durl|�d�}|�
d�}|D]}|�|�qdd
dd�}|�d�}|dur�|��D]\}}|�
|d�|kr�|j�	|d�q~|�d�dur�|�d��
d�nd}||kr�|dvr�|dur�|�
dd��d�r�|j�	dd�dd�|�
d�D�} | D]"}!|!j�	dd�}"|"r�tjd�|!�
d�|"�dd�}#|!�dt|#j��q�||fD]}$|$�
d�D]}d|��v�r|�dd�q�q�tt�|��t�|�t�|d�t�|d�k}|�r7|�s>|�t�|��W|��|SW|��|SW|��|S|��w) a
    Update a virtual network if needed.

    :param name: Network name.
    :param bridge: Bridge name.
    :param forward: Forward mode (bridge, router, nat).
        A ``None`` value creates an isolated network with no forwarding at all.

    :param vport: Virtualport type.
        The value can also be a dictionary with ``type`` and ``parameters`` keys.
        The ``parameters`` value is a dictionary of virtual port parameters.

        .. code-block:: yaml

          - vport:
              type: openvswitch
              parameters:
                interfaceid: 09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f

    :param tag: Vlan tag.
        The value can also be a dictionary with the ``tags`` and optional ``trunk`` keys.
        ``trunk`` is a boolean value indicating whether to use VLAN trunking.
        ``tags`` is a list of dictionaries with keys ``id`` and ``nativeMode``.
        The ``nativeMode`` value can be one of ``tagged`` or ``untagged``.

        .. code-block:: yaml

          - tag:
              trunk: True
              tags:
                - id: 42
                  nativeMode: untagged
                - id: 47

    :param ipv4_config: IP v4 configuration.
        Dictionary describing the IP v4 setup like IP range and
        a possible DHCP configuration. The structure is documented
        in net-define-ip_.

    :type ipv4_config: dict or None

    :param ipv6_config: IP v6 configuration.
        Dictionary describing the IP v6 setup like IP range and
        a possible DHCP configuration. The structure is documented
        in net-define-ip_.

    :type ipv6_config: dict or None

    :param connection: libvirt connection URI, overriding defaults.
    :param username: username to connect with, overriding defaults.
    :param password: password to connect with, overriding defaults.

    :param mtu: size of the Maximum Transmission Unit (MTU) of the network.
        (default ``None``)

    :param domain: DNS domain name of the DHCP server.
        The value is a dictionary with a mandatory ``name`` property and an optional ``localOnly`` boolean one.
        (default ``None``)

        .. code-block:: yaml

          - domain:
              name: lab.acme.org
              localOnly: True

    :param nat: addresses and ports to route in NAT forward mode.
        The value is a dictionary with optional keys ``address`` and ``port``.
        Both values are a dictionary with ``start`` and ``end`` values.
        (default ``None``)

        .. code-block:: yaml

          - forward: nat
          - nat:
              address:
                start: 1.2.3.4
                end: 1.2.3.10
              port:
                start: 500
                end: 1000

    :param interfaces: whitespace separated list of network interfaces devices that can be used for this network.
        (default ``None``)

        .. code-block:: yaml

          - forward: passthrough
          - interfaces: "eth10 eth11 eth12"

    :param addresses: whitespace separated list of addresses of PCI devices that can be used for this network in `hostdev` forward mode.
        (default ``None``)

        .. code-block:: yaml

          - forward: hostdev
          - interfaces: "0000:04:00.1 0000:e3:01.2"

    :param physical_function: device name of the physical interface to use in ``hostdev`` forward mode.
        (default ``None``)

        .. code-block:: yaml

          - forward: hostdev
          - physical_function: "eth0"

    :param dns: virtual network DNS configuration.
        The value is a dictionary described in net-define-dns_.
        (default ``None``)

        .. code-block:: yaml

          - dns:
              forwarders:
                - domain: example.com
                  addr: 192.168.1.1
                - addr: 8.8.8.8
                - domain: www.example.com
              txt:
                example.com: "v=spf1 a -all"
                _http.tcp.example.com: "name=value,paper=A4"
              hosts:
                192.168.1.2:
                  - mirror.acme.lab
                  - test.acme.lab
              srvs:
                - name: ldap
                  protocol: tcp
                  domain: ldapserver.example.com
                  target: .
                  port: 389
                  priority: 1
                  weight: 10

    .. versionadded:: 3003
    FcSr�rrr�rrrrI�rz"network_update.<locals>.<listcomp>r�rTriNrZconnectionsz
forward/pfr�rjr�rB)Zstp�delayr�r�)r�Zroute�openNr0r^ZvirbrcSs g|]}|�dd�dkr|�qS)�family�ipv4r�r�rrrrI�s
��ip�netmaskr)�strictrkr�r�Tr)r*r�rrVrnr�rX�insertrsr�rprrtr#r�rrr%rrP�	prefixlenrKr�r,�strip_spacesr-r�r�r�)%r0r�r�r�r�r�r?r�rAr�r�r�r�r�r�r'r)�needs_updater�r~r�elements_to_copy�to_copy�elementZforward_nodeZ
address_nodesr`Zdefault_bridge_attribsZold_bridge_noderxryZold_forwardZ
ipv4_nodesZip_noder�rjrvrrr�network_updates�
��
�



���������
��
�r�cK�6tdi|��}zdd�|��D�W|��S|��w)a^
    List all virtual networks.

    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

       salt '*' virt.list_networks
    cS�g|]}|���qSrr�r�rrrrI!rz!list_networks.<locals>.<listcomp>Nr)r*r�r��r'r)rrr�
list_networks�r�c
s�i}tdi|��}dd��dd��z?z�fdd�|��D�}��fdd�|D�}WntjyB}zt�d	|�WYd
}~nd
}~wwW|��|SW|��|S|��w)a�
    Return information on a virtual network provided its name.

    :param name: virtual network name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    If no name is provided, return the infos for all defined virtual networks.

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.network_info default
    cSsN|��}|D]}|dtjkrd|d<q|dtjkr d|d<qd|d<q|S)z3
        Get all DHCP leases for a network
        rhr�Zipv6r�)Z
DHCPLeasesrZVIR_IP_ADDR_TYPE_IPV4ZVIR_IP_ADDR_TYPE_IPV6)r��leasesZleaserrr�_net_get_leases<s


z%network_info.<locals>._net_get_leasesc
Ss4z|��WStjy}zWYd}~dSd}~ww)z7
        Get the bridge of the network or None
        N)Z
bridgeNamerr)r�r�rrr�_net_get_bridgeJs
��z%network_info.<locals>._net_get_bridgec�$g|]}�dus|���kr|�qSr�r�r�r�rrrIUsz network_info.<locals>.<listcomp>c
s<i|]}|��|���|�|��|��|���|�d��qS))rTr�r�r+r�r�)r0�
UUIDStringr�r��isPersistentr�)r�r�rrrmXs	���z network_info.<locals>.<dictcomp>�Silenced libvirt error: %sNr)r*r�rrrr�r�)r0r'rer)�netsr�r)r�r�r0r�network_info&s,

�	
�����
�r�cK�2tdi|��}z|�|���W|��S|��w)a�
    Return the XML definition of a virtual network

    :param name: libvirt network name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 3000

    CLI Example:

    .. code-block:: bash

        salt '*' virt.network_get_xml default
    Nr)r*r�rnr��r0r'r)rrr�network_get_xmlj�rcK�<tdi|��}z|�|�}t|���W|��S|��w)a�
    Start a defined virtual network.

    :param name: virtual network name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.network_start default
    Nr)r*r�rQr%r��r0r'r)r�rrr�
network_start��

rcKr)a�
    Stop a defined virtual network.

    :param name: virtual network name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.network_stop default
    Nr)r*r�rQrr�rrrr�network_stop�rrcKr)a�
    Remove a defined virtual network. This does not stop the virtual network.

    :param name: virtual network name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.network_undefine default
    Nr)r*r�rQrRr�rrrr�network_undefine�rrcK�Jtdi|��}z|�|�}t|�|dkrdnd��W|��S|��w)a�
    Set the autostart flag on a virtual network so that the network
    will start with the host system on reboot.

    :param name: virtual network name
    :param state: 'on' to auto start the network, anything else to mark the
                  virtual network not to be started when the host boots
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt "*" virt.network_set_autostart <pool> <on | off>
    r�rrNr)r*r�rQrOr�)r0r�r'r)r�rrr�network_set_autostart��

r	cs dd���fdd�|�d�D�S)z-
    Parse libvirt pool capabilities XML
    cSs�|�d�|�dd�dkd�}dD]C}i}|�|�d��}|dur'|�d�|d<d	d
�|�|�d��D�}|r;|�|�|rSd|vrEi|d<|d
krK|nd}||d|<q|S)Nrhr�r
r)r0r�)r�r�zOptions/defaultFormatr�cSs(i|]}|�d�dd�|�d�D��qS)r0cSr�rr�r�rrrrI�r�zJ_parse_pools_caps.<locals>._parse_pool_caps.<locals>.<dictcomp>.<listcomp>ryr�r�rrrrm�s��z?_parse_pools_caps.<locals>._parse_pool_caps.<locals>.<dictcomp>zOptions/enumr�r�r�)r#rXrpr�)r�r��option_kindr�Zdefault_format_nodeZ
options_enums�kindrrr�_parse_pool_caps�s(��
�z+_parse_pools_caps.<locals>._parse_pool_capsc�g|]}�|��qSrr�rGr��r
rrrIrz%_parse_pools_caps.<locals>.<listcomp>r�r�)rvrrr�_parse_pools_caps�srcs$tt|dd��}|rt�|���}t|�}nvgd��gd�}ddgd�d|d	�d
d|d�dd
iddiddddgd�ddgd�d|d	�ddgd�dgd�d	�ddiddgd�dddgd|d�dd dgd|d�d!d"d#gd$�d%d&dd'gd$�g
}|���t�����fd(d)���fd*d+�|D�}||d,�S)-zx
    Return the hypervisor connection storage pool capabilities.

    :param conn: opened libvirt connection to use
    �getStoragePoolCapabilitiesN)r%rr=)rr�r�ZbochsZcloopZdmgZisoZvpcZvdiZfatZvhd�ploopZcowZqcowr�Zqedr�r��auto)
rZext2Zext3Zext4ZufsZiso9660ZudfZgfsZgfs2Zvfatzhfs+ZxfsZocfs2r�)r0�default_source_format�source_formats�default_target_format�target_formatsr�)r0rrr0r�r�r��lvm2r�)r0rrr�)r�nfsZ	glusterfsr�rM)	r��dosZdvhZgptriZbsdZpc98�sunrr)r�linuxZfat16Zfat32z
linux-swapz	linux-lvmz
linux-raid�extendedZmpathr�r�i'r)r0r�r*rrr�iJr�iJr=)r0r�r*�iscsi-directiX$=r%cs�|d|�d�p�|dko�|�d��v|�d�|�d�d�|�d�|�d�d	�d
�d�}d
D]}dd
�|d|��D�sE|d|=q1|dsM|d=|S)Nr0r�r*rr)r�ZsourceFormatTyperr)r�r�)r�r�)r0r�r�cSsg|]}|dur|�qSr�rr�rrrrI�s
�zC_pool_capabilities.<locals>._get_backend_output.<locals>.<listcomp>r�)r#r9)�backendr�r)�all_hypervisorsr�libvirt_versionrr�_get_backend_output�s*������
�z/_pool_capabilities.<locals>._get_backend_outputcrrr)rGr )r#rrrI�rz&_pool_capabilities.<locals>.<listcomp>)Zcomputedr�)rQr�rrVrrZ
getLibVersionrd)r)Zhas_pool_capabilitiesr(r�Zimages_formatsZcommon_driversr)r#r!rr"rr�sz
�����
����[ �r�cKs,ztdi|��}t|�W|��S|��w)a�
    Return the hypervisor connection storage pool capabilities.

    The returned data are either directly extracted from libvirt or computed.
    In the latter case some pool types could be listed as supported while they
    are not. To distinguish between the two cases, check the value of the ``computed`` property.

    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 3000

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pool_capabilities

    Nr)r*r�r�r�rrr�pool_capabilities�sr$cKs�tdi|��}t||||	�}t||||||||||
||d�}z,z|r(|�|�}n|�|�}|
r3|��WntjyC}z|�d}~wwW|��dS|��w)a_
    Create libvirt pool.

    :param name: Pool name
    :param ptype:
        Pool type. See `libvirt documentation <https://libvirt.org/storage.html>`_  for the
        possible values.
    :param target: Pool full path target
    :param permissions:
        Permissions to set on the target folder. This is mostly used for filesystem-based
        pool types. See :ref:`pool-define-permissions` for more details on this structure.
    :param source_devices:
        List of source devices for pools backed by physical devices. (Default: ``None``)

        Each item in the list is a dictionary with ``path`` and optionally ``part_separator``
        keys. The path is the qualified name for iSCSI devices.

        Report to `this libvirt page <https://libvirt.org/formatstorage.html#StoragePool>`_
        for more information on the use of ``part_separator``
    :param source_dir:
        Path to the source directory for pools of type ``dir``, ``netfs`` or ``gluster``.
        (Default: ``None``)
    :param source_initiator:
        Initiator IQN for libiscsi-direct pool types. (Default: ``None``)

        .. versionadded:: 3000
    :param source_adapter:
        SCSI source definition. The value is a dictionary with ``type``, ``name``, ``parent``,
        ``managed``, ``parent_wwnn``, ``parent_wwpn``, ``parent_fabric_wwn``, ``wwnn``, ``wwpn``
        and ``parent_address`` keys.

        The ``parent_address`` value is a dictionary with ``unique_id`` and ``address`` keys.
        The address represents a PCI address and is itself a dictionary with ``domain``, ``bus``,
        ``slot`` and ``function`` properties.
        Report to `this libvirt page <https://libvirt.org/formatstorage.html#StoragePool>`_
        for the meaning and possible values of these properties.
    :param source_hosts:
        List of source for pools backed by storage from remote servers. Each item is the hostname
        optionally followed by the port separated by a colon. (Default: ``None``)
    :param source_auth:
        Source authentication details. (Default: ``None``)

        The value is a dictionary with ``type``, ``username`` and ``secret`` keys. The type
        can be one of ``ceph`` for Ceph RBD or ``chap`` for iSCSI sources.

        The ``secret`` value links to a libvirt secret object. It is a dictionary with
        ``type`` and ``value`` keys. The type value can be either ``uuid`` or ``usage``.

        Examples:

        .. code-block:: python

            source_auth={
                'type': 'ceph',
                'username': 'admin',
                'secret': {
                    'type': 'uuid',
                    'value': '2ec115d7-3a88-3ceb-bc12-0ac909a6fd87'
                }
            }

        .. code-block:: python

            source_auth={
                'type': 'chap',
                'username': 'myname',
                'secret': {
                    'type': 'usage',
                    'value': 'mycluster_myname'
                }
            }

        Since 3000, instead the source authentication can only contain ``username``
        and ``password`` properties. In this case the libvirt secret will be defined and used.
        For Ceph authentications a base64 encoded key is expected.

    :param source_name:
        Identifier of name-based sources.
    :param source_format:
        String representing the source format. The possible values are depending on the
        source type. See `libvirt documentation <https://libvirt.org/storage.html>`_ for
        the possible values.
    :param start: Pool start (default True)
    :param transient:
        When ``True``, the pool will be automatically undefined after being stopped.
        Note that a transient pool will force ``start`` to ``True``. (Default: ``False``)
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. _pool-define-permissions:

    .. rubric:: Permissions definition

    The permissions are described by a dictionary containing the following keys:

    mode
        The octal representation of the permissions. (Default: `0711`)

    owner
        the numeric user ID of the owner. (Default: from the parent folder)

    group
        the numeric ID of the group. (Default: from the parent folder)

    label
        the SELinux label. (Default: `None`)


    .. rubric:: CLI Example:

    Local folder pool:

    .. code-block:: bash

        salt '*' virt.pool_define somepool dir target=/srv/mypool                                   permissions="{'mode': '0744' 'ower': 107, 'group': 107 }"

    CIFS backed pool:

    .. code-block:: bash

        salt '*' virt.pool_define myshare netfs source_format=cifs                                   source_dir=samba_share source_hosts="['example.com']" target=/mnt/cifs

    .. versionadded:: 2019.2.0
    )	rrr�r�r�r�r�r�r�r�NTr)	r*�_pool_set_secretr�ZstoragePoolCreateXML�storagePoolDefineXMLr%rrr�)r0r�rlrrr�r�r�r�r�r�r�r�Z	transientr&r'r)r�r�r�r�rrr�pool_define�s@�
����
�r'c
Cs:dddd�}|�|�}|}	|r�d|vr�d|vr�|r�d}
z|r/|dkr%tjntj}|�||�}
n|r6|�|�}
WntjyR}zt�d|�	��WYd}~nd}~ww|
sod|�d�}
|sbd	|��}t
|||
�}|so|�|�}
|	d}|d
kr�t�
tjj�|��}|s�|
�|�||	d<|r�dnd
|r�|n|d�|	d<|	S)Nr�Zchap)r�r�rrrzSecret not found: %szPassphrase for z pool created by Salt�pool_r�rhrTr�)rhry�secret)r#r�VIR_SECRET_USAGE_TYPE_CEPH�VIR_SECRET_USAGE_TYPE_ISCSI�secretLookupByUsager�rrrr�r�ZsecretDefineXML�base64�	b64decoderNrOr��to_bytesZsetValue)r)r�r�r�rTr�r�Zsecret_types�secret_typer�r)Z
usage_typer�r�Z
secret_xmlrrrrr%{sJ
��
���





�r%c
KsBtdi|
��}d}z�|�|�}t�|���}|�d�}|dur$|�d�nd}|dur/|�d�nd}t||||	|||d�}t�t|||||||||||
|d��}gd�}|D]
}|�|�}|�	d	|�qUt
t�|��t�|�t�
|d
�t�
|d
�k}|r�|s�|�t�|��W|��|SW|��|SW|��|S|��w)a8
    Update a libvirt storage pool if needed.
    If called with test=True, this is also reporting whether an update would be performed.

    :param name: Pool name
    :param ptype:
        Pool type. See `libvirt documentation <https://libvirt.org/storage.html>`_  for the
        possible values.
    :param target: Pool full path target
    :param permissions:
        Permissions to set on the target folder. This is mostly used for filesystem-based
        pool types. See :ref:`pool-define-permissions` for more details on this structure.
    :param source_devices:
        List of source devices for pools backed by physical devices. (Default: ``None``)

        Each item in the list is a dictionary with ``path`` and optionally ``part_separator``
        keys. The path is the qualified name for iSCSI devices.

        Report to `this libvirt page <https://libvirt.org/formatstorage.html#StoragePool>`_
        for more information on the use of ``part_separator``
    :param source_dir:
        Path to the source directory for pools of type ``dir``, ``netfs`` or ``gluster``.
        (Default: ``None``)
    :param source_initiator:
        Initiator IQN for libiscsi-direct pool types. (Default: ``None``)

        .. versionadded:: 3000
    :param source_adapter:
        SCSI source definition. The value is a dictionary with ``type``, ``name``, ``parent``,
        ``managed``, ``parent_wwnn``, ``parent_wwpn``, ``parent_fabric_wwn``, ``wwnn``, ``wwpn``
        and ``parent_address`` keys.

        The ``parent_address`` value is a dictionary with ``unique_id`` and ``address`` keys.
        The address represents a PCI address and is itself a dictionary with ``domain``, ``bus``,
        ``slot`` and ``function`` properties.
        Report to `this libvirt page <https://libvirt.org/formatstorage.html#StoragePool>`_
        for the meaning and possible values of these properties.
    :param source_hosts:
        List of source for pools backed by storage from remote servers. Each item is the hostname
        optionally followed by the port separated by a colon. (Default: ``None``)
    :param source_auth:
        Source authentication details. (Default: ``None``)

        The value is a dictionary with ``type``, ``username`` and ``secret`` keys. The type
        can be one of ``ceph`` for Ceph RBD or ``chap`` for iSCSI sources.

        The ``secret`` value links to a libvirt secret object. It is a dictionary with
        ``type`` and ``value`` keys. The type value can be either ``uuid`` or ``usage``.

        Examples:

        .. code-block:: python

            source_auth={
                'type': 'ceph',
                'username': 'admin',
                'secret': {
                    'type': 'uuid',
                    'uuid': '2ec115d7-3a88-3ceb-bc12-0ac909a6fd87'
                }
            }

        .. code-block:: python

            source_auth={
                'type': 'chap',
                'username': 'myname',
                'secret': {
                    'type': 'usage',
                    'uuid': 'mycluster_myname'
                }
            }

        Since 3000, instead the source authentication can only contain ``username``
        and ``password`` properties. In this case the libvirt secret will be defined and used.
        For Ceph authentications a base64 encoded key is expected.

    :param source_name:
        Identifier of name-based sources.
    :param source_format:
        String representing the source format. The possible values are depending on the
        source type. See `libvirt documentation <https://libvirt.org/storage.html>`_ for
        the possible values.
    :param test: run in dry-run mode if set to True
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. rubric:: Example:

    Local folder pool:

    .. code-block:: bash

        salt '*' virt.pool_update somepool dir target=/srv/mypool                                   permissions="{'mode': '0744' 'ower': 107, 'group': 107 }"

    CIFS backed pool:

    .. code-block:: bash

        salt '*' virt.pool_update myshare netfs source_format=cifs                                   source_dir=samba_share source_hosts="['example.com']" target=/mnt/cifs

    .. versionadded:: 3000
    Fzsource/auth/secretNr�rT)rTr�r�)	rrr�r�r�r�r�r�r�r�)r�ru�capacityrTrTr)r*r�rrVrnrXr#r%r�r�r�r,r�r-r&r�r�)r0r�rlrrr�r�r�r�r�r�r�r�r�r'r)r�r�r~r�r�rTr�rr�r�r�rrr�pool_update�sZ{

���

��
�r2cKr�)aY
    List all storage pools.

    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.list_pools
    cSr�rr�rrrrrIm rzlist_pools.<locals>.<listcomp>Nr)r*r�r�r�rrr�
list_pools[ r�r3c
s�i}td	i|��}dd��z>z�fdd�|��D�}�fdd�|D�}Wntjy=}zt�d|�WYd}~nd}~wwW|��|SW|��|S|��w)
a�
    Return information on a storage pool provided its name.

    :param name: libvirt storage pool name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    If no name is provided, return the infos for all defined storage pools.

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pool_info default
    cSs�gd�}|��}|dt|�kr||dnd}t�|���}|�d�}|��||d|d|d|��|��|dur>|j	nd|�
d	�d
�	S)z_
        Format the pool info dictionary

        :param pool: the libvirt pool object
        )r,Zbuildingr
ZdegradedZinaccessiblerr�ztarget/pathrr
rNrh)	rTr�r1ru�freer�r��target_pathrh)rr1rrVrnrXr�r�r�rYr#)r�Zstatesr	r�r
Z	path_noderrr�_pool_extract_infos� s 
�z&pool_info.<locals>._pool_extract_infoscr�r�r�rr�rrrI� s
�zpool_info.<locals>.<listcomp>csi|]	}|���|��qSrr�r)r6rrrm� rVzpool_info.<locals>.<dictcomp>r�Nr)r*r�rrrr�r�)r0r'rer)�poolsr�r)r6r0r�	pool_infor s&
�����
�r8cKr�)a�
    Return the XML definition of a virtual storage pool

    :param name: libvirt storage pool name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 3000

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pool_get_xml default
    Nr)r*r�rnr�r�rrr�pool_get_xml� rr9cKr)a�
    Start a defined libvirt storage pool.

    :param name: libvirt storage pool name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pool_start default
    Nr)r*r�rQr%r��r0r'r)r�rrr�
pool_start� rr;cKr)a�
    Build a defined libvirt storage pool.

    :param name: libvirt storage pool name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pool_build default
    Nr)r*r�rQ�buildr�r:rrr�
pool_build� rr=cKr)a�
    Stop a defined libvirt storage pool.

    :param name: libvirt storage pool name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pool_stop default
    Nr)r*r�rQrr�r:rrr�	pool_stop� rr>c
Ks�tdi|��}zJ|�|�}t�|���}|�d�}|durFtjtjd�}||�	d�}|�d��	d�}|rFd|��|krF|�
||�}	|	��t|���W|�
�S|�
�w)	a�
    Remove a defined libvirt storage pool. The pool needs to be stopped before calling.

    :param name: libvirt storage pool name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pool_undefine default
    zsource/authN)r�r�rhr)r�r(r)r*r�rrVrnrXrr*r+r#r,rRrQr�)
r0r'r)r�r
r�r(r0Zsecret_usager)rrr�
pool_undefine!s 

�r?cKs@tdi|��}z|�|�}t|�tj��W|��S|��w)a�
    Delete the resources of a defined libvirt storage pool.

    :param name: libvirt storage pool name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pool_delete default
    Nr)r*r�rQrTrZVIR_STORAGE_POOL_DELETE_NORMALr�r:rrr�pool_delete9!s

r@cKr)a�
    Refresh a defined libvirt storage pool.

    :param name: libvirt storage pool name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt '*' virt.pool_refresh default
    Nr)r*r�rQZrefreshr�r:rrr�pool_refreshR!rrAcKr)a�
    Set the autostart flag on a libvirt storage pool so that the storage pool
    will start with the host system on reboot.

    :param name: libvirt storage pool name
    :param state: 'on' to auto start the pool, anything else to mark the
                  pool not to be started when the host boots
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt "*" virt.pool_set_autostart <pool> <on | off>
    r�rrNr)r*r�rQrOr�)r0r�r'r)r�rrr�pool_set_autostartk!r
rBcKs6tdi|��}z|�|�}|��W|��S|��w)a�
    List the volumes contained in a defined libvirt storage pool.

    :param name: libvirt storage pool name
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 2019.2.0

    CLI Example:

    .. code-block:: bash

        salt "*" virt.pool_list_volumes <pool>
    Nr)r*r�r�r�r:rrr�pool_list_volumes�!s

rCcCs|�|�}|�|�S)z�
    Helper function getting a storage volume. Will throw a libvirtError
    if the pool or the volume couldn't be found.

    :param conn: libvirt connection object to use
    :param pool: pool name
    :param vol: volume name
    )r�r�)r)r�r�r�rrr�_get_storage_vol�!s
	
rDc
CsXzdd�}t�|d�|��t�dd�WdStjy+}zWYd}~dSd}~ww)z|
    Checks whether a volume is valid for further use since those may have disappeared since
    the last pool refresh.
    cSst�d|d�dS)NzIgnore libvirt error: %sr
)rr�)Zctxtr�rrr�	discarder�!sz#_is_valid_volume.<locals>.discarderNTF)rZregisterErrorHandlerrr)r�rEr�rrr�_is_valid_volume�!s��rFcsDdd�|��D�}i}|D]��fdd����D�}|�|�q
|S)z
    Extract the path, name, pool name and backing stores path of all volumes.

    :param conn: libvirt connection to use
    cSs"g|]
}|��dtjkr|�qS)r)rr�VIR_STORAGE_POOL_RUNNINGrrrrrI�!s
�z*_get_all_volumes_paths.<locals>.<listcomp>c
sHi|] }t|�r|�����|��dd�t�|����d�D�d��qS)cSr�rr�r*rrrrI�!s��z5_get_all_volumes_paths.<locals>.<dictcomp>.<listcomp>z.//backingStore/path)r�r0�backing_stores)rFr�r0rrVrnrp)rGr�rrrrm�!s�����z*_get_all_volumes_paths.<locals>.<dictcomp>)r��listAllVolumesr�)r)r7�volumesZpool_volumesrrrr��!s�
�r�c

si}tdi|��}zszRt|��zt|�}t|t�r|n|g}Wnty*g}Ynwdd�|D����fdd���fdd�|��D�}��fdd�|D�}dd�|��D�WW|��St	j
yu}	zt�d	|	�WYd
}	~	nd
}	~	wwW|��|S|��w)a�
    Provide details on a storage volume. If no volume name is provided, the infos
    all the volumes contained in the pool are provided. If no pool is provided,
    the infos of the volumes of all pools are output.

    :param pool: libvirt storage pool name (default: ``None``)
    :param volume: name of the volume to get infos from (default: ``None``)
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 3000

    CLI Example:

    .. code-block:: bash

        salt "*" virt.volume_infos <pool> <volume>
    c	Ss2i|]}|��dd�t�|�d���d�D��qS)cSsh|]}|�d��qS)r7r�r�rrrr�!s��z*volume_infos.<locals>.<dictcomp>.<setcomp>rz.//disk/source/[@file])r0rrVrnrp)rGrArrrrm�!s����z volume_infos.<locals>.<dictcomp>c	
s�gd�}���}t�����}|�d�}|�d�}d}|dur.|j|dur*|�d�ndd�}|�d�}g}���rP�fdd	����D����fd
d����D�}|dt	|�kr^||dnd
��
����|d|d|||durx|�d�d�Sdd�S)zw
            Format the volume info dictionary

            :param vol: the libvirt storage volume object.
            )r7r�r�r�Znetdirrr�r�Nrhr�z./target/formatcs&h|]\}}���|�d�vr|�qS)rH)r�r#)rGr�r�)r�rrr$"s
�z>volume_infos.<locals>._volume_extract_infos.<locals>.<setcomp>cs(g|]\}}|�@s���|vr|�qSrr)rGr�Zvm_disks�Zas_backing_storer�rrrI)"s��z?volume_infos.<locals>._volume_extract_infos.<locals>.<listcomp>rr�rr
)rhrxr�r1ru�used_byrvr%)rrrVrnrXrYr#r�rtr1rx)	r��typesr	r�r�r�rvZformat_noderL)rHrRrKr�_volume_extract_infos"s@


��
	
����z+volume_infos.<locals>._volume_extract_infoscs6g|]}�dus|���kr|��dtjkr|�qS)Nr)r0rrrG)rG�objrrrrI:"s�z volume_infos.<locals>.<listcomp>cs*i|]}|����fdd�|��D��qS)cs6i|]}�dus|���krt|�r|���|��qSr�)r0rF)rGr��rNr�rrrmA"s
�z+volume_infos.<locals>.<dictcomp>.<dictcomp>)r0rI)rGr�rPrrrm@"s���cSsi|]	\}}|r||�qSrr)rGr�rJrrrrmH"rVr�Nr)
r*r�r5rNr.rr�rtr�rrrr�)
r�r�r'rer)rZdomains_listr7Zvolsr�r)rNrHrRr�r�r�volume_infos�!s<��

2��
���
�rQcKs>tdi|��}zt|||�}t|���W|��S|��w)a�
    Delete a libvirt managed volume.

    :param pool: libvirt storage pool name
    :param volume: name of the volume to delete
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. versionadded:: 3000

    CLI Example:

    .. code-block:: bash

        salt "*" virt.volume_delete <pool> <volume>
    Nr)r*rDrQrTr�)r�r�r'r)r�rrr�
volume_deleteP"s
rRc	
Ks�d}
zRz7tdi|	��}|�|�}t�|����d�}
|}|
dkr&||kr&|}t||||||||d�}t|||d�}
Wntj	yM}zt
|����d}~wwW|��|
S|��w)a�
    Create libvirt volume.

    :param pool: name of the pool to create the volume in
    :param name: name of the volume to define
    :param size: capacity of the volume to define in MiB
    :param allocation: allocated size of the volume in MiB. Defaults to 0.
    :param format:
        volume format. The allowed values are depending on the pool type.
        Check the virt.pool_capabilities output for the possible values and the default.
    :param type:
        type of the volume. One of file, block, dir, network, netdiri, ploop or None.
        By default, the type is guessed by libvirt from the pool type.
    :param permissions:
        Permissions to set on the target folder. This is mostly used for filesystem-based
        pool types. See :ref:`pool-define-permissions` for more details on this structure.
    :param backing_store:
        dictionary describing a backing file for the volume. It must contain a ``path``
        property pointing to the base volume and a ``format`` property defining the format
        of the base volume.

        The base volume format will not be guessed for security reasons and is thus mandatory.
    :param nocow: disable COW for the volume.
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. rubric:: CLI Example:

    Volume on ESX:

    .. code-block:: bash

        salt '*' virt.volume_define "[local-storage]" myvm/myvm.vmdk vmdk 8192

    QCow2 volume with backing file:

    .. code-block:: bash

        salt '*' virt.volume_define default myvm.qcow2 qcow2 8192                             permissions="{'mode': '0775', 'owner': '123', 'group': '345'"}"                             backing_store="{'path': '/path/to/base.img', 'format': 'raw'}"                             nocow=True

    .. versionadded:: 3001
    Frhr�)r%rurhrrrvrsrNr)
r*r�rrVrnr#rwr�rrrr�r�)r�r0rtrur%rhrrrvrsr'r3r)r�r�Znew_allocationr6r�rrr�
volume_definej"s6:
�
���
�rScCsdd�}dd�}dd�}	d}
d}d}z�z7|�|�}
|
�|�}|��}
t�|tj�}|�|
|||r3tjnd	�|rA|
�	|||	|�n|
�
||�d
}Wntjy]}zt|�
���d}~wwW|r�zt�|�Wn"ty�}z|
rv|
��|r�td|j����WYd}~nd}~ww|
r�z|
��W|Stjy�}z|r�td|�
�����WYd}~|Sd}~ww|S|r�zt�|�Wn"ty�}z|
r�|
��|r�td|j����WYd}~nd}~ww|
�rz|
��Wwtj�y}z|�rtd|�
�����WYd}~wd}~www)
zr
    Function performing the heavy duty for volume_upload but using an already
    opened libvirt connection.
    cSst�||�Sr�)r(r<)�stream�nbytes�opaquerrr�handler�"sz_volume_upload.<locals>.handlerc

Ss|}t�|dtj�}z
t�||tj�}Wnty/}z|jdkr#|�d}WYd}~nd}~ww|dkrNd}t�|dtj�}||krItd|����||}n)||krYd}||}nd}t�||tj�}	|	dkrktd��|	|krstd	��|	|}t�||tj	�||gS)
zH
        Taken from the sparsestream.py libvirt-python example.
        rr���NFz$Current position in file after EOF: TzNo trailing holezImpossible happened)
r(�lseek�SEEK_CUR�	SEEK_DATAr��errno�SEEK_END�RuntimeError�	SEEK_HOLE�SEEK_SET)
rTrVr0Zcurrn�eZinData�eofZ
sectionLenZholerrr�holeHandler�"s8
��

z#_volume_upload.<locals>.holeHandlercSst�||tj�Sr�)r(rYrZ)rT�lengthrVrrr�skipHandler�"r�z#_volume_upload.<locals>.skipHandlerNFrTzFailed to close file: zFailed to finish stream: )r�r�Z	newStreamr(r��O_RDONLYZuploadrZ$VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAMZ
sparseSendAllZsendAllrrr�r�r��abort�strerrorZfinish)r)r�r�r7rrdr�rWrcrerTr0r3r�Zvol_objr�rrrr��"s�&

�������
��
������������r�c		KsBtdi|��}d}zt|||||||d�}W|��|S|��w)a�
    Create libvirt volume.

    :param pool: name of the pool to create the volume in
    :param name: name of the volume to define
    :param file: the file to upload to the volume
    :param offset: where to start writing the data in the volume
    :param length: amount of bytes to transfer to the volume
    :param sparse: set to True to preserve data sparsiness.
    :param connection: libvirt connection URI, overriding defaults
    :param username: username to connect with, overriding defaults
    :param password: password to connect with, overriding defaults

    .. rubric:: CLI Example:

    .. code-block:: bash

        salt '*' virt.volume_upload default myvm.qcow2 /path/to/disk.qcow2

    .. versionadded:: 3001
    F)rrdr�Nr)r*r�r�)	r�r�r7rrdr�r'r)r3rrr�
volume_upload#s�
�ri)r�r�)
NNNNNNNNFN)NrNNNF)	NNNNNNNNN)
NNNNNNNNNN)Fr�)Nr�)r�NNTr�Nr�TTNNrNNNNNNNNNNFN)rrNNNNNTNNFNNNNNFNF)F)r�)FFr�)NF)NNNN)FFr)
NNNNTTNNNNNNN)NNNNNNNNNNNF)NNNNNNNNNNFT)NNF)NNNNNNNNNNF)rNNNNF)rrF)��__doc__r-r�r�rA�loggingr(rqrUrSr�rarF�urllib.parser�Z	xml.etreerZxml.saxrZjinja2.exceptionsr[Zsalt.utils.datarNZsalt.utils.filesZsalt.utils.jsonZsalt.utils.pathZsalt.utils.stringutilsZsalt.utils.templatesZsalt.utils.virtZsalt.utils.xmlutilrOr,Zsalt.utils.yamlZsalt._compatrZsalt.exceptionsrrrrr�ImportError�	getLoggerrcrZEnvironmentZFileSystemLoaderr�r�Z	templatesZTEMPLATE_DIRNAMErYrr�rr!r*r5rSr[rardrfrzr�r�r�r�r�r�r�r�r�rqrwr�r�r�r�r�r�r�r�r�r�r�rrr
rr+r.r8r<rDrRrTrYr\r^r_rhrqrtrvrwr3r|r�r�r�r�r�r�r�r�r�rrrr
rr
rrrrrrrrr!r"r#rWr$rr(r)r&r-r.r/r3r7r?r@rAr�rCrDrFrGrNr�rRrZr[r^r`rdrerfrirsrzrr�rHr�r�r�r�r�r�r�r"r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrrr	rr�r$r'r%r2r3r8r9r;r=r>r?r@rArBrCrDrFr�rQrRrSr�rirrrr�<module>s�z�
���+'&:
%
34�i�%�R�@
GX9aR98-"�=!. *




		�]G-c/.
; �/$K*(!L
	@SL#4+_,1Y7-'7]�"�~D'�3�5�/;)
p�T\