o
    ba                     @   s   d dl Z d dlZd dlZddlmZ ddlmZ ddlmZ ddlm	Z	m
Z
mZ dZdZd	ZG d
d de	ZG dd de	Zdd Zdd ZG dd de	ZG dd deZdd ZG dd deZdS )    N   )generatename)progress)log)
XMLBuilderXMLChildPropertyXMLPropertyz/devz/dev/disk/by-pathz/dev/mapperc                   @   s8   e Zd ZdZg dZedZedZedZedZ	dS )_StoragePermissionspermissions)modeownergrouplabelz./modez./ownerz./groupz./labelN)
__name__
__module____qualname__XML_NAME_XML_PROP_ORDERr   r   r   r   r    r   r   +/usr/share/virt-manager/virtinst/storage.pyr	      s    r	   c                   @   s&   e Zd ZdZedZeedddZdS )_StorageObjectzg
    Base class for building any libvirt storage object.

    Meaningless to directly instantiate.
    z./namez./targetT)relative_xpath	is_singleN)	r   r   r   __doc__r   namer   r	   r
   r   r   r   r   r   !   s    

r   c                 C   s   d}|   rtjd}|S )Nz/var/lib/libvirt/imagesz~/.local/share/libvirt/images)is_unprivilegedospath
expanduser)connr   r   r   r   _preferred_default_pool_path2   s   r    c                 C   s8   |   D ]}|j}|d urtj||kr|  S qd S N)fetch_all_poolstarget_pathr   r   abspath)r   r   poolxmlxml_pathr   r   r   _lookup_poolxml_by_path9   s   r'   c                   @   s,   e Zd ZddgZdZedZedddZdS )	_Hostr   porthostz./@namez./@portTis_intN)r   r   r   r   r   r   r   r)   r   r   r   r   r(   A   s
    r(   c                   @   s  e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZedd Zedd Zedd Zedd Zedd ZedOddZedd Zdd Zdd  Zd!d" Zd#d$ ZeeeZd%d& Zd'Zg d(Z e!d)Z"e!d*Z#e!d+Z$e!d,Z%e!d-Z&e!d.d/d0Z'e!d1d/d0Z(e!d2d/d0Z)e!d3Z*e!d4Z+e!d5Z,e!d6Z-e!d7Z.e!d8Z/e!d9Z0e1e2d:d;Z3d<d= Z4d>d? Z5d@dA Z6dBdC Z7dDdE Z8dFdG Z9dHdI Z:dJdK Z;dPdMdNZ<dLS )QStoragePoolzI
    Base class for building and installing libvirt storage pool xml
    dirfsnetfslogicaldiskiscsiscsimpathglusterrbdsheepdogzfsc              
   C   s   d}z	|  ||d}W n ty& } z| j|r!g W  Y d}~S  d}~ww td| ddlm  m} |	|}dd |
dD }td| |S )	z
        Return a list of StoragePool instances built from libvirt's pool
        source enumeration (if supported).

        :param conn: Libvirt connection
        :param pool_type: Pool type string from I{Types}
        z	<source/>r   Nz%Libvirt returned pool sources XML:
%sc                 S   s   g | ]}|j qS r   )text).0er   r   r   
<listcomp>r   s    z6StoragePool.pool_list_from_sources.<locals>.<listcomp>./source/namezSources returning: %s)findStoragePoolSources	Exceptionsupportis_error_nosupportr   debugxml.etree.ElementTreeetreeElementTree
fromstringfindall)r   	pool_type
source_xmlxmlr<   ETrootretr   r   r   pool_list_from_sourcesZ   s   	
z"StoragePool.pool_list_from_sourcesc                 C   sT   d}t | }d}|  D ]}|j|kr|} nqt| |}|r(td|j|j |S )z
        Helper to lookup the default pool. It will return one of
        * The pool named 'default'
        * If that doesn't exist, the pool pointing to the default path
        * Otherwise None
        defaultNz$Found default pool name=%s target=%s)r    r"   r   r'   r   rC   r#   )r   r   r   r%   trypoolr   r   r   lookup_default_poolw   s   

zStoragePool.lookup_default_poolc              
   C   s   t | }|r	|S z%d}t| }td| t | }|j|_||_||_|j	dddd |W S  t
yQ } ztjddd td|t|d }t|d	d	}~ww )
zb
        Attempt to lookup the 'default' pool, but if it doesn't exist,
        create it
        rP   z1Attempting to build default pool with target '%s'T)buildcreate	autostartzError building default poolexc_infoz:Couldn't create default storage pool '%(path)s': %(error)s)r   errorN)r-   rR   r    r   rC   TYPE_DIRtyper   r#   installr@   _strRuntimeError)r   r%   r   r   defpoolr<   msgr   r   r   build_default_pool   s.   

zStoragePool.build_default_poolc                 C   s   t | |}|s	dS | |jS )a  
        Return the first pool with matching matching target path.
        return the first we find, active or inactive. This iterates over
        all pools and dumps their xml, so it is NOT quick.

        :returns: virStoragePool object if found, None otherwise
        N)r'   storagePoolLookupByNamer   )r   r   r%   r   r   r   lookup_pool_by_path   s   
	zStoragePool.lookup_pool_by_pathc                    s     fdd}t j||fi |S )z
        Finds a name similar (or equal) to passed 'basename' that is not
        in use by another pool. Extra params are passed to generate_name
        c                    s"      D ]
}|j| kr dS qdS )NTF)r"   r   )r   poolr   r   r   cb   s
   
z&StoragePool.find_free_name.<locals>.cb)r   generate_name)r   basenamekwargsrf   r   re   r   find_free_name   s   zStoragePool.find_free_nameFc                 C   sR   |   d tjkrtd|   | d |r'td|   | d dS dS )z
        If the passed vmmStoragePool isn't running, start it.

        :param pool_object: vmmStoragePool to check/start
        :param refresh: If True, run refresh() as well
        r   zstarting pool=%szrefreshing pool=%sN)infolibvirtVIR_STORAGE_POOL_RUNNINGr   rC   r   rT   refresh)pool_objectrn   r   r   r   ensure_pool_is_running   s   
z"StoragePool.ensure_pool_is_runningc                 C   F   t td| z| | W n tjy   Y d S w ttd| )NStorage objectz)Name '%s' already in use by another pool.)r   validate_generic_namer\   rb   rl   libvirtError
ValueError)r   r   r   r   r   validate_name      zStoragePool.validate_namec                 C   sv   |   sd S | j| jks| j| jks| j| jkr#tjt| j	| j
S | j| jks/| j| jkr1tS | j| jkr9tS d S r!   )supports_target_pathrZ   rY   
TYPE_NETFSTYPE_FSr   r   joinr    r   r   
TYPE_ISCSI	TYPE_SCSI_DEFAULT_SCSI_TARGET
TYPE_MPATH_DEFAULT_MPATH_TARGETselfr   r   r   default_target_path   s   zStoragePool.default_target_pathc                 C   s0   | j | jks| j | jkrdS | j | jkrdS dS )N_source_dir_source_adapter_source_device)rZ   ry   TYPE_GLUSTERr}   r   r   r   r   _type_to_source_prop   s   z StoragePool._type_to_source_propc                 C   s   t | |  S r!   )getattrr   r   r   r   r   _get_source      zStoragePool._get_sourcec                 C   s   t | |  |S r!   )setattrr   )r   valr   r   r   _set_source   s   zStoragePool._set_sourcec                 C   s0   |   sd S | jtjkrdS | jtjkrdS d S )Nr7   gv0)supports_source_namerZ   r-   TYPE_RBDr   r   r   r   r   default_source_name   s   zStoragePool.default_source_namerd   )r   rZ   uuidcapacity
allocation	availableformathostsr   r   r   source_namer#   r
   	auth_typeauth_usernameauth_secret_uuidz./source/dir/@pathz./source/adapter/@namez./source/device/@path./@typez./uuid
./capacityTr+   ./allocationz./availablez./source/format/@typez./source/initiator/iqn/@namer>   z./source/auth/@typez./source/auth/@usernamez./source/auth/secret/@uuid./target/pathz./source)r   c                 C   "   | j | j| j| j| j| j| jfv S r!   )rZ   rY   rz   ry   r|   r}   r   r   r   r   r   rx   4  s
   z StoragePool.supports_target_pathc                 C      | j | j| j| j| j| jfv S r!   )rZ   TYPE_LOGICALr   r   TYPE_SHEEPDOGTYPE_ZFSr   r   r   r   r   :  s   z StoragePool.supports_source_namec                 C   r   r!   )rZ   rz   ry   	TYPE_DISKr|   r}   r   r   r   r   r   supports_source_path?  s
   z StoragePool.supports_source_pathc                 C   r   r!   )rZ   ry   r|   r   r   r   r   r   r   r   supports_hostsE  s   zStoragePool.supports_hostsc                 C   s   | j | j| j| jfv S r!   )rZ   rz   ry   r   r   r   r   r   supports_formatJ  s   zStoragePool.supports_formatc                 C   s   | j | jfv S r!   )rZ   r|   r   r   r   r   supports_iqnM  r   zStoragePool.supports_iqnc                 C   s~   | j tjks| j tjks| j tjks| j tjks| j tjkr!tjS | j tj	ks9| j tj
ks9| j tjks9| j tjkr<tjS tjS r!   )rZ   r-   r   r   r}   r   r   StorageVolume
TYPE_BLOCKr   r   r|   r   TYPE_NETWORK	TYPE_FILEr   r   r   r   get_disk_typeP  s   zStoragePool.get_disk_typec                 C   s   |  | j| j | js| j| jkrt| _n|  | _| js"| 	 | _| j
s,|  r,d| _
| j| jkr<| j
dkr>d | _
d S d S d S )Nauto)rv   r   r   r#   rZ   r   _DEFAULT_DEV_TARGETr   r   r   r   r   r   r   r   r   validatec  s   


zStoragePool.validateNc           
   
   C   s  |   }td| j| t|}z	| j|d}W n ty3 } zt	dt
| }t|dd}~ww d}	|r[z|tj W n tyZ } zt	dt
| }	W Y d}~nd}~ww |r|	sz|d W n ty } zt	dt
| }	W Y d}~nd}~ww |r|	sz|d W n ty } zt	dt
| }	W Y d}~nd}~ww |	rz	|  W t|	 ty } ztd	t
| W Y d}~t|	d}~ww | j| |S )
z+
        Install storage pool xml.
        z'Creating storage pool '%s' with xml:
%sr   z!Could not define storage pool: %sNz Could not build storage pool: %sz Could not start storage pool: %sTz%Could not set pool autostart flag: %sz(Error cleaning up pool after failure: %s)get_xmlr   rC   r   r   ensure_meterr   storagePoolDefineXMLr@   r\   r]   r^   rS   rl   VIR_STORAGE_POOL_BUILD_NEWrT   setAutostartundefinecache_new_pool)
r   meterrT   rS   rU   rK   rd   r<   r`   errmsgr   r   r   r[   w  s^   


zStoragePool.install)F)NFFF)=r   r   r   r   rY   rz   ry   r   r   r|   r}   r   r   r   r   r   staticmethodrO   rR   ra   rc   rj   rp   rv   r   r   r   r   propertysource_pathr   r   r   r   r   r   r   rZ   r   r   r   r   r   iqnr   r   r   r   r#   r   r(   r   rx   r   r   r   r   r   r   r   r[   r   r   r   r   r-   I   sz    






	
	r-   c                 C   s   d }|sd S 	 z|s| | }|  W n ty$   |dr"Y nY nw q|d u r1td d S 	 | \}}}|| |drEd S q2)NTg?z.Couldn't lookup storage volume in prog thread.r   )storageVolLookupByNamerk   r@   waitr   rC   update)volnamerd   r   eventvoldummy1dummy2allocr   r   r   _progress_thread  s0   





r   c                   @   s\  e Zd ZdZedd Zed;ddZeeddZ	eed	d
Z
eeddZeeddZeeddZdd Zdd Zdd ZeeeZedd Zdd Zdd Zdd ZeeeZedd  Zd!d" ZeeZd#Zg d$Zed%Zed&Zed'd(d)Z ed*d(d)Z!ed+Z"ed,Z#ed-Z$ed.Z%ed/d(d0Z&d1d2 Z'd3d4 Z(d5d6 Z)d;d7d8Z*d9d: Z+dS )<r   zK
    Base class for building and installing libvirt storage volume xml
    c                 C   s   | sdS | dkr
dS d|  S )N rawz.img.r   )fmtr   r   r   get_file_extension_for_format  s
   z+StorageVolume.get_file_extension_for_formatNc                    s   g  |r;d}  }|  D ]}|j |kr|j} nq|jjD ]}| }	|r:|	r:tj|	|kr: 	tj
|	 q fdd}
tjdd tj||
fi |S )a  
        Finds a name similar (or equal) to passed 'basename' that is not
        in use by another volume. Extra params are passed to generate_name

        :param collideguest: Guest object. If specified, also check to
        ensure we don't collide with any disk paths there
        Nc                    s   |  v rdS t j| S )NT)r   check_libvirt_collisionr   )trynamecollidelistro   r   r   rf     s
   z(StorageVolume.find_free_name.<locals>.cbT)rn   )r   r"   r#   devicesr2   get_source_pathr   r   dirnameappendrh   r-   rp   r   rg   )r   ro   rh   collideguestri   
pooltargetpoolnamer%   r2   	checkpathrf   r   r   r   rj     s$   	
zStorageVolume.find_free_nameVIR_STORAGE_VOL_FILEr   VIR_STORAGE_VOL_BLOCKr   VIR_STORAGE_VOL_DIR   VIR_STORAGE_VOL_NETWORK   VIR_STORAGE_VOL_NETDIR   c                 O   s4   t j| g|R i | d | _d | _d | _d| _d S )NF)r   __init__
_input_vol_pool	_pool_xml_reflink)r   argsri   r   r   r   r     s
   
zStorageVolume.__init__c                 C      | j S r!   )r   r   r   r   r   	_get_pool     zStorageVolume._get_poolc                 C   s,   t | || _t | j| jdd| _d S Nr   )parsexml)r-   rp   r   r   XMLDescr   )r   newpoolr   r   r   	_set_pool  s
   

zStorageVolume._set_poolc                 C   r   r!   )r   r   r   r   r   	input_vol  s   zStorageVolume.input_volc                 C   sN   || _ t| j| j dd}|j| _|j| _|j| _| js%| j  | _	d S d S r   )
r   r   r   r   r   r   r   r   storagePoolLookupByVolumerd   )r   r   parsevolr   r   r   set_input_vol  s   
zStorageVolume.set_input_volc                 C   r   r!   r   r   r   r   r   _get_reflink  r   zStorageVolume._get_reflinkc                 C   s
   || _ d S r!   r   )r   reflinkr   r   r   _set_reflink  s   
zStorageVolume._set_reflinkc                 C   rq   )Nrr   z+Name '%s' already in use by another volume.)r   rs   r\   r   rl   rt   ru   )rd   r   r   r   r   rv   %  rw   zStorageVolume.validate_namec                 C   sP   | j r#| j dkr| jS | j dkr| jS | j dkr| jS | j dkr#| jS | j S )Nfileblockr.   network)rZ   r   r   rY   r   r   r   r   r   r   r   _get_vol_type0  s   




zStorageVolume._get_vol_typevolume)r   keyr   r   r   r#   r
   r   z./keyr   Tr+   r   z./target/format/@typer   z./backingStore/pathz./backingStore/format/@typez ./target/features/lazy_refcounts)is_boolc                 C   s   t d| j ddlm} || j| j\}}}|}|s#t d d S t| j|d}||_	t d|
  | sBt d d S t d|j |jS )	Nz0Attempting to detect format for backing_store=%sr   )diskbackendz(Didn't find any volume for backing_storer   z"Found backing store volume XML:
%szXbacking_store volume doesn't appear to have a file format we can specify, returning NonezReturning format=%s)r   rC   backing_storer   r   manage_pathr   r   r   rd   r   r   r   )r   r   r   r   rd   dummyvolxmlr   r   r   _detect_backing_store_formatR  s&   

z*StorageVolume._detect_backing_store_formatc                 C   s   | j | jkS r!   )	file_typer   r   r   r   r   r   q  s   zStorageVolume.supports_formatc                 C   s   |  | j| j | js| j| jkrd| _| dr%| jdkr%| jj	 | _
| jjtjkr=| j| jkr=ttd | j| _|  \}}|rIt||rRt| d S d S )Nr   lazy_refcountsqcow2zNSparse logical volumes are not supported, setting allocation equal to capacity)rv   rd   r   r   r  r   _prop_is_unsetr   rA   conn_qcow2_lazy_refcountsr  r   rZ   r-   r   r   r   r   warningr\   is_size_conflictru   )r   isfatalr   r   r   r   r   y  s   zStorageVolume.validatec           
   
   C   s  | j r| js|  | _|  }td| j| d}d}| jdkr;| j s;| jj	
| jr;|tjO }| j| jkr;|tjO }| jrF|ttddO }t }t|}tjtd| j| j||fd}d|_zpzN|  td	d
| ji }||| j | j rd}d}| jr| j|| j|}ntd| | j||}|  td| j |W W |   |!  S  t"y }	 ztjddd d| jt#|	f }t$|dd}	~	ww |   |!  w )z;
        Build and install storage volume from xml
        z)Creating storage volume '%s' with xml:
%sr   r  VIR_STORAGE_VOL_CREATE_REFLINKr   zChecking storage allocation)targetr   r   TzAllocating '%(filename)s'filenamezUsing vol create flags=%sz%Storage volume '%s' install complete.zError creating storage volumerV   z)Couldn't create storage volume '%s': '%s'N)%r  backing_formatr  r   r   rC   r   r   r   rA   pool_metadata_preallocrd   rl   (VIR_STORAGE_VOL_CREATE_PREALLOC_METADATAr   r   r   r   	threadingEventr   r   Threadr   daemonstartr\   is_really_testr   createXMLFrom	createXMLendsetr{   r@   r]   r^   )
r   r   rK   
cloneflagscreateflagsr   tr`   r   r<   r   r   r   r[     sj   









zStorageVolume.installc                 C   sx   | j sdS | j  d }| j|kr#td| jd |d d }d|fS | j|kr:td| jd |d d }d|fS dS )	z
        Report if requested size exceeds its pool's available amount

        :returns: 2 element tuple:
            1. True if collision is fatal, false otherwise
            2. String message if some collision was encountered.
        )Fr   r   zThere is not enough free space on the storage pool to create the volume. (%(mem1)s M requested allocation > %(mem2)s M available)i   )mem1mem2TzThe requested volume capacity will exceed the available pool space when the volume is fully allocated. (%(mem1)s M requested capacity > %(mem2)s M available)F)rd   rk   r   r\   r   )r   availr`   r   r   r   r    s$   

zStorageVolume.is_size_conflictr!   ),r   r   r   r   r   r   rj   r   rl   r   r   rY   r   TYPE_NETDIRr   r   r   r   rd   r   r   r   r   r   rv   r   r  r   r   r   rZ   r   r   r   r   r#   r  r  r  r  r   r   r[   r  r   r   r   r   r     sV    
 





=r   )r   r  rl   r   r   r   loggerr   
xmlbuilderr   r   r   r   r~   r   r	   r   r    r'   r(   r-   r   r   r   r   r   r   <module>   s(   
  a