
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
\meN              	   @   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||}|sd S |jdsd|f }t jd|| ntj	| rd|f }d }|d krt
|d	}nt
||}|d krd 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|rtj|}|j|j }||d< |d kr|tt|d |}q||d krt|d }n|d kr|}||d< | dt k r| }n,| d	t k rd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rtj dk r|| |d n>y|| |d W n, tjk
r   t	j
d || |d Y nX t jj| rt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 }|st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|rtjjd	sztjd
| |S yFx4t	j
d	j D ]"}|j|d rtjd| |S qW 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rxdt	j
tj D ]R}t|kr|j| qytj|}W n tk
r   Y nX ||
|d < |	j| qW |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rtjd| qn ||
krtjd||
|  q||| d< xJtt|| D ]6}|| | d krqnt|| | || |< qW qW xt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rd || d< qW q&W x|D ]}|d }t||j|d}||krtjd|| |d kr2tjd| qn ||
krRtjd||
|  q||d< d}x&|D ]}|d |d krdd}P qdW |rtjd| q|j| qW g }x8|D ]0}|d d krtjd|d  n
|j| qW 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rd}qW 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rt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 qW 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