diff options
| author | Mike Fulbright <msf@redhat.com> | 2001-06-20 22:38:48 +0000 |
|---|---|---|
| committer | Mike Fulbright <msf@redhat.com> | 2001-06-20 22:38:48 +0000 |
| commit | df41d89bb6bf243dd355dfae69d32cd38725665f (patch) | |
| tree | e2216eb9d42282c89892d84cd65c3141de854033 | |
| parent | a4c0b8fd56b50048883f8aab70a7e66675641086 (diff) | |
fix ups to RAID sanity checking
| -rw-r--r-- | fsset.py | 2 | ||||
| -rw-r--r-- | iw/partition_gui.py | 82 | ||||
| -rw-r--r-- | partitioning.py | 177 | ||||
| -rw-r--r-- | textw/partition_text.py | 7 |
4 files changed, 213 insertions, 55 deletions
@@ -27,7 +27,7 @@ defaultMountPoints = ('/', '/boot', '/home', '/tmp', '/usr', '/var') fileSystemTypes = {} -availRaidLevels = ['RAID-0', 'RAID-1', 'RAID-5'] +availRaidLevels = ['RAID0', 'RAID1', 'RAID5'] def fileSystemTypeGetDefault(): return fileSystemTypeGet('ext2') diff --git a/iw/partition_gui.py b/iw/partition_gui.py index f8538a48b..b1b9883eb 100644 --- a/iw/partition_gui.py +++ b/iw/partition_gui.py @@ -305,6 +305,7 @@ def createAllowedDrivesClist(drives, reqdrives): return driveclist def createAllowedRaidPartitionsClist(allraidparts, reqraidpart): + partclist = GtkCList() partclist.set_selection_mode (SELECTION_MULTIPLE) @@ -322,7 +323,7 @@ def createAllowedRaidPartitionsClist(allraidparts, reqraidpart): return partclist -def createRaidLevelMenu(levels, reqlevel): +def createRaidLevelMenu(levels, reqlevel, raidlevelchangeCB, sparesb): leveloption = GtkOptionMenu() leveloptionmenu = GtkMenu() defindex = None @@ -333,6 +334,8 @@ def createRaidLevelMenu(levels, reqlevel): leveloptionmenu.add(item) if reqlevel and lev == reqlevel: defindex = i + if raidlevelchangeCB and sparesb: + item.connect("activate", raidlevelchangeCB, sparesb) i = i + 1 leveloption.set_menu (leveloptionmenu) @@ -352,6 +355,9 @@ def createFSTypeMenu(fstype, fstypechangeCB, mountCombo): defindex = None i = 0 for name in names: + if not fileSystemTypeGet(name).isSupported(): + continue + if fileSystemTypeGet(name).isFormattable(): item = GtkMenuItem(name) item.set_data ("type", types[name]) @@ -369,7 +375,24 @@ def createFSTypeMenu(fstype, fstypechangeCB, mountCombo): return (fstypeoption, fstypeoptionMenu) - +def raidlevelchangeCB(widget, sparesb): + raidlevel = widget.get_data("level") + numparts = sparesb.get_data("numparts") + maxspares = get_raid_max_spares(raidlevel, numparts) + if maxspares > 0: + sparesb.set_sensitive(1) + adj = sparesb.get_adjustment() + value = adj.value + if adj.value > maxspares: + value = maxspares + adj.set_all(value, 0, maxspares, + adj.step_increment, adj.page_increment, + adj.page_size) + sparesb.set_adjustment(adj) + sparesb.set_value(value) + else: + sparesb.set_value(0) + sparesb.set_sensitive(0) class PartitionWindow(InstallWindow): def __init__(self, ics): @@ -381,6 +404,7 @@ class PartitionWindow(InstallWindow): def getNext(self): self.diskStripeGraph.shutDown() self.clearTree() + self.fsset.reset() for request in self.partitions.requests: # XXX improve sanity checking if not request.fstype or (request.fstype.isMountable() and not request.mountpoint): @@ -683,8 +707,6 @@ class PartitionWindow(InstallWindow): # read out UI into a partition specification filesystem = fstypeoptionMenu.get_active().get_data("type") - print filesystem.getName() - if not newbycyl: if fixedrb.get_active(): grow = None @@ -726,7 +748,7 @@ class PartitionWindow(InstallWindow): print "new requests:" print request - err = sanityCheck(self.partitions, request) + err = sanityCheckPartitionRequest(self.partitions, request) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err)) @@ -746,7 +768,7 @@ class PartitionWindow(InstallWindow): else: request.format = 0 - err = sanityCheck(self.partitions, request) + err = sanityCheckPartitionRequest(self.partitions, request) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err)) @@ -830,6 +852,12 @@ class PartitionWindow(InstallWindow): self.tree.thaw() self.checkNextConditions() +# for r in self.partitions.requests: +# print "--------------------------" +# print r +# print "--------------------------" +# +# print "\n\n" return rc def editCb(self, widget): @@ -874,6 +902,8 @@ class PartitionWindow(InstallWindow): maintable.set_col_spacings (5) row = 0 + availraidparts = get_available_raid_partitions(self.diskset, self.partitions.requests) + # Mount Point entry maintable.attach(createAlignedLabel(_("Mount Point:")), 0, 1, row, row + 1) @@ -895,7 +925,29 @@ class PartitionWindow(InstallWindow): # raid level maintable.attach(createAlignedLabel(_("RAID Level:")), 0, 1, row, row + 1) - (leveloption, leveloptionmenu) = createRaidLevelMenu(availRaidLevels, raidrequest.raidlevel) + + # Create here, pack below + numparts = len(availraidparts) + if raidrequest.raidlevel: + maxspares = get_raid_max_spares(raidrequest.raidlevel, numparts) + else: + maxspares = 0 + + spareAdj = GtkAdjustment (value = 0, lower = 0, + upper = maxspares, step_incr = 1) + sparesb = GtkSpinButton(spareAdj, digits = 0) + sparesb.set_data("numparts", numparts) + + if maxspares > 0: + sparesb.set_sensitive(1) + else: + sparesb.set_value(0) + sparesb.set_sensitive(0) + + (leveloption, leveloptionmenu) = createRaidLevelMenu(availRaidLevels, + raidrequest.raidlevel, + raidlevelchangeCB, + sparesb) maintable.attach(leveloption, 1, 2, row, row + 1) row = row + 1 @@ -904,22 +956,16 @@ class PartitionWindow(InstallWindow): maintable.attach(createAlignedLabel(_("Raid Members:")), 0, 1, row, row + 1) - availraidparts = [] - for drive in self.diskset.disks.keys(): - availraidparts.extend(get_raid_partitions(self.diskset.disks[drive])) - # XXX need to pass in currently used partitions for this device raidclist = createAllowedRaidPartitionsClist(availraidparts, raidrequest.raidmembers) + maintable.attach(raidclist, 1, 2, row, row + 1) row = row + 1 - # number of spares + # number of spares - created widget above maintable.attach(createAlignedLabel(_("Number of spares?:")), 0, 1, row, row + 1) - spareAdj = GtkAdjustment (value = 0, lower = 0, - upper = len(availraidparts), step_incr = 1) - sparesb = GtkSpinButton(spareAdj, digits = 0) maintable.attach(sparesb, 1, 2, row, row + 1) row = row + 1 @@ -944,12 +990,16 @@ class PartitionWindow(InstallWindow): if rc == 1: dialog.close() return + elif rc == -1: + # something died in dialog + raise ValueError, "Died inside of raid edit dialog!" # read out UI into a partition specification request = copy.copy(raidrequest) filesystem = fstypeoptionMenu.get_active().get_data("type") request.fstype = filesystem + print "in editraid, fs = ",filesystem.getName() if request.fstype.isMountable(): request.mountpoint = mountCombo.entry.get_text() @@ -971,7 +1021,7 @@ class PartitionWindow(InstallWindow): print request - err = sanityCheck(self.partitions, request) + err = sanityCheckRaidRequest(self.partitions, request) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err)) diff --git a/partitioning.py b/partitioning.py index fdc92c2db..d4fcbdf6f 100644 --- a/partitioning.py +++ b/partitioning.py @@ -34,6 +34,11 @@ REQUEST_PREEXIST = 1 REQUEST_NEW = 2 REQUEST_RAID = 4 +# max partition size in kB +# XXX these are just made up, need to get real values from parted! +MAX_PART_SIZE = 1024*1024*1024 +MAX_SWAP_PART_SIZE_KB = 2147483640/1024 + fsTypes = {} fs_type = parted.file_system_type_get_next () @@ -145,45 +150,80 @@ def get_available_raid_partitions(diskset, requests): for drive in drives: disk = diskset.disks[drive] for part in get_raid_partitions(disk): + used = 0 for raid in raiddevs: - if raid.raidmembers and part in raid.raidmembers: + if raid.raidmembers: + for raidmem in raid.raidmembers: + if get_partition_name(part) == get_partition_name(raidmem.partition): + used = 1 + break + if used: break - rc.append(part) + + if not used: + rc.append(part) return rc # return minimum numer of raid members required for a raid level def get_raid_min_members(raidlevel): - if raidlevel == "RAID-0": + if raidlevel == "RAID0": return 2 - elif raidlevel == "RAID-1": + elif raidlevel == "RAID1": return 2 - elif raidlevel == "RAID-5": + elif raidlevel == "RAID5": return 3 else: raise ValueError, "invalid raidlevel in get_raid_min_members" # return max num of spares available for raidlevel and total num of members def get_raid_max_spares(raidlevel, nummembers): - if raidlevel == "RAID-0": - return 0 - elif raidlevel == "RAID-1": + if raidlevel == "RAID0": return 0 - elif raidlevel == "RAID-5": + elif raidlevel == "RAID1" or raidlevel == "RAID5": return max(0, nummembers - get_raid_min_members(raidlevel)) else: raise ValueError, "invalid raidlevel in get_raid_max_spares" -# returns error string if something not right about request -# returns error string if something not right about request -def sanityCheck(reqpartitions, newrequest): - # see if mount point is valid if its a new partition request +def get_raid_device_size(raidrequest): + if not raidrequest.raidmembers or not raidrequest.raidlevel: + return 0 - mustbeonroot = ['/bin','/dev','/sbin','/etc','/lib','/root','/mnt'] - mustbeonlinuxfs = ['/', '/boot', '/var', '/tmp', '/usr', '/home'] + raidlevel = raidrequest.raidlevel + nummembers = len(raidrequest.raidmembers) + smallest = None + sum = 0 + for member in raidrequest.raidmembers: + part = member.partition + partsize = part.geom.length * part.geom.disk.dev.sector_size + print "raid members, size->",get_partition_name(part), partsize + if raidlevel == "RAID0": + sum = sum + partsize + else: + if not smallest: + smallest = partsize + elif sizekb < smallest: + smallest = partsize + + if raidlevel == "RAID0": + return sum + elif raidlevel == "RAID1": + return smallest + elif raidlevel == "RAID5": + return (nummembers-1) * smallest + else: + raise ValueError, "Invalid raidlevel in get_raid_device_size()" - mntpt = newrequest.mountpoint - fstype = newrequest.fstype +# return name of boot mount point in current requests +def getBootableRequest(reqpartitions): + bootreq = reqpartitions.getRequestByMountPoint("/boot") + if not bootreq: + bootreq = reqpartitions.getRequestByMountPoint("/") + return bootreq + + +# sanityCheckMountPoint +def sanityCheckMountPoint(mntpt, fstype, reqtype): if mntpt: passed = 1 if not mntpt: @@ -191,41 +231,98 @@ def sanityCheck(reqpartitions, newrequest): else: if mntpt[0] != '/' or (len(mntpt) > 1 and mntpt[-1:] == '/'): passed = 0 - + if not passed: return _("The mount point is invalid. Mount points must start " "with '/' and cannot end with '/', and must contain " "printable characters.") + else: + return None else: - if newrequest.fstype.isMountable() and newrequest.type == REQUEST_NEW: + if fstype and fstype.isMountable() and reqtype == REQUEST_NEW: return _("Please specify a mount point for this partition.") else: # its an existing partition so don't force a mount point - return + return None - # mount point is defined and is legal. now make sure its unique +def isMountPointInUse(reqpartitions, newrequest): + mntpt = newrequest.mountpoint + if not mntpt: + return None + if reqpartitions and reqpartitions.requests: for request in reqpartitions.requests: - if request.mountpoint == mntpt and request.start != newrequest.start: - return _("The mount point %s is already in use, please " - "choose a different mount point." % (mntpt)) + if request.mountpoint == mntpt: + used = 0 + if newrequest.type == REQUEST_RAID: + if request.raidmembers != newrequest.raidmembers: + used = 1 + else: + if request.start != newrequest.start: + used = 1 + if used: + return _("The mount point %s is already in use, please " + "choose a different mount point." % (mntpt)) + + + return None - # further sanity checks - if fstype.isLinuxNativeFS(): - if mntpt in mustbeonroot: +def doMountPointLinuxFSChecks(newrequest): + mustbeonroot = ['/bin','/dev','/sbin','/etc','/lib','/root','/mnt'] + mustbeonlinuxfs = ['/', '/boot', '/var', '/tmp', '/usr', '/home'] + + if newrequest.fstype.isLinuxNativeFS(): + if newrequest.mountpoint in mustbeonroot: return _("This mount point is invalid. This directory must " "be on the / filesystem.") - if fstype.getName() == "linux-swap": - if newrequest.size * 1024 > MAX_SWAP_PART_SIZE_KB: - return _("This swap partition exceeds the maximum size of " - "%s MB.") % (MAX_SWAP_PART_SIZE_KB / 1024) + if newrequest.fstype.getName() == "swap": + if newrequest.type == REQUEST_RAID: + swapsize = get_raid_device_size(newrequest) + else: + swapsize = newrequest.size + + print "swapsize ->",swapsize + + if swapsize * 1024 > MAX_SWAP_PART_SIZE_KB: + return _("This swap partition exceeds the maximum size of " + "%s MB.") % (MAX_SWAP_PART_SIZE_KB / 1024) + else: + return None else: - if mntpt in mustbeonlinuxfs: + if newrequest.mountpoint in mustbeonlinuxfs: return _("This mount point must be on a linux filesystem.") return None + + + +# returns error string if something not right about request +def sanityCheckPartitionRequest(reqpartitions, newrequest): + # see if mount point is valid if its a new partition request + mntpt = newrequest.mountpoint + fstype = newrequest.fstype + reqtype = newrequest.type + + rc = sanityCheckMountPoint(mntpt, fstype, reqtype) + if rc: + return rc + + rc = isMountPointInUse(reqpartitions, newrequest) + if rc: + return rc + + rc = doMountPointLinuxFSChecks(newrequest) + if rc: + return rc + + return None + +# return error string is something not right about raid request +def sanityCheckRaidRequest(reqpartitions, newraid): + rc = sanityCheckPartitionRequest(reqpartitions, newraid) + class DeleteSpec: def __init__(self, drive, start, end): @@ -281,14 +378,24 @@ class PartitionSpec: self.currentDrive = None def __str__(self): - return "mountpoint: %s type: %s\n" %(self.mountpoint, self.fstype.getName()) +\ + if self.fstype: + fsname = self.fstype.getName() + else: + fsname = "None" + raidmem = [] + if self.raidmembers: + for i in self.raidmembers: + raidmem.append(get_partition_name(i.partition)) + + return "mountpoint: %s type: %s\n" %(self.mountpoint, fsname) +\ " size: %sM requestSize: %sM grow: %s max: %s\n" %(self.size, self.requestSize, self.grow, self.maxSize) +\ " start: %s end: %s partnum: %s\n" %(self.start, self.end, self.partnum) +\ " drive: %s primary: %s secondary: %s\n" %(self.drive, self.primary, self.secondary) +\ " format: %s, options: %s" %(self.format, self.options) +\ - " device: %s, realDevice: %s" %(self.device, self.realDevice)+\ + " device: %s, realDevice: %s\n" %(self.device, self.realDevice)+\ " raidlevel: %s" % (self.raidlevel)+\ - " raidspares: %s" % (self.raidspares) + " raidspares: %s" % (self.raidspares)+\ + " raidmembers: %s" % (raidmem) # turn a partition request into a fsset entry def toEntry(self): diff --git a/textw/partition_text.py b/textw/partition_text.py index af94948ea..623bc998c 100644 --- a/textw/partition_text.py +++ b/textw/partition_text.py @@ -403,7 +403,7 @@ class PartitionWindow: request.primary = primonly request.maxSize = maxsize - err = sanityCheck(self.partitions, request) + err = sanityCheckPartitionRequest(self.partitions, request) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err)) @@ -420,7 +420,7 @@ class PartitionWindow: else: origrequest.format = 0 - err = sanityCheck(self.partitions, origrequest) + err = sanityCheckPartitionRequest(self.partitions, origrequest) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err)) @@ -502,7 +502,7 @@ class PartitionWindow: else: request.format = 0 - err = sanityCheck(self.partitions, request) + err = sanityCheckPartitionRequest(self.partitions, request) if err: self.intf.messageWindow(_("Error With Request"), "%s" % (err)) @@ -636,6 +636,7 @@ class PartitionWindow: else: if not self.partitions.getRequestByMountPoint("/"): continue + self.fsset.reset() for request in self.partitions.requests: # XXX improve sanity checking if not request.fstype or (request.fstype.isMountable() and not request.mountpoint): |
