/[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.9 - (hide annotations) (download) (as text)
Wed Apr 5 21:11:51 2006 UTC (18 years, 8 months ago) by slords
Branch: MAIN
Changes since 1.8: +27 -37 lines
Content type: text/x-python
Cleanup

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

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