2015-04-09 01:29:48 +03:00
#
# Copyright (C) 2015 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
#
import logging
from gi . repository import Gdk
from gi . repository import Gtk
from gi . repository import GObject
from virtinst import StoragePool
from virtinst import VirtualDisk
from . import uiutil
from . asyncjob import vmmAsyncJob
from . baseclass import vmmGObjectUI
from . createpool import vmmCreatePool
from . createvol import vmmCreateVolume
EDIT_POOL_IDS = (
EDIT_POOL_NAME ,
EDIT_POOL_AUTOSTART ,
) = range ( 2 )
2015-04-11 22:08:07 +03:00
VOL_NUM_COLUMNS = 7
2015-04-09 01:29:48 +03:00
( VOL_COLUMN_KEY ,
VOL_COLUMN_NAME ,
VOL_COLUMN_CAPACITY ,
2015-04-11 22:08:07 +03:00
VOL_COLUMN_SIZESTR ,
2015-04-09 01:29:48 +03:00
VOL_COLUMN_FORMAT ,
VOL_COLUMN_INUSEBY ,
VOL_COLUMN_SENSITIVE ) = range ( VOL_NUM_COLUMNS )
POOL_NUM_COLUMNS = 4
( POOL_COLUMN_CONNKEY ,
POOL_COLUMN_LABEL ,
POOL_COLUMN_ISACTIVE ,
POOL_COLUMN_PERCENT ) = range ( POOL_NUM_COLUMNS )
ICON_RUNNING = " state_running "
ICON_SHUTOFF = " state_shutoff "
def _get_pool_size_percent ( pool ) :
cap = pool . get_capacity ( )
alloc = pool . get_allocation ( )
if not cap or alloc is None :
per = 0
else :
per = int ( ( ( float ( alloc ) / float ( cap ) ) * 100 ) )
return " <span size= ' small ' color= ' #484848 ' > %s %% </span> " % int ( per )
class vmmStorageList ( vmmGObjectUI ) :
__gsignals__ = {
" browse-clicked " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
" volume-chosen " : ( GObject . SignalFlags . RUN_FIRST , None , [ object ] ) ,
" cancel-clicked " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
}
def __init__ ( self , conn , builder , topwin , vol_sensitive_cb = None ) :
vmmGObjectUI . __init__ ( self , " storagelist.ui " ,
None , builder = builder , topwin = topwin )
self . conn = conn
# Callback function for setting volume row sensitivity. Used
# by storage browser to disallow selecting certain volumes
self . _vol_sensitive_cb = vol_sensitive_cb
# Name hint passed to addvol. Set by storagebrowser
self . _name_hint = None
self . _active_edits = [ ]
self . _addpool = None
self . _addvol = None
self . _volmenu = None
self . top_box = self . widget ( " storage-grid " )
self . builder . connect_signals ( {
" on_pool_add_clicked " : self . _pool_add ,
" on_pool_stop_clicked " : self . _pool_stop ,
" on_pool_start_clicked " : self . _pool_start ,
" on_pool_delete_clicked " : self . _pool_delete ,
" on_pool_refresh_clicked " : self . _pool_refresh ,
" on_pool_apply_clicked " : ( lambda * x : self . _pool_apply ( ) ) ,
" on_vol_delete_clicked " : self . _vol_delete ,
" on_vol_list_button_press_event " : self . _vol_popup_menu ,
" on_vol_list_changed " : self . _vol_selected ,
" on_vol_add_clicked " : self . _vol_add ,
" on_browse_cancel_clicked " : self . _cancel_clicked ,
" on_browse_local_clicked " : self . _browse_local_clicked ,
" on_choose_volume_clicked " : self . _choose_volume_clicked ,
" on_vol_list_row_activated " : self . _vol_list_row_activated ,
" on_pool_name_changed " : ( lambda * x :
self . _enable_pool_apply ( x , EDIT_POOL_NAME ) ) ,
" on_pool_autostart_toggled " : self . _pool_autostart_changed ,
} )
self . _init_ui ( )
def _cleanup ( self ) :
2015-04-10 23:53:19 +03:00
try :
self . conn . disconnect_by_func ( self . _conn_pool_count_changed )
self . conn . disconnect_by_func ( self . _conn_pool_count_changed )
self . conn . disconnect_by_func ( self . _conn_state_changed )
except :
pass
2015-04-09 01:29:48 +03:00
self . conn = None
if self . _addpool :
self . _addpool . cleanup ( )
self . _addpool = None
if self . _addvol :
self . _addvol . cleanup ( )
self . _addvol = None
self . _volmenu . destroy ( )
self . _volmenu = None
def close ( self , ignore1 = None , ignore2 = None ) :
if self . _addvol :
self . _addvol . close ( )
if self . _addpool :
self . _addpool . close ( )
if self . _volmenu :
self . _volmenu . hide ( )
##########################
# Initialization methods #
##########################
2015-04-11 22:08:07 +03:00
def _cap_sort_func ( self , model , iter1 , iter2 , ignore ) :
return cmp ( int ( model [ iter1 ] [ VOL_COLUMN_CAPACITY ] ) ,
int ( model [ iter2 ] [ VOL_COLUMN_CAPACITY ] ) )
2015-04-09 01:29:48 +03:00
def _init_ui ( self ) :
self . widget ( " storage-pages " ) . set_show_tabs ( False )
# These are enabled in storagebrowser.py
self . widget ( " browse-local " ) . set_visible ( False )
self . widget ( " browse-cancel " ) . set_visible ( False )
self . widget ( " choose-volume " ) . set_visible ( False )
# Volume list popup menu
self . _volmenu = Gtk . Menu ( )
volCopyPath = Gtk . ImageMenuItem . new_with_label ( _ ( " Copy Volume Path " ) )
volCopyImage = Gtk . Image ( )
volCopyImage . set_from_stock ( Gtk . STOCK_COPY , Gtk . IconSize . MENU )
volCopyPath . set_image ( volCopyImage )
volCopyPath . show ( )
volCopyPath . connect ( " activate " , self . _vol_copy_path )
self . _volmenu . add ( volCopyPath )
# Volume list
2015-04-11 22:08:07 +03:00
# [key, name, sizestr, capacity, format, in use by string, sensitive]
volListModel = Gtk . ListStore ( str , str , str , str , str , str , bool )
2015-04-09 01:29:48 +03:00
self . widget ( " vol-list " ) . set_model ( volListModel )
2016-02-05 18:18:16 +03:00
volCol = Gtk . TreeViewColumn ( _ ( " Volumes " ) )
2015-04-09 01:29:48 +03:00
vol_txt1 = Gtk . CellRendererText ( )
volCol . pack_start ( vol_txt1 , True )
volCol . add_attribute ( vol_txt1 , ' text ' , VOL_COLUMN_NAME )
volCol . add_attribute ( vol_txt1 , ' sensitive ' , VOL_COLUMN_SENSITIVE )
volCol . set_sort_column_id ( VOL_COLUMN_NAME )
self . widget ( " vol-list " ) . append_column ( volCol )
2016-02-05 18:18:16 +03:00
volSizeCol = Gtk . TreeViewColumn ( _ ( " Size " ) )
2015-04-09 01:29:48 +03:00
vol_txt2 = Gtk . CellRendererText ( )
volSizeCol . pack_start ( vol_txt2 , False )
2015-04-11 22:08:07 +03:00
volSizeCol . add_attribute ( vol_txt2 , ' text ' , VOL_COLUMN_SIZESTR )
2015-04-09 01:29:48 +03:00
volSizeCol . add_attribute ( vol_txt2 , ' sensitive ' , VOL_COLUMN_SENSITIVE )
volSizeCol . set_sort_column_id ( VOL_COLUMN_CAPACITY )
self . widget ( " vol-list " ) . append_column ( volSizeCol )
2015-04-11 22:08:07 +03:00
volListModel . set_sort_func ( VOL_COLUMN_CAPACITY , self . _cap_sort_func )
2015-04-09 01:29:48 +03:00
2016-02-05 18:18:16 +03:00
volFormatCol = Gtk . TreeViewColumn ( _ ( " Format " ) )
2015-04-09 01:29:48 +03:00
vol_txt3 = Gtk . CellRendererText ( )
volFormatCol . pack_start ( vol_txt3 , False )
volFormatCol . add_attribute ( vol_txt3 , ' text ' , VOL_COLUMN_FORMAT )
volFormatCol . add_attribute ( vol_txt3 , ' sensitive ' , VOL_COLUMN_SENSITIVE )
volFormatCol . set_sort_column_id ( VOL_COLUMN_FORMAT )
self . widget ( " vol-list " ) . append_column ( volFormatCol )
2016-02-05 18:18:16 +03:00
volUseCol = Gtk . TreeViewColumn ( _ ( " Used By " ) )
2015-04-09 01:29:48 +03:00
vol_txt4 = Gtk . CellRendererText ( )
volUseCol . pack_start ( vol_txt4 , False )
volUseCol . add_attribute ( vol_txt4 , ' text ' , VOL_COLUMN_INUSEBY )
volUseCol . add_attribute ( vol_txt4 , ' sensitive ' , VOL_COLUMN_SENSITIVE )
volUseCol . set_sort_column_id ( VOL_COLUMN_INUSEBY )
self . widget ( " vol-list " ) . append_column ( volUseCol )
volListModel . set_sort_column_id ( VOL_COLUMN_NAME ,
Gtk . SortType . ASCENDING )
# Init pool list
# [connkey, label, pool.is_active(), percent string]
pool_list = self . widget ( " pool-list " )
poolListModel = Gtk . ListStore ( str , str , bool , str )
pool_list . set_model ( poolListModel )
2016-02-05 18:18:16 +03:00
poolCol = Gtk . TreeViewColumn ( _ ( " Storage Pools " ) )
2015-04-09 01:29:48 +03:00
pool_txt = Gtk . CellRendererText ( )
pool_per = Gtk . CellRendererText ( )
poolCol . pack_start ( pool_per , False )
poolCol . pack_start ( pool_txt , True )
poolCol . add_attribute ( pool_txt , ' markup ' , POOL_COLUMN_LABEL )
poolCol . add_attribute ( pool_txt , ' sensitive ' , POOL_COLUMN_ISACTIVE )
poolCol . add_attribute ( pool_per , ' markup ' , POOL_COLUMN_PERCENT )
pool_list . append_column ( poolCol )
poolListModel . set_sort_column_id ( POOL_COLUMN_LABEL ,
Gtk . SortType . ASCENDING )
pool_list . get_selection ( ) . connect ( " changed " , self . _pool_selected )
pool_list . get_selection ( ) . set_select_function (
( lambda * x : self . _confirm_changes ( ) ) , None )
# Populate list and connect conn signals
self . _populate_pools ( )
2015-04-09 21:42:25 +03:00
self . conn . connect ( " pool-added " , self . _conn_pool_count_changed )
self . conn . connect ( " pool-removed " , self . _conn_pool_count_changed )
2015-04-09 01:29:48 +03:00
self . conn . connect ( " state-changed " , self . _conn_state_changed )
self . _conn_state_changed ( )
###############
# Public APIs #
###############
def refresh_page ( self ) :
self . _populate_vols ( )
self . conn . schedule_priority_tick ( pollpool = True )
def set_name_hint ( self , val ) :
self . _name_hint = val
####################
# Internal helpers #
####################
def _current_pool ( self ) :
2015-05-20 00:17:53 +03:00
connkey = uiutil . get_list_selection ( self . widget ( " pool-list " ) )
2015-05-07 18:23:00 +03:00
return connkey and self . conn . get_pool ( connkey )
2015-04-09 01:29:48 +03:00
def _current_vol ( self ) :
pool = self . _current_pool ( )
if not pool :
return None
2015-05-20 00:17:53 +03:00
connkey = uiutil . get_list_selection ( self . widget ( " vol-list " ) )
2015-05-07 18:23:00 +03:00
return connkey and pool . get_volume ( connkey )
2015-04-09 01:29:48 +03:00
def _enable_pool_apply ( self , * arglist ) :
edittype = arglist [ - 1 ]
self . widget ( " pool-apply " ) . set_sensitive ( True )
if edittype not in self . _active_edits :
self . _active_edits . append ( edittype )
def _disable_pool_apply ( self ) :
for i in EDIT_POOL_IDS :
if i in self . _active_edits :
self . _active_edits . remove ( i )
self . widget ( " pool-apply " ) . set_sensitive ( False )
2015-04-09 21:42:25 +03:00
def _update_pool_row ( self , connkey ) :
2015-04-09 01:29:48 +03:00
for row in self . widget ( " pool-list " ) . get_model ( ) :
if row [ POOL_COLUMN_CONNKEY ] != connkey :
continue
# Update active sensitivity and percent available for passed key
pool = self . conn . get_pool ( connkey )
row [ POOL_COLUMN_ISACTIVE ] = pool . is_active ( )
row [ POOL_COLUMN_PERCENT ] = _get_pool_size_percent ( pool )
break
curpool = self . _current_pool ( )
2015-04-10 16:31:13 +03:00
if not curpool or curpool . get_connkey ( ) != connkey :
2015-04-09 01:29:48 +03:00
return
# Currently selected pool changed state: force a 'pool_selected' to
# update vol list
self . _pool_selected ( self . widget ( " pool-list " ) . get_selection ( ) )
def _reset_pool_state ( self ) :
self . widget ( " pool-details " ) . set_sensitive ( False )
self . widget ( " pool-name-entry " ) . set_text ( " " )
2015-04-11 01:40:54 +03:00
self . widget ( " pool-sizes " ) . set_markup ( " " )
2015-04-09 01:29:48 +03:00
self . widget ( " pool-location " ) . set_text ( " " )
self . widget ( " pool-state-icon " ) . set_from_icon_name (
ICON_SHUTOFF , Gtk . IconSize . BUTTON )
self . widget ( " pool-state " ) . set_text ( _ ( " Inactive " ) )
self . widget ( " vol-list " ) . get_model ( ) . clear ( )
self . widget ( " pool-autostart " ) . set_label ( _ ( " Never " ) )
self . widget ( " pool-autostart " ) . set_active ( False )
self . widget ( " pool-delete " ) . set_sensitive ( False )
self . widget ( " pool-stop " ) . set_sensitive ( False )
self . widget ( " pool-start " ) . set_sensitive ( False )
2015-04-11 01:20:13 +03:00
self . widget ( " pool-refresh " ) . set_sensitive ( False )
2015-04-09 01:29:48 +03:00
self . widget ( " vol-add " ) . set_sensitive ( False )
self . widget ( " vol-delete " ) . set_sensitive ( False )
self . widget ( " vol-list " ) . set_sensitive ( False )
self . _disable_pool_apply ( )
def _populate_pool_state ( self , connkey ) :
pool = self . conn . get_pool ( connkey )
auto = pool . get_autostart ( )
active = pool . is_active ( )
# Set pool details state
self . widget ( " pool-details " ) . set_sensitive ( True )
self . widget ( " pool-name-entry " ) . set_text ( pool . get_name ( ) )
self . widget ( " pool-name-entry " ) . set_editable ( not active )
self . widget ( " pool-sizes " ) . set_markup (
2016-07-26 10:32:14 +03:00
_ ( " %s Free / <i> %s In Use</i> " ) %
2015-04-09 01:29:48 +03:00
( pool . get_pretty_available ( ) , pool . get_pretty_allocation ( ) ) )
self . widget ( " pool-location " ) . set_text (
pool . get_target_path ( ) )
self . widget ( " pool-state-icon " ) . set_from_icon_name (
( ( active and ICON_RUNNING ) or ICON_SHUTOFF ) ,
Gtk . IconSize . BUTTON )
self . widget ( " pool-state " ) . set_text (
( active and _ ( " Active " ) ) or _ ( " Inactive " ) )
self . widget ( " pool-autostart " ) . set_label (
( auto and _ ( " On Boot " ) ) or _ ( " Never " ) )
self . widget ( " pool-autostart " ) . set_active ( auto )
self . widget ( " vol-list " ) . set_sensitive ( active )
self . _populate_vols ( )
self . widget ( " pool-delete " ) . set_sensitive ( not active )
self . widget ( " pool-stop " ) . set_sensitive ( active )
self . widget ( " pool-start " ) . set_sensitive ( not active )
2015-04-11 01:20:13 +03:00
self . widget ( " pool-refresh " ) . set_sensitive ( active )
2015-04-09 01:29:48 +03:00
self . widget ( " vol-add " ) . set_sensitive ( active )
self . widget ( " vol-add " ) . set_tooltip_text ( _ ( " Create new volume " ) )
self . widget ( " vol-delete " ) . set_sensitive ( False )
if active and not pool . supports_volume_creation ( ) :
self . widget ( " vol-add " ) . set_sensitive ( False )
self . widget ( " vol-add " ) . set_tooltip_text (
_ ( " Pool does not support volume creation " ) )
def _set_storage_error_page ( self , msg ) :
self . _reset_pool_state ( )
self . widget ( " storage-pages " ) . set_current_page ( 1 )
self . widget ( " storage-error-label " ) . set_text ( msg )
def _populate_pools ( self ) :
pool_list = self . widget ( " pool-list " )
curpool = self . _current_pool ( )
model = pool_list . get_model ( )
2015-04-11 18:40:47 +03:00
# Prevent events while the model is modified
2015-04-09 01:29:48 +03:00
pool_list . set_model ( None )
2015-04-11 18:40:47 +03:00
try :
pool_list . get_selection ( ) . unselect_all ( )
model . clear ( )
for pool in self . conn . list_pools ( ) :
try :
pool . disconnect_by_func ( self . _pool_changed )
pool . disconnect_by_func ( self . _pool_changed )
except :
pass
pool . connect ( " state-changed " , self . _pool_changed )
pool . connect ( " refreshed " , self . _pool_changed )
name = pool . get_name ( )
typ = StoragePool . get_pool_type_desc ( pool . get_type ( ) )
label = " %s \n <span size= ' small ' > %s </span> " % ( name , typ )
row = [ None ] * POOL_NUM_COLUMNS
row [ POOL_COLUMN_CONNKEY ] = pool . get_connkey ( )
row [ POOL_COLUMN_LABEL ] = label
row [ POOL_COLUMN_ISACTIVE ] = pool . is_active ( )
row [ POOL_COLUMN_PERCENT ] = _get_pool_size_percent ( pool )
model . append ( row )
finally :
pool_list . set_model ( model )
2015-04-09 01:29:48 +03:00
2015-05-20 01:13:33 +03:00
uiutil . set_list_selection ( pool_list ,
2015-04-09 01:29:48 +03:00
curpool and curpool . get_connkey ( ) or None )
def _populate_vols ( self ) :
list_widget = self . widget ( " vol-list " )
pool = self . _current_pool ( )
2015-04-10 19:52:42 +03:00
vols = pool and pool . get_volumes ( ) or [ ]
2015-04-09 01:29:48 +03:00
model = list_widget . get_model ( )
list_widget . get_selection ( ) . unselect_all ( )
model . clear ( )
2015-11-11 01:27:49 +03:00
vadj = self . widget ( " vol-scroll " ) . get_vadjustment ( )
vscroll_percent = vadj . get_value ( ) / max ( vadj . get_upper ( ) , 1 )
2015-04-10 19:52:42 +03:00
for vol in vols :
key = vol . get_connkey ( )
2015-04-09 01:29:48 +03:00
try :
path = vol . get_target_path ( )
name = vol . get_pretty_name ( pool . get_type ( ) )
2015-04-11 22:08:07 +03:00
cap = str ( vol . get_capacity ( ) )
sizestr = vol . get_pretty_capacity ( )
2015-04-09 01:29:48 +03:00
fmt = vol . get_format ( ) or " "
except :
logging . debug ( " Error getting volume info for ' %s ' , "
" hiding it " , key , exc_info = True )
continue
namestr = None
try :
if path :
names = VirtualDisk . path_in_use_by ( vol . conn . get_backend ( ) ,
path )
namestr = " , " . join ( names )
if not namestr :
namestr = None
except :
logging . exception ( " Failed to determine if storage volume in "
" use. " )
sensitive = True
if self . _vol_sensitive_cb :
sensitive = self . _vol_sensitive_cb ( fmt )
row = [ None ] * VOL_NUM_COLUMNS
row [ VOL_COLUMN_KEY ] = key
row [ VOL_COLUMN_NAME ] = name
2015-04-11 22:08:07 +03:00
row [ VOL_COLUMN_SIZESTR ] = sizestr
2015-04-09 01:29:48 +03:00
row [ VOL_COLUMN_CAPACITY ] = cap
row [ VOL_COLUMN_FORMAT ] = fmt
row [ VOL_COLUMN_INUSEBY ] = namestr
row [ VOL_COLUMN_SENSITIVE ] = sensitive
model . append ( row )
2015-11-11 01:27:49 +03:00
def _reset_vscroll_position ( ) :
vadj . set_value ( vadj . get_upper ( ) * vscroll_percent )
self . idle_add ( _reset_vscroll_position )
2015-04-09 01:29:48 +03:00
def _confirm_changes ( self ) :
if not self . _active_edits :
return True
if self . err . chkbox_helper (
self . config . get_confirm_unapplied ,
self . config . set_confirm_unapplied ,
text1 = ( _ ( " There are unapplied changes. "
" Would you like to apply them now? " ) ) ,
chktext = _ ( " Don ' t warn me again. " ) ,
default = False ) :
if all ( [ edit in EDIT_POOL_IDS for edit in self . _active_edits ] ) :
self . _pool_apply ( )
self . _active_edits = [ ]
return True
#############
# Listeners #
#############
def _browse_local_clicked ( self , src ) :
ignore = src
self . emit ( " browse-clicked " )
def _choose_volume_clicked ( self , src ) :
ignore = src
self . emit ( " volume-chosen " , self . _current_vol ( ) )
def _vol_list_row_activated ( self , src , treeiter , viewcol ) :
ignore = src
ignore = treeiter
ignore = viewcol
self . emit ( " volume-chosen " , self . _current_vol ( ) )
def _pool_selected ( self , src ) :
model , treeiter = src . get_selected ( )
if treeiter is None :
self . _set_storage_error_page ( _ ( " No storage pool selected. " ) )
return
self . widget ( " storage-pages " ) . set_current_page ( 0 )
connkey = model [ treeiter ] [ 0 ]
try :
self . _populate_pool_state ( connkey )
except Exception , e :
logging . exception ( e )
self . _set_storage_error_page ( _ ( " Error selecting pool: %s " ) % e )
self . _disable_pool_apply ( )
2015-04-09 21:42:25 +03:00
def _pool_created ( self , src , connkey ) :
# The pool list will have already been updated, since this
# signal arrives only after pool-added. So all we do here is
# select the pool we just created.
ignore = src
2015-05-20 01:13:33 +03:00
uiutil . set_list_selection ( self . widget ( " pool-list " ) , connkey )
2015-04-09 01:29:48 +03:00
2015-04-09 21:42:25 +03:00
def _vol_created ( self , src , pool_connkey , volname ) :
# The vol list will have already been updated, since this
# signal arrives only after pool-refreshed. So all we do here is
# select the vol we just created.
2015-04-09 01:29:48 +03:00
ignore = src
2015-04-09 21:42:25 +03:00
pool = self . _current_pool ( )
if not pool or pool . get_connkey ( ) != pool_connkey :
return
# Select the new volume
2015-05-20 01:13:33 +03:00
uiutil . set_list_selection ( self . widget ( " vol-list " ) , volname )
2015-04-09 01:29:48 +03:00
def _pool_autostart_changed ( self , src ) :
ignore = src
auto = self . widget ( " pool-autostart " ) . get_active ( )
self . widget ( " pool-autostart " ) . set_label (
auto and _ ( " On Boot " ) or _ ( " Never " ) )
self . _enable_pool_apply ( EDIT_POOL_AUTOSTART )
def _vol_selected ( self , src ) :
model , treeiter = src . get_selected ( )
self . widget ( " vol-delete " ) . set_sensitive ( bool ( treeiter ) )
can_choose = bool ( treeiter and model [ treeiter ] [ VOL_COLUMN_SENSITIVE ] )
self . widget ( " choose-volume " ) . set_sensitive ( can_choose )
def _vol_popup_menu ( self , widget_ignore , event ) :
if event . button != 3 :
return
self . _volmenu . popup ( None , None , None , None , 0 , event . time )
2015-04-09 21:42:25 +03:00
def _cancel_clicked ( self , src ) :
ignore = src
self . emit ( " cancel-clicked " )
##############################
# Connection event listeners #
##############################
def _conn_state_changed ( self , ignore = None ) :
conn_active = self . conn . is_active ( )
self . widget ( " pool-add " ) . set_sensitive ( conn_active and
self . conn . is_storage_capable ( ) )
2015-04-10 19:57:40 +03:00
if conn_active and not self . conn . is_storage_capable ( ) :
2015-04-09 21:42:25 +03:00
self . _set_storage_error_page (
_ ( " Libvirt connection does not support storage management. " ) )
2015-04-10 19:57:40 +03:00
if conn_active :
2015-05-20 01:13:33 +03:00
uiutil . set_list_selection_by_number ( self . widget ( " pool-list " ) , 0 )
2015-04-10 19:57:40 +03:00
return
self . _set_storage_error_page ( _ ( " Connection not active. " ) )
self . _populate_pools ( )
2015-04-09 23:07:09 +03:00
def _pool_changed ( self , pool ) :
self . _update_pool_row ( pool . get_connkey ( ) )
2015-04-09 21:42:25 +03:00
def _conn_pool_count_changed ( self , src , connkey ) :
ignore = src
ignore = connkey
self . _populate_pools ( )
2015-04-09 01:29:48 +03:00
#########################
# Pool action listeners #
#########################
def _pool_stop ( self , src_ignore ) :
pool = self . _current_pool ( )
if pool is None :
return
logging . debug ( " Stopping pool ' %s ' " , pool . get_name ( ) )
vmmAsyncJob . simple_async_noshow ( pool . stop , [ ] , self ,
_ ( " Error stopping pool ' %s ' " ) % pool . get_name ( ) )
def _pool_start ( self , src ) :
ignore = src
pool = self . _current_pool ( )
if pool is None :
return
logging . debug ( " Starting pool ' %s ' " , pool . get_name ( ) )
vmmAsyncJob . simple_async_noshow ( pool . start , [ ] , self ,
_ ( " Error starting pool ' %s ' " ) % pool . get_name ( ) )
def _pool_add ( self , src ) :
ignore = src
logging . debug ( " Launching ' Add Pool ' wizard " )
try :
if self . _addpool is None :
self . _addpool = vmmCreatePool ( self . conn )
2015-04-09 21:42:25 +03:00
self . _addpool . connect ( " pool-created " , self . _pool_created )
2015-04-09 01:29:48 +03:00
self . _addpool . show ( self . topwin )
except Exception , e :
self . err . show_err ( _ ( " Error launching pool wizard: %s " ) % str ( e ) )
def _pool_delete ( self , src ) :
ignore = src
pool = self . _current_pool ( )
if pool is None :
return
result = self . err . yes_no ( _ ( " Are you sure you want to permanently "
" delete the pool %s ? " ) % pool . get_name ( ) )
if not result :
return
logging . debug ( " Deleting pool ' %s ' " , pool . get_name ( ) )
vmmAsyncJob . simple_async_noshow ( pool . delete , [ ] , self ,
_ ( " Error deleting pool ' %s ' " ) % pool . get_name ( ) )
def _pool_refresh ( self , src ) :
ignore = src
if not self . _confirm_changes ( ) :
return
pool = self . _current_pool ( )
if pool is None :
return
logging . debug ( " Refresh pool ' %s ' " , pool . get_name ( ) )
2016-06-15 00:56:06 +03:00
vmmAsyncJob . simple_async_noshow ( pool . refresh , [ ] , self ,
2015-04-09 01:29:48 +03:00
_ ( " Error refreshing pool ' %s ' " ) % pool . get_name ( ) )
def _pool_apply ( self ) :
pool = self . _current_pool ( )
if pool is None :
return
logging . debug ( " Applying changes for pool ' %s ' " , pool . get_name ( ) )
try :
if EDIT_POOL_AUTOSTART in self . _active_edits :
auto = self . widget ( " pool-autostart " ) . get_active ( )
pool . set_autostart ( auto )
if EDIT_POOL_NAME in self . _active_edits :
pool . define_name ( self . widget ( " pool-name-entry " ) . get_text ( ) )
self . idle_add ( self . _populate_pools )
except Exception , e :
self . err . show_err ( _ ( " Error changing pool settings: %s " ) % str ( e ) )
return
self . _disable_pool_apply ( )
###########################
# Volume action listeners #
###########################
def _vol_copy_path ( self , src ) :
ignore = src
vol = self . _current_vol ( )
if not vol :
return
clipboard = Gtk . Clipboard . get ( Gdk . SELECTION_CLIPBOARD )
target_path = vol . get_target_path ( )
if target_path :
clipboard . set_text ( target_path , - 1 )
def _vol_add ( self , src ) :
ignore = src
pool = self . _current_pool ( )
if pool is None :
return
logging . debug ( " Launching ' Add Volume ' wizard for pool ' %s ' " ,
pool . get_name ( ) )
try :
if self . _addvol is None :
self . _addvol = vmmCreateVolume ( self . conn , pool )
2015-04-09 21:42:25 +03:00
self . _addvol . connect ( " vol-created " , self . _vol_created )
2015-04-09 01:29:48 +03:00
else :
self . _addvol . set_parent_pool ( self . conn , pool )
self . _addvol . set_modal ( self . topwin . get_modal ( ) )
self . _addvol . set_name_hint ( self . _name_hint )
self . _addvol . show ( self . topwin )
except Exception , e :
self . err . show_err ( _ ( " Error launching volume wizard: %s " ) % str ( e ) )
def _vol_delete ( self , src_ignore ) :
vol = self . _current_vol ( )
if vol is None :
return
2015-04-09 21:42:25 +03:00
pool = self . _current_pool ( )
2015-04-09 01:29:48 +03:00
result = self . err . yes_no ( _ ( " Are you sure you want to permanently "
" delete the volume %s ? " ) % vol . get_name ( ) )
if not result :
return
def cb ( ) :
vol . delete ( )
def idlecb ( ) :
2015-04-09 21:42:25 +03:00
pool . refresh ( )
2015-04-09 01:29:48 +03:00
self . idle_add ( idlecb )
logging . debug ( " Deleting volume ' %s ' " , vol . get_name ( ) )
vmmAsyncJob . simple_async_noshow ( cb , [ ] , self ,
2015-12-08 20:44:59 +03:00
_ ( " Error deleting volume ' %s ' " ) % vol . get_name ( ) )