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

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

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