o
    wÚ7eñN  ã                
   @   sŠ  U d Z ddlZddlZddlZddlZddlmZ ddl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mZ dd	lmZ d
ZedƒZdgZdddeeeedƒgeg dœZeed< eeƒZ dZe e¡ZdZe e¡Ze de ¡Z dZ!dZ"dZ#dZ$e %e&¡Z'dd„ Z(dd„ Z)dd„ Z*d5d d!„Z+d5d"d#„Z,d6d$d%„Z-d&e.d'e.d(dfd)d*„Z/d7d+d,„Z0d-d.„ Z1d/e.d0ed1ed2e2d(df
d3d4„Z3dS )8z-Mounts: Configure mount points and swap filesé    N)Ú
whitespace)Údedent)ÚsubpÚ
type_utilsÚutil)ÚCloud)ÚConfig)Ú
MetaSchemaÚget_meta_doc)ÚPER_INSTANCEaÐ	  This module can add or remove mountpoints from ``/etc/fstab`` as well as
configure swap. The ``mounts`` config key takes a list of fstab entries to add.
Each entry is specified as a list of ``[ fs_spec, fs_file, fs_vfstype,
fs_mntops, fs-freq, fs_passno ]``. For more information on these options,
consult the manual for ``/etc/fstab``. When specifying the ``fs_spec``, if the
device name starts with one of ``xvd``, ``sd``, ``hd``, or ``vd``, the leading
``/dev`` may be omitted.

Any mounts that do not appear to either an attached block device or network
resource will be skipped with a log like "Ignoring nonexistent mount ...".

Cloud-init will attempt to add the following mount directives if available and
unconfigured in `/etc/fstab`::

    mounts:
        - ["ephemeral0", "/mnt", "auto","defaults,nofail,x-systemd.requires=cloud-init.service", "0", "2"]
        - ["swap", "none", "swap", "sw", "0", "0"]

In order to remove a previously listed mount, an entry can be added to
the `mounts` list containing ``fs_spec`` for the device to be removed but no
mountpoint (i.e. ``[ swap ]`` or ``[ swap, null ]``).

The ``mount_default_fields`` config key allows default values to be specified
for the fields in a ``mounts`` entry that are not specified, aside from the
``fs_spec`` and the ``fs_file`` fields. If specified, this must be a list
containing 6 values. It defaults to::

    mount_default_fields: [none, none, "auto","defaults,nofail,x-systemd.requires=cloud-init.service", "0", "2"]

Non-systemd init systems will vary in ``mount_default_fields``.

Swap files can be configured by setting the path to the swap file to create
with ``filename``, the size of the swap file with ``size`` maximum size of
the swap file if using an ``size: auto`` with ``maxsize``. By default no
swap file is created.

.. note::
    If multiple mounts are specified where a subsequent mount's mountpoint is
    inside of a previously declared mount's mountpoint (i.e. the 1st mount has
    a mountpoint of ``/abc`` and the 2nd mount has a mountpoint of
    ``/abc/def``) then this will not work as expected - ``cc_mounts`` first
    creates the directories for all the mountpoints **before** it starts to
    perform any mounts and so the sub-mountpoint directory will not be created
    correctly inside the parent mountpoint.

    For systems using util-linux's ``mount`` program this issue can be
    worked around by specifying ``X-mount.mkdir`` as part of a ``fs_mntops``
    value for the subsequent mount entry.
a<      # Mount ephemeral0 with "noexec" flag, /dev/sdc with mount_default_fields,
    # and /dev/xvdh with custom fs_passno "0" to avoid fsck on the mount.
    # Also provide an automatically sized swap with a max size of 10485760
    # bytes.
    mounts:
        - [ /dev/ephemeral0, /mnt, auto, "defaults,noexec" ]
        - [ sdc, /opt/data ]
        - [ xvdh, /opt/data, auto, "defaults,nofail", "0", "0" ]
    mount_default_fields: [None, None, auto, "defaults,nofail", "0", "2"]
    swap:
        filename: /my/swapfile
        size: auto
        maxsize: 10485760
    ÚallÚ	cc_mountsÚMountsz%Configure mount points and swap filesz®        # Create a 2 GB swap file at /swapfile using human-readable values
        swap:
            filename: /swapfile
            size: 2G
            maxsize: 2G
        )ÚidÚnameÚtitleÚdescriptionÚdistrosÚexamplesÚ	frequencyÚactivate_by_schema_keysÚmetaz&^([x]{0,1}[shv]d[a-z][0-9]*|sr[0-9]+)$z^.+:.*z[%s]+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)r   Úenumname© r#   ú</usr/lib/python3/dist-packages/cloudinit/config/cc_mounts.pyÚis_meta_device_nameˆ   s   €r%   c                 C   s   t  | ¡rdS dS )NTF)ÚNETWORK_NAME_REÚmatch)r   r#   r#   r$   Úis_network_device”   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   ýÿr2   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_device¨   s   ÿr:   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 	| ¡r]d|f }d }|d u rit
|d	ƒ}nt
||ƒ}|d u rtd 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 %sr3   z/dev/%szMapped metadata name %s to %sé   )ÚLOGÚdebugr(   r   Úexpand_dotted_devnameÚgetr%   r    ÚDEVICE_NAME_REr'   r2   r:   )Ú	startnameÚtransformerÚaliasesÚdevnamer-   r.   Úorigr7   r#   r#   r$   Úsanitize_devname²   sF   




ÿ
rG   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ÚmemrK   é   gÍÌÌÌÌÌì?Úmaxé   Úsizez%s MBzCsuggest %s swap for %s memory with '%s' disk given max=%s [max=%s]'rM   rL   )r   Úread_meminfor*   ÚstatvfsÚf_frsizeÚf_bfreeÚminÚintÚGBÚroundÚmathÚsqrtÚitemsÚ
isinstanceÚMBr=   r>   )ÚmemsizeÚmaxsizeÚfsysÚsugg_maxÚinforS   rK   ÚminsizerQ   ÚpinfoÚkÚvr#   r#   r$   Úsuggested_swapsizeã   sN   
€



úrh   ÚfnamerQ   Úreturnc                    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}z
tj|d
d W d S  tjyJ } 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=%sT)Úcapture)r=   r>   r   ÚProcessExecutionErrorrc   r   Údel_file)ri   rQ   ÚmethodÚcmdÚe©ÚerrmsgÚfstyper#   r$   Úcreate_swap!  s.   üû
€ýz$create_swapfile.<locals>.create_swapr<   ÚbtrfsÚtruncatez-sÚ0Úchattrz+CÚxfs)rN   é   rl   rk   z4fallocate swap creation failed, will attempt with ddi€  ÚmkswapN)r*   r+   Údirnamer   Ú
ensure_dirÚget_mount_infor   Úkernel_versionrn   r=   rc   r,   Úchmodro   )ri   rQ   rv   Úswap_dirr#   rs   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jtj	dt| |gd	 | S )
z
    fname: full path string of filename to setup
    size: the size to create. set to "auto" for recommended
    maxsize: the maximum size
    ÚautorH   z)Not creating swap: failed to read meminfoN)ra   r`   r_   r   z'Not creating swap: suggested size was 0zSetting up swap file)ÚmsgÚfuncÚargs)r*   r+   r~   r)   Úlowerr   rR   ÚIOErrorr=   r>   r   rh   rW   Úlog_timer„   )ri   rQ   r`   rƒ   r_   Úmibsizer#   r#   r$   Úsetup_swapfileV  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.imgrQ   r   r`   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…   )ri   rQ   r`   zfailed to setup swap: %s)r]   Údictr=   Úwarningr@   r>   r*   r+   r,   r   Ú	load_fileÚ
splitlinesr    Ú	Exceptionr)   Úhuman2bytesr   )Úswapcfgri   rQ   r`   Úlinerr   r#   r#   r$   Úhandle_swapcfgx  sP   


þ
þÿü


€ýr˜   r   ÚcfgÚcloudrˆ   c           $   	      sü  d}|j  ¡ }|rd}d d d|ddg}| d|¡}ddd|d	 ddgg d
¢g}g }d|v r1|d }t d|¡ g }	i }
g }tj t¡rst	 
t¡ ¡ D ](}t|v rV| |¡ qJzt |¡}W n	 tyf   Y nw ||
|d < |	 |¡ qJ| di ¡}tt|ƒƒD ]r}t|| tƒs—t d|d t || ¡¡ qt|| d ƒ}t||j|d}||kr²t d||¡ |d u r½t d|¡ q||
v rËt d||
| ¡ q||| d< tt|| ƒƒD ]}|| | d u räqÙt|| | ƒ|| |< qÙqtt|ƒƒD ]U}tt|ƒƒD ](}t|| ƒ|kr||  || ¡ q || | d u r'|| || |< q || d d u rMt|ƒD ]}|| d || d krKd || d< q6qø|D ]a}|d }t||j|d}||krjt d||¡ |d u rwt d|¡ qP||
v r‡t d||
| ¡ qP||d< d}|D ]}|d |d kržd} nq|r«t d|¡ qP| |¡ qPg }|D ]}|d d u rÉt d|d ¡ q¶| |¡ q¶t| di ¡ƒ}|ræ| |dddddg¡ t|ƒdkrôt d¡ d S g }d}d}g }|D ]-}d|d	 tf |d	< |d  dkrd}|d  d!¡r"| |d ¡ | d" |¡¡ qþd#d$„ t	 ¡   ¡ D ƒ}|D ]&}zt	 !|¡ W n tyS   t	 "td%|¡ Y nw |s^||vr^d}q9d&d$„ |D ƒ‰ d'd$„ |D ƒ‰‡ fd(d$„ˆD ƒ‡fd)d$„ˆ D ƒ }|	 #|¡ d*d+ |	¡ } t	 $t| ¡ g }!|rž|! d,d-g¡ t|ƒdkr«t d.¡ nt d/|¡ d}|rÇ|! d0d-g¡ |rÇ|! d1d2g¡ d3}"|!D ]0}#d4d5 |#¡ }"zt% %|#¡ t |"d6¡ W qË t%j&yû   t |"d7¡ t	 "t|"d7¡ Y qËw d S )8Nzdefaults,nobootwaitz=defaults,nofail,x-systemd.requires=cloud-init.service,_netdevr…   ry   Ú2Úmount_default_fieldsr;   z/mnté   )r   Únoner   Úswry   ry   Úmountszmounts configuration is %sr   Údevice_aliasesz,Mount option %s not a list, got a %s insteadr<   )rD   zchanged %s => %sz#Ignoring nonexistent named mount %sz&Device %s already defined in fstab: %szchanged default device %s => %sz+Ignoring nonexistent default named mount %sFTz-Not including %s, already previously includedz$Skipping nonexistent device named %sr   rž   rŸ   z No modifications to fstab neededz%s,%srI   r3   ú	c                 S   s    g | ]\}}d |v r|d  ‘qS )Ú
mountpointr#   )Ú.0rf   rg   r#   r#   r$   Ú
<listcomp>I  s    zhandle.<locals>.<listcomp>z Failed to make '%s' config-mountc                 S   ó   g | ]}t  d |¡‘qS ©r   ©ÚWSÚsub©r¤   Únr#   r#   r$   r¥   W  ó    c                 S   r¦   r§   r¨   r«   r#   r#   r$   r¥   X  r­   c                    ó   g | ]
}|ˆ vrd | ‘qS )z- r#   )r¤   Údrop)Úsaddsr#   r$   r¥   Z  s    c                    r®   )z+ r#   )r¤   Úadd)Úsdropsr#   r$   r¥   Z  s    z%s
Ú
Úswaponz-azNo changes to /etc/fstab made.zChanges to fstab: %sÚmountÚ	systemctlzdaemon-reloadz#Activating swap and mounts with: %szActivate mounts: %s:r   ÚPASSÚFAIL)'ÚdistroÚuses_systemdr@   r=   r>   r*   r+   r,   Ú
FSTAB_PATHr   r’   r“   ÚMNT_COMMENTÚappendr©   r5   r”   ÚrangeÚlenr]   Úlistr‘   r   Úobj_namer)   rG   Údevice_name_to_devicerc   r˜   r    r6   r    r\   r   ÚlogexcÚextendÚ
write_filer   rn   )$r   r™   rš   rˆ   Údef_mnt_optsrº   ÚdefvalsÚdefmntsÚcfgmntÚfstab_linesÚ
fstab_devsÚfstab_removedr—   Útoksr¡   ÚiÚstartÚ	sanitizedÚjÚdefmntÚ
cfgmnt_hasÚcfgmÚactlistÚxÚswapretÚcc_linesÚneedswapÚneed_mount_allÚdirsÚmount_pointsÚdÚsopsÚcontentsÚactivate_cmdsÚfmtrq   r#   )r°   r²   r$   Úhandle¨  sH  
ÿþ
ÿýÿýü€€ÿ


ýþ

ÿÿ€ÿ

þûrâ   )N)NNN)NN)4Ú__doc__ÚloggingrZ   r*   ÚreÚstringr   Útextwrapr   Ú	cloudinitr   r   r   Úcloudinit.cloudr   Úcloudinit.configr   Úcloudinit.config.schemar	   r
   Úcloudinit.settingsr   ÚMODULE_DESCRIPTIONÚexampler   r   Ú__annotations__ÚDEVICE_NAME_FILTERÚcompilerA   ÚNETWORK_NAME_FILTERr&   r©   r»   r¼   r^   rX   Ú	getLoggerÚ__name__r=   r%   r(   r2   r:   rG   rh   r)   r„   r   r˜   rÀ   râ   r#   r#   r#   r$   Ú<module>   sf   5ÿÿþí






19
:""0