import string import os from lilo import LiloConfiguration import _silo import iutil import isys class SiloInstall: def __init__ (self, todo): self.todo = todo self.linuxAlias = 1 self.bootDevice = 1 def checkUFS(self, dev): f = open("/proc/mounts","r") lines = f.readlines () f.close () mounted = None ufstype = None for line in lines: fields = string.split (line) if fields[0] == '/dev/' + dev and fields[2] == 'ufs': mounted = fields[1] if not mounted: try: os.mkdir ("/tmp/ufsmntpoint") isys.makeDevInode (dev, "/tmp/" + dev) isys.mount ("/tmp" + dev, "/tmp/ufsmntpoint", "ufs") except: try: os.remove ("/tmp/" + dev) except: pass return None root = "/tmp/ufsmntpoint" else: root = mounted if os.access (root + "/etc/system", os.X_OK): if os.access (root + "/kernel/unix", os.X_OK): ufstype = "Solaris" elif os.access (root + "/kernel/genunix", os.X_OK): ufstype = "Solaris" if os.access (root + "/vmunix", os.X_OK) or os.access (root + "/stand", os.X_OK): if os.access (root + "/bin/sh", os.X_OK): # Check if /bin/sh is a.out SPARC binary aout = None try: f = open (root + "/bin/sh", "r") aout = f.read(4) f.close() except: pass if aout and len(aout) == 4 and aout[1] == "\x03" and aout[2] == "\x01": if aout[3] == "\x07" or aout[3] == "\x08" or aout[3] == "\x0b": ufstype = "SunOS" if not mounted: try: isys.umount ("/tmp/ufsmntpoint") except: pass try: os.rmdir ("/tmp/ufsmntpoint") except: pass try: os.remove ("/tmp/" + dev) except: pass return ufstype def getSiloImages(self): todo = self.todo if not todo.ddruid: raise RuntimeError, "No disk druid object" (drives, raid) = todo.ddruid.partitionList() # rearrange the fstab so it's indexed by device mountsByDev = {} for loc in todo.mounts.keys(): (device, fsystem, reformat) = todo.mounts[loc] mountsByDev[device] = loc oldImages = {} for dev in todo.liloImages.keys(): oldImages[dev] = todo.liloImages[dev] todo.liloImages = {} nSolaris = 0 nSunOS = 0 for (dev, devName, type, start, size) in drives: # ext2 partitions get listed if # 1) they're / # 2) they're not mounted # and contain /boot of # some Linux installation # FIXME: For now only list / and UFS partitions, # for 6.2 write code which will read and parse silo.conf from other # Linux partitions and merge it in (after required device # substitions etc. # only list ext2 and ufs partitions if type != 2 and type != 6: continue if (mountsByDev.has_key(dev)): if mountsByDev[dev] == '/': todo.liloImages[dev] = ("linux", 2) elif type == 6: if not oldImages.has_key(dev): todo.liloImages[dev] = ("", type) else: todo.liloImages[dev] = oldImages[dev] ostype = self.checkUFS(dev) if ostype == "Solaris": if nSolaris == 0: todo.liloImages[dev] = ("solaris", type) else: todo.liloImages[dev] = ("solaris%d" % nSolaris, type) nSolaris = nSolaris + 1 elif ostype == "SunOS": if nSunOS == 0: todo.liloImages[dev] = ("sunos", type) else: todo.liloImages[dev] = ("sunos%d" % nSunOS, type) nSunOS = nSunOS + 1 return todo.liloImages def getSiloOptions(self): if self.todo.mounts.has_key ('/boot'): bootpart = self.todo.mounts['/boot'][0] else: bootpart = self.todo.mounts['/'][0] i = len (bootpart) - 1 while i > 0 and bootpart[i] in string.digits: i = i - 1 boothd = bootpart[:i+1] mbrpart = None (drives, raid) = self.todo.ddruid.partitionList() for (dev, devName, type, start, size) in drives: i = len (dev) - 1 while i > 0 and dev[i] in string.digits: i = i - 1 devhd = dev[:i+1] if devhd == boothd and start == 0: mbrpart = dev break if not mbrpart: mbrpart = boothd + "3" return (bootpart, boothd, mbrpart) def getSiloMbrDefault(self): # Check partition at cylinder 0 on the boot disk # is /, /boot or Linux swap if self.todo.mounts.has_key ('/boot'): bootpart = self.todo.mounts['/boot'][0] else: bootpart = self.todo.mounts['/'][0] i = len (bootpart) - 1 while i > 0 and bootpart[i] in string.digits: i = i - 1 boothd = bootpart[:i+1] (drives, raid) = self.todo.ddruid.partitionList() for (dev, devName, type, start, size) in drives: i = len (dev) - 1 while i > 0 and dev[i] in string.digits: i = i - 1 devhd = dev[:i+1] if devhd == boothd and start == 0: if type == 5: return "mbr" elif type == 2: if dev == bootpart: return "mbr" elif dev == self.todo.mounts['/'][0]: return "mbr" return "partition" return "partition" def hasUsableFloppy(self): try: f = open("/proc/devices", "r") except: return 0 lines = f.readlines () f.close () for line in lines: if string.strip (line) == "2 fd": name = _silo.promRootName() if name and name[0:10] == 'SUNW,Ultra' and string.find(name, "Engine") == -1: # Seems like SMCC Ultra box. It is highly probable # the floppies will be unbootable return 1 return 2 return 0 def setPROM(self, linuxAlias, bootDevice): self.linuxAlias = linuxAlias self.bootDevice = bootDevice def hasAliases(self): return _silo.hasAliases() def disk2PromPath(self,dev): return _silo.disk2PromPath(dev) def installSilo (self): todo = self.todo silo = LiloConfiguration () if not todo.liloImages: todo.setLiloImages(self.getSiloImages()) # OK - for this release we need to just blow away the old silo.conf # just like we used to. ## # on upgrade read in the silo config file ## if os.access (todo.instPath + '/etc/silo.conf', os.R_OK): ## silo.read (todo.instPath + '/etc/silo.conf') ## elif not todo.liloDevice: return (bootpart, boothd, mbrpart) = self.getSiloOptions() smpInstalled = (self.todo.hdList.has_key('kernel-smp') and self.todo.hdList['kernel-smp'].selected) if self.todo.mounts.has_key ('/'): (dev, fstype, format) = self.todo.mounts['/'] rootDev = dev else: raise RuntimeError, "Installing silo, but there is no root device" args = [ "silo" ] if todo.liloDevice == "mbr": device = mbrpart else: device = bootpart args.append("-t") bootDevice = self.disk2PromPath(device) i = len (bootpart) - 1 while i > 0 and bootpart[i] in string.digits: i = i - 1 silo.addEntry("partition", bootpart[i+1:]) silo.addEntry("timeout", "50") silo.addEntry("root", '/dev/' + rootDev) silo.addEntry("read-only") kernelList = [] otherList = [] main = "linux" for (drive, (label, liloType)) in todo.liloImages.items (): if (drive == rootDev) and label: main = label elif label: i = len(drive) - 1 while i > 0 and drive[i] in string.digits: i = i - 1 prompath = drive[:i+1] if prompath == boothd: prompath = drive[i+1:] else: prompath = self.disk2PromPath(prompath) if prompath: if prompath[:3] == 'sd(': prompath = prompath + drive[i+1:] else: prompath = prompath + ";" + drive[i+1:] if prompath: otherList.append (label, prompath) silo.addEntry("default", main) label = main if (smpInstalled): kernelList.append((main, self.todo.hdList['kernel-smp'], "smp")) label = main + "-up" kernelList.append((label, self.todo.hdList['kernel'], "")) for (label, kernel, tag) in kernelList: kernelTag = "-%s-%s%s" % (kernel['version'], kernel['release'], tag) initrd = todo.makeInitrd (kernelTag) if rootDev == bootpart: kernelFile = "/boot/vmlinuz" + kernelTag initrdFile = initrd else: kernelFile = "/vmlinuz" + kernelTag initrdFile = initrd[5:] sl = LiloConfiguration() sl.addEntry("label", label) if os.access (todo.instPath + initrd, os.R_OK): sl.addEntry("initrd", initrdFile) silo.addImage ("image", kernelFile, sl) for (label, device) in otherList: sl = LiloConfiguration() sl.addEntry("label", label) silo.addImage ("other", device, sl) # for (siloType, name, config) in silo.images: # # remove entries for missing kernels (upgrade) # if siloType == "image": # if not os.access (todo.instPath + name, os.R_OK): # silo.delImage (name) # # remove entries for unbootable partitions # elif siloType == "other": # device = name[5:] # isys.makeDevInode(device, '/tmp/' + device) # if not isys.checkBoot ('/tmp/' + device): # lilo.delImage (name) # os.remove ('/tmp/' + device) # pass 2, remove duplicate entries labels = [] for (siloType, name, config) in silo.images: if not name in labels: labels.append (name) else: # duplicate entry, first entry wins silo.delImage (name) if self.todo.mounts.has_key ('/boot'): silo.write(todo.instPath + "/boot/silo.conf") try: os.remove(todo.instPath + "/etc/silo.conf") except: pass os.symlink("../boot/silo.conf", todo.instPath + "/etc/silo.conf") else: silo.write(todo.instPath + "/etc/silo.conf") # XXX make me "not test mode" if todo.setupFilesystems: if todo.serial: messages = "/tmp/silo.log" else: messages = "/dev/tty3" iutil.execWithRedirect('/sbin/silo', args, stdout = None, root = todo.instPath) linuxAlias = "" if self.linuxAlias and self.hasAliases(): linuxAlias = bootDevice if not self.bootDevice: bootDevice = "" if not linuxAlias: linuxAlias = "" _silo.setPromVars(linuxAlias,bootDevice)