%installclass #Some comments of cavats #You can't use the word flash as the first word on any lines in the ks file #except when you define a flash server #There is not really a good error check of the flash line both on cmdline #and in the ks file. You can specify a server but e.g. miss the dir #This will result in a kickstart error but the error is a mount error #which isn't accurate for the type of error which is that the dir was #not applied #We don't support Upgrade in flash installs -- there is no need simply import iutil import isys import _isys import os import timer import time import pprint import pcmcia import rpm import stat from syslogd import syslog from hdrlist import PKGTYPE_MANDATORY, PKGTYPE_DEFAULT, DependencyChecker from installmethod import FileCopyException from rhpl.log import log from rhpl.translate import _ import rhpl.arch from constants import * from kickstart import KickstartBase from packages import firstbootConfiguration, sortPackages, rpmErrorClass from partitioning import * from autopart import * from fsset import * from flags import flags from kickstart import KickstartError import sys import raid import string import partRequests import urllib2 import lvm DoFlash = None class Script: def __repr__(self): str = ("(s: '%s' i: %s c: %d)") % \ (self.script, self.interp, self.inChroot) return string.replace(str, "\n", "|") def __init__(self, script, interp, inChroot, logfile = None): self.script = script self.interp = interp self.inChroot = inChroot self.logfile = logfile def run(self, chroot, serial): scriptRoot = "/" if self.inChroot: scriptRoot = chroot path = scriptRoot + "/tmp/ks-script" f = open(path, "w") f.write(self.script) f.close() os.chmod(path, 0700) if self.logfile is not None: messages = self.logfile elif serial: messages = "/tmp/ks-script.log" else: messages = "/dev/tty3" rc = iutil.execWithRedirect(self.interp, [self.interp,"/tmp/ks-script"], stdout = messages, stderr = messages, root = scriptRoot) if rc != 0: log("WARNING - Error code %s encountered running a kickstart %%pre/%%post script", rc) os.unlink(path) def setMacAddress(instPath): log("In MacAddress") log("%s" % (os.listdir(instPath + '/etc/sysconfig/network-scripts/'))) macaddress = isys.getMacAddress("eth0") try: ifcfg = open (instPath + '/etc/sysconfig/network-scripts/ifcfg-eth0', 'r') except IOError: log ("WARNING, there is no ifcfg-eth0, bad things will happen!") return lines = ifcfg.readlines () ifcfg.close () ifcfg = open (instPath + '/etc/sysconfig/network-scripts/ifcfg-eth0', 'w') for line in lines: if len (line) > 7 and line[:7] == "HWADDR=": fields = string.split (line, '=') fields[1] = str (macaddress) line = string.join (fields, '=') line = "%s\n" % (line) ifcfg.write (line) ifcfg.close () log("Leaving MacAddress") log("%s" % (os.listdir(instPath + '/etc/sysconfig/network-scripts/'))) def setRunlevel(instPath): runlevel = 3 try: inittab = open (instPath + '/etc/inittab', 'r') except IOError: log ("WARNING, there is no inittab, bad things will happen!") return lines = inittab.readlines () inittab.close () inittab = open (instPath + '/etc/inittab', 'w') for line in lines: if len (line) > 3 and line[:3] == "id:": fields = string.split (line, ':') fields[1] = str (runlevel) line = string.join (fields, ':') inittab.write (line) inittab.close () def doFlashPostInstall(method, id, instPath): if flags.test: return arch = iutil.getArch () logname = '/root/install.log' instLogName = instPath + logname instLog = open(instLogName, "a") try: from packages import copyExtraModules copyExtraModules(instPath, id.grpset, id.extraModules) # pcmcia is supported only on i386 at the moment if arch == "i386": pcmcia.createPcmciaConfig(instPath + "/etc/sysconfig/pcmcia") # we need to write out the network bits before kudzu runs # to avoid getting devices in the wrong order (#102276) # Set the mac address of eth0 on ifcfg-eth0 if id.instClass.setup == "old" and id.instClass.setmac == "yes": setMacAddress(instPath) #Commented out since we use FDD_setup to do initial configuration #elif id.instClass.setup == "new": # id.network.write(instPath) #Check if X isn't present set runlevel to 3 #If setrunlevel is set to yes set runlevel to 3 path = "%s/usr/X11R6/bin/X" % (instPath) if not os.access(path,os.F_OK) or id.instClass.setrunlevel == "yes": setRunlevel(instPath) # blah. If we're on a serial mouse, and we have X, we need to # close the mouse device, then run kudzu, then open it again. # turn it off mousedev = None # XXX currently Bad Things (X async reply) happen when doing # Mouse Magic on Sparc (Mach64, specificly) # The s390 doesn't even have a mouse! if os.environ.get('DISPLAY') == ':1' and arch != 'sparc': try: import xmouse mousedev = xmouse.get()[0] except RuntimeError: pass if mousedev: try: os.rename (mousedev, "/dev/disablemouse") except OSError: pass try: xmouse.reopen() except RuntimeError: pass if arch != "s390" and flags.setupFilesystems: # we need to unmount usbdevfs before mounting it usbWasMounted = iutil.isUSBDevFSMounted() if usbWasMounted: isys.umount('/proc/bus/usb', removeDir = 0) # see if unmount suceeded, if not pretent it isnt mounted # because we're screwed anywyas if system is going to # lock up if iutil.isUSBDevFSMounted(): usbWasMounted = 0 unmountUSB = 0 try: isys.mount('/usbfs', instPath+'/proc/bus/usb', 'usbfs') unmountUSB = 1 except: log("Mount of /proc/bus/usb in chroot failed") pass argv = [ "/usr/sbin/kudzu", "-q" ] if id.grpset.hdrlist.has_key("kernel"): ver = "%s-%s" %(id.grpset.hdrlist["kernel"][rpm.RPMTAG_VERSION], id.grpset.hdrlist["kernel"][rpm.RPMTAG_RELEASE]) argv.extend(["-k", ver]) devnull = os.open("/dev/null", os.O_RDWR) os.unlink(instPath + '/etc/sysconfig/hwconf') iutil.execWithRedirect(argv[0], argv, root = instPath, stdout = devnull) log("AFTER kudzu: %s" % (os.listdir(instPath + '/etc/sysconfig/network-scripts/'))) # turn it back on if mousedev: try: os.rename ("/dev/disablemouse", mousedev) except OSError: pass try: xmouse.reopen() except RuntimeError: pass if unmountUSB: try: isys.umount(instPath + '/proc/bus/usb', removeDir = 0) except SystemError: # if we fail to unmount, then we should just not # try to remount it. this protects us from random # suckage usbWasMounted = 0 if usbWasMounted: isys.mount('/usbfs', '/proc/bus/usb', 'usbfs') #FIX THIS GRAPHIC STUFF LATER #if id.grpset.hdrlist.has_key("rhgb") and id.grpset.hdrlist["rhgb"].isSelected(): # log("rhgb installed, adding to boot loader config") # id.bootloader.args.append("rhgb quiet") finally: pass # XXX hack - we should really write a proper lvm "config". but for now # just vgscan if they have /sbin/lvm and some appearance of volumes if (os.access(instPath + "/sbin/lvm", os.X_OK) and os.access(instPath + "/dev/mapper", os.X_OK) and len(os.listdir("/dev/mapper")) > 1): rc = iutil.execWithRedirect("/sbin/lvm", ["lvm", "vgscan", "-v"], stdout = "/dev/tty5", stderr = "/dev/tty5", root = instPath, searchPath = 1) sys.stdout.flush() if flags.setupFilesystems: syslog.stop() class InstallCallback: def packageDownloadCB(self, state, amount): pass def cb(self, what, amount, total, h, (param)): # first time here means we should pop the window telling # user to wait until we get here if (what == rpm.RPMCALLBACK_INST_OPEN_FILE): # We don't want to start the timer until we get to the first # file. self.instLog.write (self.modeText % (h[rpm.RPMTAG_NAME], h[rpm.RPMTAG_VERSION], h[rpm.RPMTAG_RELEASE], h[rpm.RPMTAG_ARCH])) self.instLog.flush () self.rpmFD = -1 self.size = h[rpm.RPMTAG_SIZE] while self.rpmFD < 0: try: fn = self.method.getRPMFilename(h, self.pkgTimer, callback=self.packageDownloadCB) self.rpmFD = os.open(fn, os.O_RDONLY) # Make sure this package seems valid try: hdr = self.ts.hdrFromFdno(self.rpmFD) os.lseek(self.rpmFD, 0, 0) # if we don't have a valid package, throw an error if not hdr: raise SystemError except: try: os.close(self.rpmFD) except: pass self.rpmFD = -1 raise FileCopyException except Exception, e: log("exception was %s for %s-%s-%s" %(e, h['name'], h['version'], h['release'])) fn = self.method.unlinkFilename(fn) return self.rpmFD elif (what == rpm.RPMCALLBACK_INST_CLOSE_FILE): os.close (self.rpmFD) elif ((what == rpm.RPMCALLBACK_UNPACK_ERROR) or (what == rpm.RPMCALLBACK_CPIO_ERROR)): pkg = "%s-%s-%s" % (h[rpm.RPMTAG_NAME], h[rpm.RPMTAG_VERSION], h[rpm.RPMTAG_RELEASE]) log("RPM error in pkg %s" % (pkg)) sys.exit(0) else: pass def __init__(self, pkgTimer, method, instLog, modeText, ts): self.method = method self.instLog = instLog self.modeText = modeText self.ts = ts self.pkgTimer = None def getAnacondaTS(instPath = None): if instPath: ts = rpm.TransactionSet(instPath) else: ts = rpm.TransactionSet() ts.setVSFlags(~(rpm.RPMVSF_NORSA|rpm.RPMVSF_NODSA)) ts.setFlags(rpm.RPMTRANS_FLAG_ANACONDA) # set color if needed. FIXME: why isn't this the default :/ if (rhpl.arch.canonArch.startswith("ppc64") or rhpl.arch.canonArch in ("s390x", "sparc64", "x86_64", "ia64")): ts.setColor(3) return ts def cpioScript(flashpath = "/mnt/flash", image = "default", rootpath = "/mnt/sysimage/"): log("In script") script = """#!/bin/sh cd %s /usr/bin/echo "Start of extract" > /tmp/cpio.log /usr/bin/echo "PWD: $PWD" >> /tmp/cpio.log /usr/bin/zcat %s/%s | /usr/bin/cpio -icBdumv --no-absolute-filenames >> /tmp/cpio.log 2>&1 #cd %s/xen2 #/usr/bin/zcat %s/%s | /usr/bin/cpio -icBdumv --no-absolute-filenames >> /tmp/cpio.log 2>&1 #cd %s/xen3 #/usr/bin/zcat %s/%s | /usr/bin/cpio -icBdumv --no-absolute-filenames >> /tmp/cpio.log 2>&1 #cd %s/xen4 #/usr/bin/zcat %s/%s | /usr/bin/cpio -icBdumv --no-absolute-filenames >> /tmp/cpio.log 2>&1 """ % (rootpath, flashpath, image, rootpath, flashpath, image, rootpath, flashpath, image, rootpath, flashpath, image) return script def doImageInstall(method, id, instPath): log("Im in do Image %s" % (instPath)) log("ID %s" % (pprint.pformat(id))) cmdline = open("/proc/cmdline").read() log("CMD %s" % (cmdline)) log("productPath %s productVersion %s productName %s" % (productPath, productVersion, productName)) command = cpioScript(image = id.instClass.image) log("Script is: %s" % (command)) scriptfile = file("/tmp/script.sh", "w") scriptfile.write(command) scriptfile.close() os.chmod("/tmp/script.sh",stat.S_IXUSR | stat.S_IRUSR) log("Start CPIO extract") os.system("/tmp/script.sh") log("Finished CPIO extract") #Ok make a loop here -- where we look at how many xen dirs we #have -- then extraxt the xen image to all of them #We need to figure out a way of restoring servers running xen... #possibly mounting things read only when we do flash snapshot # write out the fstab id.fsset.write(instPath) # rootpath mode doesn't have this file around if os.access("/tmp/modprobe.conf", os.R_OK): iutil.copyFile("/tmp/modprobe.conf", instPath + "/etc/modprobe.conf") if os.access("/tmp/zfcp.conf", os.R_OK): iutil.copyFile("/tmp/zfcp.conf", instPath + "/etc/zfcp.conf") # make a /etc/mtab so mkinitrd can handle certain hw (usb) correctly f = open(instPath + "/etc/mtab", "w+") f.write(id.fsset.mtab()) f.close() def flashdoPackageInstall(method, id, instPath): log("In Pack install") log("grpset %s" % (id.grpset.hdrlist)) if flags.test: return # set up dependency white outs import whiteout ts = getAnacondaTS(instPath) total = 0 totalSize = 0 totalFiles = 0 how = "i" rpm.addMacro("__dbi_htconfig", "hash nofsync %{__dbi_other} %{__dbi_perms}") if id.excludeDocs: rpm.addMacro("_excludedocs", "1") l = [] for p in id.grpset.hdrlist.values(): if p.isSelected(): l.append(p) l.sort(sortPackages) log("Packs to be installed: %s" % (l)) log("pack install 1") i = 0 updcount = 0 updintv = len(l) / 25 for p in l: ts.addInstall(p.hdr, p.hdr, how) log("pack install 2") depcheck = DependencyChecker(id.grpset) if not id.grpset.hdrlist.preordered(): log ("WARNING: not all packages in hdlist had order tag") # have to call ts.check before ts.order() to set up the alIndex #We don't check dep in flash install --- no need... #ts.check(depcheck.callback) ts.order() #else: # ts.check(depcheck.callback) logname = '/root/install.log' instLogName = instPath + logname try: iutil.rmrf (instLogName) except OSError: pass log("pack install 3") instLog = open(instLogName, "w+") # dont start syslogd if we arent creating filesystems if flags.setupFilesystems: syslogname = "%s%s.syslog" % (instPath, logname) try: iutil.rmrf (syslogname) except OSError: pass syslog.start (instPath, syslogname) else: syslogname = None if id.compspkg is not None: num = i + 1 else: num = i log("pack install 4") instLog.write(_("Installing %s packages\n\n") % (num,)) ts.scriptFd = instLog.fileno () rpm.setLogFile(instLog) # the transaction set dup()s the file descriptor and will close the # dup'd when we go out of scope modeText = _("Installing %s-%s-%s.%s.\n") errors = rpmErrorClass(instLog) pkgTimer = timer.Timer(start = 0) log("pack install 5") cb = InstallCallback(pkgTimer, method, instLog, modeText, ts) log("pack install 51") # write out migrate adjusted fstab so kernel RPM can get initrd right log("pack install 52") log("pack install 53") ts.setProbFilter(~rpm.RPMPROB_FILTER_DISKSPACE) log("pack install 54") problems = ts.run(cb.cb, 0) log("pack install 6") if problems: # restore old fstab if we did anything for migrating spaceneeded = {} nodeneeded = {} size = 12 log("pack install 7") for (descr, (type, mount, need)) in problems: log("(%s, (%s, %s, %s))" %(descr, type, mount, need)) if mount and mount.startswith(instPath): mount = mount[len(instPath):] if not mount: mount = '/' if type == rpm.RPMPROB_DISKSPACE: if spaceneeded.has_key (mount) and spaceneeded[mount] < need: spaceneeded[mount] = need else: spaceneeded[mount] = need elif type == nodeprob: if nodeneeded.has_key (mount) and nodeneeded[mount] < need: nodeneeded[mount] = need else: nodeneeded[mount] = need else: if descr is None: descr = "no description" log ("WARNING: unhandled problem returned from " "transaction set type %d (%s)", type, descr) log("pack install 8") probs = "" if spaceneeded: probs = probs + _("You don't appear to have enough disk space " "to install the packages you've selected. " "You need more space on the following " "file systems:\n\n") probs = probs + ("%-15s %s\n") % (_("Mount Point"), _("Space Needed")) for (mount, need) in spaceneeded.items (): log("(%s, %s)" %(mount, need)) if need > (1024*1024): need = (need + 1024 * 1024 - 1) / (1024 * 1024) suffix = "M" else: need = (need + 1023) / 1024 suffix = "k" prob = "%-15s %d %c\n" % (mount, need, suffix) probs = probs + prob log("pack install 9") if nodeneeded: if probs: probs = probs + '\n' probs = probs + _("You don't appear to have enough file nodes " "to install the packages you've selected. " "You need more file nodes on the following " "file systems:\n\n") probs = probs + ("%-15s %s\n") % (_("Mount Point"), _("Nodes Needed")) for (mount, need) in nodeneeded.items (): prob = "%-15s %d\n" % (mount, need) probs = probs + prob if len(probs) == 0: probs = ("ERROR: NO! An unexpected problem has occurred with " "your transaction set. Please see tty3 for more " "information") log("pack install 10") ts.closeDB() del ts instLog.close() if syslogname: syslog.stop() log("pack install 11") method.systemUnmounted () return DISPATCH_BACK # This should close the RPM database so that you can # do RPM ops in the chroot in a %post ks script log("pack install 12") ts.closeDB() del ts method.filesDone () log("pack install 13") # rpm environment files go bye-bye for file in ["__db.001", "__db.002", "__db.003"]: try: os.unlink("%s/var/lib/rpm/%s" %(instPath, file)) except Exception, e: log("failed to unlink /var/lib/rpm/%s: %s" %(file,e)) # FIXME: remove the /var/lib/rpm symlink that keeps us from having # db->close error messages shown. I don't really like this though :( try: os.unlink("/var/lib/rpm") except Exception, e: log("failed to unlink /var/lib/rpm: %s" %(e,)) instLog.close () log("At the end of pack install") #id.instProgress = None #Replace the normal doPreInstall if we do a flash install #A flash is never a upgrade so we remove all references to it #We basically just want to set it up and get the kernel packages #nothing else -- we don't want junk such as ldap etc since we do a image #install def flashdoPreInstall(method, id, instPath): arch = iutil.getArch () # this is a crappy hack, but I don't want bug reports from these people if (arch == "i386") and (not id.grpset.hdrlist.has_key("kernel")): log("No kernel sutible for your setup") sys.exit(0) # shorthand def select(hdrlist, name): if hdrlist.has_key(name): hdrlist[name].select(isManual = 1) return 1 return 0 def selected(hdrlist, name): if hdrlist.has_key(name) and hdrlist[name].isSelected(): return 1 return 0 foundkernel = 0 if isys.smpAvailable() or isys.htavailable(): if select(id.grpset.hdrlist, 'kernel-smp'): foundkernel = 1 if iutil.needsEnterpriseKernel(): if select(id.grpset.hdrlist, "kernel-bigmem"): foundkernel = 1 if isys.summitavailable(): if select(id.grpset.hdrlist, "kernel-summit"): foundkernel = 1 if foundkernel == 0: # we *always* need to have some sort of kernel installed select(id.grpset.hdrlist, 'kernel') cmdline = open("/proc/cmdline").read() #if cmdline.find("xen") != -1: #select(id.grpset.hdrlist, 'xen-kernel') #select(id.grpset.hdrlist, 'xen') if iutil.getArch() == "i386" and id.bootloader.useGrubVal == 0: select(id.grpset.hdrlist, 'lilo') elif iutil.getArch() == "i386" and id.bootloader.useGrubVal == 1: select(id.grpset.hdrlist, 'grub') elif iutil.getArch() == "s390": select(id.grpset.hdrlist, 's390utils') elif iutil.getArch() == "ppc": select(id.grpset.hdrlist, 'yaboot') elif iutil.getArch() == "ia64": select(id.grpset.hdrlist, 'elilo') if pcmcia.pcicType(): select(id.grpset.hdrlist, 'pcmcia-cs') for entry in id.fsset.entries: for pkg in entry.fsystem.getNeededPackages(): if select(id.grpset.hdrlist, pkg): log("Needed %s for %s" %(pkg, entry.getMountPoint())) if flags.test: return # make sure that all comps that include other comps are # selected (i.e. - recurse down the selected comps and turn # on the children while 1: try: method.mergeFullHeaders(id.grpset.hdrlist) except FileCopyException: method.unmountCD() log("Unable to merge header list") else: break if method.systemMounted (id.fsset, instPath): id.fsset.umountFilesystems(instPath) return DISPATCH_BACK for i in ( '/var', '/var/lib', '/var/lib/rpm', '/tmp', '/dev', '/etc', '/etc/sysconfig', '/etc/sysconfig/network-scripts', '/etc/X11', '/root', '/var/tmp', '/etc/rpm' ): try: os.mkdir(instPath + i) except os.error, (errno, msg): pass # log("Error making directory %s: %s" % (i, msg)) if flags.setupFilesystems: # setup /etc/rpm/platform for the post-install environment iutil.writeRpmPlatform(instPath) try: # FIXME: making the /var/lib/rpm symlink here is a hack to # workaround db->close() errors from rpm iutil.mkdirChain("/var/lib") for path in ("/var/tmp", "/var/lib/rpm"): if os.path.exists(path) and not os.path.islink(path): iutil.rmrf(path) if not os.path.islink(path): os.symlink("/mnt/sysimage/%s" %(path,), "%s" %(path,)) else: log("%s already exists as a symlink to %s" %(path, os.readlink(path),)) except Exception, e: # how this could happen isn't entirely clear; log it in case # it does and causes problems later log("error creating symlink, continuing anyway: %s" %(e,)) # SELinux hackery (#121369) if flags.selinux: try: os.mkdir(instPath + "/selinux") except Exception, e: pass try: isys.mount("/selinux", instPath + "/selinux", "selinuxfs") except Exception, e: log("error mounting selinuxfs: %s" %(e,)) # we need to have a /dev during install and now that udev is # handling /dev, it gets to be more fun. so just bind mount the # installer /dev if not id.grpset.hdrlist.has_key("dev"): log("no dev package, going to bind mount /dev") isys.mount("/dev", "/mnt/sysimage/dev", bindMount = 1) # try to copy the comps package. if it doesn't work, don't worry about it try: id.compspkg = method.copyFileToTemp("%s/base/comps.rpm" % (productPath,)) except: log("Unable to copy comps package") id.compspkg = None ##MOVE THIS TO POST INSTALL.... ## write out the fstab #id.fsset.write(instPath) ## rootpath mode doesn't have this file around #if os.access("/tmp/modprobe.conf", os.R_OK): # iutil.copyFile("/tmp/modprobe.conf", instPath + "/etc/modprobe.conf") #if os.access("/tmp/zfcp.conf", os.R_OK): # iutil.copyFile("/tmp/zfcp.conf", instPath + "/etc/zfcp.conf") ## make a /etc/mtab so mkinitrd can handle certain hw (usb) correctly #f = open(instPath + "/etc/mtab", "w+") #f.write(id.fsset.mtab()) #f.close() ##END MOVE class CustomKickstart(KickstartBase): def __init__(self, file, serial): self.flash = None self.flashimage = None self.file = file #log("I inited") #import os #log("%s" % (os.listdir("/tmp"))) #log("myFile %s" % (file)) #raise "Failed here" #global myFile #myFile=file self.flashdetect = False KickstartBase.__init__(self, file, serial) def setSteps(self, dispatch): log("I setstep") KickstartBase.setSteps(self, dispatch) #log("Step list: %s" % (dispatch.setStepList())) #Due to the fact that setSteps is called before #setInstallData we need to deal with the flash #type install here since it shoudl be able to be #given on the boot prompt of syslinux/pxelinux #hence we will need to call self.readKickstart(dispatch.id, self.file, 0, "findflash") #self.flash = "/mnt/flash" #If self.flash is set we have a flash install and should #continue setting up it's steps, if not just return #and do a normal kickstart if self.flash != None: #We don't want to install packages more than the one we want self.addBase = 0 if self.xsetup != "run": #dispatch.skipStep("checkmonitorok", 1, 1) #dispatch.skipStep("setsanex", 1,1) dispatch.skipStep("xcustom", 1, 1) dispatch.skipStep("writexconfig", 1, 1) #pass if self.xsetup == "run": log("In Xsetup") dispatch.skipStep("videocard", skip=0) dispatch.skipStep("monitor", skip=0) dispatch.skipStep("xcustom", skip=0) #pass #dispatch.id.xsetup.skipx = 0 #pass #dispatch.skipStep("xcustom", 1, 1) #dispatch.skipStep("writexconfig", 1, 1) dispatch.skipStep("findpackages", 1, 1) dispatch.skipStep("selectlangpackages", 1, 1) dispatch.skipStep("package-selection", 1, 1) dispatch.skipStep("indivpackage", 1, 1) dispatch.skipStep("handleX11pkgs", 1, 1) dispatch.skipStep("checkdeps", 1, 1) dispatch.skipStep("dependencies", 1, 1) dispatch.skipStep("confirminstall", 1, 1) dispatch.skipStep("confirmupgrade", 1, 1) #dispatch.skipStep("install", 1, 1) #dispatch.skipStep("enablefilesystems",1, 1) dispatch.skipStep("migratefilesystems",1, 1) dispatch.skipStep("setuptime", 1, 1) dispatch.skipStep("preinstallconfig", 1, 1) dispatch.skipStep("installpackages", 1, 1) import dispatch as _dispatch counter=0 for step in _dispatch.installSteps: if step[0] == "installpackages": break counter = counter + 1 log("Before") log("DISPATCH %s" % (counter)) log("After") step = ("flashpre", flashdoPreInstall, ("method", "id", "instPath")) _dispatch.installSteps.insert(counter + 1,step) step = ("flashinstall", doImageInstall, ("method", "id", "instPath")) _dispatch.installSteps.insert(counter + 2,step) step = ("flashpackage", flashdoPackageInstall, ("method", "id", "instPath")) _dispatch.installSteps.insert(counter + 3,step) step = ("flashpost", doFlashPostInstall, ("method", "id", "instPath")) _dispatch.installSteps.insert(counter + 4,step) dispatch.skipStep("postinstallconfig", 1, 1) dispatch.skipStep("writeconfig", 1, 1) dispatch.skipStep("firstboot", 1, 1) #dispatch.skipStep("instbootloader", 1, 1) dispatch.skipStep("bootdisk", 1, 1) dispatch.skipStep("makebootdisk", 1, 1) dispatch.skipStep("videocard", 1, 1) dispatch.skipStep("writeksconfig", 1, 1) dispatch.skipStep("setfilecon", 1, 1) dispatch.skipStep("copylogs", 1, 1) #dispatch.skipStep("dopostaction", 1, 1) #log("DISPATCH %s" % (_dispatch.installSteps)) #Ok we need to figure out what kind of install we have #Its either a new install with some preconfigured image #or it's a recovery of a machine. #New install #Should handle different types of images #Server image -- console runlevel 3 #Desktop image -- XDM runlevel 5 #Server #Strait install config new network interface and so #forth (resolve.conf, yp.conf, hosts, network, ifcfg-ethx etc) #Desktop (same as server plus) #Strait install -- basic X install but the default runlevel is 3 #X install -- user does a X configuraration at install time #X clone install -- Xconfiguration is cloned due to the fact that #the hw is known (e.g. deployment of a bunch of desktops with the #same hw specs) #Recovery #As with new install there is a slight difference between a server #and a desktop. We will reuse all configuration data with the exception #of HW data and X #Server #Strait recovery based on MAC address or specified MAC address if recovered #to a new HW. #Desktop (same as server plus) #As usual a bit more ticky -- X if recover to the same box (MAC address) #then we can use the old X config. If we recover to different HW we can #use the old X config if we know the HW is the same. #Strait recover -- detect HW (MAC) is the same we reuse X configuration #X recovery - HW is different, X configuraration at install time #X clone recovery -- Forced reuse of Xconfiguration due to the fact that #the hw is known (e.g. replacement of a desktops with the same hw specs) def doFlashType(self, id = None , args = None): xsetup = None image = None mac = None if args != None: (args, extra) = isys.getopt(args, '', [ 'server=', 'dir=', 'image=', 'mac=', 'xsetup=']) log("Im in Args %s" % (args)) if extra: raise KickstartValueError, "unexpected arguments to flash command" for n in args: (str, arg) = n if (str == "--image"): image = arg elif (str == "--mac"): mac = arg elif (str == "--xsetup"): xsetup = arg cmdline = open("/proc/cmdline").read() if cmdline.find("image=") != -1: tmpflash = cmdline[cmdline.index("image="):].split(" ")[0] tmpflash = tmpflash.split("=")[1].strip() image = tmpflash.split(":")[0].strip() if cmdline.find("mac=") != -1: tmpflash = cmdline[cmdline.index("mac="):].split(" ")[0] tmpflash = tmpflash.split("=")[1].strip() mac = tmpflash.split(":")[0].strip() if cmdline.find("xsetup=") != -1: tmpflash = cmdline[cmdline.index("xsetup="):].split(" ")[0] tmpflash = tmpflash.split("=")[1].strip() xsetup = tmpflash.split(":")[0].strip() #If there is no image consider it as a default server installation #If the default runlevel of the image is 5 set it to 3 -- incase #someone is using a desktop image as the default image #Assume eth0 if we don't override it at boot time with a ksdevice dev = "eth0" ksdevice = None if cmdline.find("ksdevice=") != -1: ksdevice = cmdline[cmdline.index("ksdevice="):].split(" ")[0] ksdevice = ksdevice.split("=")[1].strip() dev = ksdevice macdev = isys.getMacAddress(dev) macimg = macdev.replace(":", '') log("MACDEV %s, MACIMG %s" % (macdev,macimg)) #log("The MAC is %s" % (isys.getMacAddress("eth0"))) #tmpstring = isys.getMacAddress("eth0") #log("The Mac is %s" % (tmpstring.replace(":", ''))) if image == None: self.image = "default" self.setup = "new" self.xsetup = "skip" self.mac = macdev self.setrunlevel = "yes" self.setmac = "yes" #Check if the default image is present path = "%s/%s" % (self.flash, self.image) if os.access(path,os.F_OK): return else: raise KickstartError, "The image %s you try to install is not accessibe" % (path) #* if the image name starts with either server or desktop consider it a new # a new installation write out the new config data exception is X #* if the image name starts with server set runlevel to 3 - just in case ;) #* If the user has supplied the xsetup keyword and X is not present in the image. # Then set runlevel to 3 (if it was 5) and skip xconfiguration since the user # obviously don't know what he is doing. #* if the image name start with desktop and no xsetup is provided skip the xconfiguration # set the runlevel to 3 #* if the image name starts with desktop and xsetup keyword is new then run xconfiguration #* if the image name starts with desktop and xsetup keyword is reuse skip the xconfiguration #* If image name is a recover try to find a image based on the mac. #* If the user has supplied a mac use that MAC address as image name instead #* If the user has supplied a mac change the MAC in the ifcfg-ethx file to # match the MAC address of the new network card #* If the user has not supplied a xsetup keyword skip the xconfigurations #* If the user has not supplied a xsetup keyword then if the default # runlevel is 5 change it to 3 (incase it was a desktop and the user # wants to do the configuration later on) #* If the user has supplied the xsetup keyword and X is not present in the image. # Then set runlevel to 3 (if it was 5) and skip xconfiguration since the user # obviously don't know what he is doing. #* If the user has supplied the xsetup keyword of new execute the xsetup # step and set the runlevel of 5. #* If the user has supplied a xsetup keyword of recover then skip the xconfiguration # The old xsetup will be used #NOTE The implementation below is overly done -- lots of redundancy but easier to read self.image = "default" self.xsetup = "skip" self.setrunlevel = "yes" self.mac = None self.setmac = "yes" self.setup = "new" if image == "recover": self.setup = "old" if mac != None: #This is a recovery to new hardware self.image = mac self.mac = isys.getMacAddress("eth0") self.setmac = "yes" if xsetup == "None": self.xsetup = "skip" self.setrunlevel = "yes" elif xsetup == "new": self.xsetup = "run" self.setrunlevel = "no" elif xsetup == "recover": self.xsetup = "skip" self.setrunlevel = "no" else: self.xsetup = "skip" self.setrunlevel = "yes" else: #This is a pure recovery on the same hardware #Reuse everything image = isys.getMacAddress("eth0") self.image = string.replace(image, ':', '') self.xsetup = "skip" self.setrunlevel = no self.mac = isys.getMacAddress("eth0") self.setmac = "no" elif image.startswith("server"): self.image = image self.xsetup = "skip" self.setrunlevel = "yes" self.mac = None self.setmac = "yes" elif image.startswith("desktop"): self.image = image self.mac = None self.setmac = "yes" if xsetup == "None": self.xsetup = "skip" self.setrunlevel = "yes" elif xsetup == "new": self.xsetup = "run" self.setrunlevel = "no" elif xsetup == "reuse": self.xsetup = "skip" self.setrunlevel = "no" else: self.xsetup = "skip" self.setrunlevel = "yes" #Check if the image is present path = "%s/%s" % (self.flash, self.image) if os.access(path,os.F_OK): return else: raise KickstartError, "The image %s you try to install is not accessibe" % (path) def doFlashMount(self, id = None , args = None): server = None dir = None tmpflash = None domount = False self.flashdetect = True oldargs = args if args != None: (args, extra) = isys.getopt(args, '', [ 'server=', 'dir=', 'image=', 'mac=', 'xsetup=']) log("Im in Args %s" % (args)) if extra: raise KickstartValueError, "unexpected arguments to flash command" for n in args: (str, arg) = n if (str == "--server"): server = arg elif (str == "--dir"): dir = arg domount = True if self.flash != None: return cmdline = open("/proc/cmdline").read() if cmdline.find("flash=") != -1: tmpflash = cmdline[cmdline.index("flash="):].split(" ")[0] tmpflash = tmpflash.split("=")[1].strip() server = tmpflash.split(":")[0].strip() dir = tmpflash.split(":")[1].strip() domount = True log("Flash server=%s dir=%s tmpflash=%s" % (server, dir, tmpflash)) device="%s:%s" % (server, dir) if domount == False: return try: os.mkdir("/mnt/flash") except os.error, (errno, msg): log("Error making directory %s: %s" % (i, msg)) raise KickstartError, "Faild to make Flash directory" device = "%s:%s/%s/%s" % (server, dir, productPath, productVersion) log("DEV %s" % (device)) try: _isys.mount("nfs", device, "/mnt/flash", 1, 0, 0) log("Flash dir %s" % (os.listdir("/mnt/flash"))) self.flash = "/mnt/flash" self.doFlashType(id, oldargs) return except: pass device = "%s:%s/%s" % (server, dir, productPath) try: _isys.mount("nfs", device, "/mnt/flash", 1, 0, 0) log("Flash dir %s" % (os.listdir("/mnt/flash"))) self.flash = "/mnt/flash" self.doFlashType(id, oldargs) return except: pass device = "%s:%s" % (server, dir) try: _isys.mount("nfs", device, "/mnt/flash", 1, 0, 0) log("Flash dir %s" % (os.listdir("/mnt/flash"))) self.flash = "/mnt/flash" self.doFlashType(id, oldargs) except os.error, (errno, msg): log("Faild to mount %s on /mnt/flash" % (device)) raise KickstartError, "Faild to mount %s on /mnt/flash" % (device) # read the kickstart config... if parsePre is set, only parse # the %pre, otherwise ignore the %pre. assume we're starting in where def readKickstart(self, id, file, parsePre = 0, where = "commands"): handlers = { "auth" : self.doAuthconfig , "authconfig" : self.doAuthconfig , "autopart" : self.doAutoPart , "cdrom" : None , "clearpart" : self.doClearPart , "ignoredisk" : self.doIgnoreDisk , "device" : None , "deviceprobe" : None , "driverdisk" : None , "firewall" : self.doFirewall , "selinux" : self.doSELinux , "harddrive" : None , "install" : None , "keyboard" : self.doKeyboard , "lang" : self.doLang , "langsupport" : self.doLangSupport , "lilo" : self.doLilo , "bootloader" : self.doBootloader , "lilocheck" : self.doLiloCheck , "mouse" : self.doMouse , "network" : self.doNetwork , "nfs" : None , "part" : self.definePartition , "partition" : self.definePartition , "raid" : self.defineRaid , "volgroup" : self.defineVolumeGroup, "logvol" : self.defineLogicalVolume, "reboot" : self.doReboot , "poweroff" : self.doReboot , "halt" : self.doReboot , "shutdown" : self.doReboot , "rootpw" : self.doRootPw , "skipx" : self.doSkipX , "text" : None , "graphical" : None , "cmdline" : None , "timezone" : self.doTimezone , "flash" : None , "url" : None , "upgrade" : self.doUpgrade , "xconfig" : self.doXconfig , "monitor" : self.doMonitor , "xdisplay" : None , "zerombr" : self.doZeroMbr , "interactive" : self.doInteractive , "autostep" : self.doAutoStep , "firstboot" : self.doFirstboot , "vnc" : None , } packages = [] groups = [] excludedPackages = [] script = "" scriptInterp = "/bin/sh" scriptLog = None if where == "pre" or where == "traceback": scriptChroot = 0 else: scriptChroot = 1 from rhpl.log import log log("I in image") import os #log("%s" % (os.listdir("/tmp"))) log("WHERE: %s" % (where)) if where == "findflash": for n in open(file).readlines(): args = isys.parseArgv(n) #We can safely skip all whitespaces and comments #at this stage if not args or args[0][0] == '#': continue #Sorry but you can't use the key word flash anywhere in the #kickstart file for now if args and args[0] == "flash": self.doFlashMount(id, args[1:]) return if self.flash == None: cmdline = open("/proc/cmdline").read() if cmdline.find("flash=") != -1: self.doFlashMount() return for n in open(file).readlines(): args = isys.parseArgv(n) # don't eliminate white space or comments from scripts if where not in ["pre", "post", "traceback"]: if not args or args[0][0] == '#': continue if args and (args[0] in ["%pre", "%post", "%traceback"]): if ((where =="pre" and parsePre) or (where in ["post", "traceback"] and not parsePre)): s = Script(script, scriptInterp, scriptChroot, scriptLog) if where == "pre": self.preScripts.append(s) elif where == "post": self.postScripts.append(s) else: self.tracebackScripts.append(s) where = args[0][1:] args = isys.parseArgv(n) script = "" scriptInterp = "/bin/sh" scriptLog = None if where == "pre" or where == "traceback": scriptChroot = 0 else: scriptChroot = 1 argList = [ 'interpreter=', "log=", "logfile=" ] if where == "post": argList.append('nochroot') (args, extra) = isys.getopt(args, '', argList) for n in args: (str, arg) = n if str == "--nochroot": scriptChroot = 0 elif str == "--interpreter": scriptInterp = arg elif str == "--log" or str == "--logfile": scriptLog = arg elif args and args[0] == "%include" and not parsePre: if len(args) < 2: raise KickstartError, "Invalid %include line" else: # read in the included file and set our where appropriately where = self.readKickstart(id, args[1], where = where) elif args and args[0] == "%packages": if ((where =="pre" and parsePre) or (where in ["post", "traceback"] and not parsePre)): s = Script(script, scriptInterp, scriptChroot, scriptLog) if where == "pre": self.preScripts.append(s) elif where == "post": self.postScripts.append(s) else: self.tracebackScripts.append(s) # if we're parsing the %pre, we don't need to continue if parsePre: continue if len(args) > 1: for arg in args[1:]: if arg == "--resolvedeps": id.handleDeps = RESOLVE_DEPS elif arg == "--ignoredeps": id.handleDeps = IGNORE_DEPS elif arg == "--excludedocs": id.excludeDocs = 1 elif arg == "--ignoremissing": self.handleMissing = KS_MISSING_IGNORE elif arg == "--nobase": self.addBase = 0 where = "packages" self.skipSteps.append("package-selection") else: # if we're parsing the %pre and not in the pre, continue if parsePre and where != "pre": continue elif where == "packages": #Scan for comments in package list...drop off #everything after "#" mark try: ind = string.index(n, "#") n = n[:ind] except: #No "#" found in line pass if n[0] == '@': n = n[1:] n = string.strip (n) groups.append(n) elif n[0] == '-': n = n[1:] n = string.strip(n) excludedPackages.append(n) else: n = string.strip (n) packages.append(n) elif where == "commands": if handlers.has_key(args[0]): if handlers[args[0]] is not None: handlers[args[0]](id, args[1:]) else: # unrecognized commanr raise KickstartError, "Unrecognized ks command: %s\nOn the line: %s" % (args[0], n) elif where in ["pre", "post", "traceback"]: script = script + n else: raise KickstartError, "I'm lost in kickstart" #When we do a flash we don't need packages if self.flash == None and self.flashdetect == True: log("Adding Group") self.groupList.extend(groups) self.packageList.extend(packages) self.excludedList.extend(excludedPackages) # test to see if they specified to clear partitions and also # tried to --onpart on a logical partition # # XXX # #if iutil.getArch() == 'i386' and self.fstab: #clear = self.getClearParts() #if clear == FSEDIT_CLEAR_LINUX or clear == FSEDIT_CLEAR_ALL: #for (mntpoint, (dev, fstype, reformat)) in self.fstab: #if int(dev[-1:]) > 4: #raise RuntimeError, "Clearpart and --onpart on non-primary partition %s not allowed" % dev # if self.flash == None and self.flashdetect == True: # cmdline = open("/proc/cmdline").read() # if cmdline.find("flash=") != -1: # self.doFlashMount() if ((where =="pre" and parsePre) or (where in ["post", "traceback"] and not parsePre)): s = Script(script, scriptInterp, scriptChroot, scriptLog) if where == "pre": self.preScripts.append(s) elif where == "post": self.postScripts.append(s) else: self.tracebackScripts.append(s) return where