/[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.6 - (show annotations) (download) (as text)
Wed Nov 23 22:49:43 2005 UTC (18 years, 11 months ago) by slords
Branch: MAIN
Changes since 1.5: +19 -0 lines
Content type: text/x-python
Checkpoint

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

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