diff options
author | Matt Wilson <msw@redhat.com> | 2001-06-20 04:39:53 +0000 |
---|---|---|
committer | Matt Wilson <msw@redhat.com> | 2001-06-20 04:39:53 +0000 |
commit | c4249bbe06e028e95f6514adb7f90ae11ab3b43b (patch) | |
tree | 408350beb14885893b86938d27a46688c4986003 | |
parent | 8a566ec58b79dc8c583a4610a27a5182b31bacb8 (diff) | |
download | anaconda-c4249bbe06e028e95f6514adb7f90ae11ab3b43b.tar.gz anaconda-c4249bbe06e028e95f6514adb7f90ae11ab3b43b.tar.xz anaconda-c4249bbe06e028e95f6514adb7f90ae11ab3b43b.zip |
merge dispatch to HEAD
-rw-r--r-- | autopart.py | 357 | ||||
-rw-r--r-- | bootloader.py | 407 | ||||
-rw-r--r-- | desktop.py | 51 | ||||
-rw-r--r-- | firewall.py | 89 | ||||
-rw-r--r-- | flags.py | 25 | ||||
-rw-r--r-- | instdata.py | 143 | ||||
-rw-r--r-- | network.py | 256 | ||||
-rw-r--r-- | packages.py | 797 | ||||
-rw-r--r-- | timezone.py | 44 | ||||
-rw-r--r-- | users.py | 220 | ||||
-rw-r--r-- | videocard.py | 369 | ||||
-rw-r--r-- | xf86config.py | 485 |
12 files changed, 2980 insertions, 263 deletions
diff --git a/autopart.py b/autopart.py new file mode 100644 index 000000000..471801556 --- /dev/null +++ b/autopart.py @@ -0,0 +1,357 @@ +# +# autopart.py - auto partitioning logic +# +# Jeremy Katz <katzj@redhat.com> +# +# Copyright 2001 Red Hat, Inc. +# +# This software may be freely redistributed under the terms of the GNU +# library public license. +# +# You should have received a copy of the GNU Library Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import parted +import math +from fsset import * +from partitioning import * + +PARTITION_FAIL = -1 +PARTITION_SUCCESS = 0 + +def findFreespace(diskset): + free = {} + for drive in diskset.disks.keys(): + disk = diskset.disks[drive] + free[drive] = [] + part = disk.next_partition() + while part: + if part.type & parted.PARTITION_FREESPACE: + free[drive].append(part) + part = disk.next_partition(part) + return free + + +def bestPartType(disk): + numPrimary = len(get_primary_partitions(disk)) + if numPrimary == 4: + # raise an error? + return PARTITION_FAIL + if numPrimary == 3 and not disk.extended_partition: + return parted.PARTITION_EXTENDED + return parted.PARTITION_PRIMARY + + +# first step of partitioning voodoo +# partitions with a specific start and end cylinder requested are +# placed where they were asked to go +def fitConstrained(diskset, requests): + for request in requests.requests: + if request.type != REQUEST_NEW: + continue + if request.drive and (request.start != None) and request.end: + fsType = request.fstype.getPartedFileSystemType() + disk = diskset.disks[request.drive] + if not disk: # this shouldn't happen + raise PartitioningError, "Selected to put partition on non-existent disk!" + + startSec = start_cyl_to_sector(disk.dev, request.start) + endSec = end_cyl_to_sector(disk.dev, request.end) + + # XXX need to check overlaps properly here + if startSec < 0: + startSec = 0L + + if disk.type.check_feature(parted.DISK_TYPE_EXTENDED) and disk.extended_partition: + + if (disk.extended_part.geom.start < startSec) and (disk.extended_part.geom.end > endSec): + partType = parted.PARTITION_LOGICAL + else: + # XXX need a better way to do primary vs logical stuff + ret = bestPartType(disk) + if ret == PARTITION_FAIL: + return ret + if ret == parted.PARTITION_PRIMARY: + partType = parted.PARTITION_PRIMARY + elif ret == parted.PARTITION_EXTENDED: + newp = disk.partition_new(parted.PARTITION_EXTENDED, None, startSec, endSec) + constraint = disk.constraint_any() + disk.maximize_partition (newp, constraint) + partType = parted.PARTITION_LOGICAL + else: # shouldn't get here + raise PartitioningError, "Impossible partition type to create" + newp = disk.partition_new (partType, fsType, startSec, endSec) + constraint = disk.constraint_any () + try: + disk.add_partition (newp, constraint) + status = 1 + except parted.error, msg: + return PARTITION_FAIL +# raise PartitioningError, msg + for flag in request.fstype.getPartedPartitionFlags(): + if not newp.is_flag_available(flag): + raise PartitioningError, ("requested FileSystemType needs " + "a flag that is not available.") + newp.set_flag(flag, 1) + request.device = PartedPartitionDevice(newp).getDevice() + request.realDevice = request.device + request.currentDrive = drive + + return PARTITION_SUCCESS + + +# fit partitions of a specific size with or without a specific disk +# into the freespace +def fitSized(diskset, requests): + todo = {} + + for request in requests.requests: + if request.type != REQUEST_NEW: + continue + if request.realDevice: + continue + if not request.drive: + request.drive = diskset.disks.keys() + if type(request.drive) != type([]): + request.drive = [ request.drive ] + if not todo.has_key(len(request.drive)): + todo[len(request.drive)] = [ request ] + else: + todo[len(request.drive)].append(request) + + + number = todo.keys() + number.sort() + free = findFreespace(diskset) + + for num in number: + for request in todo[num]: + largestPart = (0, None) + request.drive.sort() + for drive in request.drive: + disk = diskset.disks[drive] + + for part in free[drive]: + partSize = getPartSize(part) + if partSize >= request.requestSize and partSize > largestPart[0]: + largestPart = (partSize, part) + + if not largestPart[1]: + return PARTITION_FAIL +# raise PartitioningError, "Can't fulfill request for partition: \n%s" %(request) + + freespace = largestPart[1] + disk = freespace.geom.disk + startSec = freespace.geom.start + 1 + endSec = startSec + ((request.requestSize * 1024L * 1024L) / disk.dev.sector_size) - 1 + + if endSec > freespace.geom.end: + endSec = freespace.geom.end + if startSec < freespace.geom.start: + startSec = freespace.geom.start + + if freespace.type & parted.PARTITION_LOGICAL: + partType = parted.PARTITION_LOGICAL + else: + # XXX need a better way to do primary vs logical stuff + ret = bestPartType(disk) + if ret == PARTITION_FAIL: + return ret + print ret + if ret == parted.PARTITION_PRIMARY: + partType = parted.PARTITION_PRIMARY + elif ret == parted.PARTITION_EXTENDED: + newp = disk.partition_new(parted.PARTITION_EXTENDED, None, startSec, endSec) + constraint = disk.constraint_any() + disk.add_partition(newp, constraint) + disk.maximize_partition (newp, constraint) + partType = parted.PARTITION_LOGICAL + else: # shouldn't get here + raise PartitioningError, "Impossible partition to create" + + fsType = request.fstype.getPartedFileSystemType() + + newp = disk.partition_new (partType, fsType, startSec, endSec) + constraint = disk.constraint_any () + try: + disk.add_partition (newp, constraint) + except parted.error, msg: + raise PartitioningError, msg + for flag in request.fstype.getPartedPartitionFlags(): + if not newp.is_flag_available(flag): + raise PartitioningError, ("requested FileSystemType needs " + "a flag that is not available.") + newp.set_flag(flag, 1) + request.device = PartedPartitionDevice(newp).getDevice() + drive = newp.geom.disk.dev.path[5:] + request.currentDrive = drive + free[drive].remove(freespace) + part = disk.next_partition(newp) + if part and part.type & parted.PARTITION_FREESPACE: + free[drive].append(part) + return PARTITION_SUCCESS + + +# grow partitions +def growParts(diskset, requests): +# print "growing" + newRequest = requests.copy() + + free = findFreespace(diskset) + freeSize = {} + + # find out the amount of free space on each drive + for key in free.keys(): + if len(free[key]) == 0: + del free[key] + continue + freeSize[key] = 0 + for part in free[key]: + freeSize[key] = freeSize[key] + getPartSize(part) + + # find growable partitions and find out the size of the growable parts + growable = {} + growSize = {} + for request in newRequest.requests: + if request.grow: + if not growable.has_key(request.currentDrive): + growable[request.currentDrive] = [ request ] + growSize[request.currentDrive] = request.size + else: + growable[request.currentDrive].append(request) + growSize[request.currentDrive] = growSize[request.currentDrive] + request.requestSize + + # there aren't any drives with growable partitions, this is easy! + if not growable.keys(): + return PARTITION_SUCCESS + + for drive in growable.keys(): + # no free space on this drive, so can't grow any of its parts + if not free.has_key(drive): + continue + + # process each request + for request in growable[drive]: + percent = request.size / (growSize[drive] * 1.0) + + request.drive = request.currentDrive + + max = int(percent * freeSize[drive]) + request.size + if max > request.maxSize: + max = request.maxSize + + min = request.requestSize + diff = max - min + cur = max - (diff / 2) + lastDiff = 0 + + # binary search + while (max != min) and (lastDiff != diff): + request.requestSize = cur + + # try adding + ret = processPartitioning(diskset, newRequest) +# print diskset.diskState() + + if ret == PARTITION_SUCCESS: + min = cur + else: + max = cur + + lastDiff = diff + diff = max - min + cur = max - (diff / 2) + + + # we could have failed on the last try, in which case we + # should go back to the smaller size + if ret == PARTITION_FAIL: + request.requestSize = min + # XXX this can't fail (?) + processPartitioning(diskset, newRequest) + + return PARTITION_SUCCESS + + +def deletePart(diskset, delete): + disk = diskset.disks[delete.drive] + part = disk.next_partition() + while part: + if part.geom.start == delete.start and part.geom.end == delete.end: + disk.delete_partition(part) + return + part = disk.next_partition(part) + + +def processPartitioning(diskset, requests): + # reset disk to original state + diskset.refreshDevices() + for request in requests.requests: + if request.type == REQUEST_NEW: + request.device = None +# request.requestSize = request.size + + # XXX - handle delete requests + for delete in requests.deletes: + deletePart(diskset, delete) +# diskset.deleteAllPartitions() + + # sort requests by size + requests.sortRequests() + + # partitioning algorithm in simplistic terms + # + # we want to allocate partitions such that the most specifically + # spelled out partitions get what they want first in order to ensure + # they don't get preempted. first conflict found returns an error + # which must be handled by the caller by saying that the partition + # add is impossible (XXX can we get an impossible situation after delete?) + # + # potentially confusing terms + # type == primary vs logical + # + # order to allocate: + # start and end cylinders given (note that start + size & !grow is equivalent) + # drive, partnum + # drive, type + # drive + # priority partition (/boot or /) + # size + + ret = fitConstrained(diskset, requests) + if ret == PARTITION_FAIL: + return ret + + ret = fitSized(diskset, requests) + if ret == PARTITION_FAIL: + return ret + + for request in requests.requests: + if request.type != REQUEST_RAID and not request.device: +# return PARTITION_FAIL + raise PartitioningError, "Unsatisfied partition request\n%s" %(request) + + return PARTITION_SUCCESS + +## print "disk layout after everything is done" +## print diskset.diskState() + + +def doPartitioning(diskset, requests): + for request in requests.requests: + request.requestSize = request.size + + ret = processPartitioning(diskset, requests) + + if ret == PARTITION_FAIL: + raise PartitioningError, "Partitioning failed" + + ret = growParts(diskset, requests) + + if ret == PARTITION_SUCCESS: + return + + raise PartitioningError, "Growing partitions failed" + diff --git a/bootloader.py b/bootloader.py new file mode 100644 index 000000000..8576ff370 --- /dev/null +++ b/bootloader.py @@ -0,0 +1,407 @@ +import isys +import partitioning +from translate import _ +from lilo import LiloConfigFile +import os +import language +from flags import flags +import iutil +import string +from log import log + +initrdsMade = {} + +class KernelArguments: + + def get(self): + return self.args + + def set(self, args): + self.args = args + + def __init__(self): + cdrw = isys.ideCdRwList() + str = "" + for device in cdrw: + if str: str = str + " " + str = str + ("%s=ide-scsi" % device) + + self.args = str + +class BootImages: + + # returns dictionary of (label, devtype) pairs indexed by device + def getImages(self): + # return a copy so users can modify it w/o affecting us + + dict = {} + for key in self.images.keys(): + dict[key] = self.images[key] + + return dict + + def setImageLabel(self, dev, label): + self.images[dev] = (label, self.images[dev][1]) + + # default is a device + def setDefault(self, default): + self.default = default + + def getDefault(self): + return self.default + + def setup(self, diskSet, fsset): + devices = {} + devs = availableBootDevices(diskSet, fsset) + for (dev, type) in devs: + devices[dev] = 1 + + # These partitions have disappeared + for dev in self.images.keys(): + if devices.has_key(dev): del self.images[dev] + + # These have appeared + for (dev, type) in devs: + if not self.images.has_key(dev): + self.images[dev] = (None, type) + + if not self.images.has_key(self.default): + entry = fsset.getEntryByMountPoint('/') + self.default = entry.device.getDevice() + (label, type) = self.images[self.default] + if not label: + self.images[self.default] = ("Red Hat Linux 7.2", type) + + def __init__(self): + self.default = None + self.images = {} + +class x86BootloaderInfo: + + def getDevice(self): + return self.device + + def setDevice(self, device): + self.device = device + + def setUseGrub(self, val): + self.useGrubVal = val + + def useGrub(self): + return self.useGrubVal + + def writeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList, + defaultDev, justConfigFile): + images = bl.images.getImages() + rootDev = fsset.getEntryByMountPoint("/").device.getDevice() + grubRootDev = grubbyPartitionName(rootDev) + + cf = '/boot/grub/grub.conf' + perms = 0644 + if os.access (instRoot + cf, os.R_OK): + perms = os.stat(instRoot + cf)[0] & 0777 + os.rename(instRoot + cf, + instRoot + cf + '.rpmsave') + + f = open(instRoot + cf, "w+") + + + bootDev = fsset.getEntryByMountPoint("/boot") + grubPath = "/grub" + cfPath = "" + if not bootDev: + bootDev = fsset.getEntryByMountPoint("/") + grubPath = "/boot/grub" + cfPath = "/boot" + else: + f.write ("# NOTICE: You have a /boot partition. This means that\n") + f.write ("# all kernel paths are relative to /boot/\n") + + bootDev = bootDev.device.getDevice() + + f.write('default=0\n') + f.write('timeout=30\n') + + for (label, version) in kernelList: + kernelTag = "-" + version + kernelFile = cfPath + "/vmlinuz" + kernelTag + + initrd = makeInitrd (kernelTag, instRoot) + + f.write('title Red Hat Linux 7.2 (%s)\n' % version) + f.write('\troot %s\n' % grubRootDev) + f.write('\tkernel %s ro root=/dev/%s' % (kernelFile, rootDev)) + if self.args.get(): + f.write(' %s' % self.args.get()) + f.write('\n') + + if os.access (instRoot + initrd, os.R_OK): + f.write('\tinitrd %s\n' % (initrd[len(cfPath):], )) + + f.close() + + part = grubbyPartitionName(bootDev) + prefix = grubbyPartitionName(bootDev) + "/" + grubPath + cmd = "root %s\ninstall %s/i386-pc/stage1 d (%s) %s/i386-pc/stage2 p %s%s/grub.conf" % \ + (part, grubPath, grubbyDiskName(bl.getDevice()), grubPath, + part, grubPath) + + log("GRUB command %s", cmd) + + if not justConfigFile: + p = os.pipe() + os.write(p[1], cmd + '\n') + os.close(p[1]) + + iutil.execWithRedirect('/sbin/grub' , + [ "grub", "--batch" ], stdin = p[0], + stdout = "/dev/tty5", stderr = "/dev/tty5", + root = instRoot) + os.close(p[0]) + + return None + + def writeLilo(self, instRoot, fsset, bl, langs, kernelList, chainList, + defaultDev, justConfigFile): + images = bl.images.getImages() + + # on upgrade read in the lilo config file + lilo = LiloConfigFile () + perms = 0644 + if os.access (instRoot + '/etc/lilo.conf', os.R_OK): + perms = os.stat(instRoot + '/etc/lilo.conf')[0] & 0777 + lilo.read (instRoot + '/etc/lilo.conf') + os.rename(instRoot + '/etc/lilo.conf', + instRoot + '/etc/lilo.conf.rpmsave') + + # Remove any invalid entries that are in the file; we probably + # just removed those kernels. + for label in lilo.listImages(): + (fsType, sl) = lilo.getImage(label) + if fsType == "other": continue + + if not os.access(instRoot + sl.getPath(), os.R_OK): + lilo.delImage(label) + + liloTarget = bl.getDevice() + + lilo.addEntry("boot", '/dev/' + liloTarget, replace = 0) + lilo.addEntry("map", "/boot/map", replace = 0) + lilo.addEntry("install", "/boot/boot.b", replace = 0) + lilo.addEntry("prompt", replace = 0) + lilo.addEntry("timeout", "50", replace = 0) + message = "/boot/message" + for lang in language.expandLangs(langs.getDefault()): + fn = "/boot/message." + lang + if os.access(instRoot + fn, os.R_OK): + message = fn + break + + lilo.addEntry("message", message, replace = 0) + + if not lilo.testEntry('lba32') and not lilo.testEntry('linear'): + lilo.addEntry("linear", replace = 0) + + rootDev = fsset.getEntryByMountPoint("/").device.getDevice() + if not rootDev: + raise RuntimeError, "Installing lilo, but there is no root device" + + if rootDev == defaultDev: + lilo.addEntry("default", kernelList[0][0]) + else: + lilo.addEntry("default", otherList[0][0]) + + for (label, version) in kernelList: + kernelTag = "-" + version + kernelFile = "/boot/vmlinuz" + kernelTag + + try: + lilo.delImage(label) + except IndexError, msg: + pass + + sl = LiloConfigFile(imageType = "image", path = kernelFile) + + initrd = makeInitrd (kernelTag, instRoot) + + sl.addEntry("label", label) + if os.access (instRoot + initrd, os.R_OK): + sl.addEntry("initrd", initrd) + + sl.addEntry("read-only") + sl.addEntry("root", '/dev/' + rootDev) + + if self.args.get(): + sl.addEntry('append', '"%s"' % self.args.get()) + + lilo.addImage (sl) + + for (label, device) in chainList: + try: + (fsType, sl) = lilo.getImage(label) + lilo.delImage(label) + except IndexError: + sl = LiloConfigFile(imageType = "other", path = device) + sl.addEntry("optional") + + sl.addEntry("label", label) + lilo.addImage (sl) + + # Sanity check #1. There could be aliases in sections which conflict + # with the new images we just created. If so, erase those aliases + imageNames = {} + for label in lilo.listImages(): + imageNames[label] = 1 + + for label in lilo.listImages(): + (fsType, sl) = lilo.getImage(label) + if sl.testEntry('alias'): + alias = sl.getEntry('alias') + if imageNames.has_key(alias): + sl.delEntry('alias') + imageNames[alias] = 1 + + # Sanity check #2. If single-key is turned on, go through all of + # the image names (including aliases) (we just built the list) and + # see if single-key will still work. + if lilo.testEntry('single-key'): + singleKeys = {} + turnOff = 0 + for label in imageNames.keys(): + l = label[0] + if singleKeys.has_key(l): + turnOff = 1 + singleKeys[l] = 1 + if turnOff: + lilo.delEntry('single-key') + + lilo.write(instRoot + "/etc/lilo.conf", perms = perms) + + if not justConfigFile: + # throw away stdout, catch stderr + str = iutil.execWithCapture(instRoot + '/sbin/lilo' , + [ "lilo", "-r", instRoot ], + catchfd = 2, closefd = 1) + else: + str = "" + + return str + + def write(self, instRoot, fsset, bl, langs, kernelList, chainList, + defaultDev, justConfig): + if self.useGrubVal: + str = self.writeGrub(instRoot, fsset, bl, langs, kernelList, + chainList, defaultDev, justConfig) + else: + str = self.writeLilo(instRoot, fsset, bl, langs, kernelList, + chainList, defaultDev, justConfig) + + + def __init__(self): + self.args = KernelArguments() + self.images = BootImages() + self.useGrubVal = 1 # use lilo otherwise + self.device = None + +def availableBootDevices(diskSet, fsset): + devs = [] + foundDos = 0 + for (dev, type) in diskSet.partitionTypes(): + if type == 'FAT' and not foundDos: + foundDos = 1 + isys.makeDevInode(dev, '/tmp/' + dev) + + try: + bootable = isys.checkBoot('/tmp/' + dev) + devs.append((dev, type)) + except: + pass + elif type == 'ntfs' or type =='hpfs': + devs.append((dev, type)) + + devs.append((fsset.getEntryByMountPoint('/').device.getDevice(), 'ext2')) + + devs.sort() + + return devs + +def partitioningComplete(dispatch, bl, fsset, diskSet): + choices = fsset.bootloaderChoices(diskSet) + if not choices: + dispatch.skipStep("instbootloader") + else: + dispatch.skipStep("instbootloader", skip = 0) + + bl.images.setup(diskSet, fsset) + +def writeBootloader(intf, instRoot, fsset, bl, langs, comps): + justConfigFile = not flags.setupFilesystems + + w = intf.waitWindow(_("Bootloader"), _("Installing bootloader...")) + + kernelList = [] + otherList = [] + rootDev = fsset.getEntryByMountPoint('/').device.getDevice() + defaultDev = bl.images.getDefault() + + for (dev, (label, type)) in bl.images.getImages().items(): + if dev == rootDev: + kernelLabel = label + elif dev == defaultDev: + otherList = [(label, dev)] + otherList + else: + otherList.append(label, dev) + + plainLabelUsed = 0 + for (version, nick) in comps.kernelVersionList(): + if plainLabelUsed: + kernelList.append(kernelLabel + "-" + nick, version) + else: + kernelList.append(kernelLabel, version) + plainLabelUsed = 1 + + bl.write(instRoot, fsset, bl, langs, kernelList, otherList, defaultDev, + justConfigFile) + + w.pop() + +def makeInitrd (kernelTag, instRoot): + global initrdsMade + + initrd = "/boot/initrd%s.img" % (kernelTag, ) + + if not initrdsMade.has_key(initrd) and flags.setupFilesystems: + iutil.execWithRedirect("/sbin/mkinitrd", + [ "/sbin/mkinitrd", + "--ifneeded", + "-f", + initrd, + kernelTag[1:] ], + stdout = None, stderr = None, searchPath = 1, + root = instRoot) + initrdsMade[kernelTag] = 1 + + return initrd + +def grubbyDiskName(name): + drives = isys.hardDriveDict().keys() + drives.sort (isys.compareDrives) + + return "hd%d" % drives.index(name) + +def grubbyPartitionName(dev): + cut = -1 + if dev[-2] in string.digits: + cut = -2 + + partNum = int(dev[cut:]) - 1 + name = dev[:cut] + + # hack off the trailing 'p' from /dev/cciss/*, for example + if name[-1] == 'p': + for letter in name: + if letter not in string.letters and letter != "/": + name = name[:-1] + break + + return "(%s,%d)" % (grubbyDiskName(name), partNum) diff --git a/desktop.py b/desktop.py new file mode 100644 index 000000000..4ab0caa92 --- /dev/null +++ b/desktop.py @@ -0,0 +1,51 @@ +import string +import kudzu +import iutil +import isys +from log import log + +class Desktop: +# +# This class represents the default desktop to run and the default runlevel +# to start in +# + + def setDefaultDesktop(self, desktop): + self.desktop = desktop + + def setDefaultRunLevel(self, runlevel): + if str(runlevel) != "3" and str(runlevel) != "5": + raise RuntimeError, "Desktop::setDefaultRunLevel() - Must specify runlevel as 3 or 5!" + self.runlevel = runlevel + + def getDefaultDesktop(self): + return self.desktop + + def getDefaultRunLevel(self): + return self.runlevel + + def __init__ (self): + self.desktop = None + self.runlevel = 3 + + def write (self, instPath): + # + # XXX + # + return + + try: + inittab = open (instPath + '/etc/inittab', 'r') + except IOError: + log ("WARNING, there is no inittab, bad things will happen!") + return + lines = inittab.readlines () + inittab.close () + inittab = open (instPath + '/etc/inittab', 'w') + for line in lines: + if len (line) > 3 and line[:3] == "id:": + fields = string.split (line, ':') + fields[1] = str (self.runlevel) + line = string.join (fields, ':') + inittab.write (line) + inittab.close () diff --git a/firewall.py b/firewall.py new file mode 100644 index 000000000..00f3c819c --- /dev/null +++ b/firewall.py @@ -0,0 +1,89 @@ +import os +import iutil +import string +from log import log +from flags import flags + +class Firewall: + def __init__ (self): + self.enabled = -1 + self.ssh = 0 + self.telnet = 0 + self.smtp = 0 + self.http = 0 + self.ftp = 0 + self.portlist = "" + self.ports = [] + self.policy = 0 + self.dhcp = 0 + self.trustdevs = [] + + def writeKS(self, f): + f.write("firewall") + + if self.enabled > 0: + for arg in self.getArgList(): + f.write(" " + arg) + else: + f.write(" --disabled") + + f.write("\n") + + def getArgList(self): + args = [] + + if self.policy: + args.append ("--medium") + else: + args.append ("--high") + if self.dhcp: + args.append ("--dhcp") + if self.portlist: + ports = string.split(self.portlist,',') + for port in ports: + port = string.strip(port) + try: + if not string.index(port,':'): + port = '%s:tcp' % port + except: + pass + self.ports.append(port) + for port in self.ports: + args = args + [ "--port", port ] + if self.smtp: + args = args + [ "--port","smtp:tcp" ] + if self.http: + args = args + [ "--port","http:tcp" ] + if self.ftp: + args = args + [ "--port","ftp:tcp" ] + if self.ssh: + args = args + [ "--port","ssh:tcp" ] + if self.telnet: + args = args + [ "--port","telnet:tcp" ] + for dev in self.trustdevs: + args = args + [ "--trust", dev ] + + return args + + def write (self, instPath): + args = [ "/usr/sbin/lokkit", "--quiet", "--nostart" ] + + if self.enabled > 0: + args = args + self.getArgList() + + try: + if flags.setupFilesystems: + iutil.execWithRedirect(args[0], args, root = instPath, + stdout = None, stderr = None) + else: + log("would have run %s", args) + except RuntimeError, msg: + log ("lokkit run failed: %s", msg) + except OSError, (errno, msg): + log ("lokkit run failed: %s", msg) + else: + # remove /etc/sysconfig/ipchains + file = instPath + "/etc/sysconfig/ipchains" + if os.access(file, os.O_RDONLY): + os.remove(file) + diff --git a/flags.py b/flags.py new file mode 100644 index 000000000..b2ef58f70 --- /dev/null +++ b/flags.py @@ -0,0 +1,25 @@ +# A lot of effort, but it only allows a limited set of flags to be referenced +class Flags: + + def __getattr__(self, attr): + if self.__dict__['flags'].has_key(attr): + return self.__dict__['flags'][attr] + + raise AttributeError, attr + + def __setattr__(self, attr, val): + if self.__dict__['flags'].has_key(attr): + self.__dict__['flags'][attr] = val + else: + raise AttributeError, attr + + def __init__(self): + self.__dict__['flags'] = {} + self.__dict__['flags']['test'] = 0 + self.__dict__['flags']['expert'] = 0 + self.__dict__['flags']['serial'] = 0 + self.__dict__['flags']['setupFilesystems'] = 1 + + +global flags +flags = Flags() diff --git a/instdata.py b/instdata.py new file mode 100644 index 000000000..fa19390c0 --- /dev/null +++ b/instdata.py @@ -0,0 +1,143 @@ +import language +import kbd +import network +import firewall +import timezone +import desktop +import users +import fsset +import partitioning +import bootloader +from simpleconfig import SimpleConfigFile +from translate import _ + +class Boolean: + def set(self, val): + self.val = val + + def get(self): + return self.val + + def __init__(self, val = 0): + self.val = val + +# Collector class for all data related to an install/upgrade. + +class InstallData: + + def reset(self): + # Reset everything except: + # + # - The mouse + # - The install language + # - The keyboard + + self.langSupport = language.Language(0) + self.instClass = None + self.network = network.Network() + self.firewall = firewall.Firewall() + self.timezone = timezone.Timezone() + self.accounts = users.Accounts() + self.rootPassword = users.RootPassword () + self.auth = users.Authentication() + self.desktop = desktop.Desktop() + self.hdList = None + self.comps = None + self.upgrade = Boolean() + self.fsset.reset() + self.diskset = partitioning.DiskSet() + self.partrequests = partitioning.PartitionRequests(self.diskset) + self.bootloader = bootloader.x86BootloaderInfo() + + def setInstallProgressClass(self, c): + self.instProgress = c + + # expects a Mouse object + def setMouse(self, mouse): + self.mouse = mouse + + # expects a VideoCardInfo object + def setVideoCard(self, video): + self.videocard = video + + # expects a Monitor object + def setMonitor(self, monitor): + self.monitor = monitor + + # expects a XF86Config object + def setXconfig(self, xconfig): + self.xconfig = xconfig + + def write(self, instPath): + self.langSupport.write (instPath) + self.mouse.write(instPath) + self.keyboard.write (instPath) + self.network.write (instPath) + self.auth.write (instPath) + self.firewall.write (instPath) + self.rootPassword.write (instPath, self.auth) + self.accounts.write (instPath, self.auth) + self.desktop.write (instPath) + self.fsset.write (instPath) + + def writeKS(self, filename): + # make it so only root can read, could have password + f = open(filename, "w", 0600) + + f.write("# Kickstart file automatically generated by anaconda.\n\n") + if self.upgrade.get(): + f.write("upgrade\n"); + else: + f.write("install\n"); + + self.instLanguage.writeKS(f) + self.langSupport.writeKS(f) + self.keyboard.writeKS(f) + self.mouse.writeKS(f) + self.xconfig.writeKS(f) + self.network.writeKS(f) + self.rootPassword.writeKS(f) + self.firewall.writeKS(f) + self.auth.writeKS(f) + self.timezone.writeKS(f) + + f.write("\n%packages\n") + packages = {} + for comp in self.comps: + if comp.isSelected(): + if comp.isSelected(justManual = 1) and comp.name != "Base": + f.write("@ %s\n" % comp.name) + + for pkg in comp.packages(): + packages[pkg] = 1 + + for pkg in self.hdList.values(): + if not packages.has_key(pkg) and pkg.isSelected(): + f.write("%s\n" % pkg.name) + if pkg.wasForcedOff(): + f.write("-%s\n" %(pkg.name)) + + f.write("\n%post\n") + self.accounts.writeKScommands(f, self.auth) + + # XXX + #self.monitor + #self.mouse + #self.videoCard + #self.fstab + #self.desktop + # + + + def __init__(self, extraModules): + self.instLanguage = language.InstallTimeLanguage() + self.keyboard = kbd.Keyboard() + + self.mouse = None + self.monitor = None + self.videocard = None + self.xconfig = None + self.extraModules = extraModules + self.fsset = fsset.FileSystemSet() + + self.reset() diff --git a/network.py b/network.py new file mode 100644 index 000000000..93caa608b --- /dev/null +++ b/network.py @@ -0,0 +1,256 @@ +from simpleconfig import SimpleConfigFile +import string +import isys +import socket +import os +from log import log + +class NetworkDevice (SimpleConfigFile): + def __str__ (self): + s = "" + s = s + "DEVICE=" + self.info["DEVICE"] + "\n" + keys = self.info.keys () + keys.sort () + keys.remove ("DEVICE") + + # Don't let onboot be turned on unless we have config information + # to go along with it + if self.get('bootproto') != 'dhcp' and not self.get('ipaddr'): + forceOffOnBoot = 1 + else: + forceOffOnBoot = 0 + + onBootWritten = 0 + for key in keys: + if key == 'ONBOOT' and forceOffOnBoot: + s = s + key + "=" + 'no' + "\n" + else: + s = s + key + "=" + self.info[key] + "\n" + + if key == 'ONBOOT': + onBootWritten = 1 + + if not onBootWritten: + s = s + 'ONBOOT=no\n' + + return s + + def __init__ (self, dev): + self.info = { "DEVICE" : dev } + +class Network: + def __init__ (self): + self.netdevices = {} + self.gateway = "" + self.primaryNS = "" + self.secondaryNS = "" + self.ternaryNS = "" + self.domains = [] + self.readData = 0 + self.isConfigured = 0 + self.hostname = "localhost.localdomain" + + try: + f = open ("/tmp/netinfo", "r") + except: + pass + else: + lines = f.readlines () + f.close () + info = {} + self.isConfigured = 1 + for line in lines: + netinf = string.splitfields (line, '=') + info [netinf[0]] = string.strip (netinf[1]) + self.netdevices [info["DEVICE"]] = NetworkDevice (info["DEVICE"]) + if info.has_key ("IPADDR"): + self.netdevices [info["DEVICE"]].set (("IPADDR", info["IPADDR"])) + if info.has_key ("NETMASK"): + self.netdevices [info["DEVICE"]].set (("NETMASK", info["NETMASK"])) + if info.has_key ("BOOTPROTO"): + self.netdevices [info["DEVICE"]].set (("BOOTPROTO", info["BOOTPROTO"])) + if info.has_key ("ONBOOT"): + self.netdevices [info["DEVICE"]].set (("ONBOOT", info["ONBOOT"])) + if info.has_key ("GATEWAY"): + self.gateway = info["GATEWAY"] + if info.has_key ("DOMAIN"): + self.domains.append(info["DOMAIN"]) + if info.has_key ("HOSTNAME"): + self.hostname = info["HOSTNAME"] + + self.readData = 1 + try: + f = open ("/etc/resolv.conf", "r") + except: + pass + else: + lines = f.readlines () + f.close () + for line in lines: + resolv = string.split (line) + if resolv and resolv[0] == 'nameserver': + if self.primaryNS == "": + self.primaryNS = resolv[1] + elif self.secondaryNS == "": + self.secondaryNS = resolv[1] + elif self.ternaryNS == "": + self.ternaryNS = resolv[1] + + def getDevice(self, device): + return self.netdevices[device] + + def available (self): + f = open ("/proc/net/dev") + lines = f.readlines() + f.close () + # skip first two lines, they are header + lines = lines[2:] + for line in lines: + dev = string.strip (line[0:6]) + if dev != "lo" and not self.netdevices.has_key (dev): + self.netdevices[dev] = NetworkDevice (dev) + return self.netdevices + + def setHostname(self, hn): + self.hostname = hn + + def lookupHostname (self): + # can't look things up if they don't exist! + if not self.hostname or self.hostname == "localhost.localdomain": return None + if not self.primaryNS: return + if not self.isConfigured: + for dev in self.netdevices.values(): + if dev.get('bootproto') == "dhcp": + self.primaryNS = isys.pumpNetDevice(dev.get('device')) + self.isConfigured = 1 + break + elif dev.get('ipaddr') and dev.get('netmask'): + try: + isys.configNetDevice(dev.get('device'), + dev.get('ipaddr'), + dev.get('netmask'), + self.gateway) + self.isConfigured = 1 + break + except SystemError: + log ("failed to configure network device %s when " + "looking up host name", dev.get('device')) + + if not self.isConfigured: + log ("no network devices were availabe to look up host name") + return None + + f = open("/etc/resolv.conf", "w") + f.write("nameserver %s\n" % self.primaryNS) + f.close() + isys.resetResolv() + isys.setResolvRetry(2) + + try: + ip = socket.gethostbyname(self.hostname) + except: + return None + + return ip + + def nameservers (self): + return [ self.primaryNS, self.secondaryNS, self.ternaryNS ] + + def writeKS(self, f): + # XXX + # + # Hopefully the first one is the right one to use. We ought to support + # multiple "network" lines + # + # This doesn't write out nodns, ever. + # + devNames = self.netdevices.keys() + devNames.sort() + dev = self.netdevices[devNames[0]] + + if dev.get('bootproto') == 'dhcp' or dev.get('ipaddr'): + f.write("network --device %s" % dev.get('device')) + if dev.get('bootproto') == 'dhcp': + f.write(" --bootproto dhcp") + else: + f.write(" --ip %s --network %s --netmask %s" % + (dev.get('ipaddr'), dev.get('netmask'), dev.get('gateway'))) + + if dev.get('nameserver'): + f.write(" --nameserver %s" % dev.get('nameserver')) + + if self.hostname and self.hostname != "localhost.localdomain": + f.write(" --hostname %s" % dev.get('hostname')) + + f.write("\n"); + + def write (self, instPath): + # /etc/sysconfig/network-scripts/ifcfg-* + for dev in self.netdevices.values (): + device = dev.get ("device") + fn = instPath + "/etc/sysconfig/network-scripts/ifcfg-" + device + f = open (fn, "w") + os.chmod(fn, 0600) + f.write (str (dev)) + f.close () + + # /etc/sysconfig/network + + f = open (instPath + "/etc/sysconfig/network", "w") + f.write ("NETWORKING=yes\n" + "HOSTNAME=") + + + # use instclass hostname if set (kickstart) to override + if self.hostname: + f.write(self.hostname + "\n") + else: + f.write("localhost.localdomain" + "\n") + if self.gateway: + f.write("GATEWAY=" + self.gateway + "\n") + f.close () + + # /etc/hosts + f = open (instPath + "/etc/hosts", "w") + localline = "127.0.0.1\t\t" + + log ("self.hostname = %s", self.hostname) + + ip = self.lookupHostname() + + # If the hostname is not resolvable, tie it to 127.0.0.1 + if not ip and self.hostname != "localhost.localdomain": + localline = localline + self.hostname + " " + l = string.split(self.hostname, ".") + if len(l) > 1: + localline = localline + l[0] + " " + + localline = localline + "localhost.localdomain localhost\n" + f.write("# Do not remove the following line, or various programs\n") + f.write("# that require network functionality will fail.\n") + f.write (localline) + + if ip: + f.write ("%s\t\t%s\n" % (ip, self.hostname)) + + # If the hostname was not looked up, but typed in by the user, + # domain might not be computed, so do it now. + if self.domains == [ "localdomain" ] or not self.domains: + if '.' in self.hostname: + # chop off everything before the leading '.' + domain = self.hostname[(string.find(self.hostname, '.') + 1):] + self.domains = [ domain ] + + # /etc/resolv.conf + f = open (instPath + "/etc/resolv.conf", "w") + + if self.domains != [ 'localdomain' ] and self.domains: + f.write ("search " + string.joinfields (self.domains, ' ') + + "\n") + + for ns in self.nameservers (): + if ns: + f.write ("nameserver " + ns + "\n") + + f.close () + diff --git a/packages.py b/packages.py new file mode 100644 index 000000000..b9da7961e --- /dev/null +++ b/packages.py @@ -0,0 +1,797 @@ +# +# packages.py: package management - mainly package installation +# +# Erik Troan <ewt@redhat.com> +# +# Copyright 2001 Red Hat, Inc. +# +# This software may be freely redistributed under the terms of the GNU +# library public license. +# +# You should have received a copy of the GNU Library Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +from translate import _ +import iutil +import isys +import rpm +import os +import timer +import sys +import string +import pcmcia +import dispatch +from log import log +from flags import flags + +def queryUpgradeContinue(intf, dir, dispatch): + if dir == dispatch.DISPATCH_BACK: + return + + rc = intf.messageWindow(_("Proceed with upgrade?"), + _("The filesystems of the Linux installation " + "you have chosen to upgrade have already been " + "mounted. You cannot go back past this point. " + "\n\n") + + _( "Would you like to continue with the upgrade?"), + type = "yesno").getrc() + if rc == 1: + sys.exit(0) + dispatch.gotoNext() + +def writeConfiguration(id, instPath): + log("Writing main configuration") + if not flags.test: + id.write(instPath) + +def writeKSConfiguration(id, instPath): + log("Writing autokickstart file") + if not flags.test: + fn = instPath + "/root/anaconda-ks.cfg" + else: + fn = "/tmp/anaconda-ks.cfg" + + id.writeKS(fn) + +def writeXConfiguration(id, instPath): + xserver = id.videocard.primaryCard().getXServer() + if not xserver: + return + + log("Writing X configuration") + if not flags.test: + fn = instPath + + if os.access (instPath + "/etc/X11/X", os.R_OK): + os.rename (instPath + "/etc/X11/X", + instPath + "/etc/X11/X.rpmsave") + + try: + os.unlink (instPath + "/etc/X11/X") + except OSError: + pass + + os.symlink ("../../usr/X11R6/bin/" + xserver, + instPath + "/etc/X11/X") + print "linked ../../usr/X11R6/bin/",xserver," to ",instPath,"/etc/X11/X" + else: + fn = "/tmp/" + + id.xconfig.write(fn+"/etc/X11") + +def readPackages(intf, method, id): + if (not id.hdList): + w = intf.waitWindow(_("Reading"), _("Reading package information...")) + id.hdList = method.readHeaders() + id.instClass.setPackageSelection(id.hdList) + w.pop() + + if not id.comps: + id.comps = method.readComps(id.hdList) + id.instClass.setGroupSelection(id.comps) + + # XXX + #updateInstClassComps () + else: + # re-evaluate all the expressions for packages with qualifiers. + + id.comps.updateSelections() + +def handleX11Packages(dir, intf, disp, id, instPath): + + if dir == dispatch.DISPATCH_BACK: + return + + # skip X setup if it is not being installed + if (not id.comps.packages.has_key('XFree86') or + not id.comps.packages['XFree86'].selected): + disp.skipStep("videocard") + disp.skipStep("monitor") + disp.skipStep("xcustom") + disp.skipStep("writexconfig") + elif disp.stepInSkipList("videocard"): + # if X is being installed, but videocard step skipped + # need to turn it back on + disp.skipStep("videocard", skip=0) + disp.skipStep("monitor", skip=0) + disp.skipStep("xcustom", skip=0) + disp.skipStep("writexconfig", skip=0) + + # set default runlevel based on packages + gnomeSelected = (id.comps.packages.has_key('gnome-core') + and id.comps.packages['gnome-core'].selected) + kdeSelected = (id.comps.packages.has_key('kdebase') + and id.comps.packages['kdebase'].selected) + + if gnomeSelected: + id.desktop.setDefaultDesktop("GNOME") + elif kdeSelected: + id.desktop.setDefaultDesktop("KDE") + + if gnomeSelected or kdeSelected: + id.desktop.setDefaultRunLevel(5) + + +def checkDependencies(dir, intf, disp, id, instPath): + if dir == dispatch.DISPATCH_BACK: + return + + win = intf.waitWindow(_("Dependency Check"), + _("Checking dependencies in packages selected for installation...")) + + id.dependencies = id.comps.verifyDeps(instPath, id.upgrade.get()) + + win.pop() + + if id.dependencies: + disp.skipStep("dependencies", skip = 0) + else: + disp.skipStep("dependencies") + +#XXX +#try: + #self.todo.getHeaderList () + #self.todo.getCompsList() + #self.files_found = "TRUE" +#except ValueError, msg: + #extra = msg +#except RuntimeError, msg: + #extra = msg +#except TypeError, msg: + #extra = msg +#except KeyError, key: + #extra = ("The comps file references a package called \"%s\" which " + #"could not be found." % (key,)) +#except: + #extra = "" +# +#if self.files_found == "FALSE": + #if extra: + #text = (_("The following error occurred while " + #"retreiving hdlist file:\n\n" + #"%s\n\n" + #"Installer will exit now.") % extra) + #else: + #text = (_("An error has occurred while retreiving the hdlist " + #"file. The installation media or image is " + #"probably corrupt. Installer will exit now.")) + #win = ErrorWindow (text) +#else: + +class InstallCallback: + + def cb(self, what, amount, total, h, (param)): + if (what == rpm.RPMCALLBACK_TRANS_START): + # step 6 is the bulk of the transaction set + # processing time + if amount == 6: + self.progressWindow = \ + self.progressWindowClass (_("Processing"), + _("Preparing to install..."), + total) + if (what == rpm.RPMCALLBACK_TRANS_PROGRESS): + if self.progressWindow: + self.progressWindow.set (amount) + + if (what == rpm.RPMCALLBACK_TRANS_STOP and self.progressWindow): + self.progressWindow.pop () + + if (what == rpm.RPMCALLBACK_INST_OPEN_FILE): + # We don't want to start the timer until we get to the first + # file. + self.pkgTimer.start() + + self.progress.setPackage(h) + self.progress.setPackageScale(0, 1) + self.instLog.write (self.modeText % (h[rpm.RPMTAG_NAME],)) + self.instLog.flush () + fn = self.method.getFilename(h, self.pkgTimer) + + self.rpmFD = -1 + while self.rpmFD < 0: + try: + self.rpmFD = os.open(fn, os.O_RDONLY) + # Make sure this package seems valid + try: + (h, isSource) = rpm.headerFromPackage(self.rpmFD) + os.lseek(self.rpmFD, 0, 0) + except: + self.rpmFD = -1 + os.close(self.rpmFD) + raise SystemError + except: + self.messageWindow(_("Error"), + _("The file %s cannot be opened. This is due to " + "a missing file, a bad package, or bad media. " + "Press <return> to try again.") % fn) + + fn = self.method.unlinkFilename(fn) + return self.rpmFD + elif (what == rpm.RPMCALLBACK_INST_PROGRESS): + if total: + self.progress.setPackageScale(amount, total) + pass + elif (what == rpm.RPMCALLBACK_INST_CLOSE_FILE): + os.close (self.rpmFD) + self.progress.completePackage(h, self.pkgTimer) + else: + pass + + self.progress.processEvents() + + def __init__(self, messageWindow, progress, pkgTimer, method, + progressWindowClass, instLog, modeText): + self.messageWindow = messageWindow + self.progress = progress + self.pkgTimer = pkgTimer + self.method = method + self.progressWindowClass = progressWindowClass + self.progressWindow = None + self.instLog = instLog + self.modeText = modeText + +def sortPackages(first, second): + # install packages in cd order (cd tag is 1000002) + one = None + two = None + + if first[1000003] != None: + one = first[1000003] + + if second[1000003] != None: + two = second[1000003] + + if one == None or two == None: + one = 0 + two = 0 + if first[1000002] != None: + one = first[1000002] + + if second[1000002] != None: + two = second[1000002] + + if one < two: + return -1 + elif one > two: + return 1 + elif string.lower(first[rpm.RPMTAG_NAME]) < string.lower(second[rpm.RPMTAG_NAME]): + return -1 + elif string.lower(first[rpm.RPMTAG_NAME]) > string.lower(second[rpm.RPMTAG_NAME]): + return 1 + + return 0 + +class rpmErrorClass: + + def cb(self): + self.f.write (rpm.errorString () + "\n") + + def __init__(self, f): + self.f = f + +def turnOnFilesystems(dir, fsset, diskset, upgrade, instPath): + if dir == dispatch.DISPATCH_BACK: + fsset.umountFilesystems(instPath) + return + + if flags.setupFilesystems: + if not upgrade.get(): + diskset.savePartitions () + fsset.formatSwap(instPath) + fsset.turnOnSwap(instPath) + fsset.makeFilesystems (instPath) + fsset.mountFilesystems (instPath) + +def doInstall(method, id, intf, instPath): + if flags.test: + return + + arch = iutil.getArch () + + if arch == "alpha": + # if were're on alpha with ARC console, set the clock + # so that our installed files won't be in the future + from milo import MiloInstall, onMILO + if onMILO (): + args = ("clock", "-A", "-s") + try: + iutil.execWithRedirect('/usr/sbin/clock', args) + except: + pass + + # shorthand + upgrade = id.upgrade.get() + + if not upgrade: + # this is NICE and LATE. It lets kickstart/server/workstation + # installs detect this properly + if (id.hdList.has_key('kernel-smp') and isys.smpAvailable()): + id.hdList['kernel-smp'].selected = 1 + + if (id.hdList.has_key('kernel-enterprise')): + import lilo + + if lilo.needsEnterpriseKernel(): + id.hdList['kernel-enterprise'].selected = 1 + + # we *always* need a kernel installed + if (id.hdList.has_key('kernel')): + id.hdList['kernel'].selected = 1 + + # if NIS is configured, install ypbind and dependencies: + if id.auth.useNIS: + id.hdList['ypbind'].selected = 1 + id.hdList['yp-tools'].selected = 1 + id.hdList['portmap'].selected = 1 + + if id.auth.useLdap: + id.hdList['nss_ldap'].selected = 1 + id.hdList['openldap'].selected = 1 + id.hdList['perl'].selected = 1 + + if id.auth.useKrb5: + id.hdList['pam_krb5'].selected = 1 + id.hdList['krb5-workstation'].selected = 1 + id.hdList['krbafs'].selected = 1 + id.hdList['krb5-libs'].selected = 1 + + xserver = id.videocard.primaryCard().getXServer() + if xserver and id.comps.packages.has_key('XFree86') and id.comps.packages['XFree86'].selected and xserver != "XFree86": + try: + id.hdList['XFree86-' + xserver[5:]].selected = 1 + except ValueError, message: + log ("Error selecting XFree86 server package: %s", message) + + # make sure that all comps that include other comps are + # selected (i.e. - recurse down the selected comps and turn + # on the children + + method.mergeFullHeaders(id.hdList) + + if upgrade: + # An old mtab can cause confusion (esp if loop devices are + # in it) + f = open(instPath + "/etc/mtab", "w+") + f.close() + + # XXX + #if method.systemMounted (fstab, instPath, id.hdList.selected()): + #fstab.umountFilesystems(instPath) + #return 1 + + for i in ( '/var', '/var/lib', '/var/lib/rpm', '/tmp', '/dev', '/etc', + '/etc/sysconfig', '/etc/sysconfig/network-scripts', + '/etc/X11' ): + try: + os.mkdir(instPath + i) + except os.error, (errno, msg): + # self.intf.messageWindow("Error", "Error making directory %s: %s" % (i, msg)) + pass + + db = rpm.opendb(1, instPath) + ts = rpm.TransactionSet(instPath, db) + + total = 0 + totalSize = 0 + + if upgrade: + how = "u" + else: + how = "i" + + l = [] + + for p in id.hdList.selected(): + l.append(p) + l.sort(sortPackages) + + for p in l: + ts.add(p.h, p.h, how) + total = total + 1 + totalSize = totalSize + (p[rpm.RPMTAG_SIZE] / 1024 ) + + if not id.hdList.preordered(): + log ("WARNING: not all packages in hdlist had order tag") + ts.order() + + if upgrade: + logname = '/tmp/upgrade.log' + else: + logname = '/tmp/install.log' + + instLogName = instPath + logname + try: + os.unlink (instLogName) + except OSError: + pass + + instLog = open(instLogName, "w+") + syslog = iutil.InstSyslog (instPath, instPath + logname) + + ts.scriptFd = instLog.fileno () + # the transaction set dup()s the file descriptor and will close the + # dup'd when we go out of scope + + if upgrade: + modeText = _("Upgrading %s.\n") + else: + modeText = _("Installing %s.\n") + + errors = rpmErrorClass(instLog) + oldError = rpm.errorSetCallback (errors.cb) + pkgTimer = timer.Timer(start = 0) + + id.instProgress.setSizes(total, totalSize) + id.instProgress.processEvents() + + cb = InstallCallback(intf.messageWindow, id.instProgress, pkgTimer, + method, intf.progressWindow, instLog, modeText) + + problems = ts.run(0, ~rpm.RPMPROB_FILTER_DISKSPACE, cb.cb, 0) + +# problems = ts.run(rpm.RPMTRANS_FLAG_TEST, ~0, self.instCallback, 0) + + if problems: + spaceneeded = {} + nodeneeded = {} + size = 12 + + # XXX + nodeprob = -1 + if rpm.__dict__.has_key ("RPMPROB_DISKNODES"): + nodeprob = rpm.RPMPROB_DISKNODES + + for (descr, (type, mount, need)) in problems: + idx = string.find (mount, "/mnt/sysimage") + if mount[0:13] == "/mnt/sysimage": + mount = mount[13:] + if not mount: + mount = '/' + + if type == rpm.RPMPROB_DISKSPACE: + if spaceneeded.has_key (mount) and spaceneeded[mount] < need: + spaceneeded[mount] = need + else: + spaceneeded[mount] = need + elif type == nodeprob: + if nodeneeded.has_key (mount) and nodeneeded[mount] < need: + nodeneeded[mount] = need + else: + nodeneeded[mount] = need + else: + log ("WARNING: unhandled problem returned from transaction set type %d", + type) + + probs = "" + if spaceneeded: + probs = probs + _("You don't appear to have enough disk space to install " + "the packages you've selected. You need more space on the " + "following filesystems:\n\n") + probs = probs + ("%-15s %s\n") % (_("Mount Point"), _("Space Needed")) + + for (mount, need) in spaceneeded.items (): + if need > (1024*1024): + need = (need + 1024 * 1024 - 1) / (1024 * 1024) + suffix = "M" + else: + need = (need + 1023) / 1024 + suffix = "k" + + prob = "%-15s %d %c\n" % (mount, need, suffix) + probs = probs + prob + if nodeneeded: + if probs: + probs = probs + '\n' + probs = probs + _("You don't appear to have enough file nodes to install " + "the packages you've selected. You need more file nodes on the " + "following filesystems:\n\n") + probs = probs + ("%-15s %s\n") % (_("Mount Point"), _("Nodes Needed")) + + for (mount, need) in nodeneeded.items (): + prob = "%-15s %d\n" % (mount, need) + probs = probs + prob + + intf.messageWindow (_("Disk Space"), probs) + + del ts + del db + instLog.close() + del syslog + + method.systemUnmounted () + + rpm.errorSetCallback (oldError) + return dispatch.DISPATCH_BACK + + # This should close the RPM database so that you can + # do RPM ops in the chroot in a %post ks script + del ts + del db + rpm.errorSetCallback (oldError) + + method.filesDone () + + del p + + if upgrade: + instLog.write ("\n\nThe following packages were available on the CD but NOT upgraded:\n") + for p in id.hdList.packages.values (): + if not p.selected: + instLog.write("%s-%s-%s.%s.rpm\n" % + (p.h[rpm.RPMTAG_NAME], + p.h[rpm.RPMTAG_VERSION], + p.h[rpm.RPMTAG_RELEASE], + p.h[rpm.RPMTAG_ARCH])) + instLog.close () + + id.instProgress = None + + createWindow = (intf.progressWindow, + (_("Post Install"), + _("Performing post install configuration..."), 8)) + w = apply(apply, createWindow) + + try: + if not upgrade: + # XXX + #if self.fdDevice[0:2] == "fd": + #self.fstab.addMount(self.fdDevice, "/mnt/floppy", "auto") + #self.fstab.write (instPath) + + w.set(1) + + copyExtraModules(instPath, id.comps, id.extraModules) + + w.set(2) + + # pcmcia is supported only on i386 at the moment + if arch == "i386": + pcmcia.createPcmciaConfig( + instPath + "/etc/sysconfig/pcmcia") + + # rootpath mode doesn't have this file around + if os.access("/tmp/modules.conf", os.R_OK): + iutil.copyFile("/tmp/modules.conf", + instPath + "/etc/modules.conf") + + # XXX + #if not self.x.skip and self.x.server: + #if os.access (instPath + "/etc/X11/X", os.R_OK): + #os.rename (instPath + "/etc/X11/X", + #instPath + "/etc/X11/X.rpmsave") + #try: + #os.unlink (instPath + "/etc/X11/X") + #except OSError: + #pass + #os.symlink ("../../usr/X11R6/bin/" + self.x.server, + #instPath + "/etc/X11/X") + + #self.x.write (instPath + "/etc/X11") + + w.set(3) + + # blah. If we're on a serial mouse, and we have X, we need to + # close the mouse device, then run kudzu, then open it again. + + # turn it off + mousedev = None + + # XXX currently Bad Things (X async reply) happen when doing + # Mouse Magic on Sparc (Mach64, specificly) + if os.environ.has_key ("DISPLAY") and not arch == "sparc": + import xmouse + try: + mousedev = xmouse.get()[0] + except RuntimeError: + pass + + if mousedev: + try: + os.rename (mousedev, "/dev/disablemouse") + except OSError: + pass + try: + xmouse.reopen() + except RuntimeError: + pass + + unmountUSB = 0 + try: + isys.mount('/usbdevfs', instPath+'/proc/bus/usb', 'usbdevfs') + unmountUSB = 1 + except: + log("Mount of /proc/bus/usb failed") + pass + + + argv = [ "/usr/sbin/kudzu", "-q" ] + devnull = os.open("/dev/null", os.O_RDWR) + iutil.execWithRedirect(argv[0], argv, root = instPath, + stdout = devnull) + # turn it back on + if mousedev: + try: + os.rename ("/dev/disablemouse", mousedev) + except OSError: + pass + try: + xmouse.reopen() + except RuntimeError: + pass + + if unmountUSB: + isys.umount(instPath + '/proc/bus/usb', removeDir = 0) + + w.set(4) + + if upgrade: + # move the rebuilt db into place. + try: + iutil.rmrf (instPath + "/var/lib/rpm.rpmsave") + except OSError: + pass + os.rename (instPath + "/var/lib/rpm", + instPath + "/var/lib/rpm.rpmsave") + os.rename (instPath + self.dbpath, + instPath + "/var/lib/rpm") + + # XXX - rpm 4.0.2 %post braindeadness support + try: + os.unlink (instPath + "/etc/rpm/macros.db1") + except OSError: + pass + + # needed for prior systems which were not xinetd based + migrateXinetd(instPath, instLogName) + + # XXX + if flags.setupFilesystems: + errors = None + + if 0: + if arch == "sparc": + errors = self.silo.install (self.fstab, instPath, + id.hdList, upgrade) + elif arch == "i386": + defaultlang = self.language.getLangNickByName(self.language.getDefault()) + langlist = expandLangs(defaultlang) + errors = self.lilo.install (self.fstab, instPath, + id.hdList, upgrade, langlist) + elif arch == "ia64": + errors = self.eli.install (self.fstab, instPath, + id.hdList, upgrade) + elif arch == "alpha": + errors = self.milo.write () + else: + raise RuntimeError, "What kind of machine is this, anyway?!" + + if errors: + w.pop() + mess = _("An error occured while installing " + "the bootloader.\n\n" + "We HIGHLY recommend you make a recovery " + "boot floppy when prompted, otherwise you " + "may not be able to reboot into Red Hat Linux." + "\n\nThe error reported was:\n\n") + errors + self.intf.messageWindow(_("Bootloader Errors"), mess) + + # make sure bootdisk window appears + if iutil.getArch () == "i386": + self.instClass.removeFromSkipList('bootdisk') + self.bootdisk = 1 + + w = apply(apply, createWindow) + + + w.set(5) + + # go ahead and depmod modules as modprobe in rc.sysinit + # will complain loaduly if we don't do it now. + depmodModules(id.comps, instPath) + + w.set(6) + + # XXX + #self.instClass.postAction(instPath, self.serial) + + w.set(7) + + if flags.setupFilesystems: + f = open("/tmp/cleanup", "w") + method.writeCleanupPath(f) + # XXX + #self.fstab.writeCleanupPath(f) + f.close() + + w.set(8) + + del syslog + + finally: + pass + + w.pop () + + sys.stdout.flush() + +def migrateXinetd(self, instPath, instLog): + if not os.access (instPath + "/usr/sbin/inetdconvert", os.X_OK): + log("did not find %s" % instPath + "/usr/sbin/inetdconvert") + return + + if not os.access (instPath + "/etc/inetd.conf.rpmsave", os.R_OK): + log("did not run inetdconvert because no inetd.conf.rpmsave found") + return + + argv = [ "/usr/sbin/inetdconvert", "--convertremaining", + "--inetdfile", "/etc/inetd.conf.rpmsave" ] + + log("found inetdconvert, executing %s" % argv) + + logfile = os.open (instLog, os.O_APPEND) + iutil.execWithRedirect(argv[0], argv, root = instPath, + stdout = logfile, stderr = logfile) + os.close(logfile) + +def copyExtraModules(instPath, comps, extraModules): + kernelVersions = comps.kernelVersionList() + + for (path, subdir, name, pkg) in extraModules: + pattern = "" + names = "" + for (n, tag) in kernelVersions: + pattern = pattern + " " + n + "/" + name + ".o" + names = names + " " + name + ".o" + command = ("cd %s/lib/modules; gunzip < %s/modules.cgz | " + + "%s/bin/cpio --quiet -iumd %s") % \ + (instPath, path, instPath, pattern) + log("running: '%s'" % (command, )) + os.system(command) + + for (n, tag) in kernelVersions: + fromFile = "%s/lib/modules/%s/%s.o" % (instPath, n, name) + toDir = "%s/lib/modules/%s/kernel/drivers/%s" % \ + (instPath, n, subdir) + to = "%s/%s.o" % (toDir, name) + + if (os.access(fromFile, os.R_OK) and + os.access(toDir, os.X_OK)): + log("moving %s to %s" % (fromFile, to)) + os.rename(fromFile, to) + + # the file might not have been owned by root in the cgz + os.chown(to, 0, 0) + else: + log("missing DD module %s (this may be okay)" % + fromFile) + +def depmodModules(comps, instPath): + kernelVersions = comps.kernelVersionList() + + for (version, tag) in kernelVersions: + iutil.execWithRedirect ("/sbin/depmod", + [ "/sbin/depmod", "-a", version ], + root = instPath, stderr = '/dev/null') + diff --git a/timezone.py b/timezone.py new file mode 100644 index 000000000..a0d1e2918 --- /dev/null +++ b/timezone.py @@ -0,0 +1,44 @@ +import iutil +from log import log + +def bool(val): + if val: return "true" + return "false" + +class Timezone: + + def writeKS(self, f): + f.write("timezone") + if self.utc: + f.write(" --utc") + f.write(" %s\n" % self.tz) + + def write(self, instPath): + fromFile = instPath + "/usr/share/zoneinfo/" + self.tz + + try: + iutil.copyFile(fromFile, instPath + "/etc/localtime") + except OSError, (errno, msg): + log ("Error copying timezone (from %s): %s" % (fromFile, msg)) + + f = open(instPath + "/etc/sysconfig/clock", "w") + + f.write('ZONE="%s"\n' % self.tz) + f.write("UTC=%s\n" % bool(self.utc)) + f.write("ARC=%s\n" % bool(self.arc)) + + f.close() + + def getTimezoneInfo(self): + return (self.tz, self.utc, self.arc) + + def setTimezoneInfo(self, timezone, asUtc = 0, asArc = 0): + self.tz = timezone + self.utc = asUtc + self.arc = asArc + + def __init__(self): + self.tz = "America/New_York" + self.utc = 0 + self.arc = 0 + diff --git a/users.py b/users.py new file mode 100644 index 000000000..e6f1e55ec --- /dev/null +++ b/users.py @@ -0,0 +1,220 @@ +import iutil +import whrandom +import crypt +import os +import string +from flags import flags +from log import log + +class Accounts: + + # List of (accountName, fullName, password) tupes + + def setUserList(self, users): + self.users = users + + def getUserList(self): + return self.users + + def writeKScommands(self, f, auth): + for (account, name, password) in self.users: + crypted = cryptPassword(password, auth.useMD5) + + f.write("/usr/sbin/useradd %s\n" % (account)); + f.write("chfn -f '%s' %s\n" % (name, account)) + f.write("/usr/sbin/usermod -p '%s' %s\n" % (crypted, account)) + f.write("\n") + + def write(self, instPath, auth): + if not self.users: return + + if not flags.setupFilesystems: + return + + for (account, name, password) in self.users: + argv = [ "/usr/sbin/useradd", account ] + iutil.execWithRedirect(argv[0], argv, root = instPath, + stdout = None) + + argv = [ "/usr/bin/chfn", "-f", name, account] + iutil.execWithRedirect(argv[0], argv, root = instPath, + stdout = None) + + setPassword(instPath, account, password, auth.useMD5) + + def __init__(self): + self.users = [] + +class Password: + def __init__ (self): + self.crypt = None + self.pure = None + + def getPure(self): + return self.pure + + def set (self, password, isCrypted = 0): + if isCrypted: + self.crypt = password + self.pure = None + else: + salt = (whrandom.choice (string.letters + + string.digits + './') + + whrandom.choice (string.letters + + string.digits + './')) + self.crypt = crypt.crypt (password, salt) + self.pure = password + + def getCrypted(self): + return self.crypt + +class RootPassword(Password): + + def write(self, instPath, auth): + pure = self.getPure() + if pure: + setPassword(instPath, "root", pure, auth.useMD5) + else: + setPassword(instPath, "root", self.getCrypted (), + auth.useMD5, alreadyCrypted = 1) + + def writeKS(self, f): + f.write("rootpw --iscrypted %s\n" % self.getCrypted()) + +def cryptPassword(password, useMD5): + if useMD5: + salt = "$1$" + saltLen = 8 + else: + salt = "" + saltLen = 2 + + for i in range(saltLen): + salt = salt + whrandom.choice (string.letters + + string.digits + './') + + return crypt.crypt (password, salt) + +def setPassword(instPath, account, password, useMD5, alreadyCrypted = 0): + if not alreadyCrypted: + password = cryptPassword(password, useMD5) + + devnull = os.open("/dev/null", os.O_RDWR) + + argv = [ "/usr/sbin/usermod", "-p", password, account ] + iutil.execWithRedirect(argv[0], argv, root = instPath, + stdout = '/dev/null', stderr = None) + os.close(devnull) + +class Authentication: + def __init__ (self): + self.useShadow = 1 + self.useMD5 = 1 + + self.useNIS = 0 + self.nisDomain = "" + self.nisuseBroadcast = 1 + self.nisServer = "" + + self.useLdap = 0 + self.useLdapauth = 0 + self.ldapServer = "" + self.ldapBasedn = "" + self.ldapTLS = "" + + self.useKrb5 = 0 + self.krb5Realm = "" + self.krb5Kdc = "" + self.krb5Admin = "" + + self.useHesiod = 0 + self.hesiodLhs = "" + self.hesiodRhs = "" + + def writeKS(self, f): + f.write("authconfig") + for arg in self.getArgList(): + if arg[0:9] != "--disable": + f.write(" " + arg) + f.write("\n") + + def getArgList(self): + args = [] + + if self.useShadow: + args.append ("--enableshadow") + else: + args.append ("--disableshadow") + + if self.useMD5: + args.append ("--enablemd5") + else: + args.append ("--disablemd5") + + + if self.useNIS: + args.append ("--enablenis") + args.append ("--nisdomain") + args.append (self.nisDomain) + if not self.nisuseBroadcast: + args.append ("--nisserver") + args.append (self.nisServer) + else: + args.append ("--disablenis") + + if self.useLdap: + args.append ("--enableldap") + else: + args.append ("--disableldap") + if self.useLdapauth: + args.append ("--enableldapauth") + else: + args.append ("--disableldapauth") + if self.useLdap or self.useLdapauth: + args.append ("--ldapserver") + args.append (self.ldapServer) + args.append ("--ldapbasedn") + args.append (self.ldapBasedn) + if self.ldapTLS: + args.append ("--enableldaptls") + else: + args.append ("--disableldaptls") + + if self.useKrb5: + args.append ("--enablekrb5") + args.append ("--krb5realm") + args.append (self.krb5Realm) + args.append ("--krb5kdc") + args.append (self.krb5Kdc) + args.append ("--krb5adminserver") + args.append (self.krb5Admin) + else: + args.append ("--disablekrb5") + + if self.useHesiod: + args.append ("--enablehesiod") + args.append ("--hesiodlhs") + args.append (self.hesiodLhs) + args.append ("--hesiodrhs") + args.append (self.hesiodRhs) + else: + args.append ("--disablehesiod") + + return args + + + def write (self, instPath): + args = [ "/usr/sbin/authconfig", "--kickstart", "--nostart" ] + args = args + self.getArgList() + + try: + if flags.setupFilesystems: + iutil.execWithRedirect(args[0], args, + stdout = None, stderr = None, + searchPath = 1, + root = instPath) + else: + log("Would have run %s", args) + except RuntimeError, msg: + log ("Error running %s: %s", args, msg) + diff --git a/videocard.py b/videocard.py new file mode 100644 index 000000000..583752156 --- /dev/null +++ b/videocard.py @@ -0,0 +1,369 @@ +import copy +import string +import kudzu +import iutil +import isys + +from log import log + +Video_cardslist = {} + +def Video_cardsDBLookup(thecard): + card = Video_cardslist[thecard] + origcard = copy.copy(card) + + count = 0 + while count < 16 and card.has_key ("SEE"): + card = Video_cardslist[card["SEE"]] + count = count + 1 + + if count >= 16: + raise RunTimeError, "Could not find card ",origcard + + return card + + +class VideoCard: +# +# This class represents the base data about a videocard. These are +# the internal members - PLEASE use methods to access values! +# +# device - if framebuffer running on card this is entry in /dev (string) +# descr - human readable description (string) +# server - X server to use (string) +# probedcard - value returned for kudzu containing 'Card:........' +# cardManf - name of manufacturer (string) +# vidRam - amount of video ram (in kB) (string) +# cardData - record from X card database, contains a dictionary of +# key/values. +# devID - ID from ddcprobe (string) +# fbmodes - if framebuffer running, video mode in use (string) +# fbbpp - if framebuffer running, pixel depth in use (string) +# +# These values will be None if undefined or not applicable. +# + + def __str__ (self): + return "device: %s\ndescr : %s\nserver: %s\ncardManf: %s\nvidRam: %s\ncarddata: %s\ndevID: %s\nfbmodes: %s\nfbbpp: %s\n" % (self.device, self.descr, self.server, self.cardManf, self.vidRam, self.cardData, self.devID, self.fbmodes, self.fbbpp) + + + def __init__ (self): + self.device = None + self.probedcard = None + self.descr = None + self.server = None + self.cardManf = None + self.vidRam = None + self.cardData = None + self.devID = None + self.fbmodes = None + self.fbbpp = None + + def setDevice(self, device): + self.device = device + + def setDescription(self, descr): + self.descr = descr + + def setProbedCard(self, card): + self.probedcard = card + + def setXServer(self, server): + self.server = server + + def setVideoRam(self, vidRam): + self.vidRam = vidRam + + def setCardData(self, card): + self.cardData = card + + def setDevID(self, devid): + self.devID = devid + + def setCardManf(self, manf): + self.cardManf = manf + + def setFBModes(self, fbmodes): + self.fbmodes = fbmodes + + def setFBBpp(self, bpp): + self.fbbpp = bpp + + def getProbedCard(self): + return self.probedcard + + def getVideoRam(self): + return self.vidRam + + def getDescription(self): + return self.descr + + def getDevice(self): + return self.device + + def getDevID(self): + return self.devID + + def getXServer(self): + return self.server + + def getFBBpp(self): + return self.fbbpp + + def shortDescription(self): + if self.devID and self.devID != "": + return self.devID + else: + return _("Unable to probe") + + # dontResolve = 1 tells us to not follow 'SEE' records to find + # true card definition + def getCardData(self, dontResolve = 0): + if dontResolve: + return self.cardData + else: + return Video_cardsDBLookup(self.cardData["NAME"]) + + def canTestSafely(self): + cardData = self.getCardData() + if cardData.has_key("DRIVER"): + curdriver = cardData["DRIVER"] + noprobedriverList = ("i810", "tdfx") + for adriver in noprobedriverList: + if curdriver == adriver: + return 0 + + return 1 + + +class VideoCardInfo: + +# +# This class represents the video cards on the system. +# +# Currently we only care about the primary card on the system. +# This can be found by using the VideoCardInfo::primaryCard() function. +# +# NOTE - X configuration is not represented here. This class is +# intended only to reprsent the available hardware on the system +# + + + def primaryCard(self, useProbed = 0): + if useProbed: + if self.orig_videocards and self.orig_primary < len(self.orig_videocards): + return self.orig_videocards[self.orig_primary] + else: + return None + else: + if self.videocards and self.primary < len(self.videocards): + return self.videocards[self.primary] + else: + return None + + + def possible_ram_sizes(self): + #--Valid video ram sizes-- + return [256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536] + + def possible_depths(self): + #--Valid bit depths-- + return ["8", "16", "24", "32"] + + def manufacturerDB(self): + return ["3DLabs", + "ABit", "AOpen", "ASUS", "ATI", "Actix", "Ark Logic", "Avance Logic", + "Compaq", "Canopus", "Cardex", "Chaintech", + "Chips & Technologies", "Cirrus", "Creative Labs", + "DFI", "DSV", "DataExpert", "Dell", "Diamond", "Digital", + "ELSA", "EONtronics", "Epson", "ExpertColor", + "Gainward", "Genoa", "Guillemot", + "Hercules", + "Intel", + "Jaton", + "LeadTek", + "MELCO", "MachSpeed", "Matrox", "Miro", + "NVIDIA", "NeoMagic", "Number Nine", + "Oak", "Octek", "Orchid", + "Paradise", "PixelView", + "Quantum", + "RIVA", "Real3D", "Rendition", + "S3", "Sharp", "SNI", "SPEA", "STB", "SiS", + "Sierra", "Sigma", "Silicon Motion", "Soyo", "Spider", "Sun", + "TechWorks", "Toshiba", "Trident", + "VideoLogic", "ViewTop", "Voodoo", + "WD", "Weitek", "WinFast"] + + def readCardsDB (self): + # all the straight servers + for server in [ "3DLabs", "8514", "FBDev", "I128", + "Mach8", "Mach32", "Mach64", "Mono", + "P9000", "S3", "S3V", "SVGA", "W32", "VGA16" ]: + Video_cardslist["Generic " + server] = { "SERVER" : server, + "NAME" : "Generic " + server } + + db = open ('/usr/X11R6/lib/X11/Cards') + lines = db.readlines () + db.close () + card = {} + name = None + for line in lines: + line = string.strip (line) + if not line and name: + Video_cardslist[name] = card + card = {} + name = None + continue + + if line and line[0] == '#': + continue + + if len (line) > 4 and line[0:4] == 'NAME': + name = line[5:] + + info = string.splitfields (line, ' ') + if card.has_key (info[0]): + card[info[0]] = card[info[0]] + '\n' + (string.joinfields (info[1:], ' ')) + else: + card[info[0]] = string.joinfields (info[1:], ' ') + + return + + def cardsDB(self): + return Video_cardslist + + def __str__(self): + retstr = "primary: %s\nvidCards: %s\n" % (self.primary, self.videocards) + if self.primaryCard(): + retstr = retstr + ("Primary Video Card Info:\n%s" % (str(self.primaryCard()))) + return retstr + + def reset(self): + self.videocards = copy.deepcopy(self.orig_videocards) + self.primary = self.orig_primary + + def __init__ (self, skipDDCProbe = 0): + + cards = kudzu.probe (kudzu.CLASS_VIDEO, + kudzu.BUS_UNSPEC, + kudzu.PROBE_ALL); + + # just use first video card we recognize + # store as a list of class VideoCard + self.videocards = [] + self.primary = None + + self.readCardsDB() + + for card in cards: + (device, server, descr) = card + + if len (server) > 9 and server[0:10] == "Server:Sun" and descr[0:4] == "Sun|": + server = "Card:Sun " + descr[4:] + if len (server) > 5 and server[0:5] == "Card:": +# info = self.cardsDBLookup (server[5:]) + info = Video_cardslist [server[5:]] + if len (server) > 7 and server[0:7] == "Server:": + info = { "NAME" : "Generic " + server[7:], + "SERVER" : server[7:] } + + if info: + vc = VideoCard() + vc.setProbedCard(server) + vc.setDevice(device) + vc.setDescription(descr) + vc.setCardData (info) + vc.setDevID (info["NAME"]) + + if (vc.getCardData().has_key("DRIVER") and + not vc.getCardData().has_key("UNSUPPORTED")): + server = "XFree86" + else: + server = "XF86_" + vc.getCardData()["SERVER"] + + vc.setXServer(server) + self.videocards.append(vc) + + + if len(self.videocards) == 0: + return + + # default primary card to be the first card found + self.primary = 0 + + # VESA probe for videoram, etc. + # for now assume fb corresponds to primary video card + if not skipDDCProbe: + try: + probe = string.split (iutil.execWithCapture ("/usr/sbin/ddcprobe", ['ddcprobe']), '\n') + for line in probe: + if line and line[:9] == "OEM Name:": + cardManf = string.strip (line[10:]) + self.primaryCard().setCardManf(cardManf) + self.primaryCard().getCardData()["VENDOR"] = cardManf + if line and line[:16] == "Memory installed": + memory = string.split (line, '=') + self.primaryCard().setVideoRam(string.strip (memory[2][:-2])) + except: + log("ddcprobe failed") + pass + + # try to get frame buffer information if we don't know video ram + if not self.primaryCard().getVideoRam() and self.primaryCard().getDevice(): + try: + (vidram, depth, mode, monitor) = isys.fbconProbe("/dev/" + self.primaryCard().getDevice()) + if vidram: + self.primaryCard().setVideoRam("%d" % vidram) + + if depth: + self.primaryCard().setFBModes({ "%d" % depth : [ mode ] }) + self.primaryCard().setFBBpp( "%d" % depth ) + except: + pass + + try: + if isys.fbinfo() != None: + x, y, depth = isys.fbinfo() + self.primaryCard().setFBBpp(depth) + except: + pass + + # kludge to handle i810 displays which require at least 16 Meg + if (self.primaryCard().getCardData()).has_key("DRIVER"): + cardData = self.primaryCard().getCardData() + if cardData["DRIVER"] == "i810": + self.primaryCard().setVideoRam("16384") + + + # save so we can reset + self.orig_videocards = copy.deepcopy(self.videocards) + self.orig_primary = self.primary + + +# +# XXX needed for kickstart only (via installclass.py::configureX()) +# some useful routines for setting videocard in various ways +# needs to be ported to new VideoCard object + + # pass videocard object for desired card; this sets card to be + # primary card + def setVidcard (self, videocard): + self.primary = self.videocards.index(videocard) + + + # find the appropriate videocard object for the requested card name + # this will only find the first instance of any card + def locateVidcardByName (self, card): + for vc in self.videocards: + print vc.getDescription() + if (vc.getDescription() == card): + return vc + raise RuntimeError, "Could not find valid video card driver" + + # find the appropriate videocard object for the requested server name + # this will only find the first instance of any card + def locateVidcardByServer (self, server): + for vc in self.videocards: + if (vc.getXServer() == server): + return vc + raise RuntimeError, "Could not find valid video card driver." diff --git a/xf86config.py b/xf86config.py index e274f8f22..07545d638 100644 --- a/xf86config.py +++ b/xf86config.py @@ -573,38 +573,42 @@ EndSection """ class XF86Config: - def __init__ (self, mouse = None, resolution = None): + def __init__ (self, video, monitor, mouse, resolution = None): + + if video: + self.setVideo(video) + else: + raise RuntimeError, "no videocard specified in XF86Config __init__" + + if monitor: + self.setMonitor(monitor) + else: + raise RuntimeError, "no monitor specified in XF86Config __init__" if mouse: self.setMouse(mouse) else: - self.mouse = Mouse (skipProbe = 1) - self.server = None - self.vidCards = [] - self.cardMan = None - self.vidRam = None - self.monEisa = None - self.monName = None - self.res = resolution + raise RuntimeError, "no mouse specified in XF86Config __init__" - self.monSect = "" - self.monID = "Unprobed Monitor" - self.state = "" - self.devID = None - self.probed = 0 self.skip = 0 - self.primary = 0 + self.res = resolution self.manualModes = {} + self.fallbackModes = {} + + + monsyncknown = (self.monitor.getMonitorHorizSync() != None) and (self.monitor.getMonitorVertSync() != None) if self.res == "640x480": self.modes = { "8" : ["640x480"] } - self.monHoriz = "31.5-35.5" - self.monVert = "50-61" + if not monsyncknown: + self.monitor.setSpecs("31.5-35.5", "50-61") else: self.modes = { "16" : ["800x600"] } - self.monHoriz = "31.5-48.5" - self.monVert = "50-70" + if not monsyncknown: + self.monitor.setSpecs("31.5-48.5", "50-70") + self.fallbackModes = self.modes + self.device = None self.keyRules = "xfree86" self.keyModel = "pc101" @@ -620,7 +624,7 @@ class XF86Config: self.monids = {} if isys.fbinfo() != None: - x, y, depth = isys.fbinfo() + (x, y, depth) = isys.fbinfo() self.fbDepth = depth else: self.fbDepth = 16 @@ -650,6 +654,12 @@ class XF86Config: def setMouse(self, mouse): self.mouse = mouse + def setVideo(self, video): + self.video = video + + def setMonitor(self, monitor): + self.monitor = monitor + def areaCompare (self, first, second): (sx1, sy1) = string.split (first, 'x') (sx2, sy2) = string.split (second, 'x') @@ -668,42 +678,47 @@ class XF86Config: def availableModes (self): modes = { "8" : [ "640x480" ] } - if not self.vidRam: + if not self.video: + return modes + + vidRam = self.video.primaryCard().getVideoRam() + + if not vidRam: return modes laptop = self.laptop() if laptop: return laptop - if string.atoi(self.vidRam) >= 8192: + if string.atoi(vidRam) >= 8192: modes["8"] = ["640x480", "800x600", "1024x768", "1152x864", "1280x1024", "1400x1050", "1600x1200"] modes["16"] = ["640x480", "800x600", "1024x768", "1152x864", "1280x1024", "1400x1050", "1600x1200"] modes["32"] = ["640x480", "800x600", "1024x768", "1152x864", "1280x1024", "1400x1050", "1600x1200"] return modes - elif string.atoi(self.vidRam) >= 6144: + elif string.atoi(vidRam) >= 6144: modes["8"] = ["640x480", "800x600", "1024x768", "1152x864", "1280x1024", "1400x1050", "1600x1200"] modes["16"] = ["640x480", "800x600", "1024x768", "1152x864", "1280x1024", "1400x1050", "1600x1200"] modes["32"] = ["640x480", "800x600", "1024x768", "1152x864", "1280x1024"] return modes - elif string.atoi(self.vidRam) >= 4096: + elif string.atoi(vidRam) >= 4096: modes["8"] = ["640x480", "800x600", "1024x768", "1152x864", "1280x1024"] modes["16"] = ["640x480", "800x600", "1024x768", "1152x864", "1280x1024"] modes["32"] = ["640x480", "800x600", "1024x768", "1152x864"] return modes - elif string.atoi(self.vidRam) >= 2048: + elif string.atoi(vidRam) >= 2048: modes["8"] = ["640x480", "800x600", "1024x768", "1152x864", "1280x1024"] modes["16"] = ["640x480", "800x600", "1024x768", "1152x864"] modes["32"] = ["640x480", "800x600"] return modes - elif string.atoi(self.vidRam) >= 1024: + elif string.atoi(vidRam) >= 1024: modes["8"] = ["640x480", "800x600", "1024x768", "1152x864"] modes["16"] = ["640x480", "800x600"] modes["32"] = [] return modes - elif string.atoi(self.vidRam) >= 512: + elif string.atoi(vidRam) >= 512: modes["8"] = ["640x480", "800x600"] modes["16"] = ["640x480"] modes["32"] = [] return modes - elif string.atoi(self.vidRam) >= 256: + elif string.atoi(vidRam) >= 256: modes["8"] = ["640x480"] return modes @@ -713,6 +728,21 @@ class XF86Config: def setModes(self, modes): self.modes = modes + def getModes(self): + return self.modes + + def setManualModes(self, modes): + self.manualModes = modes + + def getManualModes(self): + return self.manualModes + + def setFallBackModes(self, modes): + self.fallbackModes = modes + + def getFallBackModes(self): + return self.fallbackModes + def cards (self, thecard = None): cards = {} # all the straight servers @@ -762,7 +792,7 @@ class XF86Config: db = open ('/usr/X11R6/share/Xconfigurator/MonitorsDB') lines = db.readlines () db.close () - found = 0 + for line in lines: line = string.strip (line) if not line: @@ -782,179 +812,38 @@ class XF86Config: self.monids[eisa] = (man, model, eisa, vert, horiz) return self.monlist - def setMonitor (self, (monitor, (hrange, vrange))): - self.monName = monitor - self.monID = monitor - self.monHoriz = hrange - self.monVert = vrange - - # must pass card as a dictionary entry for desired card - def setVidcard (self, card): - self.vidCards = [card] - self.primary = 0 - - if self.vidCards: - self.devID = self.vidCards[self.primary]["NAME"] - if (self.vidCards[self.primary].has_key("DRIVER") and - not self.vidCards[self.primary].has_key("UNSUPPORTED")): - self.server = "XFree86" - else: - self.server = "XF86_" + self.vidCards[self.primary]["SERVER"] - - # locate dictionary entry for requested card name - # case matters - def locateVidcard (self, card): - cards = self.cards() - if cards.has_key(card): - return cards[card] - else: - return None - - # server is string name of X server (eg. "SVGA") - # case matters - def setVidcardByServer (self, server): - tmpcard = "Generic " + server - - entry = self.locateVidcard (tmpcard) - - if entry != None: - self.setVidcard (entry) - else: - raise RuntimeError, "Could not find valid video card driver." - - # card is string name of video card (eg. "Generic SVGA") - def setVidcardByName (self, card): - entry = self.locateVidcard (card) - - if entry != None: - self.setVidcard (entry) - else: - raise RuntimeError, "Could not find valid video card driver." - - def probe (self, probeMonitor = 1): -# XXX defer monitor probe, then re-enable this check -# if self.probed: -# return - self.probed = 1 - self.device = None - self.descr = None - self.primary = 0 - # PCI probe for video cards - sections = {} - - cards = [] - cards = kudzu.probe (kudzu.CLASS_VIDEO, - kudzu.BUS_UNSPEC, - kudzu.PROBE_ALL); - - for card in cards: - section = "" - (device, server, descr) = card - if device and not self.device: - self.device = device - self.primary = len(self.vidCards) - self.descr = descr - if len (server) > 9 and server[0:10] == "Server:Sun" and descr[0:4] == "Sun|": - server = "Card:Sun " + descr[4:] - if len (server) > 5 and server[0:5] == "Card:": - self.vidCards.append (self.cards (server[5:])) - if len (server) > 7 and server[0:7] == "Server:": - info = { "NAME" : "Generic " + server[7:], - "SERVER" : server[7:] } - self.vidCards.append (info) - - if self.vidCards: - self.devID = self.vidCards[self.primary]["NAME"] - if (self.vidCards[self.primary].has_key("DRIVER") and - not self.vidCards[self.primary].has_key("UNSUPPORTED")): - self.server = "XFree86" - else: - self.server = "XF86_" + self.vidCards[self.primary]["SERVER"] - - # VESA probe for monitor/videoram, etc. - if probeMonitor: - try: - probe = string.split (iutil.execWithCapture ("/usr/sbin/ddcprobe", ['ddcprobe']), '\n') - for line in probe: - if line and line[:9] == "OEM Name:": - self.cardMan = string.strip (line[10:]) - - if line and line[:16] == "Memory installed": - memory = string.split (line, '=') - self.vidRam = string.strip (memory[2][:-2]) - - if line and line[:8] == "EISA ID:": - self.monEisa = string.lower(line[9:]) - self.monID = line[9:] - - if line and line[:6] == "\tName:": - if not self.monName or len (self.monName) < len (line[7:]): - self.monName = line[7:] - - if line and line[:15] == "\tTiming ranges:": - ranges = string.split (line, ',') - self.monHoriz = string.strip (string.split (ranges[0], '=')[1]) - self.monVert = string.strip (string.split (ranges[1], '=')[1]) - - if self.vidCards and self.cardMan: - self.vidCards[self.primary]["VENDOR"] = self.cardMan - if self.monEisa: - # read the monitor DB - self.monitors() - if self.monids.has_key (self.monEisa): - (man, model, eisa, vert, horiz) = self.monids[self.monEisa] - self.monName = model - self.monID = model - self.monHoriz = horiz - self.monVert = vert - except: - pass - if not self.vidRam and self.device: - try: - (vidram, depth, mode, monitor) = isys.fbconProbe("/dev/" + self.device) - if vidram: - self.vidRam = "%d" % vidram - if depth: - self.modes = { "%d" % depth : [ mode ] } - self.monSect = monitor - self.bpp = "%d" % depth - except: - pass - - # kludge to handle i810 displays which require at least 16 Meg - if (self.vidCards - and self.vidCards[self.primary].has_key("DRIVER") - and (self.vidCards[self.primary]["DRIVER"] == "i810")): - self.vidRam = "16384" - def probeReport (self): probe = "" - if self.vidCards: - probe = probe + _("Video Card") + ": " + self.vidCards[self.primary]["NAME"] + "\n" - if self.vidRam: - probe = probe + "\t" + _("Video Ram") + ": " + self.vidRam + " kb\n" - if self.server: + if self.video: + primary = self.video.primaryCard() + vidCards = primary.getCardData() + + if vidCards: + probe = probe + _("Video Card") + ": " + vidCards["NAME"] + "\n" + if primary.getVideoRam(): + probe = probe + "\t" + _("Video Ram") + ": " + primary.getVideoRam() + " kb\n" + if primary.getXServer(): time.sleep(5) - probe = probe + "\t" + _("X server") + ": " + self.server + "\n" - if not self.server: + probe = probe + "\t" + _("X server") + ": " + primary.getXServer() + "\n" + else: time.sleep(5) probe = probe + "\t" + _("Unable to detect video card") return probe # disable monitor report - probe = probe + "\n" +# probe = probe + "\n" - if self.monName: - probe = probe + _("Monitor") + ": " + self.monName + "\n" - elif self.monEisa: - probe = probe + _("Monitor") + ": " + _("Plug and Play Monitor") + "\n" - if self.monHoriz: - probe = probe + "\t" + _("Horizontal frequency range") + ": " + self.monHoriz + " kHz\n" - if self.monHoriz: - probe = probe + "\t" + _("Vertical frequency range") + ": " + self.monVert + " Hz\n" +# if self.monName: +# probe = probe + _("Monitor") + ": " + self.monName + "\n" +# elif self.monEisa: +# probe = probe + _("Monitor") + ": " + _("Plug and Play Monitor") + "\n" +# if self.monHoriz: +# probe = probe + "\t" + _("Horizontal frequency range") + ": " + self.monHoriz + " kHz\n" +# if self.monHoriz: +# probe = probe + "\t" + _("Vertical frequency range") + ": " + self.monVert + " Hz\n" - return probe +# return probe def write (self, path): config = open (path + "/XF86Config", 'w') @@ -966,34 +855,78 @@ class XF86Config: return config = open (path + "/XF86Config-4", 'w') config.write (config4) - config.close () + config.close () + + def writeKS (self, f): + xmodes = self.getManualModes() + + if len(xmodes) == 0: + f.write("skipx\n") + return + + f.write("xconfig") + + for arg in self.getArgList(xmodes): + f.write(" " + arg) + f.write("\n") + + def getArgList(self, xmodes): + args = [] + vc = self.video.primaryCard() + + args = args + [ "--card", '"' + vc.shortDescription() + '"' ] + args = args + [ "--videoram", vc.getVideoRam() ] + args = args + [ "--hsync", self.monitor.getMonitorHorizSync() ] + args = args + [ "--vsync", self.monitor.getMonitorVertSync() ] + + # XXX this isn't really quite right, but it works for the way + # things are now + depths = xmodes.keys() + args = args + [ "--resolution", xmodes[depths[0]][0] ] + args = args + [ "--depth", depths[0] ] + + return args + def laptop (self): - if not self.descr: + + descr = self.video.primaryCard().getDescription() + if not descr: return None + # PCI descr, (horiz, vert), modes laptops = (("ATI|Rage Mobility", ("30-110", "60-110"), - { "8" : ["800x600", "1024x768", "1280x1024", "1400x1050"], - "16" : ["800x600", "1024x768", "1280x1024", "1400x1050"], - "32" : ["800x600", "1024x768", "1280x1024", "1400x1050"]}), + { "8" : ["800x600", "1024x768", "1400x1050"], + "16" : ["800x600", "1024x768", "1400x1050"], + "32" : ["800x600", "1024x768", "1400x1050"]}), ) for (card, (horiz, vert), modes) in laptops: - if (len(self.descr) >= len (card) - and self.descr[:len(card)] == card): - self.monHoriz = horiz - self.monVert = vert - self.monID = "Laptop Screen" + if (len(descr) >= len (card) + and descr[:len(card)] == card): + self.monitor.setSpecs(horiz, vert, id="Laptop Screen") return modes return None def test (self, serverflags=None, spawn=0): - if not self.server: -# print "self.server was None, doing nothing in test" + servername = self.video.primaryCard().getXServer() + if not servername: return files = self.files - modes = self.modes + laptop = self.laptop() + + # override modes if on a laptop + if laptop: + self.manualModes = laptop + + # save current manually selected mode, override if non-existant + manmodes = self.manualModes + if not manmodes: + if self.fallbackModes: + self.manualModes = self.fallbackModes + else: + self.manualModes = self.modes self.files = """ RgbPath "/usr/X11R6/lib/X11/rgb" @@ -1014,7 +947,7 @@ class XF86Config: """ f = open ('/tmp/XF86Config.test', 'w') - if self.server == "XFree86": + if servername == "XFree86": config = self.Version4Config else: config = self.Version3Config @@ -1022,16 +955,19 @@ class XF86Config: f.close () self.files = files - self.modes = modes - serverPath = "/usr/X11R6/bin/" + self.server + # restore manualmodes + self.manualModes = manmodes + + serverPath = "/usr/X11R6/bin/" + servername - server = os.fork() + print "forking" + serverpid = os.fork() - if (not server): + if (not serverpid): args = [serverPath, '-xf86config', '/tmp/XF86Config.test' ] logFile = "/tmp/X.log" - if self.server == "XFree86": + if servername == "XFree86": args = args + [ "-logfile", "/dev/null" ] if serverflags: args = args + serverflags @@ -1055,7 +991,7 @@ class XF86Config: if spawn: - return server + return serverpid child = os.fork() if (not child): @@ -1066,8 +1002,8 @@ class XF86Config: status = -1 try: pid, status = os.waitpid(child, 0) - os.kill (server, 15) - os.waitpid(server, 0) + os.kill (serverpid, 15) + os.waitpid(serverpid, 0) if not os.WIFEXITED (status) or os.WEXITSTATUS (status): if os.WEXITSTATUS (status) not in [ 0, 1, 2 ]: failed = 1 @@ -1081,43 +1017,46 @@ class XF86Config: info = {} devices = "" screens = "" - - for card in self.vidCards: - devices = devices + """ + + monitor = self.monitor + card = self.video.primaryCard() + carddata = card.getCardData() + devices = devices + """ Section "Device" Identifier "%(NAME)s" -""" % card - if card.has_key ("VENDOR"): - devices = devices + ' VendorName "%(VENDOR)s"\n' % card - if card.has_key ("BOARDNAME"): - devices = devices + ' BoardName "%(BOARD)s"\n' % card - if card.has_key ("RAMDAC"): - devices = devices + ' Ramdac "%(RAMDAC)s"\n' % card - if card.has_key ("LINE"): - devices = devices + card["LINE"] + "\n" - if self.vidRam: - devices = devices + ' VideoRam %s\n' % (self.vidRam,) - devices = devices + "EndSection\n" - - if self.devID: +""" % carddata + if carddata.has_key ("VENDOR"): + devices = devices + ' VendorName "%(VENDOR)s"\n' % carddata + if carddata.has_key ("BOARDNAME"): + devices = devices + ' BoardName "%(BOARD)s"\n' % carddata + if carddata.has_key ("RAMDAC"): + devices = devices + ' Ramdac "%(RAMDAC)s"\n' % carddata + if carddata.has_key ("LINE"): + devices = devices + carddata["LINE"] + "\n" + if card.getVideoRam(): + devices = devices + ' VideoRam %s\n' % (card.getVideoRam(),) + devices = devices + "EndSection\n" + + if card.getDevID(): screens = "" tmp = {} maxdepth = -1 - for (depth, modes) in self.modes.items (): + xmodes = self.manualModes + + for (depth, modes) in xmodes.items (): modes.sort (self.areaCompare) if len(modes) > 0 and string.atoi(depth) > maxdepth: maxdepth = string.atoi(depth) - if self.monSect: - monitor = "Probed Monitor" + if monitor.getFBMonitorSection(): + monitorname = "Probed Monitor" else: - monitor = self.monID - + monitorname = monitor.getMonitorID() for driver in [ "svga", "accel" ]: tmp["driver"] = driver - tmp["devID"] = self.devID - tmp["monitorID"] = monitor + tmp["devID"] = card.getDevID() + tmp["monitorID"] = monitorname screens = screens + """ # The %(driver)s server Section "Screen" @@ -1131,18 +1070,18 @@ Section "Screen" if self.res == "640x480": screens = screens + " DefaultColorDepth 8\n" elif maxdepth > 0: - if maxdepth > 16 and '16' in self.modes.keys() and self.modes['16']: + if maxdepth > 16 and '16' in xmodes.keys() and xmodes['16']: screens = screens + " DefaultColorDepth 16\n" else: screens = screens + " DefaultColorDepth %d\n" % maxdepth - for depth in self.modes.keys (): - if not self.modes[depth]: continue + for depth in xmodes.keys (): + if not xmodes[depth]: continue screens = screens + """ Subsection "Display" Depth %s Modes """ % depth - for res in self.modes[depth]: + for res in xmodes[depth]: screens = screens + '"' + res + '" ' screens = screens + """ ViewPort 0 0 @@ -1161,7 +1100,7 @@ Section "Screen" mouseProto = self.mouse.info['XMOUSETYPE'] info = { "acceleratedDevices" : devices, "acceleratedScreens" : screens, - "devID" : self.devID, + "devID" : card.getDevID(), "mouseProto" : mouseProto, "mouseDevice" : self.mouse.device, "XkbRules" : self.keyRules, @@ -1171,13 +1110,19 @@ Section "Screen" "enableVariant" : "#", "XkbOptions" : self.keyOptions, "enableOptions" : "#", - "monitorID" : self.monID, - "monitorHoriz" : self.monHoriz, - "monitorVert" : self.monVert, - "fbProbedMonitor" : self.monSect, + "monitorID" : monitor.getMonitorID(), + "monitorHoriz" : monitor.getMonitorHorizSync(), + "monitorVert" : monitor.getMonitorVertSync(), + "fbProbedMonitor" : monitor.getFBMonitorSection(), "files" : self.files, - "fbDepth" : self.fbDepth, } + + # HACK if no frame buffer running just wing it + if card.getFBBpp(): + info["fbDepth"] = card.getFBBpp() + else: + info["fbDepth"] = 8 + if self.keyVariant: info["enableVariant"] = "" if self.keyOptions: @@ -1194,15 +1139,16 @@ Section "Screen" return XF86Config_template % info def Version4Config(self, test=0): - if not self.vidCards: + if not self.video: raise RuntimeError, "No known video cards" screens = "" maxdepth = -1 - for depth in self.modes.keys (): - if not self.modes[depth]: continue + xmodes = self.manualModes + for depth in xmodes.keys (): + if not xmodes[depth]: continue if depth == "32": depth = "24" - self.modes["24"] = self.modes["32"] + xmodes["24"] = xmodes["32"] if maxdepth < string.atoi(depth): maxdepth = string.atoi(depth) screens = screens + """ @@ -1210,7 +1156,7 @@ Section "Screen" Depth %s Modes """ % depth - modes = self.modes[depth] + modes = xmodes[depth] modes.sort (self.areaCompare) for res in modes: screens = screens + '"' + res + '" ' @@ -1218,7 +1164,8 @@ Section "Screen" EndSubsection """ if depth == "24": - del self.modes["24"] + del xmodes["24"] + # XXX if we're going to be using IMPS/2 on # reboot, but we're using PS/2 now, we'll need # to temporarily use PS/2 so we don't frob the @@ -1234,14 +1181,26 @@ Section "Screen" emulate3 = "yes" else: emulate3 = "no" + + card = self.video.primaryCard() + carddata = card.getCardData() + monitor = self.monitor + + # set cardsoptions if unambiguous what version of XFree86 they + # apply to + cardoptions = " # no known options" + if carddata.has_key("DRIVER") and not carddata.has_key("SERVER"): + if carddata.has_key("LINE"): + cardoptions = carddata["LINE"] + data = { "mouseProto" : mouseProto, "mouseDevice" : self.mouse.device, - "cardsOptions" : " # no known options", - "cardID" : self.vidCards[self.primary]["NAME"], - "cardVendor" : self.vidCards[self.primary]["NAME"], - "cardBoardName": self.vidCards[self.primary]["NAME"], - "monitorHoriz" : self.monHoriz, - "monitorVert" : self.monVert, + "cardsOptions" : cardoptions, + "cardID" : carddata["NAME"], + "cardVendor" : carddata["NAME"], + "cardBoardName": carddata["NAME"], + "monitorHoriz" : monitor.getMonitorHorizSync(), + "monitorVert" : monitor.getMonitorVertSync(), "files" : self.files, "screenModes" : screens, "nonSparcMods" : '\n\tLoad "fbdevhw"', @@ -1267,7 +1226,7 @@ Section "Screen" data["enableOptions"] = "" if maxdepth > 0: - if maxdepth > 16 and '16' in self.modes.keys() and self.modes['16']: + if maxdepth > 16 and '16' in xmodes.keys() and xmodes['16']: data["defaultDepth"] = "\n\tDefaultDepth\t16" else: data["defaultDepth"] = "\n\tDefaultDepth\t%d" % maxdepth @@ -1278,10 +1237,10 @@ Section "Screen" data["autorepeat"] = '# Option "AutoRepeat" "200 20"' else: data["autorepeat"] = '# Option "AutoRepeat" "500 5"' - if self.vidCards[self.primary].has_key ("DRIVER"): - data["cardDriver"] = self.vidCards[self.primary]["DRIVER"] + if carddata.has_key ("DRIVER"): + data["cardDriver"] = carddata["DRIVER"] if data["cardDriver"] == "i810": - data["videoRam"] = "\tVideoRam %s\n" % self.vidRam + data["videoRam"] = "\tVideoRam %s\n" % card.getVideoRam() # DRI HACK! #if data["cardDriver"] == "r128" or data["cardDriver"] == "mga": # data["driMod"] = '\n\t#Load "dri"' |