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

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