FaiTemplates

From FAIWiki
Jump to navigation Jump to search

Abstract

Template Systems are well known in Webprogramming. But they are useful for sysadmins too. In File:FaiTS-0.01.tar.gz i try to combine the class concept of fai with templates.

Example

My goal is to create a config file for a router, /etc/network/interfaces, during a fai installation. Here is, what the target file finally should look like:

goal

/target/etc/network/interfaces:

# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)

# The loopback interface
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
       address   172.16.240.1
       netmask   255.255.255.0
       network   172.16.240.0
       broadcast 172.16.240.255

auto eth1
iface eth1 inet static
        address   192.168.1.5
        netmask   255.255.255.0
        network   192.168.1.0
        broadcast 192.168.1.255

auto eth2
iface eth2 inet static
        address   212.202.236.176
        netmask   255.255.255.0
        network   212.202.236.0
        broadcast 212.202.236.255
        gateway   212.202.236.177

template

Here is how a template for this file could look like. The way i've implemented it now, template-toolkit [1] is used as template engine. And the template-files are located in a directory tree /fai/templates, similar to the /fai/files tree in fai:

/fai/templates/etc/network/interfaces/ROUTER.tt:

# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)

# The loopback interface
auto lo
iface lo inet loopback

[% FOREACH name = interfaces.keys.sort %]
[% i = interfaces.$name -%]
auto [% name %]
iface [% name %] inet static
        address   [% i.address %]
        netmask   [% i.netmask %]
       [% IF i.network   %] network   [% i.network   %] [% END %]
       [% IF i.broadcast %] broadcast [% i.broadcast %] [% END %]
       [% IF i.gateway   %] gateway   [% i.gateway   %] [% END %] 

[% END %]

Everything between the [% %] brackets ist template-toolkit syntax. In this case, a variable named interfaces contains a list of interface definitions. Each interface-definition is assigned a to a varable named i. Each instance of i contains the parameters address and netmask, some instances also contain parameters network, broadcast, gateway.

YAML

But where to get the data from, to fill in these variables? An nice format for flat files is YAML [ http://www.yaml.org ]:

/fai/class/ROUTER.yaml:

interfaces:
  eth0:
    address: 172.16.240.5
    netmask: 255.255.255.0
    network: 172.16.240.0
    broadcast: 172.16.240.255
  eth1:
    address: 192.168.1.5
    netmask: 255.255.255.0
    network: 192.168.1.0
    broadcast: 192.168.1.255

/fai/class/EXTERN.yaml:

interfaces:
  eth0:
    address: 172.16.240.1
  eth2:
    address: 212.202.236.176
    netmask: 255.255.255.0
    network: 212.202.236.0
    broadcast: 212.202.236.255
    gateway: 212.202.236.177

class based merge

Hey, what did i win so far? Didn't i have to write one config file before ( see man interfaces (5) ), and now i have to write two files ( .yml and .tt )?

Yes, but now you're more flexible: only .yml-files that belog two your install client's class are choosen. Data in these files is aggregated / merged together. Than, again respecting fai classes, template files are choosen, where this data is filled in.

And .yml files are only the first data-source implemented. Other alternatives are an LDAP-directory, a database or the scripts called in task_class or task_configure. Each backend adding more data.

And of course I'm not limited to only fill one template with this data. I could create a template /templates/etc/udev/rules.d/30-net_persistent_names.rules/ROUTER.tt, and /templates/etc/hosts/ROUTER.tt, and so on.

Cool. Is this already implemented?

yes. i've coded a proof of concept using Template-Toolkit, YAML and Hash::Merge.

using it

File:FaiTS-0.01.tar.gz it and type:

aptitude install libclone-perl libyaml-perl libtemplate-perl
tar xzf FaiTS-0.01.tar.gz
cd FaiTS-0.01/
perl Makefile.PL
make test

If you get lots of errors and a final "All tests successful" then the code should work ...

To see something happen, you can set CLEANUP to 0 in line 27 of the file t/FaiTS.t and then run

make test 

again

If you then type

find -ls

and you'll see the .yml' (YAML) files with config data, .tt ( Template-Toolkit) templates and a target directory with a freshly created etc/network/interfaces file.

development

There are two "executables" in this package:

bin/fai-ts.pl

and

t/FaiTS.t

First i started only with bin/fai-ts.pl. But i don't like skripts getting to long, so i tried to source out as much functions as possible to a perl module lib/FaiTS.pm. For every subroutine in lib/FaiTS.pm there is a test in t/FaiTS.t. This is to further document the module, and to make sure that future changes to lib/FaiTS.pm don't break things.

Dokumentation is contained in the source as POD and accessable via perldoc:

perldoc lib/FaiTS.pm
perldoc bin/fai-ts.pl