2006-06-28 15:50:17 -04:00
|
|
|
#
|
2008-04-08 13:30:47 -05:00
|
|
|
# Copyright (C) 2006-2008 Red Hat, Inc.
|
2006-06-28 15:50:17 -04:00
|
|
|
# Copyright (C) 2006 Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
|
#
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
|
# along with this program; if not, write to the Free Software
|
2007-11-20 11:12:20 -05:00
|
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
|
# MA 02110-1301 USA.
|
2006-06-28 15:50:17 -04:00
|
|
|
#
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-06-14 16:20:06 -04:00
|
|
|
import gobject
|
2006-06-14 10:59:40 -04:00
|
|
|
import gtk
|
|
|
|
|
import gtk.glade
|
2006-06-14 18:42:04 -04:00
|
|
|
import libvirt
|
2006-06-30 12:52:10 -04:00
|
|
|
import sparkline
|
2006-09-25 18:41:47 -04:00
|
|
|
import logging
|
2007-04-10 19:07:53 -04:00
|
|
|
import traceback
|
2007-11-16 17:12:37 -05:00
|
|
|
import sys
|
2008-04-08 13:30:47 -05:00
|
|
|
import dbus
|
|
|
|
|
import traceback
|
|
|
|
|
import gtkvnc
|
|
|
|
|
import os
|
|
|
|
|
import socket
|
2008-09-09 07:06:33 -04:00
|
|
|
import cairo
|
2007-04-10 19:07:53 -04:00
|
|
|
|
|
|
|
|
from virtManager.error import vmmErrorDialog
|
2007-04-12 15:36:04 -04:00
|
|
|
from virtManager.addhardware import vmmAddHardware
|
2007-09-21 16:28:31 -04:00
|
|
|
from virtManager.choosecd import vmmChooseCD
|
2008-10-02 16:17:25 -04:00
|
|
|
from virtManager.serialcon import vmmSerialConsole
|
2007-04-10 19:07:53 -04:00
|
|
|
|
2007-04-11 14:48:36 -04:00
|
|
|
import virtinst
|
|
|
|
|
import urlgrabber.progress as progress
|
|
|
|
|
|
2007-07-14 14:43:20 -04:00
|
|
|
# Columns in hw list model
|
|
|
|
|
HW_LIST_COL_LABEL = 0
|
|
|
|
|
HW_LIST_COL_STOCK_ID = 1
|
|
|
|
|
HW_LIST_COL_STOCK_SIZE = 2
|
|
|
|
|
HW_LIST_COL_PIXBUF = 3
|
|
|
|
|
HW_LIST_COL_TYPE = 4
|
|
|
|
|
HW_LIST_COL_DEVICE = 5
|
|
|
|
|
|
2008-07-23 16:23:56 -04:00
|
|
|
# Types for the hw list model: numbers specify what order they will be listed
|
2007-07-14 14:43:20 -04:00
|
|
|
HW_LIST_TYPE_CPU = 0
|
|
|
|
|
HW_LIST_TYPE_MEMORY = 1
|
2008-07-23 16:23:56 -04:00
|
|
|
HW_LIST_TYPE_BOOT = 2
|
|
|
|
|
HW_LIST_TYPE_DISK = 3
|
|
|
|
|
HW_LIST_TYPE_NIC = 4
|
|
|
|
|
HW_LIST_TYPE_INPUT = 5
|
|
|
|
|
HW_LIST_TYPE_GRAPHICS = 6
|
2008-07-30 19:52:39 -04:00
|
|
|
HW_LIST_TYPE_SOUND = 7
|
2008-07-30 20:38:09 -04:00
|
|
|
HW_LIST_TYPE_CHAR = 8
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
# Console pages
|
|
|
|
|
PAGE_UNAVAILABLE = 0
|
|
|
|
|
PAGE_SCREENSHOT = 1
|
|
|
|
|
PAGE_AUTHENTICATE = 2
|
|
|
|
|
PAGE_VNCVIEWER = 3
|
|
|
|
|
|
2008-05-07 11:14:20 -04:00
|
|
|
PAGE_CONSOLE = 0
|
|
|
|
|
PAGE_OVERVIEW = 1
|
|
|
|
|
PAGE_DETAILS = 2
|
2008-10-02 16:17:25 -04:00
|
|
|
PAGE_DYNAMIC_OFFSET = 3
|
2008-05-07 11:14:20 -04:00
|
|
|
|
2006-06-14 16:20:06 -04:00
|
|
|
class vmmDetails(gobject.GObject):
|
|
|
|
|
__gsignals__ = {
|
|
|
|
|
"action-show-console": (gobject.SIGNAL_RUN_FIRST,
|
|
|
|
|
gobject.TYPE_NONE, (str,str)),
|
2006-07-17 13:08:58 -04:00
|
|
|
"action-save-domain": (gobject.SIGNAL_RUN_FIRST,
|
2006-11-15 12:27:36 -05:00
|
|
|
gobject.TYPE_NONE, (str,str)),
|
|
|
|
|
"action-destroy-domain": (gobject.SIGNAL_RUN_FIRST,
|
2007-03-16 16:27:50 -04:00
|
|
|
gobject.TYPE_NONE, (str,str)),
|
2007-11-27 11:31:30 -05: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 13:30:47 -05:00
|
|
|
"action-reboot-domain": (gobject.SIGNAL_RUN_FIRST,
|
|
|
|
|
gobject.TYPE_NONE, (str, str)),
|
2007-03-16 16:27:50 -04:00
|
|
|
"action-show-help": (gobject.SIGNAL_RUN_FIRST,
|
|
|
|
|
gobject.TYPE_NONE, [str]),
|
2008-06-13 14:40:26 -04:00
|
|
|
"action-exit-app": (gobject.SIGNAL_RUN_FIRST,
|
|
|
|
|
gobject.TYPE_NONE, []),
|
|
|
|
|
"action-view-manager": (gobject.SIGNAL_RUN_FIRST,
|
|
|
|
|
gobject.TYPE_NONE, []),
|
2006-06-14 16:20:06 -04:00
|
|
|
}
|
2007-07-14 14:43:20 -04:00
|
|
|
|
|
|
|
|
|
2008-06-13 12:12:37 -04:00
|
|
|
def __init__(self, config, vm, engine):
|
2006-06-14 16:20:06 -04:00
|
|
|
self.__gobject_init__()
|
2007-02-15 15:35:37 -05:00
|
|
|
self.window = gtk.glade.XML(config.get_glade_dir() + "/vmm-details.glade", "vmm-details", domain="virt-manager")
|
2006-06-14 10:59:40 -04:00
|
|
|
self.config = config
|
|
|
|
|
self.vm = vm
|
|
|
|
|
|
|
|
|
|
topwin = self.window.get_widget("vmm-details")
|
2008-06-13 12:12:37 -04:00
|
|
|
topwin.hide_all()
|
2008-03-14 13:18:44 -04:00
|
|
|
self.err = vmmErrorDialog(topwin,
|
|
|
|
|
0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE,
|
|
|
|
|
_("Unexpected Error"),
|
|
|
|
|
_("An unexpected error occurred"))
|
2008-04-08 13:30:47 -05:00
|
|
|
self.title = vm.get_name() + " " + topwin.get_title()
|
|
|
|
|
topwin.set_title(self.title)
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2008-06-13 12:12:37 -04:00
|
|
|
self.engine = engine
|
2008-10-02 16:17:25 -04:00
|
|
|
self.dynamic_tabs = []
|
2008-06-13 12:12:37 -04:00
|
|
|
|
2007-04-12 17:50:22 -04:00
|
|
|
# Don't allowing changing network/disks for Dom0
|
2008-09-05 09:41:38 -04:00
|
|
|
if self.vm.is_management_domain():
|
2007-04-12 17:50:22 -04:00
|
|
|
self.window.get_widget("add-hardware-button").set_sensitive(False)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("add-hardware-button").set_sensitive(True)
|
|
|
|
|
|
2006-06-14 17:52:49 -04:00
|
|
|
self.window.get_widget("overview-name").set_text(self.vm.get_name())
|
|
|
|
|
self.window.get_widget("overview-uuid").set_text(self.vm.get_uuid())
|
2006-06-14 10:59:40 -04:00
|
|
|
|
|
|
|
|
self.window.get_widget("control-shutdown").set_icon_widget(gtk.Image())
|
2006-07-19 12:42:19 -04:00
|
|
|
self.window.get_widget("control-shutdown").get_icon_widget().set_from_file(config.get_icon_dir() + "/icon_shutdown.png")
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
menu = gtk.Menu()
|
|
|
|
|
self.window.get_widget("control-shutdown").set_menu(menu)
|
|
|
|
|
|
|
|
|
|
rebootimg = gtk.Image()
|
|
|
|
|
rebootimg.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(self.config.get_icon_dir() + "/icon_shutdown.png", 18, 18))
|
|
|
|
|
shutdownimg = gtk.Image()
|
|
|
|
|
shutdownimg.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(self.config.get_icon_dir() + "/icon_shutdown.png", 18, 18))
|
|
|
|
|
destroyimg = gtk.Image()
|
|
|
|
|
destroyimg.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(self.config.get_icon_dir() + "/icon_shutdown.png", 18, 18))
|
|
|
|
|
|
|
|
|
|
reboot = gtk.ImageMenuItem("_Reboot")
|
|
|
|
|
reboot.set_image(rebootimg)
|
|
|
|
|
reboot.show()
|
|
|
|
|
reboot.connect("activate", self.control_vm_reboot)
|
|
|
|
|
menu.add(reboot)
|
|
|
|
|
|
|
|
|
|
shutdown = gtk.ImageMenuItem("_Poweroff")
|
|
|
|
|
shutdown.set_image(shutdownimg)
|
|
|
|
|
shutdown.show()
|
|
|
|
|
shutdown.connect("activate", self.control_vm_shutdown)
|
|
|
|
|
menu.add(shutdown)
|
|
|
|
|
|
|
|
|
|
destroy = gtk.ImageMenuItem("_Force poweroff")
|
|
|
|
|
destroy.set_image(destroyimg)
|
|
|
|
|
destroy.show()
|
|
|
|
|
destroy.connect("activate", self.control_vm_destroy)
|
|
|
|
|
menu.add(destroy)
|
|
|
|
|
|
2008-10-02 16:17:25 -04:00
|
|
|
smenu = gtk.Menu()
|
|
|
|
|
smenu.connect("show", self.populate_serial_menu)
|
|
|
|
|
self.window.get_widget("details-menu-view-serial-list").set_submenu(smenu)
|
|
|
|
|
|
|
|
|
|
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)
|
2008-04-08 13:30:47 -05:00
|
|
|
|
2006-06-14 10:59:40 -04:00
|
|
|
self.window.get_widget("hw-panel").set_show_tabs(False)
|
|
|
|
|
|
2007-04-12 15:36:04 -04:00
|
|
|
self.addhw = None
|
2007-09-21 16:28:31 -04:00
|
|
|
self.choose_cd = None
|
|
|
|
|
|
2006-06-30 12:52:10 -04:00
|
|
|
self.cpu_usage_graph = sparkline.Sparkline()
|
2008-10-06 12:56:11 -04:00
|
|
|
self.cpu_usage_graph.set_property("reversed", True)
|
2006-06-30 12:52:10 -04:00
|
|
|
self.window.get_widget("graph-table").attach(self.cpu_usage_graph, 1, 2, 0, 1)
|
|
|
|
|
|
|
|
|
|
self.memory_usage_graph = sparkline.Sparkline()
|
2008-10-06 12:56:11 -04:00
|
|
|
self.memory_usage_graph.set_property("reversed", True)
|
2006-06-30 12:52:10 -04:00
|
|
|
self.window.get_widget("graph-table").attach(self.memory_usage_graph, 1, 2, 1, 2)
|
|
|
|
|
|
2008-10-18 21:21:33 +02:00
|
|
|
self.disk_io_graph = sparkline.Sparkline()
|
|
|
|
|
self.disk_io_graph.set_property("reversed", True)
|
2008-10-18 21:24:19 +02:00
|
|
|
self.disk_io_graph.set_property("filled", False)
|
|
|
|
|
self.disk_io_graph.set_property("num_sets", 2)
|
2008-10-18 21:25:16 +02:00
|
|
|
self.disk_io_graph.set_property("rgb", map(lambda x: x/255.0,
|
|
|
|
|
[0x82, 0x00, 0x3B, 0x29, 0x5C, 0x45]))
|
2008-10-18 21:21:33 +02:00
|
|
|
self.window.get_widget("graph-table").attach(self.disk_io_graph, 1, 2, 2, 3)
|
|
|
|
|
|
2006-06-30 12:52:10 -04:00
|
|
|
self.network_traffic_graph = sparkline.Sparkline()
|
2008-10-06 12:56:11 -04:00
|
|
|
self.network_traffic_graph.set_property("reversed", True)
|
2008-10-18 21:24:19 +02:00
|
|
|
self.network_traffic_graph.set_property("filled", False)
|
|
|
|
|
self.network_traffic_graph.set_property("num_sets", 2)
|
2008-10-18 21:25:16 +02:00
|
|
|
self.network_traffic_graph.set_property("rgb", map(lambda x: x/255.0,
|
|
|
|
|
[0x82, 0x00, 0x3B, 0x29, 0x5C, 0x45]))
|
2006-06-30 12:52:10 -04:00
|
|
|
self.window.get_widget("graph-table").attach(self.network_traffic_graph, 1, 2, 3, 4)
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
self.accel_groups = gtk.accel_groups_from_object(topwin)
|
|
|
|
|
self.gtk_settings_accel = None
|
|
|
|
|
|
|
|
|
|
self.vncViewer = gtkvnc.Display()
|
|
|
|
|
self.window.get_widget("console-vnc-viewport").add(self.vncViewer)
|
|
|
|
|
self.vncViewer.realize()
|
|
|
|
|
self.vncTunnel = None
|
|
|
|
|
if self.config.get_console_keygrab() == 2:
|
|
|
|
|
self.vncViewer.set_keyboard_grab(True)
|
|
|
|
|
else:
|
|
|
|
|
self.vncViewer.set_keyboard_grab(False)
|
|
|
|
|
self.vncViewer.set_pointer_grab(True)
|
|
|
|
|
if not topwin.is_composited():
|
|
|
|
|
self.vncViewer.set_scaling(True)
|
|
|
|
|
self.window.get_widget("details-menu-view-scale-display").set_active(True)
|
|
|
|
|
|
|
|
|
|
self.vncViewer.connect("vnc-pointer-grab", self.notify_grabbed)
|
|
|
|
|
self.vncViewer.connect("vnc-pointer-ungrab", self.notify_ungrabbed)
|
|
|
|
|
|
|
|
|
|
self.vncViewer.show()
|
|
|
|
|
self.vncViewerRetriesScheduled = 0
|
|
|
|
|
self.vncViewerRetryDelay = 125
|
|
|
|
|
self.vncViewer.connect("size-request", self._force_resize)
|
|
|
|
|
self.vncViewer.connect("vnc-auth-credential", self._vnc_auth_credential)
|
|
|
|
|
self.vncViewer.connect("vnc-initialized", self._vnc_initialized)
|
|
|
|
|
self.vncViewer.connect("vnc-disconnected", self._vnc_disconnected)
|
|
|
|
|
self.vncViewer.connect("vnc-keyboard-grab", self._disable_modifiers)
|
|
|
|
|
self.vncViewer.connect("vnc-keyboard-ungrab", self._enable_modifiers)
|
|
|
|
|
self.connected = 0
|
|
|
|
|
|
|
|
|
|
self.notifyID = None
|
|
|
|
|
try:
|
|
|
|
|
bus = dbus.SessionBus()
|
|
|
|
|
self.notifyObject = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
|
|
|
|
|
self.notifyInterface = dbus.Interface(self.notifyObject, "org.freedesktop.Notifications")
|
|
|
|
|
self.notifyInterface.connect_to_signal("ActionInvoked", self.notify_action)
|
|
|
|
|
self.notifyInterface.connect_to_signal("NotificationClosed", self.notify_closed)
|
|
|
|
|
except Exception, e:
|
|
|
|
|
logging.error("Cannot initialize notification system" + str(e))
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
self.window.get_widget("console-pages").set_show_tabs(False)
|
2008-09-05 16:34:14 -04:00
|
|
|
self.window.get_widget("details-menu-view-toolbar").set_active(self.config.get_details_show_toolbar())
|
2008-04-08 13:30:47 -05:00
|
|
|
|
2006-06-14 10:59:40 -04:00
|
|
|
self.window.signal_autoconnect({
|
|
|
|
|
"on_close_details_clicked": self.close,
|
2006-09-01 11:18:49 -04:00
|
|
|
"on_details_menu_close_activate": self.close,
|
2006-06-14 10:59:40 -04:00
|
|
|
"on_vmm_details_delete_event": self.close,
|
2008-06-13 14:40:26 -04:00
|
|
|
"on_details_menu_quit_activate": self.exit_app,
|
2006-06-14 10: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 13:30:47 -05:00
|
|
|
"on_control_fullscreen_toggled": self.control_fullscreen,
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-09-01 11:18:49 -04:00
|
|
|
"on_details_menu_run_activate": self.control_vm_run,
|
2008-04-08 13:30:47 -05:00
|
|
|
"on_details_menu_poweroff_activate": self.control_vm_shutdown,
|
|
|
|
|
"on_details_menu_reboot_activate": self.control_vm_reboot,
|
2006-09-01 11:18:49 -04:00
|
|
|
"on_details_menu_save_activate": self.control_vm_save_domain,
|
2006-11-15 12:27:36 -05:00
|
|
|
"on_details_menu_destroy_activate": self.control_vm_destroy,
|
2007-09-27 17:52:29 -04:00
|
|
|
"on_details_menu_pause_activate": self.control_vm_pause,
|
2008-05-07 11:40:29 -04:00
|
|
|
"on_details_menu_screenshot_activate": self.control_vm_screenshot,
|
2006-09-01 11: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 14:40:26 -04:00
|
|
|
"on_details_menu_view_manager_activate": self.view_manager,
|
2006-09-01 11:18:49 -04:00
|
|
|
|
2008-05-07 11:26:00 -04:00
|
|
|
"on_details_pages_switch_page": self.switch_page,
|
|
|
|
|
|
2006-11-13 15:31:17 -05:00
|
|
|
"on_config_vcpus_apply_clicked": self.config_vcpus_apply,
|
|
|
|
|
"on_config_vcpus_changed": self.config_vcpus_changed,
|
|
|
|
|
"on_config_memory_changed": self.config_memory_changed,
|
|
|
|
|
"on_config_maxmem_changed": self.config_maxmem_changed,
|
2007-03-16 16:27:50 -04:00
|
|
|
"on_config_memory_apply_clicked": self.config_memory_apply,
|
2008-03-06 16:43:46 -05:00
|
|
|
"on_config_boot_device_changed": self.config_boot_options_changed,
|
|
|
|
|
"on_config_autostart_changed": self.config_boot_options_changed,
|
|
|
|
|
"on_config_boot_apply_clicked": self.config_boot_options_apply,
|
2007-03-16 16:27:50 -04:00
|
|
|
"on_details_help_activate": self.show_help,
|
2007-04-11 14:48:36 -04:00
|
|
|
|
2007-09-21 16:28:31 -04:00
|
|
|
"on_config_cdrom_connect_clicked": self.toggle_cdrom,
|
2007-04-12 18:54:33 -04:00
|
|
|
"on_config_disk_remove_clicked": self.remove_disk,
|
|
|
|
|
"on_config_network_remove_clicked": self.remove_network,
|
2007-09-25 20:05:45 -04:00
|
|
|
"on_config_input_remove_clicked": self.remove_input,
|
2007-09-26 19:39:11 -04:00
|
|
|
"on_config_graphics_remove_clicked": self.remove_graphics,
|
2008-07-30 19:52:39 -04:00
|
|
|
"on_config_sound_remove_clicked": self.remove_sound,
|
2008-07-30 20:38:09 -04:00
|
|
|
"on_config_char_remove_clicked": self.remove_char,
|
2007-04-11 14:48:36 -04:00
|
|
|
"on_add_hardware_button_clicked": self.add_hardware,
|
2008-04-08 13:30:47 -05:00
|
|
|
|
|
|
|
|
"on_details_menu_view_fullscreen_activate": self.toggle_fullscreen,
|
|
|
|
|
"on_details_menu_view_toolbar_activate": self.toggle_toolbar,
|
|
|
|
|
"on_details_menu_view_scale_display_activate": self.scale_display,
|
|
|
|
|
|
|
|
|
|
"on_details_menu_send_cad_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_cab_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf1_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf2_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf3_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf4_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf5_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf6_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf7_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf8_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf9_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf10_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf11_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_caf12_activate": self.send_key,
|
|
|
|
|
"on_details_menu_send_printscreen_activate": self.send_key,
|
2006-06-14 10:59:40 -04:00
|
|
|
})
|
|
|
|
|
|
2006-06-14 18:42:04 -04:00
|
|
|
self.vm.connect("status-changed", self.update_widget_states)
|
|
|
|
|
self.vm.connect("resources-sampled", self.refresh_resources)
|
2007-04-11 14:48:36 -04:00
|
|
|
self.window.get_widget("hw-list").get_selection().connect("changed", self.hw_selected)
|
|
|
|
|
|
2007-04-25 17:09:37 -04:00
|
|
|
self.update_widget_states(self.vm, self.vm.status())
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2007-04-11 14:48:36 -04:00
|
|
|
self.pixbuf_processor = gtk.gdk.pixbuf_new_from_file(config.get_icon_dir() + "/icon_cpu.png")
|
|
|
|
|
self.pixbuf_memory = gtk.gdk.pixbuf_new_from_file(config.get_icon_dir() + "/icon_cpu.png")
|
|
|
|
|
self.prepare_hw_list()
|
|
|
|
|
self.hw_selected()
|
2008-06-13 12:12:37 -04:00
|
|
|
self.refresh_resources(self.vm)
|
2006-08-29 15:52:19 -04:00
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
|
|
|
|
|
# Black magic todo with scrolled windows. Basically the behaviour we want
|
|
|
|
|
# is that if it possible to resize the window to show entire guest desktop
|
|
|
|
|
# then we should do that and never show scrollbars. If the local screen is
|
|
|
|
|
# too small then we can turn on scrolling. You would think the 'Automatic'
|
|
|
|
|
# policy would work, but even if viewport is identical sized to the VNC
|
|
|
|
|
# widget it still seems to show scrollbars. So we do evil stuff here
|
|
|
|
|
def _force_resize(self, src, size):
|
|
|
|
|
w,h = src.get_size_request()
|
|
|
|
|
if w == -1 or h == -1:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
topw,toph = self.window.get_widget("vmm-details").size_request()
|
|
|
|
|
|
|
|
|
|
padx = topw-w
|
|
|
|
|
pady = toph-h
|
|
|
|
|
rootw = src.get_screen().get_width()
|
|
|
|
|
rooth = src.get_screen().get_height()
|
|
|
|
|
|
|
|
|
|
maxw = rootw - 100 - padx
|
|
|
|
|
maxh = rooth - 100 - pady
|
2008-05-05 16:10:37 -04:00
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
self.window.get_widget("console-vnc-viewport").set_size_request(w, h)
|
|
|
|
|
self.window.get_widget("console-screenshot").set_size_request(w, h)
|
|
|
|
|
self.window.get_widget("console-screenshot-viewport").set_size_request(w, h)
|
|
|
|
|
self.window.get_widget("console-vnc-scroll").set_size_request(w, h)
|
|
|
|
|
if w > maxw or h > maxh:
|
|
|
|
|
self.window.get_widget("console-vnc-scroll").set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS)
|
|
|
|
|
self.window.get_widget("console-screenshot-scroll").set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("console-vnc-scroll").set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER)
|
|
|
|
|
self.window.get_widget("console-screenshot-scroll").set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER)
|
|
|
|
|
|
|
|
|
|
def _disable_modifiers(self, ignore=None):
|
|
|
|
|
topwin = self.window.get_widget("vmm-details")
|
|
|
|
|
for g in self.accel_groups:
|
|
|
|
|
topwin.remove_accel_group(g)
|
|
|
|
|
settings = gtk.settings_get_default()
|
|
|
|
|
self.gtk_settings_accel = settings.get_property('gtk-menu-bar-accel')
|
|
|
|
|
settings.set_property('gtk-menu-bar-accel', None)
|
|
|
|
|
|
|
|
|
|
def _enable_modifiers(self, ignore=None):
|
|
|
|
|
topwin = self.window.get_widget("vmm-details")
|
|
|
|
|
if self.gtk_settings_accel is None:
|
|
|
|
|
return
|
|
|
|
|
settings = gtk.settings_get_default()
|
|
|
|
|
settings.set_property('gtk-menu-bar-accel', self.gtk_settings_accel)
|
|
|
|
|
self.gtk_settings_accel = None
|
|
|
|
|
for g in self.accel_groups:
|
|
|
|
|
topwin.add_accel_group(g)
|
|
|
|
|
|
|
|
|
|
def notify_grabbed(self, src):
|
|
|
|
|
topwin = self.window.get_widget("vmm-details")
|
|
|
|
|
topwin.set_title(_("Press Ctrl+Alt to release pointer.") + " " + self.title)
|
|
|
|
|
|
|
|
|
|
if self.config.show_console_grab_notify():
|
|
|
|
|
try:
|
|
|
|
|
(x, y) = topwin.window.get_origin()
|
|
|
|
|
self.notifyID = self.notifyInterface.Notify(topwin.get_title(),
|
|
|
|
|
0,
|
|
|
|
|
'',
|
|
|
|
|
_("Pointer grabbed"),
|
|
|
|
|
_("The mouse pointer has been restricted to the virtual " \
|
|
|
|
|
"console window. To release the pointer press the key pair " \
|
|
|
|
|
"Ctrl+Alt"),
|
|
|
|
|
["dismiss", _("Do not show this notification in the future")],
|
|
|
|
|
{"desktop-entry": "virt-manager",
|
|
|
|
|
"x": x+200, "y": y},
|
|
|
|
|
8 * 1000);
|
|
|
|
|
except Exception, e:
|
|
|
|
|
logging.error("Cannot popup notification " + str(e))
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def notify_ungrabbed(self, src):
|
|
|
|
|
topwin = self.window.get_widget("vmm-details")
|
|
|
|
|
topwin.set_title(self.title)
|
|
|
|
|
|
|
|
|
|
def notify_closed(self, id, reason=None):
|
|
|
|
|
if self.notifyID is not None and self.notifyID == id:
|
|
|
|
|
self.notifyID = None
|
|
|
|
|
|
|
|
|
|
def notify_action(self, id, action):
|
|
|
|
|
if self.notifyID is None or self.notifyID != id:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if action == "dismiss":
|
|
|
|
|
self.config.set_console_grab_notify(False)
|
|
|
|
|
|
|
|
|
|
def keygrab_changed(self, src, ignore1=None,ignore2=None,ignore3=None):
|
|
|
|
|
if self.config.get_console_keygrab() == 2:
|
|
|
|
|
self.vncViewer.set_keyboard_grab(True)
|
|
|
|
|
else:
|
|
|
|
|
self.vncViewer.set_keyboard_grab(False)
|
|
|
|
|
|
|
|
|
|
def scale_display(self, src):
|
|
|
|
|
if src.get_active():
|
|
|
|
|
self.vncViewer.set_scaling(True)
|
|
|
|
|
else:
|
|
|
|
|
self.vncViewer.set_scaling(False)
|
|
|
|
|
|
|
|
|
|
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())
|
|
|
|
|
|
|
|
|
|
def toggle_fullscreen(self, src):
|
|
|
|
|
self.window.get_widget("control-fullscreen").set_active(src.get_active())
|
2006-09-01 11:18:49 -04:00
|
|
|
if src.get_active():
|
2008-04-08 13:30:47 -05:00
|
|
|
self.window.get_widget("vmm-details").fullscreen()
|
|
|
|
|
if self.config.get_console_keygrab() == 1:
|
|
|
|
|
gtk.gdk.keyboard_grab(self.vncViewer.window, False, 0L)
|
|
|
|
|
self._disable_modifiers()
|
|
|
|
|
|
|
|
|
|
tabs = self.window.get_widget("details-pages")
|
|
|
|
|
tabs.set_show_tabs(False)
|
|
|
|
|
tabs.set_border_width(0)
|
|
|
|
|
self.window.get_widget("details-toolbar").hide()
|
|
|
|
|
else:
|
|
|
|
|
if self.config.get_console_keygrab() == 1:
|
|
|
|
|
self._enable_modifiers()
|
|
|
|
|
gtk.gdk.keyboard_ungrab(0L)
|
|
|
|
|
self.window.get_widget("vmm-details").unfullscreen()
|
|
|
|
|
|
|
|
|
|
tabs = self.window.get_widget("details-pages")
|
|
|
|
|
tabs.set_show_tabs(True)
|
|
|
|
|
tabs.set_border_width(6)
|
|
|
|
|
if self.window.get_widget("details-menu-view-toolbar").get_active():
|
|
|
|
|
self.window.get_widget("details-toolbar").show()
|
|
|
|
|
|
|
|
|
|
def toggle_toolbar(self, src):
|
2008-09-05 16:34:14 -04:00
|
|
|
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():
|
2006-09-01 11:18:49 -04:00
|
|
|
self.window.get_widget("details-toolbar").show()
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("details-toolbar").hide()
|
|
|
|
|
|
2008-10-02 16: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:
|
|
|
|
|
item = gtk.CheckMenuItem(_("No serial devices found"))
|
|
|
|
|
item.set_sensitive(False)
|
|
|
|
|
src.add(item)
|
|
|
|
|
|
|
|
|
|
usable_types = [ "pty" ]
|
|
|
|
|
for dev in devs:
|
|
|
|
|
sensitive = False
|
|
|
|
|
msg = ""
|
|
|
|
|
item = gtk.CheckMenuItem(dev[0])
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
item.set_tooltip_text(msg)
|
|
|
|
|
item.set_sensitive(sensitive)
|
|
|
|
|
|
|
|
|
|
if sensitive and self.dynamic_tabs.count(dev[0]):
|
|
|
|
|
# Tab is already open, make sure marked as such
|
|
|
|
|
item.set_active(True)
|
|
|
|
|
item.connect("activate", self.control_serial_tab, dev[0], dev[2])
|
|
|
|
|
src.add(item)
|
|
|
|
|
|
|
|
|
|
src.show_all()
|
|
|
|
|
|
2006-06-14 10:59:40 -04:00
|
|
|
def show(self):
|
2008-06-13 14:40:26 -04:00
|
|
|
dialog = self.window.get_widget("vmm-details")
|
2008-06-13 12:12:37 -04:00
|
|
|
if self.is_visible():
|
2008-06-13 14:40:26 -04:00
|
|
|
dialog.present()
|
2008-06-13 12:12:37 -04:00
|
|
|
return
|
2006-06-14 10:59:40 -04:00
|
|
|
dialog.show_all()
|
|
|
|
|
dialog.present()
|
2008-06-13 12:12:37 -04:00
|
|
|
self.engine.increment_window_counter()
|
2007-04-25 17:09:37 -04:00
|
|
|
self.update_widget_states(self.vm, self.vm.status())
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2007-03-16 16:27:50 -04:00
|
|
|
def show_help(self, src):
|
|
|
|
|
# From the Details window, show the help document from the Details page
|
2007-04-12 15:36:04 -04:00
|
|
|
self.emit("action-show-help", "virt-manager-details-window")
|
2007-03-16 16:27:50 -04:00
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
def activate_console_page(self):
|
2008-05-07 11:14:20 -04:00
|
|
|
self.window.get_widget("details-pages").set_current_page(PAGE_CONSOLE)
|
2006-07-13 17:44:49 -04:00
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
def activate_performance_page(self):
|
2008-05-07 11:14:20 -04:00
|
|
|
self.window.get_widget("details-pages").set_current_page(PAGE_OVERVIEW)
|
2006-07-13 17:44:49 -04:00
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
def activate_config_page(self):
|
2008-05-07 11:14:20 -04:00
|
|
|
self.window.get_widget("details-pages").set_current_page(PAGE_DETAILS)
|
2008-04-08 13:30:47 -05:00
|
|
|
|
2006-06-14 10:59:40 -04:00
|
|
|
def close(self,ignore1=None,ignore2=None):
|
2008-04-08 13:30:47 -05:00
|
|
|
fs = self.window.get_widget("details-menu-view-fullscreen")
|
|
|
|
|
if fs.get_active():
|
|
|
|
|
fs.set_active(False)
|
|
|
|
|
|
2008-08-18 11:47:29 -04:00
|
|
|
if not self.is_visible():
|
|
|
|
|
return
|
|
|
|
|
|
2006-06-14 10:59:40 -04:00
|
|
|
self.window.get_widget("vmm-details").hide()
|
2008-04-08 13:30:47 -05:00
|
|
|
if self.vncViewer.flags() & gtk.VISIBLE:
|
2008-06-13 12:12:37 -04:00
|
|
|
try:
|
2008-04-08 13:30:47 -05:00
|
|
|
self.vncViewer.close()
|
2008-06-13 12:12:37 -04:00
|
|
|
except:
|
|
|
|
|
logging.error("Failure when disconnecting from VNC server")
|
|
|
|
|
self.engine.decrement_window_counter()
|
2006-06-14 10:59:40 -04:00
|
|
|
return 1
|
|
|
|
|
|
2008-06-13 14:40:26 -04:00
|
|
|
def exit_app(self, src):
|
|
|
|
|
self.emit("action-exit-app")
|
|
|
|
|
|
2006-11-03 10:02:02 -05:00
|
|
|
def is_visible(self):
|
|
|
|
|
if self.window.get_widget("vmm-details").flags() & gtk.VISIBLE:
|
|
|
|
|
return 1
|
|
|
|
|
return 0
|
|
|
|
|
|
2008-06-13 14:40:26 -04:00
|
|
|
def view_manager(self, src):
|
|
|
|
|
self.emit("action-view-manager")
|
|
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
def send_key(self, src):
|
|
|
|
|
keys = None
|
|
|
|
|
if src.get_name() == "details-menu-send-cad":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "Delete"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-cab":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "BackSpace"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf1":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F1"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf2":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F2"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf3":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F3"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf4":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F4"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf5":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F5"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf6":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F6"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf7":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F7"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf8":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F8"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf9":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F9"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf10":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F10"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf11":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F11"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-caf12":
|
|
|
|
|
keys = ["Control_L", "Alt_L", "F12"]
|
|
|
|
|
elif src.get_name() == "details-menu-send-printscreen":
|
2008-05-05 16:10:16 -04:00
|
|
|
keys = ["Print"]
|
2008-04-08 13:30:47 -05:00
|
|
|
|
|
|
|
|
if keys != None:
|
|
|
|
|
self.vncViewer.send_keys(keys)
|
|
|
|
|
|
|
|
|
|
|
2006-06-14 10:59:40 -04:00
|
|
|
def hw_selected(self, src=None):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
2006-09-01 15:51:50 -04:00
|
|
|
if active[1] != None:
|
2007-07-14 14:43:20 -04:00
|
|
|
pagetype = active[0].get_value(active[1], HW_LIST_COL_TYPE)
|
2006-06-14 10:59:40 -04:00
|
|
|
self.window.get_widget("hw-panel").set_sensitive(True)
|
2008-07-18 21:34:13 -04:00
|
|
|
self.window.get_widget("hw-panel").show_all()
|
2006-11-13 15:31:17 -05:00
|
|
|
|
2007-09-26 19:39:11 -04:00
|
|
|
pagenum = pagetype
|
2007-07-14 14:43:20 -04:00
|
|
|
if pagetype == HW_LIST_TYPE_CPU:
|
2006-11-13 15:31:17 -05:00
|
|
|
self.window.get_widget("config-vcpus-apply").set_sensitive(False)
|
|
|
|
|
self.refresh_config_cpu()
|
2007-07-14 14:43:20 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_MEMORY:
|
2006-11-13 15:31:17 -05:00
|
|
|
self.window.get_widget("config-memory-apply").set_sensitive(False)
|
|
|
|
|
self.refresh_config_memory()
|
2007-07-14 14:43:20 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_DISK:
|
2007-04-11 14:48:36 -04:00
|
|
|
self.refresh_disk_page()
|
2007-07-14 14:43:20 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_NIC:
|
2007-04-11 14:48:36 -04:00
|
|
|
self.refresh_network_page()
|
2007-09-25 20:05:45 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_INPUT:
|
|
|
|
|
self.refresh_input_page()
|
2007-09-26 19:39:11 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_GRAPHICS:
|
|
|
|
|
self.refresh_graphics_page()
|
2008-07-30 19:52:39 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_SOUND:
|
|
|
|
|
self.refresh_sound_page()
|
2008-07-30 20:38:09 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_CHAR:
|
|
|
|
|
self.refresh_char_page()
|
2008-03-06 16:43:46 -05:00
|
|
|
elif pagetype == HW_LIST_TYPE_BOOT:
|
|
|
|
|
self.refresh_boot_page()
|
|
|
|
|
self.window.get_widget("config-boot-options-apply").set_sensitive(False)
|
2007-09-26 19:39:11 -04:00
|
|
|
else:
|
|
|
|
|
pagenum = -1
|
2007-04-12 15:36:04 -04:00
|
|
|
|
2007-04-11 14:48:36 -04:00
|
|
|
self.window.get_widget("hw-panel").set_current_page(pagenum)
|
2006-06-14 10:59:40 -04:00
|
|
|
else:
|
2007-04-12 15:36:04 -04:00
|
|
|
self.window.get_widget("hw-panel").set_sensitive(False)
|
2006-11-15 10:51:40 -05:00
|
|
|
selection.select_path(0)
|
|
|
|
|
self.window.get_widget("hw-panel").set_current_page(0)
|
2006-06-14 10:59:40 -04:00
|
|
|
|
|
|
|
|
def control_vm_pause(self, src):
|
2006-06-14 18:42:04 -04:00
|
|
|
if self.ignorePause:
|
|
|
|
|
return
|
|
|
|
|
|
2007-11-27 11:31:30 -05:00
|
|
|
if src.get_active():
|
|
|
|
|
self.emit("action-suspend-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid())
|
2006-06-14 10:59:40 -04:00
|
|
|
else:
|
2007-11-27 11:31:30 -05:00
|
|
|
self.emit("action-resume-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid())
|
|
|
|
|
|
|
|
|
|
self.update_widget_states(self.vm, self.vm.status())
|
|
|
|
|
|
|
|
|
|
def control_vm_run(self, src):
|
|
|
|
|
self.emit("action-run-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid())
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2007-11-27 11:31:30 -05:00
|
|
|
def control_vm_shutdown(self, src):
|
|
|
|
|
self.emit("action-shutdown-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid())
|
2006-09-01 11:18:49 -04:00
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
def control_vm_reboot(self, src):
|
|
|
|
|
self.emit("action-reboot-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid())
|
|
|
|
|
|
2006-06-14 18: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())
|
|
|
|
|
|
2006-07-17 13:08:58 -04:00
|
|
|
def control_vm_save_domain(self, src):
|
|
|
|
|
self.emit("action-save-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid())
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-11-15 12:27:36 -05:00
|
|
|
def control_vm_destroy(self, src):
|
|
|
|
|
self.emit("action-destroy-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid())
|
|
|
|
|
|
2008-08-19 14:25:25 -04:00
|
|
|
def set_pause_widget_states(self, state):
|
|
|
|
|
try:
|
|
|
|
|
self.ignorePause = True
|
|
|
|
|
self.window.get_widget("control-pause").set_active(state)
|
|
|
|
|
self.window.get_widget("details-menu-pause").set_active(state)
|
|
|
|
|
finally:
|
|
|
|
|
self.ignorePause = False
|
|
|
|
|
|
2006-06-14 18:42:04 -04:00
|
|
|
def update_widget_states(self, vm, status):
|
2007-04-25 17:09:37 -04:00
|
|
|
self.toggle_toolbar(self.window.get_widget("details-menu-view-toolbar"))
|
2008-07-24 16:39:09 -04:00
|
|
|
|
2008-08-19 14:25:25 -04:00
|
|
|
if status in [ libvirt.VIR_DOMAIN_SHUTDOWN,
|
|
|
|
|
libvirt.VIR_DOMAIN_SHUTOFF ] or vm.is_read_only():
|
2006-11-15 12:27:36 -05:00
|
|
|
self.window.get_widget("details-menu-destroy").set_sensitive(False)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("details-menu-destroy").set_sensitive(True)
|
2008-08-19 14:25:25 -04:00
|
|
|
|
2008-08-22 13:41:17 -04:00
|
|
|
if status in [ libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_CRASHED ] and not self.vm.is_read_only():
|
2008-08-19 14:25:25 -04:00
|
|
|
self.window.get_widget("control-run").set_sensitive(True)
|
|
|
|
|
self.window.get_widget("details-menu-run").set_sensitive(True)
|
|
|
|
|
self.window.get_widget("config-vcpus").set_sensitive(True)
|
|
|
|
|
self.window.get_widget("config-memory").set_sensitive(True)
|
|
|
|
|
self.window.get_widget("config-maxmem").set_sensitive(True)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("control-run").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("details-menu-run").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("config-vcpus").set_sensitive(self.vm.is_vcpu_hotplug_capable())
|
|
|
|
|
self.window.get_widget("config-memory").set_sensitive(self.vm.is_memory_hotplug_capable())
|
|
|
|
|
self.window.get_widget("config-maxmem").set_sensitive(True)
|
|
|
|
|
|
|
|
|
|
if status in [libvirt.VIR_DOMAIN_SHUTDOWN, libvirt.VIR_DOMAIN_SHUTOFF,
|
|
|
|
|
libvirt.VIR_DOMAIN_CRASHED ] or vm.is_read_only():
|
|
|
|
|
self.set_pause_widget_states(False)
|
|
|
|
|
self.window.get_widget("control-shutdown").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("details-menu-shutdown").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("details-menu-save").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("control-pause").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("details-menu-pause").set_sensitive(False)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("control-pause").set_sensitive(True)
|
|
|
|
|
self.window.get_widget("details-menu-pause").set_sensitive(True)
|
|
|
|
|
self.set_pause_widget_states(status == libvirt.VIR_DOMAIN_PAUSED)
|
|
|
|
|
self.window.get_widget("control-shutdown").set_sensitive(True)
|
|
|
|
|
self.window.get_widget("details-menu-shutdown").set_sensitive(True)
|
|
|
|
|
self.window.get_widget("details-menu-save").set_sensitive(True)
|
2008-04-08 13:30:47 -05:00
|
|
|
|
|
|
|
|
if status in [ libvirt.VIR_DOMAIN_SHUTOFF ,libvirt.VIR_DOMAIN_CRASHED ]:
|
|
|
|
|
if self.window.get_widget("console-pages").get_current_page() != PAGE_UNAVAILABLE:
|
|
|
|
|
self.vncViewer.close()
|
|
|
|
|
self.window.get_widget("console-pages").set_current_page(PAGE_UNAVAILABLE)
|
|
|
|
|
self.view_vm_status()
|
|
|
|
|
else:
|
2008-05-07 10:03:56 -04:00
|
|
|
# Disabled screenshot when paused - doesn't work when scaled
|
|
|
|
|
# and you can connect to VNC when paused already, it'll simply
|
|
|
|
|
# not respond to input.
|
|
|
|
|
if status == libvirt.VIR_DOMAIN_PAUSED and 0 == 1:
|
2008-04-08 13:30:47 -05:00
|
|
|
if self.window.get_widget("console-pages").get_current_page() == PAGE_VNCVIEWER:
|
|
|
|
|
screenshot = self.window.get_widget("console-screenshot")
|
|
|
|
|
image = self.vncViewer.get_pixbuf()
|
|
|
|
|
width = image.get_width()
|
|
|
|
|
height = image.get_height()
|
|
|
|
|
pixmap = gtk.gdk.Pixmap(screenshot.get_root_window(), width, height)
|
|
|
|
|
cr = pixmap.cairo_create()
|
|
|
|
|
cr.set_source_pixbuf(image, 0, 0)
|
|
|
|
|
cr.rectangle(0, 0, width, height)
|
|
|
|
|
cr.fill()
|
|
|
|
|
|
|
|
|
|
# Set 50% gray overlayed
|
|
|
|
|
cr.set_source_rgba(0, 0, 0, 0.5)
|
|
|
|
|
cr.rectangle(0, 0, width, height)
|
|
|
|
|
cr.fill()
|
|
|
|
|
|
|
|
|
|
# Render a big text 'paused' across it
|
|
|
|
|
cr.set_source_rgba(1, 1,1, 1)
|
|
|
|
|
cr.set_font_size(80)
|
|
|
|
|
cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
|
|
|
|
|
overlay = _("paused")
|
|
|
|
|
extents = cr.text_extents(overlay)
|
|
|
|
|
x = width/2 - (extents[2]/2)
|
|
|
|
|
y = height/2 - (extents[3]/2)
|
|
|
|
|
cr.move_to(x, y)
|
|
|
|
|
cr.show_text(overlay)
|
|
|
|
|
screenshot.set_from_pixmap(pixmap, None)
|
|
|
|
|
self.activate_screenshot_page()
|
|
|
|
|
elif self.window.get_widget("console-pages").get_current_page() == PAGE_SCREENSHOT:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
if self.window.get_widget("console-pages").get_current_page() != PAGE_UNAVAILABLE:
|
|
|
|
|
self.vncViewer.close()
|
|
|
|
|
self.activate_unavailable_page(_("Console not available while paused"))
|
|
|
|
|
else:
|
2008-08-19 14:54:17 -04:00
|
|
|
page = self.window.get_widget("console-pages").get_current_page()
|
|
|
|
|
if page in [PAGE_UNAVAILABLE, PAGE_SCREENSHOT, PAGE_VNCVIEWER]:
|
2008-04-08 13:30:47 -05:00
|
|
|
if self.vncViewer.is_open():
|
|
|
|
|
self.activate_viewer_page()
|
|
|
|
|
else:
|
|
|
|
|
self.vncViewerRetriesScheduled = 0
|
|
|
|
|
self.vncViewerRetryDelay = 125
|
|
|
|
|
self.try_login()
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-06-14 18:42:04 -04: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())
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2008-05-07 11:26:00 -04:00
|
|
|
def switch_page(self, ignore1=None, ignore2=None,newpage=None):
|
|
|
|
|
details = self.window.get_widget("details-pages")
|
|
|
|
|
self.page_refresh(newpage)
|
|
|
|
|
|
2007-09-26 19:44:52 -04:00
|
|
|
def refresh_resources(self, ignore=None):
|
2007-04-12 15:36:04 -04:00
|
|
|
details = self.window.get_widget("details-pages")
|
2008-05-07 11:26:00 -04:00
|
|
|
self.page_refresh(details.get_current_page())
|
|
|
|
|
|
|
|
|
|
def page_refresh(self, page):
|
|
|
|
|
if page == PAGE_OVERVIEW:
|
2007-04-12 15:36:04 -04:00
|
|
|
self.refresh_summary()
|
2008-05-07 11:26:00 -04:00
|
|
|
elif page == PAGE_DETAILS:
|
2007-04-12 18:54:33 -04:00
|
|
|
# Add / remove new devices
|
|
|
|
|
self.repopulate_hw_list()
|
|
|
|
|
|
|
|
|
|
# Now refresh desired page
|
2007-04-11 14:48:36 -04:00
|
|
|
hw_list = self.window.get_widget("hw-list")
|
|
|
|
|
selection = hw_list.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] != None:
|
2007-07-14 14:43:20 -04:00
|
|
|
pagetype = active[0].get_value(active[1], HW_LIST_COL_TYPE)
|
|
|
|
|
device_info = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
2007-04-11 14:48:36 -04:00
|
|
|
hw_model = hw_list.get_model()
|
2007-07-14 14:43:20 -04:00
|
|
|
if pagetype == HW_LIST_TYPE_CPU:
|
2007-04-11 14:48:36 -04:00
|
|
|
self.refresh_config_cpu()
|
2007-07-14 14:43:20 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_MEMORY:
|
2007-04-11 14:48:36 -04:00
|
|
|
self.refresh_config_memory()
|
2007-07-14 14:43:20 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_DISK:
|
2007-04-11 14:48:36 -04:00
|
|
|
self.refresh_disk_page()
|
2007-07-14 14:43:20 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_NIC:
|
2007-04-11 14:48:36 -04:00
|
|
|
self.refresh_network_page()
|
2007-09-25 20:05:45 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_INPUT:
|
|
|
|
|
self.refresh_input_page()
|
2007-09-26 19:39:11 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_GRAPHICS:
|
|
|
|
|
self.refresh_graphics_page()
|
2008-07-30 19:52:39 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_SOUND:
|
|
|
|
|
self.refresh_sound_page()
|
2008-07-30 20:38:09 -04:00
|
|
|
elif pagetype == HW_LIST_TYPE_CHAR:
|
|
|
|
|
self.refresh_char_page()
|
2006-11-13 15:31:17 -05:00
|
|
|
|
|
|
|
|
def refresh_summary(self):
|
2008-10-18 21:25:16 +02:00
|
|
|
def _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()
|
|
|
|
|
|
2006-06-14 17:52:49 -04:00
|
|
|
self.window.get_widget("overview-cpu-usage-text").set_text("%d %%" % self.vm.cpu_time_percentage())
|
2006-07-26 18:19:33 -04:00
|
|
|
vm_memory = self.vm.current_memory()
|
|
|
|
|
host_memory = self.vm.get_connection().host_memory_size()
|
2007-09-27 11:09:50 -04:00
|
|
|
self.window.get_widget("overview-memory-usage-text").set_text("%d MB of %d MB" % \
|
|
|
|
|
(int(round(vm_memory/1024.0)), \
|
|
|
|
|
int(round(host_memory/1024.0))))
|
2006-06-14 10:59:40 -04:00
|
|
|
|
|
|
|
|
history_len = self.config.get_stats_history_length()
|
2008-10-18 21:21:33 +02:00
|
|
|
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())
|
2008-10-18 21:29:45 +02:00
|
|
|
|
|
|
|
|
if self.config.is_vmlist_network_traffic_visible():
|
|
|
|
|
text = _rx_tx_text(self.vm.network_rx_rate(), self.vm.network_tx_rate(), "KBytes/s")
|
|
|
|
|
self.network_traffic_graph.set_property("data_array", self.vm.network_traffic_vector())
|
|
|
|
|
else:
|
|
|
|
|
text = "sampling\ndisabled"
|
|
|
|
|
self.window.get_widget("overview-network-traffic-text").set_markup(text)
|
|
|
|
|
|
|
|
|
|
if self.config.is_vmlist_disk_io_visible():
|
|
|
|
|
text = _rx_tx_text(self.vm.disk_read_rate(), self.vm.disk_write_rate(), "KBytes/s")
|
|
|
|
|
self.disk_io_graph.set_property("data_array", self.vm.disk_io_vector())
|
|
|
|
|
else:
|
|
|
|
|
text = "sampling\ndisabled"
|
|
|
|
|
self.window.get_widget("overview-disk-usage-text").set_markup(text)
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-11-13 15:31:17 -05:00
|
|
|
def refresh_config_cpu(self):
|
2006-09-22 12:31:51 -04:00
|
|
|
self.window.get_widget("state-host-cpus").set_text("%d" % self.vm.get_connection().host_active_processor_count())
|
2006-11-13 15:31:17 -05:00
|
|
|
status = self.vm.status()
|
|
|
|
|
if status in [ libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_CRASHED ]:
|
2008-03-17 13:10:15 -04:00
|
|
|
cpu_max = self.vm.get_connection().get_max_vcpus(self.vm.get_type())
|
2007-06-18 15:16:20 -04:00
|
|
|
self.window.get_widget("config-vcpus").get_adjustment().upper = cpu_max
|
|
|
|
|
self.window.get_widget("state-vm-maxvcpus").set_text(str(cpu_max))
|
2006-11-13 15:31:17 -05:00
|
|
|
else:
|
|
|
|
|
self.window.get_widget("config-vcpus").get_adjustment().upper = self.vm.vcpu_max_count()
|
|
|
|
|
self.window.get_widget("state-vm-maxvcpus").set_text("%d" % (self.vm.vcpu_max_count()))
|
|
|
|
|
|
|
|
|
|
if not(self.window.get_widget("config-vcpus-apply").get_property("sensitive")):
|
|
|
|
|
self.window.get_widget("config-vcpus").get_adjustment().value = self.vm.vcpu_count()
|
|
|
|
|
# XXX hack - changing the value above will have just re-triggered
|
|
|
|
|
# the callback making apply button sensitive again. So we have to
|
|
|
|
|
# turn it off again....
|
|
|
|
|
self.window.get_widget("config-vcpus-apply").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("state-vm-vcpus").set_text("%d" % (self.vm.vcpu_count()))
|
|
|
|
|
|
|
|
|
|
def refresh_config_memory(self):
|
2007-09-27 11:09:50 -04:00
|
|
|
self.window.get_widget("state-host-memory").set_text("%d MB" % (int(round(self.vm.get_connection().host_memory_size()/1024))))
|
2008-03-18 14:37:22 -04:00
|
|
|
|
|
|
|
|
curmem = self.window.get_widget("config-memory").get_adjustment()
|
|
|
|
|
maxmem = self.window.get_widget("config-maxmem").get_adjustment()
|
|
|
|
|
|
|
|
|
|
|
2006-11-13 15:31:17 -05:00
|
|
|
if self.window.get_widget("config-memory-apply").get_property("sensitive"):
|
2008-03-18 14:37:22 -04:00
|
|
|
if curmem.value > maxmem.value:
|
|
|
|
|
curmem.value = maxmem.value
|
|
|
|
|
curmem.upper = maxmem.value
|
2006-11-13 15:31:17 -05:00
|
|
|
else:
|
2008-03-18 14:37:22 -04:00
|
|
|
curmem.value = int(round(self.vm.get_memory()/1024.0))
|
|
|
|
|
maxmem.value = int(round(self.vm.maximum_memory()/1024.0))
|
2006-11-13 15:31:17 -05:00
|
|
|
# XXX hack - changing the value above will have just re-triggered
|
|
|
|
|
# the callback making apply button sensitive again. So we have to
|
|
|
|
|
# turn it off again....
|
|
|
|
|
self.window.get_widget("config-memory-apply").set_sensitive(False)
|
2006-09-22 12:31:51 -04:00
|
|
|
|
2008-03-18 14:37:22 -04:00
|
|
|
if not self.window.get_widget("config-memory").get_property("sensitive"):
|
|
|
|
|
maxmem.lower = curmem.value
|
2007-09-27 11:09:50 -04:00
|
|
|
self.window.get_widget("state-vm-memory").set_text("%d MB" % int(round(self.vm.get_memory()/1024.0)))
|
2006-07-26 18:19:33 -04:00
|
|
|
|
2007-04-11 14:48:36 -04:00
|
|
|
def refresh_disk_page(self):
|
|
|
|
|
# get the currently selected line
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] != None:
|
2007-07-14 14:43:20 -04:00
|
|
|
diskinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
2007-04-12 15:36:04 -04:00
|
|
|
self.window.get_widget("disk-source-type").set_text(diskinfo[0])
|
|
|
|
|
self.window.get_widget("disk-source-path").set_text(diskinfo[1])
|
|
|
|
|
self.window.get_widget("disk-target-type").set_text(diskinfo[2])
|
|
|
|
|
self.window.get_widget("disk-target-device").set_text(diskinfo[3])
|
2007-12-17 12:28:25 -05:00
|
|
|
if diskinfo[4] == True:
|
|
|
|
|
perms = "Readonly"
|
|
|
|
|
else:
|
|
|
|
|
perms = "Read/Write"
|
|
|
|
|
if diskinfo[5] == True:
|
|
|
|
|
perms += ", Sharable"
|
|
|
|
|
self.window.get_widget("disk-permissions").set_text(perms)
|
2008-08-15 13:47:01 -04:00
|
|
|
bus = diskinfo[6] or _("Unknown")
|
|
|
|
|
self.window.get_widget("disk-bus").set_text(bus)
|
|
|
|
|
|
2007-09-21 16:28:31 -04:00
|
|
|
button = self.window.get_widget("config-cdrom-connect")
|
|
|
|
|
if diskinfo[2] == "cdrom":
|
|
|
|
|
if diskinfo[1] == "-":
|
|
|
|
|
# source device not connected
|
|
|
|
|
button.set_label(gtk.STOCK_CONNECT)
|
|
|
|
|
else:
|
|
|
|
|
button.set_label(gtk.STOCK_DISCONNECT)
|
|
|
|
|
button.show()
|
|
|
|
|
else:
|
|
|
|
|
button.hide()
|
2007-04-11 14:48:36 -04:00
|
|
|
|
|
|
|
|
def refresh_network_page(self):
|
2007-04-12 15:36:04 -04:00
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] != None:
|
2007-07-14 14:43:20 -04:00
|
|
|
netinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
2007-04-12 15:36:04 -04:00
|
|
|
self.window.get_widget("network-source-type").set_text(netinfo[0])
|
2007-04-12 17:50:22 -04:00
|
|
|
if netinfo[1] is not None:
|
|
|
|
|
self.window.get_widget("network-source-device").set_text(netinfo[1])
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("network-source-device").set_text("-")
|
2007-04-12 15:36:04 -04:00
|
|
|
self.window.get_widget("network-mac-address").set_text(netinfo[3])
|
2008-08-15 13:47:01 -04:00
|
|
|
model = netinfo[4] or _("Hypervisor Default")
|
|
|
|
|
self.window.get_widget("network-source-model").set_text(model)
|
2007-04-12 15:36:04 -04:00
|
|
|
|
2007-09-25 20:05:45 -04:00
|
|
|
def refresh_input_page(self):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] != None:
|
|
|
|
|
inputinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
|
|
|
|
if inputinfo[3] == "tablet:usb":
|
|
|
|
|
self.window.get_widget("input-dev-type").set_text(_("EvTouch USB Graphics Tablet"))
|
|
|
|
|
elif inputinfo[3] == "mouse:usb":
|
|
|
|
|
self.window.get_widget("input-dev-type").set_text(_("Generic USB Mouse"))
|
|
|
|
|
elif inputinfo[3] == "mouse:xen":
|
|
|
|
|
self.window.get_widget("input-dev-type").set_text(_("Xen Mouse"))
|
|
|
|
|
elif inputinfo[3] == "mouse:ps2":
|
|
|
|
|
self.window.get_widget("input-dev-type").set_text(_("PS/2 Mouse"))
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("input-dev-type").set_text(inputinfo[0] + " " + inputinfo[1])
|
|
|
|
|
|
|
|
|
|
if inputinfo[0] == "tablet":
|
|
|
|
|
self.window.get_widget("input-dev-mode").set_text(_("Absolute Movement"))
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("input-dev-mode").set_text(_("Relative Movement"))
|
|
|
|
|
|
|
|
|
|
# Can't remove primary Xen or PS/2 mice
|
|
|
|
|
if inputinfo[0] == "mouse" and inputinfo[1] in ("xen", "ps2"):
|
|
|
|
|
self.window.get_widget("config-input-remove").set_sensitive(False)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("config-input-remove").set_sensitive(True)
|
|
|
|
|
|
2007-09-26 19:39:11 -04:00
|
|
|
def refresh_graphics_page(self):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] != None:
|
|
|
|
|
inputinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
|
|
|
|
if inputinfo[0] == "vnc":
|
|
|
|
|
self.window.get_widget("graphics-type").set_text(_("VNC server"))
|
|
|
|
|
elif inputinfo[0] == "sdl":
|
|
|
|
|
self.window.get_widget("graphics-type").set_text(_("Local SDL window"))
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("graphics-type").set_text(inputinfo[0])
|
|
|
|
|
|
|
|
|
|
if inputinfo[0] == "vnc":
|
|
|
|
|
if inputinfo[1] == None:
|
|
|
|
|
self.window.get_widget("graphics-address").set_text("127.0.0.1")
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("graphics-address").set_text(inputinfo[1])
|
|
|
|
|
if int(inputinfo[2]) == -1:
|
|
|
|
|
self.window.get_widget("graphics-port").set_text(_("Automatically allocated"))
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("graphics-port").set_text(inputinfo[2])
|
2008-03-17 13:09:45 -04:00
|
|
|
self.window.get_widget("graphics-password").set_text("-")
|
2008-06-16 10:57:44 -04:00
|
|
|
self.window.get_widget("graphics-keymap").set_text(inputinfo[4] or "en-us")
|
2007-09-26 19:39:11 -04:00
|
|
|
else:
|
|
|
|
|
self.window.get_widget("graphics-address").set_text(_("N/A"))
|
|
|
|
|
self.window.get_widget("graphics-port").set_text(_("N/A"))
|
|
|
|
|
self.window.get_widget("graphics-password").set_text("N/A")
|
2008-03-14 13:20:56 -04:00
|
|
|
self.window.get_widget("graphics-keymap").set_text("N/A")
|
2007-09-26 19:39:11 -04:00
|
|
|
|
|
|
|
|
# Can't remove display from live guest
|
|
|
|
|
if self.vm.is_active():
|
2008-07-23 17:32:43 -04:00
|
|
|
self.window.get_widget("config-graphics-remove").set_sensitive(False)
|
2007-09-26 19:39:11 -04:00
|
|
|
else:
|
2008-07-23 17:32:43 -04:00
|
|
|
self.window.get_widget("config-graphics-remove").set_sensitive(True)
|
2007-09-26 19:39:11 -04:00
|
|
|
|
2008-07-30 19:52:39 -04:00
|
|
|
def refresh_sound_page(self):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] is None:
|
|
|
|
|
return
|
|
|
|
|
sound = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
|
|
|
|
self.window.get_widget("sound-model").set_text(sound[3])
|
|
|
|
|
|
|
|
|
|
# Can't remove sound dev from live guest
|
|
|
|
|
if self.vm.is_active():
|
|
|
|
|
self.window.get_widget("config-sound-remove").set_sensitive(False)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("config-sound-remove").set_sensitive(True)
|
|
|
|
|
|
2008-07-30 20:38:09 -04:00
|
|
|
def refresh_char_page(self):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] is None:
|
|
|
|
|
return
|
|
|
|
|
char = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
|
|
|
|
typelabel = "<b>%s Device %s</b>" % (char[0].capitalize(),
|
|
|
|
|
char[5] and _("(Primary Console)") or "")
|
|
|
|
|
self.window.get_widget("char-type").set_markup(typelabel)
|
|
|
|
|
self.window.get_widget("char-dev-type").set_text(char[1] or "-")
|
|
|
|
|
self.window.get_widget("char-target-port").set_text(char[2])
|
|
|
|
|
self.window.get_widget("char-source-path").set_text(char[4] or "-")
|
|
|
|
|
|
|
|
|
|
# Can't remove char dev from live guest
|
|
|
|
|
if self.vm.is_active() or char[0] == "console":
|
|
|
|
|
self.window.get_widget("config-char-remove").set_sensitive(False)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("config-char-remove").set_sensitive(True)
|
|
|
|
|
|
2008-03-06 16:43:46 -05:00
|
|
|
def refresh_boot_page(self):
|
|
|
|
|
# Refresh autostart
|
|
|
|
|
try:
|
|
|
|
|
autoval = self.vm.get_autostart()
|
|
|
|
|
self.window.get_widget("config-autostart").set_active(autoval)
|
|
|
|
|
self.window.get_widget("config-autostart").set_sensitive(True)
|
|
|
|
|
except libvirt.libvirtError, e:
|
|
|
|
|
# Autostart isn't supported
|
|
|
|
|
self.window.get_widget("config-autostart").set_active(False)
|
|
|
|
|
self.window.get_widget("config-autostart").set_sensitive(False)
|
|
|
|
|
|
|
|
|
|
# Refresh Boot Device list and correct selection
|
|
|
|
|
boot_combo = self.window.get_widget("config-boot-device")
|
|
|
|
|
if not self.vm.is_hvm():
|
|
|
|
|
# Boot dev selection not supported for PV guest
|
|
|
|
|
boot_combo.set_sensitive(False)
|
|
|
|
|
boot_combo.set_active(-1)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.repopulate_boot_list()
|
|
|
|
|
bootdev = self.vm.get_boot_device()
|
|
|
|
|
boot_combo = self.window.get_widget("config-boot-device")
|
|
|
|
|
boot_model = boot_combo.get_model()
|
|
|
|
|
for i in range(0, len(boot_model)):
|
|
|
|
|
if bootdev == boot_model[i][2]:
|
|
|
|
|
boot_combo.set_active(i)
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if boot_model[0][2] == None:
|
|
|
|
|
# If no boot devices, select the 'No Device' entry
|
|
|
|
|
boot_combo.set_active(0)
|
|
|
|
|
|
|
|
|
|
# TODO: if nothing selected, what to select? auto change device?
|
|
|
|
|
|
2008-04-08 13:30:47 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def view_vm_status(self):
|
|
|
|
|
status = self.vm.status()
|
|
|
|
|
if status == libvirt.VIR_DOMAIN_SHUTOFF:
|
|
|
|
|
self.activate_unavailable_page(_("Guest not running"))
|
|
|
|
|
else:
|
|
|
|
|
if status == libvirt.VIR_DOMAIN_CRASHED:
|
|
|
|
|
self.activate_unavailable_page(_("Guest has crashed"))
|
|
|
|
|
|
|
|
|
|
def _vnc_disconnected(self, src):
|
|
|
|
|
if self.vncTunnel is not None:
|
|
|
|
|
self.close_tunnel()
|
|
|
|
|
self.connected = 0
|
|
|
|
|
logging.debug("VNC disconnected")
|
|
|
|
|
if self.vm.status() in [ libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_CRASHED ]:
|
|
|
|
|
self.view_vm_status()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.activate_unavailable_page(_("TCP/IP error: VNC connection to hypervisor host got refused or disconnected!"))
|
|
|
|
|
|
|
|
|
|
if not self.is_visible():
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.schedule_retry()
|
|
|
|
|
|
|
|
|
|
def _vnc_initialized(self, src):
|
|
|
|
|
self.connected = 1
|
|
|
|
|
logging.debug("VNC initialized")
|
|
|
|
|
self.activate_viewer_page()
|
|
|
|
|
|
|
|
|
|
# Had a succesfull connect, so reset counters now
|
|
|
|
|
self.vncViewerRetriesScheduled = 0
|
|
|
|
|
self.vncViewerRetryDelay = 125
|
|
|
|
|
|
|
|
|
|
def schedule_retry(self):
|
|
|
|
|
self.vncViewerRetriesScheduled = self.vncViewerRetriesScheduled + 1
|
|
|
|
|
if self.vncViewerRetriesScheduled >= 10:
|
|
|
|
|
logging.error("Too many connection failures, not retrying again")
|
|
|
|
|
return
|
|
|
|
|
logging.warn("Retrying connection in %d ms", self.vncViewerRetryDelay)
|
|
|
|
|
gobject.timeout_add(self.vncViewerRetryDelay, self.retry_login)
|
|
|
|
|
if self.vncViewerRetryDelay < 2000:
|
|
|
|
|
self.vncViewerRetryDelay = self.vncViewerRetryDelay * 2
|
|
|
|
|
|
|
|
|
|
def retry_login(self):
|
|
|
|
|
if self.connected:
|
|
|
|
|
return
|
|
|
|
|
gtk.gdk.threads_enter()
|
|
|
|
|
try:
|
|
|
|
|
logging.debug("Got timed retry")
|
|
|
|
|
self.try_login()
|
|
|
|
|
return
|
|
|
|
|
finally:
|
|
|
|
|
gtk.gdk.threads_leave()
|
|
|
|
|
|
|
|
|
|
def open_tunnel(self, server, vncaddr, vncport, username):
|
|
|
|
|
if self.vncTunnel is not None:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
logging.debug("Spawning SSH tunnel to %s, for %s:%d" %(server, vncaddr, vncport))
|
|
|
|
|
|
|
|
|
|
fds = socket.socketpair()
|
|
|
|
|
pid = os.fork()
|
|
|
|
|
if pid == 0:
|
|
|
|
|
fds[0].close()
|
|
|
|
|
os.close(0)
|
|
|
|
|
os.close(1)
|
|
|
|
|
os.dup(fds[1].fileno())
|
|
|
|
|
os.dup(fds[1].fileno())
|
2008-05-20 10:28:32 -04:00
|
|
|
if not server.count(":"):
|
2008-08-22 13:17:37 -04:00
|
|
|
sshport = "22"
|
2008-05-20 10:28:32 -04:00
|
|
|
else:
|
|
|
|
|
(server, sshport) = server.split(":")
|
|
|
|
|
argv = ["ssh", "ssh", "-p", sshport]
|
2008-04-08 13:30:47 -05:00
|
|
|
if username:
|
|
|
|
|
argv += ['-l', username]
|
|
|
|
|
argv += [ server, "nc", vncaddr, str(vncport) ]
|
|
|
|
|
os.execlp(*argv)
|
|
|
|
|
os._exit(1)
|
|
|
|
|
else:
|
|
|
|
|
fds[1].close()
|
|
|
|
|
|
|
|
|
|
logging.debug("Tunnel PID %d FD %d" % (fds[0].fileno(), pid))
|
|
|
|
|
self.vncTunnel = [fds[0], pid]
|
|
|
|
|
return fds[0].fileno()
|
|
|
|
|
|
|
|
|
|
def close_tunnel(self):
|
|
|
|
|
if self.vncTunnel is None:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
logging.debug("Shutting down tunnel PID %d FD %d" % (self.vncTunnel[1], self.vncTunnel[0].fileno()))
|
|
|
|
|
self.vncTunnel[0].close()
|
|
|
|
|
os.waitpid(self.vncTunnel[1], 0)
|
|
|
|
|
self.vncTunnel = None
|
|
|
|
|
|
|
|
|
|
def try_login(self, src=None):
|
|
|
|
|
if self.vm.get_id() < 0:
|
|
|
|
|
self.activate_unavailable_page(_("Guest not running"))
|
|
|
|
|
self.schedule_retry()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
logging.debug("Trying console login")
|
|
|
|
|
password = self.window.get_widget("console-auth-password").get_text()
|
|
|
|
|
protocol, host, port, trans, username = self.vm.get_graphics_console()
|
|
|
|
|
|
|
|
|
|
if protocol is None:
|
|
|
|
|
logging.debug("No graphics configured in guest")
|
|
|
|
|
self.activate_unavailable_page(_("Console not configured for guest"))
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
uri = str(protocol) + "://"
|
|
|
|
|
if username:
|
|
|
|
|
uri = uri + str(username) + '@'
|
|
|
|
|
uri = uri + str(host) + ":" + str(port)
|
|
|
|
|
|
|
|
|
|
logging.debug("Graphics console configured at " + uri)
|
|
|
|
|
|
|
|
|
|
if protocol != "vnc":
|
|
|
|
|
logging.debug("Not a VNC console, disabling")
|
|
|
|
|
self.activate_unavailable_page(_("Console not supported for guest"))
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if int(port) == -1:
|
|
|
|
|
self.activate_unavailable_page(_("Console is not yet active for guest"))
|
|
|
|
|
self.schedule_retry()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.activate_unavailable_page(_("Connecting to console for guest"))
|
|
|
|
|
logging.debug("Starting connect process for %s %s" % (host, str(port)))
|
|
|
|
|
try:
|
|
|
|
|
if trans is not None and trans in ("ssh", "ext"):
|
|
|
|
|
fd = self.open_tunnel(host, "127.0.0.1", port, username)
|
|
|
|
|
self.vncViewer.open_fd(fd)
|
|
|
|
|
else:
|
|
|
|
|
self.vncViewer.open_host(host, str(port))
|
|
|
|
|
except:
|
|
|
|
|
(type, value, stacktrace) = sys.exc_info ()
|
|
|
|
|
details = \
|
|
|
|
|
"Unable to start virtual machine '%s'" % \
|
|
|
|
|
(str(type) + " " + str(value) + "\n" + \
|
|
|
|
|
traceback.format_exc (stacktrace))
|
|
|
|
|
logging.error(details)
|
|
|
|
|
|
|
|
|
|
def set_password(self, src=None):
|
|
|
|
|
txt = self.window.get_widget("console-auth-password")
|
|
|
|
|
logging.debug("Setting a password to " + str(txt.get_text()))
|
|
|
|
|
|
|
|
|
|
self.vncViewer.set_credential(gtkvnc.CREDENTIAL_PASSWORD, txt.get_text())
|
|
|
|
|
|
|
|
|
|
def _vnc_auth_credential(self, src, credList):
|
|
|
|
|
for i in range(len(credList)):
|
|
|
|
|
logging.debug("Got credential request %s", str(credList[i]))
|
|
|
|
|
if credList[i] == gtkvnc.CREDENTIAL_PASSWORD:
|
|
|
|
|
self.activate_auth_page()
|
|
|
|
|
elif credList[i] == gtkvnc.CREDENTIAL_CLIENTNAME:
|
|
|
|
|
self.vncViewer.set_credential(credList[i], "libvirt-vnc")
|
|
|
|
|
else:
|
|
|
|
|
# Force it to stop re-trying
|
|
|
|
|
self.vncViewerRetriesScheduled = 10
|
|
|
|
|
self.vncViewer.close()
|
|
|
|
|
self.activate_unavailable_page(_("Unsupported console authentication type"))
|
|
|
|
|
|
|
|
|
|
def activate_unavailable_page(self, msg):
|
|
|
|
|
self.window.get_widget("console-pages").set_current_page(PAGE_UNAVAILABLE)
|
|
|
|
|
self.window.get_widget("details-menu-vm-screenshot").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("console-unavailable").set_label("<b>" + msg + "</b>")
|
|
|
|
|
|
|
|
|
|
def activate_screenshot_page(self):
|
|
|
|
|
self.window.get_widget("console-pages").set_current_page(PAGE_SCREENSHOT)
|
|
|
|
|
self.window.get_widget("details-menu-vm-screenshot").set_sensitive(True)
|
|
|
|
|
|
|
|
|
|
def activate_auth_page(self):
|
|
|
|
|
pw = self.config.get_console_password(self.vm)
|
|
|
|
|
self.window.get_widget("details-menu-vm-screenshot").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("console-auth-password").set_text(pw)
|
|
|
|
|
self.window.get_widget("console-auth-password").grab_focus()
|
|
|
|
|
if self.config.has_keyring():
|
|
|
|
|
self.window.get_widget("console-auth-remember").set_sensitive(True)
|
|
|
|
|
if pw != None and pw != "":
|
|
|
|
|
self.window.get_widget("console-auth-remember").set_active(True)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("console-auth-remember").set_active(False)
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("console-auth-remember").set_sensitive(False)
|
|
|
|
|
self.window.get_widget("console-pages").set_current_page(PAGE_AUTHENTICATE)
|
|
|
|
|
|
|
|
|
|
def activate_viewer_page(self):
|
|
|
|
|
self.window.get_widget("console-pages").set_current_page(PAGE_VNCVIEWER)
|
|
|
|
|
self.window.get_widget("details-menu-vm-screenshot").set_sensitive(True)
|
|
|
|
|
self.vncViewer.grab_focus()
|
|
|
|
|
|
|
|
|
|
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....
|
|
|
|
|
fcdialog = gtk.FileChooserDialog(_("Save Virtual Machine Screenshot"),
|
|
|
|
|
self.window.get_widget("vmm-details"),
|
|
|
|
|
gtk.FILE_CHOOSER_ACTION_SAVE,
|
|
|
|
|
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
|
|
|
|
gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT),
|
|
|
|
|
None)
|
2008-05-07 11:36:42 -04:00
|
|
|
fcdialog.set_default_response(gtk.RESPONSE_ACCEPT)
|
2008-04-08 13:30:47 -05:00
|
|
|
png = gtk.FileFilter()
|
|
|
|
|
png.set_name("PNG files")
|
|
|
|
|
png.add_pattern("*.png")
|
|
|
|
|
fcdialog.add_filter(png)
|
|
|
|
|
fcdialog.set_do_overwrite_confirmation(True)
|
|
|
|
|
if fcdialog.run() == gtk.RESPONSE_ACCEPT:
|
|
|
|
|
fcdialog.hide()
|
|
|
|
|
file = fcdialog.get_filename()
|
|
|
|
|
if not(file.endswith(".png")):
|
|
|
|
|
file = file + ".png"
|
|
|
|
|
image = self.vncViewer.get_pixbuf()
|
|
|
|
|
width = image.get_width()
|
|
|
|
|
height = image.get_height()
|
|
|
|
|
|
|
|
|
|
# Save along with a little metadata about us & the domain
|
|
|
|
|
image.save(file, '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.window.get_widget("vmm-details"),
|
|
|
|
|
gtk.DIALOG_MODAL,
|
|
|
|
|
gtk.MESSAGE_INFO,
|
|
|
|
|
gtk.BUTTONS_OK,_("The screenshot has been saved to:\n%s") % file)
|
|
|
|
|
msg.set_title(_("Screenshot saved"))
|
|
|
|
|
msg.run()
|
|
|
|
|
msg.destroy()
|
|
|
|
|
else:
|
|
|
|
|
fcdialog.hide()
|
|
|
|
|
fcdialog.destroy()
|
|
|
|
|
|
2008-10-02 16:17:25 -04:00
|
|
|
|
|
|
|
|
# ------------------------------
|
|
|
|
|
# Serial Console pieces
|
|
|
|
|
# ------------------------------
|
|
|
|
|
|
|
|
|
|
def control_serial_tab(self, src, name, ttypath):
|
|
|
|
|
if src.get_active():
|
|
|
|
|
self._show_serial_tab(name, ttypath)
|
|
|
|
|
else:
|
|
|
|
|
self._close_serial_tab(name)
|
|
|
|
|
|
|
|
|
|
def show_serial_rcpopup(self, src, event):
|
|
|
|
|
if event.button != 3:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
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())
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
def serial_close_tab(self, src, pagenum):
|
|
|
|
|
tab_idx = (pagenum - PAGE_DYNAMIC_OFFSET)
|
|
|
|
|
if (tab_idx < 0) or (tab_idx > len(self.dynamic_tabs)-1):
|
|
|
|
|
return
|
|
|
|
|
return self._close_serial_tab(self.dynamic_tabs[tab_idx])
|
|
|
|
|
|
|
|
|
|
def serial_copy_text(self, src, terminal):
|
|
|
|
|
terminal.copy_clipboard()
|
|
|
|
|
|
|
|
|
|
def serial_paste_text(self, src, terminal):
|
|
|
|
|
terminal.paste_clipboard()
|
|
|
|
|
|
|
|
|
|
def _show_serial_tab(self, name, ttypath):
|
|
|
|
|
if not self.dynamic_tabs.count(name):
|
|
|
|
|
child = vmmSerialConsole(self.vm, ttypath)
|
|
|
|
|
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.dynamic_tabs.append(name)
|
|
|
|
|
|
|
|
|
|
page_idx = self.dynamic_tabs.index(name) + PAGE_DYNAMIC_OFFSET
|
|
|
|
|
self.window.get_widget("details-pages").set_current_page(page_idx)
|
|
|
|
|
|
|
|
|
|
def _close_serial_tab(self, name):
|
|
|
|
|
if not self.dynamic_tabs.count(name):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
page_idx = self.dynamic_tabs.index(name) + PAGE_DYNAMIC_OFFSET
|
|
|
|
|
self.window.get_widget("details-pages").remove_page(page_idx)
|
|
|
|
|
self.dynamic_tabs.remove(name)
|
|
|
|
|
|
|
|
|
|
# -----------------------
|
|
|
|
|
# Hardware Section Pieces
|
|
|
|
|
# -----------------------
|
|
|
|
|
|
2006-11-13 15:31:17 -05:00
|
|
|
def config_vcpus_changed(self, src):
|
|
|
|
|
self.window.get_widget("config-vcpus-apply").set_sensitive(True)
|
2006-07-26 18:19:33 -04:00
|
|
|
|
2006-11-13 15:31:17 -05:00
|
|
|
def config_vcpus_apply(self, src):
|
|
|
|
|
vcpus = self.window.get_widget("config-vcpus").get_adjustment().value
|
|
|
|
|
logging.info("Setting vcpus for " + self.vm.get_uuid() + " to " + str(vcpus))
|
2006-07-26 18:19:33 -04:00
|
|
|
self.vm.set_vcpu_count(vcpus)
|
2006-11-13 15:31:17 -05:00
|
|
|
self.window.get_widget("config-vcpus-apply").set_sensitive(False)
|
2006-07-26 18:19:33 -04:00
|
|
|
|
2006-11-13 15:31:17 -05:00
|
|
|
def config_memory_changed(self, src):
|
|
|
|
|
self.window.get_widget("config-memory-apply").set_sensitive(True)
|
|
|
|
|
|
|
|
|
|
def config_maxmem_changed(self, src):
|
2006-07-26 18:19:33 -04:00
|
|
|
self.window.get_widget("config-memory-apply").set_sensitive(True)
|
2006-11-13 15:31:17 -05:00
|
|
|
memory = self.window.get_widget("config-maxmem").get_adjustment().value
|
|
|
|
|
memadj = self.window.get_widget("config-memory").get_adjustment()
|
|
|
|
|
memadj.upper = memory
|
|
|
|
|
if memadj.value > memory:
|
|
|
|
|
memadj.value = memory
|
2006-07-26 18:19:33 -04:00
|
|
|
|
|
|
|
|
def config_memory_apply(self, src):
|
2006-11-13 15:31:17 -05:00
|
|
|
status = self.vm.status()
|
2008-03-18 14:37:22 -04:00
|
|
|
self.refresh_config_memory()
|
|
|
|
|
exc = None
|
|
|
|
|
curmem = None
|
|
|
|
|
maxmem = self.window.get_widget("config-maxmem").get_adjustment()
|
|
|
|
|
if self.window.get_widget("config-memory").get_property("sensitive"):
|
|
|
|
|
curmem = self.window.get_widget("config-memory").get_adjustment()
|
|
|
|
|
|
|
|
|
|
logging.info("Setting max-memory for " + self.vm.get_name() + \
|
2008-03-06 17:13:59 -05:00
|
|
|
" to " + str(maxmem.value))
|
2006-11-13 15:31:17 -05:00
|
|
|
|
2008-03-18 14:37:22 -04:00
|
|
|
actual_cur = self.vm.get_memory()
|
|
|
|
|
if curmem is not None:
|
|
|
|
|
logging.info("Setting memory for " + self.vm.get_name() + \
|
|
|
|
|
" to " + str(curmem.value))
|
|
|
|
|
if (maxmem.value * 1024) < actual_cur:
|
|
|
|
|
# Set current first to avoid error
|
|
|
|
|
try:
|
|
|
|
|
self.vm.set_memory(curmem.value * 1024)
|
|
|
|
|
self.vm.set_max_memory(maxmem.value * 1024)
|
|
|
|
|
except Exception, e:
|
|
|
|
|
exc = e
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
self.vm.set_max_memory(maxmem.value * 1024)
|
|
|
|
|
self.vm.set_memory(curmem.value * 1024)
|
|
|
|
|
except Exception, e:
|
|
|
|
|
exc = e
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
self.vm.set_max_memory(maxmem.value * 1024)
|
|
|
|
|
except Exception, e:
|
|
|
|
|
exc = e
|
|
|
|
|
|
|
|
|
|
if exc:
|
|
|
|
|
self.err.show_err(_("Error changing memory values: %s" % str(e)),\
|
|
|
|
|
"".join(traceback.format_exc()))
|
|
|
|
|
else:
|
|
|
|
|
self.window.get_widget("config-memory-apply").set_sensitive(False)
|
2006-11-13 15:31:17 -05:00
|
|
|
|
2008-03-06 16:43:46 -05:00
|
|
|
def config_boot_options_changed(self, src):
|
|
|
|
|
self.window.get_widget("config-boot-options-apply").set_sensitive(True)
|
|
|
|
|
|
|
|
|
|
def config_boot_options_apply(self, src):
|
|
|
|
|
boot = self.window.get_widget("config-boot-device")
|
|
|
|
|
auto = self.window.get_widget("config-autostart")
|
|
|
|
|
if auto.get_property("sensitive"):
|
|
|
|
|
try:
|
|
|
|
|
self.vm.set_autostart(auto.get_active())
|
|
|
|
|
except Exception, e:
|
2008-03-14 13:18:44 -04:00
|
|
|
self.err.show_err(_("Error changing autostart value: %s") % \
|
|
|
|
|
str(e), "".join(traceback.format_exc()))
|
2008-03-06 16:43:46 -05:00
|
|
|
|
|
|
|
|
if boot.get_property("sensitive"):
|
|
|
|
|
try:
|
|
|
|
|
self.vm.set_boot_device(boot.get_model()[boot.get_active()][2])
|
|
|
|
|
self.window.get_widget("config-boot-options-apply").set_sensitive(False)
|
|
|
|
|
except Exception, e:
|
2008-03-14 13:18:44 -04:00
|
|
|
self.err.show_err(_("Error changing boot device: %s" % str(e)),
|
|
|
|
|
"".join(traceback.format_exc()))
|
2008-03-06 16:43:46 -05:00
|
|
|
return
|
2006-11-13 15:31:17 -05:00
|
|
|
|
2007-04-12 18:54:33 -04:00
|
|
|
def remove_disk(self, src):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] != None:
|
2007-07-14 14:43:20 -04:00
|
|
|
diskinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
2007-12-05 14:20:42 -05:00
|
|
|
self.remove_device(self.vm.get_disk_xml(diskinfo[3]))
|
2007-09-26 19:44:52 -04:00
|
|
|
self.refresh_resources()
|
2007-04-12 18:54:33 -04:00
|
|
|
|
|
|
|
|
def remove_network(self, src):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] != None:
|
2007-07-14 14:43:20 -04:00
|
|
|
netinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
2007-04-12 18:54:33 -04:00
|
|
|
|
|
|
|
|
vnic = None
|
2007-11-16 17:12:37 -05:00
|
|
|
try:
|
|
|
|
|
if netinfo[0] == "bridge":
|
|
|
|
|
vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], bridge=netinfo[1], macaddr=netinfo[3])
|
|
|
|
|
elif netinfo[0] == "network":
|
|
|
|
|
vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], network=netinfo[1], macaddr=netinfo[3])
|
|
|
|
|
else:
|
|
|
|
|
vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], macaddr=netinfo[3])
|
|
|
|
|
except ValueError, e:
|
2008-03-14 13:18:44 -04:00
|
|
|
self.err.show_err(_("Error Removing Network: %s" % str(e)),
|
|
|
|
|
"".join(traceback.format_exc()))
|
|
|
|
|
return False
|
2007-04-12 18:54:33 -04:00
|
|
|
|
|
|
|
|
xml = vnic.get_xml_config()
|
2007-11-16 17:12:37 -05:00
|
|
|
self.remove_device(xml)
|
2007-09-26 19:44:52 -04:00
|
|
|
self.refresh_resources()
|
2007-04-12 18:54:33 -04:00
|
|
|
|
2007-09-25 20:05:45 -04:00
|
|
|
def remove_input(self, src):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] != None:
|
|
|
|
|
inputinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
|
|
|
|
|
|
|
|
|
xml = "<input type='%s' bus='%s'/>" % (inputinfo[0], inputinfo[1])
|
2007-11-16 17:12:37 -05:00
|
|
|
self.remove_device(xml)
|
2007-09-26 19:44:52 -04:00
|
|
|
self.refresh_resources()
|
2007-09-25 20:05:45 -04:00
|
|
|
|
2007-09-26 19:39:11 -04:00
|
|
|
def remove_graphics(self, src):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] != None:
|
|
|
|
|
inputinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
|
|
|
|
|
|
|
|
|
xml = "<graphics type='%s'/>" % inputinfo[0]
|
2007-11-16 17:12:37 -05:00
|
|
|
self.remove_device(xml)
|
2007-09-26 19:44:52 -04:00
|
|
|
self.refresh_resources()
|
2006-08-29 15:52:19 -04:00
|
|
|
|
2008-07-30 19:52:39 -04:00
|
|
|
def remove_sound(self, src):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] is None:
|
|
|
|
|
return
|
|
|
|
|
sound = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
|
|
|
|
|
|
|
|
|
xml = "<sound model='%s'/>" % sound[3]
|
|
|
|
|
self.remove_device(xml)
|
|
|
|
|
self.refresh_resources()
|
|
|
|
|
|
2008-07-30 20:38:09 -04:00
|
|
|
def remove_char(self, src):
|
|
|
|
|
vmlist = self.window.get_widget("hw-list")
|
|
|
|
|
selection = vmlist.get_selection()
|
|
|
|
|
active = selection.get_selected()
|
|
|
|
|
if active[1] is None:
|
|
|
|
|
return
|
|
|
|
|
char = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
|
|
|
|
|
|
|
|
|
|
xml = "<%s>\n" % char[0] + \
|
|
|
|
|
" <target port='%s'/>\n" % char[2] + \
|
|
|
|
|
"</%s>" % char[0]
|
|
|
|
|
self.remove_device(xml)
|
|
|
|
|
self.refresh_resources()
|
|
|
|
|
|
2007-04-11 14:48:36 -04:00
|
|
|
def prepare_hw_list(self):
|
2007-07-14 14:43:20 -04:00
|
|
|
hw_list_model = gtk.ListStore(str, str, int, gtk.gdk.Pixbuf, int, gobject.TYPE_PYOBJECT)
|
2007-04-11 14:48:36 -04:00
|
|
|
self.window.get_widget("hw-list").set_model(hw_list_model)
|
|
|
|
|
|
|
|
|
|
hwCol = gtk.TreeViewColumn("Hardware")
|
|
|
|
|
hw_txt = gtk.CellRendererText()
|
|
|
|
|
hw_img = gtk.CellRendererPixbuf()
|
|
|
|
|
hwCol.pack_start(hw_txt, True)
|
|
|
|
|
hwCol.pack_start(hw_img, False)
|
2007-07-14 14:43:20 -04:00
|
|
|
hwCol.add_attribute(hw_txt, 'text', HW_LIST_COL_LABEL)
|
|
|
|
|
hwCol.add_attribute(hw_img, 'stock-id', HW_LIST_COL_STOCK_ID)
|
|
|
|
|
hwCol.add_attribute(hw_img, 'stock-size', HW_LIST_COL_STOCK_SIZE)
|
|
|
|
|
hwCol.add_attribute(hw_img, 'pixbuf', HW_LIST_COL_PIXBUF)
|
2007-04-11 14:48:36 -04:00
|
|
|
self.window.get_widget("hw-list").append_column(hwCol)
|
2008-03-06 16:43:46 -05:00
|
|
|
self.prepare_boot_list()
|
2007-04-11 14:48:36 -04:00
|
|
|
|
2007-04-12 15:36:04 -04:00
|
|
|
self.populate_hw_list()
|
2008-03-06 16:43:46 -05:00
|
|
|
self.repopulate_boot_list()
|
|
|
|
|
|
|
|
|
|
def prepare_boot_list(self):
|
|
|
|
|
boot_list = self.window.get_widget("config-boot-device")
|
|
|
|
|
# model = [ display name, icon name, boot type (hd, fd, etc) ]
|
|
|
|
|
boot_list_model = gtk.ListStore(str, str, str)
|
|
|
|
|
boot_list.set_model(boot_list_model)
|
|
|
|
|
|
|
|
|
|
icon = gtk.CellRendererPixbuf()
|
|
|
|
|
boot_list.pack_start(icon, False)
|
|
|
|
|
boot_list.add_attribute(icon, 'stock-id', 1)
|
|
|
|
|
text = gtk.CellRendererText()
|
|
|
|
|
boot_list.pack_start(text, True)
|
|
|
|
|
boot_list.add_attribute(text, 'text', 0)
|
2007-04-12 15:36:04 -04:00
|
|
|
|
2007-04-11 14:48:36 -04:00
|
|
|
def populate_hw_list(self):
|
|
|
|
|
hw_list_model = self.window.get_widget("hw-list").get_model()
|
|
|
|
|
hw_list_model.clear()
|
2007-07-14 14:43:20 -04:00
|
|
|
hw_list_model.append(["Processor", None, 0, self.pixbuf_processor, HW_LIST_TYPE_CPU, []])
|
|
|
|
|
hw_list_model.append(["Memory", None, 0, self.pixbuf_memory, HW_LIST_TYPE_MEMORY, []])
|
2008-03-06 16:43:46 -05:00
|
|
|
hw_list_model.append(["Boot Options", None, 0, self.pixbuf_memory, HW_LIST_TYPE_BOOT, []])
|
2007-04-12 15:36:04 -04:00
|
|
|
self.repopulate_hw_list()
|
2007-04-11 14:48:36 -04:00
|
|
|
|
2007-04-12 15:36:04 -04:00
|
|
|
def repopulate_hw_list(self):
|
2007-04-12 18:54:33 -04:00
|
|
|
hw_list = self.window.get_widget("hw-list")
|
|
|
|
|
hw_list_model = hw_list.get_model()
|
2007-04-11 14:48:36 -04:00
|
|
|
|
2007-04-12 15:36:04 -04:00
|
|
|
# Populate list of disks
|
2007-04-12 18:54:33 -04:00
|
|
|
currentDisks = {}
|
2007-04-12 15:36:04 -04:00
|
|
|
for disk in self.vm.get_disk_devices():
|
|
|
|
|
missing = True
|
|
|
|
|
insertAt = 0
|
2007-04-12 18:54:33 -04:00
|
|
|
currentDisks[disk[3]] = 1
|
2007-04-12 15:36:04 -04:00
|
|
|
for row in hw_list_model:
|
2007-07-14 14:43:20 -04:00
|
|
|
if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_DISK and row[HW_LIST_COL_DEVICE][3] == disk[3]:
|
2007-04-12 15:36:04 -04:00
|
|
|
# Update metadata
|
2007-07-14 14:43:20 -04:00
|
|
|
row[HW_LIST_COL_DEVICE] = disk
|
2007-04-12 15:36:04 -04:00
|
|
|
missing = False
|
2007-09-25 20:05:45 -04:00
|
|
|
|
2008-07-23 16:23:56 -04:00
|
|
|
if row[HW_LIST_COL_TYPE] <= HW_LIST_TYPE_DISK:
|
2007-04-12 15:36:04 -04:00
|
|
|
insertAt = insertAt + 1
|
|
|
|
|
|
|
|
|
|
# Add in row
|
|
|
|
|
if missing:
|
2007-07-14 14:43:20 -04:00
|
|
|
stock = gtk.STOCK_HARDDISK
|
|
|
|
|
if disk[2] == "cdrom":
|
|
|
|
|
stock = gtk.STOCK_CDROM
|
|
|
|
|
elif disk[2] == "floppy":
|
|
|
|
|
stock = gtk.STOCK_FLOPPY
|
|
|
|
|
hw_list_model.insert(insertAt, ["Disk %s" % disk[3], stock, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_DISK, disk])
|
2007-04-12 15:36:04 -04:00
|
|
|
|
|
|
|
|
# Populate list of NICs
|
2007-04-12 18:54:33 -04:00
|
|
|
currentNICs = {}
|
2007-04-12 15:36:04 -04:00
|
|
|
for nic in self.vm.get_network_devices():
|
|
|
|
|
missing = True
|
|
|
|
|
insertAt = 0
|
2007-04-12 18:54:33 -04:00
|
|
|
currentNICs[nic[3]] = 1
|
2007-04-12 15:36:04 -04:00
|
|
|
for row in hw_list_model:
|
2007-07-14 14:43:20 -04:00
|
|
|
if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_NIC and row[HW_LIST_COL_DEVICE][3] == nic[3]:
|
2007-04-12 15:36:04 -04:00
|
|
|
# Update metadata
|
2007-07-14 14:43:20 -04:00
|
|
|
row[HW_LIST_COL_DEVICE] = nic
|
2007-04-12 15:36:04 -04:00
|
|
|
missing = False
|
|
|
|
|
|
2008-07-23 16:23:56 -04:00
|
|
|
if row[HW_LIST_COL_TYPE] <= HW_LIST_TYPE_NIC:
|
2007-09-25 20:05:45 -04:00
|
|
|
insertAt = insertAt + 1
|
2007-04-12 15:36:04 -04:00
|
|
|
|
|
|
|
|
# Add in row
|
|
|
|
|
if missing:
|
2007-07-14 14:43:20 -04:00
|
|
|
hw_list_model.insert(insertAt, ["NIC %s" % nic[3][-9:], gtk.STOCK_NETWORK, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_NIC, nic])
|
2007-04-12 15:36:04 -04:00
|
|
|
|
2007-09-25 20:05:45 -04:00
|
|
|
# Populate list of input devices
|
|
|
|
|
currentInputs = {}
|
|
|
|
|
for input in self.vm.get_input_devices():
|
|
|
|
|
missing = True
|
|
|
|
|
insertAt = 0
|
|
|
|
|
currentInputs[input[3]] = 1
|
|
|
|
|
for row in hw_list_model:
|
|
|
|
|
if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_INPUT and row[HW_LIST_COL_DEVICE][3] == input[3]:
|
|
|
|
|
# Update metadata
|
|
|
|
|
row[HW_LIST_COL_DEVICE] = input
|
|
|
|
|
missing = False
|
|
|
|
|
|
2008-07-23 16:23:56 -04:00
|
|
|
if row[HW_LIST_COL_TYPE] <= HW_LIST_TYPE_INPUT:
|
2007-09-26 19:39:11 -04:00
|
|
|
insertAt = insertAt + 1
|
2007-09-25 20:05:45 -04:00
|
|
|
|
|
|
|
|
# Add in row
|
|
|
|
|
if missing:
|
|
|
|
|
if input[0] == "tablet":
|
|
|
|
|
hw_list_model.insert(insertAt, [_("Tablet"), gtk.STOCK_INDEX, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_INPUT, input])
|
|
|
|
|
elif input[0] == "mouse":
|
|
|
|
|
hw_list_model.insert(insertAt, [_("Mouse"), gtk.STOCK_INDEX, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_INPUT, input])
|
|
|
|
|
else:
|
|
|
|
|
hw_list_model.insert(insertAt, [_("Input"), gtk.STOCK_INDEX, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_INPUT, input])
|
|
|
|
|
|
2007-09-26 19:39:11 -04:00
|
|
|
# Populate list of graphics devices
|
|
|
|
|
currentGraphics = {}
|
|
|
|
|
for graphic in self.vm.get_graphics_devices():
|
|
|
|
|
missing = True
|
|
|
|
|
insertAt = 0
|
|
|
|
|
currentGraphics[graphic[3]] = 1
|
|
|
|
|
for row in hw_list_model:
|
|
|
|
|
if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_GRAPHICS and row[HW_LIST_COL_DEVICE][3] == graphic[3]:
|
|
|
|
|
# Update metadata
|
|
|
|
|
row[HW_LIST_COL_DEVICE] = graphic
|
|
|
|
|
missing = False
|
|
|
|
|
|
2008-07-23 16:23:56 -04:00
|
|
|
if row[HW_LIST_COL_TYPE] <= HW_LIST_TYPE_GRAPHICS:
|
|
|
|
|
insertAt = insertAt + 1
|
2007-09-26 19:39:11 -04:00
|
|
|
|
|
|
|
|
# Add in row
|
|
|
|
|
if missing:
|
|
|
|
|
hw_list_model.insert(insertAt, [_("Display"), gtk.STOCK_SELECT_COLOR, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_GRAPHICS, graphic])
|
|
|
|
|
|
2008-07-30 19:52:39 -04:00
|
|
|
# Populate list of sound devices
|
|
|
|
|
currentSounds = {}
|
|
|
|
|
for sound in self.vm.get_sound_devices():
|
|
|
|
|
missing = True
|
|
|
|
|
insertAt = 0
|
|
|
|
|
currentSounds[sound[3]] = 1
|
|
|
|
|
for row in hw_list_model:
|
|
|
|
|
if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_SOUND and \
|
|
|
|
|
row[HW_LIST_COL_DEVICE][3] == sound[3]:
|
|
|
|
|
# Update metadata
|
|
|
|
|
row[HW_LIST_COL_DEVICE] = sound
|
|
|
|
|
missing = False
|
|
|
|
|
|
|
|
|
|
if row[HW_LIST_COL_TYPE] <= HW_LIST_TYPE_SOUND:
|
|
|
|
|
insertAt = insertAt + 1
|
|
|
|
|
# Add in row
|
|
|
|
|
if missing:
|
|
|
|
|
hw_list_model.insert(insertAt, [_("Sound: %s" % sound[3]), gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_SOUND, sound])
|
|
|
|
|
|
2008-07-30 20:38:09 -04:00
|
|
|
|
|
|
|
|
# Populate list of char devices
|
|
|
|
|
currentChars = {}
|
|
|
|
|
for char in self.vm.get_char_devices():
|
|
|
|
|
missing = True
|
|
|
|
|
insertAt = 0
|
|
|
|
|
currentChars[char[3]] = 1
|
|
|
|
|
for row in hw_list_model:
|
|
|
|
|
if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_CHAR and \
|
|
|
|
|
row[HW_LIST_COL_DEVICE][3] == char[3]:
|
|
|
|
|
# Update metadata
|
|
|
|
|
row[HW_LIST_COL_DEVICE] = char
|
|
|
|
|
missing = False
|
|
|
|
|
|
|
|
|
|
if row[HW_LIST_COL_TYPE] <= HW_LIST_TYPE_CHAR:
|
|
|
|
|
insertAt = insertAt + 1
|
|
|
|
|
# Add in row
|
|
|
|
|
if missing:
|
|
|
|
|
l = char[0].capitalize()
|
|
|
|
|
if char[0] != "console":
|
|
|
|
|
l += " %s" % char[2] # Don't show port for console
|
|
|
|
|
hw_list_model.insert(insertAt, [l, gtk.STOCK_CONNECT, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_CHAR, char])
|
|
|
|
|
|
|
|
|
|
|
2007-04-12 18:54:33 -04:00
|
|
|
# Now remove any no longer current devs
|
|
|
|
|
devs = range(len(hw_list_model))
|
|
|
|
|
devs.reverse()
|
|
|
|
|
for i in devs:
|
|
|
|
|
iter = hw_list_model.iter_nth_child(None, i)
|
|
|
|
|
row = hw_list_model[i]
|
|
|
|
|
removeIt = False
|
|
|
|
|
|
2008-07-30 19:52:39 -04:00
|
|
|
if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_DISK and not \
|
|
|
|
|
currentDisks.has_key(row[HW_LIST_COL_DEVICE][3]):
|
|
|
|
|
removeIt = True
|
|
|
|
|
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_NIC and not \
|
|
|
|
|
currentNICs.has_key(row[HW_LIST_COL_DEVICE][3]):
|
2007-04-12 18:54:33 -04:00
|
|
|
removeIt = True
|
2008-07-30 19:52:39 -04:00
|
|
|
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_INPUT and not \
|
|
|
|
|
currentInputs.has_key(row[HW_LIST_COL_DEVICE][3]):
|
2007-04-12 18:54:33 -04:00
|
|
|
removeIt = True
|
2008-07-30 19:52:39 -04:00
|
|
|
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_GRAPHICS and not \
|
|
|
|
|
currentGraphics.has_key(row[HW_LIST_COL_DEVICE][3]):
|
2007-09-25 20:05:45 -04:00
|
|
|
removeIt = True
|
2008-07-30 19:52:39 -04:00
|
|
|
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_SOUND and not \
|
|
|
|
|
currentSounds.has_key(row[HW_LIST_COL_DEVICE][3]):
|
2007-09-26 19:39:11 -04:00
|
|
|
removeIt = True
|
2008-07-30 20:38:09 -04:00
|
|
|
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_CHAR and not \
|
|
|
|
|
currentChars.has_key(row[HW_LIST_COL_DEVICE][3]):
|
|
|
|
|
removeIt = True
|
2007-04-12 18:54:33 -04:00
|
|
|
|
|
|
|
|
if removeIt:
|
|
|
|
|
# Re-select the first row, if we're viewing the device
|
|
|
|
|
# we're about to remove
|
|
|
|
|
(selModel, selIter) = hw_list.get_selection().get_selected()
|
2007-07-14 14:43:20 -04:00
|
|
|
selType = selModel.get_value(selIter, HW_LIST_COL_TYPE)
|
|
|
|
|
selInfo = selModel.get_value(selIter, HW_LIST_COL_DEVICE)
|
|
|
|
|
if selType == row[HW_LIST_COL_TYPE] and selInfo[3] == row[HW_LIST_COL_DEVICE][3]:
|
2007-04-12 18:54:33 -04:00
|
|
|
hw_list.get_selection().select_iter(selModel.iter_nth_child(None, 0))
|
|
|
|
|
|
|
|
|
|
# Now actually remove it
|
|
|
|
|
hw_list_model.remove(iter)
|
|
|
|
|
|
2008-03-06 16:43:46 -05:00
|
|
|
def repopulate_boot_list(self):
|
|
|
|
|
hw_list_model = self.window.get_widget("hw-list").get_model()
|
|
|
|
|
boot_combo = self.window.get_widget("config-boot-device")
|
|
|
|
|
boot_model = boot_combo.get_model()
|
|
|
|
|
boot_model.clear()
|
|
|
|
|
found_dev = {}
|
|
|
|
|
for row in hw_list_model:
|
|
|
|
|
if row[4] == HW_LIST_TYPE_DISK:
|
|
|
|
|
disk = row[5]
|
|
|
|
|
if disk[2] == virtinst.VirtualDisk.DEVICE_DISK and not \
|
|
|
|
|
found_dev.get(virtinst.VirtualDisk.DEVICE_DISK, False):
|
|
|
|
|
boot_model.append(["Hard Disk", gtk.STOCK_HARDDISK, "hd"])
|
|
|
|
|
found_dev[virtinst.VirtualDisk.DEVICE_DISK] = True
|
|
|
|
|
elif disk[2] == virtinst.VirtualDisk.DEVICE_CDROM and not \
|
|
|
|
|
found_dev.get(virtinst.VirtualDisk.DEVICE_CDROM, False):
|
|
|
|
|
boot_model.append(["CDROM", gtk.STOCK_CDROM, "cdrom"])
|
|
|
|
|
found_dev[virtinst.VirtualDisk.DEVICE_CDROM] = True
|
|
|
|
|
elif disk[2] == virtinst.VirtualDisk.DEVICE_FLOPPY and not \
|
|
|
|
|
found_dev.get(virtinst.VirtualDisk.DEVICE_FLOPPY, False):
|
|
|
|
|
boot_model.append(["Floppy", gtk.STOCK_FLOPPY, "fd"])
|
|
|
|
|
found_dev[virtinst.VirtualDisk.DEVICE_FLOPPY] = True
|
|
|
|
|
elif row[4] == HW_LIST_TYPE_NIC and not \
|
|
|
|
|
found_dev.get(HW_LIST_TYPE_NIC, False):
|
|
|
|
|
boot_model.append(["Network (PXE)", gtk.STOCK_NETWORK, "network"])
|
|
|
|
|
found_dev[HW_LIST_TYPE_NIC] = True
|
|
|
|
|
|
|
|
|
|
if len(boot_model) <= 0:
|
|
|
|
|
boot_model.append([_("No Boot Device"), None, None])
|
|
|
|
|
|
|
|
|
|
boot_combo.set_model(boot_model)
|
2007-04-12 15:36:04 -04:00
|
|
|
|
|
|
|
|
def add_hardware(self, src):
|
|
|
|
|
if self.addhw is None:
|
|
|
|
|
self.addhw = vmmAddHardware(self.config, self.vm)
|
2007-09-26 19:44:52 -04:00
|
|
|
self.addhw.topwin.connect("hide", self.add_hardware_done)
|
2007-04-12 15:36:04 -04:00
|
|
|
|
|
|
|
|
self.addhw.show()
|
2007-04-11 14:48:36 -04:00
|
|
|
|
2007-09-26 19:44:52 -04:00
|
|
|
def add_hardware_done(self, ignore=None):
|
|
|
|
|
self.refresh_resources()
|
|
|
|
|
|
2007-09-21 16:28:31 -04:00
|
|
|
def toggle_cdrom(self, src):
|
|
|
|
|
if src.get_label() == gtk.STOCK_DISCONNECT:
|
|
|
|
|
#disconnect the cdrom
|
2007-11-16 17:12:37 -05:00
|
|
|
try:
|
|
|
|
|
self.vm.disconnect_cdrom_device(self.window.get_widget("disk-target-device").get_text())
|
|
|
|
|
except Exception, e:
|
2008-03-14 13:18:44 -04:00
|
|
|
self.err.show_err(_("Error Removing CDROM: %s" % str(e)),
|
|
|
|
|
"".join(traceback.format_exc()))
|
2007-11-16 17:12:37 -05:00
|
|
|
return
|
2008-08-21 16:01:15 -04:00
|
|
|
|
2007-09-21 16:28:31 -04:00
|
|
|
else:
|
|
|
|
|
# connect a new cdrom
|
|
|
|
|
if self.choose_cd is None:
|
2008-09-09 07:05:58 -04:00
|
|
|
self.choose_cd = vmmChooseCD(self.config, self.window.get_widget("disk-target-device").get_text(), self.vm.get_connection())
|
2007-11-28 16:26:08 -05:00
|
|
|
self.choose_cd.connect("cdrom-chosen", self.connect_cdrom)
|
2007-09-21 16:28:31 -04:00
|
|
|
else:
|
|
|
|
|
self.choose_cd.set_target(self.window.get_widget("disk-target-device").get_text())
|
|
|
|
|
self.choose_cd.show()
|
|
|
|
|
|
|
|
|
|
def connect_cdrom(self, src, type, source, target):
|
2007-11-28 16:26:08 -05:00
|
|
|
try:
|
|
|
|
|
self.vm.connect_cdrom_device(type, source, target)
|
2008-08-21 16:01:15 -04:00
|
|
|
except Exception, e:
|
2008-03-14 13:18:44 -04:00
|
|
|
self.err.show_err(_("Error Connecting CDROM: %s" % str(e)),
|
|
|
|
|
"".join(traceback.format_exc()))
|
2006-08-29 15:52:19 -04:00
|
|
|
|
2007-11-16 17:12:37 -05:00
|
|
|
def remove_device(self, xml):
|
2008-08-21 16:01:15 -04:00
|
|
|
logging.debug("Removing device:\n%s" % xml)
|
|
|
|
|
|
|
|
|
|
detach_err = False
|
|
|
|
|
try:
|
|
|
|
|
self.vm.detach_device(xml)
|
|
|
|
|
except Exception, e:
|
|
|
|
|
logging.debug("Device could not be hotUNplugged: %s" % str(e))
|
|
|
|
|
detach_err = True
|
|
|
|
|
|
|
|
|
|
if detach_err:
|
|
|
|
|
if not self.err.yes_no(_("Are you sure you want to remove this "
|
|
|
|
|
"device?"),
|
|
|
|
|
_("This device could not be removed from "
|
|
|
|
|
"the running machine. Would you like to "
|
|
|
|
|
"remove the device after the next VM "
|
|
|
|
|
"shutdown? \n\n"
|
|
|
|
|
"Warning: this will overwrite any "
|
|
|
|
|
"other changes that require a VM "
|
|
|
|
|
"reboot.")):
|
|
|
|
|
return
|
|
|
|
|
|
2008-08-22 18:29:50 -04:00
|
|
|
if self.vm.is_active() and not detach_err:
|
|
|
|
|
return
|
|
|
|
|
|
2007-11-16 17:12:37 -05:00
|
|
|
try:
|
|
|
|
|
self.vm.remove_device(xml)
|
|
|
|
|
except Exception, e:
|
2008-03-14 13:18:44 -04:00
|
|
|
self.err.show_err(_("Error Removing Device: %s" % str(e)),
|
|
|
|
|
"".join(traceback.format_exc()))
|
|
|
|
|
|
2006-06-14 16:20:06 -04:00
|
|
|
gobject.type_register(vmmDetails)
|