2006-06-28 15:50:17 -04:00
#
2008-04-08 13:30:47 -05:00
# Copyright (C) 2006-2008 Red Hat, Inc.
2006-06-28 15: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 11:12:20 -05:00
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
2006-06-28 15:50:17 -04:00
#
2006-06-14 10:59:40 -04:00
2012-01-31 18:16:54 -05:00
import logging
2012-01-14 22:19:12 +01:00
import re
2012-01-31 18:16:54 -05:00
2012-05-14 14:24:56 +01:00
from gi . repository import GObject
from gi . repository import Gtk
from gi . repository import Gdk
from gi . repository import GdkPixbuf
2011-04-18 12:39:53 -04:00
2012-07-08 15:38:52 -04:00
from virtManager import packageutils
from virtManager import uihelpers
2007-09-09 22:57:24 -04:00
from virtManager . connection import vmmConnection
2010-12-08 17:26:19 -05:00
from virtManager . baseclass import vmmGObjectUI
2009-03-09 16:17:09 -04:00
from virtManager . delete import vmmDeleteDialog
2009-07-22 10:21:33 -04:00
from virtManager . graphwidgets import CellRendererSparkline
2009-01-26 11:12:43 -05:00
from virtManager import util as util
2006-07-20 11:16:07 -04:00
2013-02-16 13:54:45 -05:00
2012-05-14 14:24:56 +01:00
# Number of data points for performance graphs
GRAPH_LEN = 40
2006-06-14 10:59:40 -04:00
2007-08-28 17:57:25 -04:00
# fields in the tree model data set
2007-08-27 22:22:18 -04:00
ROW_HANDLE = 0
ROW_NAME = 1
2009-07-28 19:21:56 -04:00
ROW_MARKUP = 2
ROW_STATUS = 3
ROW_STATUS_ICON = 4
ROW_KEY = 5
ROW_HINT = 6
ROW_IS_CONN = 7
ROW_IS_CONN_CONNECTED = 8
ROW_IS_VM = 9
ROW_IS_VM_RUNNING = 10
2009-11-10 15:42:07 -05:00
ROW_COLOR = 11
2011-07-18 19:53:56 +01:00
ROW_INSPECTION_OS_ICON = 12
2007-08-27 22:22:18 -04:00
# Columns in the tree view
COL_NAME = 0
2011-07-12 08:49:47 -04:00
COL_GUEST_CPU = 1
COL_HOST_CPU = 2
COL_DISK = 3
COL_NETWORK = 4
2007-08-27 22:22:18 -04:00
2013-02-16 13:54:45 -05:00
try :
import gi
gi . check_version ( " 3.7.4 " )
can_set_row_none = True
2013-03-11 09:21:46 +01:00
except ( ValueError , AttributeError ) :
2013-02-16 13:54:45 -05:00
can_set_row_none = False
2009-07-26 16:15:05 -04:00
rcstring = """
style " toolbar-style " {
#GtkToolbar::button_relief = GTK_RELIEF_NONE
#GtkToolbar::shadow_type = GTK_SHADOW_NONE
GtkToolbar : : internal_padding = 2
}
style " treeview-style " {
GtkTreeView : : indent_expanders = 0
}
class " GtkToolbar " style " toolbar - style "
class " GtkTreeView " style " treeview - style "
"""
2013-01-12 16:13:53 -05:00
# XXX: This isn't working anymore. We can probably drop toolbar padding
# bit anyways, but indent_expanders is important
2012-05-14 14:24:56 +01:00
Gtk . rc_parse_string ( rcstring )
2009-07-26 16:15:05 -04:00
2010-12-08 17:26:19 -05:00
class vmmManager ( vmmGObjectUI ) :
2012-05-14 14:24:56 +01:00
__gsignals__ = {
" action-show-connect " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
" action-show-vm " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
" 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 ] ) ,
" 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 13:42:20 -04:00
def __init__ ( self ) :
2012-02-01 17:26:46 -05:00
vmmGObjectUI . __init__ ( self , " vmm-manager.ui " , " vmm-manager " )
2010-11-30 14:33:21 -05:00
2009-03-09 16:17:09 -04:00
self . delete_dialog = None
2009-07-26 16:15:05 -04:00
self . ignore_pause = False
2009-03-09 16:17:09 -04:00
2009-11-28 20:49:44 -05:00
# Mapping of VM UUID -> tree model rows to
# allow O(1) access instead of O(n)
self . rows = { }
2009-11-28 21:00:46 -05:00
w , h = self . config . get_manager_window_size ( )
2010-02-23 14:18:12 -05:00
self . topwin . set_default_size ( w or 550 , h or 550 )
2010-12-13 17:48:19 -05:00
self . prev_position = None
2009-11-28 21:00:46 -05:00
2012-05-14 14:24:56 +01:00
self . vmmenu = Gtk . Menu ( )
self . vmmenushutdown = Gtk . Menu ( )
2009-11-28 20:49:44 -05:00
self . vmmenu_items = { }
self . vmmenushutdown_items = { }
2012-05-14 14:24:56 +01:00
self . connmenu = Gtk . Menu ( )
2009-11-28 20:49:44 -05:00
self . connmenu_items = { }
2011-04-13 09:27:02 -04:00
# There seem to be ref counting issues with calling
# list.get_column, so avoid it
self . diskcol = None
self . netcol = None
2011-07-12 08:49:47 -04:00
self . guestcpucol = None
self . hostcpucol = None
2009-11-28 20:49:44 -05:00
2013-02-16 13:31:46 -05:00
self . builder . connect_signals ( {
2011-07-12 08:49:47 -04:00
" on_menu_view_guest_cpu_usage_activate " :
2012-05-14 14:24:56 +01:00
self . toggle_stats_visible_guest_cpu ,
2011-07-12 08:49:47 -04:00
" on_menu_view_host_cpu_usage_activate " :
2012-05-14 14:24:56 +01:00
self . toggle_stats_visible_host_cpu ,
2011-07-12 08:49:47 -04:00
" on_menu_view_disk_io_activate " :
2012-05-14 14:24:56 +01:00
self . toggle_stats_visible_disk ,
2011-07-12 08:49:47 -04:00
" on_menu_view_network_traffic_activate " :
2012-05-14 14:24:56 +01:00
self . toggle_stats_visible_network ,
2009-11-28 20:49:44 -05:00
" on_vm_manager_delete_event " : self . close ,
2009-11-28 21:00:46 -05:00
" on_vmm_manager_configure_event " : self . window_resized ,
2011-07-22 16:43:26 -04:00
" on_menu_file_add_connection_activate " : self . new_conn ,
2009-11-28 20:49:44 -05:00
" on_menu_file_quit_activate " : self . exit_app ,
" on_menu_file_close_activate " : self . close ,
" on_vmm_close_clicked " : self . close ,
2011-06-08 16:33:20 -04:00
" on_vm_open_clicked " : self . show_vm ,
2009-11-28 20:49:44 -05:00
" on_vm_run_clicked " : self . start_vm ,
" on_vm_new_clicked " : self . new_vm ,
" on_vm_shutdown_clicked " : self . poweroff_vm ,
" on_vm_pause_clicked " : self . pause_vm_button ,
2011-06-08 16:33:20 -04:00
" on_menu_edit_details_activate " : self . show_vm ,
2009-11-28 20:49:44 -05:00
" on_menu_edit_delete_activate " : self . do_delete ,
" on_menu_host_details_activate " : self . show_host ,
2011-06-08 16:33:20 -04:00
" on_vm_list_row_activated " : self . show_vm ,
2009-11-28 20:49:44 -05:00
" on_vm_list_button_press_event " : self . popup_vm_menu_button ,
" on_vm_list_key_press_event " : self . popup_vm_menu_key ,
" on_menu_edit_preferences_activate " : self . show_preferences ,
" on_menu_help_about_activate " : self . show_about ,
2011-04-13 09:27:02 -04:00
} )
self . init_vmlist ( )
self . init_stats ( )
self . init_toolbar ( )
self . init_context_menus ( )
2009-11-28 20:49:44 -05:00
self . vm_selected ( )
2011-07-14 13:13:13 -04:00
self . widget ( " vm-list " ) . get_selection ( ) . connect ( " changed " ,
self . vm_selected )
2009-11-28 20:49:44 -05:00
2011-07-25 15:09:42 -04:00
self . max_disk_rate = 10.0
self . max_net_rate = 10.0
2009-11-28 20:49:44 -05:00
# Initialize stat polling columns based on global polling
# preferences (we want signal handlers for this)
2011-04-18 13:14:14 -04:00
for typ , init_val in [
2011-07-12 08:49:47 -04:00
( COL_DISK , self . config . get_stats_enable_disk_poll ( ) ) ,
( COL_NETWORK , self . config . get_stats_enable_net_poll ( ) ) ] :
2009-11-28 20:49:44 -05:00
self . enable_polling ( None , None , init_val , typ )
# Select first list entry
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2010-03-03 16:58:50 -05:00
if len ( vmlist . get_model ( ) ) != 0 :
vmlist . get_selection ( ) . select_iter (
vmlist . get_model ( ) . get_iter_first ( ) )
# Queue up the default connection detector
2011-07-22 16:43:26 -04:00
self . idle_emit ( " add-default-conn " )
2009-11-28 20:49:44 -05:00
##################
# Common methods #
##################
def show ( self ) :
2012-01-31 18:16:54 -05:00
logging . debug ( " Showing manager " )
2010-12-08 17:26:19 -05:00
vis = self . is_visible ( )
2010-02-23 14:18:12 -05:00
self . topwin . present ( )
2010-12-08 17:26:19 -05:00
if vis :
return
2010-02-23 14:18:12 -05:00
2010-12-13 17:48:19 -05:00
if self . prev_position :
self . topwin . move ( * self . prev_position )
self . prev_position = None
2011-04-13 10:47:31 -04:00
self . emit ( " manager-opened " )
2009-11-28 20:49:44 -05:00
2010-12-09 11:22:35 -05:00
def close ( self , src_ignore = None , src2_ignore = None ) :
2012-01-31 18:16:54 -05:00
logging . debug ( " Closing manager " )
2010-12-08 17:26:19 -05:00
if not self . is_visible ( ) :
return
2010-12-13 17:48:19 -05:00
self . prev_position = self . topwin . get_position ( )
2010-12-08 17:26:19 -05:00
self . topwin . hide ( )
2011-04-13 10:47:31 -04:00
self . emit ( " manager-closed " )
2010-12-08 17:26:19 -05:00
return 1
2009-11-28 20:49:44 -05:00
2011-04-13 09:27:02 -04:00
2011-07-23 21:16:54 -04:00
def _cleanup ( self ) :
self . rows = None
2011-04-13 09:27:02 -04:00
2011-07-23 21:16:54 -04:00
self . diskcol = None
self . guestcpucol = None
self . hostcpucol = None
self . netcol = None
2011-04-13 09:27:02 -04:00
2011-07-23 21:16:54 -04:00
if self . delete_dialog :
self . delete_dialog . cleanup ( )
self . delete_dialog = None
self . vmmenu . destroy ( )
self . vmmenu = None
self . vmmenu_items = None
self . vmmenushutdown . destroy ( )
self . vmmenushutdown = None
self . vmmenushutdown_items = None
self . connmenu . destroy ( )
self . connmenu = None
self . connmenu_items = None
2011-04-13 09:27:02 -04:00
2009-11-28 20:49:44 -05:00
def is_visible ( self ) :
2012-05-14 14:24:56 +01:00
return bool ( self . topwin . get_visible ( ) )
2009-11-28 20:49:44 -05:00
2010-03-02 20:35:54 -05:00
def set_startup_error ( self , msg ) :
2011-07-14 13:13:13 -04:00
self . widget ( " vm-notebook " ) . set_current_page ( 1 )
self . widget ( " startup-error-label " ) . set_text ( msg )
2006-06-14 10:59:40 -04:00
2009-11-28 20:49:44 -05:00
################
# Init methods #
################
def init_stats ( self ) :
2011-04-13 09:27:02 -04:00
self . add_gconf_handle (
2011-07-12 08:49:47 -04:00
self . config . on_vmlist_guest_cpu_usage_visible_changed (
self . toggle_guest_cpu_usage_visible_widget ) )
self . add_gconf_handle (
self . config . on_vmlist_host_cpu_usage_visible_changed (
self . toggle_host_cpu_usage_visible_widget ) )
2011-04-13 09:27:02 -04:00
self . add_gconf_handle (
self . config . on_vmlist_disk_io_visible_changed (
2011-07-12 08:49:47 -04:00
self . toggle_disk_io_visible_widget ) )
2011-04-13 09: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 10:59:40 -04:00
2008-12-17 15:27:06 -05:00
# Register callbacks with the global stats enable/disable values
# that disable the associated vmlist widgets if reporting is disabled
2011-04-13 09:27:02 -04:00
self . add_gconf_handle (
self . config . on_stats_enable_disk_poll_changed ( self . enable_polling ,
2011-07-12 08:49:47 -04:00
COL_DISK ) )
2011-04-13 09:27:02 -04:00
self . add_gconf_handle (
self . config . on_stats_enable_net_poll_changed ( self . enable_polling ,
2011-07-12 08:49:47 -04:00
COL_NETWORK ) )
2011-04-13 09:27:02 -04:00
2008-12-17 15:27:06 -05:00
2011-07-14 13:13:13 -04:00
self . widget ( " menu_view_stats_guest_cpu " ) . set_active (
2011-07-12 08:49:47 -04:00
self . config . is_vmlist_guest_cpu_usage_visible ( ) )
2011-07-14 13:13:13 -04:00
self . widget ( " menu_view_stats_host_cpu " ) . set_active (
2011-07-12 08:49:47 -04:00
self . config . is_vmlist_host_cpu_usage_visible ( ) )
2011-07-14 13:13:13 -04:00
self . widget ( " menu_view_stats_disk " ) . set_active (
2009-11-28 20:49:44 -05:00
self . config . is_vmlist_disk_io_visible ( ) )
2011-07-14 13:13:13 -04:00
self . widget ( " menu_view_stats_network " ) . set_active (
2009-11-28 20:49:44 -05:00
self . config . is_vmlist_network_traffic_visible ( ) )
2009-11-11 11:02:57 -05:00
2009-11-28 20:49:44 -05:00
def init_toolbar ( self ) :
2011-07-14 13:13:13 -04:00
self . widget ( " vm-new " ) . set_icon_name ( " vm_new " )
self . widget ( " vm-open " ) . set_icon_name ( " icon_console " )
uihelpers . build_shutdown_button_menu ( self . widget ( " vm-shutdown " ) ,
self . poweroff_vm ,
self . reboot_vm ,
2013-03-16 17:59:32 -04:00
self . reset_vm ,
2011-07-14 13:13:13 -04:00
self . destroy_vm ,
self . save_vm )
tool = self . widget ( " vm-toolbar " )
2012-05-14 14:24:56 +01:00
tool . set_property ( " icon-size " , Gtk . IconSize . LARGE_TOOLBAR )
2009-11-10 12:57:28 -05:00
for c in tool . get_children ( ) :
2009-07-26 16:25:01 -04:00
c . set_homogeneous ( False )
2009-11-28 20:49:44 -05:00
def init_context_menus ( self ) :
2009-11-17 16:20:23 -05:00
def build_icon ( name ) :
2012-05-14 14:24:56 +01:00
return Gtk . Image . new_from_icon_name ( name , Gtk . IconSize . MENU )
2009-11-17 16:20:23 -05:00
def build_stock ( name ) :
2012-05-14 14:24:56 +01:00
return Gtk . Image . new_from_stock ( name , Gtk . IconSize . MENU )
2009-11-17 16:20:23 -05:00
2013-01-13 14:41:25 -05:00
shutdownmenu_icon = build_icon ( " system-shutdown " )
reboot_icon = build_icon ( " system-shutdown " )
shutdown_icon = build_icon ( " system-shutdown " )
destroy_icon = build_icon ( " system-shutdown " )
reset_icon = build_icon ( " system-shutdown " )
2012-05-14 14:24:56 +01:00
run_icon = build_stock ( Gtk . STOCK_MEDIA_PLAY )
pause_icon = build_stock ( Gtk . STOCK_MEDIA_PAUSE )
save_icon = build_stock ( Gtk . STOCK_SAVE )
resume_icon = build_stock ( Gtk . STOCK_MEDIA_PAUSE )
delete_icon = build_stock ( Gtk . STOCK_DELETE )
2007-03-08 14:39:22 -05:00
2010-05-12 15:31:36 -04:00
def add_to_menu ( menu , items , idx , text , icon , cb ) :
2012-05-14 14:24:56 +01: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 15:31:36 -04:00
if icon :
item . set_image ( icon )
item . show ( )
if cb :
item . connect ( " activate " , cb )
menu . add ( item )
items [ idx ] = item
def add_vm_menu ( idx , text , icon , cb ) :
add_to_menu ( self . vmmenu , self . vmmenu_items , idx , text , icon , cb )
def add_shutdown_menu ( idx , text , icon , cb ) :
add_to_menu ( self . vmmenushutdown , self . vmmenushutdown_items ,
idx , text , icon , cb )
def add_conn_menu ( idx , text , icon , cb ) :
add_to_menu ( self . connmenu , self . connmenu_items ,
idx , text , icon , cb )
def add_sep ( menu , items , idx ) :
2012-05-14 14:24:56 +01:00
sep = Gtk . SeparatorMenuItem ( )
2010-05-12 15:31:36 -04:00
sep . show ( )
menu . add ( sep )
items [ idx ] = sep
# Build VM context menu
add_vm_menu ( " run " , _ ( " _Run " ) , run_icon , self . start_vm )
add_vm_menu ( " pause " , _ ( " _Pause " ) , pause_icon , self . pause_vm )
add_vm_menu ( " resume " , _ ( " R_esume " ) , resume_icon , self . resume_vm )
add_vm_menu ( " shutdown " , _ ( " _Shut Down " ) , shutdownmenu_icon , None )
2008-05-13 15:59:25 -04:00
self . vmmenu_items [ " shutdown " ] . set_submenu ( self . vmmenushutdown )
2010-05-12 15:31:36 -04:00
add_shutdown_menu ( " reboot " , _ ( " _Reboot " ) , reboot_icon , self . reboot_vm )
add_shutdown_menu ( " poweroff " , _ ( " _Shut Down " ) , shutdown_icon ,
self . poweroff_vm )
2013-03-16 17:59:32 -04:00
add_shutdown_menu ( " forcereset " , _ ( " _Force Reset " ) , reset_icon ,
self . reset_vm )
2010-05-12 15:31:36 -04:00
add_shutdown_menu ( " forcepoweroff " , _ ( " _Force Off " ) , destroy_icon ,
self . destroy_vm )
add_sep ( self . vmmenushutdown , self . vmmenushutdown_items , " sep " )
add_shutdown_menu ( " save " , _ ( " Sa_ve " ) , save_icon , self . save_vm )
add_sep ( self . vmmenu , self . vmmenu_items , " hsep1 " )
add_vm_menu ( " clone " , _ ( " _Clone... " ) , None , self . open_clone_window )
add_vm_menu ( " migrate " , _ ( " _Migrate... " ) , None , self . migrate_vm )
add_vm_menu ( " delete " , _ ( " _Delete " ) , delete_icon , self . do_delete )
add_sep ( self . vmmenu , self . vmmenu_items , " hsep2 " )
2012-05-14 14:24:56 +01:00
add_vm_menu ( " open " , Gtk . STOCK_OPEN , None , self . show_vm )
2007-03-08 14:39:22 -05:00
self . vmmenu . show ( )
2006-06-14 10:59:40 -04:00
2010-05-12 15:31:36 -04:00
# Build connection context menu
2012-05-14 14:24:56 +01:00
add_conn_menu ( " create " , Gtk . STOCK_NEW , None , self . new_vm )
add_conn_menu ( " connect " , Gtk . STOCK_CONNECT , None , self . open_conn )
add_conn_menu ( " disconnect " , Gtk . STOCK_DISCONNECT , None ,
2011-07-22 16:43:26 -04:00
self . close_conn )
2010-05-12 15:31:36 -04:00
add_sep ( self . connmenu , self . connmenu_items , " hsep1 " )
2012-05-14 14:24:56 +01:00
add_conn_menu ( " delete " , Gtk . STOCK_DELETE , None , self . do_delete )
2010-05-12 15:31:36 -04:00
add_sep ( self . connmenu , self . connmenu_items , " hsep2 " )
2011-07-12 19:20:58 -04:00
add_conn_menu ( " details " , _ ( " D_etails " ) , None , self . show_host )
2007-08-13 17:13:39 -04:00
self . connmenu . show ( )
2009-11-28 20:49:44 -05:00
def init_vmlist ( self ) :
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
self . widget ( " vm-notebook " ) . set_show_tabs ( False )
2006-06-14 10:59:40 -04:00
2011-07-12 11:50:11 -04:00
# Handle, name, markup, status, status icon name, key/uuid, hint,
2011-07-18 19:53:56 +01:00
# is conn, is conn connected, is vm, is vm running, fg color,
# inspection icon
2012-05-14 14:24:56 +01:00
model = Gtk . TreeStore ( object , str , str , str , str , str , str ,
bool , bool , bool , bool , Gdk . Color ,
GdkPixbuf . Pixbuf )
2009-11-28 20:49:44 -05:00
vmlist . set_model ( model )
2012-02-01 17:26:46 -05:00
vmlist . set_tooltip_column ( ROW_HINT )
2009-11-28 20:49:44 -05:00
vmlist . set_headers_visible ( True )
2012-02-01 17:26:46 -05:00
vmlist . set_level_indentation ( - 15 )
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
nameCol = Gtk . TreeViewColumn ( _ ( " Name " ) )
2009-11-28 20:49:44 -05:00
nameCol . set_expand ( True )
nameCol . set_spacing ( 6 )
2006-11-06 10:34:54 -05:00
2009-11-28 20:49:44 -05:00
statusCol = nameCol
vmlist . append_column ( nameCol )
2008-12-17 15:27:06 -05:00
2012-05-14 14:24:56 +01:00
status_icon = Gtk . CellRendererPixbuf ( )
status_icon . set_property ( " stock-size " , Gtk . IconSize . DND )
2009-11-28 20:49:44 -05:00
statusCol . pack_start ( status_icon , False )
2011-07-12 11:50:11 -04:00
statusCol . add_attribute ( status_icon , ' icon-name ' , ROW_STATUS_ICON )
2009-11-28 20:49:44 -05:00
statusCol . add_attribute ( status_icon , ' visible ' , ROW_IS_VM )
2009-03-09 16:22:03 -04:00
2012-05-14 14:24:56 +01:00
inspection_os_icon = Gtk . CellRendererPixbuf ( )
2011-07-18 19:53:56 +01:00
statusCol . pack_start ( inspection_os_icon , False )
statusCol . add_attribute ( inspection_os_icon , ' pixbuf ' ,
ROW_INSPECTION_OS_ICON )
statusCol . add_attribute ( inspection_os_icon , ' visible ' , ROW_IS_VM )
2012-05-14 14:24:56 +01:00
name_txt = Gtk . CellRendererText ( )
2009-11-28 20:49:44 -05:00
nameCol . pack_start ( name_txt , True )
nameCol . add_attribute ( name_txt , ' markup ' , ROW_MARKUP )
nameCol . add_attribute ( name_txt , ' foreground-gdk ' , ROW_COLOR )
nameCol . set_sort_column_id ( COL_NAME )
2007-09-09 22:57:24 -04:00
2011-07-12 08:49:47 -04:00
def make_stats_column ( title , datafunc , is_visible , colnum ) :
2012-05-14 14:24:56 +01:00
col = Gtk . TreeViewColumn ( title )
2011-07-12 08:49:47 -04:00
col . set_min_width ( 140 )
2012-05-14 14:24:56 +01:00
txt = Gtk . CellRendererText ( )
2011-07-12 08:49:47 -04:00
img = CellRendererSparkline ( )
img . set_property ( " xpad " , 6 )
img . set_property ( " ypad " , 12 )
img . set_property ( " reversed " , True )
col . pack_start ( img , True )
col . pack_start ( txt , False )
col . add_attribute ( img , ' visible ' , ROW_IS_VM )
col . add_attribute ( txt , ' visible ' , ROW_IS_CONN )
col . set_cell_data_func ( img , datafunc , None )
col . set_visible ( is_visible )
col . set_sort_column_id ( colnum )
vmlist . append_column ( col )
return col
self . guestcpucol = make_stats_column ( _ ( " CPU usage " ) ,
self . guest_cpu_usage_img ,
self . config . is_vmlist_guest_cpu_usage_visible ( ) ,
COL_GUEST_CPU )
self . hostcpucol = make_stats_column ( _ ( " Host CPU usage " ) ,
self . host_cpu_usage_img ,
self . config . is_vmlist_host_cpu_usage_visible ( ) ,
COL_HOST_CPU )
self . diskcol = make_stats_column ( _ ( " Disk I/O " ) ,
self . disk_io_img ,
self . config . is_vmlist_disk_io_visible ( ) ,
COL_DISK )
self . netcol = make_stats_column ( _ ( " Network I/O " ) ,
self . network_traffic_img ,
self . config . is_vmlist_network_traffic_visible ( ) ,
COL_NETWORK )
2006-06-14 10:59:40 -04:00
2009-11-28 20:49:44 -05:00
model . set_sort_func ( COL_NAME , self . vmlist_name_sorter )
2011-07-12 08:49:47 -04:00
model . set_sort_func ( COL_GUEST_CPU , self . vmlist_guest_cpu_usage_sorter )
model . set_sort_func ( COL_HOST_CPU , self . vmlist_host_cpu_usage_sorter )
2009-11-28 20:49:44 -05:00
model . set_sort_func ( COL_DISK , self . vmlist_disk_io_sorter )
model . set_sort_func ( COL_NETWORK , self . vmlist_network_usage_sorter )
2012-05-14 14:24:56 +01:00
model . set_sort_column_id ( COL_NAME , Gtk . SortType . ASCENDING )
2009-11-28 20:49:44 -05:00
##################
# Helper methods #
##################
def current_row ( self ) :
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2009-11-28 20:49:44 -05:00
selection = vmlist . get_selection ( )
active = selection . get_selected ( )
treestore , treeiter = active
2012-11-08 14:15:02 +01:00
if treeiter is not None :
2009-11-28 20:49:44 -05:00
return treestore [ treeiter ]
return None
def current_vm ( self ) :
row = self . current_row ( )
if not row or row [ ROW_IS_CONN ] :
return None
return row [ ROW_HANDLE ]
2011-07-22 16:43:26 -04:00
def current_conn ( self ) :
2009-11-28 20:49:44 -05:00
row = self . current_row ( )
if not row :
return None
handle = row [ ROW_HANDLE ]
if row [ ROW_IS_CONN ] :
return handle
else :
2011-07-22 16:43:26 -04:00
return handle . conn
2009-11-28 20:49:44 -05:00
def current_vmuuid ( self ) :
vm = self . current_vm ( )
if vm is None :
return None
return vm . get_uuid ( )
2011-07-22 16:43:26 -04:00
def current_conn_uri ( self , default_selection = False ) :
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2010-08-22 12:50:31 -04:00
model = vmlist . get_model ( )
2011-07-22 16:43:26 -04:00
conn = self . current_conn ( )
2010-08-22 12: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-28 20:49:44 -05:00
####################
# Action listeners #
####################
2006-11-03 10:02:02 -05:00
2009-11-28 21:00:46 -05: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 11:22:35 -05:00
def exit_app ( self , src_ignore = None , src2_ignore = None ) :
2008-06-13 14:40:26 -04:00
self . emit ( " action-exit-app " )
2006-06-14 10:59:40 -04:00
2011-07-22 16:43:26 -04:00
def new_conn ( self , src_ignore = None ) :
2006-06-27 14:16:13 -04:00
self . emit ( " action-show-connect " )
2006-06-14 10:59:40 -04:00
2010-12-09 11:22:35 -05:00
def new_vm ( self , src_ignore = None ) :
2011-07-22 16:43:26 -04:00
self . emit ( " action-show-create " , self . current_conn_uri ( ) )
2009-11-28 20:49:44 -05:00
2010-12-09 11:22:35 -05:00
def show_about ( self , src_ignore ) :
2009-11-28 20:49:44 -05:00
self . emit ( " action-show-about " )
2010-12-09 11:22:35 -05:00
def show_preferences ( self , src_ignore ) :
2009-11-28 20:49:44 -05:00
self . emit ( " action-show-preferences " )
2010-12-09 11:22:35 -05:00
def show_host ( self , src_ignore ) :
2011-07-22 16:43:26 -04:00
uri = self . current_conn_uri ( default_selection = True )
2010-08-22 12:50:31 -04:00
self . emit ( " action-show-host " , uri )
2009-11-28 20:49:44 -05:00
2011-06-08 16:33:20 -04:00
def show_vm ( self , ignore , ignore2 = None , ignore3 = None ) :
2011-07-22 16:43:26 -04:00
conn = self . current_conn ( )
2011-06-08 16:33:20 -04:00
vm = self . current_vm ( )
if conn is None :
return
if vm :
self . emit ( " action-show-vm " , conn . get_uri ( ) , vm . get_uuid ( ) )
else :
2011-07-22 16:43:26 -04:00
if not self . open_conn ( ) :
2011-06-08 16:33:20 -04:00
self . emit ( " action-show-host " , conn . get_uri ( ) )
2009-11-28 20:49:44 -05:00
def open_clone_window ( self , ignore1 = None , ignore2 = None , ignore3 = None ) :
if self . current_vmuuid ( ) :
2011-07-22 16:43:26 -04:00
self . emit ( " action-clone-domain " , self . current_conn_uri ( ) ,
2009-11-28 20:49:44 -05:00
self . current_vmuuid ( ) )
def do_delete ( self , ignore = None ) :
2011-07-22 16:43:26 -04:00
conn = self . current_conn ( )
2009-11-28 20:49:44 -05:00
vm = self . current_vm ( )
if vm is None :
2011-07-22 16:43:26 -04:00
self . _do_delete_conn ( conn )
2009-11-28 20:49:44 -05:00
else :
self . _do_delete_vm ( vm )
2011-07-22 16:43:26 -04:00
def _do_delete_conn ( self , conn ) :
2009-11-28 20:49:44 -05: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 13:42:20 -04:00
2011-07-22 16:43:26 -04:00
self . emit ( " remove-conn " , conn . get_uri ( ) )
2009-11-28 20:49:44 -05:00
def _do_delete_vm ( self , vm ) :
if vm . is_active ( ) :
return
if not self . delete_dialog :
2011-04-11 16:14:23 -04:00
self . delete_dialog = vmmDeleteDialog ( )
2011-04-14 08:47:42 -04:00
self . delete_dialog . show ( vm , self . topwin )
2009-11-28 20:49:44 -05:00
def set_pause_state ( self , state ) :
2011-07-14 13:13:13 -04:00
src = self . widget ( " vm-pause " )
2009-11-28 20:49:44 -05:00
try :
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 14:49:58 -04:00
# Set button state back to original value: just let the status
# update function fix things for us
self . set_pause_state ( not do_pause )
2009-11-28 20:49:44 -05:00
if do_pause :
self . pause_vm ( None )
else :
self . resume_vm ( None )
def start_vm ( self , ignore ) :
vm = self . current_vm ( )
if vm is not None :
self . emit ( " action-run-domain " ,
2011-07-22 16:43:26 -04:00
vm . conn . get_uri ( ) , vm . get_uuid ( ) )
2009-11-28 20:49:44 -05:00
def reboot_vm ( self , ignore ) :
vm = self . current_vm ( )
if vm is not None :
self . emit ( " action-reboot-domain " ,
2011-07-22 16:43:26 -04:00
vm . conn . get_uri ( ) , vm . get_uuid ( ) )
2009-11-28 20:49:44 -05:00
def poweroff_vm ( self , ignore ) :
vm = self . current_vm ( )
if vm is not None :
self . emit ( " action-shutdown-domain " ,
2011-07-22 16:43:26 -04:00
vm . conn . get_uri ( ) , vm . get_uuid ( ) )
2009-11-28 20:49:44 -05:00
def destroy_vm ( self , ignore ) :
vm = self . current_vm ( )
if vm is not None :
self . emit ( " action-destroy-domain " ,
2011-07-22 16:43:26 -04:00
vm . conn . get_uri ( ) , vm . get_uuid ( ) )
2009-11-28 20:49:44 -05:00
2013-03-16 17:59:32 -04:00
def reset_vm ( self , ignore ) :
vm = self . current_vm ( )
if vm is not None :
self . emit ( " action-reset-domain " ,
vm . conn . get_uri ( ) , vm . get_uuid ( ) )
2010-05-12 11:42:59 -04:00
def save_vm ( self , ignore ) :
vm = self . current_vm ( )
if vm is not None :
self . emit ( " action-save-domain " ,
2011-07-22 16:43:26 -04:00
vm . conn . get_uri ( ) , vm . get_uuid ( ) )
2010-05-12 11:42:59 -04:00
2009-11-28 20:49:44 -05:00
def pause_vm ( self , ignore ) :
vm = self . current_vm ( )
if vm is not None :
self . emit ( " action-suspend-domain " ,
2011-07-22 16:43:26 -04:00
vm . conn . get_uri ( ) , vm . get_uuid ( ) )
2009-11-28 20:49:44 -05:00
def resume_vm ( self , ignore ) :
vm = self . current_vm ( )
if vm is not None :
self . emit ( " action-resume-domain " ,
2011-07-22 16:43:26 -04:00
vm . conn . get_uri ( ) , vm . get_uuid ( ) )
2009-11-28 20:49:44 -05:00
def migrate_vm ( self , ignore ) :
vm = self . current_vm ( )
if vm is not None :
self . emit ( " action-migrate-domain " ,
2011-07-22 16:43:26 -04:00
vm . conn . get_uri ( ) , vm . get_uuid ( ) )
2009-11-28 20:49:44 -05:00
2011-07-22 16:43:26 -04:00
def close_conn ( self , ignore ) :
conn = self . current_conn ( )
2009-11-28 20:49:44 -05:00
if conn . get_state ( ) != vmmConnection . STATE_DISCONNECTED :
conn . close ( )
2011-07-22 16:43:26 -04:00
def open_conn ( self , ignore = None ) :
conn = self . current_conn ( )
2009-11-28 20:49:44 -05:00
if conn . get_state ( ) == vmmConnection . STATE_DISCONNECTED :
conn . open ( )
return True
2012-02-02 16:45:18 -05:00
def _connect_error ( self , conn , errmsg , tb , warnconsole ) :
errmsg = errmsg . strip ( " \n " )
2012-01-27 18:31:21 -05:00
tb = tb . strip ( " \n " )
2012-02-02 16:45:18 -05:00
hint = " "
show_errmsg = True
if conn . is_remote ( ) :
logging . debug ( conn . get_transport ( ) )
if re . search ( r " nc: .* -- ' U ' " , tb ) :
hint + = _ ( " The remote host requires a version of netcat/nc \n "
" which supports the -U option. " )
show_errmsg = False
2012-07-08 15:38:52 -04:00
elif ( conn . get_transport ( ) [ 0 ] == " ssh " and
re . search ( r " ssh-askpass " , tb ) ) :
if self . config . askpass_package :
ret = packageutils . check_packagekit (
self . err ,
self . config . askpass_package ,
False )
if ret :
conn . open ( )
return
hint + = _ ( " You need to install openssh-askpass or "
" similar \n to connect to this host. " )
2012-02-02 16:45:18 -05:00
show_errmsg = False
else :
hint + = _ ( " Verify that the ' libvirtd ' daemon is running \n "
" on the remote host. " )
2012-01-27 18:31:21 -05:00
2012-02-02 16:45:18 -05:00
elif conn . is_xen ( ) :
hint + = _ ( " Verify that: \n "
" - A Xen host kernel was booted \n "
" - The Xen service has been started " )
2012-01-27 18:31:21 -05:00
2009-11-28 20:49:44 -05:00
else :
2012-01-27 18:31:21 -05:00
if warnconsole :
2012-02-02 16:45:18 -05:00
hint + = _ ( " Could not detect a local session: if you are \n "
" running virt-manager over ssh -X or VNC, you \n "
" may not be able to connect to libvirt as a \n "
" regular user. Try running as root. " )
show_errmsg = False
elif re . search ( r " libvirt-sock " , tb ) :
hint + = _ ( " Verify that the ' libvirtd ' daemon is running. " )
show_errmsg = False
msg = _ ( " Unable to connect to libvirt. " )
if show_errmsg :
msg + = " \n \n %s " % errmsg
if hint :
msg + = " \n \n %s " % hint
msg = msg . strip ( " \n " )
details = msg
details + = " \n \n "
details + = " Libvirt URI is: %s \n \n " % conn . get_uri ( )
details + = tb
self . err . show_err ( msg , details , title = _ ( " Virtual Machine Manager Connection Failure " ) )
2009-11-28 20:49:44 -05:00
####################################
# VM add/remove management methods #
####################################
def vm_row_key ( self , vm ) :
2011-07-22 16:43:26 -04:00
return vm . get_uuid ( ) + " : " + vm . conn . get_uri ( )
2006-07-20 11:16:07 -04:00
2011-07-22 13:54:40 -04:00
def vm_added ( self , conn , vmuuid ) :
vm = conn . get_vm ( vmuuid )
2006-10-10 17:24:59 -04:00
vm . connect ( " status-changed " , self . vm_status_changed )
vm . connect ( " resources-sampled " , self . vm_resources_sampled )
2011-07-15 15:38:59 -04:00
vm . connect ( " config-changed " , self . vm_resources_sampled , True )
2011-07-18 19:53:56 +01:00
vm . connect ( " inspection-changed " , self . vm_inspection_changed )
2006-06-14 17:52:49 -04:00
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2006-10-10 17:24:59 -04:00
model = vmlist . get_model ( )
2006-06-14 10:59:40 -04:00
2011-07-22 13:54:40 -04:00
self . _append_vm ( model , vm , conn )
2006-06-14 10:59:40 -04:00
2011-07-22 13:54:40 -04:00
def vm_removed ( self , conn , vmuuid ) :
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2009-11-28 20:49:44 -05:00
model = vmlist . get_model ( )
2011-07-22 13:54:40 -04:00
parent = self . rows [ conn . get_uri ( ) ] . iter
2009-11-28 20:49:44 -05:00
for row in range ( model . iter_n_children ( parent ) ) :
vm = model . get_value ( model . iter_nth_child ( parent , row ) , ROW_HANDLE )
if vm . get_uuid ( ) == vmuuid :
model . remove ( model . iter_nth_child ( parent , row ) )
del self . rows [ self . vm_row_key ( vm ) ]
break
2009-10-21 10:36:58 -04:00
def _build_conn_hint ( self , conn ) :
hint = conn . get_uri ( )
if conn . state == conn . STATE_DISCONNECTED :
hint + = " ( %s ) " % _ ( " Double click to connect " )
return hint
2009-09-17 12:35:41 -04:00
def _build_conn_markup ( self , conn , row ) :
2011-08-29 12:11:43 -04:00
name = util . xml_escape ( row [ ROW_NAME ] )
text = name
2009-09-17 12:35:41 -04:00
if conn . state == conn . STATE_DISCONNECTED :
2011-08-29 12:11:43 -04:00
text + = " - " + _ ( " Not Connected " )
2009-11-10 15:42:07 -05:00
elif conn . state == conn . STATE_CONNECTING :
2011-08-29 12:11:43 -04:00
text + = " - " + _ ( " Connecting... " )
2010-12-01 15:22:38 -05:00
markup = " <span size= ' smaller ' > %s </span> " % text
2009-09-17 12:35:41 -04:00
return markup
2009-11-10 15:42:07 -05:00
def _build_conn_color ( self , conn ) :
2012-05-14 14:24:56 +01:00
color = Gdk . Color ( 0 , 0 , 0 )
2011-07-12 21:32:56 -04:00
if conn . state == conn . STATE_DISCONNECTED :
2009-12-03 10:21:39 -05:00
# Color code #5b5b5b
2012-05-14 14:24:56 +01:00
color = Gdk . Color ( 23296 , 23296 , 23296 )
2009-11-10 15:42:07 -05:00
return color
2011-07-15 15:38:59 -04:00
def _build_vm_markup ( self , row ) :
2010-12-01 15:22:38 -05:00
domtext = ( " <span size= ' smaller ' weight= ' bold ' > %s </span> " %
2011-08-29 12:11:43 -04:00
util . xml_escape ( row [ ROW_NAME ] ) )
2010-12-01 15:22:38 -05:00
statetext = " <span size= ' smaller ' > %s </span> " % row [ ROW_STATUS ]
return domtext + " \n " + statetext
2009-09-17 12:35:41 -04:00
2011-03-23 16:56:12 -04:00
def _build_vm_row ( self , vm ) :
2007-08-27 22:22:18 -04:00
row = [ ]
2011-09-26 11:05:55 -04:00
2007-08-27 22:22:18 -04:00
row . insert ( ROW_HANDLE , vm )
row . insert ( ROW_NAME , vm . get_name ( ) )
2009-09-17 12:35:41 -04:00
row . insert ( ROW_MARKUP , " " )
2007-08-27 22:22:18 -04:00
row . insert ( ROW_STATUS , vm . run_status ( ) )
2011-07-12 11:50:11 -04:00
row . insert ( ROW_STATUS_ICON , vm . run_status_icon_name ( ) )
2007-08-27 22:22:18 -04:00
row . insert ( ROW_KEY , vm . get_uuid ( ) )
2012-01-17 15:31:20 -05:00
row . insert ( ROW_HINT , util . xml_escape ( vm . get_description ( ) ) )
2009-07-28 19:21:56 -04:00
row . insert ( ROW_IS_CONN , False )
row . insert ( ROW_IS_CONN_CONNECTED , True )
2009-07-26 16:25:01 -04:00
row . insert ( ROW_IS_VM , True )
row . insert ( ROW_IS_VM_RUNNING , vm . is_active ( ) )
2011-07-12 21:32:56 -04:00
row . insert ( ROW_COLOR , None )
2011-07-18 19:53:56 +01:00
row . insert ( ROW_INSPECTION_OS_ICON ,
self . get_inspection_icon_pixbuf ( vm , 16 , 16 ) )
2008-03-24 11:57:48 -04:00
2011-07-15 15:38:59 -04:00
row [ ROW_MARKUP ] = self . _build_vm_markup ( row )
2009-09-17 12:35:41 -04:00
2011-03-23 16:56:12 -04:00
return row
def _append_vm ( self , model , vm , conn ) :
row_key = self . vm_row_key ( vm )
if row_key in self . rows :
return
row = self . _build_vm_row ( vm )
parent = self . rows [ conn . get_uri ( ) ] . iter
2008-11-18 15:42:51 -05:00
_iter = model . append ( parent , row )
path = model . get_path ( _iter )
2009-11-18 13:51:36 -05:00
self . rows [ row_key ] = model [ path ]
2011-03-23 16:56:12 -04:00
2007-08-14 12:31:24 -04:00
# Expand a connection when adding a vm to it
2011-07-14 13:13:13 -04:00
self . widget ( " vm-list " ) . expand_row ( model . get_path ( parent ) , False )
2006-06-14 10:59:40 -04:00
2011-07-22 16:43:26 -04:00
def _append_conn ( self , model , conn ) :
2007-08-27 22:22:18 -04:00
row = [ ]
2007-09-09 22:57:24 -04:00
row . insert ( ROW_HANDLE , conn )
2009-07-28 19:21:56 -04:00
row . insert ( ROW_NAME , conn . get_pretty_desc_inactive ( False ) )
2009-09-17 12:35:41 -04:00
row . insert ( ROW_MARKUP , self . _build_conn_markup ( conn , row ) )
2010-12-01 15:22:38 -05:00
row . insert ( ROW_STATUS , ( " <span size= ' smaller ' > %s </span> " %
2009-07-28 19:21:56 -04:00
conn . get_state_text ( ) ) )
2007-08-27 22:22:18 -04:00
row . insert ( ROW_STATUS_ICON , None )
2007-09-09 22:57:24 -04:00
row . insert ( ROW_KEY , conn . get_uri ( ) )
2009-10-21 10:36:58 -04:00
row . insert ( ROW_HINT , self . _build_conn_hint ( conn ) )
2009-07-28 19:21:56 -04:00
row . insert ( ROW_IS_CONN , True )
row . insert ( ROW_IS_CONN_CONNECTED ,
conn . state != conn . STATE_DISCONNECTED )
2009-07-26 16:25:01 -04:00
row . insert ( ROW_IS_VM , False )
row . insert ( ROW_IS_VM_RUNNING , False )
2009-11-10 15:42:07 -05:00
row . insert ( ROW_COLOR , self . _build_conn_color ( conn ) )
2011-07-18 19:53:56 +01:00
row . insert ( ROW_INSPECTION_OS_ICON , None )
2008-03-24 11:57:48 -04:00
2008-11-18 15:42:51 -05:00
_iter = model . append ( None , row )
path = model . get_path ( _iter )
2007-09-09 22:57:24 -04:00
self . rows [ conn . get_uri ( ) ] = model [ path ]
2009-02-15 17:36:36 -05:00
return _iter
2007-08-09 16:19:41 -04:00
2011-07-22 16:43:26 -04:00
def add_conn ( self , engine_ignore , conn ) :
2010-03-02 20:35:54 -05:00
# Make sure error page isn't showing
2011-07-14 13:13:13 -04:00
self . widget ( " vm-notebook " ) . set_current_page ( 0 )
2010-03-02 20:35:54 -05:00
2010-12-10 11:47:07 -05:00
if conn . get_uri ( ) in self . rows :
2009-11-28 20:49:44 -05:00
return
conn . connect ( " vm-added " , self . vm_added )
conn . connect ( " vm-removed " , self . vm_removed )
2011-07-25 15:09:42 -04:00
conn . connect ( " resources-sampled " , self . conn_resources_sampled )
2009-11-28 20:49:44 -05:00
conn . connect ( " state-changed " , self . conn_state_changed )
conn . connect ( " connect-error " , self . _connect_error )
# add the connection to the treeModel
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2011-07-22 16:43:26 -04:00
row = self . _append_conn ( vmlist . get_model ( ) , conn )
2009-11-28 20:49:44 -05:00
vmlist . get_selection ( ) . select_iter ( row )
2006-06-14 10:59:40 -04:00
2010-12-11 23:51:20 -05:00
# Try to make sure that 2 row descriptions don't collide
connrows = [ ]
descs = [ ]
for row in self . rows . values ( ) :
if row [ ROW_IS_CONN ] :
connrows . append ( row )
for row in connrows :
descs . append ( row [ ROW_NAME ] )
for row in connrows :
conn = row [ ROW_HANDLE ]
name = row [ ROW_NAME ]
if descs . count ( name ) < = 1 :
continue
newname = conn . get_pretty_desc_inactive ( False , True )
2011-07-25 15:09:42 -04:00
self . conn_resources_sampled ( conn , newname )
2010-12-11 23:51:20 -05:00
2011-07-22 16:43:26 -04:00
def remove_conn ( self , engine_ignore , uri ) :
2011-07-14 13:13:13 -04:00
model = self . widget ( " vm-list " ) . get_model ( )
2011-04-12 11:50:10 -04:00
parent = self . rows [ uri ] . iter
if parent is None :
return
child = model . iter_children ( parent )
while child is not None :
del self . rows [ self . vm_row_key ( model . get_value ( child , ROW_HANDLE ) ) ]
model . remove ( child )
2009-11-28 20:49:44 -05:00
child = model . iter_children ( parent )
2011-04-12 11:50:10 -04:00
model . remove ( parent )
del self . rows [ uri ]
2009-11-28 20:49:44 -05:00
#############################
# State/UI updating methods #
#############################
2006-06-14 10:59:40 -04:00
2011-04-15 14:13:05 -04:00
def vm_status_changed ( self , vm , oldstatus , newstatus ) :
ignore = newstatus
2011-04-15 14:43:52 -04:00
ignore = oldstatus
2011-07-22 16:43:26 -04:00
parent = self . rows [ vm . conn . get_uri ( ) ] . iter
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2006-10-10 17:24:59 -04:00
model = vmlist . get_model ( )
missing = True
2007-08-09 16:19:41 -04:00
for row in range ( model . iter_n_children ( parent ) ) :
2008-11-18 15:42:51 -05:00
_iter = model . iter_nth_child ( parent , row )
if model . get_value ( _iter , ROW_KEY ) == vm . get_uuid ( ) :
2009-07-26 16:12:39 -04:00
missing = False
2006-10-10 17:24:59 -04:00
break
2009-07-26 16:12:39 -04:00
if missing :
2011-07-22 16:43:26 -04:00
self . _append_vm ( model , vm , vm . conn )
2006-06-14 18:42:04 -04:00
2009-07-26 16:15:05 -04:00
# Update run/shutdown/pause button states
self . vm_selected ( )
2011-04-15 14:14:12 -04:00
self . vm_resources_sampled ( vm )
2006-06-14 18:42:04 -04:00
2011-07-15 15:38:59 -04:00
def vm_resources_sampled ( self , vm , config_changed = False ) :
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2006-06-14 10:59:40 -04:00
model = vmlist . get_model ( )
2010-12-10 11:47:07 -05:00
if self . vm_row_key ( vm ) not in self . rows :
2006-11-13 15:38:10 -05:00
return
2008-10-23 11:45:27 -04:00
row = self . rows [ self . vm_row_key ( vm ) ]
2011-03-23 16:56:12 -04:00
row [ ROW_NAME ] = vm . get_name ( )
2007-08-27 22:22:18 -04:00
row [ ROW_STATUS ] = vm . run_status ( )
2011-07-12 11:50:11 -04:00
row [ ROW_STATUS_ICON ] = vm . run_status_icon_name ( )
2009-07-26 16:25:01 -04:00
row [ ROW_IS_VM_RUNNING ] = vm . is_active ( )
2011-07-15 15:38:59 -04:00
row [ ROW_MARKUP ] = self . _build_vm_markup ( row )
if config_changed :
2013-02-16 13:54:45 -05:00
desc = vm . get_description ( )
if not can_set_row_none :
desc = desc or " "
row [ ROW_HINT ] = util . xml_escape ( desc )
2011-07-15 15:38:59 -04:00
2006-10-12 14:02:45 -04:00
model . row_changed ( row . path , row . iter )
2006-06-14 10:59:40 -04:00
2011-07-18 19:53:56 +01:00
def vm_inspection_changed ( self , vm ) :
2012-02-01 17:26:46 -05:00
vmlist = self . widget ( " vm-list " )
2011-07-18 19:53:56 +01:00
model = vmlist . get_model ( )
if self . vm_row_key ( vm ) not in self . rows :
return
row = self . rows [ self . vm_row_key ( vm ) ]
row [ ROW_INSPECTION_OS_ICON ] = \
self . get_inspection_icon_pixbuf ( vm , 16 , 16 )
model . row_changed ( row . path , row . iter )
def get_inspection_icon_pixbuf ( self , vm , w , h ) :
# libguestfs gives us the PNG data as a string.
png_data = vm . inspection . icon
2012-11-08 14:15:02 +01:00
if png_data is None :
2011-07-18 19:53:56 +01:00
return None
try :
2012-05-14 14:24:56 +01:00
pb = GdkPixbuf . PixbufLoader ( image_type = " png " )
2011-07-18 19:53:56 +01:00
pb . set_size ( w , h )
pb . write ( png_data )
pb . close ( )
return pb . get_pixbuf ( )
except :
return None
2007-09-09 22:57:24 -04:00
def conn_state_changed ( self , conn ) :
2011-07-25 15:09:42 -04:00
self . conn_resources_sampled ( conn )
2009-07-26 16:15:05 -04:00
self . vm_selected ( )
2008-01-02 17:55:26 -05:00
2011-07-25 15:09:42 -04:00
def conn_resources_sampled ( self , conn , newname = None ) :
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2007-08-14 12:31:24 -04:00
model = vmlist . get_model ( )
2007-09-09 22:57:24 -04:00
row = self . rows [ conn . get_uri ( ) ]
2009-07-28 19:21:56 -04:00
2010-12-11 23:51:20 -05:00
if newname :
row [ ROW_NAME ] = newname
2009-09-17 12:35:41 -04:00
row [ ROW_MARKUP ] = self . _build_conn_markup ( conn , row )
2010-12-01 15:22:38 -05:00
row [ ROW_STATUS ] = ( " <span size= ' smaller ' > %s </span> " %
conn . get_state_text ( ) )
2009-07-28 19:21:56 -04:00
row [ ROW_IS_CONN_CONNECTED ] = conn . state != conn . STATE_DISCONNECTED
2009-11-28 20:49:44 -05:00
row [ ROW_COLOR ] = self . _build_conn_color ( conn )
2011-07-15 15:38:59 -04:00
row [ ROW_HINT ] = self . _build_conn_hint ( conn )
2006-08-08 17:02:15 -04:00
2009-11-28 20:49:44 -05:00
if conn . get_state ( ) in [ vmmConnection . STATE_DISCONNECTED ,
vmmConnection . STATE_CONNECTING ] :
# Connection went inactive, delete any VM child nodes
parent = self . rows [ conn . get_uri ( ) ] . iter
if parent is not None :
child = model . iter_children ( parent )
while child is not None :
2011-07-25 15:09:42 -04:00
del self . rows [ self . vm_row_key ( model . get_value ( child ,
ROW_HANDLE ) ) ]
2009-11-28 20:49:44 -05:00
model . remove ( child )
child = model . iter_children ( parent )
2011-07-25 15:09:42 -04:00
self . max_disk_rate = max ( self . max_disk_rate , conn . disk_io_max_rate ( ) )
self . max_net_rate = max ( self . max_net_rate ,
conn . network_traffic_max_rate ( ) )
2009-11-28 20:49:44 -05:00
model . row_changed ( row . path , row . iter )
2006-06-14 10:59:40 -04:00
2010-05-12 12:57:32 -04:00
def change_run_text ( self , can_restore ) :
if can_restore :
text = _ ( " _Restore " )
else :
text = _ ( " _Run " )
strip_text = text . replace ( " _ " , " " )
self . vmmenu_items [ " run " ] . get_child ( ) . set_label ( text )
2011-07-14 13:13:13 -04:00
self . widget ( " vm-run " ) . set_label ( strip_text )
2006-06-14 10:59:40 -04:00
2009-07-26 16:15:05 -04:00
def vm_selected ( self , ignore = None ) :
2011-07-22 16:43:26 -04:00
conn = self . current_conn ( )
2007-08-09 16:19:41 -04:00
vm = self . current_vm ( )
2009-07-26 16:15:05 -04:00
show_open = bool ( vm )
show_details = bool ( vm )
2010-08-22 12:50:31 -04:00
host_details = bool ( len ( self . rows ) )
2009-08-31 10:19:49 -04:00
delete = bool ( ( vm and vm . is_runable ( ) ) or
( not vm and conn ) )
2009-07-26 16:15:05 -04:00
show_run = bool ( vm and vm . is_runable ( ) )
is_paused = bool ( vm and vm . is_paused ( ) )
if is_paused :
show_pause = bool ( vm and vm . is_unpauseable ( ) )
2007-08-09 16:19:41 -04:00
else :
2009-07-26 16:15:05 -04:00
show_pause = bool ( vm and vm . is_pauseable ( ) )
show_shutdown = bool ( vm and vm . is_stoppable ( ) )
2010-05-12 12:57:32 -04:00
if vm and vm . managedsave_supported :
self . change_run_text ( vm . hasSavedImage ( ) )
2011-07-14 13:13:13 -04:00
self . widget ( " vm-open " ) . set_sensitive ( show_open )
self . widget ( " vm-run " ) . set_sensitive ( show_run )
self . widget ( " vm-shutdown " ) . set_sensitive ( show_shutdown )
2009-07-26 16:15:05 -04:00
self . set_pause_state ( is_paused )
2011-07-14 13:13:13 -04:00
self . widget ( " vm-pause " ) . set_sensitive ( show_pause )
2009-07-26 16:15:05 -04:00
2011-07-14 13:13:13 -04:00
self . widget ( " menu_edit_details " ) . set_sensitive ( show_details )
self . widget ( " menu_host_details " ) . set_sensitive ( host_details )
self . widget ( " menu_edit_delete " ) . set_sensitive ( delete )
2009-07-26 16:15:05 -04:00
2010-12-09 11:22:35 -05:00
def popup_vm_menu_key ( self , widget_ignore , event ) :
2012-05-14 14:24:56 +01:00
if Gdk . keyval_name ( event . keyval ) != " Menu " :
2009-11-11 09:49:34 -05:00
return False
2011-07-14 13:13:13 -04:00
vmlist = self . widget ( " vm-list " )
2009-11-11 09:49:34 -05:00
treeselection = vmlist . get_selection ( )
model , _iter = treeselection . get_selected ( )
self . popup_vm_menu ( model , _iter , event )
return True
2007-08-13 17:13:39 -04:00
2009-11-11 09:49:34 -05:00
def popup_vm_menu_button ( self , widget , event ) :
2009-11-10 16:01:56 -05:00
if event . button != 3 :
return False
2008-11-18 15:42:51 -05:00
tup = widget . get_path_at_pos ( int ( event . x ) , int ( event . y ) )
2012-11-08 14:15:02 +01:00
if tup is None :
2007-08-23 17:46:30 -04:00
return False
2008-11-18 15:42:51 -05:00
path = tup [ 0 ]
2007-08-23 17:46:30 -04:00
model = widget . get_model ( )
2008-11-18 15:42:51 -05:00
_iter = model . get_iter ( path )
2009-11-10 16:01:56 -05:00
2009-11-11 09:49:34 -05:00
self . popup_vm_menu ( model , _iter , event )
2009-12-09 11:28:38 -05:00
return False
2009-11-11 09:49:34 -05:00
def popup_vm_menu ( self , model , _iter , event ) :
2012-11-08 14:15:02 +01:00
if model . iter_parent ( _iter ) is not None :
2009-11-10 16:01:56 -05:00
# Popup the vm menu
2008-11-18 15:42:51 -05:00
vm = model . get_value ( _iter , ROW_HANDLE )
2009-11-10 16:01:56 -05:00
destroy = vm . is_destroyable ( )
run = vm . is_runable ( )
stop = vm . is_stoppable ( )
paused = vm . is_paused ( )
ro = vm . is_read_only ( )
self . vmmenu_items [ " run " ] . set_sensitive ( run )
self . vmmenu_items [ " shutdown " ] . set_sensitive ( stop )
self . vmmenu_items [ " pause " ] . set_property ( " visible " , not paused )
self . vmmenu_items [ " pause " ] . set_sensitive ( stop )
self . vmmenu_items [ " resume " ] . set_property ( " visible " , paused )
self . vmmenu_items [ " resume " ] . set_sensitive ( paused )
2009-11-15 15:29:42 -05:00
self . vmmenu_items [ " migrate " ] . set_sensitive ( stop )
2009-11-10 16:01:56 -05:00
self . vmmenu_items [ " clone " ] . set_sensitive ( not ro )
2009-11-11 10:05:34 -05:00
self . vmmenu_items [ " delete " ] . set_sensitive ( run )
2009-11-10 16:01:56 -05:00
self . vmmenushutdown_items [ " poweroff " ] . set_sensitive ( stop )
self . vmmenushutdown_items [ " reboot " ] . set_sensitive ( stop )
self . vmmenushutdown_items [ " forcepoweroff " ] . set_sensitive ( destroy )
2010-05-12 11:42:59 -04:00
self . vmmenushutdown_items [ " save " ] . set_sensitive ( destroy )
2012-05-14 14:24:56 +01:00
self . vmmenu . popup ( None , None , None , None , 0 , event . time )
2007-08-23 17:46:30 -04:00
else :
2009-11-10 16:01:56 -05:00
# Pop up connection menu
2008-11-18 15:42:51 -05:00
conn = model . get_value ( _iter , ROW_HANDLE )
2009-11-10 16:01:56 -05:00
disconn = ( conn . get_state ( ) == vmmConnection . STATE_DISCONNECTED )
conning = ( conn . get_state ( ) == vmmConnection . STATE_CONNECTING )
self . connmenu_items [ " create " ] . set_sensitive ( not disconn )
self . connmenu_items [ " disconnect " ] . set_sensitive ( not ( disconn or
conning ) )
self . connmenu_items [ " connect " ] . set_sensitive ( disconn )
2009-11-16 16:35:34 -05:00
self . connmenu_items [ " delete " ] . set_sensitive ( disconn )
2009-11-10 16:01:56 -05:00
2012-05-14 14:24:56 +01:00
self . connmenu . popup ( None , None , None , None , 0 , event . time )
2009-11-10 16:01:56 -05:00
2009-11-11 11:02:57 -05:00
2009-11-28 20:49:44 -05:00
#################
# Stats methods #
#################
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
def vmlist_name_sorter ( self , model , iter1 , iter2 , ignore ) :
2009-07-28 19:21:56 -04:00
return cmp ( model . get_value ( iter1 , ROW_NAME ) ,
model . get_value ( iter2 , ROW_NAME ) )
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
def vmlist_guest_cpu_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2011-07-12 08:49:47 -04:00
obj1 = model . get_value ( iter1 , ROW_HANDLE )
obj2 = model . get_value ( iter2 , ROW_HANDLE )
return cmp ( obj1 . guest_cpu_time_percentage ( ) ,
obj2 . guest_cpu_time_percentage ( ) )
2012-05-14 14:24:56 +01:00
def vmlist_host_cpu_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2011-07-11 21:22:50 -04:00
obj1 = model . get_value ( iter1 , ROW_HANDLE )
obj2 = model . get_value ( iter2 , ROW_HANDLE )
return cmp ( obj1 . host_cpu_time_percentage ( ) ,
obj2 . host_cpu_time_percentage ( ) )
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
def vmlist_disk_io_sorter ( self , model , iter1 , iter2 , ignore ) :
2011-07-11 21:22:50 -04:00
obj1 = model . get_value ( iter1 , ROW_HANDLE )
obj2 = model . get_value ( iter2 , ROW_HANDLE )
return cmp ( obj1 . disk_io_rate ( ) , obj2 . disk_io_rate ( ) )
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
def vmlist_network_usage_sorter ( self , model , iter1 , iter2 , ignore ) :
2011-07-11 21:22:50 -04:00
obj1 = model . get_value ( iter1 , ROW_HANDLE )
obj2 = model . get_value ( iter2 , ROW_HANDLE )
return cmp ( obj1 . network_traffic_rate ( ) , obj2 . network_traffic_rate ( ) )
2006-06-14 10:59:40 -04:00
2008-12-17 15:27:06 -05:00
def enable_polling ( self , ignore1 , ignore2 , conf_entry , userdata ) :
2011-07-12 08:49:47 -04:00
if userdata == COL_DISK :
2009-07-26 16:15:28 -04:00
widgn = " menu_view_stats_disk "
2011-07-12 08:49:47 -04:00
elif userdata == COL_NETWORK :
2009-07-26 16:15:28 -04:00
widgn = " menu_view_stats_network "
2011-07-14 13:13:13 -04:00
widget = self . widget ( widgn )
2008-12-17 15:27:06 -05:00
2009-01-26 11:12:43 -05:00
tool_text = " "
2010-12-13 16:24:49 -05:00
2012-11-08 14:15:02 +01:00
if conf_entry and ( conf_entry is True or
2008-12-17 15:27:06 -05:00
conf_entry . get_value ( ) . get_bool ( ) ) :
widget . set_sensitive ( True )
else :
if widget . get_active ( ) :
widget . set_active ( False )
widget . set_sensitive ( False )
2009-01-26 11:12:43 -05:00
tool_text = _ ( " Disabled in preferences dialog. " )
2012-02-01 17:26:46 -05:00
widget . set_tooltip_text ( tool_text )
2011-02-15 11:38:35 -05:00
2012-02-01 17:26:46 -05:00
disabled_text = _ ( " (disabled) " )
current_text = widget . get_label ( ) . strip ( disabled_text )
if tool_text :
current_text = current_text + disabled_text
widget . set_label ( current_text )
2008-12-17 15:27:06 -05:00
2009-11-11 11:02:57 -05:00
def toggle_network_traffic_visible_widget ( self , * ignore ) :
2011-07-12 08:49:47 -04:00
val = self . config . is_vmlist_network_traffic_visible ( )
self . netcol . set_visible ( val )
2011-07-14 13:13:13 -04:00
self . widget ( " menu_view_stats_network " ) . set_active ( val )
2009-07-26 16:15:28 -04:00
2009-11-11 11:02:57 -05:00
def toggle_disk_io_visible_widget ( self , * ignore ) :
2011-07-12 08:49:47 -04:00
val = self . config . is_vmlist_disk_io_visible ( )
self . diskcol . set_visible ( val )
2011-07-14 13:13:13 -04:00
self . widget ( " menu_view_stats_disk " ) . set_active ( val )
2011-07-12 08:49:47 -04:00
def toggle_guest_cpu_usage_visible_widget ( self , * ignore ) :
val = self . config . is_vmlist_guest_cpu_usage_visible ( )
self . guestcpucol . set_visible ( val )
2011-07-14 13:13:13 -04:00
self . widget ( " menu_view_stats_guest_cpu " ) . set_active ( val )
2009-07-26 16:15:28 -04:00
2011-07-12 08:49:47 -04:00
def toggle_host_cpu_usage_visible_widget ( self , * ignore ) :
val = self . config . is_vmlist_host_cpu_usage_visible ( )
self . hostcpucol . set_visible ( val )
2011-07-14 13:13:13 -04:00
self . widget ( " menu_view_stats_host_cpu " ) . set_active ( val )
2009-11-11 11:02:57 -05:00
def toggle_stats_visible ( self , src , stats_id ) :
visible = src . get_active ( )
set_stats = {
2011-07-12 08:49:47 -04:00
COL_GUEST_CPU : self . config . set_vmlist_guest_cpu_usage_visible ,
COL_HOST_CPU : self . config . set_vmlist_host_cpu_usage_visible ,
COL_DISK : self . config . set_vmlist_disk_io_visible ,
COL_NETWORK : self . config . set_vmlist_network_traffic_visible ,
2009-11-11 11:02:57 -05:00
}
set_stats [ stats_id ] ( visible )
2006-06-14 10:59:40 -04:00
2012-05-14 14:24:56 +01:00
def toggle_stats_visible_guest_cpu ( self , src ) :
self . toggle_stats_visible ( src , COL_GUEST_CPU )
def toggle_stats_visible_host_cpu ( self , src ) :
self . toggle_stats_visible ( src , COL_HOST_CPU )
def toggle_stats_visible_disk ( self , src ) :
self . toggle_stats_visible ( src , COL_DISK )
def toggle_stats_visible_network ( self , src ) :
self . toggle_stats_visible ( src , COL_NETWORK )
2011-07-12 08:49:47 -04:00
def guest_cpu_usage_img ( self , column_ignore , cell , model , _iter , data ) :
obj = model . get_value ( _iter , ROW_HANDLE )
2012-05-14 14:24:56 +01:00
if obj is None or not hasattr ( obj , " conn " ) :
2011-07-12 08:49:47 -04:00
return
2012-05-14 14:24:56 +01:00
data = obj . guest_cpu_time_vector_limit ( GRAPH_LEN )
2011-07-12 08:49:47 -04:00
cell . set_property ( ' data_array ' , data )
def host_cpu_usage_img ( self , column_ignore , cell , model , _iter , data ) :
2011-07-11 21:22:50 -04:00
obj = model . get_value ( _iter , ROW_HANDLE )
2012-05-14 14:24:56 +01:00
if obj is None or not hasattr ( obj , " conn " ) :
2007-08-14 16:28:36 -04:00
return
2011-07-11 21:22:50 -04:00
2012-05-14 14:24:56 +01:00
data = obj . host_cpu_time_vector_limit ( GRAPH_LEN )
2008-10-18 21:28:57 +02:00
cell . set_property ( ' data_array ' , data )
2010-12-09 11:22:35 -05:00
def disk_io_img ( self , column_ignore , cell , model , _iter , data ) :
2011-07-11 21:22:50 -04:00
obj = model . get_value ( _iter , ROW_HANDLE )
2012-05-14 14:24:56 +01:00
if obj is None or not hasattr ( obj , " conn " ) :
2011-07-25 15:09:42 -04:00
return
2012-05-14 14:24:56 +01:00
data = obj . disk_io_vector_limit ( GRAPH_LEN , self . max_disk_rate )
2008-10-18 21:28:57 +02:00
cell . set_property ( ' data_array ' , data )
2010-12-09 11:22:35 -05:00
def network_traffic_img ( self , column_ignore , cell , model , _iter , data ) :
2011-07-11 21:22:50 -04:00
obj = model . get_value ( _iter , ROW_HANDLE )
2012-05-14 14:24:56 +01:00
if obj is None or not hasattr ( obj , " conn " ) :
2011-07-25 15:09:42 -04:00
return
2012-05-14 14:24:56 +01:00
data = obj . network_traffic_vector_limit ( GRAPH_LEN , self . max_net_rate )
2006-06-26 17:17:45 -04:00
cell . set_property ( ' data_array ' , data )