
"T`F                 @   s_  d  Z  d d l m 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 Z
 e j e
  Z d Z e j e  Z e j d	 e  Z d
 Z d Z e j e  Z d d   Z d d   Z d d   Z d d d  Z d d   Z d d d d d  Z e e d d d d    Z d d d d  Z d d   Z d d    Z d S)!a<  
Mounts
------
**Summary:** configure mount points and swap files

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.

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. ``[ sda1 ]`` or ``[ sda1, 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,nobootwait", "0", "2"]

On a systemd booted system that default is the mostly equivalent::

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

Note that `nobootwait` is an upstart specific boot option that somewhat
equates to the more standard `nofail`.

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.

**Internal name:** ``cc_mounts``

**Module frequency:** per instance

**Supported distros:** all

**Config keys**::

    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: <file>
        size: <"auto"/size in bytes>
        maxsize: <size in bytes>
    )
whitespaceN)
type_utils)subp)utilz&^([x]{0,1}[shv]d[a-z][0-9]*|sr[0-9]+)$z^.+:.*z[%s]+z
/etc/fstabzcomment=cloudconfigc             C   sM   |  d
 k r d Sx6 d D]. } |  j  |  r |  j d  d k r d Sq Wd	 S)NamirootswapT	ephemeralebs:   F)r   zrootr   )r	   r
   )
startswithfind)nameZenumname r   </usr/lib/python3/dist-packages/cloudinit/config/cc_mounts.pyis_meta_device_nameX   s    $r   c             C   s   t  j |   r d Sd S)NTF)NETWORK_NAME_REmatch)r   r   r   r   is_network_deviced   s    r   c             C   s^   t  |  d | f d | f g } x4 | D], } d |  | f } t j j |  r* | Sq* Wd  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_devicek   s    r   c             C   s~   t  j j |   j d  d } t  j j d |  } | d  k	 rn t  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_deviceu   s    	%r$   c             C   s:  | j  d |   |  } | d k r5 d } | j  d  t |   rE |  St j |  \ } } t |  r | } | |  } | s d  S| j d  s d | f } | j  d | |  n t j |   r d | f } d  } | d  k r t | d  } n t | |  } | d  k rd  St	 | |  r6| d  k	 r2| S| Sd  S)	Nz+Attempting to determine the real name of %sr	   
ephemeral0z2Adjusted mount option from ephemeral to ephemeral0r   z/dev/%szMapped metadata name %s to %sr   )
debugr   r   Zexpand_dotted_devnamer   r   DEVICE_NAME_REr   r   r$   )Z	startnameZtransformerlogZdevnamer   r   Zorigr#   r   r   r   sanitize_devname~   s<    	r)   c                sy  |  d  k r t  j   d }  d   d   } d d d | d |  i } | d  k re | d  k re | } n | r t j |  } | j | j } | | d <| d  k r t t | d	  |  } q | | d
 k r t | d
  } n | d  k r | } | | d <d   d d   f d     f d d   f d	   d d   f d     f d d   f d   d d   f g } d  } x] | D]U \ }	 }
 |  |	 k ryt |
 |   |  } | |  d k  r| d	   k  rd } PPqyW| d  k	 r| } | | d <d } i  } xH | j   D]: \ } } t	 | t  r7d | | | | <q| | | <qWt
 j d | d | d | d | d | d  | S)Ntotal         availZnaZmax_inZmem   g?maxr   c             S   s   |  d S)Nr+   r   )xr   r   r   <lambda>   s    z$suggested_swapsize.<locals>.<lambda>c                s   d   S)Nr+   r   )r1   )GBr   r   r2      s    c             S   s   |  S)Nr   )r1   r   r   r   r2      s       c                s   d   S)Nr/   r   )r1   )r3   r   r   r2      s    @   c             S   s   |  d S)Nr+   r   )r1   r   r   r   r2      s    r   size   z%s MBzCsuggest %s swap for %s memory with '%s' disk given max=%s [max=%s]'i   @i   )r   read_meminfor   statvfsf_frsizef_bfreeminintitems
isinstanceLOGr&   )memsizemaxsizefsysZsugg_maxinfor9   r.   Zformulasr6   topfuncZMBZpinfokvr   )r3   r   suggested_swapsize   sX    
	

 
	rI   )fnamer6   returnc                s8  d      f d d   } t  j j |   } t j |  t j |  d   d k rk t j   d k  sw  d k r | |  | d	  nI y | |  | d
  Wn2 t j k
 r t	 j
 d  | |  | d	  Yn Xt  j j |   r t j |  d  y t j d |  g  Wn% t j k
 r3t j |     Yn Xd 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 rd d d d |  d d	 | g } y t j | d
 d WnQ t j k
 r } z. t  j   |  | | |  t j |     WYd  d  } ~ Xn Xd  S)Nz3Creating swapfile in '%s' on fstype '%s' using '%s'	fallocatez-lz%sMddzif=/dev/zerozof=%szbs=1Mzcount=%sZcaptureT)r@   r&   r   ProcessExecutionErrorrD   r   del_file)rJ   r6   methodcmde)errmsgfstyper   r   create_swap   s    	z$create_swapfile.<locals>.create_swapr   Zxfsr/      ZbtrfsrM   rL   z4fallocate swap creation failed, will attempt with ddi  ZmkswapN)r/   rV   )r   r   dirnamer   
ensure_dirZget_mount_infoZkernel_versionr   rN   r@   rD   r   chmodrO   )rJ   r6   rU   swap_dirr   )rS   rT   r   create_swapfile   s(    r[   c             C   s   t  j j |   } t |  j   d k r y t j   d } Wn# t k
 rc t j	 d  d SYn Xt j
 |  t d | d | d |  } t t | d   } | s t j	 d
  d St j t j	 d d d t d |  | g |  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 meminfoNrC   rB   rA   r+   r7   z'Not creating swap: suggested size was 0msgzSetting up swap filerF   argsi   )r   r   rW   r   lowerr   r8   IOErrorr@   r&   rX   rI   r=   Zlog_timer[   )rJ   r6   rB   rZ   rA   Zmibsizer   r   r   setup_swapfile  s"    		ra   c             C   s  t  |  t  s  t j d  d S|  j d d  } |  j d d  } |  j d d  } | o_ | ss t j d  d St j j |  r/t j j d	  s t j d
 |  | Sy[ xD t	 j
 d	  j   D]- } | j | d  r t j d |  | Sq Wt j d |  Wn& t k
 r.t j d |  | SYn Xye t  | t  r\| d k r\t	 j |  } t  | t  rzt	 j |  } t d | d | d |  SWn5 t k
 r} z t j d |  WYd d } ~ Xn Xd S)zdhandle 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.imgr6   r   rB   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\   rJ   zfailed to setup swap: %s)r?   dictr@   warninggetr&   r   r   r   r   	load_file
splitlinesr   	Exceptionr   Zhuman2bytesra   )ZswapcfgrJ   r6   rB   linerR   r   r   r   handle_swapcfg;  sB    			#rk   c       $         s  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 r | d }	 t j d |	  g  }
 i  } g  } t j j t  rNx| t	 j
 t  j   D]e } t | k r| j |  q y t j |  } Wn t k
 r.Yn X| | | d <|
 j |  q WxMt t |	   D]9} t |	 | t  s| j d | d t j |	 |   qat |	 | d  } t | | j |  } | | k r| j d | | f  | d  k r| j d |  qan& | | k r5| j d | | |  qa| |	 | d <xT t t |	 |   D]< } |	 | | d  k rzqZqZt |	 | |  |	 | | <qZWqaWx t t |	   D] } xn t t |   D]Z } t |	 |  | k r|	 | j | |  q|	 | | d  k r| | |	 | | <qW|	 | d d  k rx> t |  D]0 } |	 | d |	 | d k rId  |	 | d <qIWqWx | D] } | d } t | | j |  } | | k r| j d | | f  | d  k r| j d |  qn& | | k r| j d | | |  q| | d <d } x) |	 D]! } | d | d k r/d } Pq/W| rm| j d |  q|	 j |  qWg  } xB |	 D]: } | d d  k r| j d | d  q| j |  qWt | j d
 i    } | r| j | d d
 d d d g  t |  d k r)| j d  d  Sg  } d } d } g  } xv | D]n } d | d	 t f | d	 <| d d
 k r|d } | d j d  r| j | d  | j d j |   qHWd  d!   t	 j   j    D } x` | D]X } y t	 j! |  Wn% t k
 rt	 j" | d" |  Yn X| r| | k rd } qWd# 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| j d+  n | j d, |  d } | rK|! j d- d* g  | rK|! j d. d/ g  d0 }" x} |! D]u }# d1 d2 j |#  }" y! t% j% |#  | j |" d3  WqXt% j& k
 r| j |" d4  t	 j" | |" d4  YqXXqXWd  S)5Nzdefaults,nobootwaitz5defaults,nofail,x-systemd.requires=cloud-init.servicer\   02Zmount_default_fieldsr%   z/mnt   r   ZnoneZswmountszmounts configuration is %sr   z,Mount option %s not a list, got a %s insteadr   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   ).0rG   rH   r   r   r   
<listcomp>  s   	 	zhandle.<locals>.<listcomp>z Failed to make '%s' config-mountc             S   s"   g  |  ] } t  j d  |   q S)rc   )WSsub)rq   nr   r   r   rr     s   	 c             S   s"   g  |  ] } t  j d  |   q S)rc   )rs   rt   )rq   ru   r   r   r   rr     s   	 c                s&   g  |  ] } |   k r d  |  q S)z- r   )rq   Zdrop)saddsr   r   rr     s   	 c                s&   g  |  ] } |   k r d  |  q S)z+ r   )rq   add)sdropsr   r   rr     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:rc   ZPASSZFAIL)'Zdistrouses_systemdrf   r@   r&   r   r   r   
FSTAB_PATHr   rg   rh   MNT_COMMENTappendrs   r!   ri   rangelenr?   listre   r   Zobj_namer   r)   Zdevice_name_to_devicerD   rk   r   r"   ro   r>   rX   ZlogexcextendZ
write_filer   rN   )$_nameZcfgZcloudr(   Z_argsZdef_mnt_optsrz   ZdefvalsZdefmntsZcfgmntZfstab_linesZ
fstab_devsZfstab_removedrj   ZtoksistartZ	sanitizedjZdefmntZ
cfgmnt_hasZcfgmZactlistr1   ZswapretZcc_linesZneedswapZneed_mount_alldirsZmount_pointsdZsopscontentsZactivate_cmdsZfmtrQ   r   )rv   rx   r   handleh  s   
		$
	
	
r   ) __doc__stringr   Zloggingr   reZ	cloudinitr   r   r   ZDEVICE_NAME_FILTERcompiler'   ZNETWORK_NAME_FILTERr   rs   r{   r|   Z	getLogger__name__r@   r   r   r   r$   r)   rI   r   r[   ra   rk   r   r   r   r   r   <module>?   s2   
	+G.-