--- firstboot/loader.py | 249 +++++++++++++++++++++------------------------------ 1 files changed, 101 insertions(+), 148 deletions(-) diff --git a/firstboot/loader.py b/firstboot/loader.py index 78b68d7..6710c64 100644 --- a/firstboot/loader.py +++ b/firstboot/loader.py @@ -1,161 +1,114 @@ # -# Chris Lumens <clumens@xxxxxxxxxx> +# loader.py # -# Copyright 2007 Red Hat, Inc. +# Copyright (C) 2011 Red Hat, Inc. # -# This copyrighted material is made available to anyone wishing to use, modify, -# copy, or redistribute it subject to the terms and conditions of the GNU -# General Public License v.2. This program is distributed in the hope that it -# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the -# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU General Public License for more details. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. # -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat -# trademarks that are incorporated in the source code or documentation are not -# subject to the GNU General Public License and may only be used or replicated -# with the express permission of Red Hat, Inc. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. # -from firstboot.constants import * -from firstboot.module import Module -from firstboot.moduleset import ModuleSet -import ethtool -import glob -import imputil -import logging +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Red Hat Author(s): Martin Gracik <mgracik@xxxxxxxxxx> +# + +import operator import os import sys -import gettext -_ = lambda x: gettext.ldgettext("firstboot", x) - -def _check(obj, attrLst): - for attr in attrLst: - if not hasattr(obj, attr) or getattr(obj, attr) is None: - raise TypeError, attr - -def _checkModule(obj): - _check(obj, ["mode", "priority", "sidebarTitle", "title"]) - -def _checkModuleSet(obj): - _check(obj, ["mode", "path", "priority", "sidebarTitle"]) - -def _haveNetwork(): - intfs = ethtool.get_active_devices() - return len(filter(lambda i: i != "lo", intfs)) != 0 - -def _insertSorted(list, obj): - _max = len(list) - i = 0 - - while i < _max: - if obj.title > list[i].title: - i += 1 - elif obj.title == list[i].title: - list[i] = obj - return - elif obj.title < list[i].title: - break - - if i >= _max: - list.append(obj) - else: - list.insert(i, obj) - -def loadModules(moduleDir, mode=MODE_REGULAR): - # Make sure moduleDir is in the system path so imputil works. - if not moduleDir in sys.path: - sys.path.append(moduleDir) - - moduleList = [] - - # A temporary dictionary of modules to run, keyed by priority. This - # will be flattened out into a single list after all modules have been - # loaded. - _tmpDict = {} - - lst = map(lambda x: os.path.splitext(os.path.basename(x))[0], - glob.glob(moduleDir + "/*.py")) - - for module in lst: - # Attempt to load the found module. - try: - found = imputil.imp.find_module(module) - loaded = imputil.imp.load_module(module, found[0], found[1], found[2]) - except ImportError as e: - if str(e).find("firstboot_module_window") != -1: - logging.error(_("Skipping old module %s that has not been updated.") % module) - - logging.error(_("Error loading module %(module)s:\n%(error)s") % \ - {"module": module, "error": str(e)}) - continue - except Exception as e: - logging.error(_("Error loading module %(module)s:\n%(error)s") % \ - {"module": module, "error": str(e)}) - continue - - # If the module was loaded, check to see if there's a class named - # moduleClass. All firstboot modules must contain this class to be - # executed. - if loaded.__dict__.has_key("moduleClass"): - obj = loaded.moduleClass() + +from .constants import * +from .module import Module +from .moduleset import ModuleSet + +import ethtool + + +# set up logging +import logging +logging.basicConfig(level=logging.DEBUG) +log = logging.getLogger('firstboot.loader') + + +class Loader: + + def __init__(self): + self.modlist = [] + + def _check_module(self, module): + # XXX this does not work as expected + if isinstance(module, Module): + attrs = ('mode', 'priority', 'sidebarTitle', 'title') + elif isinstance(module, ModuleSet): + attrs = ('mode', 'path', 'priority', 'sidebarTitle') else: - logging.error(_("Module %s does not contain a class named moduleClass; skipping.") % module) - continue - - # Perform a bunch of sanity checks on the loaded module and skip if - # it doesn't pass. - try: - if isinstance(obj, Module): - _checkModule(obj) - else: - _checkModuleSet(obj) - except TypeError, attr: - logging.error(_("Module %(module)s does not contain the required attribute %(attr)s; skipping.") % {"module": module, "attr": attr}) - continue - - # If the loaded module requires networking which is unavailable, skip - # the module. We really should have a way to bring up the network if - # it's not already up. - if obj.needsNetwork() and not _haveNetwork(): - logging.info("skipping module %s because it requires networking" % module) - continue - - # If the loaded module should not appear for some reason, don't - # do anything else with it. - if not obj.shouldAppear(): - logging.info("skipping module %s because shouldAppear returned false" % module) - continue - - # Also, the module may not need to be run in this particular mode. - # Skip those too. - if (mode == MODE_REGULAR and not obj.mode & MODE_REGULAR) or \ - (mode == MODE_RECONFIG and not obj.mode & MODE_RECONFIG): - logging.info("skipping module %s because it should not run in this mode" % module) - continue - - # If we got here, the module should appear in firstboot. Add it. - if isinstance(obj, ModuleSet): - logging.debug("Module %s is a ModuleSet, adding" % module) - obj.loadModules(mode=mode) - - if len(obj.moduleList) == 0: - logging.info("skipping module set %s because it has no modules" % module) + return [] + + return [a for a in attrs if getattr(module, a, None) is None] + + def _has_network(self): + return [i for i in ethtool.get_active_devices() if i != 'lo'] + + def load_modules(self, module_dir, reconfig=False): + if not module_dir in sys.path: + sys.path.append(module_dir) + + modules = [os.path.splitext(f)[0] for f in os.listdir(module_dir) + if f.endswith('.py')] + + for module in modules: + log.info('loading module %s', module) + try: + imported = __import__(module) + except ImportError as e: + log.error('module could not be imported: %s', e) continue - else: - logging.debug("Successfully loaded module %s, adding" % module) - if _tmpDict.has_key(obj.priority): - _insertSorted(_tmpDict[obj.priority], obj) - else: - _tmpDict[obj.priority] = [obj] + clsobj = getattr(imported, MODCLASS, None) + if clsobj is None: + log.error('module does not implement the required class') + continue + + modobj = clsobj() + + # module sanity check + missing = self._check_module(modobj) + if missing: + log.error('module has missing attributes: %s', str(missing)) + continue + + # skip modules that require network if it's not active + if not self._has_network and modobj.needsNetwork(): + log.error('module requires active network connection') + continue + + # skip modules that should only appear in reconfig mode + if not reconfig and modobj.reconfig: + log.info('module only available in reconfig mode') + continue + + # skip hidden modules + if not modobj.shouldAppear(): + log.info('module is hidden') + continue + + # skip empty module sets + if isinstance(modobj, ModuleSet): + modobj.loadModules(mode=reconfig) + if not obj.moduleList: + log.error('module set is empty') + continue - # Now we've loaded all the modules. Flatten the _tmpDict out into a - # single list. - keys = _tmpDict.keys() - keys.sort() + # add the module to the list + self.modlist.append(modobj) - for i in keys: - moduleList.extend(_tmpDict[i]) + # sort modules + self.modlist.sort(key=operator.attrgetter('priority')) - return moduleList + return self.modlist -- 1.7.3.2 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list