2009-06-04 13:36:56 +00:00
|
|
|
# __init__.py
|
2008-09-12 00:21:12 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
import sys
|
2008-09-13 02:04:02 +00:00
|
|
|
import os
|
|
|
|
import shutil
|
|
|
|
import tempfile
|
2009-04-22 13:01:28 +00:00
|
|
|
import time
|
|
|
|
import ConfigParser
|
2009-06-04 13:36:56 +00:00
|
|
|
import re
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
from config import Container
|
|
|
|
import utils.rpmutil as rpmutil
|
2008-10-05 04:44:28 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
import images
|
2008-10-05 04:44:28 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
from exceptions import LoraxError
|
2008-09-13 00:34:15 +00:00
|
|
|
|
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
class Config(Container):
|
|
|
|
def __init__(self):
|
|
|
|
config = ('confdir', 'datadir', 'tempdir', 'debug', 'cleanup')
|
|
|
|
|
|
|
|
# options
|
|
|
|
required = ('product', 'version', 'release', 'outdir', 'repos')
|
|
|
|
optional = ('variant', 'bugurl', 'updates', 'mirrorlist')
|
|
|
|
|
|
|
|
Container.__init__(self, config + required + optional)
|
|
|
|
|
|
|
|
# set defaults
|
|
|
|
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=[])
|
|
|
|
|
|
|
|
self.set(variant='',
|
|
|
|
bugurl='',
|
|
|
|
updates='',
|
|
|
|
mirrorlist=[])
|
2008-09-12 00:21:12 +00:00
|
|
|
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
class Lorax(object):
|
|
|
|
def __init__(self, config):
|
|
|
|
assert isinstance(config, Config) == True
|
|
|
|
self.conf = config
|
|
|
|
|
|
|
|
# check if we have all required options
|
|
|
|
if not self.conf.repos:
|
|
|
|
raise LoraxError, 'missing repos'
|
|
|
|
if not self.conf.outdir:
|
|
|
|
raise LoraxError, 'missing outdir'
|
|
|
|
if not self.conf.product:
|
|
|
|
raise LoraxError, 'missing product'
|
|
|
|
if not self.conf.version:
|
|
|
|
raise LoraxError, 'missing version'
|
|
|
|
if not self.conf.release:
|
|
|
|
raise LoraxError, 'missing release'
|
|
|
|
|
|
|
|
self.yum = None
|
|
|
|
|
|
|
|
def run(self):
|
2009-04-22 13:01:28 +00:00
|
|
|
print('Collecting repos...')
|
2009-06-04 13:36:56 +00:00
|
|
|
self.collectRepos()
|
2008-10-10 07:51:45 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
# check if we have at least one valid repository
|
|
|
|
if not self.conf.repo:
|
|
|
|
sys.stderr.write('ERROR: no valid repository\n')
|
2009-04-22 13:01:28 +00:00
|
|
|
sys.exit(1)
|
2008-10-10 08:11:13 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
print('Initializing directories...')
|
2009-06-04 13:36:56 +00:00
|
|
|
self.initDirs()
|
2008-10-10 07:51:45 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
print('Initializing yum...')
|
|
|
|
self.initYum()
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
print('Setting build architecture...')
|
|
|
|
self.setBuildArch()
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
print('Writing .treeinfo...')
|
2009-06-04 13:36:56 +00:00
|
|
|
self.writeTreeInfo()
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
print('Writing .discinfo...')
|
2009-06-04 13:36:56 +00:00
|
|
|
self.writeDiscInfo()
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
print('Preparing the install tree...')
|
|
|
|
self.prepareInstRoot()
|
|
|
|
|
|
|
|
print('Creating the images...')
|
2009-04-22 13:01:28 +00:00
|
|
|
self.makeImages()
|
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
if self.conf.cleanup:
|
2009-04-22 13:01:28 +00:00
|
|
|
print('Cleaning up...')
|
|
|
|
self.cleanUp()
|
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
def collectRepos(self):
|
2009-04-22 13:01:28 +00:00
|
|
|
repolist = []
|
2009-06-04 13:36:56 +00:00
|
|
|
for repospec in self.conf.repos:
|
2009-04-22 13:01:28 +00:00
|
|
|
if repospec.startswith('/'):
|
2009-06-04 13:36:56 +00:00
|
|
|
repo = 'file://%s' % repospec
|
|
|
|
print('Adding local repo: %s' % repo)
|
2009-04-22 13:01:28 +00:00
|
|
|
repolist.append(repo)
|
|
|
|
elif repospec.startswith('http://') or repospec.startswith('ftp://'):
|
2009-06-04 13:36:56 +00:00
|
|
|
print('Adding remote repo: %s' % repospec)
|
2009-04-22 13:01:28 +00:00
|
|
|
repolist.append(repospec)
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
if not repolist:
|
2009-06-04 13:36:56 +00:00
|
|
|
repo, extrarepos = None, []
|
2009-04-22 13:01:28 +00:00
|
|
|
else:
|
2009-06-04 13:36:56 +00:00
|
|
|
repo, extrarepos = repolist[0], repolist[1:]
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
self.conf.addAttr(['repo', 'extrarepos'])
|
|
|
|
self.conf.set(repo=repo, extrarepos=extrarepos)
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
# remove repos attribute, to get a traceback, if we use it later
|
|
|
|
self.conf.delAttr('repos')
|
2009-04-22 13:01:28 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
def initDirs(self):
|
|
|
|
if not os.path.isdir(self.conf.outdir):
|
|
|
|
os.makedirs(self.conf.outdir, mode=0755)
|
2009-04-22 13:01:28 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
treedir = os.path.join(self.conf.tempdir, 'treedir', 'install')
|
|
|
|
cachedir = os.path.join(self.conf.tempdir, 'yumcache')
|
2009-04-22 13:01:28 +00:00
|
|
|
|
|
|
|
print('Working directories:')
|
2009-06-04 13:36:56 +00:00
|
|
|
print(' tempdir = %s' % self.conf.tempdir)
|
|
|
|
print(' treedir = %s' % treedir)
|
|
|
|
print(' cachedir = %s' % cachedir)
|
2009-04-22 13:01:28 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
self.conf.addAttr(['treedir', 'cachedir'])
|
|
|
|
self.conf.set(treedir=treedir, cachedir=cachedir)
|
2008-10-06 01:08:38 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
def initYum(self):
|
|
|
|
yumconf = os.path.join(self.conf.tempdir, 'yum.conf')
|
|
|
|
|
|
|
|
try:
|
|
|
|
f = open(yumconf, 'w')
|
|
|
|
except IOError:
|
|
|
|
sys.stderr.write('ERROR: Unable to write yum.conf file\n')
|
|
|
|
sys.exit(1)
|
|
|
|
else:
|
|
|
|
f.write('[main]\n')
|
|
|
|
f.write('cachedir=%s\n' % self.conf.cachedir)
|
|
|
|
f.write('keepcache=0\n')
|
|
|
|
f.write('gpgcheck=0\n')
|
|
|
|
f.write('plugins=0\n')
|
|
|
|
f.write('reposdir=\n')
|
|
|
|
f.write('tsflags=nodocs\n\n')
|
|
|
|
|
|
|
|
f.write('[loraxrepo]\n')
|
|
|
|
f.write('name=lorax repo\n')
|
|
|
|
f.write('baseurl=%s\n' % self.conf.repo)
|
|
|
|
f.write('enabled=1\n\n')
|
|
|
|
|
|
|
|
for n, extra in enumerate(self.conf.extrarepos, start=1):
|
|
|
|
f.write('[lorax-extrarepo-%d]\n' % n)
|
|
|
|
f.write('name=lorax extra repo %d\n' % n)
|
|
|
|
f.write('baseurl=%s\n' % extra)
|
|
|
|
f.write('enabled=1\n')
|
|
|
|
|
|
|
|
for n, mirror in enumerate(self.conf.mirrorlist, start=1):
|
|
|
|
f.write('[lorax-mirrorlistrepo-%d]\n' % n)
|
|
|
|
f.write('name=lorax mirrorlist repo %d\n' % n)
|
|
|
|
f.write('mirrorlist=%s\n' % mirror)
|
|
|
|
f.write('enabled=1\n')
|
2009-04-22 13:01:28 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
f.close()
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
self.conf.addAttr('yumconf')
|
|
|
|
self.conf.set(yumconf=yumconf)
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
self.yum = rpmutil.Yum(yumconf=self.conf.yumconf, installroot=self.conf.treedir)
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
# remove not needed options
|
|
|
|
self.conf.delAttr(['repo', 'extrarepos', 'mirrorlist'])
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
def setBuildArch(self):
|
|
|
|
unamearch = os.uname()[4]
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
self.conf.addAttr('buildarch')
|
|
|
|
self.conf.set(buildarch=unamearch)
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
anaconda = self.yum.find('anaconda')
|
2008-10-10 03:04:13 +00:00
|
|
|
try:
|
2009-06-04 13:36:56 +00:00
|
|
|
self.conf.set(buildarch=anaconda[0].arch)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
# set the libdir
|
|
|
|
self.conf.addAttr('libdir')
|
|
|
|
self.conf.set(libdir='lib')
|
|
|
|
# on 64-bit systems, make sure we use lib64 as the lib directory
|
|
|
|
if self.conf.buildarch.endswith('64') or self.conf.buildarch == 's390x':
|
|
|
|
self.conf.set(libdir='lib64')
|
|
|
|
|
|
|
|
def writeTreeInfo(self, discnum=1, totaldiscs=1, packagedir=''):
|
|
|
|
outfile = os.path.join(self.conf.outdir, '.treeinfo')
|
|
|
|
|
|
|
|
# don't print anything instead of None if variant is not specified
|
|
|
|
variant = ''
|
|
|
|
if self.conf.variant:
|
|
|
|
variant = self.conf.variant
|
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
data = { 'timestamp': time.time(),
|
2009-06-04 13:36:56 +00:00
|
|
|
'family': self.conf.product,
|
|
|
|
'version': self.conf.version,
|
|
|
|
'arch': self.conf.buildarch,
|
|
|
|
'variant': variant,
|
2009-04-22 13:01:28 +00:00
|
|
|
'discnum': str(discnum),
|
|
|
|
'totaldiscs': str(totaldiscs),
|
|
|
|
'packagedir': packagedir }
|
|
|
|
|
|
|
|
c = ConfigParser.ConfigParser()
|
|
|
|
|
|
|
|
section = 'general'
|
|
|
|
c.add_section(section)
|
|
|
|
for key, value in data.items():
|
|
|
|
c.set(section, key, value)
|
2008-10-06 01:08:38 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
section = 'images-%s' % self.conf.buildarch
|
|
|
|
c.add_section(section)
|
|
|
|
c.set(section, 'kernel', 'images/pxeboot/vmlinuz')
|
|
|
|
c.set(section, 'initrd', 'images/pxeboot/initrd.img')
|
|
|
|
|
|
|
|
# XXX actually create the boot iso somewhere, and set up this attribute
|
|
|
|
self.conf.addAttr('bootiso')
|
|
|
|
|
|
|
|
if self.conf.bootiso:
|
|
|
|
c.set(section, 'boot.iso', 'images/%s' % self.conf.bootiso)
|
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
try:
|
|
|
|
f = open(outfile, 'w')
|
|
|
|
except IOError:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
c.write(f)
|
|
|
|
f.close()
|
|
|
|
return True
|
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
def writeDiscInfo(self, discnum=0):
|
|
|
|
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:
|
|
|
|
f = open(outfile, 'w')
|
|
|
|
except IOError:
|
|
|
|
return False
|
|
|
|
else:
|
2009-06-04 13:36:56 +00:00
|
|
|
f.write('%f\n' % time.time())
|
|
|
|
f.write('%s\n' % self.conf.release)
|
|
|
|
f.write('%s\n' % self.conf.buildarch)
|
|
|
|
f.write('%d\n' % discnum)
|
2009-04-22 13:01:28 +00:00
|
|
|
f.close()
|
|
|
|
return True
|
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
def prepareInstRoot(self):
|
|
|
|
# XXX why do we need this?
|
|
|
|
os.symlink(os.path.join(os.path.sep, 'tmp'),
|
|
|
|
os.path.join(self.conf.treedir, 'var', 'lib', 'xkb'))
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-04-22 13:01:28 +00:00
|
|
|
def makeImages(self):
|
2009-06-04 13:36:56 +00:00
|
|
|
i = images.Images(self.conf, self.yum)
|
|
|
|
i.run()
|
2008-09-13 02:04:02 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
# XXX figure out where to put this
|
|
|
|
#def copyUpdates(self):
|
|
|
|
# if self.conf.updates and os.path.isdir(self.conf.updates):
|
|
|
|
# cp(os.path.join(self.conf.updates, '*'), self.conf.treedir)
|
|
|
|
# self.conf.delAttr('updates')
|
2008-10-05 06:59:46 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
def cleanUp(self, trash=[]):
|
2009-04-22 13:01:28 +00:00
|
|
|
for item in trash:
|
|
|
|
if os.path.isdir(item):
|
|
|
|
shutil.rmtree(item, ignore_errors=True)
|
|
|
|
else:
|
|
|
|
os.unlink(item)
|
2008-10-10 03:04:13 +00:00
|
|
|
|
2009-06-04 13:36:56 +00:00
|
|
|
# remove the whole lorax tempdir
|
|
|
|
if os.path.isdir(self.conf.tempdir):
|
|
|
|
shutil.rmtree(self.conf.tempdir, ignore_errors=True)
|