U
    ¯AdL  ã                	   @   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	 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+d1d!d"„Z,d2d#d$„Z-d3d%d&„Z.e/e/dd'œd(d)„Z0d4d*d+„Z1d,d-„ Z2e/eeee3dd.œd/d0„Z4dS )5z-Mounts: Configure mount points and swap filesé    N)ÚLogger)Ú
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 options to be specified
for the values in a ``mounts`` entry that are not specified, aside from the
``fs_spec`` and the ``fs_file``. 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.
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
    ÚallZ	cc_mountsZ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ÚtitleZdescriptionÚdistrosZexamplesZ	frequencyZ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krdS dD ]"}|   |¡r|  d¡dkr dS qdS )N)ZamiÚrootÚswapT)Ú	ephemeralZebsú:éÿÿÿÿF)Ú
startswithÚfind)r   Z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_numberZpotential_suffixesÚsuffixZpotential_partition_devicer   r   r   Ú_get_nth_partition_for_device   s    ý
r(   c                 C   sX   t j | ¡ d¡d }t j d|¡}|d k	rLt j |t j |¡ d¡d ¡}t j |¡S )Nú/r   z/sys/block/)r"   r#   ÚrealpathÚsplitÚjoinr$   )r%   Úpartition_pathZdevice_nameZsys_pathr   r   r   Ú_is_block_deviceœ   s     ÿr.   c           	      C   s
  |  d| ¡ | }|dkr&d}|  d¡ t| ƒr2| S t |¡\}}|}|rj| ||¡}||krj|  d||¡ t|ƒr¦||ƒ}|s‚d S | d¡s–d|f }|  d||¡ nt | ¡rºd|f }d }|d krÒt	|d	ƒ}nt	||ƒ}|d krèd S t
||ƒr|d k	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 %sr)   z/dev/%szMapped metadata name %s to %sé   )Údebugr    r   Zexpand_dotted_devnameÚgetr   r   ÚDEVICE_NAME_REr   r(   r.   )	Z	startnameZtransformerÚlogÚaliasesZdevnamer%   r&   Zorigr-   r   r   r   Úsanitize_devname¦   sH    




 ÿ
r6   c              	   C   sd  | d krt  ¡ d } | d }d|| dœ}|d kr>|d kr>|}nd|r–t |¡}|j|j }||d< |d kr|tt|d ƒ|ƒ}q¢||d kr¢t|d ƒ}n|d kr¢|}||d< | dt k r¼| }n,| d	t k rÒdt }nt	t
 | t ¡ƒt }t||ƒ}||d
< i }	| ¡ D ]0\}
}t|tƒr,d|t  |	|
< n||	|
< qt d|	d
 |	d |	d |	d |	d ¡ |S )NÚtotalé   Zna)ÚavailÚmax_inÚmemr9   é   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ÚmathZsqrtÚitemsÚ
isinstanceÚMBÚLOGr1   )ÚmemsizeÚmaxsizeÚfsysZsugg_maxÚinforA   r9   Zminsizer?   ZpinfoÚkÚvr   r   r   Úsuggested_swapsize×   sL    


úrS   )Úfnamer?   Úreturnc                    sð   d‰ ‡ ‡fdd„}t j | ¡}t |¡ t |¡d ‰ˆdkrJt ¡ dk sRˆdkr`|| |dƒ n>z|| |d	ƒ W n, tjk
rœ   t	 
d
¡ || |dƒ Y nX t j | ¡r¶t | d¡ zt d| g¡ W n" tjk
rê   t | ¡ ‚ Y nX dS )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rHddd|  dd	| g}ztj|d
d W nB tjk
rœ } z"t  ˆ | |||¡ t | ¡ ‚ W 5 d }~X Y nX d S )Nz3Creating swapfile in '%s' on fstype '%s' using '%s'Ú	fallocatez-lz%sMÚddzif=/dev/zerozof=%szbs=1Mzcount=%sT)Zcapture)rL   r1   r   ÚProcessExecutionErrorrP   r   Údel_file)rT   r?   ÚmethodÚcmdÚe©ÚerrmsgZfstyper   r   Úcreate_swap  s*    üû
z$create_swapfile.<locals>.create_swapr0   Zxfs)r<   é   ZbtrfsrW   rV   z4fallocate swap creation failed, will attempt with ddi€  ZmkswapN)r"   r#   Údirnamer   Ú
ensure_dirZget_mount_infoZkernel_versionr   rX   rL   rP   r$   ÚchmodrY   )rT   r?   r_   Úswap_dirr   r]   r   Úcreate_swapfile  s0    
ÿ
ÿþ

re   c                 C   s¤   t j | ¡}t|ƒ ¡ dkrfzt ¡ d }W n  tk
rL   t 	d¡ Y dS X t 
|¡ t|||d}tt|d ƒƒ}|sˆt 	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
    Úautor7   z)Not creating swap: failed to read meminfoN)rO   rN   rM   r   z'Not creating swap: suggested size was 0zSetting up swap file)ÚmsgÚfuncÚargs)r"   r#   ra   r!   Úlowerr   r@   ÚIOErrorrL   r1   rb   rS   rE   Zlog_timere   )rT   r?   rN   rd   rM   Zmibsizer   r   r   Úsetup_swapfileH  s0    

  ÿ
ürl   c              
   C   sd  t | tƒst d¡ dS |  dd¡}|  dd¡}|  dd¡}|rD|sRt d¡ dS tj |¡rètj d	¡szt d
|¡ |S zHt	 
d	¡ ¡ D ](}| |d ¡rŠt d|¡ |  W S qŠt d|¡ W n$ tk
ræ   t d|¡ | Y S X zFt |tƒr
|dkr
t	 |¡}t |tƒr t	 |¡}t|||dW S  tk
r^ } zt d|¡ W 5 d}~X Y nX dS )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.imgr?   r   rN   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/swapsrf   )rT   r?   rN   zfailed to setup swap: %s)rJ   ÚdictrL   Úwarningr2   r1   r"   r#   r$   r   Ú	load_fileÚ
splitlinesr   Ú	Exceptionr!   Zhuman2bytesrl   )ZswapcfgrT   r?   rN   Úliner\   r   r   r   Úhandle_swapcfgj  sJ    


þ ÿ


ru   )r   ÚcfgÚcloudr4   ri   rU   c           %   	      s4  d}|j  ¡ }|rd}d d d|ddg}| d|¡}ddd|d	 ddgd
dd
dddgg}g }	d|krj|d }	t d|	¡ g }
i }g }tj t¡rðt	 
t¡ ¡ D ]R}t|kr´| |¡ qœzt |¡}W n tk
rÖ   Y nX |||d < |
 |¡ qœ| di ¡}tt|	ƒƒD ]}t|	| tƒs>| d|d t |	| ¡¡ qt|	| d ƒ}t||j||d}||kr|| d||f ¡ |d kr˜| d|¡ qn ||kr¸| d||| ¡ q||	| d< tt|	| ƒƒD ]6}|	| | d krðqÔnt|	| | ƒ|	| |< qÔqtt|	ƒƒD ]ª}tt|ƒƒD ]N}t|	| ƒ|krV|	|  || ¡ n"|	| | d kr,|| |	| |< q,|	| d d krt|ƒD ],}|	| d |	| d kr–d |	| d< q–q|D ]Ì}|d }t||j||d}||kr| d||f ¡ |d kr"| d|¡ qÌn ||krB| d||| ¡ qÌ||d< d}|	D ]"}|d |d krRd} qvqR|rŒ| d|¡ qÌ|	 |¡ qÌg }|	D ]0}|d d krÆ| d|d ¡ n
| |¡ q¢t| d
i ¡ƒ}|r | |dd
dddg¡ t|ƒdkr| d¡ d S g }d}d}g }|D ]Z}d|d	 tf |d	< |d d
krZd}|d  d ¡rx| |d ¡ | d! |¡¡ q0d"d#„ t	 ¡   ¡ D ƒ}|D ]N}zt	 !|¡ W n$ tk
rÜ   t	 "|d$|¡ Y nX |s¦||kr¦d}q¦d%d#„ |D ƒ‰ d&d#„ |D ƒ‰‡ fd'd#„ˆD ƒ‡fd(d#„ˆ D ƒ } |
 #|¡ d)d* |
¡ }!t	 $t|!¡ g }"|rr|" d+d,g¡ t| ƒdkrŒ| d-¡ n| d.| ¡ d}|rÄ|" d/d,g¡ |rÄ|" d0d1g¡ d2}#|"D ]b}$d3d4 |$¡ }#zt% %|$¡ | |#d5¡ W n2 t%j&k
r*   | |#d6¡ t	 "||#d6¡ Y nX qÌd S )7Nzdefaults,nobootwaitz=defaults,nofail,x-systemd.requires=cloud-init.service,_netdevrf   Ú0Ú2Zmount_default_fieldsr/   z/mnté   r   ZnoneÚswÚmountszmounts configuration is %sr   Údevice_aliasesz,Mount option %s not a list, got a %s insteadr0   )r5   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 %sz No modifications to fstab neededz%s,%sr8   r)   ú	c                 S   s    g | ]\}}d |kr|d  ‘qS )Z
mountpointr   )Ú.0rQ   rR   r   r   r   Ú
<listcomp>=  s     zhandle.<locals>.<listcomp>z Failed to make '%s' config-mountc                 S   s   g | ]}t  d |¡‘qS ©rn   ©ÚWSÚsub©r   Únr   r   r   r€   K  s     c                 S   s   g | ]}t  d |¡‘qS r   r‚   r…   r   r   r   r€   L  s     c                    s   g | ]}|ˆ krd | ‘qS )z- r   )r   Zdrop)Úsaddsr   r   r€   N  s      c                    s   g | ]}|ˆ krd | ‘qS )z+ r   )r   Úadd)Úsdropsr   r   r€   N  s     z%s
Ú
Zswaponz-azNo changes to /etc/fstab made.zChanges to fstab: %sZmountZ	systemctlzdaemon-reloadz#Activating swap and mounts with: %szActivate mounts: %s:rn   ZPASSZFAIL)'ZdistroÚuses_systemdr2   rL   r1   r"   r#   r$   Ú
FSTAB_PATHr   rq   rr   ÚMNT_COMMENTÚappendrƒ   r+   rs   ÚrangeÚlenrJ   Úlistrp   r   Zobj_namer!   r6   Zdevice_name_to_devicerP   ru   r   r,   r|   rI   rb   ZlogexcÚextendZ
write_filer   rX   )%r   rv   rw   r4   ri   Zdef_mnt_optsr‹   ZdefvalsZdefmntsZcfgmntZfstab_linesZ
fstab_devsZfstab_removedrt   Ztoksr}   ÚiÚstartZ	sanitizedÚjZdefmntZ
cfgmnt_hasZcfgmZactlistÚxZswapretZcc_linesZneedswapZneed_mount_allÚdirsZmount_pointsÚdZsopsÚcontentsZactivate_cmdsZfmtr[   r   )r‡   r‰   r   Úhandleš  sB   
ÿþ
ý   ÿ


ý    ÿ


ý


ÿÿ

rš   )N)N)NNN)NN)5Ú__doc__ZloggingrH   r"   Úrer   Ústringr   Útextwrapr   Z	cloudinitr   r   r   Zcloudinit.cloudr   Zcloudinit.configr	   Zcloudinit.config.schemar
   r   Zcloudinit.settingsr   ZMODULE_DESCRIPTIONZexampler   r   Ú__annotations__ZDEVICE_NAME_FILTERÚcompiler3   ZNETWORK_NAME_FILTERr   rƒ   rŒ   r   rK   rF   Z	getLoggerÚ__name__rL   r   r    r(   r.   r6   rS   r!   re   rl   ru   r‘   rš   r   r   r   r   Ú<module>	   sr   (ÿÿþí





1
98
"1    þ