3 Configuration files
There are currently three configuration files, parsed in that order: pica.conf, hosts.conf and objects.conf. All of them are placed in
the /etc/pica directory. The first is a configuration file to control
behaviour of the pica main script; the second, a description of the hosts PICA
will work on; the last, a description of the objects to process.
3.1 Basic syntax
All the configuration files share a common syntax, similar to that of the DNS
config files. Before being read, they are parsed by the Perl PreProcessor.
Generally speaking, there are properties and constants, assigned to those
properties. The properties must match the following regex:
(\w|/|\.|-)+
That is, letters, slashes, dots and hyphens, in whatever order you want. Note
that there are some reserved words, that vary between configuration
files.
On the other hand, constants come in three flavours:
-
Plain
- The same as properties.
- Single quoted constants
- Whatever you want to put between single quotes,
including (but not limited to ;-)) single quotes, as \'.
- Double quoted constants
- Whatever you want to put between double quotes,
including double quotes, as \".
Please note that the difference between single and double quotes is purely
aesthetic. Just a last note: everything is case-sensitive in every
configuration file!
3.2 The Perl PreProcessor
This PICA component is the one that reads your files first, to transform them
into what PICA will really read. In fact, is a Perl sub (well, two), not
an independent program or CPAN module or something. The idea is being able to
change (in a general and efficient way) the configuration files, depending on
variables (yes, local variables) and some other checks. All of that, using
arbitrary Perl expressions, that can not only return boolean values for
conditions, but also generate part of the configuration or distribution files.
As the preprocessor is used on every PICA configuration and
distribution file, the results become terribly dynamic. Imagine
generating a configuration file for your servers, based on the name of the
host, the name of the final file to be installed, the time of the day or some
other external file or condition! You have all the power of Perl in your
hands!
The directives recognized by PPP are:
-
#include For including external files. You can use both angle
brackets and double quotes. In the first case, the file is read from the
directory where the file was read; in the former, the file will be read from
$picainclude, usually something like /var/lib/pica/include.
- #if/#elsif/#else/#fi For conditionals, from parenthesized
arbitrary Perl conditions
- #perl/#lrep For executing completely arbitrary Perl code.
Anything returned by this code will be substituted for the original code
- <# ... #> Inline #perl/#lrep environment (for
one-liners)
To support your nifty conditions, there are sub definitions (actually,
only two, ingroup and members) and some variables ($picahost and $picaobject, only defined for objects.conf; more
on that later). Subs are defined in user.pm, a special module to
put all of that stuff, placed in the PICA directory, usually /var/lib/pica. The user is supposed to modify that file if he wants to add
a new function. The current list of defined subs is:
-
ingroup
- Takes one argument and returns true if the current
processing host (that is, picahost) belongs to the given group.
- members
- Takes one argument, and returns the list of members of
the given group, or "" if there aren't any.
To add a function, you have to write it in user.pm and add it to
the EXPORT and EXPORT_OK variables. Moreover, if you want to
access a new variable, you'll have to make a glob to see it and be able to
modify it's value. You can copy and paste the current subs and globs.
3.3 pica.conf
This configuration file defines some paths needed by PICA. It's a defaults environment with some definitions. There is one special definition,
protecteddirs, with a list of directories never to be deleted, under any
circumstances (this list is checked every time PICA is about to delete some
directory recursively). Here's a pica.conf sample file:
defaults {
picaroot = /var/lib/pica; # config files
picatmp = /var/lib/pica/tmp;
picasrc = /var/lib/pica/src; # distribution files
picainclude = /usr/lib/pica/include;
sshpath = '/usr/local/bin/ssh '; # ssh binary
diffpath = '/usr/bin/diff'; # diff binary for -f command
tarpath = '/bin/tar'; # tar binary
rsyncpath = '/usr/local/bin/rsync';
protecteddirs {
/,
/bin,
/usr/bin,
/lib,
/usr/lib,
/var/lib/pica
}
}
I hope all of this is self-explanatory.
3.4 hosts.conf
It is used to configure the hosts that should be administered using PICA. We
can organize the hosts in different, possibly overlapped, groups that can be
later used in conditions, so we could install a given file only in hosts
belonging to a given group. We can also define variables for a given host and
use them later. We also can specify different values for an object variable
depending on the group we are working on by calling the ingroup sub.
Note that every host should be ``declared'' for PICA to know about it.
It's a way to try to prevent you from shooting yourself in the foot.
A simple example of the hosts.conf file could be the following:
defaults {
vars {
## ---- User defined variables ----
docdir = '/home/httpsd/html/red';
}
}
##
## Hosts Definitions
##
host machine3;
host machine2 {
vars {
var = 'this variable sucks';
}
}
host machine1;
host machine4;
host machine5;
host machine6;
host machine7;
host machine8 {
fqdn = machine8.otherdomain.net;
}
###########################
# Host Group Definitions #
###########################
##
## Group Definitions
##
## Servers
hostgroup servers {
members { machine2, machine1, machine4, machine7, machine5, machine6 }
}
## RedHat Linux Servers
hostgroup redhat {
members {
machine2, machine1, machine4, machine5, machine6
}
}
## Debian Linux Servers
hostgroup debian {
members {
machine8
}
}
#####################
# Mail servers
#####################
## No relay
hostgroup mailmaster {
members { machine2, machine1, machine4 }
}
## Mailing lists servers
hostgroup listservers {
members { machine4 }
}
## Main domain server
hostgroup ulpgcmaster {
members { machine4 }
}
################
## DNS Servers
################
hostgroup dnsservers {
members { machine2, machine1, machine4, machine5, machine6 }
}
hostgroup dnsmaster {
members { machine5, machine6 }
}
################
## NTP Service
################
## Stratum-2
hostgroup stratum2 {
members { machine2, machine1, machine4, machine5, machine6, machine7 }
}
##
## GSM server
##
hostgroup sms {
members { machine5 }
}
################
## Misc services
################
hostgroup imapservers {
members { machine4 }
}
hostgroup popservers {
members { machine4 }
}
hostgroup simapservers {
members { machine4 }
}
hostgroup tftpservers {
members { machine4 }
}
hostgroup ftpservers {
members { machine4 }
}
#######################
## Some networks
#######################
hostgroup net1 {
members { machine2, machine4, machine7 }
}
hostgroup net2 {
members { machine1 }
}
hostgroup net3 {
members { machine5, machine6 }
}
#########################################
## Documentation hosts
#########################################
hostgroup doc {
members { machine5, machine6 }
}
Whoa! What a giant file. Well, perhaps you have noticed under all this mess
that hosts (not hostgroups) can have attributes, such as ``fqdn''. This
way we can specify host information such as the name PICA will use to
create the secure connection. The list of possible host attributes is:
-
fqdn
- As we already said, it sets the name PICA will use to connect to
the host. If we don't specify it, PICA will use the host identifier (yes,
the word after the reserved word ``host''). This attribute is useful if you
have hosts in different domains and don't want to use the FQDN for the host
definition. We can also define which user we want to connect as for a
particular machine, with the ``sshuser'' attribute.
- method
- Is the method used to copy files to the host. Its possible
values are ``ssh'' and ``tar''. It will be discused later, in page
??.
- shellcmd
- Is an attribute that specifies the complete command used to
connect to the remote host. It uses the variables $sshargs and $cmd, which
will be interpolated by the ssh arguments and the command to be executed,
respectively. It defaults to ``$sshpath \$sshargs
picasshuser@$picafqdn $cmd''.
- sshuser
- The user we will connect to the machine with. It's usually
root, but for some machines we would want to change the default.
- defpathdir
- Default path to install, for the objects with relative
``source'' attribute values and no ``path'' attribute.
One very important thing to note here is that there are some special
values in the hosts.conf defaults environment. These variables
point to important directories in the remote machines3. We would like them to change in a per-host basis, but, by now,
they are ``global''. Of course, chances are this will change sometime in the
future.
The list of special values is:
-
picaalarms
- Directory where the alarms reside. In fact,
directories with the name of the different priorities are created, and the
alarms really reside there.
- picabin
- Directory where misc binaries will be put, as scheduler.
- picalib
- Directory for collections of things.
- picaobj
- Directory for objects used by alarms, mostly.
Just one last note: it is possible to specify hostgroups in the ``members''
attribute of a hostgroup, so you can build hostgroup hierarchies. It's very
useful if you have a group like ``DNS servers'' and subgroups like ``Windows
DNS servers'' and ``Linux DNS servers'' (i.e.: perhaps you want to treat all
DNS servers at once for some things, and separately for other things).
3.5 objects.conf
This one defines all the objects that will be distributed using PICA, and
depends on the current host. In general, one can include or generate
dynamically parts of it, depending on evaluations of previously defined
variables. The variables available at this time for the PPP will be:
-
Variables defined in the hosts.conf ``defaults'' environment
- Variables defined in the objects.conf ``defaults'' environment
- Variables defined in any of the groups which the current host
belongs to
- Variables defined in the current host
The latter, of course, have preference in case of multiple definition. We also
can use the internal variable $picahost to get the name of the current
host. Because of that, the possibilities explode here: we can write entire
Perl scripts (or in other languages, as far as we call them from Perl) to
dynamically generate out configuration files on the fly, depending on defined
variables, the day of the week, or whathever condition we can imagine. And
here resides the power of PICA.
The mandatory and optional attributes for the two types of objects are:
-
Mandatory attributes
-
source
- where to read the file source from. If this is a relative
path, $picasrc is prepended.
- priority
- Determines the priority of the alarm. It also determines
where the alarm will be installed in the remote host.
($picaalarms/$priority)
- source
- where to read the alarm code from. If this is a relative
path, $picasrc is prepended.
- Additional attributes
-
uid
- uid to set in the installed file. Default: 0
- gid
- gid to set in the installed file. Default: 0
- verbatim
- If set to 1, the object will be installed without
preprocessing it. It is useful to install binary files, and files that
could include preprocessor directives that we don't want to parse.
Default: 0
- perms
- file permissions to set in the installed file. Default: 644
- path
- where to install the file in the remote host. If it isn't
specified, use the same as ``source'' attribute. This attribute is only
used in file objects.
- uses
- in the case of alarms, we can specify a uses clause with
the alarm dependencies. These dependencies are regular files, that only
will recognize the alarm as its group, not any group the alarm may belong to
(most importantly, in the case of variables and default attributes).
For any of these attributes we can define default values in the ``defaults''
environment (see example).
A simple objects.conf file could be:
## Default values
defaults {
uid = 0;
gid = 0;
perms = 644;
verbatim = 0;
vars {
globalvar1 = 'value1';
}
}
file motd {
path = '/etc/motd';
source = 'Services/Info/motd';
}
##################################
# Configuration for Service: NTP #
##################################
group NTP {
file ntp.conf {
path = '/etc/ntp.conf';
source = 'Services/NTP/ntp_conf.cfg';
}
file step-tickers {
path = '/etc/ntp/step-tickers';
source = 'Services/NTP/step-tickers.cfg';
}
##
## Documentation for this Service
##
#if (ingroup('doc'))
file README.ntp {
path = '<#$docdir#>/Services/NTP/README';
source = '<#$picasrc#>/Services/NTP/README';
}
#fi
}
##################################
# Configuration for Service: DNS #
##################################
#if (ingroup('dnsservers'))
group DNS {
file named.conf {
path = '/etc/named.conf';
source = 'Services/DNS/named_conf.cfg';
}
##
## Documentation for this Service
##
# if (ingroup('doc'))
file README.dns {
path = '<#$docdir#>/Services/DNS/README';
source = 'Services/DNS/README';
}
# fi
#fi
}
## DNS check
alarm DNSChkUrgent {
priority = 'Urgent';
source = 'alarms/DNSChk';
perms = '755';
uses {
file dnschk.conf {
source = 'alarms/conf/dnschk.conf';
path = '<#picaobj#>/conf/dnschk.conf';
}
}
}
We also have a defaults section that will be seen from any object, and
we can also define variables that will only be seen by the object they are
defined in.
Anytime PICA operates with an object, it will build a namespace containing all
the variables seen by that object in the host it is working on. Of course, the
most specific definition has precedence. That is, if we define a variable in
an object, and that object belongs to a group where the same variable is also
defined, the value used is the one given in the object definition. In addition
to these variables, we always have available $picahost and $picaobject, which hold the current host and object we are processing.
As a side note, since pica 0.3.6, files that happen to be directories are
copied recursively, but treated verbatim (that is, no preprocessing is
done on any file).