Warning
TCheetah is deprecated. You should instead use Cheetah Templates in the Cfg plugin.
This document reflects the TCheetah plugin.
The TCheetah plugin allows you to use the cheetah templating system to create files, instead of the various diff-based methods offered by the Cfg plugin. It also allows you to include the results of probes executed on the client in the created files.
To begin, you will need to download and install the Cheetah templating engine from http://www.cheetahtemplate.org/. Once it is installed, you can enable it by adding TCheetah to the plugins line in /etc/bcfg2.conf on your Bcfg server. For example:
plugins = Base,Bundler,Cfg,...,TCheetah
The TCheetah plugin makes use of a Cfg-like directory structure located in in a TCheetah subdirectory of your repository, usually /var/lib/bcfg2/TCheetah. Each file has a directory containing two files, template and info. The template is a standard Cheetah template with two additions:
The info file is formatted like :info files from Cfg.
Mostly, people will want to use client metadata.
File permissions for entries handled by TCheetah are controlled via the use of info.xml files. Note that you cannot use both a Permissions entry and a Path entry to handle the same file.
self.metadata is an instance of the class ClientMetadata and documented here.
Note
If you want to use Properties, you will need to enable the Properties plugin in /etc/bcfg2.conf.
Properties.xdata is a python ElementTree object, loaded from the data in /var/lib/bcfg2/Properties/<properties file>.xml. That file should have a Properties node at its root.
Example Properties/example.xml:
<Properties>
<host>
<www.example.com>
<rootdev>/dev/sda</rootdev>
</www.example.com>
</host>
</Properties>
You may use any of the ElementTree methods to access data in your template. Several examples follow, each producing an identical result on the host ‘www.example.com’:
$self.metadata.Properties['example.xml'].xdata.find('host').find('www.example.com').find('rootdev').text
$self.metadata.Properties['example.xml'].xdata.find('host').find($self.metadata.hostname).find('rootdev').text
${self.metadata.Properties['example.xml'].xdata.xpath('host/www.example.com/rootdev')[0].text}
${self.metadata.Properties['example.xml'].xdata.xpath('host/' + self.metadata.hostname + '/rootdev')[0].text}
#set $path = 'host/' + $self.metadata.hostname + '/rootdev'
${self.metadata.Properties['example.xml'].xdata.xpath($path)[0].text}
${self.metadata.Properties['example.xml'].xdata.xpath(path)[0].text}
TCheetah works similar to Cfg in that you define all literal information about a particular file in a directory rooted at TCheetah/path_to_file. The actual file contents are placed in a file named template in that directory. Below is a simple example a file /foo.
/var/lib/bcfg2/TCheetah/foo/template
> buildfile /foo <clientname>
Hostname is $self.metadata.hostname
Filename is $Template.searchList(self)[1]['path']
Template is $Template.searchList(self)[1]['source_path']
Groups:
#for $group in $self.metadata.groups:
* $group
#end for
Categories:
#for $category in $self.metadata.categories:
* $category -- $self.metadata.categories[$category]
#end for
Probes:
#for $probe in $self.metadata.Probes:
* $probe -- $self.metadata.Probes[$probe]
#end for
/var/lib/bcfg2/TCheetah/foo/info
mode: 624
The following output can be generated with bcfg2-info. Note that probe information is not persistent, hence, it only works when clients directly query the server. For this reason, bcfg2-info output doesn’t reflect current client probe state.
<Path type="file" name="/foo" owner="root" mode="0624" group="root">
Hostname is topaz.mcs.anl.gov
Filename is /foo
Template is /var/lib/bcfg2/TCheetah/foo/template
Groups:
* desktop
* mcs-base
* ypbound
* workstation
* xserver
* debian-sarge
* debian
* a
Categories:
* test -- a
Probes:
</Path>
In many cases you can use the TCheetah plugin to avoid writing custom plugins in Python. This example randomizes the time of cron.daily execution with a stable result. Cron.daily is run at a consistent, randomized time between midnight and 7am.:
#import random
#silent random.seed($self.metadata.hostname)
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab`
# command to install the new version when you edit this file.
# This file also has a username field, that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin://bin
# m h dom mon dow user command
17 * * * * root run-parts --report /etc/cron.hourly
$random.randrange(0,59) $random.randrange(0,6) * * * root test -x /usr/sbin/anacron || run-parts --report /etc/cron.daily
47 6 * * 7 root test -x /usr/sbin/anacron || run-parts --report /etc/cron.weekly
52 6 1 * * root test -x /usr/sbin/anacron || run-parts --report /etc/cron.monthly.
Note
Comments and Cheetah As Cheetah processes your templates it will consider hash “#” style comments to be actual comments in the template and will strip them from the final config file. If you would like to preserve the comment in the final config file you need to escape the hash character ‘#’ which will tell Cheetah (and Python) that you do in fact want the comment to appear in the final config file.:
# This is a comment in my template which will be stripped when it's processed through Cheetah
\# This comment will appear in the generated config file.