a '¡DgyIã@s(UdZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z m Z ddl m Z ddlmZddlmZmZddlmZmZmZmZmZddlmZdd lmZdd lmZdd lm Z m!Z!dd l"m#Z#e#Z$d e ge$gdœZ%ee&d<ddgddœZ'edƒZ(Gdd„dƒZ)e *e+¡Z,Gdd„de-ƒZ.Gdd„de ƒZ/Gdd„de/ƒZ0Gdd„de/ƒZ1Gdd „d e/ƒZ2e3e!e4e/d!œd"d#„Z5ee6d$œd%d&„Z7ee6d$œd'd(„Z8d)d*„Z9e:d$œd+d,„Z;d-d.„Ze/e!d3œd4d5„Z?e3eee4dd6œd7d8„Z@d9e0fd:e1fd;e2ffZAdS)szResizer.__init__)rÚreturncCsdSr(r#©r*rr#r#r$Ú availableAszResizer.availablecCsdSr(r#)r*ÚdiskdevÚpartnumÚpartdevÚfsr#r#r$ÚresizeDszResizer.resizeN) r r!r"rr+rÚlistÚboolr.r3r#r#r#r$r&=s r&c@s"eZdZedœdd„Zdd„ZdS)ÚResizeGrowPart©rcCsHz.tjddgddid�j}t d|¡r,WdSWntjyBYn0dS) NÚgrowpartz--helpÚLANGÚC©Ú update_envz --update\s+TF)r ÚstdoutÚreÚsearchÚProcessExecutionError)r*rÚoutr#r#r$r.Is ÿ  zResizeGrowPart.availablec Cs\t||ƒ}|j ¡}tj|dd���}tj |d¡}d|dœ} tj |¡sVt  |d¡zt j dd||g| d�Wn`t j yÐ} zF| j d kr¦t  td ||¡t| ƒ| ‚||fWYd} ~ WdƒSd} ~ 00zt j d||g| d�WnBt j �y,} z&t  td ||¡t| ƒ| ‚WYd} ~ n d} ~ 00Wdƒn1�sD0Y|t||ƒfS) NT)ÚdirZ needs_exer8r:)r9ZTMPDIRiÀz --dry-runr;éz&Failed growpart --dry-run for (%s, %s)zFailed: growpart %s %s)Úget_sizer)Zget_tmp_exec_pathr ZtempdirÚosÚpathÚjoinÚexistsÚmkdirr r@Ú exit_coder ÚlogexcÚLOGr%) r*r/r0r1r2ÚbeforeZtmp_dirZtmpdZ growpart_tmpZmy_envÚer#r#r$r3Us8      þ  ü ,@zResizeGrowPart.resizeN©r r!r"r4r.r3r#r#r#r$r6Hs r6c@s&eZdZdZedœdd„Zdd„ZdS)Ú ResizeGrowFSaà Use FreeBSD ``growfs`` service to grow root partition to fill available space, optionally adding a swap partition at the end. Note that the service file warns us that it uses ``awk(1)``, and as such requires ``/usr`` to be present. However, cloud-init is installed into ``/usr/local``, so we should be fine. We invoke the ``growfs`` with ``service growfs onestart``, so it doesn't need to be enabled in ``rc.conf``. r7cCstj d¡o|dgkS)z'growfs only works on the root partitionz/etc/rc.d/growfsr)rErFÚisfiler-r#r#r$r.†szResizeGrowFS.availablec Csjt||ƒ}z|jjddd�Wn<tjyZ}z"t td¡t|ƒ|‚WYd}~n d}~00|t||ƒfS)NZonestartÚgrowfs)ÚactionZservicezFailed: service growfs onestart) rDr)Zmanage_servicer r@r rKrLr%)r*r/r0r1r2rMrNr#r#r$r3Šs   zResizeGrowFS.resizeN)r r!r"Ú__doc__r4r.r3r#r#r#r$rPys rPc@s"eZdZedœdd„Zdd„ZdS)Ú ResizeGpartr7cCsNz4tjddgddiddgd�j}t d|¡r2Wd SWntjyHYn0d S) NÚgpartÚhelpr9r:rrC)r<Zrcszgpart recover TF)r Ústderrr>r?r@)r*rÚerrr#r#r$r.–sÿ  zResizeGpart.availablec CsÐzt dd|g¡WnHtjy\}z.|jdkrHt td|¡t|ƒ|‚WYd}~n d}~00t||ƒ}zt ddd||g¡Wn@tjyÀ}z&t td||¡t|ƒ|‚WYd}~n d}~00|t||ƒfS) a9 GPT disks store metadata at the beginning (primary) and at the end (secondary) of the disk. When launching an image with a larger disk compared to the original image, the secondary copy is lost. Thus, the metadata will be marked CORRUPT, and need to be recovered. rVZrecoverrzFailed: gpart recover %sNr3z-izFailed: gpart resize -i %s %s)r r@rJr rKrLr%rD)r*r/r0r1r2rNrMr#r#r$r3¢s    zResizeGpart.resizeNrOr#r#r#r$rU•s rU)rr'rr,c Cs¢d}|dkrDtD]$\}}||ƒ}|j|d�r|}q6q|sžtdƒ‚nZi}tD]\}} | ||<qL||vrrtd|ƒ‚|||ƒ} | j|d�rŽ| }|sžtd|ƒ‚|S)Nrr7zNo resizers availablezunknown resize mode %szmode %s not available)ÚRESIZERSr.Ú ValueErrorÚ TypeError) rr'rZ resize_classÚ_nameÚresizerZcurZmmapÚkÚvZmclassr#r#r$Úresizer_factory»s(         ra)r,c Cs¦d}zŒz0t |tj¡}t |dtj¡WW|r6t |¡Sty~|dkrht|ƒYW|rft |¡SYW|rzt |¡dS0W|r¢t |¡n|r t |¡0dS)NrÚzfs)rEÚopenÚO_RDONLYÚlseekÚSEEK_ENDÚcloseÚFileNotFoundErrorÚ get_zfs_size)Úfilenamer2Úfdr#r#r$rDÙs* ù   ü ý ÿrDc Csn| d¡d}zt dddd|g¡\}}Wn6tjy`}zt d||¡WYd}~dSd}~00t| ¡ƒS)NrrÚzpoolÚgetz -HpovalueÚsizezFailed: zpool get size %s: %s)Úsplitr r@rLÚdebugÚintÚstrip)ZdatasetrlrnÚ_rNr#r#r$riçsricCs†| d¡r|dfSt |¡}|s(tdƒ‚|d}|d}t ¡}|dkr~|s~t t ¡¡}|dur~tj  |¡rv|dfStdƒ‚||fS)Nú/dev/z,Could not determine device of '%s' % dev_entrrCz /dev/rootz!Unable to find device '/dev/root') Ú startswithr Zget_mount_infor[Z is_containerZrootdev_from_cmdlineZ get_cmdlinerErFrH)ÚdeventÚresultÚdevr2Ú containerr#r#r$Ú devent2devñs    rzc CsÈt d¡st d¡dSzt dd|g¡WnNtjyz}z4|jdkrVt d|¡nt d|j¡WYd}~dSd}~00ttjƒ�.t dd |g¡t d |¡Wdƒd S1sº0YdS) zŒ Check if a device is an encrypted device. blockdev should have a /dev/dm-* path whereas partition is something like /dev/sda1. Ú cryptsetupz6cryptsetup not found. Assuming no encrypted partitionsFÚstatuséz#Determined that %s is not encryptedzZReceived unexpected exit code %s from cryptsetup status. Assuming no encrypted partitions.NZisLukszDetermined that %s is encryptedT)r ÚwhichrLrpr@rJÚwarningr)ÚblockdevÚ partitionrNr#r#r$Ú is_encrypted s$   ý   r‚c Cs”ddd|g}t |¡d}| d¡s2td|›�ƒ‚z d| d¡d  d ¡d›�WStyŽ}z$td |›d |›d �ƒ|‚WYd}~n d}~00dS)NZdmsetupZdepsz--options=devnamerz1 dependz5Expecting '1 dependencies' from 'dmsetup'. Received: rtz: (rCú)zRan `z$`, but received unexpected stdout: `ú`)r ruÚ RuntimeErrorroÚ IndexError)r€ZcommandZdeprNr#r#r$Úget_underlying_partition$s  ÿ ÿþr‡cCsôt ¡stjdfSz€t dt›�¡�Bt ¡�}t |¡}Wdƒn1sN0YWdƒn1sl0Y|d}t   |¡}|d}Wn.t yÀ}zt dƒ|‚WYd}~n d}~00zœt j ddd d |g|d �Wzt   dd d |t|ƒg¡Wn4t j�y.}zt d|¡WYd}~n d}~00z t ¡Wn t �y\t td¡Yn0n‚zt   dd d |t|ƒg¡Wn4t j�y°}zt d|¡WYd}~n d}~00z t ¡Wn t �yÞt td¡Yn00tjd|›d�fS)záUse 'cryptsetup resize' to resize LUKS volume. The loaded keyfile is json formatted with 'key' and 'slot' keys. key is base64 encoded. Example: {"key":"XFmCwX2FHIQp0LBWaLEMiHIyfxt1SGm16VvUAVledlY=","slot":5} zNo encryption keyfile foundzReading NÚkeyÚslotzZCould not load encryption key. This is expected if the volume has been previously resized.r{z --key-fileú-r3)ÚdataZ luksKillSlotz --batch-modez| |tjd||ff¡n”|dusN|durŒd} |durp|durpd||f} nd|} | |tj| f¡nFd} |dur²|dur²d||||f} nd|||f} | |tj| f¡WnBt�y} z(| |tjd||| ff¡WYd} ~ n d} ~ 00|S)Nzno change necessary (%s, %s)Úz*changed (%s, %s) size, new size is unknownz&changed (%s) size, new size is unknownzchanged (%s, %s) from %s to %szchanged (%s) from %s to %sz'failed to resize: disk=%s, ptnum=%s: %s)r3Úappendrrrr%r) r^rvÚdiskÚptnumr€r2ÚinfoÚoldÚnewÚmsgrNr#r#r$Ú _call_resizernsJ ýÿþü ýÿrŸ)r^r'c Csžt |¡}g}|�rš| d¡}d}d}zt|ƒ\}}WnFty|} z.| |tjd| f¡WYd} ~ qWYd} ~ n d} ~ 00t d|¡|dkr´t |t ƒr´|t ||||||ƒ7}qzt   |¡} WnLt�y} z2| |tjd|| ff¡WYd} ~ qWYd} ~ n d} ~ 00t  | j¡�sDt  | j¡�sD| |tjd|f¡q| |¡} | �rz‚t|ƒ} t| | ƒ�rº| dd„|Dƒv�rš| d|¡| d| ¡Wqt|| ƒ\} }| || |f¡n| |tjd |›d �f¡Wqt�y} z*| |tjd |›d | ›�f¡WYd} ~ qd} ~ 00qz| |¡\}}WnPttf�y€} z2| |tjd || ff¡WYd} ~ qWYd} ~ n d} ~ 00|t ||||||ƒ7}q|S)Nrzunable to convert to device: %szgrowpart found fs=%srbzstat of '%s' failed: %szdevice '%s' not a block devicecSsg|] }|d‘qS)rr#)Ú.0Úxr#r#r$Ú Úóz"resize_devices..zResizing mapped device (z!) skipped as it is not encrypted.zResizing encrypted device (z ) failed: zdevice_part_info(%s) failed: %s)ÚcopyÚpoprzr[r˜rrrLrpÚ isinstancerPrŸrEÚstatÚOSErrorÚS_ISBLKÚst_modeÚS_ISCHRZget_mapped_devicer‡r‚Úinsertr–r’rZdevice_part_infor\)r^rr'r›rvr™ršr€r2rNZstatretZunderlying_blockdevr�r|Úmessager#r#r$Úresize_devicesœs¤  ýÿ"  ýÿ"ÿýÿ    ýÿ ýÿýÿ  ýÿ"r®)ÚnameÚcfgÚcloudÚargsr,c Csºd|vrt dt¡t|d<| d¡}t|tƒs>t d¡dS| dd¡}t |¡r„|dkrtt j d|›d�d d d �t d |¡dSt | d d¡¡rºt j   d¡rºt d¡t d¡dSt |ddg¡}t|ƒsàt d¡dSzt||j|d�}WnHttf�y<}z*t d||¡|dk�r&|‚WYd}~dSd}~00t d¡�t|||jƒ} Wdƒn1�sn0Y| D]8\} } } | tjk�r¢t d| | ¡nt d| | | ¡�q|dS)Nr8z.No 'growpart' entry in cfg. Using default: %sz#'growpart' in config was not a dictrrZoffz"Growpart's 'mode' key with value 'rŒz22.2zUse 'off' instead.)Z deprecatedZdeprecated_versionZ extra_messagezgrowpart disabled: mode=%srFz/etc/growroot-disabledz0growpart disabled: /etc/growroot-disabled existsz&use ignore_growroot_disabled to ignorerrzgrowpart: empty device list)r'rz,growpart unable to find resizer for '%s': %szResizing devicesz'%s' resized: %sz '%s' %s: %s)rLrpÚDEFAULT_CONFIGrmr¦Údictrr Zis_falserZ deprecaterErFrQZget_cfg_option_listÚlenrar'r[r\r rŽr®rrr›) r¯r°r±r²Zmycfgrrr^rNZresizedÚentryrSržr#r#r$ÚhandlesRÿ      ý       . r·r8rRrV)BrTr‘r¤r�ZloggingrEZos.pathr>r§ÚabcrrÚ contextlibrÚpathlibrÚtypingrrZ cloudinitrr r r r Zcloudinit.cloudr Zcloudinit.configrZcloudinit.config.schemarZcloudinit.distrosrrZcloudinit.settingsrrrÚ__annotations__r³r�rZ getLoggerr rLr’r%r&r6rPrUr“r4rarqrDrirzr5r‚r‡r–rŸr®r·rZr#r#r#r$Úsd      üý  1& 9.t4ý