# # installclass.py: This is the prototypical class for workstation, server, and # kickstart installs. The interface to BaseInstallClass is *public* -- # ISVs/OEMs can customize the install by creating a new derived type of this # class. # # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 # Red Hat, Inc. All rights reserved. # # 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. # # 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. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # from distutils.sysconfig import get_python_lib import os, sys, iutil import isys import string import imputil import types from constants import * from product import * from blivet.partspec import * from blivet.devicelibs import swap from blivet.platform import platform import gettext _ = lambda x: gettext.ldgettext("anaconda", x) import logging log = logging.getLogger("anaconda") from flags import flags class BaseInstallClass(object): # default to not being hidden hidden = 0 pixmap = None showMinimal = 1 showLoginChoice = 0 _description = "" _descriptionFields = () name = "base" pkgstext = "" # default to showing the upgrade option showUpgrade = True bootloaderTimeoutDefault = None bootloaderExtraArgs = [] _l10n_domain = None # list of of (txt, grplist) tuples for task selection screen tasks = [] # don't select this class by default default = 0 # by default, place this under the "install" category; it gets it's # own toplevel category otherwise parentClass = ( _("Install on System"), "install.png" ) def _get_description(self): return _(self._description) % self._descriptionFields description = property(_get_description) @property def l10n_domain(self): if self._l10n_domain is None: raise RuntimeError("Localization domain for '%s' not set." % self.name) return self._l10n_domain # modifies the uri from installmethod.getMethodUri() to take into # account any installclass specific things including multiple base # repositories. takes a string or list of strings, returns a dict # with string keys and list values {%repo: %uri_list} def getPackagePaths(self, uri): if not type(uri) == types.ListType: uri = [uri,] return {'base': uri} def setPackageSelection(self, anaconda): pass def getBackend(self): # The default is to return None here, which means anaconda should # use live or yum (whichever can be detected). This method is # provided as a way for other products to specify their own. return None def setDefaultPartitioning(self, storage): autorequests = [PartSpec(mountpoint="/", fstype=storage.defaultFSType, size=1024, maxSize=50*1024, grow=True, btr=True, lv=True, encrypted=True), PartSpec(mountpoint="/home", fstype=storage.defaultFSType, size=500, grow=True, requiredSpace=50*1024, btr=True, lv=True, encrypted=True)] bootreqs = platform.setDefaultPartitioning() if bootreqs: autorequests.extend(bootreqs) swp = swap.swapSuggestion() autorequests.append(PartSpec(fstype="swap", size=swp, grow=False, lv=True, encrypted=True)) for autoreq in autorequests: if autoreq.fstype is None: if autoreq.mountpoint == "/boot": autoreq.fstype = storage.defaultBootFSType else: autoreq.fstype = storage.defaultFSType storage.autoPartitionRequests = autorequests def configure(self, anaconda): anaconda.bootloader.timeout = self.bootloaderTimeoutDefault anaconda.bootloader.boot_args.update(self.bootloaderExtraArgs) def versionMatches(self, oldver): pass def productMatches(self, oldprod): pass def productUpgradable(self, arch, oldprod, oldver): """ Return a tuple with: (Upgradable True|False, dict of tests and status) The dict has True|False for: product, version, arch tests. """ def archesEq(a, b): import re if re.match("i.86", a) and re.match("i.86", b): return True else: return a == b result = { "product" : self.productMatches(oldprod), "version" : self.versionMatches(oldver), "arch" : archesEq(arch, productArch) } return (all(result.values()), result) # sets default ONBOOT values and updates ksdata accordingly def setNetworkOnbootDefault(self, ksdata): pass def __init__(self): pass allClasses = [] allClasses_hidden = [] # returns ( className, classObject, classLogo ) tuples def availableClasses(showHidden=0): global allClasses global allClasses_hidden def _ordering(first, second): ((name1, obj, logo), priority1) = first ((name2, obj, logo), priority2) = second if priority1 < priority2: return -1 elif priority1 > priority2: return 1 if name1 < name2: return -1 elif name1 > name2: return 1 return 0 if not showHidden: if allClasses: return allClasses else: if allClasses_hidden: return allClasses_hidden path = [] env_path = [] if "ANACONDA_INSTALL_CLASSES" in os.environ: env_path += os.environ["ANACONDA_INSTALL_CLASSES"].split(":") for dir in env_path + ["installclasses", "/tmp/updates/pyanaconda/installclasses", "/tmp/product/pyanaconda/installclasses", "%s/pyanaconda/installclasses" % get_python_lib(plat_specific=1) ]: if os.access(dir, os.R_OK): path.append(dir) # append the location of installclasses to the python path so we # can import them sys.path = path + sys.path files = [] for p in reversed(path): files += os.listdir(p) done = {} list = [] for file in files: if file[0] == '.': continue if len (file) < 4: continue if file[-3:] != ".py" and file[-4:-1] != ".py": continue mainName = string.split(file, ".")[0] if done.has_key(mainName): continue done[mainName] = 1 try: found = imputil.imp.find_module(mainName) except ImportError as e: log.warning ("module import of %s failed: %s" % (mainName, sys.exc_type)) continue try: loaded = imputil.imp.load_module(mainName, found[0], found[1], found[2]) obj = loaded.InstallClass if obj.__dict__.has_key('sortPriority'): sortOrder = obj.sortPriority else: sortOrder = 0 if obj.hidden == 0 or showHidden == 1: list.append(((obj.name, obj, obj.pixmap), sortOrder)) except ImportError as e: log.warning ("module import of %s failed: %s" % (mainName, sys.exc_type)) if flags.debug: raise else: continue list.sort(_ordering) for (item, priority) in list: if showHidden: allClasses_hidden.append(item) else: allClasses.append(item) if showHidden: return allClasses_hidden else: return allClasses def getBaseInstallClass(): # figure out what installclass we should base on. allavail = availableClasses(showHidden = 1) avail = availableClasses(showHidden = 0) if len(avail) == 1: (cname, cobject, clogo) = avail[0] log.info("using only installclass %s" %(cname,)) elif len(allavail) == 1: (cname, cobject, clogo) = allavail[0] log.info("using only installclass %s" %(cname,)) # Use the highest priority install class if more than one found. elif len(avail) > 1: (cname, cobject, clogo) = avail.pop() log.info('%s is the highest priority installclass, using it' % cname) elif len(allavail) > 1: (cname, cobject, clogo) = allavail.pop() log.info('%s is the highest priority installclass, using it' % cname) # Default to the base installclass if nothing else is found. else: raise RuntimeError, "Unable to find an install class to use!!!" return cobject baseclass = getBaseInstallClass() # we need to be able to differentiate between this and custom class DefaultInstall(baseclass): def __init__(self): baseclass.__init__(self)