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

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

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


Revision 1.6 - (show annotations) (download) (as text)
Fri Jun 9 05:03:00 2006 UTC (17 years, 11 months ago) by gordonr
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +0 -0 lines
Content type: text/x-python
FILE REMOVED
See bug 1510 - all changes should be in the anaconda CVS repository

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

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