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

View File

@ -2372,10 +2372,11 @@ class vmmDetails(vmmGObjectUI):
def refresh_inspection_page(self): def refresh_inspection_page(self):
inspection_supported = self.config.inspection_supported() inspection_supported = self.config.inspection_supported()
uiutil.set_grid_row_visible(self.widget("details-overview-error"), uiutil.set_grid_row_visible(self.widget("details-overview-error"),
self.vm.inspection.error) bool(self.vm.inspection.errorstr))
if self.vm.inspection.error: if self.vm.inspection.errorstr:
msg = _("Error while inspecting the guest configuration") self.widget("details-overview-error").set_text(
self.widget("details-overview-error").set_text(msg) self.vm.inspection.errorstr)
inspection_supported = False
self.widget("details-inspection-os").set_visible(inspection_supported) self.widget("details-inspection-os").set_visible(inspection_supported)
self.widget("details-inspection-apps").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.product_variant = None
self.icon = None self.icon = None
self.applications = None self.applications = None
self.error = False self.errorstr = None
class vmmDomainSnapshot(vmmLibvirtObject): class vmmDomainSnapshot(vmmLibvirtObject):

View File

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