/[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.1 - (hide annotations) (download) (as text)
Sat Jul 2 06:33:16 2005 UTC (19 years, 5 months ago) by gordonr
Branch: MAIN
Branch point for: V7_0_alpha23
Content type: text/x-python
Initial revision

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     "SME Server": ("Mitel Networks server", "Mitel Networks SME Server", "SME Server"),
504     "CentOS-3": ("Mitel Networks server", "Mitel Networks SME Server", "SME Server"),
505     "Red Hat Enterprise Linux AS": ("Red Hat Linux Advanced Server", ),
506     "Red Hat Enterprise Linux WS": ("Red Hat Linux Advanced Workstation",),
507     # FIXME: this probably shouldn't be in a release...
508     "Red Hat Enterprise Linux": ("Red Hat Linux Advanced Server",
509     "Red Hat Linux Advanced Workstation",
510     "Red Hat Enterprise Linux AS",
511     "Red Hat Enterprise Linux ES",
512     "Red Hat Enterprise Linux WS"),
513     "Fedora Core": ("Red Hat Linux",)
514     }
515    
516     if productUpgrades.has_key(newproduct):
517     acceptable = productUpgrades[newproduct]
518     else:
519     acceptable = ()
520    
521     for p in acceptable:
522     if oldproduct.startswith(p):
523     return 1
524    
525     return 0
526    
527     class DiskSet:
528     """The disks in the system."""
529    
530     skippedDisks = []
531     mdList = []
532     def __init__ (self):
533     self.disks = {}
534     self.onlyPrimary = None
535    
536     def onlyPrimaryParts(self):
537     for disk in self.disks.values():
538     if disk.type.check_feature(parted.DISK_TYPE_EXTENDED):
539     return 0
540    
541     return 1
542    
543    
544     def startAllRaid(self):
545     """Start all of the raid devices associated with the DiskSet."""
546     driveList = []
547     origDriveList = self.driveList()
548     for drive in origDriveList:
549     if not drive in DiskSet.skippedDisks:
550     driveList.append(drive)
551     DiskSet.mdList.extend(raid.startAllRaid(driveList))
552    
553     def stopAllRaid(self):
554     """Stop all of the raid devices associated with the DiskSet."""
555     raid.stopAllRaid(DiskSet.mdList)
556     while DiskSet.mdList:
557     DiskSet.mdList.pop()
558    
559     def getLabels(self):
560     """Return a list of all of the labels used on partitions."""
561     labels = {}
562    
563     drives = self.disks.keys()
564     drives.sort()
565    
566     for drive in drives:
567     disk = self.disks[drive]
568     func = lambda part: (part.is_active() and
569     not (part.get_flag(parted.PARTITION_RAID)
570     or part.get_flag(parted.PARTITION_LVM))
571     and part.fs_type
572     and (part.fs_type.name in ("ext2",
573     "ext3", "xfs")))
574     parts = filter_partitions(disk, func)
575     for part in parts:
576     node = get_partition_name(part)
577     label = isys.readFSLabel(node)
578     if label:
579     labels[node] = label
580    
581     for dev, devices, level, numActive in DiskSet.mdList:
582     label = isys.readFSLabel(dev)
583     if label:
584     labels[dev] = label
585    
586     return labels
587    
588     def findExistingRootPartitions(self, intf, mountpoint, upgradeany = 0):
589     """Return a list of all of the partitions which look like a root fs."""
590     rootparts = []
591    
592     self.startAllRaid()
593    
594     for dev, devices, level, numActive in self.mdList:
595     (errno, msg) = (None, None)
596     found = 0
597     for fs in fsset.getFStoTry(dev):
598     try:
599     isys.mount(dev, mountpoint, fs, readOnly = 1)
600     found = 1
601     break
602     except SystemError, (errno, msg):
603     pass
604    
605     if found:
606     if os.access (mountpoint + '/etc/fstab', os.R_OK):
607     relstr = getCentOSReleaseString(mountpoint)
608     cmdline = open('/proc/cmdline', 'r').read()
609    
610     if ((cmdline.find("upgradeany") != -1) or
611     (upgradeany == 1) or
612     (productMatches(relstr, productName))):
613     rootparts.append ((dev, fs, relstr))
614     isys.umount(mountpoint)
615    
616     # now, look for candidate lvm roots
617     lvm.vgscan()
618     lvm.vgactivate()
619    
620     for (vg, lv, size) in lvm.lvlist():
621     dev = "/dev/%s/%s" %(vg, lv)
622     found = 0
623     for fs in fsset.getFStoTry(dev):
624     try:
625     isys.mount(dev, mountpoint, fs, readOnly = 1)
626     found = 1
627     break
628     except SystemError:
629     pass
630    
631     if found:
632     if os.access (mountpoint + '/etc/fstab', os.R_OK):
633     relstr = getCentOSReleaseString(mountpoint)
634     cmdline = open('/proc/cmdline', 'r').read()
635    
636     if ((cmdline.find("upgradeany") != -1) or
637     (upgradeany == 1) or
638     (productMatches(relstr, productName))):
639     rootparts.append ((dev, fs, relstr))
640     isys.umount(mountpoint)
641    
642     lvm.vgdeactivate()
643    
644     # don't stop raid until after we've looked for lvm on top of it
645     self.stopAllRaid()
646    
647     drives = self.disks.keys()
648     drives.sort()
649    
650     for drive in drives:
651     disk = self.disks[drive]
652     part = disk.next_partition ()
653     while part:
654     if (part.is_active()
655     and (part.get_flag(parted.PARTITION_RAID)
656     or part.get_flag(parted.PARTITION_LVM))):
657     pass
658     elif (part.fs_type and
659     part.fs_type.name in fsset.getUsableLinuxFs()):
660     node = get_partition_name(part)
661     try:
662     isys.mount(node, mountpoint, part.fs_type.name)
663     except SystemError, (errno, msg):
664     intf.messageWindow(_("Error"),
665     _("Error mounting file system on "
666     "%s: %s") % (node, msg))
667     part = disk.next_partition(part)
668     continue
669     if os.access (mountpoint + '/etc/fstab', os.R_OK):
670     relstr = getCentOSReleaseString(mountpoint)
671     cmdline = open('/proc/cmdline', 'r').read()
672    
673     if ((cmdline.find("upgradeany") != -1) or
674     (upgradeany == 1) or
675     (productMatches(relstr, productName))):
676     rootparts.append ((node, part.fs_type.name,
677     relstr))
678     isys.umount(mountpoint)
679    
680     part = disk.next_partition(part)
681     return rootparts
682    
683     def driveList (self):
684     """Return the list of drives on the system."""
685     drives = isys.hardDriveDict().keys()
686     drives.sort (isys.compareDrives)
687     return drives
688    
689     def drivesByName (self):
690     """Return a dictionary of the drives on the system."""
691     return isys.hardDriveDict()
692    
693     def addPartition (self, device, type, spec):
694     """Add a new partition to the device. - UNUSED."""
695     if not self.disks.has_key (device):
696     raise PartitioningError, ("unknown device passed to "
697     "addPartition: %s" % (device,))
698     disk = self.disks[device]
699    
700     part = disk.next_partition ()
701     status = 0
702     while part:
703     if (part.type == parted.PARTITION_FREESPACE
704     and part.geom.length >= spec.size):
705     newp = disk.partition_new (type, spec.fs_type,
706     part.geom.start,
707     part.geom.start + spec.size)
708     constraint = disk.dev.constraint_any ()
709     try:
710     disk.add_partition (newp, constraint)
711     status = 1
712     break
713     except parted.error, msg:
714     raise PartitioningError, msg
715     part = disk.next_partition (part)
716     if not status:
717     raise PartitioningError, ("Not enough free space on %s to create "
718     "new partition" % (device,))
719     return newp
720    
721     def deleteAllPartitions (self):
722     """Delete all partitions from all disks. - UNUSED."""
723     for disk in self.disks.values():
724     disk.delete_all ()
725    
726     def savePartitions (self):
727     """Write the partition tables out to the disks."""
728     for disk in self.disks.values():
729     disk.commit()
730     #disk.close()
731     del disk
732     self.refreshDevices()
733    
734     def refreshDevices (self, intf = None, initAll = 0,
735     zeroMbr = 0, clearDevs = []):
736     """Reread the state of the disks as they are on disk."""
737     self.closeDevices()
738     self.disks = {}
739     self.openDevices(intf, initAll, zeroMbr, clearDevs)
740    
741     def closeDevices (self):
742     """Close all of the disks which are open."""
743     for disk in self.disks.keys():
744     #self.disks[disk].close()
745     del self.disks[disk]
746    
747     def dasdFmt (self, intf = None, drive = None):
748     """Format dasd devices (s390)."""
749    
750     if self.disks.has_key(drive):
751     del self.disks[drive]
752    
753     w = intf.progressWindow (_("Initializing"),
754     _("Please wait while formatting drive %s...\n"
755     ) % (drive,), 100)
756     try:
757     isys.makeDevInode(drive, '/tmp/' + drive)
758     except:
759     pass
760    
761     argList = [ "/sbin/dasdfmt",
762     "-y",
763     "-b", "4096",
764     "-d", "cdl",
765     "-P",
766     "-F",
767     "-f",
768     "/tmp/%s" % drive]
769    
770     fd = os.open("/dev/null", os.O_RDWR | os.O_CREAT | os.O_APPEND)
771     p = os.pipe()
772     childpid = os.fork()
773     if not childpid:
774     os.close(p[0])
775     os.dup2(p[1], 1)
776     os.dup2(fd, 2)
777     os.close(p[1])
778     os.close(fd)
779     os.execv(argList[0], argList)
780     log("failed to exec %s", argList)
781     os._exit(1)
782    
783     os.close(p[1])
784    
785     num = ''
786     sync = 0
787     s = 'a'
788     while s:
789     try:
790     s = os.read(p[0], 1)
791     os.write(fd, s)
792    
793     if s != '\n':
794     try:
795     num = num + s
796     except:
797     pass
798     else:
799     if num:
800     val = string.split(num)
801     if (val[0] == 'cyl'):
802     # printf("cyl %5d of %5d | %3d%%\n",
803     val = int(val[5][:-1])
804     w and w.set(val)
805     # sync every 10%
806     if sync + 10 <= val:
807     isys.sync()
808     sync = val
809     num = ''
810     except OSError, args:
811     (errno, str) = args
812     if (errno != 4):
813     raise IOError, args
814    
815     try:
816     (pid, status) = os.waitpid(childpid, 0)
817     except OSError, (num, msg):
818     print __name__, "waitpid:", msg
819    
820     os.close(fd)
821    
822     w and w.pop()
823    
824     if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0):
825     return 0
826    
827     return 1
828    
829     def openDevices (self, intf = None, initAll = 0,
830     zeroMbr = 0, clearDevs = []):
831     """Open the disks on the system and skip unopenable devices."""
832     if self.disks:
833     return
834     for drive in self.driveList ():
835     if drive in DiskSet.skippedDisks and not initAll:
836     continue
837     deviceFile = isys.makeDevInode(drive)
838     if isys.driveIsRemovable(drive) and not flags.expert:
839     DiskSet.skippedDisks.append(drive)
840     continue
841     # FIXME: need the right fix for z/VM formatted dasd
842     if iutil.getArch() == "s390" and drive[:4] == "dasd" and isys.getDasdState(drive):
843     devs = isys.getDasdDevPort()
844     if intf is None:
845     DiskSet.skippedDisks.append(drive)
846     continue
847     rc = intf.messageWindow(_("Warning"),
848     _("The partition table on device %s (%s) was unreadable. "
849     "To create new partitions it must be initialized, "
850     "causing the loss of ALL DATA on this drive.\n\n"
851     "This operation will override any previous "
852     "installation choices about which drives to "
853     "ignore.\n\n"
854     "Would you like to initialize this drive, "
855     "erasing ALL DATA?")
856     % (drive, devs[drive]), type = "yesno")
857     if rc == 0:
858     DiskSet.skippedDisks.append(drive)
859     continue
860     else:
861     if (self.dasdFmt(intf, drive)):
862     DiskSet.skippedDisks.append(drive)
863     continue
864    
865     try:
866     dev = parted.PedDevice.get (deviceFile)
867     except parted.error, msg:
868     DiskSet.skippedDisks.append(drive)
869     continue
870    
871     if (initAll and ((clearDevs is None) or (len(clearDevs) == 0)
872     or drive in clearDevs) and not flags.test):
873     if iutil.getArch() == "s390" and drive[:4] == "dasd":
874     if (intf is None or self.dasdFmt(intf, drive)):
875     DiskSet.skippedDisks.append(drive)
876     continue
877     else:
878     try:
879     disk = dev.disk_new_fresh(getDefaultDiskType())
880     disk.commit()
881     self.disks[drive] = disk
882     except parted.error, msg:
883     DiskSet.skippedDisks.append(drive)
884     continue
885    
886     try:
887     disk = parted.PedDisk.new(dev)
888     self.disks[drive] = disk
889     except parted.error, msg:
890     recreate = 0
891     if zeroMbr:
892     log("zeroMBR was set and invalid partition table found "
893     "on %s" % (dev.path[5:]))
894     recreate = 1
895     elif not intf:
896     DiskSet.skippedDisks.append(drive)
897     continue
898     else:
899     if iutil.getArch() == "s390" and drive[:4] == "dasd":
900     devs = isys.getDasdDevPort()
901     format = drive + " (" + devs[drive] + ")"
902     else:
903     format = drive
904     rc = intf.messageWindow(_("Warning"),
905     _("The partition table on device %s was unreadable. "
906     "To create new partitions it must be initialized, "
907     "causing the loss of ALL DATA on this drive.\n\n"
908     "This operation will override any previous "
909     "installation choices about which drives to "
910     "ignore.\n\n"
911     "Would you like to initialize this drive, "
912     "erasing ALL DATA?")
913     % (format,), type = "yesno")
914     if rc == 0:
915     DiskSet.skippedDisks.append(drive)
916     continue
917     else:
918     recreate = 1
919    
920     if recreate == 1 and not flags.test:
921     if iutil.getArch() == "s390" and drive[:4] == "dasd":
922     if (intf is None or self.dasdFmt(intf, drive)):
923     DiskSet.skippedDisks.append(drive)
924     continue
925     else:
926     try:
927     disk = dev.disk_new_fresh(getDefaultDiskType())
928     disk.commit()
929     except parted.error, msg:
930     DiskSet.skippedDisks.append(drive)
931     continue
932     try:
933     disk = parted.PedDisk.new(dev)
934     self.disks[drive] = disk
935     except parted.error, msg:
936     DiskSet.skippedDisks.append(drive)
937     continue
938    
939     filter_partitions(disk, validateFsType)
940    
941     # check that their partition table is valid for their architecture
942     ret = checkDiskLabel(disk, intf)
943     if ret == 1:
944     DiskSet.skippedDisks.append(drive)
945     continue
946     elif ret == -1:
947     if iutil.getArch() == "s390" and drive[:4] == "dasd":
948     if (intf is None or self.dasdFmt(intf, drive)):
949     DiskSet.skippedDisks.append(drive)
950     continue
951     else:
952     try:
953     disk = dev.disk_new_fresh(getDefaultDiskType())
954     disk.commit()
955     except parted.error, msg:
956     DiskSet.skippedDisks.append(drive)
957     continue
958     try:
959     disk = parted.PedDisk.new(dev)
960     self.disks[drive] = disk
961     except parted.error, msg:
962     DiskSet.skippedDisks.append(drive)
963     continue
964    
965     def partitionTypes (self):
966     """Return list of (partition, partition type) tuples for all parts."""
967     rc = []
968     drives = self.disks.keys()
969     drives.sort()
970    
971     for drive in drives:
972     disk = self.disks[drive]
973     part = disk.next_partition ()
974     while part:
975     if part.type in (parted.PARTITION_PRIMARY,
976     parted.PARTITION_LOGICAL):
977     device = get_partition_name(part)
978     if part.fs_type:
979     ptype = part.fs_type.name
980     else:
981     ptype = None
982     rc.append((device, ptype))
983     part = disk.next_partition (part)
984    
985     return rc
986    
987     def diskState (self):
988     """Print out current disk state. DEBUG."""
989     rc = ""
990     for disk in self.disks.values():
991     rc = rc + ("%s: %s length %ld, maximum "
992     "primary partitions: %d\n" %
993     (disk.dev.path,
994     disk.dev.model,
995     disk.dev.length,
996     disk.max_primary_partition_count))
997    
998     part = disk.next_partition()
999     if part:
1000     rc = rc + ("Device Type Filesystem Start "
1001     "End Length Flags\n")
1002     rc = rc + ("------ ---- ---------- ----- "
1003     "--- ------ -----\n")
1004     while part:
1005     if not part.type & parted.PARTITION_METADATA:
1006     device = ""
1007     fs_type_name = ""
1008     if part.num > 0:
1009     device = get_partition_name(part)
1010     if part.fs_type:
1011     fs_type_name = part.fs_type.name
1012     partFlags = get_flags (part)
1013     rc = rc + ("%-9s %-12s %-12s %-10ld %-10ld %-10ld %7s\n"
1014     % (device, part.type_name, fs_type_name,
1015     part.geom.start, part.geom.end, part.geom.length,
1016     partFlags))
1017     part = disk.next_partition(part)
1018     return rc
1019    
1020     def checkNoDisks(self, intf):
1021     """Check that there are valid disk devices."""
1022     if len(self.disks.keys()) == 0:
1023     intf.messageWindow(_("No Drives Found"),
1024     _("An error has occurred - no valid devices were "
1025     "found on which to create new file systems. "
1026     "Please check your hardware for the cause "
1027     "of this problem."))
1028     sys.exit(0)
1029    
1030    
1031    
1032    
1033    
1034     # XXX is this all of the possibilities?
1035     dosPartitionTypes = [ 1, 6, 7, 11, 12, 14, 15 ]
1036    
1037     # master list of partition types
1038     allPartitionTypesDict = {
1039     0 : "Empty",
1040     1: "DOS 12-bit FAT",
1041     2: "XENIX root",
1042     3: "XENIX usr",
1043     4: "DOS 16-bit <32M",
1044     5: "Extended",
1045     6: "DOS 16-bit >=32M",
1046     7: "NTFS/HPFS",
1047     8: "AIX",
1048     9: "AIX bootable",
1049     10: "OS/2 Boot Manager",
1050     0xb: "Win95 FAT32",
1051     0xc: "Win95 FAT32",
1052     0xe: "Win95 FAT16",
1053     0xf: "Win95 Ext'd",
1054     0x10: "OPUS",
1055     0x11: "Hidden FAT12",
1056     0x12: "Compaq Setup",
1057     0x14: "Hidden FAT16 <32M",
1058     0x16: "Hidden FAT16",
1059     0x17: "Hidden HPFS/NTFS",
1060     0x18: "AST SmartSleep",
1061     0x1b: "Hidden Win95 FAT32",
1062     0x1c: "Hidden Win95 FAT32 (LBA)",
1063     0x1e: "Hidden Win95 FAT16 (LBA)",
1064     0x24: "NEC_DOS",
1065     0x39: "Plan 9",
1066     0x40: "Venix 80286",
1067     0x41: "PPC_PReP Boot",
1068     0x42: "SFS",
1069     0x4d: "QNX4.x",
1070     0x4e: "QNX4.x 2nd part",
1071     0x4f: "QNX4.x 2nd part",
1072     0x51: "Novell?",
1073     0x52: "Microport",
1074     0x63: "GNU HURD",
1075     0x64: "Novell Netware 286",
1076     0x65: "Novell Netware 386",
1077     0x75: "PC/IX",
1078     0x80: "Old MINIX",
1079     0x81: "Linux/MINIX",
1080     0x82: "Linux swap",
1081     0x83: "Linux native",
1082     0x84: "OS/2 hidden C:",
1083     0x85: "Linux Extended",
1084     0x86: "NTFS volume set",
1085     0x87: "NTFS volume set",
1086     0x8e: "Linux LVM",
1087     0x93: "Amoeba",
1088     0x94: "Amoeba BBT",
1089     0x9f: "BSD/OS",
1090     0xa0: "IBM Thinkpad hibernation",
1091     0xa5: "BSD/386",
1092     0xa6: "OpenBSD",
1093     0xb7: "BSDI fs",
1094     0xb8: "BSDI swap",
1095     0xc7: "Syrinx",
1096     0xdb: "CP/M",
1097     0xde: "Dell Utility",
1098     0xe1: "DOS access",
1099     0xe3: "DOS R/O",
1100     0xeb: "BEOS",
1101     0xee: "EFI GPT",
1102     0xef: "EFI (FAT-12/16/32)",
1103     0xf2: "DOS secondary",
1104     0xfd: "Linux RAID",
1105     0xff: "BBT"
1106     }
1107    
1108     max_logical_partition_count = {
1109     "hd": 59,
1110     "sd": 11,
1111     "ataraid/": 11,
1112     "rd/": 3,
1113     "cciss/": 11,
1114     "i2o/": 11,
1115     "iseries/vd": 3,
1116     "ida/": 11,
1117     "sx8/": 11,
1118     }

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