/[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.7 - (show annotations) (download) (as text)
Wed Apr 5 01:20:27 2006 UTC (18 years, 6 months ago) by slords
Branch: MAIN
Changes since 1.6: +16 -125 lines
Content type: text/x-python
Update anaconda to be in sync with 4.3 and FC4

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 d = self.numDisks
1894 if d == 1:
1895 d = 2
1896 entry = ""
1897 entry = entry + "raiddev %s/%s\n" % (devPrefix,
1898 self.device,)
1899 entry = entry + "raid-level %d\n" % (self.level,)
1900 entry = entry + "nr-raid-disks %d\n" % (d)
1901 entry = entry + "chunk-size %s\n" %(self.chunksize,)
1902 entry = entry + "persistent-superblock 1\n"
1903 entry = entry + "nr-spare-disks %d\n" % (self.spares,)
1904 i = 0
1905 for device in self.members[:self.numDisks]:
1906 entry = entry + " device %s/%s\n" % (devPrefix,
1907 device)
1908 entry = entry + " raid-disk %d\n" % (i,)
1909 i = i + 1
1910 i = 0
1911 for device in self.members[self.numDisks:]:
1912 entry = entry + " device %s/%s\n" % (devPrefix,
1913 device)
1914 entry = entry + " spare-disk %d\n" % (i,)
1915 i = i + 1
1916 if self.numDisks == 1:
1917 entry = entry + " device dev/null\n"
1918 entry = entry + " failed-disk 1\n"
1919 return entry
1920
1921 def setupDevice (self, chroot="/", devPrefix='/dev'):
1922 def devify(x):
1923 return "/dev/%s" %(x,)
1924
1925 node = "%s/%s" % (devPrefix, self.device)
1926 isys.makeDevInode(self.device, node)
1927
1928 if not self.isSetup:
1929 for device in self.members:
1930 PartitionDevice(device).setupDevice(chroot,
1931 devPrefix=devPrefix)
1932
1933 args = ["/usr/sbin/mdadm", "--create", "/dev/%s" %(self.device,),
1934 "--run", "--chunk=%s" %(self.chunksize,),
1935 "--level=%s" %(self.level,),
1936 ]
1937
1938 if self.spares > 0:
1939 args.append("--spare-devices=%s" %(self.spares,),)
1940
1941 if self.numDisks == 1 and self.level == 1:
1942 args.append("--raid-devices=2")
1943 else:
1944 args.append("--raid-devices=%s" %(self.numDisks,),)
1945
1946 args.extend(map(devify, self.members))
1947
1948 if self.numDisks == 1 and self.level == 1:
1949 args.append("missing")
1950
1951 log("going to run: %s" %(args,))
1952 iutil.execWithRedirect (args[0], args,
1953 stderr="/dev/tty5", stdout="/dev/tty5")
1954 raid.register_raid_device(self.device, self.members[:],
1955 self.level, self.numDisks)
1956 self.isSetup = 1
1957 else:
1958 isys.raidstart(self.device, self.members[0])
1959 return node
1960
1961 def getDevice (self, asBoot = 0):
1962 if not asBoot:
1963 return self.device
1964 else:
1965 return self.members[0]
1966
1967 def solidify(self):
1968 return
1969
1970 ext2 = fileSystemTypeGet("ext2")
1971 ext2.registerDeviceArgumentFunction(RAIDDevice, RAIDDevice.ext2Args)
1972
1973 class VolumeGroupDevice(Device):
1974 def __init__(self, name, physvols, pesize = 32768, existing = 0):
1975 """Creates a VolumeGroupDevice.
1976
1977 name is the name of the volume group
1978 physvols is a list of Device objects which are the physical volumes
1979 pesize is the size of physical extents in kilobytes
1980 existing is whether this vg previously existed.
1981 """
1982
1983 Device.__init__(self)
1984 self.physicalVolumes = physvols
1985 self.isSetup = existing
1986 self.name = name
1987 self.device = name
1988 self.isSetup = existing
1989
1990 self.physicalextentsize = pesize
1991
1992 def setupDevice (self, chroot="/", devPrefix='/tmp'):
1993 nodes = []
1994 for volume in self.physicalVolumes:
1995 # XXX the lvm tools are broken and will only work for /dev
1996 node = volume.setupDevice(chroot, devPrefix="/dev")
1997
1998 # XXX I should check if the pv is set up somehow so that we
1999 # can have preexisting vgs and add new pvs to them.
2000 if not self.isSetup:
2001 # now make the device into a real physical volume
2002 # XXX I don't really belong here. should
2003 # there be a PhysicalVolumeDevice(PartitionDevice) ?
2004 lvm.writeForceConf()
2005 rc = iutil.execWithRedirect("lvm",
2006 ["lvm", "pvcreate", "-ff", "-y",
2007 "-v", node],
2008 stdout = "/tmp/lvmout",
2009 stderr = "/tmp/lvmout",
2010 searchPath = 1)
2011 if rc:
2012 raise SystemError, "pvcreate failed for %s" % (volume,)
2013 lvm.unlinkConf()
2014
2015 lvm.wipeOtherMetadataFromPV(node)
2016
2017 nodes.append(node)
2018
2019 if not self.isSetup:
2020 # rescan now that we've recreated pvs. ugh.
2021 lvm.writeForceConf()
2022 lvm.vgscan()
2023
2024 args = [ "lvm", "vgcreate", "-v", "-An",
2025 "-s", "%sk" %(self.physicalextentsize,),
2026 self.name ]
2027 args.extend(nodes)
2028 rc = iutil.execWithRedirect(args[0], args,
2029 stdout = "/tmp/lvmout",
2030 stderr = "/tmp/lvmout",
2031 searchPath = 1)
2032
2033 if rc:
2034 raise SystemError, "vgcreate failed for %s" %(self.name,)
2035
2036 lvm.unlinkConf()
2037 self.isSetup = 1
2038 else:
2039 lvm.vgscan()
2040 lvm.vgactivate()
2041
2042 return "/dev/%s" % (self.name,)
2043
2044 def solidify(self):
2045 return
2046
2047 class LogicalVolumeDevice(Device):
2048 # note that size is in megabytes!
2049 def __init__(self, volumegroup, size, vgname, existing = 0):
2050 Device.__init__(self)
2051 self.volumeGroup = volumegroup
2052 self.size = size
2053 self.name = vgname
2054 self.isSetup = 0
2055 self.isSetup = existing
2056 self.doLabel = None
2057
2058 # these are attributes we might want to expose. or maybe not.
2059 # self.chunksize
2060 # self.stripes
2061 # self.stripesize
2062 # self.extents
2063 # self.readaheadsectors
2064
2065 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2066 if not self.isSetup:
2067 lvm.writeForceConf()
2068 rc = iutil.execWithRedirect("lvm",
2069 ["lvm", "lvcreate", "-L",
2070 "%dM" % (self.size,),
2071 "-n", self.name, "-An",
2072 self.volumeGroup],
2073 stdout = "/tmp/lvmout",
2074 stderr = "/tmp/lvmout",
2075 searchPath = 1)
2076 if rc:
2077 raise SystemError, "lvcreate failed for %s" %(self.name,)
2078 lvm.unlinkConf()
2079 self.isSetup = 1
2080
2081 return "/dev/%s" % (self.getDevice(),)
2082
2083 def getDevice(self, asBoot = 0):
2084 return "%s/%s" % (self.volumeGroup, self.name)
2085
2086 def solidify(self):
2087 return
2088
2089
2090 class PartitionDevice(Device):
2091 def __init__(self, partition):
2092 Device.__init__(self)
2093 if type(partition) != types.StringType:
2094 raise ValueError, "partition must be a string"
2095 self.device = partition
2096
2097 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2098 path = '%s/%s' % (devPrefix, self.getDevice(),)
2099 isys.makeDevInode(self.getDevice(), path)
2100 return path
2101
2102 class PartedPartitionDevice(PartitionDevice):
2103 def __init__(self, partition):
2104 Device.__init__(self)
2105 self.device = None
2106 self.partition = partition
2107
2108 def getDevice(self, asBoot = 0):
2109 if not self.partition:
2110 return self.device
2111
2112 return partedUtils.get_partition_name(self.partition)
2113
2114 def solidify(self):
2115 # drop reference on the parted partition object and note
2116 # the current minor number allocation
2117 self.device = self.getDevice()
2118 self.partition = None
2119
2120 class BindMountDevice(Device):
2121 def __init__(self, directory):
2122 Device.__init__(self)
2123 self.device = directory
2124
2125 def setupDevice(self, chroot="/", devPrefix="/tmp"):
2126 return chroot + self.device
2127
2128
2129
2130 class SwapFileDevice(Device):
2131 def __init__(self, file):
2132 Device.__init__(self)
2133 self.device = file
2134 self.size = 0
2135
2136 def setSize (self, size):
2137 self.size = size
2138
2139 def setupDevice (self, chroot="/", devPrefix='/tmp'):
2140 file = os.path.normpath(chroot + self.getDevice())
2141 if not os.access(file, os.R_OK):
2142 if self.size:
2143 # make sure the permissions are set properly
2144 fd = os.open(file, os.O_CREAT, 0600)
2145 os.close(fd)
2146 isys.ddfile(file, self.size, None)
2147 else:
2148 raise SystemError, (0, "swap file creation necessary, but "
2149 "required size is unknown.")
2150 return file
2151
2152 # This is a device that describes a swap file that is sitting on
2153 # the loopback filesystem host for partitionless installs.
2154 # The piggypath is the place where the loopback file host filesystem
2155 # will be mounted
2156 class PiggybackSwapFileDevice(SwapFileDevice):
2157 def __init__(self, piggypath, file):
2158 SwapFileDevice.__init__(self, file)
2159 self.piggypath = piggypath
2160
2161 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2162 return SwapFileDevice.setupDevice(self, self.piggypath, devPrefix)
2163
2164 class LoopbackDevice(Device):
2165 def __init__(self, hostPartition, hostFs):
2166 Device.__init__(self)
2167 self.host = "/dev/" + hostPartition
2168 self.hostfs = hostFs
2169 self.device = "loop1"
2170
2171 def setupDevice(self, chroot="/", devPrefix='/tmp/'):
2172 if not self.isSetup:
2173 isys.mount(self.host[5:], "/mnt/loophost", fstype = "vfat")
2174 self.device = allocateLoopback("/mnt/loophost/redhat.img")
2175 if not self.device:
2176 raise SystemError, "Unable to allocate loopback device"
2177 self.isSetup = 1
2178 path = '%s/%s' % (devPrefix, self.getDevice())
2179 else:
2180 path = '%s/%s' % (devPrefix, self.getDevice())
2181 isys.makeDevInode(self.getDevice(), path)
2182 path = os.path.normpath(path)
2183 return path
2184
2185 def getComment (self):
2186 return "# LOOP1: %s %s /redhat.img\n" % (self.host, self.hostfs)
2187
2188 def makeDevice(dev):
2189 if dev.startswith('md'):
2190 try:
2191 (mdname, devices, level, numActive) = raid.lookup_raid_device(dev)
2192 device = RAIDDevice(level, devices,
2193 minor=int(mdname[2:]),
2194 spares=len(devices) - numActive,
2195 existing=1)
2196 except KeyError:
2197 device = DevDevice(dev)
2198 else:
2199 device = DevDevice(dev)
2200 return device
2201
2202 # XXX fix RAID
2203 def readFstab (path, intf = None):
2204 fsset = FileSystemSet()
2205
2206 # first, we look at all the disks on the systems and get any ext2/3
2207 # labels off of the filesystem.
2208 # temporary, to get the labels
2209 diskset = partedUtils.DiskSet()
2210 diskset.openDevices()
2211 labels = diskset.getLabels()
2212
2213 labelToDevice = {}
2214 for device, label in labels.items():
2215 if not labelToDevice.has_key(label):
2216 labelToDevice[label] = device
2217 elif intf is not None:
2218 intf.messageWindow(_("Duplicate Labels"),
2219 _("Multiple devices on your system are "
2220 "labelled %s. Labels across devices must be "
2221 "unique for your system to function "
2222 "properly.\n\n"
2223 "Please fix this problem and restart the "
2224 "installation process.") %(label,),
2225 type="custom", custom_icon="error",
2226 custom_buttons=[_("_Reboot")])
2227 sys.exit(0)
2228 else:
2229 log("WARNING!!! Duplicate labels for %s, but no intf so trying "
2230 "to continue" %(label,))
2231
2232
2233 # mark these labels found on the system as used so the factory
2234 # doesn't give them to another device
2235 labelFactory.reserveLabels(labels)
2236
2237 loopIndex = {}
2238
2239 f = open (path, "r")
2240 lines = f.readlines ()
2241 f.close()
2242
2243 for line in lines:
2244 fields = string.split (line)
2245
2246 if not fields: continue
2247
2248 if line[0] == "#":
2249 # skip all comments
2250 continue
2251
2252 # all valid fstab entries have 6 fields; if the last two are missing
2253 # they are assumed to be zero per fstab(5)
2254 if len(fields) < 4:
2255 continue
2256 elif len(fields) == 4:
2257 fields.append(0)
2258 fields.append(0)
2259 elif len(fields) == 5:
2260 fields.append(0)
2261 elif len(fields) > 6:
2262 continue
2263 if string.find(fields[3], "noauto") != -1: continue
2264
2265 # shenanigans to handle ext3,ext2 format in fstab
2266 fstotry = fields[2]
2267 if fstotry.find(","):
2268 fstotry = fstotry.split(",")
2269 else:
2270 fstotry = [ fstotry ]
2271 fsystem = None
2272 for fs in fstotry:
2273 # if we don't support mounting the filesystem, continue
2274 if not fileSystemTypes.has_key(fs):
2275 continue
2276 fsystem = fileSystemTypeGet(fs)
2277 break
2278 if fsystem is None:
2279 continue
2280
2281 label = None
2282 if fields[0] == "none":
2283 device = Device()
2284 elif ((string.find(fields[3], "bind") != -1) and
2285 fields[0].startswith("/")):
2286 # it's a bind mount, they're Weird (tm)
2287 device = BindMountDevice(fields[0])
2288 fsystem = fileSystemTypeGet("bind")
2289 elif len(fields) >= 6 and fields[0].startswith('LABEL='):
2290 label = fields[0][6:]
2291 if labelToDevice.has_key(label):
2292 device = makeDevice(labelToDevice[label])
2293 else:
2294 log ("Warning: fstab file has LABEL=%s, but this label "
2295 "could not be found on any file system", label)
2296 # bad luck, skip this entry.
2297 continue
2298 elif fields[2] == "swap" and not fields[0].startswith('/dev/'):
2299 # swap files
2300 file = fields[0]
2301
2302 if file.startswith('/initrd/loopfs/'):
2303 file = file[14:]
2304 device = PiggybackSwapFileDevice("/mnt/loophost", file)
2305 else:
2306 device = SwapFileDevice(file)
2307 elif fields[0].startswith('/dev/loop'):
2308 # look up this loop device in the index to find the
2309 # partition that houses the filesystem image
2310 # XXX currently we assume /dev/loop1
2311 if loopIndex.has_key(device):
2312 (dev, fs) = loopIndex[device]
2313 device = LoopbackDevice(dev, fs)
2314 elif fields[0].startswith('/dev/'):
2315 device = makeDevice(fields[0][5:])
2316 else:
2317 continue
2318
2319 # if they have a filesystem being mounted as auto, we need
2320 # to sniff around a bit to figure out what it might be
2321 # if we fail at all, though, just ignore it
2322 if fsystem == "auto" and device.getDevice() != "none":
2323 try:
2324 tmp = partedUtils.sniffFilesystemType("/dev/%s" %(device.setupDevice(),))
2325 if tmp is not None:
2326 fsystem = tmp
2327 except:
2328 pass
2329
2330 entry = FileSystemSetEntry(device, fields[1], fsystem, fields[3],
2331 origfsystem=fsystem)
2332 if label:
2333 entry.setLabel(label)
2334 fsset.add(entry)
2335 return fsset
2336
2337 def getDevFD(device):
2338 try:
2339 fd = os.open(device, os.O_RDONLY)
2340 except:
2341 file = '/tmp/' + device
2342 try:
2343 isys.makeDevInode(device, file)
2344 fd = os.open(file, os.O_RDONLY)
2345 except:
2346 return -1
2347 return fd
2348
2349 def isValidExt2(device):
2350 fd = getDevFD(device)
2351 if fd == -1:
2352 return 0
2353
2354 buf = os.read(fd, 2048)
2355 os.close(fd)
2356
2357 if len(buf) != 2048:
2358 return 0
2359
2360 if struct.unpack("<H", buf[1080:1082]) == (0xef53,):
2361 return 1
2362
2363 return 0
2364
2365 def isValidXFS(device):
2366 fd = getDevFD(device)
2367 if fd == -1:
2368 return 0
2369
2370 buf = os.read(fd, 4)
2371 os.close(fd)
2372
2373 if len(buf) != 4:
2374 return 0
2375
2376 if buf == "XFSB":
2377 return 1
2378
2379 return 0
2380
2381 def isValidReiserFS(device):
2382 fd = getDevFD(device)
2383 if fd == -1:
2384 return 0
2385
2386 '''
2387 ** reiserfs 3.5.x super block begins at offset 8K
2388 ** reiserfs 3.6.x super block begins at offset 64K
2389 All versions have a magic value of "ReIsEr" at
2390 offset 0x34 from start of super block
2391 '''
2392 reiserMagicVal = "ReIsEr"
2393 reiserMagicOffset = 0x34
2394 reiserSBStart = [64*1024, 8*1024]
2395 bufSize = 0x40 # just large enough to include the magic value
2396 for SBOffset in reiserSBStart:
2397 try:
2398 os.lseek(fd, SBOffset, 0)
2399 buf = os.read(fd, bufSize)
2400 except:
2401 buf = ""
2402
2403 if len(buf) < bufSize:
2404 continue
2405
2406 if (buf[reiserMagicOffset:reiserMagicOffset+len(reiserMagicVal)] ==
2407 reiserMagicVal):
2408 os.close(fd)
2409 return 1
2410
2411 os.close(fd)
2412 return 0
2413
2414 def isValidJFS(device):
2415 fd = getDevFD(device)
2416 if fd == -1:
2417 return 0
2418
2419 try:
2420 os.lseek(fd, 32768, 0)
2421 buf = os.read(fd, 128)
2422 except:
2423 buf = ""
2424
2425 os.close(fd)
2426 if len(buf) < 4:
2427 return 0
2428
2429 if (buf[0:4] == "JFS1"):
2430 return 1
2431
2432 return 0
2433
2434 # this will return a list of types of filesystems which device
2435 # looks like it could be to try mounting as
2436 def getFStoTry(device):
2437 rc = []
2438
2439 if isValidXFS(device):
2440 rc.append("xfs")
2441
2442 if isValidReiserFS(device):
2443 rc.append("reiserfs")
2444
2445 if isValidJFS(device):
2446 rc.append("jfs")
2447
2448 if isValidExt2(device):
2449 if os.access(device, os.O_RDONLY):
2450 create = 0
2451 else:
2452 create = 1
2453 if isys.ext2HasJournal(device, makeDevNode = create):
2454 rc.append("ext3")
2455 rc.append("ext2")
2456
2457 # FIXME: need to check for swap
2458
2459 return rc
2460
2461 def allocateLoopback(file):
2462 found = 1
2463 for i in range(8):
2464 dev = "loop%d" % (i,)
2465 path = "/tmp/loop%d" % (i,)
2466 isys.makeDevInode(dev, path)
2467 try:
2468 isys.losetup(path, file)
2469 found = 1
2470 except SystemError:
2471 continue
2472 break
2473 if found:
2474 return dev
2475 return None
2476
2477 def ext2FormatFilesystem(argList, messageFile, windowCreator, mntpoint):
2478 if windowCreator:
2479 w = windowCreator(_("Formatting"),
2480 _("Formatting %s file system...") % (mntpoint,), 100)
2481 else:
2482 w = None
2483
2484 fd = os.open(messageFile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
2485 p = os.pipe()
2486 childpid = os.fork()
2487 if not childpid:
2488 os.close(p[0])
2489 os.dup2(p[1], 1)
2490 os.dup2(fd, 2)
2491 os.close(p[1])
2492 os.close(fd)
2493 os.execv(argList[0], argList)
2494 log("failed to exec %s", argList)
2495 os._exit(1)
2496
2497 os.close(p[1])
2498
2499 # ignoring SIGCHLD would be cleaner then ignoring EINTR, but
2500 # we can't use signal() in this thread?
2501
2502 s = 'a'
2503 while s and s != '\b':
2504 try:
2505 s = os.read(p[0], 1)
2506 except OSError, args:
2507 (num, str) = args
2508 if (num != 4):
2509 raise IOError, args
2510
2511 os.write(fd, s)
2512
2513 num = ''
2514 sync = 0
2515 while s:
2516 try:
2517 s = os.read(p[0], 1)
2518 os.write(fd, s)
2519
2520 if s != '\b':
2521 try:
2522 num = num + s
2523 except:
2524 pass
2525 else:
2526 if num and len(num):
2527 l = string.split(num, '/')
2528 try:
2529 val = (int(l[0]) * 100) / int(l[1])
2530 except (IndexError, TypeError):
2531 pass
2532 else:
2533 w and w.set(val)
2534 # sync every 10%
2535 if sync + 10 < val:
2536 isys.sync()
2537 sync = val
2538 num = ''
2539 except OSError, args:
2540 (errno, str) = args
2541 if (errno != 4):
2542 raise IOError, args
2543
2544 try:
2545 (pid, status) = os.waitpid(childpid, 0)
2546 except OSError, (num, msg):
2547 log("exception from waitpid while formatting: %s %s" %(num, msg))
2548 status = None
2549 os.close(fd)
2550
2551 w and w.pop()
2552
2553 # *shrug* no clue why this would happen, but hope that things are fine
2554 if status is None:
2555 return 0
2556
2557 if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0):
2558 return 0
2559
2560 return 1
2561
2562 if __name__ == "__main__":
2563 log.open("foo")
2564
2565 fsset = readFstab("fstab")
2566
2567 print fsset.fstab()
2568
2569 sys.exit(0)
2570 fsset = FileSystemSet()
2571 proc = FileSystemSetEntry(Device(), '/proc', 'proc')
2572 fsset.add(proc)
2573 devpts = FileSystemSetEntry(Device(), '/dev/pts', 'devpts')
2574 fsset.add(devpts)
2575
2576 device = LoopbackDevice("hda1", "vfat")
2577 mountpoint = FileSystemSetEntry (device, '/')
2578 fsset.add(mountpoint)
2579
2580 device = SwapFileDevice("/SWAP")
2581 mountpoint = FileSystemSetEntry (device, "swap", "swap")
2582 fsset.add(mountpoint)
2583
2584 print fsset.fstab()

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