diff --git a/src/pylorax/__init__.py b/src/pylorax/__init__.py index 6e0f3c4c..31e50fda 100644 --- a/src/pylorax/__init__.py +++ b/src/pylorax/__init__.py @@ -50,7 +50,6 @@ 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 @@ -171,13 +170,7 @@ class Lorax(BaseLoraxClass): # do we have all lorax required commands? self.lcmds = constants.LoraxRequiredCommands() - - """ - missing = self.lcmds.get_missing() - if missing: - logger.critical("missing required command: {0}".format(missing)) - sys.exit(1) - """ + # TODO: actually check for required commands # do we have a proper yum base object? logger.info("checking yum base object") @@ -185,12 +178,10 @@ class Lorax(BaseLoraxClass): logger.critical("no yum base object") sys.exit(1) - # set up yum helper logger.info("setting up yum helper") self.yum = yumhelper.LoraxYumHelper(ybo) logger.debug("using install root: {0}".format(self.yum.installroot)) - # set up build architecture logger.info("setting up build architecture") self.buildarch = self.get_buildarch() @@ -206,12 +197,10 @@ class Lorax(BaseLoraxClass): logger.debug("set efiarch = {0.efiarch}".format(self)) logger.debug("set libdir = {0.libdir}".format(self)) - # set up install tree logger.info("setting up install tree") self.installtree = LoraxInstallTree(self.yum, self.basearch, self.libdir, self.workdir) - # set up required build parameters logger.info("setting up build parameters") self.product = product self.version = version @@ -228,7 +217,6 @@ class Lorax(BaseLoraxClass): logger.debug("set bugurl = {0.bugurl}".format(self)) logger.debug("set is_beta = {0.is_beta}".format(self)) - # parse the template logger.info("parsing the template") tfile = joinpaths(self.conf.get("lorax", "sharedir"), self.conf.get("templates", "ramdisk")) @@ -277,23 +265,18 @@ class Lorax(BaseLoraxClass): for fname in pkgobj.filelist: fobj.write("{0}\n".format(fname)) - # remove locales logger.info("removing locales") self.installtree.remove_locales() - # create keymaps logger.info("creating keymaps") self.installtree.create_keymaps() - # create screenfont logger.info("creating screenfont") self.installtree.create_screenfont() - # move stubs logger.info("moving stubs") self.installtree.move_stubs() - # get the list of required modules logger.info("getting list of required modules") modules = [f[1:] for f in template if f[0] == "module"] modules = list(itertools.chain.from_iterable(modules)) @@ -331,45 +314,11 @@ class Lorax(BaseLoraxClass): # get anaconda portions self.installtree.get_anaconda_portions() - # set up output tree - self.outputtree = LoraxOutputTree(self.outputdir, self.installtree, - self.product, self.version) - - #self.outputtree.prepare() - #self.outputtree.get_isolinux() - #self.outputtree.get_memtest() - #self.outputtree.get_splash() - #self.outputtree.get_msg_files() - #self.outputtree.get_grub_conf() - # write .discinfo discinfo = DiscInfo(self.workdir, self.release, self.basearch) discinfo.write() - shutil.copy2(discinfo.path, self.outputtree.root) - - # move grubefi to workdir - grubefi = joinpaths(self.installtree.root, "boot/efi/EFI/redhat", - "grub.efi") - - if os.path.isfile(grubefi): - shutil.move(grubefi, self.workdir) - grubefi = joinpaths(self.workdir, os.path.basename(grubefi)) - else: - grubefi = None - - # move grub splash to workdir - splash = joinpaths(self.installtree.root, "boot/grub/", - "splash.xpm.gz") - - if os.path.isfile(splash): - shutil.move(splash, self.workdir) - splash = joinpaths(self.workdir, os.path.basename(splash)) - else: - splash = None - - # copy kernels to output directory - self.outputtree.get_kernels(self.workdir) + shutil.copy2(discinfo.path, self.outputdir) # create .treeinfo treeinfo = TreeInfo(self.workdir, self.product, self.version, @@ -382,9 +331,9 @@ class Lorax(BaseLoraxClass): ctype = self.conf.get("compression", "type") cspeed = self.conf.get("compression", "speed") - i = imgclass(kernellist=self.outputtree.kernels, + i = imgclass(kernellist=kernels, installtree=self.installtree, - outputroot=self.outputtree.root, + outputroot=self.outputdir, product=self.product, version=self.version, treeinfo=treeinfo, @@ -395,7 +344,6 @@ class Lorax(BaseLoraxClass): # backup required files i.backup_required(self.workdir) - # get list of not required packages logger.info("getting list of not required packages") remove = [f[1:] for f in template if f[0] == "remove"] @@ -437,113 +385,13 @@ class Lorax(BaseLoraxClass): logger.info("creating the initrd") i.create_initrd(self.libdir) - #initrds = [] - #for kernel in self.outputtree.kernels: - # suffix = "" - # if kernel.ktype == constants.K_PAE: - # suffix = "-PAE" - # elif kernel.ktype == constants.K_XEN: - # suffix = "-XEN" - # - # fname = "initrd{0}.img".format(suffix) - # - # initrd = DataHolder(fname=fname, - # fpath=joinpaths(self.workdir, fname), - # itype=kernel.ktype) - # - # logger.info("compressing install tree ({0})".format(kernel.version)) - # success, elapsed = self.installtree.compress(initrd, kernel) - # if not success: - # logger.error("error while compressing install tree") - # else: - # logger.info("took {0:.2f} seconds".format(elapsed)) - # - # initrds.append(initrd) - # - # # add kernel and initrd paths to .treeinfo - # section = "images-{0}".format("xen" if suffix else self.basearch) - # data = {"kernel": "images/pxeboot/{0}".format(kernel.fname)} - # treeinfo.add_section(section, data) - # data = {"initrd": "images/pxeboot/{0}".format(initrd.fname)} - # treeinfo.add_section(section, data) - # - ## copy initrds to outputtree - #shutil.copy2(initrds[0].fpath, self.outputtree.isolinuxdir) - # - ## create hard link - #source = joinpaths(self.outputtree.isolinuxdir, initrds[0].fname) - #link_name = joinpaths(self.outputtree.pxebootdir, initrds[0].fname) - #os.link(source, link_name) - # - #for initrd in initrds[1:]: - # shutil.copy2(initrd.fpath, self.outputtree.pxebootdir) - - # create efi images - efiboot = None - if grubefi and self.efiarch not in ("IA32",): - # create efibootdir - self.outputtree.efibootdir = joinpaths(self.outputtree.root, - "EFI/BOOT") - os.makedirs(self.outputtree.efibootdir) - - # set imgdir - self.outputtree.imgdir = joinpaths(self.outputtree.root, - "images") - - kernel = i.kernels[0] - initrd = i.initrds[0] - - # create efiboot image with kernel - logger.info("creating efiboot image with kernel") - efiboot = self.create_efiboot(kernel, initrd, grubefi, splash, - include_kernel=True) - - if efiboot is None: - logger.critical("unable to create efiboot image") - sys.exit(1) - - # create efidisk image - logger.info("creating efidisk image") - efidisk = self.create_efidisk(efiboot) - if efidisk is None: - logger.critical("unable to create efidisk image") - sys.exit(1) - - # remove efiboot image with kernel - os.unlink(efiboot) - - # create efiboot image without kernel - logger.info("creating efiboot image without kernel") - efiboot = self.create_efiboot(kernel, initrd, grubefi, splash, - include_kernel=False) - - if efiboot is None: - logger.critical("unable to create efiboot image") - sys.exit(1) - - # copy efiboot and efidisk to imgdir - shutil.copy2(efiboot, self.outputtree.imgdir) - shutil.copy2(efidisk, self.outputtree.imgdir) - # create boot iso logger.info("creating boot iso") - i.create_boot(efiboot) - - #bootiso = self.create_bootiso(self.outputtree, efiboot) - #if bootiso is None: - # logger.critical("unable to create boot iso") - # sys.exit(1) - # - #shutil.move(bootiso, self.outputtree.imgdir) - # - ## add the boot.iso - #section = "images-{0}".format(self.basearch) - #data = {"boot.iso": "images/{0}".format(os.path.basename(bootiso))} - #treeinfo.add_section(section, data) + i.create_boot(efiboot=None) # FIXME restore proper EFI function treeinfo.write() - shutil.copy2(treeinfo.path, self.outputtree.root) + shutil.copy2(treeinfo.path, self.outputdir) def get_buildarch(self): # get architecture of the available anaconda package @@ -561,204 +409,3 @@ class Lorax(BaseLoraxClass): buildarch = os.uname()[4] return buildarch - - def create_efiboot(self, kernel, initrd, grubefi, splash, - include_kernel=True): - - # create the efi tree directory - efitree = tempfile.mkdtemp(prefix="efitree.", dir=self.workdir) - - # copy kernel and initrd files to efi tree directory - if include_kernel: - shutil.copy2(kernel.fpath, efitree) - shutil.copy2(initrd.fpath, efitree) - efikernelpath = "/EFI/BOOT/{0}".format(kernel.fname) - efiinitrdpath = "/EFI/BOOT/{0}".format(initrd.fname) - else: - efikernelpath = "/images/pxeboot/{0}".format(kernel.fname) - efiinitrdpath = "/images/pxeboot/{0}".format(initrd.fname) - - efisplashpath = "/EFI/BOOT/splash.xpm.gz" - - # copy conf files to efi tree directory - src = joinpaths(self.installtree.root, "usr/share/anaconda/boot", - "*.conf") - - for fname in glob.glob(src): - shutil.copy2(fname, efitree) - - # edit the grub.conf file - grubconf = joinpaths(efitree, "grub.conf") - replace(grubconf, "@PRODUCT@", self.product) - replace(grubconf, "@VERSION@", self.version) - replace(grubconf, "@KERNELPATH@", efikernelpath) - replace(grubconf, "@INITRDPATH@", efiinitrdpath) - replace(grubconf, "@SPLASHPATH@", efisplashpath) - - if self.efiarch == "IA32": - shutil.copy2(grubconf, joinpaths(efitree, "BOOT.conf")) - - dst = joinpaths(efitree, "BOOT{0}.conf".format(self.efiarch)) - shutil.move(grubconf, dst) - - # copy grub.efi - if self.efiarch == "IA32": - shutil.copy2(grubefi, joinpaths(efitree, "BOOT.efi")) - - dst = joinpaths(efitree, "BOOT{0}.efi".format(self.efiarch)) - shutil.copy2(grubefi, dst) - - # copy splash.xpm.gz - shutil.copy2(splash, efitree) - - efiboot = joinpaths(self.workdir, "efiboot.img") - if os.path.isfile(efiboot): - os.unlink(efiboot) - - # calculate the size of the efi tree directory - overhead = constants.FS_OVERHEAD * 1024 - - sizeinbytes = overhead - for root, _, fnames in os.walk(efitree): - for fname in fnames: - fpath = joinpaths(root, fname) - fsize = os.path.getsize(fpath) - - # round to multiplications of 4096 - fsize = math.ceil(fsize / 4096.0) * 4096 - sizeinbytes += fsize - - # mkdosfs needs the size in blocks of 1024 bytes - size = int(math.ceil(sizeinbytes / 1024.0)) - - cmd = [self.lcmds.MKDOSFS, "-n", "ANACONDA", "-C", efiboot, str(size)] - logger.debug(cmd) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - proc.wait() - - # mount the efiboot image - efibootdir = tempfile.mkdtemp(prefix="efiboot.", dir=self.workdir) - - cmd = [self.lcmds.MOUNT, "-o", "loop,shortname=winnt,umask=0777", - "-t", "vfat", efiboot, efibootdir] - logger.debug(cmd) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - proc.wait() - - # copy the files to the efiboot image - dst = joinpaths(efibootdir, "EFI/BOOT") - os.makedirs(dst) - - for fname in os.listdir(efitree): - fpath = joinpaths(efitree, fname) - shutil.copy2(fpath, dst) - - if not include_kernel: - shutil.copy2(fpath, self.outputtree.efibootdir) - - # unmount the efiboot image - cmd = [self.lcmds.UMOUNT, efibootdir] - logger.debug(cmd) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - proc.wait() - - # remove the work directories - shutil.rmtree(efibootdir) - #shutil.rmtree(efitree) - - return efiboot - - def create_efidisk(self, efiboot): - efidisk = joinpaths(self.workdir, "efidisk.img") - if os.path.isfile(efidisk): - os.unlink(efidisk) - - partsize = os.path.getsize(efiboot) - disksize = 17408 + partsize + 17408 - disksize = disksize + (disksize % 512) - - # create efidisk file - with open(efidisk, "wb") as fobj: - fobj.truncate(disksize) - - # create loop device - loopdev = create_loop_dev(efidisk) - - if not loopdev: - os.unlink(efidisk) - return None - - # create dm device - dmdev = create_dm_dev("efiboot", disksize / 512, loopdev) - - if not dmdev: - remove_loop_dev(loopdev) - os.unlink(efidisk) - return None - - # create partition on dm device - cmd = [self.lcmds.PARTED, "--script", dmdev, "mklabel", "gpt", "unit", - "b", "mkpart", '\"EFI System Partition\"', "fat32", "17408", - str(partsize + 17408), "set", "1", "boot", "on"] - logger.debug(cmd) - - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - retcode = proc.wait() - - if not retcode == 0: - remove_dm_dev(dmdev) - remove_loop_dev(loopdev) - os.unlink(efidisk) - return None - - with open(efiboot, "rb") as f_from: - with open("{0}p1".format(dmdev), "wb") as f_to: - efidata = f_from.read(1024) - while efidata: - f_to.write(efidata) - efidata = f_from.read(1024) - - remove_dm_dev("{0}p1".format(dmdev)) - remove_dm_dev(dmdev) - remove_loop_dev(loopdev) - - return efidisk - - def create_bootiso(self, outputtree, efiboot=None): - bootiso = joinpaths(self.workdir, "boot.iso") - if os.path.isfile(bootiso): - os.unlink(bootiso) - - if efiboot is not None: - efiargs = ["-eltorito-alt-boot", "-e", "images/efiboot.img", - "-no-emul-boot"] - efigraft = ["EFI/BOOT={0}".format(outputtree.efibootdir)] - else: - efiargs = [] - efigraft = [] - - cmd = [self.lcmds.MKISOFS, "-o", bootiso, - "-b", "isolinux/isolinux.bin", "-c", "isolinux/boot.cat", - "-no-emul-boot", "-boot-load-size", "4", - "-boot-info-table"] + efiargs + ["-R", "-J", "-V", self.product, - "-T", "-graft-points", - "isolinux={0}".format(outputtree.isolinuxdir), - "images={0}".format(outputtree.imgdir)] + efigraft - logger.debug(cmd) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - retcode = proc.wait() - - if not retcode == 0: - return None - - # create hybrid iso - cmd = [self.lcmds.ISOHYBRID, bootiso] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - retcode = proc.wait() - - # implant iso md5 - cmd = [self.lcmds.IMPLANTISOMD5, bootiso] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - retcode = proc.wait() - - return bootiso diff --git a/src/pylorax/outputtree.py b/src/pylorax/outputtree.py deleted file mode 100644 index e37190b8..00000000 --- a/src/pylorax/outputtree.py +++ /dev/null @@ -1,188 +0,0 @@ -# -# 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 . -# -# Red Hat Author(s): Martin Gracik -# - -import logging -logger = logging.getLogger("pylorax.outputtree") - -import sys -import os -import shutil -import glob -import subprocess - -from base import BaseLoraxClass, DataHolder -from sysutils import * -import constants - - -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, workdir): - self.kernels = [] - - for n, kernel in enumerate(self.installtree.kernels): - suffix = "" - if kernel.ktype == constants.K_PAE: - suffix = "-PAE" - elif kernel.ktype == constants.K_XEN: - suffix = "-XEN" - - kname = "vmlinuz{0}".format(suffix) - - dst = joinpaths(workdir, kname) - shutil.copy2(kernel.fpath, dst) - - #if n == 0: - # # copy main kernel to isolinuxdir - # dst = joinpaths(self.isolinuxdir, kname) - # shutil.copy2(kernel.fpath, dst) - # - # # create hard link to main kernel in pxebootdir - # link_name = joinpaths(self.pxebootdir, kname) - # os.link(dst, link_name) - #else: - # # copy other kernels to pxebootdir - # dst = joinpaths(self.pxebootdir, kname) - # shutil.copy2(kernel.fpath, dst) - - # change the fname and fpath to new values - self.kernels.append(DataHolder(fname=kname, - fpath=dst, - version=kernel.version, - ktype=kernel.ktype)) - - 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 - self.isolinuxcfg = joinpaths(self.isolinuxdir, "isolinux.cfg") - shutil.copy2(syslinuxcfg, self.isolinuxcfg) - - # set product and version in isolinux.cfg - replace(self.isolinuxcfg, r"@PRODUCT@", self.product) - replace(self.isolinuxcfg, r"@VERSION@", self.version) - - def get_memtest(self): - # 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(self.isolinuxcfg, "a") as fobj: - fobj.write(text) - - break - - def get_splash(self): - 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(self.isolinuxcfg, r"default linux", "default vesamenu.c32") - replace(self.isolinuxcfg, r"prompt 1", "#prompt 1") - elif os.path.isfile(splashtolss): - cmd = [splashtolss, syslinuxsplash, splashlss] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - retcode = proc.wait() - if not retcode == 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) diff --git a/src/pylorax/sysutils.py b/src/pylorax/sysutils.py index cde3c85d..d5adcfd5 100644 --- a/src/pylorax/sysutils.py +++ b/src/pylorax/sysutils.py @@ -19,9 +19,7 @@ # Red Hat Author(s): Martin Gracik # -__all__ = ["joinpaths", "touch", "replace", "chown_", "chmod_", - "create_loop_dev", "remove_loop_dev", - "create_dm_dev", "remove_dm_dev"] +__all__ = ["joinpaths", "touch", "replace", "chown_", "chmod_"] import sys @@ -31,7 +29,6 @@ import fileinput import pwd import grp import glob -import subprocess import shutil @@ -87,48 +84,6 @@ def chmod_(path, mode, recursive=False): chmod_(nested, mode, recursive) -def create_loop_dev(fname): - cmd = ["losetup", "-f"] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - retcode = proc.wait() - if not retcode == 0: - return None - - loopdev = proc.stdout.read().strip() - - cmd = ["losetup", loopdev, fname] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - retcode = proc.wait() - if not retcode == 0: - return None - - return loopdev - - -def remove_loop_dev(dev): - cmd = ["losetup", "-d", dev] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - return proc.wait() - - -def create_dm_dev(name, size, loopdev): - table = '0 {0} linear {1} 0'.format(size, loopdev) - - cmd = ["dmsetup", "create", name, "--table", table] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - retcode = proc.wait() - if not retcode == 0: - return None - - return joinpaths("/dev/mapper", name) - - -def remove_dm_dev(dev): - cmd = ["dmsetup", "remove", dev] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - return proc.wait() - - def cpfile(src, dst): shutil.copy2(src, dst) if os.path.isdir(dst):