[virt-tools-list] [PATCH 1/3 version 2] Add inspection thread.
Richard W.M. Jones
rjones at redhat.com
Tue Apr 19 13:58:02 UTC 2011
On Tue, Apr 19, 2011 at 12:01:41PM +0100, Richard W.M. Jones wrote:
> + for disk in vm.get_disk_devices():
> + path = disk.path
> + driver_type = disk.driver_type
> + g.add_drive_opts(path, readonly=1, format=driver_type)
Oops - turns out that if the VM has any disks without <source/>
elements (eg. CD-ROMs), then path == None here. The updated patch
attached fixed this.
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
libguestfs lets you edit virtual machines. Supports shell scripting,
bindings from many languages. http://libguestfs.org
-------------- next part --------------
>From 09bf45216bc703e1bdd7d300e17321cfc9a26497 Mon Sep 17 00:00:00 2001
From: Richard W.M. Jones <rjones at redhat.com>
Date: Tue, 19 Apr 2011 10:42:55 +0100
Subject: [PATCH] Add inspection thread.
This commit adds an inspection daemon thread which performs libguestfs
inspection on domains when they first appear in the manager UI.
python-guestfs is not required.
---
src/virtManager/config.py | 25 +++++++++
src/virtManager/engine.py | 15 +++++
src/virtManager/inspection.py | 121 +++++++++++++++++++++++++++++++++++++++++
src/virtManager/manager.py | 3 +
4 files changed, 164 insertions(+), 0 deletions(-)
create mode 100644 src/virtManager/inspection.py
diff --git a/src/virtManager/config.py b/src/virtManager/config.py
index f2dfd2d..7f3f85c 100644
--- a/src/virtManager/config.py
+++ b/src/virtManager/config.py
@@ -105,6 +105,31 @@ class vmmConfig(object):
self._objects = []
self.support_threading = virtinst.support.support_threading()
+
+ # Check that we have the guestfs module with the non-broken
+ # support for Python threads. Also libvirt must be
+ # thread-safe too.
+ self.support_inspection = False
+ if self.support_threading:
+ try:
+ from guestfs import GuestFS
+ g = GuestFS()
+ version = g.version()
+ if version["major"] == 1: # major must be 1
+ if version["minor"] == 8:
+ if version["release"] >= 6: # >= 1.8.6
+ self.support_inspection = True
+ elif version["minor"] == 10:
+ if version["release"] >= 1: # >= 1.10.1
+ self.support_inspection = True
+ elif version["minor"] == 11:
+ if version["release"] >= 2: # >= 1.11.2
+ self.support_inspection = True
+ elif version["minor"] >= 12: # >= 1.12.x
+ self.support_inspection = True
+ except:
+ pass
+
self._spice_error = None
self.status_icons = {
diff --git a/src/virtManager/engine.py b/src/virtManager/engine.py
index 39a37cd..2484656 100644
--- a/src/virtManager/engine.py
+++ b/src/virtManager/engine.py
@@ -239,6 +239,9 @@ class vmmEngine(vmmGObject):
if not self.config.support_threading:
logging.debug("Libvirt doesn't support threading, skipping.")
+ self.inspection_thread = None
+ self._create_inspection_thread()
+
# Counter keeping track of how many manager and details windows
# are open. When it is decremented to 0, close the app or
# keep running in system tray if enabled
@@ -533,6 +536,18 @@ class vmmEngine(vmmGObject):
logging.debug("Exiting app normally.")
gtk.main_quit()
+ def _create_inspection_thread(self):
+ if not self.config.support_inspection:
+ logging.debug("No inspection thread because "
+ "libguestfs is too old, not available, "
+ "or libvirt is not thread safe.")
+ return
+ from virtManager.inspection import vmmInspection
+ self.inspection_thread = vmmInspection()
+ self.inspection_thread.daemon = True
+ self.inspection_thread.start()
+ return
+
def add_connection(self, uri, readOnly=None, autoconnect=False):
conn = self._check_connection(uri)
if conn:
diff --git a/src/virtManager/inspection.py b/src/virtManager/inspection.py
new file mode 100644
index 0000000..d5788f4
--- /dev/null
+++ b/src/virtManager/inspection.py
@@ -0,0 +1,121 @@
+#
+# Copyright (C) 2011 Red Hat, Inc.
+#
+# 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
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301 USA.
+#
+
+import sys
+import time
+import traceback
+from Queue import Queue
+from threading import Thread
+
+from guestfs import GuestFS
+
+import logging
+import util
+
+class vmmInspection(Thread):
+ _name = "inspection thread"
+ _wait = 15 # seconds
+
+ def __init__(self):
+ Thread.__init__(self, name=self._name)
+ self._q = Queue()
+ self._vmseen = dict()
+
+ # Called by the main thread whenever a VM is added to vmlist.
+ def vm_added(self, connection, vmuuid):
+ obj = (connection, vmuuid)
+ self._q.put(obj)
+
+ def run(self):
+ # Wait a few seconds before we do anything. This prevents
+ # inspection from being a burden for initial virt-manager
+ # interactivity (although it shouldn't affect interactivity at
+ # all).
+ logging.debug("%s: waiting" % self._name)
+ time.sleep(self._wait)
+
+ logging.debug("%s: ready" % self._name)
+
+ while True:
+ obj = self._q.get(True)
+ (connection, vmuuid) = obj
+
+ logging.debug("%s: processing started on '%s'" %
+ (self._name, vmuuid))
+ try:
+ self._process(connection, vmuuid)
+ except:
+ logging.debug("%s: exception while processing '%s':\n%s" %
+ (self._name, vmuuid, traceback.format_exc()))
+
+ self._q.task_done()
+ logging.debug("%s: processing done on '%s'" %
+ (self._name, vmuuid))
+
+ def _process(self, connection, vmuuid):
+ if not connection or connection.is_remote():
+ logging.debug("%s: %s: no connection object or "
+ "connection is remote" % (self._name, vmuuid))
+ return
+ vm = connection.get_vm(vmuuid)
+
+ # If we've already inspected this VM, don't do it again. Note
+ # that we must filter here (not before adding to the queue in
+ # the main thread) because of the case where the VM has
+ # already been enqueued but the results are not yet in the
+ # cache.
+ if vmuuid in self._vmseen: return
+
+ xml = vm.get_xml()
+
+ # Add the disks. Note they *must* be added with readonly flag set.
+ g = GuestFS()
+ for disk in vm.get_disk_devices():
+ path = disk.path
+ driver_type = disk.driver_type
+ if path != None:
+ g.add_drive_opts(path, readonly=1, format=driver_type)
+
+ g.launch()
+
+ # Inspect the operating system.
+ roots = g.inspect_os()
+ if len(roots) == 0:
+ logging.debug("%s: %s: no operating systems found" %
+ (self._name, vmuuid))
+ return
+
+ # Arbitrarily pick the first root device.
+ root = roots[0]
+
+ # Inspection results.
+ typ = g.inspect_get_type(root) # eg. "linux"
+ distro = g.inspect_get_distro(root) # eg. "fedora"
+ major_version = g.inspect_get_major_version(root) # eg. 14
+ minor_version = g.inspect_get_minor_version(root) # eg. 0
+ product_variant = g.inspect_get_product_variant(root) # string
+ hostname = g.inspect_get_hostname(root) # string
+ product_name = g.inspect_get_product_name(root) # string
+
+ # Force the libguestfs handle to close right now.
+ del g
+
+ self._vmseen[vmuuid] = True
+
+ pass
diff --git a/src/virtManager/manager.py b/src/virtManager/manager.py
index 02ebabc..2abca04 100644
--- a/src/virtManager/manager.py
+++ b/src/virtManager/manager.py
@@ -742,6 +742,9 @@ class vmmManager(vmmGObjectUI):
self._append_vm(model, vm, connection)
+ if self.engine.inspection_thread:
+ self.engine.inspection_thread.vm_added(connection, vmuuid)
+
def vm_removed(self, connection, uri_ignore, vmuuid):
vmlist = self.window.get_widget("vm-list")
model = vmlist.get_model()
--
1.7.4.4
More information about the virt-tools-list
mailing list