
    [hNH                        U d Z ddlZddlZddlZddlZddlZddlmZmZm	Z	m
Z
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 ddlmZ d	d
geg dZeed<   dZdZdZdZdZdZ ej@                  e!      Z"d Z#d Z$d Z%d7dZ&d7dZ'de(de	e(   dee(e(f   de)fdZ*d8dZ+de(de(ddfd Z,d9d!Z-d" Z.de
ee(   ee(e(f   ee(   f   fd#Z/d$ee	ee	e(            dee(e(f   d%ee(e(f   d&ee	e(      d'edeee(      fd(Z0d$eee(      deee(      fd)Z1d$eee(      d*e(dee(e(f   d%ee(e(f   d'edeee(      fd+Z2d,eee(      deee(      fd-Z3d,eee(      ddfd.Z4d/e)d0e)d1ee(   ddfd2Z5d3e(d4ed'ed5e6ddf
d6Z7y):z-Mounts: Configure mount points and swap files    N)DictListOptionalTuplecast)performancesubputil)Cloud)Config)
MetaSchema)PER_INSTANCE	cc_mountsall)iddistros	frequencyactivate_by_schema_keysmetaz&^([x]{0,1}[shv]d[a-z][0-9]*|sr[0-9]+)$z^.+:.*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)nameenumnames     </usr/lib/python3/dist-packages/cloudinit/config/cc_mounts.pyis_meta_device_namer$   ,   sB    && ) ??8$32)=     c                 :    t        j                  t        |       ryy)NTF)rematchNETWORK_NAME_FILTER)r!   s    r#   is_network_devicer*   8   s    	xx#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_devicer6   ?   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.   r/   realpathsplitjoinr0   )r1   partition_pathdevice_namesys_paths       r#   _is_block_devicer?   L   s    ''"";/55c:2>Kww||M;7H!77<<bgg&&~6<<SA"E
 77>>(##r%   c                 D   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                  t        |       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 %sr8   z/dev/zMapped metadata name %s to %s   )LOGdebugr*   r
   expand_dotted_devnamegetr$   r   r'   r(   DEVICE_NAME_FILTERr6   r?   )	startnametransformeraliasesdevnamer1   r2   origr<   s           r#   sanitize_devnamerM   V   s.   II;YG G+		FG#$($>$>w$G!K!Dkk+{;;II4dKH;'!+.%%c*'24K		14E88&	2'24KN6{AF6)
 !^4%!!r%   original	sanitized
fstab_devsreturnc                     || k7  rt         j                  d| |       |t         j                  d|        y||v rt         j                  d|||          yy)z*Get if the sanitized device name is valid.zchanged %s => %sz+Ignoring nonexistent default named mount %sFz&Device %s already defined in fstab: %sT)rC   rD   )rN   rO   rP   s      r#   sanitized_devname_is_validrS      s_     H		$h	:		?J	j	 		4y!	

 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memrX      g?max   sizez%s MBzCsuggest %s swap for %s memory with '%s' disk given max=%s [max=%s]'rZ   rY   )r
   read_meminfor.   statvfsf_frsizef_bfreeminintGBroundmathsqrtitems
isinstanceMBrC   rD   )memsizemaxsizefsyssugg_maxinfor`   rX   minsizer^   pinfokvs               r#   suggested_swapsizeru      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%   fnamer^   c                    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                 h   t         j                  d| |       |dk(  r
ddd|z  | g}n(|dk(  rddd| z  dd	|z  g}nt        j                  d
      	 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=%sz:Missing dependency: 'dd' and 'fallocate' are not availableT)capture)rC   rD   r	   ProcessExecutionErrorrp   r
   del_file)rv   r^   methodcmdeerrmsgfstypes        r#   create_swapz$create_swapfile.<locals>.create_swap   s    		A		
 [ edlE:Ct^%T!C ,,L 	IIc4()) 	HHVUD&!4MM% 	s   A* *B1=/B,,B1rB   btrfstruncatez-s0chattrz+Cxfs)r[      rz   ry   z4fallocate swap creation failed, will attempt with ddi  mkswapN)r.   r/   dirnamer
   
ensure_dirget_mount_infor	   kernel_versionr|   rC   rp   r0   chmodr}   )rv   r^   r   swap_dirr   r   s       @@r#   create_swapfiler      s4    FF< 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                  d      5  t        | |       ddd       | S # t        $ r t        j                  d       Y yw xY w# 1 sw Y   | S 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
    autorU   z)Not creating swap: failed to read meminfoN)rn   rm   rl   r   z'Not creating swap: suggested size was 0zSetting up swap file)r.   r/   r   r-   lowerr
   r_   IOErrorrC   rD   r   ru   rd   r   Timedr   )rv   r^   rm   r   rl   mibsizes         r#   setup_swapfiler     s     wwu%H
4yF"	'')'2G
 	!!7G
 #den%&G		;<			1	2 (w'( L#  	IIAB	( Ls   C ;C6C32C36D 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.imgr^   r   rm   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   )rv   r^   rm   zfailed to setup swap: %s)rj   dictrC   warningrF   rD   r.   r/   r0   r
   load_text_file
splitlinesr   	Exceptionr-   human2bytesr   )swapcfgrv   r^   rm   liner   s         r#   handle_swapcfgr   /  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(c                  B   g } i }g }t         j                  j                  t              rrt	        j
                  t              j                         D ]H  }t        |v r|j                  |       |j                         }|s0|||d   <   | j                  |       J | ||fS )as  Parse /etc/fstab.

    Parse fstab, ignoring any lines containing "comment=cloudconfig".
    :return: A 3-tuple containing:
        - A list of lines exactly as they appear in fstab
        - A dictionary with key being the first token in the line
          and value being the entire line
        - A list of any lines that were ignored due to "comment=cloudconfig"
    r   )
r.   r/   r0   
FSTAB_PATHr
   r   r   MNT_COMMENTappendr:   )fstab_linesrP   fstab_removedr   tokss        r#   parse_fstabr   _  s     KJM	ww~~j!''
3>>@ 	)Dd"$$T*::<D&*
47#""4(	) 
M11r%   mountsdevice_aliasesdefault_fieldscloudc                    g }| D ]  }t        |t              st        j                  d|       *t	        |d         }t        ||j                  |      }t        |||      r
|g|dd z   }	n|}	t        |	      D ]!  \  }
}|	||
   |	|
<   t	        |	|
         |	|
<   # |	|t        |	      d z  }	|j                  |	        |S )a  Sanitize mounts to ensure we can work with devices in config.

    Specifically:
     - Ensure the mounts configuration is a list of lists
     - Transform and sanitize device names
     - Ensure all tokens are strings
     - Add default options to any lines without options
    z%Mount option not a list, ignoring: %sr   rJ   rB   N)rj   listrC   r   r-   rM   device_name_to_devicerS   	enumeratelenr   )r   rP   r   r   r   updated_linesr   startsanitized_devnameupdated_lineindextokens               r#   sanitize_mounts_configurationr   y  s     M +$%KK?FDG,5..
 &e->
K-.ab9LL &l3 	?LE5}&4U&;U#&),u*=&>U#		? 	s<'8':;;\*5+6 r%   c                     g }g }| ddd   D ]M  }|d   |d   |v r.t         j                  d|d          |j                  |d          =|j                  |       O |ddd   S )zRemove any entries that have a device name that doesn't exist.

    If the second field of a mount line is None (not the string, the value),
    we skip it along with any other entries that came before it that share
    the same device name.
    Nr   rB   r   z$Skipping nonexistent device named %s)rC   rD   r   )r   actlistdev_denylistr   s       r#   remove_nonexistent_devicesr     sz     GLtt !7?d1g5II<d1gFQ(NN4 ! 4R4=r%   default_mount_optionsc                 L  	 t        j                  |       }ddd|ddgg dfD ]~  		d   }t        ||j                  |      }t	        |||      s.t        t        |      	d<   t        	fd	| D              }|rt        j                  d
|       n|j                  	        |S )zAdd default mounts to the user provided mount configuration.

    Add them only if no other entry has the same device name
    rA   z/mntr   r   2)r   noner   swr   r   r   r   c              3   4   K   | ]  }|d    d    k(    yw)r   N ).0cfgmdefault_mounts     r#   	<genexpr>z,add_default_mounts_to_cfg.<locals>.<genexpr>  s$      %
,0DG}Q''%
s   z-Not including %s, already previously included)copydeepcopyrM   r   rS   r   r-   anyrC   rD   r   )
r   r   rP   r   r   
new_mountsr   rO   default_already_existsr   s
            @r#   add_default_mounts_to_cfgr     s     v&J	vv'<c3G0 ) a $5..
	 *%JG  Y/a!$ %
4:%
 "
 "IIEuM-())* r%   r   c                 ^    | D cg c]  }|dd |d    dt          gz   |dd z    c}S c c}w )z=Add "comment=cloudconfig" to the mount options of each entry.N   ,r[   )r   )r   entrys     r#   add_commentr     sL      	bq	az;-011E!"I=  s   "*c                 X    t        d | D              rt        j                  ddg       yy)z1Call 'swapon -a' if any entry has a swap fs type.c              3   ,   K   | ]  }|d    dk(    yw)rV   r   Nr   )r   r   s     r#   r   z*activate_swap_if_needed.<locals>.<genexpr>  s     
3%58v
3s   swapon-aN)r   r	   )r   s    r#   activate_swap_if_neededr     s&    

37
33		8T"# 4r%   uses_systemdchanges_madedirsc                 6   d}|rd}nYt        j                         j                         D ch c]  }d|v r|d    }}t        t	        |      j                  |            }|r2t        j                  ddg       | rt        j                  ddg       yyyc c}w )	zCall 'mount -a' if needed.

    If changes were made, always call 'mount -a'. Otherwise, call 'mount -a'
    if any of the directories in the mount list are not already mounted.
    FT
mountpointmountr   	systemctlzdaemon-reloadN)r
   r   valuesboolset
differencer	   )r   r   r   do_mountvalmount_pointss         r#   mount_if_neededr     s     H {{}++-
s" 
 

 D	,,\:;		7D/"II{O45  
s   Br!   cfgargsc                 X   |j                   j                         }|rdnd}ddd|ddg}|j                  d|      }|j                  dg       }t        j	                  d	|       t               \  }	}
}|j                  d
i       }t        ||
|||      }t        |||
||      }t        |      }t        |      }t        |j                  di             }|r|j                  |dddddg       |st        j	                  d       y|D cg c]  }dj                  |       }}|D cg c]  }|d   j                  d      s|d    }}|D ]  }	 t        j                  |        |D cg c]  }|j%                  dd       }}|D cg c]  }|j%                  dd       }}|D cg c]  }||vsd|  c}|D cg c]  }||vsd|  c}z   }|	j'                  |       ddj                  |	      z  }t        j(                  t*        |       |rt        j	                  d|       nt        j	                  d       t-        |       t/        |t1        |      |       yc c}w c c}w # t         $ r t        j"                  t        d|       Y Jw xY wc c}w c c}w c c}w c c}w )z Handle the mounts configuration.z:defaults,nofail,x-systemd.after=cloud-init.service,_netdevzdefaults,nobootwaitNr   r   r   mount_default_fieldsr   zmounts configuration is %sr   r   r   r   z No modifications to fstab needed	rB   r8   z Failed to make '%s' config-mountr   z- z+ z%s

zChanges to fstab: %szNo changes to /etc/fstab made.)distror   rF   rC   rD   r   r   r   r   r   r   r   r;   r   r
   r   r   logexcreplaceextend
write_filer   r   r   r   )r!   r   r   r   r   r   hardcoded_defaultsr   r   r   rP   r   r   updated_cfgswapfiler   	cfg_linesdr   nsaddssdropsdropaddsopscontentss                             r#   handler    s    <<,,.L  	E"  f.CS#N*-'' 2+N 36''(B2GFII*F3-8]*K]WW-r2N/
NNEK ,*JK -[9Kk*Kcggfb12HHffdCEF
 			45/:;e5!;I;%>Q1)=AaD>D> D	DOOAD ,55aQYYtS!5E5,9:qaiic":F:$*@Dd%.?bK@#Ds&'8"SE
D D y!		+..HOOJ)		($/		23K(L$t*d37 <>
  	DKK?C	D 6:@ DsH   I#%I(?I(I-)JJ'	J"1J">	J'J'-$JJ)N)NNN)NN)8__doc__r   loggingrg   r.   r'   typingr   r   r   r   r   	cloudinitr   r	   r
   cloudinit.cloudr   cloudinit.configr   cloudinit.config.schemar   cloudinit.settingsr   r   __annotations__rG   r)   r   r   rk   re   	getLogger__name__rC   r$   r*   r6   r?   rM   r-   r   rS   ru   r   r   r   r   r   r   r   r   r   r   r   r  r   r%   r#   <module>r     s   4    	 	 4 4 - - ! # . + w!	j  ?  
#

g!	
$.b&sm9=c3h	&6r;3 ;c ;d ;|<-`2U49d38nd3i?@ 24+$x}-./+S#X+ cN+ #'	+
 + 
$s)_+\tDI 4S	? &!cO!! S#X! cN	!
 ! 
$s)_!Hd3i T$s)_ $T$s)_ $ $66&*626s)6	62E4 E46 E4% E4t E4 E4r%   