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$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)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)ResizeGrowPartrcCsHz.tjddgddidj}td|r,WdSWntjyBYn0dS) Ngrowpartz--helpLANGC update_envz --update\s+TF)r stdoutresearchProcessExecutionError)r*routr#r#r$r.Is   zResizeGrowPart.availablec Cs\t||}|j}tj|dd}tj|d}d|d} tj|sVt |dzt j dd||g| dWn`t j y} zF| j d krt td ||t| | ||fWYd} ~ WdSd} ~ 00zt j d||g| dWnBt j y,} z&t td ||t| | WYd} ~ n d} ~ 00Wdn1sD0Y|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 Csjt||}z|jjdddWn<tjyZ}z"ttdt||WYd}~n d}~00|t||fS)NZonestartgrowfs)actionZservicezFailed: 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) ResizeGpartr7cCsNz4tjddgddiddgdj}td|r2Wd SWntjyHYn0d S) Ngparthelpr9r:rrC)r<Zrcszgpart recover TF)r stderrr>r?r@)r*rerrr#r#r$r.s  zResizeGpart.availablec Csztdd|gWnHtjy\}z.|jdkrHttd|t||WYd}~n d}~00t||}ztddd||gWn@tjy}z&ttd||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$r3s    zResizeGpart.resizeNrOr#r#r#r$rUs rU)rr'rr,c Csd}|dkrDtD]$\}}||}|j|dr|}q6q|stdnZi}tD]\}} | ||<qL||vrrtd||||} | 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(         ra)r,c Csd}zz0t|tj}t|dtjWW|r6t|Sty~|dkrht|YW|rft|SYW|rzt|dS0W|rt|n|rt|0dS)Nrzfs)rEopenO_RDONLYlseekSEEK_ENDcloseFileNotFoundError get_zfs_size)filenamer2fdr#r#r$rDs*      rDc Csn|dd}ztdddd|g\}}Wn6tjy`}ztd||WYd}~dSd}~00t|S)Nrrzpoolgetz -HpovaluesizezFailed: zpool get size %s: %s)splitr r@rLdebugintstrip)Zdatasetrlrn_rNr#r#r$risricCs|dr|dfSt|}|s(td|d}|d}t}|dkr~|s~tt}|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)deventresultdevr2 containerr#r#r$ devent2devs    rzc CstdstddSztdd|gWnNtjyz}z4|jdkrVtd|ntd|jWYd}~dSd}~00ttj.tdd |gtd |Wdd S1s0YdS) 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 whichrLrpr@rJwarningr)blockdev partitionrNr#r#r$ is_encrypted s$      rc Csddd|g}t|d}|ds2td|z d|dd d dWSty}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)rZcommandZdeprNr#r#r$get_underlying_partition$s   rcCststjdfSztdtBt}t|}Wdn1sN0YWdn1sl0Y|d}t |}|d}Wn.t y}zt d|WYd}~n d}~00zt j ddd d |g|d Wzt dd d |t|gWn4t jy.}ztd|WYd}~n d}~00z tWn t y\ttdYn0nzt dd d |t|gWn4t jy}ztd|WYd}~n d}~00z tWn t yttdYn00tjd|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 NkeyslotzZCould not load encryption key. This is expected if the volume has been previously resized.r{z --key-file-r3)dataZ luksKillSlotz --batch-modez||tjd||ffn|dusN|durd} |durp|durpd||f} nd|} ||tj| fnFd} |dur|durd||||f} nd|||f} ||tj| fWnBty} z(||tjd||| ffWYd} ~ 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)r3appendrrrr%r) r^rvdiskptnumrr2infooldnewmsgrNr#r#r$ _call_resizernsJ  r)r^r'c Cst|}g}|r|d}d}d}zt|\}}WnFty|} z.||tjd| fWYd} ~ qWYd} ~ n d} ~ 00td||dkrt |t r|t ||||||7}qzt |} WnLty} z2||tjd|| ffWYd} ~ qWYd} ~ n d} ~ 00t | jsDt | jsD||tjd|fq||} | rzt|} t| | r| dd|Dvr|d||d| Wqt|| \} }||| |fn||tjd |d fWqty} z*||tjd |d | fWYd} ~ qd} ~ 00qz||\}}WnPttfy} z2||tjd || ffWYd} ~ 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|] }|dqS)rr#).0xr#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)copypoprzr[rrrrLrp isinstancerPrrEstatOSErrorS_ISBLKst_modeS_ISCHRZget_mapped_devicerrinsertrrrZdevice_part_infor\)r^rr'rrvrrrr2rNZstatretZunderlying_blockdevrr|messager#r#r$resize_devicess  "  "       "r)namecfgcloudargsr,c Csd|vrtdtt|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}WnHttfy<}z*td|||dkr&|WYd}~dSd}~00tdt|||j} Wdn1sn0Y| D]8\} } } | tjkrtd| | ntd| | | q|dS)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)rLrpDEFAULT_CONFIGrmrdictrr Zis_falserZ deprecaterErFrQZget_cfg_option_listlenrar'r[r\r rrrrr) rrrrZmycfgrrr^rNZresizedentryrSrr#r#r$handlesR             . rr8rRrV)BrTrrrZloggingrEZos.pathr>rabcrr contextlibrpathlibrtypingrrZ cloudinitrr r r r Zcloudinit.cloudr Zcloudinit.configrZcloudinit.config.schemarZcloudinit.distrosrrZcloudinit.settingsrrr__annotations__rrrZ getLoggerr rLrr%r&r6rPrUrr4rarqrDrirzr5rrrrrrrZr#r#r#r$sd        1& 9.t4