29 November 2016

the daily defect el7 from el6

by mo

We recently came across an issue where we needed to build CentOS 7 RPM’s from a CentOS 6 host.

Typically, when you’re building packages you would do it on the target os, os version and architecture. In this case, we chose not to standup new servers to be able to build an rpm for a slightly different version of an OS.

In the RPM spec file you can target the different os versions by using conditional code such as:

%if 0%{?el7}
  %define release_dist .el7
  %define example_init /usr/lib/systemd/system/example.service
  %define examplemon_init /usr/lib/systemd/system/examplemon.service
  %define exampleupdater_init /usr/lib/systemd/system/exampleupdater.service
  %define system_init_dir $RPM_BUILD_ROOT/usr/lib/systemd/system
%if 0%{?el6}
  %define release_dist .el6
  %define example_init /etc/init/example.conf
  %define examplemon_init /etc/init/examplemon.conf
  %define exampleupdater_init /etc/init/exampleupdater.conf
  %define system_init_dir $RPM_BUILD_ROOT/etc/init

The ?el7 syntax will detect that the host is an enterprise linux (CentOS) 7 host. Unfortunately, this doesn’t work well for us because we needed a way to generate a el7 installers from an el6 host.

There are a couple of ways to do this.

  1. use mock
  2. use chroot.

Using mock requires that we can create a el6 rpm then rebuild it as an el7 rpm. This would mean that both the el6 and el7 dependencies would need to be present in the rpmbuild.

chroot is probably the cleanest way to produce a valid el7 rpm, but requires quite a few things to be put into place to make it work. Also, we have multiple worker processes on each host that generates rpms concurrently, so this setup seemed quite risky.

The option we opted for was quite simple:

%if "%{?dist_no}" == "el7"
  %define el7 1
  %undefine el6

Then we include a special define parameter when shelling out to rpmbuild.

rpmbuild --define='dist_no el7' -ba ./SPECS/example.spec

Happy hacking!