
    W'FgN                         S SK r S SKrS SKJr  S SKrSSKJr  SSKJr  SSKJr  SSK	J
r
  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  S rS rS rS rS rS rS rS r " S S5      r " S S\5      rg)    N)chain   )generatename)progress)xmlutil)Guest)DeviceInterface)
DeviceDisk)log)DeviceChannel)DeviceSerialc                     U R                  U5      n [        R                  " SU5        UR                  5       S:w  a'  [        R                  " SU5        UR                  5         [        R                  " SU5        UR                  5         g! [        R                   a     gf = f! [        R                   a+  n[        S5      U[        U5      S.-  n[        U5      SeSnAff = f)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   debugIDdestroyundefine_strRuntimeError)connnamer   emsgs        */usr/share/virt-manager/virtinst/cloner.py_replace_vmr!      s    t$*		3T:557b=II-t4JJL		)40
    *>?SVC- -3T)*s)   B A9B( B%$B%(C'<&C""C'c                 X  ^  Sn[         R                  " X!5      nSnSnU(       af  [         R                  " SUR                  5       5      nSnU(       a%  [        [	        UR                  5       5      5      S-   nUSUR                  5        nU 4S jnUS-   n[        R                  " XS	XES
9$ )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]*$r   Fz[1-9]+$TNc                 F   > [         R                  " TR                  U 5      $ N)r   check_libvirt_collisionr   )nr   s    r    cb _generate_clone_name.<locals>.cbC   s!    33q" 	"    -clone )sep	start_num	force_num)researchgroupintr   startr   generate_name)r   basenameregexmatchr-   r.   	num_matchr'   s   `       r    _generate_clone_namer9   3   s    
 EIIe&EIIIIi7		C	 123a7INU[[]+" ("H%%hi> >r)   c                    Uc  gUnSnSU;   a;  [        UR                  SS5      S   5      S::  a  UR                  SS5      u  pESU-   n[        R                  R	                  U5      n[        R                  R                  U5      nUS-   nU (       a  Xp:X  a  Un[        R                  R                  Xh5      n[        R                  " XUS9$ )z~
Generate desired cloned path for auxiliary files, derived from the
original path, original VM name, and proposed new VM name
Nr+   .r      r*   )suffix)	lenrsplitospathdirnamer5   joinr   r4   )	orignamenewnameorigpath	cb_existsrA   r=   rB   r5   	clonebases	            r    _generate_clone_pathrI   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                      U R                  U5      $ ! [        R                   a$    [        [	        S5      [        U5      -  5      nUS ef = f)NzDomain '%s' was not found.)r   r   r   
ValueErrorr   r   )r   r   r   s      r    
_lookup_vmrL   k   sN      && q56TBCTs	    8Ac                    SnSn[         R                  " U R                  [        R                  R                  UR                  5       5      UR                  5       X#5      nUR                  U R                  5       5        U$ )Ngư>F)
r
   build_vol_installr   r@   rA   r5   get_source_pathget_parent_poolset_input_volget_vol_object)	orig_disknew_disksizesparsevol_installs        r    _build_clone_vol_installrX   s   sl     DF..(()A)A)CD  "D2K i6689r)   c                    U R                   n[        R                  nU(       d  [        R                  n[        U5      nUR	                  U5        XVl        U(       d  UR                  5         U$ UR                  5       (       a  UR                  5       (       d  UR                  UR                  :w  d  U R                  5       (       a  [        R                  " U R                  5       [        R                  5      (       aM  UR                  5       (       a8  [        R                  " UR                  5       [        R                  5      (       d%  [!        [#        S5      UR                  5       -  5      eU R                  5       (       aJ  UR%                  5       (       a5  ['        X5      nU(       d  UR(                  Ul        UR-                  U5        O&U R                  5       (       a  UR/                  X5        UR                  5         U$ )NzCClone onto existing storage volume is not currently supported: '%s')r   r
   DEVICE_DISKDEVICE_CDROMset_source_pathdevicevalidaterR   	is_remotetype
TYPE_BLOCKrO   r@   accessR_OKW_OKr   r   wants_storage_creationrX   capacity
allocationset_vol_installset_local_disk_to_clone)rS   	clonepathallow_createrV   r   r]   rT   rW   s           r    _build_clone_diskrl      s   >>D##F(($HY'O   NNMMX000))++		)335rww??((**		(224bgg>> . /191I1I1KLM M 	  ""'')).yC%0%9%9K"  -		"	"	$	$((;Or)   c                     U R                  5       (       a  [        S5      U R                  5       -  $ U R                  S:X  a8  U R                  R
                  nUS:X  a  [        S5      S-   $ [        S5      U-  $ g)zF
If the disk storage is not cloneable, return a string explaining why
zDisk path '%s' does not exist.network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)re   r   rO   r`   sourceprotocol)diskprotos     r    _get_cloneable_msgrt      s     ""$$12T5I5I5KKKyyI$$E>
 =>JKL ;<uDD r)   c                     U R                  5       (       a  [        S5      $ U R                  (       a  [        S5      $ U R                  (       d  U R                  (       a  [        S5      $ g )NzNo storage to clone.z	Read OnlyzMarked as shareable)is_emptyr   	read_only	shareabletransient_shareBacking)rr   s    r    _get_shareable_msgrz      sJ    }}'((~~~~~44&'' 5r)   c                   r    \ rS rSrSrSrSrSrS rS r	S r
S	 rS
 rS rS rS rS rS rS rS rS rSrg)_CloneDiskInfo   a  
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
r         c                    [        UR                  UR                  5       S9U l        S U l        SU l         U R                  R                  5         [        U R                  5      U l
        S U l        S U l        U R                  5         U R                  5       (       a  U R                  5         g g ! [         a  n[        U5      U l         S nAN~S nAff = f)Nparsexmlr   )r
   r   get_xmlrr   rT   _cloneable_msgset_backend_for_existing_path	Exceptionr   rz   
_share_msg_newpath_msg_actionset_clone_requestedget_share_msgset_share_requested)selfsrcdiskr   s      r    __init___CloneDiskInfo.__init__   s    w||goo6GH	 	) II335 -TYY7   "$$&    	)"%a&D	)s   B0 0
C:CCc                 6    U R                   U R                  4;   $ r$   )r   _ACTION_CLONEr   s    r    is_clone_requested!_CloneDiskInfo.is_clone_requested       || 2 2333r)   c                 6    U R                   U R                  4;   $ r$   )r   _ACTION_SHAREr   s    r    is_share_requested!_CloneDiskInfo.is_share_requested   r   r)   c                 6    U R                   U R                  4;   $ r$   )r   _ACTION_PRESERVEr   s    r    is_preserve_requested$_CloneDiskInfo.is_preserve_requested   s    || 5 5666r)   c                 0    XR                   :w  a  Xl         g g r$   )r   )r   actions     r    _set_action_CloneDiskInfo._set_action   s    \\!!L "r)   c                 :    U R                  U R                  5        g r$   )r   r   r   s    r    r   "_CloneDiskInfo.set_clone_requested       ++,r)   c                 :    U R                  U R                  5        g r$   )r   r   r   s    r    r   "_CloneDiskInfo.set_share_requested   r   r)   c                 :    U R                  U R                  5        g r$   )r   r   r   s    r    set_preserve_requested%_CloneDiskInfo.set_preserve_requested   s    ../r)   c                 R   U R                  5       (       + nU(       a  U R                  5       nU(       a  g  [        R                  U R                  XU5      U l        g ! [         a?  n[        R                  " SSS9  [        S5      U[        U5      S.-  nX`l         S nAg S nAff = f)NzError setting clone path.T)exc_infoz4Could not use path '%(path)s' for cloning: %(error)s)rA   r   )r   get_cloneable_msgClonerbuild_clone_diskrr   rT   r   r   r   r   r   r   )r   rA   rV   rk   r   r   errs          r    set_new_path_CloneDiskInfo.set_new_path   s    5577((*C	$"33IIt6;DM 	$II1DAKL!CF34C #		$s   &A 
B&'5B!!B&c                     U R                   $ r$   )r   r   s    r    r   _CloneDiskInfo.get_share_msg  s    r)   c                 n    U R                   S:X  a  [        U R                  5      U l         U R                   $ )Nr   )r   rt   rr   r   s    r    r    _CloneDiskInfo.get_cloneable_msg  s-    "$"4TYY"?D"""r)   c                     U R                   $ r$   )r   r   s    r    get_newpath_msg_CloneDiskInfo.get_newpath_msg  s       r)   c                 6   U R                  5       (       a>  U R                  5       (       a)  U R                  5       n[        SU-  5      n[        U5      eU R	                  5       (       a  g U R                  5       (       a  U R                  5       n[        U5      eg )Nz1Could not determine original disk information: %s)r   r   r   rK   r   r   )r   r   r   s      r    raise_error_CloneDiskInfo.raise_error  s    ""$$)?)?)A)A((*CG#MNCS/!""$$!!&&(CS/! "r)   )r   r   r   r   rr   rT   N)__name__
__module____qualname____firstlineno____doc__r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __static_attributes__ r)   r    r|   r|      sZ    
 MM'*447"--0$ #!	"r)   r|   c                       \ rS rSr\S 5       r\S 5       r\S 5       rSS jrS r	S r
\S	 5       r\S
 5       r\S 5       rS rS rS rS rS rS rS rS rS rS rS rSS jrSrg)r   i"  c                     [        X5      $ r$   )r9   )r   r5   s     r    generate_clone_nameCloner.generate_clone_name#  s    #D33r)   c                 (   ^  U 4S jn[        XX45      $ )Nc                 2   > [         R                  " TU 5      $ r$   )r
   path_definitely_exists)pr   s    r    rG   2Cloner.generate_clone_disk_path.<locals>.cb_exists)  s    44T1==r)   )rI   )r   rD   rE   rF   rG   s   `    r    generate_clone_disk_pathCloner.generate_clone_disk_path'  s    	>#HxKKr)   c                     [        XX#5      $ r$   )rl   )rS   rj   rk   rV   s       r    r   Cloner.build_clone_disk-  s     |LLr)   Nc                     Xl         S U l        S U l        / U l        S U l        U R                  X#5        S U l        SU l        SU l        SU l	        g )NTF)
r   
_src_guest
_new_guest
_diskinfos_nvram_diskinfo	_init_src_new_nvram_path_sparse_replace_reflink)r   r   src_namesrc_xmls       r    r   Cloner.__init__1  sM    	#x)#r)   c                 2   U(       ds  [        U R                  U5      nUR                  5       S   nU[        R                  4;  a  [        [        S5      5      e[        R                  nUR                  U5      n[        R                  " SU5        [        U R                  US9U l        [        U R                  US9U l        U R                  5         U R                  R                  R                    H'  nU R"                  R%                  ['        U5      5        M)     U R"                   Vs/ s H  owR)                  5       (       d  M  UPM     sn HC  nUR                   n[        R                  " SUR+                  5       UR-                  5       5        ME     U R                  R.                  R0                  (       aU  [3        U R                  5      n	U	R5                  U R                  R.                  R0                  5        ['        U	5      U l        ggs  snf )zN
Set up the source VM info we are cloning, from passed in VM name
or full XML
r   z Domain to clone must be shutoff.zOriginal XML:
%sr   zWants cloning: size=%s path=%sN)rL   r   infor   VIR_DOMAIN_SHUTOFFr   r   VIR_DOMAIN_XML_SECUREXMLDescr   r   r   r   r   _init_new_guestdevicesrr   r   appendr|   r   get_sizerO   r@   nvramr
   r\   r   )
r   r   r   domstatusflagsrr   ddiskinfo	old_nvrams
             r    r   Cloner._init_srcE  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MMOT%9%9%;= O
 ??##"499-I%%doo&8&8&>&>?#1)#<D  $ Os   -H	Hc                 0   SU R                   l        SU R                   l        U R                  [        R
                  " U R                  5      5        U R                   R                  R                   HN  nUR                  (       d  M  UR                  S:w  d  M(  [        R                  " [        S5      5        SUl	        MP     U R                   R                  R                   H/  nSUl        [        R                   " U R                  5      Ul        M1     U R                   R                  R$                   H  nUR&                  [(        R*                  :X  d  M#  UR,                  (       d  M6  UR.                  R0                  (       d  MS  UR,                  UR.                  R0                  ;   d  My  SUR.                  l        M     [2        R5                  U R                  U R6                  5      n[        R8                  " SU5        U R;                  U5        g)zC
Perform the series of unconditional new VM changes we always make
Nr   zLSetting the graphics device port to autoport, in order to avoid conflicting.zAuto-generated clone name '%s')r   idtitleset_clone_uuidr   generate_uuidr   r   graphicsportr   warningr   	interface
target_devr	   generate_macmacaddrchannelr`   r   	TYPE_UNIXtarget_namerp   rA   r   r   r   r   set_clone_name)r   devifacer   new_names        r    r   Cloner._init_new_guestf  sh    " $E//		:;??**33CxxxCHHNA @ A B	 4 __,,66E#E+88CEM 7 ..66G 7 77###(;(;(;##w~~':'::&*#	 7 --diiG		2H=H%r)   c                 .    U R                   R                  $ )z,
The name of the original VM we are cloning
)r   r   r   s    r    r   Cloner.src_name  s    
 ###r)   c                     U R                   $ )z2
The Guest instance of the new XML we will create
)r   r   s    r    	new_guestCloner.new_guest  s    
 r)   c                     U R                   $ r$   )r   r   s    r    nvram_diskinfoCloner.nvram_diskinfo  s    ###r)   c                 $    XR                   l        g r$   )r   r   )r   r   s     r    r   Cloner.set_clone_name  s    #r)   c                     XR                   l        U R                   R                   H  nUR                  (       d  M  Xl        M     g)z%
Override the new VMs generated UUId
N)r   uuidsysinfosystem_uuid)r   r  r  s      r    r   Cloner.set_clone_uuid  s4      $..G"""&*# /r)   c                 $    [        U5      U l        g)zW
If True, don't check for clone name collision, simply undefine
any conflicting guest.
N)boolr   r   vals     r    set_replaceCloner.set_replace  s    
 S	r)   c                     Xl         g)z#
If true, use COW lightweight copy
N)r   )r   reflinks     r    set_reflinkCloner.set_reflink  s	      r)   c                     Xl         g)z3
If True, attempt sparse allocation during cloning
N)r   )r   flgs     r    
set_sparseCloner.set_sparse  s	     r)   c                      U R                   SS $ )z-
Return the list of _CloneDiskInfo instances
N)r   r   s    r    get_diskinfosCloner.get_diskinfos  s     q!!r)   c                 |    U R                  5        Vs/ s H  nUR                  5       (       a  M  UPM     sn$ s  snf )z=
Return a list of _CloneDiskInfo that are tagged for cloning
)r!  r   )r   dis     r    get_nonshare_diskinfosCloner.get_nonshare_diskinfos  s>     "//1 -1r))+ 1 - 	- -s   99c                     Xl         g)zS
If the VM needs to have nvram content cloned, this overrides the
destination path
N)r   r  s     r    set_nvram_pathCloner.set_nvram_path  s
    
  #r)   c                    [        U R                  R                  R                  U R                  R                  R                  5       Hs  nUR
                  [        R                  :w  a  M#  S n[        U R                  U R                  R                  UR                  R                  US9UR                  l        Mu     g )Nc                     g)NFr   )rA   s    r    rG   /Cloner._prepare_serial_files.<locals>.cb_exists  s    r)   )rG   )r   r   r   consoleserialr`   r   	TYPE_FILErI   r   r  r   rp   rA   )r   r.  rG   s      r    _prepare_serial_filesCloner._prepare_serial_files  s    DOO33;; OO33::<F{{l444 "6dmm6:nn6I6I6<mm6H6H@I"KFMM<r)   c                 
   U R                   (       d  g U R                   n[        U R                  5      nUR                  R	                  5       nUR                  U5        U R                  nUc  [        R                  R                  U5      S   n[        R                  R                  U5      n[        R                  R                  U[        R                  R                  U R                  R                  5      < SU=(       d    S< 35      n[        U R                  5      nUR                  U5        UR                  5       (       a  UR!                  5       (       at  UR                  R#                  5       (       aU  UR%                  X@R&                  5        UR)                  5         U R*                  UR,                  R/                  5       l        OS U l         UR	                  5       U R                  R                  l        g )Nr   _VARSz.fd)r   r
   r   rr   rO   r\   r   r@   rA   splitextrB   rC   r5   r   r   r   re   rR   r   r   r   r   rT   get_vol_installr  r   )r   r   r   old_nvram_pathnew_nvram_pathext	nvram_dir	new_nvrams           r    _prepare_nvramCloner._prepare_nvram  sr   ##''tyy)	!668!!.1--!''"">215C7IWW\\WW%%doo&:&:;S\E\ KLN tyy)	!!.1'')),,..MM((** !!.,,?  ":>--H--/7 $(D #,#<#<#> r)   c                     [         R                  " U R                  U R                  R                  U R
                  (       + SS9  U R                  5        GH  nUR                  nUR                  (       d|  [        R                  U R                  U R                  U R                  R                  UR                  5       5      nUR!                  XPR"                  5        UR                  (       d  M  UR                  nU(       d   e[$        R&                  " SUR                  5       UR                  5       5        U R(                  (       a!  UR+                  5       nU R(                  Ul        U R                  R.                  R                   H!  nUR0                  UR0                  :X  d  M  Un	M#     W	R3                  S5        UR4                  U	l        UR6                  U	l        UR8                  U	l        U	R3                  UR                  5       5        GM     U R;                  5         U R=                  5         [>        R@                  " U RB                  RE                  5       U R                  RE                  5       5      n
[$        R&                  " SU
5        g! [         a  n[        S5      U-  n[        U5      SeSnAff = f)zB
Validate and set up all parameters needed for the new (clone) VM
F)check_collisionr^   zInvalid name for new guest: %sNzCloning srcpath=%s dstpath=%szClone guest xml diff:
%s)#r   validate_namer   r   r   r   rK   r   r%  rr   rT   r   r   r   r  rO   r   r   r   r   r   r5  r  r   targetr\   r`   driver_namedriver_typer;  r0  r   diffr   r   )r   r   r   r   rS   newpathrT   rW   rr   xmldiskrC  s              r    prepareCloner.prepare  s   	,		4??+?+?48MM0A).0 335H I$$ 99DMM,,"2246 %%g||<((((HO8II5--/1I1I1KM }}&668&*mm#//44;;)"2"22"G 5
 ##D)#==GL"+"7"7G"+"7"7G##H$<$<$>?A 6D 	""$ ||DOO335'')+		-t4Y  	,459CS/t+	,s   AJ 
K$J>>Kc                    [         R                  " S5        [        R                  " U5      nSn U R                  (       a*  [        U R                  U R                  R                  5        U R                  R                  U R                  R                  5       5      nU R                  5       nU R                  (       a  UR                  U R                  5        U H5  nUR                  5       (       d  M  UR                  R!                  U5        M7     [         R                  " S5        g! ["         a=  n[         R                  " S[%        U5      5        U(       a  UR'                  5         e SnAff = f)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   ensure_meterr   r!   r   r   r   	defineXMLr   r!  r   r   r   rT   build_storager   r   r   )r   meterr   	diskinfosr   r   s         r    start_duplicateCloner.start_duplicate<  s   
 			'(%%e,	}}DIIt';';< ))%%doo&=&=&?@C**,I##  !5!56%2244!!//6 & 			)*  	II,c!f5		s   C%D, ,
E368E..E3)	r   r   r   r   r   r   r   r   r   )NNr$   )r   r   r   r   staticmethodr   r   r   r   r   r   propertyr   r  r	  r   r   r  r  r  r!  r%  r(  r0  r;  rF  rN  r   r   r)   r    r   r   "  s    4 4 L L
 M M(=B&F $ $   $ $$+" "-#K!?H45l+r)   r   )r/   r@   	itertoolsr   r   r+   r   r   r   guestr   r   r	   r
   loggerr   r   r   r!   r9   rI   rL   rX   rl   rt   rz   r|   objectr   r   r)   r    <module>rV     su    
 	       $   " !*0>0K@
(VE&(X" X"vy+V y+r)   