2006-06-28 23:50:17 +04:00
#
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>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
2007-11-20 19:12:20 +03:00
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
2006-06-28 23:50:17 +04:00
#
2006-06-14 18:59:40 +04:00
2012-02-01 03:16:54 +04:00
import logging
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
2013-08-09 17:23:01 +04:00
from virtinst import util
2014-01-29 03:04:46 +04:00
from virtManager import vmmenu
2014-01-27 03:15:50 +04:00
from virtManager import uiutil
2010-12-09 01:26:19 +03:00
from virtManager . baseclass import vmmGObjectUI
2009-07-22 18:21:33 +04:00
from virtManager . graphwidgets import CellRendererSparkline
2006-07-20 19:16:07 +04:00
2013-08-16 17:59:33 +04:00
import libvirt
2013-02-16 22:54:45 +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
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 ( )
except :
logging . exception ( " Error loading inspection icon data " )
vm . inspection . icon = None
return None
2010-12-09 01:26:19 +03:00
class vmmManager ( vmmGObjectUI ) :
2012-05-14 17:24:56 +04:00
__gsignals__ = {
" action-show-connect " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
2013-09-22 23:13:41 +04:00
" action-show-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
2012-05-14 17:24:56 +04:00
" action-show-about " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
" action-show-host " : ( GObject . SignalFlags . RUN_FIRST , None , [ str ] ) ,
" action-show-preferences " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
" action-show-create " : ( GObject . SignalFlags . RUN_FIRST , None , [ str ] ) ,
" action-suspend-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" action-resume-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" action-run-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" action-shutdown-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" action-reset-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" action-reboot-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" action-destroy-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" action-save-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" action-migrate-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
2013-06-18 00:29:51 +04:00
" action-delete-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
2012-05-14 17:24:56 +04:00
" action-clone-domain " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" action-exit-app " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
" manager-closed " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
" manager-opened " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
" remove-conn " : ( GObject . SignalFlags . RUN_FIRST , None , [ str ] ) ,
" add-default-conn " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
}
2011-07-22 21:42:20 +04:00
def __init__ ( self ) :
2013-09-23 00:10:16 +04:00
vmmGObjectUI . __init__ ( self , " manager.ui " , " vmm-manager " )
2010-11-30 22:33:21 +03:00
2009-07-27 00:15:05 +04:00
self . ignore_pause = False
2009-03-09 23:17:09 +03:00
2014-06-03 01:17:47 +04:00
# Mapping of rowkey -> tree model rows to
2009-11-29 04:49:44 +03:00
# allow O(1) access instead of O(n)
self . rows = { }
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
2009-11-29 05:00:46 +03:00
2014-01-29 03:04:46 +04:00
self . vmmenu = vmmenu . VMActionMenu ( self , self . current_vm )
2012-05-14 17:24:56 +04:00
self . connmenu = Gtk . 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 " :
2012-05-14 17:24:56 +04:00
self . toggle_stats_visible_guest_cpu ,
2011-07-12 16:49:47 +04:00
" on_menu_view_host_cpu_usage_activate " :
2012-05-14 17:24:56 +04:00
self . toggle_stats_visible_host_cpu ,
2013-12-18 17:42:42 +04:00
" on_menu_view_memory_usage_activate " :
self . toggle_stats_visible_memory_usage ,
2011-07-12 16:49:47 +04:00
" on_menu_view_disk_io_activate " :
2012-05-14 17:24:56 +04:00
self . toggle_stats_visible_disk ,
2011-07-12 16:49:47 +04:00
" on_menu_view_network_traffic_activate " :
2012-05-14 17:24:56 +04: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 ,
2011-07-23 00:43:26 +04:00
" on_menu_file_add_connection_activate " : self . new_conn ,
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 ,
2011-06-09 00:33:20 +04:00
" on_vm_list_row_activated " : self . show_vm ,
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)
2014-02-12 00:29:30 +04:00
self . enable_polling ( COL_GUEST_CPU )
2013-04-18 01:39:25 +04:00
self . enable_polling ( COL_DISK )
self . enable_polling ( COL_NETWORK )
2014-01-13 02:39:21 +04:00
self . enable_polling ( COL_MEM )
2009-11-29 04:49:44 +03:00
2010-03-04 00:58:50 +03:00
# Queue up the default connection detector
2011-07-23 00:43:26 +04:00
self . idle_emit ( " add-default-conn " )
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
2013-06-13 17:18:46 +04:00
logging . 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
self . emit ( " manager-opened " )
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
2013-06-13 17:18:46 +04:00
logging . 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 ( )
2011-04-13 18:47:31 +04:00
self . emit ( " manager-closed " )
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 . rows = None
2011-04-13 17:27:02 +04:00
2011-07-24 05:16:54 +04:00
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
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
2009-11-29 04:49:44 +03:00
def is_visible ( self ) :
2012-05-14 17:24:56 +04:00
return bool ( self . topwin . get_visible ( ) )
2009-11-29 04:49:44 +03:00
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
2009-11-29 04:49:44 +03:00
################
# Init methods #
################
def init_stats ( self ) :
2011-04-13 17:27:02 +04:00
self . add_gconf_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 ) )
self . add_gconf_handle (
self . config . on_vmlist_host_cpu_usage_visible_changed (
self . toggle_host_cpu_usage_visible_widget ) )
2013-12-18 17:42:42 +04:00
self . add_gconf_handle (
self . config . on_vmlist_memory_usage_visible_changed (
self . toggle_memory_usage_visible_widget ) )
2011-04-13 17:27:02 +04:00
self . add_gconf_handle (
self . config . on_vmlist_disk_io_visible_changed (
2011-07-12 16:49:47 +04:00
self . toggle_disk_io_visible_widget ) )
2011-04-13 17:27:02 +04:00
self . add_gconf_handle (
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
2011-04-13 17:27:02 +04:00
self . add_gconf_handle (
2014-02-12 00:29:30 +04:00
self . config . on_stats_enable_cpu_poll_changed (
self . enable_polling , COL_GUEST_CPU ) )
2011-04-13 17:27:02 +04:00
self . add_gconf_handle (
2014-02-12 00:29:30 +04:00
self . config . on_stats_enable_disk_poll_changed (
self . enable_polling , COL_DISK ) )
self . add_gconf_handle (
self . config . on_stats_enable_net_poll_changed (
self . enable_polling , COL_NETWORK ) )
2014-01-13 02:39:21 +04:00
self . add_gconf_handle (
self . config . on_stats_enable_memory_poll_changed (
2014-02-12 00:29:30 +04:00
self . enable_polling , 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
2014-01-29 03:04:46 +04:00
menu = vmmenu . VMShutdownMenu ( self , self . current_vm )
2013-09-22 21:24:59 +04:00
self . widget ( " vm-shutdown " ) . set_icon_name ( " system-shutdown " )
self . widget ( " vm-shutdown " ) . set_menu ( menu )
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 ) :
2013-09-22 23:13:41 +04:00
def add_to_menu ( idx , text , icon , cb ) :
2012-05-14 17:24:56 +04:00
if text [ 0 : 3 ] == ' gtk ' :
item = Gtk . ImageMenuItem . new_from_stock ( text , None )
else :
item = Gtk . ImageMenuItem . new_with_mnemonic ( text )
2010-05-12 23:31:36 +04:00
if icon :
item . set_image ( icon )
if cb :
item . connect ( " activate " , cb )
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
2013-09-22 23:13:41 +04:00
add_to_menu ( " create " , Gtk . STOCK_NEW , None , self . new_vm )
add_to_menu ( " connect " , Gtk . STOCK_CONNECT , None , self . open_conn )
add_to_menu ( " disconnect " , Gtk . STOCK_DISCONNECT , None ,
2011-07-23 00:43:26 +04:00
self . close_conn )
2013-09-22 23:13:41 +04:00
self . connmenu . add ( Gtk . SeparatorMenuItem ( ) )
add_to_menu ( " delete " , Gtk . STOCK_DELETE , None , self . do_delete )
self . connmenu . add ( Gtk . SeparatorMenuItem ( ) )
add_to_menu ( " details " , _ ( " D_etails " ) , None , self . show_host )
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
##################
# Helper methods #
##################
def current_row ( self ) :
2014-04-03 18:53:54 +04:00
return uiutil . get_list_selection ( self . widget ( " vm-list " ) , None )
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 ]
2011-07-23 00:43:26 +04:00
def current_conn ( self ) :
2009-11-29 04:49:44 +03:00
row = self . current_row ( )
if not row :
return None
handle = row [ ROW_HANDLE ]
if row [ ROW_IS_CONN ] :
return handle
else :
2011-07-23 00:43:26 +04:00
return handle . conn
2009-11-29 04:49:44 +03:00
2011-07-23 00:43:26 +04:00
def current_conn_uri ( self , default_selection = False ) :
2011-07-14 21:13:13 +04:00
vmlist = self . widget ( " vm-list " )
2010-08-22 20:50:31 +04:00
model = vmlist . get_model ( )
2011-07-23 00:43:26 +04:00
conn = self . current_conn ( )
2010-08-22 20:50:31 +04:00
if conn is None and default_selection :
# Nothing selected, use first connection row
for row in model :
if row [ ROW_IS_CONN ] :
conn = row [ ROW_HANDLE ]
break
if conn :
return conn . get_uri ( )
return None
2009-11-29 04:49:44 +03:00
####################
# Action listeners #
####################
2006-11-03 18:02:02 +03:00
2009-11-29 05:00:46 +03:00
def window_resized ( self , ignore , event ) :
# Sometimes dimensions change when window isn't visible
if not self . is_visible ( ) :
return
self . config . set_manager_window_size ( event . width , event . height )
2010-12-09 19:22:35 +03:00
def exit_app ( self , src_ignore = None , src2_ignore = None ) :
2008-06-13 22:40:26 +04:00
self . emit ( " action-exit-app " )
2006-06-14 18:59:40 +04:00
2011-07-23 00:43:26 +04:00
def new_conn ( self , src_ignore = None ) :
2006-06-27 22:16:13 +04:00
self . emit ( " action-show-connect " )
2006-06-14 18:59:40 +04:00
2010-12-09 19:22:35 +03:00
def new_vm ( self , src_ignore = None ) :
2011-07-23 00:43:26 +04:00
self . emit ( " action-show-create " , self . current_conn_uri ( ) )
2009-11-29 04:49:44 +03:00
2010-12-09 19:22:35 +03:00
def show_about ( self , src_ignore ) :
2009-11-29 04:49:44 +03:00
self . emit ( " action-show-about " )
2010-12-09 19:22:35 +03:00
def show_preferences ( self , src_ignore ) :
2009-11-29 04:49:44 +03:00
self . emit ( " action-show-preferences " )
2010-12-09 19:22:35 +03:00
def show_host ( self , src_ignore ) :
2011-07-23 00:43:26 +04:00
uri = self . current_conn_uri ( default_selection = True )
2010-08-22 20:50:31 +04:00
self . emit ( " action-show-host " , uri )
2009-11-29 04:49:44 +03:00
2011-06-09 00:33:20 +04:00
def show_vm ( self , ignore , ignore2 = None , ignore3 = None ) :
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 :
return
if vm :
2014-06-03 01:17:47 +04:00
self . emit ( " action-show-domain " , conn . get_uri ( ) , vm . get_connkey ( ) )
2011-06-09 00:33:20 +04:00
else :
2011-07-23 00:43:26 +04:00
if not self . open_conn ( ) :
2011-06-09 00:33:20 +04:00
self . emit ( " action-show-host " , conn . get_uri ( ) )
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 :
2014-06-03 01:17:47 +04:00
self . emit ( " action-delete-domain " , conn . get_uri ( ) , vm . get_connkey ( ) )
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
if conn is None :
return
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
2011-07-23 00:43:26 +04:00
self . emit ( " 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 :
self . ignore_pause = True
src . set_active ( state )
finally :
self . ignore_pause = False
def pause_vm_button ( self , src ) :
if self . ignore_pause :
return
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 :
self . pause_vm ( None )
else :
self . resume_vm ( None )
def start_vm ( self , ignore ) :
vm = self . current_vm ( )
2014-06-03 01:17:47 +04:00
if vm is None :
return
self . emit ( " action-run-domain " , vm . conn . get_uri ( ) , vm . get_connkey ( ) )
2009-11-29 04:49:44 +03:00
def poweroff_vm ( self , ignore ) :
vm = self . current_vm ( )
2014-06-03 01:17:47 +04:00
if vm is None :
return
self . emit ( " action-shutdown-domain " ,
vm . conn . get_uri ( ) , vm . get_connkey ( ) )
2009-11-29 04:49:44 +03:00
def pause_vm ( self , ignore ) :
vm = self . current_vm ( )
2014-06-03 01:17:47 +04:00
if vm is None :
return
self . emit ( " action-suspend-domain " , vm . conn . get_uri ( ) , vm . get_connkey ( ) )
2009-11-29 04:49:44 +03:00
def resume_vm ( self , ignore ) :
vm = self . current_vm ( )
2014-06-03 01:17:47 +04:00
if vm is None :
return
self . emit ( " action-resume-domain " , vm . conn . get_uri ( ) , vm . get_connkey ( ) )
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 ( ) :
2009-11-29 04:49:44 +03:00
conn . open ( )
return True
####################################
# VM add/remove management methods #
####################################
def vm_row_key ( self , vm ) :
2011-07-23 00:43:26 +04:00
return vm . get_uuid ( ) + " : " + vm . conn . get_uri ( )
2006-07-20 19:16:07 +04:00
2014-06-03 01:17:47 +04:00
def vm_added ( self , conn , connkey ) :
vm = conn . get_vm ( connkey )
2014-02-13 20:16:48 +04:00
if self . vm_row_key ( vm ) in self . rows :
return
2013-09-02 17:09:31 +04:00
vm . connect ( " config-changed " , self . vm_config_changed )
2006-10-11 01:24:59 +04:00
vm . connect ( " status-changed " , self . vm_status_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
2011-07-14 21:13:13 +04:00
vmlist = self . widget ( " vm-list " )
2006-10-11 01:24:59 +04:00
model = vmlist . get_model ( )
2006-06-14 18:59:40 +04:00
2011-07-22 21:54:40 +04:00
self . _append_vm ( model , vm , conn )
2006-06-14 18:59:40 +04:00
2014-06-03 01:17:47 +04:00
def vm_removed ( self , conn , connkey ) :
2011-07-14 21:13:13 +04:00
vmlist = self . widget ( " vm-list " )
2009-11-29 04:49:44 +03:00
model = vmlist . get_model ( )
2011-07-22 21:54:40 +04:00
parent = self . rows [ conn . get_uri ( ) ] . iter
2009-11-29 04:49:44 +03:00
for row in range ( model . iter_n_children ( parent ) ) :
2014-01-27 05:21:12 +04:00
vm = model [ model . iter_nth_child ( parent , row ) ] [ ROW_HANDLE ]
2014-06-03 01:17:47 +04:00
if vm . get_connkey ( ) == connkey :
2009-11-29 04:49:44 +03:00
model . remove ( model . iter_nth_child ( parent , row ) )
del self . rows [ self . vm_row_key ( vm ) ]
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 ( ) :
2009-10-21 18:36:58 +04:00
hint + = " ( %s ) " % _ ( " Double click to connect " )
return hint
2013-09-02 02:36:58 +04:00
def _build_conn_markup ( self , conn , name ) :
name = util . 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 ( ) :
2011-08-29 20:11:43 +04:00
text + = " - " + _ ( " Not Connected " )
2014-09-12 02:16:21 +04:00
elif conn . is_connecting ( ) :
2011-08-29 20:11:43 +04:00
text + = " - " + _ ( " Connecting... " )
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 ) :
2013-04-23 21:04:33 +04:00
color = " #000000 "
2014-09-12 02:16:21 +04:00
if conn . is_disconnected ( ) :
2013-04-23 21:04:33 +04:00
color = " #5b5b5b "
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> " %
2013-09-02 02:36:58 +04:00
util . xml_escape ( name ) )
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 :
2014-07-05 02:20:08 +04:00
name = conn . get_pretty_desc ( shorthost = False )
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 )
row . insert ( ROW_HINT , util . xml_escape ( hint ) )
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
def _append_vm ( self , model , vm , conn ) :
row_key = self . vm_row_key ( vm )
if row_key in self . rows :
return
2013-09-02 02:36:58 +04:00
row = self . _build_row ( None , vm )
2011-03-23 23:56:12 +03:00
parent = self . rows [ conn . get_uri ( ) ] . iter
2008-11-18 23:42:51 +03:00
_iter = model . append ( parent , row )
path = model . get_path ( _iter )
2009-11-18 21:51:36 +03:00
self . rows [ row_key ] = model [ path ]
2011-03-23 23:56:12 +03:00
2007-08-14 20:31:24 +04:00
# Expand a connection when adding a vm to it
2011-07-14 21:13:13 +04:00
self . widget ( " vm-list " ) . expand_row ( model . get_path ( parent ) , False )
2006-06-14 18:59:40 +04:00
2013-04-20 21:43:52 +04:00
def _append_conn ( self , model , conn ) :
2013-09-02 02:36:58 +04:00
row = self . _build_row ( conn , None )
2013-04-20 21:43:52 +04:00
2008-11-18 23:42:51 +03:00
_iter = model . append ( None , row )
path = model . get_path ( _iter )
2007-09-10 06:57:24 +04:00
self . rows [ conn . get_uri ( ) ] = model [ path ]
2009-02-16 01:36:36 +03:00
return _iter
2007-08-10 00:19:41 +04:00
2014-07-05 02:20:08 +04:00
def _ensure_conn_descs_dont_collide ( self ) :
# By default we only show hostname + hypervisor in the conn label.
# So if we have two URIs like qemu+ssh://host and qemu+tcp://host,
# we want to add the transport in the description to differentiate
connrows = [ row for row in self . rows . values ( ) if row [ ROW_IS_CONN ] ]
for row in connrows :
conn = row [ ROW_HANDLE ]
connsplit = util . uri_split ( conn . get_uri ( ) )
scheme = connsplit [ 0 ]
show_transport = False
show_user = False
for checkrow in connrows :
checkconn = checkrow [ ROW_HANDLE ]
if conn is checkconn :
continue
checkconnsplit = util . uri_split ( checkconn . get_uri ( ) )
checkscheme = checkconnsplit [ 0 ]
if ( ( scheme . split ( " + " ) [ 0 ] == checkscheme . split ( " + " ) [ 0 ] ) and
connsplit [ 2 ] == checkconnsplit [ 2 ] and
connsplit [ 3 ] == checkconnsplit [ 3 ] ) :
show_transport = True
if ( " + " in scheme and " + " in checkscheme and
scheme . split ( " + " ) [ 1 ] == checkscheme . split ( " + " ) [ 1 ] ) :
show_user = True
newname = conn . get_pretty_desc (
shorthost = False , show_transport = show_transport ,
show_user = show_user )
if newname != row [ ROW_SORT_KEY ] :
self . conn_state_changed ( conn , newname = newname )
2011-07-23 00:43:26 +04:00
def add_conn ( self , engine_ignore , conn ) :
2014-06-26 17:05:34 +04:00
# Called from engine.py signal conn-added
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 )
2010-03-03 04:35:54 +03:00
2010-12-10 19:47:07 +03:00
if conn . get_uri ( ) in self . rows :
2009-11-29 04:49:44 +03:00
return
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 )
2011-07-14 21:13:13 +04:00
vmlist = self . widget ( " vm-list " )
2014-07-05 02:20:08 +04:00
self . _append_conn ( vmlist . get_model ( ) , conn )
self . _ensure_conn_descs_dont_collide ( )
2010-12-12 07:51:20 +03:00
2011-07-23 00:43:26 +04:00
def remove_conn ( self , engine_ignore , uri ) :
2014-06-26 17:05:34 +04:00
# Called from engine.py signal conn-removed
2011-07-14 21:13:13 +04:00
model = self . widget ( " vm-list " ) . get_model ( )
2011-04-12 19:50:10 +04:00
parent = self . rows [ uri ] . iter
if parent is None :
return
child = model . iter_children ( parent )
while child is not None :
2014-01-27 05:21:12 +04:00
del self . rows [ self . vm_row_key ( model [ child ] [ ROW_HANDLE ] ) ]
2011-04-12 19:50:10 +04:00
model . remove ( child )
2009-11-29 04:49:44 +03:00
child = model . iter_children ( parent )
2011-04-12 19:50:10 +04:00
model . remove ( parent )
del self . rows [ uri ]
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 ) :
row = self . rows . get ( self . vm_row_key ( vm ) , None )
if row is None :
return
self . widget ( " vm-list " ) . get_model ( ) . row_changed ( row . path , row . iter )
2006-06-15 02:42:04 +04:00
2013-09-02 17:09:31 +04:00
def vm_config_changed ( self , vm ) :
2013-09-02 02:36:58 +04:00
row = self . rows . get ( self . vm_row_key ( vm ) , None )
if row is None :
2006-11-13 23:38:10 +03:00
return
2013-08-16 17:59:33 +04:00
try :
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 ( )
2014-01-27 03:15:50 +04:00
if not uiutil . can_set_row_none :
2013-09-02 17:09:31 +04:00
desc = desc or " "
row [ ROW_HINT ] = util . xml_escape ( desc )
2013-08-16 17:59:33 +04:00
except libvirt . libvirtError , e :
2014-01-27 02:42:24 +04:00
if util . exception_is_libvirt_error ( e , " VIR_ERR_NO_DOMAIN " ) :
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 )
def vm_status_changed ( self , vm , oldstatus , newstatus ) :
ignore = newstatus
ignore = oldstatus
parent = self . rows [ vm . conn . get_uri ( ) ] . iter
vmlist = self . widget ( " vm-list " )
model = vmlist . get_model ( )
missing = True
for row in range ( model . iter_n_children ( parent ) ) :
_iter = model . iter_nth_child ( parent , row )
2014-01-27 05:21:12 +04:00
if model [ _iter ] [ ROW_HANDLE ] == vm :
2013-09-02 17:09:31 +04:00
missing = False
break
if missing :
self . _append_vm ( model , vm , vm . conn )
# Update run/shutdown/pause button states
self . update_current_selection ( )
self . vm_config_changed ( vm )
2006-06-14 18:59:40 +04:00
2011-07-18 22:53:56 +04:00
def vm_inspection_changed ( self , vm ) :
2013-09-02 02:36:58 +04:00
row = self . rows . get ( self . vm_row_key ( vm ) , None )
if row is None :
2011-07-18 22:53:56 +04:00
return
2013-09-02 02:36:58 +04:00
new_icon = _get_inspection_icon_pixbuf ( vm , 16 , 16 )
2014-01-27 03:15:50 +04:00
if not uiutil . can_set_row_none :
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
new_icon = new_icon or " "
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 ) :
vmlist = self . widget ( " vm-list " )
model = vmlist . get_model ( )
it = model . get_iter_first ( )
selected = None
while it :
key = model . get_value ( it , ROW_HANDLE )
if key . get_uri ( ) == uri :
vmlist . get_selection ( ) . select_iter ( it )
return
if not selected :
vmlist . get_selection ( ) . select_iter ( it )
selected = key
elif key . get_autoconnect ( ) and not selected . get_autoconnect ( ) :
vmlist . get_selection ( ) . select_iter ( it )
selected = key
if not uri :
return
it = model . iter_next ( it )
2013-09-02 17:09:31 +04:00
def conn_state_changed ( self , conn , newname = None ) :
2007-09-10 06:57:24 +04:00
row = self . rows [ conn . get_uri ( ) ]
2010-12-12 07:51:20 +03:00
if newname :
2013-09-02 02:36:58 +04:00
row [ ROW_SORT_KEY ] = newname
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 ( ) :
2009-11-29 04:49:44 +03:00
# Connection went inactive, delete any VM child nodes
2013-09-02 17:09:31 +04:00
parent = row . iter
2009-11-29 04:49:44 +03:00
if parent is not None :
2013-09-02 17:09:31 +04:00
model = self . widget ( " vm-list " ) . get_model ( )
2009-11-29 04:49:44 +03:00
child = model . iter_children ( parent )
while child is not None :
2013-09-02 17:09:31 +04:00
vm = model [ child ] [ ROW_HANDLE ]
del self . rows [ self . vm_row_key ( vm ) ]
2009-11-29 04:49:44 +03:00
model . remove ( child )
child = model . iter_children ( parent )
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 ) :
row = self . rows [ conn . get_uri ( ) ]
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 ( ) )
2013-09-02 17:09:31 +04:00
self . widget ( " vm-list " ) . get_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 ( )
2009-07-27 00:15:05 +04:00
show_open = bool ( vm )
show_details = bool ( vm )
2010-08-22 20:50:31 +04:00
host_details = bool ( len ( self . rows ) )
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
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 " :
2009-11-11 17:49:34 +03:00
return False
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
2009-11-11 17:49:34 +03:00
def popup_vm_menu_button ( self , widget , event ) :
2009-11-11 00:01:56 +03:00
if event . button != 3 :
return False
2008-11-18 23:42:51 +03:00
tup = widget . get_path_at_pos ( int ( event . x ) , int ( event . y ) )
2012-11-08 17:15:02 +04:00
if tup is None :
2007-08-24 01:46:30 +04:00
return False
2008-11-18 23:42:51 +03:00
path = tup [ 0 ]
2007-08-24 01:46:30 +04:00
model = widget . get_model ( )
2008-11-18 23:42:51 +03:00
_iter = model . get_iter ( path )
2009-11-11 00:01:56 +03:00
2009-11-11 17:49:34 +03:00
self . popup_vm_menu ( model , _iter , 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 )
2014-04-03 02:39:43 +04:00
self . vmmenu . popup ( None , None , None , None , 0 , event . time )
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
2012-05-14 17:24:56 +04:00
self . connmenu . popup ( None , None , None , None , 0 , event . time )
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 ) :
2014-01-27 05:21:12 +04:00
return cmp ( model [ iter1 ] [ ROW_SORT_KEY ] , model [ iter2 ] [ ROW_SORT_KEY ] )
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
return cmp ( obj1 . guest_cpu_time_percentage ( ) ,
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
return cmp ( obj1 . host_cpu_time_percentage ( ) ,
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
return cmp ( obj1 . stats_memory ( ) ,
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
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
return cmp ( obj1 . network_traffic_rate ( ) , obj2 . network_traffic_rate ( ) )
2006-06-14 18:59:40 +04:00
2013-04-18 01:39:25 +04:00
def enable_polling ( self , column ) :
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
2014-02-12 00:29:30 +04:00
for w in util . listify ( widgn ) :
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 :
if widget . get_active ( ) :
widget . set_active ( False )
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
2012-05-14 17:24:56 +04:00
data = obj . guest_cpu_time_vector_limit ( 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
2012-05-14 17:24:56 +04:00
data = obj . host_cpu_time_vector_limit ( 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
data = obj . memory_usage_vector_limit ( GRAPH_LEN )
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
2012-05-14 17:24:56 +04:00
data = obj . disk_io_vector_limit ( GRAPH_LEN , self . max_disk_rate )
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
2012-05-14 17:24:56 +04:00
data = obj . network_traffic_vector_limit ( GRAPH_LEN , self . max_net_rate )
2006-06-27 01:17:45 +04:00
cell . set_property ( ' data_array ' , data )