2006-06-29 03:50:17 +08:00
|
|
|
#
|
|
|
|
# Copyright (C) 2006 Red Hat, Inc.
|
|
|
|
# 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-21 00:12:20 +08:00
|
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
# MA 02110-1301 USA.
|
2006-06-29 03:50:17 +08:00
|
|
|
#
|
2007-11-21 00:12:20 +08:00
|
|
|
|
2013-04-12 05:16:33 +08:00
|
|
|
# pylint: disable=E0611
|
2013-02-17 03:03:30 +08:00
|
|
|
from gi.repository import GLib
|
2012-05-14 21:24:56 +08:00
|
|
|
from gi.repository import GObject
|
|
|
|
from gi.repository import Gtk
|
2013-04-12 05:16:33 +08:00
|
|
|
# pylint: enable=E0611
|
2009-11-16 09:54:55 +08:00
|
|
|
|
2006-09-26 06:41:47 +08:00
|
|
|
import logging
|
2013-07-07 08:03:42 +08:00
|
|
|
import Queue
|
2009-07-12 09:23:16 +08:00
|
|
|
import threading
|
2006-06-14 22:59:40 +08:00
|
|
|
|
2009-11-16 09:54:55 +08:00
|
|
|
import libvirt
|
|
|
|
import virtinst
|
|
|
|
|
2012-07-09 03:05:28 +08:00
|
|
|
from virtManager import packageutils
|
|
|
|
from virtManager import uihelpers
|
|
|
|
from virtManager import util
|
2006-06-14 22:59:40 +08:00
|
|
|
from virtManager.about import vmmAbout
|
2010-12-10 01:37:48 +08:00
|
|
|
from virtManager.baseclass import vmmGObject
|
2009-07-27 03:54:14 +08:00
|
|
|
from virtManager.clone import vmmCloneVM
|
2006-06-14 22:59:40 +08:00
|
|
|
from virtManager.connect import vmmConnect
|
|
|
|
from virtManager.connection import vmmConnection
|
|
|
|
from virtManager.preferences import vmmPreferences
|
2006-06-15 04:20:06 +08:00
|
|
|
from virtManager.manager import vmmManager
|
2009-11-16 04:17:03 +08:00
|
|
|
from virtManager.migrate import vmmMigrateDialog
|
2006-06-15 04:20:06 +08:00
|
|
|
from virtManager.details import vmmDetails
|
2006-07-25 01:50:11 +08:00
|
|
|
from virtManager.asyncjob import vmmAsyncJob
|
2006-08-09 05:02:15 +08:00
|
|
|
from virtManager.create import vmmCreate
|
2007-03-28 07:52:00 +08:00
|
|
|
from virtManager.host import vmmHost
|
2007-11-28 00:31:30 +08:00
|
|
|
from virtManager.error import vmmErrorDialog
|
2009-07-28 10:30:01 +08:00
|
|
|
from virtManager.systray import vmmSystray
|
2013-06-18 04:29:51 +08:00
|
|
|
from virtManager.delete import vmmDeleteDialog
|
2006-06-14 22:59:40 +08:00
|
|
|
|
2011-04-12 00:54:47 +08:00
|
|
|
# Enable this to get a report of leaked objects on app shutdown
|
2013-04-17 21:09:53 +08:00
|
|
|
# gtk3/pygobject has issues here as of Fedora 18
|
2013-01-31 01:50:55 +08:00
|
|
|
debug_ref_leaks = False
|
2011-04-12 00:54:47 +08:00
|
|
|
|
2011-06-09 04:33:20 +08:00
|
|
|
DETAILS_PERF = 1
|
|
|
|
DETAILS_CONFIG = 2
|
|
|
|
DETAILS_CONSOLE = 3
|
|
|
|
|
2013-07-07 21:42:21 +08:00
|
|
|
(PRIO_HIGH,
|
|
|
|
PRIO_LOW) = range(1, 3)
|
|
|
|
|
2013-04-14 02:34:52 +08:00
|
|
|
|
2010-12-10 01:37:48 +08:00
|
|
|
class vmmEngine(vmmGObject):
|
2012-05-14 21:24:56 +08:00
|
|
|
__gsignals__ = {
|
|
|
|
"conn-added": (GObject.SignalFlags.RUN_FIRST, None, [object]),
|
|
|
|
"conn-removed": (GObject.SignalFlags.RUN_FIRST, None, [str]),
|
|
|
|
}
|
|
|
|
|
2010-12-10 01:37:48 +08:00
|
|
|
def __init__(self):
|
|
|
|
vmmGObject.__init__(self)
|
2009-11-16 04:17:03 +08:00
|
|
|
|
2006-06-15 04:20:06 +08:00
|
|
|
self.windowConnect = None
|
2006-06-14 22:59:40 +08:00
|
|
|
self.windowPreferences = None
|
|
|
|
self.windowAbout = None
|
2006-08-09 05:02:15 +08:00
|
|
|
self.windowCreate = None
|
2007-08-10 04:19:41 +08:00
|
|
|
self.windowManager = None
|
2009-11-16 04:17:03 +08:00
|
|
|
self.windowMigrate = None
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
self.conns = {}
|
2010-12-01 03:33:21 +08:00
|
|
|
self.err = vmmErrorDialog()
|
2006-06-14 22:59:40 +08:00
|
|
|
|
|
|
|
self.timer = None
|
|
|
|
self.last_timeout = 0
|
|
|
|
|
2009-07-28 10:30:01 +08:00
|
|
|
self.systray = None
|
2013-06-18 04:29:51 +08:00
|
|
|
self.delete_dialog = None
|
2013-04-16 07:25:54 +08:00
|
|
|
self.application = Gtk.Application(
|
|
|
|
application_id="com.redhat.virt-manager",
|
|
|
|
flags=0)
|
|
|
|
self.application.connect("activate", self._activate)
|
|
|
|
self._appwindow = Gtk.Window()
|
2009-07-28 10:30:01 +08:00
|
|
|
|
2013-07-07 08:03:42 +08:00
|
|
|
self._tick_counter = 0
|
2009-07-12 09:23:16 +08:00
|
|
|
self._tick_thread_slow = False
|
2013-07-07 08:03:42 +08:00
|
|
|
self._tick_thread = threading.Thread(name="Tick thread",
|
|
|
|
target=self._handle_tick_queue,
|
|
|
|
args=())
|
|
|
|
self._tick_thread.daemon = True
|
|
|
|
self._tick_queue = Queue.PriorityQueue(100)
|
2009-07-12 09:23:16 +08:00
|
|
|
|
2011-07-23 02:19:35 +08:00
|
|
|
self.inspection = None
|
2011-07-19 02:53:54 +08:00
|
|
|
self._create_inspection_thread()
|
|
|
|
|
2008-06-14 00:12:37 +08:00
|
|
|
# Counter keeping track of how many manager and details windows
|
2009-10-29 23:08:40 +08:00
|
|
|
# are open. When it is decremented to 0, close the app or
|
|
|
|
# keep running in system tray if enabled
|
2008-06-14 00:12:37 +08:00
|
|
|
self.windows = 0
|
|
|
|
|
2013-04-16 07:25:54 +08:00
|
|
|
# Public bits set by virt-manager cli
|
|
|
|
self.skip_autostart = False
|
|
|
|
self.uri_at_startup = None
|
|
|
|
self.uri_cb = None
|
2013-05-30 05:43:38 +08:00
|
|
|
self.show_manager_window = True
|
2013-04-16 07:25:54 +08:00
|
|
|
|
2009-07-28 10:30:01 +08:00
|
|
|
self.init_systray()
|
2009-07-02 02:59:13 +08:00
|
|
|
|
2011-04-13 21:27:02 +08:00
|
|
|
self.add_gconf_handle(
|
|
|
|
self.config.on_stats_update_interval_changed(self.reschedule_timer))
|
|
|
|
self.add_gconf_handle(
|
|
|
|
self.config.on_view_system_tray_changed(self.system_tray_changed))
|
2006-06-14 22:59:40 +08:00
|
|
|
|
|
|
|
self.schedule_timer()
|
2007-09-10 10:57:24 +08:00
|
|
|
self.load_stored_uris()
|
2013-07-07 08:03:42 +08:00
|
|
|
|
|
|
|
self._tick_thread.start()
|
2006-06-14 22:59:40 +08:00
|
|
|
self.tick()
|
|
|
|
|
2010-03-04 05:58:50 +08:00
|
|
|
|
2013-04-16 07:25:54 +08:00
|
|
|
def _activate(self, ignore):
|
2013-05-30 05:43:38 +08:00
|
|
|
if self.show_manager_window:
|
|
|
|
self.show_manager()
|
|
|
|
else:
|
|
|
|
self.get_manager()
|
2013-04-16 07:25:54 +08:00
|
|
|
self.application.add_window(self._appwindow)
|
|
|
|
|
|
|
|
if self.uri_at_startup:
|
|
|
|
conn = self.add_conn_to_ui(self.uri_at_startup)
|
|
|
|
if conn and self.uri_cb:
|
|
|
|
conn.connect_opt_out("state-changed", self.uri_cb)
|
|
|
|
|
|
|
|
self.connect_to_uri(self.uri_at_startup)
|
|
|
|
|
|
|
|
if not self.skip_autostart:
|
|
|
|
self.autostart_conns()
|
|
|
|
|
|
|
|
|
2009-07-28 10:30:01 +08:00
|
|
|
def init_systray(self):
|
|
|
|
if self.systray:
|
|
|
|
return
|
|
|
|
|
2010-12-10 03:06:00 +08:00
|
|
|
self.systray = vmmSystray(self)
|
2009-10-29 23:08:40 +08:00
|
|
|
self.systray.connect("action-toggle-manager", self._do_toggle_manager)
|
2009-07-28 10:30:01 +08:00
|
|
|
self.systray.connect("action-suspend-domain", self._do_suspend_domain)
|
|
|
|
self.systray.connect("action-resume-domain", self._do_resume_domain)
|
|
|
|
self.systray.connect("action-run-domain", self._do_run_domain)
|
|
|
|
self.systray.connect("action-shutdown-domain", self._do_shutdown_domain)
|
|
|
|
self.systray.connect("action-reboot-domain", self._do_reboot_domain)
|
|
|
|
self.systray.connect("action-destroy-domain", self._do_destroy_domain)
|
2013-03-17 05:59:32 +08:00
|
|
|
self.systray.connect("action-reset-domain", self._do_reset_domain)
|
2011-06-09 04:33:20 +08:00
|
|
|
self.systray.connect("action-show-vm", self._do_show_vm)
|
2010-11-24 09:13:50 +08:00
|
|
|
self.systray.connect("action-exit-app", self.exit_app)
|
2009-07-28 10:30:01 +08:00
|
|
|
|
2009-10-29 23:08:40 +08:00
|
|
|
def system_tray_changed(self, *ignore):
|
|
|
|
systray_enabled = self.config.get_view_system_tray()
|
|
|
|
if self.windows == 0 and not systray_enabled:
|
|
|
|
# Show the manager so that the user can control the application
|
|
|
|
self.show_manager()
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
def add_default_conn(self, manager):
|
2010-03-04 05:58:50 +08:00
|
|
|
# Only add default if no connections are currently known
|
2011-07-23 04:43:26 +08:00
|
|
|
if self.config.get_conn_uris():
|
2010-03-04 05:58:50 +08:00
|
|
|
return
|
|
|
|
|
|
|
|
# Manager fail message
|
|
|
|
msg = _("Could not detect a default hypervisor. Make\n"
|
|
|
|
"sure the appropriate virtualization packages\n"
|
|
|
|
"are installed (kvm, qemu, libvirt, etc.), and\n"
|
|
|
|
"that libvirtd is running.\n\n"
|
|
|
|
"A hypervisor connection can be manually\n"
|
|
|
|
"added via File->Add Connection")
|
|
|
|
|
|
|
|
logging.debug("Determining default libvirt URI")
|
|
|
|
|
|
|
|
ret = None
|
|
|
|
try:
|
2011-01-15 04:19:58 +08:00
|
|
|
libvirt_packages = self.config.libvirt_packages
|
|
|
|
packages = self.config.hv_packages + libvirt_packages
|
|
|
|
|
2012-10-29 08:22:58 +08:00
|
|
|
ret = packageutils.check_packagekit(manager.err, packages, True)
|
2010-03-04 05:58:50 +08:00
|
|
|
except:
|
|
|
|
logging.exception("Error talking to PackageKit")
|
|
|
|
|
2012-07-09 03:38:52 +08:00
|
|
|
if ret is not None:
|
|
|
|
tryuri = "qemu:///system"
|
2010-03-04 05:58:50 +08:00
|
|
|
else:
|
2013-07-07 06:55:24 +08:00
|
|
|
tryuri = util.default_uri(always_system=True)
|
2010-03-04 05:58:50 +08:00
|
|
|
|
|
|
|
if tryuri is None:
|
|
|
|
manager.set_startup_error(msg)
|
|
|
|
return
|
|
|
|
|
2013-06-25 00:15:28 +08:00
|
|
|
warnmsg = _("The 'libvirtd' service will need to be started.\n\n"
|
|
|
|
"After that, virt-manager will connect to libvirt on\n"
|
|
|
|
"the next application start up.")
|
2013-06-14 05:35:48 +08:00
|
|
|
|
|
|
|
# Do the initial connection in an idle callback, so the
|
|
|
|
# packagekit async dialog has a chance to go away
|
|
|
|
def idle_connect():
|
|
|
|
do_start = packageutils.start_libvirtd()
|
|
|
|
if not do_start:
|
|
|
|
manager.err.ok(_("Libvirt service must be started"), warnmsg)
|
|
|
|
|
|
|
|
self.connect_to_uri(tryuri, autoconnect=True, do_start=do_start)
|
|
|
|
self.idle_add(idle_connect)
|
2010-03-04 05:58:50 +08:00
|
|
|
|
|
|
|
|
2007-08-29 05:57:25 +08:00
|
|
|
def load_stored_uris(self):
|
2011-07-23 04:43:26 +08:00
|
|
|
uris = self.config.get_conn_uris()
|
2012-11-08 18:02:17 +08:00
|
|
|
if not uris:
|
|
|
|
return
|
|
|
|
logging.debug("About to connect to uris %s", uris)
|
|
|
|
for uri in uris:
|
|
|
|
self.add_conn_to_ui(uri)
|
2007-08-29 05:57:25 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
def autostart_conns(self):
|
|
|
|
for uri in self.conns:
|
|
|
|
conn = self.conns[uri]["conn"]
|
2008-03-24 23:39:19 +08:00
|
|
|
if conn.get_autoconnect():
|
|
|
|
self.connect_to_uri(uri)
|
|
|
|
|
2006-06-15 02:36:26 +08:00
|
|
|
|
2011-07-23 01:54:40 +08:00
|
|
|
def _do_vm_removed(self, conn, vmuuid):
|
|
|
|
hvuri = conn.get_uri()
|
2011-07-23 04:43:26 +08:00
|
|
|
if vmuuid not in self.conns[hvuri]["windowDetails"]:
|
2011-04-12 06:35:21 +08:00
|
|
|
return
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
self.conns[hvuri]["windowDetails"][vmuuid].cleanup()
|
|
|
|
del(self.conns[hvuri]["windowDetails"][vmuuid])
|
2006-06-15 04:56:49 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
def _do_conn_changed(self, conn):
|
|
|
|
if (conn.get_state() == conn.STATE_ACTIVE or
|
|
|
|
conn.get_state() == conn.STATE_CONNECTING):
|
2007-09-27 09:04:02 +08:00
|
|
|
return
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
hvuri = conn.get_uri()
|
2011-04-12 06:35:21 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
for vmuuid in self.conns[hvuri]["windowDetails"].keys():
|
|
|
|
self.conns[hvuri]["windowDetails"][vmuuid].cleanup()
|
|
|
|
del(self.conns[hvuri]["windowDetails"][vmuuid])
|
2011-04-12 06:35:21 +08:00
|
|
|
|
|
|
|
if (self.windowCreate and
|
|
|
|
self.windowCreate.conn and
|
2009-03-10 04:16:45 +08:00
|
|
|
self.windowCreate.conn.get_uri() == hvuri):
|
|
|
|
self.windowCreate.close()
|
2007-09-27 09:04:02 +08:00
|
|
|
|
2013-06-15 04:22:33 +08:00
|
|
|
def reschedule_timer(self, *args, **kwargs):
|
2013-06-18 08:17:20 +08:00
|
|
|
ignore = args
|
|
|
|
ignore = kwargs
|
2006-06-14 22:59:40 +08:00
|
|
|
self.schedule_timer()
|
|
|
|
|
|
|
|
def schedule_timer(self):
|
2010-12-10 03:06:00 +08:00
|
|
|
interval = self.config.get_stats_update_interval() * 1000
|
2006-06-14 22:59:40 +08:00
|
|
|
|
2012-11-08 21:15:02 +08:00
|
|
|
if self.timer is not None:
|
|
|
|
self.remove_gobject_timeout(self.timer)
|
2006-06-14 22:59:40 +08:00
|
|
|
self.timer = None
|
|
|
|
|
2012-11-08 21:15:02 +08:00
|
|
|
self.timer = self.timeout_add(interval, self.tick)
|
2006-06-14 22:59:40 +08:00
|
|
|
|
2013-07-07 08:03:42 +08:00
|
|
|
def _add_obj_to_tick_queue(self, obj, isprio):
|
|
|
|
if self._tick_queue.full():
|
2009-07-14 21:45:23 +08:00
|
|
|
if not self._tick_thread_slow:
|
2009-07-12 09:23:16 +08:00
|
|
|
logging.debug("Tick is slow, not running at requested rate.")
|
2009-10-02 00:04:03 +08:00
|
|
|
self._tick_thread_slow = True
|
2013-07-07 08:03:42 +08:00
|
|
|
return
|
2009-07-12 09:23:16 +08:00
|
|
|
|
2013-07-07 08:03:42 +08:00
|
|
|
self._tick_counter += 1
|
2013-07-07 21:42:21 +08:00
|
|
|
self._tick_queue.put((isprio and PRIO_HIGH or PRIO_LOW,
|
2013-07-07 08:03:42 +08:00
|
|
|
self._tick_counter, obj))
|
2007-03-10 05:22:43 +08:00
|
|
|
|
2013-07-07 08:03:42 +08:00
|
|
|
def _schedule_priority_tick(self, conn, obj):
|
|
|
|
ignore = conn
|
|
|
|
self._add_obj_to_tick_queue(obj, True)
|
|
|
|
|
|
|
|
def tick(self):
|
2011-07-23 04:43:26 +08:00
|
|
|
for uri in self.conns.keys():
|
|
|
|
conn = self.conns[uri]["conn"]
|
2013-07-07 08:03:42 +08:00
|
|
|
self._add_obj_to_tick_queue(conn, False)
|
|
|
|
return 1
|
2011-07-26 01:31:36 +08:00
|
|
|
|
2013-07-07 08:03:42 +08:00
|
|
|
def _handle_tick_queue(self):
|
|
|
|
while True:
|
|
|
|
prio, ignore, obj = self._tick_queue.get()
|
2013-07-07 21:42:21 +08:00
|
|
|
stats_update = prio != PRIO_HIGH
|
|
|
|
self._tick_single_conn(obj, stats_update)
|
2013-07-07 08:03:42 +08:00
|
|
|
self._tick_queue.task_done()
|
2006-06-14 22:59:40 +08:00
|
|
|
return 1
|
|
|
|
|
2013-07-07 21:42:21 +08:00
|
|
|
def _tick_single_conn(self, conn, stats_update):
|
2013-07-07 08:03:42 +08:00
|
|
|
try:
|
2013-07-07 21:42:21 +08:00
|
|
|
conn.tick(stats_update=stats_update)
|
2013-07-07 08:03:42 +08:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
raise
|
|
|
|
except libvirt.libvirtError, e:
|
|
|
|
from_remote = getattr(libvirt, "VIR_FROM_REMOTE", None)
|
|
|
|
from_rpc = getattr(libvirt, "VIR_FROM_RPC", None)
|
|
|
|
sys_error = getattr(libvirt, "VIR_ERR_SYSTEM_ERROR", None)
|
|
|
|
|
|
|
|
dom = e.get_error_domain()
|
|
|
|
code = e.get_error_code()
|
|
|
|
|
|
|
|
if (dom in [from_remote, from_rpc] and
|
|
|
|
code in [sys_error]):
|
|
|
|
logging.exception("Could not refresh connection %s",
|
|
|
|
conn.get_uri())
|
|
|
|
logging.debug("Closing connection since libvirtd "
|
|
|
|
"appears to have stopped")
|
|
|
|
else:
|
|
|
|
error_msg = _("Error polling connection '%s': %s") \
|
|
|
|
% (conn.get_uri(), e)
|
|
|
|
self.idle_add(lambda: self.err.show_err(error_msg))
|
|
|
|
|
|
|
|
self.idle_add(conn.close)
|
|
|
|
|
|
|
|
|
2011-04-13 22:47:31 +08:00
|
|
|
def increment_window_counter(self, src):
|
|
|
|
ignore = src
|
2008-06-14 00:12:37 +08:00
|
|
|
self.windows += 1
|
2012-01-17 11:04:40 +08:00
|
|
|
logging.debug("window counter incremented to %s", self.windows)
|
2008-06-14 00:12:37 +08:00
|
|
|
|
2011-04-13 22:47:31 +08:00
|
|
|
def decrement_window_counter(self, src):
|
2008-06-14 00:12:37 +08:00
|
|
|
self.windows -= 1
|
2012-01-17 11:04:40 +08:00
|
|
|
logging.debug("window counter decremented to %s", self.windows)
|
2011-04-13 21:27:02 +08:00
|
|
|
|
2009-10-29 23:08:40 +08:00
|
|
|
# Don't exit if system tray is enabled
|
2011-04-13 21:27:02 +08:00
|
|
|
if (self.windows <= 0 and
|
|
|
|
self.systray and
|
|
|
|
not self.systray.is_visible()):
|
2013-06-11 22:44:25 +08:00
|
|
|
# Defer this to an idle callback, since we can race with
|
|
|
|
# a vmmDetails window being deleted.
|
|
|
|
self.idle_add(self.exit_app, src)
|
2008-06-14 00:12:37 +08:00
|
|
|
|
2011-07-24 09:16:54 +08:00
|
|
|
def _cleanup(self):
|
|
|
|
uihelpers.cleanup()
|
|
|
|
self.err = None
|
|
|
|
|
|
|
|
if self.inspection:
|
|
|
|
self.inspection.cleanup()
|
|
|
|
self.inspection = None
|
|
|
|
|
2012-11-08 21:15:02 +08:00
|
|
|
if self.timer is not None:
|
2013-02-17 03:03:30 +08:00
|
|
|
GLib.source_remove(self.timer)
|
2011-07-24 09:16:54 +08:00
|
|
|
|
|
|
|
if self.systray:
|
|
|
|
self.systray.cleanup()
|
|
|
|
self.systray = None
|
|
|
|
|
|
|
|
self.get_manager()
|
|
|
|
if self.windowManager:
|
|
|
|
self.windowManager.cleanup()
|
|
|
|
self.windowManager = None
|
|
|
|
|
|
|
|
if self.windowPreferences:
|
|
|
|
self.windowPreferences.cleanup()
|
|
|
|
self.windowPreferences = None
|
|
|
|
|
|
|
|
if self.windowAbout:
|
|
|
|
self.windowAbout.cleanup()
|
|
|
|
self.windowAbout = None
|
|
|
|
|
|
|
|
if self.windowConnect:
|
|
|
|
self.windowConnect.cleanup()
|
|
|
|
self.windowConnect = None
|
|
|
|
|
|
|
|
if self.windowCreate:
|
|
|
|
self.windowCreate.cleanup()
|
|
|
|
self.windowCreate = None
|
|
|
|
|
|
|
|
if self.windowMigrate:
|
|
|
|
self.windowMigrate.cleanup()
|
|
|
|
self.windowMigrate = None
|
|
|
|
|
2013-06-18 04:29:51 +08:00
|
|
|
if self.delete_dialog:
|
|
|
|
self.delete_dialog.cleanup()
|
|
|
|
self.delete_dialog = None
|
|
|
|
|
2011-07-24 09:16:54 +08:00
|
|
|
# Do this last, so any manually 'disconnected' signals
|
|
|
|
# take precedence over cleanup signal removal
|
|
|
|
for uri in self.conns:
|
|
|
|
self.cleanup_conn(uri)
|
|
|
|
self.conns = {}
|
2011-04-13 21:27:02 +08:00
|
|
|
|
2011-04-13 22:47:31 +08:00
|
|
|
def exit_app(self, src):
|
2011-04-13 21:27:02 +08:00
|
|
|
if self.err is None:
|
|
|
|
# Already in cleanup
|
|
|
|
return
|
|
|
|
|
|
|
|
self.cleanup()
|
2011-04-12 00:54:47 +08:00
|
|
|
|
|
|
|
if debug_ref_leaks:
|
2011-04-13 21:27:02 +08:00
|
|
|
objs = self.config.get_objects()
|
|
|
|
|
|
|
|
# Engine will always appear to leak
|
|
|
|
objs.remove(self.object_key)
|
|
|
|
|
2011-04-14 23:26:53 +08:00
|
|
|
if src.object_key in objs:
|
|
|
|
# UI that initiates the app exit will always appear to leak
|
|
|
|
objs.remove(src.object_key)
|
|
|
|
|
2011-04-13 21:27:02 +08:00
|
|
|
for name in objs:
|
2012-01-17 11:04:40 +08:00
|
|
|
logging.debug("Leaked %s", name)
|
2011-04-12 00:54:47 +08:00
|
|
|
|
2008-10-30 21:25:53 +08:00
|
|
|
logging.debug("Exiting app normally.")
|
2013-06-14 23:24:32 +08:00
|
|
|
|
|
|
|
# We need this if there are any asyncdialog fobjs running
|
|
|
|
if Gtk.main_level():
|
|
|
|
logging.debug("%s other gtk main loops running, killing them.",
|
|
|
|
Gtk.main_level())
|
|
|
|
for ignore in range(Gtk.main_level()):
|
|
|
|
Gtk.main_quit()
|
|
|
|
|
2013-04-16 07:25:54 +08:00
|
|
|
self.application.remove_window(self._appwindow)
|
2008-06-14 00:12:37 +08:00
|
|
|
|
2011-07-19 02:53:54 +08:00
|
|
|
def _create_inspection_thread(self):
|
2013-06-14 04:00:33 +08:00
|
|
|
logging.debug("libguestfs inspection support: %s",
|
|
|
|
self.config.support_inspection)
|
2011-07-19 02:53:54 +08:00
|
|
|
if not self.config.support_inspection:
|
|
|
|
return
|
2013-06-14 04:00:33 +08:00
|
|
|
|
2011-07-19 02:53:54 +08:00
|
|
|
from virtManager.inspection import vmmInspection
|
2011-07-23 02:19:35 +08:00
|
|
|
self.inspection = vmmInspection()
|
|
|
|
self.inspection.start()
|
2011-07-23 04:43:26 +08:00
|
|
|
self.connect("conn-added", self.inspection.conn_added)
|
|
|
|
self.connect("conn-removed", self.inspection.conn_removed)
|
2011-07-19 02:53:54 +08:00
|
|
|
return
|
|
|
|
|
2012-11-08 18:02:17 +08:00
|
|
|
|
|
|
|
def add_conn_to_ui(self, uri):
|
|
|
|
# Public method called from virt-manager.py
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._check_conn(uri)
|
2010-11-30 07:00:15 +08:00
|
|
|
if conn:
|
|
|
|
return conn
|
|
|
|
|
2011-07-15 08:52:40 +08:00
|
|
|
conn = vmmConnection(uri)
|
2011-07-23 04:43:26 +08:00
|
|
|
self.conns[uri] = {
|
|
|
|
"conn": conn,
|
2007-09-10 10:57:24 +08:00
|
|
|
"windowHost": None,
|
|
|
|
"windowDetails": {},
|
2009-07-27 03:54:14 +08:00
|
|
|
"windowClone": None,
|
2011-04-13 00:06:44 +08:00
|
|
|
}
|
2010-11-24 07:54:12 +08:00
|
|
|
|
|
|
|
conn.connect("vm-removed", self._do_vm_removed)
|
2011-07-23 04:43:26 +08:00
|
|
|
conn.connect("state-changed", self._do_conn_changed)
|
2013-07-07 08:03:42 +08:00
|
|
|
conn.connect("priority-tick", self._schedule_priority_tick)
|
2011-07-23 04:43:26 +08:00
|
|
|
self.emit("conn-added", conn)
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2009-07-15 02:48:09 +08:00
|
|
|
return conn
|
|
|
|
|
2012-11-08 18:02:17 +08:00
|
|
|
|
|
|
|
def connect_to_uri(self, uri, autoconnect=None, do_start=True):
|
|
|
|
try:
|
|
|
|
conn = self.add_conn_to_ui(uri)
|
|
|
|
|
|
|
|
if conn.get_uri() not in (self.config.get_conn_uris() or []):
|
|
|
|
self.config.add_conn(conn.get_uri())
|
|
|
|
|
|
|
|
if autoconnect is not None:
|
|
|
|
conn.set_autoconnect(bool(autoconnect))
|
|
|
|
|
|
|
|
if do_start:
|
|
|
|
conn.open()
|
|
|
|
return conn
|
|
|
|
except Exception:
|
|
|
|
logging.exception("Error connecting to %s", uri)
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
def cleanup_conn(self, uri):
|
2011-04-13 21:27:02 +08:00
|
|
|
try:
|
2011-07-23 04:43:26 +08:00
|
|
|
if self.conns[uri]["windowHost"]:
|
|
|
|
self.conns[uri]["windowHost"].cleanup()
|
|
|
|
if self.conns[uri]["windowClone"]:
|
|
|
|
self.conns[uri]["windowClone"].cleanup()
|
2011-04-13 21:27:02 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
details = self.conns[uri]["windowDetails"]
|
2011-04-13 21:27:02 +08:00
|
|
|
for win in details.values():
|
|
|
|
win.cleanup()
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
self.conns[uri]["conn"].cleanup()
|
2011-04-13 21:27:02 +08:00
|
|
|
except:
|
|
|
|
logging.exception("Error cleaning up conn in engine")
|
|
|
|
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
def remove_conn(self, src, uri):
|
2011-07-23 01:42:20 +08:00
|
|
|
ignore = src
|
2011-07-23 04:43:26 +08:00
|
|
|
self.cleanup_conn(uri)
|
|
|
|
del(self.conns[uri])
|
2011-04-12 23:50:10 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
self.emit("conn-removed", uri)
|
|
|
|
self.config.remove_conn(uri)
|
2007-09-10 10:57:24 +08:00
|
|
|
|
2011-04-12 01:06:59 +08:00
|
|
|
def connect(self, name, callback, *args):
|
|
|
|
handle_id = vmmGObject.connect(self, name, callback, *args)
|
2007-09-10 10:57:24 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
if name == "conn-added":
|
|
|
|
for uri in self.conns.keys():
|
|
|
|
self.emit("conn-added",
|
|
|
|
self.conns[uri]["conn"])
|
2007-09-10 10:57:24 +08:00
|
|
|
|
|
|
|
return handle_id
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
def _check_conn(self, uri):
|
|
|
|
conn = self.conns.get(uri)
|
2010-03-24 22:57:42 +08:00
|
|
|
if conn:
|
2011-07-23 04:43:26 +08:00
|
|
|
return conn["conn"]
|
2010-03-24 22:57:42 +08:00
|
|
|
return None
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
def _lookup_conn(self, uri):
|
|
|
|
conn = self._check_conn(uri)
|
2009-07-15 02:48:09 +08:00
|
|
|
if not conn:
|
|
|
|
raise RuntimeError(_("Unknown connection URI %s") % uri)
|
2010-03-24 22:57:42 +08:00
|
|
|
return conn
|
2006-07-18 01:08:58 +08:00
|
|
|
|
2010-11-24 07:54:12 +08:00
|
|
|
####################
|
|
|
|
# Dialog launchers #
|
|
|
|
####################
|
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_show_about(self, src):
|
2010-11-24 07:54:12 +08:00
|
|
|
try:
|
2012-11-08 21:15:02 +08:00
|
|
|
if self.windowAbout is None:
|
2010-12-09 06:26:19 +08:00
|
|
|
self.windowAbout = vmmAbout()
|
2010-11-24 07:54:12 +08:00
|
|
|
self.windowAbout.show()
|
|
|
|
except Exception, e:
|
2011-04-06 23:22:03 +08:00
|
|
|
src.err.show_err(_("Error launching 'About' dialog: %s") % str(e))
|
2010-11-24 07:54:12 +08:00
|
|
|
|
|
|
|
def _get_preferences(self):
|
|
|
|
if self.windowPreferences:
|
|
|
|
return self.windowPreferences
|
|
|
|
|
2010-12-09 06:26:19 +08:00
|
|
|
obj = vmmPreferences()
|
2010-11-24 07:54:12 +08:00
|
|
|
self.windowPreferences = obj
|
|
|
|
return self.windowPreferences
|
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_show_preferences(self, src):
|
2010-11-24 07:54:12 +08:00
|
|
|
try:
|
2011-04-14 20:47:42 +08:00
|
|
|
self._get_preferences().show(src.topwin)
|
2010-11-24 07:54:12 +08:00
|
|
|
except Exception, e:
|
2011-04-06 23:22:03 +08:00
|
|
|
src.err.show_err(_("Error launching preferences: %s") % str(e))
|
2010-11-24 07:54:12 +08:00
|
|
|
|
|
|
|
def _get_host_dialog(self, uri):
|
2011-07-23 04:43:26 +08:00
|
|
|
if self.conns[uri]["windowHost"]:
|
|
|
|
return self.conns[uri]["windowHost"]
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
con = self._lookup_conn(uri)
|
2011-04-13 22:47:31 +08:00
|
|
|
obj = vmmHost(con)
|
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
obj.connect("action-exit-app", self.exit_app)
|
2010-11-24 07:54:12 +08:00
|
|
|
obj.connect("action-view-manager", self._do_show_manager)
|
|
|
|
obj.connect("action-restore-domain", self._do_restore_domain)
|
2011-04-13 22:47:31 +08:00
|
|
|
obj.connect("host-opened", self.increment_window_counter)
|
|
|
|
obj.connect("host-closed", self.decrement_window_counter)
|
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
self.conns[uri]["windowHost"] = obj
|
|
|
|
return self.conns[uri]["windowHost"]
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_show_host(self, src, uri):
|
2010-11-24 07:54:12 +08:00
|
|
|
try:
|
|
|
|
self._get_host_dialog(uri).show()
|
|
|
|
except Exception, e:
|
2011-04-06 23:22:03 +08:00
|
|
|
src.err.show_err(_("Error launching host dialog: %s") % str(e))
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2012-11-08 18:02:17 +08:00
|
|
|
|
2010-11-24 07:54:12 +08:00
|
|
|
def _get_connect_dialog(self):
|
|
|
|
if self.windowConnect:
|
|
|
|
return self.windowConnect
|
|
|
|
|
2012-11-08 18:02:17 +08:00
|
|
|
def completed(src, uri, autoconnect):
|
2011-07-15 08:52:40 +08:00
|
|
|
ignore = src
|
|
|
|
return self.connect_to_uri(uri, autoconnect)
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2012-11-08 18:02:17 +08:00
|
|
|
def cancelled(src):
|
|
|
|
if len(self.conns.keys()) == 0:
|
|
|
|
self.exit_app(src)
|
|
|
|
|
2010-12-09 06:26:19 +08:00
|
|
|
obj = vmmConnect()
|
2012-11-08 18:02:17 +08:00
|
|
|
obj.connect("completed", completed)
|
|
|
|
obj.connect("cancelled", cancelled)
|
2010-11-24 07:54:12 +08:00
|
|
|
self.windowConnect = obj
|
|
|
|
return self.windowConnect
|
|
|
|
|
2012-11-08 18:02:17 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_show_connect(self, src):
|
2010-11-24 07:54:12 +08:00
|
|
|
try:
|
2011-04-14 20:47:42 +08:00
|
|
|
self._get_connect_dialog().show(src.topwin)
|
2010-11-24 07:54:12 +08:00
|
|
|
except Exception, e:
|
2011-04-06 23:22:03 +08:00
|
|
|
src.err.show_err(_("Error launching connect dialog: %s") % str(e))
|
2010-11-24 07:54:12 +08:00
|
|
|
|
|
|
|
def _get_details_dialog(self, uri, uuid):
|
2011-07-23 04:43:26 +08:00
|
|
|
if uuid in self.conns[uri]["windowDetails"]:
|
|
|
|
return self.conns[uri]["windowDetails"][uuid]
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
con = self._lookup_conn(uri)
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2011-04-13 22:47:31 +08:00
|
|
|
obj = vmmDetails(con.get_vm(uuid))
|
2010-11-24 07:54:12 +08:00
|
|
|
obj.connect("action-save-domain", self._do_save_domain)
|
|
|
|
obj.connect("action-destroy-domain", self._do_destroy_domain)
|
2013-03-17 05:59:32 +08:00
|
|
|
obj.connect("action-reset-domain", self._do_reset_domain)
|
2010-11-24 07:54:12 +08:00
|
|
|
obj.connect("action-suspend-domain", self._do_suspend_domain)
|
|
|
|
obj.connect("action-resume-domain", self._do_resume_domain)
|
|
|
|
obj.connect("action-run-domain", self._do_run_domain)
|
|
|
|
obj.connect("action-shutdown-domain", self._do_shutdown_domain)
|
|
|
|
obj.connect("action-reboot-domain", self._do_reboot_domain)
|
2010-11-24 09:13:50 +08:00
|
|
|
obj.connect("action-exit-app", self.exit_app)
|
2010-11-24 07:54:12 +08:00
|
|
|
obj.connect("action-view-manager", self._do_show_manager)
|
2010-11-24 09:13:50 +08:00
|
|
|
obj.connect("action-migrate-domain", self._do_show_migrate)
|
2013-06-18 04:29:51 +08:00
|
|
|
obj.connect("action-delete-domain", self._do_delete_domain)
|
2010-11-24 09:13:50 +08:00
|
|
|
obj.connect("action-clone-domain", self._do_show_clone)
|
2011-04-13 22:47:31 +08:00
|
|
|
obj.connect("details-opened", self.increment_window_counter)
|
|
|
|
obj.connect("details-closed", self.decrement_window_counter)
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
self.conns[uri]["windowDetails"][uuid] = obj
|
|
|
|
return self.conns[uri]["windowDetails"][uuid]
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2011-06-09 04:33:20 +08:00
|
|
|
def _show_vm_helper(self, src, uri, uuid, page=None, forcepage=False):
|
2010-11-24 07:54:12 +08:00
|
|
|
try:
|
|
|
|
details = self._get_details_dialog(uri, uuid)
|
2011-06-09 04:33:20 +08:00
|
|
|
|
|
|
|
if forcepage or not details.is_visible():
|
|
|
|
if page == DETAILS_PERF:
|
|
|
|
details.activate_performance_page()
|
|
|
|
elif page == DETAILS_CONFIG:
|
|
|
|
details.activate_config_page()
|
|
|
|
elif page == DETAILS_CONSOLE:
|
|
|
|
details.activate_console_page()
|
|
|
|
elif page is None:
|
|
|
|
details.activate_default_page()
|
|
|
|
|
2010-11-24 07:54:12 +08:00
|
|
|
details.show()
|
|
|
|
return details
|
|
|
|
except Exception, e:
|
2011-04-06 23:22:03 +08:00
|
|
|
src.err.show_err(_("Error launching details: %s") % str(e))
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2011-06-09 04:33:20 +08:00
|
|
|
def _do_show_vm(self, src, uri, uuid):
|
|
|
|
self._show_vm_helper(src, uri, uuid)
|
2010-11-24 07:54:12 +08:00
|
|
|
|
|
|
|
def get_manager(self):
|
|
|
|
if self.windowManager:
|
|
|
|
return self.windowManager
|
|
|
|
|
2011-07-23 01:42:20 +08:00
|
|
|
obj = vmmManager()
|
2010-11-24 07:54:12 +08:00
|
|
|
obj.connect("action-suspend-domain", self._do_suspend_domain)
|
|
|
|
obj.connect("action-resume-domain", self._do_resume_domain)
|
|
|
|
obj.connect("action-run-domain", self._do_run_domain)
|
|
|
|
obj.connect("action-shutdown-domain", self._do_shutdown_domain)
|
|
|
|
obj.connect("action-reboot-domain", self._do_reboot_domain)
|
|
|
|
obj.connect("action-destroy-domain", self._do_destroy_domain)
|
2013-03-17 05:59:32 +08:00
|
|
|
obj.connect("action-reset-domain", self._do_reset_domain)
|
2010-11-24 07:54:12 +08:00
|
|
|
obj.connect("action-save-domain", self._do_save_domain)
|
2010-11-24 09:13:50 +08:00
|
|
|
obj.connect("action-migrate-domain", self._do_show_migrate)
|
2013-06-18 04:29:51 +08:00
|
|
|
obj.connect("action-delete-domain", self._do_delete_domain)
|
2010-11-24 09:13:50 +08:00
|
|
|
obj.connect("action-clone-domain", self._do_show_clone)
|
2011-06-09 04:33:20 +08:00
|
|
|
obj.connect("action-show-vm", self._do_show_vm)
|
2010-11-24 07:54:12 +08:00
|
|
|
obj.connect("action-show-preferences", self._do_show_preferences)
|
|
|
|
obj.connect("action-show-create", self._do_show_create)
|
|
|
|
obj.connect("action-show-about", self._do_show_about)
|
|
|
|
obj.connect("action-show-host", self._do_show_host)
|
|
|
|
obj.connect("action-show-connect", self._do_show_connect)
|
2010-11-24 09:13:50 +08:00
|
|
|
obj.connect("action-exit-app", self.exit_app)
|
2011-04-13 22:47:31 +08:00
|
|
|
obj.connect("manager-opened", self.increment_window_counter)
|
|
|
|
obj.connect("manager-closed", self.decrement_window_counter)
|
2011-07-23 04:43:26 +08:00
|
|
|
obj.connect("remove-conn", self.remove_conn)
|
|
|
|
obj.connect("add-default-conn", self.add_default_conn)
|
2011-07-23 01:42:20 +08:00
|
|
|
|
2011-07-23 04:43:26 +08:00
|
|
|
self.connect("conn-added", obj.add_conn)
|
|
|
|
self.connect("conn-removed", obj.remove_conn)
|
2010-11-24 07:54:12 +08:00
|
|
|
|
|
|
|
self.windowManager = obj
|
|
|
|
return self.windowManager
|
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_toggle_manager(self, ignore):
|
2010-11-24 07:54:12 +08:00
|
|
|
manager = self.get_manager()
|
2010-12-14 06:48:19 +08:00
|
|
|
if manager.is_visible():
|
|
|
|
manager.close()
|
|
|
|
else:
|
2010-11-24 07:54:12 +08:00
|
|
|
manager.show()
|
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_show_manager(self, src):
|
2010-11-24 07:54:12 +08:00
|
|
|
try:
|
2011-04-13 21:27:02 +08:00
|
|
|
manager = self.get_manager()
|
|
|
|
manager.show()
|
2010-11-24 07:54:12 +08:00
|
|
|
except Exception, e:
|
2010-11-24 09:13:50 +08:00
|
|
|
if not src:
|
|
|
|
raise
|
2011-04-06 23:22:03 +08:00
|
|
|
src.err.show_err(_("Error launching manager: %s") % str(e))
|
2010-11-24 07:54:12 +08:00
|
|
|
|
|
|
|
def _get_create_dialog(self):
|
|
|
|
if self.windowCreate:
|
|
|
|
return self.windowCreate
|
|
|
|
|
2010-12-09 06:26:19 +08:00
|
|
|
obj = vmmCreate(self)
|
2011-06-09 04:33:20 +08:00
|
|
|
obj.connect("action-show-vm", self._do_show_vm)
|
2010-11-24 07:54:12 +08:00
|
|
|
self.windowCreate = obj
|
|
|
|
return self.windowCreate
|
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_show_create(self, src, uri):
|
2010-11-24 07:54:12 +08:00
|
|
|
try:
|
2011-04-14 20:47:42 +08:00
|
|
|
self._get_create_dialog().show(src.topwin, uri)
|
2010-11-24 07:54:12 +08:00
|
|
|
except Exception, e:
|
2011-04-06 23:22:03 +08:00
|
|
|
src.err.show_err(_("Error launching manager: %s") % str(e))
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_show_migrate(self, src, uri, uuid):
|
2010-11-24 07:54:12 +08:00
|
|
|
try:
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._lookup_conn(uri)
|
2010-11-24 07:54:12 +08:00
|
|
|
vm = conn.get_vm(uuid)
|
|
|
|
|
|
|
|
if not self.windowMigrate:
|
2010-12-09 06:26:19 +08:00
|
|
|
self.windowMigrate = vmmMigrateDialog(vm, self)
|
2010-11-24 07:54:12 +08:00
|
|
|
|
|
|
|
self.windowMigrate.set_state(vm)
|
2011-04-14 20:47:42 +08:00
|
|
|
self.windowMigrate.show(src.topwin)
|
2010-11-24 07:54:12 +08:00
|
|
|
except Exception, e:
|
2011-04-06 23:22:03 +08:00
|
|
|
src.err.show_err(_("Error launching migrate dialog: %s") % str(e))
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_show_clone(self, src, uri, uuid):
|
2011-07-23 04:43:26 +08:00
|
|
|
con = self._lookup_conn(uri)
|
2010-11-24 07:54:12 +08:00
|
|
|
orig_vm = con.get_vm(uuid)
|
2011-07-23 04:43:26 +08:00
|
|
|
clone_window = self.conns[uri]["windowClone"]
|
2010-11-24 07:54:12 +08:00
|
|
|
|
|
|
|
try:
|
2012-11-08 21:15:02 +08:00
|
|
|
if clone_window is None:
|
2010-12-09 06:26:19 +08:00
|
|
|
clone_window = vmmCloneVM(orig_vm)
|
2011-07-23 04:43:26 +08:00
|
|
|
self.conns[uri]["windowClone"] = clone_window
|
2010-11-24 07:54:12 +08:00
|
|
|
else:
|
|
|
|
clone_window.set_orig_vm(orig_vm)
|
|
|
|
|
2011-04-14 20:47:42 +08:00
|
|
|
clone_window.show(src.topwin)
|
2010-11-24 07:54:12 +08:00
|
|
|
except Exception, e:
|
2011-04-06 23:22:03 +08:00
|
|
|
src.err.show_err(_("Error setting clone parameters: %s") % str(e))
|
2010-11-24 09:13:50 +08:00
|
|
|
|
|
|
|
##########################################
|
|
|
|
# Window launchers from virt-manager cli #
|
|
|
|
##########################################
|
|
|
|
|
|
|
|
def show_manager(self):
|
|
|
|
self._do_show_manager(None)
|
|
|
|
|
2010-11-25 03:01:51 +08:00
|
|
|
def show_connect(self):
|
|
|
|
self._do_show_connect(self.get_manager())
|
|
|
|
|
|
|
|
def show_host_summary(self, uri):
|
|
|
|
self._do_show_host(self.get_manager(), uri)
|
|
|
|
|
|
|
|
def show_domain_creator(self, uri):
|
|
|
|
self._do_show_create(self.get_manager(), uri)
|
2010-11-24 09:13:50 +08:00
|
|
|
|
2010-11-25 03:01:51 +08:00
|
|
|
def show_domain_console(self, uri, uuid):
|
2011-06-09 04:33:20 +08:00
|
|
|
self._show_vm_helper(self.get_manager(), uri, uuid,
|
|
|
|
page=DETAILS_CONSOLE, forcepage=True)
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2010-11-25 03:01:51 +08:00
|
|
|
def show_domain_editor(self, uri, uuid):
|
2011-06-09 04:33:20 +08:00
|
|
|
self._show_vm_helper(self.get_manager(), uri, uuid,
|
|
|
|
page=DETAILS_CONFIG, forcepage=True)
|
2010-11-24 09:13:50 +08:00
|
|
|
|
2010-11-25 03:01:51 +08:00
|
|
|
def show_domain_performance(self, uri, uuid):
|
2011-06-09 04:33:20 +08:00
|
|
|
self._show_vm_helper(self.get_manager(), uri, uuid,
|
|
|
|
page=DETAILS_PERF, forcepage=True)
|
2010-11-24 07:54:12 +08:00
|
|
|
|
2013-07-07 08:03:42 +08:00
|
|
|
|
2010-11-24 07:54:12 +08:00
|
|
|
#######################################
|
|
|
|
# Domain actions run/destroy/save ... #
|
|
|
|
#######################################
|
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_save_domain(self, src, uri, uuid):
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._lookup_conn(uri)
|
2010-05-12 07:01:25 +08:00
|
|
|
vm = conn.get_vm(uuid)
|
2010-05-13 00:57:32 +08:00
|
|
|
managed = bool(vm.managedsave_supported)
|
2010-05-12 07:01:25 +08:00
|
|
|
|
2010-09-08 19:51:48 +08:00
|
|
|
if not managed and conn.is_remote():
|
2010-11-24 09:13:50 +08:00
|
|
|
src.err.val_err(_("Saving virtual machines over remote "
|
|
|
|
"connections is not supported with this "
|
|
|
|
"libvirt version or hypervisor."))
|
2008-01-10 05:44:10 +08:00
|
|
|
return
|
2009-03-09 03:14:00 +08:00
|
|
|
|
2011-07-23 01:11:04 +08:00
|
|
|
if not util.chkbox_helper(src, self.config.get_confirm_poweroff,
|
2011-04-15 04:43:17 +08:00
|
|
|
self.config.set_confirm_poweroff,
|
|
|
|
text1=_("Are you sure you want to save '%s'?" % vm.get_name())):
|
|
|
|
return
|
2009-03-09 03:14:00 +08:00
|
|
|
|
2010-05-13 00:57:32 +08:00
|
|
|
path = None
|
|
|
|
if not managed:
|
2010-11-24 09:13:50 +08:00
|
|
|
path = util.browse_local(src.topwin,
|
2010-05-13 00:57:32 +08:00
|
|
|
_("Save Virtual Machine"),
|
2010-12-10 03:06:00 +08:00
|
|
|
conn,
|
2012-05-14 21:24:56 +08:00
|
|
|
dialog_type=Gtk.FileChooserAction.SAVE,
|
2010-05-13 00:57:32 +08:00
|
|
|
browse_reason=self.config.CONFIG_DIR_SAVE)
|
|
|
|
if not path:
|
|
|
|
return
|
2009-04-04 02:15:15 +08:00
|
|
|
|
2013-06-14 05:05:33 +08:00
|
|
|
_cancel_cb = None
|
2010-12-09 01:52:33 +08:00
|
|
|
if vm.getjobinfo_supported:
|
2013-06-14 05:05:33 +08:00
|
|
|
_cancel_cb = (self._save_cancel, vm)
|
2010-12-09 01:52:33 +08:00
|
|
|
|
2013-07-05 20:59:58 +08:00
|
|
|
def cb(asyncjob):
|
|
|
|
vm.save(path, meter=asyncjob.get_meter())
|
|
|
|
|
|
|
|
progWin = vmmAsyncJob(cb, [],
|
2010-12-13 02:48:20 +08:00
|
|
|
_("Saving Virtual Machine"),
|
|
|
|
_("Saving virtual machine memory to disk "),
|
2013-06-14 05:05:33 +08:00
|
|
|
src.topwin, cancel_cb=_cancel_cb)
|
2010-12-10 22:57:42 +08:00
|
|
|
error, details = progWin.run()
|
2009-03-09 03:14:00 +08:00
|
|
|
|
2009-04-04 02:15:15 +08:00
|
|
|
if error is not None:
|
2010-12-10 22:57:42 +08:00
|
|
|
error = _("Error saving domain: %s") % error
|
2012-02-11 03:07:51 +08:00
|
|
|
src.err.show_err(error, details=details)
|
2007-11-28 00:31:30 +08:00
|
|
|
|
2010-12-10 22:57:42 +08:00
|
|
|
def _save_cancel(self, asyncjob, vm):
|
2010-12-09 03:14:38 +08:00
|
|
|
logging.debug("Cancelling save job")
|
2010-12-09 01:52:33 +08:00
|
|
|
if not vm:
|
|
|
|
return
|
|
|
|
|
|
|
|
try:
|
|
|
|
vm.abort_job()
|
|
|
|
except Exception, e:
|
2010-12-09 03:14:38 +08:00
|
|
|
logging.exception("Error cancelling save job")
|
2010-12-11 00:47:07 +08:00
|
|
|
asyncjob.show_warning(_("Error cancelling save job: %s") % str(e))
|
2010-12-09 01:52:33 +08:00
|
|
|
return
|
|
|
|
|
|
|
|
asyncjob.job_canceled = True
|
|
|
|
return
|
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_restore_domain(self, src, uri):
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._lookup_conn(uri)
|
2010-05-12 23:42:59 +08:00
|
|
|
if conn.is_remote():
|
2010-11-24 09:13:50 +08:00
|
|
|
src.err.val_err(_("Restoring virtual machines over remote "
|
|
|
|
"connections is not yet supported"))
|
2010-05-12 23:42:59 +08:00
|
|
|
return
|
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
path = util.browse_local(src.topwin,
|
2010-05-12 23:42:59 +08:00
|
|
|
_("Restore Virtual Machine"),
|
2010-12-10 03:06:00 +08:00
|
|
|
conn,
|
2010-05-12 23:42:59 +08:00
|
|
|
browse_reason=self.config.CONFIG_DIR_RESTORE)
|
|
|
|
|
|
|
|
if not path:
|
|
|
|
return
|
|
|
|
|
2013-07-05 20:59:58 +08:00
|
|
|
vmmAsyncJob.simple_async_noshow(conn.restore, [path], src,
|
2011-04-16 03:23:13 +08:00
|
|
|
_("Error restoring domain"))
|
2010-05-12 23:42:59 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_destroy_domain(self, src, uri, uuid):
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._lookup_conn(uri)
|
2009-07-15 02:48:09 +08:00
|
|
|
vm = conn.get_vm(uuid)
|
2011-04-15 04:43:17 +08:00
|
|
|
|
2011-07-23 01:11:04 +08:00
|
|
|
if not util.chkbox_helper(src, self.config.get_confirm_forcepoweroff,
|
2011-04-15 04:43:17 +08:00
|
|
|
self.config.set_confirm_forcepoweroff,
|
|
|
|
text1=_("Are you sure you want to force poweroff '%s'?" %
|
|
|
|
vm.get_name()),
|
|
|
|
text2=_("This will immediately poweroff the VM without "
|
|
|
|
"shutting down the OS and may cause data loss.")):
|
|
|
|
return
|
2009-07-15 02:48:09 +08:00
|
|
|
|
2012-01-17 11:04:40 +08:00
|
|
|
logging.debug("Destroying vm '%s'", vm.get_name())
|
2011-04-16 03:23:13 +08:00
|
|
|
vmmAsyncJob.simple_async_noshow(vm.destroy, [], src,
|
|
|
|
_("Error shutting down domain"))
|
2007-11-28 00:31:30 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_suspend_domain(self, src, uri, uuid):
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._lookup_conn(uri)
|
2009-07-15 02:48:09 +08:00
|
|
|
vm = conn.get_vm(uuid)
|
2009-11-19 05:11:17 +08:00
|
|
|
|
2011-07-23 01:11:04 +08:00
|
|
|
if not util.chkbox_helper(src, self.config.get_confirm_pause,
|
2011-04-15 04:43:17 +08:00
|
|
|
self.config.set_confirm_pause,
|
|
|
|
text1=_("Are you sure you want to pause '%s'?" %
|
|
|
|
vm.get_name())):
|
|
|
|
return
|
2009-07-15 02:48:09 +08:00
|
|
|
|
2012-01-17 11:04:40 +08:00
|
|
|
logging.debug("Pausing vm '%s'", vm.get_name())
|
2011-04-16 03:23:13 +08:00
|
|
|
vmmAsyncJob.simple_async_noshow(vm.suspend, [], src,
|
|
|
|
_("Error pausing domain"))
|
2009-07-15 02:48:09 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_resume_domain(self, src, uri, uuid):
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._lookup_conn(uri)
|
2009-07-15 02:48:09 +08:00
|
|
|
vm = conn.get_vm(uuid)
|
|
|
|
|
2012-01-17 11:04:40 +08:00
|
|
|
logging.debug("Unpausing vm '%s'", vm.get_name())
|
2011-04-16 03:23:13 +08:00
|
|
|
vmmAsyncJob.simple_async_noshow(vm.resume, [], src,
|
|
|
|
_("Error unpausing domain"))
|
2009-07-15 02:48:09 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_run_domain(self, src, uri, uuid):
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._lookup_conn(uri)
|
2009-07-15 02:48:09 +08:00
|
|
|
vm = conn.get_vm(uuid)
|
|
|
|
|
2012-01-17 11:04:40 +08:00
|
|
|
logging.debug("Starting vm '%s'", vm.get_name())
|
2010-12-11 03:40:08 +08:00
|
|
|
|
|
|
|
if vm.hasSavedImage():
|
2012-07-09 04:06:16 +08:00
|
|
|
def errorcb(error, details):
|
|
|
|
# This is run from the main thread
|
|
|
|
res = src.err.show_err(
|
|
|
|
_("Error restoring domain") + ": " + error,
|
|
|
|
details=details,
|
|
|
|
text2=_(
|
|
|
|
"The domain could not be restored. Would you like\n"
|
|
|
|
"to remove the saved state and perform a regular\n"
|
|
|
|
"start up?"),
|
2012-11-08 21:15:02 +08:00
|
|
|
dialog_type=Gtk.MessageType.WARNING,
|
|
|
|
buttons=Gtk.ButtonsType.YES_NO,
|
2012-07-09 04:06:16 +08:00
|
|
|
async=False)
|
|
|
|
|
|
|
|
if not res:
|
|
|
|
return
|
|
|
|
|
|
|
|
try:
|
|
|
|
vm.removeSavedImage()
|
|
|
|
self._do_run_domain(src, uri, uuid)
|
|
|
|
except Exception, e:
|
|
|
|
src.err.show_err(_("Error removing domain state: %s")
|
|
|
|
% str(e))
|
|
|
|
|
|
|
|
# VM will be restored, which can take some time, so show progress
|
2010-12-13 02:48:20 +08:00
|
|
|
title = _("Restoring Virtual Machine")
|
|
|
|
text = _("Restoring virtual machine memory from disk")
|
2011-04-15 03:28:22 +08:00
|
|
|
vmmAsyncJob.simple_async(vm.startup,
|
2012-07-09 04:06:16 +08:00
|
|
|
[], title, text, src, "", errorcb=errorcb)
|
2010-12-11 03:40:08 +08:00
|
|
|
|
|
|
|
else:
|
|
|
|
# Regular startup
|
|
|
|
errorintro = _("Error starting domain")
|
2011-04-15 03:28:22 +08:00
|
|
|
vmmAsyncJob.simple_async_noshow(vm.startup, [], src, errorintro)
|
2009-04-04 04:06:46 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_shutdown_domain(self, src, uri, uuid):
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._lookup_conn(uri)
|
2009-07-15 02:48:09 +08:00
|
|
|
vm = conn.get_vm(uuid)
|
2009-11-19 05:11:17 +08:00
|
|
|
|
2011-07-23 01:11:04 +08:00
|
|
|
if not util.chkbox_helper(src, self.config.get_confirm_poweroff,
|
2011-04-15 04:43:17 +08:00
|
|
|
self.config.set_confirm_poweroff,
|
|
|
|
text1=_("Are you sure you want to poweroff '%s'?" %
|
|
|
|
vm.get_name())):
|
|
|
|
return
|
2009-07-15 02:48:09 +08:00
|
|
|
|
2012-01-17 11:04:40 +08:00
|
|
|
logging.debug("Shutting down vm '%s'", vm.get_name())
|
2011-04-16 03:23:13 +08:00
|
|
|
vmmAsyncJob.simple_async_noshow(vm.shutdown, [], src,
|
|
|
|
_("Error shutting down domain"))
|
2007-11-28 00:31:30 +08:00
|
|
|
|
2010-11-24 09:13:50 +08:00
|
|
|
def _do_reboot_domain(self, src, uri, uuid):
|
2011-07-23 04:43:26 +08:00
|
|
|
conn = self._lookup_conn(uri)
|
2009-07-15 02:48:09 +08:00
|
|
|
vm = conn.get_vm(uuid)
|
2009-11-19 05:11:17 +08:00
|
|
|
|
2011-07-23 01:11:04 +08:00
|
|
|
if not util.chkbox_helper(src, self.config.get_confirm_poweroff,
|
2011-04-15 04:43:17 +08:00
|
|
|
self.config.set_confirm_poweroff,
|
|
|
|
text1=_("Are you sure you want to reboot '%s'?" %
|
|
|
|
vm.get_name())):
|
|
|
|
return
|
2009-07-15 02:48:09 +08:00
|
|
|
|
2012-01-17 11:04:40 +08:00
|
|
|
logging.debug("Rebooting vm '%s'", vm.get_name())
|
2011-04-16 03:23:13 +08:00
|
|
|
|
|
|
|
def reboot_cb():
|
|
|
|
no_support = False
|
|
|
|
reboot_err = None
|
|
|
|
try:
|
|
|
|
vm.reboot()
|
|
|
|
except Exception, reboot_err:
|
2013-07-06 23:20:28 +08:00
|
|
|
no_support = virtinst.util.is_error_nosupport(reboot_err)
|
2011-04-16 03:23:13 +08:00
|
|
|
if not no_support:
|
2012-02-11 03:07:51 +08:00
|
|
|
raise RuntimeError(_("Error rebooting domain: %s" %
|
|
|
|
str(reboot_err)))
|
2011-04-16 03:23:13 +08:00
|
|
|
|
2010-03-18 04:41:50 +08:00
|
|
|
if not no_support:
|
2011-04-16 03:23:13 +08:00
|
|
|
return
|
2010-03-18 04:41:50 +08:00
|
|
|
|
2011-04-16 03:23:13 +08:00
|
|
|
# Reboot isn't supported. Let's try to emulate it
|
|
|
|
logging.debug("Hypervisor doesn't support reboot, let's fake it")
|
|
|
|
try:
|
|
|
|
vm.manual_reboot()
|
|
|
|
except:
|
|
|
|
logging.exception("Could not fake a reboot")
|
2010-03-18 04:41:50 +08:00
|
|
|
|
2011-04-16 03:23:13 +08:00
|
|
|
# Raise the original error message
|
2012-02-11 03:07:51 +08:00
|
|
|
raise RuntimeError(_("Error rebooting domain: %s" %
|
|
|
|
str(reboot_err)))
|
2010-03-18 04:41:50 +08:00
|
|
|
|
2011-04-16 03:23:13 +08:00
|
|
|
vmmAsyncJob.simple_async_noshow(reboot_cb, [], src, "")
|
2008-04-09 02:30:47 +08:00
|
|
|
|
2013-03-17 05:59:32 +08:00
|
|
|
def _do_reset_domain(self, src, uri, uuid):
|
|
|
|
conn = self._lookup_conn(uri)
|
|
|
|
vm = conn.get_vm(uuid)
|
|
|
|
|
|
|
|
if not util.chkbox_helper(src, self.config.get_confirm_forcepoweroff,
|
|
|
|
self.config.set_confirm_forcepoweroff,
|
|
|
|
text1=_("Are you sure you want to force reset '%s'?" %
|
|
|
|
vm.get_name()),
|
|
|
|
text2=_("This will immediately reset the VM without "
|
|
|
|
"shutting down the OS and may cause data loss.")):
|
|
|
|
return
|
|
|
|
|
|
|
|
logging.debug("Resetting vm '%s'", vm.get_name())
|
|
|
|
vmmAsyncJob.simple_async_noshow(vm.reset, [], src,
|
|
|
|
_("Error resetting domain"))
|
2013-06-18 04:29:51 +08:00
|
|
|
|
|
|
|
def _do_delete_domain(self, src, uri, uuid):
|
|
|
|
conn = self._lookup_conn(uri)
|
|
|
|
vm = conn.get_vm(uuid)
|
|
|
|
|
|
|
|
if not self.delete_dialog:
|
|
|
|
self.delete_dialog = vmmDeleteDialog()
|
|
|
|
self.delete_dialog.show(vm, src.topwin)
|