/[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.3 - (show annotations) (download) (as text)
Mon Aug 1 04:14:22 2005 UTC (19 years, 3 months ago) by slords
Branch: MAIN
Changes since 1.2: +94 -0 lines
Content type: text/x-python
Add fsckFilesystem with progress bar for use after converting to raid

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

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