2009-08-27 07:19:49 +00:00
|
|
|
#
|
|
|
|
# __init__.py
|
|
|
|
# lorax main class
|
|
|
|
#
|
|
|
|
# Copyright (C) 2009 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/>.
|
|
|
|
#
|
2009-09-23 10:21:33 +00:00
|
|
|
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
|
|
|
|
# David Cantrell <dcantrell@redhat.com>
|
2009-08-27 07:19:49 +00:00
|
|
|
#
|
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
import sys
|
2008-09-13 02:04:02 +00:00
|
|
|
import os
|
|
|
|
import tempfile
|
2009-09-23 10:21:33 +00:00
|
|
|
import re
|
|
|
|
import shutil
|
|
|
|
import ConfigParser
|
2009-04-22 13:01:28 +00:00
|
|
|
import time
|
2009-08-19 14:51:32 +00:00
|
|
|
import datetime
|
2009-09-23 10:21:33 +00:00
|
|
|
import commands
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
from config import Container
|
2009-09-23 10:21:33 +00:00
|
|
|
from utils.yumwrapper import Yum
|
|
|
|
from utils.fileutils import copy, edit, replace
|
2008-10-05 04:44:28 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
import output
|
|
|
|
import insttree
|
2009-04-22 13:01:28 +00:00
|
|
|
import images
|
2008-10-05 04:44:28 +00:00
|
|
|
|
2008-09-13 00:34:15 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
class Config(Container):
|
2009-09-23 10:21:33 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
def __init__(self):
|
2009-09-23 10:21:33 +00:00
|
|
|
config = ("confdir", "datadir", "tempdir", "debug", "cleanup")
|
2009-06-04 13:36:56 +00:00
|
|
|
|
|
|
|
# options
|
2009-09-23 10:21:33 +00:00
|
|
|
required = ("product", "version", "release", "outdir", "repos")
|
|
|
|
optional = ("variant", "bugurl", "updates", "mirrorlist")
|
2009-06-04 13:36:56 +00:00
|
|
|
|
|
|
|
Container.__init__(self, config + required + optional)
|
|
|
|
|
|
|
|
# set defaults
|
2009-09-23 10:21:33 +00:00
|
|
|
self.set(confdir="/etc/lorax",
|
|
|
|
datadir="/usr/share/lorax",
|
|
|
|
tempdir=tempfile.mkdtemp(prefix="lorax.tmp.",
|
|
|
|
dir=tempfile.gettempdir()),
|
|
|
|
debug=False,
|
|
|
|
cleanup=False)
|
|
|
|
|
|
|
|
self.set(product="",
|
|
|
|
version="",
|
|
|
|
release="",
|
|
|
|
outdir="",
|
|
|
|
repos=[])
|
2009-06-04 13:36:56 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.set(variant="",
|
|
|
|
bugurl="",
|
|
|
|
updates="",
|
|
|
|
mirrorlist=[])
|
2009-06-04 13:36:56 +00:00
|
|
|
|
2008-09-12 00:21:12 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
class LoraxError(Exception):
|
|
|
|
pass
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
class Lorax(object):
|
2009-09-23 10:21:33 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
def __init__(self, config):
|
|
|
|
assert isinstance(config, Config) == True
|
|
|
|
self.conf = config
|
|
|
|
|
|
|
|
# check if we have all required options
|
|
|
|
if not self.conf.repos:
|
2009-06-09 14:10:01 +00:00
|
|
|
raise LoraxError, "missing required parameter 'repos'"
|
2009-06-04 13:36:56 +00:00
|
|
|
if not self.conf.outdir:
|
2009-06-09 14:10:01 +00:00
|
|
|
raise LoraxError, "missing required parameter 'outdir'"
|
2009-06-04 13:36:56 +00:00
|
|
|
if not self.conf.product:
|
2009-06-09 14:10:01 +00:00
|
|
|
raise LoraxError, "missing required parameter 'product'"
|
2009-06-04 13:36:56 +00:00
|
|
|
if not self.conf.version:
|
2009-06-09 14:10:01 +00:00
|
|
|
raise LoraxError, "missing required parameter 'version'"
|
2009-06-04 13:36:56 +00:00
|
|
|
if not self.conf.release:
|
2009-06-09 14:10:01 +00:00
|
|
|
raise LoraxError, "missing required parameter 'release'"
|
2009-06-04 13:36:56 +00:00
|
|
|
|
|
|
|
self.yum = None
|
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
# initialize the output objects
|
|
|
|
self.so, self.se = output.initialize(verbose=self.conf.debug)
|
2008-10-10 07:51:45 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
def collect_repositories(self):
|
2009-04-22 13:01:28 +00:00
|
|
|
repolist = []
|
2009-09-23 10:21:33 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
for repospec in self.conf.repos:
|
2009-09-23 10:21:33 +00:00
|
|
|
if repospec.startswith("/"):
|
|
|
|
repo = "file://%s" % (repospec,)
|
|
|
|
self.so.info("Adding local repo: %s" % (repo,))
|
2009-04-22 13:01:28 +00:00
|
|
|
repolist.append(repo)
|
2009-09-23 10:21:33 +00:00
|
|
|
elif repospec.startswith("http://") or repospec.startswith("ftp://"):
|
|
|
|
self.so.info("Adding remote repo: %s" % (repospec,))
|
2009-04-22 13:01:28 +00:00
|
|
|
repolist.append(repospec)
|
2009-08-19 14:51:32 +00:00
|
|
|
else:
|
2009-09-23 10:21:33 +00:00
|
|
|
self.se.warning("Invalid repo path: %s" % (repospec,))
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
if not repolist:
|
2009-09-23 10:21:33 +00:00
|
|
|
return False
|
2009-04-22 13:01:28 +00:00
|
|
|
else:
|
2009-09-23 10:21:33 +00:00
|
|
|
mainrepo, extrarepos = repolist[0], repolist[1:]
|
|
|
|
|
|
|
|
self.conf.addAttr(["mainrepo", "extrarepos"])
|
|
|
|
self.conf.set(mainrepo=mainrepo, extrarepos=extrarepos)
|
|
|
|
|
|
|
|
# remove not needed attributes from config
|
|
|
|
self.conf.delAttr("repos")
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def initialize_directories(self):
|
|
|
|
# create the temporary directories
|
|
|
|
treedir = os.path.join(self.conf.tempdir, "treedir", "install")
|
|
|
|
os.makedirs(treedir)
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.info("Working directories:")
|
|
|
|
|
|
|
|
self.so.indent()
|
|
|
|
self.so.info("tempdir = %s" % (self.conf.tempdir,))
|
|
|
|
self.so.info("treedir = %s" % (treedir,))
|
|
|
|
self.so.unindent()
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.conf.addAttr("treedir")
|
|
|
|
self.conf.set(treedir=treedir)
|
2009-04-22 13:01:28 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
# create the destination directories
|
2009-06-04 13:36:56 +00:00
|
|
|
if not os.path.isdir(self.conf.outdir):
|
|
|
|
os.makedirs(self.conf.outdir, mode=0755)
|
2009-04-22 13:01:28 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
imagesdir = os.path.join(self.conf.outdir, "images")
|
|
|
|
if not os.path.isdir(imagesdir):
|
|
|
|
os.makedirs(imagesdir)
|
2009-04-22 13:01:28 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
pxebootdir = os.path.join(imagesdir, "pxeboot")
|
|
|
|
if not os.path.isdir(pxebootdir):
|
|
|
|
os.makedirs(pxebootdir)
|
2009-04-22 13:01:28 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
efibootdir = os.path.join(self.conf.outdir, "EFI", "BOOT")
|
|
|
|
if not os.path.isdir(efibootdir):
|
|
|
|
os.makedirs(efibootdir)
|
2008-10-06 01:08:38 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
# create the isolinux directory
|
|
|
|
isolinuxdir = os.path.join(self.conf.outdir, "isolinux")
|
|
|
|
if not os.path.isdir(isolinuxdir):
|
|
|
|
os.makedirs(isolinuxdir)
|
|
|
|
|
|
|
|
self.so.info("Destination directories:")
|
|
|
|
|
|
|
|
self.so.indent()
|
|
|
|
self.so.info("outdir = %s" % (self.conf.outdir,))
|
|
|
|
self.so.info("imagesdir = %s" % (imagesdir,))
|
|
|
|
self.so.info("pxebootdir = %s" % (pxebootdir,))
|
|
|
|
self.so.info("efibootdir = %s" % (efibootdir,))
|
|
|
|
self.so.info("isolinuxdir = %s" % (isolinuxdir,))
|
|
|
|
self.so.unindent()
|
|
|
|
|
|
|
|
self.conf.addAttr(["imagesdir", "pxebootdir",
|
|
|
|
"efibootdir", "isolinuxdir"])
|
|
|
|
self.conf.set(imagesdir=imagesdir, pxebootdir=pxebootdir,
|
|
|
|
efibootdir=efibootdir, isolinuxdir=isolinuxdir)
|
|
|
|
|
|
|
|
def initialize_yum(self):
|
|
|
|
yumconf = os.path.join(self.conf.tempdir, "yum.conf")
|
|
|
|
|
|
|
|
# create the yum cache directory
|
|
|
|
cachedir = os.path.join(self.conf.tempdir, "yumcache")
|
2009-09-09 10:43:00 +00:00
|
|
|
os.makedirs(cachedir)
|
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
c = ConfigParser.ConfigParser()
|
|
|
|
|
|
|
|
# main section
|
|
|
|
section = "main"
|
|
|
|
data = { "cachedir": cachedir,
|
|
|
|
"keepcache": 0,
|
|
|
|
"gpgcheck": 0,
|
|
|
|
"plugins": 0,
|
|
|
|
"reposdir": "",
|
|
|
|
"tsflags": "nodocs" }
|
|
|
|
c.add_section(section)
|
|
|
|
[c.set(section, key, value) for key, value in data.items()]
|
|
|
|
|
|
|
|
# main repo
|
|
|
|
section = "lorax-repo"
|
|
|
|
data = { "name": "lorax repo",
|
|
|
|
"baseurl": self.conf.mainrepo,
|
|
|
|
"enabled": 1 }
|
|
|
|
c.add_section(section)
|
|
|
|
[c.set(section, key, value) for key, value in data.items()]
|
|
|
|
|
|
|
|
# extra repos
|
|
|
|
for n, extra in enumerate(self.conf.extrarepos, start=1):
|
|
|
|
section = "lorax-extrarepo-%d" % (n,)
|
|
|
|
data = { "name": "lorax extra repo %d" % (n,),
|
|
|
|
"baseurl": extra,
|
|
|
|
"enabled": 1 }
|
|
|
|
c.add_section(section)
|
|
|
|
[c.set(section, key, value) for key, value in data.items()]
|
|
|
|
|
|
|
|
# mirrorlist repos
|
|
|
|
for n, mirror in enumerate(self.conf.mirrorlist, start=1):
|
|
|
|
section = "lorax-mirrorlistrepo-%d" % (n,)
|
|
|
|
data = { "name": "lorax mirrorlist repo %d" % (n,),
|
|
|
|
"mirrorlist": mirror,
|
|
|
|
"enabled": 1 }
|
|
|
|
c.add_section(section)
|
|
|
|
[c.set(section, key, value) for key, value in data.items()]
|
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
try:
|
2009-09-23 10:21:33 +00:00
|
|
|
f = open(yumconf, "w")
|
2009-06-09 14:10:01 +00:00
|
|
|
except IOError as why:
|
2009-09-23 10:21:33 +00:00
|
|
|
self.se.error("Unable to write yum.conf file: %s" % (why,))
|
|
|
|
return False
|
2009-06-04 13:36:56 +00:00
|
|
|
else:
|
2009-09-23 10:21:33 +00:00
|
|
|
c.write(f)
|
2009-06-04 13:36:56 +00:00
|
|
|
f.close()
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.conf.addAttr("yumconf")
|
2009-06-04 13:36:56 +00:00
|
|
|
self.conf.set(yumconf=yumconf)
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
# remove not needed attributes from config
|
|
|
|
self.conf.delAttr(["mainrepo", "extrarepos", "mirrorlist"])
|
2009-08-26 15:16:46 +00:00
|
|
|
|
2009-06-09 14:10:01 +00:00
|
|
|
# create the Yum object
|
2009-08-26 15:16:46 +00:00
|
|
|
self.yum = Yum(yumconf=self.conf.yumconf, installroot=self.conf.treedir,
|
2009-09-23 10:21:33 +00:00
|
|
|
errfile=os.path.join(self.conf.tempdir, "yum.errors"))
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
return True
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
def set_architecture(self):
|
|
|
|
# get the system architecture
|
2009-06-04 13:36:56 +00:00
|
|
|
unamearch = os.uname()[4]
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.conf.addAttr("buildarch")
|
2009-06-04 13:36:56 +00:00
|
|
|
self.conf.set(buildarch=unamearch)
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
# get the anaconda package architecture
|
|
|
|
installed, available = self.yum.find("anaconda")
|
2008-10-10 03:04:13 +00:00
|
|
|
try:
|
2009-06-09 14:10:01 +00:00
|
|
|
self.conf.set(buildarch=available[0].arch)
|
2009-06-04 13:36:56 +00:00
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
2009-08-19 14:51:32 +00:00
|
|
|
# set basearch
|
2009-09-23 10:21:33 +00:00
|
|
|
self.conf.addAttr("basearch")
|
2009-08-19 14:51:32 +00:00
|
|
|
self.conf.set(basearch=self.conf.buildarch)
|
2009-09-23 10:21:33 +00:00
|
|
|
|
|
|
|
if re.match(r"i.86", self.conf.basearch):
|
|
|
|
self.conf.set(basearch="i386")
|
|
|
|
elif self.conf.basearch == "sparc64":
|
|
|
|
self.conf.set(basearch="sparc")
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
# set the libdir
|
2009-09-23 10:21:33 +00:00
|
|
|
self.conf.addAttr("libdir")
|
|
|
|
self.conf.set(libdir="lib")
|
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
# on 64-bit systems, make sure we use lib64 as the lib directory
|
2009-09-23 10:21:33 +00:00
|
|
|
if self.conf.buildarch.endswith("64") or self.conf.buildarch == "s390x":
|
|
|
|
self.conf.set(libdir="lib64")
|
2009-06-04 13:36:56 +00:00
|
|
|
|
2009-08-25 16:26:52 +00:00
|
|
|
# set efiarch
|
2009-09-23 10:21:33 +00:00
|
|
|
self.conf.addAttr("efiarch")
|
|
|
|
self.conf.set(efiarch="")
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
if self.conf.buildarch == "i386":
|
|
|
|
self.conf.set(efiarch="ia32")
|
|
|
|
elif self.conf.buildarch == "x86_64":
|
|
|
|
self.conf.set(efiarch="x64")
|
|
|
|
elif self.conf.buildarch == "ia64":
|
|
|
|
self.conf.set(efiarch="ia64")
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
def write_treeinfo(self, discnum=1, totaldiscs=1, packagedir=""):
|
|
|
|
outfile = os.path.join(self.conf.outdir, ".treeinfo")
|
2009-06-04 13:36:56 +00:00
|
|
|
|
2009-06-09 14:10:01 +00:00
|
|
|
# don't print anything instead of None, if variant is not specified
|
2009-09-23 10:21:33 +00:00
|
|
|
variant = ""
|
|
|
|
if self.conf.variant is not None:
|
2009-06-04 13:36:56 +00:00
|
|
|
variant = self.conf.variant
|
2009-09-23 10:21:33 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
c = ConfigParser.ConfigParser()
|
2009-09-23 10:21:33 +00:00
|
|
|
|
|
|
|
# general section
|
|
|
|
section = "general"
|
|
|
|
data = { "timestamp": time.time(),
|
|
|
|
"family": self.conf.product,
|
|
|
|
"version": self.conf.version,
|
|
|
|
"arch": self.conf.basearch,
|
|
|
|
"variant": variant,
|
|
|
|
"discnum": discnum,
|
|
|
|
"totaldiscs": totaldiscs,
|
|
|
|
"packagedir": packagedir }
|
2009-04-22 13:01:28 +00:00
|
|
|
c.add_section(section)
|
2009-09-23 10:21:33 +00:00
|
|
|
[c.set(section, key, value) for key, value in data.items()]
|
2008-10-06 01:08:38 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
# images section
|
|
|
|
section = "images-%s" % (self.conf.basearch,)
|
|
|
|
data = { "kernel": "images/pxeboot/vmlinuz",
|
|
|
|
"initrd": "images/pxeboot/initrd.img",
|
|
|
|
"boot.iso": "images/boot.iso" }
|
2009-06-04 13:36:56 +00:00
|
|
|
c.add_section(section)
|
2009-09-23 10:21:33 +00:00
|
|
|
[c.set(section, key, value) for key, value in data.items()]
|
2009-06-04 13:36:56 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
try:
|
2009-09-23 10:21:33 +00:00
|
|
|
f = open(outfile, "w")
|
|
|
|
except IOError as why:
|
|
|
|
self.se.error("Unable to write .treeinfo file: %s" % (why,))
|
2009-04-22 13:01:28 +00:00
|
|
|
return False
|
|
|
|
else:
|
|
|
|
c.write(f)
|
|
|
|
f.close()
|
2009-09-23 10:21:33 +00:00
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def write_discinfo(self, discnum="ALL"):
|
|
|
|
outfile = os.path.join(self.conf.outdir, ".discinfo")
|
2008-10-04 01:46:01 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
try:
|
2009-09-23 10:21:33 +00:00
|
|
|
f = open(outfile, "w")
|
|
|
|
except IOError as why:
|
|
|
|
self.se.error("Unable to write .discinfo file: %s" % (why,))
|
2009-04-22 13:01:28 +00:00
|
|
|
return False
|
|
|
|
else:
|
2009-09-23 10:21:33 +00:00
|
|
|
f.write("%f\n" % (time.time(),))
|
|
|
|
f.write("%s\n" % (self.conf.release,))
|
|
|
|
f.write("%s\n" % (self.conf.basearch,))
|
|
|
|
f.write("%s\n" % (discnum,))
|
2009-08-19 14:51:32 +00:00
|
|
|
f.close()
|
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
return True
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
def write_buildstamp(self):
|
2009-09-23 10:21:33 +00:00
|
|
|
outfile = os.path.join(self.conf.treedir, ".buildstamp")
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
# make image uuid
|
2009-08-19 14:51:32 +00:00
|
|
|
now = datetime.datetime.now()
|
2009-09-23 10:21:33 +00:00
|
|
|
uuid = "%s.%s" % (now.strftime("%Y%m%d%H%M"), self.conf.buildarch)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
try:
|
2009-09-23 10:21:33 +00:00
|
|
|
f = open(outfile, "w")
|
|
|
|
except IOError as why:
|
|
|
|
self.se.error("Unable to write .buildstamp file: %s" % (why,))
|
2009-08-19 14:51:32 +00:00
|
|
|
return False
|
|
|
|
else:
|
2009-09-23 10:21:33 +00:00
|
|
|
f.write("%s\n" % (uuid,))
|
|
|
|
f.write("%s\n" % (self.conf.product,))
|
|
|
|
f.write("%s\n" % (self.conf.version,))
|
|
|
|
f.write("%s\n" % (self.conf.bugurl,))
|
2009-08-19 14:51:32 +00:00
|
|
|
f.close()
|
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.conf.addAttr("buildstamp")
|
|
|
|
self.conf.set(buildstamp=outfile)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
return True
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
def prepare_output_directory(self):
|
2009-08-19 14:51:32 +00:00
|
|
|
# write the images/README
|
2009-09-23 10:21:33 +00:00
|
|
|
src = os.path.join(self.conf.datadir, "images", "README")
|
|
|
|
dst = os.path.join(self.conf.imagesdir, "README")
|
2009-09-04 11:34:04 +00:00
|
|
|
shutil.copy2(src, dst)
|
2009-09-23 10:21:33 +00:00
|
|
|
replace(dst, r"@PRODUCT@", self.conf.product)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
# write the images/pxeboot/README
|
2009-09-23 10:21:33 +00:00
|
|
|
src = os.path.join(self.conf.datadir, "images", "pxeboot", "README")
|
|
|
|
dst = os.path.join(self.conf.pxebootdir, "README")
|
2009-09-04 11:34:04 +00:00
|
|
|
shutil.copy2(src, dst)
|
2009-09-23 10:21:33 +00:00
|
|
|
replace(dst, r"@PRODUCT@", self.conf.product)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
# set up some dir variables for further use
|
2009-09-23 10:21:33 +00:00
|
|
|
anacondadir = os.path.join(self.conf.treedir,
|
|
|
|
"usr", "lib", "anaconda-runtime")
|
|
|
|
|
|
|
|
bootdiskdir = os.path.join(anacondadir, "boot")
|
|
|
|
self.conf.addAttr("bootdiskdir")
|
2009-08-25 16:26:52 +00:00
|
|
|
self.conf.set(bootdiskdir=bootdiskdir)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
syslinuxdir = os.path.join(self.conf.treedir, "usr", "lib", "syslinux")
|
|
|
|
isolinuxbin = os.path.join(syslinuxdir, "isolinux.bin")
|
|
|
|
|
|
|
|
if os.path.isfile(isolinuxbin):
|
2009-08-19 14:51:32 +00:00
|
|
|
# copy the isolinux.bin
|
2009-09-04 11:34:04 +00:00
|
|
|
shutil.copy2(isolinuxbin, self.conf.isolinuxdir)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
# copy the syslinux.cfg to isolinux/isolinux.cfg
|
2009-09-23 10:21:33 +00:00
|
|
|
isolinuxcfg = os.path.join(self.conf.isolinuxdir, "isolinux.cfg")
|
|
|
|
shutil.copy2(os.path.join(bootdiskdir, "syslinux.cfg"), isolinuxcfg)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
# set the product and version in isolinux.cfg
|
2009-09-23 10:21:33 +00:00
|
|
|
replace(isolinuxcfg, r"@PRODUCT@", self.conf.product)
|
|
|
|
replace(isolinuxcfg, r"@VERSION@", self.conf.version)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
# set up the label for finding stage2 with a hybrid iso
|
2009-09-23 10:21:33 +00:00
|
|
|
replace(isolinuxcfg, r"initrd=initrd.img",
|
|
|
|
"initrd=initrd.img stage2=hd:LABEL=%s" % (self.conf.product,))
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
# copy the grub.conf
|
2009-09-23 10:21:33 +00:00
|
|
|
shutil.copy2(os.path.join(bootdiskdir, "grub.conf"),
|
|
|
|
self.conf.isolinuxdir)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
# copy the splash files
|
2009-09-23 10:21:33 +00:00
|
|
|
vesasplash = os.path.join(anacondadir, "syslinux-vesa-splash.jpg")
|
2009-08-19 14:51:32 +00:00
|
|
|
if os.path.isfile(vesasplash):
|
2009-09-23 10:21:33 +00:00
|
|
|
shutil.copy2(vesasplash,
|
|
|
|
os.path.join(self.conf.isolinuxdir, "splash.jpg"))
|
|
|
|
|
|
|
|
vesamenu = os.path.join(syslinuxdir, "vesamenu.c32")
|
2009-09-04 11:34:04 +00:00
|
|
|
shutil.copy2(vesamenu, self.conf.isolinuxdir)
|
2009-09-23 10:21:33 +00:00
|
|
|
|
|
|
|
replace(isolinuxcfg, r"default linux", r"default vesamenu.c32")
|
|
|
|
replace(isolinuxcfg, r"prompt 1", r"#prompt 1")
|
2009-08-19 14:51:32 +00:00
|
|
|
else:
|
2009-09-23 10:21:33 +00:00
|
|
|
splashtools = os.path.join(anacondadir, "splashtools.sh")
|
|
|
|
splashlss = os.path.join(bootdiskdir, "splash.lss")
|
|
|
|
|
2009-08-19 14:51:32 +00:00
|
|
|
if os.path.isfile(splashtools):
|
2009-09-23 10:21:33 +00:00
|
|
|
cmd = "%s %s %s" % (splashtools,
|
|
|
|
os.path.join(bootdiskdir, "syslinux-splash.jpg"),
|
|
|
|
splashlss)
|
|
|
|
out = commands.getoutput(cmd)
|
|
|
|
|
2009-08-19 14:51:32 +00:00
|
|
|
if os.path.isfile(splashlss):
|
2009-09-04 11:34:04 +00:00
|
|
|
shutil.copy2(splashlss, self.conf.isolinuxdir)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
# copy the .msg files
|
|
|
|
for file in os.listdir(bootdiskdir):
|
2009-09-23 10:21:33 +00:00
|
|
|
if file.endswith(".msg"):
|
|
|
|
shutil.copy2(os.path.join(bootdiskdir, file),
|
|
|
|
self.conf.isolinuxdir)
|
|
|
|
replace(os.path.join(self.conf.isolinuxdir, file),
|
|
|
|
r"@VERSION@", self.conf.version)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
|
|
|
# if present, copy the memtest
|
2009-09-23 10:21:33 +00:00
|
|
|
for fname in os.listdir(os.path.join(self.conf.treedir, "boot")):
|
|
|
|
if fname.startswith("memtest"):
|
|
|
|
src = os.path.join(self.conf.treedir, "boot", fname)
|
|
|
|
dst = os.path.join(self.conf.isolinuxdir, "memtest")
|
2009-09-04 11:34:04 +00:00
|
|
|
shutil.copy2(src, dst)
|
|
|
|
|
|
|
|
text = "label memtest86\n"
|
|
|
|
text = text + " menu label ^Memory test\n"
|
|
|
|
text = text + " kernel memtest\n"
|
|
|
|
text = text + " append -\n"
|
|
|
|
edit(isolinuxcfg, text, append=True)
|
2009-08-19 14:51:32 +00:00
|
|
|
else:
|
2009-09-23 10:21:33 +00:00
|
|
|
return False
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
return True
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
def create_install_image(self, type="squashfs"):
|
|
|
|
# scrub the install tree
|
|
|
|
install = images.Install(self.conf)
|
|
|
|
install.run()
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
installimg = os.path.join(self.conf.imagesdir, "install.img")
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
if type == "squashfs":
|
|
|
|
cmd = "mksquashfs %s %s -all-root -no-fragments -no-progress" \
|
|
|
|
% (self.conf.treedir, installimg)
|
|
|
|
self.so.debug(cmd)
|
|
|
|
err, output = commands.getstatusoutput(cmd)
|
|
|
|
if err:
|
|
|
|
self.se.info(output)
|
|
|
|
# XXX this gives an error on read only filesystem
|
|
|
|
#return False
|
|
|
|
|
|
|
|
elif type == "cramfs":
|
|
|
|
if self.conf.buildarch == "sparc64":
|
|
|
|
crambs = "--blocksize 8192"
|
|
|
|
elif self.conf.buildarch == "sparc":
|
|
|
|
crambs = "--blocksize 4096"
|
|
|
|
else:
|
|
|
|
crambs = ""
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
cmd = "mkfs.cramfs %s %s %s" % (crambs, self.conf.treedir,
|
|
|
|
installimg)
|
|
|
|
self.so.debug(cmd)
|
|
|
|
err, output = commands.getstatusoutput(cmd)
|
|
|
|
if err:
|
|
|
|
self.se.info(output)
|
|
|
|
return False
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
elif type == "ext2":
|
|
|
|
# TODO
|
|
|
|
return False
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
# append stage2 to .treeinfo file
|
|
|
|
text = "\n[stage2]\n"
|
|
|
|
text += "mainimage = %s\n" % (installimg,)
|
|
|
|
edit(os.path.join(self.conf.outdir, ".treeinfo"), append=True, text=text)
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
return True
|
2009-09-04 11:34:04 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
def create_boot_iso(self):
|
|
|
|
efiboot = os.path.join(self.conf.imagesdir, "efiboot.img")
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
if os.path.exists(efiboot):
|
|
|
|
self.so.info("Found efiboot.img, making an EFI-capable boot.iso")
|
|
|
|
efiargs = "-eltorito-alt-boot -e images/efiboot.img -no-emul-boot"
|
|
|
|
efigraft = "EFI/BOOT=%s" % (os.path.join(self.conf.outdir,
|
|
|
|
"EFI", "BOOT"),)
|
|
|
|
else:
|
|
|
|
self.so.info("No efiboot.img found, making BIOS-only boot.iso")
|
|
|
|
efiargs = ""
|
|
|
|
efigraft = ""
|
|
|
|
|
|
|
|
biosargs = "-b isolinux/isolinux.bin -c isolinux/boot.cat" \
|
|
|
|
" -no-emul-boot -boot-load-size 4 -boot-info-table"
|
|
|
|
mkisocmd = "mkisofs -v -o %s %s %s -R -J -V %s -T -graft-points" \
|
|
|
|
" isolinux=%s images=%s %s" % (os.path.join(self.conf.imagesdir,
|
|
|
|
"boot.iso"), biosargs, efiargs, self.conf.product,
|
|
|
|
self.conf.isolinuxdir, self.conf.imagesdir, efigraft)
|
|
|
|
self.so.debug(mkisocmd)
|
|
|
|
err, out = commands.getstatusoutput(mkisocmd)
|
|
|
|
if err:
|
|
|
|
self.se.info(out)
|
|
|
|
return False
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
hybrid = os.path.join("/", "usr", "bin", "isohybrid")
|
|
|
|
if os.path.exists(hybrid):
|
|
|
|
cmd = "%s %s" % (hybrid, os.path.join(self.conf.imagesdir, "boot.iso"))
|
|
|
|
self.so.debug(cmd)
|
|
|
|
err, out = commands.getstatusoutput(cmd)
|
|
|
|
if err:
|
|
|
|
self.se.info(out)
|
|
|
|
# XXX is this a problem?
|
|
|
|
# should we return false, or just go on?
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
return True
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
def clean_up(self):
|
|
|
|
if os.path.isdir(self.conf.tempdir):
|
|
|
|
shutil.rmtree(self.conf.tempdir, ignore_errors=True)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
def run(self):
|
|
|
|
self.so.header(":: Collecting repositories")
|
|
|
|
ok = self.collect_repositories()
|
|
|
|
if not ok:
|
|
|
|
# we have no valid repository to work with
|
|
|
|
self.se.error("No valid repository")
|
2009-08-19 14:51:32 +00:00
|
|
|
sys.exit(1)
|
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.header(":: Initializing directories")
|
|
|
|
self.initialize_directories()
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.header(":: Initializing yum")
|
|
|
|
ok = self.initialize_yum()
|
|
|
|
if not ok:
|
|
|
|
# the yum object could not be initialized
|
|
|
|
self.se.error("Unable to initialize the yum object")
|
|
|
|
sys.exit(1)
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.header(":: Setting the architecture")
|
|
|
|
self.set_architecture()
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.header(":: Writing the .treeinfo file")
|
|
|
|
ok = self.write_treeinfo()
|
|
|
|
if not ok:
|
|
|
|
# XXX is this a problem?
|
|
|
|
pass
|
2009-08-19 14:51:32 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.header(":: Writing the .discinfo file")
|
|
|
|
ok = self.write_discinfo()
|
|
|
|
if not ok:
|
|
|
|
# XXX is this a problem?
|
2009-08-19 14:51:32 +00:00
|
|
|
pass
|
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.header(":: Writing the .buildstamp file")
|
|
|
|
ok = self.write_buildstamp()
|
|
|
|
if not ok:
|
|
|
|
# XXX is this a problem?
|
|
|
|
pass
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.header(":: Preparing the install tree")
|
|
|
|
tree = insttree.InstallTree(self.conf, self.yum, (self.so, self.se))
|
|
|
|
kernelfiles = tree.run()
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
if not kernelfiles:
|
|
|
|
self.se.error("No kernel image found")
|
|
|
|
sys.exit(1)
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.header(":: Preparing the output directory")
|
|
|
|
ok = self.prepare_output_directory()
|
|
|
|
if not ok:
|
|
|
|
# XXX there's no isolinux.bin, i guess this is a problem...
|
|
|
|
self.se.error("Unable to prepare the output directory")
|
|
|
|
sys.exit(1)
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.conf.addAttr(["kernelfile", "kernelver"])
|
|
|
|
for kernelfile in kernelfiles:
|
|
|
|
# get the kernel version
|
|
|
|
m = re.match(r".*vmlinuz-(.*)", kernelfile)
|
|
|
|
if m:
|
|
|
|
kernelver = m.group(1)
|
|
|
|
self.conf.set(kernelfile=kernelfile, kernelver=kernelver)
|
|
|
|
else:
|
|
|
|
self.se.warning("Invalid kernel filename '%s'" % (kernelfile,))
|
|
|
|
continue
|
|
|
|
|
|
|
|
self.so.header(":: Creating the initrd image for kernel '%s'" \
|
|
|
|
% (os.path.basename(kernelfile),))
|
|
|
|
initrd = images.InitRD(self.conf, self.yum, (self.so, self.se))
|
|
|
|
initrd.run()
|
|
|
|
|
|
|
|
self.so.header(":: Creating the install image")
|
|
|
|
ok = self.create_install_image()
|
|
|
|
if not ok:
|
|
|
|
self.se.error("Unable to create the install image")
|
|
|
|
sys.exit(1)
|
2009-08-25 16:26:52 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
self.so.header(":: Creating the boot iso")
|
|
|
|
ok = self.create_boot_iso()
|
|
|
|
if not ok:
|
|
|
|
self.se.error("Unable to create the boot iso")
|
|
|
|
sys.exit(1)
|
2008-10-10 03:04:13 +00:00
|
|
|
|
2009-09-23 10:21:33 +00:00
|
|
|
if self.conf.cleanup:
|
|
|
|
self.so.header(":: Cleaning up")
|
|
|
|
self.clean_up()
|