From 3f9938a45b2fd7705e6fd40ab41231a79aaf5861 Mon Sep 17 00:00:00 2001
From: Vratislav Podzimek <vpodzime@redhat.com>
Date: Tue, 21 Jul 2015 16:48:27 +0200
Subject: [PATCH 7/7] Better handle and report erroneous states
So that users have a chance to find out what happened and fix the issue.
Resolves: rhbz#1241064
Signed-off-by: Vratislav Podzimek <vpodzime@redhat.com>
---
org_fedora_oscap/gui/spokes/oscap.py | 93 ++++++++++++++++++++++++------------
1 file changed, 62 insertions(+), 31 deletions(-)
diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py
index 10a7ca7..e5ea225 100644
--- a/org_fedora_oscap/gui/spokes/oscap.py
+++ b/org_fedora_oscap/gui/spokes/oscap.py
@@ -19,6 +19,7 @@
#
import threading
+from functools import wraps
import gettext
_ = lambda x: gettext.ldgettext("oscap-anaconda-addon", x)
@@ -46,6 +47,9 @@ from pykickstart.errors import KickstartValueError
# pylint: disable-msg=E0611
from gi.repository import Gdk
+import logging
+log = logging.getLogger("anaconda")
+
# export only the spoke, no helper functions, classes or constants
__all__ = ["OSCAPSpoke"]
@@ -105,6 +109,21 @@ def render_message_type(column, renderer, model, itr, user_data=None):
else:
renderer.set_property("stock-id", "gtk-dialog-question")
+def set_ready(func):
+ @wraps(func)
+ def decorated(self, *args, **kwargs):
+ ret = func(self, *args, **kwargs)
+
+ self._unitialized_status = None
+ self._ready = True
+ # pylint: disable-msg=E1101
+ hubQ.send_ready(self.__class__.__name__, True)
+ hubQ.send_message(self.__class__.__name__, self.status)
+
+ return ret
+
+ return decorated
+
class OSCAPSpoke(NormalSpoke):
"""
Main class of the OSCAP addon spoke that will appear in the Security
@@ -182,6 +201,8 @@ class OSCAPSpoke(NormalSpoke):
self._fetching = False
self._fetch_flag_lock = threading.Lock()
+ self._error = None
+
def initialize(self):
"""
The initialize method that is called after the instance is created.
@@ -304,6 +325,7 @@ class OSCAPSpoke(NormalSpoke):
target=self._init_after_data_fetch,
args=(thread_name,)))
+ @set_ready
def _init_after_data_fetch(self, wait_for):
"""
Waits for data fetching to be finished, extracts it (if needed),
@@ -379,6 +401,7 @@ class OSCAPSpoke(NormalSpoke):
# fetching done
with self._fetch_flag_lock:
self._fetching = False
+
return
if self._using_ds:
@@ -403,24 +426,19 @@ class OSCAPSpoke(NormalSpoke):
# update the message store with the messages
self._update_message_store()
- # no more being unitialized
- self._unitialized_status = None
- self._ready = True
-
# all initialized, we can now let user set parameters
fire_gtk_action(self._main_notebook.set_current_page, SET_PARAMS_PAGE)
# and use control buttons
fire_gtk_action(really_show, self._control_buttons)
- # pylint: disable-msg=E1101
- hubQ.send_ready(self.__class__.__name__, True)
- hubQ.send_message(self.__class__.__name__, self.status)
-
# fetching done
with self._fetch_flag_lock:
self._fetching = False
+ # no error
+ self._error = None
+
@property
def _using_ds(self):
return self._content_handling_cls == content_handling.DataStreamHandler
@@ -620,39 +638,43 @@ class OSCAPSpoke(NormalSpoke):
# update messages according to the newly chosen profile
self._update_message_store()
+ @set_ready
+ def _set_error(self, msg):
+ self._error = msg
+ self.set_error(msg)
+
@gtk_action_wait
def _invalid_content(self):
"""Callback for informing user about provided content invalidity."""
- self._progress_label.set_markup("<b>%s</b>" % _("Invalid content "
- "provided. Enter a different URL, "
- "please."))
- self._wrong_content()
+ msg = _("Invalid content provided. Enter a different URL, please.")
+ self._progress_label.set_markup("<b>%s</b>" % msg)
+ self._wrong_content(msg)
@gtk_action_wait
def _invalid_url(self):
"""Callback for informing user about provided URL invalidity."""
- self._progress_label.set_markup("<b>%s</b>" % _("Invalid or unsupported content "
- "URL, please enter a different one."))
- self._wrong_content()
+ msg = _("Invalid or unsupported content URL, please enter a different one.")
+ self._progress_label.set_markup("<b>%s</b>" % msg)
+ self._wrong_content(msg)
@gtk_action_wait
def _data_fetch_failed(self):
"""Adapts the UI if fetching data from entered URL failed"""
- self._progress_label.set_markup("<b>%s</b>" % _("Failed to fetch "
- "content. Enter a different URL, "
- "please."))
- self._wrong_content()
+ msg = _("Failed to fetch content. Enter a different URL, please.")
+ self._progress_label.set_markup("<b>%s</b>" % msg)
+ self._wrong_content(msg)
@gtk_action_wait
def _network_problem(self):
"""Adapts the UI if network error was encountered during data fetch"""
- self._progress_label.set_markup("<b>%s</b>" % _("Network error encountered when fetching data."
- " Please check that network is setup and working."))
- self._wrong_content()
+ msg = _("Network error encountered when fetching data."
+ " Please check that network is setup and working.")
+ self._progress_label.set_markup("<b>%s</b>" % msg)
+ self._wrong_content(msg)
@gtk_action_wait
def _integrity_check_failed(self):
@@ -660,7 +682,7 @@ class OSCAPSpoke(NormalSpoke):
msg = _("The integrity check of the content failed. Cannot use the content.")
self._progress_label.set_markup("<b>%s</b>" % msg)
- self._wrong_content()
+ self._wrong_content(msg)
@gtk_action_wait
def _extraction_failed(self, err_msg):
@@ -669,17 +691,18 @@ class OSCAPSpoke(NormalSpoke):
msg = _("Failed to extract content (%s). Enter a different URL, "
"please.") % err_msg
self._progress_label.set_markup("<b>%s</b>" % msg)
- self._wrong_content()
+ self._wrong_content(msg)
@gtk_action_wait
- def _wrong_content(self):
- self._addon_data.content_url = ""
- self._addon_data.content_type = ""
+ def _wrong_content(self, msg):
+ self._addon_data.clear_all()
really_hide(self._progress_spinner)
self._fetch_button.set_sensitive(True)
self._content_url_entry.set_sensitive(True)
self._content_url_entry.grab_focus()
self._content_url_entry.select_region(0, -1)
+ self._content_handling_cls == None
+ self._set_error(msg)
@gtk_action_wait
def _switch_dry_run(self, dry_run):
@@ -792,6 +815,10 @@ class OSCAPSpoke(NormalSpoke):
"""
+ if not self._addon_data.content_defined or not self._active_profile:
+ # no errors for no content or no profile
+ self._error = None
+
# store currently selected values to the addon data attributes
if self._using_ds:
self._addon_data.datastream_id = self._current_ds_id
@@ -838,8 +865,8 @@ class OSCAPSpoke(NormalSpoke):
"""
# no error message in the store
- return all(row[0] != common.MESSAGE_TYPE_FATAL
- for row in self._message_store)
+ return not self._error and all(row[0] != common.MESSAGE_TYPE_FATAL
+ for row in self._message_store)
@property
@gtk_action_wait
@@ -854,6 +881,9 @@ class OSCAPSpoke(NormalSpoke):
"""
+ if self._error:
+ return _("Error fetching and loading content")
+
if self._unitialized_status:
# not initialized
return self._unitialized_status
@@ -951,9 +981,10 @@ class OSCAPSpoke(NormalSpoke):
really_show(self._progress_spinner)
if not data_fetch.can_fetch_from(url):
+ msg = _("Invalid or unsupported URL")
# cannot start fetching
- self._progress_label.set_markup("<b>%s</b>" % _("Invalid or unsupported URL"))
- self._wrong_content()
+ self._progress_label.set_markup("<b>%s</b>" % msg)
+ self._wrong_content(msg)
return
self._progress_label.set_text(_("Fetching content..."))
--
2.4.3