o
    m[hNH  ã                   @   s¦  U d Z ddlZddlZddlZddlZddlZddlmZmZm	Z	m
Z
mZ ddlmZmZmZ ddlmZ ddlmZ ddlmZ ddlmZ d	d
geg dœZeed< dZdZdZdZdZdZe  e!¡Z"dd„ Z#dd„ Z$dd„ Z%dIdd„Z&dIdd„Z'de(de	e( dee(e(f d e)fd!d"„Z*dJd#d$„Z+d%e(d&e(d dfd'd(„Z,dKd)d*„Z-d+d,„ Z.d e
ee( ee(e(f ee( f fd-d.„Z/d/ee	ee	e(    dee(e(f d0ee(e(f d1ee	e(  d2ed eee(  fd3d4„Z0d/eee(  d eee(  fd5d6„Z1d/eee(  d7e(dee(e(f d0ee(e(f d2ed eee(  fd8d9„Z2d:eee(  d eee(  fd;d<„Z3d:eee(  d dfd=d>„Z4d?e)d@e)dAee( d dfdBdC„Z5dDe(dEed2edFe6d df
dGdH„Z7dS )Lz-Mounts: Configure mount points and swap filesé    N)ÚDictÚListÚOptionalÚTupleÚcast)ÚperformanceÚsubpÚutil)ÚCloud)ÚConfig)Ú
MetaSchema)ÚPER_INSTANCEÚ	cc_mountsÚall)ÚidÚdistrosÚ	frequencyÚactivate_by_schema_keysÚmetaz&^([x]{0,1}[shv]d[a-z][0-9]*|sr[0-9]+)$z^.+:.*z
/etc/fstabzcomment=cloudconfigé   i   @c                 C   s8   | dv rdS dD ]}|   |¡r|  d¡dkr dS qdS )N)ÚamiÚrootÚswapT)Ú	ephemeralÚebsú:éÿÿÿÿF)Ú
startswithÚfind)ÚnameÚenumname© r!   ú</usr/lib/python3/dist-packages/cloudinit/config/cc_mounts.pyÚis_meta_device_name,   s   €r#   c                 C   s   t  t| ¡rdS dS )NTF)ÚreÚmatchÚNETWORK_NAME_FILTER)r   r!   r!   r"   Úis_network_device8   s   r'   c                 C   sH   t |ƒd|f d|f g}|D ]}d| |f }tj |¡r!|  S qd S )Nzp%sz-part%sz%s%s)ÚstrÚosÚpathÚexists)Údevice_pathÚpartition_numberÚpotential_suffixesÚsuffixÚpotential_partition_devicer!   r!   r"   Ú_get_nth_partition_for_device?   s   ýÿr1   c                 C   sX   t j | ¡ d¡d }t j d|¡}|d ur&t j |t j |¡ d¡d ¡}t j |¡S )Nú/r   z/sys/block/)r)   r*   ÚrealpathÚsplitÚjoinr+   )r,   Úpartition_pathÚdevice_nameÚsys_pathr!   r!   r"   Ú_is_block_deviceL   s   ÿr9   c                 C   s  t  d| ¡ | }|dkrd}t  d¡ t| ƒr| S t |¡\}}|}|r5| ||¡}||kr5t  d||¡ t|ƒrS||ƒ}|sAd S | d¡sKd|f }t  d||¡ nt 	t
| ¡r^d|f }d }|d u rjt|d	ƒ}nt||ƒ}|d u rud S t||ƒr‚|d ur€|S |S d S )
Nz+Attempting to determine the real name of %sr   Ú
ephemeral0z2Adjusted mount option from ephemeral to ephemeral0zMapped device alias %s to %sr2   z/dev/%szMapped metadata name %s to %sé   )ÚLOGÚdebugr'   r	   Úexpand_dotted_devnameÚgetr#   r   r$   r%   ÚDEVICE_NAME_FILTERr1   r9   )Ú	startnameÚtransformerÚaliasesÚdevnamer,   r-   Úorigr6   r!   r!   r"   Úsanitize_devnameV   sF   



ÿ
rF   ÚoriginalÚ	sanitizedÚ
fstab_devsÚreturnc                 C   sP   || krt  d| |¡ |du rt  d| ¡ dS ||v r&t  d||| ¡ dS dS )z*Get if the sanitized device name is valid.zchanged %s => %sNz+Ignoring nonexistent default named mount %sFz&Device %s already defined in fstab: %sT)r<   r=   )rG   rH   rI   r!   r!   r"   Úsanitized_devname_is_valid‡   s   ýrK   c              	   C   s`  | d u r
t  ¡ d } | d }d|| dœ}|d u r|d u r|}n2|rKt |¡}|j|j }||d< |d u r>tt|d ƒ|ƒ}n||d krJt|d ƒ}n|d u rQ|}||d< | dt k r^| }n| d	t k ridt }nt	t
 | t ¡ƒt }t||ƒ}||d
< i }	| ¡ D ]\}
}t|tƒr•d|t  |	|
< qƒ||	|
< qƒt d|	d
 |	d |	d |	d |	d ¡ |S )NÚtotalé   Úna)ÚavailÚmax_inÚmemrO   é   gÍÌÌÌÌÌì?Úmaxé   Úsizez%s MBzCsuggest %s swap for %s memory with '%s' disk given max=%s [max=%s]'rQ   rP   )r	   Úread_meminfor)   ÚstatvfsÚf_frsizeÚf_bfreeÚminÚintÚGBÚroundÚmathÚsqrtÚitemsÚ
isinstanceÚMBr<   r=   )ÚmemsizeÚmaxsizeÚfsysÚsugg_maxÚinforW   rO   ÚminsizerU   ÚpinfoÚkÚvr!   r!   r"   Úsuggested_swapsizeš   sN   
€



úrl   ÚfnamerU   c                    s  d‰ ‡ ‡fdd„}t j | ¡}t |¡ t |¡d ‰ˆdkr0t ddd| g¡ t d	d
| g¡ ˆdkrAt ¡ dk rA|| |dƒ nz|| |dƒ W n tjy^   t	 
d¡ || |dƒ Y nw t j | ¡rkt | d¡ z
t d| g¡ W dS  tjyƒ   t | ¡ ‚ w )zSize is in MiB.z6Failed to create swapfile '%s' of size %sMB via %s: %sc              
      s¢   t  d| ˆ|¡ |dkrddd| | g}n|dkr%ddd|  dd	| g}nt d
¡‚z
tj|dd� W d S  tjyP } zt  ˆ | |||¡ t | ¡ ‚ d }~ww )Nz3Creating swapfile in '%s' on fstype '%s' using '%s'Ú	fallocatez-lz%sMÚddzif=/dev/zerozof=%szbs=1Mzcount=%sz:Missing dependency: 'dd' and 'fallocate' are not availableT)Úcapture)r<   r=   r   ÚProcessExecutionErrorrg   r	   Údel_file)rm   rU   ÚmethodÚcmdÚe©ÚerrmsgÚfstyper!   r"   Úcreate_swapØ   s4   üûÿ
€ýz$create_swapfile.<locals>.create_swapr;   ÚbtrfsÚtruncatez-sÚ0Úchattrz+CÚxfs)rR   é   ro   rn   z4fallocate swap creation failed, will attempt with ddi€  ÚmkswapN)r)   r*   Údirnamer	   Ú
ensure_dirÚget_mount_infor   Úkernel_versionrq   r<   rg   r+   Úchmodrr   )rm   rU   ry   Úswap_dirr!   rv   r"   Úcreate_swapfileÓ   s0   

þ
þr‡   c                 C   sÀ   t j | ¡}t|ƒ ¡ dkr2zt ¡ d }W n ty%   t 	d¡ Y dS w t 
|¡ t|||d�}tt|d ƒƒ}|sCt 	d¡ dS t d¡� t| |ƒ W d  ƒ | S 1 sYw   Y  | S )	z�
    fname: full path string of filename to setup
    size: the size to create. set to "auto" for recommended
    maxsize: the maximum size
    ÚautorL   z)Not creating swap: failed to read meminfoN)re   rd   rc   r   z'Not creating swap: suggested size was 0zSetting up swap file)r)   r*   r�   r(   Úlowerr	   rV   ÚIOErrorr<   r=   r‚   rl   r[   r   ÚTimedr‡   )rm   rU   rd   r†   rc   Úmibsizer!   r!   r"   Úsetup_swapfile  s,   
þ
ÿ

ÿýr�   c              
   C   sZ  t | tƒst d¡ dS |  dd¡}|  dd¡}|  dd¡}|r"|s)t d¡ dS tj |¡rstj d	¡s=t d
|¡ |S z$t	 
d	¡ ¡ D ]}| |d ¡rYt d|¡ |  W S qEt d|¡ W n tyr   t d|¡ | Y S w z t |tƒr‚|dkr‚t	 |¡}t |tƒrŒt	 |¡}t|||d�W S  ty¬ } zt d|¡ W Y d}~dS d}~ww )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.imgrU   r   rd   zno need to setup swapz/proc/swapsz:swap file %s exists, but no /proc/swaps exists, being safeú zswap file %s already in usez+swap file %s exists, but not in /proc/swapsz.swap file %s exists. Error reading /proc/swapsrˆ   )rm   rU   rd   zfailed to setup swap: %s)ra   Údictr<   Úwarningr?   r=   r)   r*   r+   r	   Úload_text_fileÚ
splitlinesr   Ú	Exceptionr(   Úhuman2bytesr�   )Úswapcfgrm   rU   rd   Úlineru   r!   r!   r"   Úhandle_swapcfg/  sP   


þ
þÿü


€ýr˜   c                  C   sl   g } i }g }t j t¡r1t t¡ ¡ D ]}t|v r| |¡ q| 	¡ }|r0|||d < |  |¡ q| ||fS )as  Parse /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	   r’   r“   ÚMNT_COMMENTÚappendr4   )Úfstab_linesrI   Úfstab_removedr—   Útoksr!   r!   r"   Úparse_fstab_  s   


€
rŸ   ÚmountsÚdevice_aliasesÚdefault_fieldsÚcloudc                 C   sÀ   g }| D ]Y}t |tƒst d|¡ qt|d ƒ}t||j|d�}t|||ƒr0|g|dd…  }	n|}	t|	ƒD ]\}
}|du rE||
 |	|
< q6t|	|
 ƒ|	|
< q6|	|t	|	ƒd… 7 }	| 
|	¡ q|S )a  Sanitize 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   ©rC   r;   N)ra   Úlistr<   r‘   r(   rF   Údevice_name_to_devicerK   Ú	enumerateÚlenr›   )r    rI   r¡   r¢   r£   Úupdated_linesr—   ÚstartÚsanitized_devnameÚupdated_lineÚindexÚtokenr!   r!   r"   Úsanitize_mounts_configurationy  s&   
ÿr¯   c                 C   sl   g }g }| ddd… D ]#}|d du s|d |v r)t  d|d ¡ | |d ¡ q| |¡ q|ddd… 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.
    Nr   r;   r   z$Skipping nonexistent device named %s)r<   r=   r›   )r    ÚactlistÚdev_denylistr—   r!   r!   r"   Úremove_nonexistent_devices§  s   r²   Údefault_mount_optionsc           	         s’   t  | ¡}ddd|ddgg d¢fD ]5‰ ˆ d }t||j|d�}t|||ƒs&qtt|ƒˆ d< t‡ fd	d
„| D ƒƒ}|rAt 	d|¡ q| 
ˆ ¡ q|S )zAdd default mounts to the user provided mount configuration.

    Add them only if no other entry has the same device name
    r:   z/mntrˆ   r|   Ú2)r   Únoner   Úswr|   r|   r   r¤   c                 3   s    � | ]}|d  ˆ d  kV  qdS )r   Nr!   )Ú.0Úcfgm©Údefault_mountr!   r"   Ú	<genexpr>Ô  s   € 
ÿz,add_default_mounts_to_cfg.<locals>.<genexpr>z-Not including %s, already previously included)ÚcopyÚdeepcopyrF   r¦   rK   r   r(   Úanyr<   r=   r›   )	r    r³   rI   r¡   r£   Ú
new_mountsrª   rH   Údefault_already_existsr!   r¹   r"   Úadd_default_mounts_to_cfgº  s&   
þÿÿrÁ   r°   c                 C   s   dd„ | D ƒS )z=Add "comment=cloudconfig" to the mount options of each entry.c                 S   s8   g | ]}|d d… |d › dt › �g |dd …  ‘qS )Né   ú,rR   )rš   ©r·   Úentryr!   r!   r"   Ú
<listcomp>à  s    *ÿÿzadd_comment.<locals>.<listcomp>r!   ©r°   r!   r!   r"   Úadd_commentÞ  s   þrÈ   c                 C   s(   t dd„ | D ƒƒrt ddg¡ dS dS )z1Call 'swapon -a' if any entry has a swap fs type.c                 s   s   � | ]	}|d  dkV  qdS )rM   r   Nr!   rÄ   r!   r!   r"   r»   è  s   € z*activate_swap_if_needed.<locals>.<genexpr>Úswaponú-aN)r¾   r   rÇ   r!   r!   r"   Úactivate_swap_if_neededæ  s   ÿrË   Úuses_systemdÚchanges_madeÚdirsc                 C   sf   d}|rd}ndd„ t  ¡  ¡ D ƒ}tt|ƒ |¡ƒ}|r/t ddg¡ | r1t ddg¡ d	S d	S 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.
    FTc                 S   s   h | ]
}d |v r|d  ’qS )Ú
mountpointr!   )r·   Úvalr!   r!   r"   Ú	<setcomp>ø  s
    þz"mount_if_needed.<locals>.<setcomp>ÚmountrÊ   Ú	systemctlzdaemon-reloadN)r	   r    ÚvaluesÚboolÚsetÚ
differencer   )rÌ   rÍ   rÎ   Údo_mountÚmount_pointsr!   r!   r"   Úmount_if_neededì  s   
þýrÚ   r   ÚcfgÚargsc              	      s¾  |j  ¡ }|r	dnd}ddd|ddg}| d|¡}| dg ¡}t d	|¡ tƒ \}	}
}| d
i ¡}t||
|||ƒ}t|||
||ƒ}t|ƒ}t	|ƒ}t
| di ¡ƒ}|r^| |dddddg¡ |sgt d¡ dS dd„ |D ƒ}dd„ |D ƒ}|D ]}zt |¡ W qw ty�   t td|¡ Y qww dd„ |D ƒ‰ dd„ |D ƒ‰‡ fdd„ˆD ƒ‡fdd„ˆ D ƒ }|	 |¡ dd |	¡ }t t|¡ |rÌt d|¡ nt d¡ t|ƒ t|t|ƒ|ƒ dS )z Handle the mounts configuration.z:defaults,nofail,x-systemd.after=cloud-init.service,_netdevzdefaults,nobootwaitNrˆ   r|   r´   Úmount_default_fieldsr    zmounts configuration is %sr¡   r   rµ   r¶   z No modifications to fstab neededc                 S   s   g | ]}d   |¡‘qS )ú	)r5   rÄ   r!   r!   r"   rÆ   /  s    zhandle.<locals>.<listcomp>c                 S   s"   g | ]}|d    d¡r|d  ‘qS )r;   r2   )r   )r·   Údr!   r!   r"   rÆ   1  s   " z Failed to make '%s' config-mountc                 S   ó   g | ]}|  d d¡‘qS ©rÞ   r�   ©Úreplace©r·   Únr!   r!   r"   rÆ   9  ó    c                 S   rà   rá   râ   rä   r!   r!   r"   rÆ   :  ræ   c                    ó   g | ]}|ˆ vrd |› �‘qS )z- r!   )r·   Údrop)Úsaddsr!   r"   rÆ   <  s    c                    rç   )z+ r!   )r·   Úadd)Úsdropsr!   r"   rÆ   <  s    z%s
Ú
zChanges to fstab: %szNo changes to /etc/fstab made.)ÚdistrorÌ   r?   r<   r=   rŸ   r¯   rÁ   r²   rÈ   r˜   r›   r	   r‚   r”   ÚlogexcÚextendr5   Ú
write_filer™   rË   rÚ   rÕ   )r   rÛ   r£   rÜ   rÌ   r³   Úhardcoded_defaultsr¢   r    rœ   rI   r�   r¡   Úupdated_cfgÚswapfileÚ	cfg_linesrÎ   rß   ÚsopsÚcontentsr!   )ré   rë   r"   Úhandle  s`   
ÿýÿ
ÿ
ÿ
ÿÿ

r÷   )N)NNN)NN)8Ú__doc__r¼   Úloggingr^   r)   r$   Útypingr   r   r   r   r   Ú	cloudinitr   r   r	   Úcloudinit.cloudr
   Úcloudinit.configr   Úcloudinit.config.schemar   Úcloudinit.settingsr   r   Ú__annotations__r@   r&   r™   rš   rb   r\   Ú	getLoggerÚ__name__r<   r#   r'   r1   r9   rF   r(   rÕ   rK   rl   r‡   r�   r˜   rŸ   r¯   r²   rÁ   rÈ   rË   rÚ   r¥   r÷   r!   r!   r!   r"   Ú<module>   s¤   ü



1ÿÿ
ÿ
þ
9
>(0ÿ
þ
ý
üû

ú".
ÿþ
ý
üû

ú"$ÿÿÿ
þ"