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

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

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