2014-06-26 11:51:38 +02:00
# Copyright (C) 2006-2008, 2013-2014 Red Hat, Inc.
2006-06-28 15:50:17 -04:00
# Copyright (C) 2006 Daniel P. Berrange <berrange@redhat.com>
#
2018-04-04 14:35:41 +01:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 15:00:02 -04:00
# See the COPYING file in the top-level directory.
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
from gi . repository import GObject
from gi . repository import Gtk
from gi . repository import Gdk
from gi . repository import GdkPixbuf
2011-04-18 12:39:53 -04:00
2019-06-16 21:12:39 -04:00
from virtinst import log
2019-06-07 18:21:24 -04:00
from virtinst import xmlutil
2013-08-09 09:23:01 -04:00
2014-09-12 16:10:45 -04:00
from . import vmmenu
2019-06-16 22:19:17 -04:00
from . lib import uiutil
2014-09-12 16:10:45 -04:00
from . baseclass import vmmGObjectUI
2018-03-14 13:13:22 -04:00
from . connmanager import vmmConnectionManager
2018-03-14 18:58:22 -04:00
from . engine import vmmEngine
2019-06-16 22:19:17 -04:00
from . lib . graphwidgets import CellRendererSparkline
2006-07-20 11:16:07 -04:00
2012-05-14 14:24:56 +01:00
# Number of data points for performance graphs
GRAPH_LEN = 40
2006-06-14 10:59:40 -04:00
2007-08-28 17:57:25 -04:00
# fields in the tree model data set
2013-04-23 12:42:41 -04:00
( ROW_HANDLE ,
2013-09-01 18:36:58 -04:00
ROW_SORT_KEY ,
2013-04-23 12:42:41 -04:00
ROW_MARKUP ,
ROW_STATUS_ICON ,
ROW_HINT ,
ROW_IS_CONN ,
ROW_IS_CONN_CONNECTED ,
ROW_IS_VM ,
ROW_IS_VM_RUNNING ,
ROW_COLOR ,
2013-09-01 18:36:58 -04:00
ROW_INSPECTION_OS_ICON ) = range ( 11 )
2007-08-27 22:22:18 -04:00
# Columns in the tree view
2013-09-02 10:43:53 -04:00
( COL_NAME ,
COL_GUEST_CPU ,
COL_HOST_CPU ,
2013-12-18 14:42:42 +01:00
COL_MEM ,
2013-09-02 10:43:53 -04:00
COL_DISK ,
2013-12-18 14:42:42 +01:00
COL_NETWORK ) = range ( 6 )
2007-08-27 22:22:18 -04:00
2013-02-16 13:54:45 -05:00
2013-04-20 12:52:25 -04:00
def _style_get_prop ( widget , propname ) :
value = GObject . Value ( )
value . init ( GObject . TYPE_INT )
widget . style_get_property ( propname , value )
return value . get_int ( )
2009-07-26 16:15:05 -04:00
2017-10-21 19:18:02 -04:00
def _cmp ( a , b ) :
return ( ( a > b ) - ( a < b ) )
2013-09-01 18:36:58 -04:00
def _get_inspection_icon_pixbuf ( vm , w , h ) :
# libguestfs gives us the PNG data as a string.
png_data = vm . inspection . icon
if png_data is None :
return None
try :
pb = GdkPixbuf . PixbufLoader ( )
pb . set_size ( w , h )
pb . write ( png_data )
pb . close ( )
return pb . get_pixbuf ( )
2020-08-26 07:25:37 -04:00
except Exception : # pragma: no cover
2019-06-16 21:12:39 -04:00
log . exception ( " Error loading inspection icon data " )
2013-09-01 18:36:58 -04:00
vm . inspection . icon = None
return None
2010-12-08 17:26:19 -05:00
class vmmManager ( vmmGObjectUI ) :
2018-03-15 05:53:58 -04:00
@classmethod
def get_instance ( cls , parentobj ) :
try :
if not cls . _instance :
2018-03-17 16:08:20 -04:00
cls . _instance = vmmManager ( )
2018-03-15 05:53:58 -04:00
return cls . _instance
2020-08-20 13:34:01 -04:00
except Exception as e : # pragma: no cover
2018-03-16 18:58:11 -04:00
if not parentobj :
raise
2018-03-15 05:53:58 -04:00
parentobj . err . show_err (
_ ( " Error launching manager: %s " ) % str ( e ) )
2012-05-14 14:24:56 +01:00
2018-03-14 13:13:22 -04:00
def __init__ ( self ) :
2013-09-22 16:10:16 -04:00
vmmGObjectUI . __init__ ( self , " manager.ui " , " vmm-manager " )
2018-03-15 07:43:56 -04:00
self . _cleanup_on_app_close ( )
2010-11-30 14:33:21 -05:00
2009-11-28 21:00:46 -05:00
w , h = self . config . get_manager_window_size ( )
2010-02-23 14:18:12 -05:00
self . topwin . set_default_size ( w or 550 , h or 550 )
2010-12-13 17:48:19 -05:00
self . prev_position = None
2015-09-13 14:07:43 -04:00
self . _window_size = None
2009-11-28 21:00:46 -05:00
2014-01-28 18:04:46 -05:00
self . vmmenu = vmmenu . VMActionMenu ( self , self . current_vm )
2018-03-15 07:43:56 -04:00
self . shutdownmenu = vmmenu . VMShutdownMenu ( self , self . current_vm )
2012-05-14 14:24:56 +01:00
self . connmenu = Gtk . Menu ( )
2020-09-21 21:29:00 -04:00
self . connmenu . get_accessible ( ) . set_name ( " conn-menu " )
2009-11-28 20:49:44 -05:00
self . connmenu_items = { }
2011-04-13 09:27:02 -04:00
2013-02-16 13:31:46 -05:00
self . builder . connect_signals ( {
2011-07-12 08:49:47 -04:00
" on_menu_view_guest_cpu_usage_activate " :
2017-08-17 19:01:28 +08:00
self . toggle_stats_visible_guest_cpu ,
2011-07-12 08:49:47 -04:00
" on_menu_view_host_cpu_usage_activate " :
2017-08-17 19:01:28 +08:00
self . toggle_stats_visible_host_cpu ,
2013-12-18 14:42:42 +01:00
" on_menu_view_memory_usage_activate " :
2017-08-17 19:01:28 +08:00
self . toggle_stats_visible_memory_usage ,
2017-08-05 14:39:32 +08:00
" on_menu_view_disk_io_activate " :
2017-08-17 19:01:28 +08:00
self . toggle_stats_visible_disk ,
2011-07-12 08:49:47 -04:00
" on_menu_view_network_traffic_activate " :
2017-08-17 19:01:28 +08:00
self . toggle_stats_visible_network ,
2009-11-28 20:49:44 -05:00
" on_vm_manager_delete_event " : self . close ,
2009-11-28 21:00:46 -05:00
" on_vmm_manager_configure_event " : self . window_resized ,
2018-03-15 21:22:14 -04:00
" on_menu_file_add_connection_activate " : self . open_newconn ,
2014-02-01 13:36:02 -05:00
" on_menu_new_vm_activate " : self . new_vm ,
2009-11-28 20:49:44 -05:00
" on_menu_file_quit_activate " : self . exit_app ,
" on_menu_file_close_activate " : self . close ,
" on_vmm_close_clicked " : self . close ,
2011-06-08 16:33:20 -04:00
" on_vm_open_clicked " : self . show_vm ,
2009-11-28 20:49:44 -05:00
" on_vm_run_clicked " : self . start_vm ,
" on_vm_new_clicked " : self . new_vm ,
" on_vm_shutdown_clicked " : self . poweroff_vm ,
" on_vm_pause_clicked " : self . pause_vm_button ,
2011-06-08 16:33:20 -04:00
" on_menu_edit_details_activate " : self . show_vm ,
2009-11-28 20:49:44 -05:00
" on_menu_edit_delete_activate " : self . do_delete ,
" on_menu_host_details_activate " : self . show_host ,
2018-03-15 05:53:58 -04:00
" on_vm_list_row_activated " : self . row_activated ,
2009-11-28 20:49:44 -05:00
" on_vm_list_button_press_event " : self . popup_vm_menu_button ,
" on_vm_list_key_press_event " : self . popup_vm_menu_key ,
" on_menu_edit_preferences_activate " : self . show_preferences ,
" on_menu_help_about_activate " : self . show_about ,
2011-04-13 09:27:02 -04:00
} )
2013-09-02 10:43:53 -04:00
# There seem to be ref counting issues with calling
# list.get_column, so avoid it
self . diskcol = None
self . netcol = None
2013-12-18 14:42:42 +01:00
self . memcol = None
2013-09-02 10:43:53 -04:00
self . guestcpucol = None
self . hostcpucol = None
self . spacer_txt = None
2011-04-13 09:27:02 -04:00
self . init_vmlist ( )
2013-09-02 10:43:53 -04:00
2011-04-13 09:27:02 -04:00
self . init_stats ( )
self . init_toolbar ( )
self . init_context_menus ( )
2009-11-28 20:49:44 -05:00
2013-09-02 09:09:31 -04:00
self . update_current_selection ( )
self . widget ( " vm-list " ) . get_selection ( ) . connect (
" changed " , self . update_current_selection )
2009-11-28 20:49:44 -05:00
2011-07-25 15:09:42 -04:00
self . max_disk_rate = 10.0
self . max_net_rate = 10.0
2009-11-28 20:49:44 -05:00
# Initialize stat polling columns based on global polling
# preferences (we want signal handlers for this)
2020-08-26 07:25:37 -04:00
self . _config_polling_change_cb ( COL_GUEST_CPU )
self . _config_polling_change_cb ( COL_DISK )
self . _config_polling_change_cb ( COL_NETWORK )
self . _config_polling_change_cb ( COL_MEM )
2009-11-28 20:49:44 -05:00
2018-03-14 13:13:22 -04:00
connmanager = vmmConnectionManager . get_instance ( )
connmanager . connect ( " conn-added " , self . _conn_added )
connmanager . connect ( " conn-removed " , self . _conn_removed )
for conn in connmanager . conns . values ( ) :
self . _conn_added ( connmanager , conn )
2018-03-14 10:29:20 -04:00
2009-11-28 20:49:44 -05:00
##################
# Common methods #
##################
def show ( self ) :
2010-12-08 17:26:19 -05:00
vis = self . is_visible ( )
2010-02-23 14:18:12 -05:00
self . topwin . present ( )
2010-12-08 17:26:19 -05:00
if vis :
return
2010-02-23 14:18:12 -05:00
2019-06-16 21:12:39 -04:00
log . debug ( " Showing manager " )
2010-12-13 17:48:19 -05:00
if self . prev_position :
self . topwin . move ( * self . prev_position )
self . prev_position = None
2011-04-13 10:47:31 -04:00
2018-03-14 19:06:30 -04:00
vmmEngine . get_instance ( ) . increment_window_counter ( )
2009-11-28 20:49:44 -05:00
2010-12-09 11:22:35 -05:00
def close ( self , src_ignore = None , src2_ignore = None ) :
2010-12-08 17:26:19 -05:00
if not self . is_visible ( ) :
return
2019-06-16 21:12:39 -04:00
log . debug ( " Closing manager " )
2010-12-13 17:48:19 -05:00
self . prev_position = self . topwin . get_position ( )
2010-12-08 17:26:19 -05:00
self . topwin . hide ( )
2018-03-14 19:06:30 -04:00
vmmEngine . get_instance ( ) . decrement_window_counter ( )
2011-04-13 10:47:31 -04:00
2010-12-08 17:26:19 -05:00
return 1
2009-11-28 20:49:44 -05:00
2011-04-13 09:27:02 -04:00
2011-07-23 21:16:54 -04:00
def _cleanup ( self ) :
self . diskcol = None
self . guestcpucol = None
2013-12-18 14:42:42 +01:00
self . memcol = None
2011-07-23 21:16:54 -04:00
self . hostcpucol = None
self . netcol = None
2011-04-13 09:27:02 -04:00
2018-03-15 07:43:56 -04:00
self . shutdownmenu . destroy ( )
self . shutdownmenu = None
2014-04-02 18:39:43 -04:00
self . vmmenu . destroy ( )
2011-07-23 21:16:54 -04:00
self . vmmenu = None
self . connmenu . destroy ( )
self . connmenu = None
self . connmenu_items = None
2011-04-13 09:27:02 -04:00
2015-09-13 14:07:43 -04:00
if self . _window_size :
self . config . set_manager_window_size ( * self . _window_size )
2010-03-02 20:35:54 -05:00
def set_startup_error ( self , msg ) :
2011-07-14 13:13:13 -04:00
self . widget ( " vm-notebook " ) . set_current_page ( 1 )
self . widget ( " startup-error-label " ) . set_text ( msg )
2006-06-14 10:59:40 -04:00
2019-04-13 17:03:16 -04:00
2009-11-28 20:49:44 -05:00
################
# Init methods #
################
def init_stats ( self ) :
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2011-07-12 08:49:47 -04:00
self . config . on_vmlist_guest_cpu_usage_visible_changed (
self . toggle_guest_cpu_usage_visible_widget ) )
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2011-07-12 08:49:47 -04:00
self . config . on_vmlist_host_cpu_usage_visible_changed (
self . toggle_host_cpu_usage_visible_widget ) )
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2013-12-18 14:42:42 +01:00
self . config . on_vmlist_memory_usage_visible_changed (
self . toggle_memory_usage_visible_widget ) )
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2011-04-13 09:27:02 -04:00
self . config . on_vmlist_disk_io_visible_changed (
2011-07-12 08:49:47 -04:00
self . toggle_disk_io_visible_widget ) )
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2011-04-13 09:27:02 -04:00
self . config . on_vmlist_network_traffic_visible_changed (
self . toggle_network_traffic_visible_widget ) )
2006-06-14 10:59:40 -04:00
2008-12-17 15:27:06 -05:00
# Register callbacks with the global stats enable/disable values
# that disable the associated vmlist widgets if reporting is disabled
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2014-02-11 15:29:30 -05:00
self . config . on_stats_enable_cpu_poll_changed (
2020-08-26 07:25:37 -04:00
self . _config_polling_change_cb , COL_GUEST_CPU ) )
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2014-02-11 15:29:30 -05:00
self . config . on_stats_enable_disk_poll_changed (
2020-08-26 07:25:37 -04:00
self . _config_polling_change_cb , COL_DISK ) )
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2014-02-11 15:29:30 -05:00
self . config . on_stats_enable_net_poll_changed (
2020-08-26 07:25:37 -04:00
self . _config_polling_change_cb , COL_NETWORK ) )
2014-09-28 13:37:16 +02:00
self . add_gsettings_handle (
2014-01-12 17:39:21 -05:00
self . config . on_stats_enable_memory_poll_changed (
2020-08-26 07:25:37 -04:00
self . _config_polling_change_cb , COL_MEM ) )
2011-04-13 09:27:02 -04:00
2013-09-01 21:35:23 -04:00
self . toggle_guest_cpu_usage_visible_widget ( )
self . toggle_host_cpu_usage_visible_widget ( )
2013-12-18 14:42:42 +01:00
self . toggle_memory_usage_visible_widget ( )
2013-09-01 21:35:23 -04:00
self . toggle_disk_io_visible_widget ( )
self . toggle_network_traffic_visible_widget ( )
2008-12-17 15:27:06 -05:00
2009-11-11 11:02:57 -05:00
2009-11-28 20:49:44 -05:00
def init_toolbar ( self ) :
2011-07-14 13:13:13 -04:00
self . widget ( " vm-new " ) . set_icon_name ( " vm_new " )
self . widget ( " vm-open " ) . set_icon_name ( " icon_console " )
2013-09-22 13:24:59 -04:00
self . widget ( " vm-shutdown " ) . set_icon_name ( " system-shutdown " )
2018-03-15 07:43:56 -04:00
self . widget ( " vm-shutdown " ) . set_menu ( self . shutdownmenu )
2011-07-14 13:13:13 -04:00
tool = self . widget ( " vm-toolbar " )
2012-05-14 14:24:56 +01:00
tool . set_property ( " icon-size " , Gtk . IconSize . LARGE_TOOLBAR )
2009-11-10 12:57:28 -05:00
for c in tool . get_children ( ) :
2009-07-26 16:25:01 -04:00
c . set_homogeneous ( False )
2009-11-28 20:49:44 -05:00
def init_context_menus ( self ) :
2020-08-20 13:34:01 -04:00
def add_to_menu ( idx , text , cb ) :
2022-02-19 12:01:55 -05:00
item = Gtk . MenuItem . new_with_mnemonic ( text )
2010-05-12 15:31:36 -04:00
if cb :
item . connect ( " activate " , cb )
2018-01-09 17:33:05 -05:00
item . get_accessible ( ) . set_name ( " conn- %s " % idx )
2013-09-22 15:13:41 -04:00
self . connmenu . add ( item )
self . connmenu_items [ idx ] = item
2006-06-14 10:59:40 -04:00
2010-05-12 15:31:36 -04:00
# Build connection context menu
2022-02-19 12:01:55 -05:00
add_to_menu ( " create " , _ ( " _New " ) , self . new_vm )
add_to_menu ( " connect " , _ ( " _Connect " ) , self . open_conn )
add_to_menu ( " disconnect " , _ ( " Dis_connect " ) , self . close_conn )
2013-09-22 15:13:41 -04:00
self . connmenu . add ( Gtk . SeparatorMenuItem ( ) )
2022-02-19 12:01:55 -05:00
add_to_menu ( " delete " , _ ( " De_lete " ) , self . do_delete )
2013-09-22 15:13:41 -04:00
self . connmenu . add ( Gtk . SeparatorMenuItem ( ) )
2022-02-19 12:01:55 -05:00
add_to_menu ( " details " , _ ( " _Details " ) , self . show_host )
2013-09-22 15:13:41 -04:00
self . connmenu . show_all ( )
2007-08-13 17:13:39 -04:00
2009-11-28 20:49:44 -05:00
def init_vmlist ( self ) :
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
self . widget ( " vm-notebook " ) . set_show_tabs ( False )
2006-06-14 10:59:40 -04:00
2013-04-23 12:42:41 -04:00
rowtypes = [ ]
rowtypes . insert ( ROW_HANDLE , object ) # backing object
2013-09-01 18:36:58 -04:00
rowtypes . insert ( ROW_SORT_KEY , str ) # object name
2013-04-23 12:42:41 -04:00
rowtypes . insert ( ROW_MARKUP , str ) # row markup text
rowtypes . insert ( ROW_STATUS_ICON , str ) # status icon name
rowtypes . insert ( ROW_HINT , str ) # row tooltip
rowtypes . insert ( ROW_IS_CONN , bool ) # if object is a connection
rowtypes . insert ( ROW_IS_CONN_CONNECTED , bool ) # if conn is connected
rowtypes . insert ( ROW_IS_VM , bool ) # if row is VM
rowtypes . insert ( ROW_IS_VM_RUNNING , bool ) # if VM is running
2013-04-23 13:04:33 -04:00
rowtypes . insert ( ROW_COLOR , str ) # row markup color string
2013-04-23 14:24:52 -04:00
rowtypes . insert ( ROW_INSPECTION_OS_ICON , GdkPixbuf . Pixbuf ) # OS icon
2013-04-23 12:42:41 -04:00
model = Gtk . TreeStore ( * rowtypes )
2009-11-28 20:49:44 -05:00
vmlist . set_model ( model )
2012-02-01 17:26:46 -05:00
vmlist . set_tooltip_column ( ROW_HINT )
2009-11-28 20:49:44 -05:00
vmlist . set_headers_visible ( True )
2013-04-20 12:52:53 -04:00
vmlist . set_level_indentation (
- ( _style_get_prop ( vmlist , " expander-size " ) + 3 ) )
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
nameCol = Gtk . TreeViewColumn ( _ ( " Name " ) )
2009-11-28 20:49:44 -05:00
nameCol . set_expand ( True )
2013-09-10 16:07:11 +02:00
nameCol . set_sizing ( Gtk . TreeViewColumnSizing . AUTOSIZE )
2009-11-28 20:49:44 -05:00
nameCol . set_spacing ( 6 )
2013-09-02 10:43:53 -04:00
nameCol . set_sort_column_id ( COL_NAME )
2006-11-06 10:34:54 -05:00
2009-11-28 20:49:44 -05:00
vmlist . append_column ( nameCol )
2008-12-17 15:27:06 -05:00
2012-05-14 14:24:56 +01:00
status_icon = Gtk . CellRendererPixbuf ( )
status_icon . set_property ( " stock-size " , Gtk . IconSize . DND )
2013-09-02 10:43:53 -04:00
nameCol . pack_start ( status_icon , False )
nameCol . add_attribute ( status_icon , ' icon-name ' , ROW_STATUS_ICON )
nameCol . add_attribute ( status_icon , ' visible ' , ROW_IS_VM )
2009-03-09 16:22:03 -04:00
2012-05-14 14:24:56 +01:00
inspection_os_icon = Gtk . CellRendererPixbuf ( )
2013-09-02 10:43:53 -04:00
nameCol . pack_start ( inspection_os_icon , False )
nameCol . add_attribute ( inspection_os_icon , ' pixbuf ' ,
2011-07-18 19:53:56 +01:00
ROW_INSPECTION_OS_ICON )
2013-09-02 10:43:53 -04:00
nameCol . add_attribute ( inspection_os_icon , ' visible ' , ROW_IS_VM )
2011-07-18 19:53:56 +01:00
2012-05-14 14:24:56 +01:00
name_txt = Gtk . CellRendererText ( )
2009-11-28 20:49:44 -05:00
nameCol . pack_start ( name_txt , True )
nameCol . add_attribute ( name_txt , ' markup ' , ROW_MARKUP )
2013-04-23 13:04:33 -04:00
nameCol . add_attribute ( name_txt , ' foreground ' , ROW_COLOR )
2013-09-02 10:43:53 -04:00
self . spacer_txt = Gtk . CellRendererText ( )
self . spacer_txt . set_property ( " ypad " , 4 )
self . spacer_txt . set_property ( " visible " , False )
nameCol . pack_end ( self . spacer_txt , False )
2007-09-09 22:57:24 -04:00
2013-09-01 21:35:23 -04:00
def make_stats_column ( title , colnum ) :
2012-05-14 14:24:56 +01:00
col = Gtk . TreeViewColumn ( title )
2011-07-12 08:49:47 -04:00
col . set_min_width ( 140 )
2013-04-20 14:11:31 -04:00
2012-05-14 14:24:56 +01:00
txt = Gtk . CellRendererText ( )
2013-04-20 13:43:21 -04:00
txt . set_property ( " ypad " , 4 )
2013-04-20 14:11:31 -04:00
col . pack_start ( txt , True )
col . add_attribute ( txt , ' visible ' , ROW_IS_CONN )
2011-07-12 08:49:47 -04:00
img = CellRendererSparkline ( )
img . set_property ( " xpad " , 6 )
img . set_property ( " ypad " , 12 )
img . set_property ( " reversed " , True )
col . pack_start ( img , True )
col . add_attribute ( img , ' visible ' , ROW_IS_VM )
2013-04-20 14:11:31 -04:00
2011-07-12 08:49:47 -04:00
col . set_sort_column_id ( colnum )
vmlist . append_column ( col )
return col
2013-09-01 21:35:23 -04:00
self . guestcpucol = make_stats_column ( _ ( " CPU usage " ) , COL_GUEST_CPU )
self . hostcpucol = make_stats_column ( _ ( " Host CPU usage " ) , COL_HOST_CPU )
2013-12-18 14:42:42 +01:00
self . memcol = make_stats_column ( _ ( " Memory usage " ) , COL_MEM )
2013-09-01 21:35:23 -04:00
self . diskcol = make_stats_column ( _ ( " Disk I/O " ) , COL_DISK )
self . netcol = make_stats_column ( _ ( " Network I/O " ) , COL_NETWORK )
2006-06-14 10:59:40 -04:00
2009-11-28 20:49:44 -05:00
model . set_sort_func ( COL_NAME , self . vmlist_name_sorter )
2011-07-12 08:49:47 -04:00
model . set_sort_func ( COL_GUEST_CPU , self . vmlist_guest_cpu_usage_sorter )
model . set_sort_func ( COL_HOST_CPU , self . vmlist_host_cpu_usage_sorter )
2013-12-18 14:42:42 +01:00
model . set_sort_func ( COL_MEM , self . vmlist_memory_usage_sorter )
2009-11-28 20:49:44 -05:00
model . set_sort_func ( COL_DISK , self . vmlist_disk_io_sorter )
model . set_sort_func ( COL_NETWORK , self . vmlist_network_usage_sorter )
2012-05-14 14:24:56 +01:00
model . set_sort_column_id ( COL_NAME , Gtk . SortType . ASCENDING )
2009-11-28 20:49:44 -05:00
2018-03-17 17:35:04 -04:00
2009-11-28 20:49:44 -05:00
##################
# Helper methods #
##################
2018-03-17 17:35:04 -04:00
@property
def model ( self ) :
return self . widget ( " vm-list " ) . get_model ( )
2009-11-28 20:49:44 -05:00
def current_row ( self ) :
2015-05-19 17:17:53 -04:00
return uiutil . get_list_selected_row ( self . widget ( " vm-list " ) )
2009-11-28 20:49:44 -05:00
def current_vm ( self ) :
row = self . current_row ( )
if not row or row [ ROW_IS_CONN ] :
return None
return row [ ROW_HANDLE ]
2018-03-17 17:35:04 -04:00
def current_conn ( self ) :
2009-11-28 20:49:44 -05:00
row = self . current_row ( )
2018-03-17 17:35:04 -04:00
if not row :
return None
handle = row [ ROW_HANDLE ]
if row [ ROW_IS_CONN ] :
return handle
return handle . conn
def get_row ( self , conn_or_vm ) :
2018-10-13 14:27:10 -04:00
def _walk ( model , rowiter , obj ) :
2018-03-17 17:35:04 -04:00
while rowiter :
2018-10-13 14:27:10 -04:00
row = model [ rowiter ]
if row [ ROW_HANDLE ] == obj :
2018-03-17 17:35:04 -04:00
return row
2018-10-13 14:27:10 -04:00
if model . iter_has_child ( rowiter ) :
ret = _walk ( model , model . iter_nth_child ( rowiter , 0 ) , obj )
2018-03-17 17:35:04 -04:00
if ret :
return ret
2018-10-13 14:27:10 -04:00
rowiter = model . iter_next ( rowiter )
2018-03-17 17:35:04 -04:00
if not len ( self . model ) :
return None
2018-10-13 14:27:10 -04:00
return _walk ( self . model , self . model . get_iter_first ( ) , conn_or_vm )
2010-08-22 12:50:31 -04:00
2009-11-28 20:49:44 -05:00
####################
# Action listeners #
####################
2006-11-03 10:02:02 -05:00
2016-12-13 13:27:06 -05:00
def window_resized ( self , ignore , ignore2 ) :
2009-11-28 21:00:46 -05:00
if not self . is_visible ( ) :
return
2016-12-13 13:27:06 -05:00
self . _window_size = self . topwin . get_size ( )
2009-11-28 21:00:46 -05:00
2010-12-09 11:22:35 -05:00
def exit_app ( self , src_ignore = None , src2_ignore = None ) :
2018-03-14 18:58:22 -04:00
vmmEngine . get_instance ( ) . exit_app ( )
2006-06-14 10:59:40 -04:00
2018-03-15 21:22:14 -04:00
def open_newconn ( self , _src ) :
2019-06-16 22:03:25 -04:00
from . createconn import vmmCreateConn
vmmCreateConn . get_instance ( self ) . show ( self . topwin )
2006-06-14 10:59:40 -04:00
2018-03-15 05:53:58 -04:00
def new_vm ( self , _src ) :
2019-06-16 22:00:57 -04:00
from . createvm import vmmCreateVM
2018-03-15 05:53:58 -04:00
conn = self . current_conn ( )
2019-06-16 22:00:57 -04:00
vmmCreateVM . show_instance ( self , conn and conn . get_uri ( ) or None )
2009-11-28 20:49:44 -05:00
2018-03-13 11:52:11 -04:00
def show_about ( self , _src ) :
from . about import vmmAbout
vmmAbout . show_instance ( self )
2009-11-28 20:49:44 -05:00
2010-12-09 11:22:35 -05:00
def show_preferences ( self , src_ignore ) :
2018-03-13 11:58:36 -04:00
from . preferences import vmmPreferences
vmmPreferences . show_instance ( self )
2009-11-28 20:49:44 -05:00
2018-03-15 05:53:58 -04:00
def show_host ( self , _src ) :
from . host import vmmHost
2018-03-17 17:35:04 -04:00
conn = self . current_conn ( )
2018-03-15 05:53:58 -04:00
vmmHost . show_instance ( self , conn )
def show_vm ( self , _src ) :
vmmenu . VMActionUI . show ( self , self . current_vm ( ) )
2009-11-28 20:49:44 -05:00
2018-03-15 05:53:58 -04:00
def row_activated ( self , _src , * args ) :
ignore = args
2011-07-22 16:43:26 -04:00
conn = self . current_conn ( )
2011-06-08 16:33:20 -04:00
vm = self . current_vm ( )
if conn is None :
2020-08-26 07:25:37 -04:00
return # pragma: no cover
2011-06-08 16:33:20 -04:00
if vm :
2018-03-15 05:53:58 -04:00
self . show_vm ( _src )
elif conn . is_disconnected ( ) :
2020-08-26 07:25:37 -04:00
self . open_conn ( )
2011-06-08 16:33:20 -04:00
else :
2018-03-15 05:53:58 -04:00
self . show_host ( _src )
2009-11-28 20:49:44 -05:00
def do_delete ( self , ignore = None ) :
2011-07-22 16:43:26 -04:00
conn = self . current_conn ( )
2009-11-28 20:49:44 -05:00
vm = self . current_vm ( )
if vm is None :
2011-07-22 16:43:26 -04:00
self . _do_delete_conn ( conn )
2009-11-28 20:49:44 -05:00
else :
2018-03-14 17:48:17 -04:00
vmmenu . VMActionUI . delete ( self , vm )
2009-11-28 20:49:44 -05:00
2011-07-22 16:43:26 -04:00
def _do_delete_conn ( self , conn ) :
2009-11-28 20:49:44 -05:00
result = self . err . yes_no ( _ ( " This will remove the connection: \n \n %s \n \n "
" Are you sure? " ) % conn . get_uri ( ) )
if not result :
return
2011-07-22 13:42:20 -04:00
2018-03-15 05:53:58 -04:00
vmmConnectionManager . get_instance ( ) . remove_conn ( conn . get_uri ( ) )
2009-11-28 20:49:44 -05:00
def set_pause_state ( self , state ) :
2011-07-14 13:13:13 -04:00
src = self . widget ( " vm-pause " )
2009-11-28 20:49:44 -05:00
try :
2015-11-10 18:30:31 -05:00
src . handler_block_by_func ( self . pause_vm_button )
2009-11-28 20:49:44 -05:00
src . set_active ( state )
finally :
2015-11-10 18:30:31 -05:00
src . handler_unblock_by_func ( self . pause_vm_button )
2009-11-28 20:49:44 -05:00
def pause_vm_button ( self , src ) :
do_pause = src . get_active ( )
2011-04-15 14:49:58 -04:00
# Set button state back to original value: just let the status
# update function fix things for us
self . set_pause_state ( not do_pause )
2009-11-28 20:49:44 -05:00
if do_pause :
2018-03-08 13:42:45 -05:00
vmmenu . VMActionUI . suspend ( self , self . current_vm ( ) )
2009-11-28 20:49:44 -05:00
else :
2018-03-08 13:42:45 -05:00
vmmenu . VMActionUI . resume ( self , self . current_vm ( ) )
2009-11-28 20:49:44 -05:00
def start_vm ( self , ignore ) :
2018-03-08 13:42:45 -05:00
vmmenu . VMActionUI . run ( self , self . current_vm ( ) )
def poweroff_vm ( self , _src ) :
vmmenu . VMActionUI . shutdown ( self , self . current_vm ( ) )
2009-11-28 20:49:44 -05:00
2011-07-22 16:43:26 -04:00
def close_conn ( self , ignore ) :
conn = self . current_conn ( )
2014-09-11 18:16:21 -04:00
if not conn . is_disconnected ( ) :
2009-11-28 20:49:44 -05:00
conn . close ( )
2011-07-22 16:43:26 -04:00
def open_conn ( self , ignore = None ) :
conn = self . current_conn ( )
2014-09-11 18:16:21 -04:00
if conn . is_disconnected ( ) :
2020-08-26 07:25:37 -04:00
conn . connect_once ( " open-completed " , self . _conn_open_completed_cb )
2009-11-28 20:49:44 -05:00
conn . open ( )
return True
2020-08-26 07:25:37 -04:00
def _conn_open_completed_cb ( self , _conn , ConnectError ) :
if ConnectError :
msg , details , title = ConnectError
self . err . show_err ( msg , details , title )
2009-11-28 20:49:44 -05:00
####################################
# VM add/remove management methods #
####################################
2020-09-01 11:54:10 -04:00
def vm_added ( self , conn , vm ) :
2018-03-17 17:35:04 -04:00
vm_row = self . _build_row ( None , vm )
conn_row = self . get_row ( conn )
self . model . append ( conn_row . iter , vm_row )
2016-05-19 19:31:22 -04:00
2015-04-09 18:02:42 -04:00
vm . connect ( " state-changed " , self . vm_changed )
2013-09-02 09:09:31 -04:00
vm . connect ( " resources-sampled " , self . vm_row_updated )
2011-07-18 19:53:56 +01:00
vm . connect ( " inspection-changed " , self . vm_inspection_changed )
2006-06-14 17:52:49 -04:00
2016-05-19 19:31:22 -04:00
# Expand a connection when adding a vm to it
2018-03-17 17:35:04 -04:00
self . widget ( " vm-list " ) . expand_row ( conn_row . path , False )
2006-06-14 10:59:40 -04:00
2020-09-01 11:54:10 -04:00
def vm_removed ( self , conn , vm ) :
2018-03-17 17:35:04 -04:00
parent = self . get_row ( conn ) . iter
for rowidx in range ( self . model . iter_n_children ( parent ) ) :
rowiter = self . model . iter_nth_child ( parent , rowidx )
2020-09-01 11:54:10 -04:00
if self . model [ rowiter ] [ ROW_HANDLE ] == vm :
2018-03-17 17:35:04 -04:00
self . model . remove ( rowiter )
2009-11-28 20:49:44 -05:00
break
2009-10-21 10:36:58 -04:00
def _build_conn_hint ( self , conn ) :
hint = conn . get_uri ( )
2014-09-11 18:16:21 -04:00
if conn . is_disconnected ( ) :
2020-07-14 09:41:51 +02:00
hint = _ ( " %(uri)s (Double click to connect) " ) % { " uri " : conn . get_uri ( ) }
2009-10-21 10:36:58 -04:00
return hint
2013-09-01 18:36:58 -04:00
def _build_conn_markup ( self , conn , name ) :
2019-06-07 18:21:24 -04:00
name = xmlutil . xml_escape ( name )
2011-08-29 12:11:43 -04:00
text = name
2014-09-11 18:16:21 -04:00
if conn . is_disconnected ( ) :
2020-07-14 09:41:51 +02:00
text = _ ( " %(connection)s - Not Connected " ) % { " connection " : name }
2014-09-11 18:16:21 -04:00
elif conn . is_connecting ( ) :
2020-07-14 09:41:51 +02:00
text = _ ( " %(connection)s - Connecting... " ) % { " connection " : name }
2010-12-01 15:22:38 -05:00
markup = " <span size= ' smaller ' > %s </span> " % text
2009-09-17 12:35:41 -04:00
return markup
2009-11-10 15:42:07 -05:00
def _build_conn_color ( self , conn ) :
2019-10-02 10:32:04 -04:00
color = None
2014-09-11 18:16:21 -04:00
if conn . is_disconnected ( ) :
2020-02-01 17:16:45 -05:00
color = self . config . color_insensitive
2009-11-10 15:42:07 -05:00
return color
2013-09-01 18:36:58 -04:00
def _build_vm_markup ( self , name , status ) :
2010-12-01 15:22:38 -05:00
domtext = ( " <span size= ' smaller ' weight= ' bold ' > %s </span> " %
2019-06-07 18:21:24 -04:00
xmlutil . xml_escape ( name ) )
2013-09-01 18:36:58 -04:00
statetext = " <span size= ' smaller ' > %s </span> " % status
2010-12-01 15:22:38 -05:00
return domtext + " \n " + statetext
2009-09-17 12:35:41 -04:00
2013-09-01 18:36:58 -04:00
def _build_row ( self , conn , vm ) :
if conn :
2015-04-11 12:57:32 -04:00
name = conn . get_pretty_desc ( )
2013-09-01 18:36:58 -04:00
markup = self . _build_conn_markup ( conn , name )
status = ( " <span size= ' smaller ' > %s </span> " %
conn . get_state_text ( ) )
status_icon = None
hint = self . _build_conn_hint ( conn )
color = self . _build_conn_color ( conn )
os_icon = None
else :
2013-10-04 11:50:19 -04:00
name = vm . get_name_or_title ( )
2013-09-01 18:36:58 -04:00
status = vm . run_status ( )
markup = self . _build_vm_markup ( name , status )
status_icon = vm . run_status_icon_name ( )
hint = vm . get_description ( )
color = None
os_icon = _get_inspection_icon_pixbuf ( vm , 16 , 16 )
2011-09-26 11:05:55 -04:00
2013-09-01 18:36:58 -04:00
row = [ ]
row . insert ( ROW_HANDLE , conn or vm )
row . insert ( ROW_SORT_KEY , name )
row . insert ( ROW_MARKUP , markup )
row . insert ( ROW_STATUS_ICON , status_icon )
2019-06-07 18:21:24 -04:00
row . insert ( ROW_HINT , xmlutil . xml_escape ( hint ) )
2013-09-01 18:36:58 -04:00
row . insert ( ROW_IS_CONN , bool ( conn ) )
row . insert ( ROW_IS_CONN_CONNECTED ,
2014-09-11 18:16:21 -04:00
bool ( conn ) and not conn . is_disconnected ( ) )
2013-09-01 18:36:58 -04:00
row . insert ( ROW_IS_VM , bool ( vm ) )
row . insert ( ROW_IS_VM_RUNNING , bool ( vm ) and vm . is_active ( ) )
row . insert ( ROW_COLOR , color )
row . insert ( ROW_INSPECTION_OS_ICON , os_icon )
2009-09-17 12:35:41 -04:00
2011-03-23 16:56:12 -04:00
return row
2018-03-14 13:13:22 -04:00
def _conn_added ( self , _src , conn ) :
2010-03-02 20:35:54 -05:00
# Make sure error page isn't showing
2011-07-14 13:13:13 -04:00
self . widget ( " vm-notebook " ) . set_current_page ( 0 )
2018-03-17 17:35:04 -04:00
if self . get_row ( conn ) :
2020-08-20 13:34:01 -04:00
return # pragma: no cover
2009-11-28 20:49:44 -05:00
2018-03-17 17:35:04 -04:00
conn_row = self . _build_row ( conn , None )
self . model . append ( None , conn_row )
2016-05-19 19:23:46 -04:00
2009-11-28 20:49:44 -05:00
conn . connect ( " vm-added " , self . vm_added )
conn . connect ( " vm-removed " , self . vm_removed )
2013-09-02 09:09:31 -04:00
conn . connect ( " resources-sampled " , self . conn_row_updated )
2009-11-28 20:49:44 -05:00
conn . connect ( " state-changed " , self . conn_state_changed )
2018-03-13 12:34:26 -04:00
for vm in conn . list_vms ( ) :
2020-09-01 11:54:10 -04:00
self . vm_added ( conn , vm )
2018-03-13 12:34:26 -04:00
2020-08-26 07:25:37 -04:00
def _remove_child_rows ( self , row ) :
child = self . model . iter_children ( row . iter )
while child is not None : # pragma: no cover
# vm-removed signals should handle this, this is a fallback
# in case something goes wrong
self . model . remove ( child )
child = self . model . iter_children ( row . iter )
2018-03-14 13:13:22 -04:00
def _conn_removed ( self , _src , uri ) :
2018-03-17 17:35:04 -04:00
conn_row = None
for row in self . model :
if row [ ROW_IS_CONN ] and row [ ROW_HANDLE ] . get_uri ( ) == uri :
conn_row = row
break
2020-08-26 07:25:37 -04:00
if conn_row is None : # pragma: no cover
2011-04-12 11:50:10 -04:00
return
2020-08-26 07:25:37 -04:00
self . _remove_child_rows ( conn_row )
2018-03-17 17:35:04 -04:00
self . model . remove ( conn_row . iter )
2009-11-28 20:49:44 -05:00
#############################
# State/UI updating methods #
#############################
2006-06-14 10:59:40 -04:00
2013-09-02 09:09:31 -04:00
def vm_row_updated ( self , vm ) :
2018-03-17 17:35:04 -04:00
row = self . get_row ( vm )
2020-08-26 07:25:37 -04:00
if row is None : # pragma: no cover
2013-09-02 09:09:31 -04:00
return
2018-03-17 17:35:04 -04:00
self . model . row_changed ( row . path , row . iter )
2006-06-14 18:42:04 -04:00
2015-04-09 18:02:42 -04:00
def vm_changed ( self , vm ) :
2018-03-17 17:35:04 -04:00
row = self . get_row ( vm )
2013-09-01 18:36:58 -04:00
if row is None :
2020-08-26 07:25:37 -04:00
return # pragma: no cover
2006-11-13 15:38:10 -05:00
2013-08-16 15:59:33 +02:00
try :
2015-04-09 18:02:42 -04:00
if vm == self . current_vm ( ) :
self . update_current_selection ( )
2013-10-04 11:50:19 -04:00
name = vm . get_name_or_title ( )
2013-09-01 18:36:58 -04:00
status = vm . run_status ( )
row [ ROW_SORT_KEY ] = name
2013-08-16 15:59:33 +02:00
row [ ROW_STATUS_ICON ] = vm . run_status_icon_name ( )
row [ ROW_IS_VM_RUNNING ] = vm . is_active ( )
2013-09-01 18:36:58 -04:00
row [ ROW_MARKUP ] = self . _build_vm_markup ( name , status )
2013-08-16 15:59:33 +02:00
2013-09-02 09:09:31 -04:00
desc = vm . get_description ( )
2019-06-07 18:21:24 -04:00
row [ ROW_HINT ] = xmlutil . xml_escape ( desc )
2020-08-26 07:25:37 -04:00
except Exception as e : # pragma: no cover
2019-06-07 16:39:33 -04:00
if vm . conn . support . is_libvirt_error_no_domain ( e ) :
2013-08-16 15:59:33 +02:00
return
raise
2011-07-15 15:38:59 -04:00
2013-09-02 09:09:31 -04:00
self . vm_row_updated ( vm )
2011-07-18 19:53:56 +01:00
def vm_inspection_changed ( self , vm ) :
2018-03-17 17:35:04 -04:00
row = self . get_row ( vm )
2013-09-01 18:36:58 -04:00
if row is None :
2020-08-26 07:25:37 -04:00
return # pragma: no cover
2011-07-18 19:53:56 +01:00
2013-09-01 18:36:58 -04:00
new_icon = _get_inspection_icon_pixbuf ( vm , 16 , 16 )
inspection: Check can_set_row_none before setting icon to None.
Previously one could set the icon field of a tree model to None, but
with Gtk3 and older versions of pygobject3 this would fail.
Use can_set_row_none to test for this condition and work around it.
The previous traceback was:
Traceback (most recent call last):
File "/home/rjones/d/virt-manager/virtManager/manager.py", line 981, in vm_inspection_changed
self.get_inspection_icon_pixbuf(vm, 16, 16)
File "/usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py", line 1152, in __setitem__
self.model.set_value(self.iter, key, value)
File "/usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py", line 1298, in set_value
Gtk.TreeStore.set_value(self, treeiter, column, value)
File "/usr/lib64/python2.7/site-packages/gi/types.py", line 47, in function
return info.invoke(*args, **kwargs)
TypeError: Argument 3 does not allow None as a value
2013-06-28 18:45:53 +01:00
row [ ROW_INSPECTION_OS_ICON ] = new_icon
2013-06-13 16:10:28 -04:00
2013-09-02 09:09:31 -04:00
self . vm_row_updated ( vm )
2008-01-02 17:55:26 -05:00
2014-06-26 11:51:38 +02:00
def set_initial_selection ( self , uri ) :
2018-03-17 17:35:04 -04:00
"""
Select the passed URI in the UI . Called from engine . py via
cli - - connect $ URI
"""
sel = self . widget ( " vm-list " ) . get_selection ( )
for row in self . model :
if not row [ ROW_IS_CONN ] :
2020-08-26 07:25:37 -04:00
continue # pragma: no cover
2018-03-17 17:35:04 -04:00
conn = row [ ROW_HANDLE ]
if conn . get_uri ( ) == uri :
sel . select_iter ( row . iter )
2014-06-26 11:51:38 +02:00
return
2015-04-11 13:39:25 -04:00
def conn_state_changed ( self , conn ) :
2018-03-17 17:35:04 -04:00
row = self . get_row ( conn )
2015-04-11 13:39:25 -04:00
row [ ROW_SORT_KEY ] = conn . get_pretty_desc ( )
2013-09-01 18:36:58 -04:00
row [ ROW_MARKUP ] = self . _build_conn_markup ( conn , row [ ROW_SORT_KEY ] )
2014-09-11 18:16:21 -04:00
row [ ROW_IS_CONN_CONNECTED ] = not conn . is_disconnected ( )
2009-11-28 20:49:44 -05:00
row [ ROW_COLOR ] = self . _build_conn_color ( conn )
2011-07-15 15:38:59 -04:00
row [ ROW_HINT ] = self . _build_conn_hint ( conn )
2006-08-08 17:02:15 -04:00
2014-09-11 18:16:21 -04:00
if not conn . is_active ( ) :
2020-08-26 07:25:37 -04:00
self . _remove_child_rows ( row )
2011-07-25 15:09:42 -04:00
2013-09-02 09:09:31 -04:00
self . conn_row_updated ( conn )
self . update_current_selection ( )
def conn_row_updated ( self , conn ) :
2018-03-17 17:35:04 -04:00
row = self . get_row ( conn )
2013-09-02 09:09:31 -04:00
2011-07-25 15:09:42 -04:00
self . max_disk_rate = max ( self . max_disk_rate , conn . disk_io_max_rate ( ) )
self . max_net_rate = max ( self . max_net_rate ,
conn . network_traffic_max_rate ( ) )
2018-03-17 17:35:04 -04:00
self . model . row_changed ( row . path , row . iter )
2006-06-14 10:59:40 -04:00
2010-05-12 12:57:32 -04:00
def change_run_text ( self , can_restore ) :
if can_restore :
text = _ ( " _Restore " )
else :
text = _ ( " _Run " )
strip_text = text . replace ( " _ " , " " )
2013-09-22 15:13:41 -04:00
self . vmmenu . change_run_text ( text )
2011-07-14 13:13:13 -04:00
self . widget ( " vm-run " ) . set_label ( strip_text )
2006-06-14 10:59:40 -04:00
2013-09-02 09:09:31 -04:00
def update_current_selection ( self , ignore = None ) :
2007-08-09 16:19:41 -04:00
vm = self . current_vm ( )
2018-03-17 16:56:13 -04:00
conn = self . current_conn ( )
2009-07-26 16:15:05 -04:00
show_open = bool ( vm )
show_details = bool ( vm )
2018-03-17 16:56:13 -04:00
host_details = bool ( vm or conn )
can_delete = bool ( vm or conn )
2010-08-22 12:50:31 -04:00
2009-07-26 16:15:05 -04:00
show_run = bool ( vm and vm . is_runable ( ) )
is_paused = bool ( vm and vm . is_paused ( ) )
if is_paused :
show_pause = bool ( vm and vm . is_unpauseable ( ) )
2007-08-09 16:19:41 -04:00
else :
2009-07-26 16:15:05 -04:00
show_pause = bool ( vm and vm . is_pauseable ( ) )
show_shutdown = bool ( vm and vm . is_stoppable ( ) )
2010-05-12 12:57:32 -04:00
if vm and vm . managedsave_supported :
2014-09-11 18:01:41 -04:00
self . change_run_text ( vm . has_managed_save ( ) )
2010-05-12 12:57:32 -04:00
2011-07-14 13:13:13 -04:00
self . widget ( " vm-open " ) . set_sensitive ( show_open )
self . widget ( " vm-run " ) . set_sensitive ( show_run )
self . widget ( " vm-shutdown " ) . set_sensitive ( show_shutdown )
2013-09-22 13:24:59 -04:00
self . widget ( " vm-shutdown " ) . get_menu ( ) . update_widget_states ( vm )
2009-07-26 16:15:05 -04:00
self . set_pause_state ( is_paused )
2011-07-14 13:13:13 -04:00
self . widget ( " vm-pause " ) . set_sensitive ( show_pause )
2009-07-26 16:15:05 -04:00
2015-11-12 13:13:19 +01:00
if is_paused :
pauseTooltip = _ ( " Resume the virtual machine " )
else :
pauseTooltip = _ ( " Pause the virtual machine " )
self . widget ( " vm-pause " ) . set_tooltip_text ( pauseTooltip )
2018-03-17 16:56:13 -04:00
self . widget ( " menu_edit_delete " ) . set_sensitive ( can_delete )
2011-07-14 13:13:13 -04:00
self . widget ( " menu_edit_details " ) . set_sensitive ( show_details )
self . widget ( " menu_host_details " ) . set_sensitive ( host_details )
2009-07-26 16:15:05 -04:00
2010-12-09 11:22:35 -05:00
def popup_vm_menu_key ( self , widget_ignore , event ) :
2012-05-14 14:24:56 +01:00
if Gdk . keyval_name ( event . keyval ) != " Menu " :
2020-09-20 10:07:15 -04:00
return False # pragma: no cover
2009-11-11 09:49:34 -05:00
2014-01-26 20:21:12 -05:00
model , treeiter = self . widget ( " vm-list " ) . get_selection ( ) . get_selected ( )
self . popup_vm_menu ( model , treeiter , event )
2009-11-11 09:49:34 -05:00
return True
2007-08-13 17:13:39 -04:00
2018-03-17 17:35:04 -04:00
def popup_vm_menu_button ( self , vmlist , event ) :
2009-11-10 16:01:56 -05:00
if event . button != 3 :
return False
2018-03-17 17:35:04 -04:00
tup = vmlist . get_path_at_pos ( int ( event . x ) , int ( event . y ) )
2012-11-08 14:15:02 +01:00
if tup is None :
2020-08-26 07:25:37 -04:00
return False # pragma: no cover
2008-11-18 15:42:51 -05:00
path = tup [ 0 ]
2009-11-10 16:01:56 -05:00
2018-03-17 17:35:04 -04:00
self . popup_vm_menu ( self . model , self . model . get_iter ( path ) , event )
2009-12-09 11:28:38 -05:00
return False
2009-11-11 09:49:34 -05:00
def popup_vm_menu ( self , model , _iter , event ) :
2012-11-08 14:15:02 +01:00
if model . iter_parent ( _iter ) is not None :
2009-11-10 16:01:56 -05:00
# Popup the vm menu
2014-01-26 20:21:12 -05:00
vm = model [ _iter ] [ ROW_HANDLE ]
2013-09-22 15:13:41 -04:00
self . vmmenu . update_widget_states ( vm )
2019-04-02 16:18:57 -04:00
self . vmmenu . popup_at_pointer ( event )
2007-08-23 17:46:30 -04:00
else :
2009-11-10 16:01:56 -05:00
# Pop up connection menu
2014-01-26 20:21:12 -05:00
conn = model [ _iter ] [ ROW_HANDLE ]
2014-09-11 18:16:21 -04:00
disconn = conn . is_disconnected ( )
conning = conn . is_connecting ( )
2009-11-10 16:01:56 -05:00
self . connmenu_items [ " create " ] . set_sensitive ( not disconn )
self . connmenu_items [ " disconnect " ] . set_sensitive ( not ( disconn or
conning ) )
self . connmenu_items [ " connect " ] . set_sensitive ( disconn )
2009-11-16 16:35:34 -05:00
self . connmenu_items [ " delete " ] . set_sensitive ( disconn )
2009-11-10 16:01:56 -05:00
2019-04-02 16:18:57 -04:00
self . connmenu . popup_at_pointer ( event )
2009-11-10 16:01:56 -05:00
2009-11-11 11:02:57 -05:00
2009-11-28 20:49:44 -05:00
#################
# Stats methods #
#################
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
def vmlist_name_sorter ( self , model , iter1 , iter2 , ignore ) :
2015-03-26 19:13:29 -04:00
key1 = str ( model [ iter1 ] [ ROW_SORT_KEY ] ) . lower ( )
key2 = str ( model [ iter2 ] [ ROW_SORT_KEY ] ) . lower ( )
2017-10-21 19:18:02 -04:00
return _cmp ( key1 , key2 )
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
def vmlist_guest_cpu_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-26 20:21:12 -05:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2011-07-12 08:49:47 -04:00
2017-10-21 19:18:02 -04:00
return _cmp ( obj1 . guest_cpu_time_percentage ( ) ,
2011-07-12 08:49:47 -04:00
obj2 . guest_cpu_time_percentage ( ) )
2012-05-14 14:24:56 +01:00
def vmlist_host_cpu_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-26 20:21:12 -05:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2011-07-11 21:22:50 -04:00
2017-10-21 19:18:02 -04:00
return _cmp ( obj1 . host_cpu_time_percentage ( ) ,
2011-07-11 21:22:50 -04:00
obj2 . host_cpu_time_percentage ( ) )
2006-06-14 10:59:40 -04:00
2013-12-18 14:42:42 +01:00
def vmlist_memory_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-26 20:21:12 -05:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2013-12-18 14:42:42 +01:00
2017-10-21 19:18:02 -04:00
return _cmp ( obj1 . stats_memory ( ) ,
2013-12-18 14:42:42 +01:00
obj2 . stats_memory ( ) )
2012-05-14 14:24:56 +01:00
def vmlist_disk_io_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-26 20:21:12 -05:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2011-07-11 21:22:50 -04:00
2017-10-21 19:18:02 -04:00
return _cmp ( obj1 . disk_io_rate ( ) , obj2 . disk_io_rate ( ) )
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
def vmlist_network_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-26 20:21:12 -05:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2011-07-11 21:22:50 -04:00
2017-10-21 19:18:02 -04:00
return _cmp ( obj1 . network_traffic_rate ( ) , obj2 . network_traffic_rate ( ) )
2006-06-14 10:59:40 -04:00
2020-08-26 07:25:37 -04:00
def _config_polling_change_cb ( self , column ) :
2016-04-18 16:42:12 -04:00
# pylint: disable=redefined-variable-type
2014-02-11 15:29:30 -05:00
if column == COL_GUEST_CPU :
widgn = [ " menu_view_stats_guest_cpu " , " menu_view_stats_host_cpu " ]
do_enable = self . config . get_stats_enable_cpu_poll ( )
2013-04-17 17:39:25 -04:00
if column == COL_DISK :
2009-07-26 16:15:28 -04:00
widgn = " menu_view_stats_disk "
2013-04-17 17:39:25 -04:00
do_enable = self . config . get_stats_enable_disk_poll ( )
elif column == COL_NETWORK :
2009-07-26 16:15:28 -04:00
widgn = " menu_view_stats_network "
2013-04-17 17:39:25 -04:00
do_enable = self . config . get_stats_enable_net_poll ( )
2014-01-12 17:39:21 -05:00
elif column == COL_MEM :
widgn = " menu_view_stats_memory "
do_enable = self . config . get_stats_enable_memory_poll ( )
2008-12-17 15:27:06 -05:00
2019-06-07 18:21:24 -04:00
for w in xmlutil . listify ( widgn ) :
2014-02-11 15:29:30 -05:00
widget = self . widget ( w )
tool_text = " "
2010-12-13 16:24:49 -05:00
2014-02-11 15:29:30 -05:00
if do_enable :
widget . set_sensitive ( True )
else :
2020-08-26 07:25:37 -04:00
widget . set_active ( False )
2014-02-11 15:29:30 -05:00
widget . set_sensitive ( False )
tool_text = _ ( " Disabled in preferences dialog. " )
widget . set_tooltip_text ( tool_text )
2011-02-15 11:38:35 -05:00
2013-09-01 21:35:23 -04:00
def _toggle_graph_helper ( self , do_show , col , datafunc , menu ) :
img = - 1
for child in col . get_cells ( ) :
if isinstance ( child , CellRendererSparkline ) :
img = child
datafunc = do_show and datafunc or None
2009-07-26 16:15:28 -04:00
2013-09-01 21:35:23 -04:00
col . set_cell_data_func ( img , datafunc , None )
col . set_visible ( do_show )
self . widget ( menu ) . set_active ( do_show )
2011-07-12 08:49:47 -04:00
2013-12-18 14:42:42 +01:00
any_visible = any ( [ c . get_visible ( ) for c in
[ self . netcol , self . diskcol , self . memcol ,
self . guestcpucol , self . hostcpucol ] ] )
2013-09-02 10:43:53 -04:00
self . spacer_txt . set_property ( " visible " , not any_visible )
2013-09-01 21:35:23 -04:00
def toggle_network_traffic_visible_widget ( self ) :
self . _toggle_graph_helper (
self . config . is_vmlist_network_traffic_visible ( ) , self . netcol ,
self . network_traffic_img , " menu_view_stats_network " )
def toggle_disk_io_visible_widget ( self ) :
self . _toggle_graph_helper (
self . config . is_vmlist_disk_io_visible ( ) , self . diskcol ,
self . disk_io_img , " menu_view_stats_disk " )
2013-12-18 14:42:42 +01:00
def toggle_memory_usage_visible_widget ( self ) :
self . _toggle_graph_helper (
self . config . is_vmlist_memory_usage_visible ( ) , self . memcol ,
self . memory_usage_img , " menu_view_stats_memory " )
2013-04-17 17:39:25 -04:00
def toggle_guest_cpu_usage_visible_widget ( self ) :
2013-09-01 21:35:23 -04:00
self . _toggle_graph_helper (
self . config . is_vmlist_guest_cpu_usage_visible ( ) , self . guestcpucol ,
self . guest_cpu_usage_img , " menu_view_stats_guest_cpu " )
2013-04-17 17:39:25 -04:00
def toggle_host_cpu_usage_visible_widget ( self ) :
2013-09-01 21:35:23 -04:00
self . _toggle_graph_helper (
self . config . is_vmlist_host_cpu_usage_visible ( ) , self . hostcpucol ,
self . host_cpu_usage_img , " menu_view_stats_host_cpu " )
2009-11-11 11:02:57 -05:00
def toggle_stats_visible ( self , src , stats_id ) :
visible = src . get_active ( )
set_stats = {
2011-07-12 08:49:47 -04:00
COL_GUEST_CPU : self . config . set_vmlist_guest_cpu_usage_visible ,
COL_HOST_CPU : self . config . set_vmlist_host_cpu_usage_visible ,
2013-12-18 14:42:42 +01:00
COL_MEM : self . config . set_vmlist_memory_usage_visible ,
2011-07-12 08:49:47 -04:00
COL_DISK : self . config . set_vmlist_disk_io_visible ,
COL_NETWORK : self . config . set_vmlist_network_traffic_visible ,
2009-11-11 11:02:57 -05:00
}
set_stats [ stats_id ] ( visible )
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
def toggle_stats_visible_guest_cpu ( self , src ) :
self . toggle_stats_visible ( src , COL_GUEST_CPU )
def toggle_stats_visible_host_cpu ( self , src ) :
self . toggle_stats_visible ( src , COL_HOST_CPU )
2013-12-18 14:42:42 +01:00
def toggle_stats_visible_memory_usage ( self , src ) :
self . toggle_stats_visible ( src , COL_MEM )
2012-05-14 14:24:56 +01:00
def toggle_stats_visible_disk ( self , src ) :
self . toggle_stats_visible ( src , COL_DISK )
def toggle_stats_visible_network ( self , src ) :
self . toggle_stats_visible ( src , COL_NETWORK )
2011-07-12 08:49:47 -04:00
def guest_cpu_usage_img ( self , column_ignore , cell , model , _iter , data ) :
2013-09-01 21:35:23 -04:00
obj = model [ _iter ] [ ROW_HANDLE ]
2012-05-14 14:24:56 +01:00
if obj is None or not hasattr ( obj , " conn " ) :
2011-07-12 08:49:47 -04:00
return
2015-05-04 16:33:56 -04:00
data = obj . guest_cpu_time_vector ( GRAPH_LEN )
2011-07-12 08:49:47 -04:00
cell . set_property ( ' data_array ' , data )
def host_cpu_usage_img ( self , column_ignore , cell , model , _iter , data ) :
2013-09-01 21:35:23 -04:00
obj = model [ _iter ] [ ROW_HANDLE ]
2012-05-14 14:24:56 +01:00
if obj is None or not hasattr ( obj , " conn " ) :
2007-08-14 16:28:36 -04:00
return
2011-07-11 21:22:50 -04:00
2015-05-04 16:33:56 -04:00
data = obj . host_cpu_time_vector ( GRAPH_LEN )
2008-10-18 21:28:57 +02:00
cell . set_property ( ' data_array ' , data )
2013-12-18 14:42:42 +01:00
def memory_usage_img ( self , column_ignore , cell , model , _iter , data ) :
obj = model [ _iter ] [ ROW_HANDLE ]
if obj is None or not hasattr ( obj , " conn " ) :
return
2015-05-04 16:33:56 -04:00
data = obj . stats_memory_vector ( GRAPH_LEN )
2013-12-18 14:42:42 +01:00
cell . set_property ( ' data_array ' , data )
2010-12-09 11:22:35 -05:00
def disk_io_img ( self , column_ignore , cell , model , _iter , data ) :
2013-09-01 21:35:23 -04:00
obj = model [ _iter ] [ ROW_HANDLE ]
2012-05-14 14:24:56 +01:00
if obj is None or not hasattr ( obj , " conn " ) :
2011-07-25 15:09:42 -04:00
return
2015-05-04 16:33:56 -04:00
d1 , d2 = obj . disk_io_vectors ( GRAPH_LEN , self . max_disk_rate )
2018-02-09 14:02:04 -05:00
data = [ ( x + y ) / 2 for x , y in zip ( d1 , d2 ) ]
2008-10-18 21:28:57 +02:00
cell . set_property ( ' data_array ' , data )
2010-12-09 11:22:35 -05:00
def network_traffic_img ( self , column_ignore , cell , model , _iter , data ) :
2013-09-01 21:35:23 -04:00
obj = model [ _iter ] [ ROW_HANDLE ]
2012-05-14 14:24:56 +01:00
if obj is None or not hasattr ( obj , " conn " ) :
2011-07-25 15:09:42 -04:00
return
2015-05-04 16:33:56 -04:00
d1 , d2 = obj . network_traffic_vectors ( GRAPH_LEN , self . max_net_rate )
2018-02-09 14:02:04 -05:00
data = [ ( x + y ) / 2 for x , y in zip ( d1 , d2 ) ]
2006-06-26 17:17:45 -04:00
cell . set_property ( ' data_array ' , data )