Dynamic partitioning in Foreman kickstart templates

May 12, 2021 

Foreman's provisioning system allows creating provisioning templates with highly dynamic content. This article describes how to create dynamic content in your Foreman provisioning templates. While the example is related to dynamic partitioning in kickstart, the basic mechanisms for setting this up applies to any kind of template.

Foreman provisioning templates are written in ERB format. This allows having logic in the template itself based on user-defined host parameters. For example the Kickstart default template consumes a bunch of host parameters that allow you to define what kind of kickstart file you want Foreman to spit out for each host or host group. To give a simple example there's the "lang" parameter which sets the value for "lang" kickstart option:

lang <%= host_param('lang') || 'en_US.UTF-8' %>

Basically when "lang" parameter is set it will be used as the value of "lang". If it is not present then "lang" will be "en_US.UTF-8".

When it comes to partitioning disks you can create the partitioning layout dynamically by running a script inside the host that is being provisioned. This can be useful if you want to create a different partitioning layout on virtualized test instances and for production instances. Dynamic disk partitioning is a built-in feature in the default Kickstart template, but it is rather obscurely explained Foreman hosts documentation. In any case, it depends on several things to work correctly. First of all, you need to load a snippet in the %pre section of the template. For example:

%pre
<%= snippet "partitioning" %>
%end

The snippet itself would have contents such as this:

#Dynamic - this line tells Foreman this is a script rather then a static layout
virtual=0

# Test if we're in VirtualBox
dmidecode | egrep -i 'VirtualBox' && virtual=1
dmesg | egrep -i 'VirtualBox' && virtual=1

if [ "$virtual" -eq 1 ]; then
    cat <<EOF > /tmp/diskpart.cfg
zerombr
clearpart --all --initlabel
part / --fstype ext4 --size 2048 --grow
EOF
else
    cat <<EOF > /tmp/diskpart.cfg
zerombr
clearpart --all --initlabel
part /boot --fstype xfs --size 500 --asprimary
part pv.01 --ondisk sda --grow --size=8192
volgroup vg0 pv.01
logvol swap --vgname=vg0 --size=2048 --name=lvswap
logvol /    --vgname=vg0 --size=2048 --name=lvroot --fstype=xfs
logvol /usr --vgname=vg0 --size=8192 --name=lvusr  --fstype=xfs
logvol /tmp --vgname=vg0 --size=4096 --name=lvtmp  --fstype=xfs
logvol /opt --vgname=vg0 --size=4096 --name=lvopt  --fstype=xfs
logvol /var --vgname=vg0 --size=1024 --name=lvvar  --fstype=xfs --grow
EOF
fi

As can be seen, the script chooses a different partitioning layout on Virtualbox and on non-Virtualbox systems. The above is an adaptation of one of the examples on Foreman Wiki.The script runs on the system being provisioned and writes the partitioning layout into local file, /tmp/diskpart.cfg. Foreman realizes it needs to load that file because of this section in the Kickstart template:

<% if @dynamic -%>
%include /tmp/diskpart.cfg
<% else -%>
<%= @host.diskLayout %>
<% end -%>

The @dynamic parameter is explained in the official documentation:

@dynamic    Returns true if the partition table being used is a %pre script
            (has the #Dynamic option as the first line of the table).

What Foreman documentation is trying to say is: "If the %pre section contents start with #Dynamic then Foreman will consider it a script and then load contents /tmp/diskpart.cfg".

Samuli Seppänen
Samuli Seppänen
Author archive
menucross-circle