a ah€i¦Hã@sˆUdZddlZddlZddlZddlZddlZddlmZmZm Z m Z m Z ddl m Z mZmZddlmZddlmZddlmZddlmZd d gegd œZeed <d Ze e¡ZdZe e¡ZdZdZ dZ!dZ"e #e$¡Z%dd„Z&dd„Z'dd„Z(d@dd„Z)dAdd„Z*e+e e+ee+e+fe,dœdd„Z-dBd d!„Z.e+e+dd"œd#d$„Z/dCd%d&„Z0d'd(„Z1e ee+ee+e+fee+fd)œd*d+„Z2ee ee e+ee+e+fee+e+fee e+eeee+d,œd-d.„Z3eee+eee+d/œd0d1„Z4eee+e+ee+e+fee+e+feeee+d2œd3d4„Z5eee+eee+d5œd6d7„Z6eee+dd5œd8d9„Z7e,e,ee+dd:œd;d<„Z8e+eee9dd=œd>d?„Z:dS)Dz-Mounts: Configure mount points and swap fileséN)ÚDictÚListÚOptionalÚTupleÚcast)Ú performanceÚsubpÚutil)ÚCloud)ÚConfig)Ú MetaSchema)Ú PER_INSTANCEZ cc_mountsÚall)ÚidZdistrosZ frequencyZactivate_by_schema_keysÚmetaz&^([x]{0,1}[shv]d[a-z][0-9]*|sr[0-9]+)$z^.+:.*z /etc/fstabzcomment=cloudconfigéi@cCs8|dvr dSdD]"}| |¡r| d¡dkrdSqdS)N)ZamiÚrootÚswapT)Ú ephemeralZebsú:éÿÿÿÿF)Ú startswithÚfind)ÚnameZenumname©rú>/usr/lib/python3.9/site-packages/cloudinit/config/cc_mounts.pyÚis_meta_device_name.s rcCst |¡rdSdS)NTF)ÚNETWORK_NAME_REÚmatch)rrrrÚis_network_device:s rcCsHt|ƒd|fd|fg}|D]$}d||f}tj |¡r|SqdS)Nzp%sz-part%sz%s%s)ÚstrÚosÚpathÚexists)Ú device_pathÚpartition_numberZpotential_suffixesÚsuffixZpotential_partition_devicerrrÚ_get_nth_partition_for_deviceAsý   r'cCsXtj |¡ d¡d}tj d|¡}|durLtj |tj |¡ d¡d¡}tj |¡S)Nú/rz /sys/block/)r!r"ÚrealpathÚsplitÚjoinr#)r$Úpartition_pathZ device_nameZsys_pathrrrÚ_is_block_deviceNsÿr-cCs t d|¡|}|dkr&d}t d¡t|ƒr2|St |¡\}}|}|rj| ||¡}||krjt d||¡t|ƒr¦||ƒ}|s‚dS| d¡s–d|f}t d||¡nt  |¡rºd|f}d}|durÒt |d ƒ}nt ||ƒ}|durèdSt ||ƒr|dur|S|SdS) Nz+Attempting to determine the real name of %srÚ ephemeral0z2Adjusted mount option from ephemeral to ephemeral0zMapped device alias %s to %sr(z/dev/%szMapped metadata name %s to %sé) ÚLOGÚdebugrr Zexpand_dotted_devnameÚgetrrÚDEVICE_NAME_RErr'r-)Z startnameZ transformerÚaliasesZdevnamer$r%Zorigr,rrrÚsanitize_devnameXsF        ÿ  r5)ÚoriginalÚ sanitizedÚ fstab_devsÚreturncCsP||krt d||¡|dur.t d|¡dS||vrLt d|||¡dSdS)z*Get if the sanitized device name is valid.zchanged %s => %sNz+Ignoring nonexistent default named mount %sFz&Device %s already defined in fstab: %sT)r0r1)r6r7r8rrrÚsanitized_devname_is_valid‰s ýr:c Csd|durt ¡d}|d}d||dœ}|dur>|dur>|}nd|r–t |¡}|j|j}||d<|dur|tt|dƒ|ƒ}q¢||dkr¢t|dƒ}n |dur¢|}||d<|dtkr¼|}n,|d tkrÒdt}nt t   |t¡ƒt}t||ƒ}||d <i} |  ¡D]0\} } t | tƒr,d | t| | <n| | | <qt d | d | d | d| d| d¡|S)NÚtotaléZna)ÚavailÚmax_inÚmemr=égÍÌÌÌÌÌì?ÚmaxéÚsizez%s MBzCsuggest %s swap for %s memory with '%s' disk given max=%s [max=%s]'r?r>)r Ú read_meminfor!ÚstatvfsÚf_frsizeÚf_bfreeÚminÚintÚGBÚroundÚmathZsqrtÚitemsÚ isinstanceÚMBr0r1) ÚmemsizeÚmaxsizeÚfsysZsugg_maxÚinforEr=ZminsizerCZpinfoÚkÚvrrrÚsuggested_swapsizeœsL           úrV)ÚfnamerCr9csd‰‡‡fdd„}tj |¡}t |¡t |¡d‰ˆdkr`t ddd|g¡t d d |g¡ˆd kr‚t ¡d kr‚|||d ƒn.create_swapr/ZbtrfsÚtruncatez-sÚ0Zchattrz+CZxfs)r@érYrXz4fallocate swap creation failed, will attempt with ddi€ZmkswapN)r!r"Údirnamer Ú ensure_dirZget_mount_inforZkernel_versionrZr0rSr#Úchmodr[)rWrCraÚswap_dirrr_rÚcreate_swapfileÕs,      ricCs¾tj |¡}t|ƒ ¡dkrdzt ¡d}WntyJt  d¡YdS0t  |¡t |||d}tt |dƒƒ}|s†t  d¡dSt  d¡t||ƒWdƒn1s°0Y|S) z fname: full path string of filename to setup size: the size to create. set to "auto" for recommended maxsize: the maximum size Úautor;z)Not creating swap: failed to read meminfoN)rRrQrPrz'Not creating swap: suggested size was 0zSetting up swap file)r!r"rer Úlowerr rDÚIOErrorr0r1rfrVrIrZTimedri)rWrCrQrhrPZmibsizerrrÚsetup_swapfiles$    ÿ  (rmc Csdt|tƒst d¡dS| dd¡}| dd¡}| dd¡}|rD|sRt d¡dStj |¡rætj d ¡szt d |¡|SzHt   d ¡  ¡D](}|  |d ¡rŠt d |¡|WSqŠt d |¡Wn"t yät d|¡|YS0zFt|tƒr|dkrt  |¡}t|tƒrt  |¡}t|||dWSt y^}zt d|¡WYd}~n d}~00dS)zahandle the swap config, calling setup_swap if necessary. return None or (filename, size) z%input for swap config was not a dict.NÚfilenamez /swap.imgrCrrQzno need to setup swapz /proc/swapsz:swap file %s exists, but no /proc/swaps exists, being safeú zswap file %s already in usez+swap file %s exists, but not in /proc/swapsz.swap file %s exists. Error reading /proc/swapsrj)rWrCrQzfailed to setup swap: %s)rNÚdictr0Úwarningr2r1r!r"r#r Úload_text_fileÚ splitlinesrÚ Exceptionr Z human2bytesrm)ZswapcfgrWrCrQÚliner^rrrÚhandle_swapcfg1sH        þ   ÿ    "rv)r9cCslg}i}g}tj t¡rbt t¡ ¡D]:}t|vr>| |¡q&|  ¡}|r&|||d<| |¡q&|||fS)asParse /etc/fstab. Parse fstab, ignoring any lines containing "comment=cloudconfig". :return: A 3-tuple containing: - A list of lines exactly as they appear in fstab - A dictionary with key being the first token in the line and value being the entire line - A list of any lines that were ignored due to "comment=cloudconfig" r) r!r"r#Ú FSTAB_PATHr rrrsÚ MNT_COMMENTÚappendr*)Ú fstab_linesr8Ú fstab_removedruZtoksrrrÚ parse_fstabas     r|)Úmountsr8Údevice_aliasesÚdefault_fieldsÚcloudr9c CsÀg}|D]²}t|tƒs$t d|¡qt|dƒ}t||j|d}t|||ƒr`|g|dd…} n|} t| ƒD].\} } | durŠ|| | | <qlt| | ƒ| | <ql| |t | ƒd…7} |  | ¡q|S)aSanitize mounts to ensure we can work with devices in config. Specifically: - Ensure the mounts configuration is a list of lists - Transform and sanitize device names - Ensure all tokens are strings - Add default options to any lines without options z%Mount option not a list, ignoring: %sr©r4r/N) rNÚlistr0rqr r5Údevice_name_to_devicer:Ú enumerateÚlenry) r}r8r~rr€Z updated_linesruÚstartZsanitized_devnameZ updated_lineÚindexÚtokenrrrÚsanitize_mounts_configuration{s&   ÿ  r‰)r}r9cCslg}g}|ddd…D]F}|ddus2|d|vrRt d|d¡| |d¡q| |¡q|ddd…S)zöRemove any entries that have a device name that doesn't exist. If the second field of a mount line is None (not the string, the value), we skip it along with any other entries that came before it that share the same device name. Nrr/rz$Skipping nonexistent device named %s)r0r1ry)r}ÚactlistZ dev_denylistrurrrÚremove_nonexistent_devices©s r‹)r}Údefault_mount_optionsr8r~r€r9c s’t |¡}ddd|ddggd¢fD]j‰ˆd}t||j|d}t|||ƒsLq"tt|ƒˆd<t‡fd d „|Dƒƒ}|r‚t  d |¡q"|  ˆ¡q"|S) zAdd default mounts to the user provided mount configuration. Add them only if no other entry has the same device name r.z/mntrjrcÚ2)rÚnonerÚswrcrcrrc3s|]}|dˆdkVqdS)rNr)Ú.0Zcfgm©Z default_mountrrÚ Ösz,add_default_mounts_to_cfg..z-Not including %s, already previously included) ÚcopyÚdeepcopyr5rƒr:rr Úanyr0r1ry) r}rŒr8r~r€Z new_mountsr†r7Zdefault_already_existsrr‘rÚadd_default_mounts_to_cfg¼s& þÿ  ÿ  r–)rŠr9cCsdd„|DƒS)z=Add "comment=cloudconfig" to the mount options of each entry.cSs8g|]0}|dd…|d›dt›g|dd…‘qS)Néú,r@)rx©rÚentryrrrÚ âsÿzadd_comment..r©rŠrrrÚ add_commentàsþrcCs$tdd„|Dƒƒr t ddg¡dS)z1Call 'swapon -a' if any entry has a swap fs type.css|]}|ddkVqdS)r<rNrr™rrrr’êóz*activate_swap_if_needed..Zswaponú-aN)r•rrœrrrÚactivate_swap_if_neededèsr )Ú uses_systemdÚ changes_madeÚdirsr9cCs^d}|rd}n(dd„t ¡ ¡Dƒ}tt|ƒ |¡ƒ}|rZt ddg¡|rZt ddg¡d S) z¶Call 'mount -a' if needed. If changes were made, always call 'mount -a'. Otherwise, call 'mount -a' if any of the directories in the mount list are not already mounted. FTcSsh|]}d|vr|d’qS)Z mountpointr)rÚvalrrrÚ úsþz"mount_if_needed..ZmountrŸZ systemctlz daemon-reloadN)r r}ÚvaluesÚboolÚsetÚ differencer)r¡r¢r£Zdo_mountZ mount_pointsrrrÚmount_if_neededîs þrª)rÚcfgr€Úargsr9c sÌ|j ¡}|rdnd}ddd|ddg}| d|¡}| dg¡}t d |¡tƒ\} } } | d i¡} t|| | ||ƒ} t| || | |ƒ} t| ƒ} t | ƒ} t | d i¡ƒ}|r¼|   |d d d ddg¡t | ƒdkrÖt d¡dSdd„| Dƒ}dd„| Dƒ}|D]6}zt  |¡Wqöty*t  td|¡Yqö0qödd„|Dƒ‰dd„| Dƒ‰‡fdd„ˆDƒ‡fdd„ˆDƒ}|  |¡dd | ¡}t  t|¡|r¦t d|¡n t d¡t| ƒt|t|ƒ|ƒdS)z Handle the mounts configuration.z:defaults,nofail,x-systemd.after=cloud-init.service,_netdevzdefaults,nobootwaitNrjrcrZmount_default_fieldsr}zmounts configuration is %sr~rrŽrrz No modifications to fstab neededcSsg|]}d |¡‘qS)ú )r+r™rrrr›1ržzhandle..cSs"g|]}|d d¡r|d‘qS)r/r()r)rÚdrrrr›3ržz Failed to make '%s' config-mountcSsg|]}| dd¡‘qS©r­ro©Úreplace©rÚnrrrr›;ržcSsg|]}| dd¡‘qSr¯r°r²rrrr›<ržcsg|]}|ˆvrd|›‘qS)z- r)rZdrop)Úsaddsrrr›>ržcsg|]}|ˆvrd|›‘qS)z+ r)rÚadd)Úsdropsrrr›>sz%s Ú zChanges to fstab: %szNo changes to /etc/fstab made.)Zdistror¡r2r0r1r|r‰r–r‹rrvryr…r rfrtZlogexcÚextendr+Z write_filerwr rªr§)rr«r€r¬r¡rŒZhardcoded_defaultsrr}rzr8r{r~Z updated_cfgZswapfileZ cfg_linesr£r®ZsopsÚcontentsr)r´r¶rÚhandles^ ÿýÿ     ÿ ÿ  ÿ   rº)N)N)NNN)NN);Ú__doc__r“ZloggingrLr!ÚreÚtypingrrrrrZ cloudinitrrr Zcloudinit.cloudr Zcloudinit.configr Zcloudinit.config.schemar Zcloudinit.settingsr rÚ__annotations__ZDEVICE_NAME_FILTERÚcompiler3ZNETWORK_NAME_FILTERrrwrxrOrJZ getLoggerÚ__name__r0rrr'r-r5r r§r:rVrirmrvr|r‰r‹r–rr rªr‚rºrrrrÚ sv    ü     2þ  9> 0(    ú .     ú $  þ