
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
\¼meÚN  ã            	   @   sz  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eƒZ dZejeƒZdZejeƒZejde ƒZdZ dZ!d0Z"d1Z#ej$e%ƒZ&dd„ Z'dd„ Z(dd„ Z)d2d d!„Z*d3d"d#„Z+d4d$d%„Z,e-e-dd&œd'd(„Z.d5d)d*„Z/d+d,„ Z0e-eee1dd-œd.d/„Z2dS )6z-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
    Ú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ÚtitleÚdescriptionÚdistrosZexamplesZ	frequencyZactivate_by_schema_keysz&^([x]{0,1}[shv]d[a-z][0-9]*|sr[0-9]+)$z^.+:.*z[%s]+z
/etc/fstabzcomment=cloudconfigé   é   é   c             C   s:   | d
krdS x(dD ] }| j |ƒr| jdƒdkrdS qW d	S )NÚamiÚrootÚswapTÚ	ephemeralÚebsú:é   F)r   r   r   )r   r   éÿÿÿÿ)Ú
startswithÚfind)r   Zenumname© r   ú/usr/lib/python3.6/cc_mounts.pyÚis_meta_device_nameˆ   s    
r!   c             C   s   t j| ƒ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}x(|D ] }d| |f }tjj|ƒr |S q W 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j| ƒjdƒd }t jjd|ƒ}|d k	rLt jj|t jj|ƒjdƒd ƒ}t jj|ƒS )Nú/r   z/sys/block/r   r   )r&   r'   ÚrealpathÚsplitÚjoinr(   )r)   Úpartition_pathZdevice_nameZsys_pathr   r   r    Ú_is_block_device¨   s    r2   c             C   s
  t jd| ƒ | }|dkr&d}t jdƒ t| ƒr2| S tj|ƒ\}}|}|rj|j||ƒ}||krjt jd||ƒ t|ƒr¦||ƒ}|s‚d S |jdƒs–d|f }t jd||ƒ ntj	| ƒ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 %sr   )ÚLOGÚdebugr$   r   Zexpand_dotted_devnameÚgetr!   r   ÚDEVICE_NAME_REr#   r,   r2   )Z	startnameZtransformerÚaliasesZdevnamer)   r*   Zorigr1   r   r   r    Úsanitize_devname²   sD    





r9   c             C   sh  | d krt jƒ d } | d }d|| dœ}|d kr>|d kr>|}nd|r–tj|ƒ}|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
j| t ƒƒt }t||ƒ}||d
< i }	x<|jƒ D ]0\}
}t|tƒ�r.d|t  |	|
< n||	|
< �qW tjd|	d
 |	d |	d |	d |	d ƒ |S )NÚtotalr   Zna)Ú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ÚmathZsqrtÚitemsÚ
isinstanceÚMBr4   r5   )ÚmemsizeÚmaxsizeÚfsysZsugg_maxÚinforC   r;   ZminsizerA   ZpinfoÚkÚvr   r   r    Úsuggested_swapsizeã   sJ    



rT   )ÚfnamerA   Úreturnc                s  d‰ ‡ ‡fdd„}t jj| ƒ}tj|ƒ tj|ƒd ‰ˆdkr`tjddd| gƒ tjd	d
| gƒ ˆdkr‚tjƒ dk r‚|| |dƒ n>y|| |dƒ W n, tjk
r¾   t	j
dƒ || |dƒ Y nX t jj| ƒrØtj| dƒ ytjd| gƒ W n$ tjk
�r   tj| ƒ ‚ Y nX dS )zSize is in MiB.z6Failed to create swapfile '%s' of size %sMB via %s: %sc                s¢   t jd| ˆ|ƒ |dkr*ddd| | g}n|dkrHddd|  dd	| g}ytj|d
d� W nB tjk
rœ } z$t jˆ | |||ƒ tj| ƒ ‚ W Y d d }~X 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)r4   r5   r   ÚProcessExecutionErrorrQ   r   Údel_file)rU   rA   ÚmethodÚcmdÚe)ÚerrmsgÚfstyper   r    Úcreate_swap!  s&    

z$create_swapfile.<locals>.create_swapr   ZbtrfsÚtruncatez-sÚ0Zchattrz+CZxfsr>   é   rX   rW   z4fallocate swap creation failed, will attempt with ddi€  ZmkswapN)r>   rc   )r&   r'   Údirnamer   Ú
ensure_dirZget_mount_infor   Zkernel_versionrY   r4   rQ   r(   ÚchmodrZ   )rU   rA   r`   Úswap_dirr   )r^   r_   r    Úcreate_swapfile  s,    


rh   c             C   s¢   t jj| ƒ}t|ƒjƒ dkrdytjƒ d }W n tk
rJ   tj	dƒ dS X tj
|ƒ t|||d�}tt|d ƒƒ}|s†tj	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
    Úautor:   z)Not creating swap: failed to read meminfoN)rP   rO   rN   r   r   z'Not creating swap: suggested size was 0zSetting up swap file)ÚmsgÚfuncÚargsi   )r&   r'   rd   r%   Úlowerr   rB   ÚIOErrorr4   r5   re   rT   rG   Zlog_timerh   )rU   rA   rO   rg   rN   Zmibsizer   r   r    Úsetup_swapfileV  s(    


ro   c             C   sZ  t | tƒstjdƒ dS | jddƒ}| jddƒ}| jddƒ}|oB|sRtjdƒ dS tjj|ƒrâtjjd	ƒsztjd
|ƒ |S yFx4t	j
d	ƒjƒ D ]"}|j|d ƒrŒtjd|ƒ |S qŒW tjd|ƒ W n  tk
rà   tjd|ƒ |S X yBt |tƒoô|dk�rt	j|ƒ}t |tƒ�rt	j|ƒ}t|||d�S  tk
�rT } ztjd|ƒ W Y dd}~X 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.imgrA   r   rO   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/swapsri   )rU   rA   rO   zfailed to setup swap: %s)rL   Údictr4   Úwarningr6   r5   r&   r'   r(   r   Ú	load_fileÚ
splitlinesr   Ú	Exceptionr%   Zhuman2bytesro   )ZswapcfgrU   rA   rO   Úliner]   r   r   r    Úhandle_swapcfgx  sD    




rx   )r   ÚcfgÚcloudrl   rV   c       $         sX  d}|j jƒ }|rd}d d d|ddg}|jd|ƒ}ddd|d	 ddgd
dd
dddgg}g }d|krj|d }tjd|ƒ g }	i }
g }tjjtƒrôxdt	j
tƒjƒ D ]R}t|kr¶|j|ƒ qžytj|ƒ}W n tk
rØ   Y nX ||
|d < |	j|ƒ qžW |jdi ƒ}�xtt|ƒƒD �]}t|| tƒ�sFtjd|d tj|| ƒƒ �qt|| d ƒ}t||j|d�}||k�r~tjd||ƒ |d k�rštjd|ƒ �qn ||
k�rºtjd||
| ƒ �q||| d< xJtt|| ƒƒD ]6}|| | d k�rô�qØnt|| | ƒ|| |< �qØW �qW xÂtt|ƒƒD ]²}x^tt|ƒƒD ]N}t|| ƒ|k�rb|| j|| ƒ n"|| | d k�r8|| || |< �q8W || d d k�r&x8t|ƒD ],}|| d || d k�r¦d || d< �q¦W �q&W xÎ|D ]Æ}|d }t||j|d�}||k�rtjd||ƒ |d k�r2tjd|ƒ �qân ||
k�rRtjd||
| ƒ �qâ||d< d}x&|D ]}|d |d k�rdd}P �qdW |�rœtjd|ƒ �qâ|j|ƒ �qâW g }x8|D ]0}|d d k�rÚtjd|d ƒ n
|j|ƒ �q¶W t|jd
i ƒƒ}|�r|j|dd
dddgƒ t|ƒdk�r2tjdƒ d S g }d}d}g }xb|D ]Z}d|d	 tf |d	< |d d
k�rrd}|d jd ƒ�r�|j|d ƒ |jd!j|ƒƒ �qHW d"d#„ t	jƒ j ƒ D ƒ}xX|D ]P}yt	j!|ƒ W n$ tk
�rø   t	j"td$|ƒ Y nX | �rÂ||k�rÂd}�qÂW d%d#„ |D ƒ‰ d&d#„ |D ƒ‰‡ fd'd#„ˆD ƒ‡fd(d#„ˆ D ƒ }|	j#|ƒ d)d*j|	ƒ } t	j$t| ƒ g }!|�r’|!jd+d,gƒ t|ƒdk�r¬tjd-ƒ ntjd.|ƒ d}|�rä|!jd/d,gƒ |�rä|!jd0d1gƒ d2}"xj|!D ]b}#d3d4j|#ƒ }"yt%j%|#ƒ tj|"d5ƒ W n2 t%j&k
�rL   tj|"d6ƒ t	j"t|"d6ƒ Y nX �qîW d S )7Nzdefaults,nobootwaitz=defaults,nofail,x-systemd.requires=cloud-init.service,_netdevri   rb   Ú2Zmount_default_fieldsr3   z/mnté   r   ZnoneÚswÚmountszmounts configuration is %sr   Údevice_aliasesz,Mount option %s not a list, got a %s insteadr   )r8   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,%sr   r-   ú	c             S   s    g | ]\}}d |kr|d  ‘qS )Z
mountpointr   )Ú.0rR   rS   r   r   r    ú
<listcomp>J  s    zhandle.<locals>.<listcomp>z Failed to make '%s' config-mountc             S   s   g | ]}t jd |ƒ‘qS )rq   )ÚWSÚsub)r�   Únr   r   r    r‚   W  s    c             S   s   g | ]}t jd |ƒ‘qS )rq   )rƒ   r„   )r�   r…   r   r   r    r‚   X  s    c                s   g | ]}|ˆ krd | ‘qS )z- r   )r�   Zdrop)Úsaddsr   r    r‚   Z  s    c                s   g | ]}|ˆ krd | ‘qS )z+ r   )r�   Úadd)Úsdropsr   r    r‚   [  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:rq   ZPASSZFAIL)'ZdistroÚuses_systemdr6   r4   r5   r&   r'   r(   Ú
FSTAB_PATHr   rt   ru   ÚMNT_COMMENTÚappendrƒ   r/   rv   ÚrangeÚlenrL   Úlistrs   r   Zobj_namer%   r9   Zdevice_name_to_devicerQ   rx   r   r0   r~   rK   re   ZlogexcÚextendZ
write_filer   rY   )$r   ry   rz   rl   Zdef_mnt_optsrŠ   ZdefvalsZdefmntsZcfgmntZfstab_linesZ
fstab_devsZfstab_removedrw   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¨  s"   





$













r™   i   i   @)N)N)NNN)NN)3Ú__doc__ZloggingrJ   r&   ÚreÚstringr   Útextwrapr   Z	cloudinitr   r   r   Zcloudinit.cloudr   Zcloudinit.configr   Zcloudinit.config.schemar	   r
   Zcloudinit.settingsr   ZMODULE_DESCRIPTIONZexampler   ÚmetaZDEVICE_NAME_FILTERÚcompiler7   ZNETWORK_NAME_FILTERr"   rƒ   r‹   rŒ   rM   rH   Z	getLoggerÚ__name__r4   r!   r$   r,   r2   r9   rT   r%   rh   ro   rx   r�   r™   r   r   r   r    Ú<module>	   s\   5





1
9:
"0