diff options
author | David Lehman <dlehman@redhat.com> | 2009-02-23 13:14:27 -0600 |
---|---|---|
committer | David Lehman <dlehman@redhat.com> | 2009-02-23 13:14:27 -0600 |
commit | b2dedb483bd9514cce023c284463d18fc0f7b612 (patch) | |
tree | ef1288cfe1edb18b273f24385a03f91dcb584c5a | |
parent | e1a7fe9887886044b07587b3ec2caa2ff53ebfb2 (diff) | |
download | anaconda-b2dedb483bd9514cce023c284463d18fc0f7b612.tar.gz anaconda-b2dedb483bd9514cce023c284463d18fc0f7b612.tar.xz anaconda-b2dedb483bd9514cce023c284463d18fc0f7b612.zip |
Update UI code to use new storage module.
-rw-r--r-- | cmdline.py | 4 | ||||
-rwxr-xr-x | gui.py | 6 | ||||
-rw-r--r-- | iw/lvm_dialog_gui.py | 692 | ||||
-rw-r--r-- | iw/partition_dialog_gui.py | 410 | ||||
-rw-r--r-- | iw/partition_gui.py | 640 | ||||
-rw-r--r-- | iw/partition_ui_helpers_gui.py | 95 | ||||
-rw-r--r-- | iw/raid_dialog_gui.py | 315 | ||||
-rw-r--r-- | partIntfHelpers.py | 427 | ||||
-rw-r--r-- | text.py | 4 |
9 files changed, 1079 insertions, 1514 deletions
diff --git a/cmdline.py b/cmdline.py index 7b925c9cf..f87550c46 100644 --- a/cmdline.py +++ b/cmdline.py @@ -114,10 +114,6 @@ class InstallInterface: pass def run(self, anaconda): - anaconda.id.fsset.registerMessageWindow(self.messageWindow) - anaconda.id.fsset.registerProgressWindow(self.progressWindow) - anaconda.id.fsset.registerWaitWindow(self.waitWindow) - (step, instance) = anaconda.dispatch.currentStep() while step: if stepToClasses.has_key(step): @@ -752,7 +752,7 @@ class SaveExceptionWindow: elif len(dests) > 0: for d in dests: iter = store.append(None) - store[iter] = ("/dev/%s" % d[0], "/dev/%s - %s" % (d[0], d[1])) + store[iter] = (d[0], "%s - %s" % (d[0], d[1])) self.diskCombo.set_model(store) self.diskCombo.set_active(0) @@ -1267,10 +1267,6 @@ class InstallInterface: if anaconda.id.keyboard and not anaconda.id.x_already_set: anaconda.id.keyboard.activate() - anaconda.id.fsset.registerMessageWindow(self.messageWindow) - anaconda.id.fsset.registerProgressWindow(self.progressWindow) - anaconda.id.fsset.registerWaitWindow(self.waitWindow) - self.icw = InstallControlWindow (self.anaconda) self.icw.run (self.runres) diff --git a/iw/lvm_dialog_gui.py b/iw/lvm_dialog_gui.py index 25c0e6dda..867755ab0 100644 --- a/iw/lvm_dialog_gui.py +++ b/iw/lvm_dialog_gui.py @@ -1,5 +1,5 @@ # -# lvm_dialog_gui.py: dialog for editting a volume group request +# lvm_dialog_gui.py: dialog for editing a volume group request # # Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. # All rights reserved. @@ -27,12 +27,9 @@ import gtk import datacombo import gui -from fsset import * -from partRequests import * from partition_ui_helpers_gui import * from constants import * import lvm -from cryptodev import LUKSDevice import gettext _ = lambda x: gettext.ldgettext("anaconda", x) @@ -46,8 +43,9 @@ class VolumeGroupEditor: return max(0, lvm.MAX_LV_SLOTS - len(self.logvolreqs)) def computeSpaceValues(self, alt_pvlist=None, usepe=None): + # FIXME: stop using this in favor of the vg's methods if usepe is None: - pesize = long(self.peCombo.get_active_value()) + pesize = long(self.peCombo.get_active_value()) / 1024.0 else: pesize = long(usepe) @@ -55,11 +53,13 @@ class VolumeGroupEditor: pvlist = self.getSelectedPhysicalVolumes(self.lvmlist.get_model()) else: pvlist = alt_pvlist - tspace = self.computeVGSize(pvlist, pesize) - uspace = self.computeLVSpaceNeeded(self.logvolreqs) - fspace = tspace - uspace - return (tspace, uspace, fspace) + # XXX this should all be computed using self.vg + vgsize = self.computeVGSize(pvlist, pesize) + vgused = self.computeLVSpaceNeeded(self.vg.lvs) + vgfree = vgsize - vgused + + return (vgsize, vgused, vgfree) def getPVWastedRatio(self, newpe): """ given a new pe value, return percentage of smallest PV wasted @@ -69,10 +69,8 @@ class VolumeGroupEditor: pvlist = self.getSelectedPhysicalVolumes(self.lvmlist.get_model()) waste = 0.0 - for id in pvlist: - pvreq = self.partitions.getRequestByID(id) - pvsize = pvreq.getActualSize(self.partitions, self.diskset) - waste = max(waste, (long(pvsize*1024) % newpe)/(pvsize*1024.0)) + for pv in pvlist: + waste = max(waste, (long(pv.size*1024) % newpe)/(pv.size*1024.0)) return waste @@ -111,10 +109,10 @@ class VolumeGroupEditor: oldused = 0 used = 0 resize = 0 - for lv in self.logvolreqs: - osize = lv.getActualSize(self.partitions, self.diskset, True) + for lv in self.vg.lvs: + osize = lv.size oldused = oldused + osize - nsize = lvm.clampLVSizeRequest(osize, newpe, roundup=1) + nsize = lvm.clampSize(osize, newpe, roundup=1) if nsize != osize: resize = 1 @@ -144,11 +142,13 @@ class VolumeGroupEditor: custom_buttons=["gtk-cancel", _("C_ontinue")]) if not rc: return 0 - + + # XXX this is very sneaky, just changing the lvs' size attributes + # will we suffer for it? almost certainly. for lv in self.logvolreqs: - osize = lv.getActualSize(self.partitions, self.diskset, True) - nsize = lvm.clampLVSizeRequest(osize, newpe, roundup=1) - lv.setSize(nsize) + osize = lv.size + nsize = lvm.clampSize(osize, newpe, roundup=1) + lv.size = nsize return 1 @@ -161,24 +161,26 @@ class VolumeGroupEditor: """ curval = int(widget.get_active_value()) + # this one's in MB so we can stop with all this dividing by 1024 + curpe = curval / 1024.0 lastval = widget.get_data("lastpe") lastidx = widget.get_data("lastidx") # see if PE is too large compared to smallest PV - # remember PE is in KB, PV size is in MB maxpvsize = self.getSmallestPVSize() - if curval > maxpvsize * 1024: + if curpe > maxpvsize: self.intf.messageWindow(_("Not enough space"), _("The physical extent size cannot be " "changed because the value selected " "(%10.2f MB) is larger than the smallest " "physical volume (%10.2f MB) in the " - "volume group.") % (curval/1024.0, maxpvsize), custom_icon="error") + "volume group.") % (curpe, maxpvsize), + custom_icon="error") widget.set_active(lastidx) return 0 # see if new PE will make any PV useless due to overhead - if lvm.clampPVSize(maxpvsize, curval) * 1024 < curval: + if lvm.clampPVSize(maxpvsize, curpe) < curpe: self.intf.messageWindow(_("Not enough space"), _("The physical extent size cannot be " "changed because the value selected " @@ -186,14 +188,14 @@ class VolumeGroupEditor: "to the size of the " "smallest physical volume " "(%10.2f MB) in the " - "volume group.") % (curval/1024.0, + "volume group.") % (curpe, maxpvsize), custom_icon="error") widget.set_active(lastidx) return 0 - if self.getPVWastedRatio(curval) > 0.10: + if self.getPVWastedRatio(curpe) > 0.10: rc = self.intf.messageWindow(_("Too small"), _("This change in the value of the " "physical extent will waste " @@ -215,10 +217,9 @@ class VolumeGroupEditor: else: self.updateLogVolStore() else: - maxlv = lvm.getMaxLVSize(curval) - for lv in self.logvolreqs: - lvsize = lv.getActualSize(self.partitions, self.diskset, True) - if lvsize > maxlv: + maxlv = lvm.getMaxLVSize(curpe) + for lv in self.vg.lvs: + if lv.size > maxlv: self.intf.messageWindow(_("Not enough space"), _("The physical extent size " "cannot be changed because the " @@ -234,12 +235,15 @@ class VolumeGroupEditor: widget.set_data("lastpe", curval) widget.set_data("lastidx", widget.get_active()) + + # XXX this is pretty sneaky, too + self.vg.peSize = curpe self.updateAllowedLvmPartitionsList(self.availlvmparts, - self.partitions, self.lvmlist) self.updateVGSpaceLabels() def prettyFormatPESize(self, val): + """ Pretty print for PE size in KB """ if val < 1024: return "%s KB" % (val,) elif val < 1024*1024: @@ -285,11 +289,12 @@ class VolumeGroupEditor: # changes the toggle state val = not model.get_value(iter, 0) partname = model.get_value(iter, 1) - id = self.partitions.getRequestByDeviceName(partname).uniqueID + pv = self.storage.devicetree.getDeviceByName(partname) if val: - pvlist.append(id) + pvlist.append(pv) else: - pvlist.remove(id) + pvlist.remove(pv) + (availSpaceMB, neededSpaceMB, fspace) = self.computeSpaceValues(alt_pvlist=pvlist) if availSpaceMB < neededSpaceMB: @@ -301,12 +306,17 @@ class VolumeGroupEditor: "volumes."), custom_icon="error") return False + # XXX this is pretty sneaky + if val: + self.vg._addPV(pv) + else: + self.vg._removePV(pv) + self.updateVGSpaceLabels(alt_pvlist = pvlist) return True - def createAllowedLvmPartitionsList(self, alllvmparts, reqlvmpart, partitions, preexist = 0): - + def createAllowedLvmPartitionsList(self, alllvmparts, vgs, lvs): store = gtk.TreeStore(gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING) @@ -317,49 +327,50 @@ class VolumeGroupEditor: sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) sw.set_shadow_type(gtk.SHADOW_IN) - for part in alllvmparts: - uid = part[0] - request = partitions.getRequestByID(uid) + for device in alllvmparts: + # clip size to current PE + pesize = int(self.peCombo.get_active_value()) / 1024.0 + size = lvm.clampSize(size, pesize) + size_string = "%10.2f MB" % size + include = True + selected = False + + # now see if the pv is in use either by a vg in the tree or by + # the vg we are editing now + if device in self.vg.pvs: + selected = True + include = True + else: + for vg in vgs: + if vg.name == self.vg.name: + continue - if request.type != REQUEST_RAID: - partname = "%s" % (request.device,) - else: - partname = "md%d" % (request.raidminor,) + if device in vg.pvs: + include = False + break - size = request.getActualSize (partitions, self.diskset) - used = part[2] + if include and not self.vg.pvs: + selected = True - # clip size to current PE - pesize = int(self.peCombo.get_active_value()) - size = lvm.clampPVSize(size, pesize) - partsize = "%10.2f MB" % size - if used or not reqlvmpart: - selected = 1 - else: - selected = 0 - - if preexist == 0 or selected == 1: - partlist.append_row((partname, partsize), selected) + if include: + partlist.append_row((device.name, size_string), selected) return (partlist, sw) - def updateAllowedLvmPartitionsList(self, alllvmparts, partitions, partlist): + def updateAllowedLvmPartitionsList(self, alllvmparts, partlist): """ update sizes in pv list alllvmparts - list of pv from partitions.getAvailLVMPartitions - partitions - object holding all partition requests partlist - the checklist containing pv list """ row = 0 for part in alllvmparts: - uid = part[0] - request = partitions.getRequestByID(uid) - size = request.getActualSize(partitions, self.diskset) + size = part.size # clip size to current PE - pesize = int(self.peCombo.get_active_value()) - size = lvm.clampPVSize(size, pesize) + pesize = int(self.peCombo.get_active_value()) / 1024.0 + size = lvm.clampSize(size, pesize) partsize = "%10.2f MB" % size iter = partlist.store.get_iter((int(row),)) @@ -371,14 +382,16 @@ class VolumeGroupEditor: (model, iter) = selection.get_selected() return iter + def editLogicalVolume(self, lv, isNew = 0): + if not lv: + return - def editLogicalVolume(self, logrequest, isNew = 0): if isNew: tstr = _("Make Logical Volume") else: try: - tstr = _("Edit Logical Volume: %s") % (logrequest.logicalVolumeName,) - except: + tstr = _("Edit Logical Volume: %s") % (lv.name,) + except AttributeError: tstr = _("Edit Logical Volume") dialog = gtk.Dialog(tstr, self.parent) @@ -392,17 +405,24 @@ class VolumeGroupEditor: maintable.set_col_spacings(5) row = 0 + if lv.format.type == "luks": + usedev = self.storage.devicetree.getChildren(lv)[0] + format = usedev.format + elif lv: + usedev = lv + format = lv.format + lbl = createAlignedLabel(_("_Mount Point:")) maintable.attach(lbl, 0, 1, row,row+1) - mountCombo = createMountPointCombo(logrequest, excludeMountPoints=["/boot"]) + mountCombo = createMountPointCombo(usedev, excludeMountPoints=["/boot"]) lbl.set_mnemonic_widget(mountCombo) maintable.attach(mountCombo, 1, 2, row, row + 1) row += 1 - if not logrequest or not logrequest.getPreExisting(): + if not format.exists: lbl = createAlignedLabel(_("_File System Type:")) maintable.attach(lbl, 0, 1, row, row + 1) - newfstypeCombo = createFSTypeMenu(logrequest.fstype, + newfstypeCombo = createFSTypeMenu(format.name, fstypechangeCB, mountCombo, ignorefs = ["software RAID", "physical volume (LVM)", "vfat", "efi", "PPC PReP Boot", "Apple Bootstrap"]) @@ -412,77 +432,72 @@ class VolumeGroupEditor: else: maintable.attach(createAlignedLabel(_("Original File System Type:")), 0, 1, row, row + 1) - if logrequest.origfstype and logrequest.origfstype.getName(): - newfstypeCombo = gtk.Label(logrequest.origfstype.getName()) + if format.type: + newfstypeCombo = gtk.Label(format.name) else: newfstypeCombo = gtk.Label(_("Unknown")) maintable.attach(newfstypeCombo, 1, 2, row, row + 1) row += 1 - if logrequest.fslabel: + if getattr(format, "label", None): maintable.attach(createAlignedLabel(_("Original File System " "Label:")), 0, 1, row, row + 1) - maintable.attach(gtk.Label(logrequest.fslabel), 1, 2, row, - row + 1) + maintable.attach(gtk.Label(format.label), + 1, 2, row, row + 1) row += 1 - - if not logrequest or not logrequest.getPreExisting(): + if not lv.exists: lbl = createAlignedLabel(_("_Logical Volume Name:")) lvnameEntry = gtk.Entry(32) lbl.set_mnemonic_widget(lvnameEntry) - if logrequest and logrequest.logicalVolumeName: - lvnameEntry.set_text(logrequest.logicalVolumeName) + if lv and lv.lvname: + lvnameEntry.set_text(lv.lvname) else: - lvnameEntry.set_text(lvm.createSuggestedLVName(self.logvolreqs)) + lvnameEntry.set_text(storage.createSuggestedLVName(self.vg.lvs)) else: lbl = createAlignedLabel(_("Logical Volume Name:")) - lvnameEntry = gtk.Label(logrequest.logicalVolumeName) + lvnameEntry = gtk.Label(lv.lvname) maintable.attach(lbl, 0, 1, row, row + 1) maintable.attach(lvnameEntry, 1, 2, row, row + 1) row += 1 - if not logrequest or not logrequest.getPreExisting(): + if not lv.exists: lbl = createAlignedLabel(_("_Size (MB):")) sizeEntry = gtk.Entry(16) lbl.set_mnemonic_widget(sizeEntry) - if logrequest: - sizeEntry.set_text("%Ld" % (logrequest.getActualSize(self.partitions, self.diskset, True),)) + sizeEntry.set_text("%Ld" % lv.size) else: lbl = createAlignedLabel(_("Size (MB):")) - sizeEntry = gtk.Label(str(logrequest.size)) + sizeEntry = gtk.Label(str(lv.size)) maintable.attach(lbl, 0, 1, row, row+1) maintable.attach(sizeEntry, 1, 2, row, row + 1) row += 1 - if not logrequest or not logrequest.getPreExisting(): - pesize = int(self.peCombo.get_active_value()) - (tspace, uspace, fspace) = self.computeSpaceValues(usepe=pesize) - maxlv = min(lvm.getMaxLVSize(pesize), fspace) + if not lv.exists: + pesize = int(self.peCombo.get_active_value()) / 1024.0 + (total, used, free) = self.computeSpaceValues(usepe=pesize) + maxlv = min(lvm.getMaxLVSize(pesize), free) # add in size of current logical volume if it has a size - if logrequest and not isNew: - maxlv = maxlv + logrequest.getActualSize(self.partitions, self.diskset) + if lv and not isNew: + maxlv += lv.size + maxlabel = createAlignedLabel(_("(Max size is %s MB)") % (maxlv,)) maintable.attach(maxlabel, 1, 2, row, row + 1) self.fsoptionsDict = {} - if logrequest.getPreExisting(): - (row, self.fsoptionsDict) = createPreExistFSOptionSection(logrequest, maintable, row, mountCombo, self.partitions, ignorefs = ["software RAID", "physical volume (LVM)", "vfat"]) + if lv.exists: + (row, self.fsoptionsDict) = createPreExistFSOptionSection(usedev, maintable, row, mountCombo, self.storage, ignorefs = ["software RAID", "physical volume (LVM)", "vfat"]) # checkbutton for encryption using dm-crypt/LUKS - if not logrequest.getPreExisting(): + if not lv.exists: self.lukscb = gtk.CheckButton(_("_Encrypt")) - if logrequest.format or logrequest.type == REQUEST_NEW: - self.lukscb.set_data("formatstate", 1) - else: - self.lukscb.set_data("formatstate", 0) - - if logrequest.encryption: + self.lukscb.set_data("formatstate", 1) + if lv.format.type == "luks": self.lukscb.set_active(1) else: self.lukscb.set_active(0) @@ -500,79 +515,76 @@ class VolumeGroupEditor: dialog.destroy() return - if not logrequest or not logrequest.getPreExisting(): - fsystem = newfstypeCombo.get_active_value() - format = 1 - migrate = 0 - targetSize = None - else: - if self.fsoptionsDict.has_key("formatcb"): - format = self.fsoptionsDict["formatcb"].get_active() - if format: - fsystem = self.fsoptionsDict["fstypeCombo"].get_active_value() - else: - format = 0 + actions = [] + luksdev = None + targetSize = None + migrate_class = None + format = None - if self.fsoptionsDict.has_key("migratecb"): - migrate = self.fsoptionsDict["migratecb"].get_active() - if migrate: - fsystem = self.fsoptionsDict["migfstypeCombo"].get_active_value() - else: - migrate = 0 + if lv.format.type == "luks": + usedev = self.storage.devicetree.getChildren(lv)[0] + format = usedev.format + else: + usedev = lv + format = lv.format - if self.fsoptionsDict.has_key("resizecb") and self.fsoptionsDict["resizecb"].get_active(): - targetSize = self.fsoptionsDict["resizesb"].get_value_as_int() - else: - targetSize = None + if not lv.exists: + fmt_class = newfstypeCombo.get_active_value() + else: + # existing lv + fmt_class = self.fsoptionsDict["fstypeCombo"].get_active_value() - # set back if we are not formatting or migrating - origfstype = logrequest.origfstype - if not format and not migrate: - fsystem = origfstype + mountpoint = mountCombo.get_children()[0].get_text().strip() - mntpt = string.strip(mountCombo.get_children()[0].get_text()) + # validate logical volume name + lvname = lvnameEntry.get_text().strip() + if not lv.exists: + err = sanityCheckLogicalVolumeName(lvname) + if err: + self.intf.messageWindow(_("Illegal Logical Volume Name"), + err, custom_icon="error") + continue - if not logrequest or not logrequest.getPreExisting(): - # check size specification - badsize = 0 - try: - size = long(sizeEntry.get_text()) - except: - badsize = 1 + # check that the name is not already in use + used = 0 + for _lv in self.vg.lvs: + if lvname and lv.lvname == lvname: + continue - if badsize or size <= 0: - self.intf.messageWindow(_("Illegal size"), - _("The requested size as entered is " - "not a valid number greater " - "than 0."), custom_icon="error") - continue - else: - size = logrequest.size + if lv.lvname == lvname: + used = 1 + break - # is this an existing logical volume or one we're editting - if logrequest: - preexist = logrequest.getPreExisting() - else: - preexist = 0 + if used: + self.intf.messageWindow(_("Illegal logical volume name"), + _("The logical volume name \"%s\" is " + "already in use. Please pick " + "another.") % (lvname,), custom_icon="error") + continue # test mount point # check in pending logical volume requests # these may not have been put in master list of requests # yet if we have not hit 'OK' for the volume group creation - if fsystem.isMountable(): + if fmt_class().mountable and mountpoint: used = 0 - if logrequest: - curmntpt = logrequest.mountpoint - else: - curmntpt = None + curmntpt = format.mountpoint - for lv in self.logvolreqs: - if curmntpt and lv.mountpoint == curmntpt: + for _lv in self.logvolreqs: + if _lv.format.type == "luks": + # XXX this won't work if the lvs haven't been + # added to the tree yet + _usedev = self.tree.getChildren(_lv)[0] + _format = _usedev.format + else: + _usedev = _lv + _format = _lv.format + + if not _format.mountable or curmntpt and \ + _format.mountpoint == curmntpt: continue - if len(mntpt) == 0: - continue - if lv.mountpoint == mntpt: + if _format.mountpoint == mountpoint: used = 1 break @@ -580,47 +592,30 @@ class VolumeGroupEditor: self.intf.messageWindow(_("Mount point in use"), _("The mount point \"%s\" is in " "use. Please pick another.") % - (mntpt,), custom_icon="error") + (mountpoint,), + custom_icon="error") continue - # check out logical volumne name - lvname = string.strip(lvnameEntry.get_text()) + # check that size specification is numeric and positive + if not lv.exists: + badsize = 0 + try: + size = long(sizeEntry.get_text()) + except: + badsize = 1 - if not logrequest or not logrequest.getPreExisting(): - err = sanityCheckLogicalVolumeName(lvname) - if err: - self.intf.messageWindow(_("Illegal Logical Volume Name"),err, custom_icon="error") + if badsize or size <= 0: + self.intf.messageWindow(_("Illegal size"), + _("The requested size as entered is " + "not a valid number greater " + "than 0."), custom_icon="error") continue + else: + size = lv.size - # is it in use? - used = 0 - if logrequest: - origlvname = logrequest.logicalVolumeName - else: - origlvname = None - - for lv in self.logvolreqs: - if origlvname and lv.logicalVolumeName == origlvname: - continue - - if lv.logicalVolumeName == lvname: - used = 1 - break - - if used: - self.intf.messageWindow(_("Illegal logical volume name"), - _("The logical volume name \"%s\" is " - "already in use. Please pick " - "another.") % (lvname,), custom_icon="error") - continue - - # create potential request - request = copy.copy(logrequest) - request.encryption = copy.deepcopy(logrequest.encryption) - pesize = int(self.peCombo.get_active_value()) - size = lvm.clampLVSizeRequest(size, pesize, roundup=1) - - # do some final tests + # check that size specification is within limits + pesize = int(self.peCombo.get_active_value()) / 1024.0 + size = lvm.clampSize(size, pesize, roundup=True) maxlv = lvm.getMaxLVSize(pesize) if size > maxlv: self.intf.messageWindow(_("Not enough space"), @@ -635,107 +630,82 @@ class VolumeGroupEditor: custom_icon="error") continue - request.fstype = fsystem - - if request.fstype.isMountable(): - request.mountpoint = mntpt - else: - request.mountpoint = None - - request.preexist = preexist - request.logicalVolumeName = lvname - request.size = size - request.format = format - request.migrate = migrate - request.targetSize = targetSize - request.grow = 0 - - # this is needed to clear out any cached info about the device - # only a workaround - need to change way this is handled in - # partRequest.py really. - request.dev = None - - if self.lukscb and self.lukscb.get_active(): - if not request.encryption: - request.encryption = LUKSDevice(passphrase=self.partitions.encryptionPassphrase, format=1) + # Ok -- now we've done all the checks to validate the + # user-specified parameters. Time to set up the device... + if not lv.exists: + lv.name = lvname + lv.size = size + lv.req_grow = False + format = fmt_class(mountpoint=mountpoint) + if self.lukscb and self.lukscb.get_active() and \ + lv.format != "luks": + luksformat = format + format = getFormat("luks", + passphrase=self.storage.encryptionPassphrase) + luksdev = LUKSDevice("luks-%s" % lv.name, + format=luksformat, + parents=lv) + + actions.append(ActionCreateDevice(lv)) + if luksdev: + actions.append(ActionCreateDevice(luksdev)) else: - request.encryption = None - - # make list of original logvol requests so we can skip them - # in tests below. We check for mount point name conflicts - # above within the current volume group, so it is not - # necessary to do now. - err = request.sanityCheckRequest(self.partitions, skipMntPtExistCheck=1, pesize=pesize) - if err is None: - skiplist = [] - for lv in self.origvolreqs: - skiplist.append(lv.uniqueID) - - err = request.isMountPointInUse(self.partitions, requestSkipList=skiplist) + # existing lv + if self.fsoptionsDict.has_key("formatcb") and \ + self.fsoptionsDict["formatcb"].get_active(): + format = fmt_class(mountpoint=mountpoint) + if self.lukscb and self.lukscb.get_active() and \ + lv.format.type != "luks": + luksformat = format + format = getFormat("luks", + device=lv.path, + passphrase=self.storage.encryptionPassphrase) + luksdev = LUKSDevice("luks-%s" % lv.name, + format=luksformat, + parents=lv) + + if self.fsoptionsDict.has_key("migratecb") and \ + self.fsoptionsDict["migratecb"].get_active(): + migrate_class = self.fsoptionsDict["migfstypeCombo"].get_active_value() + + if self.fsoptionsDict.has_key("resizecb") and self.fsoptionsDict["resizecb"].get_active(): + targetSize = self.fsoptionsDict["resizesb"].get_value_as_int() + + if format: + actions.append(ActionDestroyFormat(usedev)) + actions.append(ActionCreateFormat(usedev, format) + if luksdev: + actions.append(ActionCreateDevice(luksdev)) + + err = self.storage.sanityCheckRequest(lv, + skipMntPtExistCheck=1, + pesize=pesize) + if not err: + err = self.storage.isMountPointInUse(lv) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err), custom_icon="error") continue - if (not request.format and - request.mountpoint and request.formatByDefault()): - if not queryNoFormatPreExisting(self.intf): - continue - - # see if there is room for request - (availSpaceMB, neededSpaceMB, fspace) = self.computeSpaceValues(usepe=pesize) - - tmplogreqs = [] - for l in self.logvolreqs: - if origlvname and l.logicalVolumeName == origlvname: + if usedev.format.exists and format.mountable and \ + self.storage.formatByDefault(usedev) and \ + not queryNoFormatPreExisting(self.intf): continue - - tmplogreqs.append(l) - - tmplogreqs.append(request) - neededSpaceMB = self.computeLVSpaceNeeded(tmplogreqs) - - if neededSpaceMB > availSpaceMB: - self.intf.messageWindow(_("Not enough space"), - _("The logical volumes you have " - "configured require %d MB, but the " - "volume group only has %d MB. Please " - "either make the volume group larger " - "or make the logical volume(s) smaller.") % (neededSpaceMB, availSpaceMB), custom_icon="error") - del tmplogreqs - continue # everything ok break - # now remove the previous request, insert request created above - if not isNew: - self.logvolreqs.remove(logrequest) - iter = self.getCurrentLogicalVolume() - self.logvolstore.remove(iter) - if request.targetSize is not None: - size = request.targetSize - # adjust the free space in the vg - if logrequest.targetSize is not None: - diff = request.targetSize - logrequest.targetSize - else: - diff = request.targetSize - request.size - self.origvgrequest.free -= diff - - self.logvolreqs.append(request) - - iter = self.logvolstore.append() - self.logvolstore.set_value(iter, 0, lvname) - if request.fstype and request.fstype.isMountable(): - self.logvolstore.set_value(iter, 1, mntpt) - else: - self.logvolstore.set_value(iter, 1, "N/A") - - self.logvolstore.set_value(iter, 2, "%Ld" % (size,)) + for action in actions: + oldaction = self.storage.devicetree.registerAction(action) + if oldaction: + self.actions.remove(oldaction) + self.actions.append(action) + self.updateLogVolStore() self.updateVGSpaceLabels() dialog.destroy() + return def editCurrentLogicalVolume(self): iter = self.getCurrentLogicalVolume() @@ -744,15 +714,11 @@ class VolumeGroupEditor: return logvolname = self.logvolstore.get_value(iter, 0) - logrequest = None - for lv in self.logvolreqs: - if lv.logicalVolumeName == logvolname: - logrequest = lv - - if logrequest is None: + lv = self.storage.devicetree.getDeviceByName(logvolname) + if lv is None: return - self.editLogicalVolume(logrequest) + self.editLogicalVolume(lv) def addLogicalVolumeCB(self, widget): if self.numAvailableLVSlots() < 1: @@ -761,8 +727,8 @@ class VolumeGroupEditor: "volumes per volume group.") % (lvm.MAX_LV_SLOTS,), custom_icon="error") return - (tspace, uspace, fspace) = self.computeSpaceValues() - if fspace <= 0: + (total, used, free) = self.computeSpaceValues() + if free <= 0: self.intf.messageWindow(_("No free space"), _("There is no room left in the " "volume group to create new logical " @@ -773,9 +739,10 @@ class VolumeGroupEditor: "logical volumes"), custom_icon="error") return - request = LogicalVolumeRequestSpec(fileSystemTypeGetDefault(), - size = fspace) - self.editLogicalVolume(request, isNew = 1) + lv = self.storage.newLV(self.vg, + fmt_type=self.storage.defaultFSType, + size=free) + self.editLogicalVolume(lv, isNew = 1) return def editLogicalVolumeCB(self, widget): @@ -798,9 +765,13 @@ class VolumeGroupEditor: if not rc: return - for lv in self.logvolreqs: - if lv.logicalVolumeName == logvolname: - self.logvolreqs.remove(lv) + name = "%s-%s" % (self.vg.name, logvolname) + lv = self.storage.devicetree.getDeviceByName(name) + action = ActionDestroyDevice(lv) + oldaction = self.storage.devicetree.registerAction(action) + if oldaction: + self.actions.remove(oldaction) + self.actions.append(action) self.logvolstore.remove(iter) @@ -820,9 +791,8 @@ class VolumeGroupEditor: partname = model.get_value(iter, 1) if val: - pvreq = self.partitions.getRequestByDeviceName(partname) - id = pvreq.uniqueID - pv.append(id) + dev = self.storage.devicetree.getDeviceByName(partname) + pv.append(dev) next = model.iter_next(iter) currow = currow + 1 @@ -831,10 +801,9 @@ class VolumeGroupEditor: def computeVGSize(self, pvlist, curpe): availSpaceMB = 0L - for id in pvlist: - pvreq = self.partitions.getRequestByID(id) - pvsize = pvreq.getActualSize(self.partitions, self.diskset) - pvsize = lvm.clampPVSize(pvsize, curpe) - (curpe/1024) + for pv in pvlist: + # XXX why the subtraction? + pvsize = lvm.clampSize(pvsize, curpe) - (curpe/1024) # have to clamp pvsize to multiple of PE availSpaceMB = availSpaceMB + pvsize @@ -845,29 +814,29 @@ class VolumeGroupEditor: def computeLVSpaceNeeded(self, logreqs): neededSpaceMB = 0 for lv in logreqs: - neededSpaceMB = neededSpaceMB + lv.getActualSize(self.partitions, self.diskset, True) + neededSpaceMB = neededSpaceMB + lv.size return neededSpaceMB def updateLogVolStore(self): self.logvolstore.clear() - for lv in self.logvolreqs: + for lv in self.vg.lvs: iter = self.logvolstore.append() - size = lv.getActualSize(self.partitions, self.diskset, True) - lvname = lv.logicalVolumeName - mntpt = lv.mountpoint - if lvname: + if lv.format.type == "luks": + usedev = self.storage.devicetree.getChildren(lv)[0] + else: + usedev = lv + + mntpt = getattr(usedev.format, "mountpoint", "") + if lv.lvname: self.logvolstore.set_value(iter, 0, lvname) - if lv.fstype and lv.fstype.isMountable(): - if mntpt: - self.logvolstore.set_value(iter, 1, mntpt) - else: - self.logvolstore.set_value(iter, 1, "") + if usedev.format.type and usedev.format.mountable: + self.logvolstore.set_value(iter, 1, mntpt) else: self.logvolstore.set_value(iter, 1, "N/A") - self.logvolstore.set_value(iter, 2, "%Ld" % (size,)) + self.logvolstore.set_value(iter, 2, "%Ld" % (lv.size,)) def updateVGSpaceLabels(self, alt_pvlist=None): if alt_pvlist == None: @@ -875,21 +844,21 @@ class VolumeGroupEditor: else: pvlist = alt_pvlist - (tspace, uspace, fspace) = self.computeSpaceValues(alt_pvlist=pvlist) + (total, used, free) = self.computeSpaceValues(alt_pvlist=pvlist) - self.totalSpaceLabel.set_text("%10.2f MB" % (tspace,)) - self.usedSpaceLabel.set_text("%10.2f MB" % (uspace,)) + self.totalSpaceLabel.set_text("%10.2f MB" % (total,)) + self.usedSpaceLabel.set_text("%10.2f MB" % (used,)) - if tspace > 0: - usedpercent = (100.0*uspace)/tspace + if total > 0: + usedpercent = (100.0*used)/total else: usedpercent = 0.0 self.usedPercentLabel.set_text("(%4.1f %%)" % (usedpercent,)) - self.freeSpaceLabel.set_text("%10.2f MB" % (fspace,)) - if tspace > 0: - freepercent = (100.0*fspace)/tspace + self.freeSpaceLabel.set_text("%10.2f MB" % (free,)) + if total > 0: + freepercent = (100.0*free)/total else: freepercent = 0.0 @@ -907,12 +876,16 @@ class VolumeGroupEditor: if rc == 2: self.destroy() + # cancel all the actions we have registered + self.actions.reverse() + for action in self.actions: + self.storage.devicetree.cancelAction(action) return None pvlist = self.getSelectedPhysicalVolumes(self.lvmlist.get_model()) - pesize = int(self.peCombo.get_active_value()) + pesize = int(self.peCombo.get_active_value()) / 1024.0 availSpaceMB = self.computeVGSize(pvlist, pesize) - neededSpaceMB = self.computeLVSpaceNeeded(self.logvolreqs) + neededSpaceMB = self.computeLVSpaceNeeded(self.vg.lvs) if neededSpaceMB > availSpaceMB: self.intf.messageWindow(_("Not enough space"), @@ -924,20 +897,21 @@ class VolumeGroupEditor: continue # check volume name - volname = string.strip(self.volnameEntry.get_text()) + volname = self.volnameEntry.get_text().strip() err = sanityCheckVolumeGroupName(volname) if err: self.intf.messageWindow(_("Invalid Volume Group Name"), err, custom_icon="error") continue - if self.origvgrequest: - origvname = self.origvgrequest.volumeGroupName + if self.vg: + origvname = self.vg.name else: origname = None if origvname != volname: - if self.partitions.isVolumeGroupNameInUse(volname): + # maybe we should see if _any_ device has this name + if volname in [vg.name for vg in self.storage.vgs]: self.intf.messageWindow(_("Name in use"), _("The volume group name \"%s\" is " "already in use. Please pick " @@ -946,39 +920,27 @@ class VolumeGroupEditor: continue # get physical extent - pesize = int(self.peCombo.get_active_value()) + pesize = int(self.peCombo.get_active_value()) / 1024.0 # everything ok break - request = VolumeGroupRequestSpec(physvols = pvlist, vgname = volname, - pesize = pesize) - - # if it was preexisting, it still should be - if self.origvgrequest and self.origvgrequest.getPreExisting(): - request.preexist = 1 - elif self.origvgrequest: - request.format = self.origvgrequest.format - - return (request, self.logvolreqs) + return self.actions def destroy(self): if self.dialog: self.dialog.destroy() self.dialog = None - def __init__(self, anaconda, partitions, diskset, intf, parent, origvgrequest, isNew = 0): - self.partitions = partitions - self.diskset = diskset - self.origvgrequest = origvgrequest + def __init__(self, anaconda, intf, parent, vg, isNew = 0): + self.storage = anaconda.id.storage + self.vg = vg self.isNew = isNew self.intf = intf self.parent = parent + self.actions = [] - self.availlvmparts = self.partitions.getAvailLVMPartitions(self.origvgrequest, - self.diskset) - self.logvolreqs = self.partitions.getLVMLVForVG(self.origvgrequest) - self.origvolreqs = copy.copy(self.logvolreqs) + self.availlvmparts = self.storage.unusedPVs(vg=vg) # if no PV exist, raise an error message and return if len(self.availlvmparts) < 1: @@ -997,8 +959,8 @@ class VolumeGroupEditor: tstr = _("Make LVM Volume Group") else: try: - tstr = _("Edit LVM Volume Group: %s") % (origvgrequest.volumeGroupName,) - except: + tstr = _("Edit LVM Volume Group: %s") % (vg.name,) + except AttributeError: tstr = _("Edit LVM Volume Group") dialog = gtk.Dialog(tstr, self.parent) @@ -1014,17 +976,17 @@ class VolumeGroupEditor: row = 0 # volume group name - if not origvgrequest.getPreExisting(): + if not vg.exists: lbl = createAlignedLabel(_("_Volume Group Name:")) self.volnameEntry = gtk.Entry(16) lbl.set_mnemonic_widget(self.volnameEntry) if not self.isNew: - self.volnameEntry.set_text(self.origvgrequest.volumeGroupName) + self.volnameEntry.set_text(self.vg.name) else: - self.volnameEntry.set_text(lvm.createSuggestedVGName(self.partitions, anaconda.id.network)) + self.volnameEntry.set_text(storage.suggestedVGName(anaconda.id.network)) else: lbl = createAlignedLabel(_("Volume Group Name:")) - self.volnameEntry = gtk.Label(self.origvgrequest.volumeGroupName) + self.volnameEntry = gtk.Label(self.vg.name) maintable.attach(lbl, 0, 1, row, row + 1, gtk.EXPAND|gtk.FILL, gtk.SHRINK) @@ -1032,9 +994,9 @@ class VolumeGroupEditor: row = row + 1 lbl = createAlignedLabel(_("_Physical Extent:")) - self.peCombo = self.createPEOptionMenu(self.origvgrequest.pesize) + self.peCombo = self.createPEOptionMenu(self.vg.peSize * 1024) lbl.set_mnemonic_widget(self.peCombo) - if origvgrequest.getPreExisting(): + if vg.exists: self.peCombo.set_sensitive(False) maintable.attach(lbl, 0, 1, row, row + 1, @@ -1042,8 +1004,8 @@ class VolumeGroupEditor: maintable.attach(self.peCombo, 1, 2, row, row + 1, gtk.EXPAND|gtk.FILL, gtk.SHRINK) row = row + 1 - (self.lvmlist, sw) = self.createAllowedLvmPartitionsList(self.availlvmparts, self.origvgrequest.physicalVolumes, self.partitions, origvgrequest.getPreExisting()) - if origvgrequest.getPreExisting(): + (self.lvmlist, sw) = self.createAllowedLvmPartitionsList(self.availlvmparts, self.storage.vgs) + if vg.exists: self.lvmlist.set_sensitive(False) self.lvmlist.set_size_request(275, 80) lbl = createAlignedLabel(_("Physical Volumes to _Use:")) @@ -1105,15 +1067,23 @@ class VolumeGroupEditor: gobject.TYPE_STRING, gobject.TYPE_STRING) - if self.logvolreqs: - for lvrequest in self.logvolreqs: + if self.vg.lvs: + for lv in self.vg.lvs: iter = self.logvolstore.append() - self.logvolstore.set_value(iter, 0, lvrequest.logicalVolumeName) - if lvrequest.mountpoint is not None: - self.logvolstore.set_value(iter, 1, lvrequest.mountpoint) + self.logvolstore.set_value(iter, 0, lv.lvname) + if lv.format.type == "luks": + usedev = self.storage.devicetree.getChildren(lv)[0] + format = usedev.format + else: + usedev = lv + format = usedev.format + + if getattr(format, "mountpoint", None): + self.logvolstore.set_value(iter, 1, + format.mountpoint) else: self.logvolstore.set_value(iter, 1, "") - self.logvolstore.set_value(iter, 2, "%Ld" % (lvrequest.getActualSize(self.partitions, self.diskset, True))) + self.logvolstore.set_value(iter, 2, "%Ld" % lv.size) self.logvollist = gtk.TreeView(self.logvolstore) col = gtk.TreeViewColumn(_("Logical Volume Name"), diff --git a/iw/partition_dialog_gui.py b/iw/partition_dialog_gui.py index 04e45db6a..272b8bd00 100644 --- a/iw/partition_dialog_gui.py +++ b/iw/partition_dialog_gui.py @@ -26,9 +26,7 @@ import gobject import gtk import gui -from fsset import * -from cryptodev import LUKSDevice -from partRequests import * +from storage.devices import PartitionDevice from partition_ui_helpers_gui import * from constants import * @@ -50,13 +48,6 @@ class PartitionEditor: adj.clamp_page(size, adj.upper) fillmaxszsb.set_adjustment(adj) - def cylspinchangedCB(self, widget, data): - (dev, startcylspin, endcylspin, bycyl_sizelabel) = data - startsec = dev.startCylinderToSector(startcylspin.get_value_as_int()) - endsec = dev.endCylinderToSector(endcylspin.get_value_as_int()) - cursize = (endsec - startsec)/2048 - bycyl_sizelabel.set_text("%s" % (int(cursize))) - def fillmaxszCB(self, widget, spin): spin.set_sensitive(widget.get_active()) @@ -111,150 +102,141 @@ class PartitionEditor: while 1: rc = self.dialog.run() + actions = [] # user hit cancel, do nothing if rc == 2: self.destroy() return None - if self.origrequest.type == REQUEST_NEW: + if not self.origrequest.exists: # read out UI into a partition specification - filesystem = self.newfstypeCombo.get_active_value() - - request = copy.copy(self.origrequest) - request.fstype = filesystem - request.format = True - - if request.fstype.isMountable(): - request.mountpoint = self.mountCombo.get_children()[0].get_text() - else: - request.mountpoint = None + fmt_class = self.newfstypeCombo.get_active_value() + # there's nothing about origrequest we care about + #request = copy.copy(self.origrequest) + mountpoint = self.mountCombo.get_children()[0].get_text() if self.primonlycheckbutton.get_active(): - primonly = True + primary = True else: - primonly = None + primary = None + format = fmt_class(mountpoint=mountpoint) if self.lukscb and self.lukscb.get_active(): - if not request.encryption: - request.encryption = LUKSDevice(passphrase = self.partitions.encryptionPassphrase, format=1) + luksformat = format + format = getFormat("luks", + passphrase=self.storage.encryptionPassphrase) + luksdev = LUKSDevice("luks%d" % self.storage.nextID, + format=luksformat, + parents=request) + + if self.fixedrb.get_active(): + grow = None else: - request.encryption = None - - if not self.newbycyl: - if self.fixedrb.get_active(): - grow = None - else: - grow = True - - self.sizespin.update() - - if self.fillmaxszrb.get_active(): - self.fillmaxszsb.update() - maxsize = self.fillmaxszsb.get_value_as_int() - else: - maxsize = None - - allowdrives = [] - model = self.driveview.get_model() - iter = model.get_iter_first() - while iter: - val = model.get_value(iter, 0) - drive = model.get_value(iter, 1) - - if val: - allowdrives.append(drive) - - iter = model.iter_next(iter) - - if len(allowdrives) == len(self.diskset.disks.keys()): - allowdrives = None - - request.size = self.sizespin.get_value_as_int() - request.drive = allowdrives - request.grow = grow - request.primary = primonly - request.maxSizeMB = maxsize - else: - self.startcylspin.update() - self.endcylspin.update() - - request.start = self.startcylspin.get_value_as_int() - request.end = self.endcylspin.get_value_as_int() - request.primary = primonly - - if request.end <= request.start: - self.intf.messageWindow(_("Error With Request"), - _("The end cylinder must be " - "greater than the start " - "cylinder."), custom_icon="error") + grow = True - continue + self.sizespin.update() - err = request.sanityCheckRequest(self.partitions) + if self.fillmaxszrb.get_active(): + self.fillmaxszsb.update() + maxsize = self.fillmaxszsb.get_value_as_int() + else: + maxsize = None + + allowdrives = [] + model = self.driveview.get_model() + iter = model.get_iter_first() + while iter: + val = model.get_value(iter, 0) + drive = model.get_value(iter, 1) + + if val: + allowdrives.append(drive) + + iter = model.iter_next(iter) + + if len(allowdrives) == len(self.storage.disks): + allowdrives = None + + size = self.sizespin.get_value_as_int() + disks = [] + if allowdrives: + for drive in allowdrives: + for disk in self.storage.disks: + if disk.name == drive: + disks.append(disk) + + # TODO: when will we set bootable? + request = PartitionDevice("new%d" % self.storage.nextID, + format=format, + size=size, + grow=grow, + maxsize=maxsize, + primary=primary, + parents=disks) + + err = storage.sanityCheckRequest(request) if not err: - err = doUIRAIDLVMChecks(request, self.diskset) + err = doUIRAIDLVMChecks(request, self.storage) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err), custom_icon="error") continue + + # we're all set, so create the actions + if luksdev: + actions.append(ActionCreateDevice(luksdev)) + actions.append(ActionCreateDevice(request)) else: # preexisting partition, just set mount point and format flag request = copy.copy(self.origrequest) - request.encryption = copy.deepcopy(self.origrequest.encryption) - - if self.fsoptionsDict.has_key("formatcb"): - request.format = self.fsoptionsDict["formatcb"].get_active() - if request.format: - request.fstype = self.fsoptionsDict["fstypeCombo"].get_active_value() - else: - request.format = 0 - - if self.fsoptionsDict.has_key("migratecb"): - request.migrate = self.fsoptionsDict["migratecb"].get_active() - if request.migrate: - request.fstype =self.fsoptionsDict["migfstypeCombo"].get_active_value() - else: - request.migrate = 0 - - if self.fsoptionsDict.has_key("resizecb") and self.fsoptionsDict["resizecb"].get_active(): - request.targetSize = self.fsoptionsDict["resizesb"].get_value_as_int() - else: - request.targetSize = None - - # set back if we are not formatting or migrating - origfstype = self.origrequest.origfstype - if not request.format and not request.migrate: - request.fstype = origfstype - - if request.fstype.isMountable(): - request.mountpoint = self.mountCombo.get_children()[0].get_text() - else: - request.mountpoint = None - - lukscb = self.fsoptionsDict.get("lukscb") - if lukscb and lukscb.get_active(): - if not request.encryption: - request.encryption = LUKSDevice(passphrase=self.partitions.encryptionPassphrase, format=1) - else: - request.encryption = None - - err = request.sanityCheckRequest(self.partitions) + mountpoint = self.mountCombo.get_children()[0].get_text() + if self.fsoptionsDict.has_key("formatcb") and \ + self.fsoptionsDict["formatcb"].get_active(): + fmt_class = self.fsoptionsDict["fstypeCombo"].get_active_value() + format = fmt_class(mountpoint=mountpoint) + if self.fsoptionsDict.has_key("lukscb") and \ + lukscb.get_active() and \ + request.format.type != "luks": + luksdev = LUKSDevice("luks%d" % self.storage.nextID, + format=format, + parents=request) + actions.append(ActionCreateDevice(luksdev) + format = getFormat("luks", + device=self.origrequest.path, + passphrase=self.storage.encryptionPassphrase) + actions.append(ActionCreateFormat(request, format)) + + if self.fsoptionsDict.has_key("migratecb") and \ + self.fsoptionsDict["migratecb"].get_active(): + format = getFormat(self.fsoptionsDict["migfstypeCombo"].get_active_value(), mountpoint=mountpoint) + # TODO: implement ActionMigrateFormat + #actions.append(ActionMigrateFormat(request, format)) + + if self.fsoptionsDict.has_key("resizecb") and \ + self.fsoptionsDict["resizecb"].get_active(): + size = self.fsoptionsDict["resizesb"].get_value_as_int() + actions.append(ActionResizeDevice(request, size) + if request.format.type != "none": + actions.append(ActionResizeFormat(request, size)) + + err = self.storage.sanityCheckRequest(request) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err), custom_icon="error") continue - if (not request.format and - request.mountpoint and request.formatByDefault()): + if request.format.exists and \ + getattr(request, "mountpoint", None) and \ + self.storage.formatByDefault(request)): if not queryNoFormatPreExisting(self.intf): continue - - # everything ok, fall out of loop + + # everything ok, fall out of loop break - - return request + + return actions def destroy(self): if self.dialog: @@ -265,8 +247,7 @@ class PartitionEditor: def __init__(self, anaconda, parent, origrequest, isNew = 0, restrictfs = None): self.anaconda = anaconda - self.partitions = self.anaconda.id.partitions - self.diskset = self.anaconda.id.diskset + self.storage = self.anaconda.id.storage self.intf = self.anaconda.intf self.origrequest = origrequest self.isNew = isNew @@ -275,10 +256,7 @@ class PartitionEditor: if isNew: tstr = _("Add Partition") else: - try: - tstr = _("Edit Partition: /dev/%s") % (origrequest.device,) - except: - tstr = _("Edit Partition") + tstr = _("Edit Partition: %s") % (origrequest.path,) self.dialog = gtk.Dialog(tstr, self.parent) gui.addFrame(self.dialog) @@ -291,24 +269,36 @@ class PartitionEditor: maintable.set_col_spacings(5) row = 0 - # see if we are creating a floating request or by cylinder - if self.origrequest.type == REQUEST_NEW: - self.newbycyl = self.origrequest.start != None + # if this is a luks device we need to grab info from two devices + # to make it seem like one device. wee! + if self.origrequest.format.type == "luks": + luksdev = self.storage.devicetree.getChildren(self.origrequest)[0] + fmt_type = luksdev.format.type + mountpoint = getattr(luksdev.format, "mountpoint", None) + fslabel = getattr(luksdev.format, "label", None) + # XXX might need to add migrate stuff here, too + usereq = luksdev + else: + usereq = self.origrequest # Mount Point entry lbl = createAlignedLabel(_("_Mount Point:")) maintable.attach(lbl, 0, 1, row, row + 1) - self.mountCombo = createMountPointCombo(origrequest) + self.mountCombo = createMountPointCombo(usereq) lbl.set_mnemonic_widget(self.mountCombo) maintable.attach(self.mountCombo, 1, 2, row, row + 1) row = row + 1 # Partition Type - if self.origrequest.type == REQUEST_NEW: + if not self.origrequest.format.exists: lbl = createAlignedLabel(_("File System _Type:")) maintable.attach(lbl, 0, 1, row, row + 1) - self.newfstypeCombo = createFSTypeMenu(self.origrequest.fstype, + if luksdev: + usereq = luksdev + else: + usereq = self.origrequest + self.newfstypeCombo = createFSTypeMenu(usereq.format.type, fstypechangeCB, self.mountCombo, availablefstypes = restrictfs) @@ -320,103 +310,49 @@ class PartitionEditor: row = row + 1 # allowable drives - if self.origrequest.type == REQUEST_NEW: - if not self.newbycyl: - lbl = createAlignedLabel(_("Allowable _Drives:")) - maintable.attach(lbl, 0, 1, row, row + 1) - - self.driveview = createAllowedDrivesList(self.diskset.disks, - self.origrequest.drive, - selectDrives=False, - disallowDrives=[self.anaconda.updateSrc]) - lbl.set_mnemonic_widget(self.driveview) - sw = gtk.ScrolledWindow() - sw.add(self.driveview) - sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - sw.set_shadow_type(gtk.SHADOW_IN) - maintable.attach(sw, 1, 2, row, row + 1) - self.driveview.set_size_request(375, 80) - else: - maintable.attach(createAlignedLabel(_("Drive:")), - 0, 1, row, row + 1) - maintable.attach(createAlignedLabel(origrequest.drive[0]), - 1, 2, row, row + 1) + if not self.origrequest.exists: + lbl = createAlignedLabel(_("Allowable _Drives:")) + maintable.attach(lbl, 0, 1, row, row + 1) + + self.driveview = createAllowedDrivesList(self.storage.disks, + self.origrequest.req_disks, + selectDrives=False, + disallowDrives=[self.anaconda.updateSrc]) + lbl.set_mnemonic_widget(self.driveview) + sw = gtk.ScrolledWindow() + sw.add(self.driveview) + sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + sw.set_shadow_type(gtk.SHADOW_IN) + maintable.attach(sw, 1, 2, row, row + 1) + self.driveview.set_size_request(375, 80) row = row + 1 # original fs label - if self.origrequest.type != REQUEST_NEW and self.origrequest.fslabel: + if usereq.format.exists and \ + getattr(usereq.format, "label", None): maintable.attach(createAlignedLabel(_("Original File System " "Label:")), 0, 1, row, row + 1) - fslabel = gtk.Label(self.origrequest.fslabel) + fslabel = gtk.Label(usereq.format.label) maintable.attach(fslabel, 1, 2, row, row + 1) - row = row + 1 # size - if self.origrequest.type == REQUEST_NEW: - if not self.newbycyl: - # Size specification - lbl = createAlignedLabel(_("_Size (MB):")) - maintable.attach(lbl, 0, 1, row, row + 1) - sizeAdj = gtk.Adjustment(value = 1, lower = 1, - upper = MAX_PART_SIZE, step_incr = 1) - self.sizespin = gtk.SpinButton(sizeAdj, digits = 0) - self.sizespin.set_property('numeric', True) - - if self.origrequest.size: - self.sizespin.set_value(self.origrequest.size) - - lbl.set_mnemonic_widget(self.sizespin) - maintable.attach(self.sizespin, 1, 2, row, row + 1) - bycyl_sizelabel = None - else: - # XXX need to add partition by size and - # wire in limits between start and end - dev = self.diskset.disks[origrequest.drive[0]].dev - maintable.attach(createAlignedLabel(_("Size (MB):")), - 0, 1, row, row + 1) - bycyl_sizelabel = createAlignedLabel("") - maintable.attach(bycyl_sizelabel, 1, 2, row, row + 1) - row = row + 1 + if not self.origrequest.exists: + # Size specification + lbl = createAlignedLabel(_("_Size (MB):")) + maintable.attach(lbl, 0, 1, row, row + 1) + sizeAdj = gtk.Adjustment(value = 1, lower = 1, + upper = MAX_PART_SIZE, step_incr = 1) + self.sizespin = gtk.SpinButton(sizeAdj, digits = 0) + self.sizespin.set_property('numeric', True) - lbl = createAlignedLabel(_("_Start Cylinder:")) - maintable.attach(lbl, 0, 1, row, row + 1) - - (maxcyl, h, s) = self.diskset.disks[origrequest.drive[0]].device.biosGeometry - cylAdj = gtk.Adjustment(value=origrequest.start, - lower=origrequest.start, - upper=maxcyl, - step_incr=1) - self.startcylspin = gtk.SpinButton(cylAdj, digits=0) - self.startcylspin.set_property('numeric', True) - lbl.set_mnemonic_widget(self.startcylspin) - maintable.attach(self.startcylspin, 1, 2, row, row + 1) - row = row + 1 - - endcylAdj = gtk.Adjustment(value=origrequest.end, - lower=origrequest.start, - upper=maxcyl, - step_incr=1) - lbl = createAlignedLabel(_("_End Cylinder:")) - maintable.attach(lbl, 0, 1, row, row + 1) - self.endcylspin = gtk.SpinButton(endcylAdj, digits = 0) - self.endcylspin.set_property('numeric', True) - lbl.set_mnemonic_widget(self.endcylspin) - maintable.attach(self.endcylspin, 1, 2, row, row + 1) - - self.startcylspin.connect("value-changed", self.cylspinchangedCB, - (dev, self.startcylspin, - self.endcylspin, bycyl_sizelabel)) - self.endcylspin.connect("value-changed", self.cylspinchangedCB, - (dev, self.startcylspin, - self.endcylspin, bycyl_sizelabel)) - - startsec = dev.startCylinderToSector(origrequest.start) - endsec = dev.endCylinderToSector(origrequest.end) - cursize = (endsec - startsec)/2048 - bycyl_sizelabel.set_text("%s" % (int(cursize))) + if self.origrequest.req_size: + self.sizespin.set_value(self.origrequest.req_size) + + lbl.set_mnemonic_widget(self.sizespin) + maintable.attach(self.sizespin, 1, 2, row, row + 1) else: self.sizespin = None @@ -425,45 +361,43 @@ class PartitionEditor: # format/migrate options for pre-existing partitions, as long as they # aren't protected (we'd still like to be able to mount them, though) self.fsoptionsDict = {} - if self.origrequest.type == REQUEST_PREEXIST and self.origrequest.fstype and not self.origrequest.getProtected(): - (row, self.fsoptionsDict) = createPreExistFSOptionSection(self.origrequest, maintable, row, self.mountCombo, self.partitions) + if self.origrequest.exists and \ + usereq.format.type != "none" and \ + not self.storage.isProtected(self.origrequest): + (row, self.fsoptionsDict) = createPreExistFSOptionSection(usereq, maintable, row, self.mountCombo, self.storage) # size options - if self.origrequest.type == REQUEST_NEW: - if not self.newbycyl: - (sizeframe, self.fixedrb, self.fillmaxszrb, - self.fillmaxszsb) = self.createSizeOptionsFrame(self.origrequest, - self.fillmaxszCB) - self.sizespin.connect("value-changed", self.sizespinchangedCB, - self.fillmaxszsb) - - maintable.attach(sizeframe, 0, 2, row, row + 1) - else: - # XXX need new by cyl options (if any) - pass + if not self.origrequest.exists: + (sizeframe, self.fixedrb, self.fillmaxszrb, + self.fillmaxszsb) = self.createSizeOptionsFrame(self.origrequest, + self.fillmaxszCB) + self.sizespin.connect("value-changed", self.sizespinchangedCB, + self.fillmaxszsb) + + maintable.attach(sizeframe, 0, 2, row, row + 1) row = row + 1 else: self.sizeoptiontable = None # create only as primary - if self.origrequest.type == REQUEST_NEW: + if not self.origrequest.exists: self.primonlycheckbutton = gtk.CheckButton(_("Force to be a _primary " "partition")) self.primonlycheckbutton.set_active(0) - if self.origrequest.primary: + if self.origrequest.req_primary: self.primonlycheckbutton.set_active(1) # only show if we have something other than primary - if not self.diskset.onlyPrimaryParts(): + if self.storage.extendedPartitionsSupported(): maintable.attach(self.primonlycheckbutton, 0, 2, row, row+1) row = row + 1 # checkbutton for encryption using dm-crypt/LUKS - if self.origrequest.type == REQUEST_NEW: + if not self.origrequest.exists: self.lukscb = gtk.CheckButton(_("_Encrypt")) self.lukscb.set_data("formatstate", 1) - if self.origrequest.encryption: + if self.origrequest.format.type == "luks": self.lukscb.set_active(1) else: self.lukscb.set_active(0) diff --git a/iw/partition_gui.py b/iw/partition_gui.py index b753639ba..94d8781fa 100644 --- a/iw/partition_gui.py +++ b/iw/partition_gui.py @@ -99,7 +99,7 @@ class DiskStripeSlice: if event.button == 1: self.parent.selectSlice(self.partition, 1) elif event.type == gtk.gdk._2BUTTON_PRESS: - self.editCb() + self.editCB() return True @@ -183,12 +183,12 @@ class DiskStripeSlice: clip_width=xlength-1, clip_height=yheight-1) self.hideOrShowText() - def __init__(self, parent, partition, treeView, editCb): + def __init__(self, parent, partition, treeView, editCB): self.text = None self.partition = partition self.parent = parent self.treeView = treeView - self.editCb = editCb + self.editCB = editCB pgroup = parent.getGroup() self.group = pgroup.add(gnomecanvas.CanvasGroup) @@ -199,14 +199,14 @@ class DiskStripeSlice: self.update() class DiskStripe: - def __init__(self, drive, disk, group, tree, editCb): + def __init__(self, drive, disk, group, tree, editCB): self.disk = disk self.group = group self.tree = tree self.drive = drive self.slices = [] self.hash = {} - self.editCb = editCb + self.editCB = editCB self.selected = None # XXX hack but will work for now @@ -260,17 +260,17 @@ class DiskStripe: self.selected = None def add(self, partition): - stripe = DiskStripeSlice(self, partition, self.tree, self.editCb) + stripe = DiskStripeSlice(self, partition, self.tree, self.editCB) self.slices.append(stripe) self.hash[partition] = stripe class DiskStripeGraph: - def __init__(self, tree, editCb): + def __init__(self, tree, editCB): self.canvas = gnomecanvas.Canvas() self.diskStripes = [] self.textlabels = [] self.tree = tree - self.editCb = editCb + self.editCB = editCB self.next_ypos = 0.0 def __del__(self): @@ -335,7 +335,7 @@ class DiskStripeGraph: self.textlabels.append(text) group = self.canvas.root().add(gnomecanvas.CanvasGroup, x=0, y=yoff+textheight) - stripe = DiskStripe(drive, disk, group, self.tree, self.editCb) + stripe = DiskStripe(drive, disk, group, self.tree, self.editCB) self.diskStripes.append(stripe) self.next_ypos = self.next_ypos + STRIPE_HEIGHT+textheight+10 return stripe @@ -372,8 +372,6 @@ class DiskTreeModel(gtk.TreeStore): # (N_("Size (MB)"), gobject.TYPE_STRING, 1.0, 0, isLeaf), (N_("Format"), gobject.TYPE_OBJECT, 0.5, 0, isFormattable), (N_("Size (MB)"), gobject.TYPE_STRING, 1.0, 0, 0), - (N_("Start"), gobject.TYPE_STRING, 1.0, 0, 1), - (N_("End"), gobject.TYPE_STRING, 1.0, 0, 1), ("", gobject.TYPE_STRING, 0.0, 0, 0), # the following must be the last two ("IsLeaf", gobject.TYPE_BOOLEAN, 0.0, 1, 0), @@ -488,25 +486,7 @@ class DiskTreeModel(gtk.TreeStore): # not found the partition raise RuntimeError, "could not find partition" - """ returns partition 'id' of current selection in tree """ - def getCurrentPartition(self): - selection = self.view.get_selection() - model, iter = selection.get_selected() - if not iter: - return None - - pyobject = self.titleSlot['PyObject'] - try: - val = self.get_value(iter, pyobject) - if type(val) == type("/dev/"): - if val[:5] == '/dev/': - return None - - return val - except: - return None - - """ Return name of current selected drive (if a drive is highlighted) """ + """ Return the device representing the current selection """ def getCurrentDevice(self): selection = self.view.get_selection() model, iter = selection.get_selected() @@ -516,12 +496,10 @@ class DiskTreeModel(gtk.TreeStore): pyobject = self.titleSlot['PyObject'] try: val = self.get_value(iter, pyobject) - if type(val) == type("/dev/"): - if val[:5] == '/dev/': - return val - return None - except: - return None + except Exception: + val = None + + return val def resetSelection(self): pass @@ -632,8 +610,7 @@ class PartitionWindow(InstallWindow): return rc def getNext(self): - (errors, warnings) = self.partitions.sanityCheckAllRequests(self.diskset) - + (errors, warnings) = self.storage.sanityCheckAllRequests() if errors: labelstr1 = _("The partitioning scheme you requested " "caused the following critical errors.") @@ -649,6 +626,7 @@ class PartitionWindow(InstallWindow): raise gui.StayOnScreen if warnings: + # "storage configuration" labelstr1 = _("The partitioning scheme you requested " "generated the following warnings.") labelstr2 = _("Would you like to continue with " @@ -663,8 +641,7 @@ class PartitionWindow(InstallWindow): if rc != 1: raise gui.StayOnScreen - formatWarnings = getPreExistFormatWarnings(self.partitions, - self.diskset) + formatWarnings = getPreExistFormatWarnings(self.storage) if formatWarnings: labelstr1 = _("The following pre-existing partitions have been " "selected to be formatted, destroying all data.") @@ -676,7 +653,7 @@ class PartitionWindow(InstallWindow): commentstr = "" for (dev, type, mntpt) in formatWarnings: commentstr = commentstr + \ - "/dev/%s %s %s\n" % (dev,type,mntpt) + "%s %s %s\n" % (dev,type,mntpt) rc = self.presentPartitioningComments(_("Format Warnings"), labelstr1, labelstr2, @@ -695,161 +672,164 @@ class PartitionWindow(InstallWindow): def getPrev(self): self.diskStripeGraph.shutDown() - self.diskset.refreshDevices() - self.partitions.setFromDisk(self.diskset) + self.storage.reset() self.tree.clear() del self.parent return None - def getShortFSTypeName(self, name): - if name == "physical volume (LVM)": - return "LVM PV" - - return name - def populate(self, initial = 0): - - drives = self.diskset.disks.keys() - drives.sort() - self.tree.resetSelection() self.tree.clearHiddenPartitionsList() # first do LVM - lvmrequests = self.partitions.getLVMRequests() - if lvmrequests: + vgs = self.storage.vgs + if vgs: lvmparent = self.tree.append(None) self.tree[lvmparent]['Device'] = _("LVM Volume Groups") - for vgname in lvmrequests.keys(): - vgrequest = self.partitions.getRequestByVolumeGroupName(vgname) - rsize = vgrequest.getActualSize(self.partitions, self.diskset) + for vg in vgs: + rsize = vg.size vgparent = self.tree.append(lvmparent) - self.tree[vgparent]['Device'] = "%s" % (vgname,) - if vgrequest and vgrequest.type != REQUEST_NEW and vgrequest.fslabel: - self.tree[vgparent]['Label'] = "%s" % (vgrequest.fslabel,) - else: - self.tree[vgparent]['Label'] = "" + self.tree[vgparent]['Device'] = "%s" % vg.name + self.tree[vgparent]['Label'] = "" self.tree[vgparent]['Mount Point'] = "" - self.tree[vgparent]['Start'] = "" - self.tree[vgparent]['End'] = "" self.tree[vgparent]['Size (MB)'] = "%Ld" % (rsize,) - self.tree[vgparent]['PyObject'] = str(vgrequest.uniqueID) - for lvrequest in lvmrequests[vgname]: + self.tree[vgparent]['PyObject'] = vg + for lv in vg.lvs: + if lv.format.type == "luks": + # we'll want to grab format info from the mapped + # device, not the encrypted one + dm_dev = self.storage.devicetree.getChildren(lv)[0] + format = dm_dev.format + else: + format = lv.format iter = self.tree.append(vgparent) - self.tree[iter]['Device'] = lvrequest.logicalVolumeName - if lvrequest.fstype and lvrequest.mountpoint: - self.tree[iter]['Mount Point'] = lvrequest.mountpoint + self.tree[iter]['Device'] = lv.lvname + if format.mountable and format.mountpoint: + self.tree[iter]['Mount Point'] = format.mountpoint else: self.tree[iter]['Mount Point'] = "" - self.tree[iter]['Size (MB)'] = "%Ld" % (lvrequest.getActualSize(self.partitions, self.diskset, True),) - self.tree[iter]['PyObject'] = str(lvrequest.uniqueID) + self.tree[iter]['Size (MB)'] = "%Ld" % lv.size + self.tree[iter]['PyObject'] = vg - ptype = lvrequest.fstype.getName() - if lvrequest.isEncrypted(self.partitions, True) and lvrequest.format: + if lv.format.type == "luks" and not lv.format.exists: + # we're creating the LUKS header self.tree[iter]['Format'] = self.lock_pixbuf - elif lvrequest.format: + elif not format.exists: + # we're creating a format on the device self.tree[iter]['Format'] = self.checkmark_pixbuf - self.tree[iter]['IsFormattable'] = lvrequest.fstype.isFormattable() + self.tree[iter]['IsFormattable'] = format.formattable self.tree[iter]['IsLeaf'] = True - self.tree[iter]['Type'] = ptype - self.tree[iter]['Start'] = "" - self.tree[iter]['End'] = "" + self.tree[iter]['Type'] = lv.format.name + #self.tree[iter]['Start'] = "" + #self.tree[iter]['End'] = "" # handle RAID next - raidrequests = self.partitions.getRaidRequests() - if raidrequests: + mdarrays = self.storage.mdarrays + if mdarrays: raidparent = self.tree.append(None) self.tree[raidparent]['Device'] = _("RAID Devices") - for request in raidrequests: + for array in mdarrays: mntpt = None - if request and request.fstype and request.fstype.getName() == "physical volume (LVM)": - vgreq = self.partitions.getLVMVolumeGroupMemberParent(request) - if vgreq and vgreq.volumeGroupName: - if self.show_uneditable: - mntpt = vgreq.volumeGroupName - else: - self.tree.appendToHiddenPartitionsList(str(request.uniqueID)) - continue + if array.format.type == "luks": + # look up the mapped/decrypted device since that's + # where we'll find the format we want to display + dm_dev = self.storage.getChildren(array)[0] + format = dm_dev.format + else: + format = array.format + + if format.type == "lvmpv": + vg = None + for _vg in self.storage.vgs: + if _vg.dependsOn(array): + vg = _vg + break + if vg and self.show_uneditable: + mntpt = vg.name + elif vg: + self.tree.appendToHiddenPartitionsList(array.path) + continue else: mntpt = "" + elif format.mountable and format.mountpoint: + mntpt = format.mountpoint iter = self.tree.append(raidparent) if mntpt: self.tree[iter]["Mount Point"] = mntpt + else: + self.tree[iter]["Mount Point"] = "" - if request and request.mountpoint: - self.tree[iter]["Mount Point"] = request.mountpoint - - if request.fstype: - ptype = self.getShortFSTypeName(request.fstype.getName()) - - if request.isEncrypted(self.partitions, True) and request.format: + if format.type: + ptype = format.name + if array.format.type == "luks" and \ + not array.format.exists: self.tree[iter]['Format'] = self.lock_pixbuf - elif request.format: + elif not format.exists: self.tree[iter]['Format'] = self.checkmark_pixbuf - self.tree[iter]['IsFormattable'] = request.fstype.isFormattable() + self.tree[iter]['IsFormattable'] = format.formattable else: ptype = _("None") self.tree[iter]['IsFormattable'] = False - try: - device = "/dev/md%d" % (request.raidminor,) - except: + if array.minor is not None: + device = "%s" % array.path + else: device = "Auto" self.tree[iter]['IsLeaf'] = True self.tree[iter]['Device'] = device - if request and request.type != REQUEST_NEW and request.fslabel: - self.tree[iter]['Label'] = "%s" % (request.fslabel,) + if array.format.exists and getattr(format, "label", None): + self.tree[iter]['Label'] = "%s" % format.label else: self.tree[iter]['Label'] = "" self.tree[iter]['Type'] = ptype - self.tree[iter]['Start'] = "" - self.tree[iter]['End'] = "" - self.tree[iter]['Size (MB)'] = "%Ld" % (request.getActualSize(self.partitions, self.diskset),) - self.tree[iter]['PyObject'] = str(request.uniqueID) + self.tree[iter]['Size (MB)'] = "%Ld" % array.size + self.tree[iter]['PyObject'] = array # now normal partitions + disks = self.storage.disks drvparent = self.tree.append(None) self.tree[drvparent]['Device'] = _("Hard Drives") - for drive in drives: - disk = self.diskset.disks[drive] - + for disk in disks: # add a disk stripe to the graph - stripe = self.diskStripeGraph.add(drive, disk) + stripe = self.diskStripeGraph.add(disk.name, disk.partedDisk) # add a parent node to the tree parent = self.tree.append(drvparent) - self.tree[parent]['Device'] = '/dev/%s' % (drive,) - self.tree[parent]['PyObject'] = str('/dev/%s' % (drive,)) - (cylinders, heads, sectors) = disk.device.biosGeometry + self.tree[parent]['Device'] = "%s" % disk.path + self.tree[parent]['PyObject'] = disk + (cylinders, heads, sectors) = disk.partedDisk.device.biosGeometry sectorsPerCyl = heads * sectors - extendedParent = None - part = disk.getFirstPartition() + part = disk.partedDisk.getFirstPartition() while part: if part.type & parted.PARTITION_METADATA: part = part.nextPartition() continue + + extendedParent = None + partName = part.getDeviceNodeName() + device = self.storage.devicetree.getDeviceByName(partName) + if not device: + raise RuntimeError("can't find partition %s in device" + " tree" % partName) + # ignore the tiny < 1 MB partitions (#119479) if part.getSize(unit="MB") <= 1.0: - if not part.active or not part.getFlag(parted.PARTITION_BOOT): - part = part.nextPartition() + if not part.active or not device.bootable: continue stripe.add(part) - device = part.getDeviceNodeName() - request = self.partitions.getRequestByDeviceName(device) - - if part.type == parted.PARTITION_EXTENDED: + if device.isExtended: if extendedParent: raise RuntimeError, ("can't handle more than " "one extended partition per disk") extendedParent = self.tree.append(parent) iter = extendedParent - elif part.type & parted.PARTITION_LOGICAL: + elif device.isLogical: if not extendedParent: raise RuntimeError, ("crossed logical partition " "before extended") @@ -859,16 +839,28 @@ class PartitionWindow(InstallWindow): iter = self.tree.append(parent) self.tree[iter]['IsLeaf'] = True - if request and request.mountpoint: - self.tree[iter]['Mount Point'] = request.mountpoint + if device.format.type == "luks": + # look up the mapped/decrypted device in the tree + # the format we care about will be on it + dm_dev = self.storage.devicetree.getChildren(device)[0] + format = dm_dev.format + else: + format = device.format + + if format.mountable and format.mountpoint: + self.tree[iter]['Mount Point'] = format.mountpoint else: self.tree[iter]['Mount Point'] = "" - if request and request.fstype and request.fstype.getName() == "physical volume (LVM)": - vgreq = self.partitions.getLVMVolumeGroupMemberParent(request) - if vgreq and vgreq.volumeGroupName: + if format.type == "lvmpv": + vg = None + for _vg in self.storage.vgs: + if _vg.dependsOn(part): + vg = _vg + break + if vg and vg.name: if self.show_uneditable: - self.tree[iter]['Mount Point'] = vgreq.volumeGroupName + self.tree[iter]['Mount Point'] = vg.name else: self.tree.appendToHiddenPartitionsList(part) self.tree.remove(iter) @@ -876,26 +868,31 @@ class PartitionWindow(InstallWindow): else: self.tree[iter]['Mount Point'] = "" - if request.isEncrypted(self.partitions, True) and request.format: + if device.format.type == "luks" and \ + not device.format.exists: self.tree[iter]['Format'] = self.lock_pixbuf - elif request.format: + elif format.exists: self.tree[iter]['Format'] = self.checkmark_pixbuf - if request and request.fstype: - self.tree[iter]['IsFormattable'] = request.fstype.isFormattable() + if format.type: + self.tree[iter]['IsFormattable'] = device.format.formattable - if part.type & parted.PARTITION_FREESPACE: - ptype = _("Free space") - elif part.type == parted.PARTITION_EXTENDED: + if device.isExtended: ptype = _("Extended") - elif part.getFlag(parted.PARTITION_RAID) == 1: + elif format.type == "mdmember": ptype = _("software RAID") - parreq = self.partitions.getRaidMemberParent(request) - if parreq: + mds = self.storage.mdarrays + array = None + for _array in mds: + if _array.dependsOn(device): + array = _array + break + if array: if self.show_uneditable: - try: - mddevice = "/dev/md%d" % (parreq.raidminor,) - except: + if array.minor is not None: + mddevice = "%s" % array.path + else: + mddevice = "Auto" mddevice = "Auto" self.tree[iter]['Mount Point'] = mddevice else: @@ -906,48 +903,33 @@ class PartitionWindow(InstallWindow): else: self.tree[iter]['Mount Point'] = "" - if request and request.isEncrypted(self.partitions, True) and request.format: - self.tree[iter]['Format'] = self.lock_pixbuf - elif part.fileSystem: - if request and request.fstype != None: - ptype = self.getShortFSTypeName(request.fstype.getName()) - if ptype == "foreign": - ptype = map_foreign_to_fsname(part) - else: - ptype = part.fileSystem.type - - if request and request.isEncrypted(self.partitions, True) and request.format: + if device.format.type == "luks" and \ + not device.format.exists: self.tree[iter]['Format'] = self.lock_pixbuf - elif request and request.format: - self.tree[iter]['Format'] = self.checkmark_pixbuf else: - if request and request.fstype != None: - ptype = self.getShortFSTypeName(request.fstype.getName()) - - if ptype == "foreign": - ptype = map_foreign_to_fsname(part) + if format.type: + ptype = format.name else: ptype = _("None") if part.type & parted.PARTITION_FREESPACE: devname = _("Free") else: - devname = '/dev/%s' % (device,) + devname = "%s" % device.path self.tree[iter]['Device'] = devname - if request and request.type != REQUEST_NEW and request.fslabel: - self.tree[iter]['Label'] = "%s" % (request.fslabel,) + if format.exists and + getattr(format, "label", None): + self.tree[iter]['Label'] = "%s" % format.label else: self.tree[iter]['Label'] = "" self.tree[iter]['Type'] = ptype - self.tree[iter]['Start'] = str(disk.device.startSectorToCylinder(part.geometry.start)) - self.tree[iter]['End'] = str(disk.device.endSectorToCylinder(part.geometry.end)) size = part.getSize(unit="MB") if size < 1.0: sizestr = "< 1" else: sizestr = "%Ld" % (size) self.tree[iter]['Size (MB)'] = sizestr - self.tree[iter]['PyObject'] = part + self.tree[iter]['PyObject'] = device part = part.nextPartition() @@ -955,44 +937,52 @@ class PartitionWindow(InstallWindow): apply(canvas.set_scroll_region, canvas.root().get_bounds()) self.treeView.expand_all() - def treeActivateCb(self, view, path, col): + def treeActivateCB(self, view, path, col): if self.tree.getCurrentPartition(): - self.editCb() + self.editCB() - def treeSelectCb(self, selection, *args): + def treeSelectCB(self, selection, *args): model, iter = selection.get_selected() if not iter: return - partition = model[iter]['PyObject'] - if partition: + device = model[iter]['PyObject'] + if device: + # PyObject is always a Device but not always a PartitionDevice + try: + partition = device.partedPartition + except AttributeError: + return + self.diskStripeGraph.selectSlice(partition) def newCB(self, widget): - request = NewPartitionSpec(fileSystemTypeGetDefault(), size = 200) - - self.editPartitionRequest(request, isNew = 1) - - def deleteCb(self, widget): - curselection = self.tree.getCurrentPartition() - - if curselection: - if doDeletePartitionByRequest(self.intf, self.partitions, curselection): + device = self.storage.newPartition(fmt_type=self.storage.defaultFSType, + size=200) + self.editPartition(device, isNew=1) + + def deleteCB(self, widget): + """ Right now we can say that if the device is partitioned we + want to delete all of the devices it contains. At some point + we will want to support creation and removal of partitionable + devices. This will need some work when that time comes. + """ + device = self.tree.getCurrentDevice() + if getattr(device.partedDisk): + if doDeleteDependentDevices(self.intf, + self.storage, + device): + self.refresh() + elif doDeleteDevice(self.intf, + self.storage, + device): self.refresh() - else: - curdevice = self.tree.getCurrentDevice() - if curdevice and len(curdevice) > 5: - if doDeletePartitionsByDevice(self.intf, self.partitions, self.diskset, curdevice[5:]): - self.refresh() - else: - return - def resetCb(self, *args): + def resetCB(self, *args): if not confirmResetPartitionState(self.intf): return self.diskStripeGraph.shutDown() - self.diskset.refreshDevices() - self.partitions.setFromDisk(self.diskset) + self.storage.reset() self.tree.clear() self.populate() @@ -1000,25 +990,10 @@ class PartitionWindow(InstallWindow): self.diskStripeGraph.shutDown() self.tree.clear() - # XXXX - Backup some info which doPartitioning munges if it fails - origInfoDict = {} - for request in self.partitions.requests: - try: - origInfoDict[request.uniqueID] = (request.requestSize, request.currentDrive) - except: - pass - try: - autopart.doPartitioning(self.diskset, self.partitions) + autopart.doPartitioning(self.storage) rc = 0 except PartitioningError, msg: - try: - for request in self.partitions.requests: - if request.uniqueID in origInfoDict.keys(): - (request.requestSize, request.currentDrive) = origInfoDict[request.uniqueID] - except: - log.error("Failed to restore original info") - self.intf.messageWindow(_("Error Partitioning"), _("Could not allocate requested partitions: %s.") % (msg), custom_icon="error") @@ -1045,59 +1020,66 @@ class PartitionWindow(InstallWindow): rc = -1 else: rc = 0 - reqs = self.partitions.getBootableRequest() - if reqs: - for req in reqs: - req.ignoreBootConstraints = 1 + all_devices = self.storage.devicetree.devices.values() + bootDevs = [d for d in all_devices if d.bootable] + #if reqs: + # for req in reqs: + # req.ignoreBootConstraints = 1 if not rc == -1: self.populate() return rc - def editCb(self, *args): - part = self.tree.getCurrentPartition() - - (type, request) = doEditPartitionByRequest(self.intf, self.partitions, - part) - if request: - if type == "RAID": - self.editRaidRequest(request) - elif type == "LVMVG": - self.editLVMVolumeGroup(request) - elif type == "LVMLV": - vgrequest = self.partitions.getRequestByID(request.volumeGroup) - self.editLVMVolumeGroup(vgrequest) - elif type == "NEW": - self.editPartitionRequest(request, isNew = 1) - else: - self.editPartitionRequest(request) + def editCB(self, *args): + device = self.tree.getCurrentDevice() + if not device: + intf.messageWindow(_("Unable To Edit"), + _("You must select a device to edit"), + custom_icon="error") + return + + reason = self.storage.deviceImmutable(device) + if reason: + self.intf.messageWindow(_("Unable To Edit"), + _("You cannot edit this device:\n\n") + reason, + custom_icon="error") + return + + if device.type == "mdarray": + self.editRaidArray(device) + elif device.type == "lvmvg": + self.editLVMVolumeGroup(device) + elif device.type == "lvmlv": + self.editLVMVolumeGroup(device) + elif device.type = "partition": + self.editPartition(device) # isNew implies that this request has never been successfully used before - def editRaidRequest(self, raidrequest, isNew = 0): - raideditor = raid_dialog_gui.RaidEditor(self.partitions, - self.diskset, self.intf, - self.parent, raidrequest, - isNew) - origpartitions = self.partitions.copy() + def editRaidArray(self, raiddev, isNew = 0): + raideditor = raid_dialog_gui.RaidEditor(self.storage, + self.intf, + self.parent, + raiddev, + isNew) + # is a shallow copy enough? + #origpartitions = self.storage.devicetree.copy() while 1: - request = raideditor.run() + actions = raideditor.run() - if request is None: - return - - if not isNew: - self.partitions.removeRequest(raidrequest) - if raidrequest.getPreExisting(): - delete = partRequests.DeleteRAIDSpec(raidrequest.raidminor) - self.partitions.addDelete(delete) + if not actions: + break - self.partitions.addRequest(request) + for action in actions: + # FIXME: this needs to handle exceptions + self.storage.devicetree.registerAction(action) if self.refresh(): - if not isNew: - self.partitions = origpartitions.copy() + actions.reverse() + for action in actions: + self.storage.devicetree.cancelAction(action) if self.refresh(): raise RuntimeError, ("Returning partitions to state " "prior to RAID edit failed") @@ -1108,29 +1090,30 @@ class PartitionWindow(InstallWindow): raideditor.destroy() - def editPartitionRequest(self, origrequest, isNew = 0, restrictfs = None): + def editPartition(self, device, isNew = 0, restrictfs = None): parteditor = partition_dialog_gui.PartitionEditor(self.anaconda, self.parent, - origrequest, + device, isNew = isNew, restrictfs = restrictfs) while 1: - request = parteditor.run() + actions = parteditor.run() - if request is None: - return 0 + if not actions: + break - if not isNew: - self.partitions.removeRequest(origrequest) + for action in actions: + # XXX we should handle exceptions here + self.anaconda.id.storage.devicetree.registerAction(action) - self.partitions.addRequest(request) if self.refresh(): - # the add failed; remove what we just added and put - # back what was there if we removed it - self.partitions.removeRequest(request) - if not isNew: - self.partitions.addRequest(origrequest) + # autopart failed -- cancel the actions and try to get + # back to previous state + actions.reverse() + for action in actions: + self.anaconda.id.storage.devicetree.cancelAction(action) + if self.refresh(): # this worked before and doesn't now... raise RuntimeError, ("Returning partitions to state " @@ -1141,66 +1124,34 @@ class PartitionWindow(InstallWindow): parteditor.destroy() return 1 - def editLVMVolumeGroup(self, origvgrequest, isNew = 0): - vgeditor = lvm_dialog_gui.VolumeGroupEditor(self.anaconda, - self.partitions, - self.diskset, - self.intf, self.parent, - origvgrequest, isNew) + def editLVMVolumeGroup(self, device, isNew = 0): + # we don't really need to pass in self.storage if we're passing + # self.anaconda already + vgeditor = lvm_dialog_gui.VolumeGroupEditor(self.anaconda, + self.storage + self.intf, + self.parent, + device, + isNew) - origpartitions = self.partitions.copy() - origvolreqs = origpartitions.getLVMLVForVG(origvgrequest) - - while (1): - rc = vgeditor.run() - - # - # return code is either None or a tuple containing - # volume group request and logical volume requests - # - if rc is None: - return - - (vgrequest, logvolreqs) = rc - - # first add the volume group - if not isNew: - # if an lv was preexisting and isn't in the new lv requests, - # we need to add a delete for it. - for lv in origvolreqs: - if not lv.getPreExisting(): - continue - found = 0 - for newlv in logvolreqs: - if (newlv.getPreExisting() and - newlv.logicalVolumeName == lv.logicalVolumeName): - found = 1 - break - if found == 0: - delete = partRequests.DeleteLogicalVolumeSpec(lv.logicalVolumeName, - origvgrequest.volumeGroupName) - self.partitions.addDelete(delete) - - for lv in origvolreqs: - self.partitions.removeRequest(lv) + while True: + actions = vgeditor.run() - self.partitions.removeRequest(origvgrequest) + if not actions: + break - vgID = self.partitions.addRequest(vgrequest) - - # now add the logical volumes - for lv in logvolreqs: - lv.volumeGroup = vgID - if not lv.getPreExisting(): - lv.format = 1 - self.partitions.addRequest(lv) + for action in actions: + # FIXME: handle exceptions + self.storage.devicetree.registerAction(action) if self.refresh(): - if not isNew: - self.partitions = origpartitions.copy() - if self.refresh(): - raise RuntimeError, ("Returning partitions to state " - "prior to edit failed") + actions.reverse() + for action in actions: + self.storage.devicetree.cancelAction(action) + + if self.refresh(): + raise RuntimeError, ("Returning partitions to state " + "prior to edit failed") continue else: break @@ -1208,10 +1159,8 @@ class PartitionWindow(InstallWindow): vgeditor.destroy() - def makeLvmCB(self, widget): - if (not fileSystemTypeGet('physical volume (LVM)').isSupported() or - not lvm.has_lvm()): + if not getFormat("lvmpv").supported or not lvm.has_lvm(): self.intf.messageWindow(_("Not supported"), _("LVM is NOT supported on " "this platform."), type="ok", @@ -1219,20 +1168,20 @@ class PartitionWindow(InstallWindow): return request = VolumeGroupRequestSpec(format=True) - self.editLVMVolumeGroup(request, isNew = 1) + vg = self.storage.newVG() + self.editLVMVolumeGroup(vg, isNew = 1) return def makeraidCB(self, widget): - - if not fileSystemTypeGet('software RAID').isSupported(): + if not getFormat("software RAID").supported: self.intf.messageWindow(_("Not supported"), _("Software RAID is NOT supported on " "this platform."), type="ok", custom_icon="error") return - availminors = self.partitions.getAvailableRaidMinors() + availminors = self.storage.unusedMDMinors if len(availminors) < 1: self.intf.messageWindow(_("No RAID minor device numbers available"), _("A software RAID device cannot " @@ -1245,9 +1194,7 @@ class PartitionWindow(InstallWindow): # see if we have enough free software RAID partitions first # if no raid partitions exist, raise an error message and return - request = RaidRequestSpec(fileSystemTypeGetDefault()) - availraidparts = self.partitions.getAvailRaidPartitions(request, - self.diskset) + availraidparts = self.partitions.unusedMDMembers() dialog = gtk.Dialog(_("RAID Options"), self.parent) gui.addFrame(dialog) @@ -1300,7 +1247,7 @@ class PartitionWindow(InstallWindow): createRAIDpart.set_active(1) doRAIDclone.set_sensitive(0) createRAIDdev.set_sensitive(0) - if len(availraidparts) > 0 and len(self.diskset.disks.keys()) > 1: + if len(availraidparts) > 0 and len(self.storage.disks) > 1: doRAIDclone.set_sensitive(1) if len(availraidparts) > 1: @@ -1322,13 +1269,16 @@ class PartitionWindow(InstallWindow): # see which option they choose if createRAIDpart.get_active(): - rdrequest = NewPartitionSpec(fileSystemTypeGet("software RAID"), size = 200) - rc = self.editPartitionRequest(rdrequest, isNew = 1, restrictfs=["software RAID"]) + member = self.storage.newPartition(fmt_type="software RAID", + size=200) + rc = self.editPartitionRequest(member, + isNew = 1, + restrictfs=["software RAID"]) elif createRAIDdev.get_active(): - self.editRaidRequest(request, isNew=1) + array = self.storage.newMDArray(fmt_type=self.storage.defaultFSType) + self.editRaidArray(array, isNew=1) else: - cloneDialog = raid_dialog_gui.RaidCloneDialog(self.partitions, - self.diskset, + cloneDialog = raid_dialog_gui.RaidCloneDialog(self.storage self.intf, self.parent) if cloneDialog is None: @@ -1338,16 +1288,12 @@ class PartitionWindow(InstallWindow): custom_icon="error") return - while 1: - rc = cloneDialog.run() + if cloneDialog.run(): + self.refresh() - if rc: - self.refresh() - - cloneDialog.destroy() - return + cloneDialog.destroy() + return - def viewButtonCB(self, widget): self.show_uneditable = not widget.get_active() self.diskStripeGraph.shutDown() @@ -1356,13 +1302,9 @@ class PartitionWindow(InstallWindow): def getScreen(self, anaconda): self.anaconda = anaconda - self.fsset = anaconda.id.fsset - self.diskset = anaconda.id.diskset + self.storage = anaconda.id.storage self.intf = anaconda.intf - self.diskset.openDevices() - self.partitions = anaconda.id.partitions - self.show_uneditable = 1 checkForSwapNoMatch(anaconda) @@ -1376,9 +1318,9 @@ class PartitionWindow(InstallWindow): buttonBox.set_layout(gtk.BUTTONBOX_SPREAD) ops = ((_("Ne_w"), self.newCB), - (_("_Edit"), self.editCb), - (_("_Delete"), self.deleteCb), - (_("Re_set"), self.resetCb), + (_("_Edit"), self.editCB), + (_("_Delete"), self.deleteCB), + (_("Re_set"), self.resetCB), (_("R_AID"), self.makeraidCB), (_("_LVM"), self.makeLvmCB)) @@ -1389,12 +1331,12 @@ class PartitionWindow(InstallWindow): self.tree = DiskTreeModel() self.treeView = self.tree.getTreeView() - self.treeView.connect('row-activated', self.treeActivateCb) + self.treeView.connect('row-activated', self.treeActivateCB) self.treeViewSelection = self.treeView.get_selection() - self.treeViewSelection.connect("changed", self.treeSelectCb) + self.treeViewSelection.connect("changed", self.treeSelectCB) # set up the canvas - self.diskStripeGraph = DiskStripeGraph(self.tree, self.editCb) + self.diskStripeGraph = DiskStripeGraph(self.tree, self.editCB) # do the initial population of the tree and the graph self.populate(initial = 1) diff --git a/iw/partition_ui_helpers_gui.py b/iw/partition_ui_helpers_gui.py index 5697d2b1a..97d45d267 100644 --- a/iw/partition_ui_helpers_gui.py +++ b/iw/partition_ui_helpers_gui.py @@ -28,10 +28,9 @@ import datacombo import iutil from constants import * -from fsset import * from partIntfHelpers import * -from partRequests import * from partedUtils import * +from storage.formats import device_formats, getFormat import gettext _ = lambda x: gettext.ldgettext("anaconda", x) @@ -72,13 +71,23 @@ def createAlignedLabel(text): return label +defaultMountPoints = ['/', '/boot', '/home', '/tmp', '/usr', + '/var', '/usr/local', '/opt'] + +if iutil.isS390(): + # Many s390 have 2G DASDs, we recomment putting /usr/share on its own DASD + defaultMountPoints.insert(5, '/usr/share') + +if iutil.isEfi(): + defaultMountPoints.insert(2, '/boot/efi') + def createMountPointCombo(request, excludeMountPoints=[]): mountCombo = gtk.combo_box_entry_new_text() mntptlist = [] - - if request.type != REQUEST_NEW and request.fslabel: - mntptlist.append(request.fslabel) + label = getattr(request.format, "label", None) + if request.exists and label.startswith("/"): + mntptlist.append(label) idx = 0 for p in defaultMountPoints: @@ -90,9 +99,8 @@ def createMountPointCombo(request, excludeMountPoints=[]): map(mountCombo.append_text, mntptlist) - mountpoint = request.mountpoint - - if request.fstype and request.fstype.isMountable(): + if request.format.type and request.format.mountable: + mountpoint = request.format.mountpoint mountCombo.set_sensitive(1) if mountpoint: mountCombo.get_children()[0].set_text(mountpoint) @@ -107,13 +115,14 @@ def createMountPointCombo(request, excludeMountPoints=[]): return mountCombo def setMntPtComboStateFromType(fstype, mountCombo): + format = getFormat(fstype) prevmountable = mountCombo.get_data("prevmountable") mountpoint = mountCombo.get_data("saved_mntpt") - if prevmountable and fstype.isMountable(): + if prevmountable and format.mountable: return - if fstype.isMountable(): + if format.mountable: mountCombo.set_sensitive(1) if mountpoint != None: mountCombo.get_children()[0].set_text(mountpoint) @@ -125,7 +134,7 @@ def setMntPtComboStateFromType(fstype, mountCombo): mountCombo.get_children()[0].set_text(_("<Not Applicable>")) mountCombo.set_sensitive(0) - mountCombo.set_data("prevmountable", fstype.isMountable()) + mountCombo.set_data("prevmountable", format.mountable) def fstypechangeCB(widget, mountCombo): fstype = widget.get_active_value() @@ -134,24 +143,25 @@ def fstypechangeCB(widget, mountCombo): def createAllowedDrivesStore(disks, reqdrives, drivelist, selectDrives=True, disallowDrives=[]): drivelist.clear() - drives = disks.keys() - drives.sort() - for drive in drives: - size = disks[drive].device.getSize(unit="MB") + for disk in disks: selected = 0 if selectDrives: if reqdrives: - if drive in reqdrives: + if disk.name in reqdrives: selected = 1 else: - if drive not in disallowDrives: + if disk.name not in disallowDrives: selected = 1 - sizestr = "%8.0f MB" % size - drivelist.append_row((drive, sizestr, disks[drive].device.model), selected) + sizestr = "%8.0f MB" % disk.size + # TODO: abstract disk model so we don't have to reach into parted.Disk + drivelist.append_row((disk.name, + sizestr, + disk.partedDisk.device.model), + selected) - if len(disks.keys()) < 2: + if len(disks) < 2: drivelist.set_sensitive(False) else: drivelist.set_sensitive(True) @@ -175,31 +185,33 @@ def createFSTypeMenu(fstype, fstypechangeCB, mountCombo, store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) fstypecombo = datacombo.DataComboBox(store) - types = fileSystemTypeGetTypes() + types = device_formats.keys() if availablefstypes: names = availablefstypes else: names = types.keys() - if fstype and fstype.isSupported() and fstype.isFormattable(): + fs = getFormat(fstype) + if fs and fs.supported and fs.formattable: default = fstype else: - default = fileSystemTypeGetDefault() + default = get_default_filesystem_type() names.sort() defindex = 0 i = 0 for name in names: - if not fileSystemTypeGet(name).isSupported(): + format = getFormat(name) + if not format.supported: continue if ignorefs and name in ignorefs: continue - if fileSystemTypeGet(name).isFormattable(): - fstypecombo.append(name, types[name]) - if default and default.getName() == name: + if format.formattable: + fstypecombo.append(name, device_formats[name]) + if default and default.type == name: defindex = i - defismountable = types[name].isMountable() + defismountable = format.mountable i = i + 1 fstypecombo.set_active(defindex) @@ -209,7 +221,7 @@ def createFSTypeMenu(fstype, fstypechangeCB, mountCombo, if mountCombo: mountCombo.set_data("prevmountable", - fstypecombo.get_active_value().isMountable()) + fstypecombo.get_active_value()().mountable) mountCombo.connect("changed", mountptchangeCB, fstypecombo) return fstypecombo @@ -218,7 +230,7 @@ def mountptchangeCB(widget, fstypecombo): if iutil.isEfi() and widget.get_children()[0].get_text() == "/boot/efi": fstypecombo.set_active_text("efi") if widget.get_children()[0].get_text() == "/boot": - fstypecombo.set_active_text(fileSystemTypeGetDefaultBoot().getName()) + fstypecombo.set_active_text(get_default_filesystem_type(boot=True)) def resizeOptionCB(widget, resizesb): resizesb.set_sensitive(widget.get_active()) @@ -282,11 +294,11 @@ def noformatCB(widget, data): def createPreExistFSOptionSection(origrequest, maintable, row, mountCombo, partitions, ignorefs=[]): rc = {} - ofstype = origrequest.fstype + ofstype = origrequest.format.type formatcb = gtk.CheckButton(label=_("_Format as:")) maintable.attach(formatcb, 0, 1, row, row + 1) - formatcb.set_active(istruefalse(origrequest.format)) + formatcb.set_active(istruefalse(origrequest.format.exists)) rc["formatcb"] = formatcb fstypeCombo = createFSTypeMenu(ofstype, fstypechangeCB, @@ -296,8 +308,9 @@ def createPreExistFSOptionSection(origrequest, maintable, row, mountCombo, row += 1 rc["fstypeCombo"] = fstypeCombo - if not formatcb.get_active() and not origrequest.migrate: - mountCombo.set_data("prevmountable", ofstype.isMountable()) + # TODO: sort out fs migration + if not formatcb.get_active() and not origrequest.format.migrate: + mountCombo.set_data("prevmountable", getFormat(ofstype).mountable) # this gets added to the table a bit later on lukscb = gtk.CheckButton(_("_Encrypt")) @@ -306,11 +319,12 @@ def createPreExistFSOptionSection(origrequest, maintable, row, mountCombo, (fstypeCombo, mountCombo, ofstype, lukscb)) - if origrequest.origfstype.isMigratable(): + if origrequest.format.migratable: migratecb = gtk.CheckButton(label=_("Mi_grate filesystem to:")) - migratecb.set_active(istruefalse(origrequest.migrate)) + migratecb.set_active(istruefalse(origrequest.format.migrate)) - migtypes = origrequest.origfstype.getMigratableFSTargets() + # TODO: unimplemented + migtypes = origrequest.format.migrationTargets maintable.attach(migratecb, 0, 1, row, row + 1) migfstypeCombo = createFSTypeMenu(ofstype, None, None, @@ -326,7 +340,7 @@ def createPreExistFSOptionSection(origrequest, maintable, row, mountCombo, migratecb = None migfstypeCombo = None - if origrequest.isResizable(partitions): + if origrequest.resizable: resizecb = gtk.CheckButton(label=_("_Resize")) resizecb.set_active(origrequest.targetSize is not None) rc["resizecb"] = resizecb @@ -337,7 +351,8 @@ def createPreExistFSOptionSection(origrequest, maintable, row, mountCombo, else: value = origrequest.size - reqlower = origrequest.getMinimumResizeMB(partitions) + # TODO: sort out resizing + reqlower = origrequest.getMinimumResizeMB(storage) requpper = origrequest.getMaximumResizeMB(partitions) if not origrequest.format: lower = reqlower @@ -357,7 +372,7 @@ def createPreExistFSOptionSection(origrequest, maintable, row, mountCombo, formatcb.connect("toggled", formatOptionResizeCB, resizesb) - if origrequest.encryption: + if origrequest.format.type == "luks": lukscb.set_active(1) lukscb.set_data("encrypted", 1) else: diff --git a/iw/raid_dialog_gui.py b/iw/raid_dialog_gui.py index 21cb2bcb8..8b6ed5e55 100644 --- a/iw/raid_dialog_gui.py +++ b/iw/raid_dialog_gui.py @@ -28,10 +28,7 @@ import gtk import datacombo import gui -from fsset import * from raid import availRaidLevels -from cryptodev import LUKSDevice -from partRequests import * from partition_ui_helpers_gui import * from constants import * @@ -56,18 +53,17 @@ class RaidEditor: tempDevList = [] if not self.isNew: # We need this list if we are editing. - for id in reqraidpart: - tempDevList.append(self.partitions.getRequestByID(id).device) + for dev in reqraidpart: + tempDevList.append(dev) partrow = 0 - for part, size, used in allraidparts: - partname = "%s" % part - partsize = "%8.0f MB" % size + for part in allraidparts: + partname = "%s" % part.name + partsize = "%8.0f MB" % part.size if self.isNew: partlist.append_row((partname, partsize), False) else: - # Ask self.partitions what devices to list as selected. if part in tempDevList: #list the partition and put it as selected partlist.append_row((partname, partsize), True) @@ -117,7 +113,7 @@ class RaidEditor: numparts = sparesb.get_data("numparts") maxspares = raid.get_raid_max_spares(raidlevel, numparts) - if maxspares > 0 and raidlevel != "RAID0": + if maxspares > 0 and raidlevel != "raid0": adj = sparesb.get_adjustment() value = adj.value if adj.value > maxspares: @@ -145,20 +141,8 @@ class RaidEditor: self.destroy() return None - # read out UI into a partition specification - request = copy.copy(self.origrequest) - request.encryption = copy.deepcopy(self.origrequest.encryption) - - # doesn't make sense for RAID device - if not self.origrequest.getPreExisting(): - filesystem = self.fstypeCombo.get_active_value() - request.fstype = filesystem - - if request.fstype.isMountable(): - request.mountpoint = self.mountCombo.get_children()[0].get_text() - else: - request.mountpoint = None - + actions = [] + luksdev = None raidmembers = [] model = self.raidlist.get_model() iter = model.get_iter_first() @@ -167,82 +151,75 @@ class RaidEditor: part = model.get_value(iter, 1) if val: - req = self.partitions.getRequestByDeviceName(part) - raidmembers.append(req.uniqueID) + dev = self.storage.devicetree.getDeviceByName(part) + raidmembers.append(dev) iter = model.iter_next(iter) - if not self.origrequest.getPreExisting(): - request.raidminor = int(self.minorCombo.get_active_value()) + if not self.origrequest.exists: + # new device + fmt_class = self.fstypeCombo.get_active_value() + mountpoint = self.mountCombo.get_children()[0].get_text() + raidminor = int(self.minorCombo.get_active_value()) - request.raidmembers = raidmembers model = self.levelcombo.get_model() - request.raidlevel = model[self.levelcombo.get_active()][0] + raidlevel = model[self.levelcombo.get_active()][0] - if request.raidlevel != "RAID0": + if raidlevel != "RAID0": self.sparesb.update() - request.raidspares = self.sparesb.get_value_as_int() + spares = self.sparesb.get_value_as_int() else: - request.raidspares = 0 - - if self.formatButton: - request.format = self.formatButton.get_active() - else: - request.format = 0 - - if self.lukscb and self.lukscb.get_active(): - if not request.encryption: - request.encryption = LUKSDevice(passphrase=self.partitions.encryptionPassphrase, format=1) - else: - request.encryption = None + spares = 0 + + format = fmt_class(mountpoint=mountpoint) + if self.fsoptionsDict.has_key("lukscb") and \ + self.fsoptionsDict["lukscb"].get_active() and \ + self.origrequest.format.type != "luks": + luksdev = LUKSDevice("luks-%s" % request.name, + format=format + parents=self.origrequest) + format = getFormat("luks", + passphrase=self.storage.encryptionPassphrase) else: - if self.fsoptionsDict.has_key("formatcb"): - request.format = self.fsoptionsDict["formatcb"].get_active() - if request.format: - request.fsystem = self.fsoptionsDict["fstypeCombo"].get_active_value() - else: - request.format = 0 - - if self.fsoptionsDict.has_key("migratecb"): - request.migrate = self.fsoptionsDict["migratecb"].get_active() - if request.migrate: - request.fsystem = self.fsoptionsDict["migfstypeCombo"].get_active_value() - else: - request.migrate = 0 - - # set back if we are not formatting or migrating - origfstype = self.origrequest.origfstype - if not request.format and not request.migrate: - request.fstype = origfstype - - if request.fstype.isMountable(): - request.mountpoint = self.mountCombo.get_children()[0].get_text() - else: - request.mountpoint = None - - lukscb = self.fsoptionsDict.get("lukscb") - if lukscb and lukscb.get_active(): - if not request.encryption: - request.encryption = LUKSDevice(passphrase=self.partitions.encryptionPassphrase, format=1) - else: - request.encryption = None - - err = request.sanityCheckRequest(self.partitions) + # existing device + fmt_class = self.fsoptionsDict["fstypeCombo"].get_active_value() + mountpoint = self.mountCombo.get_children()[0].get_text() + if self.fsoptionsDict.has_key("formatcb") and \ + self.fsoptionsDict["formatcb"].get_active(): + format = fmt_class(mountpoint=mountpoint) + if self.fsoptionsDict.has_key("lukscb") and \ + self.fsoptionsDict["lukscb"].get_active() and \ + request.format.type != "luks": + luksdev = LUKSDevice("luks-%s" % request.name, + format=format, + parents=request) + format = getFormat("luks", + device=self.origrequest.path, + passphrase=self.storage.encryptionPassphrase) + + if self.fsoptionsDict.has_key("migratecb") and \ + self.fsoptionsDict["migratecb"].get_active(): + fstype = self.fsoptionsDict["migfstypeCombo"].get_active_value() + + err = self.storage.sanityCheckRequest(request) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err), custom_icon="error") continue - if (not request.format and - request.mountpoint and request.formatByDefault()): + if request.format.exists and \ + self.storage.formatByDefault(request): if not queryNoFormatPreExisting(self.intf): continue # everything ok, break out break + actions.append(ActionCreateDevice(self.origrequest)) + if luksdev: + actions.append(ActionCreateDevice(luksdev)) - return request + return actions def destroy(self): if self.dialog: @@ -250,9 +227,8 @@ class RaidEditor: self.dialog = None - def __init__(self, partitions, diskset, intf, parent, origrequest, isNew = 0): - self.partitions = partitions - self.diskset = diskset + def __init__(self, storage, intf, parent, origrequest, isNew = 0): + self.storage = storage self.origrequest = origrequest self.isNew = isNew self.intf = intf @@ -263,8 +239,8 @@ class RaidEditor: # # start of editRaidRequest # - availraidparts = self.partitions.getAvailRaidPartitions(origrequest, - self.diskset) + availraidparts = self.storage.unusedMDMembers(array=self.origrequest) + # if no raid partitions exist, raise an error message and return if len(availraidparts) < 2: dlg = gtk.MessageDialog(self.parent, 0, gtk.MESSAGE_ERROR, @@ -285,8 +261,8 @@ class RaidEditor: if isNew: tstr = _("Make RAID Device") else: - try: - tstr = _("Edit RAID Device: /dev/md%s") % (origrequest.raidminor,) + if origrequest.minor is not None: + tstr = _("Edit RAID Device: %s") % (origrequest.path,) except: tstr = _("Edit RAID Device") @@ -313,11 +289,18 @@ class RaidEditor: self.lukscb = gtk.CheckButton(_("_Encrypt")) self.lukscb.set_data("formatstate", 1) + if origrequest.format.type == "luks": + usedev = self.storage.devicetree.getChildren(origrequest)[0] + format = usedev.format + else: + usedev = origrequest + format = origrequest.format + # Filesystem Type - if not origrequest.getPreExisting(): + if not origrequest.exists: lbl = createAlignedLabel(_("_File System Type:")) maintable.attach(lbl, 0, 1, row, row + 1) - self.fstypeCombo = createFSTypeMenu(origrequest.fstype, + self.fstypeCombo = createFSTypeMenu(format.name, fstypechangeCB, self.mountCombo, ignorefs = ["software RAID", "efi", "PPC PReP Boot", "Apple Bootstrap"]) @@ -327,29 +310,29 @@ class RaidEditor: else: maintable.attach(createAlignedLabel(_("Original File System Type:")), 0, 1, row, row + 1) - if origrequest.fstype.getName(): - self.fstypeCombo = gtk.Label(origrequest.fstype.getName()) + if format.type: + self.fstypeCombo = gtk.Label(format.name) else: self.fstypeCombo = gtk.Label(_("Unknown")) maintable.attach(self.fstypeCombo, 1, 2, row, row + 1) row += 1 - if origrequest.fslabel: + if getattr(format, "label", None): maintable.attach(createAlignedLabel(_("Original File System " "Label:")), 0, 1, row, row + 1) - maintable.attach(gtk.Label(origrequest.fslabel), 1, 2, row, - row + 1) + maintable.attach(gtk.Label(format.label), + 1, 2, row, row + 1) row += 1 # raid minors lbl = createAlignedLabel(_("RAID _Device:")) maintable.attach(lbl, 0, 1, row, row + 1) - if not origrequest.getPreExisting(): - availminors = self.partitions.getAvailableRaidMinors()[:16] - reqminor = origrequest.raidminor + if not origrequest.exists: + availminors = self.storage.unusedMDMinors()[:16] + reqminor = origrequest.minor if reqminor is not None: availminors.append(reqminor) @@ -357,7 +340,7 @@ class RaidEditor: self.minorCombo = self.createRaidMinorMenu(availminors, reqminor) lbl.set_mnemonic_widget(self.minorCombo) else: - self.minorCombo = gtk.Label("md%s" %(origrequest.raidminor,)) + self.minorCombo = gtk.Label("%s" %(origrequest.name,)) maintable.attach(self.minorCombo, 1, 2, row, row + 1) row = row + 1 @@ -365,16 +348,17 @@ class RaidEditor: lbl = createAlignedLabel(_("RAID _Level:")) maintable.attach(lbl, 0, 1, row, row + 1) - if not origrequest.getPreExisting(): + if not origrequest.exists: # Create here, pack below numparts = len(availraidparts) - if origrequest.raidspares: - nspares = origrequest.raidspares + if origrequest.spares: + nspares = origrequest.spares else: nspares = 0 - if origrequest.raidlevel: - maxspares = raid.get_raid_max_spares(origrequest.raidlevel, numparts) + if origrequest.level: + maxspares = raid.get_raid_max_spares(origrequest.level, + numparts) else: maxspares = 0 @@ -389,15 +373,15 @@ class RaidEditor: self.sparesb.set_value(0) self.sparesb.set_sensitive(0) else: - self.sparesb = gtk.Label(str(origrequest.raidspares)) + self.sparesb = gtk.Label(str(origrequest.spares)) - if not origrequest.getPreExisting(): + if not origrequest.exists: self.levelcombo = self.createRaidLevelMenu(availRaidLevels, - origrequest.raidlevel) + origrequest.level) lbl.set_mnemonic_widget(self.levelcombo) else: - self.levelcombo = gtk.Label(origrequest.raidlevel) + self.levelcombo = gtk.Label(origrequest.level) maintable.attach(self.levelcombo, 1, 2, row, row + 1) row = row + 1 @@ -408,15 +392,15 @@ class RaidEditor: # XXX need to pass in currently used partitions for this device (self.raidlist, sw) = self.createAllowedRaidPartitionsList(availraidparts, - origrequest.raidmembers, - origrequest.getPreExisting()) + origrequest.devices, + origrequest.exists) lbl.set_mnemonic_widget(self.raidlist) self.raidlist.set_size_request(275, 80) maintable.attach(sw, 1, 2, row, row + 1) row = row + 1 - if origrequest.getPreExisting(): + if origrequest.exists: self.raidlist.set_sensitive(False) # number of spares - created widget above @@ -429,26 +413,26 @@ class RaidEditor: # format or not? self.formatButton = None self.fsoptionsDict = {} - if (origrequest.fstype and origrequest.fstype.isFormattable()) and not origrequest.getPreExisting(): + if not format.exists: self.formatButton = gtk.CheckButton(_("_Format partition?")) - if origrequest.format == None or origrequest.format != 0: + if not format.type: self.formatButton.set_active(1) else: self.formatButton.set_active(0) # it only makes sense to show this for preexisting RAID - if origrequest.getPreExisting(): + if origrequest.exists: maintable.attach(self.formatButton, 0, 2, row, row + 1) row = row + 1 # checkbutton for encryption using dm-crypt/LUKS - if self.origrequest.encryption: + if origrequest.format.type == "luks": self.lukscb.set_active(1) else: self.lukscb.set_active(0) maintable.attach(self.lukscb, 0, 2, row, row + 1) row = row + 1 else: - (row, self.fsoptionsDict) = createPreExistFSOptionSection(self.origrequest, maintable, row, self.mountCombo, self.partitions) + (row, self.fsoptionsDict) = createPreExistFSOptionSection(usedev, maintable, row, self.mountCombo, self.storage) # put main table into dialog dialog.vbox.pack_start(maintable) @@ -460,7 +444,7 @@ class RaidEditor: class RaidCloneDialog: - def createDriveList(self, diskset): + def createDriveList(self, disks): store = gtk.ListStore(gobject.TYPE_STRING) view = gtk.TreeView(store) @@ -470,12 +454,9 @@ class RaidCloneDialog: sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) sw.set_shadow_type(gtk.SHADOW_IN) - drives = diskset.disks.keys() - drives.sort() - - for drive in drives: + for disk in disks: iter = store.append() - store.set_value(iter, 0, drive) + store.set_value(iter, 0, disk.name) view.set_property("headers-visible", False) @@ -485,27 +466,18 @@ class RaidCloneDialog: return (sw, view) def getInterestingRequestsForDrive(self, drive): - allrequests = self.partitions.getRequestsByDevice(self.diskset, drive) + disk = self.storage.devicetree.getDeviceByName(drive) + allrequests = self.storage.getDependentDevices(disk) - if allrequests is None or len(allrequests) == 0: + if not allrequests: return allrequests # remove extended partitions requests = [] for req in allrequests: - try: - part = parted.getPartitionByName(req.device) - except: - part = None - - if part: - if part.type & parted.PARTITION_EXTENDED: - continue - elif part.type & parted.PARTITION_FREESPACE: - continue - elif part.type & parted.PARTITION_METADATA: - continue - else: + if req.type == "partition" and req.isExtended: + continue + elif req.type != "partition": continue requests.append(req) @@ -525,7 +497,7 @@ class RaidCloneDialog: return 1 for req in requests: - if not req.fstype or req.fstype.getName() != "software RAID": + if req.format.type != "mdmember": self.intf.messageWindow(_("Source Drive Error"), _("The source drive you selected has " "partitions which are not of " @@ -536,21 +508,23 @@ class RaidCloneDialog: custom_icon="error") return 1 + sourceDev = self.storage.devicetree.getDeviceByName(self.sourceDrive) for req in requests: - if not req.drive or req.drive[0] != self.sourceDrive or len(req.drive) > 1: + if not req.req_disks or len(req.req_disks) > 1 or \ + req.req_disks[0] != self.sourceDrive: self.intf.messageWindow(_("Source Drive Error"), _("The source drive you selected has " "partitions which are not " - "constrained to the drive /dev/%s.\n\n" + "constrained to the drive %s.\n\n" "You must remove these partitions " "or restrict them to this " "drive " "before this drive can be cloned. ") - %(self.sourceDrive,), custom_icon="error") + %(sourceDev.path,), custom_icon="error") return 1 for req in requests: - if self.partitions.isRaidMember(req): + if req not in self.storage.unusedMDMembers(): self.intf.messageWindow(_("Source Drive Error"), _("The source drive you selected has " "software RAID partition(s) which " @@ -564,6 +538,7 @@ class RaidCloneDialog: return 0 def sanityCheckTargetDrives(self): + sourceDev = self.storage.devicetree.getDeviceByName(self.sourceDrive) if self.targetDrives is None or len(self.targetDrives) < 1: self.intf.messageWindow(_("Target Drive Error"), _("Please select the target drives " @@ -572,8 +547,10 @@ class RaidCloneDialog: if self.sourceDrive in self.targetDrives: self.intf.messageWindow(_("Target Drive Error"), - _("The source drive /dev/%s cannot be " - "selected as a target drive as well.") % (self.sourceDrive,), custom_icon="error") + _("The source drive %s cannot be " + "selected as a target drive as well.") + % (self.sourceDev.path,), + custom_icon="error") return 1 for drive in self.targetDrives: @@ -581,24 +558,20 @@ class RaidCloneDialog: if requests is None: continue + targetDev = self.storage.devicetree.getDeviceByName(drive) for req in requests: - rc = partIntfHelpers.isNotChangable(req, self.partitions) - - # If the partition is protected, we also can't delete it so - # specify a reason why. - if rc is None and req.getProtected(): - rc = _("This partition is holding the data for the hard " - "drive install.") + rc = self.storage.deviceImmutable(req) if rc: self.intf.messageWindow(_("Target Drive Error"), - _("The target drive /dev/%s " + _("The target drive %s " "has a partition which cannot " "be removed for the following " "reason:\n\n\"%s\"\n\n" "You must remove this partition " "before " "this drive can be a target.") % - (drive, rc), custom_icon="error") + (targetDev.path, rc), + custom_icon="error") return 1 return 0 @@ -609,27 +582,28 @@ class RaidCloneDialog: requests = self.getInterestingRequestsForDrive(self.sourceDrive) # no requests to clone, bail out - if requests is None or len(requests) == 0: + if not requests: return 0 # now try to clear the target drives - for device in self.targetDrives: - rc = doDeletePartitionsByDevice(self.intf, self.partitions, - self.diskset, device, - confirm=0, quiet=1) + for devname in self.targetDrives: + device = self.storage.devicetree.getDeviceByName(devname) + doDeleteDependentDevices(self.intf, self.storage, + device, confirm=0, quiet=1) # now clone! for req in requests: for drive in self.targetDrives: - newreq = copy.copy(req) - newreq.drive = [drive] - newreq.uniqueID = None - newreq.device = None - newreq.preexist = 0 - newreq.dev = None - self.partitions.addRequest(newreq) + # this feels really dirty + device = self.storage.devicetree.getDeviceByName(drive) + newdev = copy.deepcopy(req) + newdev.req_disks = [device] + newdev.exists = False + newdev.format.exists = False + newdev.format.device = None + self.storage.createDevice(newdev) - return 0 + return def targetSelectFunc(self, model, path, iter): @@ -672,10 +646,10 @@ class RaidCloneDialog: continue # now give them last chance to bail - msgtxt = _("The drive /dev/%s will now be cloned to the " + msgtxt = _("The drive %s will now be cloned to the " "following drives:\n\n" % (self.sourceDrive,)) for drive in self.targetDrives: - msgtxt = msgtxt + "\t" + "/dev/%s" % (drive,) + msgtxt = msgtxt + "\t" + "%s" % (drive,) msgtxt = msgtxt + _("\n\nWARNING! ALL DATA ON THE TARGET DRIVES " "WILL BE DESTROYED.") @@ -708,9 +682,8 @@ class RaidCloneDialog: self.dialog = None - def __init__(self, partitions, diskset, intf, parent): - self.partitions = partitions - self.diskset = diskset + def __init__(self, storage, intf, parent): + self.storage = storage self.intf = intf self.parent = parent @@ -748,7 +721,7 @@ class RaidCloneDialog: lbl = gtk.Label(_("Source Drive:")) lbl.set_alignment(0.0, 0.0) box.pack_start(lbl, padding=5) - (sw, self.sourceView) = self.createDriveList(diskset) + (sw, self.sourceView) = self.createDriveList(storage.disks) selection = self.sourceView.get_selection() selection.set_mode(gtk.SELECTION_SINGLE) box.pack_start(sw) @@ -756,7 +729,7 @@ class RaidCloneDialog: lbl = gtk.Label(_("Target Drive(s):")) lbl.set_alignment(0.0, 0.0) box.pack_start(lbl, padding=5) - (sw, self.targetView) = self.createDriveList(diskset) + (sw, self.targetView) = self.createDriveList(storage.disks) selection = self.targetView.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) box.pack_start(sw) diff --git a/partIntfHelpers.py b/partIntfHelpers.py index 13c87220d..9393cd267 100644 --- a/partIntfHelpers.py +++ b/partIntfHelpers.py @@ -26,11 +26,8 @@ import string from constants import * -import partedUtils import parted -import fsset import iutil -import partRequests import gettext _ = lambda x: gettext.ldgettext("anaconda", x) @@ -106,331 +103,98 @@ def sanityCheckMountPoint(mntpt, fstype, preexisting, format): else: return None else: - if (fstype and fstype.isMountable() and (not preexisting or format)): + if (fstype and fstype.mountable and (not preexisting or format)): return _("Please specify a mount point for this partition.") else: # its an existing partition so don't force a mount point return None -def isNotChangable(request, requestlist): - if request: - if requestlist.isRaidMember(request): - parentreq = requestlist.getRaidMemberParent(request) - if parentreq.raidminor is not None: - return _("This partition is part of " - "the RAID device /dev/md%s.") % (parentreq.raidminor,) - else: - return _("This partition is part of a RAID device.") - - if requestlist.isLVMVolumeGroupMember(request): - parentreq = requestlist.getLVMVolumeGroupMemberParent(request) - if parentreq.volumeGroupName is not None: - return _("This partition is part of the " - "LVM volume group '%s'.") % (parentreq.volumeGroupName,) - else: - return _("This partition is part of a LVM volume group.") - - return None - - -def doDeletePartitionByRequest(intf, requestlist, partition, - confirm=1, quiet=0): +def doDeleteDevice(intf, storage, device, confirm=1, quiet=0): """Delete a partition from the request list. intf is the interface - requestlist is the list of requests - partition is either the part object or the uniqueID if not a part + storage is the storage instance + device is the device to delete """ - - if partition == None: + if not device: intf.messageWindow(_("Unable To Delete"), _("You must first select a partition to delete."), custom_icon="error") - return 0 + return False - if type(partition) == type("RAID"): - device = partition - elif partition.type & parted.PARTITION_FREESPACE: - intf.messageWindow(_("Unable To Delete"), - _("You cannot delete free space."), - custom_icon="error") - return 0 - elif partition.type & parted.PARTITION_PROTECTED: - # LDL formatted DASDs always have one partition, you'd have to reformat the - # DASD in CDL mode to get rid of it + reason = storage.deviceImmutable(device) + if reason: intf.messageWindow(_("Unable To Delete"), - _("You cannot delete a partition of a LDL formatted DASD."), - custom_icon="error") - return 0 - else: - device = partition.getDeviceNodeName() - - ret = requestlist.containsImmutablePart(partition) - if ret: - if not quiet: - intf.messageWindow(_("Unable To Delete"), - _("You cannot delete this " - "partition, as it is an extended partition " - "which contains %s") %(ret), - custom_icon="error") - return 0 - - # see if device is in our partition requests, remove - if type(partition) == type("RAID"): - request = requestlist.getRequestByID(device) - else: - request = requestlist.getRequestByDeviceName(device) - - if request: - state = isNotChangable(request, requestlist) - - # If the partition is protected, we also can't delete it so specify a - # reason why. - if state is None and request.getProtected(): - state = _("This partition is holding the data for the hard " - "drive install.") - - if state: - if not quiet: - intf.messageWindow(_("Unable To Delete"), - _("You cannot delete this partition:\n\n") + state, - custom_icon="error") - return 0 - - if confirm and not confirmDeleteRequest(intf, request): - return 0 - - if request.getPreExisting(): - if isinstance(request, partRequests.PartitionSpec): - # get the drive - drive = partedUtils.get_partition_drive(partition) - - if partition.type & parted.PARTITION_EXTENDED: - requestlist.deleteAllLogicalPartitions(partition) - - delete = partRequests.DeleteSpec(drive, - partition.geometry.start, - partition.geometry.end) - requestlist.addDelete(delete) - elif isinstance(request, partRequests.LogicalVolumeRequestSpec): - vgreq = requestlist.getRequestByID(request.volumeGroup) - delete = partRequests.DeleteLogicalVolumeSpec(request.logicalVolumeName, - vgreq.volumeGroupName) - requestlist.addDelete(delete) - elif isinstance(request, partRequests.VolumeGroupRequestSpec): - delete = partRequests.DeleteVolumeGroupSpec(request.volumeGroupName) - requestlist.addDelete(delete) - # FIXME: do we need to do anything with preexisting raids? - - # now remove the request - requestlist.deleteDependentRequests(request) - requestlist.removeRequest(request) - else: # is this a extended partition we made? - if partition.type & parted.PARTITION_EXTENDED: - requestlist.deleteAllLogicalPartitions(partition) - else: - #raise ValueError, "Deleting a non-existent partition" - return 0 + reason, + customer_icon="error") + return False + + if confirm and not confirmDelete(intf, device): + return False - del partition - return 1 + for dep in storage.deviceDeps(device): + storage.deleteDevice(dep) -def doDeletePartitionsByDevice(intf, requestlist, diskset, device, - confirm=1, quiet=0): - """ Remove all partitions currently on device """ + storage.deleteDevice(device) + return True + +def doDeleteDependentDevices(intf, storage, device, confirm=1, quiet=0): + """ Remove all devices/partitions currently on device """ if confirm: rc = intf.messageWindow(_("Confirm Delete"), _("You are about to delete all partitions on " - "the device '/dev/%s'.") % (device,), + "the device '%s'.") % (device.path,), type="custom", custom_icon="warning", custom_buttons=[_("Cancel"), _("_Delete")]) if not rc: - return - - requests = requestlist.getRequestsByDevice(diskset, device) - if not requests: - return - - # get list of unique IDs of these requests - reqIDs = set() - reqparts = {} - - for req in requests: - for drive in req.drive: - part = diskset.disks[drive].getPartitionByPath("/dev/%s" % req.device) - - if part.type & parted.PARTITION_FREESPACE or \ - part.type & parted.PARTITION_METADATA or \ - part.type & parted.PARTITION_PROTECTED: - continue - - reqIDs.add(req.uniqueID) - - if reqparts.has_key(req.uniqueID): - reqparts[req.uniqueID].append(part) - else: - reqparts[req.uniqueID] = [ part ] - - reqIDs = list(reqIDs) - - # now go thru and try to delete the unique IDs - for id in reqIDs: - try: - req = requestlist.getRequestByID(id) - if req is None: - continue - for partlist in reqparts[id]: - for part in partlist: - rc = doDeletePartitionByRequest(intf, requestlist, part, - confirm=0, quiet=1) - if not rc: - pass - except: - pass - - # see which partitions are left - notdeleted = [] - left_requests = requestlist.getRequestsByDevice(diskset, device) - if left_requests: - # get list of unique IDs of these requests - leftIDs = set() - - for req in left_requests: - for drive in req.drive: - part = diskset.disks[drive].getPartitionByPath("/dev/%s" % req.device) - - if part.type & parted.PARTITION_FREESPACE or \ - part.type & parted.PARTITION_METADATA or \ - part.type & parted.PARTITION_PROTECTED: - continue - - leftIDs.add(req.uniqueID) - - leftIDs = list(leftIDs) - - for id in leftIDs: - req = requestlist.getRequestByID(id) - notdeleted.append(req) - - # see if we need to report any failures - some were because we removed - # an extended partition which contained other members of our delete list - outlist = "" - for req in notdeleted: - newreq = requestlist.getRequestByID(req.uniqueID) - if newreq: - outlist = outlist + "\t/dev/%s\n" % (newreq.device,) - - if outlist != "" and not quiet: + return False + + deps = storage.deviceDeps(device) + if not deps: + # nothing to do + return False + + immmutable = [] + for dep in deps: + if storage.deviceImmutable(dep): + immutable.append(dep.path) + continue + else: + storage.deleteDevice(dep) + + if immutable and not quiet: + remaining = "\n\t" + "\n\t".join(immutable) + "\n" intf.messageWindow(_("Notice"), _("The following partitions were not deleted " "because they are in use:\n\n%s") % outlist, custom_icon="warning") - return 1 - - -def doEditPartitionByRequest(intf, requestlist, part): - """Edit a partition from the request list. - - intf is the interface - requestlist is the list of requests - partition is either the part object or the uniqueID if not a part - """ - - if part == None: - intf.messageWindow(_("Unable To Edit"), - _("You must select a partition to edit"), custom_icon="error") - - return (None, None) - - if type(part) == type("RAID"): - - # see if device is in our partition requests, remove - request = requestlist.getRequestByID(int(part)) - - if request: - state = isNotChangable(request, requestlist) - if state is not None: - intf.messageWindow(_("Unable To Edit"), _("You cannot edit this partition:\n\n") + state, - custom_icon="error") - return (None, None) - - if request.type == REQUEST_RAID: - return ("RAID", request) - elif request.type == REQUEST_VG: - return ("LVMVG", request) - elif request.type == REQUEST_LV: - return ("LVMLV", request) - else: - return (None, None) - elif part.type & parted.PARTITION_FREESPACE: - request = partRequests.PartitionSpec(fsset.fileSystemTypeGetDefault(), - start = part.geometry.device.startSectorToCylinder(part.geometry.start), - end = part.geometry.device.endSectorToCylinder(part.geometry.end), - drive = [ partedUtils.get_partition_drive(part) ]) - - return ("NEW", request) - elif part.type & parted.PARTITION_EXTENDED: - return (None, None) - - ret = requestlist.containsImmutablePart(part) - if ret: - intf.messageWindow(_("Unable To Edit"), - _("You cannot edit this " - "partition, as it is an extended partition " - "which contains %s") %(ret), custom_icon="error") - return (None, None) - - name = part.getDeviceNodeName() - request = requestlist.getRequestByDeviceName(name) - if request: - state = isNotChangable(request, requestlist) - if state is not None: - intf.messageWindow(_("Unable To Edit"), - _("You cannot edit this partition:\n\n") + state, custom_icon="error") - return (None, None) - - return ("PARTITION", request) - else: # shouldn't ever happen - raise ValueError, ("Trying to edit non-existent partition %s" - % (part.getDeviceNodeName(),)) - + return True def checkForSwapNoMatch(anaconda): """Check for any partitions of type 0x82 which don't have a swap fs.""" - diskset = anaconda.id.diskset - - for request in anaconda.id.partitions.requests: - if not hasattr(request, "drive") or not request.fstype: + for device in anaconda.id.storage.partitions: + if not device.exists: + # this is only for existing partitions continue - for drive in request.drive: - part = diskset.disks[drive].getPartitionByPath("/dev/%s" % request.device) - - if (part and (not part.type & parted.PARTITION_FREESPACE) - and (part.getFlag(parted.PARTITION_SWAP)) - and (request.fstype and request.fstype.getName() != "swap") - and (not request.format)): - rc = anaconda.intf.messageWindow(_("Format as Swap?"), - _("/dev/%s has a partition type of 0x82 " - "(Linux swap) but does not appear to " - "be formatted as a Linux swap " - "partition.\n\n" - "Would you like to format this " - "partition as a swap partition?") - % (request.device), type = "yesno", - custom_icon="question") - if rc == 1: - request.format = 1 - request.fstype = fsset.fileSystemTypeGet("swap") - if request.fstype.getName() == "software RAID": - part.setFlag(parted.PARTITION_RAID) - else: - part.unsetFlag(parted.PARTITION_RAID) - - partedUtils.set_partition_file_system_type(part, - request.fstype) + if device.partType & parted.PARTITION_SWAP and \ + not device.format.type == "swap": + rc = anaconda.intf.messageWindow(_("Format as Swap?"), + _("%s has a partition type of 0x82 " + "(Linux swap) but does not appear to " + "be formatted as a Linux swap " + "partition.\n\n" + "Would you like to format this " + "partition as a swap partition?") + % device.path, type = "yesno", + custom_icon="question") + if rc == 1: + format = getFormat("swap", device=device.path) + anaconda.id.storage.formatDevice(device, format) + + return def mustHaveSelectedDrive(intf): txt =_("You need to select at least one hard drive to install %s.") % (productName,) @@ -498,63 +262,42 @@ def partitionPreExistFormatWarnings(intf, warnings): type="yesno", custom_icon="warning") return rc -def getPreExistFormatWarnings(partitions, diskset): - """Return a list of preexisting partitions being formatted.""" - - devs = [] - for request in partitions.requests: - if request.getPreExisting() == 1: - devs.append(request.uniqueID) +def getPreExistFormatWarnings(storage): + """Return a list of preexisting devices being formatted.""" + devices = [] + for device in storage.devicetree.devices.values(): + if device.exists and not device.format.exists: + devices.append(device) - devs.sort() - + devices.sort(key=lambda d: d.name) rc = [] - for dev in devs: - request = partitions.getRequestByID(dev) - if request.format: - if request.fstype.isMountable(): - mntpt = request.mountpoint - else: - mntpt = "" - - if isinstance(request, partRequests.PartitionSpec): - dev = request.device - elif isinstance(request, partRequests.RaidRequestSpec): - dev = "md%s" %(request.raidminor,) - elif isinstance(request, partRequests.VolumeGroupRequestSpec): - dev = request.volumeGroupName - elif isinstance(request, partRequests.LogicalVolumeRequestSpec): - vgreq = partitions.getRequestByID(request.volumeGroup) - dev = "%s/%s" %(vgreq.volumeGroupName, - request.logicalVolumeName) - - rc.append((dev, request.fstype.getName(), mntpt)) - - if len(rc) == 0: - return None - else: - return rc + for device in devices: + rc.append((device.path, + device.format.type, + getattr(device.format, "mountpoint", ""))) + return rc -def confirmDeleteRequest(intf, request): - """Confirm the deletion of a request.""" - if not request: +def confirmDelete(intf, device): + """Confirm the deletion of a device.""" + if not device: return - if request.type == REQUEST_VG: + if device.type == "lvmvg": errmsg = (_("You are about to delete the volume group \"%s\"." "\n\nALL logical volumes in this volume group " - "will be lost!") % (request.volumeGroupName,)) - elif request.type == REQUEST_LV: + "will be lost!") % device.name) + elif device.type == "lvmlv": errmsg = (_("You are about to delete the logical volume \"%s\".") - % (request.logicalVolumeName,)) - elif request.type == REQUEST_RAID: + % (device.name) + elif device.type == "mdarray": errmsg = _("You are about to delete a RAID device.") + elif device.type == "partition": + errmsg = (_("You are about to delete the %s partition.") + % device.path) else: - if request.device: - errmsg = _("You are about to delete the /dev/%s partition.") % (request.device,) - else: - # XXX can this ever happen? - errmsg = _("The partition you selected will be deleted.") + # we may want something a little bit prettier than device.type + errmsg = (_("You are about to delete the %s %s") % (device.type, + device.name)) rc = intf.messageWindow(_("Confirm Delete"), errmsg, type="custom", custom_buttons=[_("Cancel"), _("_Delete")], @@ -629,10 +629,6 @@ class InstallInterface: # draw the frame after setting up the fallback self.drawFrame() - anaconda.id.fsset.registerMessageWindow(self.messageWindow) - anaconda.id.fsset.registerProgressWindow(self.progressWindow) - anaconda.id.fsset.registerWaitWindow(self.waitWindow) - lastrc = INSTALL_OK (step, instance) = anaconda.dispatch.currentStep() while step: |