/[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.2 - (hide annotations) (download) (as text)
Sun Jul 31 16:24:57 2005 UTC (19 years, 3 months ago) by slords
Branch: MAIN
Changes since 1.1: +1 -0 lines
Content type: text/x-python
Second major pass as anaconda installer
- Install/Upgrade both functional in text & gui
- Added upgrade warning for systems < 21:6.0-11
- TODO: raid migration for upgrades
- TODO: status message for post-{install,upgrade}

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

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