
    x[hyI              
       r   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ZddlZddlZddl	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mZ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 m!Z! ddl"m#Z# e#Z$de ge$g dZ%ee&d<   ddgddZ' ed      Z( G d d      Z) ejT                  e+      Z, G d de-      Z. G d de
      Z/ G d de/      Z0 G d de/      Z1 G d d e/      Z2d!e3d"e!d#e4d$e/fd%Z5d$ee6   fd&Z7d$ee6   fd'Z8d( Z9d$e:fd)Z;d* Z<d$ee3e3f   fd+Z=d, Z>d-e/d"e!fd.Z?d/e3d0ed1ed2e4d$df
d3Z@d4e0fd5e1fd6e2ffZAy)7zGrowpart: Grow partitions    N)ABCabstractmethod)suppress)Path)OptionalTuple)	lifecycleperformancesubp
temp_utilsutil)Cloud)Config)
MetaSchema)ALL_DISTROSDistro)
PER_ALWAYScc_growpart)iddistros	frequencyactivate_by_schema_keysmetaauto/F)modedevicesignore_growroot_disabledz/cc_growpart_keydatac                       e Zd ZdZdZdZdZy)RESIZESKIPPEDCHANGEDNOCHANGEFAILEDN)__name__
__module____qualname__r!   r"   r#   r$        >/usr/lib/python3/dist-packages/cloudinit/config/cc_growpart.pyr    r    /   s    GGHFr)   r    c                       e Zd Zy)ResizeFailedExceptionN)r%   r&   r'   r(   r)   r*   r,   r,   9   s    r)   r,   c                   B    e Zd ZdefdZededefd       Zed        Z	y)Resizerdistroc                     || _         y N)_distro)selfr/   s     r*   __init__zResizer.__init__>   s	    r)   r   returnc                      y r1   r(   r3   r   s     r*   	availablezResizer.availableA   s    03r)   c                      y r1   r(   )r3   diskdevpartnumpartdevfss        r*   resizezResizer.resizeD   s    58r)   N)
r%   r&   r'   r   r4   r   listboolr8   r>   r(   r)   r*   r.   r.   =   s6    v  33$3 38 8r)   r.   c                       e Zd ZdefdZd Zy)ResizeGrowPartr   c                     	 t        j                   ddgddi      j                  }t        j                  d|      ry	 y# t         j                  $ r Y yw xY w)	Ngrowpartz--helpLANGC
update_envz--update\s+TF)r   stdoutresearchProcessExecutionError)r3   r   outs      r*   r8   zResizeGrowPart.availableI   se    	))X&FC=f  yy- .
  )) 		s   ;A   AAc                 4   t        ||      }| j                  j                         }t        j                  |d      5 }t
        j                  j                  |d      }d|d}	t
        j                  j                  |      st        j                  |d       	 t        j                  dd||g|	       	 t        j                  d||g|	       	 d d d        |t        ||      fS # t        j                  $ rN}
|
j                  d	k7  r(t        j                  t        d
||       t!        |
      |
||fcY d }
~
cd d d        S d }
~
ww xY w# t        j                  $ r-}
t        j                  t        d||       t!        |
      |
d }
~
ww xY w# 1 sw Y   xY w)NT)dir	needs_exerD   rF   )rE   TMPDIRi  z	--dry-runrG      z&Failed growpart --dry-run for (%s, %s)zFailed: growpart %s %s)get_sizer2   get_tmp_exec_pathr   tempdirospathjoinexistsmkdirr   rL   	exit_coder   logexcLOGr,   )r3   r:   r;   r<   r=   beforetmp_dirtmpdgrowpart_tmpmy_enves              r*   r>   zResizeGrowPart.resizeU   sj   '2& ,,002Gt< 	677<<j9L!\:F77>>,/u-(		gw?%6		:w8VL-	66 "-..# -- 	(;;!#KK@	 029'''	6 	6	( -- 6C!97GL+A.A56/	6 	6sT   AFC'6E'E::E4E5FEFF(FFFFNr%   r&   r'   r?   r8   r>   r(   r)   r*   rB   rB   H   s    
 
!/r)   rB   c                   "    e Zd ZdZdefdZd Zy)ResizeGrowFSa  
    Use FreeBSD ``growfs`` service to grow root partition to fill available
    space, optionally adding a swap partition at the end.

    Note that the service file warns us that it uses ``awk(1)``, and as
    such requires ``/usr`` to be present. However, cloud-init is installed
    into ``/usr/local``, so we should be fine.

    We invoke the ``growfs`` with ``service growfs onestart``, so it
    doesn't need to be enabled in ``rc.conf``.
    r   c                 P    t         j                  j                  d      xr |dgk(  S )z'growfs only works on the root partitionz/etc/rc.d/growfsr   )rV   rW   isfiler7   s     r*   r8   zResizeGrowFS.available   s"    ww~~01Fg#6FFr)   c                     t        ||      }	 | j                  j                  dd       |t        ||      fS # t        j                  $ r+}t        j                  t        d       t        |      |d }~ww xY w)Nonestartgrowfs)actionservicezFailed: service growfs onestart)	rS   r2   manage_servicer   rL   r   r\   r]   r,   )r3   r:   r;   r<   r=   r^   rc   s          r*   r>   zResizeGrowFS.resize   sr    '2&	2LL''z8'L
 "-..	 )) 	2KK>?'*1	2s   9 A7&A22A7N)r%   r&   r'   __doc__r?   r8   r>   r(   r)   r*   rf   rf   y   s    
G G/r)   rf   c                       e Zd ZdefdZd Zy)ResizeGpartr   c                     	 t        j                   ddgddiddg      j                  }t        j                  d|      ry		 y
# t         j                  $ r Y y
w xY w)NgparthelprE   rF   r   rR   )rH   rcszgpart recover TF)r   stderrrJ   rK   rL   )r3   r   errs      r*   r8   zResizeGpart.available   sl    	))&!vsm!Qf  yy*C0 1
  )) 		s   >A AAc                    	 t        j                   dd|g       t        ||      }	 t        j                   ddd||g       |t        ||      fS # t         j                  $ r@}|j                  dk7  r't        j                  t
        d|       t        |      |Y d}~d}~ww xY w# t         j                  $ r-}t        j                  t
        d||       t        |      |d}~ww xY w)	a9  
        GPT disks store metadata at the beginning (primary) and at the
        end (secondary) of the disk. When launching an image with a
        larger disk compared to the original image, the secondary copy
        is lost. Thus, the metadata will be marked CORRUPT, and need to
        be recovered.
        rs   recoverr   zFailed: gpart recover %sNr>   z-izFailed: gpart resize -i %s %s)r   rL   r[   r   r\   r]   r,   rS   )r3   r:   r;   r<   r=   rc   r^   s          r*   r>   zResizeGpart.resize   s    	6IIw	734 '2&	2IIw$AB
 "-.. )) 	6{{aC!;WE+A.A5  	6 )) 	2KK<gwO'*1	2s.   A B% B""6BB"%C%8(C  C%Nrd   r(   r)   r*   rq   rq      s    
 
/r)   rq   r   r/   r   r5   c                 6   d }| dk(  r;t         D ]#  \  }} ||      }|j                  |      s!|} n |st        d      |S i }t         D ]
  \  }}	|	||<    | |vrt        d| z         ||    |      }
|
j                  |      r|
}|st        d| z        |S )Nr   )r   zNo resizers availablezunknown resize mode %szmode %s not available)RESIZERSr8   
ValueError	TypeError)r   r/   r   resize_class_nameresizercurmmapkvmclasss              r*   resizer_factoryr      s    Lv~& 	NE7&/C}}W}-"		 455"   	DAqDG	 t4t;<<dF#G,!L4t;<<r)   c                    d }	 t        j                  | t         j                        }t        j                  |dt         j                        |rt        j
                  |       S S # t        $ rE |dk(  r%t        |       cY |rt        j
                  |       S S Y |rt        j
                  |       y y w xY w# |rt        j
                  |       w w xY w)Nr   zfs)rV   openO_RDONLYlseekSEEK_ENDcloseFileNotFoundErrorget_zfs_size)filenamer=   fds      r*   rS   rS      s    	B	WWXr{{+xxAr{{+ HHRL   ;)) HHRL  HHRL 
 HHRL s*   AA% %B3>B6 B6 2B33B6 6Cc                    | j                  d      d   }	 t        j                  dddd|g      \  }}t        |j                               S # t        j                  $ r!}t        j	                  d||       Y d }~y d }~ww xY w)Nr   r   zpoolgetz	-HpovaluesizezFailed: zpool get size %s: %s)splitr   rL   r]   debugintstrip)datasetr   r   _rc   s        r*   r   r      sv    MM#q!E))We[&%HIa tzz| %% 		15!<s   A B A;;B c                 p   | j                  d      r| d fS t        j                  |       }|st        d      |d   }|d   }t        j                         }|dk(  rY|sWt        j
                  t        j                               }|.t        j                  j                  |      r|d fS t        d      ||fS )N/dev/z,Could not determine device of '%s' % dev_entr   rR   z	/dev/rootz!Unable to find device '/dev/root')

startswithr   get_mount_infor|   is_containerrootdev_from_cmdlineget_cmdlinerV   rW   rY   )deventresultdevr=   	containers        r*   
devent2devr      s    !t|  (FGHH
)C	B!!#I k)''(8(8(:;;ww~~c" Dy @AA7Nr)   c                    t        j                  d      st        j                  d       y	 t        j                   dd| g       t        t         j                        5  t        j                   dd	|g       t        j                  d
|        	 ddd       y# t         j                  $ rP}|j
                  dk(  rt        j                  d|        n t        j                  d|j
                         Y d}~yd}~ww xY w# 1 sw Y   yxY w)z
    Check if a device is an encrypted device. blockdev should have
    a /dev/dm-* path whereas partition is something like /dev/sda1.
    
cryptsetupz6cryptsetup not found. Assuming no encrypted partitionsFstatus   z#Determined that %s is not encryptedzZReceived unexpected exit code %s from cryptsetup status. Assuming no encrypted partitions.NisLukszDetermined that %s is encryptedT)r   whichr]   r   rL   r[   warningr   )blockdev	partitionrc   s      r*   is_encryptedr   	  s    
 ::l#		JK		<845 
$,,	- 		<956		3X>  %% 	;;!II;XFKKG
 	 s$   B 0C=C:*AC55C:=Dc                    ddd| g}t        j                   |      d   }|j                  d      st        d|       	 d|j                  d      d	   j                  d
      d    S # t        $ r}t        d| d| d      |d }~ww xY w)Ndmsetupdepsz--options=devnamer   z1 dependz5Expecting '1 dependencies' from 'dmsetup'. Received: r   z: (rR   )zRan `z$`, but received unexpected stdout: ``)r   r   RuntimeErrorr   
IndexError)r   commanddeprc   s       r*   get_underlying_partitionr   $  s    &"5x@Gyy!!$C >>*%CC5I
 	
syy'*005a89:: G9@QG
	s   (A( (	B	1BB	c                 x   t         j                         st        j                  dfS 	 t	        j
                  dt                5  t         j                         5 }t        j                  |      }ddd       ddd       d   }t        j                  |      }|d   }	 t        j                  ddd	d
| g|       	 t        j                  ddd|t        |      g       	 t         j%                          t        j*                  d|  dfS # 1 sw Y   xY w# 1 sw Y   xY w# t        $ r}t        d      |d}~ww xY w# t        j                  $ r }t         j#                  d|       Y d}~d}~ww xY w# t        $ r t'        j(                  t         d       Y w xY w# 	 t        j                  ddd|t        |      g       n6# t        j                  $ r }t         j#                  d|       Y d}~nd}~ww xY w	 t         j%                          w # t        $ r t'        j(                  t         d       Y w w xY wxY w)zUse 'cryptsetup resize' to resize LUKS volume.

    The loaded keyfile is json formatted with 'key' and 'slot' keys.
    key is base64 encoded. Example:
    {"key":"XFmCwX2FHIQp0LBWaLEMiHIyfxt1SGm16VvUAVledlY=","slot":5}
    zNo encryption keyfile foundzReading NkeyslotzZCould not load encryption key. This is expected if the volume has been previously resized.r   z
--key-file-r>   )dataluksKillSlotz--batch-modez<Failed to kill luks slot after resizing encrypted volume: %sz8Failed to remove keyfile after resizing encrypted volumez'Successfully resized encrypted volume '')KEYDATA_PATHrY   r    r!   r
   Timedr   jsonloadbase64	b64decode	Exceptionr   r   strrL   r]   r   unlinkr   r\   r"   )r   r   fkeydatar   decoded_keyr   rc   s           r*   resize_encryptedr   5  s%      =>>|n%
 	#	#"#iilG	# 	# en&&s+v		<hA	

	II ""I	! 	
1(1= S	# 	# 	# 	#  6
 	, )) 	KKN 	  	KKO	#	II ""I )) 	KKN 	
	! 	KKO	s   D" DD
/D7'D" F <#D?  E5 
D	DDD" "	D<+D77D<?E2E--E25#FFH9 #GH9G7G2-H92G77H9;HH9#H63H95H66H9c                    g }	 | j                  ||||      \  }}||k(  r+|j                  |t        j                  d|d|df       |S ||9d}	||
d|d|d}	nd|z  }	|j                  |t        j                  |	f       |S d}	||d|d|d|d	|}	nd|d|d	|}	|j                  |t        j                  |	f       	 |S # t
        $ r6}
|j                  |t        j                  d
|d|d|
f       Y d }
~
|S d }
~
ww xY w)Nzno change necessary (z, r    z	changed (z) size, new size is unknownz&changed (%s) size, new size is unknownz) from z to zfailed to resize: disk=z, ptnum=z: )r>   appendr    r#   r"   r,   r$   )r   r   diskptnumr   r=   infooldnewmsgrc   s              r*   _call_resizerr   n  s;   D(
>>$x<S#:KKOO6:EBL K? [CKCEM
 ?IKK56, K) CEM	 7?SIKK56 K ! 
=A5!L	
 	
 K
s%   AC ;C AC 	D+DDr   c           	         t        j                   |      }g }|r|j                  d      }d }d }	 t        |      \  }}t        j                  d|       |dk(  r$t        | t              r|t        | |||||      z  }f	 t        j                  |      }
t        j                  |
j                         sEt        j"                  |
j                         s&|j	                  |t
        j                  d|z  f       |j%                  |      }|r	 t'        |      }t)        ||      r_||D cg c]  }|d   	 c}vr&|j+                  d|       |j+                  d|       Ft-        ||      \  }}|j	                  |||f       n&|j	                  |t
        j                  d| d	f       	 |j3                  |      \  }}|t        | |||||      z  }|r|S # t        $ r0}	|j	                  |t
        j                  d|	z  f       Y d }	~	d }	~	ww xY w# t        $ r3}	|j	                  |t
        j                  d|d|	f       Y d }	~	3d }	~	ww xY wc c}w # t.        $ r2}	|j	                  |t
        j0                  d
| d|	 f       Y d }	~	d }	~	ww xY w# t4        t        f$ r3}	|j	                  |t
        j                  d|d|	f       Y d }	~	d }	~	ww xY w)Nr   zunable to convert to device: %szgrowpart found fs=%sr   z	stat of 'z
' failed: zdevice '%s' not a block devicezResizing mapped device (z!) skipped as it is not encrypted.zResizing encrypted device (z
) failed: zdevice_part_info()copypopr   r|   r   r    r!   r]   r   
isinstancerf   r   rV   statOSErrorS_ISBLKst_modeS_ISCHRget_mapped_devicer   r   insertr   r   r$   device_part_infor}   )r   r   r/   r   r   r   r   r   r=   rc   statretunderlying_blockdevr   xr   messages                   r*   resize_devicesr     s   ii GD
Q
	%f-LHb 			("- ;:g|<M'64"MMD
	ggh'G ||GOO,T\\OO6
 KKNN4x? $66x@%4X>	 3Y? t(<!1(<<  q&1q)4 &6x&KOFGKK""# KK""NN6xj A6 6$ 
	 11(;KD% 	gvtUHbIIU X KK  	KKNN59 	,  	KKNN191= 	8 )=4  5hZz!M  :& 	KKNN9A1E 	sx   G ?H I (I4(I A
I +J 	H!%HH	I(III 	J!(JJK%(KKnamecfgcloudargsc                    d|vr#t         j                  dt               t        |d<   |j                  d      }t	        |t
              st         j                  d       y |j                  dd      }t        j                  |      r8|dk7  rt        j                  d| dd	d
       t         j                  d|       y t        j                  |j                  dd            rJt        j                  j                  d      r+t         j                  d       t         j                  d       y t        j                  |ddg      }t        |      st         j                  d       y 	 t!        ||j"                  |      }t)        j*                  d      5  t-        |||j"                        }	d d d        	D ]I  \  }
}}|t.        j0                  k(  rt         j3                  d|
|       2t         j                  d|
||       K y # t$        t&        f$ r(}t         j                  d||       |dk7  r|Y d }~y d }~ww xY w# 1 sw Y   xY w)NrD   z.No 'growpart' entry in cfg.  Using default: %sz#'growpart' in config was not a dictr   r   offz"Growpart's 'mode' key with value 'r   z22.2zUse 'off' instead.)
deprecateddeprecated_versionextra_messagezgrowpart disabled: mode=%sr   Fz/etc/growroot-disabledz0growpart disabled: /etc/growroot-disabled existsz&use ignore_growroot_disabled to ignorer   r   zgrowpart: empty device list)r/   r   z,growpart unable to find resizer for '%s': %szResizing devicesz'%s' resized: %sz'%s' %s: %s)r]   r   DEFAULT_CONFIGr   r   dictr   r   is_falser	   	deprecaterV   rW   rh   get_cfg_option_listlenr   r/   r|   r}   r
   r   r   r    r"   r   )r   r   r   r   mycfgr   r   r   rc   resizedentryrl   r   s                r*   handler     s   		<n	
 )JGGJEeT"9:99VV$D}}T5=?vQG#)2
 			.5}}UYY95AB77>>23IIHIII>?&&ui#?Gw<		/0!$u||WM 
		-	. A '5<<@A% 9vsV^^#HH'4IImUFC8	9 	" 		@$J6>G	A As$   'H H=H:H55H:=IrD   rk   rs   )Bro   r   r   r   loggingrV   os.pathrJ   r   abcr   r   
contextlibr   pathlibr   typingr   r   	cloudinitr	   r
   r   r   r   cloudinit.cloudr   cloudinit.configr   cloudinit.config.schemar   cloudinit.distrosr   r   cloudinit.settingsr   r   r   __annotations__r   r   r    	getLoggerr%   r]   r   r,   r.   rB   rf   rq   r   r?   r   r   rS   r   r   r@   r   r   r   r   r   r   r{   r(   r)   r*   <module>r     s         	  	  #   " D D ! # . 1 )	
}!	j  u % *+  g!	I 	9c 9./W ./b/7 /8#/' #/L# v   <hsm Xc] 0 6"6U38_ 6r+\qG qf qh09 096 09% 09t 09 09h  |kr)   