/[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.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Sat Jul 2 06:33:16 2005 UTC (19 years, 3 months ago) by gordonr
Branch: V7_0_alpha23
CVS Tags: SMEServer
Changes since 1.1: +0 -0 lines
Content type: text/x-python
Error occurred while calculating annotation data.
Initial import of cdrom.image directory

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