Building a custom CentOS 7 kickstart disc, part 2

Note: this series of articles applies to CentOS 7; for CentOS 6, see this series.

Once you’ve decided which packages you’re going to include in your kickstart disc, it’s time to pull them all together.

Which RPMs do you need? Assuming that you are including at least the @core and @base package groups (and you should), you’ll need the RPMs for all the packages in those groups.

One way to obtain the list of RPMs you need is to look in the file comps.xml for the core and base groups. You will see XML like this:

At a bare minimum, you will want all the required packages from within the core group. I also like to install the base group. Look for <packagereq type="mandatory"> and <packagereq type="default"> entries within the <group> tags. This tells you which packages to get. These package names correspond to the names of the RPM files.

To make this easier, I have built a script to parse the comps.xml file and gather all the non-optional packages for the base and core package groups. Download gather_packages.pl and save it in your ~/kickstart_build/utils directory.

Before you can run gather_packages.pl, you’ll need to install some perl libraries. All I wanted to use was XML::Simple, but that set off a chain of dependencies. Use the rpm command below to install all the dependencies.

Note that I started with the minimal install; your system may start with a different set of packages installed, so you may get messages indicating that one or more of these packages is already installed (or you might get errors about additional dependencies that you don’t have installed that I did happen to have installed). These should be fairly easily resolved.

Once you have the prerequisites installed, run the script this way:

By default, gather_packages.pl will gather all the packages for the base and core package groups. You can specify more on the command line. For example, for my system, I do this:

Add your own RPMs

If you want to add any RPMs not included in the base and core groups (for example, httpd, php, or mysql), copy those into the ~/kickstart_build/isolinux/Packages directory at this time.

Resolve dependencies

Now we have all the base and core RPMs in our ~/kickstart_build/isolinux/Packages directory, along with any other RPMs you’ve added, but many are missing their dependencies. So the next step is to track down all the dependencies of these packages and throw those into the directory, too. You can use another script, resolve_deps.pl, to perform this step.

Testing dependencies

Once you’ve got a set of RPMs ready, you’ll need to test the dependencies of the RPMs. Each RPM may require that other RPMs be installed in order for it to be installed. If each RPM’s dependencies are included in the set of RPMs, then all the dependencies are resolved. The objective is to have a set of RPMs that have no unresolved dependencies.

To test the dependencies in your set of RPMs, run these commands:

If you find you have unresolved dependencies (and you will almost certainly have some), you can do one of two things:

  • remove the RPM with the unresolved dependencies (a good idea if the RPM is going to set off a chain of dependencies that you don’t want, for example X Windows on a server class installation)
  • track down the RPMs to fulfill the dependency

Here, again, you need a little bit of savvy to determine which packages should be removed. In general, if the package is one that you explicitly added to the base and core groups, then you’ll probably want to find the dependencies and include them. If it’s an RPM that you don’t really want (one that got matched by the wildcard, for example), you might decide to eliminate that RPM.

Resolving dependencies

The resolve_deps.pl script will get most dependencies automatically. But not always.

Some RPMs report their dependencies in strange ways. For example, usbutils reports a dependency on /usr/bin/pkg-config. But not a single package in the distribution reports that it provides /usr/bin/pkg-config.

/usr/bin/pkg-config is contained within the pkgconfig RPM. But the RPM reports that it provides the following:

Note that rpm does not report that the package provides “/usr/bin/pkg-config“. My script isn’t smart enough to know that pkgconfig(pkg-config) means that the binary /usr/bin/pkg-config gets installed. So the dependency goes unmatched.

There are a few packages in the base and core groups that do this, but not too many, thankfully. After running resolve_deps.pl, I got these failed dependencies when I tested the repo:

So through some sleuthing, I determined that I needed these files:

Depending on which package groups you specified to gather_packages.pl, you may have additional situations like this that require more investigation. If you’ve brought in RPMs from other repos, or you’ve included your own compiled RPMs, the situation could be even more complicated, but if you are doing this, hopefully you know how to deal with it.

When resolve_deps.pl runs, it creates a file /tmp/providers.txt that lists every RPM and the capabilities provided by each. It might help you match up some of these non-obvious dependencies.

If you have installed CentOS 7 to another system with a lot of RPMs installed, you can use the rpm -q --whatprovides query on that system to try to track it down.

When all else fails, try googling for “rpm /path/to/file/in/question”; sometimes you can figure it out that way.

This is an iterative process. Every time you add a new RPM to the directory, you need to test the dependencies. Be prepared to spend a while chasing down these dependencies to build a fine-tuned collection of RPMs with no unresolved dependencies.

“Hidden” dependencies

One would hope that the resulting collection of RPMs would be complete, providing all dependencies. However, it seems that anaconda can’t complete the installation without some additional packages:

  • authconfig (@base)
  • chrony (@base)
  • firewalld (@base)
  • grub2 (@anaconda-tools)

(the containing package group for each package is listed in parens)

If you’re using gather_packages.pl, these should not be a problem; gather_packages.pl always includes the @base package group. It also includes grub2 specifically because of this problem.

Next steps

The next step is to build your disk image. I will cover that in the next installment.

Part 1 • Part 2 • Part 3Part 4

13 thoughts on “Building a custom CentOS 7 kickstart disc, part 2

  1. Hi
    I used that as a base to build a CentOS 6 kickstart ISO, (well the CentOS 6 version). Unfortunately, for CentOS7, I am left with an un-bootable system. I discovered the vmlinuz is not installed and the initrd images are missing from the resulting system.
    There seems to be a few file that are quietly now installed….
    I am experimenting – happy to work through with it get to a bootable result.
    First, I will read the pages again…. 😉
    Thank you for you help

    Regards
    buggy

    1. hi Buggycode,
      Did you notice that there were 2 way to gather all the packages for the base and core package groups. Choosing the 2nd way to gather all the packages, you will resolve such a problem you encountered : )

  2. buggycode

    I am having a similar issue with my kickstart script. got everything working, installing looking good.

    But when I reboot after install the boot loader won’t load and if I hit alt tab over to see the log during the install I get the following:

    WARN anaconda: no kernel was installed — boot loader config unchanged.

    doing this with Centos 7

    Can anyone give me a hint as to what the issue is?

    Barry McCormick

    1. hi Barry McCormick,
      The first time i build the custom iso and then finished installation, i found the same question like you mentioned! But…
      Did you notice that there were 2 way to gather all the packages for the base and core package groups. Choosing the 2nd way to gather all the packages, you will resolve such a problem you encountered : )
      If that still does not work, copy all the packages from DVD or minimal-version from iso which definitely can resolve your packages dependencies problem. And it definitely works!

  3. Thanks for this really helpful blog! I was really battling without it.

    I found it best to get rid of the inst.stage2=hd:LABEL in isolinux.cfg:

    sed -i ‘s/inst.stage2=hd:LABEL=CentOS\\x207\\x20x86_64/inst.ks=cdrom:\/dev\/cdrom:\/ks\/ks.cfg/’ ~/kickstart_build/isolinux/isolinux.cfg

    1. Thank you for your comment as it helped me. With my setup I am appending the following kernel parameters: inst.ks=http://… and inst.repo=http://… and it just kept getting stuck with “no suitable images” after trying to remount /dev/sr0 (I didn’t want to access any packages or whatnot on /dev/sr0 but over the network).

      Removing the inst.stage2 parameter solved that error for me.

  4. hi
    when i run this command ~/kickstart_build/utils/gather_packages.pl ~/kickstart_build/comps.xml \ ~/kickstart_build/all_rpms ~/kickstart_build/isolinux/Packages x86_64
    show this lines for me

    RPM source path ‘ ‘ does not exist

    parse_comps.pl comps_file rpm_src_path arch [xtra_grps_and_pkgs]

    comps_file the full path to the comps.xml file (as provided
    in the original distro

    rpm_src_path the full path to the directory of all RPMs from
    the distro

    rpm_dst_path the full path to the directory where you want
    to save the RPMs for your kickstart

    arch the target system architecture (e.g. x86_64)

    xtra_grps_and_pkgs a list of extra groups and packages, separated by spaces

    1. Something isn’t right here. Either you didn’t really type the command the way you presented it here, or your gather_packages.pl is corrupt somehow.

      You’re going to have to look at the code for gather_packages.pl and probably add some print statements to it so you can see what is inside the @ARGV array, specifically the value for $rpm_src_path.

      If the script is intact, and you really typed the command the way you pasted it here, it should not have output an empty string for $rpm_src_path.

  5. Hi,

    I’m having an issue as well, which may be related to what people describe here.
    When I issue the command gather_packages.pl /tar/no-lang.comps.xml /mnt/Packages /tar/kickstart_build/isolinux/Packages x86_64
    where /mnt/Packages is the mounted CentOS7 DVD, and /tar/kickstart_build/isolinux/Packages is the _empty_ directory where the rpms need to go, I get two errors.

    First, I get an error that rm goes wrong because the dir is empty. More of a warning, I guess.

    Second, and more importantly, the script aborts, saying :
    Not an ARRAY reference at ./gather_packages.pl line 47.

    which is: foreach $group (@{$comps->{group}})

    Please advise.

    Thanks,
    Hans

  6. I replaced line 38 with the above and now it runs but none of the rpms from core or base get copied, only the additional packages added at the end of the list.

  7. OK after changing line 38 I had to change the following lines as well

    line 49
    $id = $group->{id};
    with
    $id = $group->{id}[0];

    line 56
    $packagelist = $group->{packagelist};
    with
    $packagelist = $group->{packagelist}[0];

Leave a Reply

Your email address will not be published. Required fields are marked *