/[smeserver]/cdrom.image/updates/fsset.py
ViewVC logotype

Annotation of /cdrom.image/updates/fsset.py

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (hide annotations) (download) (as text)
Mon Aug 1 05:34:53 2005 UTC (19 years, 4 months ago) by slords
Branch: MAIN
Changes since 1.4: +2 -2 lines
Content type: text/x-python
Missing only applies to raid level 1

1 gordonr 1.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 slords 1.3 self.checkable = 0
145 gordonr 1.1 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 slords 1.3 def checkDevice(self, entry, progress, chroot='/'):
275     if self.isCheckable():
276     raise RuntimeError, "checkDevice method not defined"
277    
278 gordonr 1.1 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 slords 1.3 def isCheckable(self):
289     return self.checkable
290    
291 gordonr 1.1 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 slords 1.3 self.checkable = 1
519 gordonr 1.1 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 slords 1.3
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 gordonr 1.1
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 slords 1.2 ret['mbr'] = (bl.drivelist[0], N_("Master Boot Record (MBR)"))
1246 gordonr 1.1 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 slords 1.3 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 gordonr 1.1 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 slords 1.4 def checkFilesystems (self, chroot='/'):
1511     for entry in self.entries:
1512     if entry.fsystem.isCheckable():
1513     self.checkEntry(entry, chroot)
1514    
1515 gordonr 1.1 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 slords 1.5 if self.numDisks == 1 and self.level == 1:
1962 gordonr 1.1 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 slords 1.5 if self.numDisks == 1 and self.level == 1:
1969 gordonr 1.1 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 slords 1.3 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 slords 1.4 if os.WIFEXITED(status) and ((os.WEXITSTATUS(status) == 0) or (os.WEXITSTATUS(status) == 1)):
2648 slords 1.3 return 0
2649    
2650     return 1
2651    
2652 gordonr 1.1 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