diff --git a/lorax.spec b/lorax.spec
index 6ac926c3..3d5e9873 100644
--- a/lorax.spec
+++ b/lorax.spec
@@ -37,9 +37,9 @@ Requires: squashfs-tools >= 4.2
Requires: util-linux
Requires: xz
Requires: pigz
-Requires: yum
Requires: pykickstart
Requires: dracut >= 030
+Requires: dnf
%if 0%{?fedora}
# Fedora specific deps
diff --git a/src/pylorax/__init__.py b/src/pylorax/__init__.py
index 8942d6c2..44b180bc 100644
--- a/src/pylorax/__init__.py
+++ b/src/pylorax/__init__.py
@@ -36,7 +36,7 @@ import selinux
from pylorax.base import BaseLoraxClass, DataHolder
import pylorax.output as output
-import yum
+import dnf
from pylorax.sysutils import joinpaths, remove, linktree
from rpmUtils.arch import getBaseArch
@@ -96,9 +96,6 @@ class Lorax(BaseLoraxClass):
self.conf.add_section("templates")
self.conf.set("templates", "ramdisk", "ramdisk.ltmpl")
- self.conf.add_section("yum")
- self.conf.set("yum", "skipbroken", "0")
-
self.conf.add_section("compression")
self.conf.set("compression", "type", "xz")
self.conf.set("compression", "args", "")
@@ -149,7 +146,7 @@ class Lorax(BaseLoraxClass):
fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
- def run(self, ybo, product, version, release, variant="", bugurl="",
+ def run(self, dbo, product, version, release, variant="", bugurl="",
isfinal=False, workdir=None, outputdir=None, buildarch=None, volid=None,
domacboot=True, doupgrade=True, remove_temp=False,
installpkgs=None,
@@ -221,16 +218,16 @@ class Lorax(BaseLoraxClass):
logger.critical("selinux must be disabled or in Permissive mode")
sys.exit(1)
- # do we have a proper yum base object?
- logger.info("checking yum base object")
- if not isinstance(ybo, yum.YumBase):
- logger.critical("no yum base object")
+ # do we have a proper dnf base object?
+ logger.info("checking dnf base object")
+ if not isinstance(dbo, dnf.Base):
+ logger.critical("no dnf base object")
sys.exit(1)
- self.inroot = ybo.conf.installroot
+ self.inroot = dbo.conf.installroot
logger.debug("using install root: {0}".format(self.inroot))
if not buildarch:
- buildarch = get_buildarch(ybo)
+ buildarch = get_buildarch(dbo)
logger.info("setting up build architecture")
self.arch = ArchData(buildarch)
@@ -253,15 +250,14 @@ class Lorax(BaseLoraxClass):
sys.exit(1)
templatedir = self.conf.get("lorax", "sharedir")
- # NOTE: rb.root = ybo.conf.installroot (== self.inroot)
+ # NOTE: rb.root = dbo.conf.installroot (== self.inroot)
rb = RuntimeBuilder(product=self.product, arch=self.arch,
- yum=ybo, templatedir=templatedir,
+ dbo=dbo, templatedir=templatedir,
installpkgs=installpkgs,
add_templates=add_templates,
add_template_vars=add_template_vars)
logger.info("installing runtime packages")
- rb.yum.conf.skip_broken = self.conf.getboolean("yum", "skipbroken")
rb.install()
# write .buildstamp
@@ -358,10 +354,12 @@ class Lorax(BaseLoraxClass):
remove(self.workdir)
-def get_buildarch(ybo):
+def get_buildarch(dbo):
# get architecture of the available anaconda package
buildarch = None
- for anaconda in ybo.doPackageLists(patterns=["anaconda"]).available:
+ q = dbo.sack.query()
+ a = q.available()
+ for anaconda in a.filter(name="anaconda"):
if anaconda.arch != "src":
buildarch = anaconda.arch
break
diff --git a/src/pylorax/dnfhelper.py b/src/pylorax/dnfhelper.py
new file mode 100644
index 00000000..8bf82302
--- /dev/null
+++ b/src/pylorax/dnfhelper.py
@@ -0,0 +1,107 @@
+#
+# dnfhelper.py
+#
+# Copyright (C) 2010-2014 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
+# Brian C. Lane
+#
+
+import logging
+logger = logging.getLogger("pylorax.dnfhelper")
+import dnf
+import collections
+import time
+import pylorax.output as output
+
+__all__ = ['LoraxDownloadCallback', 'LoraxRpmCallback']
+
+def _paced(fn):
+ """Execute `fn` no more often then every 2 seconds."""
+ def paced_fn(self, *args):
+ now = time.time()
+ if now - self.last_time < 2:
+ return
+ self.last_time = now
+ return fn(self, *args)
+ return paced_fn
+
+
+class LoraxDownloadCallback(dnf.callback.DownloadProgress):
+ def __init__(self):
+ self.downloads = collections.defaultdict(int)
+ self.last_time = time.time()
+ self.total_files = 0
+ self.total_size = 0
+
+ self.pkgno = 0
+ self.total = 0
+
+ self.output = output.LoraxOutput()
+
+ @_paced
+ def _update(self):
+ msg = "Downloading %(pkgno)s / %(total_files)s RPMs, " \
+ "%(downloaded)s / %(total_size)s (%(percent)d%%) done.\n"
+ downloaded = sum(self.downloads.values())
+ vals = {
+ 'downloaded' : downloaded,
+ 'percent' : int(100 * downloaded/self.total_size),
+ 'pkgno' : self.pkgno,
+ 'total_files' : self.total_files,
+ 'total_size' : self.total_size
+ }
+ self.output.write(msg % vals)
+
+ def end(self, payload, status, err_msg):
+ nevra = str(payload)
+ if status is dnf.callback.STATUS_OK:
+ self.downloads[nevra] = payload.download_size
+ self.pkgno += 1
+ self._update()
+ return
+ logger.critical("Failed to download '%s': %d - %s", nevra, status, err_msg)
+
+ def progress(self, payload, done):
+ nevra = str(payload)
+ self.downloads[nevra] = done
+ self._update()
+
+ def start(self, total_files, total_size):
+ self.total_files = total_files
+ self.total_size = total_size
+
+
+class LoraxRpmCallback(dnf.callback.LoggingTransactionDisplay):
+ def __init__(self, queue):
+ super(LoraxRpmCallback, self).__init__()
+ self._queue = queue
+ self._last_ts = None
+ self.cnt = 0
+
+ def event(self, package, action, te_current, te_total, ts_current, ts_total):
+ if action == self.PKG_INSTALL and te_current == 0:
+ # do not report same package twice
+ if self._last_ts == ts_current:
+ return
+ self._last_ts = ts_current
+
+ msg = '(%d/%d) %s.%s' % \
+ (ts_current, ts_total, package.name, package.arch)
+ self.cnt += 1
+ self._queue.put(('install', msg))
+ elif action == self.TRANS_POST:
+ self._queue.put(('post', None))
diff --git a/src/pylorax/ltmpl.py b/src/pylorax/ltmpl.py
index 99f26a57..f5d6f335 100644
--- a/src/pylorax/ltmpl.py
+++ b/src/pylorax/ltmpl.py
@@ -28,15 +28,18 @@ from os.path import basename, isdir
from subprocess import CalledProcessError
from pylorax.sysutils import joinpaths, cpfile, mvfile, replace, remove
-from pylorax.yumhelper import LoraxDownloadCallback, LoraxTransactionCallback, LoraxRpmCallback
+from pylorax.dnfhelper import LoraxDownloadCallback, LoraxRpmCallback
from pylorax.base import DataHolder
from pylorax.executils import runcmd, runcmd_output
from pylorax.imgutils import mkcpio
+import pylorax.output as output
from mako.lookup import TemplateLookup
from mako.exceptions import text_error_template
import sys, traceback
import struct
+import dnf
+import multiprocessing
class LoraxTemplate(object):
def __init__(self, directories=None):
@@ -108,7 +111,7 @@ class LoraxTemplateRunner(object):
This class parses and executes Lorax templates. Sample usage:
# install a bunch of packages
- runner = LoraxTemplateRunner(inroot=rundir, outroot=rundir, yum=yum_obj)
+ runner = LoraxTemplateRunner(inroot=rundir, outroot=rundir, dbo=dnf_obj)
runner.run("install-packages.ltmpl")
# modify a runtime dir
@@ -145,11 +148,11 @@ class LoraxTemplateRunner(object):
* Commands should raise exceptions for errors - don't use sys.exit()
'''
- def __init__(self, inroot, outroot, yum=None, fatalerrors=True,
+ def __init__(self, inroot, outroot, dbo=None, fatalerrors=True,
templatedir=None, defaults=None):
self.inroot = inroot
self.outroot = outroot
- self.yum = yum
+ self.dbo = dbo
self.fatalerrors = fatalerrors
self.templatedir = templatedir or "/usr/share/lorax"
self.templatefile = None
@@ -166,8 +169,8 @@ class LoraxTemplateRunner(object):
return joinpaths(self.inroot, path)
def _filelist(self, *pkgs):
- pkglist = self.yum.doPackageLists(pkgnarrow="installed", patterns=pkgs)
- return set([f for pkg in pkglist.installed for f in pkg.filelist+pkg.ghostlist])
+ pkglist = self.dbo.doPackageLists(pkgnarrow="installed", patterns=pkgs)
+ return set([f for pkg in pkglist for f in pkg.files])
def _getsize(self, *files):
return sum(os.path.getsize(self._out(f)) for f in files if os.path.isfile(self._out(f)))
@@ -447,9 +450,9 @@ class LoraxTemplateRunner(object):
cmd = cmd[1:]
try:
- output = runcmd_output(cmd, cwd=cwd)
- if output:
- logger.debug('command output:\n%s', output)
+ stdout = runcmd_output(cmd, cwd=cwd)
+ if stdout:
+ logger.debug('command output:\n%s', stdout)
logger.debug("command finished successfully")
except CalledProcessError as e:
if e.output:
@@ -471,10 +474,10 @@ class LoraxTemplateRunner(object):
for p in pkgs:
try:
- self.yum.install(pattern=p)
+ self.dbo.install(p)
except Exception as e: # pylint: disable=broad-except
# FIXME: save exception and re-raise after the loop finishes
- logger.error("installpkg %s failed: %s",p,str(e))
+ logger.error("installpkg %s failed: %s", p, str(e))
if required:
raise
@@ -501,19 +504,60 @@ class LoraxTemplateRunner(object):
Actually install all the packages requested by previous 'installpkg'
commands.
'''
- self.yum.buildTransaction()
- dl_callback = LoraxDownloadCallback()
- self.yum.repos.setProgressBar(dl_callback)
- self.yum.processTransaction(callback=LoraxTransactionCallback(dl_callback),
- rpmDisplay=LoraxRpmCallback())
+
+ def do_transaction(base, queue):
+ try:
+ display = LoraxRpmCallback(queue)
+ base.do_transaction(display=display)
+ except BaseException as e:
+ logger.error("The transaction process has ended abruptly: %s", e)
+ queue.put(('quit', str(e)))
+
+ self.dbo.reset()
+ try:
+ logger.info("Checking dependencies")
+ self.dbo.resolve()
+ except dnf.exceptions.DepsolveError as e:
+ logger.error("Dependency check failed: %s", e)
+ raise
+ logger.info("%d packages selected", len(self.dbo.transaction))
+ if len(self.dbo.transaction) == 0:
+ raise Exception("No packages in transaction")
+
+ pkgs_to_download = self.dbo.transaction.install_set
+ logger.info("Downloading packages")
+ progress = LoraxDownloadCallback()
+ try:
+ self.dbo.download_packages(pkgs_to_download, progress)
+ except dnf.exceptions.DownloadError as e:
+ logger.error("Failed to download the following packages: %s", e)
+ raise
+
+ logger.info("Preparing transaction from installation source")
+ queue = multiprocessing.Queue()
+ msgout = output.LoraxOutput()
+ process = multiprocessing.Process(target=do_transaction, args=(self.dbo, queue))
+ process.start()
+ (token, msg) = queue.get()
+ while token not in ('post', 'quit'):
+ if token == 'install':
+ logging.info("%s", msg)
+ msgout.writeline(msg)
+ (token, msg) = queue.get()
+ if token == 'quit':
+ logger.error("Transaction failed.")
+ raise Exception("Transaction failed")
+
+ logger.info("Performing post-installation setup tasks")
+ process.join()
# verify if all packages that were supposed to be installed,
# are really installed
- errs = [t.po for t in self.yum.tsInfo if not self.yum.rpmdb.contains(po=t.po)]
+ errs = [t.po for t in self.dbo.tsInfo if not self.dbo.rpmdb.contains(po=t.po)]
for po in errs:
logger.error("package '%s' was not installed", po)
- self.yum.closeRpmDB()
+ self.dbo.close()
def removefrom(self, pkg, *globs):
'''
diff --git a/src/pylorax/treebuilder.py b/src/pylorax/treebuilder.py
index baad1ac5..5a56233d 100644
--- a/src/pylorax/treebuilder.py
+++ b/src/pylorax/treebuilder.py
@@ -67,19 +67,19 @@ def generate_module_info(moddir, outfile=None):
class RuntimeBuilder(object):
'''Builds the anaconda runtime image.'''
- def __init__(self, product, arch, yum, templatedir=None,
+ def __init__(self, product, arch, dbo, templatedir=None,
installpkgs=None,
add_templates=None,
add_template_vars=None):
- root = yum.conf.installroot
+ root = dbo.conf.installroot
# use a copy of product so we can modify it locally
product = product.copy()
product.name = product.name.lower()
- self.vars = DataHolder(arch=arch, product=product, yum=yum, root=root,
+ self.vars = DataHolder(arch=arch, product=product, dbo=dbo, root=root,
basearch=arch.basearch, libdir=arch.libdir)
- self.yum = yum
+ self.dbo = dbo
self._runner = LoraxTemplateRunner(inroot=root, outroot=root,
- yum=yum, templatedir=templatedir)
+ dbo=dbo, templatedir=templatedir)
self.add_templates = add_templates or []
self.add_template_vars = add_template_vars or {}
self._installpkgs = installpkgs or []
@@ -87,7 +87,9 @@ class RuntimeBuilder(object):
def _install_branding(self):
release = None
- for pkg in self.yum.whatProvides('/etc/system-release', None, None):
+ q = self.dbo.sack.query()
+ a = q.available()
+ for pkg in a.filter(provides='/etc/system-release'):
if pkg.name.startswith('generic'):
continue
else:
@@ -119,9 +121,10 @@ class RuntimeBuilder(object):
'''debugging data: write out lists of package contents'''
if not os.path.isdir(pkglistdir):
os.makedirs(pkglistdir)
- for pkgobj in self.yum.doPackageLists(pkgnarrow='installed').installed:
+ q = self.dbo.sack.query()
+ for pkgobj in q.installed():
with open(joinpaths(pkglistdir, pkgobj.name), "w") as fobj:
- for fname in pkgobj.filelist + pkgobj.dirlist:
+ for fname in pkgobj.files:
fobj.write("{0}\n".format(fname))
def postinstall(self):
@@ -143,8 +146,9 @@ class RuntimeBuilder(object):
'''debugging data: write a big list of pkg sizes'''
fobj = open(pkgsizefile, "w")
getsize = lambda f: os.lstat(f).st_size if os.path.exists(f) else 0
- for p in sorted(self.yum.doPackageLists(pkgnarrow='installed').installed):
- pkgsize = sum(getsize(joinpaths(self.vars.root,f)) for f in p.filelist)
+ q = self.dbo.sack.query()
+ for p in sorted(q.installed()):
+ pkgsize = sum(getsize(joinpaths(self.vars.root,f)) for f in p.files)
fobj.write("{0.name}.{0.arch}: {1}\n".format(p, pkgsize))
def generate_module_data(self):
diff --git a/src/pylorax/yumhelper.py b/src/pylorax/yumhelper.py
deleted file mode 100644
index 79a32053..00000000
--- a/src/pylorax/yumhelper.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#
-# yumhelper.py
-#
-# Copyright (C) 2010-2014 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.yumhelper")
-import sys
-import yum, yum.callbacks, yum.rpmtrans
-import pylorax.output as output
-
-__all__ = ['LoraxDownloadCallback', 'LoraxTransactionCallback',
- 'LoraxRpmCallback']
-
-class LoraxDownloadCallback(yum.callbacks.DownloadBaseCallback):
- def __init__(self):
- yum.callbacks.DownloadBaseCallback.__init__(self)
-
- self.pkgno = 0
- self.total = 0
-
- self.output = output.LoraxOutput()
-
-
- def updateProgress(self, name, frac, fread, ftime):
- """
- Update the progress bar
- @param name: filename
- @param frac: progress fraction (0 -> 1)
- @param fread: formated string containing BytesRead
- @param ftime: formated string containing remaining or elapsed time
- """
- # Only update when it is finished downloading
- if frac < 1:
- return
-
- self.pkgno += 1
- info = "({0:3d}/{1:3d}) "
- info = info.format(self.pkgno, self.total)
-
- infolen, pkglen = len(info), len(name)
- if (infolen + pkglen) > self.output.width:
- name = "{0}...".format(name[:self.output.width-infolen-3])
-
- msg = "{0}{1}\n".format(info, name)
- self.output.write(msg)
-
-
-class LoraxTransactionCallback(object):
-
- def __init__(self, dl_callback):
- self.output = output.LoraxOutput()
-
- self.dl_callback = dl_callback
-
- def event(self, state, data=None):
- if state == yum.callbacks.PT_DOWNLOAD:
- self.output.write("downloading packages\n")
- elif state == yum.callbacks.PT_DOWNLOAD_PKGS:
- # Initialize the total number of packages being downloaded
- self.dl_callback.total = len(data)
- elif state == yum.callbacks.PT_GPGCHECK:
- self.output.write("checking package signatures\n")
- elif state == yum.callbacks.PT_TEST_TRANS:
- self.output.write("running test transaction\n")
- elif state == yum.callbacks.PT_TRANSACTION:
- self.output.write("running transaction\n")
-
-
-class LoraxRpmCallback(yum.rpmtrans.RPMBaseCallback):
-
- def __init__(self):
- yum.rpmtrans.RPMBaseCallback.__init__(self)
- self.output = output.LoraxOutput()
-
- def event(self, package, action, te_current, te_total,
- ts_current, ts_total):
-
- action_str = self.action[action].encode("utf-8")
- info = "({0:3d}/{1:3d}) [{2:3.0f}%] {3} "
- info = info.format(ts_current, ts_total,
- float(te_current) / float(te_total) * 100,
- action_str.lower())
-
- pkg = "{0}".format(package)
-
- infolen, pkglen = len(info), len(pkg)
- if (infolen + pkglen) > self.output.width:
- pkg = "{0}...".format(pkg[:self.output.width-infolen-3])
-
- msg = "{0}{1}".format(info, pkg)
-
- # When not outputting to a tty we only want to print it once at the end
- if sys.stdout.isatty():
- self.output.write(msg + "\r")
- if te_current == te_total:
- self.output.write("\n")
- elif te_current == te_total:
- self.output.write(msg + "\n")
-
-
- def filelog(self, package, action):
- if self.fileaction.get(action) == "Installed":
- logger.debug("{0} installed successfully".format(package))
-
- def errorlog(self, msg):
- logger.warning("RPM transaction error: %s", msg)
-
- def scriptout(self, package, msgs):
- if msgs:
- logger.info("%s scriptlet output:\n%s", package, msgs)
diff --git a/src/sbin/lorax b/src/sbin/lorax
index ce25a87b..cfa66d1a 100755
--- a/src/sbin/lorax
+++ b/src/sbin/lorax
@@ -25,20 +25,16 @@ import logging
log = logging.getLogger("lorax")
program_log = logging.getLogger("program")
pylorax_log = logging.getLogger("pylorax")
-yum_log = logging.getLogger("yum")
+dnf_log = logging.getLogger("dnf")
import sys
import os
import tempfile
from optparse import OptionParser, OptionGroup
-import ConfigParser
import shutil
-import yum
-# This is a bit of a hack to short circuit yum's internal logging
-# handler setup. We already set one up so we don't need it to run.
-yum.logginglevels._added_handlers = True
+import dnf
import pylorax
def setup_logging(opts):
@@ -67,12 +63,12 @@ def setup_logging(opts):
fh.setLevel(logging.DEBUG)
program_log.addHandler(fh)
- # yum logging
- yum_log.setLevel(logging.DEBUG)
- logfile = os.path.abspath(os.path.dirname(opts.logfile))+"/yum.log"
+ # dnf logging
+ dnf_log.setLevel(logging.DEBUG)
+ logfile = os.path.abspath(os.path.dirname(opts.logfile))+"/dnf.log"
fh = logging.FileHandler(filename=logfile, mode="w")
fh.setLevel(logging.DEBUG)
- yum_log.addHandler(fh)
+ dnf_log.addHandler(fh)
def main(args):
@@ -116,9 +112,6 @@ def main(args):
help="config file", metavar="STRING")
optional.add_option("--proxy", default=None,
help="repo proxy url:port", metavar="STRING")
- optional.add_option("-e", "--excludepkgs", default=[],
- action="append", metavar="STRING",
- help="package glob to exclude (may be listed multiple times)")
optional.add_option("-i", "--installpkgs", default=[],
action="append", metavar="STRING",
help="package glob to install before runtime-install.tmpl runs. (may be listed multiple times)")
@@ -180,17 +173,16 @@ def main(args):
# create the temporary directory for lorax
tempdir = tempfile.mkdtemp(prefix="lorax.", dir=tempfile.gettempdir())
- # create the yumbase object
installtree = os.path.join(tempdir, "installtree")
os.mkdir(installtree)
- yumtempdir = os.path.join(tempdir, "yum")
- os.mkdir(yumtempdir)
+ dnftempdir = os.path.join(tempdir, "dnf")
+ os.mkdir(dnftempdir)
- yb = get_yum_base_object(installtree, opts.source, opts.mirrorlist,
- yumtempdir, opts.proxy, opts.excludepkgs)
+ dnfbase = get_dnf_base_object(installtree, opts.source, opts.mirrorlist,
+ dnftempdir, opts.proxy, opts.version)
- if yb is None:
- print("error: unable to create the yumbase object", file=sys.stderr)
+ if dnfbase is None:
+ print("error: unable to create the dnf base object", file=sys.stderr)
shutil.rmtree(tempdir)
sys.exit(1)
@@ -204,7 +196,7 @@ def main(args):
# run lorax
lorax = pylorax.Lorax()
lorax.configure(conf_file=opts.config)
- lorax.run(yb, opts.product, opts.version, opts.release,
+ lorax.run(dnfbase, opts.product, opts.version, opts.release,
opts.variant, opts.bugurl, opts.isfinal,
workdir=tempdir, outputdir=outputdir, buildarch=opts.buildarch,
volid=opts.volid, domacboot=opts.domacboot, doupgrade=opts.doupgrade,
@@ -214,9 +206,17 @@ def main(args):
remove_temp=True)
-def get_yum_base_object(installroot, repositories, mirrorlists=None,
- tempdir="/var/tmp", proxy=None, excludepkgs=None):
+def get_dnf_base_object(installroot, repositories, mirrorlists=None,
+ tempdir="/var/tmp", proxy=None, releasever="21"):
+ """ Create a dnf Base object and setup the repositories and installroot
+ :param string installroot: Full path to the installroot
+ :param list repositories: List of repositories to use for the installation
+ :param list mirrorlist: List of mirrors to use
+ :param string tempdir: Path of temporary directory
+ :param string proxy: http proxy to use when fetching packages
+ :param string releasever: Release version to pass to dnf
+ """
def sanitize_repo(repo):
"""Convert bare paths to file:/// URIs, and silently reject protocols unhandled by yum"""
if repo.startswith("/"):
@@ -227,7 +227,6 @@ def get_yum_base_object(installroot, repositories, mirrorlists=None,
return None
mirrorlists = mirrorlists or []
- excludepkgs = excludepkgs or []
# sanitize the repositories
repositories = map(sanitize_repo, repositories)
@@ -237,78 +236,70 @@ def get_yum_base_object(installroot, repositories, mirrorlists=None,
repositories = filter(bool, repositories)
mirrorlists = filter(bool, mirrorlists)
- cachedir = os.path.join(tempdir, "yum.cache")
+ cachedir = os.path.join(tempdir, "dnf.cache")
if not os.path.isdir(cachedir):
os.mkdir(cachedir)
- yumconf = os.path.join(tempdir, "yum.conf")
- c = ConfigParser.ConfigParser()
+ logdir = os.path.join(tempdir, "dnf.logs")
+ if not os.path.isdir(logdir):
+ os.mkdir(logdir)
- # add the main section
- section = "main"
- data = {"cachedir": cachedir,
- "keepcache": 0,
- "gpgcheck": 0,
- "plugins": 0,
- "reposdir": "",
- "tsflags": "nodocs"}
+ dnfbase = dnf.Base()
+ conf = dnfbase.conf
+ conf.logdir = logdir
+ conf.cachedir = cachedir
+
+ # Turn off logging to the console
+ conf.debuglevel = 0
+ conf.errorlevel = 0
+ dnfbase.logging.setup_from_dnf_conf(conf)
+
+ conf.releasever = releasever
+ conf.installroot = installroot
+ conf.prepend_installroot('persistdir')
+ conf.tsflags.append('nodocs')
if proxy:
- data["proxy"] = proxy
+ conf.proxy = proxy
- if excludepkgs:
- data["exclude"] = " ".join(excludepkgs)
-
- c.add_section(section)
- map(lambda (key, value): c.set(section, key, value), data.items())
-
- # add the main repository - the first repository from list
- section = "lorax-repo"
- data = {"name": "lorax repo",
- "baseurl": repositories[0],
- "enabled": 1}
-
- c.add_section(section)
- map(lambda (key, value): c.set(section, key, value), data.items())
-
- # add the extra repositories
- for n, extra in enumerate(repositories[1:], start=1):
- section = "lorax-extra-repo-{0:d}".format(n)
- data = {"name": "lorax extra repo {0:d}".format(n),
- "baseurl": extra,
- "enabled": 1}
-
- c.add_section(section)
- map(lambda (key, value): c.set(section, key, value), data.items())
+ # add the repositories
+ for i, r in enumerate(repositories):
+ repo_name = "lorax-repo-%d" % i
+ repo = dnf.repo.Repo(repo_name, cachedir)
+ repo.baseurl = [r]
+ if proxy:
+ repo.proxy = proxy
+ repo.enable()
+ dnfbase.repos.add(repo)
+ log.info("Added '%s': %s", repo_name, r)
+ log.info("Fetching metadata...")
+ try:
+ repo.load()
+ except dnf.exceptions.RepoError as e:
+ log.error("Error fetching metadata for %s: %s", repo_name, e)
+ return None
# add the mirrorlists
- for n, mirror in enumerate(mirrorlists, start=1):
- section = "lorax-mirrorlist-{0:d}".format(n)
- data = {"name": "lorax mirrorlist {0:d}".format(n),
- "mirrorlist": mirror,
- "enabled": 1 }
+ for i, r in enumerate(mirrorlists):
+ repo_name = "lorax-mirrorlist-%d" % i
+ repo = dnf.repo.Repo(repo_name, cachedir)
+ repo.mirrorlist = r
+ if proxy:
+ repo.proxy = proxy
+ repo.enable()
+ dnfbase.repos.add(repo)
+ log.info("Added '%s': %s", repo_name, r)
+ log.info("Fetching metadata...")
+ try:
+ repo.load()
+ except dnf.exceptions.RepoError as e:
+ log.error("Error fetching metadata for %s: %s", repo_name, e)
+ return None
- c.add_section(section)
- map(lambda (key, value): c.set(section, key, value), data.items())
+ dnfbase.fill_sack(load_system_repo=False)
+ dnfbase.read_comps()
- # write the yum configuration file
- with open(yumconf, "w") as f:
- c.write(f)
-
- # create the yum base object
- yb = yum.YumBase()
-
- yb.preconf.fn = yumconf
- yb.preconf.root = installroot
- #yb.repos.setCacheDir(cachedir)
-
- # Turn on as much yum logging as we can
- yb.preconf.debuglevel = 6
- yb.preconf.errorlevel = 6
- yb.logger.setLevel(logging.DEBUG)
- yb.verbose_logger.setLevel(logging.DEBUG)
-
- return yb
+ return dnfbase
if __name__ == "__main__":