2006-06-28 23:50:17 +04:00
#
2008-04-08 22:30:47 +04:00
# Copyright (C) 2006-2008 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
2006-06-15 00:20:06 +04:00
import gobject
2006-06-14 18:59:40 +04:00
import gtk
import gtk . glade
2006-06-15 02:42:04 +04:00
import libvirt
2006-09-26 02:41:47 +04:00
import logging
2007-04-11 03:07:53 +04:00
import traceback
2008-04-08 22:30:47 +04:00
import os
2007-04-11 03:07:53 +04:00
2009-11-29 04:49:44 +03:00
import virtManager . uihelpers as uihelpers
2007-04-11 03:07:53 +04:00
from virtManager . error import vmmErrorDialog
2007-04-12 23:36:04 +04:00
from virtManager . addhardware import vmmAddHardware
2007-09-22 00:28:31 +04:00
from virtManager . choosecd import vmmChooseCD
2009-10-30 20:25:27 +03:00
from virtManager . console import vmmConsolePages
2008-10-03 00:17:25 +04:00
from virtManager . serialcon import vmmSerialConsole
2009-07-22 18:21:33 +04:00
from virtManager . graphwidgets import Sparkline
2009-01-26 19:12:43 +03:00
from virtManager import util as util
2007-04-11 03:07:53 +04:00
2007-04-11 22:48:36 +04:00
import virtinst
2007-07-14 22:43:20 +04:00
# Columns in hw list model
HW_LIST_COL_LABEL = 0
2009-07-20 23:09:32 +04:00
HW_LIST_COL_ICON_NAME = 1
HW_LIST_COL_ICON_SIZE = 2
HW_LIST_COL_TYPE = 3
HW_LIST_COL_DEVICE = 4
2007-07-14 22:43:20 +04:00
2008-07-24 00:23:56 +04:00
# Types for the hw list model: numbers specify what order they will be listed
2009-02-09 22:55:18 +03:00
HW_LIST_TYPE_GENERAL = 0
HW_LIST_TYPE_STATS = 1
HW_LIST_TYPE_CPU = 2
HW_LIST_TYPE_MEMORY = 3
HW_LIST_TYPE_BOOT = 4
HW_LIST_TYPE_DISK = 5
HW_LIST_TYPE_NIC = 6
HW_LIST_TYPE_INPUT = 7
HW_LIST_TYPE_GRAPHICS = 8
HW_LIST_TYPE_SOUND = 9
HW_LIST_TYPE_CHAR = 10
HW_LIST_TYPE_HOSTDEV = 11
2009-07-09 22:35:55 +04:00
HW_LIST_TYPE_VIDEO = 12
2010-03-24 07:22:17 +03:00
HW_LIST_TYPE_WATCHDOG = 13
2006-06-14 18:59:40 +04:00
2009-11-05 00:30:51 +03:00
remove_pages = [ HW_LIST_TYPE_NIC , HW_LIST_TYPE_INPUT ,
2009-07-09 22:35:36 +04:00
HW_LIST_TYPE_GRAPHICS , HW_LIST_TYPE_SOUND , HW_LIST_TYPE_CHAR ,
2010-03-24 07:22:17 +03:00
HW_LIST_TYPE_HOSTDEV , HW_LIST_TYPE_DISK , HW_LIST_TYPE_VIDEO ,
HW_LIST_TYPE_WATCHDOG ]
2009-07-09 22:35:36 +04:00
2010-02-25 04:37:41 +03:00
# Boot device columns
BOOT_DEV_TYPE = 0
BOOT_LABEL = 1
BOOT_ICON = 2
BOOT_ACTIVE = 3
2009-02-24 02:50:27 +03:00
# Main tab pages
2008-05-07 19:14:20 +04:00
PAGE_CONSOLE = 0
2009-02-09 22:55:18 +03:00
PAGE_DETAILS = 1
PAGE_DYNAMIC_OFFSET = 2
2008-05-07 19:14:20 +04:00
2009-12-02 05:34:29 +03:00
def prettyify_disk_bus ( bus ) :
if bus in [ " ide " , " scsi " , " usb " ] :
return bus . upper ( )
if bus in [ " xen " ] :
return bus . capitalize ( )
if bus == " virtio " :
return " VirtIO "
return bus
def prettyify_disk ( devtype , bus , idx ) :
busstr = prettyify_disk_bus ( bus ) or " "
if devtype == " floppy " :
devstr = " Floppy "
busstr = " "
elif devtype == " cdrom " :
devstr = " CDROM "
else :
devstr = devtype . capitalize ( )
if busstr :
ret = " %s %s " % ( busstr , devstr )
else :
ret = devstr
return " %s %s " % ( ret , idx )
2009-10-30 20:25:27 +03:00
2010-09-07 20:09:48 +04:00
def safeint ( val , fmt = " %.3d " ) :
try :
int ( val )
except :
return str ( val )
return fmt % int ( val )
2010-03-04 23:29:51 +03:00
def prettyify_bytes ( val ) :
if val > ( 1024 * 1024 * 1024 ) :
return " %2.2f GB " % ( val / ( 1024.0 * 1024.0 * 1024.0 ) )
2010-03-04 02:43:48 +03:00
else :
2010-03-04 23:29:51 +03:00
return " %2.2f MB " % ( val / ( 1024.0 * 1024.0 ) )
2010-03-04 02:43:48 +03:00
2010-09-07 20:09:48 +04:00
def build_hostdev_label ( hostdev ) :
# String shown in the devices details section
srclabel = " "
# String shown in the VMs hardware list
hwlabel = " "
typ = hostdev . type
vendor = hostdev . vendor
product = hostdev . product
addrbus = hostdev . bus
addrdev = hostdev . device
addrslt = hostdev . slot
addrfun = hostdev . function
addrdom = hostdev . domain
def dehex ( val ) :
if val . startswith ( " 0x " ) :
val = val [ 2 : ]
return val
hwlabel = typ . upper ( )
srclabel = typ . upper ( )
if vendor and product :
# USB by vendor + product
devstr = " %s : %s " % ( dehex ( vendor ) , dehex ( product ) )
srclabel + = devstr
hwlabel + = devstr
elif addrbus and addrdev :
# USB by bus + dev
srclabel + = ( " Bus %s Device %s " %
( safeint ( addrbus ) , safeint ( addrdev ) ) )
hwlabel + = " %s : %s " % ( safeint ( addrbus ) , safeint ( addrdev ) )
elif addrbus and addrslt and addrfun and addrdom :
# PCI by bus:slot:function
devstr = ( " %s : %s : %s . %s " %
( dehex ( addrdom ) , dehex ( addrbus ) ,
dehex ( addrslt ) , dehex ( addrfun ) ) )
srclabel + = devstr
hwlabel + = devstr
return srclabel , hwlabel
def lookup_nodedev ( vmmconn , hostdev ) :
def intify ( val , do_hex = False ) :
try :
if do_hex :
return int ( val or ' 0x00 ' , 16 )
else :
return int ( val )
except :
return - 1
def attrVal ( node , attr ) :
if not hasattr ( node , attr ) :
return None
return getattr ( node , attr )
devtype = hostdev . type
vendor_id = hostdev . vendor or - 1
product_id = hostdev . product or - 1
device = intify ( hostdev . device , True )
bus = intify ( hostdev . bus , True )
domain = intify ( hostdev . domain , True )
func = intify ( hostdev . function , True )
slot = intify ( hostdev . slot , True )
found_dev = None
# For USB we want a device, not a bus
if devtype == ' usb ' :
devtype = ' usb_device '
devs = vmmconn . get_devices ( devtype , None )
for dev in devs :
# Try to get info from {product|vendor}_id
if ( attrVal ( dev , " product_id " ) == product_id and
attrVal ( dev , " vendor_id " ) == vendor_id ) :
found_dev = dev
break
else :
# Try to get info from bus/addr
dev_id = intify ( attrVal ( dev , " device " ) )
bus_id = intify ( attrVal ( dev , " bus " ) )
dom_id = intify ( attrVal ( dev , " domain " ) )
func_id = intify ( attrVal ( dev , " function " ) )
slot_id = intify ( attrVal ( dev , " slot " ) )
if ( ( dev_id == device and bus_id == bus ) or
( dom_id == domain and func_id == func and
bus_id == bus and slot_id == slot ) ) :
found_dev = dev
break
return found_dev
2006-06-15 00:20:06 +04:00
class vmmDetails ( gobject . GObject ) :
__gsignals__ = {
" action-show-console " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , ( str , str ) ) ,
2006-07-17 21:08:58 +04:00
" action-save-domain " : ( gobject . SIGNAL_RUN_FIRST ,
2006-11-15 20:27:36 +03:00
gobject . TYPE_NONE , ( str , str ) ) ,
" action-destroy-domain " : ( gobject . SIGNAL_RUN_FIRST ,
2007-03-16 23:27:50 +03:00
gobject . TYPE_NONE , ( str , str ) ) ,
2007-11-27 19:31:30 +03:00
" action-suspend-domain " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , ( str , str ) ) ,
" action-resume-domain " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , ( str , str ) ) ,
" action-run-domain " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , ( str , str ) ) ,
" action-shutdown-domain " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , ( str , str ) ) ,
2008-04-08 22:30:47 +04:00
" action-reboot-domain " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , ( str , str ) ) ,
2007-03-16 23:27:50 +03:00
" action-show-help " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , [ str ] ) ,
2008-06-13 22:40:26 +04:00
" action-exit-app " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , [ ] ) ,
" action-view-manager " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , [ ] ) ,
2008-10-30 23:38:13 +03:00
" action-migrate-domain " : ( gobject . SIGNAL_RUN_FIRST ,
2009-11-18 21:51:36 +03:00
gobject . TYPE_NONE , ( str , str ) ) ,
2009-07-26 23:54:14 +04:00
" action-clone-domain " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , ( str , str ) ) ,
2010-02-07 20:18:28 +03:00
" details-closed " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE , ( ) ) ,
2006-06-15 00:20:06 +04:00
}
2007-07-14 22:43:20 +04:00
2010-02-07 20:18:28 +03:00
def __init__ ( self , config , vm , engine , parent = None ) :
2006-06-15 00:20:06 +04:00
self . __gobject_init__ ( )
2009-11-02 19:21:50 +03:00
self . window = gtk . glade . XML ( ( config . get_glade_dir ( ) +
" /vmm-details.glade " ) ,
" vmm-details " , domain = " virt-manager " )
2006-06-14 18:59:40 +04:00
self . config = config
self . vm = vm
2009-12-02 17:54:29 +03:00
self . conn = self . vm . get_connection ( )
2009-10-30 20:25:27 +03:00
self . engine = engine
2006-06-14 18:59:40 +04:00
2009-07-20 22:52:53 +04:00
self . topwin = self . window . get_widget ( " vmm-details " )
self . err = vmmErrorDialog ( self . topwin ,
2008-03-14 20:18:44 +03:00
0 , gtk . MESSAGE_ERROR , gtk . BUTTONS_CLOSE ,
_ ( " Unexpected Error " ) ,
_ ( " An unexpected error occurred " ) )
2006-06-14 18:59:40 +04:00
2010-02-07 20:18:28 +03:00
self . is_customize_dialog = False
if parent :
self . is_customize_dialog = True
# Details window is being abused as a 'configure before install'
# dialog, set things as appropriate
self . topwin . set_type_hint ( gtk . gdk . WINDOW_TYPE_HINT_DIALOG )
self . topwin . set_transient_for ( parent )
self . window . get_widget ( " customize-toolbar " ) . show ( )
self . window . get_widget ( " details-toolbar " ) . hide ( )
self . window . get_widget ( " details-menubar " ) . hide ( )
pages = self . window . get_widget ( " details-pages " )
pages . set_current_page ( PAGE_DETAILS )
2009-07-28 17:40:43 +04:00
self . serial_tabs = [ ]
self . last_console_page = PAGE_CONSOLE
2007-04-12 23:36:04 +04:00
self . addhw = None
2009-12-14 22:52:52 +03:00
self . media_choosers = { " cdrom " : None , " floppy " : None }
2009-03-01 03:27:20 +03:00
2009-11-02 19:21:50 +03:00
self . ignorePause = False
self . ignoreDetails = False
2006-06-14 18:59:40 +04:00
2009-10-30 20:25:27 +03:00
self . console = vmmConsolePages ( self . config , self . vm , self . engine ,
self . window )
2008-04-08 22:30:47 +04:00
2009-11-29 04:07:01 +03:00
# Set default window size
w , h = self . vm . get_details_window_size ( )
self . topwin . set_default_size ( w or 800 , h or 600 )
2010-02-12 22:01:59 +03:00
self . addhwmenu = None
2009-11-02 19:21:50 +03:00
self . init_menus ( )
self . init_details ( )
self . serial_popup = None
self . serial_copy = None
self . serial_paste = None
self . serial_close = None
self . init_serial ( )
self . cpu_usage_graph = None
self . memory_usage_graph = None
self . disk_io_graph = None
self . network_traffic_graph = None
self . init_graphs ( )
2008-04-08 22:30:47 +04:00
2006-06-14 18:59:40 +04:00
self . window . signal_autoconnect ( {
" on_close_details_clicked " : self . close ,
2006-09-01 19:18:49 +04:00
" on_details_menu_close_activate " : self . close ,
2006-06-14 18:59:40 +04:00
" on_vmm_details_delete_event " : self . close ,
2009-11-29 04:07:01 +03:00
" on_vmm_details_configure_event " : self . window_resized ,
2008-06-13 22:40:26 +04:00
" on_details_menu_quit_activate " : self . exit_app ,
2006-06-14 18:59:40 +04:00
2009-10-21 20:01:53 +04:00
" on_control_vm_details_toggled " : self . details_console_changed ,
" on_control_vm_console_toggled " : self . details_console_changed ,
2006-06-14 18:59:40 +04:00
" on_control_run_clicked " : self . control_vm_run ,
" on_control_shutdown_clicked " : self . control_vm_shutdown ,
" on_control_pause_toggled " : self . control_vm_pause ,
2008-04-08 22:30:47 +04:00
" on_control_fullscreen_toggled " : self . control_fullscreen ,
2006-06-14 18:59:40 +04:00
2010-02-07 20:18:28 +03:00
" on_details_customize_finish_clicked " : self . close ,
2006-09-01 19:18:49 +04:00
" on_details_menu_run_activate " : self . control_vm_run ,
2008-04-08 22:30:47 +04:00
" on_details_menu_poweroff_activate " : self . control_vm_shutdown ,
" on_details_menu_reboot_activate " : self . control_vm_reboot ,
2010-05-12 19:42:59 +04:00
" on_details_menu_save_activate " : self . control_vm_save ,
2006-11-15 20:27:36 +03:00
" on_details_menu_destroy_activate " : self . control_vm_destroy ,
2007-09-28 01:52:29 +04:00
" on_details_menu_pause_activate " : self . control_vm_pause ,
2009-07-26 23:54:14 +04:00
" on_details_menu_clone_activate " : self . control_vm_clone ,
2009-11-18 21:51:36 +03:00
" on_details_menu_migrate_activate " : self . control_vm_migrate ,
2008-05-07 19:40:29 +04:00
" on_details_menu_screenshot_activate " : self . control_vm_screenshot ,
2006-09-01 19:18:49 +04:00
" on_details_menu_graphics_activate " : self . control_vm_console ,
" on_details_menu_view_toolbar_activate " : self . toggle_toolbar ,
2008-06-13 22:40:26 +04:00
" on_details_menu_view_manager_activate " : self . view_manager ,
2009-10-21 20:01:53 +04:00
" on_details_menu_view_details_toggled " : self . details_console_changed ,
" on_details_menu_view_console_toggled " : self . details_console_changed ,
2006-09-01 19:18:49 +04:00
2008-05-07 19:26:00 +04:00
" on_details_pages_switch_page " : self . switch_page ,
2009-11-04 19:09:41 +03:00
" on_overview_acpi_changed " : self . config_enable_apply ,
" on_overview_apic_changed " : self . config_enable_apply ,
2009-11-04 16:46:09 +03:00
" on_overview_clock_changed " : self . config_enable_apply ,
2010-02-25 04:37:41 +03:00
" on_security_label_changed " : self . security_label_changed ,
" on_security_type_changed " : self . security_type_changed ,
" on_security_model_changed " : self . security_model_changed ,
2010-05-13 20:55:08 +04:00
" on_config_vcpus_changed " : self . config_vcpus_changed ,
2010-06-21 21:32:59 +04:00
" on_config_vcpupin_changed " : self . config_vcpus_changed ,
" on_config_vcpupin_generate_clicked " : self . config_vcpupin_generate ,
2010-02-25 04:37:41 +03:00
2006-11-13 23:31:17 +03:00
" on_config_memory_changed " : self . config_memory_changed ,
" on_config_maxmem_changed " : self . config_maxmem_changed ,
2010-02-25 04:37:41 +03:00
" on_config_boot_moveup_clicked " : ( self . config_boot_move , True ) ,
" on_config_boot_movedown_clicked " : ( self . config_boot_move ,
False ) ,
" on_config_autostart_changed " : self . config_enable_apply ,
2009-11-05 00:30:51 +03:00
" on_disk_readonly_changed " : self . config_enable_apply ,
" on_disk_shareable_changed " : self . config_enable_apply ,
2010-05-20 16:34:32 +04:00
" on_disk_cache_combo_changed " : self . config_enable_apply ,
2010-02-25 04:37:41 +03:00
2010-03-24 05:15:53 +03:00
" on_network_model_combo_changed " : self . config_enable_apply ,
" on_sound_model_combo_changed " : self . config_enable_apply ,
2009-11-05 22:59:11 +03:00
" on_video_model_combo_changed " : self . config_enable_apply ,
2009-07-09 22:35:36 +04:00
2010-03-24 07:22:17 +03:00
" on_watchdog_model_combo_changed " : self . config_enable_apply ,
" on_watchdog_action_combo_changed " : self . config_enable_apply ,
2009-07-09 22:35:36 +04:00
" on_config_apply_clicked " : self . config_apply ,
2007-03-16 23:27:50 +03:00
" on_details_help_activate " : self . show_help ,
2007-04-11 22:48:36 +04:00
2009-12-11 03:18:24 +03:00
" on_config_cdrom_connect_clicked " : self . toggle_storage_media ,
2009-07-09 22:35:36 +04:00
" on_config_remove_clicked " : self . remove_xml_dev ,
2007-04-11 22:48:36 +04:00
" on_add_hardware_button_clicked " : self . add_hardware ,
2008-04-08 22:30:47 +04:00
2010-02-12 22:01:59 +03:00
" on_hw_list_button_press_event " : self . popup_addhw_menu ,
2009-10-30 20:25:27 +03:00
# Listeners stored in vmmConsolePages
" on_details_menu_view_fullscreen_activate " : self . console . toggle_fullscreen ,
2009-11-29 04:07:01 +03:00
" on_details_menu_view_size_to_vm_activate " : self . console . size_to_vm ,
2009-10-30 20:25:27 +03:00
" on_details_menu_view_scale_always_toggled " : self . console . set_scale_type ,
" on_details_menu_view_scale_fullscreen_toggled " : self . console . set_scale_type ,
" on_details_menu_view_scale_never_toggled " : self . console . set_scale_type ,
" on_details_menu_send_cad_activate " : self . console . send_key ,
" on_details_menu_send_cab_activate " : self . console . send_key ,
" on_details_menu_send_caf1_activate " : self . console . send_key ,
" on_details_menu_send_caf2_activate " : self . console . send_key ,
" on_details_menu_send_caf3_activate " : self . console . send_key ,
" on_details_menu_send_caf4_activate " : self . console . send_key ,
" on_details_menu_send_caf5_activate " : self . console . send_key ,
" on_details_menu_send_caf6_activate " : self . console . send_key ,
" on_details_menu_send_caf7_activate " : self . console . send_key ,
" on_details_menu_send_caf8_activate " : self . console . send_key ,
" on_details_menu_send_caf9_activate " : self . console . send_key ,
" on_details_menu_send_caf10_activate " : self . console . send_key ,
" on_details_menu_send_caf11_activate " : self . console . send_key ,
" on_details_menu_send_caf12_activate " : self . console . send_key ,
" on_details_menu_send_printscreen_activate " : self . console . send_key ,
" on_console_auth_password_activate " : self . console . auth_login ,
" on_console_auth_login_clicked " : self . console . auth_login ,
} )
2006-06-14 18:59:40 +04:00
2009-11-02 19:21:50 +03:00
# Deliberately keep all this after signal connection
2010-11-30 19:49:47 +03:00
self . vm . connect ( " status-changed " , self . refresh_vm_state )
self . vm . connect ( " config-changed " , self . refresh_vm_state )
2006-06-15 02:42:04 +04:00
self . vm . connect ( " resources-sampled " , self . refresh_resources )
2010-02-25 04:37:41 +03:00
self . window . get_widget ( " hw-list " ) . get_selection ( ) . connect (
" changed " ,
self . hw_selected )
self . window . get_widget ( " config-boot-list " ) . get_selection ( ) . connect (
" changed " ,
self . config_bootdev_selected )
2007-04-11 22:48:36 +04:00
2009-11-17 23:06:15 +03:00
finish_img = gtk . image_new_from_stock ( gtk . STOCK_ADD ,
gtk . ICON_SIZE_BUTTON )
self . window . get_widget ( " add-hardware-button " ) . set_image ( finish_img )
2006-06-14 18:59:40 +04:00
2009-11-04 21:18:14 +03:00
self . populate_hw_list ( )
self . repopulate_boot_list ( )
2010-02-10 19:54:12 +03:00
self . hw_selected ( )
2010-11-30 19:49:47 +03:00
self . refresh_vm_state ( )
2006-08-29 23:52:19 +04:00
2008-04-08 22:30:47 +04:00
2009-11-04 21:18:14 +03:00
def show ( self ) :
if self . is_visible ( ) :
self . topwin . present ( )
return
self . topwin . present ( )
self . engine . increment_window_counter ( )
2010-11-30 19:49:47 +03:00
self . refresh_vm_state ( )
2009-11-04 21:18:14 +03:00
2010-02-07 20:18:28 +03:00
def close ( self , ignore1 = None , ignore2 = None ) :
2009-11-04 21:18:14 +03:00
fs = self . window . get_widget ( " details-menu-view-fullscreen " )
if fs . get_active ( ) :
fs . set_active ( False )
if not self . is_visible ( ) :
return
self . topwin . hide ( )
if self . console . vncViewer . flags ( ) & gtk . VISIBLE :
try :
self . console . vncViewer . close ( )
except :
logging . error ( " Failure when disconnecting from VNC server " )
self . engine . decrement_window_counter ( )
2010-02-07 20:18:28 +03:00
self . emit ( " details-closed " )
2009-11-04 21:18:14 +03:00
return 1
def is_visible ( self ) :
if self . topwin . flags ( ) & gtk . VISIBLE :
return 1
return 0
2009-11-02 19:21:50 +03:00
##########################
# Initialization helpers #
##########################
def init_menus ( self ) :
# Shutdown button menu
2009-11-29 04:49:44 +03:00
uihelpers . build_shutdown_button_menu (
self . config ,
2009-11-02 19:21:50 +03:00
self . window . get_widget ( " control-shutdown " ) ,
self . control_vm_shutdown ,
self . control_vm_reboot ,
2010-05-12 19:42:59 +04:00
self . control_vm_destroy ,
self . control_vm_save )
2009-11-02 19:21:50 +03:00
2009-11-18 01:47:34 +03:00
icon_name = self . config . get_shutdown_icon_name ( )
for name in [ " details-menu-shutdown " ,
" details-menu-reboot " ,
" details-menu-poweroff " ,
" details-menu-destroy " ] :
image = gtk . image_new_from_icon_name ( icon_name , gtk . ICON_SIZE_MENU )
self . window . get_widget ( name ) . set_image ( image )
2010-02-12 22:01:59 +03:00
# Add HW popup menu
self . addhwmenu = gtk . Menu ( )
addHW = gtk . ImageMenuItem ( _ ( " Add Hardware " ) )
addHWImg = gtk . Image ( )
addHWImg . set_from_stock ( gtk . STOCK_ADD , gtk . ICON_SIZE_MENU )
addHW . set_image ( addHWImg )
addHW . show ( )
addHW . connect ( " activate " , self . add_hardware )
self . addhwmenu . add ( addHW )
2009-11-02 19:21:50 +03:00
# Serial list menu
smenu = gtk . Menu ( )
smenu . connect ( " show " , self . populate_serial_menu )
self . window . get_widget ( " details-menu-view-serial-list " ) . set_submenu ( smenu )
# Don't allowing changing network/disks for Dom0
dom0 = self . vm . is_management_domain ( )
self . window . get_widget ( " add-hardware-button " ) . set_sensitive ( not dom0 )
self . window . get_widget ( " hw-panel " ) . set_show_tabs ( False )
self . window . get_widget ( " details-pages " ) . set_show_tabs ( False )
self . window . get_widget ( " console-pages " ) . set_show_tabs ( False )
self . window . get_widget ( " details-menu-view-toolbar " ) . set_active ( self . config . get_details_show_toolbar ( ) )
# XXX: Help docs useless/out of date
self . window . get_widget ( " help_menuitem " ) . hide ( )
def init_serial ( self ) :
self . serial_popup = gtk . Menu ( )
self . serial_copy = gtk . ImageMenuItem ( gtk . STOCK_COPY )
self . serial_popup . add ( self . serial_copy )
self . serial_paste = gtk . ImageMenuItem ( gtk . STOCK_PASTE )
self . serial_popup . add ( self . serial_paste )
self . serial_popup . add ( gtk . SeparatorMenuItem ( ) )
self . serial_close = gtk . ImageMenuItem ( _ ( " Close tab " ) )
close_image = gtk . Image ( )
close_image . set_from_stock ( gtk . STOCK_CLOSE , gtk . ICON_SIZE_MENU )
self . serial_close . set_image ( close_image )
self . serial_popup . add ( self . serial_close )
def init_graphs ( self ) :
graph_table = self . window . get_widget ( " graph-table " )
self . cpu_usage_graph = Sparkline ( )
self . cpu_usage_graph . set_property ( " reversed " , True )
graph_table . attach ( self . cpu_usage_graph , 1 , 2 , 0 , 1 )
self . memory_usage_graph = Sparkline ( )
self . memory_usage_graph . set_property ( " reversed " , True )
graph_table . attach ( self . memory_usage_graph , 1 , 2 , 1 , 2 )
self . disk_io_graph = Sparkline ( )
self . disk_io_graph . set_property ( " reversed " , True )
self . disk_io_graph . set_property ( " filled " , False )
self . disk_io_graph . set_property ( " num_sets " , 2 )
self . disk_io_graph . set_property ( " rgb " , map ( lambda x : x / 255.0 ,
[ 0x82 , 0x00 , 0x3B , 0x29 , 0x5C , 0x45 ] ) )
graph_table . attach ( self . disk_io_graph , 1 , 2 , 2 , 3 )
self . network_traffic_graph = Sparkline ( )
self . network_traffic_graph . set_property ( " reversed " , True )
self . network_traffic_graph . set_property ( " filled " , False )
self . network_traffic_graph . set_property ( " num_sets " , 2 )
self . network_traffic_graph . set_property ( " rgb " ,
map ( lambda x : x / 255.0 ,
[ 0x82 , 0x00 , 0x3B ,
0x29 , 0x5C , 0x45 ] ) )
graph_table . attach ( self . network_traffic_graph , 1 , 2 , 3 , 4 )
2010-06-21 21:47:07 +04:00
graph_table . show_all ( )
2009-11-02 19:21:50 +03:00
def init_details ( self ) :
2009-11-04 21:18:14 +03:00
# Hardware list
2010-09-08 02:38:01 +04:00
# [ label, icon name, icon size, hw type, hw data/class]
2009-11-04 21:18:14 +03:00
hw_list_model = gtk . ListStore ( str , str , int , int ,
2010-09-08 02:38:01 +04:00
gobject . TYPE_PYOBJECT )
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " hw-list " ) . set_model ( hw_list_model )
hwCol = gtk . TreeViewColumn ( " Hardware " )
hwCol . set_spacing ( 6 )
hwCol . set_min_width ( 165 )
hw_txt = gtk . CellRendererText ( )
hw_img = gtk . CellRendererPixbuf ( )
hwCol . pack_start ( hw_img , False )
hwCol . pack_start ( hw_txt , True )
hwCol . add_attribute ( hw_txt , ' text ' , HW_LIST_COL_LABEL )
hwCol . add_attribute ( hw_img , ' stock-size ' , HW_LIST_COL_ICON_SIZE )
hwCol . add_attribute ( hw_img , ' icon-name ' , HW_LIST_COL_ICON_NAME )
self . window . get_widget ( " hw-list " ) . append_column ( hwCol )
2010-02-10 20:16:59 +03:00
# Description text view
desc = self . window . get_widget ( " overview-description " )
buf = gtk . TextBuffer ( )
buf . connect ( " changed " , self . config_enable_apply )
desc . set_buffer ( buf )
2009-11-04 21:16:38 +03:00
# Clock combo
clock_combo = self . window . get_widget ( " overview-clock-combo " )
clock_model = gtk . ListStore ( str )
clock_combo . set_model ( clock_model )
text = gtk . CellRendererText ( )
clock_combo . pack_start ( text , True )
clock_combo . add_attribute ( text , ' text ' , 0 )
clock_model . set_sort_column_id ( 0 , gtk . SORT_ASCENDING )
for offset in [ " localtime " , " utc " ] :
clock_model . append ( [ offset ] )
2009-11-02 19:21:50 +03:00
# Security info tooltips
util . tooltip_wrapper ( self . window . get_widget ( " security-static-info " ) ,
2010-04-05 20:21:03 +04:00
_ ( " Static SELinux security type tells libvirt to always start the guest process with the specified label. The administrator is responsible for making sure the images are labeled correctly on disk. " ) )
2009-11-02 19:21:50 +03:00
util . tooltip_wrapper ( self . window . get_widget ( " security-dynamic-info " ) ,
_ ( " The dynamic SELinux security type tells libvirt to automatically pick a unique label for the guest process and guest image, ensuring total isolation of the guest. (Default) " ) )
2009-11-16 19:36:13 +03:00
# VCPU Pinning list
2010-06-21 21:32:59 +04:00
generate_cpuset = self . window . get_widget ( " config-vcpupin-generate " )
generate_warn = self . window . get_widget ( " config-vcpupin-generate-err " )
if not self . conn . get_capabilities ( ) . host . topology :
generate_cpuset . set_sensitive ( False )
generate_warn . show ( )
util . tooltip_wrapper ( generate_warn ,
_ ( " Libvirt did not detect NUMA capabilities. " ) )
2009-11-16 19:36:13 +03:00
# [ VCPU #, Currently running on Phys CPU #, CPU Pinning list ]
vcpu_list = self . window . get_widget ( " config-vcpu-list " )
vcpu_model = gtk . ListStore ( str , str , str )
vcpu_list . set_model ( vcpu_model )
vcpuCol = gtk . TreeViewColumn ( _ ( " VCPU " ) )
physCol = gtk . TreeViewColumn ( _ ( " On CPU " ) )
pinCol = gtk . TreeViewColumn ( _ ( " Pinning " ) )
vcpu_list . append_column ( vcpuCol )
vcpu_list . append_column ( physCol )
vcpu_list . append_column ( pinCol )
vcpu_text = gtk . CellRendererText ( )
vcpuCol . pack_start ( vcpu_text , True )
vcpuCol . add_attribute ( vcpu_text , ' text ' , 0 )
vcpuCol . set_sort_column_id ( 0 )
phys_text = gtk . CellRendererText ( )
physCol . pack_start ( phys_text , True )
physCol . add_attribute ( phys_text , ' text ' , 1 )
physCol . set_sort_column_id ( 1 )
pin_text = gtk . CellRendererText ( )
pin_text . set_property ( " editable " , True )
pin_text . connect ( " edited " , self . config_vcpu_pin )
pinCol . pack_start ( pin_text , True )
pinCol . add_attribute ( pin_text , ' text ' , 2 )
2009-11-04 21:18:14 +03:00
# Boot device list
2010-02-25 04:37:41 +03:00
boot_list = self . window . get_widget ( " config-boot-list " )
# model = [ XML boot type, display name, icon name, enabled ]
boot_list_model = gtk . ListStore ( str , str , str , bool )
2009-11-04 21:18:14 +03:00
boot_list . set_model ( boot_list_model )
2009-11-02 19:21:50 +03:00
2010-02-25 04:37:41 +03:00
chkCol = gtk . TreeViewColumn ( )
txtCol = gtk . TreeViewColumn ( )
boot_list . append_column ( chkCol )
boot_list . append_column ( txtCol )
chk = gtk . CellRendererToggle ( )
chk . connect ( " toggled " , self . config_boot_toggled )
chkCol . pack_start ( chk , False )
chkCol . add_attribute ( chk , ' active ' , BOOT_ACTIVE )
2009-11-04 21:18:14 +03:00
icon = gtk . CellRendererPixbuf ( )
2010-02-25 04:37:41 +03:00
txtCol . pack_start ( icon , False )
txtCol . add_attribute ( icon , ' icon-name ' , BOOT_ICON )
2009-11-04 21:18:14 +03:00
text = gtk . CellRendererText ( )
2010-02-25 04:37:41 +03:00
txtCol . pack_start ( text , True )
txtCol . add_attribute ( text , ' text ' , BOOT_LABEL )
txtCol . add_attribute ( text , ' sensitive ' , BOOT_ACTIVE )
2008-04-08 22:30:47 +04:00
2010-11-29 22:06:43 +03:00
no_default = not self . is_customize_dialog
2010-05-20 16:34:32 +04:00
# Disk cache combo
disk_cache = self . window . get_widget ( " disk-cache-combo " )
uihelpers . build_cache_combo ( self . vm , disk_cache )
2010-03-24 05:15:53 +03:00
# Network model
net_model = self . window . get_widget ( " network-model-combo " )
uihelpers . build_netmodel_combo ( self . vm , net_model )
# Sound model
sound_dev = self . window . get_widget ( " sound-model-combo " )
uihelpers . build_sound_combo ( self . vm , sound_dev , no_default = no_default )
2009-11-05 22:59:11 +03:00
# Video model combo
video_dev = self . window . get_widget ( " video-model-combo " )
2010-03-24 05:15:53 +03:00
uihelpers . build_video_combo ( self . vm , video_dev , no_default = no_default )
2010-03-24 07:22:17 +03:00
# Watchdog model combo
combo = self . window . get_widget ( " watchdog-model-combo " )
uihelpers . build_watchdogmodel_combo ( self . vm , combo ,
no_default = no_default )
# Watchdog action combo
combo = self . window . get_widget ( " watchdog-action-combo " )
uihelpers . build_watchdogaction_combo ( self . vm , combo ,
no_default = no_default )
2010-03-24 05:15:53 +03:00
# Helper function to handle the combo/label pattern used for
# video model, sound model, network model, etc.
def set_combo_label ( self , prefix , model_idx , value ) :
model_label = self . window . get_widget ( prefix + " -label " )
model_combo = self . window . get_widget ( prefix + " -combo " )
model_list = map ( lambda x : x [ model_idx ] , model_combo . get_model ( ) )
model_in_list = ( value in model_list )
model_label . set_property ( " visible " , not model_in_list )
model_combo . set_property ( " visible " , model_in_list )
model_label . set_text ( value or " " )
if model_in_list :
model_combo . set_active ( model_list . index ( value ) )
2009-11-04 21:18:14 +03:00
##########################
# Window state listeners #
##########################
2006-09-01 19:18:49 +04:00
2009-11-29 04:07:01 +03:00
def window_resized ( self , ignore , event ) :
# Sometimes dimensions change when window isn't visible
if not self . is_visible ( ) :
return
self . vm . set_details_window_size ( event . width , event . height )
2010-02-12 22:01:59 +03:00
def popup_addhw_menu ( self , widget , event ) :
if event . button != 3 :
return
self . addhwmenu . popup ( None , None , None , 0 , event . time )
2008-10-03 00:17:25 +04:00
def populate_serial_menu ( self , src ) :
for ent in src :
src . remove ( ent )
devs = self . vm . get_serial_devs ( )
if len ( devs ) == 0 :
2010-09-04 01:56:40 +04:00
item = gtk . MenuItem ( _ ( " No text console available " ) )
2008-10-03 00:17:25 +04:00
item . set_sensitive ( False )
src . add ( item )
2009-07-28 17:40:43 +04:00
on_serial = ( self . last_console_page > = PAGE_DYNAMIC_OFFSET )
serial_page_dev = None
if on_serial :
serial_idx = self . last_console_page - PAGE_DYNAMIC_OFFSET
if len ( self . serial_tabs ) > = serial_idx :
serial_page_dev = self . serial_tabs [ serial_idx ]
on_graphics = ( self . last_console_page == PAGE_CONSOLE )
group = None
2008-10-03 00:17:25 +04:00
usable_types = [ " pty " ]
for dev in devs :
sensitive = False
msg = " "
2009-07-28 17:40:43 +04:00
item = gtk . RadioMenuItem ( group , dev [ 0 ] )
if group == None :
group = item
2008-10-03 00:17:25 +04:00
if self . vm . get_connection ( ) . is_remote ( ) :
msg = _ ( " Serial console not yet supported over remote "
" connection. " )
elif not self . vm . is_active ( ) :
msg = _ ( " Serial console not available for inactive guest. " )
elif not dev [ 1 ] in usable_types :
msg = _ ( " Console for device type ' %s ' not yet supported. " ) % \
dev [ 1 ]
elif dev [ 2 ] and not os . access ( dev [ 2 ] , os . R_OK | os . W_OK ) :
msg = _ ( " Can not access console path ' %s ' . " ) % str ( dev [ 2 ] )
else :
sensitive = True
if not sensitive :
2009-01-26 19:12:43 +03:00
util . tooltip_wrapper ( item , msg )
2008-10-03 00:17:25 +04:00
item . set_sensitive ( sensitive )
2009-07-28 17:40:43 +04:00
if sensitive and on_serial and serial_page_dev == dev [ 0 ] :
2008-10-03 00:17:25 +04:00
# Tab is already open, make sure marked as such
item . set_active ( True )
2009-07-28 17:40:43 +04:00
item . connect ( " toggled " , self . control_serial_tab , dev [ 0 ] , dev [ 3 ] )
src . add ( item )
src . add ( gtk . SeparatorMenuItem ( ) )
devs = self . vm . get_graphics_devices ( )
if len ( devs ) == 0 :
2010-09-04 01:56:40 +04:00
item = gtk . MenuItem ( _ ( " No graphical console available " ) )
2009-07-28 17:40:43 +04:00
item . set_sensitive ( False )
src . add ( item )
else :
dev = devs [ 0 ]
2010-09-04 01:56:40 +04:00
item = gtk . RadioMenuItem ( group , _ ( " Graphical Console %s " ) %
dev . type . upper ( ) )
2009-07-28 17:40:43 +04:00
if group == None :
group = item
if on_graphics :
item . set_active ( True )
2010-09-04 01:56:40 +04:00
item . connect ( " toggled " , self . control_serial_tab ,
dev . virtual_device_type , dev . type )
2008-10-03 00:17:25 +04:00
src . add ( item )
src . show_all ( )
2009-11-04 21:18:14 +03:00
def control_fullscreen ( self , src ) :
menu = self . window . get_widget ( " details-menu-view-fullscreen " )
if src . get_active ( ) != menu . get_active ( ) :
menu . set_active ( src . get_active ( ) )
2008-06-13 22:40:26 +04:00
2009-11-04 21:18:14 +03:00
def toggle_toolbar ( self , src ) :
active = src . get_active ( )
self . config . set_details_show_toolbar ( active )
if active and not \
self . window . get_widget ( " details-menu-view-fullscreen " ) . get_active ( ) :
self . window . get_widget ( " toolbar-box " ) . show ( )
else :
self . window . get_widget ( " toolbar-box " ) . hide ( )
2006-11-03 18:02:02 +03:00
2010-02-25 04:37:41 +03:00
def get_boot_selection ( self ) :
widget = self . window . get_widget ( " config-boot-list " )
selection = widget . get_selection ( )
model , treepath = selection . get_selected ( )
if treepath == None :
return None
return model [ treepath ]
2010-11-24 22:19:44 +03:00
def set_hw_selection ( self , page ) :
hwlist = self . window . get_widget ( " hw-list " )
selection = hwlist . get_selection ( )
selection . select_path ( str ( page ) )
2009-11-04 21:18:14 +03:00
def get_hw_selection ( self , field ) :
vmlist = self . window . get_widget ( " hw-list " )
selection = vmlist . get_selection ( )
active = selection . get_selected ( )
if active [ 1 ] == None :
return None
2010-11-24 22:19:44 +03:00
return active [ 0 ] . get_value ( active [ 1 ] , field )
2008-06-13 22:40:26 +04:00
2010-02-10 19:54:12 +03:00
def force_get_hw_pagetype ( self , page = None ) :
if page :
return page
2009-07-09 22:35:44 +04:00
2010-02-10 19:54:12 +03:00
page = self . get_hw_selection ( HW_LIST_COL_TYPE )
if page is None :
page = HW_LIST_TYPE_GENERAL
2009-03-01 03:27:20 +03:00
self . window . get_widget ( " hw-list " ) . get_selection ( ) . select_path ( 0 )
2010-02-10 19:54:12 +03:00
return page
def hw_selected ( self , src = None , page = None , selected = True ) :
pagetype = self . force_get_hw_pagetype ( page )
2009-07-29 05:24:02 +04:00
self . window . get_widget ( " config-remove " ) . set_sensitive ( True )
2009-03-01 03:27:20 +03:00
self . window . get_widget ( " hw-panel " ) . set_sensitive ( True )
2010-06-21 21:32:59 +04:00
self . window . get_widget ( " hw-panel " ) . show ( )
2007-04-12 23:36:04 +04:00
2010-03-04 02:47:59 +03:00
try :
if pagetype == HW_LIST_TYPE_GENERAL :
self . refresh_overview_page ( )
elif pagetype == HW_LIST_TYPE_STATS :
self . refresh_stats_page ( )
elif pagetype == HW_LIST_TYPE_CPU :
self . refresh_config_cpu ( )
elif pagetype == HW_LIST_TYPE_MEMORY :
self . refresh_config_memory ( )
elif pagetype == HW_LIST_TYPE_BOOT :
self . refresh_boot_page ( )
elif pagetype == HW_LIST_TYPE_DISK :
self . refresh_disk_page ( )
elif pagetype == HW_LIST_TYPE_NIC :
self . refresh_network_page ( )
elif pagetype == HW_LIST_TYPE_INPUT :
self . refresh_input_page ( )
elif pagetype == HW_LIST_TYPE_GRAPHICS :
self . refresh_graphics_page ( )
elif pagetype == HW_LIST_TYPE_SOUND :
self . refresh_sound_page ( )
elif pagetype == HW_LIST_TYPE_CHAR :
self . refresh_char_page ( )
elif pagetype == HW_LIST_TYPE_HOSTDEV :
self . refresh_hostdev_page ( )
elif pagetype == HW_LIST_TYPE_VIDEO :
self . refresh_video_page ( )
2010-03-24 07:22:17 +03:00
elif pagetype == HW_LIST_TYPE_WATCHDOG :
self . refresh_watchdog_page ( )
2010-03-04 02:47:59 +03:00
else :
pagetype = - 1
except Exception , e :
self . err . show_err ( _ ( " Error refreshing hardware page: %s " ) % str ( e ) ,
" " . join ( traceback . format_exc ( ) ) )
return
2009-03-01 03:27:20 +03:00
2009-07-09 22:35:44 +04:00
rem = pagetype in remove_pages
if selected :
self . window . get_widget ( " config-apply " ) . set_sensitive ( False )
self . window . get_widget ( " config-remove " ) . set_property ( " visible " , rem )
2009-07-09 22:35:36 +04:00
2009-03-01 03:27:20 +03:00
self . window . get_widget ( " hw-panel " ) . set_current_page ( pagetype )
2006-06-14 18:59:40 +04:00
2009-10-21 20:01:53 +04:00
def details_console_changed ( self , src ) :
if self . ignoreDetails :
2009-07-28 17:40:43 +04:00
return
2009-10-21 20:01:53 +04:00
if not src . get_active ( ) :
2009-07-28 17:40:43 +04:00
return
2009-10-21 20:01:53 +04:00
is_details = False
if ( src == self . window . get_widget ( " control-vm-details " ) or
src == self . window . get_widget ( " details-menu-view-details " ) ) :
is_details = True
pages = self . window . get_widget ( " details-pages " )
if is_details :
2009-07-28 17:40:43 +04:00
pages . set_current_page ( PAGE_DETAILS )
2009-10-21 20:01:53 +04:00
else :
2009-07-28 17:40:43 +04:00
pages . set_current_page ( self . last_console_page )
2009-10-21 20:01:53 +04:00
def sync_details_console_view ( self , is_details ) :
details = self . window . get_widget ( " control-vm-details " )
details_menu = self . window . get_widget ( " details-menu-view-details " )
console = self . window . get_widget ( " control-vm-console " )
console_menu = self . window . get_widget ( " details-menu-view-console " )
try :
self . ignoreDetails = True
details . set_active ( is_details )
details_menu . set_active ( is_details )
console . set_active ( not is_details )
console_menu . set_active ( not is_details )
finally :
self . ignoreDetails = False
2009-11-04 21:18:14 +03:00
def switch_page ( self , ignore1 = None , ignore2 = None , newpage = None ) :
self . page_refresh ( newpage )
self . sync_details_console_view ( newpage == PAGE_DETAILS )
if newpage == PAGE_CONSOLE or newpage > = PAGE_DYNAMIC_OFFSET :
self . last_console_page = newpage
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 ( " _ " , " " )
self . window . get_widget ( " details-menu-run " ) . get_child ( ) . set_label ( text )
self . window . get_widget ( " control-run " ) . set_label ( strip_text )
2010-11-30 19:49:47 +03:00
def refresh_vm_state ( self , ignore1 = None , ignore2 = None , ignore3 = None ) :
vm = self . vm
status = self . vm . status ( )
self . toggle_toolbar (
self . window . get_widget ( " details-menu-view-toolbar " ) )
2009-11-04 21:18:14 +03:00
destroy = vm . is_destroyable ( )
run = vm . is_runable ( )
stop = vm . is_stoppable ( )
paused = vm . is_paused ( )
ro = vm . is_read_only ( )
2010-05-12 20:57:32 +04:00
if vm . managedsave_supported :
self . change_run_text ( vm . hasSavedImage ( ) )
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " details-menu-destroy " ) . set_sensitive ( destroy )
self . window . get_widget ( " control-run " ) . set_sensitive ( run )
self . window . get_widget ( " details-menu-run " ) . set_sensitive ( run )
2009-11-15 23:29:42 +03:00
self . window . get_widget ( " details-menu-migrate " ) . set_sensitive ( stop )
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " control-shutdown " ) . set_sensitive ( stop )
self . window . get_widget ( " details-menu-shutdown " ) . set_sensitive ( stop )
self . window . get_widget ( " details-menu-save " ) . set_sensitive ( stop )
self . window . get_widget ( " control-pause " ) . set_sensitive ( stop )
self . window . get_widget ( " details-menu-pause " ) . set_sensitive ( stop )
# Set pause widget states
try :
self . ignorePause = True
self . window . get_widget ( " control-pause " ) . set_active ( paused )
self . window . get_widget ( " details-menu-pause " ) . set_active ( paused )
finally :
self . ignorePause = False
self . window . get_widget ( " config-vcpus " ) . set_sensitive ( not ro )
self . window . get_widget ( " config-vcpupin " ) . set_sensitive ( not ro )
self . window . get_widget ( " config-memory " ) . set_sensitive ( not ro )
self . window . get_widget ( " config-maxmem " ) . set_sensitive ( not ro )
2009-11-29 04:13:55 +03:00
# Disable send key menu entries for offline VM
send_key = self . window . get_widget ( " details-menu-send-key " )
for c in send_key . get_submenu ( ) . get_children ( ) :
c . set_sensitive ( not ( run or paused ) )
2009-11-04 21:18:14 +03:00
self . console . update_widget_states ( vm , status )
2010-11-30 19:49:47 +03:00
self . window . get_widget ( " overview-status-text " ) . set_text (
self . vm . run_status ( ) )
self . window . get_widget ( " overview-status-icon " ) . set_from_pixbuf (
self . vm . run_status_icon ( ) )
details = self . window . get_widget ( " details-pages " )
self . page_refresh ( details . get_current_page ( ) )
2009-11-04 21:18:14 +03:00
#############################
# External action listeners #
#############################
def show_help ( self , src ) :
self . emit ( " action-show-help " , " virt-manager-details-window " )
def view_manager ( self , src ) :
self . emit ( " action-view-manager " )
def exit_app ( self , src ) :
self . emit ( " action-exit-app " )
def activate_console_page ( self ) :
self . window . get_widget ( " details-pages " ) . set_current_page ( PAGE_CONSOLE )
def activate_performance_page ( self ) :
self . window . get_widget ( " details-pages " ) . set_current_page ( PAGE_DETAILS )
2010-11-24 22:19:44 +03:00
self . set_hw_selection ( HW_LIST_TYPE_STATS )
2009-11-04 21:18:14 +03:00
def activate_config_page ( self ) :
self . window . get_widget ( " details-pages " ) . set_current_page ( PAGE_DETAILS )
def add_hardware ( self , src ) :
if self . addhw is None :
self . addhw = vmmAddHardware ( self . config , self . vm )
self . addhw . show ( )
def remove_xml_dev ( self , src ) :
info = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not info :
return
2010-09-08 02:38:01 +04:00
devtype = info . virtual_device_type
self . remove_device ( devtype , info )
2009-11-04 21:18:14 +03:00
2006-06-14 18:59:40 +04:00
def control_vm_pause ( self , src ) :
2006-06-15 02:42:04 +04:00
if self . ignorePause :
return
2007-11-27 19:31:30 +03:00
if src . get_active ( ) :
self . emit ( " action-suspend-domain " , self . vm . get_connection ( ) . get_uri ( ) , self . vm . get_uuid ( ) )
2006-06-14 18:59:40 +04:00
else :
2007-11-27 19:31:30 +03:00
self . emit ( " action-resume-domain " , self . vm . get_connection ( ) . get_uri ( ) , self . vm . get_uuid ( ) )
def control_vm_run ( self , src ) :
self . emit ( " action-run-domain " , self . vm . get_connection ( ) . get_uri ( ) , self . vm . get_uuid ( ) )
2006-06-14 18:59:40 +04:00
2007-11-27 19:31:30 +03:00
def control_vm_shutdown ( self , src ) :
2009-11-04 21:18:14 +03:00
self . emit ( " action-shutdown-domain " , self . vm . get_connection ( ) . get_uri ( ) , self . vm . get_uuid ( ) )
2006-09-01 19:18:49 +04:00
2008-04-08 22:30:47 +04:00
def control_vm_reboot ( self , src ) :
2009-11-04 21:18:14 +03:00
self . emit ( " action-reboot-domain " , self . vm . get_connection ( ) . get_uri ( ) , self . vm . get_uuid ( ) )
2008-04-08 22:30:47 +04:00
2006-06-15 02:51:58 +04:00
def control_vm_console ( self , src ) :
self . emit ( " action-show-console " , self . vm . get_connection ( ) . get_uri ( ) , self . vm . get_uuid ( ) )
2010-05-12 19:42:59 +04:00
def control_vm_save ( self , src ) :
2006-07-17 21:08:58 +04:00
self . emit ( " action-save-domain " , self . vm . get_connection ( ) . get_uri ( ) , self . vm . get_uuid ( ) )
2006-06-14 18:59:40 +04:00
2006-11-15 20:27:36 +03:00
def control_vm_destroy ( self , src ) :
self . emit ( " action-destroy-domain " , self . vm . get_connection ( ) . get_uri ( ) , self . vm . get_uuid ( ) )
2009-07-26 23:54:14 +04:00
def control_vm_clone ( self , src ) :
self . emit ( " action-clone-domain " , self . vm . get_connection ( ) . get_uri ( ) ,
self . vm . get_uuid ( ) )
2009-11-18 21:51:36 +03:00
def control_vm_migrate ( self , src ) :
2009-03-09 23:21:53 +03:00
self . emit ( " action-migrate-domain " , self . vm . get_connection ( ) . get_uri ( ) ,
2009-11-18 21:51:36 +03:00
self . vm . get_uuid ( ) )
2008-10-30 23:38:13 +03:00
2009-10-30 20:25:27 +03:00
def control_vm_screenshot ( self , src ) :
# If someone feels kind they could extend this code to allow
# user to choose what image format they'd like to save in....
path = util . browse_local ( self . topwin ,
_ ( " Save Virtual Machine Screenshot " ) ,
self . config , self . vm . get_connection ( ) ,
_type = ( " png " , " PNG files " ) ,
dialog_type = gtk . FILE_CHOOSER_ACTION_SAVE ,
browse_reason = self . config . CONFIG_DIR_SCREENSHOT )
if not path :
return
filename = path
if not ( filename . endswith ( " .png " ) ) :
filename + = " .png "
image = self . console . vncViewer . get_pixbuf ( )
# Save along with a little metadata about us & the domain
image . save ( filename , ' png ' ,
{ ' tEXt::Hypervisor URI ' : self . vm . get_connection ( ) . get_uri ( ) ,
' tEXt::Domain Name ' : self . vm . get_name ( ) ,
' tEXt::Domain UUID ' : self . vm . get_uuid ( ) ,
' tEXt::Generator App ' : self . config . get_appname ( ) ,
' tEXt::Generator Version ' : self . config . get_appversion ( ) } )
msg = gtk . MessageDialog ( self . topwin ,
gtk . DIALOG_MODAL ,
gtk . MESSAGE_INFO ,
gtk . BUTTONS_OK ,
( _ ( " The screenshot has been saved to: \n %s " ) %
filename ) )
msg . set_title ( _ ( " Screenshot saved " ) )
msg . run ( )
msg . destroy ( )
2008-08-19 22:25:25 +04:00
2009-11-04 21:18:14 +03:00
# ------------------------------
# Serial Console pieces
# ------------------------------
2008-07-25 00:39:09 +04:00
2009-11-04 21:18:14 +03:00
def control_serial_tab ( self , src , name , target_port ) :
is_graphics = ( name == " graphics " )
is_serial = not is_graphics
2009-10-21 18:09:09 +04:00
2009-11-04 21:18:14 +03:00
if is_graphics :
self . window . get_widget ( " details-pages " ) . set_current_page ( PAGE_CONSOLE )
elif is_serial :
self . _show_serial_tab ( name , target_port )
2009-10-21 18:09:09 +04:00
2009-11-04 21:18:14 +03:00
def show_serial_rcpopup ( self , src , event ) :
if event . button != 3 :
return
2009-10-21 18:09:09 +04:00
2009-11-04 21:18:14 +03:00
self . serial_popup . show_all ( )
self . serial_copy . connect ( " activate " , self . serial_copy_text , src )
self . serial_paste . connect ( " activate " , self . serial_paste_text , src )
self . serial_close . connect ( " activate " , self . serial_close_tab ,
self . window . get_widget ( " details-pages " ) . get_current_page ( ) )
2008-08-19 22:25:25 +04:00
2009-11-04 21:18:14 +03:00
if src . get_has_selection ( ) :
self . serial_copy . set_sensitive ( True )
else :
self . serial_copy . set_sensitive ( False )
self . serial_popup . popup ( None , None , None , 0 , event . time )
2008-10-30 23:38:13 +03:00
2009-11-04 21:18:14 +03:00
def serial_close_tab ( self , src , pagenum ) :
tab_idx = ( pagenum - PAGE_DYNAMIC_OFFSET )
if ( tab_idx < 0 ) or ( tab_idx > len ( self . serial_tabs ) - 1 ) :
return
return self . _close_serial_tab ( self . serial_tabs [ tab_idx ] )
2006-06-14 18:59:40 +04:00
2009-11-04 21:18:14 +03:00
def serial_copy_text ( self , src , terminal ) :
terminal . copy_clipboard ( )
2006-06-14 18:59:40 +04:00
2009-11-04 21:18:14 +03:00
def serial_paste_text ( self , src , terminal ) :
terminal . paste_clipboard ( )
2008-05-07 19:26:00 +04:00
2009-11-04 21:18:14 +03:00
def _show_serial_tab ( self , name , target_port ) :
if not self . serial_tabs . count ( name ) :
child = vmmSerialConsole ( self . vm , target_port )
child . terminal . connect ( " button-press-event " ,
self . show_serial_rcpopup )
title = gtk . Label ( name )
child . show_all ( )
self . window . get_widget ( " details-pages " ) . append_page ( child , title )
self . serial_tabs . append ( name )
2009-07-28 17:40:43 +04:00
2009-11-04 21:18:14 +03:00
page_idx = self . serial_tabs . index ( name ) + PAGE_DYNAMIC_OFFSET
self . window . get_widget ( " details-pages " ) . set_current_page ( page_idx )
2009-07-28 17:40:43 +04:00
2009-11-04 21:18:14 +03:00
def _close_serial_tab ( self , name ) :
if not self . serial_tabs . count ( name ) :
return
2009-03-01 03:27:20 +03:00
2009-11-04 21:18:14 +03:00
page_idx = self . serial_tabs . index ( name ) + PAGE_DYNAMIC_OFFSET
self . window . get_widget ( " details-pages " ) . remove_page ( page_idx )
self . serial_tabs . remove ( name )
2009-07-15 01:06:37 +04:00
2010-02-25 04:37:41 +03:00
############################
# Details/Hardware getters #
############################
def get_config_boot_devs ( self ) :
boot_model = self . window . get_widget ( " config-boot-list " ) . get_model ( )
devs = [ ]
for row in boot_model :
if row [ BOOT_ACTIVE ] :
devs . append ( row [ BOOT_DEV_TYPE ] )
return devs
2009-03-01 03:27:20 +03:00
2009-11-04 21:18:14 +03:00
##############################
# Details/Hardware listeners #
##############################
2010-02-10 20:16:59 +03:00
def config_enable_apply ( self , ignore1 = None , ignore2 = None ) :
2009-11-04 19:09:41 +03:00
self . window . get_widget ( " config-apply " ) . set_sensitive ( True )
2009-11-04 21:18:14 +03:00
# Overview -> Security
def security_model_changed ( self , combo ) :
model = combo . get_model ( )
idx = combo . get_active ( )
if idx < 0 :
2009-03-01 03:27:20 +03:00
return
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " config-apply " ) . set_sensitive ( True )
val = model [ idx ] [ 0 ]
2010-02-07 20:18:28 +03:00
show_type = ( val . lower ( ) != " none " )
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " security-type-box " ) . set_sensitive ( show_type )
2009-03-01 03:27:20 +03:00
2009-11-04 21:18:14 +03:00
def security_label_changed ( self , label ) :
self . window . get_widget ( " config-apply " ) . set_sensitive ( True )
2009-03-01 03:27:20 +03:00
2009-11-04 21:18:14 +03:00
def security_type_changed ( self , button , sensitive = True ) :
self . window . get_widget ( " config-apply " ) . set_sensitive ( True )
self . window . get_widget ( " security-label " ) . set_sensitive ( not button . get_active ( ) )
2009-07-09 22:35:44 +04:00
2009-11-04 21:18:14 +03:00
# Memory
def config_get_maxmem ( self ) :
maxadj = self . window . get_widget ( " config-maxmem " ) . get_adjustment ( )
txtmax = self . window . get_widget ( " config-maxmem " ) . get_text ( )
try :
maxmem = int ( txtmax )
except :
maxmem = maxadj . value
return maxmem
2009-05-12 21:09:08 +04:00
2009-11-04 21:18:14 +03:00
def config_get_memory ( self ) :
memadj = self . window . get_widget ( " config-memory " ) . get_adjustment ( )
txtmem = self . window . get_widget ( " config-memory " ) . get_text ( )
try :
mem = int ( txtmem )
except :
mem = memadj . value
return mem
2009-05-12 21:09:08 +04:00
2009-11-04 21:18:14 +03:00
def config_maxmem_changed ( self , src ) :
self . window . get_widget ( " config-apply " ) . set_sensitive ( True )
2009-11-04 21:16:38 +03:00
2009-11-04 21:18:14 +03:00
def config_memory_changed ( self , src ) :
self . window . get_widget ( " config-apply " ) . set_sensitive ( True )
2009-11-04 21:16:38 +03:00
2009-11-04 21:18:14 +03:00
maxadj = self . window . get_widget ( " config-maxmem " ) . get_adjustment ( )
2009-11-04 21:16:38 +03:00
2009-11-04 21:18:14 +03:00
mem = self . config_get_memory ( )
if maxadj . value < mem :
maxadj . value = mem
maxadj . lower = mem
2009-11-04 21:16:38 +03:00
2010-06-21 21:32:59 +04:00
def generate_cpuset ( self ) :
mem = int ( self . vm . get_memory ( ) ) / 1024 / 1024
return virtinst . Guest . generate_cpuset ( self . conn . vmm , mem )
2010-05-13 20:55:08 +04:00
# VCPUS
2010-06-21 21:32:59 +04:00
def config_vcpupin_generate ( self , ignore ) :
try :
pinstr = self . generate_cpuset ( )
except Exception , e :
return self . err . val_err (
_ ( " Error generating CPU configuration: %s " ) % str ( e ) )
self . window . get_widget ( " config-vcpupin " ) . set_text ( " " )
self . window . get_widget ( " config-vcpupin " ) . set_text ( pinstr )
2010-05-13 20:55:08 +04:00
def config_vcpus_changed ( self , ignore ) :
conn = self . vm . get_connection ( )
host_active_count = conn . host_active_processor_count ( )
vcpus_adj = self . window . get_widget ( " config-vcpus " ) . get_adjustment ( )
# Warn about overcommit
warn = bool ( vcpus_adj . value > host_active_count )
self . window . get_widget ( " config-vcpus-warn-box " ) . set_property (
" visible " , warn )
self . config_enable_apply ( )
2009-11-04 21:18:14 +03:00
# Boot device / Autostart
2010-02-25 04:37:41 +03:00
def config_bootdev_selected ( self , ignore ) :
boot_row = self . get_boot_selection ( )
boot_selection = boot_row and boot_row [ BOOT_DEV_TYPE ]
boot_devs = self . get_config_boot_devs ( )
up_widget = self . window . get_widget ( " config-boot-moveup " )
down_widget = self . window . get_widget ( " config-boot-movedown " )
down_widget . set_sensitive ( bool ( boot_devs and
boot_selection and
boot_selection in boot_devs and
boot_selection != boot_devs [ - 1 ] ) )
up_widget . set_sensitive ( bool ( boot_devs and boot_selection and
boot_selection in boot_devs and
boot_selection != boot_devs [ 0 ] ) )
def config_boot_toggled ( self , ignore , index ) :
boot_model = self . window . get_widget ( " config-boot-list " ) . get_model ( )
boot_row = boot_model [ index ]
is_active = boot_row [ BOOT_ACTIVE ]
boot_row [ BOOT_ACTIVE ] = not is_active
self . repopulate_boot_list ( self . get_config_boot_devs ( ) ,
boot_row [ BOOT_DEV_TYPE ] )
self . config_enable_apply ( )
def config_boot_move ( self , src , move_up ) :
boot_row = self . get_boot_selection ( )
if not boot_row :
return
boot_selection = boot_row [ BOOT_DEV_TYPE ]
boot_devs = self . get_config_boot_devs ( )
boot_idx = boot_devs . index ( boot_selection )
if move_up :
new_idx = boot_idx - 1
else :
new_idx = boot_idx + 1
if new_idx < 0 or new_idx > = len ( boot_devs ) :
# Somehow we got out of bounds
return
swap_dev = boot_devs [ new_idx ]
boot_devs [ new_idx ] = boot_selection
boot_devs [ boot_idx ] = swap_dev
self . repopulate_boot_list ( boot_devs , boot_selection )
self . config_enable_apply ( )
2009-07-07 20:16:03 +04:00
2009-11-04 00:15:18 +03:00
# CDROM Eject/Connect
2009-12-11 03:18:24 +03:00
def toggle_storage_media ( self , src ) :
2010-09-03 22:10:04 +04:00
disk = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not disk :
2009-11-04 00:15:18 +03:00
return
2010-09-08 02:38:01 +04:00
dev_id_info = disk
2010-09-03 22:10:04 +04:00
curpath = disk . path
devtype = disk . device
2009-12-11 03:18:24 +03:00
2009-11-04 00:15:18 +03:00
if curpath :
# Disconnect cdrom
2010-09-09 01:53:51 +04:00
self . change_storage_media ( dev_id_info , None )
return
2009-11-04 00:15:18 +03:00
2010-09-09 01:53:51 +04:00
def change_cdrom_wrapper ( src , dev_id_info , newpath ) :
return self . change_storage_media ( dev_id_info , newpath )
2009-11-04 00:15:18 +03:00
2010-09-09 01:53:51 +04:00
# Launch 'Choose CD' dialog
if self . media_choosers [ devtype ] is None :
ret = vmmChooseCD ( self . config ,
dev_id_info ,
self . vm . get_connection ( ) ,
devtype )
2009-12-14 22:52:52 +03:00
2010-09-09 01:53:51 +04:00
ret . connect ( " cdrom-chosen " , change_cdrom_wrapper )
self . media_choosers [ devtype ] = ret
2009-12-14 22:52:52 +03:00
2010-09-09 01:53:51 +04:00
dialog = self . media_choosers [ devtype ]
dialog . dev_id_info = dev_id_info
dialog . show ( )
2009-07-07 20:16:03 +04:00
2009-11-04 21:18:14 +03:00
##################################################
# Details/Hardware config changes (apply button) #
##################################################
2009-07-07 20:16:03 +04:00
2009-11-04 21:18:14 +03:00
def config_apply ( self , ignore ) :
pagetype = self . get_hw_selection ( HW_LIST_COL_TYPE )
2010-09-08 02:38:01 +04:00
devobj = self . get_hw_selection ( HW_LIST_COL_DEVICE )
key = devobj
2009-11-04 21:18:14 +03:00
ret = False
if pagetype is HW_LIST_TYPE_GENERAL :
2009-11-04 19:09:41 +03:00
ret = self . config_overview_apply ( )
2009-11-04 21:18:14 +03:00
elif pagetype is HW_LIST_TYPE_CPU :
ret = self . config_vcpus_apply ( )
elif pagetype is HW_LIST_TYPE_MEMORY :
ret = self . config_memory_apply ( )
elif pagetype is HW_LIST_TYPE_BOOT :
ret = self . config_boot_options_apply ( )
2009-11-05 00:30:51 +03:00
elif pagetype is HW_LIST_TYPE_DISK :
2010-09-03 22:05:29 +04:00
ret = self . config_disk_apply ( key )
2010-03-24 05:15:53 +03:00
elif pagetype is HW_LIST_TYPE_NIC :
2010-09-03 22:05:29 +04:00
ret = self . config_network_apply ( key )
2010-03-24 05:15:53 +03:00
elif pagetype is HW_LIST_TYPE_SOUND :
2010-09-03 22:05:29 +04:00
ret = self . config_sound_apply ( key )
2009-11-05 22:59:11 +03:00
elif pagetype is HW_LIST_TYPE_VIDEO :
2010-09-03 22:05:29 +04:00
ret = self . config_video_apply ( key )
2010-03-24 07:22:17 +03:00
elif pagetype is HW_LIST_TYPE_WATCHDOG :
2010-09-03 22:05:29 +04:00
ret = self . config_watchdog_apply ( key )
2009-07-07 20:16:03 +04:00
else :
2009-11-04 21:18:14 +03:00
ret = False
2009-07-07 20:16:03 +04:00
2009-11-04 21:18:14 +03:00
if ret is not False :
self . window . get_widget ( " config-apply " ) . set_sensitive ( False )
2009-07-07 20:16:03 +04:00
2010-03-24 05:15:53 +03:00
# Helper for accessing value of combo/label pattern
def get_combo_label_value ( self , prefix , model_idx = 0 ) :
combo = self . window . get_widget ( prefix + " -combo " )
2010-05-20 16:34:32 +04:00
label = self . window . get_widget ( prefix + " -label " )
2010-03-24 05:15:53 +03:00
value = None
if combo . get_property ( " visible " ) :
value = combo . get_model ( ) [ combo . get_active ( ) ] [ model_idx ]
2010-05-20 16:34:32 +04:00
else :
value = label . get_text ( )
2010-03-24 05:15:53 +03:00
return value
2009-11-04 19:09:41 +03:00
# Overview section
def config_overview_apply ( self ) :
# Machine details
enable_acpi = self . window . get_widget ( " overview-acpi " ) . get_active ( )
enable_apic = self . window . get_widget ( " overview-apic " ) . get_active ( )
2009-11-04 16:46:09 +03:00
clock_combo = self . window . get_widget ( " overview-clock-combo " )
if clock_combo . get_property ( " visible " ) :
clock = clock_combo . get_model ( ) [ clock_combo . get_active ( ) ] [ 0 ]
else :
clock = self . window . get_widget ( " overview-clock-label " ) . get_text ( )
2009-11-04 19:09:41 +03:00
# Security
2009-11-04 21:18:14 +03:00
combo = self . window . get_widget ( " security-model " )
model = combo . get_model ( )
semodel = model [ combo . get_active ( ) ] [ 0 ]
2008-10-18 23:25:16 +04:00
2009-11-04 21:18:14 +03:00
if not semodel or str ( semodel ) . lower ( ) == " none " :
semodel = None
2008-12-17 23:27:06 +03:00
2009-11-04 21:18:14 +03:00
if self . window . get_widget ( " security-dynamic " ) . get_active ( ) :
setype = " dynamic "
else :
setype = " static "
2009-07-27 00:09:46 +04:00
2009-11-04 21:18:14 +03:00
selabel = self . window . get_widget ( " security-label " ) . get_text ( )
2009-11-04 21:23:22 +03:00
2010-02-10 20:16:59 +03:00
# Description
desc_widget = self . window . get_widget ( " overview-description " )
desc = desc_widget . get_buffer ( ) . get_property ( " text " ) or " "
2009-11-04 19:09:41 +03:00
return self . _change_config_helper ( [ self . vm . define_acpi ,
self . vm . define_apic ,
2009-11-04 16:46:09 +03:00
self . vm . define_clock ,
2010-02-10 20:16:59 +03:00
self . vm . define_seclabel ,
self . vm . define_description , ] ,
2009-11-04 19:09:41 +03:00
[ ( enable_acpi , ) ,
( enable_apic , ) ,
2009-11-04 16:46:09 +03:00
( clock , ) ,
2010-02-10 20:16:59 +03:00
( semodel , setype , selabel ) ,
( desc , ) ] )
2009-07-27 00:09:46 +04:00
2009-11-04 21:18:14 +03:00
# CPUs
def config_vcpus_apply ( self ) :
vcpus = self . window . get_widget ( " config-vcpus " ) . get_adjustment ( ) . value
cpuset = self . window . get_widget ( " config-vcpupin " ) . get_text ( )
2008-12-17 23:27:06 +03:00
2009-11-04 21:18:14 +03:00
logging . info ( " Setting vcpus for %s to %s , cpuset is %s " %
( self . vm . get_name ( ) , str ( vcpus ) , cpuset ) )
2008-12-17 23:27:06 +03:00
2009-11-16 19:36:13 +03:00
return self . _change_config_helper ( [ self . vm . define_vcpus ,
self . vm . define_cpuset ] ,
[ ( vcpus , ) ,
( cpuset , ) ] ,
2009-11-04 21:23:22 +03:00
self . vm . hotplug_vcpus ,
( vcpus , ) )
2006-06-14 18:59:40 +04:00
2009-11-16 19:36:13 +03:00
def config_vcpu_pin ( self , src , path , new_text ) :
vcpu_list = self . window . get_widget ( " config-vcpu-list " )
vcpu_model = vcpu_list . get_model ( )
row = vcpu_model [ path ]
conn = self . vm . get_connection ( )
try :
vcpu_num = int ( row [ 0 ] )
pinlist = virtinst . Guest . cpuset_str_to_tuple ( conn . vmm , new_text )
except Exception , e :
self . err . val_err ( _ ( " Error building pin list: %s " ) % str ( e ) )
return
try :
self . vm . pin_vcpu ( vcpu_num , pinlist )
except Exception , e :
self . err . show_err ( _ ( " Error pinning vcpus: %s " ) % str ( e ) ,
" " . join ( traceback . format_exc ( ) ) )
return
self . refresh_config_cpu ( )
2009-11-04 21:18:14 +03:00
# Memory
def config_memory_apply ( self ) :
self . refresh_config_memory ( )
curmem = None
maxmem = self . config_get_maxmem ( )
if self . window . get_widget ( " config-memory " ) . get_property ( " sensitive " ) :
curmem = self . config_get_memory ( )
if curmem :
curmem = int ( curmem ) * 1024
if maxmem :
maxmem = int ( maxmem ) * 1024
2009-11-04 21:23:22 +03:00
return self . _change_config_helper ( self . vm . define_both_mem ,
( curmem , maxmem ) ,
self . vm . hotplug_both_mem ,
( curmem , maxmem ) )
2009-11-04 21:18:14 +03:00
# Boot device / Autostart
def config_boot_options_apply ( self ) :
auto = self . window . get_widget ( " config-autostart " )
2009-11-04 21:23:22 +03:00
2009-11-04 21:18:14 +03:00
if auto . get_property ( " sensitive " ) :
try :
self . vm . set_autostart ( auto . get_active ( ) )
except Exception , e :
2009-11-04 21:23:22 +03:00
self . err . show_err ( ( _ ( " Error changing autostart value: %s " ) %
str ( e ) ) , " " . join ( traceback . format_exc ( ) ) )
2009-11-04 21:18:14 +03:00
return False
2010-02-25 04:37:41 +03:00
bootdevs = self . get_config_boot_devs ( )
return self . _change_config_helper ( self . vm . set_boot_device ,
( bootdevs , ) )
2009-11-04 21:23:22 +03:00
2009-11-04 21:18:14 +03:00
# CDROM
2010-09-09 01:53:51 +04:00
def change_storage_media ( self , dev_id_info , newpath ) :
2009-12-11 03:18:24 +03:00
return self . _change_config_helper ( self . vm . define_storage_media ,
2010-09-09 01:53:51 +04:00
( dev_id_info , newpath ) ,
2009-12-11 03:18:24 +03:00
self . vm . hotplug_storage_media ,
2010-09-09 01:53:51 +04:00
( dev_id_info , newpath ) )
2009-11-04 21:18:14 +03:00
2009-11-05 00:30:51 +03:00
# Disk options
def config_disk_apply ( self , dev_id_info ) :
do_readonly = self . window . get_widget ( " disk-readonly " ) . get_active ( )
do_shareable = self . window . get_widget ( " disk-shareable " ) . get_active ( )
2010-05-20 16:34:32 +04:00
cache = self . get_combo_label_value ( " disk-cache " )
2009-11-05 00:30:51 +03:00
return self . _change_config_helper ( [ self . vm . define_disk_readonly ,
2010-05-20 16:34:32 +04:00
self . vm . define_disk_shareable ,
self . vm . define_disk_cache ] ,
2009-11-05 00:30:51 +03:00
[ ( dev_id_info , do_readonly ) ,
2010-05-20 16:34:32 +04:00
( dev_id_info , do_shareable ) ,
( dev_id_info , cache ) ] )
2009-11-05 00:30:51 +03:00
2010-03-24 05:15:53 +03:00
# Audio options
def config_sound_apply ( self , dev_id_info ) :
model = self . get_combo_label_value ( " sound-model " )
if model :
return self . _change_config_helper ( self . vm . define_sound_model ,
( dev_id_info , model ) )
2009-11-05 00:30:51 +03:00
2010-03-24 05:15:53 +03:00
# Network options
def config_network_apply ( self , dev_id_info ) :
model = self . get_combo_label_value ( " network-model " )
return self . _change_config_helper ( self . vm . define_network_model ,
( dev_id_info , model ) )
2009-11-05 22:59:11 +03:00
2010-03-24 05:15:53 +03:00
# Video options
def config_video_apply ( self , dev_id_info ) :
model = self . get_combo_label_value ( " video-model " )
2009-11-05 22:59:11 +03:00
if model :
return self . _change_config_helper ( self . vm . define_video_model ,
( dev_id_info , model ) )
2009-11-04 21:18:14 +03:00
2010-03-24 07:22:17 +03:00
# Watchdog options
def config_watchdog_apply ( self , dev_id_info ) :
model = self . get_combo_label_value ( " watchdog-model " )
action = self . get_combo_label_value ( " watchdog-action " )
if model or action :
return self . _change_config_helper ( [ self . vm . define_watchdog_model ,
self . vm . define_watchdog_action ] ,
[ ( dev_id_info , model ) ,
( dev_id_info , action ) ] )
2009-11-04 00:15:18 +03:00
# Device removal
2009-11-04 21:18:14 +03:00
def remove_device ( self , dev_type , dev_id_info ) :
logging . debug ( " Removing device: %s %s " % ( dev_type , dev_id_info ) )
2009-11-19 00:46:36 +03:00
do_prompt = self . config . get_confirm_removedev ( )
if do_prompt :
res = self . err . warn_chkbox (
text1 = ( _ ( " Are you sure you want to remove this device? " ) ) ,
chktext = _ ( " Don ' t ask me again. " ) ,
buttons = gtk . BUTTONS_YES_NO )
response , skip_prompt = res
if not response :
return
self . config . set_confirm_removedev ( not skip_prompt )
2009-11-04 21:18:14 +03:00
2009-11-20 17:29:26 +03:00
# Define the change
try :
2010-09-09 01:53:51 +04:00
self . vm . remove_device ( dev_id_info )
2009-11-20 17:29:26 +03:00
except Exception , e :
self . err . show_err ( _ ( " Error Removing Device: %s " % str ( e ) ) ,
" " . join ( traceback . format_exc ( ) ) )
return
# Try to hot remove
2009-11-04 21:18:14 +03:00
detach_err = False
try :
if self . vm . is_active ( ) :
2010-09-09 01:53:51 +04:00
self . vm . detach_device ( dev_id_info )
2009-11-04 21:18:14 +03:00
except Exception , e :
logging . debug ( " Device could not be hotUNplugged: %s " % str ( e ) )
detach_err = True
2009-11-19 00:46:36 +03:00
if detach_err :
self . err . show_info (
_ ( " Device could not be removed from the running machine. " ) ,
_ ( " This change will take effect after the next VM reboot " ) )
2009-11-04 21:18:14 +03:00
2009-11-04 21:23:22 +03:00
# Generic config change helpers
def _change_config_helper ( self ,
define_funcs , define_funcs_args ,
hotplug_funcs = None , hotplug_funcs_args = None ) :
"""
Requires at least a ' define ' function and arglist to be specified
( a function where we change the inactive guest config ) .
Arguments can be a single arg or a list or appropriate arg type ( e . g .
a list of functions for define_funcs )
"""
def listify ( val ) :
if not val :
return [ ]
if type ( val ) is not list :
return [ val ]
return val
define_funcs = listify ( define_funcs )
define_funcs_args = listify ( define_funcs_args )
hotplug_funcs = listify ( hotplug_funcs )
hotplug_funcs_args = listify ( hotplug_funcs_args )
hotplug_err = False
active = self . vm . is_active ( )
# Hotplug change
func = None
if active and hotplug_funcs :
for idx in range ( len ( hotplug_funcs ) ) :
func = hotplug_funcs [ idx ]
args = hotplug_funcs_args [ idx ]
try :
func ( * args )
except Exception , e :
logging . debug ( " Hotplug failed: func= %s : %s " % ( func ,
str ( e ) ) )
hotplug_err = True
# Persistent config change
2010-09-09 01:53:51 +04:00
try :
for idx in range ( len ( define_funcs ) ) :
func = define_funcs [ idx ]
args = define_funcs_args [ idx ]
2009-11-04 21:23:22 +03:00
func ( * args )
2010-09-09 01:53:51 +04:00
if define_funcs :
self . vm . redefine_cached ( )
except Exception , e :
self . err . show_err ( ( _ ( " Error changing VM configuration: %s " ) %
str ( e ) ) , " " . join ( traceback . format_exc ( ) ) )
# If we fail, make sure we flush the cache
self . vm . refresh_xml ( )
return False
2009-11-04 21:23:22 +03:00
if ( hotplug_err or
( active and not len ( hotplug_funcs ) == len ( define_funcs ) ) ) :
if len ( define_funcs ) > 1 :
2009-11-16 19:36:13 +03:00
self . err . show_info ( _ ( " Some changes may require a guest reboot "
" to take effect. " ) )
2009-11-04 21:23:22 +03:00
else :
self . err . show_info ( _ ( " These changes will take effect after "
" the next guest reboot. " ) )
return True
2009-11-04 21:18:14 +03:00
########################
# Details page refresh #
########################
def refresh_resources ( self , ignore ) :
details = self . window . get_widget ( " details-pages " )
page = details . get_current_page ( )
# If the dialog is visible, we want to make sure the XML is always
# up to date
if self . is_visible ( ) :
self . vm . refresh_xml ( )
2009-11-16 19:36:13 +03:00
# Stats page needs to be refreshed every tick
2009-11-04 21:18:14 +03:00
if ( page == PAGE_DETAILS and
self . get_hw_selection ( HW_LIST_COL_TYPE ) == HW_LIST_TYPE_STATS ) :
self . refresh_stats_page ( )
def page_refresh ( self , page ) :
if page != PAGE_DETAILS :
return
# This function should only be called when the VM xml actually
# changes (not everytime it is refreshed). This saves us from blindly
# parsing the xml every tick
# Add / remove new devices
self . repopulate_hw_list ( )
pagetype = self . get_hw_selection ( HW_LIST_COL_TYPE )
if pagetype is None :
return
2010-02-25 04:46:25 +03:00
if self . window . get_widget ( " config-apply " ) . get_property ( " sensitive " ) :
# Apply button sensitive means user is making changes, don't
# erase them
return
2009-11-04 21:18:14 +03:00
self . hw_selected ( page = pagetype )
def refresh_overview_page ( self ) :
# Basic details
self . window . get_widget ( " overview-name " ) . set_text ( self . vm . get_name ( ) )
self . window . get_widget ( " overview-uuid " ) . set_text ( self . vm . get_uuid ( ) )
2010-02-10 20:16:59 +03:00
desc = self . vm . get_description ( ) or " "
desc_widget = self . window . get_widget ( " overview-description " )
desc_widget . get_buffer ( ) . set_text ( desc )
2009-11-04 21:18:14 +03:00
# Hypervisor Details
self . window . get_widget ( " overview-hv " ) . set_text ( self . vm . get_pretty_hv_type ( ) )
arch = self . vm . get_arch ( ) or _ ( " Unknown " )
emu = self . vm . get_emulator ( ) or _ ( " None " )
self . window . get_widget ( " overview-arch " ) . set_text ( arch )
self . window . get_widget ( " overview-emulator " ) . set_text ( emu )
# Machine settings
acpi = self . vm . get_acpi ( )
apic = self . vm . get_apic ( )
clock = self . vm . get_clock ( )
self . window . get_widget ( " overview-acpi " ) . set_active ( acpi )
self . window . get_widget ( " overview-apic " ) . set_active ( apic )
2010-03-24 05:15:53 +03:00
2009-11-04 21:18:14 +03:00
if not clock :
clock = _ ( " Same as host " )
2010-03-24 05:15:53 +03:00
self . set_combo_label ( " overview-clock " , 0 , clock )
2009-11-04 21:18:14 +03:00
# Security details
vmmodel , ignore , vmlabel = self . vm . get_seclabel ( )
semodel_combo = self . window . get_widget ( " security-model " )
semodel_model = semodel_combo . get_model ( )
caps = self . vm . get_connection ( ) . get_capabilities ( )
semodel_model . clear ( )
semodel_model . append ( [ " None " ] )
if caps . host . secmodel and caps . host . secmodel . model :
semodel_model . append ( [ caps . host . secmodel . model ] )
active = 0
for i in range ( 0 , len ( semodel_model ) ) :
if vmmodel and vmmodel == semodel_model [ i ] [ 0 ] :
active = i
break
semodel_combo . set_active ( active )
if self . vm . get_seclabel ( ) [ 1 ] == " static " :
self . window . get_widget ( " security-static " ) . set_active ( True )
else :
self . window . get_widget ( " security-dynamic " ) . set_active ( True )
self . window . get_widget ( " security-label " ) . set_text ( vmlabel )
semodel_combo . emit ( " changed " )
def refresh_stats_page ( self ) :
2010-08-22 03:27:45 +04:00
def _dsk_rx_tx_text ( rx , tx , unit ) :
return ( ' <span color= " #82003B " > %(rx)d %(unit)s read</span> \n '
' <span color= " #295C45 " > %(tx)d %(unit)s write</span> ' %
locals ( ) )
def _net_rx_tx_text ( rx , tx , unit ) :
return ( ' <span color= " #82003B " > %(rx)d %(unit)s in</span> \n '
' <span color= " #295C45 " > %(tx)d %(unit)s out</span> ' %
locals ( ) )
2009-11-04 21:18:14 +03:00
cpu_txt = _ ( " Disabled " )
mem_txt = _ ( " Disabled " )
dsk_txt = _ ( " Disabled " )
net_txt = _ ( " Disabled " )
cpu_txt = " %d %% " % self . vm . cpu_time_percentage ( )
vm_memory = self . vm . current_memory ( )
host_memory = self . vm . get_connection ( ) . host_memory_size ( )
mem_txt = " %d MB of %d MB " % ( int ( round ( vm_memory / 1024.0 ) ) ,
int ( round ( host_memory / 1024.0 ) ) )
if self . config . get_stats_enable_disk_poll ( ) :
2010-08-22 03:27:45 +04:00
dsk_txt = _dsk_rx_tx_text ( self . vm . disk_read_rate ( ) ,
self . vm . disk_write_rate ( ) , " KB/s " )
2009-11-04 21:18:14 +03:00
if self . config . get_stats_enable_net_poll ( ) :
2010-08-22 03:27:45 +04:00
net_txt = _net_rx_tx_text ( self . vm . network_rx_rate ( ) ,
self . vm . network_tx_rate ( ) , " KB/s " )
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " overview-cpu-usage-text " ) . set_text ( cpu_txt )
self . window . get_widget ( " overview-memory-usage-text " ) . set_text ( mem_txt )
self . window . get_widget ( " overview-network-traffic-text " ) . set_markup ( net_txt )
self . window . get_widget ( " overview-disk-usage-text " ) . set_markup ( dsk_txt )
self . cpu_usage_graph . set_property ( " data_array " ,
self . vm . cpu_time_vector ( ) )
self . memory_usage_graph . set_property ( " data_array " ,
self . vm . current_memory_vector ( ) )
self . disk_io_graph . set_property ( " data_array " ,
self . vm . disk_io_vector ( ) )
self . network_traffic_graph . set_property ( " data_array " ,
self . vm . network_traffic_vector ( ) )
def refresh_config_cpu ( self ) :
2009-11-11 20:56:58 +03:00
conn = self . vm . get_connection ( )
host_active_count = conn . host_active_processor_count ( )
cpu_max = ( self . vm . is_runable ( ) and
conn . get_max_vcpus ( self . vm . get_hv_type ( ) ) or
self . vm . vcpu_max_count ( ) )
curvcpus = self . vm . vcpu_count ( )
vcpupin = self . vm . vcpu_pinning ( )
config_apply = self . window . get_widget ( " config-apply " )
vcpus_adj = self . window . get_widget ( " config-vcpus " ) . get_adjustment ( )
vcpus_adj . upper = cpu_max
self . window . get_widget ( " state-host-cpus " ) . set_text ( " %s " %
host_active_count )
self . window . get_widget ( " state-vm-maxvcpus " ) . set_text ( str ( cpu_max ) )
2006-11-13 23:31:17 +03:00
2009-11-11 20:56:58 +03:00
if not config_apply . get_property ( " sensitive " ) :
vcpus_adj . value = curvcpus
self . window . get_widget ( " state-vm-vcpus " ) . set_text ( str ( curvcpus ) )
2009-11-16 19:36:13 +03:00
2010-05-13 20:55:08 +04:00
# Warn about overcommit
warn = bool ( vcpus_adj . value > host_active_count )
self . window . get_widget ( " config-vcpus-warn-box " ) . set_property (
" visible " , warn )
2009-11-16 19:36:13 +03:00
# Populate VCPU pinning
2009-11-11 20:56:58 +03:00
self . window . get_widget ( " config-vcpupin " ) . set_text ( vcpupin )
2006-11-13 23:31:17 +03:00
2009-11-16 19:36:13 +03:00
vcpu_list = self . window . get_widget ( " config-vcpu-list " )
vcpu_model = vcpu_list . get_model ( )
vcpu_model . clear ( )
reason = " "
if not self . vm . is_active ( ) :
reason = _ ( " VCPU info only available for running domain. " )
elif not self . vm . getvcpus_supported :
reason = _ ( " Virtual machine does not support runtime VPCU info. " )
else :
try :
vcpu_info , vcpu_pinning = self . vm . vcpu_info ( )
except Exception , e :
reason = _ ( " Error getting VCPU info: %s " ) % str ( e )
vcpu_list . set_sensitive ( not bool ( reason ) )
util . tooltip_wrapper ( vcpu_list , reason or None )
if reason :
return
def build_cpuset_str ( pin_info ) :
pinstr = " "
for i in range ( host_active_count ) :
if i < len ( pin_info ) and pin_info [ i ] :
pinstr + = ( " , %s " % str ( i ) )
return pinstr . strip ( " , " )
for idx in range ( len ( vcpu_info ) ) :
vcpu = vcpu_info [ idx ] [ 0 ]
vcpucur = vcpu_info [ idx ] [ 3 ]
vcpupin = build_cpuset_str ( vcpu_pinning [ idx ] )
vcpu_model . append ( [ vcpu , vcpucur , vcpupin ] )
2006-11-13 23:31:17 +03:00
def refresh_config_memory ( self ) :
2009-11-11 20:56:58 +03:00
host_mem_widget = self . window . get_widget ( " state-host-memory " )
vm_mem_widget = self . window . get_widget ( " state-vm-memory " )
host_mem = self . vm . get_connection ( ) . host_memory_size ( ) / 1024
vm_cur_mem = self . vm . get_memory ( ) / 1024.0
vm_max_mem = self . vm . maximum_memory ( ) / 1024.0
host_mem_widget . set_text ( " %d MB " % ( int ( round ( host_mem ) ) ) )
vm_mem_widget . set_text ( " %d MB " % int ( round ( vm_cur_mem ) ) )
2008-03-18 21:37:22 +03:00
curmem = self . window . get_widget ( " config-memory " ) . get_adjustment ( )
maxmem = self . window . get_widget ( " config-maxmem " ) . get_adjustment ( )
2009-07-09 22:35:36 +04:00
if self . window . get_widget ( " config-apply " ) . get_property ( " sensitive " ) :
2009-06-17 02:04:29 +04:00
memval = self . config_get_memory ( )
maxval = self . config_get_maxmem ( )
if maxval < memval :
maxmem . value = memval
maxmem . lower = memval
2006-11-13 23:31:17 +03:00
else :
2009-11-11 20:56:58 +03:00
curmem . value = int ( round ( vm_cur_mem ) )
maxmem . value = int ( round ( vm_max_mem ) )
2006-09-22 20:31:51 +04:00
2009-11-11 20:56:58 +03:00
if ( not
self . window . get_widget ( " config-memory " ) . get_property ( " sensitive " ) ) :
2008-03-18 21:37:22 +03:00
maxmem . lower = curmem . value
2009-11-11 20:56:58 +03:00
2006-07-27 02:19:33 +04:00
2009-01-15 19:23:23 +03:00
def refresh_disk_page ( self ) :
2010-09-03 22:10:04 +04:00
disk = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not disk :
2009-01-15 19:23:23 +03:00
return
2010-09-03 22:10:04 +04:00
path = disk . path
devtype = disk . device
ro = disk . read_only
share = disk . shareable
bus = disk . bus
idx = disk . disk_bus_index
cache = disk . driver_cache
2009-11-04 23:41:18 +03:00
2010-03-04 02:43:48 +03:00
size = _ ( " Unknown " )
if not path :
size = " - "
else :
vol = self . conn . get_vol_by_path ( path )
if vol :
size = vol . get_pretty_capacity ( )
elif not self . conn . is_remote ( ) :
2010-03-04 23:36:29 +03:00
ignore , val = virtinst . VirtualDisk . stat_local_path ( path )
if val != 0 :
size = prettyify_bytes ( val )
2010-03-04 02:43:48 +03:00
2009-11-05 00:30:51 +03:00
is_cdrom = ( devtype == virtinst . VirtualDisk . DEVICE_CDROM )
2009-12-11 03:18:24 +03:00
is_floppy = ( devtype == virtinst . VirtualDisk . DEVICE_FLOPPY )
2009-11-05 00:30:51 +03:00
2009-12-02 05:34:29 +03:00
pretty_name = prettyify_disk ( devtype , bus , idx )
2009-11-04 23:41:18 +03:00
self . window . get_widget ( " disk-source-path " ) . set_text ( path or " - " )
self . window . get_widget ( " disk-target-type " ) . set_text ( pretty_name )
self . window . get_widget ( " disk-readonly " ) . set_active ( ro )
2009-11-05 00:30:51 +03:00
self . window . get_widget ( " disk-readonly " ) . set_sensitive ( not is_cdrom )
2009-11-04 23:41:18 +03:00
self . window . get_widget ( " disk-shareable " ) . set_active ( share )
2010-03-04 02:43:48 +03:00
self . window . get_widget ( " disk-size " ) . set_text ( size )
2010-05-20 16:34:32 +04:00
self . set_combo_label ( " disk-cache " , 0 , cache )
2009-11-04 23:41:18 +03:00
2009-01-15 19:23:23 +03:00
button = self . window . get_widget ( " config-cdrom-connect " )
2009-12-11 03:18:24 +03:00
if is_cdrom or is_floppy :
2009-11-04 23:41:18 +03:00
if not path :
2009-01-15 19:23:23 +03:00
# source device not connected
button . set_label ( gtk . STOCK_CONNECT )
2007-09-22 00:28:31 +04:00
else :
2009-01-15 19:23:23 +03:00
button . set_label ( gtk . STOCK_DISCONNECT )
button . show ( )
else :
button . hide ( )
2007-04-11 22:48:36 +04:00
def refresh_network_page ( self ) :
2010-09-03 23:19:54 +04:00
net = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not net :
2009-01-15 19:23:23 +03:00
return
2010-09-03 23:19:54 +04:00
nettype = net . type
source = net . get_source ( )
model = net . model
2009-12-02 17:54:29 +03:00
netobj = None
if nettype == virtinst . VirtualNetworkInterface . TYPE_VIRTUAL :
name_dict = { }
for uuid in self . conn . list_net_uuids ( ) :
2010-09-03 23:19:54 +04:00
vnet = self . conn . get_net ( uuid )
name = vnet . get_name ( )
name_dict [ name ] = vnet
2009-12-02 17:54:29 +03:00
if source and name_dict . has_key ( source ) :
netobj = name_dict [ source ]
desc = uihelpers . pretty_network_desc ( nettype , source , netobj )
2010-09-03 23:19:54 +04:00
self . window . get_widget ( " network-mac-address " ) . set_text ( net . macaddr )
2009-12-02 17:54:29 +03:00
self . window . get_widget ( " network-source-device " ) . set_text ( desc )
2009-01-15 19:23:23 +03:00
2010-03-24 05:15:53 +03:00
uihelpers . populate_netmodel_combo ( self . vm ,
self . window . get_widget ( " network-model-combo " ) )
self . set_combo_label ( " network-model " , 0 , model )
2007-04-12 23:36:04 +04:00
2007-09-26 04:05:45 +04:00
def refresh_input_page ( self ) :
2010-09-03 23:59:33 +04:00
inp = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not inp :
2009-01-15 19:23:23 +03:00
return
2007-09-26 04:05:45 +04:00
2010-09-03 23:59:33 +04:00
ident = " %s : %s " % ( inp . type , inp . bus )
if ident == " tablet:usb " :
2009-11-11 20:56:58 +03:00
dev = _ ( " EvTouch USB Graphics Tablet " )
2010-09-03 23:59:33 +04:00
elif ident == " mouse:usb " :
2009-11-11 20:56:58 +03:00
dev = _ ( " Generic USB Mouse " )
2010-09-03 23:59:33 +04:00
elif ident == " mouse:xen " :
2009-11-11 20:56:58 +03:00
dev = _ ( " Xen Mouse " )
2010-09-03 23:59:33 +04:00
elif ident == " mouse:ps2 " :
2009-11-11 20:56:58 +03:00
dev = _ ( " PS/2 Mouse " )
2009-01-15 19:23:23 +03:00
else :
2010-09-03 23:59:33 +04:00
dev = inp . bus + " " + inp . type
2007-09-26 04:05:45 +04:00
2010-09-03 23:59:33 +04:00
if inp . type == " tablet " :
2009-11-11 20:56:58 +03:00
mode = _ ( " Absolute Movement " )
2009-01-15 19:23:23 +03:00
else :
2009-11-11 20:56:58 +03:00
mode = _ ( " Relative Movement " )
self . window . get_widget ( " input-dev-type " ) . set_text ( dev )
self . window . get_widget ( " input-dev-mode " ) . set_text ( mode )
2009-01-15 19:23:23 +03:00
# Can't remove primary Xen or PS/2 mice
2010-09-03 23:59:33 +04:00
if inp . type == " mouse " and inp . bus in ( " xen " , " ps2 " ) :
2009-07-09 22:35:36 +04:00
self . window . get_widget ( " config-remove " ) . set_sensitive ( False )
2009-01-15 19:23:23 +03:00
else :
2009-07-09 22:35:36 +04:00
self . window . get_widget ( " config-remove " ) . set_sensitive ( True )
2007-09-26 04:05:45 +04:00
2007-09-27 03:39:11 +04:00
def refresh_graphics_page ( self ) :
2010-09-03 23:59:33 +04:00
gfx = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not gfx :
2009-01-15 19:23:23 +03:00
return
2007-09-27 03:39:11 +04:00
2010-09-03 23:59:33 +04:00
is_vnc = ( gfx . type == " vnc " )
is_sdl = ( gfx . type == " sdl " )
2009-11-11 20:56:58 +03:00
port = _ ( " N/A " )
if is_vnc :
gtype = _ ( " VNC server " )
2010-09-03 23:59:33 +04:00
port = ( gfx . port == - 1 and
2009-11-11 20:56:58 +03:00
_ ( " Automatically allocated " ) or
2010-09-03 23:59:33 +04:00
str ( gfx . port ) )
2009-11-11 20:56:58 +03:00
elif is_sdl :
gtype = _ ( " Local SDL window " )
2009-01-15 19:23:23 +03:00
else :
2010-09-03 23:59:33 +04:00
gtype = gfx . type
2009-01-15 19:23:23 +03:00
2010-09-03 23:59:33 +04:00
address = ( is_vnc and ( gfx . listen or " 127.0.0.1 " ) or _ ( " N/A " ) )
2009-11-11 20:56:58 +03:00
passwd = ( is_vnc and " - " or _ ( " N/A " ) )
2010-09-03 23:59:33 +04:00
keymap = ( is_vnc and ( gfx . keymap or _ ( " None " ) ) or _ ( " N/A " ) )
2009-11-11 20:56:58 +03:00
self . window . get_widget ( " graphics-type " ) . set_text ( gtype )
self . window . get_widget ( " graphics-address " ) . set_text ( address )
self . window . get_widget ( " graphics-port " ) . set_text ( port )
self . window . get_widget ( " graphics-password " ) . set_text ( passwd )
self . window . get_widget ( " graphics-keymap " ) . set_text ( keymap )
2009-01-15 19:23:23 +03:00
2008-07-31 03:52:39 +04:00
def refresh_sound_page ( self ) :
2010-09-03 23:59:33 +04:00
sound = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not sound :
2008-07-31 03:52:39 +04:00
return
2009-01-15 19:23:23 +03:00
2010-09-03 23:59:33 +04:00
self . set_combo_label ( " sound-model " , 0 , sound . model )
2008-07-31 03:52:39 +04:00
2008-07-31 04:38:09 +04:00
def refresh_char_page ( self ) :
2010-09-04 01:56:40 +04:00
chardev = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not chardev :
2009-11-04 21:18:14 +03:00
return
2009-06-17 02:04:29 +04:00
2010-09-04 01:56:40 +04:00
char_type = chardev . virtual_device_type . capitalize ( )
2010-09-09 01:53:51 +04:00
target_port = chardev . target_port
2010-09-04 01:56:40 +04:00
dev_type = chardev . char_type or " pty "
src_path = chardev . source_path
2010-09-08 02:38:01 +04:00
primary = hasattr ( chardev , " virtmanager_console_dup " )
2009-12-03 18:37:57 +03:00
2010-09-13 17:31:32 +04:00
typelabel = " "
if char_type == " serial " :
typelabel = _ ( " Serial Device " )
elif char_type == " parallel " :
typelabel = _ ( " Parallel Device " )
elif char_type == " console " :
typelabel = _ ( " Console Device " )
elif char_type == " channel " :
typelabel = _ ( " Channel Device " )
else :
typelabel = _ ( " %s Device " ) % char_type . capitalize ( )
2010-09-04 01:56:40 +04:00
if target_port is not None :
typelabel + = " %s " % ( int ( target_port ) + 1 )
2009-12-03 18:37:57 +03:00
if primary :
typelabel + = " ( %s ) " % _ ( " Primary Console " )
typelabel = " <b> %s </b> " % typelabel
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " char-type " ) . set_markup ( typelabel )
2009-12-03 18:37:57 +03:00
self . window . get_widget ( " char-dev-type " ) . set_text ( dev_type )
self . window . get_widget ( " char-source-path " ) . set_text ( src_path or " - " )
2009-06-17 02:04:29 +04:00
2009-11-04 21:18:14 +03:00
def refresh_hostdev_page ( self ) :
2010-09-07 20:09:48 +04:00
hostdev = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not hostdev :
2009-11-04 21:18:14 +03:00
return
2009-06-17 02:04:29 +04:00
2010-09-07 20:09:48 +04:00
devtype = hostdev . type
pretty_name = None
nodedev = lookup_nodedev ( self . vm . get_connection ( ) , hostdev )
if nodedev :
pretty_name = nodedev . pretty_name ( )
2008-03-07 00:43:46 +03:00
2010-09-07 20:09:48 +04:00
if not pretty_name :
pretty_name = build_hostdev_label ( hostdev ) [ 0 ] or " - "
2008-03-07 00:43:46 +03:00
2010-09-07 20:09:48 +04:00
devlabel = " <b>Physical %s Device</b> " % devtype . upper ( )
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " hostdev-title " ) . set_markup ( devlabel )
2010-09-07 20:09:48 +04:00
self . window . get_widget ( " hostdev-source " ) . set_text ( pretty_name )
2006-11-13 23:31:17 +03:00
2009-11-04 21:18:14 +03:00
def refresh_video_page ( self ) :
2010-09-03 23:59:33 +04:00
vid = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not vid :
2008-07-31 04:38:09 +04:00
return
2010-09-03 23:59:33 +04:00
model = vid . model_type
ram = vid . vram
heads = vid . heads
2009-11-04 21:18:14 +03:00
try :
ramlabel = ram and " %d MB " % ( int ( ram ) / 1024 ) or " - "
except :
ramlabel = " - "
2008-07-31 04:38:09 +04:00
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " video-ram " ) . set_text ( ramlabel )
self . window . get_widget ( " video-heads " ) . set_text ( heads and heads or " - " )
2007-04-11 22:48:36 +04:00
2010-03-24 05:15:53 +03:00
self . set_combo_label ( " video-model " , 0 , model )
2009-11-05 22:59:11 +03:00
2010-03-24 07:22:17 +03:00
def refresh_watchdog_page ( self ) :
2010-09-03 23:59:33 +04:00
watch = self . get_hw_selection ( HW_LIST_COL_DEVICE )
if not watch :
2010-03-24 07:22:17 +03:00
return
2010-09-03 23:59:33 +04:00
model = watch . model
action = watch . action
2010-03-24 07:22:17 +03:00
self . set_combo_label ( " watchdog-model " , 0 , model )
self . set_combo_label ( " watchdog-action " , 0 , action )
2009-11-04 21:18:14 +03:00
def refresh_boot_page ( self ) :
# Refresh autostart
try :
2009-12-03 18:37:57 +03:00
# Older libvirt versions return None if not supported
2009-11-04 21:18:14 +03:00
autoval = self . vm . get_autostart ( )
2009-12-03 18:37:57 +03:00
except libvirt . libvirtError :
autoval = None
if autoval is not None :
2009-11-04 21:18:14 +03:00
self . window . get_widget ( " config-autostart " ) . set_active ( autoval )
self . window . get_widget ( " config-autostart " ) . set_sensitive ( True )
2009-12-03 18:37:57 +03:00
else :
2009-11-04 21:18:14 +03:00
# Autostart isn't supported
self . window . get_widget ( " config-autostart " ) . set_active ( False )
self . window . get_widget ( " config-autostart " ) . set_sensitive ( False )
2010-02-25 04:37:41 +03:00
# Refresh Boot Device list
2008-03-07 00:43:46 +03:00
self . repopulate_boot_list ( )
2007-04-12 23:36:04 +04:00
2009-11-04 21:18:14 +03:00
############################
# Hardware list population #
############################
2009-07-20 23:09:32 +04:00
2007-04-11 22:48:36 +04:00
def populate_hw_list ( self ) :
hw_list_model = self . window . get_widget ( " hw-list " ) . get_model ( )
hw_list_model . clear ( )
2009-07-20 23:09:32 +04:00
2009-11-04 21:18:14 +03:00
def add_hw_list_option ( title , page_id , data , icon_name ) :
hw_list_model . append ( [ title , icon_name ,
gtk . ICON_SIZE_LARGE_TOOLBAR ,
2010-09-08 02:38:01 +04:00
page_id , data ] )
2009-07-20 23:09:32 +04:00
2009-11-04 21:18:14 +03:00
add_hw_list_option ( " Overview " , HW_LIST_TYPE_GENERAL , [ ] , " computer " )
2010-02-07 20:18:28 +03:00
if not self . is_customize_dialog :
add_hw_list_option ( " Performance " , HW_LIST_TYPE_STATS , [ ] ,
" utilities-system-monitor " )
2009-11-04 21:18:14 +03:00
add_hw_list_option ( " Processor " , HW_LIST_TYPE_CPU , [ ] , " device_cpu " )
add_hw_list_option ( " Memory " , HW_LIST_TYPE_MEMORY , [ ] , " device_mem " )
add_hw_list_option ( " Boot Options " , HW_LIST_TYPE_BOOT , [ ] , " system-run " )
2007-04-11 22:48:36 +04:00
2009-11-04 21:18:14 +03:00
self . repopulate_hw_list ( )
2009-07-20 23:09:32 +04:00
2007-04-12 23:36:04 +04:00
def repopulate_hw_list ( self ) :
2007-04-13 02:54:33 +04:00
hw_list = self . window . get_widget ( " hw-list " )
hw_list_model = hw_list . get_model ( )
2007-04-11 22:48:36 +04:00
2010-09-08 02:38:01 +04:00
currentDevices = [ ]
def dev_cmp ( origdev , newdev ) :
if not origdev :
return False
if origdev == newdev :
return True
if not origdev . get_xml_node_path ( ) :
return False
return origdev . get_xml_node_path ( ) == newdev . get_xml_node_path ( )
def add_hw_list_option ( idx , name , page_id , info , icon_name ) :
2009-07-20 23:09:32 +04:00
hw_list_model . insert ( idx , [ name , icon_name ,
gtk . ICON_SIZE_LARGE_TOOLBAR ,
2010-09-08 02:38:01 +04:00
page_id , info ] )
2009-07-20 23:09:32 +04:00
2010-09-08 02:38:01 +04:00
def update_hwlist ( hwtype , info , name , icon_name ) :
2009-07-20 23:09:32 +04:00
"""
See if passed hw is already in list , and if so , update info .
If not in list , add it !
2009-01-15 19:17:30 +03:00
"""
2010-09-08 02:38:01 +04:00
currentDevices . append ( info )
2007-04-12 23:36:04 +04:00
insertAt = 0
for row in hw_list_model :
2010-09-08 02:38:01 +04:00
rowdev = row [ HW_LIST_COL_DEVICE ]
if dev_cmp ( rowdev , info ) :
2009-07-20 23:09:32 +04:00
# Update existing HW info
2009-01-15 19:17:30 +03:00
row [ HW_LIST_COL_DEVICE ] = info
2009-12-14 01:17:56 +03:00
row [ HW_LIST_COL_LABEL ] = name
2010-09-08 02:38:01 +04:00
row [ HW_LIST_COL_ICON_NAME ] = icon_name
2009-07-20 23:09:32 +04:00
return
2007-09-26 04:05:45 +04:00
2009-01-15 19:17:30 +03:00
if row [ HW_LIST_COL_TYPE ] < = hwtype :
insertAt + = 1
2009-07-20 23:09:32 +04:00
# Add the new HW row
2010-09-08 02:38:01 +04:00
add_hw_list_option ( insertAt , name , hwtype , info , icon_name )
2009-01-15 19:17:30 +03:00
# Populate list of disks
2010-09-03 22:10:04 +04:00
for disk in self . vm . get_disk_devices ( ) :
devtype = disk . device
bus = disk . bus
idx = disk . disk_bus_index
2010-09-03 22:05:29 +04:00
2009-07-20 23:09:32 +04:00
icon = " drive-harddisk "
2010-09-03 22:05:29 +04:00
if devtype == " cdrom " :
2009-07-20 23:09:32 +04:00
icon = " media-optical "
2010-09-03 22:05:29 +04:00
elif devtype == " floppy " :
2009-07-20 23:09:32 +04:00
icon = " media-floppy "
2009-12-02 05:34:29 +03:00
label = prettyify_disk ( devtype , bus , idx )
2010-09-08 02:38:01 +04:00
update_hwlist ( HW_LIST_TYPE_DISK , disk , label , icon )
2007-04-12 23:36:04 +04:00
# Populate list of NICs
2010-09-03 23:19:54 +04:00
for net in self . vm . get_network_devices ( ) :
mac = net . macaddr
2010-09-03 22:05:29 +04:00
2010-09-03 23:19:54 +04:00
update_hwlist ( HW_LIST_TYPE_NIC , net ,
2010-09-08 02:38:01 +04:00
" NIC %s " % mac [ - 9 : ] , " network-idle " )
2007-04-12 23:36:04 +04:00
2007-09-26 04:05:45 +04:00
# Populate list of input devices
2010-09-03 23:59:33 +04:00
for inp in self . vm . get_input_devices ( ) :
inptype = inp . type
2010-09-03 22:05:29 +04:00
2009-07-20 23:09:32 +04:00
icon = " input-mouse "
2010-09-03 22:05:29 +04:00
if inptype == " tablet " :
2009-07-20 23:09:32 +04:00
label = _ ( " Tablet " )
icon = " input-tablet "
2010-09-03 22:05:29 +04:00
elif inptype == " mouse " :
2009-07-20 23:09:32 +04:00
label = _ ( " Mouse " )
else :
label = _ ( " Input " )
2010-09-08 02:38:01 +04:00
update_hwlist ( HW_LIST_TYPE_INPUT , inp , label , icon )
2007-09-26 04:05:45 +04:00
2007-09-27 03:39:11 +04:00
# Populate list of graphics devices
2010-09-03 23:59:33 +04:00
for gfx in self . vm . get_graphics_devices ( ) :
update_hwlist ( HW_LIST_TYPE_GRAPHICS , gfx ,
2010-09-08 02:38:01 +04:00
_ ( " Display %s " ) % ( gfx . type . upper ( ) ) ,
" video-display " )
2007-09-27 03:39:11 +04:00
2008-07-31 03:52:39 +04:00
# Populate list of sound devices
2010-09-03 23:59:33 +04:00
for sound in self . vm . get_sound_devices ( ) :
update_hwlist ( HW_LIST_TYPE_SOUND , sound ,
2010-09-08 02:38:01 +04:00
_ ( " Sound: %s " % sound . model ) , " audio-card " )
2008-07-31 03:52:39 +04:00
2008-07-31 04:38:09 +04:00
# Populate list of char devices
2010-09-04 01:56:40 +04:00
for chardev in self . vm . get_char_devices ( ) :
devtype = chardev . virtual_device_type
2010-09-09 01:53:51 +04:00
port = chardev . target_port
2010-09-04 01:56:40 +04:00
2010-09-03 22:05:29 +04:00
label = devtype . capitalize ( )
if devtype != " console " :
2010-05-11 22:07:19 +04:00
# Don't show port for console
2010-09-03 22:05:29 +04:00
label + = " %s " % ( int ( port ) + 1 )
2009-01-15 19:17:30 +03:00
2010-09-04 01:56:40 +04:00
update_hwlist ( HW_LIST_TYPE_CHAR , chardev , label ,
2010-09-08 02:38:01 +04:00
" device_serial " )
2008-07-31 04:38:09 +04:00
2009-01-23 01:00:38 +03:00
# Populate host devices
2010-09-07 20:09:48 +04:00
for hostdev in self . vm . get_hostdev_devices ( ) :
devtype = hostdev . type
label = build_hostdev_label ( hostdev ) [ 1 ]
2010-09-03 22:05:29 +04:00
if devtype == " usb " :
2009-07-22 20:38:56 +04:00
icon = " device_usb "
else :
icon = " device_pci "
2010-09-08 02:38:01 +04:00
update_hwlist ( HW_LIST_TYPE_HOSTDEV , hostdev , label , icon )
2009-01-23 01:00:38 +03:00
2009-07-09 22:35:55 +04:00
# Populate video devices
2010-09-03 23:59:33 +04:00
for vid in self . vm . get_video_devices ( ) :
2010-09-08 02:38:01 +04:00
update_hwlist ( HW_LIST_TYPE_VIDEO , vid , _ ( " Video " ) , " video-display " )
2008-07-31 04:38:09 +04:00
2010-09-03 23:59:33 +04:00
for watch in self . vm . get_watchdog_devices ( ) :
update_hwlist ( HW_LIST_TYPE_WATCHDOG , watch , _ ( " Watchdog " ) ,
2010-09-08 02:38:01 +04:00
" device_pci " )
2010-03-24 07:22:17 +03:00
2007-04-13 02:54:33 +04:00
devs = range ( len ( hw_list_model ) )
devs . reverse ( )
for i in devs :
2008-11-19 01:01:22 +03:00
_iter = hw_list_model . iter_nth_child ( None , i )
2010-09-08 02:38:01 +04:00
olddev = hw_list_model [ i ] [ HW_LIST_COL_DEVICE ]
# Existing device, don't remove it
if not olddev or olddev in currentDevices :
continue
hw_list_model . remove ( _iter )
2007-04-13 02:54:33 +04:00
2010-02-25 04:37:41 +03:00
def repopulate_boot_list ( self , bootdevs = None , dev_select = None ) :
boot_list = self . window . get_widget ( " config-boot-list " )
boot_model = boot_list . get_model ( )
old_order = map ( lambda x : x [ BOOT_DEV_TYPE ] , boot_model )
2008-03-07 00:43:46 +03:00
boot_model . clear ( )
2010-02-25 04:37:41 +03:00
if bootdevs == None :
bootdevs = self . vm . get_boot_device ( )
boot_rows = {
" hd " : [ " hd " , " Hard Disk " , " drive-harddisk " , False ] ,
" cdrom " : [ " cdrom " , " CDROM " , " media-optical " , False ] ,
" network " : [ " network " , " Network (PXE) " , " network-idle " , False ] ,
" fd " : [ " fd " , " Floppy " , " media-floppy " , False ] ,
}
for dev in bootdevs :
foundrow = None
for key , row in boot_rows . items ( ) :
if key == dev :
foundrow = row
del ( boot_rows [ key ] )
break
if not foundrow :
# Some boot device listed that we don't know about.
foundrow = [ dev , " Boot type ' %s ' " % dev ,
" drive-harddisk " , True ]
foundrow [ BOOT_ACTIVE ] = True
boot_model . append ( foundrow )
# Append all remaining boot_rows that aren't enabled
for dev in old_order :
if boot_rows . has_key ( dev ) :
boot_model . append ( boot_rows [ dev ] )
del ( boot_rows [ dev ] )
for row in boot_rows . values ( ) :
boot_model . append ( row )
boot_list . set_model ( boot_model )
selection = boot_list . get_selection ( )
if dev_select :
idx = 0
for row in boot_model :
if row [ BOOT_DEV_TYPE ] == dev_select :
break
idx + = 1
boot_list . get_selection ( ) . select_path ( str ( idx ) )
elif not selection . get_selected ( ) [ 1 ] :
# Set a default selection
selection . select_path ( " 0 " )
2007-04-12 23:36:04 +04:00
2006-06-15 00:20:06 +04:00
gobject . type_register ( vmmDetails )