From e1a7fe9887886044b07587b3ec2caa2ff53ebfb2 Mon Sep 17 00:00:00 2001 From: David Lehman Date: Mon, 23 Feb 2009 12:21:24 -0600 Subject: Updates to make existing code use the new storage module. --- anaconda | 3 +- backend.py | 7 +- bootloader.py | 51 +++----- dispatch.py | 10 +- exception.py | 2 +- installclass.py | 17 ++- installmethod.py | 6 +- instdata.py | 36 ++---- isys/isys.py | 358 +------------------------------------------------------ kickstart.py | 56 +++++---- livecd.py | 39 +++--- network.py | 4 +- packages.py | 137 ++++++++++++--------- rescue.py | 46 ++++--- upgrade.py | 207 +++++--------------------------- yuminstall.py | 26 ++-- 16 files changed, 236 insertions(+), 769 deletions(-) diff --git a/anaconda b/anaconda index f669ee0e8..199168b05 100755 --- a/anaconda +++ b/anaconda @@ -983,11 +983,10 @@ if __name__ == "__main__": # Skip the disk options in rootpath mode if flags.rootpath: - anaconda.dispatch.skipStep("partitionobjinit", permanent = 1) anaconda.dispatch.skipStep("parttype", permanent = 1) anaconda.dispatch.skipStep("autopartitionexecute", permanent = 1) anaconda.dispatch.skipStep("partition", permanent = 1) - anaconda.dispatch.skipStep("partitiondone", permanent = 1) + anaconda.dispatch.skipStep("storagedone", permanent = 1) anaconda.dispatch.skipStep("bootloader", permanent = 1) anaconda.dispatch.skipStep("bootloaderadvanced", permanent = 1) anaconda.dispatch.skipStep("upgbootloader", permanent = 1) diff --git a/backend.py b/backend.py index e8bcf4f5c..475785b12 100644 --- a/backend.py +++ b/backend.py @@ -85,8 +85,8 @@ class AnacondaBackend: # the initrd might need iscsi-initiator-utils, and chances are # it was not installed yet the first time mkinitrd was run, as # mkinitrd does not require it. - for disk in anaconda.id.diskset.disks.keys(): - if isys.driveIsIscsi(disk): + for disk in anaconda.id.storage.disks: + if isys.driveIsIscsi(disk.path): has_iscsi_disk = True break @@ -156,8 +156,9 @@ class AnacondaBackend: if not anaconda.mediaDevice or not os.path.exists(installimg): return + free = anaconda.id.storage.fsset.fsFreeSpace(anaconda.rootPath) self._loopbackFile = "%s%s/rhinstall-install.img" % (anaconda.rootPath, - anaconda.id.fsset.filesystemSpace(anaconda.rootPath)[0][0]) + free[0][0]) try: win = anaconda.intf.waitWindow(_("Copying File"), diff --git a/bootloader.py b/bootloader.py index b78cfd701..7ad11b4d5 100644 --- a/bootloader.py +++ b/bootloader.py @@ -60,49 +60,36 @@ def bootloaderSetupChoices(anaconda): anaconda.id.bootloader.updateDriveList(pref) if iutil.isEfi() and not anaconda.id.bootloader.device: - drives = anaconda.id.diskset.disks.keys() - drives.sort() bootPart = None - for drive in drives: - disk = anaconda.id.diskset.disks[drive] - for part in disk.partitions: - if part.active and partedUtils.isEfiSystemPartition(part): - bootPart = part.getDeviceNodeName() + partitions = anaconda.id.storage.partitions + for part in partitions: + if part.partedPartition.active and \ + partedUtils.isEfiSystemPartition(part.partedPartition): + bootPart = part.name break - if bootPart: - break if bootPart: anaconda.id.bootloader.setDevice(bootPart) - dev = Device() - dev.device = bootPart - anaconda.id.fsset.add(FileSystemSetEntry(dev, None, fileSystemTypeGet("efi"))) # iSeries bootloader on upgrades if iutil.getPPCMachine() == "iSeries" and not anaconda.id.bootloader.device: - drives = anaconda.id.diskset.disks.keys() - drives.sort() bootPart = None - for drive in drives: - disk = anaconda.id.diskset.disks[drive] - for part in disk.partitions: - if part.active and part.getFlag(parted.PARTITION_PREP): - bootPart = part.getDeviceNodeName() - break - if bootPart: + partitions = anaconda.id.storage.partitions + for part in partitions: + if part.partedPartition.active and \ + part.partedPartition.getFlag(parted.PARTITION_PREP): + bootPart = part.name break if bootPart: anaconda.id.bootloader.setDevice(bootPart) - dev = Device() - dev.device = bootPart - anaconda.id.fsset.add(FileSystemSetEntry(dev, None, fileSystemTypeGet("PPC PReP Boot"))) - choices = anaconda.id.fsset.bootloaderChoices(anaconda.id.diskset, anaconda.id.bootloader) + choices = anaconda.id.storage.fsset.bootloaderChoices(anaconda.id.bootloader) if not choices and iutil.getPPCMachine() != "iSeries": anaconda.dispatch.skipStep("instbootloader") else: anaconda.dispatch.skipStep("instbootloader", skip = 0) - anaconda.id.bootloader.images.setup(anaconda.id.diskset, anaconda.id.fsset) + # FIXME: ... + anaconda.id.bootloader.images.setup(anaconda.id.storage) if anaconda.id.bootloader.defaultDevice != None and choices: keys = choices.keys() @@ -150,11 +137,7 @@ def writeBootloader(anaconda): kernelList = [] otherList = [] - root = anaconda.id.fsset.getEntryByMountPoint('/') - if root: - rootDev = root.device.getDevice() - else: - rootDev = None + rootDev = getattr(anaconda.id.rootDevice, "path", None) defaultDev = anaconda.id.bootloader.images.getDefault() kernelLabel = None @@ -204,8 +187,10 @@ def writeBootloader(anaconda): dosync() try: - anaconda.id.bootloader.write(anaconda.rootPath, anaconda.id.fsset, anaconda.id.bootloader, - anaconda.id.instLanguage, kernelList, otherList, defaultDev, + anaconda.id.bootloader.write(anaconda.rootPath, anaconda.id.storage, + anaconda.id.bootloader, + anaconda.id.instLanguage, + kernelList, otherList, defaultDev, justConfigFile, anaconda.intf) if not justConfigFile: w.pop() diff --git a/dispatch.py b/dispatch.py index b773404dd..a09a86183 100644 --- a/dispatch.py +++ b/dispatch.py @@ -34,8 +34,9 @@ from packages import setupTimezone from packages import setFileCons from packages import regKeyScreen from packages import writeRegKey -from partitions import partitionObjectsInitialize -from partitions import partitioningComplete +from storage import storageInitialize +from storage import storageComplete +from storage.partitioning import doAutoPartition from bootloader import writeBootloader, bootloaderSetupChoices from flags import flags from upgrade import upgradeMountFilesystems, queryUpgradeArch @@ -71,13 +72,13 @@ installSteps = [ ("keyboard", ), ("betanag", betaNagScreen, ), ("regkey", regKeyScreen, ), + ("storageinit", storageInitialize, ), ("findrootparts", findRootParts, ), ("findinstall", ), ("network", ), ("timezone", ), ("accounts", ), ("setuptime", setupTimezone, ), - ("partitionobjinit", partitionObjectsInitialize, ), ("parttype", ), ("autopartitionexecute", doAutoPartition, ), ("partition", ), @@ -88,8 +89,7 @@ installSteps = [ ("addswap", ), ("upgrademigfind", upgradeMigrateFind, ), ("upgrademigratefs", ), - ("partitiondone", partitioningComplete, ), - ("migratefilesystems", doMigrateFilesystems, ), + ("storagedone", storageComplete, ), ("enablefilesystems", turnOnFilesystems, ), ("upgbootloader", ), ("bootloadersetup", bootloaderSetupChoices, ), diff --git a/exception.py b/exception.py index 7b6fdea9d..681b3ec5d 100644 --- a/exception.py +++ b/exception.py @@ -223,7 +223,7 @@ class AnacondaExceptionDump: for file in ("/tmp/syslog", "/tmp/anaconda.log", "/tmp/lvmout", "/tmp/resize.out", - "/tmp/program.log", + "/tmp/program.log", "/tmp/storage.log", anaconda.rootPath + "/root/install.log", anaconda.rootPath + "/root/upgrade.log"): try: diff --git a/installclass.py b/installclass.py index a3a97aed5..4a1e95269 100644 --- a/installclass.py +++ b/installclass.py @@ -96,14 +96,14 @@ class BaseInstallClass(object): "language", "keyboard", "welcome", + "storageinit", "findrootparts", "betanag", "installtype", - "partitionobjinit", "parttype", "autopartitionexecute", "partition", - "partitiondone", + "storagedone", "bootloadersetup", "bootloader", "network", @@ -116,7 +116,6 @@ class BaseInstallClass(object): "confirminstall", "install", "enablefilesystems", - "migratefilesystems", "setuptime", "preinstallconfig", "installpackages", @@ -188,11 +187,11 @@ class BaseInstallClass(object): from backend import AnacondaBackend return AnacondaBackend - def setDefaultPartitioning(self, partitions, clear = CLEARPART_TYPE_LINUX, + def setDefaultPartitioning(self, storage, clear = CLEARPART_TYPE_LINUX, doClear = 1, useLVM = True): autorequests = [ ("/", None, 1024, None, 1, 1, 1) ] - bootreq = getAutopartitionBoot(partitions) + bootreq = getAutopartitionBoot(storage) if bootreq: autorequests.extend(bootreq) @@ -200,13 +199,13 @@ class BaseInstallClass(object): autorequests.append((None, "swap", minswap, maxswap, 1, 1, 1)) if doClear: - partitions.autoClearPartType = clear - partitions.autoClearPartDrives = [] + storage.autoClearPartType = clear + storage.autoClearPartDrives = [] if useLVM: - partitions.autoPartitionRequests = autoCreateLVMPartitionRequests(autorequests) + storage.autoPartitionRequests = autoCreateLVMPartitionRequests(autorequests) else: - partitions.autoPartitionRequests = autoCreatePartitionRequests(autorequests) + storage.autoPartitionRequests = autoCreatePartitionRequests(autorequests) def setInstallData(self, anaconda): diff --git a/installmethod.py b/installmethod.py index ce1dd7f99..d62201583 100644 --- a/installmethod.py +++ b/installmethod.py @@ -47,9 +47,9 @@ def doMethodComplete(anaconda): isys.ejectCdrom(dev) mtab = "/dev/root / ext3 ro 0 0\n" - for ent in anaconda.id.fsset.entries: - if ent.mountpoint == "/": - mtab = "/dev/root / %s ro 0 0\n" %(ent.fsystem.name,) + rootDevice = anaconda.id.storage.rootDevice + if rootDevice: + mtab = "/dev/root / %s ro 0 0\n" % rootDevice.format.type f = open(anaconda.rootPath + "/etc/mtab", "w+") f.write(mtab) diff --git a/instdata.py b/instdata.py index 25aee6157..86f389363 100644 --- a/instdata.py +++ b/instdata.py @@ -30,12 +30,8 @@ import firewall import security import timezone import desktop -import fsset import bootloader -import partitions -import partedUtils -import iscsi -import zfcp +import storage import urllib import iutil import isys @@ -67,8 +63,6 @@ class InstallData: self.instClass = None self.network = network.Network() - self.iscsi = iscsi.iscsi() - self.zfcp = zfcp.ZFCP() self.firewall = firewall.Firewall() self.security = security.Security() self.timezone = timezone.Timezone() @@ -80,10 +74,7 @@ class InstallData: self.upgrade = None if flags.cmdline.has_key("preupgrade"): self.upgrade = True - # XXX move fsset and/or diskset into Partitions object? - self.fsset.reset() - self.diskset = partedUtils.DiskSet(self.anaconda) - self.partitions = partitions.Partitions(self.anaconda) + self.storage = storage.Storage(self.anaconda) self.bootloader = bootloader.getBootloader() self.upgradeRoot = None self.rootParts = None @@ -102,19 +93,13 @@ class InstallData: if os.path.exists("/dev/live") and \ stat.S_ISBLK(os.stat("/dev/live")[stat.ST_MODE]): target = os.readlink("/dev/live") - self.partitions.protected = [target] + self.storage.protectedPartitions = [target] elif self.anaconda.methodstr and self.anaconda.methodstr.startswith("hd:"): method = self.anaconda.methodstr[3:] - device = method.split(":", 3)[0] + devspec = method.split(":", 3)[0] - if device.startswith("LABEL="): - dev = isys.getDeviceByToken("LABEL", device[6:]) - elif device.startswith("UUID="): - dev = isys.getDeviceByToken("UUID", device[5:]) - else: - dev = device - - if dev is None: + device = storage.resolveDevice(devspec) + if device is None: if self.getUpgrade(): return else: @@ -125,10 +110,7 @@ class InstallData: type="custom", custom_buttons = [_("_Exit installer")]) sys.exit(1) - if dev.startswith("/dev/"): - dev = dev[5:] - - self.partitions.protected = [dev] + self.storage.protectedPartitions = [device.name] def setInstallProgressClass(self, c): self.instProgress = c @@ -286,7 +268,6 @@ class InstallData: if not self.isHeadless: self.keyboard.writeKS(f) self.network.writeKS(f) - self.zfcp.writeKS(f) if self.rootPassword["isCrypted"]: args = " --iscrypted %s" % self.rootPassword["password"] @@ -312,7 +293,7 @@ class InstallData: self.security.writeKS(f) self.timezone.writeKS(f) self.bootloader.writeKS(f) - self.partitions.writeKS(f) + self.storage.writeKS(f) # FIXME: unimplemented if self.backend is not None: self.backend.writeKS(f) @@ -339,6 +320,5 @@ class InstallData: self.videocard = None self.isHeadless = 0 self.extraModules = extraModules - self.fsset = fsset.FileSystemSet() self.reset() diff --git a/isys/isys.py b/isys/isys.py index e6c4b3476..fb2fa5d57 100755 --- a/isys/isys.py +++ b/isys/isys.py @@ -59,7 +59,6 @@ NM_STATE_CONNECTED = 3 NM_STATE_DISCONNECTED = 4 mountCount = {} -raidCount = {} MIN_RAM = _isys.MIN_RAM MIN_GUI_RAM = _isys.MIN_GUI_RAM @@ -71,194 +70,12 @@ EARLY_SWAP_RAM = _isys.EARLY_SWAP_RAM def pathSpaceAvailable(path): return _isys.devSpaceFree(path) -mdadmOutput = "/tmp/mdadmout" - -## An error occured when running mdadm. -class MdadmError(Exception): - ## The constructor. - # @param args The arguments passed to the mdadm command. - # @param name The the name of the RAID device used in the mdadm command. - def __init__(self, args, name=None): - self.args = args - self.name = name - self.log = self.getCmdOutput() - - ## Get the output of the last mdadm command run. - # @return The formatted output of the mdadm command which caused an error. - def getCmdOutput(self): - f = open(mdadmOutput, "r") - lines = reduce(lambda x,y: x + [string.strip(y),], f.readlines(), []) - lines = string.join(reduce(lambda x,y: x + [" %s" % (y,)], \ - lines, []), "\n") - return lines - - def __str__(self): - s = "" - if not self.name is None: - s = " for device %s" % (self.name,) - command = "mdadm " + string.join(self.args, " ") - return "'%s' failed%s\nLog:\n%s" % (command, s, self.log) - -def _mdadm(*args): - try: - lines = iutil.execWithCapture("mdadm", args, stderr = mdadmOutput) - lines = string.split(lines, '\n') - lines = reduce(lambda x,y: x + [y.strip(),], lines, []) - return lines - except: - raise MdadmError, args - -def _getRaidInfo(drive): - log.info("mdadm -E %s" % (drive,)) - try: - lines = _mdadm("-E", drive) - except MdadmError: - ei = sys.exc_info() - ei[1].name = drive - raise ei[0], ei[1], ei[2] - - info = { - 'major': "-1", - 'minor': "-1", - 'uuid' : "", - 'level': -1, - 'nrDisks': -1, - 'totalDisks': -1, - 'mdMinor': -1, - } - - for line in lines: - vals = string.split(string.strip(line), ' : ') - if len(vals) != 2: - continue - if vals[0] == "Version": - vals = string.split(vals[1], ".") - info['major'] = vals[0] - info['minor'] = vals[1] - elif vals[0] == "UUID": - info['uuid'] = vals[1] - elif vals[0] == "Raid Level": - info['level'] = int(vals[1][4:]) - elif vals[0] == "Raid Devices": - info['nrDisks'] = int(vals[1]) - elif vals[0] == "Total Devices": - info['totalDisks'] = int(vals[1]) - elif vals[0] == "Preferred Minor": - info['mdMinor'] = int(vals[1]) - else: - continue - - if info['uuid'] == "": - raise ValueError, info - - return info - -def _stopRaid(mdDevice): - log.info("mdadm --stop %s" % (mdDevice,)) - try: - _mdadm("--stop", mdDevice) - except MdadmError: - ei = sys.exc_info() - ei[1].name = mdDevice - raise ei[0], ei[1], ei[2] - -def raidstop(mdDevice): - log.info("stopping raid device %s" %(mdDevice,)) - if raidCount.has_key (mdDevice): - if raidCount[mdDevice] > 1: - raidCount[mdDevice] = raidCount[mdDevice] - 1 - return - del raidCount[mdDevice] - - devInode = "/dev/%s" % mdDevice - - try: - _stopRaid(devInode) - except: - pass - -def _startRaid(mdDevice, mdMinor, uuid): - log.info("mdadm -A --uuid=%s --super-minor=%s %s" % (uuid, mdMinor, mdDevice)) - try: - _mdadm("-A", "--uuid=%s" % (uuid,), "--super-minor=%s" % (mdMinor,), \ - mdDevice) - except MdadmError: - ei = sys.exc_info() - ei[1].name = mdDevice - raise ei[0], ei[1], ei[2] - -def raidstart(mdDevice, aMember): - log.info("starting raid device %s" %(mdDevice,)) - if raidCount.has_key(mdDevice) and raidCount[mdDevice]: - raidCount[mdDevice] = raidCount[mdDevice] + 1 - return - - raidCount[mdDevice] = 1 - - mdInode = "/dev/%s" % mdDevice - mbrInode = "/dev/%s" % aMember - - if os.path.exists(mdInode): - minor = os.minor(os.stat(mdInode).st_rdev) - else: - minor = int(mdDevice[2:]) - try: - info = _getRaidInfo(mbrInode) - if info.has_key('mdMinor'): - minor = info['mdMinor'] - _startRaid(mdInode, minor, info['uuid']) - except: - pass - -## Remove the superblock from a RAID device. -# @param device The complete path to the RAID device name to wipe. -def wipeRaidSB(device): - try: - fd = os.open(device, os.O_WRONLY) - except OSError, e: - log.warning("error wiping raid device superblock for %s: %s", device, e) - return - - try: - _isys.wiperaidsb(fd) - finally: - os.close(fd) - return - -## Get the raw superblock from a RAID device. -# @param The basename of a RAID device to check. This device node does not -# need to exist to begin with. -# @return A RAID superblock in its raw on-disk format. -def raidsb(mdDevice): - return raidsbFromDevice("/dev/%s" % mdDevice) - -## Get the superblock from a RAID device. -# @param The full path to a RAID device name to check. This device node must -# already exist. -# @return A tuple of the contents of the RAID superblock, or ValueError on -# error. -def raidsbFromDevice(device): - try: - info = _getRaidInfo(device) - return (info['major'], info['minor'], info['uuid'], info['level'], - info['nrDisks'], info['totalDisks'], info['mdMinor']) - except: - raise ValueError - -def getRaidChunkFromDevice(device): - fd = os.open(device, os.O_RDONLY) - rc = 64 - try: - rc = _isys.getraidchunk(fd) - finally: - os.close(fd) - return rc - ## Set up an already existing device node to be used as a loopback device. # @param device The full path to a device node to set up as a loopback device. # @param file The file to mount as loopback on device. # @param readOnly Should this loopback device be used read-only? def losetup(device, file, readOnly = 0): + # FIXME: implement this as a storage.devices.Device subclass if readOnly: mode = os.O_RDONLY else: @@ -272,6 +89,7 @@ def losetup(device, file, readOnly = 0): os.close(targ) def lochangefd(device, file): + # FIXME: implement this as a storage.devices.Device subclass loop = os.open(device, os.O_RDONLY) targ = os.open(file, os.O_RDONLY) try: @@ -283,6 +101,7 @@ def lochangefd(device, file): ## Disable a previously setup loopback device. # @param device The full path to an existing loopback device node. def unlosetup(device): + # FIXME: implement this as a storage.devices.Device subclass loop = os.open(device, os.O_RDONLY) try: _isys.unlosetup(loop) @@ -407,175 +226,6 @@ def swapon (path): def loadKeymap(keymap): return _isys.loadKeymap (keymap) -cachedDrives = None - -## Clear the drive dict cache. -# This method clears the drive dict cache. If the drive state changes (by -# loading and unloading modules, attaching removable devices, etc.) then this -# function must be called before any of the *DriveDict or *DriveList functions. -# If not, those functions will return information that does not reflect the -# current machine state. -def flushDriveDict(): - global cachedDrives - cachedDrives = None - -def driveDict(klassArg): - import parted - global cachedDrives - if cachedDrives is None: - new = {} - for dev in minihal.get_devices_by_type("storage"): - if dev['device'] is None: # none devices make no sense - continue - - device = dev['device'].replace('/dev/','') - # we can't actually use the sg devices, so ignore them - if device.startswith("sg"): - log.info("ignoring sg device %s" %(device,)) - continue - - # we can't actually use the st devices, so ignore them - if device.startswith("st"): - log.info("ignoring st device %s" %(device,)) - continue - - # we want to ignore md devices as they're not hard disks in our pov - if device.startswith("md"): - continue - - if dev['storage.drive_type'] != 'disk': - new[device] = dev - continue - try: - if not mediaPresent (device): - new[device] = dev - continue - - # blacklist the device which the live image is running from - # installing over that is almost certainly the wrong - # thing to do. - if os.path.exists("/dev/live") and \ - stat.S_ISBLK(os.stat("/dev/live")[stat.ST_MODE]): - livetarget = os.path.realpath("/dev/live") - if livetarget.startswith(dev['device']): - log.info("%s looks to be the live device; ignoring" % (device,)) - continue - - if device.startswith("sd"): - peddev = parted.getDevice(dev['device']) - model = peddev.model - - # blacklist *STMF on power5 iSeries boxes - if iutil.isPPC() and \ - model.find("IBM *STMF KERNEL") != -1: - log.info("%s looks like STMF, ignoring" % (device,)) - del peddev - continue - - # blacklist PS3 flash - if iutil.isPPC() and \ - model.find("SCEI Flash-5") != -1: - log.info("%s looks like PS3 flash, ignoring" % \ - (device,)) - del peddev - continue - - # blacklist DGC/EMC LUNs for which we have no ACL. - # We should be ignoring LUN_Z for all vendors, but I - # don't know how (if) other vendors encode this into - # the model info. - # - # XXX I need to work some SCC2 LUN mode page detection - # into libbdevid, and then this should use that instead. - # -- pjones - if str(peddev.model) == "DGC LUNZ": - log.info("%s looks like a LUN_Z device, ignoring" % \ - (device,)) - del peddev - continue - - del peddev - new[device] = dev - except Exception, e: - log.debug("exception checking disk blacklist on %s: %s" % \ - (device, e)) - cachedDrives = new - - ret = {} - for key,dev in cachedDrives.items(): - # XXX these devices should have deviceclass attributes. Or they - # should all be subclasses in a device tree and we should be able - # to use isinstance on all of them. Not both. - if isinstance(dev, block.MultiPath) or isinstance(dev, block.RaidSet): - if klassArg == "disk": - ret[key] = dev - elif dev['storage.drive_type'] == klassArg: - ret[key] = dev - return ret - -## Get all the hard drives attached to the system. -# This method queries the drive dict cache for all hard drives. If the cache -# is empty, this will cause all disk devices to be probed. If the status of -# the devices has changed, flushDriveDict must be called first. -# -# @see flushDriveDict -# @see driveDict -# @return A dict of all the hard drive descriptions, keyed on device name. -def hardDriveDict(): - ret = {} - dict = driveDict("disk") - for item in dict.keys(): - try: - ret[item] = dict[item]['description'] - except AttributeError: - ret[item] = "" - return ret - -## Get all the removable drives attached to the system. -# This method queries the drive dict cache for all removable drives. If the cache -# is empty, this will cause all disk devices to be probed. If the status of -# the devices has changed, flushDriveDict must be run called first. -# -# @see flushDriveDict -# @see driveDict -# @return A dict of all the removable drive descriptions, keyed on device name. -def removableDriveDict(): - ret = {} - dict = driveDict("disk") - for item in dict.keys(): - if dict[item]['storage.removable'] != 0: - try: - ret[item] = dict[item]['description'] - except AttributeError: - ret[item] = "" - return ret - -## Get all CD/DVD drives attached to the system. -# This method queries the drive dict cache for all hard drives. If the cache -# is empty, this will cause all disk devices to be probed. If the status of -# the devices has changed, flushDriveDict must be called first. -# -# @see flushDriveDict -# @see driveDict -# @return A sorted list of all the CD/DVD drives, without any leading /dev/. -def cdromList(): - list = driveDict("cdrom").keys() - list.sort() - return list - -## Get all tape drives attached to the system. -# This method queries the drive dict cache for all hard drives. If the cache -# is empty, this will cause all disk devices to be probed. If the status of -# the devices has changed, flushDriveDict must be called first. -# -# @see flushDriveDict -# @see driveDict -# @return A sorted list of all the tape drives, without any leading /dev/. -def tapeDriveList(): - list = driveDict("tape").keys() - list.sort() - return list - def getDasdPorts(): return _isys.getDasdPorts() @@ -788,6 +438,7 @@ def ext2HasJournal(device): return hasjournal def ejectCdrom(device): + # XXX this should go into storage.devices.OpticalDevice if not os.path.exists(device): device = "/dev/%s" % device @@ -834,6 +485,7 @@ def driveUsesModule(device, modules): # @param device The basename of the device node. # @return True if media is present in device, False otherwise. def mediaPresent(device): + # XXX this should go into storage.devices.RemovableDevice or similar try: fd = os.open("/dev/%s" % device, os.O_RDONLY) except OSError, (errno, strerror): diff --git a/kickstart.py b/kickstart.py index 9a7099f25..0fee19e07 100644 --- a/kickstart.py +++ b/kickstart.py @@ -24,13 +24,11 @@ import isys import os import tempfile from autopart import * -from fsset import * from flags import flags from constants import * import sys import raid import string -import partRequests import urlgrabber.grabber as grabber import lvm import warnings @@ -149,8 +147,8 @@ class AutoPart(commands.autopart.F9_AutoPart): self.handler.id.instClass.setDefaultPartitioning(self.handler.id, doClear = 0) if self.encrypted: - self.handler.id.partitions.autoEncrypt = True - self.handler.id.partitions.encryptionPassphrase = self.passphrase + self.handler.id.storage.autoEncrypt = True + self.handler.id.storage.encryptionPassphrase = self.passphrase self.handler.skipSteps.extend(["partition", "zfcpconfig", "parttype"]) return retval @@ -181,7 +179,11 @@ class Bootloader(commands.bootloader.F8_Bootloader): self.handler.id.bootloader.doUpgradeOnly = 1 if self.driveorder: - hds = isys.hardDriveDict().keys() + # XXX I don't like that we are supposed to have scanned the + # storage devices already and yet we cannot know about + # ignoredDisks, exclusiveDisks, or iscsi disks before we + # have processed the kickstart config file. + hds = [d.name for d in self.handler.id.storage.disks] for disk in self.driveorder: if disk not in hds: raise KickstartValueError, formatErrorMsg(self.lineno, msg="Specified nonexistent disk %s in driveorder command" % disk) @@ -238,10 +240,10 @@ class ClearPart(commands.clearpart.FC3_ClearPart): if disk not in hds: raise KickstartValueError, formatErrorMsg(self.lineno, msg="Specified nonexistent disk %s in clearpart command" % disk) - self.handler.id.partitions.autoClearPartType = self.type - self.handler.id.partitions.autoClearPartDrives = self.drives + self.handler.id.storage.autoClearPartType = self.type + self.handler.id.storage.autoClearPartDrives = self.drives if self.initAll: - self.handler.id.partitions.reinitializeDisks = self.initAll + self.handler.id.storage.reinitializeDisks = self.initAll return retval @@ -269,15 +271,13 @@ class IgnoreDisk(commands.ignoredisk.F8_IgnoreDisk): def parse(self, args): retval = commands.ignoredisk.F8_IgnoreDisk.parse(self, args) - diskset = self.handler.id.diskset for drive in self.ignoredisk: - if not drive in diskset.skippedDisks: - diskset.skippedDisks.append(drive) + if not drive in self.handler.id.storage.ignoredDisks: + self.handler.id.storage.ignoredDisks.append(drive) - diskset = self.handler.id.diskset for drive in self.onlyuse: - if not drive in diskset.exclusiveDisks: - diskset.exclusiveDisks.append(drive) + if not drive in self.handler.id.storage.exclusiveDisks: + self.handler.id.storage.exclusiveDisks.append(drive) return retval @@ -304,8 +304,6 @@ class Iscsi(commands.iscsi.F10_Iscsi): if self.handler.id.iscsi.addTarget(**kwargs): log.info("added iscsi target: %s" %(target.ipaddr,)) - # FIXME: flush the drive dict so we figure drives out again - isys.flushDriveDict() return retval class IscsiName(commands.iscsiname.FC6_IscsiName): @@ -359,7 +357,7 @@ class LogVol(commands.logvol.F9_LogVol): except KeyError: raise KickstartValueError, formatErrorMsg(self.lineno, msg="No volume group exists with the name '%s'. Specify volume groups before logical volumes." % lvd.vgname) - for areq in self.handler.id.partitions.autoPartitionRequests: + for areq in self.handler.id.storage.autoPartitionRequests: if areq.type == REQUEST_LV: if areq.volumeGroup == vgid and areq.logicalVolumeName == lvd.name: raise KickstartValueError, formatErrorMsg(self.lineno, msg="Logical volume name already used in volume group %s" % lvd.vgname) @@ -395,8 +393,8 @@ class LogVol(commands.logvol.F9_LogVol): if lvd.encrypted: if lvd.passphrase and \ - not self.handler.anaconda.id.partitions.encryptionPassphrase: - self.handler.anaconda.id.partitions.encryptionPassphrase = lvd.passphrase + not self.handler.anaconda.id.storage.encryptionPassphrase: + self.handler.anaconda.id.storage.encryptionPassphrase = lvd.passphrase request.encryption = cryptodev.LUKSDevice(passphrase=lvd.passphrase, format=lvd.format) addPartRequest(self.handler.anaconda, request) @@ -635,7 +633,7 @@ class Partition(commands.partition.F9_Partition): request.uniqueID = uniqueID if pd.onPart != "": request.device = pd.onPart - for areq in self.handler.id.partitions.autoPartitionRequests: + for areq in self.handler.id.storage.autoPartitionRequests: if areq.device is not None and areq.device == pd.onPart: raise KickstartValueError, formatErrorMsg(self.lineno, "Partition already used") @@ -644,8 +642,8 @@ class Partition(commands.partition.F9_Partition): if pd.encrypted: if pd.passphrase and \ - not self.handler.anaconda.id.partitions.encryptionPassphrase: - self.handler.anaconda.id.partitions.encryptionPassphrase = pd.passphrase + not self.handler.anaconda.id.storage.encryptionPassphrase: + self.handler.anaconda.id.storage.encryptionPassphrase = pd.passphrase request.encryption = cryptodev.LUKSDevice(passphrase=pd.passphrase, format=pd.format) addPartRequest(self.handler.anaconda, request) @@ -728,8 +726,8 @@ class Raid(commands.raid.F9_Raid): if rd.encrypted: if rd.passphrase and \ - not self.handler.anaconda.id.partitions.encryptionPassphrase: - self.handler.anaconda.id.partitions.encryptionPassphrase = rd.passphrase + not self.handler.anaconda.id.storage.encryptionPassphrase: + self.handler.anaconda.id.storage.encryptionPassphrase = rd.passphrase request.encryption = cryptodev.LUKSDevice(passphrase=rd.passphrase, format=rd.format) addPartRequest(self.handler.anaconda, request) @@ -830,7 +828,7 @@ class XConfig(commands.xconfig.F10_XConfig): class ZeroMbr(commands.zerombr.FC3_ZeroMbr): def parse(self, args): retval = commands.zerombr.FC3_ZeroMbr.parse(self, args) - self.handler.id.partitions.zeroMbr = 1 + self.handler.id.storage.zeroMbr = 1 return retval class ZFCP(commands.zfcp.FC3_ZFCP): @@ -1002,14 +1000,14 @@ class AnacondaKSParser(KickstartParser): # else with this mountpoint so that you can use autopart and override / def addPartRequest(anaconda, request): if not request.mountpoint: - anaconda.id.partitions.autoPartitionRequests.append(request) + anaconda.id.storage.autoPartitionRequests.append(request) return - for req in anaconda.id.partitions.autoPartitionRequests: + for req in anaconda.id.storage.autoPartitionRequests: if req.mountpoint and req.mountpoint == request.mountpoint: - anaconda.id.partitions.autoPartitionRequests.remove(req) + anaconda.id.storage.autoPartitionRequests.remove(req) break - anaconda.id.partitions.autoPartitionRequests.append(request) + anaconda.id.storage.autoPartitionRequests.append(request) def processKickstartFile(anaconda, file): # make sure our disks are alive diff --git a/livecd.py b/livecd.py index 5d7d3f7b7..695f241d6 100644 --- a/livecd.py +++ b/livecd.py @@ -41,7 +41,6 @@ _ = lambda x: gettext.ldgettext("anaconda", x) import backend import isys import iutil -import fsset import packages @@ -174,16 +173,9 @@ class LiveCDCopyBackend(backend.AnacondaBackend): osimg = self._getLiveBlockDevice() # the real image osfd = os.open(osimg, os.O_RDONLY) - r = anaconda.id.fsset.getEntryByMountPoint("/") - rootfs = r.device.setupDevice() - rootfd = os.open(rootfs, os.O_WRONLY) - - # set the rootfs to have the right type. this lets things work - # given ext2 or ext3 (and in the future, ext4) - # FIXME: should we try to migrate if there isn't a match? - roottype = isys.readFSType(osimg) - if roottype is not None: - r.fsystem = fsset.fileSystemTypeGet(roottype) + rootDevice = anaconda.id.fsset.rootDevice + rootDevice.setup() + rootfd = os.open(rootDevice.path, os.O_WRONLY) readamt = 1024 * 1024 * 8 # 8 megs at a time size = self._getLiveSize() @@ -222,6 +214,7 @@ class LiveCDCopyBackend(backend.AnacondaBackend): anaconda.id.instProgress = None def _doFilesystemMangling(self, anaconda): + # FIXME: this whole method is a big fucking mess log.info("doing post-install fs mangling") wait = anaconda.intf.waitWindow(_("Doing post-installation"), _("Performing post-installation filesystem changes. This may take several minutes...")) @@ -233,12 +226,16 @@ class LiveCDCopyBackend(backend.AnacondaBackend): anaconda.id.fsset.mountFilesystems(anaconda) # restore the label of / to what we think it is - r = anaconda.id.fsset.getEntryByMountPoint("/") - anaconda.id.fsset.labelEntry(r, anaconda.rootPath, True) + rootDevice = anaconda.id.fsset.rootDevice + rootDevice.setup() # ensure we have a random UUID on the rootfs # FIXME: this should be abstracted per filesystem type - iutil.execWithRedirect("tune2fs", ["-U", "random", "/dev/%s" % (r.device.getDevice())], - stdout="/dev/tty5", stderr="/dev/tty5", + iutil.execWithRedirect("tune2fs", + ["-U", + "random", + rootDevice.path], + stdout="/dev/tty5", + stderr="/dev/tty5", searchPath = 1) # for any filesystem that's _not_ on the root, we need to handle @@ -246,6 +243,7 @@ class LiveCDCopyBackend(backend.AnacondaBackend): # this is pretty distasteful, but should work with things like # having a separate /usr/local + # XXX wow, what in the hell is going on here? # get a list of fsset entries that are relevant entries = sorted(filter(lambda e: not e.fsystem.isKernelFS() and \ e.getMountPoint(), anaconda.id.fsset.entries)) @@ -314,13 +312,12 @@ class LiveCDCopyBackend(backend.AnacondaBackend): def _resizeRootfs(self, anaconda, win = None): log.info("going to do resize") - r = anaconda.id.fsset.getEntryByMountPoint("/") - rootdev = r.device.getDevice() + rootDevice = anaconda.id.fsset.rootDevice # FIXME: we'd like to have progress here to give an idea of # how long it will take. or at least, to give an indefinite # progress window. but, not for this time - cmd = ["resize2fs", "/dev/%s" %(rootdev,), "-p"] + cmd = ["resize2fs", rootDevice.path, "-p"] out = open("/dev/tty5", "w") proc = subprocess.Popen(cmd, stdout=out, stderr=out) rc = proc.poll() @@ -376,9 +373,8 @@ class LiveCDCopyBackend(backend.AnacondaBackend): # FIXME: really, this should be in the general sanity checking, but # trying to weave that in is a little tricky at present. ossize = self._getLiveSizeMB() - slash = anaconda.id.partitions.getRequestByMountPoint("/") - if slash and \ - slash.getActualSize(anaconda.id.partitions, anaconda.id.diskset) < ossize: + slash = anaconda.id.fsset.rootDevice + if slash.size < ossize: rc = anaconda.intf.messageWindow(_("Error"), _("The root filesystem you created is " "not large enough for this live " @@ -391,7 +387,6 @@ class LiveCDCopyBackend(backend.AnacondaBackend): return DISPATCH_BACK else: sys.exit(1) - # package/group selection doesn't apply for this backend def groupExists(self, group): diff --git a/network.py b/network.py index af6d858f7..3531de999 100644 --- a/network.py +++ b/network.py @@ -585,8 +585,8 @@ class Network: # tell NM not to touch the interface(s) actually used for /, but we # have no logic to determine that if anaconda is not None: - rootdev = anaconda.id.fsset.getEntryByMountPoint("/").device - if rootdev.isNetdev(): + rootdev = anaconda.id.storage.fsset.rootDevice + if rootdev.isNetdev: f.write("NM_CONTROLLED=no\n") f.close() diff --git a/packages.py b/packages.py index f871c49f8..b34725a73 100644 --- a/packages.py +++ b/packages.py @@ -107,19 +107,6 @@ def doMigrateFilesystems(anaconda): bindMountDevDirectory(anaconda.rootPath) def turnOnFilesystems(anaconda): - def handleResizeError(e, dev): - if os.path.exists("/tmp/resize.out"): - details = open("/tmp/resize.out", "r").read() - else: - details = "%s" %(e,) - anaconda.intf.detailedMessageWindow(_("Resizing Failed"), - _("There was an error encountered " - "resizing the device %s.") %(dev,), - details, - type = "custom", - custom_buttons = [_("_Exit installer")]) - sys.exit(1) - if anaconda.dir == DISPATCH_BACK: log.info("unmounting filesystems") anaconda.id.fsset.umountFilesystems(anaconda.rootPath) @@ -133,53 +120,87 @@ def turnOnFilesystems(anaconda): iutil.execWithRedirect("swapoff", ["-a"], stdout = "/dev/tty5", stderr="/dev/tty5", searchPath = 1) - anaconda.id.partitions.doMetaDeletes(anaconda.id.diskset) - anaconda.id.fsset.setActive(anaconda.id.diskset, anaconda.id.partitions.requests) - try: - anaconda.id.fsset.shrinkFilesystems(anaconda.id.diskset, anaconda.rootPath) - except fsset.ResizeError, (e, dev): - handleResizeError(e, dev) - if not anaconda.id.fsset.isActive(): - anaconda.id.diskset.savePartitions () - # this is somewhat lame, but we seem to be racing with - # device node creation sometimes. so wait for device nodes - # to settle - time.sleep(1) - w = anaconda.intf.waitWindow(_("Activating"), _("Activating new partitions. Please wait...")) - rc = iutil.execWithRedirect("/sbin/udevadm", [ "settle" ], - stdout = "/dev/tty5", - stderr = "/dev/tty5", - searchPath = 1) - w.pop() - - anaconda.id.partitions.doEncryptionRetrofits() - - try: - anaconda.id.partitions.doMetaResizes(anaconda.id.diskset) - except lvm.LVResizeError, e: - handleResizeError("%s" %(e,), "%s/%s" %(e.vgname, e.lvname)) try: - anaconda.id.fsset.growFilesystems(anaconda.id.diskset, anaconda.rootPath) - except fsset.ResizeError, (e, dev): - handleResizeError(e, dev) - - if not anaconda.id.fsset.volumesCreated: - try: - anaconda.id.fsset.createLogicalVolumes(anaconda.rootPath) - except SystemError, e: - log.error("createLogicalVolumes failed with %s", str(e)) - anaconda.intf.messageWindow(_("LVM operation failed"), - str(e)+"\n\n"+_("The installer will now exit..."), - type="custom", custom_icon="error", custom_buttons=[_("_Reboot")]) - sys.exit(0) - - anaconda.id.fsset.formatSwap(anaconda.rootPath) - anaconda.id.fsset.turnOnSwap(anaconda.rootPath) - anaconda.id.fsset.makeFilesystems(anaconda.rootPath, - anaconda.backend.skipFormatRoot) - anaconda.id.fsset.mountFilesystems(anaconda,0,0, - anaconda.backend.skipFormatRoot) + anaconda.id.storage.processActions(anaconda.intf) + except DeviceResizeError as (msg, device): + # XXX does this make any sense? do we support resize of + # devices other than partitions? + anaconda.intf.detailedMessageWindow(_("Device Resize Failed"), + _("An error was encountered while " + "resizing device %s.") % (device,), + msg, + type = "custom", + custom_buttons = [_("_Exit installer")]) + sys.exit(1) + except DeviceCreateError as (msg, device): + anaconda.intf.detailedMessageWindow(_("Device Creation Failed"), + _("An error was encountered while " + "creating device %s.") % (device,), + msg, + type = "custom", + custom_buttons = [_("_Exit installer")]) + sys.exit(1) + except DeviceDestroyError as (msg, device): + anaconda.intf.detailedMessageWindow(_("Device Removal Failed"), + _("An error was encountered while " + "removing device %s.") % (device,), + msg, + type = "custom", + custom_buttons = [_("_Exit installer")]) + sys.exit(1) + except DeviceError as (msg, device): + anaconda.intf.detailedMessageWindow(_("Device Setup Failed"), + _("An error was encountered while " + "setting up device %s.") % (device,), + msg, + type = "custom", + custom_buttons = [_("_Exit installer")]) + sys.exit(1) + except FSResizeError as (msg, device): + if os.path.exists("/tmp/resize.out"): + details = open("/tmp/resize.out", "r").read() + else: + details = "%s" %(msg,) + anaconda.intf.detailedMessageWindow(_("Resizing Failed"), + _("There was an error encountered while " + "resizing the device %s.") %(device,), + details, + type = "custom", + custom_buttons = [_("_Exit installer")]) + sys.exit(1) + except FSMigrateError as (msg, device): + anaconda.intf.detailedMessageWindow(_("Migration Failed"), + _("An error was encountered while " + "migrating filesystem on device %s.") + % (device,), + msg, + type = "custom", + custom_buttons = [_("_Exit installer")]) + sys.exit(1) + except FormatCreateError as (msg, device): + anaconda.intf.detailedMessageWindow(_("Formatting Failed"), + _("An error was encountered while " + "formatting device %s.") % (device,), + msg, + type = "custom", + custom_buttons = [_("_Exit installer")]) + sys.exit(1) + except Exception as msg: + # catch-all + anaconda.intf.detailedMessageWindow(_("Storage Activation Failed"), + _("An error was encountered while " + "activating your storage configuration.") + msg, + type = "custom", + custom_buttons = [_("_Exit installer")]) + sys.exit(1) + + anaconda.id.fsset.turnOnSwap(anaconda.intf) + anaconda.id.storage.fsset.mountFilesystems(anaconda, + raiseErrors=False, + readOnly=False, + skipRoot=anaconda.backend.skipFormatRoot) def setupTimezone(anaconda): # we don't need this on an upgrade or going backwards diff --git a/rescue.py b/rescue.py index 42e5b960c..3006971a8 100644 --- a/rescue.py +++ b/rescue.py @@ -29,8 +29,8 @@ from flags import flags import sys import os import isys +from storage import mountExistingSystem import iutil -import fsset import shutil import time import network @@ -101,14 +101,17 @@ class RescueInterface: # XXX grub-install is stupid and uses df output to figure out # things when installing grub. make /etc/mtab be at least # moderately useful. -def makeMtab(instPath, theFsset): - child = os.fork() - if (not child): - os.chroot(instPath) +def makeMtab(instPath, fsset): + try: f = open("/etc/mtab", "w+") - f.write(theFsset.mtab()) + except IOError, e: + log.info("failed to open /etc/mtab for write: %s" % e) + return + + try: + f.write(fsset.mtab()) + finally: f.close() - os._exit(0) # make sure they have a resolv.conf in the chroot def makeResolvConf(instPath): @@ -265,17 +268,14 @@ def runRescue(anaconda, instClass): else: scroll = 0 - partList = [] - for (drive, fs, relstr, label, uuid) in disks: - if label: - partList.append("%s (%s)" % (drive, label)) - else: - partList.append(drive) + devList = [] + for (device, relstr) in disks: + devList.append(device.path) (button, choice) = \ ListboxChoiceWindow(screen, _("System to Rescue"), - _("What partition holds the root partition " - "of your installation?"), partList, + _("Which device holds the root partition " + "of your installation?"), devList, [ _("OK"), _("Exit") ], width = 30, scroll = scroll, height = height, help = "multipleroot") @@ -283,19 +283,15 @@ def runRescue(anaconda, instClass): if button == string.lower (_("Exit")): root = None else: - root = disks[choice] + root = disks[choice][0] rootmounted = 0 if root: try: - fs = fsset.FileSystemSet() - - # only pass first two parts of tuple for root, since third - # element is a comment we dont want - rc = upgrade.mountRootPartition(anaconda, root[:2], fs, - allowDirty = 1, warnDirty = 1, - readOnly = readOnly) + rc = mountExistingSystem(anaconda, root, + allowDirty = 1, warnDirty = 1, + readOnly = readOnly) if rc == -1: if anaconda.isKickstart: @@ -325,7 +321,7 @@ def runRescue(anaconda, instClass): # now turn on swap if not readOnly: try: - fs.turnOnSwap("/") + anaconda.id.storage.fsset.turnOnSwap(anaconda.intf) except: log.error("Error enabling swap") @@ -412,7 +408,7 @@ def runRescue(anaconda, instClass): msgStr = "" if rootmounted and not readOnly: - makeMtab(anaconda.rootPath, fs) + makeMtab(anaconda.rootPath, anaconda.id.storage.fsset) try: makeResolvConf(anaconda.rootPath) except Exception, e: diff --git a/upgrade.py b/upgrade.py index a554d3bbe..98979b836 100644 --- a/upgrade.py +++ b/upgrade.py @@ -26,14 +26,13 @@ import iutil import time import sys import os.path -import partedUtils import string import selinux -import lvm from flags import flags -from fsset import * from constants import * from product import productName +from storage import findExistingRootDevices, FSSet +from storage.formats import getFormat import rhpl import rhpl.arch @@ -134,11 +133,8 @@ def findRootParts(anaconda): root_device=anaconda.id.ksdata.upgrade.root_device anaconda.id.upgradeRoot = [] - for (dev, fs, meta, label, uuid) in anaconda.id.rootParts: - if (root_device is not None) and ((dev == root_device) or (("UUID=%s" % uuid) == root_device) or (("LABEL=%s" % label) == root_device)): - anaconda.id.upgradeRoot.append( (dev, fs) ) - else: - anaconda.id.upgradeRoot.append( (dev, fs) ) + for (dev, label) in anaconda.id.rootParts: + anaconda.id.upgradeRoot.append( (dev, fs) ) if anaconda.id.rootParts is not None and len(anaconda.id.rootParts) > 0: anaconda.dispatch.skipStep("findinstall", skip = 0) @@ -149,111 +145,19 @@ def findRootParts(anaconda): anaconda.dispatch.skipStep("installtype", skip = 0) def findExistingRoots(anaconda, upgradeany = 0): - # make ibft configured iscsi disks available - anaconda.id.iscsi.startup(anaconda.intf) - if not flags.setupFilesystems: (prod, ver) = partedUtils.getReleaseString (anaconda.rootPath) if flags.cmdline.has_key("upgradeany") or upgradeany == 1 or anaconda.id.instClass.productUpgradable(prod, ver): - return [(anaconda.rootPath, 'ext2', "")] + return [(anaconda.rootPath, "")] return [] - anaconda.id.diskset.openDevices() - anaconda.id.partitions.getEncryptedDevices(anaconda.id.diskset) - rootparts = anaconda.id.diskset.findExistingRootPartitions(upgradeany = upgradeany) - - # close the devices to make sure we don't leave things sitting open - anaconda.id.diskset.closeDevices() - - # this is a hack... need to clear the skipped disk list after this - partedUtils.DiskSet.skippedDisks = [] - partedUtils.DiskSet.exclusiveDisks = [] - return rootparts -def getDirtyDevString(dirtyDevs): - ret = "" - for dev in dirtyDevs: - if dev != "loop": - ret = "/dev/%s\n" % (dev,) - else: - ret = "%s\n" % (dev,) - return ret - -def mountRootPartition(anaconda, rootInfo, oldfsset, allowDirty = 0, - warnDirty = 0, readOnly = 0): - (root, rootFs) = rootInfo - bindMount = 0 - - encryptedDevices = anaconda.id.partitions.encryptedDevices - diskset = partedUtils.DiskSet(anaconda) - diskset.openDevices() - for cryptoDev in encryptedDevices.values(): - cryptoDev.openDevice() - diskset.startMPath() - diskset.startDmRaid() - diskset.startMdRaid() - for cryptoDev in encryptedDevices.values(): - cryptoDev.openDevice() - lvm.vgscan() - lvm.vgactivate() - for cryptoDev in encryptedDevices.values(): - cryptoDev.openDevice() - - if root in anaconda.id.partitions.protectedPartitions() and os.path.ismount("/mnt/isodir"): - root = "/mnt/isodir" - bindMount = 1 - - log.info("going to mount %s on %s as %s" %(root, anaconda.rootPath, rootFs)) - isys.mount(root, anaconda.rootPath, rootFs, bindMount=bindMount) - - oldfsset.reset() - newfsset = readFstab(anaconda) - - for entry in newfsset.entries: - oldfsset.add(entry) - - if not bindMount: - isys.umount(anaconda.rootPath) - - dirtyDevs = oldfsset.hasDirtyFilesystems(anaconda.rootPath) - if not allowDirty and dirtyDevs != []: - lvm.vgdeactivate() - diskset.stopMdRaid() - diskset.stopDmRaid() - diskset.stopMPath() - anaconda.intf.messageWindow(_("Dirty File Systems"), - _("The following file systems for your Linux system " - "were not unmounted cleanly. Please boot your " - "Linux installation, let the file systems be " - "checked and shut down cleanly to upgrade.\n" - "%s" %(getDirtyDevString(dirtyDevs),))) - sys.exit(0) - elif warnDirty and dirtyDevs != []: - rc = anaconda.intf.messageWindow(_("Dirty File Systems"), - _("The following file systems for your Linux " - "system were not unmounted cleanly. Would " - "you like to mount them anyway?\n" - "%s" % (getDirtyDevString(dirtyDevs,))), - type = "yesno") - if rc == 0: - return -1 - - if flags.setupFilesystems: - for dev, crypto in encryptedDevices.items(): - if crypto.openDevice(): - log.error("failed to open encrypted device %s" % (dev,)) - - oldfsset.mountFilesystems(anaconda, readOnly = readOnly, - skiprootfs = bindMount) - - rootEntry = oldfsset.getEntryByMountPoint("/") - if (not rootEntry or not rootEntry.fsystem or not rootEntry.fsystem.isMountable()): - raise RuntimeError, "/etc/fstab did not list a fstype for the root partition which we support" - def bindMountDevDirectory(instPath): - fs = fileSystemTypeGet("bind") - fs.mount("/dev", "/dev", bindMount=1, instroot=instPath) + getFormat("bind", + device="/dev", + mountpoint="/dev", + exists=True).mount(chroot=instPath) # returns None if no filesystem exist to migrate def upgradeMigrateFind(anaconda): @@ -295,13 +199,15 @@ def upgradeSwapSuggestion(anaconda): fsList = [] - for entry in anaconda.id.fsset.entries: - if entry.fsystem.getName() in getUsableLinuxFs(): - if flags.setupFilesystems and not entry.isMounted(): + for device in anaconda.id.fsset.devices: + if not device.format: + continue + if device.format.mountable and device.format.linuxNative: + if flags.setupFilesystems and not device.format.status: continue - space = isys.pathSpaceAvailable(anaconda.rootPath + entry.mountpoint) + space = isys.pathSpaceAvailable(anaconda.rootPath + device.format.mountpoint) if space > 16: - info = (entry.mountpoint, entry.device.getDevice(), space) + info = (device, space) fsList.append(info) suggestion = mem * 2 - swap @@ -311,57 +217,11 @@ def upgradeSwapSuggestion(anaconda): suggestion = 32 suggSize = 0 suggMnt = None - for (mnt, part, size) in fsList: + for (device, size) in fsList: if (size > suggSize) and (size > (suggestion + 100)): - suggMnt = mnt - - anaconda.id.upgradeSwapInfo = (fsList, suggestion, suggMnt) - -def swapfileExists(swapname): - try: - os.lstat(swapname) - return 1 - except: - return 0 + suggDev = device -def createSwapFile(instPath, theFsset, mntPoint, size): - fstabPath = instPath + "/etc/fstab" - prefix = "" - - if mntPoint != "/": - file = mntPoint + "/SWAP" - else: - file = "/SWAP" - - swapFileDict = {} - for entry in theFsset.entries: - if entry.fsystem.getName() == "swap": - swapFileDict[entry.device.getName()] = 1 - - count = 0 - while (swapfileExists(instPath + file) or - swapFileDict.has_key(file)): - count = count + 1 - tmpFile = "/SWAP-%d" % (count) - if mntPoint != "/": - file = mntPoint + tmpFile - else: - file = tmpFile - - device = SwapFileDevice(file) - device.setSize(size) - fsystem = fileSystemTypeGet("swap") - entry = FileSystemSetEntry(device, "swap", fsystem) - entry.setFormat(1) - theFsset.add(entry) - theFsset.formatEntry(entry, instPath) - theFsset.turnOnSwap(instPath, upgrading=True) - - # XXX generalize fstab modification - f = open(fstabPath, "a") - format = "%-23s %-23s %-7s %-15s %d %d\n"; - f.write(format % (prefix + file, "swap", "swap", "defaults", 0, 0)) - f.close() + anaconda.id.upgradeSwapInfo = (fsList, suggestion, suggDev) # XXX handle going backwards def upgradeMountFilesystems(anaconda): @@ -369,21 +229,15 @@ def upgradeMountFilesystems(anaconda): if flags.setupFilesystems: try: - mountRootPartition(anaconda, anaconda.id.upgradeRoot[0], anaconda.id.fsset, - allowDirty = 0) - except SystemError: + mountExistingSystem(anaconda, + anaconda.id.upgradeRoot[0], + allowDirty = 0) + except Exception: anaconda.intf.messageWindow(_("Mount failed"), _("One or more of the file systems listed in the " "/etc/fstab on your Linux system cannot be mounted. " "Please fix this problem and try to upgrade again.")) sys.exit(0) - except RuntimeError: - anaconda.intf.messageWindow(_("Mount failed"), - _("One or more of the file systems listed in the " - "/etc/fstab of your Linux system are inconsistent and " - "cannot be mounted. Please fix this problem and try to " - "upgrade again.")) - sys.exit(0) checkLinks = ( '/etc', '/var', '/var/lib', '/var/lib/rpm', '/boot', '/tmp', '/var/tmp', '/root', @@ -430,15 +284,11 @@ def upgradeMountFilesystems(anaconda): % (anaconda.rootPath + "/etc/fstab",), type="ok") return DISPATCH_BACK - - newfsset = readFstab(anaconda) - for entry in newfsset.entries: - anaconda.id.fsset.add(entry) + + anaconda.id.storage.fsset.parseFSTab(chroot=anaconda.rootPath) if flags.setupFilesystems: - if iutil.isPPC(): - anaconda.id.fsset.formatSwap(anaconda.rootPath, forceFormat=True) - anaconda.id.fsset.turnOnSwap(anaconda.rootPath, upgrading=True) - anaconda.id.fsset.mkDevRoot(anaconda.rootPath) + anaconda.id.storage.fsset.turnOnSwap(upgrading=True) + anaconda.id.storage.fsset.mkDevRoot(anaconda.rootPath) # if they've been booting with selinux disabled, then we should # disable it during the install as well (#242510) @@ -458,9 +308,9 @@ def setSteps(anaconda): "keyboard", "welcome", "installtype", + "storageinit", "findrootparts", "findinstall", - "partitionobjinit", "upgrademount", "upgrademigfind", "upgrademigratefs", @@ -473,7 +323,6 @@ def setSteps(anaconda): "confirmupgrade", "postselection", "install", - "migratefilesystems", "preinstallconfig", "installpackages", "postinstallconfig", diff --git a/yuminstall.py b/yuminstall.py index 2d63dac5d..68fd5a191 100644 --- a/yuminstall.py +++ b/yuminstall.py @@ -1293,26 +1293,18 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon elif iutil.isIA64(): self.selectPackage("elilo") - def selectFSPackages(self, fsset, diskset): - for entry in fsset.entries: - map(self.selectPackage, entry.fsystem.getNeededPackages()) - if entry.device.crypto: - self.selectPackage("cryptsetup-luks") - - for disk in diskset.disks.keys(): - if isys.driveIsIscsi(disk): + def selectFSPackages(self, storage): + for device in storage.fsset.devices: + # this takes care of device and filesystem packages + map(self.selectPackage, device.packages) + + for disk in storage.disks: + # FIXME: this should get handled by the above + if isys.driveIsIscsi(disk.path): log.info("ensuring iscsi is installed") self.selectPackage("iscsi-initiator-utils") break - if diskset.__class__.mpList: - log.info("ensuring device-mapper-multipath is installed") - self.selectPackage("device-mapper-multipath") - if diskset.__class__.dmList: - log.info("ensuring dmraid is installed") - self.selectPackage("dmraid") - - # anaconda requires several programs on the installed system to complete # installation, but we have no guarantees that some of these will be # installed (they could have been removed in kickstart). So we'll force @@ -1335,7 +1327,7 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon # New installs only - upgrades will already have all this stuff. self.selectBestKernel(anaconda) self.selectBootloader() - self.selectFSPackages(anaconda.id.fsset, anaconda.id.diskset) + self.selectFSPackages(anaconda.id.storage) self.selectAnacondaNeeds() if anaconda.id.getUpgrade(): -- cgit