2014-09-11 19:13:31 +04:00
# Copyright (C) 2009, 2012-2014 Red Hat, Inc.
2009-03-09 23:17:09 +03:00
# Copyright (C) 2009 Cole Robinson <crobinso@redhat.com>
#
2018-04-04 16:35:41 +03:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 22:00:02 +03:00
# See the COPYING file in the top-level directory.
2009-03-09 23:17:09 +03:00
2010-12-10 19:47:07 +03:00
import os
import stat
2009-03-09 23:17:09 +03:00
import traceback
2016-06-07 18:33:21 +03:00
from gi . repository import Gtk
from gi . repository import Gdk
from gi . repository import Pango
2009-03-09 23:17:09 +03:00
import virtinst
2019-06-17 04:12:39 +03:00
from virtinst import log
2019-06-08 01:21:24 +03:00
from virtinst import xmlutil
2009-03-09 23:17:09 +03:00
2014-09-13 00:10:45 +04:00
from . asyncjob import vmmAsyncJob
from . baseclass import vmmGObjectUI
2019-06-17 05:19:17 +03:00
from . lib import uiutil
2009-03-09 23:17:09 +03:00
STORAGE_ROW_CONFIRM = 0
STORAGE_ROW_CANT_DELETE = 1
STORAGE_ROW_PATH = 2
STORAGE_ROW_TARGET = 3
STORAGE_ROW_ICON_SHOW = 4
STORAGE_ROW_ICON = 5
STORAGE_ROW_ICON_SIZE = 6
STORAGE_ROW_TOOLTIP = 7
2013-04-13 22:34:52 +04:00
2020-01-02 11:03:04 +03:00
class _vmmDeleteBase ( vmmGObjectUI ) :
2018-03-15 00:48:17 +03:00
@classmethod
def show_instance ( cls , parentobj , vm ) :
try :
if not cls . _instance :
2018-03-17 23:08:20 +03:00
cls . _instance = vmmDeleteDialog ( )
2018-03-15 00:48:17 +03:00
cls . _instance . show ( parentobj . topwin , vm )
except Exception as e :
parentobj . err . show_err (
_ ( " Error launching delete dialog: %s " ) % str ( e ) )
2011-04-12 00:14:23 +04:00
def __init__ ( self ) :
2013-09-23 00:10:16 +04:00
vmmGObjectUI . __init__ ( self , " delete.ui " , " vmm-delete " )
2011-04-12 00:14:23 +04:00
self . vm = None
2020-01-02 11:03:04 +03:00
self . disk = None
2009-03-09 23:17:09 +03:00
2013-02-16 22:31:46 +04:00
self . builder . connect_signals ( {
2017-08-05 09:39:32 +03:00
" on_vmm_delete_delete_event " : self . close ,
" on_delete_cancel_clicked " : self . close ,
2019-11-20 22:47:07 +03:00
" on_delete_ok_clicked " : self . _finish_clicked_cb ,
" on_delete_remove_storage_toggled " : self . _toggle_remove_storage ,
2009-03-09 23:17:09 +03:00
} )
2011-04-18 19:25:28 +04:00
self . bind_escape_key_close ( )
2018-03-15 14:43:56 +03:00
self . _cleanup_on_app_close ( )
2009-03-09 23:17:09 +03:00
2013-09-27 18:14:53 +04:00
self . _init_state ( )
2009-03-09 23:17:09 +03:00
2020-01-02 11:03:04 +03:00
def _get_dialog_title ( self ) :
raise NotImplementedError
2020-01-02 11:13:57 +03:00
def _get_disk_datas ( self ) :
raise NotImplementedError
2020-01-02 11:49:49 +03:00
def _get_title_text ( self , devs ) :
raise NotImplementedError
2013-09-27 18:14:53 +04:00
def _init_state ( self ) :
blue = Gdk . Color . parse ( " #0072A8 " ) [ 1 ]
self . widget ( " header " ) . modify_bg ( Gtk . StateType . NORMAL , blue )
2009-03-09 23:17:09 +03:00
2019-11-20 22:47:07 +03:00
_prepare_storage_list ( self . widget ( " delete-storage-list " ) )
2009-03-09 23:17:09 +03:00
2018-03-15 00:48:17 +03:00
def show ( self , parent , vm ) :
2019-06-17 04:12:39 +03:00
log . debug ( " Showing delete wizard " )
2018-03-15 14:43:56 +03:00
self . _set_vm ( vm )
2019-11-20 22:47:07 +03:00
self . _reset_state ( )
2011-04-14 16:47:42 +04:00
self . topwin . set_transient_for ( parent )
2009-03-09 23:17:09 +03:00
self . topwin . present ( )
def close ( self , ignore1 = None , ignore2 = None ) :
2019-06-17 04:12:39 +03:00
log . debug ( " Closing delete wizard " )
2009-03-09 23:17:09 +03:00
self . topwin . hide ( )
2018-03-15 14:43:56 +03:00
self . _set_vm ( None )
2009-03-09 23:17:09 +03:00
return 1
2019-12-18 11:39:57 +03:00
2011-07-24 05:16:54 +04:00
def _cleanup ( self ) :
2018-03-15 14:43:56 +03:00
pass
2019-11-20 22:47:07 +03:00
##########################
# Initialization methods #
##########################
2018-03-15 14:43:56 +03:00
def _set_vm ( self , newvm ) :
oldvm = self . vm
if oldvm :
oldvm . conn . disconnect_by_obj ( self )
if newvm :
newvm . conn . connect ( " vm-removed " , self . _vm_removed )
self . vm = newvm
2011-04-13 17:27:02 +04:00
2019-11-20 22:47:07 +03:00
def _reset_state ( self ) :
2019-12-18 11:39:57 +03:00
# Set VM name or disk.target in title'
2020-01-02 11:03:04 +03:00
text = self . _get_dialog_title ( )
2019-12-18 11:39:57 +03:00
2013-09-27 18:14:53 +04:00
title_str = ( " <span size= ' large ' color= ' white ' > %s ' %s ' </span> " %
2019-12-18 11:39:57 +03:00
( _ ( " Delete " ) , xmlutil . xml_escape ( text ) ) )
2013-09-27 18:14:53 +04:00
self . widget ( " header-label " ) . set_markup ( title_str )
2009-03-09 23:17:09 +03:00
2015-05-21 00:42:45 +03:00
self . topwin . resize ( 1 , 1 )
2011-07-14 21:13:13 +04:00
self . widget ( " delete-cancel " ) . grab_focus ( )
2009-12-15 00:48:35 +03:00
2013-06-18 07:29:20 +04:00
# Show warning message if VM is running
2019-12-19 12:35:08 +03:00
vm_active = self . vm . is_active ( ) and not self . disk
2014-01-27 03:15:50 +04:00
uiutil . set_grid_row_visible (
2013-09-27 18:14:53 +04:00
self . widget ( " delete-warn-running-vm-box " ) , vm_active )
2013-06-18 07:29:20 +04:00
2014-02-17 17:11:49 +04:00
# Enable storage removal by default
2012-12-03 20:12:59 +04:00
self . widget ( " delete-remove-storage " ) . set_active ( True )
2011-07-14 21:13:13 +04:00
self . widget ( " delete-remove-storage " ) . toggled ( )
2020-01-02 11:13:57 +03:00
diskdatas = self . _get_disk_datas ( )
2019-11-20 22:47:07 +03:00
_populate_storage_list ( self . widget ( " delete-storage-list " ) ,
2019-11-20 23:22:03 +03:00
self . vm , self . vm . conn , diskdatas )
2019-11-20 22:47:07 +03:00
################
# UI listeners #
################
def _finish_clicked_cb ( self , src ) :
self . _finish ( )
2009-03-09 23:17:09 +03:00
2019-11-20 22:47:07 +03:00
def _vm_removed ( self , _conn , connkey ) :
if self . vm . get_connkey ( ) == connkey :
self . close ( )
def _toggle_remove_storage ( self , src ) :
2013-09-27 18:14:53 +04:00
dodel = src . get_active ( )
2014-01-27 03:15:50 +04:00
uiutil . set_grid_row_visible (
2013-09-27 18:14:53 +04:00
self . widget ( " delete-storage-scroll " ) , dodel )
2019-11-20 22:47:07 +03:00
#########################
# finish/delete methods #
#########################
def _get_paths_to_delete ( self ) :
2011-07-14 21:13:13 +04:00
del_list = self . widget ( " delete-storage-list " )
2009-03-09 23:17:09 +03:00
model = del_list . get_model ( )
paths = [ ]
2011-07-14 21:13:13 +04:00
if self . widget ( " delete-remove-storage " ) . get_active ( ) :
2009-03-09 23:17:09 +03:00
for row in model :
if ( not row [ STORAGE_ROW_CANT_DELETE ] and
row [ STORAGE_ROW_CONFIRM ] ) :
paths . append ( row [ STORAGE_ROW_PATH ] )
return paths
2019-11-20 22:47:07 +03:00
def _delete_finished_cb ( self , error , details ) :
2017-04-27 22:00:17 +03:00
self . reset_finish_cursor ( )
2013-09-07 04:59:01 +04:00
if error is not None :
self . err . show_err ( error , details = details )
self . close ( )
2019-11-20 22:47:07 +03:00
def _finish ( self ) :
devs = self . _get_paths_to_delete ( )
2009-03-09 23:17:09 +03:00
2012-12-03 20:12:59 +04:00
if devs :
2013-09-27 18:14:53 +04:00
title = _ ( " Are you sure you want to delete the storage? " )
message = ( _ ( " The following paths will be deleted: \n \n %s " ) %
" \n " . join ( devs ) )
2014-01-27 02:42:24 +04:00
ret = self . err . chkbox_helper (
self . config . get_confirm_delstorage ,
self . config . set_confirm_delstorage ,
text1 = title , text2 = message )
2012-12-03 20:12:59 +04:00
if not ret :
return
2017-04-27 22:00:17 +03:00
self . set_finish_cursor ( )
2020-01-02 11:49:49 +03:00
title , text = self . _get_title_text ( devs )
2009-03-09 23:17:09 +03:00
2018-03-15 14:43:56 +03:00
progWin = vmmAsyncJob ( self . _async_delete , [ self . vm , devs ] ,
2019-11-20 22:47:07 +03:00
self . _delete_finished_cb , [ ] ,
2011-04-14 16:47:42 +04:00
title , text , self . topwin )
2013-09-07 04:59:01 +04:00
progWin . run ( )
2018-03-15 14:43:56 +03:00
self . _set_vm ( None )
2009-03-09 23:17:09 +03:00
2018-03-15 14:43:56 +03:00
def _async_delete ( self , asyncjob , vm , paths ) :
2009-03-09 23:17:09 +03:00
storage_errors = [ ]
2011-03-24 19:59:40 +03:00
details = " "
2018-03-15 14:43:56 +03:00
undefine = vm . is_persistent ( )
2009-03-09 23:17:09 +03:00
try :
2018-03-15 14:43:56 +03:00
if vm . is_active ( ) :
2019-06-17 04:12:39 +03:00
log . debug ( " Forcing VM ' %s ' power off. " , vm . get_name ( ) )
2018-03-15 14:43:56 +03:00
vm . destroy ( )
2013-06-18 07:29:20 +04:00
2018-03-15 14:43:56 +03:00
conn = vm . conn . get_backend ( )
2012-02-10 19:24:43 +04:00
meter = asyncjob . get_meter ( )
2019-12-18 11:39:57 +03:00
if not paths and self . disk :
vm . remove_device ( self . disk )
2009-03-09 23:17:09 +03:00
for path in paths :
try :
2019-06-17 04:12:39 +03:00
log . debug ( " Deleting path: %s " , path )
2010-12-10 19:47:07 +03:00
meter . start ( text = _ ( " Deleting path ' %s ' " ) % path )
2019-12-18 11:39:57 +03:00
self . _async_delete_dev ( vm , conn , path , meter )
2017-05-05 19:47:21 +03:00
except Exception as e :
2009-03-09 23:17:09 +03:00
storage_errors . append ( ( str ( e ) ,
" " . join ( traceback . format_exc ( ) ) ) )
meter . end ( 0 )
2019-12-18 11:39:57 +03:00
if undefine and not self . disk :
2019-06-17 04:12:39 +03:00
log . debug ( " Removing VM ' %s ' " , vm . get_name ( ) )
2018-03-15 14:43:56 +03:00
vm . delete ( )
2009-03-09 23:17:09 +03:00
2017-05-05 19:47:21 +03:00
except Exception as e :
2009-04-03 22:15:15 +04:00
error = ( _ ( " Error deleting virtual machine ' %s ' : %s " ) %
2018-03-15 14:43:56 +03:00
( vm . get_name ( ) , str ( e ) ) )
2009-04-03 22:15:15 +04:00
details = " " . join ( traceback . format_exc ( ) )
2009-03-09 23:17:09 +03:00
storage_errstr = " "
for errinfo in storage_errors :
storage_errstr + = " %s \n %s \n " % ( errinfo [ 0 ] , errinfo [ 1 ] )
2011-08-29 22:01:40 +04:00
if not storage_errstr and not details :
2009-03-09 23:17:09 +03:00
return
# We had extra storage errors. If there was another error message,
# errors to it. Otherwise, build the main error around them.
2009-04-03 22:15:15 +04:00
if details :
details + = " \n \n "
details + = _ ( " Additionally, there were errors removing "
2009-03-09 23:17:09 +03:00
" certain storage devices: \n " )
2009-04-03 22:15:15 +04:00
details + = storage_errstr
2009-03-09 23:17:09 +03:00
else :
2009-04-03 22:15:15 +04:00
error = _ ( " Errors encountered while removing certain "
2009-03-09 23:17:09 +03:00
" storage devices. " )
2009-04-03 22:15:15 +04:00
details = storage_errstr
if error :
asyncjob . set_error ( error , details )
2018-03-15 14:43:56 +03:00
vm . conn . schedule_priority_tick ( pollvm = True )
2009-03-09 23:17:09 +03:00
2019-12-18 11:39:57 +03:00
def _async_delete_dev ( self , vm , conn , path , ignore ) :
2009-03-09 23:17:09 +03:00
vol = None
try :
vol = conn . storageVolLookupByPath ( path )
2017-07-24 11:26:48 +03:00
except Exception :
2019-06-17 04:12:39 +03:00
log . debug ( " Path ' %s ' is not managed. Deleting locally " , path )
2009-03-09 23:17:09 +03:00
if vol :
vol . delete ( 0 )
else :
os . unlink ( path )
2019-12-18 11:39:57 +03:00
self . _async_delete_xmldev ( vm , path , ignore )
def _async_delete_xmldev ( self , vm , path , ignore ) :
for d in vm . xmlobj . devices . disk :
if d . path == path :
dev = d
break
vm . remove_device ( dev )
2009-03-09 23:17:09 +03:00
2020-01-02 11:03:04 +03:00
class vmmDeleteDialog ( _vmmDeleteBase ) :
def _get_dialog_title ( self ) :
return self . vm . get_name ( )
2020-01-02 11:13:57 +03:00
def _get_disk_datas ( self ) :
return _build_diskdata_for_vm ( self . vm )
2020-01-02 11:49:49 +03:00
def _get_title_text ( self , devs ) :
if devs :
title = _ ( " Deleting virtual machine ' %s ' and selected storage "
" (this may take a while) " ) % self . vm . get_name ( )
text = title
else :
title = _ ( " Deleting virtual machine ' %s ' " ) % self . vm . get_name ( )
text = title
return [ title , text ]
2020-01-02 11:03:04 +03:00
class vmmDeleteStorage ( _vmmDeleteBase ) :
def __init__ ( self , disk ) :
_vmmDeleteBase . __init__ ( self )
self . disk = disk
def _get_dialog_title ( self ) :
return self . disk . target
2020-01-02 11:13:57 +03:00
def _get_disk_datas ( self ) :
return [ _DiskData . from_disk ( self . disk ) ]
2020-01-02 11:49:49 +03:00
def _get_title_text ( self , devs ) :
title = _ ( " Deleting the selected storage " )
text = _ ( ' %s ' ) % self . disk . target
return [ title , text ]
2020-01-02 11:03:04 +03:00
2019-11-20 22:47:07 +03:00
###################
# UI init helpers #
###################
2019-11-20 23:22:03 +03:00
class _DiskData :
"""
Helper class to contain all info we need to decide whether we
should default to deleting a path
"""
@staticmethod
def from_disk ( disk ) :
"""
Build _DiskData from a DeviceDisk object
"""
return _DiskData (
disk . target ,
disk . path ,
disk . read_only ,
disk . shareable ,
disk . device in [ " cdrom " , " floppy " ] )
def __init__ ( self , label , path , ro , shared , is_media ) :
self . label = label
self . path = path
self . ro = ro
self . shared = shared
self . is_media = is_media
def _build_diskdata_for_vm ( vm ) :
"""
Return a list of _DiskData for all VM resources the app attempts to delete
"""
diskdatas = [ ]
for disk in vm . xmlobj . devices . disk :
diskdatas . append ( _DiskData . from_disk ( disk ) )
diskdatas . append (
_DiskData ( " kernel " , vm . get_xmlobj ( ) . os . kernel , True , False , True ) )
diskdatas . append (
_DiskData ( " initrd " , vm . get_xmlobj ( ) . os . initrd , True , False , True ) )
diskdatas . append (
_DiskData ( " dtb " , vm . get_xmlobj ( ) . os . dtb , True , False , True ) )
return diskdatas
def _populate_storage_list ( storage_list , vm , conn , diskdatas ) :
"""
Fill in the storage list UI from the passed list of _DiskData
"""
2009-03-09 23:17:09 +03:00
model = storage_list . get_model ( )
model . clear ( )
2019-11-20 23:22:03 +03:00
for diskdata in diskdatas :
if not diskdata . path :
2014-01-15 02:26:29 +04:00
continue
2009-03-09 23:17:09 +03:00
# There are a few pieces here
# 1) Can we even delete the storage? If not, make the checkbox
# inconsistent. self.can_delete decides this for us, and if
# we can't delete, gives us a nice message to show the user
# for that row.
#
# 2) If we can delete, do we want to delete this storage by
# default? Reasons not to, are if the storage is marked
2014-02-26 05:36:16 +04:00
# readonly or shareable, or is in use by another VM.
2009-03-09 23:17:09 +03:00
default = False
definfo = None
2019-11-20 23:22:03 +03:00
vol = conn . get_vol_by_path ( diskdata . path )
can_del , delinfo = _can_delete ( conn , vol , diskdata . path )
2009-03-09 23:17:09 +03:00
if can_del :
2019-11-20 22:47:07 +03:00
default , definfo = _do_we_default ( conn , vm . get_name ( ) , vol ,
2019-11-20 23:22:03 +03:00
diskdata )
2009-03-09 23:17:09 +03:00
info = None
if not can_del :
info = delinfo
elif not default :
info = definfo
2012-05-14 17:24:56 +04:00
icon = Gtk . STOCK_DIALOG_WARNING
icon_size = Gtk . IconSize . LARGE_TOOLBAR
2009-03-09 23:17:09 +03:00
2019-11-20 23:22:03 +03:00
row = [ default , not can_del , diskdata . path , diskdata . label ,
2009-03-09 23:17:09 +03:00
bool ( info ) , icon , icon_size , info ]
model . append ( row )
2019-11-20 22:47:07 +03:00
def _prepare_storage_list ( storage_list ) :
2009-03-09 23:17:09 +03:00
# Checkbox, deleteable?, storage path, target (hda), icon stock,
# icon size, tooltip
2012-05-14 17:24:56 +04:00
model = Gtk . ListStore ( bool , bool , str , str , bool , str , int , str )
2009-03-09 23:17:09 +03:00
storage_list . set_model ( model )
2013-04-17 17:09:53 +04:00
storage_list . set_tooltip_column ( STORAGE_ROW_TOOLTIP )
2009-03-09 23:17:09 +03:00
2012-05-14 17:24:56 +04:00
confirmCol = Gtk . TreeViewColumn ( )
targetCol = Gtk . TreeViewColumn ( _ ( " Target " ) )
infoCol = Gtk . TreeViewColumn ( )
2015-05-21 00:42:45 +03:00
pathCol = Gtk . TreeViewColumn ( _ ( " Storage Path " ) )
pathCol . set_sizing ( Gtk . TreeViewColumnSizing . AUTOSIZE )
pathCol . set_expand ( True )
2009-03-09 23:17:09 +03:00
storage_list . append_column ( confirmCol )
storage_list . append_column ( pathCol )
storage_list . append_column ( targetCol )
storage_list . append_column ( infoCol )
2012-05-14 17:24:56 +04:00
chkbox = Gtk . CellRendererToggle ( )
2019-11-20 22:47:07 +03:00
chkbox . connect ( ' toggled ' , _storage_item_toggled , storage_list )
2009-03-09 23:17:09 +03:00
confirmCol . pack_start ( chkbox , False )
confirmCol . add_attribute ( chkbox , ' active ' , STORAGE_ROW_CONFIRM )
confirmCol . add_attribute ( chkbox , ' inconsistent ' ,
STORAGE_ROW_CANT_DELETE )
confirmCol . set_sort_column_id ( STORAGE_ROW_CANT_DELETE )
2012-05-14 17:24:56 +04:00
path_txt = Gtk . CellRendererText ( )
2009-03-09 23:17:09 +03:00
pathCol . pack_start ( path_txt , True )
pathCol . add_attribute ( path_txt , ' text ' , STORAGE_ROW_PATH )
pathCol . set_sort_column_id ( STORAGE_ROW_PATH )
2015-05-21 00:42:45 +03:00
path_txt . set_property ( " width-chars " , 50 )
path_txt . set_property ( " ellipsize " , Pango . EllipsizeMode . MIDDLE )
2009-03-09 23:17:09 +03:00
2012-05-14 17:24:56 +04:00
target_txt = Gtk . CellRendererText ( )
2009-03-09 23:17:09 +03:00
targetCol . pack_start ( target_txt , False )
targetCol . add_attribute ( target_txt , ' text ' , STORAGE_ROW_TARGET )
targetCol . set_sort_column_id ( STORAGE_ROW_TARGET )
2012-05-14 17:24:56 +04:00
info_img = Gtk . CellRendererPixbuf ( )
2009-03-09 23:17:09 +03:00
infoCol . pack_start ( info_img , False )
infoCol . add_attribute ( info_img , ' visible ' , STORAGE_ROW_ICON_SHOW )
infoCol . add_attribute ( info_img , ' stock-id ' , STORAGE_ROW_ICON )
infoCol . add_attribute ( info_img , ' stock-size ' , STORAGE_ROW_ICON_SIZE )
infoCol . set_sort_column_id ( STORAGE_ROW_ICON )
2013-04-13 22:34:52 +04:00
2019-11-20 22:47:07 +03:00
def _storage_item_toggled ( src , index , storage_list ) :
2009-03-09 23:17:09 +03:00
active = src . get_active ( )
model = storage_list . get_model ( )
model [ index ] [ STORAGE_ROW_CONFIRM ] = not active
2013-04-13 22:34:52 +04:00
2019-11-20 22:47:07 +03:00
def _can_delete ( conn , vol , path ) :
2009-03-09 23:17:09 +03:00
""" Is the passed path even deleteable """
ret = True
msg = None
if vol :
# Managed storage
2017-03-06 11:28:52 +03:00
pool_type = vol . get_parent_pool ( ) . get_type ( )
if pool_type == virtinst . StoragePool . TYPE_ISCSI :
2009-03-09 23:17:09 +03:00
msg = _ ( " Cannot delete iscsi share. " )
2017-03-06 11:28:52 +03:00
elif pool_type == virtinst . StoragePool . TYPE_SCSI :
msg = _ ( " Cannot delete SCSI device. " )
2009-03-09 23:17:09 +03:00
else :
if conn . is_remote ( ) :
msg = _ ( " Cannot delete unmanaged remote storage. " )
elif not os . path . exists ( path ) :
msg = _ ( " Path does not exist. " )
elif not os . access ( os . path . dirname ( path ) , os . W_OK ) :
msg = _ ( " No write access to parent directory. " )
elif stat . S_ISBLK ( os . stat ( path ) [ stat . ST_MODE ] ) :
msg = _ ( " Cannot delete unmanaged block device. " )
if msg :
ret = False
return ( ret , msg )
2013-04-13 22:34:52 +04:00
2019-11-20 23:22:03 +03:00
def _do_we_default ( conn , vm_name , vol , diskdata ) :
2009-03-09 23:17:09 +03:00
""" Returns (do we delete by default?, info string if not) """
info = " "
def append_str ( str1 , str2 , delim = " \n " ) :
if not str2 :
return str1
if str1 :
str1 + = delim
str1 + = str2
return str1
2019-11-20 23:22:03 +03:00
if diskdata . ro :
2009-03-09 23:17:09 +03:00
info = append_str ( info , _ ( " Storage is read-only. " ) )
2019-11-20 23:22:03 +03:00
elif not vol and not os . access ( diskdata . path , os . W_OK ) :
2009-03-09 23:17:09 +03:00
info = append_str ( info , _ ( " No write access to path. " ) )
2019-11-20 23:22:03 +03:00
if diskdata . shared :
2009-03-09 23:17:09 +03:00
info = append_str ( info , _ ( " Storage is marked as shareable. " ) )
2019-11-20 23:22:03 +03:00
if not info and diskdata . is_media :
2016-06-17 20:06:35 +03:00
info = append_str ( info , _ ( " Storage is a media device. " ) )
2009-03-09 23:17:09 +03:00
try :
2019-11-20 23:22:03 +03:00
names = virtinst . DeviceDisk . path_in_use_by ( conn . get_backend ( ) ,
diskdata . path )
2009-03-09 23:17:09 +03:00
if len ( names ) > 1 :
namestr = " "
names . remove ( vm_name )
for name in names :
namestr = append_str ( namestr , name , delim = " \n - " )
info = append_str ( info , _ ( " Storage is in use by the following "
" virtual machines: \n - %s " % namestr ) )
2017-05-05 19:47:21 +03:00
except Exception as e :
2019-06-17 04:12:39 +03:00
log . exception ( " Failed checking disk conflict: %s " , str ( e ) )
2009-03-09 23:17:09 +03:00
return ( not info , info )