diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | installmethod.py | 80 | ||||
-rw-r--r-- | iutil.py | 105 |
3 files changed, 140 insertions, 47 deletions
@@ -3,6 +3,8 @@ * image.py (ImageInstallMethod.getSourcePath): Remove unused method. + * instalmethod.py, iutil.py: Add API documentation. + 2007-07-26 Bill Nottingham <notting@redhat.com> * anaconda.spec: Bump version diff --git a/installmethod.py b/installmethod.py index c2a3e2fae..099ee82fe 100644 --- a/installmethod.py +++ b/installmethod.py @@ -1,7 +1,7 @@ # # installmethod.py - Base class for install methods # -# Copyright 1999-2002 Red Hat, Inc. +# Copyright 1999-2007 Red Hat, Inc. # # This software may be freely redistributed under the terms of the GNU # library public license. @@ -18,19 +18,34 @@ from constants import * import logging log = logging.getLogger("anaconda") +## Raised by subclasses of InstallMethod when an error occurs copying a file. class FileCopyException(Exception): + ## The constructor. + # @param s An optional message to be added to the exception. def __init__(self, s = ""): self.args = s - +## The base installation method class. +# This is an abstract class that defines the methods that make up an +# installation method. This class should not be used except as the superclass +# for a specific method. Most methods in this class should be redefined by +# subclasses, though things like mountCD, unmountCD, ejectCD, and the cleanup +# methods may not need to be redefined. By default, most methods pass. class InstallMethod: + ## Return the list of protected partitions. + # Protected partitions are the installation source for the hard drive + # installation method. Partitions on this list may be mounted, but may + # not be formatted. + # + # @return The list of protected partitions, or an empty list otherwise. def protectedPartitions(self): return [] + ## Return a directory that can be used for writing temporary data to. + # @returns A valid temporary directory, or /tmp by default. def getTempPath(self): root = self.rootPath - pathlist = [ "/var/tmp", "/tmp", - "/." ] + pathlist = [ "/var/tmp", "/tmp", "/." ] tmppath = None for p in pathlist: if (os.access(root + p, os.X_OK)): @@ -43,54 +58,91 @@ class InstallMethod: return tmppath + ## Fetch a file from the installation source. + # @param filename The filename to fetch. + # @param callback A function to be called when the file is fetched. This + # function expects a message and size as parameters. + # @param destdir The directory where the fetched file should be put. + # @param retry How many times to attempt fetching the file. + # @return The complete path to the fetched file on the local system. def getFilename(self, filename, callback=None, destdir=None, retry=1): pass + ## Perform method-specific actions to unmount any installation media. def systemUnmounted(self): pass - def systemMounted(self, fstab, mntPoint): + ## Perform method-specific actions to mount any installation media. + # @param fsset An instance of FileSystemSet. + # @param mntPoint The root of the filesystem to mount the media onto. + def systemMounted(self, fsset, mntPoint): pass + ## Method-specific cleanup function to be called at the end of installation. + # @see doMethodComplete + # @see postAction def filesDone(self): pass + ## Remove a file if it was fetched from a remote system. + # @param fullName The full path to the file to be removed. def unlinkFilename(self, fullName): pass + ## The constructor. + # @param method The --method= parameter passed to anaconda from loader. + # @param rootpath The --rootpath= parameter passed to anaconda from loader. + # @param intf An instance of the InstallInterface class. def __init__(self, method, rootpath, intf): self.rootPath = rootpath self.intf = intf self.tree = None self.splitmethod = False + ## Get the base URI for the method. + # @return The base URI for this installation method. def getMethodUri(self): pass - def getSourcePath(self): - pass - + ## Unmount any CD media. def unmountCD(self): pass + ## Eject any CD media from the drive. def ejectCD(self): pass + ## Construct a method-specific error message. + # @param pkgname The name of the package that could not be fetched. + # @return A method-specific error message. def badPackageError(self, pkgname): pass + ## Switch CDs. + # @param mediano The CD media number to switch to. + # @param filename The file to be read that requires switching media. def switchMedia(self, mediano, filename=""): pass - # this is very very very late. it's even after kickstart %post. - # only use this if you really know what you're doing. + ## Method to be run at the very end of installation. + # + # This method is run very late. It's the last step to be run before + # showing the completion screen. Only use this if you really know what + # you're doing. + # @param anaconda An instance of the Anaconda class. + # @see filesDone + # @see doMethodComplete def postAction(self, anaconda): pass -# This handles any cleanup needed for the method. It occurs *very* late -# and is mainly used for unmounting media and ejecting the CD. If we're on -# a kickstart install, don't eject the CD since there's a command to do that -# if the user wants. +## Do method-specific cleanups. +# +# This occurs very late and is mainly used for unmounting media and ejecting +# the CD. If we're on a kickstart install, don't eject the CD since there's +# a kickstart command to do that. +# @param anaconda An instance of the Anaconda class. +# @see InstallMethod::postAction +# @see InstallMethod::filesDone def doMethodComplete(anaconda): anaconda.method.filesDone() @@ -3,7 +3,7 @@ # # Erik Troan <ewt@redhat.com> # -# Copyright 1999-2003 Red Hat, Inc. +# Copyright 1999-2007 Red Hat, Inc. # # This software may be freely redistributed under the terms of the GNU # library public license. @@ -24,6 +24,15 @@ from flags import flags import logging log = logging.getLogger("anaconda") +## Run an external program and redirect the output to a file. +# @param command The command to run. +# @param argv A list of arguments. +# @param stdin The file descriptor to read stdin from. +# @param stdout The file descriptor to redirect stdout to. +# @param stderr The file descriptor to redirect stderr to. +# @param searchPath Should command be searched for in $PATH? +# @param root The directory to chroot to before running command. +# @return The return code of command. def execWithRedirect(command, argv, stdin = 0, stdout = 1, stderr = 2, searchPath = 0, root = '/'): def chroot (): @@ -54,6 +63,13 @@ def execWithRedirect(command, argv, stdin = 0, stdout = 1, stderr = 2, return ret +## Run an external program and capture standard out. +# @param command The command to run. +# @param argv A list of arguments. +# @param stdin The file descriptor to read stdin from. +# @param stderr The file descriptor to redirect stderr to. +# @param root The directory to chroot to before running command. +# @return The output of command from stdout. def execWithCapture(command, argv, stdin = 0, stderr = 2, root='/'): def chroot(): os.chroot(root) @@ -80,6 +96,7 @@ def execWithCapture(command, argv, stdin = 0, stderr = 2, root='/'): pipe.wait() return rc +## Run a shell. def execConsole(): try: proc = subprocess.Popen(["/bin/sh"]) @@ -87,7 +104,9 @@ def execConsole(): except OSError, (errno, msg): raise RuntimeError, "Error running /bin/sh: " + msg -# return size of directory (and subdirs) in kilobytes +## Get the size of a directory and all its subdirectories. +# @param dir The name of the directory to find the size of. +# @return The size of the directory in kilobytes. def getDirSize(dir): def getSubdirSize(dir): # returns size in bytes @@ -108,7 +127,8 @@ def getDirSize(dir): return dsize return getSubdirSize(dir)/1024 -# this is in kilobytes - returns amount of RAM not used by /tmp +## Get the amount of RAM not used by /tmp. +# @return The amount of available memory in kilobytes. def memAvailable(): tram = memInstalled() @@ -118,7 +138,8 @@ def memAvailable(): return tram - ramused -# this is in kilobytes +## Get the amount of RAM installed in the machine. +# @return The amount of installed memory in kilobytes. def memInstalled(): f = open("/proc/meminfo", "r") lines = f.readlines() @@ -132,7 +153,9 @@ def memInstalled(): return int(mem) -# try to keep 2.4 kernel swapper happy! +## Suggest the size of the swap partition that will be created. +# @param quiet Should size information be logged? +# @return A tuple of the minimum and maximum swap size, in megabytes. def swapSuggestion(quiet=0): mem = memInstalled()/1024 mem = ((mem/16)+1)*16 @@ -155,9 +178,8 @@ def swapSuggestion(quiet=0): return (minswap, maxswap) - -# this is a mkdir that won't fail if a directory already exists and will -# happily make all of the directories leading up to it. +## Create a directory path. Don't fail if the directory already exists. +# @param dir The directory path to create. def mkdirChain(dir): try: os.makedirs(dir, 0755) @@ -167,9 +189,11 @@ def mkdirChain(dir): return except: pass - + log.error("could not create directory %s: %s" % (dir, msg)) +## Get the total amount of swap memory. +# @return The total amount of swap memory in kilobytes, or 0 if unknown. def swapAmount(): f = open("/proc/meminfo", "r") lines = f.readlines() @@ -180,11 +204,14 @@ def swapAmount(): fields = string.split(l) return int(fields[1]) return 0 - -def copyDeviceNode(src, dest): - """Copies the device node at src to dest by looking at the type of device, - major, and minor of src and doing a new mknod at dest""" +## Copy a device node. +# Copies a device node by looking at the device type, major and minor device +# numbers, and doing a mknod on the new device name. +# +# @param src The name of the source device node. +# @param dest The name of the new device node to create. +def copyDeviceNode(src, dest): filestat = os.lstat(src) mode = filestat[stat.ST_MODE] if stat.S_ISBLK(mode): @@ -197,7 +224,8 @@ def copyDeviceNode(src, dest): os.mknod(dest, mode | type, filestat.st_rdev) -# make the device-mapper control node +## Create the device mapper control node. +# @param root The root of the filesystem to create the device node in. def makeDMNode(root="/"): major = minor = None @@ -226,12 +254,12 @@ def makeDMNode(root="/"): except: pass -# make some miscellaneous character device nodes +## Make some miscellaneous character device nodes. def makeCharDeviceNodes(): for dev in ["input/event0", "input/event1", "input/event2", "input/event3"]: isys.makeDevInode(dev, "/dev/%s" % (dev,)) -# make the device nodes for all of the drives on the system +## Make the device nodes for all the drives in the system. def makeDriveDeviceNodes(): hardDrives = isys.hardDriveDict() for drive in hardDrives.keys(): @@ -275,9 +303,11 @@ def makeDriveDeviceNodes(): for loopMinor in range(0, 8): loop = "loop%d" %(loopMinor,) isys.makeDevInode(loop, "/dev/%s" %(loop,)) - -# this is disgusting and I feel very dirty + +## Determine if the hardware supports iSeries storage devices. +# @return 1 if so, 0 otherwise. def hasiSeriesNativeStorage(): + # this is disgusting and I feel very dirty if rhpl.getArch() != "ppc": return @@ -293,12 +323,12 @@ def hasiSeriesNativeStorage(): return 0 -# return the ppc machine variety type +## Get the PPC machine variety type. +# @return The PPC machine type, or 0 if not PPC. def getPPCMachine(): - if rhpl.getArch() != "ppc": return 0 - + machine = rhpl.getPPCMachine() if machine is None: log.warning("Unable to find PowerPC machine type") @@ -307,10 +337,11 @@ def getPPCMachine(): return machine -# return the pmac machine id +## Get the powermac machine ID. +# @return The powermac machine id, or 0 if not PPC. def getPPCMacID(): machine = None - + if rhpl.getArch() != "ppc": return 0 if getPPCMachine() != "PMac": @@ -328,11 +359,12 @@ def getPPCMacID(): log.warning("No Power Mac machine id") return 0 -# return the pmac generation +## Get the powermac generation. +# @return The powermac generation, or 0 if not powermac. def getPPCMacGen(): # XXX: should NuBus be here? pmacGen = ['OldWorld', 'NewWorld', 'NuBus'] - + if rhpl.getArch() != "ppc": return 0 if getPPCMachine() != "PMac": @@ -357,7 +389,8 @@ def getPPCMacGen(): log.warning("Unknown Power Mac generation: %s" %(gen,)) return 0 -# return if pmac machine is it an iBook/PowerBook +## Determine if the hardware is an iBook or PowerBook +# @return 1 if so, 0 otherwise. def getPPCMacBook(): if rhpl.getArch() != "ppc": return 0 @@ -374,6 +407,8 @@ def getPPCMacBook(): return 0 cell = None +## Determine if the hardware is the Cell platform. +# @return True if so, False otherwise. def isCell(): global cell if cell is not None: @@ -394,12 +429,13 @@ def isCell(): return cell mactel = None -# return True if this is one of the Intel-based Apple Macs +## Determine if the hardware is an Intel-based Apple Mac. +# @return True if so, False otherwise. def isMactel(): global mactel if mactel is not None: return mactel - + if rhpl.getArch() not in ("x86_64", "i386"): mactel = False elif not os.path.exists("/usr/sbin/dmidecode"): @@ -414,6 +450,8 @@ def isMactel(): return mactel efi = None +## Determine if the hardware supports EFI. +# @return True if so, False otherwise. def isEfi(): global efi if efi is not None: @@ -427,9 +465,9 @@ def isEfi(): return efi +## Extract the CPU feature flags from /proc/cpuinfo +# @return A list of CPU feature flags, or an empty list on error. def cpuFeatureFlags(): - """Convenience function to get CPU feature flags from /proc/cpuinfo.""" - if rhpl.getArch() not in ("i386", "x86_64"): return False f = open("/proc/cpuinfo", "r") @@ -447,6 +485,8 @@ def cpuFeatureFlags(): return [] +## Generate the /etc/rpm/platform and /etc/rpm/macros files. +# @param root The root of the filesystem to create the files in. def writeRpmPlatform(root="/"): import rhpl.arch @@ -464,8 +504,8 @@ def writeRpmPlatform(root="/"): myarch = flags.targetarch # now make the current install believe it, too - rhpl.arch.canonArch = myarch - + rhpl.arch.canonArch = myarch + f = open("%s/etc/rpm/platform" %(root,), 'w+') f.write("%s-redhat-linux\n" %(myarch,)) f.close() @@ -496,4 +536,3 @@ def writeRpmPlatform(root="/"): f.write("%_prefer_color 1\n") f.close() - |