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

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

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