/[smeserver]/cdrom.image/updates/partedUtils.py
ViewVC logotype

Annotation of /cdrom.image/updates/partedUtils.py

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (hide annotations) (download) (as text)
Sat Jul 30 15:05:50 2005 UTC (19 years, 3 months ago) by slords
Branch: MAIN
Changes since 1.1: +1 -2 lines
Content type: text/x-python
kickstart not necessary and gonna be hard to support

1 gordonr 1.1 #
2     # partedUtils.py: helper functions for use with parted objects
3     #
4     # Matt Wilson <msw@redhat.com>
5     # Jeremy Katz <katzj@redhat.com>
6     # Mike Fulbright <msf@redhat.com>
7     # Karsten Hopp <karsten@redhat.com>
8     #
9     # Copyright 2002-2003 Red Hat, Inc.
10     #
11     # This software may be freely redistributed under the terms of the GNU
12     # library public license.
13     #
14     # You should have received a copy of the GNU Library Public License
15     # along with this program; if not, write to the Free Software
16     # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17     #
18     """Helper functions for use when dealing with parted objects."""
19    
20     import parted
21     import math
22     import os, sys, string, struct
23    
24     from product import *
25     import fsset
26     import iutil, isys
27     import raid
28     import lvm
29     from flags import flags
30     from partErrors import *
31    
32     from rhpl.log import log
33     from rhpl.translate import _
34    
35     fsTypes = {}
36    
37     fs_type = parted.file_system_type_get_next ()
38     while fs_type:
39     fsTypes[fs_type.name] = fs_type
40     fs_type = parted.file_system_type_get_next (fs_type)
41    
42    
43    
44     def get_flags (part):
45     """Retrieve a list of strings representing the flags on the partition."""
46     string=""
47     if not part.is_active ():
48     return string
49     first=1
50     flag = parted.partition_flag_next (0)
51     while flag:
52     if part.get_flag (flag):
53     string = string + parted.partition_flag_get_name (flag)
54     if first:
55     first = 0
56     else:
57     string = string + ", "
58     flag = parted.partition_flag_next (flag)
59     return string
60    
61     def start_sector_to_cyl(device, sector):
62     """Return the closest cylinder (round down) to sector on device."""
63     return int(math.floor((float(sector)
64     / (device.heads * device.sectors)) + 1))
65    
66     def end_sector_to_cyl(device, sector):
67     """Return the closest cylinder (round up) to sector on device."""
68     return int(math.ceil(float((sector + 1))
69     / (device.heads * device.sectors)))
70    
71     def start_cyl_to_sector(device, cyl):
72     "Return the sector corresponding to cylinder as a starting cylinder."
73     return long((cyl - 1) * (device.heads * device.sectors))
74    
75     def end_cyl_to_sector(device, cyl):
76     "Return the sector corresponding to cylinder as a ending cylinder."
77     return long(((cyl) * (device.heads * device.sectors)) - 1)
78    
79     def getPartSize(partition):
80     """Return the size of partition in sectors."""
81     return partition.geom.length
82    
83     def getPartSizeMB(partition):
84     """Return the size of partition in megabytes."""
85     return (partition.geom.length * partition.geom.dev.sector_size
86     / 1024.0 / 1024.0)
87    
88     def getDeviceSizeMB(dev):
89     """Return the size of dev in megabytes."""
90     return (float(dev.heads * dev.cylinders * dev.sectors) / (1024 * 1024)
91     * dev.sector_size)
92    
93     def get_partition_by_name(disks, partname):
94     """Return the parted part object associated with partname.
95    
96     Arguments:
97     disks -- Dictionary of diskname->PedDisk objects
98     partname -- Name of partition to find
99    
100     Return:
101     PedPartition object with name partname. None if no such partition.
102     """
103     for diskname in disks.keys():
104     disk = disks[diskname]
105     part = disk.next_partition()
106     while part:
107     if get_partition_name(part) == partname:
108     return part
109    
110     part = disk.next_partition(part)
111    
112     return None
113    
114     def get_partition_name(partition):
115     """Return the device name for the PedPartition partition."""
116     if (partition.geom.dev.type == parted.DEVICE_DAC960
117     or partition.geom.dev.type == parted.DEVICE_CPQARRAY):
118     return "%sp%d" % (partition.geom.dev.path[5:],
119     partition.num)
120     if (parted.__dict__.has_key("DEVICE_SX8") and
121     partition.geom.dev.type == parted.DEVICE_SX8):
122     return "%sp%d" % (partition.geom.dev.path[5:],
123     partition.num)
124    
125     return "%s%d" % (partition.geom.dev.path[5:],
126     partition.num)
127    
128    
129     def get_partition_file_system_type(part):
130     """Return the file system type of the PedPartition part.
131    
132     Arguments:
133     part -- PedPartition object
134    
135     Return:
136     Filesystem object (as defined in fsset.py)
137     """
138     if part.fs_type is None and part.native_type == 0x41:
139     ptype = fsset.fileSystemTypeGet("PPC PReP Boot")
140     elif part.fs_type == None:
141     return None
142     elif part.fs_type.name == "linux-swap":
143     ptype = fsset.fileSystemTypeGet("swap")
144     elif (part.fs_type.name == "FAT" or part.fs_type.name == "fat16"
145     or part.fs_type.name == "fat32"):
146     ptype = fsset.fileSystemTypeGet("vfat")
147     else:
148     try:
149     ptype = fsset.fileSystemTypeGet(part.fs_type.name)
150     except:
151     ptype = fsset.fileSystemTypeGet("foreign")
152    
153     return ptype
154    
155    
156     def set_partition_file_system_type(part, fstype):
157     """Set partition type of part to PedFileSystemType implied by fstype."""
158     if fstype == None:
159     return
160     try:
161     for flag in fstype.getPartedPartitionFlags():
162     if not part.is_flag_available(flag):
163     raise PartitioningError, ("requested FileSystemType needs "
164     "a flag that is not available.")
165     part.set_flag(flag, 1)
166     part.set_system(fstype.getPartedFileSystemType())
167     except:
168     print "Failed to set partition type to ",fstype.getName()
169     pass
170    
171     def get_partition_drive(partition):
172     """Return the device name for disk that PedPartition partition is on."""
173     return "%s" %(partition.geom.dev.path[5:])
174    
175     def get_max_logical_partitions(disk):
176     if not disk.type.check_feature(parted.DISK_TYPE_EXTENDED):
177     return 0
178     dev = disk.dev.path[5:]
179     for key in max_logical_partition_count.keys():
180     if dev.startswith(key):
181     return max_logical_partition_count[key]
182     # FIXME: if we don't know about it, should we pretend it can't have
183     # logicals? probably safer to just use something reasonable
184     return 11
185    
186     def map_foreign_to_fsname(type):
187     """Return the partition type associated with the numeric type."""
188     if type in allPartitionTypesDict.keys():
189     return allPartitionTypesDict[type]
190     else:
191     return _("Foreign")
192    
193     def filter_partitions(disk, func):
194     rc = []
195     part = disk.next_partition ()
196     while part:
197     if func(part):
198     rc.append(part)
199     part = disk.next_partition (part)
200    
201     return rc
202    
203     def get_all_partitions(disk):
204     """Return a list of all PedPartition objects on disk."""
205     func = lambda part: part.is_active()
206     return filter_partitions(disk, func)
207    
208     def get_logical_partitions(disk):
209     """Return a list of logical PedPartition objects on disk."""
210     func = lambda part: (part.is_active()
211     and part.type & parted.PARTITION_LOGICAL)
212     return filter_partitions(disk, func)
213    
214     def get_primary_partitions(disk):
215     """Return a list of primary PedPartition objects on disk."""
216     func = lambda part: part.type == parted.PARTITION_PRIMARY
217     return filter_partitions(disk, func)
218    
219     def get_raid_partitions(disk):
220     """Return a list of RAID-type PedPartition objects on disk."""
221     func = lambda part: (part.is_active()
222     and part.get_flag(parted.PARTITION_RAID) == 1)
223     return filter_partitions(disk, func)
224    
225     def get_lvm_partitions(disk):
226     """Return a list of physical volume-type PedPartition objects on disk."""
227     func = lambda part: (part.is_active()
228     and part.get_flag(parted.PARTITION_LVM) == 1)
229     return filter_partitions(disk, func)
230    
231    
232     def getDefaultDiskType():
233     """Get the default partition table type for this architecture."""
234     if iutil.getArch() == "i386":
235     return parted.disk_type_get("msdos")
236     elif iutil.getArch() == "ia64":
237     return parted.disk_type_get("gpt")
238     elif iutil.getArch() == "s390":
239     # the "default" type is dasd, but we don't really do dasd
240     # formatting with parted and use dasdfmt directly for them
241     # so if we get here, it's an fcp disk and we should write
242     # an msdos partition table (#144199)
243     return parted.disk_type_get("msdos")
244     elif iutil.getArch() == "alpha":
245     return parted.disk_type_get("bsd")
246     elif iutil.getArch() == "sparc":
247     return parted.disk_type_get("sun")
248     elif iutil.getArch() == "ppc":
249     if iutil.getPPCMachine() == "PMac":
250     return parted.disk_type_get("mac")
251     else:
252     return parted.disk_type_get("msdos")
253     else:
254     return parted.disk_type_get("msdos")
255    
256     archLabels = {'i386': ['msdos'],
257     's390': ['dasd', 'msdos'],
258     'alpha': ['bsd', 'msdos'],
259     'sparc': ['sun'],
260     'ia64': ['msdos', 'gpt'],
261     'ppc': ['msdos', 'mac'],
262     'x86_64': ['msdos']}
263    
264     # this is kind of crappy, but we don't really want to allow LDL formatted
265     # dasd to be used during the install
266     def checkDasdFmt(disk, intf):
267     if iutil.getArch() != "s390":
268     return 0
269    
270     if disk.type.name != "dasd":
271     return 0
272    
273     # FIXME: there has to be a better way to check LDL vs CDL
274     # how do I test ldl vs cdl?
275     if disk.max_primary_partition_count > 1:
276     return 0
277    
278     if intf:
279     try:
280     devs = isys.getDasdDevPort()
281     dev = "/dev/%s (%s)" %(disk.dev.path[5:], devs[device])
282     except Exception, e:
283     log("exception getting dasd dev ports: %s" %(e,))
284     dev = "/dev/%s" %(disk.dev.path[5:],)
285    
286     rc = intf.messageWindow(_("Warning"),
287     _("The device %s is LDL formatted instead of "
288     "CDL formatted. LDL formatted DASDs are not "
289     "supported for usage during an install of %s. "
290     "If you wish to use this disk for installation, "
291     "it must be re-initialized causing the loss of "
292     "ALL DATA on this drive.\n\n"
293     "Would you like to reformat this DASD using CDL "
294     "format?")
295     %(dev, productName), type = "yesno")
296     if rc == 0:
297     return 1
298     else:
299     return -1
300     else:
301     return 1
302    
303    
304     def checkDiskLabel(disk, intf):
305     """Check that the disk label on disk is valid for this machine type."""
306     arch = iutil.getArch()
307     if arch in archLabels.keys():
308     if disk.type.name in archLabels[arch]:
309     # this is kind of a hack since we don't want LDL to be used
310     return checkDasdFmt(disk, intf)
311     else:
312     if disk.type.name == "msdos":
313     return 0
314    
315     if intf:
316     rc = intf.messageWindow(_("Warning"),
317     _("/dev/%s currently has a %s partition "
318     "layout. To use this disk for "
319     "the installation of %s, it must be "
320     "re-initialized, causing the loss of "
321     "ALL DATA on this drive.\n\n"
322     "Would you like to format this "
323     "drive?")
324     %(disk.dev.path[5:], disk.type.name,
325     productName), type="custom",
326     custom_buttons = [ _("_Ignore drive"),
327     _("_Format drive") ],
328     custom_icon="question")
329    
330     if rc == 0:
331     return 1
332     else:
333     return -1
334     else:
335     return 1
336    
337     # attempt to associate a parted filesystem type on a partition that
338     # didn't probe as one type or another.
339     def validateFsType(part):
340     # we only care about primary and logical partitions
341     if not part.type in (parted.PARTITION_PRIMARY,
342     parted.PARTITION_LOGICAL):
343     return
344     # if the partition already has a type, no need to search
345     if part.fs_type:
346     return
347    
348     # first fsystem to probe wins, so sort the types into a preferred
349     # order.
350     fsnames = fsTypes.keys()
351     goodTypes = ['ext3', 'ext2']
352     badTypes = ['linux-swap',]
353     for fstype in goodTypes:
354     fsnames.remove(fstype)
355     fsnames = goodTypes + fsnames
356     for fstype in badTypes:
357     fsnames.remove(fstype)
358     fsnames.extend(badTypes)
359    
360     # now check each type, and set the partition system accordingly.
361     for fsname in fsnames:
362     fstype = fsTypes[fsname]
363     if fstype.probe_specific(part.geom) != None:
364     # XXX verify that this will not modify system type
365     # in the case where a user does not modify partitions
366     part.set_system(fstype)
367     return
368    
369     def isLinuxNativeByNumtype(numtype):
370     """Check if the type is a 'Linux native' filesystem."""
371     linuxtypes = [0x82, 0x83, 0x8e, 0xfd]
372    
373     for t in linuxtypes:
374     if int(numtype) == t:
375     return 1
376    
377     return 0
378    
379     def sniffFilesystemType(device):
380     """Sniff to determine the type of fs on device.
381    
382     device - name of device to sniff. we try to create it if it doesn't exist.
383     """
384    
385     if os.access(device, os.O_RDONLY):
386     dev = device
387     else:
388     dev = "/tmp/" + device
389     if not os.access(dev, os.O_RDONLY):
390     try:
391     isys.makeDevInode(device, dev)
392     except:
393     pass
394    
395     pagesize = isys.getpagesize()
396     if pagesize > 2048:
397     num = pagesize
398     else:
399     num = 2048
400     try:
401     fd = os.open(dev, os.O_RDONLY)
402     buf = os.read(fd, num)
403     os.close(fd)
404     except:
405     return None
406    
407     if len(buf) < pagesize:
408     try:
409     log("Tried to read pagesize for %s in sniffFilesystemType and only read %s", dev, len(buf))
410     except:
411     pass
412     return None
413    
414     # physical volumes start with HM (see linux/lvm.h
415     # and LVM/ver/tools/lib/pv_copy.c)
416     if buf.startswith("HM"):
417     return "physical volume (LVM)"
418     # sniff for LVM2 label. see LVM/ver/lib/label/label.[ch] for a
419     # description of the label and LVM/ver/lib/format_text/layout.h
420     for sec in range(0, 4):
421     off = (sec * 512) + 24
422     if buf[off:].startswith("LVM2"):
423     return "physical volume (LVM)"
424    
425     try:
426     isys.raidsbFromDevice(dev)
427     return "software RAID"
428     except:
429     pass
430    
431     # ext2 check
432     if struct.unpack("<H", buf[1080:1082]) == (0xef53,):
433     if isys.ext2HasJournal(dev, makeDevNode = 0):
434     return "ext3"
435     else:
436     return "ext2"
437    
438     # xfs signature
439     if buf.startswith("XFSB"):
440     return "xfs"
441    
442     # 2.6 doesn't support version 0, so we don't like SWAP-SPACE
443     if (buf[pagesize - 10:] == "SWAPSPACE2"):
444     return "swap"
445    
446     if fsset.isValidReiserFS(dev):
447     return "reiserfs"
448    
449     if fsset.isValidJFS(dev):
450     return "jfs"
451    
452     # FIXME: we don't look for vfat
453    
454     return None
455    
456     def getCentOSReleaseString(mountpoint):
457     if os.access(mountpoint + "/etc/e-smith-release", os.R_OK):
458     log("/etc/e-smith-release found");
459     f = open(mountpoint + "/etc/e-smith-release", "r")
460     try:
461     lines = f.readlines()
462     except IOError:
463     try:
464     f.close()
465     except:
466     pass
467     return ""
468     f.close()
469     # return the first line with the newline at the end stripped
470     if len(lines) == 0:
471     return ""
472     relstr = string.strip(lines[0][:-1])
473    
474     # get the release name and version
475     # assumes that form is something
476     # like "Red Hat Linux release 6.2 (Zoot)"
477     if relstr.find("release") != -1:
478     try:
479     idx = relstr.find("release")
480     prod = relstr[:idx - 1]
481    
482     ver = ""
483     for a in relstr[idx + 8:]:
484     if a in string.digits + ".":
485     ver = ver + a
486     else:
487     break
488    
489     relstr = prod + " " + ver
490     except:
491     pass # don't worry, just use the relstr as we have it
492     log("Found relstr %s", relstr);
493     return relstr
494     return ""
495    
496     def productMatches(oldproduct, newproduct):
497     log("productMatches called: %s %s", oldproduct, newproduct);
498     """Determine if this is a reasonable product to upgrade old product"""
499     if oldproduct.startswith(newproduct):
500     return 1
501    
502     productUpgrades = {
503 slords 1.2 "SME Server": ("SME Server", "SME Server", "SME Server"),
504 gordonr 1.1 "Red Hat Enterprise Linux AS": ("Red Hat Linux Advanced Server", ),
505     "Red Hat Enterprise Linux WS": ("Red Hat Linux Advanced Workstation",),
506     # FIXME: this probably shouldn't be in a release...
507     "Red Hat Enterprise Linux": ("Red Hat Linux Advanced Server",
508     "Red Hat Linux Advanced Workstation",
509     "Red Hat Enterprise Linux AS",
510     "Red Hat Enterprise Linux ES",
511     "Red Hat Enterprise Linux WS"),
512     "Fedora Core": ("Red Hat Linux",)
513     }
514    
515     if productUpgrades.has_key(newproduct):
516     acceptable = productUpgrades[newproduct]
517     else:
518     acceptable = ()
519    
520     for p in acceptable:
521     if oldproduct.startswith(p):
522     return 1
523    
524     return 0
525    
526     class DiskSet:
527     """The disks in the system."""
528    
529     skippedDisks = []
530     mdList = []
531     def __init__ (self):
532     self.disks = {}
533     self.onlyPrimary = None
534    
535     def onlyPrimaryParts(self):
536     for disk in self.disks.values():
537     if disk.type.check_feature(parted.DISK_TYPE_EXTENDED):
538     return 0
539    
540     return 1
541    
542    
543     def startAllRaid(self):
544     """Start all of the raid devices associated with the DiskSet."""
545     driveList = []
546     origDriveList = self.driveList()
547     for drive in origDriveList:
548     if not drive in DiskSet.skippedDisks:
549     driveList.append(drive)
550     DiskSet.mdList.extend(raid.startAllRaid(driveList))
551    
552     def stopAllRaid(self):
553     """Stop all of the raid devices associated with the DiskSet."""
554     raid.stopAllRaid(DiskSet.mdList)
555     while DiskSet.mdList:
556     DiskSet.mdList.pop()
557    
558     def getLabels(self):
559     """Return a list of all of the labels used on partitions."""
560     labels = {}
561    
562     drives = self.disks.keys()
563     drives.sort()
564    
565     for drive in drives:
566     disk = self.disks[drive]
567     func = lambda part: (part.is_active() and
568     not (part.get_flag(parted.PARTITION_RAID)
569     or part.get_flag(parted.PARTITION_LVM))
570     and part.fs_type
571     and (part.fs_type.name in ("ext2",
572     "ext3", "xfs")))
573     parts = filter_partitions(disk, func)
574     for part in parts:
575     node = get_partition_name(part)
576     label = isys.readFSLabel(node)
577     if label:
578     labels[node] = label
579    
580     for dev, devices, level, numActive in DiskSet.mdList:
581     label = isys.readFSLabel(dev)
582     if label:
583     labels[dev] = label
584    
585     return labels
586    
587     def findExistingRootPartitions(self, intf, mountpoint, upgradeany = 0):
588     """Return a list of all of the partitions which look like a root fs."""
589     rootparts = []
590    
591     self.startAllRaid()
592    
593     for dev, devices, level, numActive in self.mdList:
594     (errno, msg) = (None, None)
595     found = 0
596     for fs in fsset.getFStoTry(dev):
597     try:
598     isys.mount(dev, mountpoint, fs, readOnly = 1)
599     found = 1
600     break
601     except SystemError, (errno, msg):
602     pass
603    
604     if found:
605     if os.access (mountpoint + '/etc/fstab', os.R_OK):
606     relstr = getCentOSReleaseString(mountpoint)
607     cmdline = open('/proc/cmdline', 'r').read()
608    
609     if ((cmdline.find("upgradeany") != -1) or
610     (upgradeany == 1) or
611     (productMatches(relstr, productName))):
612     rootparts.append ((dev, fs, relstr))
613     isys.umount(mountpoint)
614    
615     # now, look for candidate lvm roots
616     lvm.vgscan()
617     lvm.vgactivate()
618    
619     for (vg, lv, size) in lvm.lvlist():
620     dev = "/dev/%s/%s" %(vg, lv)
621     found = 0
622     for fs in fsset.getFStoTry(dev):
623     try:
624     isys.mount(dev, mountpoint, fs, readOnly = 1)
625     found = 1
626     break
627     except SystemError:
628     pass
629    
630     if found:
631     if os.access (mountpoint + '/etc/fstab', os.R_OK):
632     relstr = getCentOSReleaseString(mountpoint)
633     cmdline = open('/proc/cmdline', 'r').read()
634    
635     if ((cmdline.find("upgradeany") != -1) or
636     (upgradeany == 1) or
637     (productMatches(relstr, productName))):
638     rootparts.append ((dev, fs, relstr))
639     isys.umount(mountpoint)
640    
641     lvm.vgdeactivate()
642    
643     # don't stop raid until after we've looked for lvm on top of it
644     self.stopAllRaid()
645    
646     drives = self.disks.keys()
647     drives.sort()
648    
649     for drive in drives:
650     disk = self.disks[drive]
651     part = disk.next_partition ()
652     while part:
653     if (part.is_active()
654     and (part.get_flag(parted.PARTITION_RAID)
655     or part.get_flag(parted.PARTITION_LVM))):
656     pass
657     elif (part.fs_type and
658     part.fs_type.name in fsset.getUsableLinuxFs()):
659     node = get_partition_name(part)
660     try:
661     isys.mount(node, mountpoint, part.fs_type.name)
662     except SystemError, (errno, msg):
663     intf.messageWindow(_("Error"),
664     _("Error mounting file system on "
665     "%s: %s") % (node, msg))
666     part = disk.next_partition(part)
667     continue
668     if os.access (mountpoint + '/etc/fstab', os.R_OK):
669     relstr = getCentOSReleaseString(mountpoint)
670     cmdline = open('/proc/cmdline', 'r').read()
671    
672     if ((cmdline.find("upgradeany") != -1) or
673     (upgradeany == 1) or
674     (productMatches(relstr, productName))):
675     rootparts.append ((node, part.fs_type.name,
676     relstr))
677     isys.umount(mountpoint)
678    
679     part = disk.next_partition(part)
680     return rootparts
681    
682     def driveList (self):
683     """Return the list of drives on the system."""
684     drives = isys.hardDriveDict().keys()
685     drives.sort (isys.compareDrives)
686     return drives
687    
688     def drivesByName (self):
689     """Return a dictionary of the drives on the system."""
690     return isys.hardDriveDict()
691    
692     def addPartition (self, device, type, spec):
693     """Add a new partition to the device. - UNUSED."""
694     if not self.disks.has_key (device):
695     raise PartitioningError, ("unknown device passed to "
696     "addPartition: %s" % (device,))
697     disk = self.disks[device]
698    
699     part = disk.next_partition ()
700     status = 0
701     while part:
702     if (part.type == parted.PARTITION_FREESPACE
703     and part.geom.length >= spec.size):
704     newp = disk.partition_new (type, spec.fs_type,
705     part.geom.start,
706     part.geom.start + spec.size)
707     constraint = disk.dev.constraint_any ()
708     try:
709     disk.add_partition (newp, constraint)
710     status = 1
711     break
712     except parted.error, msg:
713     raise PartitioningError, msg
714     part = disk.next_partition (part)
715     if not status:
716     raise PartitioningError, ("Not enough free space on %s to create "
717     "new partition" % (device,))
718     return newp
719    
720     def deleteAllPartitions (self):
721     """Delete all partitions from all disks. - UNUSED."""
722     for disk in self.disks.values():
723     disk.delete_all ()
724    
725     def savePartitions (self):
726     """Write the partition tables out to the disks."""
727     for disk in self.disks.values():
728     disk.commit()
729     #disk.close()
730     del disk
731     self.refreshDevices()
732    
733     def refreshDevices (self, intf = None, initAll = 0,
734     zeroMbr = 0, clearDevs = []):
735     """Reread the state of the disks as they are on disk."""
736     self.closeDevices()
737     self.disks = {}
738     self.openDevices(intf, initAll, zeroMbr, clearDevs)
739    
740     def closeDevices (self):
741     """Close all of the disks which are open."""
742     for disk in self.disks.keys():
743     #self.disks[disk].close()
744     del self.disks[disk]
745    
746     def dasdFmt (self, intf = None, drive = None):
747     """Format dasd devices (s390)."""
748    
749     if self.disks.has_key(drive):
750     del self.disks[drive]
751    
752     w = intf.progressWindow (_("Initializing"),
753     _("Please wait while formatting drive %s...\n"
754     ) % (drive,), 100)
755     try:
756     isys.makeDevInode(drive, '/tmp/' + drive)
757     except:
758     pass
759    
760     argList = [ "/sbin/dasdfmt",
761     "-y",
762     "-b", "4096",
763     "-d", "cdl",
764     "-P",
765     "-F",
766     "-f",
767     "/tmp/%s" % drive]
768    
769     fd = os.open("/dev/null", os.O_RDWR | os.O_CREAT | os.O_APPEND)
770     p = os.pipe()
771     childpid = os.fork()
772     if not childpid:
773     os.close(p[0])
774     os.dup2(p[1], 1)
775     os.dup2(fd, 2)
776     os.close(p[1])
777     os.close(fd)
778     os.execv(argList[0], argList)
779     log("failed to exec %s", argList)
780     os._exit(1)
781    
782     os.close(p[1])
783    
784     num = ''
785     sync = 0
786     s = 'a'
787     while s:
788     try:
789     s = os.read(p[0], 1)
790     os.write(fd, s)
791    
792     if s != '\n':
793     try:
794     num = num + s
795     except:
796     pass
797     else:
798     if num:
799     val = string.split(num)
800     if (val[0] == 'cyl'):
801     # printf("cyl %5d of %5d | %3d%%\n",
802     val = int(val[5][:-1])
803     w and w.set(val)
804     # sync every 10%
805     if sync + 10 <= val:
806     isys.sync()
807     sync = val
808     num = ''
809     except OSError, args:
810     (errno, str) = args
811     if (errno != 4):
812     raise IOError, args
813    
814     try:
815     (pid, status) = os.waitpid(childpid, 0)
816     except OSError, (num, msg):
817     print __name__, "waitpid:", msg
818    
819     os.close(fd)
820    
821     w and w.pop()
822    
823     if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0):
824     return 0
825    
826     return 1
827    
828     def openDevices (self, intf = None, initAll = 0,
829     zeroMbr = 0, clearDevs = []):
830     """Open the disks on the system and skip unopenable devices."""
831     if self.disks:
832     return
833     for drive in self.driveList ():
834     if drive in DiskSet.skippedDisks and not initAll:
835     continue
836     deviceFile = isys.makeDevInode(drive)
837     if isys.driveIsRemovable(drive) and not flags.expert:
838     DiskSet.skippedDisks.append(drive)
839     continue
840     # FIXME: need the right fix for z/VM formatted dasd
841     if iutil.getArch() == "s390" and drive[:4] == "dasd" and isys.getDasdState(drive):
842     devs = isys.getDasdDevPort()
843     if intf is None:
844     DiskSet.skippedDisks.append(drive)
845     continue
846     rc = intf.messageWindow(_("Warning"),
847     _("The partition table on device %s (%s) was unreadable. "
848     "To create new partitions it must be initialized, "
849     "causing the loss of ALL DATA on this drive.\n\n"
850     "This operation will override any previous "
851     "installation choices about which drives to "
852     "ignore.\n\n"
853     "Would you like to initialize this drive, "
854     "erasing ALL DATA?")
855     % (drive, devs[drive]), type = "yesno")
856     if rc == 0:
857     DiskSet.skippedDisks.append(drive)
858     continue
859     else:
860     if (self.dasdFmt(intf, drive)):
861     DiskSet.skippedDisks.append(drive)
862     continue
863    
864     try:
865     dev = parted.PedDevice.get (deviceFile)
866     except parted.error, msg:
867     DiskSet.skippedDisks.append(drive)
868     continue
869    
870     if (initAll and ((clearDevs is None) or (len(clearDevs) == 0)
871     or drive in clearDevs) and not flags.test):
872     if iutil.getArch() == "s390" and drive[:4] == "dasd":
873     if (intf is None or self.dasdFmt(intf, drive)):
874     DiskSet.skippedDisks.append(drive)
875     continue
876     else:
877     try:
878     disk = dev.disk_new_fresh(getDefaultDiskType())
879     disk.commit()
880     self.disks[drive] = disk
881     except parted.error, msg:
882     DiskSet.skippedDisks.append(drive)
883     continue
884    
885     try:
886     disk = parted.PedDisk.new(dev)
887     self.disks[drive] = disk
888     except parted.error, msg:
889     recreate = 0
890     if zeroMbr:
891     log("zeroMBR was set and invalid partition table found "
892     "on %s" % (dev.path[5:]))
893     recreate = 1
894     elif not intf:
895     DiskSet.skippedDisks.append(drive)
896     continue
897     else:
898     if iutil.getArch() == "s390" and drive[:4] == "dasd":
899     devs = isys.getDasdDevPort()
900     format = drive + " (" + devs[drive] + ")"
901     else:
902     format = drive
903     rc = intf.messageWindow(_("Warning"),
904     _("The partition table on device %s was unreadable. "
905     "To create new partitions it must be initialized, "
906     "causing the loss of ALL DATA on this drive.\n\n"
907     "This operation will override any previous "
908     "installation choices about which drives to "
909     "ignore.\n\n"
910     "Would you like to initialize this drive, "
911     "erasing ALL DATA?")
912     % (format,), type = "yesno")
913     if rc == 0:
914     DiskSet.skippedDisks.append(drive)
915     continue
916     else:
917     recreate = 1
918    
919     if recreate == 1 and not flags.test:
920     if iutil.getArch() == "s390" and drive[:4] == "dasd":
921     if (intf is None or self.dasdFmt(intf, drive)):
922     DiskSet.skippedDisks.append(drive)
923     continue
924     else:
925     try:
926     disk = dev.disk_new_fresh(getDefaultDiskType())
927     disk.commit()
928     except parted.error, msg:
929     DiskSet.skippedDisks.append(drive)
930     continue
931     try:
932     disk = parted.PedDisk.new(dev)
933     self.disks[drive] = disk
934     except parted.error, msg:
935     DiskSet.skippedDisks.append(drive)
936     continue
937    
938     filter_partitions(disk, validateFsType)
939    
940     # check that their partition table is valid for their architecture
941     ret = checkDiskLabel(disk, intf)
942     if ret == 1:
943     DiskSet.skippedDisks.append(drive)
944     continue
945     elif ret == -1:
946     if iutil.getArch() == "s390" and drive[:4] == "dasd":
947     if (intf is None or self.dasdFmt(intf, drive)):
948     DiskSet.skippedDisks.append(drive)
949     continue
950     else:
951     try:
952     disk = dev.disk_new_fresh(getDefaultDiskType())
953     disk.commit()
954     except parted.error, msg:
955     DiskSet.skippedDisks.append(drive)
956     continue
957     try:
958     disk = parted.PedDisk.new(dev)
959     self.disks[drive] = disk
960     except parted.error, msg:
961     DiskSet.skippedDisks.append(drive)
962     continue
963    
964     def partitionTypes (self):
965     """Return list of (partition, partition type) tuples for all parts."""
966     rc = []
967     drives = self.disks.keys()
968     drives.sort()
969    
970     for drive in drives:
971     disk = self.disks[drive]
972     part = disk.next_partition ()
973     while part:
974     if part.type in (parted.PARTITION_PRIMARY,
975     parted.PARTITION_LOGICAL):
976     device = get_partition_name(part)
977     if part.fs_type:
978     ptype = part.fs_type.name
979     else:
980     ptype = None
981     rc.append((device, ptype))
982     part = disk.next_partition (part)
983    
984     return rc
985    
986     def diskState (self):
987     """Print out current disk state. DEBUG."""
988     rc = ""
989     for disk in self.disks.values():
990     rc = rc + ("%s: %s length %ld, maximum "
991     "primary partitions: %d\n" %
992     (disk.dev.path,
993     disk.dev.model,
994     disk.dev.length,
995     disk.max_primary_partition_count))
996    
997     part = disk.next_partition()
998     if part:
999     rc = rc + ("Device Type Filesystem Start "
1000     "End Length Flags\n")
1001     rc = rc + ("------ ---- ---------- ----- "
1002     "--- ------ -----\n")
1003     while part:
1004     if not part.type & parted.PARTITION_METADATA:
1005     device = ""
1006     fs_type_name = ""
1007     if part.num > 0:
1008     device = get_partition_name(part)
1009     if part.fs_type:
1010     fs_type_name = part.fs_type.name
1011     partFlags = get_flags (part)
1012     rc = rc + ("%-9s %-12s %-12s %-10ld %-10ld %-10ld %7s\n"
1013     % (device, part.type_name, fs_type_name,
1014     part.geom.start, part.geom.end, part.geom.length,
1015     partFlags))
1016     part = disk.next_partition(part)
1017     return rc
1018    
1019     def checkNoDisks(self, intf):
1020     """Check that there are valid disk devices."""
1021     if len(self.disks.keys()) == 0:
1022     intf.messageWindow(_("No Drives Found"),
1023     _("An error has occurred - no valid devices were "
1024     "found on which to create new file systems. "
1025     "Please check your hardware for the cause "
1026     "of this problem."))
1027     sys.exit(0)
1028    
1029    
1030    
1031    
1032    
1033     # XXX is this all of the possibilities?
1034     dosPartitionTypes = [ 1, 6, 7, 11, 12, 14, 15 ]
1035    
1036     # master list of partition types
1037     allPartitionTypesDict = {
1038     0 : "Empty",
1039     1: "DOS 12-bit FAT",
1040     2: "XENIX root",
1041     3: "XENIX usr",
1042     4: "DOS 16-bit <32M",
1043     5: "Extended",
1044     6: "DOS 16-bit >=32M",
1045     7: "NTFS/HPFS",
1046     8: "AIX",
1047     9: "AIX bootable",
1048     10: "OS/2 Boot Manager",
1049     0xb: "Win95 FAT32",
1050     0xc: "Win95 FAT32",
1051     0xe: "Win95 FAT16",
1052     0xf: "Win95 Ext'd",
1053     0x10: "OPUS",
1054     0x11: "Hidden FAT12",
1055     0x12: "Compaq Setup",
1056     0x14: "Hidden FAT16 <32M",
1057     0x16: "Hidden FAT16",
1058     0x17: "Hidden HPFS/NTFS",
1059     0x18: "AST SmartSleep",
1060     0x1b: "Hidden Win95 FAT32",
1061     0x1c: "Hidden Win95 FAT32 (LBA)",
1062     0x1e: "Hidden Win95 FAT16 (LBA)",
1063     0x24: "NEC_DOS",
1064     0x39: "Plan 9",
1065     0x40: "Venix 80286",
1066     0x41: "PPC_PReP Boot",
1067     0x42: "SFS",
1068     0x4d: "QNX4.x",
1069     0x4e: "QNX4.x 2nd part",
1070     0x4f: "QNX4.x 2nd part",
1071     0x51: "Novell?",
1072     0x52: "Microport",
1073     0x63: "GNU HURD",
1074     0x64: "Novell Netware 286",
1075     0x65: "Novell Netware 386",
1076     0x75: "PC/IX",
1077     0x80: "Old MINIX",
1078     0x81: "Linux/MINIX",
1079     0x82: "Linux swap",
1080     0x83: "Linux native",
1081     0x84: "OS/2 hidden C:",
1082     0x85: "Linux Extended",
1083     0x86: "NTFS volume set",
1084     0x87: "NTFS volume set",
1085     0x8e: "Linux LVM",
1086     0x93: "Amoeba",
1087     0x94: "Amoeba BBT",
1088     0x9f: "BSD/OS",
1089     0xa0: "IBM Thinkpad hibernation",
1090     0xa5: "BSD/386",
1091     0xa6: "OpenBSD",
1092     0xb7: "BSDI fs",
1093     0xb8: "BSDI swap",
1094     0xc7: "Syrinx",
1095     0xdb: "CP/M",
1096     0xde: "Dell Utility",
1097     0xe1: "DOS access",
1098     0xe3: "DOS R/O",
1099     0xeb: "BEOS",
1100     0xee: "EFI GPT",
1101     0xef: "EFI (FAT-12/16/32)",
1102     0xf2: "DOS secondary",
1103     0xfd: "Linux RAID",
1104     0xff: "BBT"
1105     }
1106    
1107     max_logical_partition_count = {
1108     "hd": 59,
1109     "sd": 11,
1110     "ataraid/": 11,
1111     "rd/": 3,
1112     "cciss/": 11,
1113     "i2o/": 11,
1114     "iseries/vd": 3,
1115     "ida/": 11,
1116     "sx8/": 11,
1117     }

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed