/[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.2 - (show annotations) (download) (as text)
Sun Jul 31 16:24:57 2005 UTC (19 years, 3 months ago) by slords
Branch: MAIN
Changes since 1.1: +1 -0 lines
Content type: text/x-python
Second major pass as anaconda installer
- Install/Upgrade both functional in text & gui
- Added upgrade warning for systems < 21:6.0-11
- TODO: raid migration for upgrades
- TODO: status message for post-{install,upgrade}

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 label = labelFactory.createLabel("SWAP-%s" %entry.device.getDevice(),
739 self.maxLabelChars)
740 rc = iutil.execWithRedirect ("/usr/sbin/mkswap",
741 [ "mkswap", '-v1', "-L", label, file ],
742 stdout = "/dev/tty5",
743 stderr = "/dev/tty5",
744 searchPath = 1)
745 if rc:
746 raise SystemError
747 entry.setLabel(label)
748
749 fileSystemTypeRegister(swapFileSystem())
750
751 class FATFileSystem(FileSystemType):
752 def __init__(self):
753 FileSystemType.__init__(self)
754 self.partedFileSystemType = parted.file_system_type_get("fat32")
755 self.formattable = 1
756 self.checked = 0
757 self.maxSizeMB = 1024 * 1024
758 self.name = "vfat"
759 self.packages = [ "dosfstools" ]
760
761 def formatDevice(self, entry, progress, chroot='/'):
762 devicePath = entry.device.setupDevice(chroot)
763 devArgs = self.getDeviceArgs(entry.device)
764 args = [ "mkdosfs", devicePath ]
765 args.extend(devArgs)
766
767 rc = iutil.execWithRedirect("/usr/sbin/mkdosfs", args,
768 stdout = "/dev/tty5",
769 stderr = "/dev/tty5")
770 if rc:
771 raise SystemError
772
773 fileSystemTypeRegister(FATFileSystem())
774
775 class NTFSFileSystem(FileSystemType):
776 def __init__(self):
777 FileSystemType.__init__(self)
778 self.partedFileSystemType = parted.file_system_type_get("ntfs")
779 self.formattable = 0
780 self.checked = 0
781 self.name = "ntfs"
782
783 fileSystemTypeRegister(NTFSFileSystem())
784
785 class hfsFileSystem(FileSystemType):
786 def __init__(self):
787 FileSystemType.__init__(self)
788 self.partedFileSystemType = parted.file_system_type_get("hfs")
789 self.formattable = 1
790 self.checked = 0
791 self.name = "hfs"
792 self.supported = 0
793
794 def isMountable(self):
795 return 0
796
797 def formatDevice(self, entry, progress, chroot='/'):
798 devicePath = entry.device.setupDevice(chroot)
799 devArgs = self.getDeviceArgs(entry.device)
800 args = [ "hformat", devicePath ]
801 args.extend(devArgs)
802
803 rc = iutil.execWithRedirect("/usr/bin/hformat", args,
804 stdout = "/dev/tty5",
805 stderr = "/dev/tty5")
806 if rc:
807 raise SystemError
808
809 fileSystemTypeRegister(hfsFileSystem())
810
811 class applebootstrapFileSystem(hfsFileSystem):
812 def __init__(self):
813 hfsFileSystem.__init__(self)
814 self.partedPartitionFlags = [ parted.PARTITION_BOOT ]
815 self.maxSizeMB = 1
816 self.name = "Apple Bootstrap"
817 if iutil.getPPCMacGen() == "NewWorld":
818 self.supported = 1
819 else:
820 self.supported = 0
821
822 fileSystemTypeRegister(applebootstrapFileSystem())
823
824 class prepbootFileSystem(FileSystemType):
825 def __init__(self):
826 FileSystemType.__init__(self)
827 self.partedFileSystemType = None
828 self.checked = 0
829 self.name = "PPC PReP Boot"
830 self.maxSizeMB = 10
831
832 if iutil.getPPCMachine() == "iSeries":
833 self.maxSizeMB = 64
834
835 # supported for use on the pseries
836 if (iutil.getPPCMachine() == "pSeries" or
837 iutil.getPPCMachine() == "iSeries"):
838 self.supported = 1
839 self.formattable = 1
840 else:
841 self.supported = 0
842 self.formattable = 0
843
844 def formatDevice(self, entry, progress, chroot='/'):
845 # copy and paste job from booty/bootloaderInfo.py...
846 def getDiskPart(dev):
847 cut = len(dev)
848 if (dev.startswith('rd/') or dev.startswith('ida/') or
849 dev.startswith('cciss/') or dev.startswith('i2o/')
850 or dev.startswith("sx8/")):
851 if dev[-2] == 'p':
852 cut = -1
853 elif dev[-3] == 'p':
854 cut = -2
855 else:
856 if dev[-2] in string.digits:
857 cut = -2
858 elif dev[-1] in string.digits:
859 cut = -1
860
861 name = dev[:cut]
862
863 # hack off the trailing 'p' from /dev/cciss/*, for example
864 if name[-1] == 'p':
865 for letter in name:
866 if letter not in string.letters and letter != "/":
867 name = name[:-1]
868 break
869
870 if cut < 0:
871 partNum = int(dev[cut:])
872 else:
873 partNum = None
874
875 return (name, partNum)
876
877 # FIXME: oh dear is this a hack beyond my wildest imagination.
878 # parted doesn't really know how to do these, so we're going to
879 # exec sfdisk and make it set the partition type. this is bloody
880 # ugly
881 devicePath = entry.device.setupDevice(chroot)
882 (disk, part) = getDiskPart(devicePath)
883 if disk is None or part is None:
884 log("oops, somehow got a bogus device for the PReP partition "
885 "(%s)" %(devicePath,))
886 return
887
888 args = [ "sfdisk", "--change-id", disk, "%d" %(part,), "41" ]
889 if disk.startswith("/tmp/") and not os.access(disk, os.R_OK):
890 isys.makeDevInode(disk[5:], disk)
891
892 log("going to run %s" %(args,))
893 rc = iutil.execWithRedirect("/usr/sbin/sfdisk", args,
894 stdout = "/dev/tty5", stderr = "/dev/tty5")
895 if rc:
896 raise SystemError
897
898 fileSystemTypeRegister(prepbootFileSystem())
899
900 class ForeignFileSystem(FileSystemType):
901 def __init__(self):
902 FileSystemType.__init__(self)
903 self.formattable = 0
904 self.checked = 0
905 self.name = "foreign"
906
907 def formatDevice(self, entry, progress, chroot='/'):
908 return
909
910 fileSystemTypeRegister(ForeignFileSystem())
911
912 class PsudoFileSystem(FileSystemType):
913 def __init__(self, name):
914 FileSystemType.__init__(self)
915 self.formattable = 0
916 self.checked = 0
917 self.name = name
918 self.supported = 0
919
920 class ProcFileSystem(PsudoFileSystem):
921 def __init__(self):
922 PsudoFileSystem.__init__(self, "proc")
923
924 fileSystemTypeRegister(ProcFileSystem())
925
926 class SysfsFileSystem(PsudoFileSystem):
927 def __init__(self):
928 PsudoFileSystem.__init__(self, "sysfs")
929
930 fileSystemTypeRegister(SysfsFileSystem())
931
932 class SelinuxfsFileSystem(PsudoFileSystem):
933 def __init__(self):
934 PsudoFileSystem.__init__(self, "selinuxfs")
935
936 fileSystemTypeRegister(SelinuxfsFileSystem())
937
938 class DevptsFileSystem(PsudoFileSystem):
939 def __init__(self):
940 PsudoFileSystem.__init__(self, "devpts")
941 self.defaultOptions = "gid=5,mode=620"
942
943 def isMountable(self):
944 return 0
945
946 fileSystemTypeRegister(DevptsFileSystem())
947
948 class DevshmFileSystem(PsudoFileSystem):
949 def __init__(self):
950 PsudoFileSystem.__init__(self, "tmpfs")
951
952 def isMountable(self):
953 return 0
954
955 fileSystemTypeRegister(DevshmFileSystem())
956
957 class AutoFileSystem(PsudoFileSystem):
958 def __init__(self):
959 PsudoFileSystem.__init__(self, "auto")
960
961 fileSystemTypeRegister(AutoFileSystem())
962
963 class BindFileSystem(AutoFileSystem):
964 def __init__(self):
965 PsudoFileSystem.__init__(self, "bind")
966
967 def isMountable(self):
968 return 1
969
970 fileSystemTypeRegister(BindFileSystem())
971
972 class FileSystemSet:
973 def __init__(self):
974 self.messageWindow = None
975 self.progressWindow = None
976 self.waitWindow = None
977 self.mountcount = 0
978 self.migratedfs = 0
979 self.reset()
980 self.volumesCreated = 0
981
982 def isActive(self):
983 return self.mountcount != 0
984
985 def registerMessageWindow(self, method):
986 self.messageWindow = method
987
988 def registerProgressWindow(self, method):
989 self.progressWindow = method
990
991 def registerWaitWindow(self, method):
992 self.waitWindow = method
993
994 def reset (self):
995 self.entries = []
996 proc = FileSystemSetEntry(Device(), '/proc', fileSystemTypeGet("proc"))
997 self.add(proc)
998 sys = FileSystemSetEntry(Device(), '/sys', fileSystemTypeGet("sysfs"))
999 self.add(sys)
1000 pts = FileSystemSetEntry(Device(), '/dev/pts',
1001 fileSystemTypeGet("devpts"), "gid=5,mode=620")
1002 self.add(pts)
1003 shm = FileSystemSetEntry(Device(), '/dev/shm', fileSystemTypeGet("tmpfs"))
1004 self.add(shm)
1005
1006 def verify (self):
1007 for entry in self.entries:
1008 if type(entry.__dict__) != type({}):
1009 raise RuntimeError, "fsset internals inconsistent"
1010
1011 def add (self, entry):
1012 # remove any existing duplicate entries
1013 for existing in self.entries:
1014 if (existing.device.getDevice() == entry.device.getDevice()
1015 and existing.mountpoint == entry.mountpoint):
1016 self.remove(existing)
1017 # XXX debuggin'
1018 ## log ("fsset at %s\n"
1019 ## "adding entry for %s\n"
1020 ## "entry object %s, class __dict__ is %s",
1021 ## self, entry.mountpoint, entry,
1022 ## isys.printObject(entry.__dict__))
1023 self.entries.append(entry)
1024 self.entries.sort (mountCompare)
1025
1026 def remove (self, entry):
1027 self.entries.remove(entry)
1028
1029 def getEntryByMountPoint(self, mount):
1030 for entry in self.entries:
1031 if entry.mountpoint == mount:
1032 return entry
1033 return None
1034
1035 def getEntryByDeviceName(self, dev):
1036 for entry in self.entries:
1037 if entry.device.getDevice() == dev:
1038 return entry
1039 return None
1040
1041 def copy (self):
1042 new = FileSystemSet()
1043 for entry in self.entries:
1044 new.add (entry)
1045 return new
1046
1047 def fstab (self):
1048 format = "%-23s %-23s %-7s %-15s %d %d\n"
1049 fstab = ""
1050 for entry in self.entries:
1051 if entry.mountpoint:
1052 if entry.getLabel():
1053 device = "LABEL=%s" % (entry.getLabel(),)
1054 else:
1055 device = devify(entry.device.getDevice())
1056 fstab = fstab + entry.device.getComment()
1057 fstab = fstab + format % (device, entry.mountpoint,
1058 entry.fsystem.getName(),
1059 entry.options, entry.fsck,
1060 entry.order)
1061 return fstab
1062
1063 def mtab (self):
1064 format = "%s %s %s %s 0 0\n"
1065 mtab = ""
1066 for entry in self.entries:
1067 if not entry.isMounted():
1068 continue
1069 if entry.mountpoint:
1070 # swap doesn't end up in the mtab
1071 if entry.fsystem.getName() == "swap":
1072 continue
1073 if entry.options:
1074 options = "rw," + entry.options
1075 else:
1076 options = "rw"
1077 mtab = mtab + format % (devify(entry.device.getDevice()),
1078 entry.mountpoint,
1079 entry.fsystem.getName(),
1080 options)
1081 return mtab
1082
1083 def raidtab(self):
1084 # set up raidtab...
1085 raidtab = ""
1086 for entry in self.entries:
1087 if entry.device.getName() == "RAIDDevice":
1088 raidtab = raidtab + entry.device.raidTab()
1089
1090 return raidtab
1091
1092 def mdadmConf(self):
1093 raident = 0
1094
1095 cf = """
1096 # mdadm.conf written out by anaconda
1097 DEVICE partitions
1098 MAILADDR root
1099 """
1100 for ent in self.entries:
1101 if ent.device.getName() != "RAIDDevice":
1102 continue
1103
1104 raident +=1
1105 cf = cf + ent.device.mdadmLine()
1106
1107 if raident > 0:
1108 return cf
1109 return
1110
1111 def write (self, prefix):
1112 f = open (prefix + "/etc/fstab", "w")
1113 f.write (self.fstab())
1114 f.close ()
1115
1116 cf = self.mdadmConf()
1117
1118 if cf:
1119 f = open (prefix + "/etc/mdadm.conf", "w")
1120 f.write (cf)
1121 f.close ()
1122
1123 # touch mtab
1124 open (prefix + "/etc/mtab", "w+")
1125 f.close ()
1126
1127 def restoreMigratedFstab(self, prefix):
1128 if not self.migratedfs:
1129 return
1130
1131 fname = prefix + "/etc/fstab"
1132 if os.access(fname + ".rpmsave", os.R_OK):
1133 os.rename(fname + ".rpmsave", fname)
1134
1135 def migratewrite(self, prefix):
1136 if not self.migratedfs:
1137 return
1138
1139 fname = prefix + "/etc/fstab"
1140 f = open (fname, "r")
1141 lines = f.readlines()
1142 f.close()
1143
1144 perms = os.stat(fname)[0] & 0777
1145 os.rename(fname, fname + ".rpmsave")
1146 f = open (fname, "w+")
1147 os.chmod(fname, perms)
1148
1149 for line in lines:
1150 fields = string.split(line)
1151
1152 # try to be smart like in fsset.py::readFstab()
1153 if not fields or line[0] == "#":
1154 f.write(line)
1155 continue
1156
1157 if len (fields) < 4 or len (fields) > 6:
1158 f.write(line)
1159 continue
1160
1161 if string.find(fields[3], "noauto") != -1:
1162 f.write(line)
1163 continue
1164
1165 mntpt = fields[1]
1166 entry = self.getEntryByMountPoint(mntpt)
1167 if not entry or not entry.getMigrate():
1168 f.write(line)
1169 elif entry.origfsystem.getName() != fields[2]:
1170 f.write(line)
1171 else:
1172 fields[2] = entry.fsystem.getName()
1173 newline = "%-23s %-23s %-7s %-15s %s %s\n" % (fields[0],
1174 fields[1],
1175 fields[2],
1176 fields[3],
1177 fields[4],
1178 fields[5])
1179 f.write(newline)
1180
1181 f.close()
1182
1183 # return the "boot" devicce
1184 def getBootDev(self):
1185 mntDict = {}
1186 bootDev = None
1187 for entry in self.entries:
1188 mntDict[entry.mountpoint] = entry.device
1189
1190 # FIXME: this ppc stuff feels kind of crufty -- the abstraction
1191 # here needs a little bit of work
1192 if iutil.getPPCMacGen() == "NewWorld":
1193 for entry in self.entries:
1194 if entry.fsystem.getName() == "Apple Bootstrap":
1195 bootDev = entry.device
1196 elif (iutil.getPPCMachine() == "pSeries" or
1197 iutil.getPPCMachine() == "iSeries"):
1198 # we want the first prep partition or the first newly formatted one
1199 bestprep = None
1200 for entry in self.entries:
1201 if ((entry.fsystem.getName() == "PPC PReP Boot")
1202 and ((bestprep is None) or
1203 ((bestprep.format == 0) and (entry.format == 1)))):
1204 bestprep = entry
1205 if bestprep:
1206 bootDev = bestprep.device
1207 elif iutil.getArch() == "ia64":
1208 if mntDict.has_key("/boot/efi"):
1209 bootDev = mntDict['/boot/efi']
1210 elif mntDict.has_key("/boot"):
1211 bootDev = mntDict['/boot']
1212 else:
1213 bootDev = mntDict['/']
1214
1215 return bootDev
1216
1217 def bootloaderChoices(self, diskSet, bl):
1218 ret = {}
1219 bootDev = self.getBootDev()
1220
1221 if bootDev is None:
1222 log("no boot device set")
1223 return ret
1224
1225 if bootDev.getName() == "RAIDDevice":
1226 ret['boot'] = (bootDev.device, N_("RAID Device"))
1227 ret['mbr'] = (bl.drivelist[0], N_("Master Boot Record (MBR)"))
1228 return ret
1229
1230 if iutil.getPPCMacGen() == "NewWorld":
1231 ret['boot'] = (bootDev.device, N_("Apple Bootstrap"))
1232 n = 1
1233 for entry in self.entries:
1234 if ((entry.fsystem.getName() == "Apple Bootstrap") and (
1235 entry.device.getDevice() != bootDev.device)):
1236 ret['boot%d' %(n,)] = (entry.device.getDevice(),
1237 N_("Apple Bootstrap"))
1238 n = n + 1
1239 return ret
1240 elif (iutil.getPPCMachine() == "pSeries" or
1241 iutil.getPPCMachine() == "iSeries"):
1242 ret['boot'] = (bootDev.device, N_("PPC PReP Boot"))
1243 return ret
1244
1245 ret['boot'] = (bootDev.device, N_("First sector of boot partition"))
1246 ret['mbr'] = (bl.drivelist[0], N_("Master Boot Record (MBR)"))
1247 return ret
1248
1249 # set active partition on disks
1250 # if an active partition is set, leave it alone; if none set
1251 # set either our boot partition or the first partition on the drive active
1252 def setActive(self, diskset):
1253 dev = self.getBootDev()
1254
1255 if dev is None:
1256 return
1257
1258 bootDev = dev.device
1259
1260 # on ia64, *only* /boot/efi should be marked bootable
1261 # similarly, on pseries, we really only want the PReP partition active
1262 if (iutil.getArch() == "ia64" or iutil.getPPCMachine() == "pSeries"
1263 or iutil.getPPCMachine() == "iSeries"):
1264 part = partedUtils.get_partition_by_name(diskset.disks, bootDev)
1265 if part and part.is_flag_available(parted.PARTITION_BOOT):
1266 part.set_flag(parted.PARTITION_BOOT, 1)
1267 return
1268
1269 for drive in diskset.disks.keys():
1270 foundActive = 0
1271 bootPart = None
1272 disk = diskset.disks[drive]
1273 part = disk.next_partition()
1274 while part:
1275 if not part.is_active():
1276 part = disk.next_partition(part)
1277 continue
1278
1279 if not part.is_flag_available(parted.PARTITION_BOOT):
1280 foundActive = 1
1281 part = None
1282 continue
1283
1284 if part.get_flag(parted.PARTITION_BOOT):
1285 foundActive = 1
1286 part = None
1287 continue
1288
1289 if not bootPart:
1290 bootPart = part
1291
1292 if partedUtils.get_partition_name(part) == bootDev:
1293 bootPart = part
1294
1295 part = disk.next_partition(part)
1296
1297 if bootPart and not foundActive:
1298 bootPart.set_flag(parted.PARTITION_BOOT, 1)
1299
1300 if bootPart:
1301 del bootPart
1302
1303 def formatSwap (self, chroot):
1304 formatted = []
1305 notformatted = []
1306
1307 for entry in self.entries:
1308 if (not entry.fsystem or not entry.fsystem.getName() == "swap" or
1309 entry.isMounted()):
1310 continue
1311 if not entry.getFormat():
1312 notformatted.append(entry)
1313 continue
1314 try:
1315 self.formatEntry(entry, chroot)
1316 formatted.append(entry)
1317 except SystemError:
1318 if self.messageWindow:
1319 self.messageWindow(_("Error"),
1320 _("An error occurred trying to "
1321 "initialize swap on device %s. This "
1322 "problem is serious, and the install "
1323 "cannot continue.\n\n"
1324 "Press <Enter> to reboot your system.")
1325 % (entry.device.getDevice(),))
1326 sys.exit(0)
1327
1328 for entry in formatted:
1329 try:
1330 self.labelEntry(entry, chroot)
1331 except SystemError:
1332 # should be OK, fall back to by device
1333 pass
1334
1335 # find if there's a label on the ones we're not formatting
1336 for entry in notformatted:
1337 dev = entry.device.getDevice()
1338 if not dev or dev == "none":
1339 continue
1340 try:
1341 label = isys.readFSLabel(dev)
1342 except:
1343 continue
1344 if label:
1345 entry.setLabel(label)
1346
1347 def turnOnSwap (self, chroot):
1348 for entry in self.entries:
1349 if (entry.fsystem and entry.fsystem.getName() == "swap"
1350 and not entry.isMounted()):
1351 try:
1352 entry.mount(chroot)
1353 self.mountcount = self.mountcount + 1
1354 except SystemError, (num, msg):
1355 if self.messageWindow:
1356 self.messageWindow(_("Error"),
1357 _("Error enabling swap device %s: "
1358 "%s\n\n"
1359 "This most likely means this "
1360 "swap partition has not been "
1361 "initialized."
1362 "\n\n"
1363 "Press OK to reboot your "
1364 "system.")
1365 % (entry.device.getDevice(), msg))
1366 sys.exit(0)
1367
1368 def labelEntry(self, entry, chroot):
1369 label = entry.device.getLabel()
1370 if label:
1371 entry.setLabel(label)
1372 elif entry.device.doLabel is not None:
1373 entry.fsystem.labelDevice(entry, chroot)
1374
1375 def formatEntry(self, entry, chroot):
1376 log("formatting %s as %s" %(entry.mountpoint, entry.fsystem.name))
1377 entry.fsystem.formatDevice(entry, self.progressWindow, chroot)
1378
1379 def badblocksEntry(self, entry, chroot):
1380 entry.fsystem.badblocksDevice(entry, self.progressWindow, chroot)
1381
1382 def getMigratableEntries(self):
1383 retval = []
1384 for entry in self.entries:
1385 if entry.origfsystem and entry.origfsystem.isMigratable():
1386 retval.append(entry)
1387
1388 return retval
1389
1390 def formattablePartitions(self):
1391 list = []
1392 for entry in self.entries:
1393 if entry.fsystem.isFormattable():
1394 list.append (entry)
1395 return list
1396
1397 def checkBadblocks(self, chroot='/'):
1398 for entry in self.entries:
1399 if (not entry.fsystem.isFormattable() or not entry.getBadblocks()
1400 or entry.isMounted()):
1401 continue
1402 try:
1403 self.badblocksEntry(entry, chroot)
1404 except BadBlocksError:
1405 log("Bad blocks detected on device %s",entry.device.getDevice())
1406 if self.messageWindow:
1407 self.messageWindow(_("Error"),
1408 _("Bad blocks have been detected on "
1409 "device /dev/%s. We do "
1410 "not recommend you use this device."
1411 "\n\n"
1412 "Press <Enter> to reboot your system") %
1413 (entry.device.getDevice(),))
1414 sys.exit(0)
1415
1416 except SystemError:
1417 if self.messageWindow:
1418 self.messageWindow(_("Error"),
1419 _("An error occurred searching for "
1420 "bad blocks on %s. This problem is "
1421 "serious, and the install cannot "
1422 "continue.\n\n"
1423 "Press <Enter> to reboot your system.")
1424 % (entry.device.getDevice(),))
1425 sys.exit(0)
1426
1427 def createLogicalVolumes (self, chroot='/'):
1428 # first set up the volume groups
1429 for entry in self.entries:
1430 if entry.fsystem.name == "volume group (LVM)":
1431 entry.device.setupDevice(chroot)
1432
1433 # then set up the logical volumes
1434 for entry in self.entries:
1435 if isinstance(entry.device, LogicalVolumeDevice):
1436 entry.device.setupDevice(chroot)
1437 self.volumesCreated = 1
1438
1439
1440 def makeFilesystems (self, chroot='/'):
1441 formatted = []
1442 notformatted = []
1443 for entry in self.entries:
1444 if (not entry.fsystem.isFormattable() or not entry.getFormat()
1445 or entry.isMounted()):
1446 notformatted.append(entry)
1447 continue
1448 try:
1449 self.formatEntry(entry, chroot)
1450 formatted.append(entry)
1451 except SystemError:
1452 if self.messageWindow:
1453 self.messageWindow(_("Error"),
1454 _("An error occurred trying to "
1455 "format %s. This problem is "
1456 "serious, and the install cannot "
1457 "continue.\n\n"
1458 "Press <Enter> to reboot your system.")
1459 % (entry.device.getDevice(),))
1460 sys.exit(0)
1461
1462 for entry in formatted:
1463 try:
1464 self.labelEntry(entry, chroot)
1465 except SystemError:
1466 # should be OK, we'll still use the device name to mount.
1467 pass
1468
1469 # go through and have labels for the ones we don't format
1470 for entry in notformatted:
1471 dev = entry.device.getDevice()
1472 if not dev or dev == "none":
1473 continue
1474 if not entry.mountpoint or entry.mountpoint == "swap":
1475 continue
1476 try:
1477 label = isys.readFSLabel(dev)
1478 except:
1479 continue
1480 if label:
1481 entry.setLabel(label)
1482 else:
1483 self.labelEntry(entry, chroot)
1484
1485 def haveMigratedFilesystems(self):
1486 return self.migratedfs
1487
1488 def migrateFilesystems (self, chroot='/'):
1489 if self.migratedfs:
1490 return
1491
1492 for entry in self.entries:
1493 if not entry.origfsystem:
1494 continue
1495
1496 if not entry.origfsystem.isMigratable() or not entry.getMigrate():
1497 continue
1498 try:
1499 entry.origfsystem.migrateFileSystem(entry, self.messageWindow,
1500 chroot)
1501 except SystemError:
1502 if self.messageWindow:
1503 self.messageWindow(_("Error"),
1504 _("An error occurred trying to "
1505 "migrate %s. This problem is "
1506 "serious, and the install cannot "
1507 "continue.\n\n"
1508 "Press <Enter> to reboot your system.")
1509 % (entry.device.getDevice(),))
1510 sys.exit(0)
1511
1512 self.migratedfs = 1
1513
1514 def mountFilesystems(self, instPath = '/', raiseErrors = 0, readOnly = 0):
1515 for entry in self.entries:
1516 if not entry.fsystem.isMountable():
1517 continue
1518 try:
1519 log("trying to mount %s on %s" %(entry.device.getDevice(), entry.mountpoint))
1520 entry.mount(instPath, readOnly = readOnly)
1521 self.mountcount = self.mountcount + 1
1522 except OSError, (num, msg):
1523 if self.messageWindow:
1524 if num == errno.EEXIST:
1525 self.messageWindow(_("Invalid mount point"),
1526 _("An error occurred when trying "
1527 "to create %s. Some element of "
1528 "this path is not a directory. "
1529 "This is a fatal error and the "
1530 "install cannot continue.\n\n"
1531 "Press <Enter> to reboot your "
1532 "system.") % (entry.mountpoint,))
1533 else:
1534 self.messageWindow(_("Invalid mount point"),
1535 _("An error occurred when trying "
1536 "to create %s: %s. This is "
1537 "a fatal error and the install "
1538 "cannot continue.\n\n"
1539 "Press <Enter> to reboot your "
1540 "system.") % (entry.mountpoint,
1541 msg))
1542 sys.exit(0)
1543 except SystemError, (num, msg):
1544 if raiseErrors:
1545 raise SystemError, (num, msg)
1546 if self.messageWindow:
1547 self.messageWindow(_("Error"),
1548 _("Error mounting device %s as %s: "
1549 "%s\n\n"
1550 "This most likely means this "
1551 "partition has not been formatted."
1552 "\n\n"
1553 "Press OK to reboot your system.")
1554 % (entry.device.getDevice(),
1555 entry.mountpoint, msg))
1556 sys.exit(0)
1557
1558 self.makeLVMNodes(instPath)
1559
1560 def makeLVMNodes(self, instPath, trylvm1 = 0):
1561 # XXX hack to make the device node exist for the root fs if
1562 # it's a logical volume so that mkinitrd can create the initrd.
1563 root = self.getEntryByMountPoint("/")
1564
1565 rootlvm1 = 0
1566 if trylvm1:
1567 dev = root.device.getDevice()
1568 # lvm1 major is 58
1569 if os.access("%s/dev/%s" %(instPath, dev), os.R_OK) and posix.major(os.stat("%s/dev/%s" %(instPath, dev)).st_rdev) == 58:
1570 rootlvm1 = 1
1571
1572 if isinstance(root.device, LogicalVolumeDevice) or rootlvm1:
1573 # now make sure all of the device nodes exist. *sigh*
1574 rc = iutil.execWithRedirect("lvm",
1575 ["lvm", "vgmknodes", "-v"],
1576 stdout = "/tmp/lvmout",
1577 stderr = "/tmp/lvmout",
1578 searchPath = 1)
1579
1580 rootDev = "/dev/%s" % (root.device.getDevice(),)
1581 rootdir = instPath + rootDev[:string.rfind(rootDev, "/")]
1582 if not os.path.exists(instPath + "/dev/mapper/control"):
1583 iutil.makeDMNode(root=instPath)
1584 if not os.path.isdir(rootdir):
1585 os.makedirs(rootdir)
1586 dmdev = "/dev/mapper/" + root.device.getDevice().replace("/", "-")
1587 if os.path.exists(instPath + dmdev):
1588 os.unlink(instPath + dmdev)
1589 iutil.copyDeviceNode(dmdev, instPath + dmdev)
1590 # unlink existing so that we dtrt on upgrades
1591 if os.path.exists(instPath + rootDev):
1592 os.unlink(instPath + rootDev)
1593 os.symlink(dmdev, instPath + rootDev)
1594 if not os.path.isdir("%s/etc/lvm" %(instPath,)):
1595 os.makedirs("%s/etc/lvm" %(instPath,))
1596
1597 def filesystemSpace(self, chroot='/'):
1598 space = []
1599 for entry in self.entries:
1600 if not entry.isMounted():
1601 continue
1602 # we can't put swap files on swap partitions; that's nonsense
1603 if entry.mountpoint == "swap":
1604 continue
1605 path = "%s/%s" % (chroot, entry.mountpoint)
1606 try:
1607 space.append((entry.mountpoint, isys.fsSpaceAvailable(path)))
1608 except SystemError:
1609 log("failed to get space available in filesystemSpace() for %s" %(entry.mountpoint,))
1610
1611 def spaceSort(a, b):
1612 (m1, s1) = a
1613 (m2, s2) = b
1614
1615 if (s1 > s2):
1616 return -1
1617 elif s1 < s2:
1618 return 1
1619
1620 return 0
1621
1622 space.sort(spaceSort)
1623 return space
1624
1625 def hasDirtyFilesystems(self, mountpoint):
1626 ret = []
1627
1628 for entry in self.entries:
1629 # XXX - multifsify, virtualize isdirty per fstype
1630 if entry.fsystem.getName() != "ext2": continue
1631 if entry.getFormat(): continue
1632 if isinstance(entry.device.getDevice(), BindMountDevice): continue
1633
1634 try:
1635 if isys.ext2IsDirty(entry.device.getDevice()):
1636 log("%s is a dirty ext2 partition" % entry.device.getDevice())
1637 ret.append(entry.device.getDevice())
1638 except Exception, e:
1639 log("got an exception checking %s for being dirty, hoping it's not" %(entry.device.getDevice(),))
1640
1641 return ret
1642
1643 def umountFilesystems(self, instPath, ignoreErrors = 0):
1644 # XXX remove special case
1645 try:
1646 isys.umount(instPath + '/proc/bus/usb', removeDir = 0)
1647 log("Umount USB OK")
1648 except:
1649 # log("Umount USB Fail")
1650 pass
1651
1652 # take a slice so we don't modify self.entries
1653 reverse = self.entries[:]
1654 reverse.reverse()
1655
1656 for entry in reverse:
1657 entry.umount(instPath)
1658
1659 class FileSystemSetEntry:
1660 def __init__ (self, device, mountpoint,
1661 fsystem=None, options=None,
1662 origfsystem=None, migrate=0,
1663 order=-1, fsck=-1, format=0,
1664 badblocks = 0):
1665 if not fsystem:
1666 fsystem = fileSystemTypeGet("ext2")
1667 self.device = device
1668 self.mountpoint = mountpoint
1669 self.fsystem = fsystem
1670 self.origfsystem = origfsystem
1671 self.migrate = migrate
1672 if options:
1673 self.options = options
1674 else:
1675 self.options = fsystem.getDefaultOptions(mountpoint)
1676 self.mountcount = 0
1677 self.label = None
1678 if fsck == -1:
1679 self.fsck = fsystem.isChecked()
1680 else:
1681 self.fsck = fsck
1682 if order == -1:
1683 if mountpoint == '/':
1684 self.order = 1
1685 elif self.fsck:
1686 self.order = 2
1687 else:
1688 self.order = 0
1689 else:
1690 self.order = order
1691 if format and not fsystem.isFormattable():
1692 raise RuntimeError, ("file system type %s is not formattable, "
1693 "but has been added to fsset with format "
1694 "flag on" % fsystem.getName())
1695 self.format = format
1696 self.badblocks = badblocks
1697
1698 def mount(self, chroot='/', devPrefix='/tmp', readOnly = 0):
1699 device = self.device.setupDevice(chroot, devPrefix=devPrefix)
1700
1701 # FIXME: we really should migrate before turnOnFilesystems.
1702 # but it's too late now
1703 if (self.migrate == 1) and (self.origfsystem is not None):
1704 self.origfsystem.mount(device, "%s/%s" % (chroot, self.mountpoint),
1705 readOnly = readOnly,
1706 bindMount = isinstance(self.device,
1707 BindMountDevice))
1708 else:
1709 self.fsystem.mount(device, "%s/%s" % (chroot, self.mountpoint),
1710 readOnly = readOnly,
1711 bindMount = isinstance(self.device,
1712 BindMountDevice))
1713
1714 self.mountcount = self.mountcount + 1
1715
1716 def umount(self, chroot='/'):
1717 if self.mountcount > 0:
1718 try:
1719 self.fsystem.umount(self.device, "%s/%s" % (chroot,
1720 self.mountpoint))
1721 self.mountcount = self.mountcount - 1
1722 except RuntimeError:
1723 pass
1724
1725 def setFileSystemType(self, fstype):
1726 self.fsystem = fstype
1727
1728 def setBadblocks(self, state):
1729 self.badblocks = state
1730
1731 def getBadblocks(self):
1732 return self.badblocks
1733
1734 def getMountPoint(self):
1735 return self.mountpoint
1736
1737 def setFormat (self, state):
1738 if self.migrate and state:
1739 raise ValueError, "Trying to set format bit on when migrate is set!"
1740 self.format = state
1741
1742 def getFormat (self):
1743 return self.format
1744
1745 def setMigrate (self, state):
1746 if self.format and state:
1747 raise ValueError, "Trying to set migrate bit on when format is set!"
1748
1749 self.migrate = state
1750
1751 def getMigrate (self):
1752 return self.migrate
1753
1754 def isMounted (self):
1755 return self.mountcount > 0
1756
1757 def getLabel (self):
1758 return self.label
1759
1760 def setLabel (self, label):
1761 self.label = label
1762
1763 def __str__(self):
1764 if not self.mountpoint:
1765 mntpt = "None"
1766 else:
1767 mntpt = self.mountpoint
1768
1769 str = ("fsentry -- device: %(device)s mountpoint: %(mountpoint)s\n"
1770 " fsystem: %(fsystem)s format: %(format)s\n"
1771 " ismounted: %(mounted)s \n"%
1772 {"device": self.device.getDevice(), "mountpoint": mntpt,
1773 "fsystem": self.fsystem.getName(), "format": self.format,
1774 "mounted": self.mountcount})
1775 return str
1776
1777
1778 class Device:
1779 def __init__(self):
1780 self.device = "none"
1781 self.fsoptions = {}
1782 self.label = None
1783 self.isSetup = 0
1784 self.doLabel = 1
1785
1786 def getComment (self):
1787 return ""
1788
1789 def getDevice (self, asBoot = 0):
1790 return self.device
1791
1792 def setupDevice (self, chroot='/', devPrefix='/tmp'):
1793 return self.device
1794
1795 def cleanupDevice (self, chroot, devPrefix='/tmp'):
1796 pass
1797
1798 def solidify (self):
1799 pass
1800
1801 def getName(self):
1802 return self.__class__.__name__
1803
1804 def getLabel(self):
1805 try:
1806 return isys.readFSLabel(self.setupDevice(), makeDevNode = 0)
1807 except:
1808 return ""
1809
1810 class DevDevice(Device):
1811 """Device with a device node rooted in /dev that we just always use
1812 the pre-created device node for."""
1813 def __init__(self, dev):
1814 Device.__init__(self)
1815 self.device = dev
1816
1817 def getDevice(self, asBoot = 0):
1818 return self.device
1819
1820 def setupDevice(self, chroot='/', devPrefix='/dev'):
1821 return "/dev/%s" %(self.getDevice(),)
1822
1823 class RAIDDevice(Device):
1824 # XXX usedMajors does not take in account any EXISTING md device
1825 # on the system for installs. We need to examine all partitions
1826 # to investigate which minors are really available.
1827 usedMajors = {}
1828
1829 # members is a list of Device based instances that will be
1830 # a part of this raid device
1831 def __init__(self, level, members, minor=-1, spares=0, existing=0,
1832 chunksize = 64):
1833 Device.__init__(self)
1834 self.level = level
1835 self.members = members
1836 self.spares = spares
1837 self.numDisks = len(members) - spares
1838 self.isSetup = existing
1839 self.doLabel = None
1840 if chunksize is not None:
1841 self.chunksize = chunksize
1842 else:
1843 self.chunksize = 256
1844
1845 if len(members) < spares:
1846 raise RuntimeError, ("you requiested more spare devices "
1847 "than online devices!")
1848
1849 if level == 5:
1850 if self.numDisks < 3:
1851 raise RuntimeError, "RAID 5 requires at least 3 online members"
1852
1853 # there are 32 major md devices, 0...31
1854 if minor == -1 or minor is None:
1855 for I in range(32):
1856 if not RAIDDevice.usedMajors.has_key(I):
1857 minor = I
1858 break
1859
1860 if minor == -1:
1861 raise RuntimeError, ("Unable to allocate minor number for "
1862 "raid device")
1863
1864 RAIDDevice.usedMajors[minor] = None
1865 self.device = "md" + str(minor)
1866 self.minor = minor
1867
1868 # make sure the list of raid members is sorted
1869 self.members.sort()
1870
1871 def __del__ (self):
1872 del RAIDDevice.usedMajors[self.minor]
1873
1874 def ext2Args (self):
1875 if self.level == 5:
1876 return [ '-R', 'stride=%d' % ((self.numDisks - 1) * 16) ]
1877 elif self.level == 0:
1878 return [ '-R', 'stride=%d' % (self.numDisks * 16) ]
1879 return []
1880
1881 def mdadmLine (self, devPrefix="/dev"):
1882 return "ARRAY %s/%s super-minor=%s\n" %(devPrefix, self.device,
1883 self.minor)
1884
1885 def raidTab (self, devPrefix='/dev'):
1886 d = self.numDisks
1887 if d == 1:
1888 d = 2
1889 entry = ""
1890 entry = entry + "raiddev %s/%s\n" % (devPrefix,
1891 self.device,)
1892 entry = entry + "raid-level %d\n" % (self.level,)
1893 entry = entry + "nr-raid-disks %d\n" % (d)
1894 entry = entry + "chunk-size %s\n" %(self.chunksize,)
1895 entry = entry + "persistent-superblock 1\n"
1896 entry = entry + "nr-spare-disks %d\n" % (self.spares,)
1897 i = 0
1898 for device in self.members[:self.numDisks]:
1899 entry = entry + " device %s/%s\n" % (devPrefix,
1900 device)
1901 entry = entry + " raid-disk %d\n" % (i,)
1902 i = i + 1
1903 i = 0
1904 for device in self.members[self.numDisks:]:
1905 entry = entry + " device %s/%s\n" % (devPrefix,
1906 device)
1907 entry = entry + " spare-disk %d\n" % (i,)
1908 i = i + 1
1909 if self.numDisks == 1:
1910 entry = entry + " device dev/null\n"
1911 entry = entry + " failed-disk 1\n"
1912 return entry
1913
1914 def setupDevice (self, chroot="/", devPrefix='/dev'):
1915 def devify(x):
1916 return "/dev/%s" %(x,)
1917
1918 node = "%s/%s" % (devPrefix, self.device)
1919 isys.makeDevInode(self.device, node)
1920
1921 if not self.isSetup:
1922 for device in self.members:
1923 PartitionDevice(device).setupDevice(chroot,
1924 devPrefix=devPrefix)
1925
1926 args = ["/usr/sbin/mdadm", "--create", "/dev/%s" %(self.device,),
1927 "--run", "--chunk=%s" %(self.chunksize,),
1928 "--level=%s" %(self.level,),
1929 ]
1930
1931 if self.spares > 0:
1932 args.append("--spare-devices=%s" %(self.spares,),)
1933
1934 if self.numDisks == 1:
1935 args.append("--raid-devices=2")
1936 else:
1937 args.append("--raid-devices=%s" %(self.numDisks,),)
1938
1939 args.extend(map(devify, self.members))
1940
1941 if self.numDisks == 1:
1942 args.append("missing")
1943
1944 log("going to run: %s" %(args,))
1945 iutil.execWithRedirect (args[0], args,
1946 stderr="/dev/tty5", stdout="/dev/tty5")
1947 raid.register_raid_device(self.device, self.members[:],
1948 self.level, self.numDisks)
1949 self.isSetup = 1
1950 else:
1951 isys.raidstart(self.device, self.members[0])
1952 return node
1953
1954 def getDevice (self, asBoot = 0):
1955 if not asBoot:
1956 return self.device
1957 else:
1958 return self.members[0]
1959
1960 def solidify(self):
1961 return
1962
1963 ext2 = fileSystemTypeGet("ext2")
1964 ext2.registerDeviceArgumentFunction(RAIDDevice, RAIDDevice.ext2Args)
1965
1966 class VolumeGroupDevice(Device):
1967 def __init__(self, name, physvols, pesize = 32768, existing = 0):
1968 """Creates a VolumeGroupDevice.
1969
1970 name is the name of the volume group
1971 physvols is a list of Device objects which are the physical volumes
1972 pesize is the size of physical extents in kilobytes
1973 existing is whether this vg previously existed.
1974 """
1975
1976 Device.__init__(self)
1977 self.physicalVolumes = physvols
1978 self.isSetup = existing
1979 self.name = name
1980 self.device = name
1981 self.isSetup = existing
1982
1983 self.physicalextentsize = pesize
1984
1985 def setupDevice (self, chroot="/", devPrefix='/tmp'):
1986 nodes = []
1987 for volume in self.physicalVolumes:
1988 # XXX the lvm tools are broken and will only work for /dev
1989 node = volume.setupDevice(chroot, devPrefix="/dev")
1990
1991 # XXX I should check if the pv is set up somehow so that we
1992 # can have preexisting vgs and add new pvs to them.
1993 if not self.isSetup:
1994 # now make the device into a real physical volume
1995 # XXX I don't really belong here. should
1996 # there be a PhysicalVolumeDevice(PartitionDevice) ?
1997 lvm.writeForceConf()
1998 rc = iutil.execWithRedirect("lvm",
1999 ["lvm", "pvcreate", "-ff", "-y",
2000 "-v", node],
2001 stdout = "/tmp/lvmout",
2002 stderr = "/tmp/lvmout",
2003 searchPath = 1)
2004 if rc:
2005 raise SystemError, "pvcreate failed for %s" % (volume,)
2006 lvm.unlinkConf()
2007
2008 lvm.wipeOtherMetadataFromPV(node)
2009
2010 nodes.append(node)
2011
2012 if not self.isSetup:
2013 # rescan now that we've recreated pvs. ugh.
2014 lvm.writeForceConf()
2015 lvm.vgscan()
2016
2017 args = [ "lvm", "vgcreate", "-v", "-An",
2018 "-s", "%sk" %(self.physicalextentsize,),
2019 self.name ]
2020 args.extend(nodes)
2021 rc = iutil.execWithRedirect(args[0], args,
2022 stdout = "/tmp/lvmout",
2023 stderr = "/tmp/lvmout",
2024 searchPath = 1)
2025
2026 if rc:
2027 raise SystemError, "vgcreate failed for %s" %(self.name,)
2028
2029 lvm.unlinkConf()
2030 self.isSetup = 1
2031 else:
2032 lvm.vgscan()
2033 lvm.vgactivate()
2034
2035 return "/dev/%s" % (self.name,)
2036
2037 def solidify(self):
2038 return
2039
2040 class LogicalVolumeDevice(Device):
2041 # note that size is in megabytes!
2042 def __init__(self, volumegroup, size, vgname, existing = 0):
2043 Device.__init__(self)
2044 self.volumeGroup = volumegroup
2045 self.size = size
2046 self.name = vgname
2047 self.isSetup = 0
2048 self.isSetup = existing
2049 self.doLabel = None
2050
2051 # these are attributes we might want to expose. or maybe not.
2052 # self.chunksize
2053 # self.stripes
2054 # self.stripesize
2055 # self.extents
2056 # self.readaheadsectors
2057
2058 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2059 if not self.isSetup:
2060 lvm.writeForceConf()
2061 rc = iutil.execWithRedirect("lvm",
2062 ["lvm", "lvcreate", "-L",
2063 "%dM" % (self.size,),
2064 "-n", self.name, "-An",
2065 self.volumeGroup],
2066 stdout = "/tmp/lvmout",
2067 stderr = "/tmp/lvmout",
2068 searchPath = 1)
2069 if rc:
2070 raise SystemError, "lvcreate failed for %s" %(self.name,)
2071 lvm.unlinkConf()
2072 self.isSetup = 1
2073
2074 return "/dev/%s" % (self.getDevice(),)
2075
2076 def getDevice(self, asBoot = 0):
2077 return "%s/%s" % (self.volumeGroup, self.name)
2078
2079 def solidify(self):
2080 return
2081
2082
2083 class PartitionDevice(Device):
2084 def __init__(self, partition):
2085 Device.__init__(self)
2086 if type(partition) != types.StringType:
2087 raise ValueError, "partition must be a string"
2088 self.device = partition
2089
2090 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2091 path = '%s/%s' % (devPrefix, self.getDevice(),)
2092 isys.makeDevInode(self.getDevice(), path)
2093 return path
2094
2095 class PartedPartitionDevice(PartitionDevice):
2096 def __init__(self, partition):
2097 Device.__init__(self)
2098 self.device = None
2099 self.partition = partition
2100
2101 def getDevice(self, asBoot = 0):
2102 if not self.partition:
2103 return self.device
2104
2105 return partedUtils.get_partition_name(self.partition)
2106
2107 def solidify(self):
2108 # drop reference on the parted partition object and note
2109 # the current minor number allocation
2110 self.device = self.getDevice()
2111 self.partition = None
2112
2113 class BindMountDevice(Device):
2114 def __init__(self, directory):
2115 Device.__init__(self)
2116 self.device = directory
2117
2118 def setupDevice(self, chroot="/", devPrefix="/tmp"):
2119 return chroot + self.device
2120
2121
2122
2123 class SwapFileDevice(Device):
2124 def __init__(self, file):
2125 Device.__init__(self)
2126 self.device = file
2127 self.size = 0
2128
2129 def setSize (self, size):
2130 self.size = size
2131
2132 def setupDevice (self, chroot="/", devPrefix='/tmp'):
2133 file = os.path.normpath(chroot + self.getDevice())
2134 if not os.access(file, os.R_OK):
2135 if self.size:
2136 # make sure the permissions are set properly
2137 fd = os.open(file, os.O_CREAT, 0600)
2138 os.close(fd)
2139 isys.ddfile(file, self.size, None)
2140 else:
2141 raise SystemError, (0, "swap file creation necessary, but "
2142 "required size is unknown.")
2143 return file
2144
2145 # This is a device that describes a swap file that is sitting on
2146 # the loopback filesystem host for partitionless installs.
2147 # The piggypath is the place where the loopback file host filesystem
2148 # will be mounted
2149 class PiggybackSwapFileDevice(SwapFileDevice):
2150 def __init__(self, piggypath, file):
2151 SwapFileDevice.__init__(self, file)
2152 self.piggypath = piggypath
2153
2154 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2155 return SwapFileDevice.setupDevice(self, self.piggypath, devPrefix)
2156
2157 class LoopbackDevice(Device):
2158 def __init__(self, hostPartition, hostFs):
2159 Device.__init__(self)
2160 self.host = "/dev/" + hostPartition
2161 self.hostfs = hostFs
2162 self.device = "loop1"
2163
2164 def setupDevice(self, chroot="/", devPrefix='/tmp/'):
2165 if not self.isSetup:
2166 isys.mount(self.host[5:], "/mnt/loophost", fstype = "vfat")
2167 self.device = allocateLoopback("/mnt/loophost/redhat.img")
2168 if not self.device:
2169 raise SystemError, "Unable to allocate loopback device"
2170 self.isSetup = 1
2171 path = '%s/%s' % (devPrefix, self.getDevice())
2172 else:
2173 path = '%s/%s' % (devPrefix, self.getDevice())
2174 isys.makeDevInode(self.getDevice(), path)
2175 path = os.path.normpath(path)
2176 return path
2177
2178 def getComment (self):
2179 return "# LOOP1: %s %s /redhat.img\n" % (self.host, self.hostfs)
2180
2181 def makeDevice(dev):
2182 if dev.startswith('md'):
2183 try:
2184 (mdname, devices, level, numActive) = raid.lookup_raid_device(dev)
2185 device = RAIDDevice(level, devices,
2186 minor=int(mdname[2:]),
2187 spares=len(devices) - numActive,
2188 existing=1)
2189 except KeyError:
2190 device = DevDevice(dev)
2191 else:
2192 device = DevDevice(dev)
2193 return device
2194
2195 # XXX fix RAID
2196 def readFstab (path, intf = None):
2197 fsset = FileSystemSet()
2198
2199 # first, we look at all the disks on the systems and get any ext2/3
2200 # labels off of the filesystem.
2201 # temporary, to get the labels
2202 diskset = partedUtils.DiskSet()
2203 diskset.openDevices()
2204 labels = diskset.getLabels()
2205
2206 labelToDevice = {}
2207 for device, label in labels.items():
2208 if not labelToDevice.has_key(label):
2209 labelToDevice[label] = device
2210 elif intf is not None:
2211 intf.messageWindow(_("Duplicate Labels"),
2212 _("Multiple devices on your system are "
2213 "labelled %s. Labels across devices must be "
2214 "unique for your system to function "
2215 "properly.\n\n"
2216 "Please fix this problem and restart the "
2217 "installation process.") %(label,),
2218 type="custom", custom_icon="error",
2219 custom_buttons=[_("_Reboot")])
2220 sys.exit(0)
2221 else:
2222 log("WARNING!!! Duplicate labels for %s, but no intf so trying "
2223 "to continue" %(label,))
2224
2225
2226 # mark these labels found on the system as used so the factory
2227 # doesn't give them to another device
2228 labelFactory.reserveLabels(labels)
2229
2230 loopIndex = {}
2231
2232 f = open (path, "r")
2233 lines = f.readlines ()
2234 f.close()
2235
2236 for line in lines:
2237 fields = string.split (line)
2238
2239 if not fields: continue
2240
2241 if line[0] == "#":
2242 # skip all comments
2243 continue
2244
2245 # all valid fstab entries have 6 fields; if the last two are missing
2246 # they are assumed to be zero per fstab(5)
2247 if len(fields) < 4:
2248 continue
2249 elif len(fields) == 4:
2250 fields.append(0)
2251 fields.append(0)
2252 elif len(fields) == 5:
2253 fields.append(0)
2254 elif len(fields) > 6:
2255 continue
2256 if string.find(fields[3], "noauto") != -1: continue
2257
2258 # shenanigans to handle ext3,ext2 format in fstab
2259 fstotry = fields[2]
2260 if fstotry.find(","):
2261 fstotry = fstotry.split(",")
2262 else:
2263 fstotry = [ fstotry ]
2264 fsystem = None
2265 for fs in fstotry:
2266 # if we don't support mounting the filesystem, continue
2267 if not fileSystemTypes.has_key(fs):
2268 continue
2269 fsystem = fileSystemTypeGet(fs)
2270 break
2271 if fsystem is None:
2272 continue
2273
2274 label = None
2275 if fields[0] == "none":
2276 device = Device()
2277 elif ((string.find(fields[3], "bind") != -1) and
2278 fields[0].startswith("/")):
2279 # it's a bind mount, they're Weird (tm)
2280 device = BindMountDevice(fields[0])
2281 fsystem = fileSystemTypeGet("bind")
2282 elif len(fields) >= 6 and fields[0].startswith('LABEL='):
2283 label = fields[0][6:]
2284 if labelToDevice.has_key(label):
2285 device = makeDevice(labelToDevice[label])
2286 else:
2287 log ("Warning: fstab file has LABEL=%s, but this label "
2288 "could not be found on any file system", label)
2289 # bad luck, skip this entry.
2290 continue
2291 elif fields[2] == "swap" and not fields[0].startswith('/dev/'):
2292 # swap files
2293 file = fields[0]
2294
2295 if file.startswith('/initrd/loopfs/'):
2296 file = file[14:]
2297 device = PiggybackSwapFileDevice("/mnt/loophost", file)
2298 else:
2299 device = SwapFileDevice(file)
2300 elif fields[0].startswith('/dev/loop'):
2301 # look up this loop device in the index to find the
2302 # partition that houses the filesystem image
2303 # XXX currently we assume /dev/loop1
2304 if loopIndex.has_key(device):
2305 (dev, fs) = loopIndex[device]
2306 device = LoopbackDevice(dev, fs)
2307 elif fields[0].startswith('/dev/'):
2308 device = makeDevice(fields[0][5:])
2309 else:
2310 continue
2311
2312 # if they have a filesystem being mounted as auto, we need
2313 # to sniff around a bit to figure out what it might be
2314 # if we fail at all, though, just ignore it
2315 if fsystem == "auto" and device.getDevice() != "none":
2316 try:
2317 tmp = partedUtils.sniffFilesystemType("/dev/%s" %(device.setupDevice(),))
2318 if tmp is not None:
2319 fsystem = tmp
2320 except:
2321 pass
2322
2323 entry = FileSystemSetEntry(device, fields[1], fsystem, fields[3],
2324 origfsystem=fsystem)
2325 if label:
2326 entry.setLabel(label)
2327 fsset.add(entry)
2328 return fsset
2329
2330 def getDevFD(device):
2331 try:
2332 fd = os.open(device, os.O_RDONLY)
2333 except:
2334 file = '/tmp/' + device
2335 try:
2336 isys.makeDevInode(device, file)
2337 fd = os.open(file, os.O_RDONLY)
2338 except:
2339 return -1
2340 return fd
2341
2342 def isValidExt2(device):
2343 fd = getDevFD(device)
2344 if fd == -1:
2345 return 0
2346
2347 buf = os.read(fd, 2048)
2348 os.close(fd)
2349
2350 if len(buf) != 2048:
2351 return 0
2352
2353 if struct.unpack("<H", buf[1080:1082]) == (0xef53,):
2354 return 1
2355
2356 return 0
2357
2358 def isValidXFS(device):
2359 fd = getDevFD(device)
2360 if fd == -1:
2361 return 0
2362
2363 buf = os.read(fd, 4)
2364 os.close(fd)
2365
2366 if len(buf) != 4:
2367 return 0
2368
2369 if buf == "XFSB":
2370 return 1
2371
2372 return 0
2373
2374 def isValidReiserFS(device):
2375 fd = getDevFD(device)
2376 if fd == -1:
2377 return 0
2378
2379 '''
2380 ** reiserfs 3.5.x super block begins at offset 8K
2381 ** reiserfs 3.6.x super block begins at offset 64K
2382 All versions have a magic value of "ReIsEr" at
2383 offset 0x34 from start of super block
2384 '''
2385 reiserMagicVal = "ReIsEr"
2386 reiserMagicOffset = 0x34
2387 reiserSBStart = [64*1024, 8*1024]
2388 bufSize = 0x40 # just large enough to include the magic value
2389 for SBOffset in reiserSBStart:
2390 try:
2391 os.lseek(fd, SBOffset, 0)
2392 buf = os.read(fd, bufSize)
2393 except:
2394 buf = ""
2395
2396 if len(buf) < bufSize:
2397 continue
2398
2399 if (buf[reiserMagicOffset:reiserMagicOffset+len(reiserMagicVal)] ==
2400 reiserMagicVal):
2401 os.close(fd)
2402 return 1
2403
2404 os.close(fd)
2405 return 0
2406
2407 def isValidJFS(device):
2408 fd = getDevFD(device)
2409 if fd == -1:
2410 return 0
2411
2412 try:
2413 os.lseek(fd, 32768, 0)
2414 buf = os.read(fd, 128)
2415 except:
2416 buf = ""
2417
2418 os.close(fd)
2419 if len(buf) < 4:
2420 return 0
2421
2422 if (buf[0:4] == "JFS1"):
2423 return 1
2424
2425 return 0
2426
2427 # this will return a list of types of filesystems which device
2428 # looks like it could be to try mounting as
2429 def getFStoTry(device):
2430 rc = []
2431
2432 if isValidXFS(device):
2433 rc.append("xfs")
2434
2435 if isValidReiserFS(device):
2436 rc.append("reiserfs")
2437
2438 if isValidJFS(device):
2439 rc.append("jfs")
2440
2441 if isValidExt2(device):
2442 if os.access(device, os.O_RDONLY):
2443 create = 0
2444 else:
2445 create = 1
2446 if isys.ext2HasJournal(device, makeDevNode = create):
2447 rc.append("ext3")
2448 rc.append("ext2")
2449
2450 # FIXME: need to check for swap
2451
2452 return rc
2453
2454 def allocateLoopback(file):
2455 found = 1
2456 for i in range(8):
2457 dev = "loop%d" % (i,)
2458 path = "/tmp/loop%d" % (i,)
2459 isys.makeDevInode(dev, path)
2460 try:
2461 isys.losetup(path, file)
2462 found = 1
2463 except SystemError:
2464 continue
2465 break
2466 if found:
2467 return dev
2468 return None
2469
2470 def ext2FormatFilesystem(argList, messageFile, windowCreator, mntpoint):
2471 if windowCreator:
2472 w = windowCreator(_("Formatting"),
2473 _("Formatting %s file system...") % (mntpoint,), 100)
2474 else:
2475 w = None
2476
2477 fd = os.open(messageFile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
2478 p = os.pipe()
2479 childpid = os.fork()
2480 if not childpid:
2481 os.close(p[0])
2482 os.dup2(p[1], 1)
2483 os.dup2(fd, 2)
2484 os.close(p[1])
2485 os.close(fd)
2486 os.execv(argList[0], argList)
2487 log("failed to exec %s", argList)
2488 os._exit(1)
2489
2490 os.close(p[1])
2491
2492 # ignoring SIGCHLD would be cleaner then ignoring EINTR, but
2493 # we can't use signal() in this thread?
2494
2495 s = 'a'
2496 while s and s != '\b':
2497 try:
2498 s = os.read(p[0], 1)
2499 except OSError, args:
2500 (num, str) = args
2501 if (num != 4):
2502 raise IOError, args
2503
2504 os.write(fd, s)
2505
2506 num = ''
2507 sync = 0
2508 while s:
2509 try:
2510 s = os.read(p[0], 1)
2511 os.write(fd, s)
2512
2513 if s != '\b':
2514 try:
2515 num = num + s
2516 except:
2517 pass
2518 else:
2519 if num and len(num):
2520 l = string.split(num, '/')
2521 try:
2522 val = (int(l[0]) * 100) / int(l[1])
2523 except (IndexError, TypeError):
2524 pass
2525 else:
2526 w and w.set(val)
2527 # sync every 10%
2528 if sync + 10 < val:
2529 isys.sync()
2530 sync = val
2531 num = ''
2532 except OSError, args:
2533 (errno, str) = args
2534 if (errno != 4):
2535 raise IOError, args
2536
2537 try:
2538 (pid, status) = os.waitpid(childpid, 0)
2539 except OSError, (num, msg):
2540 log("exception from waitpid while formatting: %s %s" %(num, msg))
2541 status = None
2542 os.close(fd)
2543
2544 w and w.pop()
2545
2546 # *shrug* no clue why this would happen, but hope that things are fine
2547 if status is None:
2548 return 0
2549
2550 if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0):
2551 return 0
2552
2553 return 1
2554
2555 if __name__ == "__main__":
2556 log.open("foo")
2557
2558 fsset = readFstab("fstab")
2559
2560 print fsset.fstab()
2561
2562 sys.exit(0)
2563 fsset = FileSystemSet()
2564 proc = FileSystemSetEntry(Device(), '/proc', 'proc')
2565 fsset.add(proc)
2566 devpts = FileSystemSetEntry(Device(), '/dev/pts', 'devpts')
2567 fsset.add(devpts)
2568
2569 device = LoopbackDevice("hda1", "vfat")
2570 mountpoint = FileSystemSetEntry (device, '/')
2571 fsset.add(mountpoint)
2572
2573 device = SwapFileDevice("/SWAP")
2574 mountpoint = FileSystemSetEntry (device, "swap", "swap")
2575 fsset.add(mountpoint)
2576
2577 print fsset.fstab()

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