a '¡Dglvã@sšUdZddlZddlZddlZddlmZddlmZmZm Z ddl m Z ddl m Z ddlmZddlmZdd lmZd d iZe e¡Zd eged dgdœZeed<ee e eddœdd„Zdd„Zdd„ZdJdd„ZdKdd„Z dd„Z!dLdd „Z"d!d"„Z#d#d$„Z$dMd&d'„Z%d(d)„Z&d*d+„Z'd,d-„Z(d.d/„Z)d0d1„Z*d2d3„Z+d4d5„Z,d6d7„Z-d8d9„Z.d:d;„Z/dd?„Z1d@dA„Z2dBdC„Z3dDdE„Z4dFdG„Z5dHdI„Z6dS)Nz1Disk Setup: Configure partitions and filesystems.éN)ÚPath)Ú performanceÚsubpÚutil)ÚCloud)ÚConfig)Ú MetaSchema)Ú ALL_DISTROS)Ú PER_INSTANCEÚLANGÚCZ cc_disk_setupÚ disk_setupÚfs_setup)ÚidZdistrosZ frequencyZactivate_by_schema_keysÚmeta)ÚnameÚcfgÚcloudÚargsÚreturnc s²| di¡‰‡‡fdd„}| d¡}t|tƒræt||ƒt dt|ƒ¡| ¡D]”\}}t|tƒspt d|¡qPz>t   d|›¡t ||ƒWdƒn1s¢0YWqPt yâ}zt  td |¡WYd}~qPd}~00qP| d ¡} t| tƒr®t d t| ƒ¡t| |ƒ| D]’}t|tƒs:t d |¡qz8t   d ¡t|ƒWdƒn1sf0YWn6t y¨}zt  td|¡WYd}~n d}~00qdS)z[ See doc/examples/cloud-config-disk-setup.txt for documentation on the format. Údevice_aliasescsˆ |¡}ˆ |p|¡p|S)N)ÚgetZdevice_name_to_device)Zcandr©rr©úB/usr/lib/python3.9/site-packages/cloudinit/config/cc_disk_setup.pyÚalias_to_device(s zhandle..alias_to_devicer zPartitioning disks: %szInvalid disk definition for %szCreating partition on Nz Failed partitioning operation %srzsetting up filesystems: %sz"Invalid file system definition: %szCreating new filesystemz%Failed during filesystem operation %s)rÚ isinstanceÚdictÚupdate_disk_setup_devicesÚLOGÚdebugÚstrÚitemsÚwarningrZTimedÚmkpartÚ ExceptionrÚlogexcÚlistÚupdate_fs_setup_devicesÚmkfs) rrrrrr ÚdiskÚ definitionÚerrrrÚhandle!s<      ÿ,(      ,r-cCs‚t|ƒD]t}||ƒ}|dus||kr&q||vrBt d||¡||=||||<t||tƒrh|||d<||=t d||¡qdS)Nz0Replacing %s in disk_setup for translation of %sÚ _orignamez,updated disk_setup device entry '%s' to '%s')r'rÚinforrr )r ÚtformerÚorignameZ transformedrrrrMs( ý  ýrcCs¬|D]¢}t|tƒs t d|¡q| d¡}|dur4qt |¡\}}||ƒ}|durv|}t d|||¡||d<||d<|rd|vržt d|||¡|d|d<||d<qdS)Nz"entry in disk_setup not a dict: %sÚdevicez%s is mapped to disk=%s part=%sr.Ú partitionzKPartition '%s' from dotted device name '%s' overrides 'partition' key in %sZ _partition)rrrr#rrZexpand_dotted_devnamer )r r0r+r1ÚdevÚpartZtformedrrrr(gs4   ÿû r(ccs@t |¡}|r||d…}dd„|DƒD]\}}||fVq(dS)zd Returns the key/value pairs of output sent as string like: FOO='BAR' HOME='127.0.0.1' NcSsg|]}| d¡‘qS)ú=)Úsplit©Ú.0ÚxrrrÚ –óz"value_splitter..)Úshlexr7)ÚvaluesÚstartZ_valuesÚkeyÚvaluerrrÚvalue_splitters   rBFc csÀdddd|g}|r| d¡d}zt |¡\}}Wn6tyh}ztd||fƒ|‚WYd}~n d}~00dd „| ¡ ¡Dƒ}|D]6}ddddd œ}t|ƒD]\} } | ||  ¡<qž|Vq„dS) aƒ Enumerate the elements of a child device. Parameters: device: the kernel device name nodeps : don't enumerate children devices Return a dict describing the disk: type: the entry type, i.e disk or part fstype: the filesystem type, if it exists label: file system label, if it exists name: the device name, i.e. sda Zlsblkz--pairsz--outputzNAME,TYPE,FSTYPE,LABELz--nodepsNú"Failed during disk check for %s %scSs g|]}t| ¡ƒdkr|‘qS)r)Úlenr7r8rrrr;¼r<z"enumerate_disk..)rÚtypeÚfstypeÚlabel)Úappendrr%Ú RuntimeErrorÚstripÚ splitlinesrBÚlower) r2ÚnodepsZ lsblk_cmdr/Ú_errr,Úpartsr5Údr@rArrrÚenumerate_diskšs6û  ÿþürQcCs.t|ddD]}d|vr |d ¡Sq dS)z@ Return the device type of the device by calling lsblk. T)rMrEN)rQrL)r2rPrrrÚ device_typeÌsrRcCsVd}z t|ƒ}Wn ty0t d|¡YdS0|rB|dkrBdS|sR|dkrRdSdS)z0 Check if the device is a valid device. ÚzQuery against device %s failedFr5Tr*)rRr%rr#)rr3Zd_typerrrÚis_device_valid×s     rTc CsÒd\}}}}ddd|g}ztj|ddgd\}}Wn6tyh}ztd||fƒ|‚WYd }~n d }~00|rÈt| ¡ƒd krÈt|d d D]<\}} | ¡d kr¤| }qŠ| ¡d kr¶| }qŠ| ¡dkrŠ| }qŠ|||fS)zÏ Check if the device has a filesystem on it Output of blkid is generally something like: /dev/sda: LABEL="Backup500G" UUID="..." TYPE="ext4" Return values are device, label, type, uuid )NNNNZblkidz-cz /dev/nullré)ZrcsrCNé)r?rGrEÚuuid)rr%rIrDrKrBrL) r2ÚoutrGÚfs_typerWZ blkid_cmdrNr,r@rArrrÚcheck_fsés(   ÿþ   rZcCst|ƒ\}}}|S)z7 Returns true if the device has a file system. )rZ)r2Ú_rYrrrÚ is_filesystem sr\TcCsî|dur d}|sddg}d}t|ƒD]®}|d|krP|durPd|ddfS|d|kr„|rl|d |ksp|s„d|dd fS|d |vr$|d dks¤|dr¨d }|d dkr¶q$|ds$d|ddfSq$|sà|dfSt d ¡d S)a Find a device that is either matches the spec, or the first The return is value is (, ) where the device is the device to use and the bool is whether the device matches the fs_type and label. Note: This works with GPT partition tables! NrSr*r5FrFú/dev/%srrGTrEz5Failed to find device during available device search.)NF)rQrr#)r2rYrGZ valid_targetsÚ label_matchÚ replace_fsZraw_device_usedrPrrrÚfind_device_nodes6  ÿ ÿÿ   r`cCs2ttt|ƒƒƒdkrdSt|ƒ\}}}|r.dSdS)z¥ Check if the device is currently used. Returns true if the device has either a file system or a partition entry is no filesystem found on the disk. rVTF)rDr'rQrZ)r2r[Ú check_fstyperrrÚ is_disk_usedIs rbc Cstz,t dd|g¡\}}t dd|g¡\}}Wn6tyb}ztd||fƒ|‚WYd}~n d}~00t|ƒt|ƒS)NÚblockdevz --getsize64z--getsszFailed to get %s size %s)rr%rIÚint)r2Z size_in_bytesr[Z sector_sizer,rrrÚ get_hdd_size]s (rec Csüt|ƒdd|g}ztj|d|d\}}Wn6tyb}ztd||fƒ|‚WYd}~n d}~00g}| ¡D]†}| ¡}t|ƒdkrŠqp||dvrp|d ¡d vr¨qpd} tt d t|ƒƒd d D](} ||   ¡rÂ|| d krÂ|| } qìqÂ|  | ¡qp|S)zÒ Returns true if the partition layout matches the one on the disk Layout should be a list of values. At this time, this only verifies that the number of partitions and their labels is correct. Úsfdiskz-lú%s ©Údataú(Error running partition command on %s %sNréÿÿÿÿ)ZextendedÚemptyrVT)Úreverseú/) Ú read_parttblrr%rIrKr7rDrLÚsortedÚrangeÚisdigitrH) r2ÚlayoutÚprt_cmdrXrNr,Ú found_layoutÚlineÚ_lineZ type_labelr:rrrÚcheck_partition_mbr_layoutgs2  ÿþ    rxc CsÌdd|g}ztj|td\}}Wn6tyV}ztd||fƒ|‚WYd}~n d}~00t| ¡ƒ}|D]}| ¡ d¡rhq€qhdd„|Dƒ}g} |D]0} t| ƒdkr¼|   d ¡r¼| d d …} |   | ¡q–| S) NÚsgdiskz-p)Z update_envrjÚNumbercSsg|]}| ¡ ¡d‘qS)é)rJr7)r9rvrrrr;­r<z.check_partition_gpt_layout..éZ00rrU) rÚ LANG_C_ENVr%rIÚiterrKrJÚ startswithrDÚendswithrH) r2rsrtrXrNr,Z out_linesrvZcodesZcleanedÚcoderrrÚcheck_partition_gpt_layouts(  ÿþ   r‚cCsÊd|krt||ƒ}nd|kr(t||ƒ}ntdƒ‚t d||||¡t|tƒrd|r`t|ƒdkr`dSdSt|ƒt|ƒkrÆdd „|Dƒ}t d ||¡t||ƒD]&\}}|d uršt |ƒt |ƒkršdSqšdSdS) zÎ See if the partition lay out matches. This is future a future proofing function. In order to add support for other disk layout schemes, add a function called check_partition_%s_layout ÚgptÚmbrúUnable to determine table typez6called check_partition_%s_layout(%s, %s), returned: %srVTFcSs*g|]"}t|ttfƒr"t|dƒnd‘qS)rVN)rÚtupler'r!r8rrrr;Øsz*check_partition_layout..zLayout types=%s. Found types=%sN) r‚rxrIrr rÚboolrDÚzipr!)Ú table_typer2rsruZ layout_typesZitypeZftyperrrÚcheck_partition_layout¸s8  û ÿÿrŠc Cst|tƒst|tƒrdSt|ƒdkr.t|tƒs8t|tƒs@tdƒ‚t|ƒ}|dkrXtdƒ‚g}d}|D]€}d}|}|d7}t|tƒr¢t|ƒdkrštd |ƒ‚|\}}tt|ƒt|ƒd ƒ}||krÒ| d |¡qd| d ||f¡qdd  |¡} t|ƒdkr td| ƒ‚| S)a@ Calculate the layout of the partition table. Partition sizes are defined as percentage values or a tuple of percentage and partition type. For example: [ 33, [66: 82] ] Defines the first partition to be a size of 1/3 the disk, while the remaining 2/3's will be of type Linux Swap. z,,83rzPartition layout is invalidr|z$Only simply partitioning is allowed.éSrVrUú%Partition was incorrectly defined: %sédz,,%sz,%s,%sÚ z-Calculated partition definition is too big %s) rr'r‡rDrIrdÚfloatrHÚjoin) ÚsizersZ last_part_numÚpart_definitionZpart_numr5Z part_typeÚpercentÚ part_sizeZsfdisk_definitionrrrÚget_partition_mbr_layoutæsB ÿ  ÿ ÿÿr•cCsžt|tƒrdddgfgSg}|D]h}t|tƒrPt|ƒdkrFtd|ƒ‚|\}}n|}d}tt|ƒt|ƒdƒ}| |dd |¡gf¡q d|ddd<|S)NrrUrŒrz+{}rk) rr‡r'rDrIrdrrHÚformat)r‘rsZpartition_specsr3r“Úpartition_typer”rrrÚget_partition_gpt_layouts    ÿ r˜cCsvd}d}d}t|dƒD}| ||¡| | tj¡| ||¡| ¡Wdƒn1s`0Yt|ƒdS)Nóizrb+)ÚopenÚwriteÚseekÚosÚSEEK_ENDÚflushro)r2ZnullZ start_lenZend_lenÚfprrrÚpurge_disk_ptable7s &r¡c CsŽt|ƒD]x}|ddvrddd|dg}zt d|d¡t |¡Wqty~}ztd|dƒ|‚WYd }~qd }~00qt|ƒd S) z( Remove partition table entries rE)r*ZcryptZwipefsz--allr]rzPurging filesystem on /dev/%szFailed FS purge of /dev/%sN)rQrr/rr%rIr¡)r2rPZ wipefs_cmdr,rrrÚ purge_diskFs   ÿþr¢cCs0d|krt||ƒSd|kr$t||ƒStdƒ‚dS)zï Call the appropriate function for creating the table definition. Returns the table definition This is a future proofing function. To add support for other layouts, simply add a "get_partition_%s_layout" function. r„rƒr…N)r•r˜rI)r‰r‘rsrrrÚget_partition_layoutZs   r£c Cszd}t |¡r||g}n dd|g}t ¡zt |¡Wn4tyl}zt td|¡WYd}~n d}~00t ¡dS)zq `Partprobe` is preferred over `blkdev` since it is more reliably able to probe the partition table. Ú partprobercz --rereadptz%Failed reading the partition table %sN)rÚwhichrÚudevadm_settler%r&r)r2r¤Z probe_cmdr,rrrrojs   &roc Csddd|g}ztj|d|dWn6tyV}ztd||fƒ|‚WYd}~n d}~00t|ƒdS)zV Break out of mbr partition to allow for future partition types, i.e. gpt rfz--forcergrhz Failed to partition device %s %sN)rr%rIro)r2rsrtr,rrrÚexec_mkpart_mbr}s  ÿþr§c Cs²z„t dd|g¡t|ƒD]f\}\}\}}|d7}t ddd |||¡|g¡|durt|ƒ dd¡}t ddd  ||¡|g¡qWn ty¤t d |¡‚Yn0t|ƒdS) Nryz-ZrVz-nz{}:{}:{}r|Ú0z-tz{}:{}zFailed to partition device %s) rÚ enumerater–r!Úljustr%rr#ro)r2rsÚindexr—r?ÚendZpinputrrrÚexec_mkpart_gptŽs( üÿÿ   r­cCs8tj |¡s,t ¡tj |¡s,td|ƒ‚t ¡dS)z?Assert that device exists and settle so it is fully recognized.zBDevice %s did not exist and was not created with a udevadm settle.N)rÚpathÚexistsrr¦rI©r2rrrÚassert_and_settle_device©s  ÿÿr±cCsœt|ƒtj |¡}t d|¡| dd¡}| dd¡}| dd¡}t d¡t|tƒr\|r`|snt d¡d St d |¡t |ƒs’t d j |d ƒ‚t|t ƒr¾|  ¡d kr¾t d¡t|ƒd St d¡t|||ƒrât d¡dSt d¡|st|ƒst|ƒrt d|¡d St d|¡t|ƒ}t d¡t|||ƒ}t d|¡t d|¡d|krnt||ƒnd|kr„t||ƒnt dƒ‚t d|¡d S)að Creates the partition table. Parameters: definition: dictionary describing how to create the partition. The following are supported values in the dict: overwrite: Should the partition table be created regardless of any pre-existing data? layout: the layout of the partition table table_type: Which partition table to use, defaults to MBR device: the device to work on. z!Checking values for %s definitionÚ overwriteFrsr‰r„z Checking against default devicesz)Device is not to be partitioned, skippingNz'Checking if device %s is a valid devicez%Device {device} is not a disk device!r°Úremovez,Instructed to remove partition table entriesz!Checking if device layout matchesz"Device partitioning layout matchesTz'Checking if device is safe to partitionz-Skipping partitioning on configured device %szChecking for device size of %szCalculating partition layoutz Layout is: %szCreating partition table on %srƒr…zPartition table created for %s)r±rr®Úrealpathrr rrr‡rTrIr–r!rLr¢rŠrbr\rer£r§r­)r2r+r²rsr‰Z device_sizer’rrrr$¹sN         ÿ               r$cCsDddddddœ}d| ¡vr d}| ¡|vr4||St d|¡dS)z9 A force flag might be -F or -F, this look it up z-Fz-f)ÚextZbtrfsZxfsZreiserfsZswaprµzForce flag for %s is unknown.rS)rLrr#)ZfsÚflagsrrrÚlookup_force_flagsû   r·c Cs¼| d¡}| d¡}t| dd¡ƒ}| d¡}| dg¡}| dg¡}| dd ¡}| d d ¡}t|ƒtj |¡}t d |¡|rŒ| ¡rZ| ¡rÞ|d  ¡rª|›d }d||f}t |ƒ  ¡sÐt  d¡dSt d||¡t d|¡t |ƒ\} } } t d|| | ¡| |krL| |krLt d|¡|s>t d|¡dSt d|¡n t d|¡nà|rt|ƒ  ¡dvr|} t d|¡d} |  ¡dkr˜d } t|||| |d\}}t d| |¡|rÐt d¡dS|sî|rî|rît d|¡|s:t d|¡dSn4|rt|ƒ  ¡d kr,t d!|¡nt d"¡dSt d#|||¡|s`t  d$|¡dS|s||s|td%j|d&ƒ‚d }|rÄ|d|||d'œ}d}|r°t  d(|¡|r^t  d)|¡nšt d*|¡}|sæt d+|¡}|sþt  d,||¡dS|g}|r| d-|g¡|s,t|ƒd.krDt|ƒ}|rD| |¡|rT| |¡| |¡t d/||¡ztj||d0Wn8ty¶}ztd1||fƒ|‚WYd}~n d}~00dS)2a¦ Create a file system on the device. label: defines the label to use on the device fs_cfg: defines how the filesystem is to look The following values are required generally: device: which device or cloud defined default_device filesystem: which file system type overwrite: indiscriminately create the file system partition: when device does not define a partition, setting this to a number will mean device + partition. When set to 'auto', the first free device or the first device which matches both label and type will be used. 'any' means the first filesystem that matches on the device. When 'cmd' is provided then no other parameter is required. rGr2r3ÚanyÚ filesystemÚcmdZ extra_optsr_Fr²z#Checking %s against default devicesrkÚpz%s%sz/Path %s does not exist or is not a block deviceNz%Manual request of partition %s for %szChecking device %sz0Device '%s' has check_label='%s' check_fstype=%sz Existing file system found at %sz"Device %s has required file systemzDestroying filesystem on %sz#Device %s is cleared for formatting)Úautor¸z-Identifying device to create %s filesystem onT)rYrGr^r_z(Automatic device for %s identified as %sz,Found filesystem match, skipping formatting.z*Replacing file system on %s as instructed.zENo device available that matches request. Skipping fs creation for %sZnonez.Using the raw device to place filesystem %s onz(Error in device identification handling.z;File system type '%s' with label '%s' will be created on %szDevice is not known: %szENo way to create filesystem '{label}'. fs_type or fs_cmd must be set.)rG)rGr¹r2z8fs_setup:overwrite ignored because cmd was specified: %sz9fs_setup:extra_opts ignored because cmd was specified: %szmkfs.%szmk%sz.Cannot create fstype '%s'. No mkfs.%s commandz-Lr*zCreating file system %s on %s)ÚshellzFailed to exec of '%s': %s)rr!r±rr®r´rr rrrÚis_block_devicer#rZrLr`rIr–rr¥ÚextendrRr·rHr%)Zfs_cfgrGr2r3rYZfs_cmdZfs_optsZ fs_replacer²Z check_labelrar[Zodevicer^Zreuser½Zmkfs_cmdZ force_flagr,rrrr)sø              ÿ ü   û   ý ü  ÿÿýþþý   r))N)F)F)NNNTN)7Ú__doc__Zloggingrr=ÚpathlibrZ cloudinitrrrZcloudinit.cloudrZcloudinit.configrZcloudinit.config.schemarZcloudinit.distrosr Zcloudinit.settingsr r}Z getLoggerÚ__name__rrÚ__annotations__r!r'r-rr(rBrQrRrTrZr\r`rbrerxr‚rŠr•r˜r¡r¢r£ror§r­r±r$r·r)rrrrÚsb       ü,& 2   ú 8 ().9G