/[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.8 - (show annotations) (download) (as text)
Wed Apr 5 04:20:56 2006 UTC (18 years, 7 months ago) by slords
Branch: MAIN
Changes since 1.7: +23 -0 lines
Content type: text/x-python
Create /boot partition first to get it in sync faster.
Install grub so hard drives can fail nicely.

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 (entry.mountpoint != '/boot'):
1452 continue
1453 if (not entry.fsystem.isFormattable() or not entry.getFormat()
1454 or entry.isMounted()):
1455 notformatted.append(entry)
1456 continue
1457 try:
1458 self.formatEntry(entry, chroot)
1459 formatted.append(entry)
1460 except SystemError:
1461 if self.messageWindow:
1462 self.messageWindow(_("Error"),
1463 _("An error occurred trying to "
1464 "format %s. This problem is "
1465 "serious, and the install cannot "
1466 "continue.\n\n"
1467 "Press <Enter> to reboot your system.")
1468 % (entry.device.getDevice(),))
1469 sys.exit(0)
1470
1471 for entry in self.entries:
1472 if (entry.mountpoint == '/boot'):
1473 continue
1474 if (not entry.fsystem.isFormattable() or not entry.getFormat()
1475 or entry.isMounted()):
1476 notformatted.append(entry)
1477 continue
1478 try:
1479 self.formatEntry(entry, chroot)
1480 formatted.append(entry)
1481 except SystemError:
1482 if self.messageWindow:
1483 self.messageWindow(_("Error"),
1484 _("An error occurred trying to "
1485 "format %s. This problem is "
1486 "serious, and the install cannot "
1487 "continue.\n\n"
1488 "Press <Enter> to reboot your system.")
1489 % (entry.device.getDevice(),))
1490 sys.exit(0)
1491
1492 for entry in formatted:
1493 try:
1494 self.labelEntry(entry, chroot)
1495 except SystemError:
1496 # should be OK, we'll still use the device name to mount.
1497 pass
1498
1499 # go through and have labels for the ones we don't format
1500 for entry in notformatted:
1501 dev = entry.device.getDevice()
1502 if not dev or dev == "none":
1503 continue
1504 if not entry.mountpoint or entry.mountpoint == "swap":
1505 continue
1506 try:
1507 label = isys.readFSLabel(dev)
1508 except:
1509 continue
1510 if label:
1511 entry.setLabel(label)
1512 else:
1513 self.labelEntry(entry, chroot)
1514
1515 def haveMigratedFilesystems(self):
1516 return self.migratedfs
1517
1518 def migrateFilesystems (self, chroot='/'):
1519 if self.migratedfs:
1520 return
1521
1522 for entry in self.entries:
1523 if not entry.origfsystem:
1524 continue
1525
1526 if not entry.origfsystem.isMigratable() or not entry.getMigrate():
1527 continue
1528 try:
1529 entry.origfsystem.migrateFileSystem(entry, self.messageWindow,
1530 chroot)
1531 except SystemError:
1532 if self.messageWindow:
1533 self.messageWindow(_("Error"),
1534 _("An error occurred trying to "
1535 "migrate %s. This problem is "
1536 "serious, and the install cannot "
1537 "continue.\n\n"
1538 "Press <Enter> to reboot your system.")
1539 % (entry.device.getDevice(),))
1540 sys.exit(0)
1541
1542 self.migratedfs = 1
1543
1544 def mountFilesystems(self, instPath = '/', raiseErrors = 0, readOnly = 0):
1545 for entry in self.entries:
1546 if not entry.fsystem.isMountable():
1547 continue
1548 try:
1549 log("trying to mount %s on %s" %(entry.device.getDevice(), entry.mountpoint))
1550 entry.mount(instPath, readOnly = readOnly)
1551 self.mountcount = self.mountcount + 1
1552 except OSError, (num, msg):
1553 if self.messageWindow:
1554 if num == errno.EEXIST:
1555 self.messageWindow(_("Invalid mount point"),
1556 _("An error occurred when trying "
1557 "to create %s. Some element of "
1558 "this path is not a directory. "
1559 "This is a fatal error and the "
1560 "install cannot continue.\n\n"
1561 "Press <Enter> to reboot your "
1562 "system.") % (entry.mountpoint,))
1563 else:
1564 self.messageWindow(_("Invalid mount point"),
1565 _("An error occurred when trying "
1566 "to create %s: %s. This is "
1567 "a fatal error and the install "
1568 "cannot continue.\n\n"
1569 "Press <Enter> to reboot your "
1570 "system.") % (entry.mountpoint,
1571 msg))
1572 sys.exit(0)
1573 except SystemError, (num, msg):
1574 if raiseErrors:
1575 raise SystemError, (num, msg)
1576 if self.messageWindow:
1577 self.messageWindow(_("Error"),
1578 _("Error mounting device %s as %s: "
1579 "%s\n\n"
1580 "This most likely means this "
1581 "partition has not been formatted."
1582 "\n\n"
1583 "Press OK to reboot your system.")
1584 % (entry.device.getDevice(),
1585 entry.mountpoint, msg))
1586 sys.exit(0)
1587
1588 self.makeLVMNodes(instPath)
1589
1590 def makeLVMNodes(self, instPath, trylvm1 = 0):
1591 # XXX hack to make the device node exist for the root fs if
1592 # it's a logical volume so that mkinitrd can create the initrd.
1593 root = self.getEntryByMountPoint("/")
1594
1595 rootlvm1 = 0
1596 if trylvm1:
1597 dev = root.device.getDevice()
1598 # lvm1 major is 58
1599 if os.access("%s/dev/%s" %(instPath, dev), os.R_OK) and posix.major(os.stat("%s/dev/%s" %(instPath, dev)).st_rdev) == 58:
1600 rootlvm1 = 1
1601
1602 if isinstance(root.device, LogicalVolumeDevice) or rootlvm1:
1603 # now make sure all of the device nodes exist. *sigh*
1604 rc = iutil.execWithRedirect("lvm",
1605 ["lvm", "vgmknodes", "-v"],
1606 stdout = "/tmp/lvmout",
1607 stderr = "/tmp/lvmout",
1608 searchPath = 1)
1609
1610 rootDev = "/dev/%s" % (root.device.getDevice(),)
1611 rootdir = instPath + rootDev[:string.rfind(rootDev, "/")]
1612 if not os.path.exists(instPath + "/dev/mapper/control"):
1613 iutil.makeDMNode(root=instPath)
1614 if not os.path.isdir(rootdir):
1615 os.makedirs(rootdir)
1616 dmdev = "/dev/mapper/" + root.device.getDevice().replace("/", "-")
1617 if os.path.exists(instPath + dmdev):
1618 os.unlink(instPath + dmdev)
1619 iutil.copyDeviceNode(dmdev, instPath + dmdev)
1620 # unlink existing so that we dtrt on upgrades
1621 if os.path.exists(instPath + rootDev):
1622 os.unlink(instPath + rootDev)
1623 os.symlink(dmdev, instPath + rootDev)
1624 if not os.path.isdir("%s/etc/lvm" %(instPath,)):
1625 os.makedirs("%s/etc/lvm" %(instPath,))
1626
1627 def filesystemSpace(self, chroot='/'):
1628 space = []
1629 for entry in self.entries:
1630 if not entry.isMounted():
1631 continue
1632 # we can't put swap files on swap partitions; that's nonsense
1633 if entry.mountpoint == "swap":
1634 continue
1635 path = "%s/%s" % (chroot, entry.mountpoint)
1636 try:
1637 space.append((entry.mountpoint, isys.fsSpaceAvailable(path)))
1638 except SystemError:
1639 log("failed to get space available in filesystemSpace() for %s" %(entry.mountpoint,))
1640
1641 def spaceSort(a, b):
1642 (m1, s1) = a
1643 (m2, s2) = b
1644
1645 if (s1 > s2):
1646 return -1
1647 elif s1 < s2:
1648 return 1
1649
1650 return 0
1651
1652 space.sort(spaceSort)
1653 return space
1654
1655 def hasDirtyFilesystems(self, mountpoint):
1656 ret = []
1657
1658 for entry in self.entries:
1659 # XXX - multifsify, virtualize isdirty per fstype
1660 if entry.fsystem.getName() != "ext2": continue
1661 if entry.getFormat(): continue
1662 if isinstance(entry.device.getDevice(), BindMountDevice): continue
1663
1664 try:
1665 if isys.ext2IsDirty(entry.device.getDevice()):
1666 log("%s is a dirty ext2 partition" % entry.device.getDevice())
1667 ret.append(entry.device.getDevice())
1668 except Exception, e:
1669 log("got an exception checking %s for being dirty, hoping it's not" %(entry.device.getDevice(),))
1670
1671 return ret
1672
1673 def umountFilesystems(self, instPath, ignoreErrors = 0):
1674 # XXX remove special case
1675 try:
1676 isys.umount(instPath + '/proc/bus/usb', removeDir = 0)
1677 log("Umount USB OK")
1678 except:
1679 # log("Umount USB Fail")
1680 pass
1681
1682 # take a slice so we don't modify self.entries
1683 reverse = self.entries[:]
1684 reverse.reverse()
1685
1686 for entry in reverse:
1687 entry.umount(instPath)
1688
1689 class FileSystemSetEntry:
1690 def __init__ (self, device, mountpoint,
1691 fsystem=None, options=None,
1692 origfsystem=None, migrate=0,
1693 order=-1, fsck=-1, format=0,
1694 badblocks = 0):
1695 if not fsystem:
1696 fsystem = fileSystemTypeGet("ext2")
1697 self.device = device
1698 self.mountpoint = mountpoint
1699 self.fsystem = fsystem
1700 self.origfsystem = origfsystem
1701 self.migrate = migrate
1702 if options:
1703 self.options = options
1704 else:
1705 self.options = fsystem.getDefaultOptions(mountpoint)
1706 self.mountcount = 0
1707 self.label = None
1708 if fsck == -1:
1709 self.fsck = fsystem.isChecked()
1710 else:
1711 self.fsck = fsck
1712 if order == -1:
1713 if mountpoint == '/':
1714 self.order = 1
1715 elif self.fsck:
1716 self.order = 2
1717 else:
1718 self.order = 0
1719 else:
1720 self.order = order
1721 if format and not fsystem.isFormattable():
1722 raise RuntimeError, ("file system type %s is not formattable, "
1723 "but has been added to fsset with format "
1724 "flag on" % fsystem.getName())
1725 self.format = format
1726 self.badblocks = badblocks
1727
1728 def mount(self, chroot='/', devPrefix='/tmp', readOnly = 0):
1729 device = self.device.setupDevice(chroot, devPrefix=devPrefix)
1730
1731 # FIXME: we really should migrate before turnOnFilesystems.
1732 # but it's too late now
1733 if (self.migrate == 1) and (self.origfsystem is not None):
1734 self.origfsystem.mount(device, "%s/%s" % (chroot, self.mountpoint),
1735 readOnly = readOnly,
1736 bindMount = isinstance(self.device,
1737 BindMountDevice))
1738 else:
1739 self.fsystem.mount(device, "%s/%s" % (chroot, self.mountpoint),
1740 readOnly = readOnly,
1741 bindMount = isinstance(self.device,
1742 BindMountDevice))
1743
1744 self.mountcount = self.mountcount + 1
1745
1746 def umount(self, chroot='/'):
1747 if self.mountcount > 0:
1748 try:
1749 self.fsystem.umount(self.device, "%s/%s" % (chroot,
1750 self.mountpoint))
1751 self.mountcount = self.mountcount - 1
1752 except RuntimeError:
1753 pass
1754
1755 def setFileSystemType(self, fstype):
1756 self.fsystem = fstype
1757
1758 def setBadblocks(self, state):
1759 self.badblocks = state
1760
1761 def getBadblocks(self):
1762 return self.badblocks
1763
1764 def getMountPoint(self):
1765 return self.mountpoint
1766
1767 def setFormat (self, state):
1768 if self.migrate and state:
1769 raise ValueError, "Trying to set format bit on when migrate is set!"
1770 self.format = state
1771
1772 def getFormat (self):
1773 return self.format
1774
1775 def setMigrate (self, state):
1776 if self.format and state:
1777 raise ValueError, "Trying to set migrate bit on when format is set!"
1778
1779 self.migrate = state
1780
1781 def getMigrate (self):
1782 return self.migrate
1783
1784 def isMounted (self):
1785 return self.mountcount > 0
1786
1787 def getLabel (self):
1788 return self.label
1789
1790 def setLabel (self, label):
1791 self.label = label
1792
1793 def __str__(self):
1794 if not self.mountpoint:
1795 mntpt = "None"
1796 else:
1797 mntpt = self.mountpoint
1798
1799 str = ("fsentry -- device: %(device)s mountpoint: %(mountpoint)s\n"
1800 " fsystem: %(fsystem)s format: %(format)s\n"
1801 " ismounted: %(mounted)s \n"%
1802 {"device": self.device.getDevice(), "mountpoint": mntpt,
1803 "fsystem": self.fsystem.getName(), "format": self.format,
1804 "mounted": self.mountcount})
1805 return str
1806
1807
1808 class Device:
1809 def __init__(self):
1810 self.device = "none"
1811 self.fsoptions = {}
1812 self.label = None
1813 self.isSetup = 0
1814 self.doLabel = 1
1815
1816 def getComment (self):
1817 return ""
1818
1819 def getDevice (self, asBoot = 0):
1820 return self.device
1821
1822 def setupDevice (self, chroot='/', devPrefix='/tmp'):
1823 return self.device
1824
1825 def cleanupDevice (self, chroot, devPrefix='/tmp'):
1826 pass
1827
1828 def solidify (self):
1829 pass
1830
1831 def getName(self):
1832 return self.__class__.__name__
1833
1834 def getLabel(self):
1835 try:
1836 return isys.readFSLabel(self.setupDevice(), makeDevNode = 0)
1837 except:
1838 return ""
1839
1840 class DevDevice(Device):
1841 """Device with a device node rooted in /dev that we just always use
1842 the pre-created device node for."""
1843 def __init__(self, dev):
1844 Device.__init__(self)
1845 self.device = dev
1846
1847 def getDevice(self, asBoot = 0):
1848 return self.device
1849
1850 def setupDevice(self, chroot='/', devPrefix='/dev'):
1851 return "/dev/%s" %(self.getDevice(),)
1852
1853 class RAIDDevice(Device):
1854 # XXX usedMajors does not take in account any EXISTING md device
1855 # on the system for installs. We need to examine all partitions
1856 # to investigate which minors are really available.
1857 usedMajors = {}
1858
1859 # members is a list of Device based instances that will be
1860 # a part of this raid device
1861 def __init__(self, level, members, minor=-1, spares=0, existing=0,
1862 chunksize = 64):
1863 Device.__init__(self)
1864 self.level = level
1865 self.members = members
1866 self.spares = spares
1867 self.numDisks = len(members) - spares
1868 self.isSetup = existing
1869 self.doLabel = None
1870 if chunksize is not None:
1871 self.chunksize = chunksize
1872 else:
1873 self.chunksize = 256
1874
1875 if len(members) < spares:
1876 raise RuntimeError, ("you requiested more spare devices "
1877 "than online devices!")
1878
1879 if level == 5:
1880 if self.numDisks < 3:
1881 raise RuntimeError, "RAID 5 requires at least 3 online members"
1882
1883 # there are 32 major md devices, 0...31
1884 if minor == -1 or minor is None:
1885 for I in range(32):
1886 if not RAIDDevice.usedMajors.has_key(I):
1887 minor = I
1888 break
1889
1890 if minor == -1:
1891 raise RuntimeError, ("Unable to allocate minor number for "
1892 "raid device")
1893
1894 RAIDDevice.usedMajors[minor] = None
1895 self.device = "md" + str(minor)
1896 self.minor = minor
1897
1898 # make sure the list of raid members is sorted
1899 self.members.sort()
1900
1901 def __del__ (self):
1902 del RAIDDevice.usedMajors[self.minor]
1903
1904 def ext2Args (self):
1905 if self.level == 5:
1906 return [ '-R', 'stride=%d' % ((self.numDisks - 1) * 16) ]
1907 elif self.level == 0:
1908 return [ '-R', 'stride=%d' % (self.numDisks * 16) ]
1909 return []
1910
1911 def mdadmLine (self, devPrefix="/dev"):
1912 return "ARRAY %s/%s super-minor=%s\n" %(devPrefix, self.device,
1913 self.minor)
1914
1915 def raidTab (self, devPrefix='/dev'):
1916 d = self.numDisks
1917 if d == 1:
1918 d = 2
1919 entry = ""
1920 entry = entry + "raiddev %s/%s\n" % (devPrefix,
1921 self.device,)
1922 entry = entry + "raid-level %d\n" % (self.level,)
1923 entry = entry + "nr-raid-disks %d\n" % (d)
1924 entry = entry + "chunk-size %s\n" %(self.chunksize,)
1925 entry = entry + "persistent-superblock 1\n"
1926 entry = entry + "nr-spare-disks %d\n" % (self.spares,)
1927 i = 0
1928 for device in self.members[:self.numDisks]:
1929 entry = entry + " device %s/%s\n" % (devPrefix,
1930 device)
1931 entry = entry + " raid-disk %d\n" % (i,)
1932 i = i + 1
1933 i = 0
1934 for device in self.members[self.numDisks:]:
1935 entry = entry + " device %s/%s\n" % (devPrefix,
1936 device)
1937 entry = entry + " spare-disk %d\n" % (i,)
1938 i = i + 1
1939 if self.numDisks == 1:
1940 entry = entry + " device dev/null\n"
1941 entry = entry + " failed-disk 1\n"
1942 return entry
1943
1944 def setupDevice (self, chroot="/", devPrefix='/dev'):
1945 def devify(x):
1946 return "/dev/%s" %(x,)
1947
1948 node = "%s/%s" % (devPrefix, self.device)
1949 isys.makeDevInode(self.device, node)
1950
1951 if not self.isSetup:
1952 for device in self.members:
1953 PartitionDevice(device).setupDevice(chroot,
1954 devPrefix=devPrefix)
1955
1956 args = ["/usr/sbin/mdadm", "--create", "/dev/%s" %(self.device,),
1957 "--run", "--chunk=%s" %(self.chunksize,),
1958 "--level=%s" %(self.level,),
1959 ]
1960
1961 if self.spares > 0:
1962 args.append("--spare-devices=%s" %(self.spares,),)
1963
1964 if self.numDisks == 1 and self.level == 1:
1965 args.append("--raid-devices=2")
1966 else:
1967 args.append("--raid-devices=%s" %(self.numDisks,),)
1968
1969 args.extend(map(devify, self.members))
1970
1971 if self.numDisks == 1 and self.level == 1:
1972 args.append("missing")
1973
1974 log("going to run: %s" %(args,))
1975 iutil.execWithRedirect (args[0], args,
1976 stderr="/dev/tty5", stdout="/dev/tty5")
1977 raid.register_raid_device(self.device, self.members[:],
1978 self.level, self.numDisks)
1979 self.isSetup = 1
1980 else:
1981 isys.raidstart(self.device, self.members[0])
1982 return node
1983
1984 def getDevice (self, asBoot = 0):
1985 if not asBoot:
1986 return self.device
1987 else:
1988 return self.members[0]
1989
1990 def solidify(self):
1991 return
1992
1993 ext2 = fileSystemTypeGet("ext2")
1994 ext2.registerDeviceArgumentFunction(RAIDDevice, RAIDDevice.ext2Args)
1995
1996 class VolumeGroupDevice(Device):
1997 def __init__(self, name, physvols, pesize = 32768, existing = 0):
1998 """Creates a VolumeGroupDevice.
1999
2000 name is the name of the volume group
2001 physvols is a list of Device objects which are the physical volumes
2002 pesize is the size of physical extents in kilobytes
2003 existing is whether this vg previously existed.
2004 """
2005
2006 Device.__init__(self)
2007 self.physicalVolumes = physvols
2008 self.isSetup = existing
2009 self.name = name
2010 self.device = name
2011 self.isSetup = existing
2012
2013 self.physicalextentsize = pesize
2014
2015 def setupDevice (self, chroot="/", devPrefix='/tmp'):
2016 nodes = []
2017 for volume in self.physicalVolumes:
2018 # XXX the lvm tools are broken and will only work for /dev
2019 node = volume.setupDevice(chroot, devPrefix="/dev")
2020
2021 # XXX I should check if the pv is set up somehow so that we
2022 # can have preexisting vgs and add new pvs to them.
2023 if not self.isSetup:
2024 # now make the device into a real physical volume
2025 # XXX I don't really belong here. should
2026 # there be a PhysicalVolumeDevice(PartitionDevice) ?
2027 lvm.writeForceConf()
2028 rc = iutil.execWithRedirect("lvm",
2029 ["lvm", "pvcreate", "-ff", "-y",
2030 "-v", node],
2031 stdout = "/tmp/lvmout",
2032 stderr = "/tmp/lvmout",
2033 searchPath = 1)
2034 if rc:
2035 raise SystemError, "pvcreate failed for %s" % (volume,)
2036 lvm.unlinkConf()
2037
2038 lvm.wipeOtherMetadataFromPV(node)
2039
2040 nodes.append(node)
2041
2042 if not self.isSetup:
2043 # rescan now that we've recreated pvs. ugh.
2044 lvm.writeForceConf()
2045 lvm.vgscan()
2046
2047 args = [ "lvm", "vgcreate", "-v", "-An",
2048 "-s", "%sk" %(self.physicalextentsize,),
2049 self.name ]
2050 args.extend(nodes)
2051 rc = iutil.execWithRedirect(args[0], args,
2052 stdout = "/tmp/lvmout",
2053 stderr = "/tmp/lvmout",
2054 searchPath = 1)
2055
2056 if rc:
2057 raise SystemError, "vgcreate failed for %s" %(self.name,)
2058
2059 lvm.unlinkConf()
2060 self.isSetup = 1
2061 else:
2062 lvm.vgscan()
2063 lvm.vgactivate()
2064
2065 return "/dev/%s" % (self.name,)
2066
2067 def solidify(self):
2068 return
2069
2070 class LogicalVolumeDevice(Device):
2071 # note that size is in megabytes!
2072 def __init__(self, volumegroup, size, vgname, existing = 0):
2073 Device.__init__(self)
2074 self.volumeGroup = volumegroup
2075 self.size = size
2076 self.name = vgname
2077 self.isSetup = 0
2078 self.isSetup = existing
2079 self.doLabel = None
2080
2081 # these are attributes we might want to expose. or maybe not.
2082 # self.chunksize
2083 # self.stripes
2084 # self.stripesize
2085 # self.extents
2086 # self.readaheadsectors
2087
2088 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2089 if not self.isSetup:
2090 lvm.writeForceConf()
2091 rc = iutil.execWithRedirect("lvm",
2092 ["lvm", "lvcreate", "-L",
2093 "%dM" % (self.size,),
2094 "-n", self.name, "-An",
2095 self.volumeGroup],
2096 stdout = "/tmp/lvmout",
2097 stderr = "/tmp/lvmout",
2098 searchPath = 1)
2099 if rc:
2100 raise SystemError, "lvcreate failed for %s" %(self.name,)
2101 lvm.unlinkConf()
2102 self.isSetup = 1
2103
2104 return "/dev/%s" % (self.getDevice(),)
2105
2106 def getDevice(self, asBoot = 0):
2107 return "%s/%s" % (self.volumeGroup, self.name)
2108
2109 def solidify(self):
2110 return
2111
2112
2113 class PartitionDevice(Device):
2114 def __init__(self, partition):
2115 Device.__init__(self)
2116 if type(partition) != types.StringType:
2117 raise ValueError, "partition must be a string"
2118 self.device = partition
2119
2120 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2121 path = '%s/%s' % (devPrefix, self.getDevice(),)
2122 isys.makeDevInode(self.getDevice(), path)
2123 return path
2124
2125 class PartedPartitionDevice(PartitionDevice):
2126 def __init__(self, partition):
2127 Device.__init__(self)
2128 self.device = None
2129 self.partition = partition
2130
2131 def getDevice(self, asBoot = 0):
2132 if not self.partition:
2133 return self.device
2134
2135 return partedUtils.get_partition_name(self.partition)
2136
2137 def solidify(self):
2138 # drop reference on the parted partition object and note
2139 # the current minor number allocation
2140 self.device = self.getDevice()
2141 self.partition = None
2142
2143 class BindMountDevice(Device):
2144 def __init__(self, directory):
2145 Device.__init__(self)
2146 self.device = directory
2147
2148 def setupDevice(self, chroot="/", devPrefix="/tmp"):
2149 return chroot + self.device
2150
2151
2152
2153 class SwapFileDevice(Device):
2154 def __init__(self, file):
2155 Device.__init__(self)
2156 self.device = file
2157 self.size = 0
2158
2159 def setSize (self, size):
2160 self.size = size
2161
2162 def setupDevice (self, chroot="/", devPrefix='/tmp'):
2163 file = os.path.normpath(chroot + self.getDevice())
2164 if not os.access(file, os.R_OK):
2165 if self.size:
2166 # make sure the permissions are set properly
2167 fd = os.open(file, os.O_CREAT, 0600)
2168 os.close(fd)
2169 isys.ddfile(file, self.size, None)
2170 else:
2171 raise SystemError, (0, "swap file creation necessary, but "
2172 "required size is unknown.")
2173 return file
2174
2175 # This is a device that describes a swap file that is sitting on
2176 # the loopback filesystem host for partitionless installs.
2177 # The piggypath is the place where the loopback file host filesystem
2178 # will be mounted
2179 class PiggybackSwapFileDevice(SwapFileDevice):
2180 def __init__(self, piggypath, file):
2181 SwapFileDevice.__init__(self, file)
2182 self.piggypath = piggypath
2183
2184 def setupDevice(self, chroot="/", devPrefix='/tmp'):
2185 return SwapFileDevice.setupDevice(self, self.piggypath, devPrefix)
2186
2187 class LoopbackDevice(Device):
2188 def __init__(self, hostPartition, hostFs):
2189 Device.__init__(self)
2190 self.host = "/dev/" + hostPartition
2191 self.hostfs = hostFs
2192 self.device = "loop1"
2193
2194 def setupDevice(self, chroot="/", devPrefix='/tmp/'):
2195 if not self.isSetup:
2196 isys.mount(self.host[5:], "/mnt/loophost", fstype = "vfat")
2197 self.device = allocateLoopback("/mnt/loophost/redhat.img")
2198 if not self.device:
2199 raise SystemError, "Unable to allocate loopback device"
2200 self.isSetup = 1
2201 path = '%s/%s' % (devPrefix, self.getDevice())
2202 else:
2203 path = '%s/%s' % (devPrefix, self.getDevice())
2204 isys.makeDevInode(self.getDevice(), path)
2205 path = os.path.normpath(path)
2206 return path
2207
2208 def getComment (self):
2209 return "# LOOP1: %s %s /redhat.img\n" % (self.host, self.hostfs)
2210
2211 def makeDevice(dev):
2212 if dev.startswith('md'):
2213 try:
2214 (mdname, devices, level, numActive) = raid.lookup_raid_device(dev)
2215 device = RAIDDevice(level, devices,
2216 minor=int(mdname[2:]),
2217 spares=len(devices) - numActive,
2218 existing=1)
2219 except KeyError:
2220 device = DevDevice(dev)
2221 else:
2222 device = DevDevice(dev)
2223 return device
2224
2225 # XXX fix RAID
2226 def readFstab (path, intf = None):
2227 fsset = FileSystemSet()
2228
2229 # first, we look at all the disks on the systems and get any ext2/3
2230 # labels off of the filesystem.
2231 # temporary, to get the labels
2232 diskset = partedUtils.DiskSet()
2233 diskset.openDevices()
2234 labels = diskset.getLabels()
2235
2236 labelToDevice = {}
2237 for device, label in labels.items():
2238 if not labelToDevice.has_key(label):
2239 labelToDevice[label] = device
2240 elif intf is not None:
2241 intf.messageWindow(_("Duplicate Labels"),
2242 _("Multiple devices on your system are "
2243 "labelled %s. Labels across devices must be "
2244 "unique for your system to function "
2245 "properly.\n\n"
2246 "Please fix this problem and restart the "
2247 "installation process.") %(label,),
2248 type="custom", custom_icon="error",
2249 custom_buttons=[_("_Reboot")])
2250 sys.exit(0)
2251 else:
2252 log("WARNING!!! Duplicate labels for %s, but no intf so trying "
2253 "to continue" %(label,))
2254
2255
2256 # mark these labels found on the system as used so the factory
2257 # doesn't give them to another device
2258 labelFactory.reserveLabels(labels)
2259
2260 loopIndex = {}
2261
2262 f = open (path, "r")
2263 lines = f.readlines ()
2264 f.close()
2265
2266 for line in lines:
2267 fields = string.split (line)
2268
2269 if not fields: continue
2270
2271 if line[0] == "#":
2272 # skip all comments
2273 continue
2274
2275 # all valid fstab entries have 6 fields; if the last two are missing
2276 # they are assumed to be zero per fstab(5)
2277 if len(fields) < 4:
2278 continue
2279 elif len(fields) == 4:
2280 fields.append(0)
2281 fields.append(0)
2282 elif len(fields) == 5:
2283 fields.append(0)
2284 elif len(fields) > 6:
2285 continue
2286 if string.find(fields[3], "noauto") != -1: continue
2287
2288 # shenanigans to handle ext3,ext2 format in fstab
2289 fstotry = fields[2]
2290 if fstotry.find(","):
2291 fstotry = fstotry.split(",")
2292 else:
2293 fstotry = [ fstotry ]
2294 fsystem = None
2295 for fs in fstotry:
2296 # if we don't support mounting the filesystem, continue
2297 if not fileSystemTypes.has_key(fs):
2298 continue
2299 fsystem = fileSystemTypeGet(fs)
2300 break
2301 if fsystem is None:
2302 continue
2303
2304 label = None
2305 if fields[0] == "none":
2306 device = Device()
2307 elif ((string.find(fields[3], "bind") != -1) and
2308 fields[0].startswith("/")):
2309 # it's a bind mount, they're Weird (tm)
2310 device = BindMountDevice(fields[0])
2311 fsystem = fileSystemTypeGet("bind")
2312 elif len(fields) >= 6 and fields[0].startswith('LABEL='):
2313 label = fields[0][6:]
2314 if labelToDevice.has_key(label):
2315 device = makeDevice(labelToDevice[label])
2316 else:
2317 log ("Warning: fstab file has LABEL=%s, but this label "
2318 "could not be found on any file system", label)
2319 # bad luck, skip this entry.
2320 continue
2321 elif fields[2] == "swap" and not fields[0].startswith('/dev/'):
2322 # swap files
2323 file = fields[0]
2324
2325 if file.startswith('/initrd/loopfs/'):
2326 file = file[14:]
2327 device = PiggybackSwapFileDevice("/mnt/loophost", file)
2328 else:
2329 device = SwapFileDevice(file)
2330 elif fields[0].startswith('/dev/loop'):
2331 # look up this loop device in the index to find the
2332 # partition that houses the filesystem image
2333 # XXX currently we assume /dev/loop1
2334 if loopIndex.has_key(device):
2335 (dev, fs) = loopIndex[device]
2336 device = LoopbackDevice(dev, fs)
2337 elif fields[0].startswith('/dev/'):
2338 device = makeDevice(fields[0][5:])
2339 else:
2340 continue
2341
2342 # if they have a filesystem being mounted as auto, we need
2343 # to sniff around a bit to figure out what it might be
2344 # if we fail at all, though, just ignore it
2345 if fsystem == "auto" and device.getDevice() != "none":
2346 try:
2347 tmp = partedUtils.sniffFilesystemType("/dev/%s" %(device.setupDevice(),))
2348 if tmp is not None:
2349 fsystem = tmp
2350 except:
2351 pass
2352
2353 entry = FileSystemSetEntry(device, fields[1], fsystem, fields[3],
2354 origfsystem=fsystem)
2355 if label:
2356 entry.setLabel(label)
2357 fsset.add(entry)
2358 return fsset
2359
2360 def getDevFD(device):
2361 try:
2362 fd = os.open(device, os.O_RDONLY)
2363 except:
2364 file = '/tmp/' + device
2365 try:
2366 isys.makeDevInode(device, file)
2367 fd = os.open(file, os.O_RDONLY)
2368 except:
2369 return -1
2370 return fd
2371
2372 def isValidExt2(device):
2373 fd = getDevFD(device)
2374 if fd == -1:
2375 return 0
2376
2377 buf = os.read(fd, 2048)
2378 os.close(fd)
2379
2380 if len(buf) != 2048:
2381 return 0
2382
2383 if struct.unpack("<H", buf[1080:1082]) == (0xef53,):
2384 return 1
2385
2386 return 0
2387
2388 def isValidXFS(device):
2389 fd = getDevFD(device)
2390 if fd == -1:
2391 return 0
2392
2393 buf = os.read(fd, 4)
2394 os.close(fd)
2395
2396 if len(buf) != 4:
2397 return 0
2398
2399 if buf == "XFSB":
2400 return 1
2401
2402 return 0
2403
2404 def isValidReiserFS(device):
2405 fd = getDevFD(device)
2406 if fd == -1:
2407 return 0
2408
2409 '''
2410 ** reiserfs 3.5.x super block begins at offset 8K
2411 ** reiserfs 3.6.x super block begins at offset 64K
2412 All versions have a magic value of "ReIsEr" at
2413 offset 0x34 from start of super block
2414 '''
2415 reiserMagicVal = "ReIsEr"
2416 reiserMagicOffset = 0x34
2417 reiserSBStart = [64*1024, 8*1024]
2418 bufSize = 0x40 # just large enough to include the magic value
2419 for SBOffset in reiserSBStart:
2420 try:
2421 os.lseek(fd, SBOffset, 0)
2422 buf = os.read(fd, bufSize)
2423 except:
2424 buf = ""
2425
2426 if len(buf) < bufSize:
2427 continue
2428
2429 if (buf[reiserMagicOffset:reiserMagicOffset+len(reiserMagicVal)] ==
2430 reiserMagicVal):
2431 os.close(fd)
2432 return 1
2433
2434 os.close(fd)
2435 return 0
2436
2437 def isValidJFS(device):
2438 fd = getDevFD(device)
2439 if fd == -1:
2440 return 0
2441
2442 try:
2443 os.lseek(fd, 32768, 0)
2444 buf = os.read(fd, 128)
2445 except:
2446 buf = ""
2447
2448 os.close(fd)
2449 if len(buf) < 4:
2450 return 0
2451
2452 if (buf[0:4] == "JFS1"):
2453 return 1
2454
2455 return 0
2456
2457 # this will return a list of types of filesystems which device
2458 # looks like it could be to try mounting as
2459 def getFStoTry(device):
2460 rc = []
2461
2462 if isValidXFS(device):
2463 rc.append("xfs")
2464
2465 if isValidReiserFS(device):
2466 rc.append("reiserfs")
2467
2468 if isValidJFS(device):
2469 rc.append("jfs")
2470
2471 if isValidExt2(device):
2472 if os.access(device, os.O_RDONLY):
2473 create = 0
2474 else:
2475 create = 1
2476 if isys.ext2HasJournal(device, makeDevNode = create):
2477 rc.append("ext3")
2478 rc.append("ext2")
2479
2480 # FIXME: need to check for swap
2481
2482 return rc
2483
2484 def allocateLoopback(file):
2485 found = 1
2486 for i in range(8):
2487 dev = "loop%d" % (i,)
2488 path = "/tmp/loop%d" % (i,)
2489 isys.makeDevInode(dev, path)
2490 try:
2491 isys.losetup(path, file)
2492 found = 1
2493 except SystemError:
2494 continue
2495 break
2496 if found:
2497 return dev
2498 return None
2499
2500 def ext2FormatFilesystem(argList, messageFile, windowCreator, mntpoint):
2501 if windowCreator:
2502 w = windowCreator(_("Formatting"),
2503 _("Formatting %s file system...") % (mntpoint,), 100)
2504 else:
2505 w = None
2506
2507 fd = os.open(messageFile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
2508 p = os.pipe()
2509 childpid = os.fork()
2510 if not childpid:
2511 os.close(p[0])
2512 os.dup2(p[1], 1)
2513 os.dup2(fd, 2)
2514 os.close(p[1])
2515 os.close(fd)
2516 os.execv(argList[0], argList)
2517 log("failed to exec %s", argList)
2518 os._exit(1)
2519
2520 os.close(p[1])
2521
2522 # ignoring SIGCHLD would be cleaner then ignoring EINTR, but
2523 # we can't use signal() in this thread?
2524
2525 s = 'a'
2526 while s and s != '\b':
2527 try:
2528 s = os.read(p[0], 1)
2529 except OSError, args:
2530 (num, str) = args
2531 if (num != 4):
2532 raise IOError, args
2533
2534 os.write(fd, s)
2535
2536 num = ''
2537 sync = 0
2538 while s:
2539 try:
2540 s = os.read(p[0], 1)
2541 os.write(fd, s)
2542
2543 if s != '\b':
2544 try:
2545 num = num + s
2546 except:
2547 pass
2548 else:
2549 if num and len(num):
2550 l = string.split(num, '/')
2551 try:
2552 val = (int(l[0]) * 100) / int(l[1])
2553 except (IndexError, TypeError):
2554 pass
2555 else:
2556 w and w.set(val)
2557 # sync every 10%
2558 if sync + 10 < val:
2559 isys.sync()
2560 sync = val
2561 num = ''
2562 except OSError, args:
2563 (errno, str) = args
2564 if (errno != 4):
2565 raise IOError, args
2566
2567 try:
2568 (pid, status) = os.waitpid(childpid, 0)
2569 except OSError, (num, msg):
2570 log("exception from waitpid while formatting: %s %s" %(num, msg))
2571 status = None
2572 os.close(fd)
2573
2574 w and w.pop()
2575
2576 # *shrug* no clue why this would happen, but hope that things are fine
2577 if status is None:
2578 return 0
2579
2580 if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0):
2581 return 0
2582
2583 return 1
2584
2585 if __name__ == "__main__":
2586 log.open("foo")
2587
2588 fsset = readFstab("fstab")
2589
2590 print fsset.fstab()
2591
2592 sys.exit(0)
2593 fsset = FileSystemSet()
2594 proc = FileSystemSetEntry(Device(), '/proc', 'proc')
2595 fsset.add(proc)
2596 devpts = FileSystemSetEntry(Device(), '/dev/pts', 'devpts')
2597 fsset.add(devpts)
2598
2599 device = LoopbackDevice("hda1", "vfat")
2600 mountpoint = FileSystemSetEntry (device, '/')
2601 fsset.add(mountpoint)
2602
2603 device = SwapFileDevice("/SWAP")
2604 mountpoint = FileSystemSetEntry (device, "swap", "swap")
2605 fsset.add(mountpoint)
2606
2607 print fsset.fstab()

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