[PATCH] add mechanism for general purpose parameter passing to Image Factory
by Ian McLeod
We originally added semi-generic parameter passing for OVA support and
then overloaded it for Vagrant support, before breaking that back out
as specific image types.
This change adds a fairly generic mechanism for parameter passthrough
to plugins and the base builder that does not require patching the
builder and CLI each time a new class of parameter is added to Factory.
The immediate reason for doing this is to expose the Docker plugin's
ability to set custom labels, environments and commands, but it is
likely to be useful for other things in the future.
---
builder/kojid | 39 ++++++++++++++++++++++++++++++++++-----
cli/koji | 15 ++++++++++++++-
2 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/builder/kojid b/builder/kojid
index 4ea93f2..ad427cd 100755
--- a/builder/kojid
+++ b/builder/kojid
@@ -3178,6 +3178,25 @@ class BaseImageTask(OzImageTask):
raise koji.ApplianceError('Image status is %s: %s' %
(status, details))
+ def _mergeFactoryParams(self, img_opts, fixed_params):
+ """
+ Merge any KV pairs passed in via --factory-parameter CLI options
+ into an existing dictionary that will eventually be passed to
+ factory build commands. This allows a fairly generic mechanism
+ for parameter passthrough to plugins and the base builder that does
+ not require patching the builder and CLI each time.
+
+ @args:
+ img_opts - an existing dict with any pre-existing parameters
+ fixed_params - list of parameters that must not be overriden
+ @returns:
+ nothing - dict is modified in place
+ """
+ if self.opts.get('factory_parameter'):
+ for kvp in self.opts.get('factory_parameter'):
+ if kvp[0] not in fixed_params:
+ img_opts[kvp[0]] = kvp[1]
+
def _buildBase(self, template, params, wait=True):
"""
Build a base image using ImageFactory. This is a "raw" image.
@@ -3194,7 +3213,10 @@ class BaseImageTask(OzImageTask):
# may need to still upload ozlog and remove the log handler
self.logger.info('dispatching a baseimg builder')
self.logger.debug('templates: %s' % template)
- self.logger.debug('params: %s' % params)
+ self.logger.debug('pre-merge params: %s' % params)
+ # We enforce various things related to the ks file - do not allow override
+ self._mergeFactoryParams(params, [ 'install_script' ])
+ self.logger.debug('post-merge params: %s' % params)
base = self.bd.builder_for_base_image(template, parameters=params)
if wait:
base.base_thread.join()
@@ -3245,19 +3267,22 @@ class BaseImageTask(OzImageTask):
if format == 'vagrant-virtualbox':
format = 'vsphere-ova'
img_opts['vsphere_ova_format'] = 'vagrant-virtualbox'
+ fixed_params = [ 'vsphere_ova_format' ]
if format == 'vagrant-libvirt':
format = 'rhevm-ova'
img_opts['rhevm_ova_format'] = 'vagrant-libvirt'
+ fixed_params = [ 'rhevm_ova_format' ]
if format == 'vagrant-vmware-fusion':
format = 'vsphere-ova'
img_opts['vsphere_ova_format'] = 'vagrant-vmware-fusion'
# The initial disk image transform for VMWare Fusion/Workstation requires a "standard" VMDK
# not the stream oriented format used for VirtualBox or regular VMWare OVAs
img_opts['vsphere_vmdk_format'] = 'standard'
+ fixed_params = [ 'vsphere_ova_format', 'vsphere_vmdk_format' ]
targ = self._do_target_image(self.base_img.base_image.identifier,
- format.replace('-ova', ''), img_opts=img_opts)
+ format.replace('-ova', ''), img_opts=img_opts, fixed_params=fixed_params)
targ2 = self._do_target_image(targ.target_image.identifier, 'OVA',
- img_opts=img_opts)
+ img_opts=img_opts, fixed_params=fixed_params)
return {'image': targ2.target_image.data}
def _buildDocker(self, format):
@@ -3275,7 +3300,7 @@ class BaseImageTask(OzImageTask):
'docker', img_opts=img_opts)
return {'image': targ.target_image.data}
- def _do_target_image(self, base_id, image_type, img_opts={}):
+ def _do_target_image(self, base_id, image_type, img_opts={}, fixed_params=[]):
"""
A generic method for building what ImageFactory calls "target images".
These are images based on a raw disk that was built before using the
@@ -3287,6 +3312,8 @@ class BaseImageTask(OzImageTask):
uses this to figure out what plugin to run
img_opts - a dict of additional options that specific to the target
type we pass in via image_type
+ fixed_params - a list of parameter keys that should not be overriden
+ by the --factory-parameter CLI
@returns:
A Builder() object from ImageFactory that contains information
about the image building include state and progress.
@@ -3294,7 +3321,9 @@ class BaseImageTask(OzImageTask):
# TODO: test the failure case where IF itself throws an exception
# ungracefully (missing a plugin for example)
# may need to still upload ozlog and remove the log handler
- self.logger.debug('img_opts: %s' % img_opts)
+ self.logger.debug('img_opts_pre_merge: %s' % img_opts)
+ self._mergeFactoryParams(img_opts, fixed_params)
+ self.logger.debug('img_opts_post_merge: %s' % img_opts)
target = self.bd.builder_for_target_image(image_type,
image_id=base_id, template=None, parameters=img_opts)
target.target_thread.join()
diff --git a/cli/koji b/cli/koji
index 64c5356..cbfa2d0 100755
--- a/cli/koji
+++ b/cli/koji
@@ -5306,6 +5306,11 @@ def handle_image_build(options, session, args):
parser.add_option("--ova-option", action="append",
help=_("Override a value in the OVA description XML. Provide a value " +
"in a name=value format, such as 'ovf_memory_mb=6144'"))
+ parser.add_option("--factory-parameter", nargs=2, action="append",
+ help=_("Pass a parameter to Image Factory. The results are highly specific " +
+ "to the image format being created. This is a two argument parameter " +
+ "that can be specified an arbitrary number of times. For example: "
+ "--factory-parameter docker_cmd '[ \"/bin/echo Hello World\" ]'"))
parser.add_option("--release", help=_("Forcibly set the release field"))
parser.add_option("--repo", action="append",
help=_("Specify a repo that will override the repo used to install " +
@@ -5355,6 +5360,14 @@ def handle_image_build(options, session, args):
for k, v in config.items(section):
task_options.ova_option.append('%s=%s' % (k, v))
+ # as do factory-parameters
+ section = 'factory-parameters'
+ if config.has_section(section):
+ task_options.factory_parameter = [ ]
+ for k, v in config.items(section):
+ # We do this, rather than a dict, to match what argparse spits out
+ task_options.factory_parameter.append( (k, v) )
+
else:
if len(args) < 5:
parser.error(_("At least five arguments are required: a name, " +
@@ -5483,7 +5496,7 @@ def _build_image_oz(options, task_opts, session, args):
hub_opts = {}
for opt in ('ksurl', 'ksversion', 'kickstart', 'scratch', 'repo',
'release', 'skip_tag', 'specfile', 'distro', 'format',
- 'disk_size', 'ova_option'):
+ 'disk_size', 'ova_option', 'factory_parameter'):
val = getattr(task_opts, opt, None)
if val is not None:
hub_opts[opt] = val
--
2.1.0
7 years, 10 months
[PATCH] use createrepo_c instead of createrepo to make repos if it is available
by Dennis Gilmore
Signed-off-by: Dennis Gilmore <dennis(a)ausil.us>
---
builder/kojid | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/builder/kojid b/builder/kojid
index 3a92ec3..4e53fb5 100755
--- a/builder/kojid
+++ b/builder/kojid
@@ -4252,7 +4252,11 @@ class CreaterepoTask(BaseTaskHandler):
def create_local_repo(self, rinfo, arch, pkglist, groupdata, oldrepo):
koji.ensuredir(self.outdir)
- cmd = ['/usr/bin/createrepo', '-vd', '-o', self.outdir]
+ if os.path.isfile('/usr/bin/createrepo_c'):
+ cmd = ['/usr/bin/createrepo_c']
+ else:
+ cmd = ['/usr/bin/createrepo']
+ cmd.extend(['-vd', '-o', self.outdir])
if pkglist is not None:
cmd.extend(['-i', pkglist])
if os.path.isfile(groupdata):
--
2.4.0
7 years, 11 months
[PATCH 1/2] Move config processing from CLI to koji.read_config().
by Daniel Mach
---
cli/koji | 85 ++------------------------------------------
koji/__init__.py | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 109 insertions(+), 82 deletions(-)
diff --git a/cli/koji b/cli/koji
index 47d9691..66f4d99 100755
--- a/cli/koji
+++ b/cli/koji
@@ -186,88 +186,9 @@ def get_options():
list_commands()
parser.error('Unknown command: %s' % args[0])
assert False
- # load local config
- defaults = {
- 'server' : 'http://localhost/kojihub',
- 'weburl' : 'http://localhost/koji',
- 'topurl' : None,
- 'pkgurl' : None,
- 'topdir' : '/mnt/koji',
- 'max_retries' : None,
- 'retry_interval': None,
- 'anon_retry' : None,
- 'offline_retry' : None,
- 'offline_retry_interval' : None,
- 'keepalive' : True,
- 'timeout' : None,
- 'use_fast_upload': False,
- 'poll_interval': 5,
- 'krbservice': 'host',
- 'cert': '~/.koji/client.crt',
- 'ca': '~/.koji/clientca.crt',
- 'serverca': '~/.koji/serverca.crt',
- 'authtype': None
- }
- #note: later config files override earlier ones
- configs = koji.config_directory_contents('/etc/koji.conf.d')
- if os.access('/etc/koji.conf', os.F_OK):
- configs.append('/etc/koji.conf')
- if options.configFile:
- fn = os.path.expanduser(options.configFile)
- if os.path.isdir(fn):
- contents = koji.config_directory_contents(fn)
- if not contents:
- parser.error("No config files found in directory: %s" % fn)
- configs.extend(contents)
- else:
- if not os.access(fn, os.F_OK):
- parser.error("No such file: %s" % fn)
- configs.append(fn)
- else:
- user_config_dir = os.path.expanduser("~/.koji/config.d")
- configs.extend(koji.config_directory_contents(user_config_dir))
- fn = os.path.expanduser("~/.koji/config")
- if os.access(fn, os.F_OK):
- configs.append(fn)
- got_conf = False
- for configFile in configs:
- f = open(configFile)
- config = ConfigParser.ConfigParser()
- config.readfp(f)
- f.close()
- if config.has_section(options.profile):
- got_conf = True
- for name, value in config.items(options.profile):
- #note the defaults dictionary also serves to indicate which
- #options *can* be set via the config file. Such options should
- #not have a default value set in the option parser.
- if defaults.has_key(name):
- if name in ('anon_retry', 'offline_retry', 'keepalive', 'use_fast_upload'):
- defaults[name] = config.getboolean(options.profile, name)
- elif name in ('max_retries', 'retry_interval',
- 'offline_retry_interval', 'poll_interval', 'timeout'):
- try:
- defaults[name] = int(value)
- except ValueError:
- parser.error("value for %s config option must be a valid integer" % name)
- assert False
- else:
- defaults[name] = value
- if configs and not got_conf:
- warn("Warning: no configuration for profile name: %s" % options.profile)
- for name, value in defaults.iteritems():
- if getattr(options, name, None) is None:
- setattr(options, name, value)
- dir_opts = ('topdir', 'cert', 'ca', 'serverca')
- for name in dir_opts:
- # expand paths here, so we don't have to worry about it later
- value = os.path.expanduser(getattr(options, name))
- setattr(options, name, value)
-
- #honor topdir
- if options.topdir:
- koji.BASEDIR = options.topdir
- koji.pathinfo.topdir = options.topdir
+
+ defaults = koji.read_config(options.profile, user_config=options.configFile)
+ options._update_loose(defaults.__dict__)
#pkgurl is obsolete
if options.pkgurl:
diff --git a/koji/__init__.py b/koji/__init__.py
index f45ff70..9951a28 100644
--- a/koji/__init__.py
+++ b/koji/__init__.py
@@ -28,6 +28,7 @@ except ImportError:
sys.stderr.write("Warning: Could not install krbV module. Kerberos support will be disabled.\n")
sys.stderr.flush()
import base64
+import ConfigParser
import datetime
import errno
from fnmatch import fnmatch
@@ -35,6 +36,7 @@ import httplib
import logging
import logging.handlers
from koji.util import md5_constructor
+import optparse
import os
import os.path
import pwd
@@ -1457,6 +1459,110 @@ def config_directory_contents(dir_name):
return configs
+def _config_directory_contents(dir_name):
+ configs = []
+ try:
+ conf_dir_contents = os.listdir(dir_name)
+ except OSError, exception:
+ if exception.errno != errno.ENOENT:
+ raise
+ else:
+ for name in sorted(conf_dir_contents):
+ if not name.endswith('.conf'):
+ continue
+ config_full_name = os.path.join(dir_name, name)
+ configs.append(config_full_name)
+ return configs
+
+
+def read_config(profile_name, user_config=None):
+ config_defaults = {
+ 'server': 'http://localhost/kojihub',
+ 'weburl': 'http://localhost/koji',
+ 'topurl': None,
+ 'pkgurl': None,
+ 'topdir': '/mnt/koji',
+ 'max_retries': None,
+ 'retry_interval': None,
+ 'anon_retry': None,
+ 'offline_retry': None,
+ 'offline_retry_interval': None,
+ 'keepalive': True,
+ 'timeout': None,
+ 'use_fast_upload': False,
+ 'poll_interval': 5,
+ 'krbservice': 'host',
+ 'cert': '~/.koji/client.crt',
+ 'ca': '~/.koji/clientca.crt',
+ 'serverca': '~/.koji/serverca.crt',
+ 'authtype': None
+ }
+
+ int_options = ['max_retries', 'retry_interval', 'offline_retry_interval', 'poll_interval', 'timeout']
+ bool_options = ['anon_retry', 'offline_retry', 'keepalive', 'use_fast_upload']
+ path_options = ['topdir', 'cert', 'ca', 'serverca']
+
+ result = config_defaults.copy()
+ for option in config_defaults:
+ if option in path_options:
+ result[option] = os.path.expanduser(result[option])
+
+ configs = []
+
+ # main config
+ configs.append("/etc/koji.conf")
+
+ # conf.d
+ configs.extend(_config_directory_contents("/etc/koji.conf.d"))
+
+ # user config
+ configs.append(os.path.expanduser("~/.koji/config"))
+
+ # user conf.d
+ configs.extend(_config_directory_contents(os.path.expanduser("~/.koji/conf.d")))
+
+ # TODO: read configs via xdg.BaseDirectory.load_config_path("koji")
+
+ # user config specified in runtime
+ if user_config is not None:
+ configs.append(user_config)
+
+ # read configs in particular order, use the last value found
+ for config_path in configs:
+ if not os.access(config_path, os.F_OK):
+ continue
+ config = ConfigParser.SafeConfigParser()
+ config.readfp(open(config_path, "r"))
+
+ if profile_name not in config.sections():
+ continue
+
+ # check for invalid options
+ invalid_options = []
+ for option in config.options(profile_name):
+ if option not in result:
+ invalid_options.append(option)
+
+ if invalid_options:
+ raise ValueError("Invalid options: %s" % ", ".join(invalid_options))
+
+ for option in config.options(profile_name):
+ if option in bool_options:
+ result[option] = config.getboolean(profile_name, option)
+ elif option in int_options:
+ result[option] = config.getint(profile_name, option)
+ else:
+ result[option] = config.get(profile_name, option)
+ if option in path_options:
+ result[option] = os.path.expanduser(result[option])
+
+ result["profile"] = profile_name
+
+ # convert dict to optparse Values
+ options = optparse.Values(result)
+ return options
+
+
class PathInfo(object):
# ASCII numbers and upper- and lower-case letter for use in tmpdir()
ASCII_CHARS = [chr(i) for i in range(48, 58) + range(65, 91) + range(97, 123)]
--
2.5.0
7 years, 11 months
Re: buildsys Digest, Vol 128, Issue 7
by Gustav Paul
Hi guys
Sorry to spam the list - I have tried every conceivable method of
unsubscribing from this list and nothing works.
Please! Unsubscribe me!
On Thu, Oct 29, 2015 at 2:00 PM, <buildsys-request(a)lists.fedoraproject.org>
wrote:
> Send buildsys mailing list submissions to
> buildsys(a)lists.fedoraproject.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
> https://admin.fedoraproject.org/mailman/listinfo/buildsys
> or, via email, send a message with subject or body 'help' to
> buildsys-request(a)lists.fedoraproject.org
>
> You can reach the person managing the list at
> buildsys-owner(a)lists.fedoraproject.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of buildsys digest..."
>
>
> Today's Topics:
>
> 1. Re: Koji and spec file with not the most up-to-date version
> of a package (Sebastien Moretti)
> 2. Re: Koji and spec file with not the most up-to-date version
> of a package (Dennis Gilmore)
> 3. Re: Koji and spec file with not the most up-to-date version
> of a package (Matthew Miller)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Wed, 28 Oct 2015 14:51:45 +0100
> From: Sebastien Moretti <sebastien.moretti(a)unil.ch>
> To: buildsys(a)lists.fedoraproject.org
> Subject: Re: Koji and spec file with not the most up-to-date version
> of a package
> Message-ID: <5630D2F1.1020301(a)unil.ch>
> Content-Type: text/plain; charset=utf-8; format=flowed
>
> >> Hi
> >>
> >> We use Koji and have an issue with some packages (let say B)
> >> requiring a particular version of another package (A = 1.2 ) which
> >> has a more up-to-date version (A = 1.2 & A = 1.5).
> >> e.g.
> >> Name: B
> >> BuildRequires: A = 1.2
> >>
> >> In that case, Koji builds fail:
> >> DEBUG util.py:388: Error: Package: B-3.4.2-4.el6.x86_64 (build)
> >> DEBUG util.py:388: Requires: A = 1.2
> >> DEBUG util.py:388: Available: A = 1.5-1.x86_64 (build)
> >> DEBUG util.py:388: A = 1.5
> >>
> >>
> >>
> >> Is there a way to avoid that behavior?
> >> When no version is specified, use the most up-to-date, when a
> >> particular version is required, use that one.
> >
> > koji repos can contain only single build of a package, that's by design
> >
> >
> > Dan
>
> But if I try
> yum info A
> it will return A-1.5
>
> If I try
> yum info A-1.2
> it will return A-1.2
>
> So both should be in the repos, right?
>
> --
> Sébastien Moretti
>
>
>
> ------------------------------
>
> Message: 2
> Date: Wed, 28 Oct 2015 09:14:34 -0500
> From: Dennis Gilmore <dennis(a)ausil.us>
> To: Discussion of Fedora build system
> <buildsys(a)lists.fedoraproject.org>
> Subject: Re: Koji and spec file with not the most up-to-date version
> of a package
> Message-ID: <24934932.tKV2aVA0zT(a)ra.ausil.us>
> Content-Type: text/plain; charset="utf-8"
>
> On Wednesday, October 28, 2015 02:51:45 PM Sebastien Moretti wrote:
> > >> Hi
> > >>
> > >> We use Koji and have an issue with some packages (let say B)
> > >> requiring a particular version of another package (A = 1.2 ) which
> > >> has a more up-to-date version (A = 1.2 & A = 1.5).
> > >> e.g.
> > >> Name: B
> > >> BuildRequires: A = 1.2
> > >>
> > >> In that case, Koji builds fail:
> > >> DEBUG util.py:388: Error: Package: B-3.4.2-4.el6.x86_64 (build)
> > >> DEBUG util.py:388: Requires: A = 1.2
> > >> DEBUG util.py:388: Available: A = 1.5-1.x86_64 (build)
> > >> DEBUG util.py:388: A = 1.5
> > >>
> > >>
> > >>
> > >> Is there a way to avoid that behavior?
> > >> When no version is specified, use the most up-to-date, when a
> > >> particular version is required, use that one.
> > >
> > > koji repos can contain only single build of a package, that's by design
> > >
> > > Dan
> >
> > But if I try
> > yum info A
> > it will return A-1.5
> >
> > If I try
> > yum info A-1.2
> > it will return A-1.2
> >
> > So both should be in the repos, right?
>
> no koji only has the last tagged version of a package in its repos. if you
> need multiple versions of something you will need to manage that in the
> packaging. having a12 a15 etc packages
>
> Dennis
>
> Dennis
>
>
> -------------- next part --------------
> A non-text attachment was scrubbed...
> Name: signature.asc
> Type: application/pgp-signature
> Size: 819 bytes
> Desc: This is a digitally signed message part.
> URL: <
> http://lists.fedoraproject.org/pipermail/buildsys/attachments/20151028/df...
> >
>
> ------------------------------
>
> Message: 3
> Date: Wed, 28 Oct 2015 10:38:48 -0400
> From: Matthew Miller <mattdm(a)fedoraproject.org>
> To: Discussion of Fedora build system
> <buildsys(a)lists.fedoraproject.org>
> Subject: Re: Koji and spec file with not the most up-to-date version
> of a package
> Message-ID: <20151028143848.GA25076(a)mattdm.org>
> Content-Type: text/plain; charset=us-ascii
>
> On Tue, Oct 27, 2015 at 04:05:25PM +0100, Sebastien Moretti wrote:
> > Both A-1.2 and A-1.5 are available in my build repos.
> >
> > If A-1.2 was not in build repos, the error message would be
> > different I guess.
>
> Is it possible for you to create different repos for the build
> requirements for your different products?
>
>
> --
> Matthew Miller
> <mattdm(a)fedoraproject.org>
> Fedora Project Leader
>
>
> ------------------------------
>
> --
> buildsys mailing list
> buildsys(a)lists.fedoraproject.org
> https://admin.fedoraproject.org/mailman/listinfo/buildsys
>
> End of buildsys Digest, Vol 128, Issue 7
> ****************************************
>
7 years, 11 months
Koji and spec file with not the most up-to-date version of a package
by Sebastien Moretti
Hi
We use Koji and have an issue with some packages (let say B) requiring a
particular version of another package (A = 1.2 ) which has a more
up-to-date version (A = 1.2 & A = 1.5).
e.g.
Name: B
BuildRequires: A = 1.2
In that case, Koji builds fail:
DEBUG util.py:388: Error: Package: B-3.4.2-4.el6.x86_64 (build)
DEBUG util.py:388: Requires: A = 1.2
DEBUG util.py:388: Available: A = 1.5-1.x86_64 (build)
DEBUG util.py:388: A = 1.5
Is there a way to avoid that behavior?
When no version is specified, use the most up-to-date, when a particular
version is required, use that one.
Regards
Mock Version: 1.2.7
--
Sébastien Moretti
7 years, 11 months
[PATCH] add mechanism for general purpose parameter passing to Image Factory
by Ian McLeod
We originally added semi-generic parameter passing for OVA support and
then overloaded it for Vagrant support, before breaking that back out
as specific image types.
This change adds a fairly generic mechanism for parameter passthrough
to plugins and the base builder that does not require patching the
builder and CLI each time a new class of parameter is added to Factory.
The immediate reason for doing this is to expose the Docker plugin's
ability to set custom labels, environments and commands, but it is
likely to be useful for other things in the future.
---
builder/kojid | 39 ++++++++++++++++++++++++++++++++++-----
cli/koji | 15 ++++++++++++++-
2 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/builder/kojid b/builder/kojid
index 4ea93f2..ad427cd 100755
--- a/builder/kojid
+++ b/builder/kojid
@@ -3178,6 +3178,25 @@ class BaseImageTask(OzImageTask):
raise koji.ApplianceError('Image status is %s: %s' %
(status, details))
+ def _mergeFactoryParams(self, img_opts, fixed_params):
+ """
+ Merge any KV pairs passed in via --factory-parameter CLI options
+ into an existing dictionary that will eventually be passed to
+ factory build commands. This allows a fairly generic mechanism
+ for parameter passthrough to plugins and the base builder that does
+ not require patching the builder and CLI each time.
+
+ @args:
+ img_opts - an existing dict with any pre-existing parameters
+ fixed_params - list of parameters that must not be overriden
+ @returns:
+ nothing - dict is modified in place
+ """
+ if self.opts.get('factory_parameter'):
+ for kvp in self.opts.get('factory_parameter'):
+ if kvp[0] not in fixed_params:
+ img_opts[kvp[0]] = kvp[1]
+
def _buildBase(self, template, params, wait=True):
"""
Build a base image using ImageFactory. This is a "raw" image.
@@ -3194,7 +3213,10 @@ class BaseImageTask(OzImageTask):
# may need to still upload ozlog and remove the log handler
self.logger.info('dispatching a baseimg builder')
self.logger.debug('templates: %s' % template)
- self.logger.debug('params: %s' % params)
+ self.logger.debug('pre-merge params: %s' % params)
+ # We enforce various things related to the ks file - do not allow override
+ self._mergeFactoryParams(params, [ 'install_script' ])
+ self.logger.debug('post-merge params: %s' % params)
base = self.bd.builder_for_base_image(template, parameters=params)
if wait:
base.base_thread.join()
@@ -3245,19 +3267,22 @@ class BaseImageTask(OzImageTask):
if format == 'vagrant-virtualbox':
format = 'vsphere-ova'
img_opts['vsphere_ova_format'] = 'vagrant-virtualbox'
+ fixed_params = [ 'vsphere_ova_format' ]
if format == 'vagrant-libvirt':
format = 'rhevm-ova'
img_opts['rhevm_ova_format'] = 'vagrant-libvirt'
+ fixed_params = [ 'rhevm_ova_format' ]
if format == 'vagrant-vmware-fusion':
format = 'vsphere-ova'
img_opts['vsphere_ova_format'] = 'vagrant-vmware-fusion'
# The initial disk image transform for VMWare Fusion/Workstation requires a "standard" VMDK
# not the stream oriented format used for VirtualBox or regular VMWare OVAs
img_opts['vsphere_vmdk_format'] = 'standard'
+ fixed_params = [ 'vsphere_ova_format', 'vsphere_vmdk_format' ]
targ = self._do_target_image(self.base_img.base_image.identifier,
- format.replace('-ova', ''), img_opts=img_opts)
+ format.replace('-ova', ''), img_opts=img_opts, fixed_params=fixed_params)
targ2 = self._do_target_image(targ.target_image.identifier, 'OVA',
- img_opts=img_opts)
+ img_opts=img_opts, fixed_params=fixed_params)
return {'image': targ2.target_image.data}
def _buildDocker(self, format):
@@ -3275,7 +3300,7 @@ class BaseImageTask(OzImageTask):
'docker', img_opts=img_opts)
return {'image': targ.target_image.data}
- def _do_target_image(self, base_id, image_type, img_opts={}):
+ def _do_target_image(self, base_id, image_type, img_opts={}, fixed_params=[]):
"""
A generic method for building what ImageFactory calls "target images".
These are images based on a raw disk that was built before using the
@@ -3287,6 +3312,8 @@ class BaseImageTask(OzImageTask):
uses this to figure out what plugin to run
img_opts - a dict of additional options that specific to the target
type we pass in via image_type
+ fixed_params - a list of parameter keys that should not be overriden
+ by the --factory-parameter CLI
@returns:
A Builder() object from ImageFactory that contains information
about the image building include state and progress.
@@ -3294,7 +3321,9 @@ class BaseImageTask(OzImageTask):
# TODO: test the failure case where IF itself throws an exception
# ungracefully (missing a plugin for example)
# may need to still upload ozlog and remove the log handler
- self.logger.debug('img_opts: %s' % img_opts)
+ self.logger.debug('img_opts_pre_merge: %s' % img_opts)
+ self._mergeFactoryParams(img_opts, fixed_params)
+ self.logger.debug('img_opts_post_merge: %s' % img_opts)
target = self.bd.builder_for_target_image(image_type,
image_id=base_id, template=None, parameters=img_opts)
target.target_thread.join()
diff --git a/cli/koji b/cli/koji
index 64c5356..cbfa2d0 100755
--- a/cli/koji
+++ b/cli/koji
@@ -5306,6 +5306,11 @@ def handle_image_build(options, session, args):
parser.add_option("--ova-option", action="append",
help=_("Override a value in the OVA description XML. Provide a value " +
"in a name=value format, such as 'ovf_memory_mb=6144'"))
+ parser.add_option("--factory-parameter", nargs=2, action="append",
+ help=_("Pass a parameter to Image Factory. The results are highly specific " +
+ "to the image format being created. This is a two argument parameter " +
+ "that can be specified an arbitrary number of times. For example: "
+ "--factory-parameter docker_cmd '[ \"/bin/echo Hello World\" ]'"))
parser.add_option("--release", help=_("Forcibly set the release field"))
parser.add_option("--repo", action="append",
help=_("Specify a repo that will override the repo used to install " +
@@ -5355,6 +5360,14 @@ def handle_image_build(options, session, args):
for k, v in config.items(section):
task_options.ova_option.append('%s=%s' % (k, v))
+ # as do factory-parameters
+ section = 'factory-parameters'
+ if config.has_section(section):
+ task_options.factory_parameter = [ ]
+ for k, v in config.items(section):
+ # We do this, rather than a dict, to match what argparse spits out
+ task_options.factory_parameter.append( (k, v) )
+
else:
if len(args) < 5:
parser.error(_("At least five arguments are required: a name, " +
@@ -5483,7 +5496,7 @@ def _build_image_oz(options, task_opts, session, args):
hub_opts = {}
for opt in ('ksurl', 'ksversion', 'kickstart', 'scratch', 'repo',
'release', 'skip_tag', 'specfile', 'distro', 'format',
- 'disk_size', 'ova_option'):
+ 'disk_size', 'ova_option', 'factory_parameter'):
val = getattr(task_opts, opt, None)
if val is not None:
hub_opts[opt] = val
--
2.1.0
7 years, 11 months
Koji Developer Docs
by Jay Greguske
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,
Do Koji Developer docs exist? Say I know what I'm doing with Python,
and I want to contribute patches to Koji, where do I start? I vaguely
recall someone mentioning these were written somewhere, but I cannot
find them anywhere on the Fedora wiki or the Koji roject site.
If not, I'll get started on them some time soon. A definitive 'no'
would let me get started earlier. :)
- - Jay
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
iQEcBAEBAgAGBQJWJqesAAoJEMzORChHoQ3aCfwH/A13BessGSlGJL48a6UnrMO4
sjTIlaSoJ8MOSIcSoxGBOrVbsNSva9A8KAxjXi4yofb7H5H8D5ndRzbUaJr7oYjW
EVwXNudjK5UFOwQgx79wo/s5sLPRPOqQzH2aW037WqvwMC7KfQpcTMOBXxz1GVwH
DEC5fIg2dnU8YMtoQG45JqxPSdumDfvlM0L9s80iiM4bwKqdRRQRMQvoW2tt36QY
ywZdD/HQqyl9luybK45kHvaE/L6ffyiMrvq8ipybAlYz4iUB6byy28QwUK3H8XGw
WfO18LRuN6Pm2HinDzdPGoQSbxnRAQbFm03ajpP9yPZEZc8tzD9E7CBiRvwuLvE=
=0vx/
-----END PGP SIGNATURE-----
7 years, 11 months
[PATCH] ensure qcow2 v2 compatible output regardless of local qemu-img version
by Ian McLeod
---
builder/kojid | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/builder/kojid b/builder/kojid
index 4ea93f2..6461f30 100755
--- a/builder/kojid
+++ b/builder/kojid
@@ -84,6 +84,8 @@ try:
from imgfac.PersistentImageManager import PersistentImageManager
from imgfac.BaseImage import BaseImage
from imgfac.TargetImage import TargetImage
+ # NOTE: import below requires Factory 1.1.7 or higher
+ from imgfac.FactoryUtils import qemu_convert_cmd
ozif_enabled = True
except ImportError:
pass
@@ -3318,8 +3320,18 @@ class BaseImageTask(OzImageTask):
newimg = os.path.join(self.workdir, self.imgname + '.%s' % ofmt)
cmd = ['/usr/bin/qemu-img', 'convert', '-f', 'raw', '-O',
format, self.base_img.base_image.data, newimg]
- if format in ('qcow', 'qcow2'):
+ if format == 'qcow':
cmd.insert(2, '-c') # enable compression for qcow images
+ if format == 'qcow2':
+ # qemu-img changed its default behavior at some point to generate a
+ # v3 image when the requested output format is qcow2. We don't
+ # want koji to output different formats based on the verison of
+ # qemu-img that happens to be on the builder. Here we use a function
+ # inside of Image Factory that detects qemu-img behavior and adds
+ # the correct options to ensure original "v2" compatibility
+ cmd = qemu_convert_cmd(self.base_img.base_image.data, newimg, compress=True)
+ # Factory does not use a full path - for consistency, force that here
+ cmd[0] = '/usr/bin/qemu-img'
conlog = os.path.join(self.workdir,
'qemu-img-%s-%s.log' % (format, self.arch))
log_output(self.session, cmd[0], cmd, conlog,
--
2.1.0
7 years, 12 months
mock question how do not clean BUILDROOT after build ?
by Sérgio Basto
Hi,
Mock after building and write the rpms, always execute %clean, doesn't
matter if I add --no-cleanup-after, example [1].
Have we any simple way to mock not perform %clean, at the end ?
I need it to debug the make install ...
Thanks,
[1]
Wrote: /builddir/build/RPMS/libmp4v2-debuginfo-2.1.0-0.4.trunkREV507.fc21.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.ilJSts
+ umask 022
+ cd /builddir/build/BUILD
+ cd mp4v2-trunk
+ /usr/bin/rm
-rf /builddir/build/BUILDROOT/libmp4v2-2.1.0-0.4.trunkREV507.fc21.x86_64
+ exit 0
--
Sérgio M. B.
7 years, 12 months