U '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$gdZ%ee&d<ddgddZ'edZ(GdddZ)e*e+Z,Gddde-Z.Gddde Z/Gddde/Z0Gddde/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!d3d4d5Z?e3eee4dd6d7d8Z@d9e0fd:e1fd;e2ffZAdS)/usr/lib/python3/dist-packages/cloudinit/config/cc_growpart.pyr/src@s eZdZdS)ResizeFailedExceptionN)r r!r"r#r#r#r$r%9sr%c@s:eZdZedddZeeedddZeddZ d S) Resizer)distrocCs ||_dSN)_distro)selfr'r#r#r$__init__>szResizer.__init__)rreturncCsdSr(r#r*rr#r#r$ availableAszResizer.availablecCsdSr(r#)r*diskdevpartnumpartdevfsr#r#r$resizeDszResizer.resizeN) r r!r"rr+rlistboolr.r3r#r#r#r$r&=s r&c@s"eZdZedddZddZdS)ResizeGrowPartrcCsJz.tjddgddidj}td|r,WdSWntjk rDYnXdS) Ngrowpartz--helpLANGC update_envz --update\s+TF)r stdoutresearchProcessExecutionError)r*routr#r#r$r.Is  zResizeGrowPart.availablec CsDt||}|j}tj|dd }tj|d}d|d} tj|sVt |dzt j dd||g| dWn`t j k r} z@| j d krt td ||t| | ||fWYW5QRSd} ~ XYnXzt j d||g| dWn@t j k r*} zt td ||t| | W5d} ~ XYnXW5QRX|t||fS) NT)dirZ needs_exer8r:)r9ZTMPDIRiz --dry-runr;z&Failed growpart --dry-run for (%s, %s)zFailed: growpart %s %s)get_sizer)Zget_tmp_exec_pathr Ztempdirospathjoinexistsmkdirr r@ exit_coder logexcLOGr%) r*r/r0r1r2beforeZtmp_dirZtmpdZ growpart_tmpZmy_enver#r#r$r3Us8         *&zResizeGrowPart.resizeNr r!r"r4r.r3r#r#r#r$r6Hs r6c@s&eZdZdZedddZddZdS) 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``. r7cCstjdo|dgkS)z'growfs only works on the root partitionz/etc/rc.d/growfsr)rErFisfiler-r#r#r$r.szResizeGrowFS.availablec Csht||}z|jjdddWn:tjk rX}zttdt||W5d}~XYnX|t||fS)NZonestartgrowfs)actionservicezFailed: service growfs onestart) rDr)Zmanage_servicer r@r rKrLr%)r*r/r0r1r2rMrNr#r#r$r3s  zResizeGrowFS.resizeN)r r!r"__doc__r4r.r3r#r#r#r$rPys rPc@s"eZdZedddZddZdS) ResizeGpartr7cCsPz4tjddgddiddgdj}td|r2Wd SWntjk rJYnXd S) Ngparthelpr9r:rrC)r<Zrcszgpart recover TF)r stderrr>r?r@)r*rerrr#r#r$r.s  zResizeGpart.availablec Csztdd|gWnFtjk rZ}z&|jdkrJttd|t||W5d}~XYnXt||}ztddd||gWn>tjk r}zttd||t||W5d}~XYnX|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. rWZrecoverrzFailed: gpart recover %sNr3z-izFailed: gpart resize -i %s %s)r r@rJr rKrLr%rD)r*r/r0r1r2rNrMr#r#r$r3s  zResizeGpart.resizeNrOr#r#r#r$rVs rV)rr'rr,c Csd}|dkrDtD]$\}}||}|j|dr|}q6q|stdnZi}tD]\}} | ||<qL||krrtd||||} | j|dr| }|std||S)Nrr7zNo resizers availablezunknown resize mode %szmode %s not available)RESIZERSr. ValueError TypeError) rr'rZ resize_class_nameresizerZcurZmmapkvZmclassr#r#r$resizer_factorys(         rb)r,c Csvd}z\z$t|tj}t|dtjWW8Stk r\|dkrRt|YWSYW dSXW5|rpt|XdS)Nrzfs)rEcloseopenO_RDONLYlseekSEEK_ENDFileNotFoundError get_zfs_size)filenamer2fdr#r#r$rDsrDc Csp|dd}ztdddd|g\}}Wn8tjk rb}ztd||WYdSd}~XYnXt|S)Nrrzpoolgetz -HpovaluesizezFailed: zpool get size %s: %s)splitr r@rLdebugintstrip)Zdatasetrmro_rNr#r#r$rjsrjcCs|dr|dfSt|}|s(td|d}|d}t}|dkr~|s~tt}|dkr~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)deventresultZdevr2Z containerr#r#r$ devent2devs    ryc CstdstddSztdd|gWnPtjk r|}z0|jdkrXtd|ntd|jWYdSd}~XYnXttj,tdd |gtd |W5QRd SQRXdS) 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 partitionsFstatusz#Determined that %s is not encryptedzZReceived unexpected exit code %s from cryptsetup status. Assuming no encrypted partitions.NZisLukszDetermined that %s is encryptedT)r ZwhichrLrqr@rJwarningr)blockdev partitionrNr#r#r$ is_encrypted s$     rc Csddd|g}t|d}|ds2td|z d|dd d dWStk r}ztd |d |d |W5d}~XYnXdS)NZdmsetupZdepsz--options=devnamerz1 dependz5Expecting '1 dependencies' from 'dmsetup'. Received: ruz: (rC)zRan `z$`, but received unexpected stdout: ``)r rv RuntimeErrorrp IndexError)r~ZcommandZdeprNr#r#r$get_underlying_partition$s   rcCsJtstjdfSzXtdt$t}t|}W5QRXW5QRX|d}t |}|d}Wn,t k r}zt d|W5d}~XYnXzt j dd d d|g|dW5zt ddd |t|gWn2t jk r}ztd |W5d}~XYnXz tWn"t k r4ttd YnXXtjd|dfS)zUse '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 keyslotzZCould not load encryption key. This is expected if the volume has been previously resized.NrzZ luksKillSlotz --batch-modez||tjd||ffn|dksN|dkrd} |dk rp|dkrpd||f} nd|} ||tj| fnFd} |dk r|dkrd||||f} nd|||f} ||tj| fWn@tk r} z ||tjd||| ffW5d} ~ XYnX|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)r3appendrrrr%r) r_rwdiskptnumr~r2infooldnewmsgrNr#r#r$ _call_resizernsJ  r)r_r'c Cst|}g}|r|d}d}d}zt|\}}Wn@tk rv} z"||tjd| fWYqW5d} ~ XYnXtd||dkrt |t r|t ||||||7}qzt |} WnFtk r} z&||tjd|| ffWYqW5d} ~ XYnXt | js8t | js8||tjd|fq||} | rzt|} t| | r| dd|Dkr|d||d| Wqt|| \} }||| |fn||tjd |d fWqtk r } z"||tjd |d | fW5d} ~ XYqXqz||\}}WnJttfk rl} z&||tjd || ffWYqW5d} ~ XYnX|t ||||||7}q|S)Nrzunable to convert to device: %szgrowpart found fs=%srczstat of '%s' failed: %szdevice '%s' not a block devicecSsg|] }|dqS)rr#).0xr#r#r$ sz"resize_devices..zResizing mapped device (z!) skipped as it is not encrypted.zResizing encrypted device (z ) failed: zdevice_part_info(%s) failed: %s)copypopryr\rrrrLrq isinstancerPrrEstatOSErrorS_ISBLKst_modeS_ISCHRZget_mapped_devicerrinsertrrrZdevice_part_infor])r_rr'rrwrrr~r2rNZstatretZunderlying_blockdevrr{messager#r#r$resize_devicess           r)namecfgcloudargsr,c Csd|krtdtt|d<|d}t|ts>tddS|dd}t|r|dkrtt j d|dd d d td |dSt|d drt j drtdtddSt|ddg}t|stddSzt||j|d}WnJttfk r>}z&td|||dkr(|WYdSd}~XYnXtdt|||j} W5QRX| D]8\} } } | tjkrtd| | ntd| | | qhdS)Nr8z.No 'growpart' entry in cfg. Using default: %sz#'growpart' in config was not a dictrrZoffz"Growpart's 'mode' key with value 'rz22.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)rLrqDEFAULT_CONFIGrnrdictr}r Zis_falserZ deprecaterErFrQZget_cfg_option_listlenrbr'r\r]r rrrrr) rrrrZmycfgrrr_rNZresizedentryrSrr#r#r$handlesT              rr8rRrW)BrUrrrZloggingrEos.pathr>rabcrr contextlibrpathlibrtypingrrZ cloudinitrr r r r Zcloudinit.cloudr Zcloudinit.configrZcloudinit.config.schemarZcloudinit.distrosrrZcloudinit.settingsrrr__annotations__rrrZ getLoggerr rLrr%r&r6rPrVrr4rbrrrDrjryr5rrrrrrr[r#r#r#r$sd        1& 9.t4