/[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.8 - (hide annotations) (download) (as text)
Wed Apr 5 04:20:56 2006 UTC (18 years, 6 months ago) by slords
Branch: MAIN
Changes since 1.7: +23 -0 lines
Content type: text/x-python
Create /boot partition first to get it in sync faster.
Install grub so hard drives can fail nicely.

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 slords 1.7 devName = entry.device.getDevice()
739     # we'll keep the SWAP-* naming for all devs but Compaq SMART2
740     # nodes (#170500)
741     if devName[0:6] == "cciss/":
742     swapLabel = "SW-%s" % (devName)
743     else:
744     swapLabel = "SWAP-%s" % (devName)
745     label = labelFactory.createLabel("%s" %swapLabel, self.maxLabelChars)
746 gordonr 1.1 rc = iutil.execWithRedirect ("/usr/sbin/mkswap",
747     [ "mkswap", '-v1', "-L", label, file ],
748     stdout = "/dev/tty5",
749     stderr = "/dev/tty5",
750     searchPath = 1)
751     if rc:
752     raise SystemError
753     entry.setLabel(label)
754    
755     fileSystemTypeRegister(swapFileSystem())
756    
757     class FATFileSystem(FileSystemType):
758     def __init__(self):
759     FileSystemType.__init__(self)
760     self.partedFileSystemType = parted.file_system_type_get("fat32")
761     self.formattable = 1
762     self.checked = 0
763     self.maxSizeMB = 1024 * 1024
764     self.name = "vfat"
765     self.packages = [ "dosfstools" ]
766    
767     def formatDevice(self, entry, progress, chroot='/'):
768     devicePath = entry.device.setupDevice(chroot)
769     devArgs = self.getDeviceArgs(entry.device)
770     args = [ "mkdosfs", devicePath ]
771     args.extend(devArgs)
772    
773     rc = iutil.execWithRedirect("/usr/sbin/mkdosfs", args,
774     stdout = "/dev/tty5",
775     stderr = "/dev/tty5")
776     if rc:
777     raise SystemError
778    
779     fileSystemTypeRegister(FATFileSystem())
780    
781     class NTFSFileSystem(FileSystemType):
782     def __init__(self):
783     FileSystemType.__init__(self)
784     self.partedFileSystemType = parted.file_system_type_get("ntfs")
785     self.formattable = 0
786     self.checked = 0
787     self.name = "ntfs"
788    
789     fileSystemTypeRegister(NTFSFileSystem())
790    
791     class hfsFileSystem(FileSystemType):
792     def __init__(self):
793     FileSystemType.__init__(self)
794     self.partedFileSystemType = parted.file_system_type_get("hfs")
795     self.formattable = 1
796     self.checked = 0
797     self.name = "hfs"
798     self.supported = 0
799    
800     def isMountable(self):
801     return 0
802    
803     def formatDevice(self, entry, progress, chroot='/'):
804     devicePath = entry.device.setupDevice(chroot)
805     devArgs = self.getDeviceArgs(entry.device)
806     args = [ "hformat", devicePath ]
807     args.extend(devArgs)
808    
809     rc = iutil.execWithRedirect("/usr/bin/hformat", args,
810     stdout = "/dev/tty5",
811     stderr = "/dev/tty5")
812     if rc:
813     raise SystemError
814    
815     fileSystemTypeRegister(hfsFileSystem())
816    
817     class applebootstrapFileSystem(hfsFileSystem):
818     def __init__(self):
819     hfsFileSystem.__init__(self)
820     self.partedPartitionFlags = [ parted.PARTITION_BOOT ]
821     self.maxSizeMB = 1
822     self.name = "Apple Bootstrap"
823     if iutil.getPPCMacGen() == "NewWorld":
824     self.supported = 1
825     else:
826     self.supported = 0
827    
828     fileSystemTypeRegister(applebootstrapFileSystem())
829    
830     class prepbootFileSystem(FileSystemType):
831     def __init__(self):
832     FileSystemType.__init__(self)
833     self.partedFileSystemType = None
834 slords 1.7 self.partedPartitionFlags = [ parted.PARTITION_BOOT ]
835 gordonr 1.1 self.checked = 0
836     self.name = "PPC PReP Boot"
837     self.maxSizeMB = 10
838    
839     if iutil.getPPCMachine() == "iSeries":
840     self.maxSizeMB = 64
841    
842     # supported for use on the pseries
843     if (iutil.getPPCMachine() == "pSeries" or
844     iutil.getPPCMachine() == "iSeries"):
845     self.supported = 1
846     self.formattable = 1
847     else:
848     self.supported = 0
849     self.formattable = 0
850    
851     def formatDevice(self, entry, progress, chroot='/'):
852     # copy and paste job from booty/bootloaderInfo.py...
853     def getDiskPart(dev):
854     cut = len(dev)
855     if (dev.startswith('rd/') or dev.startswith('ida/') or
856     dev.startswith('cciss/') or dev.startswith('i2o/')
857     or dev.startswith("sx8/")):
858     if dev[-2] == 'p':
859     cut = -1
860     elif dev[-3] == 'p':
861     cut = -2
862     else:
863     if dev[-2] in string.digits:
864     cut = -2
865     elif dev[-1] in string.digits:
866     cut = -1
867    
868     name = dev[:cut]
869    
870     # hack off the trailing 'p' from /dev/cciss/*, for example
871     if name[-1] == 'p':
872     for letter in name:
873     if letter not in string.letters and letter != "/":
874     name = name[:-1]
875     break
876    
877     if cut < 0:
878     partNum = int(dev[cut:])
879     else:
880     partNum = None
881    
882     return (name, partNum)
883    
884     # FIXME: oh dear is this a hack beyond my wildest imagination.
885     # parted doesn't really know how to do these, so we're going to
886     # exec sfdisk and make it set the partition type. this is bloody
887     # ugly
888     devicePath = entry.device.setupDevice(chroot)
889     (disk, part) = getDiskPart(devicePath)
890     if disk is None or part is None:
891     log("oops, somehow got a bogus device for the PReP partition "
892     "(%s)" %(devicePath,))
893     return
894    
895     args = [ "sfdisk", "--change-id", disk, "%d" %(part,), "41" ]
896     if disk.startswith("/tmp/") and not os.access(disk, os.R_OK):
897     isys.makeDevInode(disk[5:], disk)
898    
899     log("going to run %s" %(args,))
900     rc = iutil.execWithRedirect("/usr/sbin/sfdisk", args,
901     stdout = "/dev/tty5", stderr = "/dev/tty5")
902     if rc:
903     raise SystemError
904    
905     fileSystemTypeRegister(prepbootFileSystem())
906    
907     class ForeignFileSystem(FileSystemType):
908     def __init__(self):
909     FileSystemType.__init__(self)
910     self.formattable = 0
911     self.checked = 0
912     self.name = "foreign"
913    
914     def formatDevice(self, entry, progress, chroot='/'):
915     return
916    
917     fileSystemTypeRegister(ForeignFileSystem())
918    
919     class PsudoFileSystem(FileSystemType):
920     def __init__(self, name):
921     FileSystemType.__init__(self)
922     self.formattable = 0
923     self.checked = 0
924     self.name = name
925     self.supported = 0
926    
927     class ProcFileSystem(PsudoFileSystem):
928     def __init__(self):
929     PsudoFileSystem.__init__(self, "proc")
930    
931     fileSystemTypeRegister(ProcFileSystem())
932    
933     class SysfsFileSystem(PsudoFileSystem):
934     def __init__(self):
935     PsudoFileSystem.__init__(self, "sysfs")
936    
937     fileSystemTypeRegister(SysfsFileSystem())
938    
939     class SelinuxfsFileSystem(PsudoFileSystem):
940     def __init__(self):
941     PsudoFileSystem.__init__(self, "selinuxfs")
942    
943     fileSystemTypeRegister(SelinuxfsFileSystem())
944    
945     class DevptsFileSystem(PsudoFileSystem):
946     def __init__(self):
947     PsudoFileSystem.__init__(self, "devpts")
948     self.defaultOptions = "gid=5,mode=620"
949    
950     def isMountable(self):
951     return 0
952    
953     fileSystemTypeRegister(DevptsFileSystem())
954    
955     class DevshmFileSystem(PsudoFileSystem):
956     def __init__(self):
957     PsudoFileSystem.__init__(self, "tmpfs")
958    
959     def isMountable(self):
960     return 0
961    
962     fileSystemTypeRegister(DevshmFileSystem())
963    
964     class AutoFileSystem(PsudoFileSystem):
965     def __init__(self):
966     PsudoFileSystem.__init__(self, "auto")
967    
968     fileSystemTypeRegister(AutoFileSystem())
969    
970     class BindFileSystem(AutoFileSystem):
971     def __init__(self):
972     PsudoFileSystem.__init__(self, "bind")
973    
974     def isMountable(self):
975     return 1
976    
977     fileSystemTypeRegister(BindFileSystem())
978    
979     class FileSystemSet:
980     def __init__(self):
981     self.messageWindow = None
982     self.progressWindow = None
983     self.waitWindow = None
984     self.mountcount = 0
985     self.migratedfs = 0
986     self.reset()
987     self.volumesCreated = 0
988    
989     def isActive(self):
990     return self.mountcount != 0
991    
992     def registerMessageWindow(self, method):
993     self.messageWindow = method
994    
995     def registerProgressWindow(self, method):
996     self.progressWindow = method
997    
998     def registerWaitWindow(self, method):
999     self.waitWindow = method
1000    
1001     def reset (self):
1002     self.entries = []
1003     proc = FileSystemSetEntry(Device(), '/proc', fileSystemTypeGet("proc"))
1004     self.add(proc)
1005     sys = FileSystemSetEntry(Device(), '/sys', fileSystemTypeGet("sysfs"))
1006     self.add(sys)
1007     pts = FileSystemSetEntry(Device(), '/dev/pts',
1008     fileSystemTypeGet("devpts"), "gid=5,mode=620")
1009     self.add(pts)
1010     shm = FileSystemSetEntry(Device(), '/dev/shm', fileSystemTypeGet("tmpfs"))
1011     self.add(shm)
1012    
1013     def verify (self):
1014     for entry in self.entries:
1015     if type(entry.__dict__) != type({}):
1016     raise RuntimeError, "fsset internals inconsistent"
1017    
1018     def add (self, entry):
1019     # remove any existing duplicate entries
1020     for existing in self.entries:
1021     if (existing.device.getDevice() == entry.device.getDevice()
1022     and existing.mountpoint == entry.mountpoint):
1023     self.remove(existing)
1024     # XXX debuggin'
1025     ## log ("fsset at %s\n"
1026     ## "adding entry for %s\n"
1027     ## "entry object %s, class __dict__ is %s",
1028     ## self, entry.mountpoint, entry,
1029     ## isys.printObject(entry.__dict__))
1030     self.entries.append(entry)
1031     self.entries.sort (mountCompare)
1032    
1033     def remove (self, entry):
1034     self.entries.remove(entry)
1035    
1036     def getEntryByMountPoint(self, mount):
1037     for entry in self.entries:
1038     if entry.mountpoint == mount:
1039     return entry
1040     return None
1041    
1042     def getEntryByDeviceName(self, dev):
1043     for entry in self.entries:
1044     if entry.device.getDevice() == dev:
1045     return entry
1046     return None
1047    
1048     def copy (self):
1049     new = FileSystemSet()
1050     for entry in self.entries:
1051     new.add (entry)
1052     return new
1053    
1054     def fstab (self):
1055     format = "%-23s %-23s %-7s %-15s %d %d\n"
1056     fstab = ""
1057     for entry in self.entries:
1058     if entry.mountpoint:
1059     if entry.getLabel():
1060     device = "LABEL=%s" % (entry.getLabel(),)
1061     else:
1062     device = devify(entry.device.getDevice())
1063     fstab = fstab + entry.device.getComment()
1064     fstab = fstab + format % (device, entry.mountpoint,
1065     entry.fsystem.getName(),
1066     entry.options, entry.fsck,
1067     entry.order)
1068     return fstab
1069    
1070     def mtab (self):
1071     format = "%s %s %s %s 0 0\n"
1072     mtab = ""
1073     for entry in self.entries:
1074     if not entry.isMounted():
1075     continue
1076     if entry.mountpoint:
1077     # swap doesn't end up in the mtab
1078     if entry.fsystem.getName() == "swap":
1079     continue
1080     if entry.options:
1081     options = "rw," + entry.options
1082     else:
1083     options = "rw"
1084     mtab = mtab + format % (devify(entry.device.getDevice()),
1085     entry.mountpoint,
1086     entry.fsystem.getName(),
1087     options)
1088     return mtab
1089    
1090     def raidtab(self):
1091     # set up raidtab...
1092     raidtab = ""
1093     for entry in self.entries:
1094     if entry.device.getName() == "RAIDDevice":
1095     raidtab = raidtab + entry.device.raidTab()
1096    
1097     return raidtab
1098    
1099     def mdadmConf(self):
1100     raident = 0
1101    
1102     cf = """
1103     # mdadm.conf written out by anaconda
1104     DEVICE partitions
1105     MAILADDR root
1106     """
1107     for ent in self.entries:
1108     if ent.device.getName() != "RAIDDevice":
1109     continue
1110    
1111     raident +=1
1112     cf = cf + ent.device.mdadmLine()
1113    
1114     if raident > 0:
1115     return cf
1116     return
1117    
1118     def write (self, prefix):
1119     f = open (prefix + "/etc/fstab", "w")
1120     f.write (self.fstab())
1121     f.close ()
1122    
1123     cf = self.mdadmConf()
1124    
1125     if cf:
1126     f = open (prefix + "/etc/mdadm.conf", "w")
1127     f.write (cf)
1128     f.close ()
1129    
1130     # touch mtab
1131     open (prefix + "/etc/mtab", "w+")
1132     f.close ()
1133    
1134     def restoreMigratedFstab(self, prefix):
1135     if not self.migratedfs:
1136     return
1137    
1138     fname = prefix + "/etc/fstab"
1139     if os.access(fname + ".rpmsave", os.R_OK):
1140     os.rename(fname + ".rpmsave", fname)
1141    
1142     def migratewrite(self, prefix):
1143     if not self.migratedfs:
1144     return
1145    
1146     fname = prefix + "/etc/fstab"
1147     f = open (fname, "r")
1148     lines = f.readlines()
1149     f.close()
1150    
1151     perms = os.stat(fname)[0] & 0777
1152     os.rename(fname, fname + ".rpmsave")
1153     f = open (fname, "w+")
1154     os.chmod(fname, perms)
1155    
1156     for line in lines:
1157     fields = string.split(line)
1158    
1159     # try to be smart like in fsset.py::readFstab()
1160     if not fields or line[0] == "#":
1161     f.write(line)
1162     continue
1163    
1164     if len (fields) < 4 or len (fields) > 6:
1165     f.write(line)
1166     continue
1167    
1168     if string.find(fields[3], "noauto") != -1:
1169     f.write(line)
1170     continue
1171    
1172     mntpt = fields[1]
1173     entry = self.getEntryByMountPoint(mntpt)
1174     if not entry or not entry.getMigrate():
1175     f.write(line)
1176     elif entry.origfsystem.getName() != fields[2]:
1177     f.write(line)
1178     else:
1179     fields[2] = entry.fsystem.getName()
1180     newline = "%-23s %-23s %-7s %-15s %s %s\n" % (fields[0],
1181     fields[1],
1182     fields[2],
1183     fields[3],
1184     fields[4],
1185     fields[5])
1186     f.write(newline)
1187    
1188     f.close()
1189    
1190 slords 1.7 # return the "boot" device
1191 gordonr 1.1 def getBootDev(self):
1192     mntDict = {}
1193     bootDev = None
1194     for entry in self.entries:
1195     mntDict[entry.mountpoint] = entry.device
1196    
1197     # FIXME: this ppc stuff feels kind of crufty -- the abstraction
1198     # here needs a little bit of work
1199     if iutil.getPPCMacGen() == "NewWorld":
1200     for entry in self.entries:
1201     if entry.fsystem.getName() == "Apple Bootstrap":
1202     bootDev = entry.device
1203     elif (iutil.getPPCMachine() == "pSeries" or
1204     iutil.getPPCMachine() == "iSeries"):
1205     # we want the first prep partition or the first newly formatted one
1206     bestprep = None
1207     for entry in self.entries:
1208     if ((entry.fsystem.getName() == "PPC PReP Boot")
1209     and ((bestprep is None) or
1210     ((bestprep.format == 0) and (entry.format == 1)))):
1211     bestprep = entry
1212     if bestprep:
1213     bootDev = bestprep.device
1214     elif iutil.getArch() == "ia64":
1215     if mntDict.has_key("/boot/efi"):
1216     bootDev = mntDict['/boot/efi']
1217     elif mntDict.has_key("/boot"):
1218     bootDev = mntDict['/boot']
1219     else:
1220     bootDev = mntDict['/']
1221    
1222     return bootDev
1223    
1224     def bootloaderChoices(self, diskSet, bl):
1225     ret = {}
1226     bootDev = self.getBootDev()
1227    
1228     if bootDev is None:
1229     log("no boot device set")
1230     return ret
1231    
1232     if bootDev.getName() == "RAIDDevice":
1233     ret['boot'] = (bootDev.device, N_("RAID Device"))
1234 slords 1.2 ret['mbr'] = (bl.drivelist[0], N_("Master Boot Record (MBR)"))
1235 gordonr 1.1 return ret
1236    
1237     if iutil.getPPCMacGen() == "NewWorld":
1238     ret['boot'] = (bootDev.device, N_("Apple Bootstrap"))
1239     n = 1
1240     for entry in self.entries:
1241     if ((entry.fsystem.getName() == "Apple Bootstrap") and (
1242     entry.device.getDevice() != bootDev.device)):
1243     ret['boot%d' %(n,)] = (entry.device.getDevice(),
1244     N_("Apple Bootstrap"))
1245     n = n + 1
1246     return ret
1247     elif (iutil.getPPCMachine() == "pSeries" or
1248     iutil.getPPCMachine() == "iSeries"):
1249     ret['boot'] = (bootDev.device, N_("PPC PReP Boot"))
1250     return ret
1251    
1252     ret['boot'] = (bootDev.device, N_("First sector of boot partition"))
1253     ret['mbr'] = (bl.drivelist[0], N_("Master Boot Record (MBR)"))
1254     return ret
1255    
1256     # set active partition on disks
1257     # if an active partition is set, leave it alone; if none set
1258     # set either our boot partition or the first partition on the drive active
1259     def setActive(self, diskset):
1260     dev = self.getBootDev()
1261    
1262     if dev is None:
1263     return
1264    
1265     bootDev = dev.device
1266    
1267     # on ia64, *only* /boot/efi should be marked bootable
1268     # similarly, on pseries, we really only want the PReP partition active
1269     if (iutil.getArch() == "ia64" or iutil.getPPCMachine() == "pSeries"
1270     or iutil.getPPCMachine() == "iSeries"):
1271     part = partedUtils.get_partition_by_name(diskset.disks, bootDev)
1272     if part and part.is_flag_available(parted.PARTITION_BOOT):
1273     part.set_flag(parted.PARTITION_BOOT, 1)
1274     return
1275    
1276     for drive in diskset.disks.keys():
1277     foundActive = 0
1278     bootPart = None
1279     disk = diskset.disks[drive]
1280     part = disk.next_partition()
1281     while part:
1282     if not part.is_active():
1283     part = disk.next_partition(part)
1284     continue
1285    
1286     if not part.is_flag_available(parted.PARTITION_BOOT):
1287     foundActive = 1
1288     part = None
1289     continue
1290    
1291     if part.get_flag(parted.PARTITION_BOOT):
1292     foundActive = 1
1293     part = None
1294     continue
1295    
1296     if not bootPart:
1297     bootPart = part
1298    
1299     if partedUtils.get_partition_name(part) == bootDev:
1300     bootPart = part
1301    
1302     part = disk.next_partition(part)
1303    
1304     if bootPart and not foundActive:
1305     bootPart.set_flag(parted.PARTITION_BOOT, 1)
1306    
1307     if bootPart:
1308     del bootPart
1309    
1310     def formatSwap (self, chroot):
1311     formatted = []
1312     notformatted = []
1313    
1314     for entry in self.entries:
1315     if (not entry.fsystem or not entry.fsystem.getName() == "swap" or
1316     entry.isMounted()):
1317     continue
1318     if not entry.getFormat():
1319     notformatted.append(entry)
1320     continue
1321     try:
1322     self.formatEntry(entry, chroot)
1323     formatted.append(entry)
1324     except SystemError:
1325     if self.messageWindow:
1326     self.messageWindow(_("Error"),
1327     _("An error occurred trying to "
1328     "initialize swap on device %s. This "
1329     "problem is serious, and the install "
1330     "cannot continue.\n\n"
1331     "Press <Enter> to reboot your system.")
1332     % (entry.device.getDevice(),))
1333     sys.exit(0)
1334    
1335     for entry in formatted:
1336     try:
1337     self.labelEntry(entry, chroot)
1338     except SystemError:
1339     # should be OK, fall back to by device
1340     pass
1341    
1342     # find if there's a label on the ones we're not formatting
1343     for entry in notformatted:
1344     dev = entry.device.getDevice()
1345     if not dev or dev == "none":
1346     continue
1347     try:
1348     label = isys.readFSLabel(dev)
1349     except:
1350     continue
1351     if label:
1352     entry.setLabel(label)
1353    
1354     def turnOnSwap (self, chroot):
1355     for entry in self.entries:
1356     if (entry.fsystem and entry.fsystem.getName() == "swap"
1357     and not entry.isMounted()):
1358     try:
1359     entry.mount(chroot)
1360     self.mountcount = self.mountcount + 1
1361     except SystemError, (num, msg):
1362     if self.messageWindow:
1363     self.messageWindow(_("Error"),
1364     _("Error enabling swap device %s: "
1365     "%s\n\n"
1366     "This most likely means this "
1367     "swap partition has not been "
1368     "initialized."
1369     "\n\n"
1370     "Press OK to reboot your "
1371     "system.")
1372     % (entry.device.getDevice(), msg))
1373     sys.exit(0)
1374    
1375     def labelEntry(self, entry, chroot):
1376     label = entry.device.getLabel()
1377     if label:
1378     entry.setLabel(label)
1379     elif entry.device.doLabel is not None:
1380     entry.fsystem.labelDevice(entry, chroot)
1381    
1382     def formatEntry(self, entry, chroot):
1383     log("formatting %s as %s" %(entry.mountpoint, entry.fsystem.name))
1384     entry.fsystem.formatDevice(entry, self.progressWindow, chroot)
1385    
1386     def badblocksEntry(self, entry, chroot):
1387     entry.fsystem.badblocksDevice(entry, self.progressWindow, chroot)
1388    
1389     def getMigratableEntries(self):
1390     retval = []
1391     for entry in self.entries:
1392     if entry.origfsystem and entry.origfsystem.isMigratable():
1393     retval.append(entry)
1394    
1395     return retval
1396    
1397     def formattablePartitions(self):
1398     list = []
1399     for entry in self.entries:
1400     if entry.fsystem.isFormattable():
1401     list.append (entry)
1402     return list
1403    
1404     def checkBadblocks(self, chroot='/'):
1405     for entry in self.entries:
1406     if (not entry.fsystem.isFormattable() or not entry.getBadblocks()
1407     or entry.isMounted()):
1408     continue
1409     try:
1410     self.badblocksEntry(entry, chroot)
1411     except BadBlocksError:
1412     log("Bad blocks detected on device %s",entry.device.getDevice())
1413     if self.messageWindow:
1414     self.messageWindow(_("Error"),
1415     _("Bad blocks have been detected on "
1416     "device /dev/%s. We do "
1417     "not recommend you use this device."
1418     "\n\n"
1419     "Press <Enter> to reboot your system") %
1420     (entry.device.getDevice(),))
1421     sys.exit(0)
1422    
1423     except SystemError:
1424     if self.messageWindow:
1425     self.messageWindow(_("Error"),
1426     _("An error occurred searching for "
1427     "bad blocks on %s. This problem is "
1428     "serious, and the install cannot "
1429     "continue.\n\n"
1430     "Press <Enter> to reboot your system.")
1431     % (entry.device.getDevice(),))
1432     sys.exit(0)
1433    
1434     def createLogicalVolumes (self, chroot='/'):
1435     # first set up the volume groups
1436     for entry in self.entries:
1437     if entry.fsystem.name == "volume group (LVM)":
1438     entry.device.setupDevice(chroot)
1439    
1440     # then set up the logical volumes
1441     for entry in self.entries:
1442     if isinstance(entry.device, LogicalVolumeDevice):
1443     entry.device.setupDevice(chroot)
1444     self.volumesCreated = 1
1445    
1446    
1447     def makeFilesystems (self, chroot='/'):
1448     formatted = []
1449     notformatted = []
1450     for entry in self.entries:
1451 slords 1.8 if (entry.mountpoint != '/boot'):
1452     continue
1453     if (not entry.fsystem.isFormattable() or not entry.getFormat()
1454     or entry.isMounted()):
1455     notformatted.append(entry)
1456     continue
1457     try:
1458     self.formatEntry(entry, chroot)
1459     formatted.append(entry)
1460     except SystemError:
1461     if self.messageWindow:
1462     self.messageWindow(_("Error"),
1463     _("An error occurred trying to "
1464     "format %s. This problem is "
1465     "serious, and the install cannot "
1466     "continue.\n\n"
1467     "Press <Enter> to reboot your system.")
1468     % (entry.device.getDevice(),))
1469     sys.exit(0)
1470    
1471     for entry in self.entries:
1472     if (entry.mountpoint == '/boot'):
1473     continue
1474 gordonr 1.1 if (not entry.fsystem.isFormattable() or not entry.getFormat()
1475     or entry.isMounted()):
1476     notformatted.append(entry)
1477     continue
1478     try:
1479     self.formatEntry(entry, chroot)
1480     formatted.append(entry)
1481     except SystemError:
1482     if self.messageWindow:
1483     self.messageWindow(_("Error"),
1484     _("An error occurred trying to "
1485     "format %s. This problem is "
1486     "serious, and the install cannot "
1487     "continue.\n\n"
1488     "Press <Enter> to reboot your system.")
1489     % (entry.device.getDevice(),))
1490     sys.exit(0)
1491    
1492     for entry in formatted:
1493     try:
1494     self.labelEntry(entry, chroot)
1495     except SystemError:
1496     # should be OK, we'll still use the device name to mount.
1497     pass
1498    
1499     # go through and have labels for the ones we don't format
1500     for entry in notformatted:
1501     dev = entry.device.getDevice()
1502     if not dev or dev == "none":
1503     continue
1504     if not entry.mountpoint or entry.mountpoint == "swap":
1505     continue
1506     try:
1507     label = isys.readFSLabel(dev)
1508     except:
1509     continue
1510     if label:
1511     entry.setLabel(label)
1512     else:
1513     self.labelEntry(entry, chroot)
1514    
1515     def haveMigratedFilesystems(self):
1516     return self.migratedfs
1517    
1518     def migrateFilesystems (self, chroot='/'):
1519     if self.migratedfs:
1520     return
1521    
1522     for entry in self.entries:
1523     if not entry.origfsystem:
1524     continue
1525    
1526     if not entry.origfsystem.isMigratable() or not entry.getMigrate():
1527     continue
1528     try:
1529     entry.origfsystem.migrateFileSystem(entry, self.messageWindow,
1530     chroot)
1531     except SystemError:
1532     if self.messageWindow:
1533     self.messageWindow(_("Error"),
1534     _("An error occurred trying to "
1535     "migrate %s. This problem is "
1536     "serious, and the install cannot "
1537     "continue.\n\n"
1538     "Press <Enter> to reboot your system.")
1539     % (entry.device.getDevice(),))
1540     sys.exit(0)
1541    
1542     self.migratedfs = 1
1543    
1544     def mountFilesystems(self, instPath = '/', raiseErrors = 0, readOnly = 0):
1545     for entry in self.entries:
1546     if not entry.fsystem.isMountable():
1547     continue
1548     try:
1549     log("trying to mount %s on %s" %(entry.device.getDevice(), entry.mountpoint))
1550     entry.mount(instPath, readOnly = readOnly)
1551     self.mountcount = self.mountcount + 1
1552     except OSError, (num, msg):
1553     if self.messageWindow:
1554     if num == errno.EEXIST:
1555     self.messageWindow(_("Invalid mount point"),
1556     _("An error occurred when trying "
1557     "to create %s. Some element of "
1558     "this path is not a directory. "
1559     "This is a fatal error and the "
1560     "install cannot continue.\n\n"
1561     "Press <Enter> to reboot your "
1562     "system.") % (entry.mountpoint,))
1563     else:
1564     self.messageWindow(_("Invalid mount point"),
1565     _("An error occurred when trying "
1566     "to create %s: %s. This is "
1567     "a fatal error and the install "
1568     "cannot continue.\n\n"
1569     "Press <Enter> to reboot your "
1570     "system.") % (entry.mountpoint,
1571     msg))
1572     sys.exit(0)
1573     except SystemError, (num, msg):
1574     if raiseErrors:
1575     raise SystemError, (num, msg)
1576     if self.messageWindow:
1577     self.messageWindow(_("Error"),
1578     _("Error mounting device %s as %s: "
1579     "%s\n\n"
1580     "This most likely means this "
1581     "partition has not been formatted."
1582     "\n\n"
1583     "Press OK to reboot your system.")
1584     % (entry.device.getDevice(),
1585     entry.mountpoint, msg))
1586     sys.exit(0)
1587    
1588     self.makeLVMNodes(instPath)
1589    
1590     def makeLVMNodes(self, instPath, trylvm1 = 0):
1591     # XXX hack to make the device node exist for the root fs if
1592     # it's a logical volume so that mkinitrd can create the initrd.
1593     root = self.getEntryByMountPoint("/")
1594    
1595     rootlvm1 = 0
1596     if trylvm1:
1597     dev = root.device.getDevice()
1598     # lvm1 major is 58
1599     if os.access("%s/dev/%s" %(instPath, dev), os.R_OK) and posix.major(os.stat("%s/dev/%s" %(instPath, dev)).st_rdev) == 58:
1600     rootlvm1 = 1
1601    
1602     if isinstance(root.device, LogicalVolumeDevice) or rootlvm1:
1603     # now make sure all of the device nodes exist. *sigh*
1604     rc = iutil.execWithRedirect("lvm",
1605     ["lvm", "vgmknodes", "-v"],
1606     stdout = "/tmp/lvmout",
1607     stderr = "/tmp/lvmout",
1608     searchPath = 1)
1609    
1610     rootDev = "/dev/%s" % (root.device.getDevice(),)
1611     rootdir = instPath + rootDev[:string.rfind(rootDev, "/")]
1612     if not os.path.exists(instPath + "/dev/mapper/control"):
1613     iutil.makeDMNode(root=instPath)
1614     if not os.path.isdir(rootdir):
1615     os.makedirs(rootdir)
1616     dmdev = "/dev/mapper/" + root.device.getDevice().replace("/", "-")
1617     if os.path.exists(instPath + dmdev):
1618     os.unlink(instPath + dmdev)
1619     iutil.copyDeviceNode(dmdev, instPath + dmdev)
1620     # unlink existing so that we dtrt on upgrades
1621     if os.path.exists(instPath + rootDev):
1622     os.unlink(instPath + rootDev)
1623     os.symlink(dmdev, instPath + rootDev)
1624     if not os.path.isdir("%s/etc/lvm" %(instPath,)):
1625     os.makedirs("%s/etc/lvm" %(instPath,))
1626    
1627     def filesystemSpace(self, chroot='/'):
1628     space = []
1629     for entry in self.entries:
1630     if not entry.isMounted():
1631     continue
1632     # we can't put swap files on swap partitions; that's nonsense
1633     if entry.mountpoint == "swap":
1634     continue
1635     path = "%s/%s" % (chroot, entry.mountpoint)
1636     try:
1637     space.append((entry.mountpoint, isys.fsSpaceAvailable(path)))
1638     except SystemError:
1639     log("failed to get space available in filesystemSpace() for %s" %(entry.mountpoint,))
1640    
1641     def spaceSort(a, b):
1642     (m1, s1) = a
1643     (m2, s2) = b
1644    
1645     if (s1 > s2):
1646     return -1
1647     elif s1 < s2:
1648     return 1
1649    
1650     return 0
1651    
1652     space.sort(spaceSort)
1653     return space
1654    
1655     def hasDirtyFilesystems(self, mountpoint):
1656     ret = []
1657    
1658     for entry in self.entries:
1659     # XXX - multifsify, virtualize isdirty per fstype
1660     if entry.fsystem.getName() != "ext2": continue
1661     if entry.getFormat(): continue
1662     if isinstance(entry.device.getDevice(), BindMountDevice): continue
1663    
1664     try:
1665     if isys.ext2IsDirty(entry.device.getDevice()):
1666     log("%s is a dirty ext2 partition" % entry.device.getDevice())
1667     ret.append(entry.device.getDevice())
1668     except Exception, e:
1669     log("got an exception checking %s for being dirty, hoping it's not" %(entry.device.getDevice(),))
1670    
1671     return ret
1672    
1673     def umountFilesystems(self, instPath, ignoreErrors = 0):
1674     # XXX remove special case
1675     try:
1676     isys.umount(instPath + '/proc/bus/usb', removeDir = 0)
1677     log("Umount USB OK")
1678     except:
1679     # log("Umount USB Fail")
1680     pass
1681    
1682     # take a slice so we don't modify self.entries
1683     reverse = self.entries[:]
1684     reverse.reverse()
1685    
1686     for entry in reverse:
1687     entry.umount(instPath)
1688    
1689     class FileSystemSetEntry:
1690     def __init__ (self, device, mountpoint,
1691     fsystem=None, options=None,
1692     origfsystem=None, migrate=0,
1693     order=-1, fsck=-1, format=0,
1694     badblocks = 0):
1695     if not fsystem:
1696     fsystem = fileSystemTypeGet("ext2")
1697     self.device = device
1698     self.mountpoint = mountpoint
1699     self.fsystem = fsystem
1700     self.origfsystem = origfsystem
1701     self.migrate = migrate
1702     if options:
1703     self.options = options
1704     else:
1705     self.options = fsystem.getDefaultOptions(mountpoint)
1706     self.mountcount = 0
1707     self.label = None
1708     if fsck == -1:
1709     self.fsck = fsystem.isChecked()
1710     else:
1711     self.fsck = fsck
1712     if order == -1:
1713     if mountpoint == '/':
1714     self.order = 1
1715     elif self.fsck:
1716     self.order = 2
1717     else:
1718     self.order = 0
1719     else:
1720     self.order = order
1721     if format and not fsystem.isFormattable():
1722     raise RuntimeError, ("file system type %s is not formattable, "
1723     "but has been added to fsset with format "
1724     "flag on" % fsystem.getName())
1725     self.format = format
1726     self.badblocks = badblocks
1727    
1728     def mount(self, chroot='/', devPrefix='/tmp', readOnly = 0):
1729     device = self.device.setupDevice(chroot, devPrefix=devPrefix)
1730    
1731     # FIXME: we really should migrate before turnOnFilesystems.
1732     # but it's too late now
1733     if (self.migrate == 1) and (self.origfsystem is not None):
1734     self.origfsystem.mount(device, "%s/%s" % (chroot, self.mountpoint),
1735     readOnly = readOnly,
1736     bindMount = isinstance(self.device,
1737     BindMountDevice))
1738     else:
1739     self.fsystem.mount(device, "%s/%s" % (chroot, self.mountpoint),
1740     readOnly = readOnly,
1741     bindMount = isinstance(self.device,
1742     BindMountDevice))
1743    
1744     self.mountcount = self.mountcount + 1
1745    
1746     def umount(self, chroot='/'):
1747     if self.mountcount > 0:
1748     try:
1749     self.fsystem.umount(self.device, "%s/%s" % (chroot,
1750     self.mountpoint))
1751     self.mountcount = self.mountcount - 1
1752     except RuntimeError:
1753     pass
1754    
1755     def setFileSystemType(self, fstype):
1756     self.fsystem = fstype
1757    
1758     def setBadblocks(self, state):
1759     self.badblocks = state
1760    
1761     def getBadblocks(self):
1762     return self.badblocks
1763    
1764     def getMountPoint(self):
1765     return self.mountpoint
1766    
1767     def setFormat (self, state):
1768     if self.migrate and state:
1769     raise ValueError, "Trying to set format bit on when migrate is set!"
1770     self.format = state
1771    
1772     def getFormat (self):
1773     return self.format
1774    
1775     def setMigrate (self, state):
1776     if self.format and state:
1777     raise ValueError, "Trying to set migrate bit on when format is set!"
1778    
1779     self.migrate = state
1780    
1781     def getMigrate (self):
1782     return self.migrate
1783    
1784     def isMounted (self):
1785     return self.mountcount > 0
1786    
1787     def getLabel (self):
1788     return self.label
1789    
1790     def setLabel (self, label):
1791     self.label = label
1792    
1793     def __str__(self):
1794     if not self.mountpoint:
1795     mntpt = "None"
1796     else:
1797     mntpt = self.mountpoint
1798    
1799     str = ("fsentry -- device: %(device)s mountpoint: %(mountpoint)s\n"
1800     " fsystem: %(fsystem)s format: %(format)s\n"
1801     " ismounted: %(mounted)s \n"%
1802     {"device": self.device.getDevice(), "mountpoint": mntpt,
1803     "fsystem": self.fsystem.getName(), "format": self.format,
1804     "mounted": self.mountcount})
1805     return str
1806    
1807    
1808     class Device:
1809     def __init__(self):
1810     self.device = "none"
1811     self.fsoptions = {}
1812     self.label = None
1813     self.isSetup = 0
1814     self.doLabel = 1
1815    
1816     def getComment (self):
1817     return ""
1818    
1819     def getDevice (self, asBoot = 0):
1820     return self.device
1821    
1822     def setupDevice (self, chroot='/', devPrefix='/tmp'):
1823     return self.device
1824    
1825     def cleanupDevice (self, chroot, devPrefix='/tmp'):
1826     pass
1827    
1828     def solidify (self):
1829     pass
1830    
1831     def getName(self):
1832     return self.__class__.__name__
1833    
1834     def getLabel(self):
1835     try:
1836     return isys.readFSLabel(self.setupDevice(), makeDevNode = 0)
1837     except:
1838     return ""
1839    
1840     class DevDevice(Device):
1841     """Device with a device node rooted in /dev that we just always use
1842     the pre-created device node for."""
1843     def __init__(self, dev):
1844     Device.__init__(self)
1845     self.device = dev
1846    
1847     def getDevice(self, asBoot = 0):
1848     return self.device
1849    
1850     def setupDevice(self, chroot='/', devPrefix='/dev'):
1851     return "/dev/%s" %(self.getDevice(),)
1852    
1853     class RAIDDevice(Device):
1854     # XXX usedMajors does not take in account any EXISTING md device
1855     # on the system for installs. We need to examine all partitions
1856     # to investigate which minors are really available.
1857     usedMajors = {}
1858    
1859     # members is a list of Device based instances that will be
1860     # a part of this raid device
1861     def __init__(self, level, members, minor=-1, spares=0, existing=0,
1862     chunksize = 64):
1863     Device.__init__(self)
1864     self.level = level
1865     self.members = members
1866     self.spares = spares
1867     self.numDisks = len(members) - spares
1868     self.isSetup = existing
1869     self.doLabel = None
1870     if chunksize is not None:
1871     self.chunksize = chunksize
1872     else:
1873     self.chunksize = 256
1874    
1875     if len(members) < spares:
1876     raise RuntimeError, ("you requiested more spare devices "
1877     "than online devices!")
1878    
1879     if level == 5:
1880     if self.numDisks < 3:
1881     raise RuntimeError, "RAID 5 requires at least 3 online members"
1882    
1883     # there are 32 major md devices, 0...31
1884     if minor == -1 or minor is None:
1885     for I in range(32):
1886     if not RAIDDevice.usedMajors.has_key(I):
1887     minor = I
1888     break
1889    
1890     if minor == -1:
1891     raise RuntimeError, ("Unable to allocate minor number for "
1892     "raid device")
1893    
1894     RAIDDevice.usedMajors[minor] = None
1895     self.device = "md" + str(minor)
1896     self.minor = minor
1897    
1898     # make sure the list of raid members is sorted
1899     self.members.sort()
1900    
1901     def __del__ (self):
1902     del RAIDDevice.usedMajors[self.minor]
1903    
1904     def ext2Args (self):
1905     if self.level == 5:
1906     return [ '-R', 'stride=%d' % ((self.numDisks - 1) * 16) ]
1907     elif self.level == 0:
1908     return [ '-R', 'stride=%d' % (self.numDisks * 16) ]
1909     return []
1910    
1911     def mdadmLine (self, devPrefix="/dev"):
1912     return "ARRAY %s/%s super-minor=%s\n" %(devPrefix, self.device,
1913     self.minor)
1914    
1915     def raidTab (self, devPrefix='/dev'):
1916     d = self.numDisks
1917     if d == 1:
1918     d = 2
1919     entry = ""
1920     entry = entry + "raiddev %s/%s\n" % (devPrefix,
1921     self.device,)
1922     entry = entry + "raid-level %d\n" % (self.level,)
1923     entry = entry + "nr-raid-disks %d\n" % (d)
1924     entry = entry + "chunk-size %s\n" %(self.chunksize,)
1925     entry = entry + "persistent-superblock 1\n"
1926     entry = entry + "nr-spare-disks %d\n" % (self.spares,)
1927     i = 0
1928     for device in self.members[:self.numDisks]:
1929     entry = entry + " device %s/%s\n" % (devPrefix,
1930     device)
1931     entry = entry + " raid-disk %d\n" % (i,)
1932     i = i + 1
1933     i = 0
1934     for device in self.members[self.numDisks:]:
1935     entry = entry + " device %s/%s\n" % (devPrefix,
1936     device)
1937     entry = entry + " spare-disk %d\n" % (i,)
1938     i = i + 1
1939 slords 1.7 if self.numDisks == 1:
1940 gordonr 1.1 entry = entry + " device dev/null\n"
1941     entry = entry + " failed-disk 1\n"
1942     return entry
1943    
1944     def setupDevice (self, chroot="/", devPrefix='/dev'):
1945     def devify(x):
1946     return "/dev/%s" %(x,)
1947    
1948     node = "%s/%s" % (devPrefix, self.device)
1949     isys.makeDevInode(self.device, node)
1950    
1951     if not self.isSetup:
1952     for device in self.members:
1953     PartitionDevice(device).setupDevice(chroot,
1954     devPrefix=devPrefix)
1955    
1956 slords 1.7 args = ["/usr/sbin/mdadm", "--create", "/dev/%s" %(self.device,),
1957     "--run", "--chunk=%s" %(self.chunksize,),
1958     "--level=%s" %(self.level,),
1959     ]
1960 gordonr 1.1
1961     if self.spares > 0:
1962     args.append("--spare-devices=%s" %(self.spares,),)
1963    
1964 slords 1.5 if self.numDisks == 1 and self.level == 1:
1965 gordonr 1.1 args.append("--raid-devices=2")
1966 slords 1.7 else:
1967 gordonr 1.1 args.append("--raid-devices=%s" %(self.numDisks,),)
1968    
1969     args.extend(map(devify, self.members))
1970    
1971 slords 1.5 if self.numDisks == 1 and self.level == 1:
1972 gordonr 1.1 args.append("missing")
1973    
1974     log("going to run: %s" %(args,))
1975     iutil.execWithRedirect (args[0], args,
1976     stderr="/dev/tty5", stdout="/dev/tty5")
1977     raid.register_raid_device(self.device, self.members[:],
1978     self.level, self.numDisks)
1979     self.isSetup = 1
1980     else:
1981     isys.raidstart(self.device, self.members[0])
1982     return node
1983    
1984     def getDevice (self, asBoot = 0):
1985     if not asBoot:
1986     return self.device
1987     else:
1988     return self.members[0]
1989    
1990     def solidify(self):
1991     return
1992    
1993     ext2 = fileSystemTypeGet("ext2")
1994     ext2.registerDeviceArgumentFunction(RAIDDevice, RAIDDevice.ext2Args)
1995    
1996     class VolumeGroupDevice(Device):
1997     def __init__(self, name, physvols, pesize = 32768, existing = 0):
1998     """Creates a VolumeGroupDevice.
1999    
2000     name is the name of the volume group
2001     physvols is a list of Device objects which are the physical volumes
2002     pesize is the size of physical extents in kilobytes
2003     existing is whether this vg previously existed.
2004     """
2005    
2006     Device.__init__(self)
2007     self.physicalVolumes = physvols
2008     self.isSetup = existing
2009     self.name = name
2010     self.device = name
2011     self.isSetup = existing
2012    
2013     self.physicalextentsize = pesize
2014    
2015     def setupDevice (self, chroot="/", devPrefix='/tmp'):
2016     nodes = []
2017     for volume in self.physicalVolumes:
2018     # XXX the lvm tools are broken and will only work for /dev
2019     node = volume.setupDevice(chroot, devPrefix="/dev")
2020    
2021     # XXX I should check if the pv is set up somehow so that we
2022     # can have preexisting vgs and add new pvs to them.
2023     if not self.isSetup:
2024     # now make the device into a real physical volume
2025     # XXX I don't really belong here. should
2026     # there be a PhysicalVolumeDevice(PartitionDevice) ?
2027     lvm.writeForceConf()
2028     rc = iutil.execWithRedirect("lvm",
2029     ["lvm", "pvcreate", "-ff", "-y",
2030     "-v", node],
2031     stdout = "/tmp/lvmout",
2032     stderr = "/tmp/lvmout",
2033     searchPath = 1)
2034     if rc:
2035     raise SystemError, "pvcreate failed for %s" % (volume,)
2036     lvm.unlinkConf()
2037    
2038     lvm.wipeOtherMetadataFromPV(node)
2039    
2040     nodes.append(node)
2041    
2042     if not self.isSetup:
2043     # rescan now that we've recreated pvs. ugh.
2044     lvm.writeForceConf()
2045     lvm.vgscan()
2046    
2047     args = [ "lvm", "vgcreate", "-v", "-An",
2048     "-s", "%sk" %(self.physicalextentsize,),
2049     self.name ]
2050     args.extend(nodes)
2051     rc = iutil.execWithRedirect(args[0], args,
2052     stdout = "/tmp/lvmout",
2053     stderr = "/tmp/lvmout",
2054     searchPath = 1)
2055    
2056     if rc:
2057     raise SystemError, "vgcreate failed for %s" %(self.name,)
2058    
2059     lvm.unlinkConf()
2060     self.isSetup = 1
2061     else:
2062     lvm.vgscan()
2063     lvm.vgactivate()
2064    
2065     return "/dev/%s" % (self.name,)
2066    
2067     def solidify(self):
2068     return
2069    
2070     class LogicalVolumeDevice(Device):
2071     # note that size is in megabytes!
2072     def __init__(self, volumegroup, size, vgname, existing = 0):
2073     Device.__init__(self)
2074     self.volumeGroup = volumegroup
2075     self.size = size
2076     self.name = vgname
2077     self.isSetup = 0
2078     self.isSetup = existing
2079     self.doLabel = None
2080    
2081     # these are attributes we might want to expose. or maybe not.
2082     # self.chunksize
2083     # self.stripes
2084     # self.stripesize
2085     # self.extents
2086     # self.readaheadsectors
2087    
2088     def setupDevice(self, chroot="/", devPrefix='/tmp'):
2089     if not self.isSetup:
2090     lvm.writeForceConf()
2091     rc = iutil.execWithRedirect("lvm",
2092     ["lvm", "lvcreate", "-L",
2093     "%dM" % (self.size,),
2094     "-n", self.name, "-An",
2095     self.volumeGroup],
2096     stdout = "/tmp/lvmout",
2097     stderr = "/tmp/lvmout",
2098     searchPath = 1)
2099     if rc:
2100     raise SystemError, "lvcreate failed for %s" %(self.name,)
2101     lvm.unlinkConf()
2102     self.isSetup = 1
2103    
2104     return "/dev/%s" % (self.getDevice(),)
2105    
2106     def getDevice(self, asBoot = 0):
2107     return "%s/%s" % (self.volumeGroup, self.name)
2108    
2109     def solidify(self):
2110     return
2111    
2112    
2113     class PartitionDevice(Device):
2114     def __init__(self, partition):
2115     Device.__init__(self)
2116     if type(partition) != types.StringType:
2117     raise ValueError, "partition must be a string"
2118     self.device = partition
2119    
2120     def setupDevice(self, chroot="/", devPrefix='/tmp'):
2121     path = '%s/%s' % (devPrefix, self.getDevice(),)
2122     isys.makeDevInode(self.getDevice(), path)
2123     return path
2124    
2125     class PartedPartitionDevice(PartitionDevice):
2126     def __init__(self, partition):
2127     Device.__init__(self)
2128     self.device = None
2129     self.partition = partition
2130    
2131     def getDevice(self, asBoot = 0):
2132     if not self.partition:
2133     return self.device
2134    
2135     return partedUtils.get_partition_name(self.partition)
2136    
2137     def solidify(self):
2138     # drop reference on the parted partition object and note
2139     # the current minor number allocation
2140     self.device = self.getDevice()
2141     self.partition = None
2142    
2143     class BindMountDevice(Device):
2144     def __init__(self, directory):
2145     Device.__init__(self)
2146     self.device = directory
2147    
2148     def setupDevice(self, chroot="/", devPrefix="/tmp"):
2149     return chroot + self.device
2150    
2151    
2152    
2153     class SwapFileDevice(Device):
2154     def __init__(self, file):
2155     Device.__init__(self)
2156     self.device = file
2157     self.size = 0
2158    
2159     def setSize (self, size):
2160     self.size = size
2161    
2162     def setupDevice (self, chroot="/", devPrefix='/tmp'):
2163     file = os.path.normpath(chroot + self.getDevice())
2164     if not os.access(file, os.R_OK):
2165     if self.size:
2166     # make sure the permissions are set properly
2167     fd = os.open(file, os.O_CREAT, 0600)
2168     os.close(fd)
2169     isys.ddfile(file, self.size, None)
2170     else:
2171     raise SystemError, (0, "swap file creation necessary, but "
2172     "required size is unknown.")
2173     return file
2174    
2175     # This is a device that describes a swap file that is sitting on
2176     # the loopback filesystem host for partitionless installs.
2177     # The piggypath is the place where the loopback file host filesystem
2178     # will be mounted
2179     class PiggybackSwapFileDevice(SwapFileDevice):
2180     def __init__(self, piggypath, file):
2181     SwapFileDevice.__init__(self, file)
2182     self.piggypath = piggypath
2183    
2184     def setupDevice(self, chroot="/", devPrefix='/tmp'):
2185     return SwapFileDevice.setupDevice(self, self.piggypath, devPrefix)
2186    
2187     class LoopbackDevice(Device):
2188     def __init__(self, hostPartition, hostFs):
2189     Device.__init__(self)
2190     self.host = "/dev/" + hostPartition
2191     self.hostfs = hostFs
2192     self.device = "loop1"
2193    
2194     def setupDevice(self, chroot="/", devPrefix='/tmp/'):
2195     if not self.isSetup:
2196     isys.mount(self.host[5:], "/mnt/loophost", fstype = "vfat")
2197     self.device = allocateLoopback("/mnt/loophost/redhat.img")
2198     if not self.device:
2199     raise SystemError, "Unable to allocate loopback device"
2200     self.isSetup = 1
2201     path = '%s/%s' % (devPrefix, self.getDevice())
2202     else:
2203     path = '%s/%s' % (devPrefix, self.getDevice())
2204     isys.makeDevInode(self.getDevice(), path)
2205     path = os.path.normpath(path)
2206     return path
2207    
2208     def getComment (self):
2209     return "# LOOP1: %s %s /redhat.img\n" % (self.host, self.hostfs)
2210    
2211     def makeDevice(dev):
2212     if dev.startswith('md'):
2213     try:
2214     (mdname, devices, level, numActive) = raid.lookup_raid_device(dev)
2215     device = RAIDDevice(level, devices,
2216     minor=int(mdname[2:]),
2217     spares=len(devices) - numActive,
2218     existing=1)
2219     except KeyError:
2220     device = DevDevice(dev)
2221     else:
2222     device = DevDevice(dev)
2223     return device
2224    
2225     # XXX fix RAID
2226     def readFstab (path, intf = None):
2227     fsset = FileSystemSet()
2228    
2229     # first, we look at all the disks on the systems and get any ext2/3
2230     # labels off of the filesystem.
2231     # temporary, to get the labels
2232     diskset = partedUtils.DiskSet()
2233     diskset.openDevices()
2234     labels = diskset.getLabels()
2235    
2236     labelToDevice = {}
2237     for device, label in labels.items():
2238     if not labelToDevice.has_key(label):
2239     labelToDevice[label] = device
2240     elif intf is not None:
2241     intf.messageWindow(_("Duplicate Labels"),
2242     _("Multiple devices on your system are "
2243     "labelled %s. Labels across devices must be "
2244     "unique for your system to function "
2245     "properly.\n\n"
2246     "Please fix this problem and restart the "
2247     "installation process.") %(label,),
2248     type="custom", custom_icon="error",
2249     custom_buttons=[_("_Reboot")])
2250     sys.exit(0)
2251     else:
2252     log("WARNING!!! Duplicate labels for %s, but no intf so trying "
2253     "to continue" %(label,))
2254    
2255    
2256     # mark these labels found on the system as used so the factory
2257     # doesn't give them to another device
2258     labelFactory.reserveLabels(labels)
2259    
2260     loopIndex = {}
2261    
2262     f = open (path, "r")
2263     lines = f.readlines ()
2264     f.close()
2265    
2266     for line in lines:
2267     fields = string.split (line)
2268    
2269     if not fields: continue
2270    
2271     if line[0] == "#":
2272     # skip all comments
2273     continue
2274    
2275     # all valid fstab entries have 6 fields; if the last two are missing
2276     # they are assumed to be zero per fstab(5)
2277     if len(fields) < 4:
2278     continue
2279     elif len(fields) == 4:
2280     fields.append(0)
2281     fields.append(0)
2282     elif len(fields) == 5:
2283     fields.append(0)
2284     elif len(fields) > 6:
2285     continue
2286     if string.find(fields[3], "noauto") != -1: continue
2287    
2288     # shenanigans to handle ext3,ext2 format in fstab
2289     fstotry = fields[2]
2290     if fstotry.find(","):
2291     fstotry = fstotry.split(",")
2292     else:
2293     fstotry = [ fstotry ]
2294     fsystem = None
2295     for fs in fstotry:
2296     # if we don't support mounting the filesystem, continue
2297     if not fileSystemTypes.has_key(fs):
2298     continue
2299     fsystem = fileSystemTypeGet(fs)
2300     break
2301     if fsystem is None:
2302     continue
2303    
2304     label = None
2305     if fields[0] == "none":
2306     device = Device()
2307     elif ((string.find(fields[3], "bind") != -1) and
2308     fields[0].startswith("/")):
2309     # it's a bind mount, they're Weird (tm)
2310     device = BindMountDevice(fields[0])
2311     fsystem = fileSystemTypeGet("bind")
2312     elif len(fields) >= 6 and fields[0].startswith('LABEL='):
2313     label = fields[0][6:]
2314     if labelToDevice.has_key(label):
2315     device = makeDevice(labelToDevice[label])
2316     else:
2317     log ("Warning: fstab file has LABEL=%s, but this label "
2318     "could not be found on any file system", label)
2319     # bad luck, skip this entry.
2320     continue
2321     elif fields[2] == "swap" and not fields[0].startswith('/dev/'):
2322     # swap files
2323     file = fields[0]
2324    
2325     if file.startswith('/initrd/loopfs/'):
2326     file = file[14:]
2327     device = PiggybackSwapFileDevice("/mnt/loophost", file)
2328     else:
2329     device = SwapFileDevice(file)
2330     elif fields[0].startswith('/dev/loop'):
2331     # look up this loop device in the index to find the
2332     # partition that houses the filesystem image
2333     # XXX currently we assume /dev/loop1
2334     if loopIndex.has_key(device):
2335     (dev, fs) = loopIndex[device]
2336     device = LoopbackDevice(dev, fs)
2337     elif fields[0].startswith('/dev/'):
2338     device = makeDevice(fields[0][5:])
2339     else:
2340     continue
2341    
2342     # if they have a filesystem being mounted as auto, we need
2343     # to sniff around a bit to figure out what it might be
2344     # if we fail at all, though, just ignore it
2345     if fsystem == "auto" and device.getDevice() != "none":
2346     try:
2347     tmp = partedUtils.sniffFilesystemType("/dev/%s" %(device.setupDevice(),))
2348     if tmp is not None:
2349     fsystem = tmp
2350     except:
2351     pass
2352    
2353     entry = FileSystemSetEntry(device, fields[1], fsystem, fields[3],
2354     origfsystem=fsystem)
2355     if label:
2356     entry.setLabel(label)
2357     fsset.add(entry)
2358     return fsset
2359    
2360     def getDevFD(device):
2361     try:
2362     fd = os.open(device, os.O_RDONLY)
2363     except:
2364     file = '/tmp/' + device
2365     try:
2366     isys.makeDevInode(device, file)
2367     fd = os.open(file, os.O_RDONLY)
2368     except:
2369     return -1
2370     return fd
2371    
2372     def isValidExt2(device):
2373     fd = getDevFD(device)
2374     if fd == -1:
2375     return 0
2376    
2377     buf = os.read(fd, 2048)
2378     os.close(fd)
2379    
2380     if len(buf) != 2048:
2381     return 0
2382    
2383     if struct.unpack("<H", buf[1080:1082]) == (0xef53,):
2384     return 1
2385    
2386     return 0
2387    
2388     def isValidXFS(device):
2389     fd = getDevFD(device)
2390     if fd == -1:
2391     return 0
2392    
2393     buf = os.read(fd, 4)
2394     os.close(fd)
2395    
2396     if len(buf) != 4:
2397     return 0
2398    
2399     if buf == "XFSB":
2400     return 1
2401    
2402     return 0
2403    
2404     def isValidReiserFS(device):
2405     fd = getDevFD(device)
2406     if fd == -1:
2407     return 0
2408    
2409     '''
2410     ** reiserfs 3.5.x super block begins at offset 8K
2411     ** reiserfs 3.6.x super block begins at offset 64K
2412     All versions have a magic value of "ReIsEr" at
2413     offset 0x34 from start of super block
2414     '''
2415     reiserMagicVal = "ReIsEr"
2416     reiserMagicOffset = 0x34
2417     reiserSBStart = [64*1024, 8*1024]
2418     bufSize = 0x40 # just large enough to include the magic value
2419     for SBOffset in reiserSBStart:
2420     try:
2421     os.lseek(fd, SBOffset, 0)
2422     buf = os.read(fd, bufSize)
2423     except:
2424     buf = ""
2425    
2426     if len(buf) < bufSize:
2427     continue
2428    
2429     if (buf[reiserMagicOffset:reiserMagicOffset+len(reiserMagicVal)] ==
2430     reiserMagicVal):
2431     os.close(fd)
2432     return 1
2433    
2434     os.close(fd)
2435     return 0
2436    
2437     def isValidJFS(device):
2438     fd = getDevFD(device)
2439     if fd == -1:
2440     return 0
2441    
2442     try:
2443     os.lseek(fd, 32768, 0)
2444     buf = os.read(fd, 128)
2445     except:
2446     buf = ""
2447    
2448     os.close(fd)
2449     if len(buf) < 4:
2450     return 0
2451    
2452     if (buf[0:4] == "JFS1"):
2453     return 1
2454    
2455     return 0
2456    
2457     # this will return a list of types of filesystems which device
2458     # looks like it could be to try mounting as
2459     def getFStoTry(device):
2460     rc = []
2461    
2462     if isValidXFS(device):
2463     rc.append("xfs")
2464    
2465     if isValidReiserFS(device):
2466     rc.append("reiserfs")
2467    
2468     if isValidJFS(device):
2469     rc.append("jfs")
2470    
2471     if isValidExt2(device):
2472     if os.access(device, os.O_RDONLY):
2473     create = 0
2474     else:
2475     create = 1
2476     if isys.ext2HasJournal(device, makeDevNode = create):
2477     rc.append("ext3")
2478     rc.append("ext2")
2479    
2480     # FIXME: need to check for swap
2481    
2482     return rc
2483    
2484     def allocateLoopback(file):
2485     found = 1
2486     for i in range(8):
2487     dev = "loop%d" % (i,)
2488     path = "/tmp/loop%d" % (i,)
2489     isys.makeDevInode(dev, path)
2490     try:
2491     isys.losetup(path, file)
2492     found = 1
2493     except SystemError:
2494     continue
2495     break
2496     if found:
2497     return dev
2498     return None
2499    
2500     def ext2FormatFilesystem(argList, messageFile, windowCreator, mntpoint):
2501     if windowCreator:
2502     w = windowCreator(_("Formatting"),
2503     _("Formatting %s file system...") % (mntpoint,), 100)
2504     else:
2505     w = None
2506    
2507     fd = os.open(messageFile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
2508     p = os.pipe()
2509     childpid = os.fork()
2510     if not childpid:
2511     os.close(p[0])
2512     os.dup2(p[1], 1)
2513     os.dup2(fd, 2)
2514     os.close(p[1])
2515     os.close(fd)
2516     os.execv(argList[0], argList)
2517     log("failed to exec %s", argList)
2518     os._exit(1)
2519    
2520     os.close(p[1])
2521    
2522     # ignoring SIGCHLD would be cleaner then ignoring EINTR, but
2523     # we can't use signal() in this thread?
2524    
2525     s = 'a'
2526     while s and s != '\b':
2527     try:
2528     s = os.read(p[0], 1)
2529     except OSError, args:
2530     (num, str) = args
2531     if (num != 4):
2532     raise IOError, args
2533    
2534     os.write(fd, s)
2535    
2536     num = ''
2537     sync = 0
2538     while s:
2539     try:
2540     s = os.read(p[0], 1)
2541     os.write(fd, s)
2542    
2543     if s != '\b':
2544     try:
2545     num = num + s
2546     except:
2547     pass
2548     else:
2549     if num and len(num):
2550     l = string.split(num, '/')
2551     try:
2552     val = (int(l[0]) * 100) / int(l[1])
2553     except (IndexError, TypeError):
2554     pass
2555     else:
2556     w and w.set(val)
2557     # sync every 10%
2558     if sync + 10 < val:
2559     isys.sync()
2560     sync = val
2561     num = ''
2562     except OSError, args:
2563     (errno, str) = args
2564     if (errno != 4):
2565     raise IOError, args
2566    
2567     try:
2568     (pid, status) = os.waitpid(childpid, 0)
2569     except OSError, (num, msg):
2570     log("exception from waitpid while formatting: %s %s" %(num, msg))
2571     status = None
2572     os.close(fd)
2573    
2574     w and w.pop()
2575    
2576     # *shrug* no clue why this would happen, but hope that things are fine
2577     if status is None:
2578     return 0
2579    
2580     if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0):
2581     return 0
2582    
2583     return 1
2584    
2585     if __name__ == "__main__":
2586     log.open("foo")
2587    
2588     fsset = readFstab("fstab")
2589    
2590     print fsset.fstab()
2591    
2592     sys.exit(0)
2593     fsset = FileSystemSet()
2594     proc = FileSystemSetEntry(Device(), '/proc', 'proc')
2595     fsset.add(proc)
2596     devpts = FileSystemSetEntry(Device(), '/dev/pts', 'devpts')
2597     fsset.add(devpts)
2598    
2599     device = LoopbackDevice("hda1", "vfat")
2600     mountpoint = FileSystemSetEntry (device, '/')
2601     fsset.add(mountpoint)
2602    
2603     device = SwapFileDevice("/SWAP")
2604     mountpoint = FileSystemSetEntry (device, "swap", "swap")
2605     fsset.add(mountpoint)
2606    
2607     print fsset.fstab()

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