o
    AVb°P  ã                   @   s¦   d dl Z d dlmZ d dlmZ d dlZd dlmZ d dlmZ d dlmZ ddlm	Z	 dd	l
mZ dd
lmZ ddlmZ dd„ ZG dd„ dƒZG dd„ deƒZdS )é    N)ÚGtk)ÚPango)ÚCloner)Úlog)Úxmlutilé   )Úuiutil)ÚvmmGObjectUI)ÚvmmAsyncJob)ÚvmmStorageBrowserc                 C   s&   |   ¡ r|   ¡ S | j ¡ rtdƒS dS )z"Is the passed path even clone-ablezNo storage to clone.N)Úget_cloneable_msgÚdiskÚis_emptyÚ_)Údiskinfo© r   ú,/usr/share/virt-manager/virtManager/clone.pyÚ_get_cloneable_msg   s
   
ÿr   c                   @   s˜   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$S )%Ú_StorageInfozô
    Our wrapper class that is close to Cloner _DiskInfo content.
    We track all user choices explicitly in this class, and then
    serialize them into the actual cloner diskinfo once the
    user clicks 'Clone' to complete the process.
    c                 C   s‚   || _ |j| _| ¡ | _|jj| _| ¡ | _	t
|ƒ| _d | _|jo%|j ¡ | _| js.|  ¡  | ¡ | _| j	s:|  ¡ s?d| _d S d S ©NF)Ú	_diskinfor   Ú
_orig_diskÚget_nameÚ_orig_vm_nameÚ	new_guestÚnameÚ_new_vm_nameÚget_share_msgÚ	share_msgr   Úcloneable_msgÚ_manual_pathÚnew_diskÚget_source_pathÚ_generated_pathÚ_reset_generated_pathÚis_clone_requestedÚ_is_clone_requestedÚis_cloneable)ÚselfÚvmÚclonerr   r   r   r   Ú__init__&   s    



ÿ

ÿz_StorageInfo.__init__c                 C   s   t | jƒ S ©N)Úboolr   ©r(   r   r   r   r'   :   ó   z_StorageInfo.is_cloneablec                 C   s   | j S r,   ©r&   r.   r   r   r   r%   <   s   z_StorageInfo.is_clone_requestedc                 C   ó   | j  S r,   r0   r.   r   r   r   Úis_share_requested>   ó   z_StorageInfo.is_share_requestedc                 C   r1   r,   )r   r.   r   r   r   Úwarn_about_sharing@   r3   z_StorageInfo.warn_about_sharingc                 C   s   | j jS r,   )r   Útargetr.   r   r   r   Ú
get_targetC   r3   z_StorageInfo.get_targetc                 C   s
   | j  ¡ S r,   )r   r"   r.   r   r   r   Úget_orig_disk_pathE   ó   
z_StorageInfo.get_orig_disk_pathc                 C   s   | j r| j S | jS r,   )r    r#   r.   r   r   r   Úget_new_disk_pathG   s   z_StorageInfo.get_new_disk_pathc                 C   s   t |ƒ| _d S r,   )r-   r&   ©r(   Úvalr   r   r   Úset_clone_requestedL   s   z _StorageInfo.set_clone_requestedc                 C   s
   || _ d S r,   )r    r:   r   r   r   Úset_manual_pathN   r8   z_StorageInfo.set_manual_pathc                 C   s$   |r|| j kr	d S || _ |  ¡  d S r,   )r   r$   r:   r   r   r   Úset_new_vm_nameP   s   z_StorageInfo.set_new_vm_namec                 C   s$   t  | jj| j| j| j ¡ ¡| _d S r,   )r   Úgenerate_clone_disk_pathr   Úconnr   r   r"   r#   r.   r   r   r   r$   V   s   
üz"_StorageInfo._reset_generated_pathc                 C   s<   | j s| ¡  d |_d S | ¡  d}|  ¡ }| ||¡ d S )NT)r&   Úset_share_requestedr!   r<   r9   Úset_new_path)r(   r   ÚsparseÚnewpathr   r   r   Úset_values_on_diskinfo]   s   z#_StorageInfo.set_values_on_diskinfoc                 C   s®   g }|  tdƒ|  ¡  ¡ |  tdƒ|  ¡  ¡ |  ¡ r'|  tdƒ|  ¡  ¡ |  d¡ | jr<|  tdƒd| ji ¡ n|  tdƒ¡ | jrR|  tdƒd| ji ¡ d |¡S )	NzDisk target: %szOriginal path: %szNew path: %sÚ
z$Storage is safe to share: %(reason)sÚreasonz.Sharing this storage is potentially dangerous.z$Storage is not cloneable: %(reason)s)Úappendr   r6   r7   r9   r   r   Újoin)r(   Úlinesr   r   r   Úget_tooltipm   s$   


ÿÿ
ÿ
z_StorageInfo.get_tooltipc                 C   sª   g }d}|   ¡ }|r||7 }n|tdƒ7 }| |¡ d}|  ¡ r*|tdƒ| ¡  7 }|  ¡ r@|tdƒ7 }|  ¡ }|r@|d| 7 }|rG| |¡ d |¡}dt 	|¡ }|S )NÚ zNo storage.zShare disk with %szClone this diskz (%s)rF   z<small>%s</small>)
r7   r   rH   r2   r   r%   Úget_size_labelrI   r   Ú
xml_escape)r(   r)   rJ   ÚlineÚpathÚ	sizelabelÚlabelÚmarkupr   r   r   Ú
get_markup   s(   



z_StorageInfo.get_markupc                 C   s    | j  ¡ rdS | j  ¡ rdS dS )Nzmedia-floppyzmedia-opticalzdrive-harddisk)r   Ú	is_floppyÚis_cdromr.   r   r   r   Úget_icon_name›   s
   

z_StorageInfo.get_icon_namec                 C   s   | j  ¡ }|s	dS dt|ƒ S )NrL   z%.1f GiB)r   Úget_sizeÚfloat)r(   Úsizer   r   r   rM   ¢   s   
z_StorageInfo.get_size_labelN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r+   r'   r%   r2   r4   r6   r7   r9   r<   r=   r>   r$   rE   rK   rT   rW   rM   r   r   r   r   r      s&    r   c                   @   s
  e Zd Zedd„ ƒZdd„ Zedd„ ƒZdd„ Zd	d
„ Z	d>dd„Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd?d.d/„Zd0d1„ Zd2d3„ Zd4d5„ Zd6d7„ Zd?d8d9„Z d:d;„ Z!d<d=„ Z"dS )@Ú
vmmCloneVMc              
   C   sŠ   z%|j  ¡ }| jd u ri | _|| jvrtƒ | j|< | j|  |j|¡ W d S  tyD } z|j t	dƒt
|ƒ ¡ W Y d }~d S d }~ww )Nz Error launching clone dialog: %s)r@   Úget_uriÚ
_instancesr_   ÚshowÚtopwinÚ	ExceptionÚerrÚshow_errr   Ústr)ÚclsÚ	parentobjr)   ÚuriÚer   r   r   Úshow_instanceª   s   


ÿ€ÿzvmmCloneVM.show_instancec                 C   sŒ   t  | dd¡ d | _d | _d | _|  d¡| _| j | j¡ | j	 
| j| j| j| j| j| j| j| j| j| jdœ
¡ |  ¡  |  ¡  |  ¡  d S )Nzclone.uiz	vmm-cloneúvmm-change-storage)
Úon_clone_delete_eventÚon_clone_cancel_clickedÚon_clone_ok_clickedÚon_storage_selection_changedÚon_storage_details_clickedÚ"on_vmm_change_storage_delete_eventÚ on_change_storage_cancel_clickedÚon_change_storage_ok_clickedÚ!on_change_storage_doclone_toggledÚ on_change_storage_browse_clicked)r	   r+   r)   Ú_storage_listÚ_storage_browserÚwidgetÚ_storage_dialogÚset_transient_forrc   ÚbuilderÚconnect_signalsÚ	_close_cbÚ_finish_clicked_cbÚ_storage_selection_changed_cbÚ_storage_details_clicked_cbÚ_storage_dialog_close_cbÚ_storage_dialog_finish_cbÚ"_storage_dialog_doclone_toggled_cbÚ_storage_dialog_browse_cbÚbind_escape_key_closeÚ_cleanup_on_app_closeÚ_init_uir.   r   r   r   r+   ¸   s*   ôzvmmCloneVM.__init__c                 C   s   | j r| j jpd S r,   )r)   r@   r.   r   r   r   r@   Ú   s   zvmmCloneVM.connc                 C   sD   t  d¡ |  |¡ |  ¡  | j |¡ | j dd¡ | j ¡  d S )NzShowing clone wizardr   )r   ÚdebugÚ_set_vmÚ_reset_staterc   r|   ÚresizeÚpresent)r(   Úparentr)   r   r   r   rb   Þ   s   

zvmmCloneVM.showc                 C   s   | j  ¡  dS )Nr   )r{   Úhider.   r   r   r   Ú_storage_dialog_closeæ   s   
z vmmCloneVM._storage_dialog_closeNc                 C   s0   t  d¡ |  ¡  | j ¡  |  d ¡ d | _dS )NzClosing clone wizardr   )r   rŠ   r‘   rc   r   r‹   rx   )r(   Úignore1Úignore2r   r   r   Úcloseê   s   


zvmmCloneVM.closec                 C   s   | j |kr|  ¡  d S d S r,   )r)   r”   )r(   Ú_connr)   r   r   r   Ú_vm_removed_cbó   s   
ÿzvmmCloneVM._vm_removed_cbc                 C   s4   | j }|r|j | ¡ |r|j d| j¡ || _ d S )Nz
vm-removed)r)   r@   Údisconnect_by_objÚconnectr–   )r(   ÚnewvmÚoldvmr   r   r   r‹   ÷   s   
zvmmCloneVM._set_vmc                 C   s.   | j  ¡  d | _ | jr| j ¡  d | _d S d S r,   )r{   Údestroyry   Úcleanupr.   r   r   r   Ú_cleanupÿ   s   


þzvmmCloneVM._cleanupc                    s€  ˆ   d¡}t tt¡}| |¡ | d¡ t tdƒ¡}t tdƒ¡}| tj	j
¡ | d¡ | |¡ | |¡ dd„ }| |¡ t ¡ }| dˆ j¡ t ¡ }| d	tjj¡ | |d
¡ | |d
¡ ‡ fdd„}| ||¡ | ||¡ t ¡ }	| d¡ |	 dd¡ |	 dtjj¡ t ¡ }
|
 d	tjj¡ |
 dd¡ | |
d
¡ | |	d¡ ‡ fdd„}| |	|¡ | |
|¡ d S )Nústorage-listr   ÚCloneÚStorageTc                 S   s   | | d dkS )Nr   Ú	separatorr   )Ú_modelÚ_iterr   r   r   Úseparator_cb  s   z)vmmCloneVM._init_ui.<locals>.separator_cbÚtoggledz
stock-sizeFc                    s¸   || d }|dkrd S ˆ j | }| ¡ }| ¡ }|  ¡ d }	|  ¡ d }
|
 d|¡ |
 d|¡ |	 d| ¡ d}| ¡ r@d}|	 d|¡ | ¡ }||| d krZ||| d< d S d S )	Nr   r¡   r   ÚactiveÚvisiblezdialog-informationzdialog-warningú	icon-name)rx   r'   r%   Ú	get_cellsÚset_propertyr4   rK   )ÚcolumnÚcellÚmodelr£   Údatar5   Úsinfor§   r¦   Ú_chkimgÚ_chkboxÚiconÚtooltipr.   r   r   Úchk_cell_data_cb'  s&   
ÿz-vmmCloneVM._init_ui.<locals>.chk_cell_data_cbr   zwidth-charsé   Ú	ellipsizeé   c           
         sf   || d }|dkrd S ˆ j | }|  ¡ d }|  ¡ d }| ˆ j¡}	| d|	¡ | d| ¡ ¡ d S )Nr   r¡   r   rS   r¨   )rx   r©   rT   r)   rª   rW   )
r«   r¬   r­   r£   r®   r5   r¯   Ú_pathimgÚ_pathtxtrS   r.   r   r   Úpath_cbH  s   
z$vmmCloneVM._init_ui.<locals>.path_cb)rz   r   Ú	ListStorerg   Ú	set_modelÚset_tooltip_columnÚTreeViewColumnr   Ú
set_sizingÚTreeViewColumnSizingÚAUTOSIZEÚ
set_expandÚappend_columnÚset_row_separator_funcÚCellRendererToggler˜   Ú_storage_clone_toggled_cbÚCellRendererPixbufrª   ÚIconSizeÚMENUÚ
pack_startÚset_cell_data_funcÚCellRendererTextÚset_sort_column_idr   ÚEllipsizeModeÚMIDDLEÚset_padding)r(   Ústorage_listr­   ÚcloneColÚpathColr¤   ÚchkboxÚchkimgr´   ÚpathtxtÚpathimgrº   r   r.   r   r‰     sB   







zvmmCloneVM._init_uic                 C   sÂ   |   d¡ ¡  |   d¡ d¡ |  ¡ }| ¡  |   d¡ |j¡ |   d¡ |jj¡ t 	|   d¡| j
 ¡ ¡ |   d¡ | j
 ¡ ¡ t ¡ | _| ¡ D ]}t| j||ƒ}|| j| ¡ < qJ|  ¡  d S )Nzclone-cancelúclone-new-namerL   zclone-orig-namezclone-dest-host)rz   Ú
grab_focusÚset_textÚ_build_clonerÚprepareÚsrc_namer   r   r   Úset_grid_row_visibler@   Ú	is_remoteÚget_pretty_descÚcollectionsÚOrderedDictrx   Úget_diskinfosr   r)   r6   Ú_populate_storage_ui)r(   r*   r   r¯   r   r   r   rŒ   W  s   ÿ
zvmmCloneVM._reset_statec                 C   s@   | j  ¡ }| j ¡ }|  d¡ ¡ }t||d}|r| |¡ |S )NrØ   )rÝ   )r@   Úget_backendr)   r   rz   Úget_textr   Úset_clone_name)r(   r@   Ú	orig_nameÚnew_namer*   r   r   r   rÛ   s  s   


zvmmCloneVM._build_clonerc                 C   s0   |   d¡ ¡ }t| j ¡ ƒD ]}| |¡ qd S )NrØ   )rz   ræ   Úlistrx   Úvaluesr>   )r(   Únewnamer¯   r   r   r   Ú_set_paths_from_clone_name  s   ÿz%vmmCloneVM._set_paths_from_clone_namec                 C   sN   |   d¡ ¡ }| ¡  | j ¡ D ]}| | ¡ | ¡ g¡ | ddg¡ qdS )zO
        Fill in the storage UI from the collected StorageInfo classes
        rž   r¡   N)rz   Ú	get_modelÚclearrx   rë   rH   r6   rK   )r(   r­   r¯   r   r   r   rä   †  s   þzvmmCloneVM._populate_storage_uic                 C   sT   |   d¡ ¡ }|| }|d }| j| }| d¡ }| |¡ | d|j|j¡ d S )Nrž   r   r¦   zrow-changed)rz   rî   rx   Úget_propertyr<   ÚemitrP   Úiter)r(   ÚsrcÚtreepathr­   Úrowr5   r¯   r¦   r   r   r   rÆ     s   

z$vmmCloneVM._storage_clone_toggled_cbc                 C   sâ   t  |  d¡¡}| j| }|  ¡  | ¡ }| ¡ }| ¡ }| ¡ }| 	¡ }|  d¡ 
d¡ |  d¡ ¡  |  d¡ |¡ |  d¡ |¡ |  d¡ |pLd¡ |  d¡ 
|¡ |  d¡ |p^d	¡ |  d¡ |¡ |  d
¡ ¡  d S )Nrž   úchange-storage-docloneTzchange-storage-origúchange-storage-targetzchange-storage-sizeú-úchange-storage-newrL   rm   )r   Úget_list_selectionrz   rx   rí   r7   r9   rM   r'   r%   Ú
set_activer¥   rÚ   Úset_sensitiveÚshow_all)r(   Útgtr¯   ÚorigÚnewrZ   Ú	can_cloneÚdo_cloner   r   r   Ú_show_storage_windowž  s"   
zvmmCloneVM._show_storage_windowc                 C   s    |   d¡ ¡ }| j| }|   d¡ ¡ }| |¡ |s |  ¡  d S |   d¡ ¡ }tj | j	j
 ¡ |¡rEtdƒ}tdƒ}| j ||¡}|sEd S | |¡ |  ¡  d S )Nr÷   rö   rù   z(Cloning will overwrite the existing filezqUsing an existing image will overwrite the path during the clone process. Are you sure you want to use this path?)rz   ræ   rx   Ú
get_activer<   r‘   ÚvirtinstÚ
DeviceDiskÚpath_definitely_existsr)   r@   rå   r   re   Úyes_nor=   )r(   r5   r¯   r  Únew_pathÚtext1Útext2Úresr   r   r   Ú_storage_dialog_finish¹  s$   

ÿ
z!vmmCloneVM._storage_dialog_finishc                 C   sž   g }d}| j  ¡ D ]}| ¡ r| | ¡ ¡ q	| ¡ sq	|d| ¡ | ¡ f 7 }q	|rB| j 	t
dƒt
dƒ| j ¡ |dœ ¡}|sBdS | ¡ D ]}| ¡  qFd S )NrL   z%s: %s
z1Sharing storage may cause data to be overwritten.z‰The following disk devices will be shared with %(vmname)s:

%(pathlist)s
Running the new guest could overwrite data in these disk images.)ÚvmnameÚpathlistF)rx   rë   r%   rH   r9   r4   r6   r7   re   Ú	ok_cancelr   r)   r   rã   Úraise_error)r(   r*   Ú	new_pathsÚwarn_strr¯   r  r   r   r   r   Ú	_validateÙ  s0   
ÿ
ÿýþ
ÿzvmmCloneVM._validatec                 C   sR   |   ¡  |d urtdƒ|jj|dœ }| jj||d d S |jdd |  ¡  d S )Nz8Error creating virtual machine clone '%(vm)s': %(error)s)r)   Úerror)ÚdetailsT)Úpollvm)Úreset_finish_cursorr   r   r   re   rf   Úschedule_priority_tickr”   )r(   r  r  r@   r*   r   r   r   Ú
_finish_cbó  s   þÿzvmmCloneVM._finish_cbc           	   	   C   sž   |  ¡ }g }| ¡ D ]}|j}| ¡ }|sq
| ¡ }||vr#| |¡ q
| |¡ |D ]!}z| j |¡}|  	|j
¡ W q+ tyL   tjd|dd Y q+w d S )Nz4Error looking up pool=%s for refresh after VM clone.T)Úexc_info)Ú	get_meterÚget_nonshare_diskinfosr!   Úget_parent_poolr   rH   Ústart_duplicater@   Úget_pool_by_nameÚidle_addÚrefreshrd   r   rŠ   )	r(   Úasyncjobr*   ÚmeterÚrefresh_poolsr   r   ÚpoolÚpoolnamer   r   r   Ú_async_clone  s,   
€

ÿÿüzvmmCloneVM._async_clonec                 C   sn   |   ¡  |  ¡ }| ¡ D ]}|jj}| j| }| |¡ q| ¡  | ¡ D ]}| ¡  q%|  	|¡du r5d S |S r   )
rí   rÛ   rã   r   r5   rx   rE   rÜ   r  r  )r(   r*   r   r5   r¯   r   r   r   Ú_build_final_cloner  s   

zvmmCloneVM._build_final_clonerc              
   C   sº   z|   ¡ }|s
W d S W n  ty+ } ztdƒt|ƒ }| j |¡W  Y d }~S d }~ww |  ¡  tdƒ|jj }|}| 	¡ rFtdƒ|jj }t
| j|g| j| j|g||| jƒ}| ¡  d S )NzError with clone settings: %sz#Creating virtual machine clone '%s'zPCreating virtual machine clone '%s' and selected storage (this may take a while))r)  rd   r   rg   re   rf   Úset_finish_cursorr   r   r  r
   r(  r  r@   rc   Úrun)r(   r*   rk   ÚmsgÚtitleÚtextÚprogWinr   r   r   Ú_finish+  s0   ÿ€þÿþ
þzvmmCloneVM._finishc                 C   ó   |   ¡ S r,   )r”   ©r(   ró   Úeventr   r   r   r   I  r3   zvmmCloneVM._close_cbc                 C   r1  r,   )r0  ©r(   ró   r   r   r   r€   K  r3   zvmmCloneVM._finish_clicked_cbc                 C   s(   t  |  d¡¡}|  d¡ t|ƒ¡ d S )Nrž   zstorage-details-button)r   Úget_list_selected_rowrz   rü   r-   )r(   ró   rõ   r   r   r   r   N  s   z(vmmCloneVM._storage_selection_changed_cbc                 C   ó   |   ¡  d S r,   )r  r4  r   r   r   r‚   R  r/   z&vmmCloneVM._storage_details_clicked_cbc                 C   s,   |  ¡ }|  d¡ |¡ |  d¡ |¡ d S )Nrù   zchange-storage-browse)r  rz   rü   )r(   ró   r  r   r   r   r…   U  s   z-vmmCloneVM._storage_dialog_doclone_toggled_cbc                 C   r1  r,   )r‘   r2  r   r   r   rƒ   Z  r3   z#vmmCloneVM._storage_dialog_close_cbc                 C   r6  r,   )r  r4  r   r   r   r„   \  r/   z$vmmCloneVM._storage_dialog_finish_cbc                    s@   ‡ fdd„}ˆ j d u rtˆ jƒˆ _ ˆ j  |¡ ˆ j  ˆ j¡ d S )Nc                    s   ˆ   d¡ |¡ d S )Nrù   )rz   rÚ   )Ú
src_ignoreÚtxtr.   r   r   Úcallback`  s   z6vmmCloneVM._storage_dialog_browse_cb.<locals>.callback)ry   r   r@   Úset_finish_cbrb   rc   )r(   Úignorer9  r   r.   r   r†   _  s
   
z$vmmCloneVM._storage_dialog_browse_cb)NNr,   )#r[   r\   r]   Úclassmethodrl   r+   Úpropertyr@   rb   r‘   r”   r–   r‹   r   r‰   rŒ   rÛ   rí   rä   rÆ   r  r  r  r  r(  r)  r0  r   r€   r   r‚   r…   rƒ   r„   r†   r   r   r   r   r_   ©   sB    
"

	K
 

r_   )rá   Úgi.repositoryr   r   r  r   r   r   Úlibr   Ú	baseclassr	   r#  r
   Ústoragebrowser   r   r   r_   r   r   r   r   Ú<module>   s    