/[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.3 - (hide annotations) (download) (as text)
Mon Aug 1 04:14:22 2005 UTC (19 years, 4 months ago) by slords
Branch: MAIN
Changes since 1.2: +94 -0 lines
Content type: text/x-python
Add fsckFilesystem with progress bar for use after converting to raid

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

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