Mini Shell

Direktori : /lib/python3.6/site-packages/blivet/__pycache__/
Upload File :
Current File : //lib/python3.6/site-packages/blivet/__pycache__/partitioning.cpython-36.pyc

3

�Mf�M�@sddlmZmZddlmZddlZddlZejdd�ddlZddl	Z	ddl
mZmZm
Z
ddlmZdd	lmZmZmZmZdd
lmZddlmZddlmZmZmZddlZejd
�Zdd�Zej e�Z!dGdd�Z"dHdd�Z#dd�Z$dd�Z%dd�Z&dIdd�Z'dJdd�Z(dd �Z)dKd!d"�Z*d#d$�Z+d%d&�Z,dLd'd(�Z-Gd)d*�d*e.�Z/Gd+d,�d,e/�Z0Gd-d.�d.e/�Z1Gd/d0�d0e.�Z2Gd1d2�d2e2�Z3Gd3d4�d4e2�Z4Gd5d6�d6e4�Z5d7d8�Z6Gd9d:�d:e.�Z7Gd;d<�d<e.�Z8d=d>�Z9dMd?d@�Z:dAdB�Z;ej e;�Z<dCdD�Z=dEdF�Z>dS)N�)�gt�lt)�DecimalNZBlockDevz2.0�)�DeviceError�PartitioningError�AlignmentError)�flags)�Device�PartitionDevice�
LUKSDevice�device_path_to_name)�Size)�_)�	stringize�
unicodeize�compareZblivetcCs�d}|j}|j}|dk	r$|dkr$dS|dkr8|dk	r8dS|dk	rR|dk	rRt||�S|jrb||j8}|jrr||j7}|jr�|jr�|d8}n6|jr�|jr�|d7}n|tt|j�t|j��d7}|t|j|j�d8}|t|j|j�d7}|t|j|j�d8}|j�r`|j�r`|j�r.|j�r.|d8}n2|j�rJ|j�rJ|d7}n|t|j|j�d8}t	|j
d	��r�t	|j
d	��r�|t|j
j|j
j�d
7}|dk�r�d}n|dk�r�d}|S)
ag More specifically defined partitions come first.

        < 1 => x < y
          0 => x == y
        > 1 => x > y

        :param part1: the first partition
        :type part1: :class:`devices.PartitionDevice`
        :param part2: the other partition
        :type part2: :class:`devices.PartitionDevice`
        :return: see above
        :rtype: int
    rNri����d�2��
mountpoint�
���r)�req_start_sectorr�weight�	req_disks�len�req_primary�req_grow�
req_base_size�req_max_size�hasattr�formatr)Zpart1Zpart2�retZpart1_startZpart2_start�r%�"/usr/lib/python3.6/partitioning.py�partition_compare,sF








r'cCs�d}|j�}|jtj�}|j}||jkr�||jdkrl|rH|rHtj}q�|sX|sjtj}q�|sdtj}q�tj}q�|sxtj}q�|r�tj}n
|r�tj}|S)a Return the type of partition to create next on a disk.

        Return a parted partition type value representing the type of the
        next partition we will create on this disk.

        If there is only one free primary partition and we can create an
        extended partition, we do that.

        If there are free primary slots and an extended partition we will
        recommend creating a primary partition. This can be overridden
        with the keyword argument no_primary.

        :param disk: the disk from which a partition may be allocated
        :type disk: :class:`parted.Disk`
        :keyword no_primary: refuse to return :const:`parted.PARTITION_NORMAL`
        :returns: the chosen partition type
        :rtype: a parted PARTITION_* constant
    Nr)	�getExtendedPartitionZsupportsFeature�partedZDISK_TYPE_EXTENDED�primaryPartitionCount�maxPrimaryPartitionCount�PARTITION_EXTENDED�PARTITION_NORMAL�PARTITION_LOGICAL)�disk�
no_primary�	part_type�extendedZsupports_extendedZ
primary_countr%r%r&�get_next_partition_typews*

r3cCs2tjd|jj||||||�|j�}|p4tjddd�}�x�|j�D�]�}	|dk	r�|j|	|	j	�r�tjd|	j	|	j
�y|j|	|	j	�}
Wntk
r�d}
YnX|
|	j	kr�d}
|
dkr�tjd�qBtj
|	j|
|	j
d�}	tjd	|	j	|	j
t|	jd
d���|dk	�r|	j|��rtjd�qB|�r\|jj|	�}|�r<|tjk�sP|�r\|tjk�r\tjd
�qB|	j	|jk�rvtjd�qB|�r�td�}t|	j	|jj�}
|
|}||k�r�tjd|�qBtjd|	j	|	j
t|	jd
d���t|	jd
d��}|�s�|tjk�r�t}nt}||krB|�s ||	j|j�rB|	}|rBPqBW|S)a� Return the "best" free region on the specified disk.

        For non-boot partitions, we return the largest free region on the
        disk. For boot partitions, we return the first region that is
        large enough to hold the partition.

        Partition type (parted's PARTITION_NORMAL, PARTITION_LOGICAL) is
        taken into account when locating a suitable free region.

        For locating the best region from among several disks, the keyword
        argument best_free allows the specification of a current "best"
        free region with which to compare the best from this disk. The
        overall best region is returned.

        :param disk: the disk
        :type disk: :class:`parted.Disk`
        :param part_type: the type of partition we want to allocate
        :type part_type: one of parted's PARTITION_* constants
        :param req_size: the requested size of the partition in MiB
        :type req_size: :class:`~.size.Size`
        :keyword start: requested start sector for the partition
        :type start: int
        :keyword boot: whether this will be a bootable partition
        :type boot: bool
        :keyword best_free: current best free region for this partition
        :type best_free: :class:`parted.Geometry`
        :keyword grow: indicates whether this is a growable request
        :type grow: bool
        :keyword alignment: disk alignment requirements
        :type alignment: :class:`parted.Alignment`

    z]get_best_free_space_region: disk=%s part_type=%d req_size=%s boot=%s best=%s grow=%s start=%srr)�offset�	grainSizeNz%aligning start sector of region %d-%dz/failed to align start sector -- skipping region)�device�start�endzchecking %d-%d (%s)�B)�unitz3free region does not contain requested start sectorz$free region not suitable for requestz5free range start sector beyond max for new partitionsz2 TiBz1free range position would place boot req above %sz current free range is %d-%d (%s))�log�debugr6�pathr(r)�	Alignment�getFreeSpaceRegions�	isAlignedr7r8�alignUp�ArithmeticError�Geometryr�	getLengthZcontainsSector�geometry�containsr-r.�maxPartitionStartSector�
sectorSizer,rr�length)r/r1�req_sizer7�boot�	best_free�grow�	alignmentr2Z	free_geomZ
aligned_startZin_extended�max_bootZ
free_start�req_endZ	free_size�opr%r%r&�get_best_free_space_region�sr#









rRcCst||�S)a Convert length in sectors to size.

        :param sectors: sector count
        :type sectors: int
        :param sector_size: sector size
        :type sector_size: :class:`~.size.Size`
        :returns: the size
        :rtype: :class:`~.size.Size`
    )r)Zsectors�sector_sizer%r%r&�sectors_to_size"s
rTcCst||�S)a Convert size to length in sectors.

        :param size: size
        :type size: :class:`~.size.Size`
        :param sector_size: sector size in bytes
        :type sector_size: :class:`~.size.Size`
        :returns: sector count
        :rtype: int
    )�int)�sizerSr%r%r&�size_to_sectors/s
rWcs�tjddd�|D�dd�|D��g�xZ|D]R}|jr,|j|kr,|jrHq,|jrPq,|jr`�j|�|jjj	j
|j�d|_d|_q,W��fdd�}x:|D]2}|jj}|||�r�tjd|j�|jj	j
|�q�WdS)	a Remove newly added partitions from disks.

        Remove all non-existent partitions from the disks in blivet's model.

        :param: disks: list of partitioned disks
        :type disks: list of :class:`~.devices.StorageDevice`
        :param remove: list of partitions to remove
        :type remove: list of :class:`~.devices.PartitionDevice`
        :param all_partitions: list of all partitions on the disks
        :type all_partitions: list of :class:`~.devices.PartitionDevice`
        :returns: None
        :rtype: NoneType
    z:removing all non-preexisting partitions %s from disk(s) %scSsg|]}d|j|jf�qS)z	%s(id %d))�name�id)�.0�pr%r%r&�
<listcomp>Ksz)remove_new_partitions.<locals>.<listcomp>cSsg|]
}|j�qSr%)rX)rZ�dr%r%r&r\LsNcsP�rL|jjrL�dd��D�kr$dStjr.dSt�fdd��D��rHdSdSdS)z� We may want to remove extended partition from the disk too.
            This should happen if we don't have the PartitionDevice object
            or in installer_mode after we've removed all logical paritions.
        css|]}|jVqdS)N)�parted_partition)rZr[r%r%r&�	<genexpr>fszBremove_new_partitions.<locals>._remove_extended.<locals>.<genexpr>TFc3s|]}|j�jkVqdS)N)r/)rZ�l)r2r%r&r_msN)r#Zlogical_partitionsr	Zkeep_empty_ext_partitions�any)r/r2)�all_partitions�removed_logical)r2r&�_remove_extended_sz/remove_new_partitions.<locals>._remove_extendedz)removing empty extended partition from %s)
r;r<r^r/�exists�is_extendedZ
is_logical�appendr#�parted_disk�removePartition�extended_partitionrX)�disks�removerb�partrdr/r2r%)rbrcr&�remove_new_partitions<s*




rncCsR|dkr`|dkr t|j|j�}n|}y|j|d�}Wntk
rP|j�}YnX|j|d�}ntjddd�}tjddd�}t	j
d|�t|j�}	|dk	r�|dkr�|t||	�d}n�|j
}|j||�s�|j||�}|jdkr�|dkr�|j||�}|tjk�r||j7}||j
k�r$t	j
d	|j
|�|tjk�rL|�rL|j}||d}
nt||	�}
||
d}|j||��s�|j||�}t	j
d
|
||d�||k�r�ttd���tj|j||d�}|jj}|�r�|j|k�r�ttd
���tj|j||d�}
tj|d�}y|jj|
|d�Wn:tj k
�rL}zttd�t!|���WYdd}~XnX|
S)a� Add a new partition to a disk.

        :param disklabel: the disklabel to add the partition to
        :type disklabel: :class:`~.formats.DiskLabel`
        :param free: the free region in which to place the new partition
        :type free: :class:`parted.Geometry`
        :param part_type: the partition type
        :type part_type: a parted.PARTITION_* constant
        :param size: size of the new partition
        :type size: :class:`~.size.Size`
        :keyword start: starting sector for the partition
        :type start: int
        :keyword end: ending sector for the partition
        :type end: int
        :raises: :class:`~.errors.PartitioningError`
        :returns: the newly added partitions
        :rtype: :class:`parted.Partition`

        .. note::

            The new partition will be aligned using the kernel-provided optimal
            alignment unless a start sector is provided.

    N)rV)rNrr)r5r4zusing alignment: %sZsunz#adjusted start sector from %d to %dzadjusted length from %d to %dz$unable to allocate aligned partition)r6r7r8z&requested size exceeds maximum allowed)r/�typerE)�	exactGeom)�	partition�
constraintz#failed to add partition to disk: %sr)"rTrIrS�
get_alignmentr�get_minimal_alignment�get_end_alignmentr)r>r;r<rrWr7r@ZalignNearestZ
label_typerAr.r5r,r8rrrC�
parted_devicerh�maxPartitionLength�	Partition�
Constraint�addPartition�_pedZPartitionException�str)�	disklabel�freer1rVr7r8Z_sizerN�
end_alignmentrSrIZnew_geomZ
max_lengthrqrr�er%r%r&�
add_partition|sf



&r�FcCstg}xj|D]b}x\|jjj�D]L}|jjj}|j|kr|r^|j|j|}tjd|j|�||_|j|�qWq
W|S)a Return a list of free regions on the specified disks.

        :param disks: list of disks
        :type disks: list of :class:`~.devices.Disk`
        :param align: align the region length to disk grain_size
        :type align: bool
        :returns: list of free regions
        :rtype: list of :class:`parted.Geometry`

        Only free regions guaranteed to contain at least one aligned sector for
        both the start and end alignments in the
        :class:`~.formats.disklabel.DiskLabel` are returned.
    z+length of free region aligned from %d to %d)	r#rhr?rNr5rIr;r<rg)rk�alignr~r/�f�
grain_sizeZaligned_lengthr%r%r&�get_free_regions�s



r�cCs�x|D]�}|jj}|s\x@|jD]6}|j|kr |jr |jrF|j|�q |jj|dd�q Wqt	|j
��}|jj|�}|r�|js�||_xN|jD]D}|j|kr�|jr�|j|jjkr�|jr�|j|�q�|jj|dd�q�W|r�qt
||d�}|g|_||_|jj|�qWdS)a0 Reconcile extended partition changes with the DeviceTree.

        :param storage: the Blivet instance
        :type storage: :class:`~.Blivet`
        :param disks: list of disks
        :type disks: list of :class:`~.devices.StorageDevice`
        :returns: :const:`None`
        :rtype: NoneType
    F)�	modparent)�parentsN)r#rj�
partitionsr/rfreZdestroy_device�
devicetree�_remove_devicer
�getDeviceNodeNameZget_device_by_namer^rr�Z_add_device)�storagerkr/r2rmZ
extended_namer6r%r%r&�update_extended_partitions�s4r�cCsrdd�|jD�}x^|D]V}y|j�Wqtk
rj}z(tjd|j|�ttd�|j��WYdd}~XqXqWxB|jD]8}|j	rx|j
rx|jjj
|dd�rx|jj|dd	d
�qxW|jdd�}|�r$x"|jD]}d|_|j	s�|j|_q�W|jjd|jjd��}y
d	|_Wntk
�r"YnXt|||�t|�}	zzy(t||||	|d
�t|||	|jd�Wntk
�rz�Yn6Xx2|jD](}tjd|�d|_|j|_|j|_�q�WWdg|_x$|jD]}|j
�rҐq�|j��q�Wt||�x�dd�|jD�D]l}|j �}
|
dk�r8ttd�|j!j|j!j"|j!j#d���n.|
dk�r�ttd�|j!j|j!j"|j!j#d����q�WXdS)a� Allocate and grow partitions.

        When this function returns without error, all PartitionDevice
        instances must have their parents set to the disk they are
        allocated on, and their parted_partition attribute set to the
        appropriate parted.Partition instance from their containing
        disk. All req_xxxx attributes must be unchanged.

        :param storage: Blivet instance
        :type storage: :class:`~.Blivet`
        :param boot_disk: optional parameter, the disk the bootloader is on
        :type boot_device: :class:`~.devices.StorageDevice`
        :raises: :class:`~.errors.PartitioningError`
        :returns: :const:`None`
    cSs g|]}|jjr|jr|�qSr%)r#Z	supportedZ	protected)rZr]r%r%r&r\Dsz#do_partitioning.<locals>.<listcomp>zfailed to set up disk %s: %szdisk %s inaccessibleNZcreate)r6Zaction_typeFT)r��forcez/boot�/)�	boot_disk)�	size_setszfixing size of %scSsg|]}|js|�qSr%)re)rZr[r%r%r&r\�srzapartition is too small for %(format)s formatting (allowable size is %(min_size)s to %(max_size)s))r#�min_size�max_sizezapartition is too large for %(format)s formatting (allowable size is %(min_size)s to %(max_size)s))$ZpartitionedZsetuprr;�errorrXrrr�rerfr�Zactions�findr��req_bootabler rJZmountpoints�get�AttributeErrorrnr��allocate_partitions�grow_partitionsr��	Exceptionr<rrVZupdate_namer�Z
check_sizer#r�r�)r�r�rkr/r�rqr�rmZboot_devicer~Zproblemr%r%r&�do_partitioning4sd
(



r�cCs^y|j|d�}Wntk
r,|j�}YnXt|j�}t||�\}}|||rT|ntd�S)N)rVr)rsrrtrr5�divmod)rVr}rNr�Zgrains�remr%r%r&�align_size_for_disklabel�s
r�cs�fdd�|D�S)aTResolve disk tags to a disk list.

        :param disks: available disks
        :type disks: list of :class:`~.devices.StorageDevice`
        :param tags: tags to select disks based on
        :type tags: list of str

        If tags contains multiple values it is interpeted as
        "include disks containing *any* of these tags".
    cs&g|]�t�fdd��D��r��qS)c3s|]}|�jkVqdS)N)�tags)rZ�tag)r/r%r&r_�sz/resolve_disk_tags.<locals>.<listcomp>.<genexpr>)ra)rZ)r�)r/r&r\�sz%resolve_disk_tags.<locals>.<listcomp>r%)rkr�r%)r�r&�resolve_disk_tags�sr�c*&Cs�tjddd�|D�dd�|D��dd�|D�}|jtd�i}i}x0|D](}|j|j�krJ|j||j<|||j<qJWt|||��x<|D�]2}	|	jr�|	j	r�q�g}
|	j
r�|	j
}
n|	jr�t||	j�}
n|}
|
j|j
d�|�rx8|
dd�D](}||kr�|
j|�}|
jd|
j|��q�W|	jd	k}tjd
|	j|	jdd�|
D�||	j|	j|	j|	j|	j|	j�d}
d}d}d}�x�|
D�]�}y||j}Wn$tk
�r�td|j��YnXd}|
}y|j|	jd
�}Wntk
�r�|j�}YnX|	j�r�d}tjd|j�|	jdk�rt|	j|�}n|	j}||	jk�r>tjd|	j||j�t |j!�}|dk�rdtjd|j��qp|	j�r�|t"j#k�r�|j!j$|j!j%k�r�t"j#}ntjd|j��qpn|	j&dk	�r�||	j&k�r�|	j&}t'|j!|||	j|||	j|d�}||
k�r>|	j�r>|t"j#k�r>tjd�t |j!dd�}|�r>t'|j!|||	j|||	j|d�}|�r<|
|k�r<d}|d|j|	�d�}t(dd�|D���r�tjd�d}�x�|j�D�]�}tjd|�g}x4|d|j|	��D]}|j)j|k�r�|j*|��q�W||jk�r�|}|}|t"j+k�rp||	j&k�rpt,|||d�t"j-}t'|j!|||	j||	j|d�}|�sptj.d�|t"j+k�r�|j/} |j!j0| ��q�d}!yt,|||||	j|	j�}!Wn$t1k
�r�tjd��w�YnX|!|	_||	_)|j*|	�t2||||�}"d}#t3||j4�}$xp|"D]h}%|%j5�||%j67}|#|%j67}#xD|%j7D]:}&tjd|&j8j|&j8j|&j6t9|&j6|$�t9|&j6|&j:|$���qW�q�Wtjd||#t9|#|$���q�W|!�r�|j!j0|!�d|	_d|	_)|t"j+k�r�|j/} |j!j0| �tjd|�|
dk	�r�||k�r�tjd ||�d!}n|}|�r<tjd"|j|�|}|}tjd#|j;|j<t3|j=d$d%���tjd&|�|}
|
�rp|�rptjd'�P�qpW|
dk�rptt>d(���|}|j}|	jdk�r�t|	j|�}'n|	j}'|t"j+k�rB||	j&k�rBtjd)�t,||
|d�}(|'|(j?j@|jAjB|j4k�rtjd*�|'|jAjB|j4}'t"j-}tjd+�t'|j!||'|	j||	j|jAd�}
|
�sBtt>d,���yt,||
||'|	j|	j�})Wn"t1k
�r~tt>d-���YnXtjd.|)jC�t3|)j=d$d%��|j8�|)|	_||	_)|j!jD|	j�|	_q�WdS)/a� Allocate partitions based on requested features.

        :param storage: a Blivet instance
        :type storage: :class:`~.Blivet`
        :param disks: list of usable disks
        :type disks: list of :class:`~.devices.StorageDevice`
        :param partitions: list of partitions
        :type partitions: list of :class:`~.devices.PartitionDevice`
        :param freespace: list of free regions on disks
        :type freespace: list of :class:`parted.Geometry`
        :param boot_disk: optional parameter, the disk the bootloader is on
        :type boot_device: :class:`~.devices.StorageDevice`
        :raises: :class:`~.errors.PartitioningError`
        :returns: :const:`None`

        Non-existing partitions are sorted according to their requested
        attributes, and then allocated.

        The basic approach to sorting is that the more specifically-
        defined a request is, the earlier it will be allocated. See
        :func:`partitionCompare` for details of the sorting criteria.

        The :class:`~.devices.PartitionDevice` instances will have their name
        and parents attributes set once they have been allocated.
    z-allocate_partitions: disks=%s ; partitions=%scSsg|]
}|j�qSr%)rX)rZr]r%r%r&r\�sz'allocate_partitions.<locals>.<listcomp>cSsg|]}d|j|jf�qS)z	%s(id %d))rXrY)rZr[r%r%r&r\�scSsg|]}|js|�qSr%)re)rZr[r%r%r&r\�s)�keyNri�z�allocating partition: %s ; id: %d ; disks: %s ;
boot: %s ; primary: %s ; size: %s ; grow: %s ; max_size: %s ; start: %s ; end: %scSsg|]
}|j�qSr%)rX)rZr]r%r%r&r\�szBRequested disk %s doesn't have a usable disklabel for partitioning)rVzchecking freespace on %sz$size %s rounded up to %s for disk %szno free partition slots on %sz no primary slots available on %s)r7rLrKrMrNz3not enough free space for primary -- trying logicalT)r0rcSsg|]
}|j�qSr%)r)rZr[r%r%r&r\Msz*evaluating growth potential for new layoutzcalculating growth for disk %s)r7rKrMrNz@not enough space after adding extended partition for growth testz4failed to allocate aligned partition for growth testz(request %d (%s) growth: %d (%s) size: %szdisk %s growth: %d (%s)ztotal growth: %d sectorszkeeping old free: %d <= %dFz!updating use_disk to %s, type: %sznew free: %d-%d / %sr9)r:z(new free allows for %d sectors of growthz%found free space for bootable requestz.Unable to allocate requested partition scheme.zcreating extended partitionzYnot enough free space after creating extended partition - shrinking the logical partitionzrecalculating free spacez7not enough free space after creating extended partitionz$failed to allocate aligned partitionz-created partition %s of %s and added it to %s)Er;r<�sort�_partition_compare_keyr=�keysr#rnr^rfrZ
req_disk_tagsr�Zcompare_disks_key�index�insert�poprrXrYrrJrr!rZreq_end_sector�KeyErrorrrsrrtr�r3rhr)r-r*r+Z
req_part_typerRrar/rgr,r�r.�inforjrirB�get_disk_chunksrrS�
grow_requests�growth�requestsr6rT�baser7r8rDrrErIrNr5r��getPartitionByPath)*r�rkr�Z	freespacer��new_partitionsZ
disklabelsZ	all_disksr/Z_partrZ
boot_indexrKr~Zuse_diskr1r�Z_diskr}ZbestZcurrent_freerNrJZ
new_part_type�update�	allocated�
new_growthZ	disk_pathZ
temp_partsZ_pZ
_part_typeZ_freer�Z	temp_part�chunksZdisk_growthZdisk_sector_size�chunk�reqZaligned_sizeZextrqr%r%r&r��s�






















r�c@sDeZdZdZdd�Zedd��Zedd��Zedd	��Zd
d�Z	dS)
�Requestzs A partition request.

        Request instances are used for calculating how much to grow
        partitions.
    cCs,||_d|_d|_t|dd�|_d|_dS)zz
            :param device: the device being requested
            :type device: :class:`~.devices.StorageDevice`
        rrTN)r6r��
max_growth�getattr�doner�)�selfr6r%r%r&�__init__
s
zRequest.__init__cCsdS)zC Requested reserved fixed extra space for the request (in sectors) rr%)r�r%r%r&�reserve_requestszRequest.reserve_requestcCst|jdd�S)z# True if this request is growable. rT)r�r6)r�r%r%r&�growable szRequest.growablecCs|jjS)z< The id of the Device instance this request corresponds to. )r6rY)r�r%r%r&rY%sz
Request.idc
Cs2d|jj|j|jj|j|j|j|j|j	d�}|S)Nz�%(type)s instance --
id = %(id)s  name = %(name)s  growable = %(growable)s
base = %(base)d  growth = %(growth)d  max_grow = %(max_grow)d
done = %(done)s)rorYrXr�r�r�Zmax_growr�)
�	__class__�__name__rYr6rXr�r�r�r�r�)r��sr%r%r&�__repr__*s

zRequest.__repr__N)
r��
__module__�__qualname__�__doc__r��propertyr�r�rYr�r%r%r%r&r�sr�cseZdZ�fdd�Z�ZS)�PartitionRequestcs�tt|�j|�|jjj|_t|jjj	j
�}|jr�dd�|j|j
jfD�}|rVt|�ntd�}dd�t||�|jjjfD�}|r�t|�}||j|_|jdkr�d|_dS)z�
            :param partition: the partition being requested
            :type partition: :class:`~.devices.PartitionDevice`
        cSsg|]}|dkr|�qS)rr%)rZrVr%r%r&r\Csz-PartitionRequest.__init__.<locals>.<listcomp>rcSsg|]}|dkr|�qS)rr%)rZr`r%r%r&r\FsTN)�superr�r�r^rErIr�rr/r6rHrr!r#r��minrWrwr�r�)r�rqrSZminsZreq_format_max_size�limitsZmax_sectors)r�r%r&r�8s
zPartitionRequest.__init__)r�r�r�r��
__classcell__r%r%)r�r&r�6sr�cs,eZdZ�fdd�Ze�fdd��Z�ZS)�	LVRequestcs�tt|�j��t�jj�jdd��jj�|_�j	r��fdd��jj�j
��jj�jj�fD�}|r�t
|�}||j|_|jdkr�d|_dS)z�
            :param lv: the logical volume being requested
            :type lv: :class:`~.devices.LVMLogicalVolumeDevice`
        T)�roundupcs(g|] }|td�krt|�jj��qS)r)rrU�vg�pe_size)rZr`)�lvr%r&r\_sz&LVRequest.__init__.<locals>.<listcomp>rN)r�r�r�rUr�r�rVr�r�rr!r#r�r�r�r�)r�r�r�Z	max_units)r�)r�r&r�Ss 

zLVRequest.__init__csb|j}tt|�j}|jr<|t|jj|jj	dd�|jj
�7}|t|jj|jdd�|jj
�7}|S)NT)r�)r6r�r�r��cachedrUr�r��cacherVr�Zmetadata_vg_space_used)r�r�Zreserve)r�r%r&r�js$"zLVRequest.reserve_request)r�r�r�r�r�r�r�r%r%)r�r&r�Qsr�c@s�eZdZdZd&dd�Zdd�Zdd�Zd	d
�Zdd�Zd
d�Z	dd�Z
edd��Zedd��Z
edd��Zedd��Zdd�Zdd�Zdd�Zd'dd �Zd!d"�Zd(d$d%�ZdS))�Chunkz4 A free region from which devices will be allocated NcCsTt|d�sd|_||_||_d|_g|_t|t�rJx|D]}|j|�q8Wg|_	dS)z�
            :param length: the length of the chunk (units vary with subclass)
            :type length: int
            :keyword requests: list of requests to add
            :type requests: list of :class:`Request`
        r=Nr)
r"r=rI�poolr�r��
isinstance�list�add_request�	skip_list)r�rIr�r�r%r%r&r�xs


zChunk.__init__cCs.d|jj|j|j|j|j�|j|jd�}|S)Nzs%(type)s instance --
device = %(device)s  length = %(length)d  size = %(size)s
remaining = %(rem)d  pool = %(pool)d)ror6rIrVr�r�)r�r�r=rI�length_to_sizer��	remaining)r�r�r%r%r&r��s

zChunk.__repr__cCsd|j|jf}|S)Nz%d on %s)rIr=)r�r�r%r%r&�
_to_string�szChunk._to_stringcCst|j��S)N)rr�)r�r%r%r&�__str__�sz
Chunk.__str__cCst|j��S)N)rr�)r�r%r%r&�__unicode__�szChunk.__unicode__cCsXtjd|jj|�|jj|�|j|j8_|j|j8_|j	sT|j|j7_dS)zz Add a request to this chunk.

            :param req: the request to add
            :type req: :class:`Request`
        zadding request %d to chunk %sN)
r;r<r6rYr�rgr�r�r�r�)r�r�r%r%r&r��szChunk.add_requestcCsrtjd|||j|��|j|kr<tjd||j�ttd���|j|8_|j|7_||jkrn|jj	|�dS)aN Reclaim units from a request and return them to the pool.

            :param request: the request to reclaim units from
            :type request: :class:`Request`
            :param amount: number of units to reclaim from the request
            :type amount: int
            :raises: ValueError
            :returns: None
        zreclaim: %s %d (%s)z2tried to reclaim %d from request with %d of growthz*cannot reclaim more than request has grownN)
r;r<r�r�r��
ValueErrorrr�r�rg)r��request�amountr%r%r&�reclaim�s



z
Chunk.reclaimcCstdd�|jD��S)z/ Sum of growth for all requests in this chunk. css|]}|jVqdS)N)r�)rZ�rr%r%r&r_�szChunk.growth.<locals>.<genexpr>)�sumr�)r�r%r%r&r��szChunk.growthcCsx|jD]}|jrdSqWdS)z< True if this chunk contains at least one growable request. TF)r�r�)r�r�r%r%r&�has_growable�szChunk.has_growablecCstdd�|jD��S)z5 Number of requests still being grown in this chunk. cSsg|]}|js|�qSr%)r�)rZr]r%r%r&r\�sz#Chunk.remaining.<locals>.<listcomp>)rr�)r�r%r%r&r��szChunk.remainingcCs|jdkp|jdkS)z= True if we are finished growing all requests in this chunk. r)r�r�)r�r%r%r&r��sz
Chunk.donecCs|jS)N)r�)r�r�r%r%r&r��szChunk.max_growthcCs|S)Nr%)r�rIr%r%r&r��szChunk.length_to_sizecCs|S)Nr%)r�rVr%r%r&�size_to_length�szChunk.size_to_lengthcCs||j|�}|rx|j|krx|j|kr`|j|}tjd||j|�|jj|jj�|j|7_||_|dk	rr||j	8}d|_
|S)a] Enforce max growth and return extra units to the pool.

            :param req: the request to trim
            :type req: :class:`Request`
            :keyword base: base unit count to adjust if req is done growing
            :type base: int
            :returns: the new base or None if no base was given
            :rtype: int or None
        z taking back %d (%s) from %d (%s)NT)r�r�r;r<r�r6rYrXr�r�r�)r�r�r�r��extrar%r%r&�trim_over_grown_request�s





zChunk.trim_over_grown_requestcCsdS)Nr%)r�r%r%r&�
sort_requestsszChunk.sort_requestsFcCs�tjd|�|j�x|jD]}tjd|�qW|j}d}�x|joT|joT||jk�rH|j}||_|rvt||j�}tjd|j|j|j	|j��x�|jD]�}|js�||j
kr�q�|s�t|j�t|j�}t||�}|j|7_|j|8_tjd||j	|�|j
j|j
j�|j||d�}tjd|j
j|j
j|j|j	|j��q�Wq>W|j�r�x�|jD]�}|j�sZ||j
k�rv�qZ|j}|j|7_d|_tjd||j	|�|j
j|j
j�|j|�tjd|j
j|j
j|j|j	|j��|jdk�rZP�qZWg|_
dS)	aB Calculate growth amounts for requests in this chunk.

            :keyword uniform: grow requests uniformly instead of proportionally
            :type uniform: bool

            The default mode of growth is as follows: given a total number of
            available units, requests receive an allotment proportional to their
            base sizes. That means a request with base size 1000 will grow four
            times as fast as a request with base size 250.

            Under uniform growth, all requests receive an equal portion of the
            free units.
        zChunk.grow_requests: %rzreq: %rrz%%d requests and %s (%s) left in chunkzadding %s (%s) to %d (%s))r�z6new grow amount for request %d (%s) is %s units, or %sN)r;r<r�r�r�r�r�rUr�r�r�rr�r6rYrXr�)r�Zuniformr�Znew_baseZ	last_poolr�r[Zsharer%r%r&r�	sZ


zChunk.grow_requests)N)N)F)r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r%r%r%r&r�ts$

r�csreZdZdZd�fdd�	Z�fdd�Zdd�Zd	d
�Zdd�Z�fd
d�Z	dd�Z
dd�Zdd�Zdd�Z
�ZS)�	DiskChunkz? A free region on disk from which partitions will be allocated Ncs>||_t|jjj�|_|jjj|_tt|�j|jj	|d�dS)a~
            :param geometry: the free region this chunk represents
            :type geometry: :class:`parted.Geometry`
            :keyword requests: list of requests to add initially
            :type requests: list of :class:`PartitionRequest`

            .. note::

                We will limit partition growth based on disklabel limitations
                for partition end sector, so a 10TB disk with an msdos disklabel
                will be treated like a 2TiB disk.

            .. note::

                If you plan to allocate aligned partitions you should pass in an
                aligned geometry instance.

        )r�N)
rErr6rHrSr=r�r�r�rI)r�rEr�)r�r%r&r�aszDiskChunk.__init__cs0tt|�j�}|d|jj|jj|jd�7}|S)Nz@ start = %(start)d  end = %(end)d
sector_size = %(sector_size)s
)r7r8rS)r�r�r�rEr7r8rS)r�r�)r�r%r&r�ys
zDiskChunk.__repr__cCs d|j|jj|jj|jf}|S)Nz%d (%d-%d) on %s)rIrEr7r8r=)r�r�r%r%r&r��szDiskChunk._to_stringcCst|j��S)N)rr�)r�r%r%r&r��szDiskChunk.__str__cCst|j��S)N)rr�)r�r%r%r&r��szDiskChunk.__unicode__cs�t|t�sttd���|js�|jjjj}t	||j
j�}||j
jkrXt
jd�ttd���||j
jd}||jkr�t
jd|�||_tt|�j|�dS)z� Add a request to this chunk.

            :param req: the request to add
            :type req: :class:`PartitionRequest`
        z3DiskChunk requests must be of type PartitionRequestz.chunk start sector is beyond disklabel maximumz-partitions allocated outside disklabel limitsrz.adjusting pool to %d based on disklabel limitsN)r�r�r�rr�r6r^r/rGr�rEr8r7r;r�rr�r<r�r�r�)r�r��
max_sectorZ	chunk_endZnew_pool)r�r%r&r��s


zDiskChunk.add_requestc
Cs�|jjjj}|jjjj}d}x(|jD]}|jjjj|kr$||j7}q$W||7}g}|jjjj}|j	||�|jj
r�ttd�|j
�}|j	||�|jr�|j	|j�t|�}	|	S)z� Return the maximum possible growth for a request.

            :param req: the request
            :type req: :class:`PartitionRequest`
        rz2 TiB)r6r^rEr8r7r�r�r/rGrgr�rWrrSr�r�)
r�r�rPZ	req_startr�r�r�r�rOr�r%r%r&r��s"zDiskChunk.max_growthcCst||j�S)N)rTrS)r�rIr%r%r&r��szDiskChunk.length_to_sizecCst||j�S)N)rWrS)r�rVr%r%r&r��szDiskChunk.size_to_lengthcCs|jjdd�d�dS)NcSs|jjjjS)N)r6r^rEr7)r�r%r%r&�<lambda>�sz)DiskChunk.sort_requests.<locals>.<lambda>)r�)r�r�)r�r%r%r&r��szDiskChunk.sort_requests)N)r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r%r%)r�r&r�]s	)r�csFeZdZdZd
�fdd�	Z�fdd�Zdd�Zd	d
�Zdd�Z�Z	S)�VGChunkz= A free region in an LVM VG from which LVs will be allocated NcsF||_|j|_|jt|j|jdd�|j�}tt|�j	||d�dS)a
            :param vg: the volume group whose free space this chunk represents
            :type vg: :class:`~.devices.LVMVolumeGroupDevice`
            :keyword requests: list of requests to add initially
            :type requests: list of :class:`LVRequest`
        T)r�)r�N)
r�r=ZextentsrUr�Zreserved_spacer�r�r�r�)r�r�r��usable_extents)r�r%r&r��s zVGChunk.__init__cs*t|t�sttd���tt|�j|�dS)z| Add a request to this chunk.

            :param req: the request to add
            :type req: :class:`LVRequest`
        z*VGChunk requests must be of type LVRequestN)r�r�r�rr�r�r�)r�r�)r�r%r&r��s
zVGChunk.add_requestcCs|jj|S)N)r�r�)r�rIr%r%r&r��szVGChunk.length_to_sizecCst||jj�S)N)rUr�r�)r�rVr%r%r&r��szVGChunk.size_to_lengthcCs|jjtd�dS)N)r�)r�r��_lv_compare_key)r�r%r%r&r�szVGChunk.sort_requests)N)
r�r�r�r�r�r�r�r�r�r�r%r%)r�r&r��sr�cs"eZdZdZd�fdd�	Z�ZS)�
ThinPoolChunkzD A free region in an LVM thin pool from which LVs will be allocated Ncs6|j|_|j|_|j|jj}tt|�j||d�dS)a
            :param pool: the thin pool whose free space this chunk represents
            :type pool: :class:`~.devices.LVMLogicalVolumeDevice`
            :keyword requests: list of requests to add initially
            :type requests: list of :class:`LVRequest`
        )r�N)r�r=rVr�r�r�r�)r�r�r�r�)r�r%r&r�
szThinPoolChunk.__init__)N)r�r�r�r�r�r�r%r%)r�r&r�sr�csP�fdd�|D�}�fdd�|D�}g}x�|dd�D]�}y0t|j�jj�}�jj|d�}�jj|d�}	Wn tk
r�|j|�w6YnX|j||j	�}
|	j
||j�}|
|kr�|j|�q6tj
|j|
|d�}|j|jkr�|j|�q6|jt|��q6WxR|D]J}
|
j�rq�x:t|�D].\}}|j|
jj��r||jt|
��P�qWq�W|S)aY Return a list of Chunk instances representing a disk.

        :param disk: the disk
        :type disk: :class:`~.devices.StorageDevice`
        :param partitions: list of partitions
        :type partitions: list of :class:`~.devices.PartitionDevice`
        :param free: list of free regions
        :type free: list of :class:`parted.Geometry`
        :returns: list of chunks representing the disk
        :rtype: list of :class:`DiskChunk`

        Partitions and free regions not on the specified disk are ignored.

        Chunks contain an aligned version of the free region's geometry.
    cs"g|]}|j�kr|jr|�qSr%)r/re)rZr[)r/r%r&r\(sz#get_disk_chunks.<locals>.<listcomp>csg|]}|jj�jkr|�qSr%)r6r=)rZr�)r/r%r&r\)sN)rV)rN)r6r7r8)rTrIr#rSrsrurrlrAr7�	alignDownr8r)rCr6r5rgr�rf�	enumeraterFr^rEr�r�)r/r�r~Z
disk_parts�	disk_freer�r�rVrNrZal_startZal_endZgeomr[�ir%)r/r&r�s>



r�c@s4eZdZdZdd�Zdd�Zedd��Zdd	�Zd
S)�TotalSizeSetz� Set of device requests with a target combined size.

        This will be handled by growing the requests until the desired combined
        size has been achieved.
    cCspg|_x.|D]&}t|t�r"|j}n|}|jj|�qW||_g|_tdd�|jD�td��|_	t
jd|j	�dS)z�
            :param devices: the set of devices
            :type devices: list of :class:`~.devices.PartitionDevice`
            :param size: the target combined size
            :type size: :class:`~.size.Size`
        css|]}|jVqdS)N)r )rZr]r%r%r&r_ssz(TotalSizeSet.__init__.<locals>.<genexpr>rzset.allocated = %dN)�devicesr�r�slavergrVr�r�rr�r;r<)r�r�rVr6rqr%r%r&r�_s

zTotalSizeSet.__init__cCs*tjd||j|j|j�|j|7_dS)Nz4allocating %d to TotalSizeSet with %d/%d (%d needed))r;r<r�rV�needed)r�r�r%r%r&�allocatevszTotalSizeSet.allocatecCs|j|jS)N)rVr�)r�r%r%r&r�{szTotalSizeSet.neededcCs*tjd||j|j|j�|j|8_dS)Nz8deallocating %d from TotalSizeSet with %d/%d (%d needed))r;r<r�rVr�)r�r�r%r%r&�
deallocateszTotalSizeSet.deallocateN)	r�r�r�r�r�r�r�r�r�r%r%r%r&r�Ws
r�c@seZdZdZddd�ZdS)�SameSizeSetz3 Set of device requests with a common target size. FNcCsZg|_x.|D]&}t|t�r"|j}n|}|jj|�qW|t|�|_||_||_g|_	dS)a�
            :param devices: the set of devices
            :type devices: list of :class:`~.devices.PartitionDevice`
            :param size: target size for each device/request
            :type size: :class:`~.size.Size`
            :keyword grow: whether the devices can be grown
            :type grow: bool
            :keyword max_size: the maximum size for growable devices
            :type max_size: :class:`~.size.Size`
        N)
r�r�rr�rgrrVrMr�r�)r�r�rVrMr�r6rqr%r%r&r��s

zSameSizeSet.__init__)FN)r�r�r�r�r�r%r%r%r&r��sr�csi}i�i}x6|D].}x(|jD]}|�|j<|||<d||<qWqW�x�td�D�]�}tdd�|D��}�xR|D�]H}t|t��r�tjddd�|jD�|j	|j
�x<|jD]2}	�|	}||}|j||}
|j|j
|
��q�Wt�fdd�|jD�dd	�d
d�}|j}x�|D]�}||}tjd|�tjd
|j�|jdk�r�|j|�t|j�}
|
|jk�r||dk�r|tjd��qnt|
|j�}
|||
7<|j||
�|j|j
|
��|jdk�rd
|_�qWqpt|t�rp�fdd�|jD�}tdd�|D��}tjddd�|jD�|j
�tjd|�x�|D]�}||}|j|j
�|j}tjd||�tt||�d�}|j|k�r�|j|}
|||
7<|j||
�d
|_n|j|k�r,d
|_�q,WqpWx|j�D]}|j||<�q�Wx*|D]"}||�r�|j�r�|j��q�WqPWdS)Nr�cSsg|]}|df�qS)rr%)rZr�r%r%r&r\�sz$manage_size_sets.<locals>.<listcomp>z
set: %s %d/%dcSsg|]
}|j�qSr%)rX)rZr]r%r%r&r\�scsg|]}�|�qSr%r%)rZr])�requests_by_devicer%r&r\�scSs|jS)N)r�)r�r%r%r&r��sz"manage_size_sets.<locals>.<lambda>T)r��reversez%sz
needed: %dz not reclaiming from this requestcsg|]}�|�qSr%r%)rZr])r�r%r&r\�scSsg|]
}|j�qSr%)r�)rZr�r%r%r&r\�sz
set: %s %dcSsg|]
}|j�qSr%)rX)rZr]r%r%r&r\�szmin growth is %dzmax growth for %s is %d)r�r6�range�dictr�r�r;r<r�r�rVr�r�r��sortedr�r�rr�r�r�r�r�r��maxr�r�)r�r�Zgrowth_by_requestZchunks_by_requestr�r�r�Z	reclaimedZssr6r�r�r�r�Z_min_growthZ_max_growthZ
min_growthr%)r�r&�manage_size_sets�sv







rc s"tjddd�|D�dd�|D��dd�|D�}|sBtjd�dS|dkrNg}tjdd	d�|D��g}x\|D]T��fd
d�|D�}|s�tjd�j�qnt�||�}tjd�jt|��|j|�qnWx|D]}|js�q�|j�q�Wt||��x,|D�]"�tjd
�j��x|D�]}|j	�j	k�r*�q|j�s6�q�j
}	|jj}
|	j
�}t|	jdd�}|j|j|
��sx|j|j|
�}
g}
x�|jD]�}|jjj}tjd|jj|jj|�|tjk�r��q�|j|j}|	j
|j|�d�}|	j|d�}|tjk�r�|
|j7}
|
|d}|j|j|��s$|j|j|�}tj |	j!|
|d�}tjd|jj|�|d}
tj"|	j#||d�}|
j$||jf��q�Wt%�gdd�|jD�|�tjd�tjd|�|�r�|jj&|��r�tjd�j�d}xH|
D]@\}}|jtjk�r�q�|�s|jj|k�r�|jj|j}�q�Wtj |	j!||jj'd�}tjd|�tj"|	j#tj|d�}dd�|
D�}x4t(|�D](\}}|tjk�rf|
j)||df�P�qfWx�|
D]x\}}|�r�|j}n|j*�}tjd||j�tj+|jd�}|	j#j,||d�|j	}|�r�||_�|_-|	j#j.|�}||_�q�W�qWq�WdS) a Grow all growable partition requests.

        Partitions have already been allocated from chunks of free space on
        the disks. This function does not modify the ordering of partitions
        or the free chunks from which they are allocated.

        Free space within a given chunk is allocated to each growable
        partition allocated from that chunk in an amount corresponding to
        the ratio of that partition's base size to the sum of the base sizes
        of all growable partitions allocated from the chunk.

        :param disks: all usable disks
        :type disks: list of :class:`~.devices.StorageDevice`
        :param partitions: all partitions
        :type partitions: list of :class:`~.devices.PartitionDevice`
        :param free: all free regions on disks
        :type free: list of :class:`parted.Geometry`
        :keyword size_sets: list of size-related partition sets
        :type size_sets: list of :class:`TotalSizeSet` or :class:`SameSizeSet`
        :returns: :const:`None`
    z(grow_partitions: disks=%s, partitions=%scSsg|]
}|j�qSr%)rX)rZr]r%r%r&r\sz#grow_partitions.<locals>.<listcomp>cSsg|]}d|j|jf�qS)z	%s(id %d))rXrY)rZr[r%r%r&r\scSsg|]}|jr|�qSr%)r)rZr[r%r%r&r\szno growable partitionsNzgrowable partitions are %scSsg|]
}|j�qSr%)rX)rZr[r%r%r&r\scsg|]}|jj�jkr|�qSr%)r6r=)rZr�)r/r%r&r\!szno free space on %szdisk %s has %d chunkszgrowing partitions on %srEzpartition %s (%d): %s)rV)rNr)r6r7r8znew geometry for %s: %s)r/rorEcSsg|]
}|j�qSr%)r6)rZr�r%r%r&r\oszback from remove_new_partitionszextended: %sz*setting up new geometry for extended on %srznew geometry for extended: %scSsg|]\}}|j�qSr%)ro)rZr[r]r%r%r&r\�szsetting %s new geometry: %s)rp)rqrr)/r;r<rXr�r�extendr�r�rr=r#rEr7rsr�rjr@rAr�r6r^rorYr)r,r�r�r�rur.r5r�rCrvrxrhrgrnrFr8r�r�r�ryrzr/r�) rkr�r~r�Zall_growabler�r�Zdisk_chunksr�r}r7Zdefault_alignmentZextended_geometryr�r[ZptypeZ
new_lengthrNrr8Znew_geometryZ
new_partitionZ	ext_startrqr6Znew_extendedZptypesZpt_idxrXrrr=Znewpartr%)r/r&r��s�






r�cCs�t|t�s|j}t|t�s |j}d}|t|j|j�d8}|t|j|j�d7}|jr�|jr�|jrt|jrt|d8}n.|jr�|jr�|d7}n|t|j|j�d8}|dkr�d}n|dkr�d}|S)zp More specifically defined lvs come first.

        < 1 => x < y
          0 => x == y
        > 1 => x > y
    rrrrrr)r�r
r6rrVrr!)Zlv1Zlv2r$r%r%r&�
lv_compare�s$



rcCs8x2|jD](}|jjsq|j|j|j�}||j_qWdS)z4 grow the lvs by the amounts the VGChunk calculated N)r�r6rr�r�r�rV)r�r�rVr%r%r&�_apply_chunk_growth�s
rc
s��x�|jD�]��j}|dkr,ttd���n|s@tjd�j�q
tjd�j|dd��jD���fdd��jD�}g}x2|D]*}|�jkr|t	|j
|j|j�|_|j|_
q|Wdd��jD�}td	d
�|D��dkr�td��t�fd
d
�|D��}�j|}x6|D].}t|jtd�|�}�j||_
|_�q�Wt�dd�|D�d�}	|	j�t|	�xX�jD]N}
�j}|
j�r�|
jtd�k�r�|
j��j|k�r^|
j
�j|8_
�q^Wx:�jD]0}
dd�|
jD�}t|
|�}|j�t|��q�Wq
WdS)a� Grow LVs according to the sizes of the PVs.

        Strategy for growth involving thin pools:
            - Applies to device factory class as well.
            - Overcommit is not allowed.
            - Pool lv's base size includes sizes of thin lvs within it.
            - Pool is grown along with other non-thin lvs.
            - Thin lvs within each pool are grown separately using the
              ThinPoolChunk class.
    rz!not enough space for LVM requestszvg %s has no free spacezvg %s: %s free ; lvs: %scSsg|]
}|j�qSr%)Zlvname)rZr`r%r%r&r\�szgrow_lvm.<locals>.<listcomp>csg|]}|�jkr|�qSr%)Zthinlvs)rZr�)r�r%r&r\�scSsg|]}|jr|�qSr%)�req_percent)rZr�r%r%r&r\scss|]}|jVqdS)N)r)rZr�r%r%r&r_szgrow_lvm.<locals>.<genexpr>rz0sum of percentages within a vg cannot exceed 100c3s$|]}�j|jdd��jVqdS)F)r�N)r�rJr�)rZr�)r�r%r&r_sz0.01cSsg|]}t|��qSr%)r�)rZr`r%r%r&r\s)r�cSsg|]}t|��qSr%)r�)rZr`r%r%r&r\"sN)ZvgsZ
free_spacerrr;r<rXZlvsZ	thinpoolsrr�rJZ
used_spacerVr�r�Zfree_extentsrUrrr�r�r�rZpmspare_sizereZ
metadata_sizerZautoset_md_sizer�)
r�Z
total_freeZfatlvsr�r�Zpercentage_based_lvsZpercent_baseZpercentage_basisZnew_extentsr�r�Zorig_pmspare_sizeZ
thin_chunkr%)r�r&�grow_lvm�sL





r	)N)NNNNN)NN)F)N)N)N)?�operatorrrZdecimalr�	functoolsZgiZrequire_versionr)r{�errorsrrrr	r�r
rrr
rVrZi18nr�utilrrrZloggingZ	getLoggerr;r'�
cmp_to_keyr�r3rRrTrWrnr�r�r�r�r�r�r��objectr�r�r�r�r�r�r�r�r�r�rr�rr�rr	r%r%r%r&�<module>sf
H

5
t

@
d
7
^
[1#j'@.T
5%