%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