/[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.7 - (hide annotations) (download) (as text)
Wed Apr 5 01:20:27 2006 UTC (18 years, 6 months ago) by slords
Branch: MAIN
Changes since 1.6: +16 -125 lines
Content type: text/x-python
Update anaconda to be in sync with 4.3 and FC4

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     d = self.numDisks
1894     if d == 1:
1895     d = 2
1896     entry = ""
1897     entry = entry + "raiddev %s/%s\n" % (devPrefix,
1898     self.device,)
1899     entry = entry + "raid-level %d\n" % (self.level,)
1900     entry = entry + "nr-raid-disks %d\n" % (d)
1901     entry = entry + "chunk-size %s\n" %(self.chunksize,)
1902     entry = entry + "persistent-superblock 1\n"
1903     entry = entry + "nr-spare-disks %d\n" % (self.spares,)
1904     i = 0
1905     for device in self.members[:self.numDisks]:
1906     entry = entry + " device %s/%s\n" % (devPrefix,
1907     device)
1908     entry = entry + " raid-disk %d\n" % (i,)
1909     i = i + 1
1910     i = 0
1911     for device in self.members[self.numDisks:]:
1912     entry = entry + " device %s/%s\n" % (devPrefix,
1913     device)
1914     entry = entry + " spare-disk %d\n" % (i,)
1915     i = i + 1
1916 slords 1.7 if self.numDisks == 1:
1917 gordonr 1.1 entry = entry + " device dev/null\n"
1918     entry = entry + " failed-disk 1\n"
1919     return entry
1920    
1921     def setupDevice (self, chroot="/", devPrefix='/dev'):
1922     def devify(x):
1923     return "/dev/%s" %(x,)
1924    
1925     node = "%s/%s" % (devPrefix, self.device)
1926     isys.makeDevInode(self.device, node)
1927    
1928     if not self.isSetup:
1929     for device in self.members:
1930     PartitionDevice(device).setupDevice(chroot,
1931     devPrefix=devPrefix)
1932    
1933 slords 1.7 args = ["/usr/sbin/mdadm", "--create", "/dev/%s" %(self.device,),
1934     "--run", "--chunk=%s" %(self.chunksize,),
1935     "--level=%s" %(self.level,),
1936     ]
1937 gordonr 1.1
1938     if self.spares > 0:
1939     args.append("--spare-devices=%s" %(self.spares,),)
1940    
1941 slords 1.5 if self.numDisks == 1 and self.level == 1:
1942 gordonr 1.1 args.append("--raid-devices=2")
1943 slords 1.7 else:
1944 gordonr 1.1 args.append("--raid-devices=%s" %(self.numDisks,),)
1945    
1946     args.extend(map(devify, self.members))
1947    
1948 slords 1.5 if self.numDisks == 1 and self.level == 1:
1949 gordonr 1.1 args.append("missing")
1950    
1951     log("going to run: %s" %(args,))
1952     iutil.execWithRedirect (args[0], args,
1953     stderr="/dev/tty5", stdout="/dev/tty5")
1954     raid.register_raid_device(self.device, self.members[:],
1955     self.level, self.numDisks)
1956     self.isSetup = 1
1957     else:
1958     isys.raidstart(self.device, self.members[0])
1959     return node
1960    
1961     def getDevice (self, asBoot = 0):
1962     if not asBoot:
1963     return self.device
1964     else:
1965     return self.members[0]
1966    
1967     def solidify(self):
1968     return
1969    
1970     ext2 = fileSystemTypeGet("ext2")
1971     ext2.registerDeviceArgumentFunction(RAIDDevice, RAIDDevice.ext2Args)
1972    
1973     class VolumeGroupDevice(Device):
1974     def __init__(self, name, physvols, pesize = 32768, existing = 0):
1975     """Creates a VolumeGroupDevice.
1976    
1977     name is the name of the volume group
1978     physvols is a list of Device objects which are the physical volumes
1979     pesize is the size of physical extents in kilobytes
1980     existing is whether this vg previously existed.
1981     """
1982    
1983     Device.__init__(self)
1984     self.physicalVolumes = physvols
1985     self.isSetup = existing
1986     self.name = name
1987     self.device = name
1988     self.isSetup = existing
1989    
1990     self.physicalextentsize = pesize
1991    
1992     def setupDevice (self, chroot="/", devPrefix='/tmp'):
1993     nodes = []
1994     for volume in self.physicalVolumes:
1995     # XXX the lvm tools are broken and will only work for /dev
1996     node = volume.setupDevice(chroot, devPrefix="/dev")
1997    
1998     # XXX I should check if the pv is set up somehow so that we
1999     # can have preexisting vgs and add new pvs to them.
2000     if not self.isSetup:
2001     # now make the device into a real physical volume
2002     # XXX I don't really belong here. should
2003     # there be a PhysicalVolumeDevice(PartitionDevice) ?
2004     lvm.writeForceConf()
2005     rc = iutil.execWithRedirect("lvm",
2006     ["lvm", "pvcreate", "-ff", "-y",
2007     "-v", node],
2008     stdout = "/tmp/lvmout",
2009     stderr = "/tmp/lvmout",
2010     searchPath = 1)
2011     if rc:
2012     raise SystemError, "pvcreate failed for %s" % (volume,)
2013     lvm.unlinkConf()
2014    
2015     lvm.wipeOtherMetadataFromPV(node)
2016    
2017     nodes.append(node)
2018    
2019     if not self.isSetup:
2020     # rescan now that we've recreated pvs. ugh.
2021     lvm.writeForceConf()
2022     lvm.vgscan()
2023    
2024     args = [ "lvm", "vgcreate", "-v", "-An",
2025     "-s", "%sk" %(self.physicalextentsize,),
2026     self.name ]
2027     args.extend(nodes)
2028     rc = iutil.execWithRedirect(args[0], args,
2029     stdout = "/tmp/lvmout",
2030     stderr = "/tmp/lvmout",
2031     searchPath = 1)
2032    
2033     if rc:
2034     raise SystemError, "vgcreate failed for %s" %(self.name,)
2035    
2036     lvm.unlinkConf()
2037     self.isSetup = 1
2038     else:
2039     lvm.vgscan()
2040     lvm.vgactivate()
2041    
2042     return "/dev/%s" % (self.name,)
2043    
2044     def solidify(self):
2045     return
2046    
2047     class LogicalVolumeDevice(Device):
2048     # note that size is in megabytes!
2049     def __init__(self, volumegroup, size, vgname, existing = 0):
2050     Device.__init__(self)
2051     self.volumeGroup = volumegroup
2052     self.size = size
2053     self.name = vgname
2054     self.isSetup = 0
2055     self.isSetup = existing
2056     self.doLabel = None
2057    
2058     # these are attributes we might want to expose. or maybe not.
2059     # self.chunksize
2060     # self.stripes
2061     # self.stripesize
2062     # self.extents
2063     # self.readaheadsectors
2064    
2065     def setupDevice(self, chroot="/", devPrefix='/tmp'):
2066     if not self.isSetup:
2067     lvm.writeForceConf()
2068     rc = iutil.execWithRedirect("lvm",
2069     ["lvm", "lvcreate", "-L",
2070     "%dM" % (self.size,),
2071     "-n", self.name, "-An",
2072     self.volumeGroup],
2073     stdout = "/tmp/lvmout",
2074     stderr = "/tmp/lvmout",
2075     searchPath = 1)
2076     if rc:
2077     raise SystemError, "lvcreate failed for %s" %(self.name,)
2078     lvm.unlinkConf()
2079     self.isSetup = 1
2080    
2081     return "/dev/%s" % (self.getDevice(),)
2082    
2083     def getDevice(self, asBoot = 0):
2084     return "%s/%s" % (self.volumeGroup, self.name)
2085    
2086     def solidify(self):
2087     return
2088    
2089    
2090     class PartitionDevice(Device):
2091     def __init__(self, partition):
2092     Device.__init__(self)
2093     if type(partition) != types.StringType:
2094     raise ValueError, "partition must be a string"
2095     self.device = partition
2096    
2097     def setupDevice(self, chroot="/", devPrefix='/tmp'):
2098     path = '%s/%s' % (devPrefix, self.getDevice(),)
2099     isys.makeDevInode(self.getDevice(), path)
2100     return path
2101    
2102     class PartedPartitionDevice(PartitionDevice):
2103     def __init__(self, partition):
2104     Device.__init__(self)
2105     self.device = None
2106     self.partition = partition
2107    
2108     def getDevice(self, asBoot = 0):
2109     if not self.partition:
2110     return self.device
2111    
2112     return partedUtils.get_partition_name(self.partition)
2113    
2114     def solidify(self):
2115     # drop reference on the parted partition object and note
2116     # the current minor number allocation
2117     self.device = self.getDevice()
2118     self.partition = None
2119    
2120     class BindMountDevice(Device):
2121     def __init__(self, directory):
2122     Device.__init__(self)
2123     self.device = directory
2124    
2125     def setupDevice(self, chroot="/", devPrefix="/tmp"):
2126     return chroot + self.device
2127    
2128    
2129    
2130     class SwapFileDevice(Device):
2131     def __init__(self, file):
2132     Device.__init__(self)
2133     self.device = file
2134     self.size = 0
2135    
2136     def setSize (self, size):
2137     self.size = size
2138    
2139     def setupDevice (self, chroot="/", devPrefix='/tmp'):
2140     file = os.path.normpath(chroot + self.getDevice())
2141     if not os.access(file, os.R_OK):
2142     if self.size:
2143     # make sure the permissions are set properly
2144     fd = os.open(file, os.O_CREAT, 0600)
2145     os.close(fd)
2146     isys.ddfile(file, self.size, None)
2147     else:
2148     raise SystemError, (0, "swap file creation necessary, but "
2149     "required size is unknown.")
2150     return file
2151    
2152     # This is a device that describes a swap file that is sitting on
2153     # the loopback filesystem host for partitionless installs.
2154     # The piggypath is the place where the loopback file host filesystem
2155     # will be mounted
2156     class PiggybackSwapFileDevice(SwapFileDevice):
2157     def __init__(self, piggypath, file):
2158     SwapFileDevice.__init__(self, file)
2159     self.piggypath = piggypath
2160    
2161     def setupDevice(self, chroot="/", devPrefix='/tmp'):
2162     return SwapFileDevice.setupDevice(self, self.piggypath, devPrefix)
2163    
2164     class LoopbackDevice(Device):
2165     def __init__(self, hostPartition, hostFs):
2166     Device.__init__(self)
2167     self.host = "/dev/" + hostPartition
2168     self.hostfs = hostFs
2169     self.device = "loop1"
2170    
2171     def setupDevice(self, chroot="/", devPrefix='/tmp/'):
2172     if not self.isSetup:
2173     isys.mount(self.host[5:], "/mnt/loophost", fstype = "vfat")
2174     self.device = allocateLoopback("/mnt/loophost/redhat.img")
2175     if not self.device:
2176     raise SystemError, "Unable to allocate loopback device"
2177     self.isSetup = 1
2178     path = '%s/%s' % (devPrefix, self.getDevice())
2179     else:
2180     path = '%s/%s' % (devPrefix, self.getDevice())
2181     isys.makeDevInode(self.getDevice(), path)
2182     path = os.path.normpath(path)
2183     return path
2184    
2185     def getComment (self):
2186     return "# LOOP1: %s %s /redhat.img\n" % (self.host, self.hostfs)
2187    
2188     def makeDevice(dev):
2189     if dev.startswith('md'):
2190     try:
2191     (mdname, devices, level, numActive) = raid.lookup_raid_device(dev)
2192     device = RAIDDevice(level, devices,
2193     minor=int(mdname[2:]),
2194     spares=len(devices) - numActive,
2195     existing=1)
2196     except KeyError:
2197     device = DevDevice(dev)
2198     else:
2199     device = DevDevice(dev)
2200     return device
2201    
2202     # XXX fix RAID
2203     def readFstab (path, intf = None):
2204     fsset = FileSystemSet()
2205    
2206     # first, we look at all the disks on the systems and get any ext2/3
2207     # labels off of the filesystem.
2208     # temporary, to get the labels
2209     diskset = partedUtils.DiskSet()
2210     diskset.openDevices()
2211     labels = diskset.getLabels()
2212    
2213     labelToDevice = {}
2214     for device, label in labels.items():
2215     if not labelToDevice.has_key(label):
2216     labelToDevice[label] = device
2217     elif intf is not None:
2218     intf.messageWindow(_("Duplicate Labels"),
2219     _("Multiple devices on your system are "
2220     "labelled %s. Labels across devices must be "
2221     "unique for your system to function "
2222     "properly.\n\n"
2223     "Please fix this problem and restart the "
2224     "installation process.") %(label,),
2225     type="custom", custom_icon="error",
2226     custom_buttons=[_("_Reboot")])
2227     sys.exit(0)
2228     else:
2229     log("WARNING!!! Duplicate labels for %s, but no intf so trying "
2230     "to continue" %(label,))
2231    
2232    
2233     # mark these labels found on the system as used so the factory
2234     # doesn't give them to another device
2235     labelFactory.reserveLabels(labels)
2236    
2237     loopIndex = {}
2238    
2239     f = open (path, "r")
2240     lines = f.readlines ()
2241     f.close()
2242    
2243     for line in lines:
2244     fields = string.split (line)
2245    
2246     if not fields: continue
2247    
2248     if line[0] == "#":
2249     # skip all comments
2250     continue
2251    
2252     # all valid fstab entries have 6 fields; if the last two are missing
2253     # they are assumed to be zero per fstab(5)
2254     if len(fields) < 4:
2255     continue
2256     elif len(fields) == 4:
2257     fields.append(0)
2258     fields.append(0)
2259     elif len(fields) == 5:
2260     fields.append(0)
2261     elif len(fields) > 6:
2262     continue
2263     if string.find(fields[3], "noauto") != -1: continue
2264    
2265     # shenanigans to handle ext3,ext2 format in fstab
2266     fstotry = fields[2]
2267     if fstotry.find(","):
2268     fstotry = fstotry.split(",")
2269     else:
2270     fstotry = [ fstotry ]
2271     fsystem = None
2272     for fs in fstotry:
2273     # if we don't support mounting the filesystem, continue
2274     if not fileSystemTypes.has_key(fs):
2275     continue
2276     fsystem = fileSystemTypeGet(fs)
2277     break
2278     if fsystem is None:
2279     continue
2280    
2281     label = None
2282     if fields[0] == "none":
2283     device = Device()
2284     elif ((string.find(fields[3], "bind") != -1) and
2285     fields[0].startswith("/")):
2286     # it's a bind mount, they're Weird (tm)
2287     device = BindMountDevice(fields[0])
2288     fsystem = fileSystemTypeGet("bind")
2289     elif len(fields) >= 6 and fields[0].startswith('LABEL='):
2290     label = fields[0][6:]
2291     if labelToDevice.has_key(label):
2292     device = makeDevice(labelToDevice[label])
2293     else:
2294     log ("Warning: fstab file has LABEL=%s, but this label "
2295     "could not be found on any file system", label)
2296     # bad luck, skip this entry.
2297     continue
2298     elif fields[2] == "swap" and not fields[0].startswith('/dev/'):
2299     # swap files
2300     file = fields[0]
2301    
2302     if file.startswith('/initrd/loopfs/'):
2303     file = file[14:]
2304     device = PiggybackSwapFileDevice("/mnt/loophost", file)
2305     else:
2306     device = SwapFileDevice(file)
2307     elif fields[0].startswith('/dev/loop'):
2308     # look up this loop device in the index to find the
2309     # partition that houses the filesystem image
2310     # XXX currently we assume /dev/loop1
2311     if loopIndex.has_key(device):
2312     (dev, fs) = loopIndex[device]
2313     device = LoopbackDevice(dev, fs)
2314     elif fields[0].startswith('/dev/'):
2315     device = makeDevice(fields[0][5:])
2316     else:
2317     continue
2318    
2319     # if they have a filesystem being mounted as auto, we need
2320     # to sniff around a bit to figure out what it might be
2321     # if we fail at all, though, just ignore it
2322     if fsystem == "auto" and device.getDevice() != "none":
2323     try:
2324     tmp = partedUtils.sniffFilesystemType("/dev/%s" %(device.setupDevice(),))
2325     if tmp is not None:
2326     fsystem = tmp
2327     except:
2328     pass
2329    
2330     entry = FileSystemSetEntry(device, fields[1], fsystem, fields[3],
2331     origfsystem=fsystem)
2332     if label:
2333     entry.setLabel(label)
2334     fsset.add(entry)
2335     return fsset
2336    
2337     def getDevFD(device):
2338     try:
2339     fd = os.open(device, os.O_RDONLY)
2340     except:
2341     file = '/tmp/' + device
2342     try:
2343     isys.makeDevInode(device, file)
2344     fd = os.open(file, os.O_RDONLY)
2345     except:
2346     return -1
2347     return fd
2348    
2349     def isValidExt2(device):
2350     fd = getDevFD(device)
2351     if fd == -1:
2352     return 0
2353    
2354     buf = os.read(fd, 2048)
2355     os.close(fd)
2356    
2357     if len(buf) != 2048:
2358     return 0
2359    
2360     if struct.unpack("<H", buf[1080:1082]) == (0xef53,):
2361     return 1
2362    
2363     return 0
2364    
2365     def isValidXFS(device):
2366     fd = getDevFD(device)
2367     if fd == -1:
2368     return 0
2369    
2370     buf = os.read(fd, 4)
2371     os.close(fd)
2372    
2373     if len(buf) != 4:
2374     return 0
2375    
2376     if buf == "XFSB":
2377     return 1
2378    
2379     return 0
2380    
2381     def isValidReiserFS(device):
2382     fd = getDevFD(device)
2383     if fd == -1:
2384     return 0
2385    
2386     '''
2387     ** reiserfs 3.5.x super block begins at offset 8K
2388     ** reiserfs 3.6.x super block begins at offset 64K
2389     All versions have a magic value of "ReIsEr" at
2390     offset 0x34 from start of super block
2391     '''
2392     reiserMagicVal = "ReIsEr"
2393     reiserMagicOffset = 0x34
2394     reiserSBStart = [64*1024, 8*1024]
2395     bufSize = 0x40 # just large enough to include the magic value
2396     for SBOffset in reiserSBStart:
2397     try:
2398     os.lseek(fd, SBOffset, 0)
2399     buf = os.read(fd, bufSize)
2400     except:
2401     buf = ""
2402    
2403     if len(buf) < bufSize:
2404     continue
2405    
2406     if (buf[reiserMagicOffset:reiserMagicOffset+len(reiserMagicVal)] ==
2407     reiserMagicVal):
2408     os.close(fd)
2409     return 1
2410    
2411     os.close(fd)
2412     return 0
2413    
2414     def isValidJFS(device):
2415     fd = getDevFD(device)
2416     if fd == -1:
2417     return 0
2418    
2419     try:
2420     os.lseek(fd, 32768, 0)
2421     buf = os.read(fd, 128)
2422     except:
2423     buf = ""
2424    
2425     os.close(fd)
2426     if len(buf) < 4:
2427     return 0
2428    
2429     if (buf[0:4] == "JFS1"):
2430     return 1
2431    
2432     return 0
2433    
2434     # this will return a list of types of filesystems which device
2435     # looks like it could be to try mounting as
2436     def getFStoTry(device):
2437     rc = []
2438    
2439     if isValidXFS(device):
2440     rc.append("xfs")
2441    
2442     if isValidReiserFS(device):
2443     rc.append("reiserfs")
2444    
2445     if isValidJFS(device):
2446     rc.append("jfs")
2447    
2448     if isValidExt2(device):
2449     if os.access(device, os.O_RDONLY):
2450     create = 0
2451     else:
2452     create = 1
2453     if isys.ext2HasJournal(device, makeDevNode = create):
2454     rc.append("ext3")
2455     rc.append("ext2")
2456    
2457     # FIXME: need to check for swap
2458    
2459     return rc
2460    
2461     def allocateLoopback(file):
2462     found = 1
2463     for i in range(8):
2464     dev = "loop%d" % (i,)
2465     path = "/tmp/loop%d" % (i,)
2466     isys.makeDevInode(dev, path)
2467     try:
2468     isys.losetup(path, file)
2469     found = 1
2470     except SystemError:
2471     continue
2472     break
2473     if found:
2474     return dev
2475     return None
2476    
2477     def ext2FormatFilesystem(argList, messageFile, windowCreator, mntpoint):
2478     if windowCreator:
2479     w = windowCreator(_("Formatting"),
2480     _("Formatting %s file system...") % (mntpoint,), 100)
2481     else:
2482     w = None
2483    
2484     fd = os.open(messageFile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
2485     p = os.pipe()
2486     childpid = os.fork()
2487     if not childpid:
2488     os.close(p[0])
2489     os.dup2(p[1], 1)
2490     os.dup2(fd, 2)
2491     os.close(p[1])
2492     os.close(fd)
2493     os.execv(argList[0], argList)
2494     log("failed to exec %s", argList)
2495     os._exit(1)
2496    
2497     os.close(p[1])
2498    
2499     # ignoring SIGCHLD would be cleaner then ignoring EINTR, but
2500     # we can't use signal() in this thread?
2501    
2502     s = 'a'
2503     while s and s != '\b':
2504     try:
2505     s = os.read(p[0], 1)
2506     except OSError, args:
2507     (num, str) = args
2508     if (num != 4):
2509     raise IOError, args
2510    
2511     os.write(fd, s)
2512    
2513     num = ''
2514     sync = 0
2515     while s:
2516     try:
2517     s = os.read(p[0], 1)
2518     os.write(fd, s)
2519    
2520     if s != '\b':
2521     try:
2522     num = num + s
2523     except:
2524     pass
2525     else:
2526     if num and len(num):
2527     l = string.split(num, '/')
2528     try:
2529     val = (int(l[0]) * 100) / int(l[1])
2530     except (IndexError, TypeError):
2531     pass
2532     else:
2533     w and w.set(val)
2534     # sync every 10%
2535     if sync + 10 < val:
2536     isys.sync()
2537     sync = val
2538     num = ''
2539     except OSError, args:
2540     (errno, str) = args
2541     if (errno != 4):
2542     raise IOError, args
2543    
2544     try:
2545     (pid, status) = os.waitpid(childpid, 0)
2546     except OSError, (num, msg):
2547     log("exception from waitpid while formatting: %s %s" %(num, msg))
2548     status = None
2549     os.close(fd)
2550    
2551     w and w.pop()
2552    
2553     # *shrug* no clue why this would happen, but hope that things are fine
2554     if status is None:
2555     return 0
2556    
2557     if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0):
2558     return 0
2559    
2560     return 1
2561    
2562     if __name__ == "__main__":
2563     log.open("foo")
2564    
2565     fsset = readFstab("fstab")
2566    
2567     print fsset.fstab()
2568    
2569     sys.exit(0)
2570     fsset = FileSystemSet()
2571     proc = FileSystemSetEntry(Device(), '/proc', 'proc')
2572     fsset.add(proc)
2573     devpts = FileSystemSetEntry(Device(), '/dev/pts', 'devpts')
2574     fsset.add(devpts)
2575    
2576     device = LoopbackDevice("hda1", "vfat")
2577     mountpoint = FileSystemSetEntry (device, '/')
2578     fsset.add(mountpoint)
2579    
2580     device = SwapFileDevice("/SWAP")
2581     mountpoint = FileSystemSetEntry (device, "swap", "swap")
2582     fsset.add(mountpoint)
2583    
2584     print fsset.fstab()

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