U ¤¹Dg¦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|dkr dSdD]"}| |¡r| d¡dkrdSqdS)N)ZamiÚrootÚswapT)Ú ephemeralZebsú:éÿÿÿÿF)Ú startswithÚfind)ÚnameZenumname©rú %sNz+Ignoring nonexistent default named mount %sFz&Device %s already defined in fstab: %sT)r0r1)r6r7r8rrrÚsanitized_devname_is_valid‰s ýr:c Csd|dkrt ¡d}|d}d||dœ}|dkr>|dkr>|}nd|r–t |¡}|j|j}||d<|dkr|tt|dƒ|ƒ}q¢||dkr¢t|dƒ}n |dkr¢|}||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>z|||dƒWn,tjk r¾t   d¡|||d ƒYnXtj  |¡rØt  |d¡zt d|g¡Wn$tjk rt  |¡‚YnXdS)zSize is in MiB.z6Failed to create swapfile '%s' of size %sMB via %s: %sc s®t d|ˆ|¡|dkr*ddd||g}n*|dkrJddd|dd |g}n t d ¡‚ztj|d d WnBtjk r¨}z"t ˆ||||¡t |¡‚W5d}~XYnXdS) Nz3Creating swapfile in '%s' on fstype '%s' using '%s'Ú fallocatez-lz%sMÚddz if=/dev/zerozof=%szbs=1Mzcount=%sz:Missing dependency: 'dd' and 'fallocate' are not availableT)Zcapture)r0r1rÚProcessExecutionErrorrSr Údel_file)rWrCÚmethodÚcmdÚe©ÚerrmsgZfstyperrÚ create_swapÚs0üûÿ z$create_swapfile..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,      ric Cs¬tj |¡}t|ƒ ¡dkrfzt ¡d}Wn tk rLt  d¡YdSXt  |¡t |||d}tt |dƒƒ}|sˆt  d¡dSt  d¡t||ƒW5QRX|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 k ræt d|¡|YSXzFt|tƒr |dkr t  |¡}t|tƒr t  |¡}t|||dWSt k r^}zt d|¡W5d}~XYnXdS)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_swapcfg1sJ        þ  ÿ    rv)r9cCslg}i}g}tj t¡rbt t¡ ¡D]:}t|kr>| |¡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].\} } | dkrŠ|| | | <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}|ddks2|d|krRt 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|ddgddddddgfD]j‰ˆd }t||j|d }t|||ƒsTq*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Ú2rÚnoneÚswrrc3s|]}|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’êsz*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|kr|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]8}zt  |¡Wqötk r,t  td|¡YqöXqö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›1szhandle..cSs"g|]}|d d¡r|d‘qS)r/r()r)rÚdrrrr›3sz Failed to make '%s' config-mountcSsg|]}| dd¡‘qS©r¬ro©Úreplace©rÚnrrrr›;scSsg|]}| dd¡‘qSr®r¯r±rrrr›<scsg|]}|ˆkrd|›‘qS)z- r)rZdrop)Úsaddsrrr›>scsg|]}|ˆkrd|›‘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Úhandlesp ÿýÿ    ÿÿ  ÿ   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Ú s~    ü     2 þ  9> 0(    ú .     ú $ þ