Create new Runroot class and use it everywhere where runroot task is executed.
This adds new `Runroot` class and new `runroot_method` option which makes it possible to choose between two currently available runroot methods: - Local - Koji The main goal of this commit is to make it possible to add new runroot methods in the future and this is the first step in that direction. Signed-off-by: Jan Kaluza <jkaluza@redhat.com>
This commit is contained in:
parent
45cdbb2faf
commit
75bb48a882
@ -855,7 +855,16 @@ Options
|
|||||||
"koji", which points to Fedora's koji.fedoraproject.org.
|
"koji", which points to Fedora's koji.fedoraproject.org.
|
||||||
|
|
||||||
**runroot** [mandatory]
|
**runroot** [mandatory]
|
||||||
(*bool*) -- run some tasks such as buildinstall or createiso in koji build root (True) or locally (False)
|
(*bool*) -- run some tasks such as buildinstall or createiso in koji build root (True) or locally (False).
|
||||||
|
There might also be other runroot methods available. These can be chosen by ``runroot_method`` option.
|
||||||
|
|
||||||
|
**runroot_method**
|
||||||
|
(*str*) -- Runroot method to use. It can further specify the runroot method
|
||||||
|
in case the ``runroot`` is set to True.
|
||||||
|
|
||||||
|
Available methods are:
|
||||||
|
* ``local`` -- runroot tasks are run locally
|
||||||
|
* ``koji`` -- runroot tasks are run in Koji
|
||||||
|
|
||||||
**runroot_channel**
|
**runroot_channel**
|
||||||
(*str*) -- name of koji channel
|
(*str*) -- name of koji channel
|
||||||
|
@ -560,6 +560,10 @@ def make_schema():
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": False,
|
"default": False,
|
||||||
},
|
},
|
||||||
|
"runroot_method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["local", "koji"],
|
||||||
|
},
|
||||||
"create_jigdo": {
|
"create_jigdo": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": True,
|
"default": True,
|
||||||
|
@ -30,10 +30,10 @@ from pungi.util import get_volid, get_arch_variant_data
|
|||||||
from pungi.util import get_file_size, get_mtime, failable, makedirs
|
from pungi.util import get_file_size, get_mtime, failable, makedirs
|
||||||
from pungi.util import copy_all, translate_path
|
from pungi.util import copy_all, translate_path
|
||||||
from pungi.wrappers.lorax import LoraxWrapper
|
from pungi.wrappers.lorax import LoraxWrapper
|
||||||
from pungi.wrappers.kojiwrapper import get_buildroot_rpms, KojiWrapper
|
|
||||||
from pungi.wrappers import iso
|
from pungi.wrappers import iso
|
||||||
from pungi.wrappers.scm import get_file_from_scm
|
from pungi.wrappers.scm import get_file_from_scm
|
||||||
from pungi.phases.base import PhaseBase
|
from pungi.phases.base import PhaseBase
|
||||||
|
from pungi.runroot import Runroot
|
||||||
|
|
||||||
|
|
||||||
class BuildinstallPhase(PhaseBase):
|
class BuildinstallPhase(PhaseBase):
|
||||||
@ -452,40 +452,24 @@ class BuildinstallThread(WorkerThread):
|
|||||||
|
|
||||||
self.pool.log_info("[BEGIN] %s" % msg)
|
self.pool.log_info("[BEGIN] %s" % msg)
|
||||||
|
|
||||||
task_id = None
|
# Get list of packages which are neded in runroot.
|
||||||
if runroot:
|
|
||||||
# run in a koji build root
|
|
||||||
packages = []
|
packages = []
|
||||||
if buildinstall_method == "lorax":
|
if buildinstall_method == "lorax":
|
||||||
packages += ["lorax"]
|
packages += ["lorax"]
|
||||||
elif buildinstall_method == "buildinstall":
|
elif buildinstall_method == "buildinstall":
|
||||||
packages += ["anaconda"]
|
packages += ["anaconda"]
|
||||||
runroot_channel = compose.conf.get("runroot_channel")
|
|
||||||
runroot_tag = compose.conf["runroot_tag"]
|
|
||||||
|
|
||||||
koji_wrapper = KojiWrapper(compose.conf["koji_profile"])
|
# This should avoid a possible race condition with multiple processes
|
||||||
koji_cmd = koji_wrapper.get_runroot_cmd(
|
# trying to get a kerberos ticket at the same time.
|
||||||
runroot_tag, arch, cmd,
|
|
||||||
channel=runroot_channel,
|
|
||||||
use_shell=True, task_id=True,
|
|
||||||
packages=packages, mounts=[compose.topdir],
|
|
||||||
weight=compose.conf['runroot_weights'].get('buildinstall'),
|
|
||||||
destdir=output_dir,
|
|
||||||
)
|
|
||||||
|
|
||||||
# avoid race conditions?
|
|
||||||
# Kerberos authentication failed: Permission denied in replay cache code (-1765328215)
|
# Kerberos authentication failed: Permission denied in replay cache code (-1765328215)
|
||||||
time.sleep(num * 3)
|
time.sleep(num * 3)
|
||||||
|
|
||||||
output = koji_wrapper.run_runroot_cmd(koji_cmd, log_file=log_file)
|
# Start the runroot task.
|
||||||
if output["retcode"] != 0:
|
runroot = Runroot(compose)
|
||||||
raise RuntimeError("Runroot task failed: %s. See %s for more details."
|
runroot.run(
|
||||||
% (output["task_id"], log_file))
|
cmd, log_file=log_file, arch=arch, packages=packages,
|
||||||
task_id = output["task_id"]
|
mounts=[compose.topdir], output_dir=output_dir,
|
||||||
|
weight=compose.conf['runroot_weights'].get('buildinstall'))
|
||||||
else:
|
|
||||||
# run locally
|
|
||||||
run(cmd, show_cmd=True, logfile=log_file)
|
|
||||||
|
|
||||||
if final_output_dir != output_dir:
|
if final_output_dir != output_dir:
|
||||||
if not os.path.exists(final_output_dir):
|
if not os.path.exists(final_output_dir):
|
||||||
@ -502,7 +486,7 @@ class BuildinstallThread(WorkerThread):
|
|||||||
copy_all(log_dir, final_log_dir)
|
copy_all(log_dir, final_log_dir)
|
||||||
|
|
||||||
log_file = compose.paths.log.log_file(arch, log_filename + '-RPMs')
|
log_file = compose.paths.log.log_file(arch, log_filename + '-RPMs')
|
||||||
rpms = get_buildroot_rpms(compose, task_id)
|
rpms = runroot.get_buildroot_rpms()
|
||||||
with open(log_file, "w") as f:
|
with open(log_file, "w") as f:
|
||||||
f.write("\n".join(rpms))
|
f.write("\n".join(rpms))
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
|
||||||
import random
|
import random
|
||||||
import shutil
|
import shutil
|
||||||
import stat
|
import stat
|
||||||
@ -28,12 +27,13 @@ from six.moves import shlex_quote
|
|||||||
|
|
||||||
from pungi.wrappers import iso
|
from pungi.wrappers import iso
|
||||||
from pungi.wrappers.createrepo import CreaterepoWrapper
|
from pungi.wrappers.createrepo import CreaterepoWrapper
|
||||||
from pungi.wrappers.kojiwrapper import KojiWrapper
|
from pungi.wrappers import kojiwrapper
|
||||||
from pungi.phases.base import PhaseBase, PhaseLoggerMixin
|
from pungi.phases.base import PhaseBase, PhaseLoggerMixin
|
||||||
from pungi.util import (makedirs, get_volid, get_arch_variant_data, failable,
|
from pungi.util import (makedirs, get_volid, get_arch_variant_data, failable,
|
||||||
get_file_size, get_mtime)
|
get_file_size, get_mtime)
|
||||||
from pungi.media_split import MediaSplitter, convert_media_size
|
from pungi.media_split import MediaSplitter, convert_media_size
|
||||||
from pungi.compose_metadata.discinfo import read_discinfo, write_discinfo
|
from pungi.compose_metadata.discinfo import read_discinfo, write_discinfo
|
||||||
|
from pungi.runroot import Runroot
|
||||||
|
|
||||||
from .. import createiso
|
from .. import createiso
|
||||||
|
|
||||||
@ -269,8 +269,6 @@ def add_iso_to_metadata(
|
|||||||
|
|
||||||
def run_createiso_command(runroot, num, compose, bootable, arch, cmd, mounts,
|
def run_createiso_command(runroot, num, compose, bootable, arch, cmd, mounts,
|
||||||
log_file, with_jigdo=True):
|
log_file, with_jigdo=True):
|
||||||
if runroot:
|
|
||||||
# run in a koji build root
|
|
||||||
packages = ["coreutils", "genisoimage", "isomd5sum"]
|
packages = ["coreutils", "genisoimage", "isomd5sum"]
|
||||||
if with_jigdo and compose.conf['create_jigdo']:
|
if with_jigdo and compose.conf['create_jigdo']:
|
||||||
packages.append('jigdo')
|
packages.append('jigdo')
|
||||||
@ -281,19 +279,18 @@ def run_createiso_command(runroot, num, compose, bootable, arch, cmd, mounts,
|
|||||||
}
|
}
|
||||||
packages.extend(extra_packages[compose.conf["buildinstall_method"]])
|
packages.extend(extra_packages[compose.conf["buildinstall_method"]])
|
||||||
|
|
||||||
runroot_channel = compose.conf.get("runroot_channel")
|
runroot = Runroot(compose)
|
||||||
runroot_tag = compose.conf["runroot_tag"]
|
|
||||||
|
|
||||||
# get info about build arches in buildroot_tag
|
build_arch = arch
|
||||||
koji_wrapper = KojiWrapper(compose.conf["koji_profile"])
|
if runroot.runroot_method == "koji" and not bootable:
|
||||||
|
runroot_tag = compose.conf["runroot_tag"]
|
||||||
|
koji_wrapper = kojiwrapper.KojiWrapper(compose.conf["koji_profile"])
|
||||||
koji_proxy = koji_wrapper.koji_proxy
|
koji_proxy = koji_wrapper.koji_proxy
|
||||||
tag_info = koji_proxy.getTag(runroot_tag)
|
tag_info = koji_proxy.getTag(runroot_tag)
|
||||||
if not tag_info:
|
if not tag_info:
|
||||||
raise RuntimeError('Tag "%s" does not exist.' % runroot_tag)
|
raise RuntimeError('Tag "%s" does not exist.' % runroot_tag)
|
||||||
tag_arches = tag_info["arches"].split(" ")
|
tag_arches = tag_info["arches"].split(" ")
|
||||||
|
|
||||||
build_arch = arch
|
|
||||||
if not bootable:
|
|
||||||
if "x86_64" in tag_arches:
|
if "x86_64" in tag_arches:
|
||||||
# assign non-bootable images to x86_64 if possible
|
# assign non-bootable images to x86_64 if possible
|
||||||
build_arch = "x86_64"
|
build_arch = "x86_64"
|
||||||
@ -301,26 +298,9 @@ def run_createiso_command(runroot, num, compose, bootable, arch, cmd, mounts,
|
|||||||
# pick random arch from available runroot tag arches
|
# pick random arch from available runroot tag arches
|
||||||
build_arch = random.choice(tag_arches)
|
build_arch = random.choice(tag_arches)
|
||||||
|
|
||||||
koji_cmd = koji_wrapper.get_runroot_cmd(
|
runroot.run(
|
||||||
runroot_tag, build_arch, cmd,
|
cmd, log_file=log_file, arch=build_arch, packages=packages, mounts=mounts,
|
||||||
channel=runroot_channel, use_shell=True, task_id=True,
|
weight=compose.conf['runroot_weights'].get('createiso'))
|
||||||
packages=packages, mounts=mounts,
|
|
||||||
weight=compose.conf['runroot_weights'].get('createiso')
|
|
||||||
)
|
|
||||||
|
|
||||||
# This should avoid a possible race condition with multiple processes
|
|
||||||
# trying to get a kerberos ticket at the same time.
|
|
||||||
# Kerberos authentication failed: Permission denied in replay cache code (-1765328215)
|
|
||||||
time.sleep(num * 3)
|
|
||||||
|
|
||||||
output = koji_wrapper.run_runroot_cmd(koji_cmd, log_file=log_file)
|
|
||||||
if output["retcode"] != 0:
|
|
||||||
raise RuntimeError("Runroot task failed: %s. See %s for more details."
|
|
||||||
% (output["task_id"], log_file))
|
|
||||||
|
|
||||||
else:
|
|
||||||
# run locally
|
|
||||||
run(cmd, show_cmd=True, logfile=log_file)
|
|
||||||
|
|
||||||
|
|
||||||
def split_iso(compose, arch, variant, no_split=False, logger=None):
|
def split_iso(compose, arch, variant, no_split=False, logger=None):
|
||||||
|
@ -7,11 +7,12 @@ from kobo import shortcuts
|
|||||||
from kobo.threads import ThreadPool, WorkerThread
|
from kobo.threads import ThreadPool, WorkerThread
|
||||||
|
|
||||||
from pungi.arch_utils import getBaseArch
|
from pungi.arch_utils import getBaseArch
|
||||||
|
from pungi.runroot import Runroot
|
||||||
from .base import ConfigGuardedPhase
|
from .base import ConfigGuardedPhase
|
||||||
from .. import util
|
from .. import util
|
||||||
from ..ostree.utils import get_ref_from_treefile, get_commitid_from_commitid_file
|
from ..ostree.utils import get_ref_from_treefile, get_commitid_from_commitid_file
|
||||||
from ..util import get_repo_dicts, translate_path
|
from ..util import get_repo_dicts, translate_path
|
||||||
from ..wrappers import kojiwrapper, scm
|
from ..wrappers import scm
|
||||||
|
|
||||||
|
|
||||||
class OSTreePhase(ConfigGuardedPhase):
|
class OSTreePhase(ConfigGuardedPhase):
|
||||||
@ -90,7 +91,7 @@ class OSTreeThread(WorkerThread):
|
|||||||
# mount it.
|
# mount it.
|
||||||
util.makedirs(config['ostree_repo'])
|
util.makedirs(config['ostree_repo'])
|
||||||
|
|
||||||
task_id = self._run_ostree_cmd(compose, variant, arch, config, repodir,
|
self._run_ostree_cmd(compose, variant, arch, config, repodir,
|
||||||
extra_config_file=extra_config_file)
|
extra_config_file=extra_config_file)
|
||||||
|
|
||||||
if compose.notifier:
|
if compose.notifier:
|
||||||
@ -116,7 +117,7 @@ class OSTreeThread(WorkerThread):
|
|||||||
repo_path=translate_path(compose, config['ostree_repo']),
|
repo_path=translate_path(compose, config['ostree_repo']),
|
||||||
local_repo_path=config['ostree_repo'])
|
local_repo_path=config['ostree_repo'])
|
||||||
|
|
||||||
self.pool.log_info('[DONE ] %s (task id: %s)' % (msg, task_id))
|
self.pool.log_info('[DONE ] %s' % (msg))
|
||||||
|
|
||||||
def _run_ostree_cmd(self, compose, variant, arch, config, config_repo, extra_config_file=None):
|
def _run_ostree_cmd(self, compose, variant, arch, config, config_repo, extra_config_file=None):
|
||||||
cmd = [
|
cmd = [
|
||||||
@ -144,24 +145,15 @@ class OSTreeThread(WorkerThread):
|
|||||||
if config.get('force_new_commit', False):
|
if config.get('force_new_commit', False):
|
||||||
cmd.append('--force-new-commit')
|
cmd.append('--force-new-commit')
|
||||||
|
|
||||||
runroot_channel = compose.conf.get("runroot_channel")
|
|
||||||
runroot_tag = compose.conf["runroot_tag"]
|
|
||||||
|
|
||||||
packages = ['pungi', 'ostree', 'rpm-ostree']
|
packages = ['pungi', 'ostree', 'rpm-ostree']
|
||||||
log_file = os.path.join(self.logdir, 'runroot.log')
|
log_file = os.path.join(self.logdir, 'runroot.log')
|
||||||
mounts = [compose.topdir, config['ostree_repo']]
|
mounts = [compose.topdir, config['ostree_repo']]
|
||||||
koji = kojiwrapper.KojiWrapper(compose.conf["koji_profile"])
|
|
||||||
koji_cmd = koji.get_runroot_cmd(runroot_tag, arch, cmd,
|
runroot = Runroot(compose)
|
||||||
channel=runroot_channel,
|
runroot.run(
|
||||||
use_shell=True, task_id=True,
|
cmd, log_file=log_file, arch=arch, packages=packages,
|
||||||
packages=packages, mounts=mounts,
|
mounts=mounts, new_chroot=True,
|
||||||
new_chroot=True,
|
weight=compose.conf['runroot_weights'].get('ostree'))
|
||||||
weight=compose.conf["runroot_weights"].get('ostree'))
|
|
||||||
output = koji.run_runroot_cmd(koji_cmd, log_file=log_file)
|
|
||||||
if output["retcode"] != 0:
|
|
||||||
raise RuntimeError("Runroot task failed: %s. See %s for more details."
|
|
||||||
% (output["task_id"], log_file))
|
|
||||||
return output['task_id']
|
|
||||||
|
|
||||||
def _clone_repo(self, repodir, url, branch):
|
def _clone_repo(self, repodir, url, branch):
|
||||||
scm.get_dir_from_scm({'scm': 'git', 'repo': url, 'branch': branch, 'dir': '.'},
|
scm.get_dir_from_scm({'scm': 'git', 'repo': url, 'branch': branch, 'dir': '.'},
|
||||||
|
@ -11,7 +11,8 @@ from .base import ConfigGuardedPhase, PhaseLoggerMixin
|
|||||||
from .. import util
|
from .. import util
|
||||||
from ..arch import get_valid_arches
|
from ..arch import get_valid_arches
|
||||||
from ..util import get_volid, get_repo_urls, version_generator, translate_path
|
from ..util import get_volid, get_repo_urls, version_generator, translate_path
|
||||||
from ..wrappers import kojiwrapper, iso, lorax, scm
|
from ..wrappers import iso, lorax, scm
|
||||||
|
from ..runroot import Runroot
|
||||||
|
|
||||||
|
|
||||||
class OstreeInstallerPhase(PhaseLoggerMixin, ConfigGuardedPhase):
|
class OstreeInstallerPhase(PhaseLoggerMixin, ConfigGuardedPhase):
|
||||||
@ -87,12 +88,12 @@ class OstreeInstallerThread(WorkerThread):
|
|||||||
disc_type = compose.conf['disc_types'].get('ostree', 'ostree')
|
disc_type = compose.conf['disc_types'].get('ostree', 'ostree')
|
||||||
|
|
||||||
volid = get_volid(compose, arch, variant, disc_type=disc_type)
|
volid = get_volid(compose, arch, variant, disc_type=disc_type)
|
||||||
task_id = self._run_ostree_cmd(compose, variant, arch, config, repos, output_dir, volid)
|
self._run_ostree_cmd(compose, variant, arch, config, repos, output_dir, volid)
|
||||||
|
|
||||||
filename = compose.get_image_name(arch, variant, disc_type=disc_type)
|
filename = compose.get_image_name(arch, variant, disc_type=disc_type)
|
||||||
self._copy_image(compose, variant, arch, filename, output_dir)
|
self._copy_image(compose, variant, arch, filename, output_dir)
|
||||||
self._add_to_manifest(compose, variant, arch, filename)
|
self._add_to_manifest(compose, variant, arch, filename)
|
||||||
self.pool.log_info('[DONE ] %s, (task id: %s)' % (msg, task_id))
|
self.pool.log_info('[DONE ] %s' % (msg))
|
||||||
|
|
||||||
def _clone_templates(self, url, branch='master'):
|
def _clone_templates(self, url, branch='master'):
|
||||||
if not url:
|
if not url:
|
||||||
@ -180,20 +181,11 @@ class OstreeInstallerThread(WorkerThread):
|
|||||||
cmd = 'rm -rf %s && %s' % (shlex_quote(output_dir),
|
cmd = 'rm -rf %s && %s' % (shlex_quote(output_dir),
|
||||||
' '.join([shlex_quote(x) for x in lorax_cmd]))
|
' '.join([shlex_quote(x) for x in lorax_cmd]))
|
||||||
|
|
||||||
runroot_channel = compose.conf.get("runroot_channel")
|
|
||||||
runroot_tag = compose.conf["runroot_tag"]
|
|
||||||
|
|
||||||
packages = ['pungi', 'lorax', 'ostree']
|
packages = ['pungi', 'lorax', 'ostree']
|
||||||
log_file = os.path.join(self.logdir, 'runroot.log')
|
log_file = os.path.join(self.logdir, 'runroot.log')
|
||||||
koji = kojiwrapper.KojiWrapper(compose.conf["koji_profile"])
|
|
||||||
koji_cmd = koji.get_runroot_cmd(runroot_tag, arch, cmd,
|
runroot = Runroot(compose)
|
||||||
channel=runroot_channel,
|
runroot.run(
|
||||||
use_shell=True, task_id=True,
|
cmd, log_file=log_file, arch=arch, packages=packages,
|
||||||
packages=packages, mounts=[compose.topdir],
|
mounts=[compose.topdir], output_dir=output_dir,
|
||||||
weight=compose.conf['runroot_weights'].get('ostree_installer'),
|
weight=compose.conf['runroot_weights'].get('ostree_installer'))
|
||||||
destdir=output_dir)
|
|
||||||
output = koji.run_runroot_cmd(koji_cmd, log_file=log_file)
|
|
||||||
if output["retcode"] != 0:
|
|
||||||
raise RuntimeError("Runroot task failed: %s. See %s for more details."
|
|
||||||
% (output["task_id"], log_file))
|
|
||||||
return output['task_id']
|
|
||||||
|
138
pungi/runroot.py
Normal file
138
pungi/runroot.py
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
# 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; version 2 of the License.
|
||||||
|
#
|
||||||
|
# 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 Library 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 <https://gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import kobo.log
|
||||||
|
from kobo.shortcuts import run
|
||||||
|
|
||||||
|
from pungi.wrappers import kojiwrapper
|
||||||
|
|
||||||
|
|
||||||
|
class Runroot(kobo.log.LoggingBase):
|
||||||
|
def __init__(self, compose, logger=None):
|
||||||
|
"""
|
||||||
|
Creates new Runroot instance.
|
||||||
|
|
||||||
|
:param Compose compose: Compose instance.
|
||||||
|
:param Logger logger: Logger instance to log message to.
|
||||||
|
"""
|
||||||
|
kobo.log.LoggingBase.__init__(self, logger=logger)
|
||||||
|
self.compose = compose
|
||||||
|
self.runroot_method = self.get_runroot_method()
|
||||||
|
# Holds the result of last `run()` call.
|
||||||
|
self._result = None
|
||||||
|
|
||||||
|
def get_runroot_method(self):
|
||||||
|
"""
|
||||||
|
Returns the runroot method by checking the `runroot` and
|
||||||
|
`runroot_method` options in configuration.
|
||||||
|
|
||||||
|
:return: The "local" or "koji" string.
|
||||||
|
"""
|
||||||
|
runroot = self.compose.conf.get("runroot", None)
|
||||||
|
runroot_method = self.compose.conf.get("runroot_method", None)
|
||||||
|
if runroot is None and runroot_method is None:
|
||||||
|
raise ValueError("No runroot_method set.")
|
||||||
|
if runroot is False:
|
||||||
|
runroot_method = "local"
|
||||||
|
elif runroot and not runroot_method:
|
||||||
|
runroot_method = "koji"
|
||||||
|
return runroot_method
|
||||||
|
|
||||||
|
def _run_local(self, command, log_file=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Runs the runroot command locally.
|
||||||
|
"""
|
||||||
|
run(command, show_cmd=True, logfile=log_file)
|
||||||
|
self._result = True
|
||||||
|
|
||||||
|
def _run_koji(self, command, log_file=None, packages=None,
|
||||||
|
arch=None, output_dir=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Runs the runroot command in Koji.
|
||||||
|
"""
|
||||||
|
runroot_channel = self.compose.conf.get("runroot_channel")
|
||||||
|
runroot_tag = self.compose.conf["runroot_tag"]
|
||||||
|
|
||||||
|
if output_dir:
|
||||||
|
kwargs["destdir"] = output_dir
|
||||||
|
|
||||||
|
koji_wrapper = kojiwrapper.KojiWrapper(self.compose.conf["koji_profile"])
|
||||||
|
koji_cmd = koji_wrapper.get_runroot_cmd(
|
||||||
|
runroot_tag, arch, command,
|
||||||
|
channel=runroot_channel, use_shell=True, task_id=True,
|
||||||
|
packages=packages, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
output = koji_wrapper.run_runroot_cmd(koji_cmd, log_file=log_file)
|
||||||
|
if output["retcode"] != 0:
|
||||||
|
raise RuntimeError("Runroot task failed: %s. See %s for more details."
|
||||||
|
% (output["task_id"], log_file))
|
||||||
|
self._result = output
|
||||||
|
|
||||||
|
def run(self, command, log_file=None, packages=None, arch=None,
|
||||||
|
output_dir=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Runs the runroot task using the `Runroot.runroot_method`. Blocks until
|
||||||
|
the runroot task is successfully finished. Raises an exception on error.
|
||||||
|
|
||||||
|
The **kwargs are optional and matches the `KojiWrapper.get_runroot_cmd()`
|
||||||
|
kwargs. Some `runroot_method` methods might ignore the kwargs which
|
||||||
|
do not make sense for them.
|
||||||
|
|
||||||
|
:param str command: Command to execute.
|
||||||
|
:param str log_file: Log file into which the output of runroot task will
|
||||||
|
be logged.
|
||||||
|
:param list packages: List of packages which are needed for runroot task
|
||||||
|
to be executed.
|
||||||
|
:param str arch: Architecture on which the runroot task should be
|
||||||
|
executed.
|
||||||
|
:param str output_dir: Directory where the `command` stores its output.
|
||||||
|
The permissions of this output_dir might be changed by `runroot_method`
|
||||||
|
to allow the executor of this runroot task to accesss them.
|
||||||
|
See `KojiWrapper.get_runroot_cmd()` for more information.
|
||||||
|
"""
|
||||||
|
if self.runroot_method == "local":
|
||||||
|
self._run_local(
|
||||||
|
command, log_file=log_file, packages=packages, arch=arch,
|
||||||
|
output_dir=output_dir, **kwargs)
|
||||||
|
elif self.runroot_method == "koji":
|
||||||
|
self._run_koji(
|
||||||
|
command, log_file=log_file, packages=packages, arch=arch,
|
||||||
|
output_dir=output_dir, **kwargs)
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown runroot_method %r." % self.runroot_method)
|
||||||
|
|
||||||
|
def get_buildroot_rpms(self):
|
||||||
|
"""
|
||||||
|
Returns the list of RPMs installed in a buildroot in which the runroot
|
||||||
|
task was executed. This is needed to track what actually generated
|
||||||
|
the data generated by runroot task.
|
||||||
|
|
||||||
|
This must be called after the `run()` method successfully finished,
|
||||||
|
otherwise raises an exception.
|
||||||
|
|
||||||
|
:return: List of RPMs in buildroot in which the runroot task run.
|
||||||
|
"""
|
||||||
|
if not self._result:
|
||||||
|
raise ValueError("Runroot.get_build_rpms before runroot task finished.")
|
||||||
|
if self.runroot_method in ["local", "koji"]:
|
||||||
|
if self.runroot_method == "local":
|
||||||
|
task_id = None
|
||||||
|
else:
|
||||||
|
task_id = self._result["task_id"]
|
||||||
|
return kojiwrapper.get_buildroot_rpms(self.compose, task_id)
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown runroot_method %r." % self.runroot_method)
|
@ -734,8 +734,8 @@ class BuildinstallThreadTestCase(PungiTestCase):
|
|||||||
self.pool = mock.Mock(finished_tasks=set())
|
self.pool = mock.Mock(finished_tasks=set())
|
||||||
self.cmd = mock.Mock()
|
self.cmd = mock.Mock()
|
||||||
|
|
||||||
@mock.patch('pungi.phases.buildinstall.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
@mock.patch('pungi.phases.buildinstall.get_buildroot_rpms')
|
@mock.patch('pungi.wrappers.kojiwrapper.get_buildroot_rpms')
|
||||||
@mock.patch('pungi.phases.buildinstall.run')
|
@mock.patch('pungi.phases.buildinstall.run')
|
||||||
def test_buildinstall_thread_with_lorax_in_runroot(self, run, get_buildroot_rpms, KojiWrapperMock):
|
def test_buildinstall_thread_with_lorax_in_runroot(self, run, get_buildroot_rpms, KojiWrapperMock):
|
||||||
compose = BuildInstallCompose(self.topdir, {
|
compose = BuildInstallCompose(self.topdir, {
|
||||||
@ -779,8 +779,8 @@ class BuildinstallThreadTestCase(PungiTestCase):
|
|||||||
self.assertItemsEqual(rpms, ['bash', 'zsh'])
|
self.assertItemsEqual(rpms, ['bash', 'zsh'])
|
||||||
self.assertItemsEqual(self.pool.finished_tasks, [('Server', 'x86_64')])
|
self.assertItemsEqual(self.pool.finished_tasks, [('Server', 'x86_64')])
|
||||||
|
|
||||||
@mock.patch('pungi.phases.buildinstall.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
@mock.patch('pungi.phases.buildinstall.get_buildroot_rpms')
|
@mock.patch('pungi.wrappers.kojiwrapper.get_buildroot_rpms')
|
||||||
@mock.patch('pungi.phases.buildinstall.run')
|
@mock.patch('pungi.phases.buildinstall.run')
|
||||||
def test_buildinstall_thread_with_buildinstall_in_runroot(self, run, get_buildroot_rpms, KojiWrapperMock):
|
def test_buildinstall_thread_with_buildinstall_in_runroot(self, run, get_buildroot_rpms, KojiWrapperMock):
|
||||||
compose = BuildInstallCompose(self.topdir, {
|
compose = BuildInstallCompose(self.topdir, {
|
||||||
@ -823,8 +823,8 @@ class BuildinstallThreadTestCase(PungiTestCase):
|
|||||||
self.assertItemsEqual(rpms, ['bash', 'zsh'])
|
self.assertItemsEqual(rpms, ['bash', 'zsh'])
|
||||||
self.assertItemsEqual(self.pool.finished_tasks, [(None, 'x86_64')])
|
self.assertItemsEqual(self.pool.finished_tasks, [(None, 'x86_64')])
|
||||||
|
|
||||||
@mock.patch('pungi.phases.buildinstall.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
@mock.patch('pungi.phases.buildinstall.get_buildroot_rpms')
|
@mock.patch('pungi.wrappers.kojiwrapper.get_buildroot_rpms')
|
||||||
@mock.patch('pungi.phases.buildinstall.run')
|
@mock.patch('pungi.phases.buildinstall.run')
|
||||||
def test_buildinstall_fail_exit_code(self, run, get_buildroot_rpms, KojiWrapperMock):
|
def test_buildinstall_fail_exit_code(self, run, get_buildroot_rpms, KojiWrapperMock):
|
||||||
compose = BuildInstallCompose(self.topdir, {
|
compose = BuildInstallCompose(self.topdir, {
|
||||||
@ -858,8 +858,8 @@ class BuildinstallThreadTestCase(PungiTestCase):
|
|||||||
])
|
])
|
||||||
self.assertItemsEqual(self.pool.finished_tasks, [])
|
self.assertItemsEqual(self.pool.finished_tasks, [])
|
||||||
|
|
||||||
@mock.patch('pungi.phases.buildinstall.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
@mock.patch('pungi.phases.buildinstall.get_buildroot_rpms')
|
@mock.patch('pungi.wrappers.kojiwrapper.get_buildroot_rpms')
|
||||||
@mock.patch('pungi.phases.buildinstall.run')
|
@mock.patch('pungi.phases.buildinstall.run')
|
||||||
def test_lorax_fail_exit_code(self, run, get_buildroot_rpms, KojiWrapperMock):
|
def test_lorax_fail_exit_code(self, run, get_buildroot_rpms, KojiWrapperMock):
|
||||||
compose = BuildInstallCompose(self.topdir, {
|
compose = BuildInstallCompose(self.topdir, {
|
||||||
@ -892,8 +892,8 @@ class BuildinstallThreadTestCase(PungiTestCase):
|
|||||||
])
|
])
|
||||||
self.assertItemsEqual(self.pool.finished_tasks, [])
|
self.assertItemsEqual(self.pool.finished_tasks, [])
|
||||||
|
|
||||||
@mock.patch('pungi.phases.buildinstall.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
@mock.patch('pungi.phases.buildinstall.get_buildroot_rpms')
|
@mock.patch('pungi.wrappers.kojiwrapper.get_buildroot_rpms')
|
||||||
@mock.patch('pungi.phases.buildinstall.run')
|
@mock.patch('pungi.phases.buildinstall.run')
|
||||||
def test_skips_on_existing_output_dir(self, run, get_buildroot_rpms, KojiWrapperMock):
|
def test_skips_on_existing_output_dir(self, run, get_buildroot_rpms, KojiWrapperMock):
|
||||||
compose = BuildInstallCompose(self.topdir, {
|
compose = BuildInstallCompose(self.topdir, {
|
||||||
@ -921,8 +921,8 @@ class BuildinstallThreadTestCase(PungiTestCase):
|
|||||||
self.assertTrue(os.path.exists(dummy_file))
|
self.assertTrue(os.path.exists(dummy_file))
|
||||||
self.assertItemsEqual(self.pool.finished_tasks, [])
|
self.assertItemsEqual(self.pool.finished_tasks, [])
|
||||||
|
|
||||||
@mock.patch('pungi.phases.buildinstall.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
@mock.patch('pungi.phases.buildinstall.get_buildroot_rpms')
|
@mock.patch('pungi.wrappers.kojiwrapper.get_buildroot_rpms')
|
||||||
@mock.patch('pungi.phases.buildinstall.run')
|
@mock.patch('pungi.phases.buildinstall.run')
|
||||||
@mock.patch('pungi.phases.buildinstall.copy_all')
|
@mock.patch('pungi.phases.buildinstall.copy_all')
|
||||||
def test_buildinstall_thread_with_lorax_custom_buildinstall_topdir(
|
def test_buildinstall_thread_with_lorax_custom_buildinstall_topdir(
|
||||||
|
@ -348,7 +348,7 @@ class CreateisoThreadTest(helpers.PungiTestCase):
|
|||||||
@mock.patch('pungi.phases.createiso.iso')
|
@mock.patch('pungi.phases.createiso.iso')
|
||||||
@mock.patch('pungi.phases.createiso.get_mtime')
|
@mock.patch('pungi.phases.createiso.get_mtime')
|
||||||
@mock.patch('pungi.phases.createiso.get_file_size')
|
@mock.patch('pungi.phases.createiso.get_file_size')
|
||||||
@mock.patch('pungi.phases.createiso.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
def test_process_in_runroot(self, KojiWrapper, get_file_size, get_mtime, iso):
|
def test_process_in_runroot(self, KojiWrapper, get_file_size, get_mtime, iso):
|
||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
'release_short': 'test',
|
'release_short': 'test',
|
||||||
@ -412,7 +412,7 @@ class CreateisoThreadTest(helpers.PungiTestCase):
|
|||||||
@mock.patch('pungi.phases.createiso.iso')
|
@mock.patch('pungi.phases.createiso.iso')
|
||||||
@mock.patch('pungi.phases.createiso.get_mtime')
|
@mock.patch('pungi.phases.createiso.get_mtime')
|
||||||
@mock.patch('pungi.phases.createiso.get_file_size')
|
@mock.patch('pungi.phases.createiso.get_file_size')
|
||||||
@mock.patch('pungi.phases.createiso.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
def test_process_source_iso(self, KojiWrapper, get_file_size, get_mtime, iso):
|
def test_process_source_iso(self, KojiWrapper, get_file_size, get_mtime, iso):
|
||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
'release_short': 'test',
|
'release_short': 'test',
|
||||||
@ -477,7 +477,7 @@ class CreateisoThreadTest(helpers.PungiTestCase):
|
|||||||
@mock.patch('pungi.phases.createiso.iso')
|
@mock.patch('pungi.phases.createiso.iso')
|
||||||
@mock.patch('pungi.phases.createiso.get_mtime')
|
@mock.patch('pungi.phases.createiso.get_mtime')
|
||||||
@mock.patch('pungi.phases.createiso.get_file_size')
|
@mock.patch('pungi.phases.createiso.get_file_size')
|
||||||
@mock.patch('pungi.phases.createiso.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
def test_process_bootable(self, KojiWrapper, get_file_size, get_mtime, iso):
|
def test_process_bootable(self, KojiWrapper, get_file_size, get_mtime, iso):
|
||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
'release_short': 'test',
|
'release_short': 'test',
|
||||||
@ -513,7 +513,8 @@ class CreateisoThreadTest(helpers.PungiTestCase):
|
|||||||
with mock.patch('time.sleep'):
|
with mock.patch('time.sleep'):
|
||||||
t.process((compose, cmd, compose.variants['Server'], 'x86_64'), 1)
|
t.process((compose, cmd, compose.variants['Server'], 'x86_64'), 1)
|
||||||
|
|
||||||
self.assertEqual(getTag.call_args_list, [mock.call('f25-build')])
|
# There is no need to call getTag if `bootable` is True.
|
||||||
|
self.assertEqual(getTag.call_args_list, [])
|
||||||
self.assertEqual(get_runroot_cmd.call_args_list,
|
self.assertEqual(get_runroot_cmd.call_args_list,
|
||||||
[mock.call('f25-build', 'x86_64', cmd['cmd'], channel=None,
|
[mock.call('f25-build', 'x86_64', cmd['cmd'], channel=None,
|
||||||
mounts=[self.topdir],
|
mounts=[self.topdir],
|
||||||
@ -543,7 +544,7 @@ class CreateisoThreadTest(helpers.PungiTestCase):
|
|||||||
@mock.patch('pungi.phases.createiso.iso')
|
@mock.patch('pungi.phases.createiso.iso')
|
||||||
@mock.patch('pungi.phases.createiso.get_mtime')
|
@mock.patch('pungi.phases.createiso.get_mtime')
|
||||||
@mock.patch('pungi.phases.createiso.get_file_size')
|
@mock.patch('pungi.phases.createiso.get_file_size')
|
||||||
@mock.patch('pungi.phases.createiso.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
def test_process_in_runroot_non_existing_tag(self, KojiWrapper, get_file_size,
|
def test_process_in_runroot_non_existing_tag(self, KojiWrapper, get_file_size,
|
||||||
get_mtime, iso):
|
get_mtime, iso):
|
||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
@ -575,7 +576,7 @@ class CreateisoThreadTest(helpers.PungiTestCase):
|
|||||||
@mock.patch('pungi.phases.createiso.iso')
|
@mock.patch('pungi.phases.createiso.iso')
|
||||||
@mock.patch('pungi.phases.createiso.get_mtime')
|
@mock.patch('pungi.phases.createiso.get_mtime')
|
||||||
@mock.patch('pungi.phases.createiso.get_file_size')
|
@mock.patch('pungi.phases.createiso.get_file_size')
|
||||||
@mock.patch('pungi.phases.createiso.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
def test_process_in_runroot_crash(self, KojiWrapper, get_file_size, get_mtime, iso):
|
def test_process_in_runroot_crash(self, KojiWrapper, get_file_size, get_mtime, iso):
|
||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
'release_short': 'test',
|
'release_short': 'test',
|
||||||
@ -614,7 +615,7 @@ class CreateisoThreadTest(helpers.PungiTestCase):
|
|||||||
@mock.patch('pungi.phases.createiso.iso')
|
@mock.patch('pungi.phases.createiso.iso')
|
||||||
@mock.patch('pungi.phases.createiso.get_mtime')
|
@mock.patch('pungi.phases.createiso.get_mtime')
|
||||||
@mock.patch('pungi.phases.createiso.get_file_size')
|
@mock.patch('pungi.phases.createiso.get_file_size')
|
||||||
@mock.patch('pungi.phases.createiso.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
def test_process_in_runroot_fail(self, KojiWrapper, get_file_size, get_mtime, iso):
|
def test_process_in_runroot_fail(self, KojiWrapper, get_file_size, get_mtime, iso):
|
||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
'release_short': 'test',
|
'release_short': 'test',
|
||||||
@ -658,8 +659,8 @@ class CreateisoThreadTest(helpers.PungiTestCase):
|
|||||||
@mock.patch('pungi.phases.createiso.iso')
|
@mock.patch('pungi.phases.createiso.iso')
|
||||||
@mock.patch('pungi.phases.createiso.get_mtime')
|
@mock.patch('pungi.phases.createiso.get_mtime')
|
||||||
@mock.patch('pungi.phases.createiso.get_file_size')
|
@mock.patch('pungi.phases.createiso.get_file_size')
|
||||||
@mock.patch('pungi.phases.createiso.run')
|
@mock.patch('pungi.runroot.run')
|
||||||
@mock.patch('pungi.phases.createiso.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
def test_process_locally(self, KojiWrapper, run, get_file_size, get_mtime, iso):
|
def test_process_locally(self, KojiWrapper, run, get_file_size, get_mtime, iso):
|
||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
'release_short': 'test',
|
'release_short': 'test',
|
||||||
@ -703,8 +704,8 @@ class CreateisoThreadTest(helpers.PungiTestCase):
|
|||||||
self.assertEqual(image.type, 'dvd')
|
self.assertEqual(image.type, 'dvd')
|
||||||
self.assertEqual(image.subvariant, 'Server')
|
self.assertEqual(image.subvariant, 'Server')
|
||||||
|
|
||||||
@mock.patch('pungi.phases.createiso.run')
|
@mock.patch('pungi.runroot.run')
|
||||||
@mock.patch('pungi.phases.createiso.KojiWrapper')
|
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
|
||||||
def test_process_locally_crash(self, KojiWrapper, run):
|
def test_process_locally_crash(self, KojiWrapper, run):
|
||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
'release_short': 'test',
|
'release_short': 'test',
|
||||||
|
@ -28,7 +28,8 @@ class OstreeInstallerPhaseTest(helpers.PungiTestCase):
|
|||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
'ostree_installer': [
|
'ostree_installer': [
|
||||||
('^Everything$', {'x86_64': cfg})
|
('^Everything$', {'x86_64': cfg})
|
||||||
]
|
],
|
||||||
|
'runroot': True,
|
||||||
})
|
})
|
||||||
|
|
||||||
pool = ThreadPool.return_value
|
pool = ThreadPool.return_value
|
||||||
@ -101,6 +102,7 @@ class OstreeThreadTest(helpers.PungiTestCase):
|
|||||||
'translate_paths': [
|
'translate_paths': [
|
||||||
(self.topdir + '/work', 'http://example.com/work')
|
(self.topdir + '/work', 'http://example.com/work')
|
||||||
],
|
],
|
||||||
|
'runroot': True,
|
||||||
})
|
})
|
||||||
|
|
||||||
def assertImageAdded(self, compose, ImageCls, iso):
|
def assertImageAdded(self, compose, ImageCls, iso):
|
||||||
|
@ -23,7 +23,8 @@ class OSTreePhaseTest(helpers.PungiTestCase):
|
|||||||
compose = helpers.DummyCompose(self.topdir, {
|
compose = helpers.DummyCompose(self.topdir, {
|
||||||
'ostree': [
|
'ostree': [
|
||||||
('^Everything$', {'x86_64': cfg})
|
('^Everything$', {'x86_64': cfg})
|
||||||
]
|
],
|
||||||
|
'runroot': True,
|
||||||
})
|
})
|
||||||
|
|
||||||
pool = ThreadPool.return_value
|
pool = ThreadPool.return_value
|
||||||
@ -112,14 +113,15 @@ class OSTreeThreadTest(helpers.PungiTestCase):
|
|||||||
'config_url': 'https://git.fedorahosted.org/git/fedora-atomic.git',
|
'config_url': 'https://git.fedorahosted.org/git/fedora-atomic.git',
|
||||||
'config_branch': 'f24',
|
'config_branch': 'f24',
|
||||||
'treefile': 'fedora-atomic-docker-host.json',
|
'treefile': 'fedora-atomic-docker-host.json',
|
||||||
'ostree_repo': self.repo
|
'ostree_repo': self.repo,
|
||||||
}
|
}
|
||||||
self.compose = helpers.DummyCompose(self.topdir, {
|
self.compose = helpers.DummyCompose(self.topdir, {
|
||||||
'koji_profile': 'koji',
|
'koji_profile': 'koji',
|
||||||
'runroot_tag': 'rrt',
|
'runroot_tag': 'rrt',
|
||||||
'translate_paths': [
|
'translate_paths': [
|
||||||
(self.topdir, 'http://example.com')
|
(self.topdir, 'http://example.com')
|
||||||
]
|
],
|
||||||
|
'runroot': True
|
||||||
})
|
})
|
||||||
self.pool = mock.Mock()
|
self.pool = mock.Mock()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user