Break up __init__.py into more modules

This commit is contained in:
Martin Gracik 2010-11-23 11:14:25 +01:00
parent 1084413b6b
commit 3413733661
6 changed files with 925 additions and 726 deletions

View File

@ -64,6 +64,12 @@ import ltmpl
import constants
from sysutils import *
from installtree import LoraxInstallTree
from outputtree import LoraxOutputTree
from buildstamp import BuildStamp
from treeinfo import TreeInfo
from discinfo import DiscInfo
ARCHMAPS = {
"i386": {"base": "i386", "efi": "IA32", "is64": False},
@ -702,729 +708,3 @@ class Lorax(BaseLoraxClass):
rc = p.wait()
return bootiso
class LoraxInstallTree(BaseLoraxClass):
def __init__(self, yum, basearch, libdir):
BaseLoraxClass.__init__(self)
self.yum = yum
self.root = self.yum.installroot
self.basearch = basearch
self.libdir = libdir
self.lcmds = constants.LoraxRequiredCommands()
def remove_locales(self):
chroot = lambda: os.chroot(self.root)
# get locales we need to keep
langtable = joinpaths(self.root, "usr/share/anaconda/lang-table")
with open(langtable, "r") as fobj:
langs = fobj.readlines()
langs = map(lambda l: l.split()[3].replace(".UTF-8", ".utf8"), langs)
langs = set(langs)
# get locales from locale-archive
localearch = "/usr/lib/locale/locale-archive"
cmd = [self.lcmds.LOCALEDEF, "--list-archive", localearch]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, preexec_fn=chroot)
output = p.stdout.read()
remove = set(output.split()) - langs
# remove not needed locales
cmd = [self.lcmds.LOCALEDEF, "-i", localearch,
"--delete-from-archive"] + list(remove)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, preexec_fn=chroot)
p.wait()
localearch = joinpaths(self.root, localearch)
shutil.move(localearch, localearch + ".tmpl")
p = subprocess.Popen([self.lcmds.BUILD_LOCALE_ARCHIVE],
preexec_fn=chroot)
p.wait()
# remove unneeded locales from /usr/share/locale
with open(langtable, "r") as fobj:
langs = fobj.readlines()
langs = map(lambda l: l.split()[1], langs)
localedir = joinpaths(self.root, "usr/share/locale")
for fname in os.listdir(localedir):
fpath = joinpaths(localedir, fname)
if os.path.isdir(fpath) and fname not in langs:
shutil.rmtree(fpath)
# move the lang-table to etc
shutil.move(langtable, joinpaths(self.root, "etc"))
def create_keymaps(self):
keymaps = joinpaths(self.root, "etc/keymaps.gz")
# look for override
override = "keymaps-override-{0.basearch}".format(self)
override = joinpaths(self.root, "usr/share/anaconda", override)
if os.path.isfile(override):
logger.debug("using keymaps override")
shutil.move(override, keymaps)
else:
# create keymaps
cmd = [joinpaths(self.root, "usr/share/anaconda", "getkeymaps"),
basearch, keymaps, self.root]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
p.wait()
return True
def create_screenfont(self):
dst = joinpaths(self.root, "etc/screenfont.gz")
screenfont = "screenfont-{0.basearch}.gz".format(self)
screenfont = joinpaths(self.root, "usr/share/anaconda", screenfont)
if not os.path.isfile(screenfont):
return False
else:
shutil.move(screenfont, dst)
return True
def move_stubs(self):
stubs = ("list-harddrives", "loadkeys", "losetup", "mknod",
"raidstart", "raidstop")
for stub in stubs:
src = joinpaths(self.root, "usr/share/anaconda",
"{0}-stub".format(stub))
dst = joinpaths(self.root, "usr/bin", stub)
if os.path.isfile(src):
shutil.move(src, dst)
# move restart-anaconda
src = joinpaths(self.root, "usr/share/anaconda", "restart-anaconda")
dst = joinpaths(self.root, "usr/bin")
shutil.move(src, dst)
# move sitecustomize.py
pythonpath = joinpaths(self.root, "usr", self.libdir, "python?.?")
for path in glob.glob(pythonpath):
src = joinpaths(path, "site-packages/pyanaconda/sitecustomize.py")
dst = joinpaths(path, "site-packages")
shutil.move(src, dst)
def cleanup_python_files(self):
for root, dnames, fnames in os.walk(self.root):
for fname in fnames:
if fname.endswith(".py"):
path = joinpaths(root, fname, follow_symlinks=False)
pyo, pyc = path + "o", path + "c"
if os.path.isfile(pyo):
os.unlink(pyo)
if os.path.isfile(pyc):
os.unlink(pyc)
os.symlink("/dev/null", pyc)
def move_modules(self):
shutil.move(joinpaths(self.root, "lib/modules"),
joinpaths(self.root, "modules"))
shutil.move(joinpaths(self.root, "lib/firmware"),
joinpaths(self.root, "firmware"))
os.symlink("../modules", joinpaths(self.root, "lib/modules"))
os.symlink("../firmware", joinpaths(self.root, "lib/firmware"))
def cleanup_kernel_modules(self, keepmodules, kernel):
moddir = joinpaths(self.root, "modules", kernel.version)
fwdir = joinpaths(self.root, "firmware")
# expand required modules
modules = set()
pattern = re.compile(r"\.ko$")
for name in keepmodules:
if name.startswith("="):
group = name[1:]
if group in ("scsi", "ata"):
p = joinpaths(moddir, "modules.block")
elif group == "net":
p = joinpaths(moddir, "modules.networking")
else:
p = joinpaths(moddir, "modules.{0}".format(group))
if os.path.isfile(p):
with open(p, "r") as fobj:
for line in fobj:
module = pattern.sub("", line.strip())
modules.add(module)
else:
modules.add(name)
# resolve modules dependencies
moddep = joinpaths(moddir, "modules.dep")
with open(moddep, "r") as fobj:
lines = map(lambda line: line.strip(), fobj.readlines())
modpattern = re.compile(r"^.*/(?P<name>.*)\.ko:(?P<deps>.*)$")
deppattern = re.compile(r"^.*/(?P<name>.*)\.ko$")
unresolved = True
while unresolved:
unresolved = False
for line in lines:
m = modpattern.match(line)
modname = m.group("name")
if modname in modules:
# add the dependencies
for dep in m.group("deps").split():
m = deppattern.match(dep)
depname = m.group("name")
if depname not in modules:
unresolved = True
modules.add(depname)
# required firmware
firmware = set()
# XXX required firmware
firmware.add("atmel_at76c504c-wpa.bin")
firmware.add("iwlwifi-3945-1.ucode")
firmware.add("iwlwifi-3945.ucode")
firmware.add("zd1211/zd1211_uph")
firmware.add("zd1211/zd1211_uphm")
firmware.add("zd1211/zd1211b_uph")
firmware.add("zd1211/zd1211b_uphm")
# remove not needed modules
for root, dnames, fnames in os.walk(moddir):
for fname in fnames:
path = os.path.join(root, fname)
name, ext = os.path.splitext(fname)
if ext == ".ko":
if name not in modules:
os.unlink(path)
logger.debug("removed module {0}".format(path))
else:
# get the required firmware
cmd = [self.lcmds.MODINFO, "-F", "firmware", path]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output = p.stdout.read()
firmware |= set(output.split())
# remove not needed firmware
firmware = map(lambda fw: joinpaths(fwdir, fw), list(firmware))
for root, dnames, fnames in os.walk(fwdir):
for fname in fnames:
path = joinpaths(root, fname)
if path not in firmware:
os.unlink(path)
logger.debug("removed firmware {0}".format(path))
# get the modules paths
modpaths = {}
for root, dnames, fnames in os.walk(moddir):
for fname in fnames:
modpaths[fname] = joinpaths(root, fname)
# create the modules list
modlist = {}
for modtype, fname in (("scsi", "modules.block"),
("eth", "modules.networking")):
fname = joinpaths(moddir, fname)
with open(fname, "r") as fobj:
lines = map(lambda l: l.strip(), fobj.readlines())
lines = filter(lambda l: l, lines)
for line in lines:
modname, ext = os.path.splitext(line)
if (line not in modpaths or
modname in ("floppy", "libiscsi", "scsi_mod")):
continue
cmd = [self.lcmds.MODINFO, "-F", "description", modpaths[line]]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output = p.stdout.read()
try:
desc = output.splitlines()[0]
desc = desc.strip()[:65]
except IndexError:
desc = "{0} driver".format(modname)
info = '{0}\n\t{1}\n\t"{2}"\n'
info = info.format(modname, modtype, desc)
modlist[modname] = info
# write the module-info
moduleinfo = joinpaths(os.path.dirname(moddir), "module-info")
with open(moduleinfo, "w") as fobj:
fobj.write("Version 0\n")
for modname in sorted(modlist.keys()):
fobj.write(modlist[modname])
def compress_modules(self, kernel):
moddir = joinpaths(self.root, "modules", kernel.version)
for root, dnames, fnames in os.walk(moddir):
for fname in filter(lambda f: f.endswith(".ko"), fnames):
path = os.path.join(root, fname)
with open(path, "rb") as fobj:
data = fobj.read()
gzipped = gzip.open("{0}.gz".format(path), "wb")
gzipped.write(data)
gzipped.close()
os.unlink(path)
def run_depmod(self, kernel):
systemmap = "System.map-{0.version}".format(kernel)
systemmap = joinpaths(self.root, "boot", systemmap)
cmd = [self.lcmds.DEPMOD, "-a", "-F", systemmap, "-b", self.root,
kernel.version]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
rc = p.wait()
if not rc == 0:
logger.critical(p.stdout.read())
sys.exit(1)
moddir = joinpaths(self.root, "modules", kernel.version)
# remove *map files
mapfiles = joinpaths(moddir, "*map")
for fpath in glob.glob(mapfiles):
os.unlink(fpath)
# remove build and source symlinks
for fname in ["build", "source"]:
os.unlink(joinpaths(moddir, fname))
def create_gconf(self):
gconfdir = joinpaths(self.root, ".gconf/desktop")
os.makedirs(gconfdir)
touch(joinpaths(gconfdir, "%gconf.xml"))
gconfdir = joinpaths(gconfdir, "gnome")
os.mkdir(gconfdir)
touch(joinpaths(gconfdir, "%gconf.xml"))
gconfdir = joinpaths(gconfdir, "interface")
os.mkdir(gconfdir)
text = """<?xml version="1.0"?>
<gconf>
<entry name="accessibility" mtime="1176200664" type="bool" value="true">
</entry>
<entry name="at-spi-corba" mtime="1176200664" type="bool" value="false">
</entry>
</gconf>
"""
with open(joinpaths(gconfdir, "%gconf.xml"), "w") as fobj:
fobj.write(text)
def move_repos(self):
src = joinpaths(self.root, "etc/yum.repos.d")
dst = joinpaths(self.root, "etc/anaconda.repos.d")
shutil.move(src, dst)
def create_depmod_conf(self):
text = "search updates built-in\n"
with open(joinpaths(self.root, "etc/depmod.d/dd.conf"), "w") as fobj:
fobj.write(text)
# XXX
def misc_tree_modifications(self):
# replace init with anaconda init
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "init")
dst = joinpaths(self.root, "sbin", "init")
os.unlink(dst)
shutil.copy2(src, dst)
# init symlinks
target = "/sbin/init"
name = joinpaths(self.root, "init")
os.symlink(target, name)
for fname in ["halt", "poweroff", "reboot"]:
name = joinpaths(self.root, "sbin", fname)
os.unlink(name)
os.symlink("init", name)
for fname in ["runlevel", "shutdown", "telinit"]:
name = joinpaths(self.root, "sbin", fname)
os.unlink(name)
# mtab symlink
target = "/proc/mounts"
name = joinpaths(self.root, "etc", "mtab")
os.symlink(target, name)
# create resolv.conf
touch(joinpaths(self.root, "etc", "resolv.conf"))
def get_config_files(self, src_dir):
# anaconda needs to change a couple of the default gconf entries
gconf = joinpaths(self.root, "etc", "gconf", "gconf.xml.defaults")
# 0 - path, 1 - entry type, 2 - value
gconf_settings = \
[("/apps/metacity/general/button_layout", "string", ":"),
("/apps/metacity/general/action_right_click_titlebar",
"string", "none"),
("/apps/metacity/window_keybindings/close", "string", "disabled"),
("/apps/metacity/global_keybindings/run_command_window_screenshot",
"string", "disabled"),
("/apps/metacity/global_keybindings/run_command_screenshot",
"string", "disabled"),
("/desktop/gnome/interface/accessibility", "bool", "true"),
("/desktop/gnome/interface/at-spi-corba", "bool", "false")]
for path, entry_type, value in gconf_settings:
cmd = [self.lcmds.GCONFTOOL, "--direct",
"--config-source=xml:readwrite:{0}".format(gconf),
"-s", "-t", entry_type, path, value]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
p.wait()
# get rsyslog config
src = joinpaths(src_dir, "rsyslog.conf")
dst = joinpaths(self.root, "etc")
shutil.copy2(src, dst)
# get .bash_history
src = joinpaths(src_dir, ".bash_history")
dst = joinpaths(self.root, "root")
shutil.copy2(src, dst)
# get .profile
src = joinpaths(src_dir, ".profile")
dst = joinpaths(self.root, "root")
shutil.copy2(src, dst)
# get libuser.conf
src = joinpaths(src_dir, "libuser.conf")
dst = joinpaths(self.root, "etc")
shutil.copy2(src, dst)
# get selinux config
if os.path.exists(joinpaths(self.root, "etc/selinux/targeted")):
src = joinpaths(src_dir, "selinux.config")
dst = joinpaths(self.root, "etc/selinux", "config")
shutil.copy2(src, dst)
def setup_sshd(self, src_dir):
# get sshd config
src = joinpaths(src_dir, "sshd_config.anaconda")
dst = joinpaths(self.root, "etc", "ssh")
shutil.copy2(src, dst)
src = joinpaths(src_dir, "pam.sshd")
dst = joinpaths(self.root, "etc", "pam.d", "sshd")
shutil.copy2(src, dst)
dst = joinpaths(self.root, "etc", "pam.d", "login")
shutil.copy2(src, dst)
dst = joinpaths(self.root, "etc", "pam.d", "remote")
shutil.copy2(src, dst)
# enable root shell logins and
# 'install' account that starts anaconda on login
passwd = joinpaths(self.root, "etc", "passwd")
with open(passwd, "a") as fobj:
fobj.write("sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin\n")
fobj.write("install:x:0:0:root:/root:/sbin/loader\n")
shadow = joinpaths(self.root, "etc", "shadow")
with open(shadow, "a") as fobj:
fobj.write("root::14438:0:99999:7:::\n")
fobj.write("install::14438:0:99999:7:::\n")
# change permissions
chmod_(shadow, 400)
def get_anaconda_portions(self):
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "loader")
dst = joinpaths(self.root, "sbin")
shutil.copy2(src, dst)
src = joinpaths(self.root, "usr/share/anaconda", "loader.tr")
dst = joinpaths(self.root, "etc")
shutil.move(src, dst)
src = joinpaths(self.root, "usr/libexec/anaconda", "auditd")
dst = joinpaths(self.root, "sbin")
shutil.copy2(src, dst)
def compress(self, initrd):
chdir = lambda: os.chdir(self.root)
start = time.time()
find = subprocess.Popen([self.lcmds.FIND, "."], stdout=subprocess.PIPE,
preexec_fn=chdir)
cpio = subprocess.Popen([self.lcmds.CPIO, "--quiet", "-c", "-o"],
stdin=find.stdout, stdout=subprocess.PIPE,
preexec_fn=chdir)
gzipped = gzip.open(initrd.fpath, "wb")
gzipped.write(cpio.stdout.read())
gzipped.close()
elapsed = time.time() - start
return True, elapsed
@property
def kernels(self):
kerneldir = "boot"
if self.basearch == "ia64":
kerneldir = "boot/efi/EFI/redhat"
kerneldir = joinpaths(self.root, kerneldir)
kpattern = re.compile(r"vmlinuz-(?P<ver>[-._0-9a-z]+?"
r"(?P<pae>(PAE)?)(?P<xen>(xen)?))$")
kernels = []
for fname in os.listdir(kerneldir):
m = kpattern.match(fname)
if m:
type = K_NORMAL
if m.group("pae"):
type = K_PAE
elif m.group("xen"):
type = K_XEN
kernels.append(Kernel(fname,
joinpaths(kerneldir, fname),
m.group("ver"),
type))
kernels = sorted(kernels, key=operator.attrgetter("type"))
return kernels
class LoraxOutputTree(BaseLoraxClass):
def __init__(self, root, installtree, product, version):
BaseLoraxClass.__init__(self)
self.root = root
self.installtree = installtree
self.product = product
self.version = version
def prepare(self):
imgdir = joinpaths(self.root, "images")
os.makedirs(imgdir)
logger.debug("created directory {0}".format(imgdir))
pxebootdir = joinpaths(self.root, "images/pxeboot")
os.makedirs(pxebootdir)
logger.debug("created directory {0}".format(pxebootdir))
isolinuxdir = joinpaths(self.root, "isolinux")
os.makedirs(isolinuxdir)
logger.debug("created directory {0}".format(isolinuxdir))
efibootdir = joinpaths(self.root, "EFI/BOOT")
os.makedirs(efibootdir)
logger.debug("created directory {0}".format(efibootdir))
self.imgdir = imgdir
self.pxebootdir = pxebootdir
self.isolinuxdir = isolinuxdir
self.efibootdir = efibootdir
def get_kernels(self, kernels):
# get the main kernel
self.main_kernel = kernels.pop(0)
# copy kernel to isolinuxdir
shutil.copy2(self.main_kernel.fpath, self.isolinuxdir)
# create kernel hard link in pxebootdir
source = joinpaths(self.isolinuxdir, self.main_kernel.fname)
link_name = joinpaths(self.pxebootdir, self.main_kernel.fname)
os.link(source, link_name)
# other kernels
for kernel in kernels:
shutil.copy2(kernel.fpath, self.pxebootdir)
def get_isolinux(self):
isolinuxbin = joinpaths(self.installtree.root,
"usr/share/syslinux/isolinux.bin")
syslinuxcfg = joinpaths(self.installtree.root,
"usr/share/anaconda/boot/syslinux.cfg")
# copy isolinux.bin
shutil.copy2(isolinuxbin, self.isolinuxdir)
# copy syslinux.cfg
isolinuxcfg = joinpaths(self.isolinuxdir, "isolinux.cfg")
shutil.copy2(syslinuxcfg, isolinuxcfg)
# set product and version in isolinux.cfg
replace(isolinuxcfg, r"@PRODUCT@", self.product)
replace(isolinuxcfg, r"@VERSION@", self.version)
# copy memtest
memtest = joinpaths(self.installtree.root,
"boot/memtest*")
for fname in glob.glob(memtest):
shutil.copy2(fname, joinpaths(self.isolinuxdir, "memtest"))
text = """label memtest86
menu label ^Memory test
kernel memtest
append -
"""
with open(isolinuxcfg, "a") as fobj:
fobj.write(text)
break
# get splash
vesasplash = joinpaths(self.installtree.root, "usr/share/anaconda",
"boot/syslinux-vesa-splash.jpg")
vesamenu = joinpaths(self.installtree.root,
"usr/share/syslinux/vesamenu.c32")
splashtolss = joinpaths(self.installtree.root,
"usr/share/anaconda/splashtolss.sh")
syslinuxsplash = joinpaths(self.installtree.root, "usr/share/anaconda",
"boot/syslinux-splash.jpg")
splashlss = joinpaths(self.installtree.root, "usr/share/anaconda",
"boot/splash.lss")
if os.path.isfile(vesasplash):
shutil.copy2(vesasplash, joinpaths(self.isolinuxdir, "splash.jpg"))
shutil.copy2(vesamenu, self.isolinuxdir)
replace(isolinuxcfg, r"default linux", "default vesamenu.c32")
replace(isolinuxcfg, r"prompt 1", "#prompt 1")
elif os.path.isfile(splashtolss):
cmd = [splashtolss, syslinuxsplash, splashlss]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
rc = p.wait()
if not rc == 0:
logger.error("failed to create splash.lss")
sys.exit(1)
if os.path.isfile(splashlss):
shutil.copy2(splashlss, self.isolinuxdir)
def get_msg_files(self):
msgfiles = joinpaths(self.installtree.root,
"usr/share/anaconda/boot/*.msg")
for fname in glob.glob(msgfiles):
shutil.copy2(fname, self.isolinuxdir)
path = joinpaths(self.isolinuxdir, os.path.basename(fname))
replace(path, r"@VERSION@", self.version)
def get_grub_conf(self):
grubconf = joinpaths(self.installtree.root,
"usr/share/anaconda/boot/grub.conf")
shutil.copy2(grubconf, self.isolinuxdir)
grubconf = joinpaths(self.isolinuxdir, "grub.conf")
replace(grubconf, r"@PRODUCT@", self.product)
replace(grubconf, r"@VERSION@", self.version)
class BuildStamp(object):
def __init__(self, workdir, product, version, bugurl, is_beta, buildarch):
self.path = joinpaths(workdir, ".buildstamp")
self.product = product
self.version = version
self.bugurl = bugurl
self.is_beta = is_beta
now = datetime.datetime.now()
now = now.strftime("%Y%m%d%H%M")
self.uuid = "{0}.{1}".format(now, buildarch)
def write(self):
logger.info("writing .buildstamp file")
with open(self.path, "w") as fobj:
fobj.write("[Main]\n")
fobj.write("BugURL={0.bugurl}\n".format(self))
fobj.write("IsBeta={0.is_beta}\n".format(self))
fobj.write("Product={0.product}\n".format(self))
fobj.write("UUID={0.uuid}\n".format(self))
fobj.write("Version={0.version}".format(self))
class DiscInfo(object):
def __init__(self, workdir, release, basearch, discnum="ALL"):
self.path = joinpaths(workdir, ".discinfo")
self.release = release
self.basearch = basearch
self.discnum = discnum
def write(self):
logger.info("writing .discinfo file")
with open(self.path, "w") as fobj:
fobj.write("{0:f}\n".format(time.time()))
fobj.write("{0}\n".format(self.release))
fobj.write("{0}\n".format(self.basearch))
fobj.write("{0}\n".format(self.discnum))
class TreeInfo(object):
def __init__(self, workdir, product, version, variant, basearch,
discnum=1, totaldiscs=1, packagedir=""):
self.path = joinpaths(workdir, ".treeinfo")
self.c = ConfigParser.ConfigParser()
section = "general"
data = {"timestamp": time.time(),
"family": product,
"version": version,
"variant": variant or "",
"arch": basearch,
"discnum": discnum,
"totaldiscs": totaldiscs,
"packagedir": packagedir}
self.c.add_section(section)
map(lambda (key, value): self.c.set(section, key, value), data.items())
def add_section(self, section, data):
if not self.c.has_section(section):
self.c.add_section(section)
map(lambda (key, value): self.c.set(section, key, value), data.items())
def write(self):
logger.info("writing .treeinfo file")
with open(self.path, "w") as fobj:
self.c.write(fobj)

51
src/pylorax/buildstamp.py Normal file
View File

@ -0,0 +1,51 @@
#
# buildstamp.py
#
# Copyright (C) 2010 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import logging
logger = logging.getLogger("pylorax.buildstamp")
import datetime
from sysutils import *
class BuildStamp(object):
def __init__(self, workdir, product, version, bugurl, is_beta, buildarch):
self.path = joinpaths(workdir, ".buildstamp")
self.product = product
self.version = version
self.bugurl = bugurl
self.is_beta = is_beta
now = datetime.datetime.now()
now = now.strftime("%Y%m%d%H%M")
self.uuid = "{0}.{1}".format(now, buildarch)
def write(self):
logger.info("writing .buildstamp file")
with open(self.path, "w") as fobj:
fobj.write("[Main]\n")
fobj.write("BugURL={0.bugurl}\n".format(self))
fobj.write("IsBeta={0.is_beta}\n".format(self))
fobj.write("Product={0.product}\n".format(self))
fobj.write("UUID={0.uuid}\n".format(self))
fobj.write("Version={0.version}".format(self))

44
src/pylorax/discinfo.py Normal file
View File

@ -0,0 +1,44 @@
#
# discinfo.py
#
# Copyright (C) 2010 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import logging
logger = logging.getLogger("pylorax.discinfo")
import time
from sysutils import *
class DiscInfo(object):
def __init__(self, workdir, release, basearch, discnum="ALL"):
self.path = joinpaths(workdir, ".discinfo")
self.release = release
self.basearch = basearch
self.discnum = discnum
def write(self):
logger.info("writing .discinfo file")
with open(self.path, "w") as fobj:
fobj.write("{0:f}\n".format(time.time()))
fobj.write("{0}\n".format(self.release))
fobj.write("{0}\n".format(self.basearch))
fobj.write("{0}\n".format(self.discnum))

575
src/pylorax/installtree.py Normal file
View File

@ -0,0 +1,575 @@
#
# installtree.py
#
# Copyright (C) 2010 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import logging
logger = logging.getLogger("pylorax.installtree")
import sys
import os
import ConfigParser
import tempfile
import shutil
import gzip
import shlex
import fnmatch
import re
import itertools
import glob
import time
import datetime
import itertools
import subprocess
import operator
import math
from collections import namedtuple
from base import BaseLoraxClass
import output
import yum
import yumhelper
import ltmpl
import constants
from sysutils import *
# kernel types
K_NORMAL = 0
K_PAE = 1
K_XEN = 1
# XXX kernel tuple
Kernel = namedtuple("Kernel", "fname fpath version type")
class LoraxInstallTree(BaseLoraxClass):
def __init__(self, yum, basearch, libdir):
BaseLoraxClass.__init__(self)
self.yum = yum
self.root = self.yum.installroot
self.basearch = basearch
self.libdir = libdir
self.lcmds = constants.LoraxRequiredCommands()
def remove_locales(self):
chroot = lambda: os.chroot(self.root)
# get locales we need to keep
langtable = joinpaths(self.root, "usr/share/anaconda/lang-table")
with open(langtable, "r") as fobj:
langs = fobj.readlines()
langs = map(lambda l: l.split()[3].replace(".UTF-8", ".utf8"), langs)
langs = set(langs)
# get locales from locale-archive
localearch = "/usr/lib/locale/locale-archive"
cmd = [self.lcmds.LOCALEDEF, "--list-archive", localearch]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, preexec_fn=chroot)
output = p.stdout.read()
remove = set(output.split()) - langs
# remove not needed locales
cmd = [self.lcmds.LOCALEDEF, "-i", localearch,
"--delete-from-archive"] + list(remove)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, preexec_fn=chroot)
p.wait()
localearch = joinpaths(self.root, localearch)
shutil.move(localearch, localearch + ".tmpl")
p = subprocess.Popen([self.lcmds.BUILD_LOCALE_ARCHIVE],
preexec_fn=chroot)
p.wait()
# remove unneeded locales from /usr/share/locale
with open(langtable, "r") as fobj:
langs = fobj.readlines()
langs = map(lambda l: l.split()[1], langs)
localedir = joinpaths(self.root, "usr/share/locale")
for fname in os.listdir(localedir):
fpath = joinpaths(localedir, fname)
if os.path.isdir(fpath) and fname not in langs:
shutil.rmtree(fpath)
# move the lang-table to etc
shutil.move(langtable, joinpaths(self.root, "etc"))
def create_keymaps(self):
keymaps = joinpaths(self.root, "etc/keymaps.gz")
# look for override
override = "keymaps-override-{0.basearch}".format(self)
override = joinpaths(self.root, "usr/share/anaconda", override)
if os.path.isfile(override):
logger.debug("using keymaps override")
shutil.move(override, keymaps)
else:
# create keymaps
cmd = [joinpaths(self.root, "usr/share/anaconda", "getkeymaps"),
basearch, keymaps, self.root]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
p.wait()
return True
def create_screenfont(self):
dst = joinpaths(self.root, "etc/screenfont.gz")
screenfont = "screenfont-{0.basearch}.gz".format(self)
screenfont = joinpaths(self.root, "usr/share/anaconda", screenfont)
if not os.path.isfile(screenfont):
return False
else:
shutil.move(screenfont, dst)
return True
def move_stubs(self):
stubs = ("list-harddrives", "loadkeys", "losetup", "mknod",
"raidstart", "raidstop")
for stub in stubs:
src = joinpaths(self.root, "usr/share/anaconda",
"{0}-stub".format(stub))
dst = joinpaths(self.root, "usr/bin", stub)
if os.path.isfile(src):
shutil.move(src, dst)
# move restart-anaconda
src = joinpaths(self.root, "usr/share/anaconda", "restart-anaconda")
dst = joinpaths(self.root, "usr/bin")
shutil.move(src, dst)
# move sitecustomize.py
pythonpath = joinpaths(self.root, "usr", self.libdir, "python?.?")
for path in glob.glob(pythonpath):
src = joinpaths(path, "site-packages/pyanaconda/sitecustomize.py")
dst = joinpaths(path, "site-packages")
shutil.move(src, dst)
def cleanup_python_files(self):
for root, dnames, fnames in os.walk(self.root):
for fname in fnames:
if fname.endswith(".py"):
path = joinpaths(root, fname, follow_symlinks=False)
pyo, pyc = path + "o", path + "c"
if os.path.isfile(pyo):
os.unlink(pyo)
if os.path.isfile(pyc):
os.unlink(pyc)
os.symlink("/dev/null", pyc)
def move_modules(self):
shutil.move(joinpaths(self.root, "lib/modules"),
joinpaths(self.root, "modules"))
shutil.move(joinpaths(self.root, "lib/firmware"),
joinpaths(self.root, "firmware"))
os.symlink("../modules", joinpaths(self.root, "lib/modules"))
os.symlink("../firmware", joinpaths(self.root, "lib/firmware"))
def cleanup_kernel_modules(self, keepmodules, kernel):
moddir = joinpaths(self.root, "modules", kernel.version)
fwdir = joinpaths(self.root, "firmware")
# expand required modules
modules = set()
pattern = re.compile(r"\.ko$")
for name in keepmodules:
if name.startswith("="):
group = name[1:]
if group in ("scsi", "ata"):
p = joinpaths(moddir, "modules.block")
elif group == "net":
p = joinpaths(moddir, "modules.networking")
else:
p = joinpaths(moddir, "modules.{0}".format(group))
if os.path.isfile(p):
with open(p, "r") as fobj:
for line in fobj:
module = pattern.sub("", line.strip())
modules.add(module)
else:
modules.add(name)
# resolve modules dependencies
moddep = joinpaths(moddir, "modules.dep")
with open(moddep, "r") as fobj:
lines = map(lambda line: line.strip(), fobj.readlines())
modpattern = re.compile(r"^.*/(?P<name>.*)\.ko:(?P<deps>.*)$")
deppattern = re.compile(r"^.*/(?P<name>.*)\.ko$")
unresolved = True
while unresolved:
unresolved = False
for line in lines:
m = modpattern.match(line)
modname = m.group("name")
if modname in modules:
# add the dependencies
for dep in m.group("deps").split():
m = deppattern.match(dep)
depname = m.group("name")
if depname not in modules:
unresolved = True
modules.add(depname)
# required firmware
firmware = set()
# XXX required firmware
firmware.add("atmel_at76c504c-wpa.bin")
firmware.add("iwlwifi-3945-1.ucode")
firmware.add("iwlwifi-3945.ucode")
firmware.add("zd1211/zd1211_uph")
firmware.add("zd1211/zd1211_uphm")
firmware.add("zd1211/zd1211b_uph")
firmware.add("zd1211/zd1211b_uphm")
# remove not needed modules
for root, dnames, fnames in os.walk(moddir):
for fname in fnames:
path = os.path.join(root, fname)
name, ext = os.path.splitext(fname)
if ext == ".ko":
if name not in modules:
os.unlink(path)
logger.debug("removed module {0}".format(path))
else:
# get the required firmware
cmd = [self.lcmds.MODINFO, "-F", "firmware", path]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output = p.stdout.read()
firmware |= set(output.split())
# remove not needed firmware
firmware = map(lambda fw: joinpaths(fwdir, fw), list(firmware))
for root, dnames, fnames in os.walk(fwdir):
for fname in fnames:
path = joinpaths(root, fname)
if path not in firmware:
os.unlink(path)
logger.debug("removed firmware {0}".format(path))
# get the modules paths
modpaths = {}
for root, dnames, fnames in os.walk(moddir):
for fname in fnames:
modpaths[fname] = joinpaths(root, fname)
# create the modules list
modlist = {}
for modtype, fname in (("scsi", "modules.block"),
("eth", "modules.networking")):
fname = joinpaths(moddir, fname)
with open(fname, "r") as fobj:
lines = map(lambda l: l.strip(), fobj.readlines())
lines = filter(lambda l: l, lines)
for line in lines:
modname, ext = os.path.splitext(line)
if (line not in modpaths or
modname in ("floppy", "libiscsi", "scsi_mod")):
continue
cmd = [self.lcmds.MODINFO, "-F", "description", modpaths[line]]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output = p.stdout.read()
try:
desc = output.splitlines()[0]
desc = desc.strip()[:65]
except IndexError:
desc = "{0} driver".format(modname)
info = '{0}\n\t{1}\n\t"{2}"\n'
info = info.format(modname, modtype, desc)
modlist[modname] = info
# write the module-info
moduleinfo = joinpaths(os.path.dirname(moddir), "module-info")
with open(moduleinfo, "w") as fobj:
fobj.write("Version 0\n")
for modname in sorted(modlist.keys()):
fobj.write(modlist[modname])
def compress_modules(self, kernel):
moddir = joinpaths(self.root, "modules", kernel.version)
for root, dnames, fnames in os.walk(moddir):
for fname in filter(lambda f: f.endswith(".ko"), fnames):
path = os.path.join(root, fname)
with open(path, "rb") as fobj:
data = fobj.read()
gzipped = gzip.open("{0}.gz".format(path), "wb")
gzipped.write(data)
gzipped.close()
os.unlink(path)
def run_depmod(self, kernel):
systemmap = "System.map-{0.version}".format(kernel)
systemmap = joinpaths(self.root, "boot", systemmap)
cmd = [self.lcmds.DEPMOD, "-a", "-F", systemmap, "-b", self.root,
kernel.version]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
rc = p.wait()
if not rc == 0:
logger.critical(p.stdout.read())
sys.exit(1)
moddir = joinpaths(self.root, "modules", kernel.version)
# remove *map files
mapfiles = joinpaths(moddir, "*map")
for fpath in glob.glob(mapfiles):
os.unlink(fpath)
# remove build and source symlinks
for fname in ["build", "source"]:
os.unlink(joinpaths(moddir, fname))
def create_gconf(self):
gconfdir = joinpaths(self.root, ".gconf/desktop")
os.makedirs(gconfdir)
touch(joinpaths(gconfdir, "%gconf.xml"))
gconfdir = joinpaths(gconfdir, "gnome")
os.mkdir(gconfdir)
touch(joinpaths(gconfdir, "%gconf.xml"))
gconfdir = joinpaths(gconfdir, "interface")
os.mkdir(gconfdir)
text = """<?xml version="1.0"?>
<gconf>
<entry name="accessibility" mtime="1176200664" type="bool" value="true">
</entry>
<entry name="at-spi-corba" mtime="1176200664" type="bool" value="false">
</entry>
</gconf>
"""
with open(joinpaths(gconfdir, "%gconf.xml"), "w") as fobj:
fobj.write(text)
def move_repos(self):
src = joinpaths(self.root, "etc/yum.repos.d")
dst = joinpaths(self.root, "etc/anaconda.repos.d")
shutil.move(src, dst)
def create_depmod_conf(self):
text = "search updates built-in\n"
with open(joinpaths(self.root, "etc/depmod.d/dd.conf"), "w") as fobj:
fobj.write(text)
# XXX
def misc_tree_modifications(self):
# replace init with anaconda init
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "init")
dst = joinpaths(self.root, "sbin", "init")
os.unlink(dst)
shutil.copy2(src, dst)
# init symlinks
target = "/sbin/init"
name = joinpaths(self.root, "init")
os.symlink(target, name)
for fname in ["halt", "poweroff", "reboot"]:
name = joinpaths(self.root, "sbin", fname)
os.unlink(name)
os.symlink("init", name)
for fname in ["runlevel", "shutdown", "telinit"]:
name = joinpaths(self.root, "sbin", fname)
os.unlink(name)
# mtab symlink
target = "/proc/mounts"
name = joinpaths(self.root, "etc", "mtab")
os.symlink(target, name)
# create resolv.conf
touch(joinpaths(self.root, "etc", "resolv.conf"))
def get_config_files(self, src_dir):
# anaconda needs to change a couple of the default gconf entries
gconf = joinpaths(self.root, "etc", "gconf", "gconf.xml.defaults")
# 0 - path, 1 - entry type, 2 - value
gconf_settings = \
[("/apps/metacity/general/button_layout", "string", ":"),
("/apps/metacity/general/action_right_click_titlebar",
"string", "none"),
("/apps/metacity/window_keybindings/close", "string", "disabled"),
("/apps/metacity/global_keybindings/run_command_window_screenshot",
"string", "disabled"),
("/apps/metacity/global_keybindings/run_command_screenshot",
"string", "disabled"),
("/desktop/gnome/interface/accessibility", "bool", "true"),
("/desktop/gnome/interface/at-spi-corba", "bool", "false")]
for path, entry_type, value in gconf_settings:
cmd = [self.lcmds.GCONFTOOL, "--direct",
"--config-source=xml:readwrite:{0}".format(gconf),
"-s", "-t", entry_type, path, value]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
p.wait()
# get rsyslog config
src = joinpaths(src_dir, "rsyslog.conf")
dst = joinpaths(self.root, "etc")
shutil.copy2(src, dst)
# get .bash_history
src = joinpaths(src_dir, ".bash_history")
dst = joinpaths(self.root, "root")
shutil.copy2(src, dst)
# get .profile
src = joinpaths(src_dir, ".profile")
dst = joinpaths(self.root, "root")
shutil.copy2(src, dst)
# get libuser.conf
src = joinpaths(src_dir, "libuser.conf")
dst = joinpaths(self.root, "etc")
shutil.copy2(src, dst)
# get selinux config
if os.path.exists(joinpaths(self.root, "etc/selinux/targeted")):
src = joinpaths(src_dir, "selinux.config")
dst = joinpaths(self.root, "etc/selinux", "config")
shutil.copy2(src, dst)
def setup_sshd(self, src_dir):
# get sshd config
src = joinpaths(src_dir, "sshd_config.anaconda")
dst = joinpaths(self.root, "etc", "ssh")
shutil.copy2(src, dst)
src = joinpaths(src_dir, "pam.sshd")
dst = joinpaths(self.root, "etc", "pam.d", "sshd")
shutil.copy2(src, dst)
dst = joinpaths(self.root, "etc", "pam.d", "login")
shutil.copy2(src, dst)
dst = joinpaths(self.root, "etc", "pam.d", "remote")
shutil.copy2(src, dst)
# enable root shell logins and
# 'install' account that starts anaconda on login
passwd = joinpaths(self.root, "etc", "passwd")
with open(passwd, "a") as fobj:
fobj.write("sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin\n")
fobj.write("install:x:0:0:root:/root:/sbin/loader\n")
shadow = joinpaths(self.root, "etc", "shadow")
with open(shadow, "a") as fobj:
fobj.write("root::14438:0:99999:7:::\n")
fobj.write("install::14438:0:99999:7:::\n")
# change permissions
chmod_(shadow, 400)
def get_anaconda_portions(self):
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "loader")
dst = joinpaths(self.root, "sbin")
shutil.copy2(src, dst)
src = joinpaths(self.root, "usr/share/anaconda", "loader.tr")
dst = joinpaths(self.root, "etc")
shutil.move(src, dst)
src = joinpaths(self.root, "usr/libexec/anaconda", "auditd")
dst = joinpaths(self.root, "sbin")
shutil.copy2(src, dst)
def compress(self, initrd):
chdir = lambda: os.chdir(self.root)
start = time.time()
find = subprocess.Popen([self.lcmds.FIND, "."], stdout=subprocess.PIPE,
preexec_fn=chdir)
cpio = subprocess.Popen([self.lcmds.CPIO, "--quiet", "-c", "-o"],
stdin=find.stdout, stdout=subprocess.PIPE,
preexec_fn=chdir)
gzipped = gzip.open(initrd.fpath, "wb")
gzipped.write(cpio.stdout.read())
gzipped.close()
elapsed = time.time() - start
return True, elapsed
@property
def kernels(self):
kerneldir = "boot"
if self.basearch == "ia64":
kerneldir = "boot/efi/EFI/redhat"
kerneldir = joinpaths(self.root, kerneldir)
kpattern = re.compile(r"vmlinuz-(?P<ver>[-._0-9a-z]+?"
r"(?P<pae>(PAE)?)(?P<xen>(xen)?))$")
kernels = []
for fname in os.listdir(kerneldir):
m = kpattern.match(fname)
if m:
type = K_NORMAL
if m.group("pae"):
type = K_PAE
elif m.group("xen"):
type = K_XEN
kernels.append(Kernel(fname,
joinpaths(kerneldir, fname),
m.group("ver"),
type))
kernels = sorted(kernels, key=operator.attrgetter("type"))
return kernels

189
src/pylorax/outputtree.py Normal file
View File

@ -0,0 +1,189 @@
#
# outputtree.py
#
# Copyright (C) 2010 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import logging
logger = logging.getLogger("pylorax.outputtree")
import sys
import os
import ConfigParser
import tempfile
import shutil
import gzip
import shlex
import fnmatch
import re
import itertools
import glob
import time
import datetime
import itertools
import subprocess
import operator
import math
from collections import namedtuple
from base import BaseLoraxClass
import output
import yum
import yumhelper
import ltmpl
import constants
from sysutils import *
class LoraxOutputTree(BaseLoraxClass):
def __init__(self, root, installtree, product, version):
BaseLoraxClass.__init__(self)
self.root = root
self.installtree = installtree
self.product = product
self.version = version
def prepare(self):
imgdir = joinpaths(self.root, "images")
os.makedirs(imgdir)
logger.debug("created directory {0}".format(imgdir))
pxebootdir = joinpaths(self.root, "images/pxeboot")
os.makedirs(pxebootdir)
logger.debug("created directory {0}".format(pxebootdir))
isolinuxdir = joinpaths(self.root, "isolinux")
os.makedirs(isolinuxdir)
logger.debug("created directory {0}".format(isolinuxdir))
efibootdir = joinpaths(self.root, "EFI/BOOT")
os.makedirs(efibootdir)
logger.debug("created directory {0}".format(efibootdir))
self.imgdir = imgdir
self.pxebootdir = pxebootdir
self.isolinuxdir = isolinuxdir
self.efibootdir = efibootdir
def get_kernels(self, kernels):
# get the main kernel
self.main_kernel = kernels.pop(0)
# copy kernel to isolinuxdir
shutil.copy2(self.main_kernel.fpath, self.isolinuxdir)
# create kernel hard link in pxebootdir
source = joinpaths(self.isolinuxdir, self.main_kernel.fname)
link_name = joinpaths(self.pxebootdir, self.main_kernel.fname)
os.link(source, link_name)
# other kernels
for kernel in kernels:
shutil.copy2(kernel.fpath, self.pxebootdir)
def get_isolinux(self):
isolinuxbin = joinpaths(self.installtree.root,
"usr/share/syslinux/isolinux.bin")
syslinuxcfg = joinpaths(self.installtree.root,
"usr/share/anaconda/boot/syslinux.cfg")
# copy isolinux.bin
shutil.copy2(isolinuxbin, self.isolinuxdir)
# copy syslinux.cfg
isolinuxcfg = joinpaths(self.isolinuxdir, "isolinux.cfg")
shutil.copy2(syslinuxcfg, isolinuxcfg)
# set product and version in isolinux.cfg
replace(isolinuxcfg, r"@PRODUCT@", self.product)
replace(isolinuxcfg, r"@VERSION@", self.version)
# copy memtest
memtest = joinpaths(self.installtree.root,
"boot/memtest*")
for fname in glob.glob(memtest):
shutil.copy2(fname, joinpaths(self.isolinuxdir, "memtest"))
text = """label memtest86
menu label ^Memory test
kernel memtest
append -
"""
with open(isolinuxcfg, "a") as fobj:
fobj.write(text)
break
# get splash
vesasplash = joinpaths(self.installtree.root, "usr/share/anaconda",
"boot/syslinux-vesa-splash.jpg")
vesamenu = joinpaths(self.installtree.root,
"usr/share/syslinux/vesamenu.c32")
splashtolss = joinpaths(self.installtree.root,
"usr/share/anaconda/splashtolss.sh")
syslinuxsplash = joinpaths(self.installtree.root, "usr/share/anaconda",
"boot/syslinux-splash.jpg")
splashlss = joinpaths(self.installtree.root, "usr/share/anaconda",
"boot/splash.lss")
if os.path.isfile(vesasplash):
shutil.copy2(vesasplash, joinpaths(self.isolinuxdir, "splash.jpg"))
shutil.copy2(vesamenu, self.isolinuxdir)
replace(isolinuxcfg, r"default linux", "default vesamenu.c32")
replace(isolinuxcfg, r"prompt 1", "#prompt 1")
elif os.path.isfile(splashtolss):
cmd = [splashtolss, syslinuxsplash, splashlss]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
rc = p.wait()
if not rc == 0:
logger.error("failed to create splash.lss")
sys.exit(1)
if os.path.isfile(splashlss):
shutil.copy2(splashlss, self.isolinuxdir)
def get_msg_files(self):
msgfiles = joinpaths(self.installtree.root,
"usr/share/anaconda/boot/*.msg")
for fname in glob.glob(msgfiles):
shutil.copy2(fname, self.isolinuxdir)
path = joinpaths(self.isolinuxdir, os.path.basename(fname))
replace(path, r"@VERSION@", self.version)
def get_grub_conf(self):
grubconf = joinpaths(self.installtree.root,
"usr/share/anaconda/boot/grub.conf")
shutil.copy2(grubconf, self.isolinuxdir)
grubconf = joinpaths(self.isolinuxdir, "grub.conf")
replace(grubconf, r"@PRODUCT@", self.product)
replace(grubconf, r"@VERSION@", self.version)

60
src/pylorax/treeinfo.py Normal file
View File

@ -0,0 +1,60 @@
#
# treeinfo.py
#
# Copyright (C) 2010 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import logging
logger = logging.getLogger("pylorax.treeinfo")
import ConfigParser
import time
from sysutils import *
class TreeInfo(object):
def __init__(self, workdir, product, version, variant, basearch,
discnum=1, totaldiscs=1, packagedir=""):
self.path = joinpaths(workdir, ".treeinfo")
self.c = ConfigParser.ConfigParser()
section = "general"
data = {"timestamp": time.time(),
"family": product,
"version": version,
"variant": variant or "",
"arch": basearch,
"discnum": discnum,
"totaldiscs": totaldiscs,
"packagedir": packagedir}
self.c.add_section(section)
map(lambda (key, value): self.c.set(section, key, value), data.items())
def add_section(self, section, data):
if not self.c.has_section(section):
self.c.add_section(section)
map(lambda (key, value): self.c.set(section, key, value), data.items())
def write(self):
logger.info("writing .treeinfo file")
with open(self.path, "w") as fobj:
self.c.write(fobj)