Blame org_fedora_oscap/gui/spokes/oscap.py

Packit Service 39273c
#
Packit Service 39273c
# Copyright (C) 2013  Red Hat, Inc.
Packit Service 39273c
#
Packit Service 39273c
# This copyrighted material is made available to anyone wishing to use,
Packit Service 39273c
# modify, copy, or redistribute it subject to the terms and conditions of
Packit Service 39273c
# the GNU General Public License v.2, or (at your option) any later version.
Packit Service 39273c
# This program is distributed in the hope that it will be useful, but WITHOUT
Packit Service 39273c
# ANY WARRANTY expressed or implied, including the implied warranties of
Packit Service 39273c
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Packit Service 39273c
# Public License for more details.  You should have received a copy of the
Packit Service 39273c
# GNU General Public License along with this program; if not, write to the
Packit Service 39273c
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 39273c
# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
Packit Service 39273c
# source code or documentation are not subject to the GNU General Public
Packit Service 39273c
# License and may only be used or replicated with the express permission of
Packit Service 39273c
# Red Hat, Inc.
Packit Service 39273c
#
Packit Service 39273c
# Red Hat Author(s): Vratislav Podzimek <vpodzime@redhat.com>
Packit Service 39273c
#
Packit Service 39273c
Packit Service 39273c
import threading
Packit Service 39273c
import logging
Packit Service 39273c
from functools import wraps
Packit Service 39273c
Packit Service 39273c
# the path to addons is in sys.path so we can import things
Packit Service 39273c
# from org_fedora_oscap
Packit Service 39273c
from org_fedora_oscap import common
Packit Service 39273c
from org_fedora_oscap import data_fetch
Packit Service 39273c
from org_fedora_oscap import rule_handling
Packit Service 39273c
from org_fedora_oscap import content_handling
Packit Service 39273c
from org_fedora_oscap import utils
Packit Service 39273c
from org_fedora_oscap.common import dry_run_skip
Packit Service 39273c
from pyanaconda.threading import threadMgr, AnacondaThread
Packit Service 39273c
from pyanaconda.ui.gui.spokes import NormalSpoke
Packit Service 39273c
from pyanaconda.ui.communication import hubQ
Packit Service 39273c
from pyanaconda.ui.gui.utils import async_action_wait, really_hide, really_show
Packit Service 39273c
from pyanaconda.ui.gui.utils import set_treeview_selection, fire_gtk_action
Packit Service 39273c
from pyanaconda.ui.categories.system import SystemCategory
Packit Service 39273c
from pykickstart.errors import KickstartValueError
Packit Service 39273c
Packit Service 39273c
from pyanaconda.modules.common.constants.services import USERS
Packit Service 39273c
Packit Service 39273c
# pylint: disable-msg=E0611
Packit Service 39273c
from gi.repository import Gdk
Packit Service 39273c
Packit Service 39273c
log = logging.getLogger("anaconda")
Packit Service 39273c
Packit Service 39273c
_ = common._
Packit Service 39273c
N_ = common.N_
Packit Service 39273c
Packit Service 39273c
# export only the spoke, no helper functions, classes or constants
Packit Service 39273c
__all__ = ["OSCAPSpoke"]
Packit Service 39273c
Packit Service 39273c
# pages in the main notebook
Packit Service 39273c
SET_PARAMS_PAGE = 0
Packit Service 39273c
GET_CONTENT_PAGE = 1
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
class GtkActionList(object):
Packit Service 39273c
    """Class for scheduling Gtk actions to be all run at once."""
Packit Service 39273c
Packit Service 39273c
    def __init__(self):
Packit Service 39273c
        self._actions = []
Packit Service 39273c
Packit Service 39273c
    def add_action(self, func, *args):
Packit Service 39273c
        """Add Gtk action to be run later."""
Packit Service 39273c
Packit Service 39273c
        @async_action_wait
Packit Service 39273c
        def gtk_action():
Packit Service 39273c
            func(*args)
Packit Service 39273c
Packit Service 39273c
        self._actions.append(gtk_action)
Packit Service 39273c
Packit Service 39273c
    def fire(self):
Packit Service 39273c
        """Run all scheduled Gtk actions."""
Packit Service 39273c
Packit Service 39273c
        for action in self._actions:
Packit Service 39273c
            action()
Packit Service 39273c
Packit Service 39273c
        self._actions = []
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
# helper functions
Packit Service 39273c
def set_combo_selection(combo, item, unset_first=False):
Packit Service 39273c
    """
Packit Service 39273c
    Set selected item of the combobox.
Packit Service 39273c
Packit Service 39273c
    :return: True if successfully set, False otherwise
Packit Service 39273c
    :rtype: bool
Packit Service 39273c
Packit Service 39273c
    """
Packit Service 39273c
Packit Service 39273c
    if unset_first:
Packit Service 39273c
        combo.set_active_iter(None)
Packit Service 39273c
Packit Service 39273c
    model = combo.get_model()
Packit Service 39273c
    if not model:
Packit Service 39273c
        return False
Packit Service 39273c
Packit Service 39273c
    itr = model.get_iter_first()
Packit Service 39273c
    while itr:
Packit Service 39273c
        if model[itr][0] == item:
Packit Service 39273c
            combo.set_active_iter(itr)
Packit Service 39273c
            return True
Packit Service 39273c
Packit Service 39273c
        itr = model.iter_next(itr)
Packit Service 39273c
Packit Service 39273c
        return False
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def get_combo_selection(combo):
Packit Service 39273c
    """
Packit Service 39273c
    Get the selected item of the combobox.
Packit Service 39273c
Packit Service 39273c
    :return: selected item or None
Packit Service 39273c
Packit Service 39273c
    """
Packit Service 39273c
Packit Service 39273c
    model = combo.get_model()
Packit Service 39273c
    itr = combo.get_active_iter()
Packit Service 39273c
    if not itr or not model:
Packit Service 39273c
        return None
Packit Service 39273c
Packit Service 39273c
    return model[itr][0]
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def render_message_type(column, renderer, model, itr, user_data=None):
Packit Service 39273c
    # get message type from the first column
Packit Service 39273c
    value = model[itr][0]
Packit Service 39273c
Packit Service 39273c
    if value == common.MESSAGE_TYPE_FATAL:
Packit Service 39273c
        renderer.set_property("stock-id", "gtk-dialog-error")
Packit Service 39273c
    elif value == common.MESSAGE_TYPE_WARNING:
Packit Service 39273c
        renderer.set_property("stock-id", "gtk-dialog-warning")
Packit Service 39273c
    elif value == common.MESSAGE_TYPE_INFO:
Packit Service 39273c
        renderer.set_property("stock-id", "gtk-info")
Packit Service 39273c
    else:
Packit Service 39273c
        renderer.set_property("stock-id", "gtk-dialog-question")
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def set_ready(func):
Packit Service 39273c
    @wraps(func)
Packit Service 39273c
    def decorated(self, *args, **kwargs):
Packit Service 39273c
        ret = func(self, *args, **kwargs)
Packit Service 39273c
Packit Service 39273c
        self._unitialized_status = None
Packit Service 39273c
        self._ready = True
Packit Service 39273c
        # pylint: disable-msg=E1101
Packit Service 39273c
        hubQ.send_ready(self.__class__.__name__, True)
Packit Service 39273c
        hubQ.send_message(self.__class__.__name__, self.status)
Packit Service 39273c
Packit Service 39273c
        return ret
Packit Service 39273c
Packit Service 39273c
    return decorated
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
class OSCAPSpoke(NormalSpoke):
Packit Service 39273c
    """
Packit Service 39273c
    Main class of the OSCAP addon spoke that will appear in the Security
Packit Service 39273c
    category on the Summary hub. It allows interactive choosing of the data
Packit Service 39273c
    stream, checklist and profile driving the evaluation and remediation of the
Packit Service 39273c
    available SCAP content in the installation process.
Packit Service 39273c
Packit Service 39273c
    :see: pyanaconda.ui.common.UIObject
Packit Service 39273c
    :see: pyanaconda.ui.common.Spoke
Packit Service 39273c
    :see: pyanaconda.ui.gui.GUIObject
Packit Service 39273c
Packit Service 39273c
    """
Packit Service 39273c
Packit Service 39273c
    # class attributes defined by API #
Packit Service 39273c
Packit Service 39273c
    # list all top-level objects from the .glade file that should be exposed
Packit Service 39273c
    # to the spoke or leave empty to extract everything
Packit Service 39273c
    builderObjects = ["OSCAPspokeWindow", "profilesStore", "changesStore",
Packit Service 39273c
                      "dsStore", "xccdfStore", "profilesStore",
Packit Service 39273c
                      ]
Packit Service 39273c
Packit Service 39273c
    # the name of the main window widget
Packit Service 39273c
    mainWidgetName = "OSCAPspokeWindow"
Packit Service 39273c
Packit Service 39273c
    # name of the .glade file in the same directory as this source
Packit Service 39273c
    uiFile = "oscap.glade"
Packit Service 39273c
Packit Service 39273c
    # id of the help content for this spoke
Packit Service 39273c
    help_id = "SecurityPolicySpoke"
Packit Service 39273c
Packit Service 39273c
    # domain of oscap-anaconda-addon translations
Packit Service 39273c
    translationDomain = "oscap-anaconda-addon"
Packit Service 39273c
Packit Service 39273c
    # category this spoke belongs to
Packit Service 39273c
    category = SystemCategory
Packit Service 39273c
Packit Service 39273c
    # spoke icon (will be displayed on the hub)
Packit Service 39273c
    # preferred are the -symbolic icons as these are used in Anaconda's spokes
Packit Service 39273c
    icon = "changes-prevent-symbolic"
Packit Service 39273c
Packit Service 39273c
    # title of the spoke (will be displayed on the hub)
Packit Service 39273c
    title = N_("_Security Policy")
Packit Service 39273c
Packit Service 39273c
    # methods defined by API and helper methods #
Packit Service 39273c
    def __init__(self, data, storage, payload):
Packit Service 39273c
        """
Packit Service 39273c
        :see: pyanaconda.ui.common.Spoke.__init__
Packit Service 39273c
        :param data: data object passed to every spoke to load/store data
Packit Service 39273c
                     from/to it
Packit Service 39273c
        :type data: pykickstart.base.BaseHandler
Packit Service 39273c
        :param storage: object storing storage-related information
Packit Service 39273c
                        (disks, partitioning, bootloader, etc.)
Packit Service 39273c
        :type storage: blivet.Blivet
Packit Service 39273c
        :param payload: object storing packaging-related information
Packit Service 39273c
        :type payload: pyanaconda.packaging.Payload
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        NormalSpoke.__init__(self, data, storage, payload)
Packit Service 39273c
        self._addon_data = self.data.addons.org_fedora_oscap
Packit Service 39273c
        # workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1673071
Packit Service 39273c
        self.title = _(self.title)
Packit Service 39273c
        self._storage = storage
Packit Service 39273c
        self._ready = False
Packit Service 39273c
Packit Service 39273c
        # the first status provided
Packit Service 39273c
        self._unitialized_status = _("Not ready")
Packit Service 39273c
Packit Service 39273c
        self._content_handler = None
Packit Service 39273c
        self._content_handling_cls = None
Packit Service 39273c
        self._ds_checklists = None
Packit Service 39273c
Packit Service 39273c
        # used for changing profiles, stored as self._addon_data.rule_data when
Packit Service 39273c
        # leaving the spoke
Packit Service 39273c
        self._rule_data = None
Packit Service 39273c
Packit Service 39273c
        # used for storing previously set root password if we need to remove it
Packit Service 39273c
        # due to the chosen policy (so that we can put it back in case of
Packit Service 39273c
        # revert)
Packit Service 39273c
        self.__old_root_pw = None
Packit Service 39273c
Packit Service 39273c
        # used to check if the profile was changed or not
Packit Service 39273c
        self._active_profile = None
Packit Service 39273c
Packit Service 39273c
        # prevent multiple simultaneous data fetches
Packit Service 39273c
        self._fetching = False
Packit Service 39273c
        self._fetch_flag_lock = threading.Lock()
Packit Service 39273c
Packit Service 39273c
        self._error = None
Packit Service 39273c
Packit Service 39273c
        # wait for all Anaconda spokes to initialiuze
Packit Service 39273c
        self._anaconda_spokes_initialized = threading.Event()
Packit Service 39273c
        self.initialization_controller.init_done.connect(self._all_anaconda_spokes_initialized)
Packit Service 39273c
Packit Service 39273c
    def _all_anaconda_spokes_initialized(self):
Packit Service 39273c
        log.debug("OSCAP addon: Anaconda init_done signal triggered")
Packit Service 39273c
        self._anaconda_spokes_initialized.set()
Packit Service 39273c
Packit Service 39273c
    def initialize(self):
Packit Service 39273c
        """
Packit Service 39273c
        The initialize method that is called after the instance is created.
Packit Service 39273c
        The difference between __init__ and this method is that this may take
Packit Service 39273c
        a long time and thus could be called in a separated thread.
Packit Service 39273c
Packit Service 39273c
        :see: pyanaconda.ui.common.UIObject.initialize
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        NormalSpoke.initialize(self)
Packit Service 39273c
        column = self.builder.get_object("messageTypeColumn")
Packit Service 39273c
        renderer = self.builder.get_object("messageTypeRenderer")
Packit Service 39273c
        column.set_cell_data_func(renderer, render_message_type)
Packit Service 39273c
Packit Service 39273c
        # the main notebook containing two pages -- for settings parameters and
Packit Service 39273c
        # for entering content URL
Packit Service 39273c
        self._main_notebook = self.builder.get_object("mainNotebook")
Packit Service 39273c
Packit Service 39273c
        # the store that holds the messages that come from the rules evaluation
Packit Service 39273c
        self._message_store = self.builder.get_object("changesStore")
Packit Service 39273c
Packit Service 39273c
        # stores with data streams, checklists and profiles
Packit Service 39273c
        self._ds_store = self.builder.get_object("dsStore")
Packit Service 39273c
        self._xccdf_store = self.builder.get_object("xccdfStore")
Packit Service 39273c
        self._profiles_store = self.builder.get_object("profilesStore")
Packit Service 39273c
Packit Service 39273c
        # comboboxes for data streams and checklists
Packit Service 39273c
        self._ids_box = self.builder.get_object("idsBox")
Packit Service 39273c
        self._ds_combo = self.builder.get_object("dsCombo")
Packit Service 39273c
        self._xccdf_combo = self.builder.get_object("xccdfCombo")
Packit Service 39273c
Packit Service 39273c
        # profiles view and selection
Packit Service 39273c
        self._profiles_view = self.builder.get_object("profilesView")
Packit Service 39273c
        self._profiles_selection = self.builder.get_object("profilesSelection")
Packit Service 39273c
        selected_column = self.builder.get_object("selectedColumn")
Packit Service 39273c
        selected_renderer = self.builder.get_object("selectedRenderer")
Packit Service 39273c
        selected_column.set_cell_data_func(selected_renderer,
Packit Service 39273c
                                           self._render_selected)
Packit Service 39273c
Packit Service 39273c
        # button for switching profiles
Packit Service 39273c
        self._choose_button = self.builder.get_object("chooseProfileButton")
Packit Service 39273c
Packit Service 39273c
        # toggle switching the dry-run mode
Packit Service 39273c
        self._dry_run_switch = self.builder.get_object("dryRunSwitch")
Packit Service 39273c
Packit Service 39273c
        # control buttons
Packit Service 39273c
        self._control_buttons = self.builder.get_object("controlButtons")
Packit Service 39273c
Packit Service 39273c
        # content URL entering, content fetching, ...
Packit Service 39273c
        self._no_content_label = self.builder.get_object("noContentLabel")
Packit Service 39273c
        self._content_url_entry = self.builder.get_object("urlEntry")
Packit Service 39273c
        self._fetch_button = self.builder.get_object("fetchButton")
Packit Service 39273c
        self._progress_box = self.builder.get_object("progressBox")
Packit Service 39273c
        self._progress_spinner = self.builder.get_object("progressSpinner")
Packit Service 39273c
        self._progress_label = self.builder.get_object("progressLabel")
Packit Service 39273c
        self._ssg_button = self.builder.get_object("ssgButton")
Packit Service 39273c
Packit Service 39273c
        # if no content was specified and SSG is available, use it
Packit Service 39273c
        if not self._addon_data.content_type and common.ssg_available():
Packit Service 39273c
            self._addon_data.content_type = "scap-security-guide"
Packit Service 39273c
            self._addon_data.content_path = common.SSG_DIR + common.SSG_CONTENT
Packit Service 39273c
Packit Service 39273c
        if not self._addon_data.content_defined:
Packit Service 39273c
            # nothing more to be done now, the spoke is ready
Packit Service 39273c
            self._ready = True
Packit Service 39273c
Packit Service 39273c
            # no more being unitialized
Packit Service 39273c
            self._unitialized_status = None
Packit Service 39273c
Packit Service 39273c
            # user is going to enter the content URL
Packit Service 39273c
            self._content_url_entry.grab_focus()
Packit Service 39273c
Packit Service 39273c
            # pylint: disable-msg=E1101
Packit Service 39273c
            hubQ.send_ready(self.__class__.__name__, True)
Packit Service 39273c
        else:
Packit Service 39273c
            # else fetch data
Packit Service 39273c
            self._fetch_data_and_initialize()
Packit Service 39273c
Packit Service 39273c
    def _render_selected(self, column, renderer, model, itr, user_data=None):
Packit Service 39273c
        if model[itr][2]:
Packit Service 39273c
            renderer.set_property("stock-id", "gtk-apply")
Packit Service 39273c
        else:
Packit Service 39273c
            renderer.set_property("stock-id", None)
Packit Service 39273c
Packit Service 39273c
    def _fetch_data_and_initialize(self):
Packit Service 39273c
        """Fetch data from a specified URL and initialize everything."""
Packit Service 39273c
Packit Service 39273c
        with self._fetch_flag_lock:
Packit Service 39273c
            if self._fetching:
Packit Service 39273c
                # prevent multiple fetches running simultaneously
Packit Service 39273c
                return
Packit Service 39273c
            self._fetching = True
Packit Service 39273c
Packit Service 39273c
        thread_name = None
Packit Service 39273c
        if any(self._addon_data.content_url.startswith(net_prefix)
Packit Service 39273c
               for net_prefix in data_fetch.NET_URL_PREFIXES):
Packit Service 39273c
            # need to fetch data over network
Packit Service 39273c
            try:
Packit Service 39273c
                thread_name = common.wait_and_fetch_net_data(
Packit Service 39273c
                                     self._addon_data.content_url,
Packit Service 39273c
                                     self._addon_data.raw_preinst_content_path,
Packit Service 39273c
                                     self._addon_data.certificates)
Packit Service 39273c
            except common.OSCAPaddonNetworkError:
Packit Service 39273c
                self._network_problem()
Packit Service 39273c
                with self._fetch_flag_lock:
Packit Service 39273c
                    self._fetching = False
Packit Service 39273c
                return
Packit Service 39273c
            except KickstartValueError:
Packit Service 39273c
                self._invalid_url()
Packit Service 39273c
                with self._fetch_flag_lock:
Packit Service 39273c
                    self._fetching = False
Packit Service 39273c
                return
Packit Service 39273c
Packit Service 39273c
        # pylint: disable-msg=E1101
Packit Service 39273c
        hubQ.send_message(self.__class__.__name__,
Packit Service 39273c
                          _("Fetching content data"))
Packit Service 39273c
        # pylint: disable-msg=E1101
Packit Service 39273c
        hubQ.send_not_ready(self.__class__.__name__)
Packit Service 39273c
        threadMgr.add(AnacondaThread(name="OSCAPguiWaitForDataFetchThread",
Packit Service 39273c
                                     target=self._init_after_data_fetch,
Packit Service 39273c
                                     args=(thread_name,)))
Packit Service 39273c
Packit Service 39273c
    @set_ready
Packit Service 39273c
    def _init_after_data_fetch(self, wait_for):
Packit Service 39273c
        """
Packit Service 39273c
        Waits for data fetching to be finished, extracts it (if needed),
Packit Service 39273c
        populates the stores and evaluates pre-installation fixes from the
Packit Service 39273c
        content and marks the spoke as ready in the end.
Packit Service 39273c
Packit Service 39273c
        :param wait_for: name of the thread to wait for (if any)
Packit Service 39273c
        :type wait_for: str or None
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        try:
Packit Service 39273c
            threadMgr.wait(wait_for)
Packit Service 39273c
        except data_fetch.DataFetchError:
Packit Service 39273c
            self._data_fetch_failed()
Packit Service 39273c
            with self._fetch_flag_lock:
Packit Service 39273c
                self._fetching = False
Packit Service 39273c
            return
Packit Service 39273c
        finally:
Packit Service 39273c
            # stop the spinner in any case
Packit Service 39273c
            fire_gtk_action(self._progress_spinner.stop)
Packit Service 39273c
Packit Service 39273c
        if self._addon_data.fingerprint:
Packit Service 39273c
            hash_obj = utils.get_hashing_algorithm(self._addon_data.fingerprint)
Packit Service 39273c
            digest = utils.get_file_fingerprint(self._addon_data.raw_preinst_content_path,
Packit Service 39273c
                                                hash_obj)
Packit Service 39273c
            if digest != self._addon_data.fingerprint:
Packit Service 39273c
                self._integrity_check_failed()
Packit Service 39273c
                # fetching done
Packit Service 39273c
                with self._fetch_flag_lock:
Packit Service 39273c
                    self._fetching = False
Packit Service 39273c
                return
Packit Service 39273c
Packit Service 39273c
        # RPM is an archive at this phase
Packit Service 39273c
        if self._addon_data.content_type in ("archive", "rpm"):
Packit Service 39273c
            # extract the content
Packit Service 39273c
            try:
Packit Service 39273c
                fpaths = common.extract_data(self._addon_data.raw_preinst_content_path,
Packit Service 39273c
                                             common.INSTALLATION_CONTENT_DIR,
Packit Service 39273c
                                             [self._addon_data.content_path])
Packit Service 39273c
            except common.ExtractionError as err:
Packit Service 39273c
                self._extraction_failed(str(err))
Packit Service 39273c
                # fetching done
Packit Service 39273c
                with self._fetch_flag_lock:
Packit Service 39273c
                    self._fetching = False
Packit Service 39273c
                return
Packit Service 39273c
Packit Service 39273c
            # and populate missing fields
Packit Service 39273c
            self._content_handling_cls, files = content_handling.explore_content_files(fpaths)
Packit Service 39273c
            files = common.strip_content_dir(files)
Packit Service 39273c
Packit Service 39273c
            # pylint: disable-msg=E1103
Packit Service 39273c
            self._addon_data.content_path = self._addon_data.content_path or files.xccdf
Packit Service 39273c
            self._addon_data.cpe_path = self._addon_data.cpe_path or files.cpe
Packit Service 39273c
            self._addon_data.tailoring_path = (self._addon_data.tailoring_path or
Packit Service 39273c
                                               files.tailoring)
Packit Service 39273c
        elif self._addon_data.content_type == "datastream":
Packit Service 39273c
            self._content_handling_cls = content_handling.DataStreamHandler
Packit Service 39273c
        elif self._addon_data.content_type == "scap-security-guide":
Packit Service 39273c
            self._content_handling_cls = content_handling.BenchmarkHandler
Packit Service 39273c
        else:
Packit Service 39273c
            raise common.OSCAPaddonError("Unsupported content type")
Packit Service 39273c
Packit Service 39273c
        try:
Packit Service 39273c
            self._content_handler = self._content_handling_cls(self._addon_data.preinst_content_path,
Packit Service 39273c
                                                               self._addon_data.preinst_tailoring_path)
Packit Service 39273c
        except content_handling.ContentHandlingError:
Packit Service 39273c
            self._invalid_content()
Packit Service 39273c
            # fetching done
Packit Service 39273c
            with self._fetch_flag_lock:
Packit Service 39273c
                self._fetching = False
Packit Service 39273c
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        if self._using_ds:
Packit Service 39273c
            # populate the stores from items from the content
Packit Service 39273c
            self._ds_checklists = self._content_handler.get_data_streams_checklists()
Packit Service 39273c
            add_ds_ids = GtkActionList()
Packit Service 39273c
            add_ds_ids.add_action(self._ds_store.clear)
Packit Service 39273c
            for dstream in self._ds_checklists.keys():
Packit Service 39273c
                add_ds_ids.add_action(self._add_ds_id, dstream)
Packit Service 39273c
            add_ds_ids.fire()
Packit Service 39273c
Packit Service 39273c
        self._update_ids_visibility()
Packit Service 39273c
Packit Service 39273c
        # refresh UI elements
Packit Service 39273c
        self.refresh()
Packit Service 39273c
Packit Service 39273c
        # let all initialization and configuration happen before we evaluate
Packit Service 39273c
        # the setup
Packit Service 39273c
        if not self._anaconda_spokes_initialized.is_set():
Packit Service 39273c
            # only wait (and log the messages) if the event is not set yet
Packit Service 39273c
            log.debug("OSCAP addon: waiting for all Anaconda spokes to be initialized")
Packit Service 39273c
            self._anaconda_spokes_initialized.wait()
Packit Service 39273c
            log.debug("OSCAP addon: all Anaconda spokes have been initialized - continuing")
Packit Service 39273c
Packit Service 39273c
        # try to switch to the chosen profile (if any)
Packit Service 39273c
        selected = self._switch_profile()
Packit Service 39273c
Packit Service 39273c
        if self._addon_data.profile_id and not selected:
Packit Service 39273c
            # profile ID given, but it was impossible to select it -> invalid
Packit Service 39273c
            # profile ID given
Packit Service 39273c
            self._invalid_profile_id()
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        # initialize the self._addon_data.rule_data
Packit Service 39273c
        self._addon_data.rule_data = self._rule_data
Packit Service 39273c
Packit Service 39273c
        # update the message store with the messages
Packit Service 39273c
        self._update_message_store()
Packit Service 39273c
Packit Service 39273c
        # all initialized, we can now let user set parameters
Packit Service 39273c
        fire_gtk_action(self._main_notebook.set_current_page, SET_PARAMS_PAGE)
Packit Service 39273c
Packit Service 39273c
        # and use control buttons
Packit Service 39273c
        fire_gtk_action(really_show, self._control_buttons)
Packit Service 39273c
Packit Service 39273c
        # fetching done
Packit Service 39273c
        with self._fetch_flag_lock:
Packit Service 39273c
            self._fetching = False
Packit Service 39273c
Packit Service 39273c
        # no error
Packit Service 39273c
        self._set_error(None)
Packit Service 39273c
Packit Service 39273c
    @property
Packit Service 39273c
    def _using_ds(self):
Packit Service 39273c
        return self._content_handling_cls == content_handling.DataStreamHandler
Packit Service 39273c
Packit Service 39273c
    @property
Packit Service 39273c
    def _current_ds_id(self):
Packit Service 39273c
        return get_combo_selection(self._ds_combo)
Packit Service 39273c
Packit Service 39273c
    @property
Packit Service 39273c
    def _current_xccdf_id(self):
Packit Service 39273c
        return get_combo_selection(self._xccdf_combo)
Packit Service 39273c
Packit Service 39273c
    @property
Packit Service 39273c
    def _current_profile_id(self):
Packit Service 39273c
        store, itr = self._profiles_selection.get_selected()
Packit Service 39273c
        if not store or not itr:
Packit Service 39273c
            return None
Packit Service 39273c
        else:
Packit Service 39273c
            return store[itr][0]
Packit Service 39273c
Packit Service 39273c
    def _add_ds_id(self, ds_id):
Packit Service 39273c
        """
Packit Service 39273c
        Add data stream ID to the data streams store.
Packit Service 39273c
Packit Service 39273c
        :param ds_id: data stream ID
Packit Service 39273c
        :type ds_id: str
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        self._ds_store.append([ds_id])
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _update_ids_visibility(self):
Packit Service 39273c
        """
Packit Service 39273c
        Updates visibility of the combo boxes that are used to select the DS
Packit Service 39273c
        and XCCDF IDs.
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        if self._using_ds:
Packit Service 39273c
            # only show the combo boxes if there are multiple data streams or
Packit Service 39273c
            # multiple xccdfs (IOW if there's something to choose from)
Packit Service 39273c
            ds_ids = list(self._ds_checklists.keys())
Packit Service 39273c
            if len(ds_ids) > 1 or len(self._ds_checklists[ds_ids[0]]) > 1:
Packit Service 39273c
                really_show(self._ids_box)
Packit Service 39273c
                return
Packit Service 39273c
Packit Service 39273c
        # not showing, hide instead
Packit Service 39273c
        really_hide(self._ids_box)
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _update_xccdfs_store(self):
Packit Service 39273c
        """
Packit Service 39273c
        Clears and repopulates the store with XCCDF IDs from the currently
Packit Service 39273c
        selected data stream.
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        if self._ds_checklists is None:
Packit Service 39273c
            # not initialized, cannot do anything
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        self._xccdf_store.clear()
Packit Service 39273c
        for xccdf_id in self._ds_checklists[self._current_ds_id]:
Packit Service 39273c
            self._xccdf_store.append([xccdf_id])
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _update_profiles_store(self):
Packit Service 39273c
        """
Packit Service 39273c
        Clears and repopulates the store with profiles from the currently
Packit Service 39273c
        selected data stream and checklist.
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        if self._content_handler is None:
Packit Service 39273c
            # not initialized, cannot do anything
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        if self._using_ds and self._ds_checklists is None:
Packit Service 39273c
            # not initialized, cannot do anything
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        self._profiles_store.clear()
Packit Service 39273c
Packit Service 39273c
        if self._using_ds:
Packit Service 39273c
            profiles = self._content_handler.get_profiles(self._current_ds_id,
Packit Service 39273c
                                                          self._current_xccdf_id)
Packit Service 39273c
        else:
Packit Service 39273c
            # pylint: disable-msg=E1103
Packit Service 39273c
            profiles = self._content_handler.profiles
Packit Service 39273c
Packit Service 39273c
        for profile in profiles:
Packit Service 39273c
            profile_markup = '%s\n%s' \
Packit Service 39273c
                                % (profile.title, profile.description)
Packit Service 39273c
            self._profiles_store.append([profile.id,
Packit Service 39273c
                                         profile_markup,
Packit Service 39273c
                                         profile.id == self._active_profile])
Packit Service 39273c
Packit Service 39273c
    def _add_message(self, message):
Packit Service 39273c
        """
Packit Service 39273c
        Add message to the store.
Packit Service 39273c
Packit Service 39273c
        :param message: message to be added
Packit Service 39273c
        :type message: org_fedora_oscap.common.RuleMessage
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        self._message_store.append([message.type, message.text])
Packit Service 39273c
Packit Service 39273c
    @dry_run_skip
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _update_message_store(self, report_only=False):
Packit Service 39273c
        """
Packit Service 39273c
        Updates the message store with messages from rule evaluation.
Packit Service 39273c
Packit Service 39273c
        :param report_only: wheter to do changes in configuration or just
Packit Service 39273c
                            report
Packit Service 39273c
        :type report_only: bool
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        self._message_store.clear()
Packit Service 39273c
Packit Service 39273c
        if not self._rule_data:
Packit Service 39273c
            # RuleData instance not initialized, cannot do anything
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        messages = self._rule_data.eval_rules(self.data, self._storage,
Packit Service 39273c
                                              report_only)
Packit Service 39273c
        if not messages:
Packit Service 39273c
            # no messages from the rules, add a message informing about that
Packit Service 39273c
            if not self._active_profile:
Packit Service 39273c
                # because of no profile
Packit Service 39273c
                message = common.RuleMessage(self.__class__,
Packit Service 39273c
                                             common.MESSAGE_TYPE_INFO,
Packit Service 39273c
                                             _("No profile selected"))
Packit Service 39273c
            else:
Packit Service 39273c
                # because of no pre-inst rules
Packit Service 39273c
                message = common.RuleMessage(self.__class__,
Packit Service 39273c
                                             common.MESSAGE_TYPE_INFO,
Packit Service 39273c
                                             _("No rules for the pre-installation phase"))
Packit Service 39273c
            self._add_message(message)
Packit Service 39273c
Packit Service 39273c
            # nothing more to be done
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        self._resolve_rootpw_issues(messages, report_only)
Packit Service 39273c
        for msg in messages:
Packit Service 39273c
            self._add_message(msg)
Packit Service 39273c
Packit Service 39273c
    def _resolve_rootpw_issues(self, messages, report_only):
Packit Service 39273c
        """Mitigate root password issues (which are not fatal in GUI)"""
Packit Service 39273c
        fatal_rootpw_msgs = [
Packit Service 39273c
            msg for msg in messages
Packit Service 39273c
            if msg.origin == rule_handling.PasswdRules and msg.type == common.MESSAGE_TYPE_FATAL]
Packit Service 39273c
Packit Service 39273c
        if fatal_rootpw_msgs:
Packit Service 39273c
            for msg in fatal_rootpw_msgs:
Packit Service 39273c
                # cannot just change the message type because it is a namedtuple
Packit Service 39273c
                messages.remove(msg)
Packit Service 39273c
Packit Service 39273c
                msg = common.RuleMessage(
Packit Service 39273c
                    self.__class__, common.MESSAGE_TYPE_WARNING, msg.text)
Packit Service 39273c
                messages.append(msg)
Packit Service 39273c
Packit Service 39273c
            if not report_only:
Packit Service 39273c
                users_proxy = USERS.get_proxy()
Packit Service 39273c
Packit Service 39273c
                self.__old_root_pw = users_proxy.RootPassword
Packit Service 39273c
                self.data.rootpw.password = None
Packit Service 39273c
                self.__old_root_pw_seen = users_proxy.IsRootpwKickstarted
Packit Service 39273c
                self.data.rootpw.seen = False
Packit Service 39273c
Packit Service 39273c
    def _revert_rootpw_changes(self):
Packit Service 39273c
        if self.__old_root_pw is not None:
Packit Service 39273c
            users_proxy = USERS.get_proxy()
Packit Service 39273c
Packit Service 39273c
            users_proxy.SetRootPassword(self.__old_root_pw)
Packit Service 39273c
            self.__old_root_pw = None
Packit Service 39273c
Packit Service 39273c
            users_proxy.SetRootpwKickstarted(self.__old_root_pw_seen)
Packit Service 39273c
            self.__old_root_pw_seen = None
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _unselect_profile(self, profile_id):
Packit Service 39273c
        """Unselects the given profile."""
Packit Service 39273c
Packit Service 39273c
        if not profile_id:
Packit Service 39273c
            # no profile specified, nothing to do
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        itr = self._profiles_store.get_iter_first()
Packit Service 39273c
        while itr:
Packit Service 39273c
            if self._profiles_store[itr][0] == profile_id:
Packit Service 39273c
                self._profiles_store.set_value(itr, 2, False)
Packit Service 39273c
            itr = self._profiles_store.iter_next(itr)
Packit Service 39273c
Packit Service 39273c
        if self._rule_data:
Packit Service 39273c
            # revert changes and clear rule_data (no longer valid)
Packit Service 39273c
            self._rule_data.revert_changes(self.data, self._storage)
Packit Service 39273c
            self._revert_rootpw_changes()
Packit Service 39273c
            self._rule_data = None
Packit Service 39273c
Packit Service 39273c
        self._active_profile = None
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _select_profile(self, profile_id):
Packit Service 39273c
        """Selects the given profile."""
Packit Service 39273c
Packit Service 39273c
        if not profile_id:
Packit Service 39273c
            # no profile specified, nothing to do
Packit Service 39273c
            return False
Packit Service 39273c
Packit Service 39273c
        if self._using_ds:
Packit Service 39273c
            ds = self._current_ds_id
Packit Service 39273c
            xccdf = self._current_xccdf_id
Packit Service 39273c
Packit Service 39273c
            if not all((ds, xccdf, profile_id)):
Packit Service 39273c
                # something is not set -> do nothing
Packit Service 39273c
                return False
Packit Service 39273c
        else:
Packit Service 39273c
            ds = None
Packit Service 39273c
            xccdf = None
Packit Service 39273c
Packit Service 39273c
        # get pre-install fix rules from the content
Packit Service 39273c
        try:
Packit Service 39273c
            rules = common.get_fix_rules_pre(profile_id,
Packit Service 39273c
                                             self._addon_data.preinst_content_path,
Packit Service 39273c
                                             ds, xccdf,
Packit Service 39273c
                                             self._addon_data.preinst_tailoring_path)
Packit Service 39273c
        except common.OSCAPaddonError as exc:
Packit Service 39273c
            log.error(
Packit Service 39273c
                "Failed to get rules for the profile '{}': {}"
Packit Service 39273c
                .format(profile_id, str(exc)))
Packit Service 39273c
            self._set_error(
Packit Service 39273c
                "Failed to get rules for the profile '{}'"
Packit Service 39273c
                .format(profile_id))
Packit Service 39273c
            return False
Packit Service 39273c
Packit Service 39273c
        itr = self._profiles_store.get_iter_first()
Packit Service 39273c
        while itr:
Packit Service 39273c
            if self._profiles_store[itr][0] == profile_id:
Packit Service 39273c
                self._profiles_store.set_value(itr, 2, True)
Packit Service 39273c
            itr = self._profiles_store.iter_next(itr)
Packit Service 39273c
Packit Service 39273c
        # parse and store rules with a clean RuleData instance
Packit Service 39273c
        self._rule_data = rule_handling.RuleData()
Packit Service 39273c
        for rule in rules.splitlines():
Packit Service 39273c
            self._rule_data.new_rule(rule)
Packit Service 39273c
Packit Service 39273c
        # remember the active profile
Packit Service 39273c
        self._active_profile = profile_id
Packit Service 39273c
Packit Service 39273c
        return True
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    @dry_run_skip
Packit Service 39273c
    def _switch_profile(self):
Packit Service 39273c
        """Switches to a current selected profile.
Packit Service 39273c
Packit Service 39273c
        :returns: whether some profile was selected or not
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        self._set_error(None)
Packit Service 39273c
        profile = self._current_profile_id
Packit Service 39273c
        if not profile:
Packit Service 39273c
            return False
Packit Service 39273c
Packit Service 39273c
        self._unselect_profile(self._active_profile)
Packit Service 39273c
        ret = self._select_profile(profile)
Packit Service 39273c
Packit Service 39273c
        # update messages according to the newly chosen profile
Packit Service 39273c
        self._update_message_store()
Packit Service 39273c
Packit Service 39273c
        return ret
Packit Service 39273c
Packit Service 39273c
    @set_ready
Packit Service 39273c
    def _set_error(self, msg):
Packit Service 39273c
        """Set or clear error message"""
Packit Service 39273c
        if msg:
Packit Service 39273c
            self._error = msg
Packit Service 39273c
            self.clear_info()
Packit Service 39273c
            self.set_error(msg)
Packit Service 39273c
        else:
Packit Service 39273c
            self._error = None
Packit Service 39273c
            self.clear_info()
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _invalid_content(self):
Packit Service 39273c
        """Callback for informing user about provided content invalidity."""
Packit Service 39273c
Packit Service 39273c
        msg = _("Invalid content provided. Enter a different URL, please.")
Packit Service 39273c
        self._progress_label.set_markup("%s" % msg)
Packit Service 39273c
        self._wrong_content(msg)
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _invalid_url(self):
Packit Service 39273c
        """Callback for informing user about provided URL invalidity."""
Packit Service 39273c
Packit Service 39273c
        msg = _("Invalid or unsupported content URL, please enter a different one.")
Packit Service 39273c
        self._progress_label.set_markup("%s" % msg)
Packit Service 39273c
        self._wrong_content(msg)
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _data_fetch_failed(self):
Packit Service 39273c
        """Adapts the UI if fetching data from entered URL failed"""
Packit Service 39273c
Packit Service 39273c
        msg = _("Failed to fetch content. Enter a different URL, please.")
Packit Service 39273c
        self._progress_label.set_markup("%s" % msg)
Packit Service 39273c
        self._wrong_content(msg)
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _network_problem(self):
Packit Service 39273c
        """Adapts the UI if network error was encountered during data fetch"""
Packit Service 39273c
Packit Service 39273c
        msg = _("Network error encountered when fetching data."
Packit Service 39273c
                " Please check that network is setup and working.")
Packit Service 39273c
        self._progress_label.set_markup("%s" % msg)
Packit Service 39273c
        self._wrong_content(msg)
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _integrity_check_failed(self):
Packit Service 39273c
        """Adapts the UI if integrity check fails"""
Packit Service 39273c
Packit Service 39273c
        msg = _("The integrity check of the content failed. Cannot use the content.")
Packit Service 39273c
        self._progress_label.set_markup("%s" % msg)
Packit Service 39273c
        self._wrong_content(msg)
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _extraction_failed(self, err_msg):
Packit Service 39273c
        """Adapts the UI if extracting data from entered URL failed"""
Packit Service 39273c
Packit Service 39273c
        msg = _("Failed to extract content (%s). Enter a different URL, "
Packit Service 39273c
                "please.") % err_msg
Packit Service 39273c
        self._progress_label.set_markup("%s" % msg)
Packit Service 39273c
        self._wrong_content(msg)
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _wrong_content(self, msg):
Packit Service 39273c
        self._addon_data.clear_all()
Packit Service 39273c
        really_hide(self._progress_spinner)
Packit Service 39273c
        self._fetch_button.set_sensitive(True)
Packit Service 39273c
        self._content_url_entry.set_sensitive(True)
Packit Service 39273c
        self._content_url_entry.grab_focus()
Packit Service 39273c
        self._content_url_entry.select_region(0, -1)
Packit Service 39273c
        self._content_handling_cls = None
Packit Service 39273c
        self._set_error(msg)
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _invalid_profile_id(self):
Packit Service 39273c
        msg = _("Profile with ID '%s' not defined in the content. Select a different profile, please") % self._addon_data.profile_id
Packit Service 39273c
        self._set_error(msg)
Packit Service 39273c
        self._addon_data.profile_id = None
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def _switch_dry_run(self, dry_run):
Packit Service 39273c
        self._choose_button.set_sensitive(not dry_run)
Packit Service 39273c
Packit Service 39273c
        if dry_run:
Packit Service 39273c
            # no profile can be selected in the dry-run mode
Packit Service 39273c
            self._unselect_profile(self._active_profile)
Packit Service 39273c
Packit Service 39273c
            # no messages in the dry-run mode
Packit Service 39273c
            self._message_store.clear()
Packit Service 39273c
            message = common.RuleMessage(self.__class__,
Packit Service 39273c
                                         common.MESSAGE_TYPE_INFO,
Packit Service 39273c
                                         _("Not applying security policy"))
Packit Service 39273c
            self._add_message(message)
Packit Service 39273c
Packit Service 39273c
            self._set_error(None)
Packit Service 39273c
        else:
Packit Service 39273c
            # mark the active profile as selected
Packit Service 39273c
            self._select_profile(self._active_profile)
Packit Service 39273c
            self._update_message_store()
Packit Service 39273c
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def refresh(self):
Packit Service 39273c
        """
Packit Service 39273c
        The refresh method that is called every time the spoke is displayed.
Packit Service 39273c
        It should update the UI elements according to the contents of
Packit Service 39273c
        self.data.
Packit Service 39273c
Packit Service 39273c
        :see: pyanaconda.ui.common.UIObject.refresh
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        if not self._addon_data.content_defined:
Packit Service 39273c
            # hide the control buttons
Packit Service 39273c
            really_hide(self._control_buttons)
Packit Service 39273c
Packit Service 39273c
            # provide SSG if available
Packit Service 39273c
            if common.ssg_available():
Packit Service 39273c
                # show the SSG button and tweak the rest of the line
Packit Service 39273c
                # (the label)
Packit Service 39273c
                really_show(self._ssg_button)
Packit Service 39273c
                # TRANSLATORS: the other choice if SCAP Security Guide is also
Packit Service 39273c
                # available
Packit Service 39273c
                tip = _(" or enter data stream content or archive URL below:")
Packit Service 39273c
            else:
Packit Service 39273c
                # hide the SSG button
Packit Service 39273c
                really_hide(self._ssg_button)
Packit Service 39273c
                tip = _("No content found. Please enter data stream content or "
Packit Service 39273c
                        "archive URL below:")
Packit Service 39273c
Packit Service 39273c
            self._no_content_label.set_text(tip)
Packit Service 39273c
Packit Service 39273c
            # hide the progress box, no progress now
Packit Service 39273c
            with self._fetch_flag_lock:
Packit Service 39273c
                if not self._fetching:
Packit Service 39273c
                    really_hide(self._progress_box)
Packit Service 39273c
Packit Service 39273c
                    self._content_url_entry.set_sensitive(True)
Packit Service 39273c
                    self._fetch_button.set_sensitive(True)
Packit Service 39273c
Packit Service 39273c
                    if not self._content_url_entry.get_text():
Packit Service 39273c
                        # no text -> no info/warning
Packit Service 39273c
                        self._progress_label.set_text("")
Packit Service 39273c
Packit Service 39273c
            # switch to the page allowing user to enter content URL and fetch
Packit Service 39273c
            # it
Packit Service 39273c
            self._main_notebook.set_current_page(GET_CONTENT_PAGE)
Packit Service 39273c
            self._content_url_entry.grab_focus()
Packit Service 39273c
Packit Service 39273c
            # nothing more to do here
Packit Service 39273c
            return
Packit Service 39273c
        else:
Packit Service 39273c
            # show control buttons
Packit Service 39273c
            really_show(self._control_buttons)
Packit Service 39273c
Packit Service 39273c
            self._main_notebook.set_current_page(SET_PARAMS_PAGE)
Packit Service 39273c
Packit Service 39273c
        self._active_profile = self._addon_data.profile_id
Packit Service 39273c
Packit Service 39273c
        self._update_ids_visibility()
Packit Service 39273c
Packit Service 39273c
        if self._using_ds:
Packit Service 39273c
            if self._addon_data.datastream_id:
Packit Service 39273c
                set_combo_selection(self._ds_combo,
Packit Service 39273c
                                    self._addon_data.datastream_id,
Packit Service 39273c
                                    unset_first=True)
Packit Service 39273c
            else:
Packit Service 39273c
                try:
Packit Service 39273c
                    default_ds = next(iter(self._ds_checklists.keys()))
Packit Service 39273c
                    set_combo_selection(self._ds_combo, default_ds,
Packit Service 39273c
                                        unset_first=True)
Packit Service 39273c
                except StopIteration:
Packit Service 39273c
                    # no data stream available
Packit Service 39273c
                    pass
Packit Service 39273c
Packit Service 39273c
                if self._addon_data.datastream_id and self._addon_data.xccdf_id:
Packit Service 39273c
                    set_combo_selection(self._xccdf_combo,
Packit Service 39273c
                                        self._addon_data.xccdf_id,
Packit Service 39273c
                                        unset_first=True)
Packit Service 39273c
        else:
Packit Service 39273c
            # no combobox changes --> need to update profiles store manually
Packit Service 39273c
            self._update_profiles_store()
Packit Service 39273c
Packit Service 39273c
        if self._addon_data.profile_id:
Packit Service 39273c
            set_treeview_selection(self._profiles_view,
Packit Service 39273c
                                   self._addon_data.profile_id)
Packit Service 39273c
Packit Service 39273c
        self._rule_data = self._addon_data.rule_data
Packit Service 39273c
Packit Service 39273c
        self._update_message_store()
Packit Service 39273c
Packit Service 39273c
    def apply(self):
Packit Service 39273c
        """
Packit Service 39273c
        The apply method that is called when the spoke is left. It should
Packit Service 39273c
        update the contents of self.data with values set in the GUI elements.
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        if not self._addon_data.content_defined or not self._active_profile:
Packit Service 39273c
            # no errors for no content or no profile
Packit Service 39273c
            self._set_error(None)
Packit Service 39273c
Packit Service 39273c
        # store currently selected values to the addon data attributes
Packit Service 39273c
        if self._using_ds:
Packit Service 39273c
            self._addon_data.datastream_id = self._current_ds_id
Packit Service 39273c
            self._addon_data.xccdf_id = self._current_xccdf_id
Packit Service 39273c
Packit Service 39273c
        self._addon_data.profile_id = self._active_profile
Packit Service 39273c
Packit Service 39273c
        self._addon_data.rule_data = self._rule_data
Packit Service 39273c
Packit Service 39273c
        self._addon_data.dry_run = not self._dry_run_switch.get_active()
Packit Service 39273c
Packit Service 39273c
    def execute(self):
Packit Service 39273c
        """
Packit Service 39273c
        The excecute method that is called when the spoke is left. It is
Packit Service 39273c
        supposed to do all changes to the runtime environment according to
Packit Service 39273c
        the values set in the GUI elements.
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        # nothing to do here
Packit Service 39273c
        pass
Packit Service 39273c
Packit Service 39273c
    @property
Packit Service 39273c
    def ready(self):
Packit Service 39273c
        """
Packit Service 39273c
        The ready property that tells whether the spoke is ready (can be
Packit Service 39273c
        visited) or not.
Packit Service 39273c
Packit Service 39273c
        :rtype: bool
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        return self._ready
Packit Service 39273c
Packit Service 39273c
    @property
Packit Service 39273c
    def completed(self):
Packit Service 39273c
        """
Packit Service 39273c
        The completed property that tells whether all mandatory items on the
Packit Service 39273c
        spoke are set, or not. The spoke will be marked on the hub as completed
Packit Service 39273c
        or uncompleted acording to the returned value.
Packit Service 39273c
Packit Service 39273c
        :rtype: bool
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        # no error message in the store
Packit Service 39273c
        return not self._error and all(row[0] != common.MESSAGE_TYPE_FATAL
Packit Service 39273c
                                       for row in self._message_store)
Packit Service 39273c
Packit Service 39273c
    @property
Packit Service 39273c
    @async_action_wait
Packit Service 39273c
    def status(self):
Packit Service 39273c
        """
Packit Service 39273c
        The status property that is a brief string describing the state of the
Packit Service 39273c
        spoke. It should describe whether all values are set and if possible
Packit Service 39273c
        also the values themselves. The returned value will appear on the hub
Packit Service 39273c
        below the spoke's title.
Packit Service 39273c
Packit Service 39273c
        :rtype: str
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        if self._error:
Packit Service 39273c
            return _("Error fetching and loading content")
Packit Service 39273c
Packit Service 39273c
        if self._unitialized_status:
Packit Service 39273c
            # not initialized
Packit Service 39273c
            return self._unitialized_status
Packit Service 39273c
Packit Service 39273c
        if not self._addon_data.content_defined:
Packit Service 39273c
            return _("No content found")
Packit Service 39273c
Packit Service 39273c
        if not self._active_profile:
Packit Service 39273c
            return _("No profile selected")
Packit Service 39273c
Packit Service 39273c
        # update message store, something may changed from the last update
Packit Service 39273c
        self._update_message_store(report_only=True)
Packit Service 39273c
Packit Service 39273c
        warning_found = False
Packit Service 39273c
        for row in self._message_store:
Packit Service 39273c
            if row[0] == common.MESSAGE_TYPE_FATAL:
Packit Service 39273c
                return _("Misconfiguration detected")
Packit Service 39273c
            elif row[0] == common.MESSAGE_TYPE_WARNING:
Packit Service 39273c
                warning_found = True
Packit Service 39273c
Packit Service 39273c
        # TODO: at least the last two status messages need a better wording
Packit Service 39273c
        if warning_found:
Packit Service 39273c
            return _("Warnings appeared")
Packit Service 39273c
Packit Service 39273c
        return _("Everything okay")
Packit Service 39273c
Packit Service 39273c
    def on_ds_combo_changed(self, *args):
Packit Service 39273c
        """Handler for the datastream ID change."""
Packit Service 39273c
Packit Service 39273c
        ds_id = self._current_ds_id
Packit Service 39273c
        if not ds_id:
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        self._update_xccdfs_store()
Packit Service 39273c
        first_checklist = self._ds_checklists[ds_id][0]
Packit Service 39273c
Packit Service 39273c
        set_combo_selection(self._xccdf_combo, first_checklist)
Packit Service 39273c
Packit Service 39273c
    def on_xccdf_combo_changed(self, *args):
Packit Service 39273c
        """Handler for the XCCDF ID change."""
Packit Service 39273c
Packit Service 39273c
        # may take a while
Packit Service 39273c
        self._update_profiles_store()
Packit Service 39273c
Packit Service 39273c
    @dry_run_skip
Packit Service 39273c
    def on_profiles_selection_changed(self, *args):
Packit Service 39273c
        """Handler for the profile selection change."""
Packit Service 39273c
Packit Service 39273c
        cur_profile = self._current_profile_id
Packit Service 39273c
        if cur_profile:
Packit Service 39273c
            if cur_profile != self._active_profile:
Packit Service 39273c
                # new profile selected, make the selection button sensitive
Packit Service 39273c
                self._choose_button.set_sensitive(True)
Packit Service 39273c
            else:
Packit Service 39273c
                # current active profile selected
Packit Service 39273c
                self._choose_button.set_sensitive(False)
Packit Service 39273c
Packit Service 39273c
    @dry_run_skip
Packit Service 39273c
    def on_profile_clicked(self, widget, event, *args):
Packit Service 39273c
        """Handler for the profile being clicked on."""
Packit Service 39273c
Packit Service 39273c
        # if a profile is double-clicked, we should switch to it
Packit Service 39273c
        if event.type == Gdk.EventType._2BUTTON_PRESS:
Packit Service 39273c
            self._switch_profile()
Packit Service 39273c
Packit Service 39273c
            # active profile selected
Packit Service 39273c
            self._choose_button.set_sensitive(False)
Packit Service 39273c
Packit Service 39273c
        # let the other actions hooked to the click happen as well
Packit Service 39273c
        return False
Packit Service 39273c
Packit Service 39273c
    def on_profile_chosen(self, *args):
Packit Service 39273c
        """
Packit Service 39273c
        Handler for the profile being chosen
Packit Service 39273c
        (e.g. "Select profile" button hit).
Packit Service 39273c
Packit Service 39273c
        """
Packit Service 39273c
Packit Service 39273c
        # switch profile
Packit Service 39273c
        self._switch_profile()
Packit Service 39273c
Packit Service 39273c
        # active profile selected
Packit Service 39273c
        self._choose_button.set_sensitive(False)
Packit Service 39273c
Packit Service 39273c
    def on_fetch_button_clicked(self, *args):
Packit Service 39273c
        """Handler for the Fetch button"""
Packit Service 39273c
Packit Service 39273c
        with self._fetch_flag_lock:
Packit Service 39273c
            if self._fetching:
Packit Service 39273c
                # some other fetching/pre-processing running, give up
Packit Service 39273c
                return
Packit Service 39273c
Packit Service 39273c
        # prevent user from changing the URL in the meantime
Packit Service 39273c
        self._content_url_entry.set_sensitive(False)
Packit Service 39273c
        self._fetch_button.set_sensitive(False)
Packit Service 39273c
        url = self._content_url_entry.get_text()
Packit Service 39273c
        really_show(self._progress_box)
Packit Service 39273c
        really_show(self._progress_spinner)
Packit Service 39273c
Packit Service 39273c
        if not data_fetch.can_fetch_from(url):
Packit Service 39273c
            msg = _("Invalid or unsupported URL")
Packit Service 39273c
            # cannot start fetching
Packit Service 39273c
            self._progress_label.set_markup("%s" % msg)
Packit Service 39273c
            self._wrong_content(msg)
Packit Service 39273c
            return
Packit Service 39273c
Packit Service 39273c
        self._progress_label.set_text(_("Fetching content..."))
Packit Service 39273c
        self._progress_spinner.start()
Packit Service 39273c
        self._addon_data.content_url = url
Packit Service 39273c
        if url.endswith(".rpm"):
Packit Service 39273c
            self._addon_data.content_type = "rpm"
Packit Service 39273c
        elif any(url.endswith(arch_type) for arch_type in common.SUPPORTED_ARCHIVES):
Packit Service 39273c
            self._addon_data.content_type = "archive"
Packit Service 39273c
        else:
Packit Service 39273c
            self._addon_data.content_type = "datastream"
Packit Service 39273c
Packit Service 39273c
        self._fetch_data_and_initialize()
Packit Service 39273c
Packit Service 39273c
    def on_dry_run_toggled(self, switch, *args):
Packit Service 39273c
        dry_run = not switch.get_active()
Packit Service 39273c
        self._addon_data.dry_run = dry_run
Packit Service 39273c
        self._switch_dry_run(dry_run)
Packit Service 39273c
Packit Service 39273c
    def on_change_content_clicked(self, *args):
Packit Service 39273c
        self._unselect_profile(self._active_profile)
Packit Service 39273c
        self._addon_data.clear_all()
Packit Service 39273c
        self.refresh()
Packit Service 39273c
Packit Service 39273c
    def on_use_ssg_clicked(self, *args):
Packit Service 39273c
        self._addon_data.clear_all()
Packit Service 39273c
        self._addon_data.content_type = "scap-security-guide"
Packit Service 39273c
        self._addon_data.content_path = common.SSG_DIR + common.SSG_CONTENT
Packit Service 39273c
        self._fetch_data_and_initialize()