PkgForge Builder Admin - Configuring mock
Author: Stephen Quinney

# PkgForge Admin - Configuring mock

The RPM builders rely on the Redhat mock build tool. This document describes the necessary configuration.

The mock tool requires access to yum enabled package repositories to satisfy the build dependencies of packages which are to be built. The instructions in this document assume that you have access to mirrors of the necessary Redhat/ScientificLinux/Fedora repositories. You will also need to regularly run the createrepo tool on your local package repositories (buckets in LCFG terminology) to generate the necessary metadata.

For building packages you will need a reasonable amount of local disk space (probably at least 20GB but it depends on the number of different chroots you use). By default the packages are built in sub-directories of `/var/lib/mock/` and the cached chroots are stored in `/var/cache/mock`. Both of these locations can be changed in the `/etc/mock/site-defaults.cfg` configuration file.

The PkgForge builders have a concept of a package bucket. Basically this is the directory into which a package will be submitted once it has been successfully built. It normally makes sense to ensure that the dependencies for packages are resolvable within certain sets of buckets. For example, we aim to ensure that packages in our publically-accessible lcfg bucket do not have dependencies that can only be resolved from our restricted-access local buckets (e.g. inf and uoe). To ensure this happens mock must have a different chroot for each package bucket on each platform and each architecture. The PkgForge builders expect to find mock chroot configurations named like: platform-bucket-architecture. This normally means configuration files named like `/etc/mock/f13-world-i386.cfg`.

Most of the configuration for a chroot is actually for yum. As an example, here are the mock configuration options for a Fedora 13 i386 chroot for the world bucket. The syntax is python so some care has to be taken to ensure you do not completely break mock when it loads the file.

    config_opts['root'] = 'f13-world-i386'
    config_opts['target_arch'] = 'i686'
    config_opts['chroot_setup_cmd'] = 'groupinstall buildsys-build'
    config_opts['dist'] = 'f13'  # only useful for --resultdir variable subst
    config_opts['resultdir'] = '/disk/scratch/mock/results/world/f13'

    # ccache not available on epel5
    config_opts['plugin_conf']['ccache_enable'] = True

The two important bits here are the resultdir and the chroot_setup_cmd options. The results directory should point to somewhere with sufficient space and should be a different directory for each platform/architecture/bucket combination to keep everything sane. The setup command is passed to yum and is what installs the initial set of build-dependencies. The buildsys-build package group contains all the essential build-dependencies which are not normally specified in a specfile.

The following is the yum configuration for the previous example:

    config_opts['yum.conf'] = """
    [main]
    cachedir=/var/cache/yum
    debuglevel=1
    logfile=/var/log/yum.log
    reposdir=/dev/null
    retries=20
    obsoletes=1
    gpgcheck=0
    assumeyes=1
    metadata_expire=60

    #repos

    [f13base]
    name=f13base
    baseurl=http://http.pkgs.inf.ed.ac.uk/sites/f13/Everything/i386/os
    enabled=1
    gpgcheck=0

    [f13updates]
    name=f13updates
    baseurl=http://http.pkgs.inf.ed.ac.uk/sites/f13/updates/i386
    enabled=1
    gpgcheck=0

    [f13world]
    name=f13world
    baseurl=http://http.pkgs.inf.ed.ac.uk/rpms/layers/world/f13
    enabled=1
    gpgcheck=0

    [f13lcfg]
    name=f13lcfg
    baseurl=http://http.pkgs.inf.ed.ac.uk/rpms/layers/lcfg/f13
    enabled=1
    gpgcheck=0

    [local]
    name=local
    baseurl=file:///disk/scratch/mock/results/world/f13
    enabled=1
    gpgcheck=0

    """

The main configuration is pretty much standard. The important bit is to ensure that the metadata_expire option is sufficiently low that yum will reload the metadata for every build. This allows builds to depend on packages generated by previous builds. After that the rest are the required yum-enabled package repositories which can be used to install build-dependencies.

Beyond that, the only other really important bit to note is the local repository. This makes it possible to use packages built using this chroot during this run as build-dependencies for subsequent builds. To do this the createrepo_on_rpms option must be set to `True` in the `site-defaults.cfg` file. This does sometimes cause problems with file permissions when it comes to the PkgForge builders cleaning out a results directory before doing a new build. To get around this issue the createrepo_command option in the `site-defaults.cfg` file should be set to `/usr/sbin/createrepo_hack`. The hack script is a pretty simple wrapper around the real `createrepo` command:

    #!/bin/bash

    dir=$1

    /usr/bin/createrepo -d -q -x '*.src.rpm' $dir
    retval=$?

    if [ "$EUID" -eq 0 ]; then
       chmod -R g+w $dir
    fi

    exit $retval

This script is normally run as root so it can fix up the group-mode on all the files and directories in the tree.

## Using LCFG

The simplest method of configuring all the mock chroot files is to use the LCFG mock component. Here is an example for SL6, see the lcfg-mock(8) manual page for full details of the available resources.

    #include <lcfg/options/mock.h>

    !mock.basedir                mSET(/disk/scratch/mock)

That sets up the defaults and the necessary PAM configuration. Only one global change is made and that is to the mock base directory so a separate partition can be used. Next is to create the full list of available repositories:

    #define MOCK_SITEPKGS_BASE http://http.pkgs.inf.ed.ac.uk/sites
    #define MOCK_PKGS_BASE     http://http.pkgs.inf.ed.ac.uk/rpms/layers
    #define MOCK_SL6_GROUPS_BASE file:///var/lib/mock/repositories/sl6/

    !mock.repositories          mADD(sl6base)
    mock.baseurl_sl6base        MOCK_SITEPKGS_BASE/sl6/6.0/i386/os

    !mock.repositories          mADD(sl6updates)
    mock.baseurl_sl6updates     MOCK_SITEPKGS_BASE/sl6/6.0/i386/updates/security

    !mock.repositories          mADD(sl6epel)
    mock.baseurl_sl6epel        MOCK_SITEPKGS_BASE/epel/6/i386

    !mock.repositories          mADD(sl6groups)
    mock.baseurl_sl6groups      MOCK_SL6_GROUPS_BASE

    !mock.repositories          mADD(sl6lcfg)
    mock.baseurl_sl6lcfg        MOCK_PKGS_BASE/lcfg/sl6

    !mock.repositories          mADD(sl6world)
    mock.baseurl_sl6world       MOCK_PKGS_BASE/world/sl6

    !mock.repositories          mADD(sl6uoe)
    mock.baseurl_sl6uoe         MOCK_PKGS_BASE/uoe/sl6

    !mock.repositories          mADD(sl6inf)
    mock.baseurl_sl6inf         MOCK_PKGS_BASE/inf/sl6

    !mock.repositories          mADD(sl6devel)
    mock.baseurl_sl6devel       MOCK_PKGS_BASE/devel/sl6

This list does not actually create any configuration files. The next step is to create the chroots, each has a list of the repository names which are to be used.

    !mock.chroots                   mADD(sl6)
    mock.chrtname_sl6               sl6-i386
    mock.basearch_sl6               i686
    mock.dist_sl6                   sl6
    mock.ccache_sl6                 no
    mock.repos_sl6                  sl6base sl6groups sl6updates local
    mock.resultdir_sl6              <%mock.basedir%>/results/sl/6/i386
    mock.baseurl_sl6_local          file://<%mock.resultdir_sl6%>

    !mock.chroots                   mADD(sl6_lcfg)
    mock.chrtname_sl6_lcfg          sl6-lcfg-i386
    mock.basearch_sl6_lcfg          i686
    mock.dist_sl6_lcfg              sl6
    mock.repos_sl6_lcfg             sl6base sl6groups sl6updates sl6epel sl6lcfg local
    mock.resultdir_sl6_lcfg         <%mock.basedir%>/results/lcfg/sl6
    mock.baseurl_sl6_lcfg_local     file://<%mock.resultdir_sl6_lcfg%>

    !mock.chroots                   mADD(sl6_world)
    mock.chrtname_sl6_world         sl6-world-i386
    mock.basearch_sl6_world         i686
    mock.dist_sl6_world             sl6
    mock.repos_sl6_world            sl6base sl6groups sl6updates sl6epel sl6world sl6lcfg local
    mock.resultdir_sl6_world        <%mock.basedir%>/results/world/sl6
    mock.baseurl_sl6_world_local    file://<%mock.resultdir_sl6_world%>

    !mock.chroots                   mADD(sl6_uoe)
    mock.chrtname_sl6_uoe           sl6-uoe-i386
    mock.basearch_sl6_uoe           i686
    mock.dist_sl6_uoe               sl6
    mock.repos_sl6_uoe              sl6base sl6groups sl6updates sl6epel sl6world sl6uoe sl6lcfg local
    mock.resultdir_sl6_uoe          <%mock.basedir%>/results/uoe/sl6
    mock.baseurl_sl6_uoe_local      file://<%mock.resultdir_sl6_uoe%>

    !mock.chroots                   mADD(sl6_inf)
    mock.chrtname_sl6_inf           sl6-inf-i386
    mock.basearch_sl6_inf           i686
    mock.dist_sl6_inf               sl6
    mock.repos_sl6_inf              sl6base sl6groups sl6updates sl6epel sl6world sl6uoe sl6inf sl6lcfg local
    mock.resultdir_sl6_inf          <%mock.basedir%>/results/inf/sl6
    mock.baseurl_sl6_inf_local      file://<%mock.resultdir_sl6_inf%>

    !mock.chroots                   mADD(sl6_devel)
    mock.chrtname_sl6_devel         sl6-devel-i386
    mock.basearch_sl6_devel         i686
    mock.dist_sl6_devel             sl6
    mock.repos_sl6_devel            sl6base sl6groups sl6updates sl6epel sl6world sl6uoe sl6inf sl6lcfg sl6devel local
    mock.resultdir_sl6_devel        <%mock.basedir%>/results/devel/sl6
    mock.baseurl_sl6_devel_local    file://<%mock.resultdir_sl6_devel%>

The component supports the overriding of repository-configuration options on a per-chroot basis. This is used to set the baseurl option for each local repository to the correct location for the chroot.