+
    hN  c                   s    ^ RI t ^ RIt^ RIHt ^ RIt^RIHt ^RIHt ^RIHt ^RI	H
t
 ^RIHt ^RIHt ^R	IHt ^R
IHt ^RIHt R tR tR tR tR tR tR tR t ! R R4      t ! R R4      tR# )i    N)chain)generatename)progress)xmlutil)Guest)DeviceInterface)
DeviceDisk)log)DeviceChannel)DeviceSerialc                s    V P                  V4      p \        P                  ! RT4       TP                  4       R8w  d(   \        P                  ! RT4       TP                  4        \        P                  ! RT4       TP                  4        R#   \        P                   d     R# i ; i  \        P                   d1   p\        R4      RTR\        T4      /,          p\        T4      RhRp?ii ; i)	z8
Remove the existing VM with the same name if requested
NzExplicitly replacing guest '%s'zDestroying guest '%s'zUndefining guest '%s'z+Could not remove old vm '%(vm)s': %(error)svmerror)lookupByNamelibvirtlibvirtErrorr   debugZIDZdestroyundefine_strRuntimeError)connnamer
   emsg   &&   */usr/share/virt-manager/virtinst/cloner.py_replace_vmr      s    t$*		3T:557b=II-t4JJL		)40
    *=>$gWZ[\W]A^^3T)*s)   B A:B, B)(B),C1+C,,C1c                sr  a  Rp\         P                  ! W!4      p^pRpV'       dl   \         P                  ! RVP                  4       4      pRpV'       d*   \        \	        VP                  4       4      4      ^,           pVRVP                  4        pV 3R lpVR,           p\        P                  ! WRWER	7      # )
zh
If the orig name is "foo-clone", we don't want the clone to be
"foo-clone-clone", we want "foo-clone1"
z-clone[1-9]*$Fz[1-9]+$TNc                 sF   < \         P                  ! SP                  V 4      # N)r   Zcheck_libvirt_collisionr   )Znr      &r   cbZ _generate_clone_name.<locals>.cbB   s    33D4E4EqII    -clone )Zsep	start_num	force_num)reZsearchZgroupZintr   Zstartr   generate_name)r   basenameZregexZmatchr"   r#   Z	num_matchr   s   f&      r   _generate_clone_namer'   2   s    
 EIIe&EIIIIi7		C	 123a7IOekkm,J ("H%%"	 r   c                s   Vf   R# TpRpRV9   dE   \        VP                  R^4      ^,          4      ^8:  d   VP                  R^4      w  rERV,           p\        P                  P	                  V4      p\        P                  P                  V4      pVR,           pV '       d	   Wp8X  d   Tp\        P                  P                  Wh4      p\        P                  ! WVR7      # )z~
Generate desired cloned path for auxiliary files, derived from the
original path, original VM name, and proposed new VM name
Nr!   Z.r    )suffix)	ZlenZrsplitospathdirnamer&   joinr   r%   )	orignamenewnameorigpath	cb_existsr*   r(   r+   r&   Z	clonebases	   &&&&     r   _generate_clone_pathr1   K   s    
 DF h3xsA6q9:a?sA.vggood#Gww%H8#IH(	W0I%%i6JJr   c                 s     V P                  V4      #   \        P                   d)    \        \	        R 4      \        T4      ,          4      pTRhi ; i)zDomain '%s' was not found.N)r   r   r   
ValueErrorr   r   )r   r   r      && r   
_lookup_vmr4   k   sN      && q56TBCTs	    =Ac                 s   R pRp\         P                  ! V P                  \        P                  P                  VP                  4       4      VP                  4       VV4      pVP                  V P                  4       4       V# )gư>F)
r   Zbuild_vol_installr   r)   r*   r&   get_source_pathZget_parent_poolZset_input_volget_vol_object)	orig_disknew_diskZsizesparsevol_installr   r   _build_clone_vol_installr;   s   sq     DF..
1134  "K i6689r   c                 s4   V P                   p\        P                  pV'       g   \        P                  p\        V4      pVP	                  V4       WVn        V'       g   VP                  4        V# VP                  4       '       d   VP                  4       '       g   VP                  VP                  8w  g   V P                  4       '       d   \        P                  ! V P                  4       \        P                  4      '       dP   VP                  4       '       d:   \        P                  ! VP                  4       \        P                  4      '       g*   \!        \#        R 4      VP                  4       ,          4      hV P                  4       '       dM   VP%                  4       '       d7   \'        W4      pV'       g   VP(                  Vn        VP-                  V4       M'V P                  4       '       d   VP/                  W4       VP                  4        V# )zCClone onto existing storage volume is not currently supported: '%s')r   r   ZDEVICE_DISKZDEVICE_CDROMset_source_pathdevicevalidater6   Z	is_remotetypeZ
TYPE_BLOCKr5   r)   ZaccessZR_OKZW_OKr   r   wants_storage_creationr;   ZcapacityZ
allocationZset_vol_installZset_local_disk_to_clone)r7   	clonepathallow_creater9   r   r=   r8   r:   s   &&&&    r   _build_clone_diskrC      s|   >>D##F(($HY'O   NN}} 3 33,,..99Y668"''BB++--99X557AAWX**,- 
 !!h&E&E&G&G.yC%0%9%9K"  -		"	"	$	$((;Or   c                s   V P                  4       '       d!   \        R4      V P                  4       ,          # V P                  R8X  dB   V P                  P
                  pVR8X  d   \        R4      R,           # \        R4      V,          # R# )zF
If the disk storage is not cloneable, return a string explaining why
zDisk path '%s' does not exist.ZnetworkZrbdz)Cloning rbd volumes is not yet supported.z8 https://github.com/virt-manager/virt-manager/issues/177z(Disk network type '%s' is not cloneable.N)r@   r   r5   r?   sourceZprotocol)diskZproto   & r   _get_cloneable_msgrG      s     ""$$12T5I5I5KKKyyI$$E>
 =>LM ;<uDD r   c                 s    V P                  4       '       d   \        R 4      # V P                  '       d   \        R4      # V P                  '       g   V P                  '       d   \        R4      # R# )zNo storage to clone.z	Read OnlyzMarked as shareableN)Zis_emptyr   Z	read_onlyZ	shareableZtransient_shareBacking)rE      &r   _get_shareable_msgrI      sQ    }}'((~~~~~~~444&'' 5r   c                   s~   a  ] tR t^t o Rt^t^t^tR tR t	R t
R tR tR tR tR	 tR
 tR tR tR tR tRtV tR# )_CloneDiskInfoa  
Class that tracks some additional information about how we want
to default handle each disk of the source VM

For any source disk there's 3 main scenarios:

* clone: Copy contents from src to dst. If dst path doesn't
        exist we attempt to create it. If it exists we overwrite it
* preserve: Destination path is an existing, and no copying is performed.
* share: Original disk XML is used unchanged for the new disk
c                s   \        VP                  VP                  4       R 7      V n        RV n        RV n         V P                  P                  4        \        V P                  4      V n
        RV n        RV n        V P                  4        V P                  4       '       d   V P                  4        R# R#   \         d   p\        T4      T n         Rp?LRp?ii ; i)ZparsexmlNr   )r   r   get_xmlrE   r8   _cloneable_msgZset_backend_for_existing_path	Exceptionr   rI   
_share_msg_newpath_msg_actionset_clone_requestedget_share_msgset_share_requested)selfZsrcdiskr   r3   r   __init__Z_CloneDiskInfo.__init__   s    w||goo6GH	 	) II335 -TYY7   "$$&    	)"%a&D	)s   B6 6CCCc                6    V P                   V P                  39   # r   )rQ   _ACTION_CLONErU   rH   r   is_clone_requestedZ!_CloneDiskInfo.is_clone_requested       || 2 2333r   c                rW   r   )rQ   _ACTION_SHARErY   rH   r   is_share_requestedZ!_CloneDiskInfo.is_share_requested   r[   r   c                rW   r   )rQ   _ACTION_PRESERVErY   rH   r   is_preserve_requestedZ$_CloneDiskInfo.is_preserve_requested   s    || 5 5666r   c                s6    WP                   8w  d	   Wn         R # R # r   )rQ   )rU   Zaction   &&r   _set_actionZ_CloneDiskInfo._set_action   s    \\!!L "r   c                <    V P                  V P                  4       R # r   )ra   rX   rY   rH   r   rR   Z"_CloneDiskInfo.set_clone_requested      ++,r   c                rb   r   )ra   r\   rY   rH   r   rT   Z"_CloneDiskInfo.set_share_requested  rc   r   c                rb   r   )ra   r^   rY   rH   r   set_preserve_requestedZ%_CloneDiskInfo.set_preserve_requested  s    ../r   c                sn   V P                  4       '       * pV'       d   V P                  4       pV'       d   R #  \        P                  V P                  WV4      V n        R #   \         dI   p\        P                  ! RRR7       \        R4      RTR\        T4      /,          pY`n         R p?R # R p?ii ; i)NzError setting clone path.T)Zexc_infoz4Could not use path '%(path)s' for cloning: %(error)sr*   r   )r_   get_cloneable_msgClonerbuild_clone_diskrE   r8   rN   r   r   r   r   rP   )rU   r*   r9   rB   r   r   errs   &&&    r   set_new_pathZ_CloneDiskInfo.set_new_path
  s    5577((*C	$"33DIItSYZDM 	$II1DAJKQO C !$	$s   &A! !B4,=B//B4c                    V P                   # r   )rO   rY   rH   r   rS   Z_CloneDiskInfo.get_share_msg  s    r   c                sp    V P                   R8X  d   \        V P                  4      V n         V P                   # )i   r   )rM   rG   rE   rY   rH   r   re   Z _CloneDiskInfo.get_cloneable_msg  s-    "$"4TYY"?D"""r   c                rj   r   )rP   rY   rH   r   get_newpath_msgZ_CloneDiskInfo.get_newpath_msg#  s       r   c                sJ   V P                  4       '       dD   V P                  4       '       d.   V P                  4       p\        R 4      V,          p\        V4      hV P	                  4       '       d   R# V P                  4       '       d   V P                  4       p\        V4      hR# )z1Could not determine original disk information: %sN)rZ   re   r   r2   r]   rk   )rU   r   rh      &  r   raise_errorZ_CloneDiskInfo.raise_error&  s    ""$$)?)?)A)A((*CGH3NCS/!""$$!!&&(CS/! "r   )rQ   rM   rP   rO   rE   r8   N)__name__
__module____qualname____firstlineno__Z__doc__r\   rX   r^   rV   rZ   r]   r_   ra   rR   rT   rd   ri   rS   re   rk   rm   __static_attributes____classdictcell__Z__classdict__   @r   rJ   rJ      sb     
 MM'*447"--0$"#
!	" 	"r   rJ   c                   s   a  ] tR tRt o ]R 4       t]R 4       t]R 4       tRR ltR t	R t
]R	 4       t]R
 4       t]R 4       tR tR tR tR tR tR tR tR tR tR tR tRR ltRtV tR# )rf   i2  c                s    \        W4      # r   )r'   )r   r&   r`   r   generate_clone_nameZCloner.generate_clone_name3  s    #D33r   c                s(   a  V 3R  lp\        WW44      # )c                 s2   < \         P                  ! SV 4      # r   )r   Zpath_definitely_exists)Zpr   r   r   r0   Z2Cloner.generate_clone_disk_path.<locals>.cb_exists9  s    44T1==r   )r1   )r   r-   r.   r/   r0   s   f&&& r   generate_clone_disk_pathZCloner.generate_clone_disk_path7  s    	> $HxKKr   c                s    \        WW#4      # r   )rC   )r7   rA   rB   r9      &&&&r   rg   ZCloner.build_clone_disk>  s     |LLr   Nc                s    Wn         R V n        R V n        . V n        R V n        V P                  W#4       R V n        RV n        RV n        RV n	        R # )NTF)
r   
_src_guest
_new_guest
_diskinfos_nvram_diskinfo	_init_src_new_nvram_path_sparse_replace_reflink)rU   r   src_namesrc_xmlrx   r   rV   ZCloner.__init__B  sM    	#x)#r   c                sP   V'       gy   \        V P                  V4      pVP                  4       ^ ,          pV\        P                  39  d   \        \        R4      4      h\        P                  pVP                  V4      p\        P                  ! RV4       \        V P                  VR7      V n        \        V P                  VR7      V n        V P                  4        V P                  P                  P                    F'  pV P"                  P%                  \'        V4      4       K)  	  V P"                   Uu. uF  qwP)                  4       '       g   K  VNK  	  up FC  pVP                   p\        P                  ! RVP+                  4       VP-                  4       4       KE  	  V P                  P.                  P0                  '       dW   \3        V P                  4      p	V	P5                  V P                  P.                  P0                  4       \'        V	4      V n        R# R# u upi )zN
Set up the source VM info we are cloning, from passed in VM name
or full XML
z Domain to clone must be shutoff.zOriginal XML:
%srK   zWants cloning: size=%s path=%sN)r4   r   Zinfor   ZVIR_DOMAIN_SHUTOFFr   r   ZVIR_DOMAIN_XML_SECUREZXMLDescr   r   r   ry   rz   _init_new_guestdevicesrE   r{   appendrJ   rZ   Zget_sizer5   r)   nvramr   r<   r|   )
rU   r   r   domZstatusZflagsrE   Zddiskinfo	old_nvrams
   &&&       r   r}   ZCloner._init_srcU  s   
 TYY1CXXZ]Fg8899"1%G#HII11Ekk%(G		%w/		G<		G< OO++00DOO"">$#78 1$(OONOq7K7K7MONH==DII6I]I]I_` O ??###"499-I%%doo&8&8&>&>?#1)#<D  $	 Os   9H#H#c                s>   RV P                   n        RV P                   n        V P                  \        P
                  ! V P                  4      4       V P                   P                  P                   FP  pVP                  '       g   K  VP                  R8w  g   K*  \        P                  ! \        R4      4       RVn	        KR  	  V P                   P                  P                   F/  pRVn        \        P                   ! V P                  4      Vn        K1  	  V P                   P                  P$                   F  pVP&                  \(        P*                  8X  g   K$  VP,                  '       g   K8  VP.                  P0                  '       g   KV  VP,                  VP.                  P0                  9   g   K}  RVP.                  n        K  	  \2        P5                  V P                  V P6                  4      p\        P8                  ! RV4       V P;                  V4       R# )zC
Perform the series of unconditional new VM changes we always make
NzLSetting the graphics device port to autoport, in order to avoid conflicting.zAuto-generated clone name '%s'r   )rz   ZidZtitleset_clone_uuidr   Zgenerate_uuidr   r   ZgraphicsZportr   Zwarningr   Z	interfaceZ
target_devr   Zgenerate_macZmacaddrchannelr?   r   Z	TYPE_UNIXZtarget_namerD   r*   rf   rv   r   r   set_clone_name)rU   ZdevZifacer   Znew_names   &    r   r   ZCloner._init_new_guestu  si    " $E//		:;??**33CxxxCHHN9  4 __,,66E#E+88CEM 7 ..66G 7 77'''NN'''''7>>+>+>>&*# 7 --diiG		2H=H%r   c                s.    V P                   P                  # )z,
The name of the original VM we are cloning
)ry   r   rY   rH   r   r   ZCloner.src_name  s    
 ###r   c                rj   )z2
The Guest instance of the new XML we will create
)rz   rY   rH   r   	new_guestZCloner.new_guest  s    
 r   c                rj   r   )r|   rY   rH   r   nvram_diskinfoZCloner.nvram_diskinfo  s    ###r   c                s&    WP                   n        R # r   )rz   r   )rU   r   r`   r   r   ZCloner.set_clone_name  s    #r   c                s    WP                   n        V P                   P                   F  pVP                  '       g   K  Wn        K  	  R# )z%
Override the new VMs generated UUId
N)rz   uuidsysinfoZsystem_uuid)rU   r   r   r3   r   r   ZCloner.set_clone_uuid  s4      $..G"""&*# /r   c                s&    \        V4      V n        R# )zW
If True, don't check for clone name collision, simply undefine
any conflicting guest.
N)Zboolr   rU   Zvalr`   r   set_replaceZCloner.set_replace  s    
 S	r   c                    Wn         R# )z#
If true, use COW lightweight copy
N)r   )rU   reflinkr`   r   set_reflinkZCloner.set_reflink  s	      r   c                r   )z3
If True, attempt sparse allocation during cloning
N)r   )rU   Zflgr`   r   
set_sparseZCloner.set_sparse  s	     r   c                s(    V P                   R,          # )z-
Return the list of _CloneDiskInfo instances
:NNN)r{   rY   rH   r   get_diskinfosZCloner.get_diskinfos  s     q!!r   c                sz    V P                  4        Uu. uF  qP                  4       '       d   K  VNK  	  up# u upi )z=
Return a list of _CloneDiskInfo that are tagged for cloning
)r   r]   )rU   ZdirF   r   get_nonshare_diskinfosZCloner.get_nonshare_diskinfos  s2     "//1Q1r9N9N9P1QQQs   88c                r   )zS
If the VM needs to have nvram content cloned, this overrides the
destination path
N)r~   r   r`   r   set_nvram_pathZCloner.set_nvram_path  s
    
  #r   c                s   \        V P                  P                  P                  V P                  P                  P                  4       Fw  pVP
                  \        P                  8w  d   K$  R  p\        V P                  V P                  P                  VP                  P                  VR7      VP                  n        Ky  	  R# )c                 s    R # )F )r*   rH   r   r0   Z/Cloner._prepare_serial_files.<locals>.cb_exists  s    r   )r0   N)r    rz   r   Zconsoleserialr?   r	   Z	TYPE_FILEr1   r   r   r   rD   r*   )rU   r   r0   rl   r   _prepare_serial_filesZCloner._prepare_serial_files  s    DOO33;;T__=T=T=[=[\F{{l444 "6t~~22FMM4F4FR["FMM ]r   c                s"   V P                   '       g   R # V P                   p\        V P                  4      pVP                  P	                  4       pVP                  V4       V P                  pVf   \        P                  P                  V4      ^,          p\        P                  P                  V4      p\        P                  P                  T\        P                  P                  V P                  P                  4      : RT;'       g    R: 24      p\        V P                  4      pVP                  V4       VP                  4       '       d   VP!                  4       '       dv   VP                  P#                  4       '       dV   VP%                  W@P&                  4       VP)                  4        V P*                  VP,                  P/                  4       n        MR V n         VP	                  4       V P                  P                  n        R # )NZ_VARSz.fd)r|   r   r   rE   r5   r<   r~   r)   r*   Zsplitextr+   r,   r&   rz   r   rZ   r@   r6   ri   r   rm   r   r8   get_vol_installr   r   )rU   r   r   Zold_nvram_pathZnew_nvram_pathZextZ	nvram_dirZ	new_nvrams   &       r   _prepare_nvramZCloner._prepare_nvram  sy   ###''tyy)	!668!!.1--!''"">215C7IWW\\"''*:*:4??;O;O*PRUR^R^Y^R^_N tyy)	!!.1 ''))0022,,..
 !!.,,?  ":>--H--/7 $(D #,#<#<#> r   c                s    \         P                  ! V P                  V P                  P                  V P
                  '       * RR7       T P                  4        EF  pTP                  pTP                  '       g~   \        P                  T P                  T P                  T P                  P                  TP                  4       4      pTP!                  YPP"                  4       TP                  '       g   K  TP                  p\$        P&                  ! RTP                  4       TP                  4       4       T P(                  '       d"   TP+                  4       pT P(                  Tn        T P                  P.                  P                   F"  pTP0                  TP0                  8X  g   K   Tp	K$  	  X	P3                  R4       TP4                  T	n        TP6                  T	n        TP8                  T	n        T	P3                  TP                  4       4       EK  	  T P;                  4        T P=                  4        \>        P@                  ! T PB                  PE                  4       T P                  PE                  4       4      p
\$        P&                  ! RT
4       R#   \         d$   p\        R4      T,          p\        T4      RhRp?ii ; i)zB
Validate and set up all parameters needed for the new (clone) VM
F)Zcheck_collisionr>   zInvalid name for new guest: %sNzCloning srcpath=%s dstpath=%szClone guest xml diff:
%s)#r   Zvalidate_namer   rz   r   r   r2   r   r   rE   r8   rf   rw   r   r   r5   ri   r   r   r   r   r   r   r   Ztargetr<   r?   Zdriver_nameZdriver_typer   r   r   diffry   rL   )rU   r   r   r   r7   Znewpathr8   r:   rE   Zxmldiskr   s   &          r   prepareZCloner.prepare  s   	,		4??//T]]AR]b 335H I$$$ 99IIt}}dnn.A.A9C\C\C^ %%g||<(((((HII/))+((* }}}&668&*mm#//44;;)"2"22"G 5
 ##D)#==GL"+"7"7G"+"7"7G##H$<$<$>?E 6H 	""$ ||DOO335t7N7N7PQ		-t4[  	,459CS/t+	,s   AJ K$KKc                s   \         P                  ! R4       \        P                  ! V4      pRp V P                  '       d+   \        V P                  V P                  P                  4       V P                  P                  V P                  P                  4       4      pV P                  4       pV P                  '       d   VP                  V P                  4       V F6  pVP                  4       '       g   K  VP                  P!                  V4       K8  	  \         P                  ! R4       R#   \"         d?   p\         P                  ! R\%        T4      4       T'       d   TP'                  4        h Rp?ii ; i)z[
Actually perform the duplication: cloning disks if needed and defining
the new clone xml.
zStarting duplicate.NzDuplicate failed: %szDuplicating finished.)r   r   r   Zensure_meterr   r   r   rz   r   Z	defineXMLrL   r   r|   r   rZ   r8   Zbuild_storagerN   r   r   )rU   Zmeterr   Z	diskinfosr   r   s   &&    r   start_duplicateZCloner.start_duplicateO  s   
 			'(%%e,	}}}DIIt';';< ))%%doo&=&=&?@C**,I###  !5!56%2244!!//6 & 			)*  	II,c!f5		s%   D0 A>D0 AD0 0E9;9E44E9)	r{   rz   r~   r|   r   r   r   ry   r   )NNr   )rn   ro   rp   rq   Zstaticmethodrv   rw   rg   rV   r}   r   Zpropertyr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rr   rs   rt   ru   r   rf   rf   2  s     4 4 L L M M&=@#&R $ $   $ $$+" "R##?J55n+ +r   rf   )r$   r)   Z	itertoolsr    r   r!   r   r   r   Zguestr   r   r   r   Zloggerr   r   r	   r   r'   r1   r4   r;   rC   rG   rI   rJ   rf   r   r   r   <module>r      ss    
 	       $   " !*.2K@"*ZE((a" a"H|+ |+r   