2014-06-26 13:51:38 +04:00
# Copyright (C) 2006-2008, 2013-2014 Red Hat, Inc.
2006-06-28 23:50:17 +04:00
# Copyright (C) 2006 Daniel P. Berrange <berrange@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.
2006-06-14 18:59:40 +04:00
2012-05-14 17:24:56 +04:00
from gi . repository import GObject
from gi . repository import Gtk
from gi . repository import Gdk
from gi . repository import GdkPixbuf
2011-04-18 20:39:53 +04:00
2019-06-17 04:12:39 +03:00
from virtinst import log
2019-06-08 01:21:24 +03:00
from virtinst import xmlutil
2013-08-09 17:23:01 +04:00
2014-09-13 00:10:45 +04:00
from . import vmmenu
2019-06-17 05:19:17 +03:00
from . lib import uiutil
2014-09-13 00:10:45 +04:00
from . baseclass import vmmGObjectUI
2018-03-14 20:13:22 +03:00
from . connmanager import vmmConnectionManager
2018-03-15 01:58:22 +03:00
from . engine import vmmEngine
2019-06-17 05:19:17 +03:00
from . lib . graphwidgets import CellRendererSparkline
2006-07-20 19:16:07 +04:00
2012-05-14 17:24:56 +04:00
# Number of data points for performance graphs
GRAPH_LEN = 40
2006-06-14 18:59:40 +04:00
2007-08-29 01:57:25 +04:00
# fields in the tree model data set
2013-04-23 20:42:41 +04:00
( ROW_HANDLE ,
2013-09-02 02:36:58 +04:00
ROW_SORT_KEY ,
2013-04-23 20: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-02 02:36:58 +04:00
ROW_INSPECTION_OS_ICON ) = range ( 11 )
2007-08-28 06:22:18 +04:00
# Columns in the tree view
2013-09-02 18:43:53 +04:00
( COL_NAME ,
COL_GUEST_CPU ,
COL_HOST_CPU ,
2013-12-18 17:42:42 +04:00
COL_MEM ,
2013-09-02 18:43:53 +04:00
COL_DISK ,
2013-12-18 17:42:42 +04:00
COL_NETWORK ) = range ( 6 )
2007-08-28 06:22:18 +04:00
2013-02-16 22:54:45 +04:00
2013-04-20 20: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-27 00:15:05 +04:00
2017-10-22 02:18:02 +03:00
def _cmp ( a , b ) :
return ( ( a > b ) - ( a < b ) )
2013-09-02 02: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 14:25:37 +03:00
except Exception : # pragma: no cover
2019-06-17 04:12:39 +03:00
log . exception ( " Error loading inspection icon data " )
2013-09-02 02:36:58 +04:00
vm . inspection . icon = None
return None
2010-12-09 01:26:19 +03:00
class vmmManager ( vmmGObjectUI ) :
2018-03-15 12:53:58 +03:00
@classmethod
def get_instance ( cls , parentobj ) :
try :
if not cls . _instance :
2018-03-17 23:08:20 +03:00
cls . _instance = vmmManager ( )
2018-03-15 12:53:58 +03:00
return cls . _instance
2020-08-20 20:34:01 +03:00
except Exception as e : # pragma: no cover
2018-03-17 01:58:11 +03:00
if not parentobj :
raise
2018-03-15 12:53:58 +03:00
parentobj . err . show_err (
_ ( " Error launching manager: %s " ) % str ( e ) )
2012-05-14 17:24:56 +04:00
2018-03-14 20:13:22 +03:00
def __init__ ( self ) :
2013-09-23 00:10:16 +04:00
vmmGObjectUI . __init__ ( self , " manager.ui " , " vmm-manager " )
2018-03-15 14:43:56 +03:00
self . _cleanup_on_app_close ( )
2010-11-30 22:33:21 +03:00
2009-11-29 05:00:46 +03:00
w , h = self . config . get_manager_window_size ( )
2010-02-23 22:18:12 +03:00
self . topwin . set_default_size ( w or 550 , h or 550 )
2010-12-14 01:48:19 +03:00
self . prev_position = None
2015-09-13 21:07:43 +03:00
self . _window_size = None
2009-11-29 05:00:46 +03:00
2014-01-29 03:04:46 +04:00
self . vmmenu = vmmenu . VMActionMenu ( self , self . current_vm )
2018-03-15 14:43:56 +03:00
self . shutdownmenu = vmmenu . VMShutdownMenu ( self , self . current_vm )
2012-05-14 17:24:56 +04:00
self . connmenu = Gtk . Menu ( )
2020-09-22 04:29:00 +03:00
self . connmenu . get_accessible ( ) . set_name ( " conn-menu " )
2009-11-29 04:49:44 +03:00
self . connmenu_items = { }
2011-04-13 17:27:02 +04:00
2013-02-16 22:31:46 +04:00
self . builder . connect_signals ( {
2011-07-12 16:49:47 +04:00
" on_menu_view_guest_cpu_usage_activate " :
2017-08-17 14:01:28 +03:00
self . toggle_stats_visible_guest_cpu ,
2011-07-12 16:49:47 +04:00
" on_menu_view_host_cpu_usage_activate " :
2017-08-17 14:01:28 +03:00
self . toggle_stats_visible_host_cpu ,
2013-12-18 17:42:42 +04:00
" on_menu_view_memory_usage_activate " :
2017-08-17 14:01:28 +03:00
self . toggle_stats_visible_memory_usage ,
2017-08-05 09:39:32 +03:00
" on_menu_view_disk_io_activate " :
2017-08-17 14:01:28 +03:00
self . toggle_stats_visible_disk ,
2011-07-12 16:49:47 +04:00
" on_menu_view_network_traffic_activate " :
2017-08-17 14:01:28 +03:00
self . toggle_stats_visible_network ,
2009-11-29 04:49:44 +03:00
" on_vm_manager_delete_event " : self . close ,
2009-11-29 05:00:46 +03:00
" on_vmm_manager_configure_event " : self . window_resized ,
2018-03-16 04:22:14 +03:00
" on_menu_file_add_connection_activate " : self . open_newconn ,
2014-02-01 22:36:02 +04:00
" on_menu_new_vm_activate " : self . new_vm ,
2009-11-29 04:49:44 +03:00
" on_menu_file_quit_activate " : self . exit_app ,
" on_menu_file_close_activate " : self . close ,
" on_vmm_close_clicked " : self . close ,
2011-06-09 00:33:20 +04:00
" on_vm_open_clicked " : self . show_vm ,
2009-11-29 04:49:44 +03: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-09 00:33:20 +04:00
" on_menu_edit_details_activate " : self . show_vm ,
2009-11-29 04:49:44 +03:00
" on_menu_edit_delete_activate " : self . do_delete ,
" on_menu_host_details_activate " : self . show_host ,
2018-03-15 12:53:58 +03:00
" on_vm_list_row_activated " : self . row_activated ,
2009-11-29 04:49:44 +03: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 17:27:02 +04:00
} )
2013-09-02 18: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 17:42:42 +04:00
self . memcol = None
2013-09-02 18:43:53 +04:00
self . guestcpucol = None
self . hostcpucol = None
self . spacer_txt = None
2011-04-13 17:27:02 +04:00
self . init_vmlist ( )
2013-09-02 18:43:53 +04:00
2011-04-13 17:27:02 +04:00
self . init_stats ( )
self . init_toolbar ( )
self . init_context_menus ( )
2009-11-29 04:49:44 +03:00
2013-09-02 17:09:31 +04:00
self . update_current_selection ( )
self . widget ( " vm-list " ) . get_selection ( ) . connect (
" changed " , self . update_current_selection )
2009-11-29 04:49:44 +03:00
2011-07-25 23:09:42 +04:00
self . max_disk_rate = 10.0
self . max_net_rate = 10.0
2009-11-29 04:49:44 +03:00
# Initialize stat polling columns based on global polling
# preferences (we want signal handlers for this)
2020-08-26 14:25:37 +03: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-29 04:49:44 +03:00
2018-03-14 20:13:22 +03: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 17:29:20 +03:00
2009-11-29 04:49:44 +03:00
##################
# Common methods #
##################
def show ( self ) :
2010-12-09 01:26:19 +03:00
vis = self . is_visible ( )
2010-02-23 22:18:12 +03:00
self . topwin . present ( )
2010-12-09 01:26:19 +03:00
if vis :
return
2010-02-23 22:18:12 +03:00
2019-06-17 04:12:39 +03:00
log . debug ( " Showing manager " )
2010-12-14 01:48:19 +03:00
if self . prev_position :
self . topwin . move ( * self . prev_position )
self . prev_position = None
2011-04-13 18:47:31 +04:00
2018-03-15 02:06:30 +03:00
vmmEngine . get_instance ( ) . increment_window_counter ( )
2009-11-29 04:49:44 +03:00
2010-12-09 19:22:35 +03:00
def close ( self , src_ignore = None , src2_ignore = None ) :
2010-12-09 01:26:19 +03:00
if not self . is_visible ( ) :
return
2019-06-17 04:12:39 +03:00
log . debug ( " Closing manager " )
2010-12-14 01:48:19 +03:00
self . prev_position = self . topwin . get_position ( )
2010-12-09 01:26:19 +03:00
self . topwin . hide ( )
2018-03-15 02:06:30 +03:00
vmmEngine . get_instance ( ) . decrement_window_counter ( )
2011-04-13 18:47:31 +04:00
2010-12-09 01:26:19 +03:00
return 1
2009-11-29 04:49:44 +03:00
2011-04-13 17:27:02 +04:00
2011-07-24 05:16:54 +04:00
def _cleanup ( self ) :
self . diskcol = None
self . guestcpucol = None
2013-12-18 17:42:42 +04:00
self . memcol = None
2011-07-24 05:16:54 +04:00
self . hostcpucol = None
self . netcol = None
2011-04-13 17:27:02 +04:00
2018-03-15 14:43:56 +03:00
self . shutdownmenu . destroy ( )
self . shutdownmenu = None
2014-04-03 02:39:43 +04:00
self . vmmenu . destroy ( )
2011-07-24 05:16:54 +04:00
self . vmmenu = None
self . connmenu . destroy ( )
self . connmenu = None
self . connmenu_items = None
2011-04-13 17:27:02 +04:00
2015-09-13 21:07:43 +03:00
if self . _window_size :
self . config . set_manager_window_size ( * self . _window_size )
2010-03-03 04:35:54 +03:00
def set_startup_error ( self , msg ) :
2011-07-14 21:13:13 +04:00
self . widget ( " vm-notebook " ) . set_current_page ( 1 )
self . widget ( " startup-error-label " ) . set_text ( msg )
2006-06-14 18:59:40 +04:00
2019-04-14 00:03:16 +03:00
2009-11-29 04:49:44 +03:00
################
# Init methods #
################
def init_stats ( self ) :
2014-09-28 15:37:16 +04:00
self . add_gsettings_handle (
2011-07-12 16:49:47 +04:00
self . config . on_vmlist_guest_cpu_usage_visible_changed (
self . toggle_guest_cpu_usage_visible_widget ) )
2014-09-28 15:37:16 +04:00
self . add_gsettings_handle (
2011-07-12 16:49:47 +04:00
self . config . on_vmlist_host_cpu_usage_visible_changed (
self . toggle_host_cpu_usage_visible_widget ) )
2014-09-28 15:37:16 +04:00
self . add_gsettings_handle (
2013-12-18 17:42:42 +04:00
self . config . on_vmlist_memory_usage_visible_changed (
self . toggle_memory_usage_visible_widget ) )
2014-09-28 15:37:16 +04:00
self . add_gsettings_handle (
2011-04-13 17:27:02 +04:00
self . config . on_vmlist_disk_io_visible_changed (
2011-07-12 16:49:47 +04:00
self . toggle_disk_io_visible_widget ) )
2014-09-28 15:37:16 +04:00
self . add_gsettings_handle (
2011-04-13 17:27:02 +04:00
self . config . on_vmlist_network_traffic_visible_changed (
self . toggle_network_traffic_visible_widget ) )
2006-06-14 18:59:40 +04:00
2008-12-17 23:27:06 +03:00
# Register callbacks with the global stats enable/disable values
# that disable the associated vmlist widgets if reporting is disabled
2014-09-28 15:37:16 +04:00
self . add_gsettings_handle (
2014-02-12 00:29:30 +04:00
self . config . on_stats_enable_cpu_poll_changed (
2020-08-26 14:25:37 +03:00
self . _config_polling_change_cb , COL_GUEST_CPU ) )
2014-09-28 15:37:16 +04:00
self . add_gsettings_handle (
2014-02-12 00:29:30 +04:00
self . config . on_stats_enable_disk_poll_changed (
2020-08-26 14:25:37 +03:00
self . _config_polling_change_cb , COL_DISK ) )
2014-09-28 15:37:16 +04:00
self . add_gsettings_handle (
2014-02-12 00:29:30 +04:00
self . config . on_stats_enable_net_poll_changed (
2020-08-26 14:25:37 +03:00
self . _config_polling_change_cb , COL_NETWORK ) )
2014-09-28 15:37:16 +04:00
self . add_gsettings_handle (
2014-01-13 02:39:21 +04:00
self . config . on_stats_enable_memory_poll_changed (
2020-08-26 14:25:37 +03:00
self . _config_polling_change_cb , COL_MEM ) )
2011-04-13 17:27:02 +04:00
2013-09-02 05:35:23 +04:00
self . toggle_guest_cpu_usage_visible_widget ( )
self . toggle_host_cpu_usage_visible_widget ( )
2013-12-18 17:42:42 +04:00
self . toggle_memory_usage_visible_widget ( )
2013-09-02 05:35:23 +04:00
self . toggle_disk_io_visible_widget ( )
self . toggle_network_traffic_visible_widget ( )
2008-12-17 23:27:06 +03:00
2009-11-11 19:02:57 +03:00
2009-11-29 04:49:44 +03:00
def init_toolbar ( self ) :
2011-07-14 21: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 21:24:59 +04:00
self . widget ( " vm-shutdown " ) . set_icon_name ( " system-shutdown " )
2018-03-15 14:43:56 +03:00
self . widget ( " vm-shutdown " ) . set_menu ( self . shutdownmenu )
2011-07-14 21:13:13 +04:00
tool = self . widget ( " vm-toolbar " )
2012-05-14 17:24:56 +04:00
tool . set_property ( " icon-size " , Gtk . IconSize . LARGE_TOOLBAR )
2009-11-10 20:57:28 +03:00
for c in tool . get_children ( ) :
2009-07-27 00:25:01 +04:00
c . set_homogeneous ( False )
2009-11-29 04:49:44 +03:00
def init_context_menus ( self ) :
2020-08-20 20:34:01 +03:00
def add_to_menu ( idx , text , cb ) :
2022-02-19 20:01:55 +03:00
item = Gtk . MenuItem . new_with_mnemonic ( text )
2010-05-12 23:31:36 +04:00
if cb :
item . connect ( " activate " , cb )
2018-01-10 01:33:05 +03:00
item . get_accessible ( ) . set_name ( " conn- %s " % idx )
2013-09-22 23:13:41 +04:00
self . connmenu . add ( item )
self . connmenu_items [ idx ] = item
2006-06-14 18:59:40 +04:00
2010-05-12 23:31:36 +04:00
# Build connection context menu
2022-02-19 20:01:55 +03: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 23:13:41 +04:00
self . connmenu . add ( Gtk . SeparatorMenuItem ( ) )
2022-02-19 20:01:55 +03:00
add_to_menu ( " delete " , _ ( " De_lete " ) , self . do_delete )
2013-09-22 23:13:41 +04:00
self . connmenu . add ( Gtk . SeparatorMenuItem ( ) )
2022-02-19 20:01:55 +03:00
add_to_menu ( " details " , _ ( " _Details " ) , self . show_host )
2013-09-22 23:13:41 +04:00
self . connmenu . show_all ( )
2007-08-14 01:13:39 +04:00
2009-11-29 04:49:44 +03:00
def init_vmlist ( self ) :
2011-07-14 21:13:13 +04:00
vmlist = self . widget ( " vm-list " )
self . widget ( " vm-notebook " ) . set_show_tabs ( False )
2006-06-14 18:59:40 +04:00
2013-04-23 20:42:41 +04:00
rowtypes = [ ]
rowtypes . insert ( ROW_HANDLE , object ) # backing object
2013-09-02 02:36:58 +04:00
rowtypes . insert ( ROW_SORT_KEY , str ) # object name
2013-04-23 20: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 21:04:33 +04:00
rowtypes . insert ( ROW_COLOR , str ) # row markup color string
2013-04-23 22:24:52 +04:00
rowtypes . insert ( ROW_INSPECTION_OS_ICON , GdkPixbuf . Pixbuf ) # OS icon
2013-04-23 20:42:41 +04:00
model = Gtk . TreeStore ( * rowtypes )
2009-11-29 04:49:44 +03:00
vmlist . set_model ( model )
2012-02-02 02:26:46 +04:00
vmlist . set_tooltip_column ( ROW_HINT )
2009-11-29 04:49:44 +03:00
vmlist . set_headers_visible ( True )
2013-04-20 20:52:53 +04:00
vmlist . set_level_indentation (
- ( _style_get_prop ( vmlist , " expander-size " ) + 3 ) )
2006-06-14 18:59:40 +04:00
2012-05-14 17:24:56 +04:00
nameCol = Gtk . TreeViewColumn ( _ ( " Name " ) )
2009-11-29 04:49:44 +03:00
nameCol . set_expand ( True )
2013-09-10 18:07:11 +04:00
nameCol . set_sizing ( Gtk . TreeViewColumnSizing . AUTOSIZE )
2009-11-29 04:49:44 +03:00
nameCol . set_spacing ( 6 )
2013-09-02 18:43:53 +04:00
nameCol . set_sort_column_id ( COL_NAME )
2006-11-06 18:34:54 +03:00
2009-11-29 04:49:44 +03:00
vmlist . append_column ( nameCol )
2008-12-17 23:27:06 +03:00
2012-05-14 17:24:56 +04:00
status_icon = Gtk . CellRendererPixbuf ( )
status_icon . set_property ( " stock-size " , Gtk . IconSize . DND )
2013-09-02 18: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 23:22:03 +03:00
2012-05-14 17:24:56 +04:00
inspection_os_icon = Gtk . CellRendererPixbuf ( )
2013-09-02 18:43:53 +04:00
nameCol . pack_start ( inspection_os_icon , False )
nameCol . add_attribute ( inspection_os_icon , ' pixbuf ' ,
2011-07-18 22:53:56 +04:00
ROW_INSPECTION_OS_ICON )
2013-09-02 18:43:53 +04:00
nameCol . add_attribute ( inspection_os_icon , ' visible ' , ROW_IS_VM )
2011-07-18 22:53:56 +04:00
2012-05-14 17:24:56 +04:00
name_txt = Gtk . CellRendererText ( )
2009-11-29 04:49:44 +03:00
nameCol . pack_start ( name_txt , True )
nameCol . add_attribute ( name_txt , ' markup ' , ROW_MARKUP )
2013-04-23 21:04:33 +04:00
nameCol . add_attribute ( name_txt , ' foreground ' , ROW_COLOR )
2013-09-02 18: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-10 06:57:24 +04:00
2013-09-02 05:35:23 +04:00
def make_stats_column ( title , colnum ) :
2012-05-14 17:24:56 +04:00
col = Gtk . TreeViewColumn ( title )
2011-07-12 16:49:47 +04:00
col . set_min_width ( 140 )
2013-04-20 22:11:31 +04:00
2012-05-14 17:24:56 +04:00
txt = Gtk . CellRendererText ( )
2013-04-20 21:43:21 +04:00
txt . set_property ( " ypad " , 4 )
2013-04-20 22:11:31 +04:00
col . pack_start ( txt , True )
col . add_attribute ( txt , ' visible ' , ROW_IS_CONN )
2011-07-12 16: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 22:11:31 +04:00
2011-07-12 16:49:47 +04:00
col . set_sort_column_id ( colnum )
vmlist . append_column ( col )
return col
2013-09-02 05: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 17:42:42 +04:00
self . memcol = make_stats_column ( _ ( " Memory usage " ) , COL_MEM )
2013-09-02 05: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 18:59:40 +04:00
2009-11-29 04:49:44 +03:00
model . set_sort_func ( COL_NAME , self . vmlist_name_sorter )
2011-07-12 16: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 17:42:42 +04:00
model . set_sort_func ( COL_MEM , self . vmlist_memory_usage_sorter )
2009-11-29 04:49:44 +03: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 17:24:56 +04:00
model . set_sort_column_id ( COL_NAME , Gtk . SortType . ASCENDING )
2009-11-29 04:49:44 +03:00
2018-03-18 00:35:04 +03:00
2009-11-29 04:49:44 +03:00
##################
# Helper methods #
##################
2018-03-18 00:35:04 +03:00
@property
def model ( self ) :
return self . widget ( " vm-list " ) . get_model ( )
2009-11-29 04:49:44 +03:00
def current_row ( self ) :
2015-05-20 00:17:53 +03:00
return uiutil . get_list_selected_row ( self . widget ( " vm-list " ) )
2009-11-29 04:49:44 +03: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-18 00:35:04 +03:00
def current_conn ( self ) :
2009-11-29 04:49:44 +03:00
row = self . current_row ( )
2018-03-18 00:35:04 +03: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 21:27:10 +03:00
def _walk ( model , rowiter , obj ) :
2018-03-18 00:35:04 +03:00
while rowiter :
2018-10-13 21:27:10 +03:00
row = model [ rowiter ]
if row [ ROW_HANDLE ] == obj :
2018-03-18 00:35:04 +03:00
return row
2018-10-13 21:27:10 +03:00
if model . iter_has_child ( rowiter ) :
ret = _walk ( model , model . iter_nth_child ( rowiter , 0 ) , obj )
2018-03-18 00:35:04 +03:00
if ret :
return ret
2018-10-13 21:27:10 +03:00
rowiter = model . iter_next ( rowiter )
2018-03-18 00:35:04 +03:00
if not len ( self . model ) :
return None
2018-10-13 21:27:10 +03:00
return _walk ( self . model , self . model . get_iter_first ( ) , conn_or_vm )
2010-08-22 20:50:31 +04:00
2009-11-29 04:49:44 +03:00
####################
# Action listeners #
####################
2006-11-03 18:02:02 +03:00
2016-12-13 21:27:06 +03:00
def window_resized ( self , ignore , ignore2 ) :
2009-11-29 05:00:46 +03:00
if not self . is_visible ( ) :
return
2016-12-13 21:27:06 +03:00
self . _window_size = self . topwin . get_size ( )
2009-11-29 05:00:46 +03:00
2010-12-09 19:22:35 +03:00
def exit_app ( self , src_ignore = None , src2_ignore = None ) :
2018-03-15 01:58:22 +03:00
vmmEngine . get_instance ( ) . exit_app ( )
2006-06-14 18:59:40 +04:00
2018-03-16 04:22:14 +03:00
def open_newconn ( self , _src ) :
2019-06-17 05:03:25 +03:00
from . createconn import vmmCreateConn
vmmCreateConn . get_instance ( self ) . show ( self . topwin )
2006-06-14 18:59:40 +04:00
2018-03-15 12:53:58 +03:00
def new_vm ( self , _src ) :
2019-06-17 05:00:57 +03:00
from . createvm import vmmCreateVM
2018-03-15 12:53:58 +03:00
conn = self . current_conn ( )
2019-06-17 05:00:57 +03:00
vmmCreateVM . show_instance ( self , conn and conn . get_uri ( ) or None )
2009-11-29 04:49:44 +03:00
2018-03-13 18:52:11 +03:00
def show_about ( self , _src ) :
from . about import vmmAbout
vmmAbout . show_instance ( self )
2009-11-29 04:49:44 +03:00
2010-12-09 19:22:35 +03:00
def show_preferences ( self , src_ignore ) :
2018-03-13 18:58:36 +03:00
from . preferences import vmmPreferences
vmmPreferences . show_instance ( self )
2009-11-29 04:49:44 +03:00
2018-03-15 12:53:58 +03:00
def show_host ( self , _src ) :
from . host import vmmHost
2018-03-18 00:35:04 +03:00
conn = self . current_conn ( )
2018-03-15 12:53:58 +03:00
vmmHost . show_instance ( self , conn )
def show_vm ( self , _src ) :
vmmenu . VMActionUI . show ( self , self . current_vm ( ) )
2009-11-29 04:49:44 +03:00
2018-03-15 12:53:58 +03:00
def row_activated ( self , _src , * args ) :
ignore = args
2011-07-23 00:43:26 +04:00
conn = self . current_conn ( )
2011-06-09 00:33:20 +04:00
vm = self . current_vm ( )
if conn is None :
2020-08-26 14:25:37 +03:00
return # pragma: no cover
2011-06-09 00:33:20 +04:00
if vm :
2018-03-15 12:53:58 +03:00
self . show_vm ( _src )
elif conn . is_disconnected ( ) :
2020-08-26 14:25:37 +03:00
self . open_conn ( )
2011-06-09 00:33:20 +04:00
else :
2018-03-15 12:53:58 +03:00
self . show_host ( _src )
2009-11-29 04:49:44 +03:00
def do_delete ( self , ignore = None ) :
2011-07-23 00:43:26 +04:00
conn = self . current_conn ( )
2009-11-29 04:49:44 +03:00
vm = self . current_vm ( )
if vm is None :
2011-07-23 00:43:26 +04:00
self . _do_delete_conn ( conn )
2009-11-29 04:49:44 +03:00
else :
2018-03-15 00:48:17 +03:00
vmmenu . VMActionUI . delete ( self , vm )
2009-11-29 04:49:44 +03:00
2011-07-23 00:43:26 +04:00
def _do_delete_conn ( self , conn ) :
2009-11-29 04:49:44 +03: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 21:42:20 +04:00
2018-03-15 12:53:58 +03:00
vmmConnectionManager . get_instance ( ) . remove_conn ( conn . get_uri ( ) )
2009-11-29 04:49:44 +03:00
def set_pause_state ( self , state ) :
2011-07-14 21:13:13 +04:00
src = self . widget ( " vm-pause " )
2009-11-29 04:49:44 +03:00
try :
2015-11-11 02:30:31 +03:00
src . handler_block_by_func ( self . pause_vm_button )
2009-11-29 04:49:44 +03:00
src . set_active ( state )
finally :
2015-11-11 02:30:31 +03:00
src . handler_unblock_by_func ( self . pause_vm_button )
2009-11-29 04:49:44 +03:00
def pause_vm_button ( self , src ) :
do_pause = src . get_active ( )
2011-04-15 22: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-29 04:49:44 +03:00
if do_pause :
2018-03-08 21:42:45 +03:00
vmmenu . VMActionUI . suspend ( self , self . current_vm ( ) )
2009-11-29 04:49:44 +03:00
else :
2018-03-08 21:42:45 +03:00
vmmenu . VMActionUI . resume ( self , self . current_vm ( ) )
2009-11-29 04:49:44 +03:00
def start_vm ( self , ignore ) :
2018-03-08 21:42:45 +03:00
vmmenu . VMActionUI . run ( self , self . current_vm ( ) )
def poweroff_vm ( self , _src ) :
vmmenu . VMActionUI . shutdown ( self , self . current_vm ( ) )
2009-11-29 04:49:44 +03:00
2011-07-23 00:43:26 +04:00
def close_conn ( self , ignore ) :
conn = self . current_conn ( )
2014-09-12 02:16:21 +04:00
if not conn . is_disconnected ( ) :
2009-11-29 04:49:44 +03:00
conn . close ( )
2011-07-23 00:43:26 +04:00
def open_conn ( self , ignore = None ) :
conn = self . current_conn ( )
2014-09-12 02:16:21 +04:00
if conn . is_disconnected ( ) :
2020-08-26 14:25:37 +03:00
conn . connect_once ( " open-completed " , self . _conn_open_completed_cb )
2009-11-29 04:49:44 +03:00
conn . open ( )
return True
2020-08-26 14:25:37 +03:00
def _conn_open_completed_cb ( self , _conn , ConnectError ) :
if ConnectError :
msg , details , title = ConnectError
self . err . show_err ( msg , details , title )
2009-11-29 04:49:44 +03:00
####################################
# VM add/remove management methods #
####################################
2020-09-01 18:54:10 +03:00
def vm_added ( self , conn , vm ) :
2018-03-18 00:35:04 +03:00
vm_row = self . _build_row ( None , vm )
conn_row = self . get_row ( conn )
self . model . append ( conn_row . iter , vm_row )
2016-05-20 02:31:22 +03:00
2015-04-10 01:02:42 +03:00
vm . connect ( " state-changed " , self . vm_changed )
2013-09-02 17:09:31 +04:00
vm . connect ( " resources-sampled " , self . vm_row_updated )
2011-07-18 22:53:56 +04:00
vm . connect ( " inspection-changed " , self . vm_inspection_changed )
2006-06-15 01:52:49 +04:00
2016-05-20 02:31:22 +03:00
# Expand a connection when adding a vm to it
2018-03-18 00:35:04 +03:00
self . widget ( " vm-list " ) . expand_row ( conn_row . path , False )
2006-06-14 18:59:40 +04:00
2020-09-01 18:54:10 +03:00
def vm_removed ( self , conn , vm ) :
2018-03-18 00:35:04 +03: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 18:54:10 +03:00
if self . model [ rowiter ] [ ROW_HANDLE ] == vm :
2018-03-18 00:35:04 +03:00
self . model . remove ( rowiter )
2009-11-29 04:49:44 +03:00
break
2009-10-21 18:36:58 +04:00
def _build_conn_hint ( self , conn ) :
hint = conn . get_uri ( )
2014-09-12 02:16:21 +04:00
if conn . is_disconnected ( ) :
2020-07-14 10:41:51 +03:00
hint = _ ( " %(uri)s (Double click to connect) " ) % { " uri " : conn . get_uri ( ) }
2009-10-21 18:36:58 +04:00
return hint
2013-09-02 02:36:58 +04:00
def _build_conn_markup ( self , conn , name ) :
2019-06-08 01:21:24 +03:00
name = xmlutil . xml_escape ( name )
2011-08-29 20:11:43 +04:00
text = name
2014-09-12 02:16:21 +04:00
if conn . is_disconnected ( ) :
2020-07-14 10:41:51 +03:00
text = _ ( " %(connection)s - Not Connected " ) % { " connection " : name }
2014-09-12 02:16:21 +04:00
elif conn . is_connecting ( ) :
2020-07-14 10:41:51 +03:00
text = _ ( " %(connection)s - Connecting... " ) % { " connection " : name }
2010-12-01 23:22:38 +03:00
markup = " <span size= ' smaller ' > %s </span> " % text
2009-09-17 20:35:41 +04:00
return markup
2009-11-10 23:42:07 +03:00
def _build_conn_color ( self , conn ) :
2019-10-02 17:32:04 +03:00
color = None
2014-09-12 02:16:21 +04:00
if conn . is_disconnected ( ) :
2020-02-02 01:16:45 +03:00
color = self . config . color_insensitive
2009-11-10 23:42:07 +03:00
return color
2013-09-02 02:36:58 +04:00
def _build_vm_markup ( self , name , status ) :
2010-12-01 23:22:38 +03:00
domtext = ( " <span size= ' smaller ' weight= ' bold ' > %s </span> " %
2019-06-08 01:21:24 +03:00
xmlutil . xml_escape ( name ) )
2013-09-02 02:36:58 +04:00
statetext = " <span size= ' smaller ' > %s </span> " % status
2010-12-01 23:22:38 +03:00
return domtext + " \n " + statetext
2009-09-17 20:35:41 +04:00
2013-09-02 02:36:58 +04:00
def _build_row ( self , conn , vm ) :
if conn :
2015-04-11 19:57:32 +03:00
name = conn . get_pretty_desc ( )
2013-09-02 02: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 19:50:19 +04:00
name = vm . get_name_or_title ( )
2013-09-02 02: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 19:05:55 +04:00
2013-09-02 02: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-08 01:21:24 +03:00
row . insert ( ROW_HINT , xmlutil . xml_escape ( hint ) )
2013-09-02 02:36:58 +04:00
row . insert ( ROW_IS_CONN , bool ( conn ) )
row . insert ( ROW_IS_CONN_CONNECTED ,
2014-09-12 02:16:21 +04:00
bool ( conn ) and not conn . is_disconnected ( ) )
2013-09-02 02: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 20:35:41 +04:00
2011-03-23 23:56:12 +03:00
return row
2018-03-14 20:13:22 +03:00
def _conn_added ( self , _src , conn ) :
2010-03-03 04:35:54 +03:00
# Make sure error page isn't showing
2011-07-14 21:13:13 +04:00
self . widget ( " vm-notebook " ) . set_current_page ( 0 )
2018-03-18 00:35:04 +03:00
if self . get_row ( conn ) :
2020-08-20 20:34:01 +03:00
return # pragma: no cover
2009-11-29 04:49:44 +03:00
2018-03-18 00:35:04 +03:00
conn_row = self . _build_row ( conn , None )
self . model . append ( None , conn_row )
2016-05-20 02:23:46 +03:00
2009-11-29 04:49:44 +03:00
conn . connect ( " vm-added " , self . vm_added )
conn . connect ( " vm-removed " , self . vm_removed )
2013-09-02 17:09:31 +04:00
conn . connect ( " resources-sampled " , self . conn_row_updated )
2009-11-29 04:49:44 +03:00
conn . connect ( " state-changed " , self . conn_state_changed )
2018-03-13 19:34:26 +03:00
for vm in conn . list_vms ( ) :
2020-09-01 18:54:10 +03:00
self . vm_added ( conn , vm )
2018-03-13 19:34:26 +03:00
2020-08-26 14:25:37 +03: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 20:13:22 +03:00
def _conn_removed ( self , _src , uri ) :
2018-03-18 00:35:04 +03: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 14:25:37 +03:00
if conn_row is None : # pragma: no cover
2011-04-12 19:50:10 +04:00
return
2020-08-26 14:25:37 +03:00
self . _remove_child_rows ( conn_row )
2018-03-18 00:35:04 +03:00
self . model . remove ( conn_row . iter )
2009-11-29 04:49:44 +03:00
#############################
# State/UI updating methods #
#############################
2006-06-14 18:59:40 +04:00
2013-09-02 17:09:31 +04:00
def vm_row_updated ( self , vm ) :
2018-03-18 00:35:04 +03:00
row = self . get_row ( vm )
2020-08-26 14:25:37 +03:00
if row is None : # pragma: no cover
2013-09-02 17:09:31 +04:00
return
2018-03-18 00:35:04 +03:00
self . model . row_changed ( row . path , row . iter )
2006-06-15 02:42:04 +04:00
2015-04-10 01:02:42 +03:00
def vm_changed ( self , vm ) :
2018-03-18 00:35:04 +03:00
row = self . get_row ( vm )
2013-09-02 02:36:58 +04:00
if row is None :
2020-08-26 14:25:37 +03:00
return # pragma: no cover
2006-11-13 23:38:10 +03:00
2013-08-16 17:59:33 +04:00
try :
2015-04-10 01:02:42 +03:00
if vm == self . current_vm ( ) :
self . update_current_selection ( )
2013-10-04 19:50:19 +04:00
name = vm . get_name_or_title ( )
2013-09-02 02:36:58 +04:00
status = vm . run_status ( )
row [ ROW_SORT_KEY ] = name
2013-08-16 17:59:33 +04:00
row [ ROW_STATUS_ICON ] = vm . run_status_icon_name ( )
row [ ROW_IS_VM_RUNNING ] = vm . is_active ( )
2013-09-02 02:36:58 +04:00
row [ ROW_MARKUP ] = self . _build_vm_markup ( name , status )
2013-08-16 17:59:33 +04:00
2013-09-02 17:09:31 +04:00
desc = vm . get_description ( )
2019-06-08 01:21:24 +03:00
row [ ROW_HINT ] = xmlutil . xml_escape ( desc )
2020-08-26 14:25:37 +03:00
except Exception as e : # pragma: no cover
2019-06-07 23:39:33 +03:00
if vm . conn . support . is_libvirt_error_no_domain ( e ) :
2013-08-16 17:59:33 +04:00
return
raise
2011-07-15 23:38:59 +04:00
2013-09-02 17:09:31 +04:00
self . vm_row_updated ( vm )
2011-07-18 22:53:56 +04:00
def vm_inspection_changed ( self , vm ) :
2018-03-18 00:35:04 +03:00
row = self . get_row ( vm )
2013-09-02 02:36:58 +04:00
if row is None :
2020-08-26 14:25:37 +03:00
return # pragma: no cover
2011-07-18 22:53:56 +04:00
2013-09-02 02: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 21:45:53 +04:00
row [ ROW_INSPECTION_OS_ICON ] = new_icon
2013-06-14 00:10:28 +04:00
2013-09-02 17:09:31 +04:00
self . vm_row_updated ( vm )
2008-01-03 01:55:26 +03:00
2014-06-26 13:51:38 +04:00
def set_initial_selection ( self , uri ) :
2018-03-18 00:35:04 +03: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 14:25:37 +03:00
continue # pragma: no cover
2018-03-18 00:35:04 +03:00
conn = row [ ROW_HANDLE ]
if conn . get_uri ( ) == uri :
sel . select_iter ( row . iter )
2014-06-26 13:51:38 +04:00
return
2015-04-11 20:39:25 +03:00
def conn_state_changed ( self , conn ) :
2018-03-18 00:35:04 +03:00
row = self . get_row ( conn )
2015-04-11 20:39:25 +03:00
row [ ROW_SORT_KEY ] = conn . get_pretty_desc ( )
2013-09-02 02:36:58 +04:00
row [ ROW_MARKUP ] = self . _build_conn_markup ( conn , row [ ROW_SORT_KEY ] )
2014-09-12 02:16:21 +04:00
row [ ROW_IS_CONN_CONNECTED ] = not conn . is_disconnected ( )
2009-11-29 04:49:44 +03:00
row [ ROW_COLOR ] = self . _build_conn_color ( conn )
2011-07-15 23:38:59 +04:00
row [ ROW_HINT ] = self . _build_conn_hint ( conn )
2006-08-09 01:02:15 +04:00
2014-09-12 02:16:21 +04:00
if not conn . is_active ( ) :
2020-08-26 14:25:37 +03:00
self . _remove_child_rows ( row )
2011-07-25 23:09:42 +04:00
2013-09-02 17:09:31 +04:00
self . conn_row_updated ( conn )
self . update_current_selection ( )
def conn_row_updated ( self , conn ) :
2018-03-18 00:35:04 +03:00
row = self . get_row ( conn )
2013-09-02 17:09:31 +04:00
2011-07-25 23: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-18 00:35:04 +03:00
self . model . row_changed ( row . path , row . iter )
2006-06-14 18:59:40 +04:00
2010-05-12 20: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 23:13:41 +04:00
self . vmmenu . change_run_text ( text )
2011-07-14 21:13:13 +04:00
self . widget ( " vm-run " ) . set_label ( strip_text )
2006-06-14 18:59:40 +04:00
2013-09-02 17:09:31 +04:00
def update_current_selection ( self , ignore = None ) :
2007-08-10 00:19:41 +04:00
vm = self . current_vm ( )
2018-03-17 23:56:13 +03:00
conn = self . current_conn ( )
2009-07-27 00:15:05 +04:00
show_open = bool ( vm )
show_details = bool ( vm )
2018-03-17 23:56:13 +03:00
host_details = bool ( vm or conn )
can_delete = bool ( vm or conn )
2010-08-22 20:50:31 +04:00
2009-07-27 00: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-10 00:19:41 +04:00
else :
2009-07-27 00:15:05 +04:00
show_pause = bool ( vm and vm . is_pauseable ( ) )
show_shutdown = bool ( vm and vm . is_stoppable ( ) )
2010-05-12 20:57:32 +04:00
if vm and vm . managedsave_supported :
2014-09-12 02:01:41 +04:00
self . change_run_text ( vm . has_managed_save ( ) )
2010-05-12 20:57:32 +04:00
2011-07-14 21: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 21:24:59 +04:00
self . widget ( " vm-shutdown " ) . get_menu ( ) . update_widget_states ( vm )
2009-07-27 00:15:05 +04:00
self . set_pause_state ( is_paused )
2011-07-14 21:13:13 +04:00
self . widget ( " vm-pause " ) . set_sensitive ( show_pause )
2009-07-27 00:15:05 +04:00
2015-11-12 15:13:19 +03: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 23:56:13 +03:00
self . widget ( " menu_edit_delete " ) . set_sensitive ( can_delete )
2011-07-14 21:13:13 +04:00
self . widget ( " menu_edit_details " ) . set_sensitive ( show_details )
self . widget ( " menu_host_details " ) . set_sensitive ( host_details )
2009-07-27 00:15:05 +04:00
2010-12-09 19:22:35 +03:00
def popup_vm_menu_key ( self , widget_ignore , event ) :
2012-05-14 17:24:56 +04:00
if Gdk . keyval_name ( event . keyval ) != " Menu " :
2020-09-20 17:07:15 +03:00
return False # pragma: no cover
2009-11-11 17:49:34 +03:00
2014-01-27 05:21:12 +04:00
model , treeiter = self . widget ( " vm-list " ) . get_selection ( ) . get_selected ( )
self . popup_vm_menu ( model , treeiter , event )
2009-11-11 17:49:34 +03:00
return True
2007-08-14 01:13:39 +04:00
2018-03-18 00:35:04 +03:00
def popup_vm_menu_button ( self , vmlist , event ) :
2009-11-11 00:01:56 +03:00
if event . button != 3 :
return False
2018-03-18 00:35:04 +03:00
tup = vmlist . get_path_at_pos ( int ( event . x ) , int ( event . y ) )
2012-11-08 17:15:02 +04:00
if tup is None :
2020-08-26 14:25:37 +03:00
return False # pragma: no cover
2008-11-18 23:42:51 +03:00
path = tup [ 0 ]
2009-11-11 00:01:56 +03:00
2018-03-18 00:35:04 +03:00
self . popup_vm_menu ( self . model , self . model . get_iter ( path ) , event )
2009-12-09 19:28:38 +03:00
return False
2009-11-11 17:49:34 +03:00
def popup_vm_menu ( self , model , _iter , event ) :
2012-11-08 17:15:02 +04:00
if model . iter_parent ( _iter ) is not None :
2009-11-11 00:01:56 +03:00
# Popup the vm menu
2014-01-27 05:21:12 +04:00
vm = model [ _iter ] [ ROW_HANDLE ]
2013-09-22 23:13:41 +04:00
self . vmmenu . update_widget_states ( vm )
2019-04-02 23:18:57 +03:00
self . vmmenu . popup_at_pointer ( event )
2007-08-24 01:46:30 +04:00
else :
2009-11-11 00:01:56 +03:00
# Pop up connection menu
2014-01-27 05:21:12 +04:00
conn = model [ _iter ] [ ROW_HANDLE ]
2014-09-12 02:16:21 +04:00
disconn = conn . is_disconnected ( )
conning = conn . is_connecting ( )
2009-11-11 00:01:56 +03: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-17 00:35:34 +03:00
self . connmenu_items [ " delete " ] . set_sensitive ( disconn )
2009-11-11 00:01:56 +03:00
2019-04-02 23:18:57 +03:00
self . connmenu . popup_at_pointer ( event )
2009-11-11 00:01:56 +03:00
2009-11-11 19:02:57 +03:00
2009-11-29 04:49:44 +03:00
#################
# Stats methods #
#################
2006-06-14 18:59:40 +04:00
2012-05-14 17:24:56 +04:00
def vmlist_name_sorter ( self , model , iter1 , iter2 , ignore ) :
2015-03-27 02:13:29 +03:00
key1 = str ( model [ iter1 ] [ ROW_SORT_KEY ] ) . lower ( )
key2 = str ( model [ iter2 ] [ ROW_SORT_KEY ] ) . lower ( )
2017-10-22 02:18:02 +03:00
return _cmp ( key1 , key2 )
2006-06-14 18:59:40 +04:00
2012-05-14 17:24:56 +04:00
def vmlist_guest_cpu_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-27 05:21:12 +04:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2011-07-12 16:49:47 +04:00
2017-10-22 02:18:02 +03:00
return _cmp ( obj1 . guest_cpu_time_percentage ( ) ,
2011-07-12 16:49:47 +04:00
obj2 . guest_cpu_time_percentage ( ) )
2012-05-14 17:24:56 +04:00
def vmlist_host_cpu_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-27 05:21:12 +04:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2011-07-12 05:22:50 +04:00
2017-10-22 02:18:02 +03:00
return _cmp ( obj1 . host_cpu_time_percentage ( ) ,
2011-07-12 05:22:50 +04:00
obj2 . host_cpu_time_percentage ( ) )
2006-06-14 18:59:40 +04:00
2013-12-18 17:42:42 +04:00
def vmlist_memory_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-27 05:21:12 +04:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2013-12-18 17:42:42 +04:00
2017-10-22 02:18:02 +03:00
return _cmp ( obj1 . stats_memory ( ) ,
2013-12-18 17:42:42 +04:00
obj2 . stats_memory ( ) )
2012-05-14 17:24:56 +04:00
def vmlist_disk_io_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-27 05:21:12 +04:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2011-07-12 05:22:50 +04:00
2017-10-22 02:18:02 +03:00
return _cmp ( obj1 . disk_io_rate ( ) , obj2 . disk_io_rate ( ) )
2006-06-14 18:59:40 +04:00
2012-05-14 17:24:56 +04:00
def vmlist_network_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2014-01-27 05:21:12 +04:00
obj1 = model [ iter1 ] [ ROW_HANDLE ]
obj2 = model [ iter2 ] [ ROW_HANDLE ]
2011-07-12 05:22:50 +04:00
2017-10-22 02:18:02 +03:00
return _cmp ( obj1 . network_traffic_rate ( ) , obj2 . network_traffic_rate ( ) )
2006-06-14 18:59:40 +04:00
2020-08-26 14:25:37 +03:00
def _config_polling_change_cb ( self , column ) :
2016-04-18 23:42:12 +03:00
# pylint: disable=redefined-variable-type
2014-02-12 00:29:30 +04: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-18 01:39:25 +04:00
if column == COL_DISK :
2009-07-27 00:15:28 +04:00
widgn = " menu_view_stats_disk "
2013-04-18 01:39:25 +04:00
do_enable = self . config . get_stats_enable_disk_poll ( )
elif column == COL_NETWORK :
2009-07-27 00:15:28 +04:00
widgn = " menu_view_stats_network "
2013-04-18 01:39:25 +04:00
do_enable = self . config . get_stats_enable_net_poll ( )
2014-01-13 02:39:21 +04:00
elif column == COL_MEM :
widgn = " menu_view_stats_memory "
do_enable = self . config . get_stats_enable_memory_poll ( )
2008-12-17 23:27:06 +03:00
2019-06-08 01:21:24 +03:00
for w in xmlutil . listify ( widgn ) :
2014-02-12 00:29:30 +04:00
widget = self . widget ( w )
tool_text = " "
2010-12-14 00:24:49 +03:00
2014-02-12 00:29:30 +04:00
if do_enable :
widget . set_sensitive ( True )
else :
2020-08-26 14:25:37 +03:00
widget . set_active ( False )
2014-02-12 00:29:30 +04:00
widget . set_sensitive ( False )
tool_text = _ ( " Disabled in preferences dialog. " )
widget . set_tooltip_text ( tool_text )
2011-02-15 19:38:35 +03:00
2013-09-02 05: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-27 00:15:28 +04:00
2013-09-02 05: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 16:49:47 +04:00
2013-12-18 17:42:42 +04:00
any_visible = any ( [ c . get_visible ( ) for c in
[ self . netcol , self . diskcol , self . memcol ,
self . guestcpucol , self . hostcpucol ] ] )
2013-09-02 18:43:53 +04:00
self . spacer_txt . set_property ( " visible " , not any_visible )
2013-09-02 05: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 17:42:42 +04: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-18 01:39:25 +04:00
def toggle_guest_cpu_usage_visible_widget ( self ) :
2013-09-02 05: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-18 01:39:25 +04:00
def toggle_host_cpu_usage_visible_widget ( self ) :
2013-09-02 05: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 19:02:57 +03:00
def toggle_stats_visible ( self , src , stats_id ) :
visible = src . get_active ( )
set_stats = {
2011-07-12 16: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 17:42:42 +04:00
COL_MEM : self . config . set_vmlist_memory_usage_visible ,
2011-07-12 16: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 19:02:57 +03:00
}
set_stats [ stats_id ] ( visible )
2006-06-14 18:59:40 +04:00
2012-05-14 17:24:56 +04: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 17:42:42 +04:00
def toggle_stats_visible_memory_usage ( self , src ) :
self . toggle_stats_visible ( src , COL_MEM )
2012-05-14 17:24:56 +04: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 16:49:47 +04:00
def guest_cpu_usage_img ( self , column_ignore , cell , model , _iter , data ) :
2013-09-02 05:35:23 +04:00
obj = model [ _iter ] [ ROW_HANDLE ]
2012-05-14 17:24:56 +04:00
if obj is None or not hasattr ( obj , " conn " ) :
2011-07-12 16:49:47 +04:00
return
2015-05-04 23:33:56 +03:00
data = obj . guest_cpu_time_vector ( GRAPH_LEN )
2011-07-12 16:49:47 +04:00
cell . set_property ( ' data_array ' , data )
def host_cpu_usage_img ( self , column_ignore , cell , model , _iter , data ) :
2013-09-02 05:35:23 +04:00
obj = model [ _iter ] [ ROW_HANDLE ]
2012-05-14 17:24:56 +04:00
if obj is None or not hasattr ( obj , " conn " ) :
2007-08-15 00:28:36 +04:00
return
2011-07-12 05:22:50 +04:00
2015-05-04 23:33:56 +03:00
data = obj . host_cpu_time_vector ( GRAPH_LEN )
2008-10-18 23:28:57 +04:00
cell . set_property ( ' data_array ' , data )
2013-12-18 17:42:42 +04: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 23:33:56 +03:00
data = obj . stats_memory_vector ( GRAPH_LEN )
2013-12-18 17:42:42 +04:00
cell . set_property ( ' data_array ' , data )
2010-12-09 19:22:35 +03:00
def disk_io_img ( self , column_ignore , cell , model , _iter , data ) :
2013-09-02 05:35:23 +04:00
obj = model [ _iter ] [ ROW_HANDLE ]
2012-05-14 17:24:56 +04:00
if obj is None or not hasattr ( obj , " conn " ) :
2011-07-25 23:09:42 +04:00
return
2015-05-04 23:33:56 +03:00
d1 , d2 = obj . disk_io_vectors ( GRAPH_LEN , self . max_disk_rate )
2018-02-09 22:02:04 +03:00
data = [ ( x + y ) / 2 for x , y in zip ( d1 , d2 ) ]
2008-10-18 23:28:57 +04:00
cell . set_property ( ' data_array ' , data )
2010-12-09 19:22:35 +03:00
def network_traffic_img ( self , column_ignore , cell , model , _iter , data ) :
2013-09-02 05:35:23 +04:00
obj = model [ _iter ] [ ROW_HANDLE ]
2012-05-14 17:24:56 +04:00
if obj is None or not hasattr ( obj , " conn " ) :
2011-07-25 23:09:42 +04:00
return
2015-05-04 23:33:56 +03:00
d1 , d2 = obj . network_traffic_vectors ( GRAPH_LEN , self . max_net_rate )
2018-02-09 22:02:04 +03:00
data = [ ( x + y ) / 2 for x , y in zip ( d1 , d2 ) ]
2006-06-27 01:17:45 +04:00
cell . set_property ( ' data_array ' , data )