You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qubes-installer-qubes-os/firstboot/loader.py

160 lines
5.6 KiB

#
# Chris Lumens <clumens@redhat.com>
#
# Copyright 2007 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.
#
# 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.
#
from firstboot.constants import *
from firstboot.module import Module
from firstboot.moduleset import ModuleSet
import ethtool
import glob
import imputil
import logging
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 %s:\n%s") % (module, str(e)))
continue
except Exception as e:
logging.error(_("Error loading module %s:\n%s") % (module, 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()
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 %s does not contain the required attribute %s; skipping.") % (module, 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)
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]
# Now we've loaded all the modules. Flatten the _tmpDict out into a
# single list.
keys = _tmpDict.keys()
keys.sort()
for i in keys:
moduleList.extend(_tmpDict[i])
return moduleList