[firstboot 01/13] Rewritten loader

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 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


[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux