inspection: Show inspection error in details page

This commit is contained in:
Cole Robinson 2018-03-13 16:37:46 -04:00
parent c21e0db6ea
commit 2dcfaafcac
4 changed files with 220 additions and 230 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.2 -->
<!-- Generated with glade 3.20.3 -->
<interface>
<requires lib="gtk+" version="3.14"/>
<object class="GtkAccelGroup" id="accelgroup1"/>
@ -1399,171 +1399,114 @@
</packing>
</child>
<child>
<object class="GtkBox" id="box12">
<object class="GtkBox" id="box14">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkBox" id="box14">
<object class="GtkFrame" id="details-inspection-os">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkFrame" id="details-inspection-os">
<object class="GtkAlignment" id="alignment43">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<property name="left_padding">12</property>
<child>
<object class="GtkAlignment" id="alignment43">
<object class="GtkGrid" id="table17">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<property name="border_width">3</property>
<property name="row_spacing">6</property>
<property name="column_spacing">6</property>
<child>
<object class="GtkGrid" id="table17">
<object class="GtkLabel" id="label72">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">3</property>
<property name="row_spacing">6</property>
<property name="column_spacing">6</property>
<child>
<object class="GtkLabel" id="label72">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Product name:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="inspection-hostname">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label">foo</property>
<property name="selectable">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label71">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Hostname:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Operating system:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="inspection-product-name">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label">foo</property>
<property name="selectable">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="inspection-type">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">foo</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<property name="halign">end</property>
<property name="label" translatable="yes">Product name:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label70">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Operating System&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkExpander" id="details-inspection-apps">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkAlignment" id="alignment44">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">3</property>
<property name="left_padding">21</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow6">
<property name="height_request">150</property>
<object class="GtkLabel" id="inspection-hostname">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">etched-in</property>
<child>
<object class="GtkTreeView" id="inspection-apps">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection"/>
</child>
</object>
</child>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label">foo</property>
<property name="selectable">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label71">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Hostname:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Operating system:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="inspection-product-name">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label">foo</property>
<property name="selectable">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="inspection-type">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">foo</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label73">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Applications&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child type="label">
<object class="GtkLabel" id="label70">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Operating System&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
@ -1573,71 +1516,124 @@
</packing>
</child>
<child>
<object class="GtkGrid" id="details-overview-error-box">
<object class="GtkExpander" id="details-inspection-apps">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">end</property>
<property name="orientation">vertical</property>
<property name="column_spacing">6</property>
<property name="can_focus">True</property>
<child>
<object class="GtkImage" id="image1">
<object class="GtkAlignment" id="alignment44">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">start</property>
<property name="stock">gtk-dialog-warning</property>
<property name="top_padding">3</property>
<property name="left_padding">21</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow6">
<property name="height_request">150</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">etched-in</property>
<child>
<object class="GtkTreeView" id="inspection-apps">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection"/>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="details-overview-error">
<child type="label">
<object class="GtkLabel" id="label73">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">start</property>
<property name="label" translatable="yes">Error message bar</property>
<property name="max_width_chars">80</property>
<property name="label" translatable="yes">&lt;b&gt;Applications&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="details-inspection-refresh">
<property name="label" translatable="yes">Refresh</property>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">end</property>
<signal name="clicked" handler="on_details_inspection_refresh_clicked" swapped="no"/>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkGrid" id="details-overview-error-box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<property name="column_spacing">6</property>
<child>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">start</property>
<property name="stock">gtk-dialog-warning</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="details-overview-error">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">start</property>
<property name="label">Error message baraaaaaaaa aaaaaaaaaaaaaa aaaaaaaaaaaaaaaa</property>
<property name="justify">fill</property>
<property name="wrap">True</property>
<property name="max_width_chars">60</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="details-inspection-refresh">
<property name="label" translatable="yes">Refresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">end</property>
<property name="valign">start</property>
<signal name="clicked" handler="on_details_inspection_refresh_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="box12-atkobject">
<property name="AtkObject::accessible-name">inspection-tab</property>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child type="tab">

View File

@ -2372,10 +2372,11 @@ class vmmDetails(vmmGObjectUI):
def refresh_inspection_page(self):
inspection_supported = self.config.inspection_supported()
uiutil.set_grid_row_visible(self.widget("details-overview-error"),
self.vm.inspection.error)
if self.vm.inspection.error:
msg = _("Error while inspecting the guest configuration")
self.widget("details-overview-error").set_text(msg)
bool(self.vm.inspection.errorstr))
if self.vm.inspection.errorstr:
self.widget("details-overview-error").set_text(
self.vm.inspection.errorstr)
inspection_supported = False
self.widget("details-inspection-os").set_visible(inspection_supported)
self.widget("details-inspection-apps").set_visible(inspection_supported)

View File

@ -146,7 +146,7 @@ class vmmInspectionData(object):
self.product_variant = None
self.icon = None
self.applications = None
self.error = False
self.errorstr = None
class vmmDomainSnapshot(vmmLibvirtObject):

View File

@ -26,6 +26,12 @@ from .baseclass import vmmGObject
from .domain import vmmInspectionData
def _inspection_error(_errstr):
data = vmmInspectionData()
data.errorstr = _errstr
return data
class vmmInspection(vmmGObject):
# Can't find a way to make Thread release our reference
_leak_check = False
@ -63,7 +69,6 @@ class vmmInspection(vmmGObject):
self._q = queue.Queue()
self._conns = {}
self._vmseen = {}
self._cached_data = {}
val = self.config.get_libguestfs_inspect_vms()
@ -78,7 +83,6 @@ class vmmInspection(vmmGObject):
self._stop()
self._q = queue.Queue()
self._conns = {}
self._vmseen = {}
self._cached_data = {}
# Called by the main thread whenever a connection is added or
@ -135,9 +139,7 @@ class vmmInspection(vmmGObject):
if cmd == "conn_added":
conn = obj[1]
uri = conn.get_uri()
if (conn.is_remote() or
conn.is_test() or
uri in self._conns):
if uri in self._conns:
return
self._conns[uri] = conn
@ -167,51 +169,45 @@ class vmmInspection(vmmGObject):
# all we need is to remove it from the "seen" cache,
# as the data itself will be replaced once the new
# results are available.
self._vmseen.pop(vmuuid)
self._cached_data.pop(vmuuid, None)
self._process_vm(conn, vm)
# Try processing a single VM, keeping into account whether it was
# visited already, and whether there are cached data for it.
def _process_vm(self, conn, vm):
def set_inspection_error(vm):
data = vmmInspectionData()
data.error = True
self._set_vm_inspection_data(vm, data)
# Try processing a single VM, keeping into account whether it was
# visited already, and whether there are cached data for it.
def _set_vm_inspection_data(_data):
vm.inspection = _data
vm.inspection_data_updated()
self._cached_data[vm.get_uuid()] = _data
prettyvm = conn.get_uri() + ":" + vm.get_name()
vmuuid = vm.get_uuid()
prettyvm = vmuuid
if vmuuid in self._cached_data:
data = self._cached_data.get(vmuuid)
if vm.inspection != data:
logging.debug("Found cached data for %s", prettyvm)
_set_vm_inspection_data(data)
return
try:
prettyvm = conn.get_uri() + ":" + vm.get_name()
if vmuuid in self._vmseen:
data = self._cached_data.get(vmuuid)
if not data:
return
if vm.inspection != data:
logging.debug("Found cached data for %s", prettyvm)
self._set_vm_inspection_data(vm, data)
return
# Whether success or failure, we've "seen" this VM now.
self._vmseen[vmuuid] = True
try:
data = self._inspect_vm(conn, vm)
if data:
self._set_vm_inspection_data(vm, data)
else:
set_inspection_error(vm)
except Exception:
set_inspection_error(vm)
raise
except Exception:
data = self._inspect_vm(conn, vm)
except Exception as e:
data = _inspection_error(_("Error inspection VM: %s") % str(e))
logging.exception("%s: exception while processing", prettyvm)
_set_vm_inspection_data(data)
def _inspect_vm(self, conn, vm):
if self._thread is None:
return
if conn.is_remote():
return _inspection_error(
_("Cannot inspect VM on remote connection"))
if conn.is_test():
return _inspection_error("Cannot inspect VM on test connection")
import guestfs # pylint: disable=import-error
g = guestfs.GuestFS(close_on_exit=False)
@ -222,14 +218,17 @@ class vmmInspection(vmmGObject):
except Exception as e:
logging.debug("%s: Error launching libguestfs appliance: %s",
prettyvm, str(e))
return None
return _inspection_error(
_("Error launching libguestfs appliance: %s") % str(e))
logging.debug("%s: inspection appliance connected", prettyvm)
# Inspect the operating system.
roots = g.inspect_os()
if len(roots) == 0:
logging.debug("%s: no operating systems found", prettyvm)
return None
return _inspection_error(
_("Inspection found no operating systems."))
# Arbitrarily pick the first root device.
root = roots[0]
@ -313,11 +312,5 @@ class vmmInspection(vmmGObject):
data.product_variant = str(product_variant)
data.icon = icon
data.applications = list(apps or [])
data.error = False
return data
def _set_vm_inspection_data(self, vm, data):
vm.inspection = data
vm.inspection_data_updated()
self._cached_data[vm.get_uuid()] = data