
    fN              
          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j8                  e      ZdZ ej8                  e      Z ej8                  dez        Z dZ!dZ"dZ#dZ$ ejJ                  e&      Z'd Z(d Z)d Z*d+dZ+d+dZ,d,dZ-d e.d!e.d"dfd#Z/d-d$Z0d% Z1d&e.d'ed(ed)e2d"df
d*Z3y).z-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                 l    | dv rydD ]*  }| j                  |      s| j                  d      dk(  s* y y)N)amirootswapT)	ephemeralebs:F)
startswithfind)r   enumnames     </usr/lib/python3/dist-packages/cloudinit/config/cc_mounts.pyis_meta_device_namer&      sB    && ) ??8$32)=     c                 0    t         j                  |       ryy)NTF)NETWORK_NAME_REmatch)r   s    r%   is_network_devicer+      s    T"r'   c                     t        |      d|d|g}|D ]+  }| |}t        j                  j                  |      s)|c S  y )Npz-part)strospathexists)device_pathpartition_numberpotential_suffixessuffixpotential_partition_devices        r%   _get_nth_partition_for_devicer7      sW    !#%'
 % ./:F%C"77>>45--. r'   c                    t         j                  j                  |       j                  d      d   }t         j                  j	                  d|      }|Ot         j                  j	                  |t         j                  j                  |      j                  d      d         }t         j                  j                  |      S )N/r!   z/sys/block/)r/   r0   realpathsplitjoinr1   )r2   partition_pathdevice_namesys_paths       r%   _is_block_devicer@      s    ''"";/55c:2>Kww||M;7H!77<<bgg&&~6<<SA"E
 77>>(##r'   c                 :   t         j                  d|        | }|dk(  rd}t         j                  d       t        |       r| S t        j                  |      \  }}|}|r.|j                  ||      }||k7  rt         j                  d||       t        |      r9 ||      }|sy |j                  d      sd|}t         j                  d||       nt        j                  |       rd|}d }|t        |d	      }nt        ||      }|y t        ||      r||S |S y )
Nz+Attempting to determine the real name of %sr   
ephemeral0z2Adjusted mount option from ephemeral to ephemeral0zMapped device alias %s to %sr9   z/dev/zMapped metadata name %s to %s   )LOGdebugr+   r   expand_dotted_devnamegetr&   r"   DEVICE_NAME_REr*   r7   r@   )	startnametransformeraliasesdevnamer2   r3   origr=   s           r%   sanitize_devnamerN      s-   II;YG G+		FG#$($>$>w$G!K!Dkk+{;;II4dKH;'!+.%%c*'24K		14E	*'24KN6{AF6)
 !^4%!!r'   c           	         | t        j                         d   } | dz  }d|| d}|||}nk|ret        j                  |      }|j                  |j
                  z  }||d<   |t        t        |dz        |      }n||dz  kD  rt        |dz        }n||}||d<   | dt        z  k  r| }nB| d	t        z  k  r
dt        z  }n,t        t        j                  | t        z              t        z  }t        ||      }||d
<   i }	|j                         D ]*  \  }
}t        |t              rd|t        z  z  |	|
<   &||	|
<   , t        j!                  d|	d
   |	d   |	d   |	d   |	d          |S )Ntotal   na)availmax_inmemrS      g?max   sizez%s MBzCsuggest %s swap for %s memory with '%s' disk given max=%s [max=%s]'rU   rT   )r   read_meminfor/   statvfsf_frsizef_bfreeminintGBroundmathsqrtitems
isinstanceMBrD   rE   )memsizemaxsizefsyssugg_maxinfor[   rS   minsizerY   pinfokvs               r%   suggested_swapsizerp      s   ##%g.{HWW=D|	**T"  7??2W?#eai.(3G&%#+&G	DKR	27	b&		'B,/025w DDLE

 1a!b&)E!HE!H	 IIMfeghe Kr'   fnamerY   returnc                    dfd}t         j                  j                  |       }t        j                  |       t        j
                  |      d   dk(  r1t        j                  ddd| g       t        j                  dd	| g       d
k(  r"t        j                         dk  r || |d       n	  || |d       t         j                  j                  |       rt        j                  | d       	 t        j                  d| g       y# t        j                  $ r" t        j                  d        || |d       Y w xY w# t        j                  $ r t        j                  |         w xY w)zSize is in MiB.z6Failed to create swapfile '%s' of size %sMB via %s: %sc                 <   t         j                  d| |       |dk(  r
ddd|z  | g}n|dk(  rddd| z  dd	|z  g}	 t        j                  d
       y # t        j                  $ r4}t         j	                  | |||       t        j                  |         d }~ww xY w)Nz3Creating swapfile in '%s' on fstype '%s' using '%s'	fallocatez-lz%sMddzif=/dev/zerozof=%szbs=1Mzcount=%sT)capture)rD   rE   r   ProcessExecutionErrorrk   r   del_file)rq   rY   methodcmdeerrmsgfstypes        r%   create_swapz$create_swapfile.<locals>.create_swap!  s    		A		
 [ edlE:Ct^%T!C	IIc4()) 	HHVUD&!4MM% 	s   A B'/BBrC   btrfstruncatez-s0chattrz+Cxfs)rV      rv   ru   z4fallocate swap creation failed, will attempt with ddi  mkswapN)r/   r0   dirnamer   
ensure_dirget_mount_infor   kernel_versionrx   rD   rk   r1   chmodry   )rq   rY   r   swap_dirr}   r~   s       @@r%   create_swapfiler     s4    FF4 wwu%HOOH  *1-F		:tS%01		8T5)*4..07:E4&	+t[1
 
ww~~e

5% 		8U#$ )) 	+HHKLtT*	+ %% es   5
D 5E 2EE*E/c                    t         j                  j                  |       }t        |      j	                         dk(  r;	 t        j                         d   }t        j                  |       t        |||      }t        t        |dz              }|st        j                  d       yt        j                  t        j                  dt        | |g	       | S # t        $ r t        j                  d       Y yw xY w)
z
    fname: full path string of filename to setup
    size: the size to create. set to "auto" for recommended
    maxsize: the maximum size
    autorP   z)Not creating swap: failed to read meminfoN)ri   rh   rg   r   z'Not creating swap: suggested size was 0zSetting up swap file)msgfuncargs)r/   r0   r   r.   lowerr   rZ   IOErrorrD   rE   r   rp   r_   log_timer   )rq   rY   rh   r   rg   mibsizes         r%   setup_swapfiler   V  s     wwu%H
4yF"	'')'2G
 	!!7G
 #den%&G		;<MM		"W	 L+  	IIAB	s   C C65C6c                    t        | t              st        j                  d       y| j	                  dd      }| j	                  dd      }| j	                  dd      }|r|st        j                  d       yt        j                  j                  |      rt        j                  j                  d	      st        j                  d
|       |S 	 t        j                  d	      j                         D ]0  }|j                  |dz         st        j                  d|       |c S  t        j                  d|       	 t        |t              r|dk7  rt        j                  |      }t        |t              rt        j                  |      }t!        |||      S # t        $ r t        j                  d|       |cY S w xY w# t        $ r }t        j                  d|       Y d}~yd}~ww xY 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.imgrY   r   rh   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   )rq   rY   rh   zfailed to setup swap: %s)re   dictrD   warningrG   rE   r/   r0   r1   r   load_text_file
splitlinesr"   	Exceptionr.   human2bytesr   )swapcfgrq   rY   rh   liner|   s         r%   handle_swapcfgr   x  s    gt$;<KK
K0E;;vq!Dkk)T*GU		)*	ww~~eww~~m,IIL L
	++M:EEG !??53;/II;UC L! IICUK3dC TV^##D)Dgs#&&w/GEgFF  	KK@% L		  3.223s7   :F 	F #F ;AF? !F<;F<?	G(G##G(r   cfgcloudr   c           	      <   d}|j                   j                         }|rd}d d d|ddg}|j                  d|      }ddd|d	   ddgg d
g}g }d|v r|d   }t        j	                  d|       g }	i }
g }t
        j                  j                  t              rut        j                  t              j                         D ]K  }t        |v r|j                  |       	 t        j                  |      }||
d   <   |	j                  |       M |j                  di       }t#        t%        |            D ]  }t'        ||   t(              s1t        j+                  d|dz   t-        j.                  ||                Ht1        ||   d         }t3        ||j4                  |      }||k7  rt        j	                  d||       |t        j	                  d|       ||
v rt        j7                  d||
|          |||   d<   t#        t%        ||               D ]"  }||   |   t1        ||   |         ||   |<   $  t#        t%        |            D ]  }t#        t%        |            D ]?  }t%        ||         |k  r||   j                  ||          ,||   |   5||   ||   |<   A ||   d   bt#        |      D ]  }||   d   ||   d   k(  sd ||   d<     |D ]  }|d   }t3        ||j4                  |      }||k7  rt        j	                  d||       |t        j	                  d|       U||
v rt        j	                  d||
|          t||d<   d}|D ]  }|d   |d   k(  sd} n |rt        j	                  d|       |j                  |        g }|D ]2  }|d   t        j	                  d|d          "|j                  |       4 t9        |j                  di             }|r|j                  |dddddg       t%        |      dk(  rt        j	                  d       y g }d}d}g }|D ]e  }|d	   dt        |d	<   |d    dk(  rd}|d   j;                  d!      r|j                  |d          |j                  d"j=                  |             g t        j>                         jA                         D cg c]  \  }}d#|v s|d#    } }}|D ]"  }!	 t        jB                  |!       |r|!| vs!d}$ |D "cg c]  }"t        jG                  d%|"       }#}"|D "cg c]  }"t        jG                  d%|"       }$}"|$D %cg c]  }%|%|#vsd&|%z    c}%|#D &cg c]  }&|&|$vsd'|&z    c}&z   }'|	jI                  |       d(d)j=                  |	      z  }(t        jJ                  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                  d/d0g       d1}*|)D ]B  }+d2d%j=                  |+      z   }*	 tM        jL                  |+       t        j	                  |*d3       D y # t         $ r Y w xY wc c}}w # t         $ r t        jD                  t        d$|!       Y w xY wc c}"w c c}"w c c}%w c c}&w # tL        jN                  $ r4 t        j+                  |*d4       t        jD                  t        |*d4       Y w xY w)5Nzdefaults,nobootwaitz=defaults,nofail,x-systemd.requires=cloud-init.service,_netdevr   r   2mount_default_fieldsrB   z/mnt   )r   noner   swr   r   mountszmounts configuration is %sr   device_aliasesz,Mount option %s not a list, got a %s insteadrC   )rK   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 needed,rQ   r9   	
mountpointz Failed to make '%s' config-mountr   z- z+ 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:PASSFAIL)(distrouses_systemdrG   rD   rE   r/   r0   r1   
FSTAB_PATHr   r   r   MNT_COMMENTappendWSr;   r   rangelenre   listr   r   obj_namer.   rN   device_name_to_devicerk   r   r"   r<   r   rd   r   logexcsubextend
write_filer   rx   ),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entryrn   ro   mount_pointsdnsaddssdropsdropaddsopscontentsactivate_cmdsfmtr{   s,                                               r%   handler     s\   (L<<,,.LK 	 T6<c:Ggg,g6G 
vvwqz3<0G
 F3XII*F3KJM	ww~~j!''
3>>@ 
	%Dd"$$T*xx~ #'JtAwt$
	% WW-r2N3v; $1&)T*KK>Q##F1I.
 F1IaL!$5..
	 II(%;II;UC*$HH89%
  q	! s6!9~& 	1Aay|#"6!9Q<0q	!		1A$1L 3v; (s7|$ 	*A6!9~"q	  ,1%&qzq	!		* !9Q<1X (!9Q<6!9Q</#'F1IaL(($  q	$5..
	 II7	JIICUK*$II89%
 q	
 	DAw&)#!
	
 IIEuMf=D G Q4<II<adCNN1	 SWWVR01GsC@A
7|q		45HHND *#Ah4a8vH8s#KKa!		%()* %)KKM$7$7$9 Aq\Q=N,L   	"	DOOA !<"7!N	" &..RVVC^.E.&34bffS!n4F4$*@Dd%.?D4K@#Ds&'8s
D D x 		+..HOOJ)Mh-.
4yA~		23		($/gt_-  +!?@
/C *$sxx}4	*IIcNIIc6"	*M  z  	DKK?C	D /4@ D: )) 	*KKV$KKS&)	*sg   Y?ZZ!Z[ )[	[
[
#	[-[+[?	ZZ$Z=<Z=A\\)N)NNN)NN)4__doc__loggingrb   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compilerH   NETWORK_NAME_FILTERr)   r   r   r   rf   r`   	getLogger__name__rD   r&   r+   r7   r@   rN   rp   r.   r   r   r   r   r    r'   r%   <module>r      sy   4   	 	   , , ! # < +3 j $ ' 4%	
 !'j , t
 ? ./ "**01RZZ:&'
#

g!	
$.b6r73 7c 7d 7tD-`Q* Q*6 Q*% Q*t Q* Q*r'   