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

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

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


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

1 #
2 # fstab.py: filesystem management
3 #
4 # Matt Wilson <msw@redhat.com>
5 #
6 # Copyright 2001-2002 Red Hat, Inc.
7 #
8 # This software may be freely redistributed under the terms of the GNU
9 # library public license.
10 #
11 # You should have received a copy of the GNU Library Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
14 #
15
16 import string
17 import isys
18 import iutil
19 import os
20 import posix
21 import errno
22 import parted
23 import sys
24 import struct
25 import partitioning
26 import partedUtils
27 import raid
28 import lvm
29 import types
30
31 from rhpl.log import log
32 from rhpl.translate import _, N_
33
34 class BadBlocksError(Exception):
35 pass
36
37 defaultMountPoints = ['/', '/home', '/tmp', '/usr', '/var', '/usr/local', '/opt']
38
39 if iutil.getArch() == "s390":
40 # Many s390 have 2G DASDs, we recomment putting /usr/share on its own DASD
41 defaultMountPoints.insert(4, '/usr/share')
42
43 if iutil.getArch() == "ia64":
44 defaultMountPoints.insert(1, '/boot/efi')
45 else:
46 defaultMountPoints.insert(1, '/boot')
47
48 fileSystemTypes = {}
49
50 # XXX define availraidlevels and defaultmntpts as arch characteristics
51 availRaidLevels = raid.getRaidLevels()
52
53 def fileSystemTypeGetDefault():
54 if fileSystemTypeGet('ext3').isSupported():
55 return fileSystemTypeGet('ext3')
56 elif fileSystemTypeGet('ext2').isSupported():
57 return fileSystemTypeGet('ext2')
58 else:
59 raise ValueError, "You have neither ext3 or ext2 support in your kernel!"
60
61
62 def fileSystemTypeGet(key):
63 return fileSystemTypes[key]
64
65 def fileSystemTypeRegister(klass):
66 fileSystemTypes[klass.getName()] = klass
67
68 def fileSystemTypeGetTypes():
69 return fileSystemTypes.copy()
70
71 def getUsableLinuxFs():
72 rc = []
73 for fsType in fileSystemTypes.keys():
74 if fileSystemTypes[fsType].isMountable() and \
75 fileSystemTypes[fsType].isLinuxNativeFS():
76 rc.append(fsType)
77
78 # make sure the default is first in the list, kind of ugly
79 default = fileSystemTypeGetDefault()
80 defaultName = default.getName()
81 if defaultName in rc:
82 del rc[rc.index(defaultName)]
83 rc.insert(0, defaultName)
84 return rc
85
86 def mountCompare(a, b):
87 one = a.mountpoint
88 two = b.mountpoint
89 if one < two:
90 return -1
91 elif two > one:
92 return 1
93 return 0
94
95 def devify(device):
96 if device != "none" and device[0] != '/':
97 return "/dev/" + device
98 return device
99
100 class LabelFactory:
101 def __init__(self):
102 self.labels = None
103
104 def createLabel(self, mountpoint, maxLabelChars):
105 if self.labels == None:
106
107 self.labels = {}
108 diskset = partedUtils.DiskSet()
109 diskset.openDevices()
110 diskset.stopAllRaid()
111 diskset.startAllRaid()
112 labels = diskset.getLabels()
113 del diskset
114 self.reserveLabels(labels)
115
116 if len(mountpoint) > maxLabelChars:
117 mountpoint = mountpoint[0:maxLabelChars]
118 count = 0
119 while self.labels.has_key(mountpoint):
120 count = count + 1
121 s = "%s" % count
122 if (len(mountpoint) + len(s)) <= maxLabelChars:
123 mountpoint = mountpoint + s
124 else:
125 strip = len(mountpoint) + len(s) - maxLabelChars
126 mountpoint = mountpoint[0:len(mountpoint) - strip] + s
127 self.labels[mountpoint] = 1
128
129 return mountpoint
130
131 def reserveLabels(self, labels):
132 if self.labels == None:
133 self.labels = {}
134 for device, label in labels.items():
135 self.labels[label] = 1
136
137 labelFactory = LabelFactory()
138
139 class FileSystemType:
140 kernelFilesystems = {}
141 def __init__(self):
142 self.deviceArguments = {}
143 self.formattable = 0
144 self.checked = 0
145 self.name = ""
146 self.linuxnativefs = 0
147 self.partedFileSystemType = None
148 self.partedPartitionFlags = []
149 self.maxSizeMB = 8 * 1024 * 1024
150 self.supported = -1
151 self.defaultOptions = "defaults"
152 self.migratetofs = None
153 self.extraFormatArgs = []
154 self.maxLabelChars = 16
155 self.packages = []
156
157 def mount(self, device, mountpoint, readOnly=0, bindMount=0):
158 if not self.isMountable():
159 return
160 iutil.mkdirChain(mountpoint)
161 isys.mount(device, mountpoint, fstype = self.getName(),
162 readOnly = readOnly, bindMount = bindMount)
163
164 def umount(self, device, path):
165 isys.umount(path, removeDir = 0)
166
167 def getName(self):
168 return self.name
169
170 def getNeededPackages(self):
171 return self.packages
172
173 def registerDeviceArgumentFunction(self, klass, function):
174 self.deviceArguments[klass] = function
175
176 def badblocksDevice(self, entry, windowCreator, chroot='/'):
177 if windowCreator:
178 w = windowCreator(_("Checking for Bad Blocks"),
179 _("Checking for bad blocks on /dev/%s...")
180 % (entry.device.getDevice(),), 100)
181 else:
182 w = None
183
184 devicePath = entry.device.setupDevice(chroot)
185 args = [ "/usr/sbin/badblocks", "-vv", devicePath ]
186
187 # entirely too much cutting and pasting from ext2FormatFileSystem
188 fd = os.open("/dev/tty5", os.O_RDWR | os.O_CREAT | os.O_APPEND)
189 p = os.pipe()
190 childpid = os.fork()
191 if not childpid:
192 os.close(p[0])
193 os.dup2(p[1], 1)
194 os.dup2(p[1], 2)
195 os.close(p[1])
196 os.close(fd)
197 os.execv(args[0], args)
198 log("failed to exec %s", args)
199 os._exit(1)
200
201 os.close(p[1])
202
203 s = 'a'
204 while s and s != ':':
205 try:
206 s = os.read(p[0], 1)
207 except OSError, args:
208 (num, str) = args
209 if (num != 4):
210 raise IOError, args
211
212 os.write(fd, s)
213
214 num = ''
215 numbad = 0
216 while s:
217 try:
218 s = os.read(p[0], 1)
219 os.write(fd, s)
220
221 if s not in ['\b', '\n']:
222 try:
223 num = num + s
224 except:
225 pass
226 else:
227 if s == '\b':
228 if num:
229 l = string.split(num, '/')
230 val = (long(l[0]) * 100) / long(l[1])
231 w and w.set(val)
232 else:
233 try:
234 blocknum = long(num)
235 numbad = numbad + 1
236 except:
237 pass
238
239 if numbad > 0:
240 raise BadBlocksError
241
242 num = ''
243 except OSError, args:
244 (num, str) = args
245 if (num != 4):
246 raise IOError, args
247
248 try:
249 (pid, status) = os.waitpid(childpid, 0)
250 except OSError, (num, msg):
251 log("exception from waitpid in badblocks: %s %s" % (num, msg))
252 status = None
253 os.close(fd)
254
255 w and w.pop()
256
257 if numbad > 0:
258 raise BadBlocksError
259
260 # have no clue how this would happen, but hope we're okay
261 if status is None:
262 return
263
264 if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0):
265 return
266
267 raise SystemError
268
269 def formatDevice(self, entry, progress, chroot='/'):
270 if self.isFormattable():
271 raise RuntimeError, "formatDevice method not defined"
272
273 def migrateFileSystem(self, device, message, chroot='/'):
274 if self.isMigratable():
275 raise RuntimeError, "migrateFileSystem method not defined"
276
277 def labelDevice(self, entry, chroot):
278 pass
279
280 def isFormattable(self):
281 return self.formattable
282
283 def isLinuxNativeFS(self):
284 return self.linuxnativefs
285
286 def readProcFilesystems(self):
287 f = open("/proc/filesystems", 'r')
288 if not f:
289 pass
290 lines = f.readlines()
291 for line in lines:
292 fields = string.split(line)
293 if fields[0] == "nodev":
294 fsystem = fields[1]
295 else:
296 fsystem = fields[0]
297 FileSystemType.kernelFilesystems[fsystem] = None
298
299 def isMountable(self):
300 if not FileSystemType.kernelFilesystems:
301 self.readProcFilesystems()
302
303 return FileSystemType.kernelFilesystems.has_key(self.getName())
304
305 def isSupported(self):
306 if self.supported == -1:
307 return self.isMountable()
308 return self.supported
309
310 def isChecked(self):
311 return self.checked
312
313 def getDeviceArgs(self, device):
314 deviceArgsFunction = self.deviceArguments.get(device.__class__)
315 if not deviceArgsFunction:
316 return []
317 return deviceArgsFunction(device)
318
319 def getPartedFileSystemType(self):
320 return self.partedFileSystemType
321
322 def getPartedPartitionFlags(self):
323 return self.partedPartitionFlags
324
325 # note that this returns the maximum size of a filesystem in megabytes
326 def getMaxSizeMB(self):
327 return self.maxSizeMB
328
329 def getDefaultOptions(self, mountpoint):
330 return self.defaultOptions
331
332 def getMigratableFSTargets(self):
333 retval = []
334 if not self.migratetofs:
335 return retval
336
337 for fs in self.migratetofs:
338 if fileSystemTypeGet(fs).isSupported():
339 retval.append(fs)
340
341 return retval
342
343 def isMigratable(self):
344 if len(self.getMigratableFSTargets()) > 0:
345 return 1
346 else:
347 return 0
348
349
350 class reiserfsFileSystem(FileSystemType):
351 def __init__(self):
352 FileSystemType.__init__(self)
353 self.partedFileSystemType = parted.file_system_type_get("reiserfs")
354 self.formattable = 1
355 self.checked = 1
356 self.linuxnativefs = 1
357 # this is totally, 100% unsupported. Boot with "linux reiserfs"
358 # at the boot: prompt will let you make new reiserfs filesystems
359 # in the installer. Bugs filed when you use this will be closed
360 # WONTFIX.
361 try:
362 f = open("/proc/cmdline")
363 line = f.readline()
364 if string.find(line, " reiserfs") != -1:
365 self.supported = -1
366 else:
367 self.supported = 0
368 del f
369 except:
370 self.supported = 0
371 self.name = "reiserfs"
372 self.packages = [ "reiserfs-utils" ]
373
374 self.maxSizeMB = 8 * 1024 * 1024
375
376
377 def formatDevice(self, entry, progress, chroot='/'):
378 devicePath = entry.device.setupDevice(chroot)
379
380 p = os.pipe()
381 os.write(p[1], "y\n")
382 os.close(p[1])
383
384 rc = iutil.execWithRedirect("/usr/sbin/mkreiserfs",
385 ["mkreiserfs", devicePath ],
386 stdin = p[0],
387 stdout = "/dev/tty5",
388 stderr = "/dev/tty5")
389
390 if rc:
391 raise SystemError
392
393 fileSystemTypeRegister(reiserfsFileSystem())
394
395 class xfsFileSystem(FileSystemType):
396 def __init__(self):
397 FileSystemType.__init__(self)
398 self.partedFileSystemType = parted.file_system_type_get("xfs")
399 self.formattable = 1
400 self.checked = 1
401 self.linuxnativefs = 1
402 self.name = "xfs"
403 self.maxSizeMB = 16 * 1024 * 1024
404 self.maxLabelChars = 12
405 # this is totally, 100% unsupported. Boot with "linux xfs"
406 # at the boot: prompt will let you make new xfs filesystems
407 # in the installer. Bugs filed when you use this will be closed
408 # WONTFIX.
409 try:
410 f = open("/proc/cmdline")
411 line = f.readline()
412 if string.find(line, " xfs") != -1:
413 self.supported = -1
414 else:
415 self.supported = 0
416 del f
417 except:
418 self.supported = 0
419
420 self.packages = [ "xfsprogs" ]
421
422 def formatDevice(self, entry, progress, chroot='/'):
423 devicePath = entry.device.setupDevice(chroot)
424
425 rc = iutil.execWithRedirect("/usr/sbin/mkfs.xfs",
426 ["mkfs.xfs", "-f", "-l", "internal",
427 devicePath ],
428 stdout = "/dev/tty5",
429 stderr = "/dev/tty5")
430
431 if rc:
432 raise SystemError
433
434 def labelDevice(self, entry, chroot):
435 devicePath = entry.device.setupDevice(chroot)
436 label = labelFactory.createLabel(entry.mountpoint, self.maxLabelChars)
437 db_cmd = "label " + label
438 rc = iutil.execWithRedirect("/usr/sbin/xfs_db",
439 ["xfs_db", "-x", "-c", db_cmd,
440 devicePath],
441 stdout = "/dev/tty5",
442 stderr = "/dev/tty5")
443 if rc:
444 raise SystemError
445 entry.setLabel(label)
446
447 fileSystemTypeRegister(xfsFileSystem())
448
449 class jfsFileSystem(FileSystemType):
450 def __init__(self):
451 FileSystemType.__init__(self)
452 self.partedFileSystemType = parted.file_system_type_get("jfs")
453 self.formattable = 1
454 self.checked = 1
455 self.linuxnativefs = 1
456 self.maxLabelChars = 16
457 # this is totally, 100% unsupported. Boot with "linux jfs"
458 # at the boot: prompt will let you make new reiserfs filesystems
459 # in the installer. Bugs filed when you use this will be closed
460 # WONTFIX.
461 try:
462 f = open("/proc/cmdline")
463 line = f.readline()
464 if string.find(line, " jfs") != -1:
465 self.supported = -1
466 else:
467 self.supported = 0
468 del f
469 except:
470 self.supported = 0
471
472 if not os.access("/usr/sbin/mkfs.jfs", os.X_OK):
473 self.supported = 0
474
475 self.name = "jfs"
476 self.packages = [ "jfsutils" ]
477
478 self.maxSizeMB = 8 * 1024 * 1024
479
480 def labelDevice(self, entry, chroot):
481 devicePath = entry.device.setupDevice(chroot)
482 label = labelFactory.createLabel(entry.mountpoint, self.maxLabelChars)
483 rc = iutil.execWithRedirect("/usr/sbin/jfs_tune",
484 ["jfs_tune", "-L", label, devicePath],
485 stdout = "/dev/tty5",
486 stderr = "/dev/tty5")
487 if rc:
488 raise SystemError
489 entry.setLabel(label)
490
491 def formatDevice(self, entry, progress, chroot='/'):
492 devicePath = entry.device.setupDevice(chroot)
493
494 rc = iutil.execWithRedirect("/usr/sbin/mkfs.jfs",
495 ["mkfs.jfs", "-q",
496 devicePath ],
497 stdout = "/dev/tty5",
498 stderr = "/dev/tty5")
499
500 if rc:
501 raise SystemError
502
503 fileSystemTypeRegister(jfsFileSystem())
504
505 class extFileSystem(FileSystemType):
506 def __init__(self):
507 FileSystemType.__init__(self)
508 self.partedFileSystemType = None
509 self.formattable = 1
510 self.checked = 1
511 self.linuxnativefs = 1
512 self.maxSizeMB = 8 * 1024 * 1024
513 self.packages = [ "e2fsprogs" ]
514
515 def labelDevice(self, entry, chroot):
516 devicePath = entry.device.setupDevice(chroot)
517 label = labelFactory.createLabel(entry.mountpoint, self.maxLabelChars)
518 rc = iutil.execWithRedirect("/usr/sbin/e2label",
519 ["e2label", devicePath, label],
520 stdout = "/dev/tty5",
521 stderr = "/dev/tty5")
522 if rc:
523 raise SystemError
524 entry.setLabel(label)
525
526 def formatDevice(self, entry, progress, chroot='/'):
527 devicePath = entry.device.setupDevice(chroot)
528 devArgs = self.getDeviceArgs(entry.device)
529 args = [ "/usr/sbin/mke2fs", devicePath]
530
531 args.extend(devArgs)
532 args.extend(self.extraFormatArgs)
533
534 rc = ext2FormatFilesystem(args, "/dev/tty5",
535 progress,
536 entry.mountpoint)
537 if rc:
538 raise SystemError
539
540 # this is only for ext3 filesystems, but migration is a method
541 # of the ext2 fstype, so it needs to be here. FIXME should be moved
542 def setExt3Options(self, entry, message, chroot='/'):
543 devicePath = entry.device.setupDevice(chroot)
544
545 # if no journal, don't turn off the fsck
546 if not isys.ext2HasJournal(devicePath, makeDevNode = 0):
547 return
548
549 rc = iutil.execWithRedirect("/usr/sbin/tune2fs",
550 ["tunefs", "-c0", "-i0", "-Odir_index",
551 devicePath],
552 stdout = "/dev/tty5",
553 stderr = "/dev/tty5")
554
555 class ext2FileSystem(extFileSystem):
556 def __init__(self):
557 extFileSystem.__init__(self)
558 self.name = "ext2"
559 self.partedFileSystemType = parted.file_system_type_get("ext2")
560 self.migratetofs = ['ext3']
561
562 def migrateFileSystem(self, entry, message, chroot='/'):
563 devicePath = entry.device.setupDevice(chroot)
564
565 if not entry.fsystem or not entry.origfsystem:
566 raise RuntimeError, ("Trying to migrate fs w/o fsystem or "
567 "origfsystem set")
568 if entry.fsystem.getName() != "ext3":
569 raise RuntimeError, ("Trying to migrate ext2 to something other "
570 "than ext3")
571
572 # if journal already exists skip
573 if isys.ext2HasJournal(devicePath, makeDevNode = 0):
574 log("Skipping migration of %s, has a journal already.\n" % devicePath)
575 return
576
577 rc = iutil.execWithRedirect("/usr/sbin/tune2fs",
578 ["tune2fs", "-j", devicePath ],
579 stdout = "/dev/tty5",
580 stderr = "/dev/tty5")
581
582 if rc:
583 raise SystemError
584
585 # XXX this should never happen, but appears to have done
586 # so several times based on reports in bugzilla.
587 # At least we can avoid leaving them with a system which won't boot
588 if not isys.ext2HasJournal(devicePath, makeDevNode = 0):
589 log("Migration of %s attempted but no journal exists after "
590 "running tune2fs.\n" % (devicePath))
591 if message:
592 rc = message(_("Error"),
593 _("An error occurred migrating %s to ext3. It is "
594 "possible to continue without migrating this "
595 "file system if desired.\n\n"
596 "Would you like to continue without migrating %s?")
597 % (devicePath, devicePath), type = "yesno")
598 if rc == 0:
599 sys.exit(0)
600 entry.fsystem = entry.origfsystem
601 else:
602 extFileSystem.setExt3Options(self, entry, message, chroot)
603
604
605 fileSystemTypeRegister(ext2FileSystem())
606
607 class ext3FileSystem(extFileSystem):
608 def __init__(self):
609 extFileSystem.__init__(self)
610 self.name = "ext3"
611 self.extraFormatArgs = [ "-j" ]
612 self.partedFileSystemType = parted.file_system_type_get("ext3")
613
614 def formatDevice(self, entry, progress, chroot='/'):
615 extFileSystem.formatDevice(self, entry, progress, chroot)
616 extFileSystem.setExt3Options(self, entry, progress, chroot)
617
618 fileSystemTypeRegister(ext3FileSystem())
619
620 class raidMemberDummyFileSystem(FileSystemType):
621 def __init__(self):
622 FileSystemType.__init__(self)
623 self.partedFileSystemType = parted.file_system_type_get("ext2")
624 self.partedPartitionFlags = [ parted.PARTITION_RAID ]
625 self.formattable = 1
626 self.checked = 0
627 self.linuxnativefs = 1
628 self.name = "software RAID"
629 self.maxSizeMB = 8 * 1024 * 1024
630 self.supported = 1
631
632 if len(availRaidLevels) == 0:
633 self.supported = 0
634
635 self.packages = [ "mdadm" ]
636
637 def formatDevice(self, entry, progress, chroot='/'):
638 # mkraid did all we need to format this partition...
639 pass
640
641 fileSystemTypeRegister(raidMemberDummyFileSystem())
642
643 class lvmPhysicalVolumeDummyFileSystem(FileSystemType):
644 def __init__(self):
645 FileSystemType.__init__(self)
646 self.partedFileSystemType = parted.file_system_type_get("ext2")
647 self.partedPartitionFlags = [ parted.PARTITION_LVM ]
648 self.formattable = 1
649 self.checked = 0
650 self.linuxnativefs = 1
651 self.name = "physical volume (LVM)"
652 self.maxSizeMB = 8 * 1024 * 1024
653 self.supported = 1
654 self.packages = [ "lvm2" ]
655
656 def isMountable(self):
657 return 0
658
659 def formatDevice(self, entry, progress, chroot='/'):
660 # already done by the pvcreate during volume creation
661 pass
662
663 fileSystemTypeRegister(lvmPhysicalVolumeDummyFileSystem())
664
665 class lvmVolumeGroupDummyFileSystem(FileSystemType):
666 def __init__(self):
667 FileSystemType.__init__(self)
668 self.partedFileSystemType = parted.file_system_type_get("ext2")
669 self.formattable = 1
670 self.checked = 0
671 self.linuxnativefs = 0
672 self.name = "volume group (LVM)"
673 self.supported = 0
674 self.maxSizeMB = 8 * 1024 * 1024
675 self.packages = [ "lvm2" ]
676
677 def isMountable(self):
678 return 0
679
680 def formatDevice(self, entry, progress, chroot='/'):
681 # the vgcreate already did this
682 pass
683
684 fileSystemTypeRegister(lvmVolumeGroupDummyFileSystem())
685
686 class swapFileSystem(FileSystemType):
687 enabledSwaps = {}
688
689 def __init__(self):
690 FileSystemType.__init__(self)
691 self.partedFileSystemType = parted.file_system_type_get("linux-swap")
692 self.formattable = 1
693 self.name = "swap"
694 self.maxSizeMB = 8 * 1024 * 1024
695 self.linuxnativefs = 1
696 self.supported = 1
697
698
699 def mount(self, device, mountpoint, readOnly=0, bindMount=0):
700 pagesize = isys.getpagesize()
701 buf = None
702 if pagesize > 2048:
703 num = pagesize
704 else:
705 num = 2048
706 try:
707 fd = os.open(dev, os.O_RDONLY)
708 buf = os.read(fd, num)
709 os.close(fd)
710 except:
711 pass
712
713 # FIXME: we should ask if they want to reinitialize swaps that
714 # are of format 0 (#122101)
715 if buf is not None and len(buf) == pagesize:
716 if buf[pagesize - 10:] == "SWAP-SPACE":
717 log("SWAP is of format 0, skipping it")
718 return
719
720 isys.swapon (device)
721
722 def umount(self, device, path):
723 # unfortunately, turning off swap is bad.
724 raise RuntimeError, "unable to turn off swap"
725
726 def formatDevice(self, entry, progress, chroot='/'):
727 file = entry.device.setupDevice(chroot)
728 rc = iutil.execWithRedirect ("/usr/sbin/mkswap",
729 [ "mkswap", '-v1', file ],
730 stdout = "/dev/tty5",
731 stderr = "/dev/tty5",
732 searchPath = 1)
733 if rc:
734 raise SystemError
735
736 def labelDevice(self, entry, chroot):
737 file = entry.device.setupDevice(chroot)
738 devName = entry.device.getDevice()
739 # we'll keep the SWAP-* naming for all devs but Compaq SMART2
740 # nodes (#170500)
741 if devName[0:6] == "cciss/":
742 swapLabel = "SW-%s" % (devName)
743 else:
744 swapLabel = "SWAP-%s" % (devName)
745 label = labelFactory.createLabel("%s" %swapLabel, self.maxLabelChars)
746 rc = iutil.execWithRedirect ("/usr/sbin/mkswap",
747 [ "mkswap", '-v1', "-L", label, file ],
748 stdout = "/dev/tty5",
749 stderr = "/dev/tty5",
750 searchPath = 1)
751 if rc:
752 raise SystemError
753 entry.setLabel(label)
754
755 fileSystemTypeRegister(swapFileSystem())
756
757 class FATFileSystem(FileSystemType):
758 def __init__(self):
759 FileSystemType.__init__(self)
760 self.partedFileSystemType = parted.file_system_type_get("fat32")
761 self.formattable = 1
762 self.checked = 0
763 self.maxSizeMB = 1024 * 1024
764 self.name = "vfat"
765 self.packages = [ "dosfstools" ]
766
767 def formatDevice(self, entry, progress, chroot='/'):
768 devicePath = entry.device.setupDevice(chroot)
769 devArgs = self.getDeviceArgs(entry.device)
770 args = [ "mkdosfs", devicePath ]
771 args.extend(devArgs)
772
773 rc = iutil.execWithRedirect("/usr/sbin/mkdosfs", args,
774 stdout = "/dev/tty5",
775 stderr = "/dev/tty5")
776 if rc:
777 raise SystemError
778
779 fileSystemTypeRegister(FATFileSystem())
780
781 class NTFSFileSystem(FileSystemType):
782 def __init__(self):
783 FileSystemType.__init__(self)
784 self.partedFileSystemType = parted.file_system_type_get("ntfs")
785 self.formattable = 0
786 self.checked = 0
787 self.name = "ntfs"
788
789 fileSystemTypeRegister(NTFSFileSystem())
790
791 class hfsFileSystem(FileSystemType):
792 def __init__(self):
793 FileSystemType.__init__(self)
794 self.partedFileSystemType = parted.file_system_type_get("hfs")
795 self.formattable = 1
796 self.checked = 0
797 self.name = "hfs"
798 self.supported = 0
799
800 def isMountable(self):
801 return 0
802
803 def formatDevice(self, entry, progress, chroot='/'):
804 devicePath = entry.device.setupDevice(chroot)
805 devArgs = self.getDeviceArgs(entry.device)
806 args = [ "hformat", devicePath ]
807 args.extend(devArgs)
808
809 rc = iutil.execWithRedirect("/usr/bin/hformat", args,
810 stdout = "/dev/tty5",
811 stderr = "/dev/tty5")
812 if rc:
813 raise SystemError
814
815 fileSystemTypeRegister(hfsFileSystem())
816
817 class applebootstrapFileSystem(hfsFileSystem):
818 def __init__(self):
819 hfsFileSystem.__init__(self)
820 self.partedPartitionFlags = [ parted.PARTITION_BOOT ]
821 self.maxSizeMB = 1
822 self.name = "Apple Bootstrap"
823 if iutil.getPPCMacGen() == "NewWorld":
824 self.supported = 1
825 else:
826 self.supported = 0
827
828 fileSystemTypeRegister(applebootstrapFileSystem())
829
830 class prepbootFileSystem(FileSystemType):
831 def __init__(self):
832 FileSystemType.__init__(self)
833 self.partedFileSystemType = None
834 self.partedPartitionFlags = [ parted.PARTITION_BOOT ]
835 self.checked = 0
836 self.name = "PPC PReP Boot"
837 self.maxSizeMB = 10
838
839 if iutil.getPPCMachine() == "iSeries":
840 self.maxSizeMB = 64
841
842 # supported for use on the pseries
843 if (iutil.getPPCMachine() == "pSeries" or
844 iutil.getPPCMachine() == "iSeries"):
845 self.supported = 1
846 self.formattable = 1
847 else:
848 self.supported = 0
849 self.formattable = 0
850
851 def formatDevice(self, entry, progress, chroot='/'):
852 # copy and paste job from booty/bootloaderInfo.py...
853 def getDiskPart(dev):
854 cut = len(dev)
855 if (dev.startswith('rd/') or dev.startswith('ida/') or
856 dev.startswith('cciss/') or dev.startswith('i2o/')
857 or dev.startswith("sx8/")):
858 if dev[-2] == 'p':
859 cut = -1
860 elif dev[-3] == 'p':
861 cut = -2
862 else:
863 if dev[-2] in string.digits:
864 cut = -2
865 elif dev[-1] in string.digits:
866 cut = -1
867
868 name = dev[:cut]
869
870 # hack off the trailing 'p' from /dev/cciss/*, for example
871 if name[-1] == 'p':
872 for letter in name:
873 if letter not in string.letters and letter != "/":
874 name = name[:-1]
875 break
876
877 if cut < 0:
878 partNum = int(dev[cut:])
879 else:
880 partNum = None
881
882 return (name, partNum)
883
884 # FIXME: oh dear is this a hack beyond my wildest imagination.
885 # parted doesn't really know how to do these, so we're going to
886 # exec sfdisk and make it set the partition type. this is bloody
887 # ugly
888 devicePath = entry.device.setupDevice(chroot)
889 (disk, part) = getDiskPart(devicePath)
890 if disk is None or part is None:
891 log("oops, somehow got a bogus device for the PReP partition "
892 "(%s)" %(devicePath,))
893 return
894
895 args = [ "sfdisk", "--change-id", disk, "%d" %(part,), "41" ]
896 if disk.startswith("/tmp/") and not os.access(disk, os.R_OK):
897 isys.makeDevInode(disk[5:], disk)
898
899 log("going to run %s" %(args,))
900 rc = iutil.execWithRedirect("/usr/sbin/sfdisk", args,
901 stdout = "/dev/tty5", stderr = "/dev/tty5")
902 if rc:
903 raise SystemError
904
905 fileSystemTypeRegister(prepbootFileSystem())
906
907 class ForeignFileSystem(FileSystemType):
908 def __init__(self):
909 FileSystemType.__init__(self)
910 self.formattable = 0
911 self.checked = 0
912 self.name = "foreign"
913
914 def formatDevice(self, entry, progress, chroot='/'):
915 return
916
917 fileSystemTypeRegister(ForeignFileSystem())
918
919 class PsudoFileSystem(FileSystemType):
920 def __init__(self, name):
921 FileSystemType.__init__(self)
922 self.formattable = 0
923 self.checked = 0
924 self.name = name
925 self.supported = 0
926
927 class ProcFileSystem(PsudoFileSystem):
928 def __init__(self):
929 PsudoFileSystem.__init__(self, "proc")
930
931 fileSystemTypeRegister(ProcFileSystem())
932
933 class SysfsFileSystem(PsudoFileSystem):
934 def __init__(self):
935 PsudoFileSystem.__init__(self, "sysfs")
936
937 fileSystemTypeRegister(SysfsFileSystem())
938
939 class SelinuxfsFileSystem(PsudoFileSystem):
940 def __init__(self):
941 PsudoFileSystem.__init__(self, "selinuxfs")
942
943 fileSystemTypeRegister(SelinuxfsFileSystem())
944
945 class DevptsFileSystem(PsudoFileSystem):
946 def __init__(self):
947 PsudoFileSystem.__init__(self, "devpts")
948 self.defaultOptions = "gid=5,mode=620"
949
950 def isMountable(self):
951 return 0
952
953 fileSystemTypeRegister(DevptsFileSystem())
954
955 class DevshmFileSystem(PsudoFileSystem):
956 def __init__(self):
957 PsudoFileSystem.__init__(self, "tmpfs")
958
959 def isMountable(self):
960 return 0
961
962 fileSystemTypeRegister(DevshmFileSystem())
963
964 class AutoFileSystem(PsudoFileSystem):
965 def __init__(self):
966 PsudoFileSystem.__init__(self, "auto")
967
968 fileSystemTypeRegister(AutoFileSystem())
969
970 class BindFileSystem(AutoFileSystem):
971 def __init__(self):
972 PsudoFileSystem.__init__(self, "bind")
973
974 def isMountable(self):
975 return 1
976
977 fileSystemTypeRegister(BindFileSystem())
978
979 class FileSystemSet:
980 def __init__(self):
981 self.messageWindow = None
982 self.progressWindow = None
983 self.waitWindow = None
984 self.mountcount = 0
985 self.migratedfs = 0
986 self.reset()
987 self.volumesCreated = 0
988
989 def isActive(self):
990 return self.mountcount != 0
991
992 def registerMessageWindow(self, method):
993 self.messageWindow = method
994
995 def registerProgressWindow(self, method):
996 self.progressWindow = method
997
998 def registerWaitWindow(self, method):
999 self.waitWindow = method
1000
1001 def reset (self):
1002 self.entries = []
1003 proc = FileSystemSetEntry(Device(), '/proc', fileSystemTypeGet("proc"))
1004 self.add(proc)
1005 sys = FileSystemSetEntry(Device(), '/sys', fileSystemTypeGet("sysfs"))
1006 self.add(sys)
1007 pts = FileSystemSetEntry(Device(), '/dev/pts',
1008 fileSystemTypeGet("devpts"), "gid=5,mode=620")
1009 self.add(pts)
1010 shm = FileSystemSetEntry(Device(), '/dev/shm', fileSystemTypeGet("tmpfs"))
1011 self.add(shm)
1012
1013 def verify (self):
1014 for entry in self.entries:
1015 if type(entry.__dict__) != type({}):
1016 raise RuntimeError, "fsset internals inconsistent"
1017
1018 def add (self, entry):
1019 # remove any existing duplicate entries
1020 for existing in self.entries:
1021 if (existing.device.getDevice() == entry.device.getDevice()
1022 and existing.mountpoint == entry.mountpoint):
1023 self.remove(existing)
1024 # XXX debuggin'
1025 ## log ("fsset at %s\n"
1026 ## "adding entry for %s\n"
1027 ## "entry object %s, class __dict__ is %s",
1028 ## self, entry.mountpoint, entry,
1029 ## isys.printObject(entry.__dict__))
1030 self.entries.append(entry)
1031 self.entries.sort (mountCompare)
1032
1033 def remove (self, entry):
1034 self.entries.remove(entry)
1035
1036 def getEntryByMountPoint(self, mount):
1037 for entry in self.entries:
1038 if entry.mountpoint == mount:
1039 return entry
1040 return None
1041
1042 def getEntryByDeviceName(self, dev):
1043 for entry in self.entries:
1044 if entry.device.getDevice() == dev:
1045 return entry
1046 return None
1047
1048 def copy (self):
1049 new = FileSystemSet()
1050 for entry in self.entries:
1051 new.add (entry)
1052 return new
1053
1054 def fstab (self):
1055 format = "%-23s %-23s %-7s %-15s %d %d\n"
1056 fstab = ""
1057 for entry in self.entries:
1058 if entry.mountpoint:
1059 if entry.getLabel():
1060 device = "LABEL=%s" % (entry.getLabel(),)
1061 else:
1062 device = devify(entry.device.getDevice())
1063 fstab = fstab + entry.device.getComment()
1064 fstab = fstab + format % (device, entry.mountpoint,
1065 entry.fsystem.getName(),
1066 entry.options, entry.fsck,
1067 entry.order)
1068 return fstab
1069
1070 def mtab (self):
1071 format = "%s %s %s %s 0 0\n"
1072 mtab = ""
1073 for entry in self.entries:
1074 if not entry.isMounted():
1075 continue
1076 if entry.mountpoint:
1077 # swap doesn't end up in the mtab
1078 if entry.fsystem.getName() == "swap":
1079 continue
1080 if entry.options:
1081 options = "rw," + entry.options
1082 else:
1083 options = "rw"
1084 mtab = mtab + format % (devify(entry.device.getDevice()),
1085 entry.mountpoint,
1086 entry.fsystem.getName(),
1087 options)
1088 return mtab
1089
1090 def raidtab(self):
1091 # set up raidtab...
1092 raidtab = ""
1093 for entry in self.entries:
1094 if entry.device.getName() == "RAIDDevice":
1095 raidtab = raidtab + entry.device.raidTab()
1096
1097 return raidtab
1098
1099 def mdadmConf(self):
1100 raident = 0
1101
1102 cf = """
1103 # mdadm.conf written out by anaconda
1104 DEVICE partitions
1105 MAILADDR root
1106 """
1107 for ent in self.entries:
1108 if ent.device.getName() != "RAIDDevice":
1109 continue
1110
1111 raident +=1
1112 cf = cf + ent.device.mdadmLine()
1113
1114 if raident > 0:
1115 return cf
1116 return
1117
1118 def write (self, prefix):
1119 f = open (prefix + "/etc/fstab", "w")
1120 f.write (self.fstab())
1121 f.close ()
1122
1123 cf = self.mdadmConf()
1124
1125 if cf:
1126 f = open (prefix + "/etc/mdadm.conf", "w")
1127 f.write (cf)
1128 f.close ()
1129
1130 # touch mtab
1131 open (prefix + "/etc/mtab", "w+")
1132 f.close ()
1133
1134 def restoreMigratedFstab(self, prefix):
1135 if not self.migratedfs:
1136 return
1137
1138 fname = prefix + "/etc/fstab"
1139 if os.access(fname + ".rpmsave", os.R_OK):
1140 os.rename(fname + ".rpmsave", fname)
1141
1142 def migratewrite(self, prefix):
1143 if not self.migratedfs:
1144 return
1145
1146 fname = prefix + "/etc/fstab"
1147 f = open (fname, "r")
1148 lines = f.readlines()
1149 f.close()
1150
1151 perms = os.stat(fname)[0] & 0777
1152 os.rename(fname, fname + ".rpmsave")
1153 f = open (fname, "w+")
1154 os.chmod(fname, perms)
1155
1156 for line in lines:
1157 fields = string.split(line)
1158
1159 # try to be smart like in fsset.py::readFstab()
1160 if not fields or line[0] == "#":
1161 f.write(line)
1162 continue
1163
1164 if len (fields) < 4 or len (fields) > 6:
1165 f.write(line)
1166 continue
1167
1168 if string.find(fields[3], "noauto") != -1:
1169 f.write(line)
1170 continue
1171
1172 mntpt = fields[1]
1173 entry = self.getEntryByMountPoint(mntpt)
1174 if not entry or not entry.getMigrate():
1175 f.write(line)
1176 elif entry.origfsystem.getName() != fields[2]:
1177 f.write(line)
1178 else:
1179 fields[2] = entry.fsystem.getName()
1180 newline = "%-23s %-23s %-7s %-15s %s %s\n" % (fields[0],
1181 fields[1],
1182 fields[2],
1183 fields[3],
1184 fields[4],
1185 fields[5])
1186 f.write(newline)
1187
1188 f.close()
1189
1190 # return the "boot" device
1191 def getBootDev(self):
1192 mntDict = {}
1193 bootDev = None
1194 for entry in self.entries:
1195 mntDict[entry.mountpoint] = entry.device
1196
1197 # FIXME: this ppc stuff feels kind of crufty -- the abstraction
1198 # here needs a little bit of work
1199 if iutil.getPPCMacGen() == "NewWorld":
1200 for entry in self.entries:
1201 if entry.fsystem.getName() == "Apple Bootstrap":
1202 bootDev = entry.device
1203 elif (iutil.getPPCMachine() == "pSeries" or
1204 iutil.getPPCMachine() == "iSeries"):
1205 # we want the first prep partition or the first newly formatted one
1206 bestprep = None
1207 for entry in self.entries:
1208 if ((entry.fsystem.getName() == "PPC PReP Boot")
1209 and ((bestprep is None) or
1210 ((bestprep.format == 0) and (entry.format == 1)))):
1211 bestprep = entry
1212 if bestprep:
1213 bootDev = bestprep.device
1214 elif iutil.getArch() == "ia64":
1215 if mntDict.has_key("/boot/efi"):
1216 bootDev = mntDict['/boot/efi']
1217 elif mntDict.has_key("/boot"):
1218 bootDev = mntDict['/boot']
1219 else:
1220 bootDev = mntDict['/']
1221
1222 return bootDev
1223
1224 def bootloaderChoices(self, diskSet, bl):
1225 ret = {}
1226 bootDev = self.getBootDev()
1227
1228 if bootDev is None:
1229 log("no boot device set")
1230 return ret
1231
1232 if bootDev.getName() == "RAIDDevice":
1233 ret['boot'] = (bootDev.device, N_("RAID Device"))
1234 ret['mbr'] = (bl.drivelist[0], N_("Master Boot Record (MBR)"))
1235 return ret
1236
1237 if iutil.getPPCMacGen() == "NewWorld":
1238 ret['boot'] = (bootDev.device, N_("Apple Bootstrap"))
1239 n = 1
1240 for entry in self.entries:
1241 if ((entry.fsystem.getName() == "Apple Bootstrap") and (
1242 entry.device.getDevice() != bootDev.device)):
1243 ret['boot%d' %(n,)] = (entry.device.getDevice(),
1244 N_("Apple Bootstrap"))
1245 n = n + 1
1246 return ret
1247 elif (iutil.getPPCMachine() == "pSeries" or
1248 iutil.getPPCMachine() == "iSeries"):
1249 ret['boot'] = (bootDev.device, N_("PPC PReP Boot"))
1250 return ret
1251
1252 ret['boot'] = (bootDev.device, N_("First sector of boot partition"))
1253 ret['mbr'] = (bl.drivelist[0], N_("Master Boot Record (MBR)"))
1254 return ret
1255
1256 # set active partition on disks
1257 # if an active partition is set, leave it alone; if none set
1258 # set either our boot partition or the first partition on the drive active
1259 def setActive(self, diskset):
1260 dev = self.getBootDev()
1261
1262 if dev is None:
1263 return
1264
1265 bootDev = dev.device
1266
1267 # on ia64, *only* /boot/efi should be marked bootable
1268 # similarly, on pseries, we really only want the PReP partition active
1269 if (iutil.getArch() == "ia64" or iutil.getPPCMachine() == "pSeries"
1270 or iutil.getPPCMachine() == "iSeries"):
1271 part = partedUtils.get_partition_by_name(diskset.disks, bootDev)
1272 if part and part.is_flag_available(parted.PARTITION_BOOT):
1273 part.set_flag(parted.PARTITION_BOOT, 1)
1274 return
1275
1276 for drive in diskset.disks.keys():
1277 foundActive = 0
1278 bootPart = None
1279 disk = diskset.disks[drive]
1280 part = disk.next_partition()
1281 while part:
1282 if not part.is_active():
1283 part = disk.next_partition(part)
1284 continue
1285
1286 if not part.is_flag_available(parted.PARTITION_BOOT):
1287 foundActive = 1
1288 part = None
1289 continue
1290
1291 if part.get_flag(parted.PARTITION_BOOT):
1292 foundActive = 1
1293 part = None
1294 continue
1295
1296 if not bootPart:
1297 bootPart = part
1298
1299 if partedUtils.get_partition_name(part) == bootDev:
1300 bootPart = part
1301
1302 part = disk.next_partition(part)
1303
1304 if bootPart and not foundActive:
1305 bootPart.set_flag(parted.PARTITION_BOOT, 1)
1306
1307 if bootPart:
1308 del bootPart
1309
1310 def formatSwap (self, chroot):
1311 formatted = []
1312 notformatted = []
1313
1314 for entry in self.entries:
1315 if (not entry.fsystem or not entry.fsystem.getName() == "swap" or
1316 entry.isMounted()):
1317 continue
1318 if not entry.getFormat():
1319 notformatted.append(entry)
1320 continue
1321 try:
1322 self.formatEntry(entry, chroot)
1323 formatted.append(entry)
1324 except SystemError:
1325 if self.messageWindow:
1326 self.messageWindow(_("Error"),
1327 _("An error occurred trying to "
1328 "initialize swap on device %s. This "
1329 "problem is serious, and the install "
1330 "cannot continue.\n\n"
1331 "Press <Enter> to reboot your system.")
1332 % (entry.device.getDevice(),))
1333 sys.exit(0)
1334
1335 for entry in formatted:
1336 try:
1337 self.labelEntry(entry, chroot)
1338 except SystemError:
1339 # should be OK, fall back to by device
1340 pass
1341
1342 # find if there's a label on the ones we're not formatting
1343 for entry in notformatted:
1344 dev = entry.device.getDevice()
1345 if not dev or dev == "none":
1346 continue
1347 try:
1348 label = isys.readFSLabel(dev)
1349 except:
1350 continue
1351 if label:
1352 entry.setLabel(label)
1353
1354 def turnOnSwap (self, chroot):
1355 for entry in self.entries:
1356 if (entry.fsystem and entry.fsystem.getName() == "swap"
1357 and not entry.isMounted()):
1358 try:
1359 entry.mount(chroot)
1360 self.mountcount = self.mountcount + 1
1361 except SystemError, (num, msg):
1362 if self.messageWindow:
1363 self.messageWindow(_("Error"),
1364 _("Error enabling swap device %s: "
1365 "%s\n\n"
1366 "This most likely means this "
1367 "swap partition has not been "
1368 "initialized."
1369 "\n\n"
1370 "Press OK to reboot your "
1371 "system.")
1372 % (entry.device.getDevice(), msg))
1373 sys.exit(0)
1374
1375 def labelEntry(self, entry, chroot):
1376 label = entry.device.getLabel()
1377 if label:
1378 entry.setLabel(label)
1379 elif entry.device.doLabel is not None:
1380 entry.fsystem.labelDevice(entry, chroot)
1381
1382 def formatEntry(self, entry, chroot):
1383 log("formatting %s as %s" %(entry.mountpoint, entry.fsystem.name))
1384 entry.fsystem.formatDevice(entry, self.progressWindow, chroot)
1385
1386 def badblocksEntry(self, entry, chroot):
1387 entry.fsystem.badblocksDevice(entry, self.progressWindow, chroot)
1388
1389 def getMigratableEntries(self):
1390 retval = []
1391 for entry in self.entries:
1392 if entry.origfsystem and entry.origfsystem.isMigratable():
1393 retval.append(entry)
1394
1395 return retval
1396
1397 def formattablePartitions(self):
1398 list = []
1399 for entry in self.entries:
1400 if entry.fsystem.isFormattable():
1401 list.append (entry)
1402 return list
1403
1404 def checkBadblocks(self, chroot='/'):
1405 for entry in self.entries:
1406 if (not entry.fsystem.isFormattable() or not entry.getBadblocks()
1407 or entry.isMounted()):
1408 continue
1409 try:
1410 self.badblocksEntry(entry, chroot)
1411 except BadBlocksError:
1412 log("Bad blocks detected on device %s",entry.device.getDevice())
1413 if self.messageWindow:
1414 self.messageWindow(_("Error"),
1415 _("Bad blocks have been detected on "
1416 "device /dev/%s. We do "
1417 "not recommend you use this device."
1418 "\n\n"
1419 "Press <Enter> to reboot your system") %
1420 (entry.device.getDevice(),))
1421 sys.exit(0)
1422
1423 except SystemError:
1424 if self.messageWindow:
1425 self.messageWindow(_("Error"),
1426 _("An error occurred searching for "
1427 "bad blocks on %s. This problem is "
1428 "serious, and the install cannot "
1429 "continue.\n\n"
1430 "Press <Enter> to reboot your system.")
1431 % (entry.device.getDevice(),))
1432 sys.exit(0)
1433
1434 def createLogicalVolumes (self, chroot='/'):
1435 # first set up the volume groups
1436 for entry in self.entries:
1437 if entry.fsystem.name == "volume group (LVM)":
1438 entry.device.setupDevice(chroot)
1439
1440 # then set up the logical volumes
1441 for entry in self.entries:
1442 if isinstance(entry.device, LogicalVolumeDevice):
1443 entry.device.setupDevice(chroot)
1444 self.volumesCreated = 1
1445
1446
1447 def makeFilesystems (self, chroot='/'):
1448 formatted = []
1449 notformatted = []
1450 for entry in self.entries:
1451 if (not entry.fsystem.isFormattable() or not entry.getFormat()
1452 or entry.isMounted()):
1453 notformatted.append(entry)
1454 continue
1455 try:
1456 self.formatEntry(entry, chroot)
1457 formatted.append(entry)
1458 except SystemError:
1459 if self.messageWindow:
1460 self.messageWindow(_("Error"),
1461 _("An error occurred trying to "
1462 "format %s. This problem is "
1463 "serious, and the install cannot "
1464 "continue.\n\n"
1465 "Press <Enter> to reboot your system.")
1466 % (entry.device.getDevice(),))
1467 sys.exit(0)
1468
1469 for entry in formatted:
1470 try:
1471 self.labelEntry(entry, chroot)
1472 except SystemError:
1473 # should be OK, we'll still use the device name to mount.
1474 pass
1475
1476 # go through and have labels for the ones we don't format
1477 for entry in notformatted:
1478 dev = entry.device.getDevice()
1479 if not dev or dev == "none":
1480 continue
1481 if not entry.mountpoint or entry.mountpoint == "swap":
1482 continue
1483 try:
1484 label = isys.readFSLabel(dev)
1485 except:
1486 continue
1487 if label:
1488 entry.setLabel(label)
1489 else:
1490 self.labelEntry(entry, chroot)
1491
1492 def haveMigratedFilesystems(self):
1493 return self.migratedfs
1494
1495 def migrateFilesystems (self, chroot='/'):
1496 if self.migratedfs:
1497 return
1498
1499 for entry in self.entries:
1500 if not entry.origfsystem:
1501 continue
1502
1503 if not entry.origfsystem.isMigratable() or not entry.getMigrate():
1504 continue
1505 try:
1506 entry.origfsystem.migrateFileSystem(entry, self.messageWindow,
1507 chroot)
1508 except SystemError:
1509 if self.messageWindow:
1510 self.messageWindow(_("Error"),
1511 _("An error occurred trying to "
1512 "migrate %s. This problem is "
1513 "serious, and the install cannot "
1514 "continue.\n\n"
1515 "Press <Enter> to reboot your system.")
1516 % (entry.device.getDevice(),))
1517 sys.exit(0)
1518
1519 self.migratedfs = 1
1520
1521 def mountFilesystems(self, instPath = '/', raiseErrors = 0, readOnly = 0):
1522 for entry in self.entries:
1523 if not entry.fsystem.isMountable():
1524 continue
1525 try:
1526 log("trying to mount %s on %s" %(entry.device.getDevice(), entry.mountpoint))
1527 entry.mount(instPath, readOnly = readOnly)
1528 self.mountcount = self.mountcount + 1
1529 except OSError, (num, msg):
1530 if self.messageWindow:
1531 if num == errno.EEXIST:
1532 self.messageWindow(_("Invalid mount point"),
1533 _("An error occurred when trying "
1534 "to create %s. Some element of "
1535 "this path is not a directory. "
1536 "This is a fatal error and the "
1537 "install cannot continue.\n\n"
1538 "Press <Enter> to reboot your "
1539 "system.") % (entry.mountpoint,))
1540 else:
1541 self.messageWindow(_("Invalid mount point"),
1542 _("An error occurred when trying "
1543 "to create %s: %s. This is "
1544 "a fatal error and the install "
1545 "cannot continue.\n\n"
1546 "Press <Enter> to reboot your "
1547 "system.") % (entry.mountpoint,
1548 msg))
1549 sys.exit(0)
1550 except SystemError, (num, msg):
1551 if raiseErrors:
1552 raise SystemError, (num, msg)
1553 if self.messageWindow:
1554 self.messageWindow(_("Error"),
1555 _("Error mounting device %s as %s: "
1556 "%s\n\n"
1557 "This most likely means this "
1558 "partition has not been formatted."
1559 "\n\n"
1560 "Press OK to reboot your system.")
1561 % (entry.device.getDevice(),
1562 entry.mountpoint, msg))
1563 sys.exit(0)
1564
1565 self.makeLVMNodes(instPath)
1566
1567 def makeLVMNodes(self, instPath, trylvm1 = 0):
1568 # XXX hack to make the device node exist for the root fs if
1569 # it's a logical volume so that mkinitrd can create the initrd.
1570 root = self.getEntryByMountPoint("/")
1571
1572 rootlvm1 = 0
1573 if trylvm1:
1574 dev = root.device.getDevice()
1575 # lvm1 major is 58
1576 if os.access("%s/dev/%s" %(instPath, dev), os.R_OK) and posix.major(os.stat("%s/dev/%s" %(instPath, dev)).st_rdev) == 58:
1577 rootlvm1 = 1
1578
1579 if isinstance(root.device, LogicalVolumeDevice) or rootlvm1:
1580 # now make sure all of the device nodes exist. *sigh*
1581 rc = iutil.execWithRedirect("lvm",
1582 ["lvm", "vgmknodes", "-v"],
1583 stdout = "/tmp/lvmout",
1584 stderr = "/tmp/lvmout",
1585 searchPath = 1)
1586
1587 rootDev = "/dev/%s" % (root.device.getDevice(),)
1588 rootdir = instPath + rootDev[:string.rfind(rootDev, "/")]
1589 if not os.path.exists(instPath + "/dev/mapper/control"):
1590 iutil.makeDMNode(root=instPath)
1591 if not os.path.isdir(rootdir):
1592 os.makedirs(rootdir)
1593 dmdev = "/dev/mapper/" + root.device.getDevice().replace("/", "-")
1594 if os.path.exists(instPath + dmdev):
1595 os.unlink(instPath + dmdev)
1596 iutil.copyDeviceNode(dmdev, instPath + dmdev)
1597 # unlink existing so that we dtrt on upgrades
1598 if os.path.exists(instPath + rootDev):
1599 os.unlink(instPath + rootDev)
1600 os.symlink(dmdev, instPath + rootDev)
1601 if not os.path.isdir("%s/etc/lvm" %(instPath,)):
1602 os.makedirs("%s/etc/lvm" %(instPath,))
1603
1604 def filesystemSpace(self, chroot='/'):
1605 space = []
1606 for entry in self.entries:
1607 if not entry.isMounted():
1608 continue
1609 # we can't put swap files on swap partitions; that's nonsense
1610 if entry.mountpoint == "swap":
1611 continue
1612 path = "%s/%s" % (chroot, entry.mountpoint)
1613 try:
1614 space.append((entry.mountpoint, isys.fsSpaceAvailable(path)))
1615 except SystemError:
1616 log("failed to get space available in filesystemSpace() for %s" %(entry.mountpoint,))
1617
1618 def spaceSort(a, b):
1619 (m1, s1) = a
1620 (m2, s2) = b
1621
1622 if (s1 > s2):
1623 return -1
1624 elif s1 < s2:
1625 return 1
1626
1627 return 0
1628
1629 space.sort(spaceSort)
1630 return space
1631
1632 def hasDirtyFilesystems(self, mountpoint):
1633 ret = []
1634
1635 for entry in self.entries:
1636 # XXX - multifsify, virtualize isdirty per fstype
1637 if entry.fsystem.getName() != "ext2": continue
1638 if entry.getFormat(): continue
1639 if isinstance(entry.device.getDevice(), BindMountDevice): continue
1640
1641 try:
1642 if isys.ext2IsDirty(entry.device.getDevice()):
1643 log("%s is a dirty ext2 partition" % entry.device.getDevice())
1644 ret.append(entry.device.getDevice())
1645 except Exception, e:
1646 log("got an exception checking %s for being dirty, hoping it's not" %(entry.device.getDevice(),))
1647
1648 return ret
1649
1650 def umountFilesystems(self, instPath, ignoreErrors = 0):
1651 # XXX remove special case
1652 try:
1653 isys.umount(instPath + '/proc/bus/usb', removeDir = 0)
1654 log("Umount USB OK")
1655 except:
1656 # log("Umount USB Fail")
1657 pass
1658
1659 # take a slice so we don't modify self.entries
1660 reverse = self.entries[:]
1661 reverse.reverse()
1662
1663 for entry in reverse:
1664 entry.umount(instPath)
1665
1666 class FileSystemSetEntry:
1667 def __init__ (self, device, mountpoint,
1668 fsystem=None, options=None,
1669 origfsystem=None, migrate=0,
1670 order=-1, fsck=-1, format=0,
1671 badblocks = 0):
1672 if not fsystem:
1673 fsystem = fileSystemTypeGet("ext2")
1674 self.device = device
1675 self.mountpoint = mountpoint
1676 self.fsystem = fsystem
1677 self.origfsystem = origfsystem
1678 self.migrate = migrate
1679 if options:
1680 self.options = options
1681 else:
1682 self.options = fsystem.getDefaultOptions(mountpoint)
1683 self.mountcount = 0
1684 self.label = None
1685 if fsck == -1:
1686 self.fsck = fsystem.isChecked()
1687 else:
1688 self.fsck = fsck
1689 if order == -1:
1690 if mountpoint == '/':
1691 self.order = 1
1692 elif self.fsck:
1693 self.order = 2
1694 else:
1695 self.order = 0
1696 else:
1697 self.order = order
1698 if format and not fsystem.isFormattable():
1699 raise RuntimeError, ("file system type %s is not formattable, "
1700 "but has been added to fsset with format "
1701 "flag on" % fsystem.getName())
1702 self.format = format
1703 self.badblocks = badblocks
1704
1705 def mount(self, chroot='/', devPrefix='/tmp', readOnly = 0):
1706 device = self.device.setupDevice(chroot, devPrefix=devPrefix)
1707
1708 # FIXME: we really should migrate before turnOnFilesystems.
1709 # but it's too late now
1710 if (self.migrate == 1) and (self.origfsystem is not None):
1711 self.origfsystem.mount(device, "%s/%s" % (chroot, self.mountpoint),
1712 readOnly = readOnly,
1713 bindMount = isinstance(self.device,
1714 BindMountDevice))
1715 else:
1716 self.fsystem.mount(device, "%s/%s" % (chroot, self.mountpoint),
1717 readOnly = readOnly,
1718 bindMount = isinstance(self.device,
1719 BindMountDevice))
1720
1721 self.mountcount = self.mountcount + 1
1722
1723 def umount(self, chroot='/'):
1724 if self.mountcount > 0:
1725 try:
1726 self.fsystem.umount(self.device, "%s/%s" % (chroot,
1727 self.mountpoint))
1728 self.mountcount = self.mountcount - 1
1729 except RuntimeError:
1730 pass
1731
1732 def setFileSystemType(self, fstype):
1733 self.fsystem = fstype
1734
1735 def setBadblocks(self, state):
1736 self.badblocks = state
1737
1738 def getBadblocks(self):
1739 return self.badblocks
1740
1741 def getMountPoint(self):
1742 return self.mountpoint
1743
1744 def setFormat (self, state):
1745 if self.migrate and state:
1746 raise ValueError, "Trying to set format bit on when migrate is set!"
1747 self.format = state
1748
1749 def getFormat (self):
1750 return self.format
1751
1752 def setMigrate (self, state):
1753 if self.format and state:
1754 raise ValueError, "Trying to set migrate bit on when format is set!"
1755
1756 self.migrate = state
1757
1758 def getMigrate (self):
1759 return self.migrate
1760
1761 def isMounted (self):
1762 return self.mountcount > 0
1763
1764 def getLabel (self):
1765 return self.label
1766
1767 def setLabel (self, label):
1768 self.label = label
1769
1770 def __str__(self):
1771 if not self.mountpoint:
1772 mntpt = "None"
1773 else:
1774 mntpt = self.mountpoint
1775
1776 str = ("fsentry -- device: %(device)s mountpoint: %(mountpoint)s\n"
1777 " fsystem: %(fsystem)s format: %(format)s\n"
1778 " ismounted: %(mounted)s \n"%
1779 {"device": self.device.getDevice(), "mountpoint": mntpt,
1780 "fsystem": self.fsystem.getName(), "format": self.format,
1781 "mounted": self.mountcount})
1782 return str
1783
1784
1785 class Device:
1786 def __init__(self):
1787 self.device = "none"
1788 self.fsoptions = {}
1789 self.label = None
1790 self.isSetup = 0
1791 self.doLabel = 1
1792
1793 def getComment (self):
1794 return ""
1795
1796 def getDevice (self, asBoot = 0):
1797 return self.device
1798
1799 def setupDevice (self, chroot='/', devPrefix='/tmp'):
1800 return self.device
1801
1802 def cleanupDevice (self, chroot, devPrefix='/tmp'):
1803 pass
1804
1805 def solidify (self):
1806 pass
1807
1808 def getName(self):
1809 return self.__class__.__name__
1810
1811 def getLabel(self):
1812 try:
1813 return isys.readFSLabel(self.setupDevice(), makeDevNode = 0)
1814 except:
1815 return ""
1816
1817 class DevDevice(Device):
1818 """Device with a device node rooted in /dev that we just always use
1819 the pre-created device node for."""
1820 def __init__(self, dev):
1821 Device.__init__(self)
1822 self.device = dev
1823
1824 def getDevice(self, asBoot = 0):
1825 return self.device
1826
1827 def setupDevice(self, chroot='/', devPrefix='/dev'):
1828 return "/dev/%s" %(self.getDevice(),)
1829
1830 class RAIDDevice(Device):
1831 # XXX usedMajors does not take in account any EXISTING md device
1832 # on the system for installs. We need to examine all partitions
1833 # to investigate which minors are really available.
1834 usedMajors = {}
1835
1836 # members is a list of Device based instances that will be
1837 # a part of this raid device
1838 def __init__(self, level, members, minor=-1, spares=0, existing=0,
1839 chunksize = 64):
1840 Device.__init__(self)
1841 self.level = level
1842 self.members = members
1843 self.spares = spares
1844 self.numDisks = len(members) - spares
1845 self.isSetup = existing
1846 self.doLabel = None
1847 if chunksize is not None:
1848 self.chunksize = chunksize
1849 else:
1850 self.chunksize = 256
1851
1852 if len(members) < spares:
1853 raise RuntimeError, ("you requiested more spare devices "
1854 "than online devices!")
1855
1856 if level == 5:
1857 if self.numDisks < 3:
1858 raise RuntimeError, "RAID 5 requires at least 3 online members"
1859
1860 # there are 32 major md devices, 0...31
1861 if minor == -1 or minor is None:
1862 for I in range(32):
1863 if not RAIDDevice.usedMajors.has_key(I):
1864 minor = I
1865 break
1866
1867 if minor == -1:
1868 raise RuntimeError, ("Unable to allocate minor number for "
1869 "raid device")
1870
1871 RAIDDevice.usedMajors[minor] = None
1872 self.device = "md" + str(minor)
1873 self.minor = minor
1874
1875 # make sure the list of raid members is sorted
1876 self.members.sort()
1877
1878 def __del__ (self):
1879 del RAIDDevice.usedMajors[self.minor]
1880
1881 def ext2Args (self):
1882 if self.level == 5:
1883 return [ '-R', 'stride=%d' % ((self.numDisks - 1) * 16) ]
1884 elif self.level == 0:
1885 return [ '-R', 'stride=%d' % (self.numDisks * 16) ]
1886 return []
1887
1888 def mdadmLine (self, devPrefix="/dev"):
1889 return "ARRAY %s/%s super-minor=%s\n" %(devPrefix, self.device,
1890 self.minor)
1891
1892 def raidTab (self, devPrefix='/dev'):
1893 if self.level == 1:
1894 nDisks = max(2, self.numDisks)
1895 elif self.level == 5:
1896 nDisks = max(3, self.numDisks)
1897 elif self.level == 6:
1898 nDisks = max(4, self.numDisks)
1899 else:
1900 nDisks = self.numDisks
1901
1902 entry = ""
1903 entry = entry + "raiddev %s/%s\n" % (devPrefix,
1904 self.device,)
1905 entry = entry + "raid-level %d\n" % (self.level,)
1906 entry = entry + "nr-raid-disks %d\n" % (nDisks,)
1907 entry = entry + "chunk-size %s\n" %(self.chunksize,)
1908 entry = entry + "persistent-superblock 1\n"
1909 entry = entry + "nr-spare-disks %d\n" % (self.spares,)
1910 i = 0
1911 for device in self.members[:self.numDisks]:
1912 entry = entry + " device %s/%s\n" % (devPrefix,
1913 device)
1914 entry = entry + " raid-disk %d\n" % (i,)
1915 i = i + 1
1916 while i < nDisks:
1917 entry = entry + " device dev/null\n"
1918 entry = entry + " failed-disk %d\n" % (i,)
1919 i = i + 1
1920 i = 0
1921 for device in self.members[self.numDisks:]:
1922 entry = entry + " device %s/%s\n" % (devPrefix,
1923 device)
1924 entry = entry + " spare-disk %d\n" % (i,)
1925 i = i + 1
1926 return entry
1927
1928 def setupDevice (self, chroot="/", devPrefix='/dev'):
1929 def devify(x):
1930 return "/dev/%s" %(x,)
1931
1932 if self.level == 1:
1933 nDisks = max(2, self.numDisks)
1934 elif self.level == 5:
1935 nDisks = max(3, self.numDisks)
1936 elif self.level == 6:
1937 nDisks = max(4, self.numDisks)
1938 else:
1939 nDisks = self.numDisks
1940
1941 node = "%s/%s" % (devPrefix, self.device)
1942 isys.makeDevInode(self.device, node)
1943
1944 if not self.isSetup:
1945 for device in self.members:
1946 PartitionDevice(device).setupDevice(chroot,
1947 devPrefix=devPrefix)
1948
1949 args = ["/usr/sbin/mdadm", "--create", "/dev/%s" %(self.device,),
1950 "--run", "--chunk=%s" %(self.chunksize,),
1951 "--level=%s" %(self.level,),
1952 "--raid-devices=%s" %(nDisks,)]
1953
1954 if self.spares > 0:
1955 args.append("--spare-devices=%s" %(self.spares,),)
1956
1957 args.extend(map(devify, self.members))
1958
1959 i = 0
1960 while self.numDisks + i < nDisks:
1961 args.append("missing")
1962 i = i + 1
1963
1964 log("going to run: %s" %(args,))
1965 iutil.execWithRedirect (args[0], args,
1966 stderr="/dev/tty5", stdout="/dev/tty5")
1967 raid.register_raid_device(self.device, self.members[:],
1968 self.level, self.numDisks)
1969 self.isSetup = 1
1970 else:
1971 isys.raidstart(self.device, self.members[0])
1972 return node
1973
1974 def getDevice (self, asBoot = 0):
1975 if not asBoot:
1976 return self.device
1977 else:
1978 return self.members[0]
1979
1980 def solidify(self):
1981 return
1982
1983 ext2 = fileSystemTypeGet("ext2")
1984 ext2.registerDeviceArgumentFunction(RAIDDevice, RAIDDevice.ext2Args)
1985
1986 class VolumeGroupDevice(Device):
1987 def __init__(self, name, physvols, pesize = 32768, existing = 0):
1988 """Creates a VolumeGroupDevice.
1989
1990 name is the name of the volume group
1991 physvols is a list of Device objects which are the physical volumes
1992 pesize is the size of physical extents in kilobytes
1993 existing is whether this vg previously existed.
1994 """
1995
1996 Device.__init__(self)
1997 self.physicalVolumes = physvols
1998 self.isSetup = existing
1999 self.name = name
2000 self.device = name
2001 self.isSetup = existing
2002
2003 self.physicalextentsize = pesize
2004
2005 def setupDevice (self, chroot="/", devPrefix='/tmp'):
2006 nodes = []
2007 for volume in self.physicalVolumes:
2008 # XXX the lvm tools are broken and will only work for /dev
2009 node = volume.setupDevice(chroot, devPrefix="/dev")
2010
2011 # XXX I should check if the pv is set up somehow so that we
2012 # can have preexisting vgs and add new pvs to them.
2013 if not self.isSetup:
2014 # now make the device into a real physical volume
2015 # XXX I don't really belong here. should
2016 # there be a PhysicalVolumeDevice(PartitionDevice) ?
2017 lvm.writeForceConf()
2018 rc = iutil.execWithRedirect("lvm",
2019 ["lvm", "pvcreate", "-ff", "-y",
2020 "-v", node],
2021 stdout = "/tmp/lvmout",
2022 stderr = "/tmp/lvmout",
2023 searchPath = 1)
2024 if rc:
2025 raise SystemError, "pvcreate failed for %s" % (volume,)
2026 lvm.unlinkConf()
2027
2028 lvm.wipeOtherMetadataFromPV(node)
2029
2030 nodes.append(node)
2031
2032 if not self.isSetup:
2033 # rescan now that we've recreated pvs. ugh.
2034 lvm.writeForceConf()
2035 lvm.vgscan()
2036
2037 args = [ "lvm", "vgcreate", "-v", "-An",
2038 "-s", "%sk" %(self.physicalextentsize,),
2039 self.name ]
2040 args.extend(nodes)
2041 rc = iutil.execWithRedirect(args[0], args,
2042 stdout = "/tmp/lvmout",
2043 stderr = "/tmp/lvmout",
2044 searchPath = 1)
2045
2046 if rc:
2047 raise SystemError, "vgcreate failed for %s" %(self.name,)
2048
2049 lvm.unlinkConf()
2050 self.isSetup = 1
2051 else:
2052 lvm.vgscan()
2053 lvm.vgactivate()
2054
2055 return "/dev/%s" % (self.name,)
2056
2057 def solidify(self):
2058 return
2059
2060 class LogicalVolumeDevice(Device):
2061 # note that size is in megabytes!
2062 def __init__(self, volumegroup, size, vgname, existing = 0):
2063 Device.__init__(self)
2064 self.volumeGroup = volumegroup
2065 self.size = size
2066 self.name = vgname
2067 self.isSetup = 0
2068 self.isSetup = existing
2069 self.doLabel = None
2070
2071 # these are attributes we might want to expose. or maybe not.
2072 # self.chunksize
2073 # self.stripes
2074 # self.stripesize
2075 # self.extents
2076 # self.readaheadsectors
2077
2078 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2079 if not self.isSetup:
2080 lvm.writeForceConf()
2081 rc = iutil.execWithRedirect("lvm",
2082 ["lvm", "lvcreate", "-L",
2083 "%dM" % (self.size,),
2084 "-n", self.name, "-An",
2085 self.volumeGroup],
2086 stdout = "/tmp/lvmout",
2087 stderr = "/tmp/lvmout",
2088 searchPath = 1)
2089 if rc:
2090 raise SystemError, "lvcreate failed for %s" %(self.name,)
2091 lvm.unlinkConf()
2092 self.isSetup = 1
2093
2094 return "/dev/%s" % (self.getDevice(),)
2095
2096 def getDevice(self, asBoot = 0):
2097 return "%s/%s" % (self.volumeGroup, self.name)
2098
2099 def solidify(self):
2100 return
2101
2102
2103 class PartitionDevice(Device):
2104 def __init__(self, partition):
2105 Device.__init__(self)
2106 if type(partition) != types.StringType:
2107 raise ValueError, "partition must be a string"
2108 self.device = partition
2109
2110 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2111 path = '%s/%s' % (devPrefix, self.getDevice(),)
2112 isys.makeDevInode(self.getDevice(), path)
2113 return path
2114
2115 class PartedPartitionDevice(PartitionDevice):
2116 def __init__(self, partition):
2117 Device.__init__(self)
2118 self.device = None
2119 self.partition = partition
2120
2121 def getDevice(self, asBoot = 0):
2122 if not self.partition:
2123 return self.device
2124
2125 return partedUtils.get_partition_name(self.partition)
2126
2127 def solidify(self):
2128 # drop reference on the parted partition object and note
2129 # the current minor number allocation
2130 self.device = self.getDevice()
2131 self.partition = None
2132
2133 class BindMountDevice(Device):
2134 def __init__(self, directory):
2135 Device.__init__(self)
2136 self.device = directory
2137
2138 def setupDevice(self, chroot="/", devPrefix="/tmp"):
2139 return chroot + self.device
2140
2141
2142
2143 class SwapFileDevice(Device):
2144 def __init__(self, file):
2145 Device.__init__(self)
2146 self.device = file
2147 self.size = 0
2148
2149 def setSize (self, size):
2150 self.size = size
2151
2152 def setupDevice (self, chroot="/", devPrefix='/tmp'):
2153 file = os.path.normpath(chroot + self.getDevice())
2154 if not os.access(file, os.R_OK):
2155 if self.size:
2156 # make sure the permissions are set properly
2157 fd = os.open(file, os.O_CREAT, 0600)
2158 os.close(fd)
2159 isys.ddfile(file, self.size, None)
2160 else:
2161 raise SystemError, (0, "swap file creation necessary, but "
2162 "required size is unknown.")
2163 return file
2164
2165 # This is a device that describes a swap file that is sitting on
2166 # the loopback filesystem host for partitionless installs.
2167 # The piggypath is the place where the loopback file host filesystem
2168 # will be mounted
2169 class PiggybackSwapFileDevice(SwapFileDevice):
2170 def __init__(self, piggypath, file):
2171 SwapFileDevice.__init__(self, file)
2172 self.piggypath = piggypath
2173
2174 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2175 return SwapFileDevice.setupDevice(self, self.piggypath, devPrefix)
2176
2177 class LoopbackDevice(Device):
2178 def __init__(self, hostPartition, hostFs):
2179 Device.__init__(self)
2180 self.host = "/dev/" + hostPartition
2181 self.hostfs = hostFs
2182 self.device = "loop1"
2183
2184 def setupDevice(self, chroot="/", devPrefix='/tmp/'):
2185 if not self.isSetup:
2186 isys.mount(self.host[5:], "/mnt/loophost", fstype = "vfat")
2187 self.device = allocateLoopback("/mnt/loophost/redhat.img")
2188 if not self.device:
2189 raise SystemError, "Unable to allocate loopback device"
2190 self.isSetup = 1
2191 path = '%s/%s' % (devPrefix, self.getDevice())
2192 else:
2193 path = '%s/%s' % (devPrefix, self.getDevice())
2194 isys.makeDevInode(self.getDevice(), path)
2195 path = os.path.normpath(path)
2196 return path
2197
2198 def getComment (self):
2199 return "# LOOP1: %s %s /redhat.img\n" % (self.host, self.hostfs)
2200
2201 def makeDevice(dev):
2202 if dev.startswith('md'):
2203 try:
2204 (mdname, devices, level, numActive) = raid.lookup_raid_device(dev)
2205 device = RAIDDevice(level, devices,
2206 minor=int(mdname[2:]),
2207 spares=len(devices) - numActive,
2208 existing=1)
2209 except KeyError:
2210 device = DevDevice(dev)
2211 else:
2212 device = DevDevice(dev)
2213 return device
2214
2215 # XXX fix RAID
2216 def readFstab (path, intf = None):
2217 fsset = FileSystemSet()
2218
2219 # first, we look at all the disks on the systems and get any ext2/3
2220 # labels off of the filesystem.
2221 # temporary, to get the labels
2222 diskset = partedUtils.DiskSet()
2223 diskset.openDevices()
2224 labels = diskset.getLabels()
2225
2226 labelToDevice = {}
2227 for device, label in labels.items():
2228 if not labelToDevice.has_key(label):
2229 labelToDevice[label] = device
2230 elif intf is not None:
2231 intf.messageWindow(_("Duplicate Labels"),
2232 _("Multiple devices on your system are "
2233 "labelled %s. Labels across devices must be "
2234 "unique for your system to function "
2235 "properly.\n\n"
2236 "Please fix this problem and restart the "
2237 "installation process.") %(label,),
2238 type="custom", custom_icon="error",
2239 custom_buttons=[_("_Reboot")])
2240 sys.exit(0)
2241 else:
2242 log("WARNING!!! Duplicate labels for %s, but no intf so trying "
2243 "to continue" %(label,))
2244
2245
2246 # mark these labels found on the system as used so the factory
2247 # doesn't give them to another device
2248 labelFactory.reserveLabels(labels)
2249
2250 loopIndex = {}
2251
2252 f = open (path, "r")
2253 lines = f.readlines ()
2254 f.close()
2255
2256 for line in lines:
2257 fields = string.split (line)
2258
2259 if not fields: continue
2260
2261 if line[0] == "#":
2262 # skip all comments
2263 continue
2264
2265 # all valid fstab entries have 6 fields; if the last two are missing
2266 # they are assumed to be zero per fstab(5)
2267 if len(fields) < 4:
2268 continue
2269 elif len(fields) == 4:
2270 fields.append(0)
2271 fields.append(0)
2272 elif len(fields) == 5:
2273 fields.append(0)
2274 elif len(fields) > 6:
2275 continue
2276 if string.find(fields[3], "noauto") != -1: continue
2277
2278 # shenanigans to handle ext3,ext2 format in fstab
2279 fstotry = fields[2]
2280 if fstotry.find(","):
2281 fstotry = fstotry.split(",")
2282 else:
2283 fstotry = [ fstotry ]
2284 fsystem = None
2285 for fs in fstotry:
2286 # if we don't support mounting the filesystem, continue
2287 if not fileSystemTypes.has_key(fs):
2288 continue
2289 fsystem = fileSystemTypeGet(fs)
2290 break
2291 if fsystem is None:
2292 continue
2293
2294 label = None
2295 if fields[0] == "none":
2296 device = Device()
2297 elif ((string.find(fields[3], "bind") != -1) and
2298 fields[0].startswith("/")):
2299 # it's a bind mount, they're Weird (tm)
2300 device = BindMountDevice(fields[0])
2301 fsystem = fileSystemTypeGet("bind")
2302 elif len(fields) >= 6 and fields[0].startswith('LABEL='):
2303 label = fields[0][6:]
2304 if labelToDevice.has_key(label):
2305 device = makeDevice(labelToDevice[label])
2306 else:
2307 log ("Warning: fstab file has LABEL=%s, but this label "
2308 "could not be found on any file system", label)
2309 # bad luck, skip this entry.
2310 continue
2311 elif fields[2] == "swap" and not fields[0].startswith('/dev/'):
2312 # swap files
2313 file = fields[0]
2314
2315 if file.startswith('/initrd/loopfs/'):
2316 file = file[14:]
2317 device = PiggybackSwapFileDevice("/mnt/loophost", file)
2318 else:
2319 device = SwapFileDevice(file)
2320 elif fields[0].startswith('/dev/loop'):
2321 # look up this loop device in the index to find the
2322 # partition that houses the filesystem image
2323 # XXX currently we assume /dev/loop1
2324 if loopIndex.has_key(device):
2325 (dev, fs) = loopIndex[device]
2326 device = LoopbackDevice(dev, fs)
2327 elif fields[0].startswith('/dev/'):
2328 device = makeDevice(fields[0][5:])
2329 else:
2330 continue
2331
2332 # if they have a filesystem being mounted as auto, we need
2333 # to sniff around a bit to figure out what it might be
2334 # if we fail at all, though, just ignore it
2335 if fsystem == "auto" and device.getDevice() != "none":
2336 try:
2337 tmp = partedUtils.sniffFilesystemType("/dev/%s" %(device.setupDevice(),))
2338 if tmp is not None:
2339 fsystem = tmp
2340 except:
2341 pass
2342
2343 entry = FileSystemSetEntry(device, fields[1], fsystem, fields[3],
2344 origfsystem=fsystem)
2345 if label:
2346 entry.setLabel(label)
2347 fsset.add(entry)
2348 return fsset
2349
2350 def getDevFD(device):
2351 try:
2352 fd = os.open(device, os.O_RDONLY)
2353 except:
2354 file = '/tmp/' + device
2355 try:
2356 isys.makeDevInode(device, file)
2357 fd = os.open(file, os.O_RDONLY)
2358 except:
2359 return -1
2360 return fd
2361
2362 def isValidExt2(device):
2363 fd = getDevFD(device)
2364 if fd == -1:
2365 return 0
2366
2367 buf = os.read(fd, 2048)
2368 os.close(fd)
2369
2370 if len(buf) != 2048:
2371 return 0
2372
2373 if struct.unpack("<H", buf[1080:1082]) == (0xef53,):
2374 return 1
2375
2376 return 0
2377
2378 def isValidXFS(device):
2379 fd = getDevFD(device)
2380 if fd == -1:
2381 return 0
2382
2383 buf = os.read(fd, 4)
2384 os.close(fd)
2385
2386 if len(buf) != 4:
2387 return 0
2388
2389 if buf == "XFSB":
2390 return 1
2391
2392 return 0
2393
2394 def isValidReiserFS(device):
2395 fd = getDevFD(device)
2396 if fd == -1:
2397 return 0
2398
2399 '''
2400 ** reiserfs 3.5.x super block begins at offset 8K
2401 ** reiserfs 3.6.x super block begins at offset 64K
2402 All versions have a magic value of "ReIsEr" at
2403 offset 0x34 from start of super block
2404 '''
2405 reiserMagicVal = "ReIsEr"
2406 reiserMagicOffset = 0x34
2407 reiserSBStart = [64*1024, 8*1024]
2408 bufSize = 0x40 # just large enough to include the magic value
2409 for SBOffset in reiserSBStart:
2410 try:
2411 os.lseek(fd, SBOffset, 0)
2412 buf = os.read(fd, bufSize)
2413 except:
2414 buf = ""
2415
2416 if len(buf) < bufSize:
2417 continue
2418
2419 if (buf[reiserMagicOffset:reiserMagicOffset+len(reiserMagicVal)] ==
2420 reiserMagicVal):
2421 os.close(fd)
2422 return 1
2423
2424 os.close(fd)
2425 return 0
2426
2427 def isValidJFS(device):
2428 fd = getDevFD(device)
2429 if fd == -1:
2430 return 0
2431
2432 try:
2433 os.lseek(fd, 32768, 0)
2434 buf = os.read(fd, 128)
2435 except:
2436 buf = ""
2437
2438 os.close(fd)
2439 if len(buf) < 4:
2440 return 0
2441
2442 if (buf[0:4] == "JFS1"):
2443 return 1
2444
2445 return 0
2446
2447 # this will return a list of types of filesystems which device
2448 # looks like it could be to try mounting as
2449 def getFStoTry(device):
2450 rc = []
2451
2452 if isValidXFS(device):
2453 rc.append("xfs")
2454
2455 if isValidReiserFS(device):
2456 rc.append("reiserfs")
2457
2458 if isValidJFS(device):
2459 rc.append("jfs")
2460
2461 if isValidExt2(device):
2462 if os.access(device, os.O_RDONLY):
2463 create = 0
2464 else:
2465 create = 1
2466 if isys.ext2HasJournal(device, makeDevNode = create):
2467 rc.append("ext3")
2468 rc.append("ext2")
2469
2470 # FIXME: need to check for swap
2471
2472 return rc
2473
2474 def allocateLoopback(file):
2475 found = 1
2476 for i in range(8):
2477 dev = "loop%d" % (i,)
2478 path = "/tmp/loop%d" % (i,)
2479 isys.makeDevInode(dev, path)
2480 try:
2481 isys.losetup(path, file)
2482 found = 1
2483 except SystemError:
2484 continue
2485 break
2486 if found:
2487 return dev
2488 return None
2489
2490 def ext2FormatFilesystem(argList, messageFile, windowCreator, mntpoint):
2491 if windowCreator:
2492 w = windowCreator(_("Formatting"),
2493 _("Formatting %s file system...") % (mntpoint,), 100)
2494 else:
2495 w = None
2496
2497 fd = os.open(messageFile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
2498 p = os.pipe()
2499 childpid = os.fork()
2500 if not childpid:
2501 os.close(p[0])
2502 os.dup2(p[1], 1)
2503 os.dup2(fd, 2)
2504 os.close(p[1])
2505 os.close(fd)
2506 os.execv(argList[0], argList)
2507 log("failed to exec %s", argList)
2508 os._exit(1)
2509
2510 os.close(p[1])
2511
2512 # ignoring SIGCHLD would be cleaner then ignoring EINTR, but
2513 # we can't use signal() in this thread?
2514
2515 s = 'a'
2516 while s and s != '\b':
2517 try:
2518 s = os.read(p[0], 1)
2519 except OSError, args:
2520 (num, str) = args
2521 if (num != 4):
2522 raise IOError, args
2523
2524 os.write(fd, s)
2525
2526 num = ''
2527 sync = 0
2528 while s:
2529 try:
2530 s = os.read(p[0], 1)
2531 os.write(fd, s)
2532
2533 if s != '\b':
2534 try:
2535 num = num + s
2536 except:
2537 pass
2538 else:
2539 if num and len(num):
2540 l = string.split(num, '/')
2541 try:
2542 val = (int(l[0]) * 100) / int(l[1])
2543 except (IndexError, TypeError):
2544 pass
2545 else:
2546 w and w.set(val)
2547 # sync every 10%
2548 if sync + 10 < val:
2549 isys.sync()
2550 sync = val
2551 num = ''
2552 except OSError, args:
2553 (errno, str) = args
2554 if (errno != 4):
2555 raise IOError, args
2556
2557 try:
2558 (pid, status) = os.waitpid(childpid, 0)
2559 except OSError, (num, msg):
2560 log("exception from waitpid while formatting: %s %s" %(num, msg))
2561 status = None
2562 os.close(fd)
2563
2564 w and w.pop()
2565
2566 # *shrug* no clue why this would happen, but hope that things are fine
2567 if status is None:
2568 return 0
2569
2570 if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0):
2571 return 0
2572
2573 return 1
2574
2575 if __name__ == "__main__":
2576 log.open("foo")
2577
2578 fsset = readFstab("fstab")
2579
2580 print fsset.fstab()
2581
2582 sys.exit(0)
2583 fsset = FileSystemSet()
2584 proc = FileSystemSetEntry(Device(), '/proc', 'proc')
2585 fsset.add(proc)
2586 devpts = FileSystemSetEntry(Device(), '/dev/pts', 'devpts')
2587 fsset.add(devpts)
2588
2589 device = LoopbackDevice("hda1", "vfat")
2590 mountpoint = FileSystemSetEntry (device, '/')
2591 fsset.add(mountpoint)
2592
2593 device = SwapFileDevice("/SWAP")
2594 mountpoint = FileSystemSetEntry (device, "swap", "swap")
2595 fsset.add(mountpoint)
2596
2597 print fsset.fstab()

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