La problématique sur des architectures dont le nombre de serveurs croît, est que cela ralentit notablement les taches d'administration:
L'intéret de cfengine est de centraliser les efforts de configuration et de maintenance des packages, d'automatiser la distribution de ces fichiers sur toute la plate-forme, enfin de vérifier quotidiennement ou ponctuellement que la plate-forme est dans un état nominal.
Cfagent comprend la syntaxe de cfagent.conf, son fichier de configuration principal. Dans cfagent.conf, l'intégrateur aura accès à un système de variables, de classes et d'actions qui lui permettront de définir quel est l'état parfait d'un serveur. Ensuite, selon la volonté de l'intégrateur, cfagent:
Il faut toujours garder en tête qu'un serveur cfengine est capable de modifier n'importe quel fichier dans une multitude de serveurs. Autant dire qu'un bon serveur cfengine a la main sur toute une plateforme (d'où un raccourci vers Skynet, le célèbre logiciel qui prit en main le système de défense Américain avant d'envoyer des bombes nucléaires vers les russes). Cela a deux conséquences importantes:
Sera lancé sur les serveurs de production. C'est lui qui, d'après un fichier de configuration descriptif, fera en sorte que le serveur tende vers un état parfait.
Cfservd a pour principal but de recevoir des requetes venant de cfagent, et de lui répondre si cfagent en a le droit. Il est possible de crypter cette partie de la communication. Les requetes usuelles sont:
Cfrun peut aussi envoyer des requetes vers cfservd, mais cette fois-ci uniquement pour demander à ce que cfagent soit lancé sur la machine sur laquelle tourne cfservd. Cela permettra donc de lancer en une ligne de commande cfagent sur plusieurs serveurs distants (sur lesquels cfservd doit tourner)
La configuration de cfagent représente 95 % du travail du Cf-ingénieur.
Update.conf est le premier fichier de configuration lu par cfagent. Il définit la manière dont cfagent doit récupérer son fichier de configuration principal, cfagent.conf. C'est le seul fichier qui ne puisse ou ne doive pas etre transmis automatiquement entre cfagent et cfservd. Cela garanti que cfagent pourra toujours communiquer avec cfservd.
C'est le fichier dans lequel l'administrateur peut décrire l'état parfait d'une machine. Il doit toujours commencer par l'action « control ». Il peut inclure d'autres fichiers de configuration grace à l'action « import ». Les fichiers de configuration importés pourront contenir les memes actions, leur contenu sera alors concaténé avec celui de cfagent.conf.
Commençons tout de suite avec un exemple:
copy: solaris:: /etc/inet/hosts dest=/var/backup/hosts
« copy: » est une action. Comme son nom l'indique, elle demande à cfengine de copier des fichiers. « solaris » est une classe. Elle définit une condition d'action. Les “::” après “solaris” veulent dire “SI la classe est définie, ALORS …” . « /etc/inet/hosts » est le fichier source de copie et /var/backup/hosts est le fichier destination. On dit que « dest= » est un mot clé de « copy ». Donc dans ce cas précis, si la classe « solaris » est définie, cfagent copiera /etc/inet/hosts dans /var/backup.
Il existe un grand nombre d'actions disponibles pour cfagent. Les plus utilisées sont les suivantes:
La grande liste d'actions disponibles permet de configurer l'ensemble du système.
La variable spéciale « actionsequence » définit quelles actions seront lancées et dans quel ordre. Par exemple:
control: actionsequence = ( links shellcommands copy )
Ici, seules les actions « links », « shellcommands », puis « copy » seront interprétées par cfagent. Si plus tard dans la configuration vous avez définit une autre action, « directories » par exemple, elle ne sera pas prise en compte.
NOTE: Les actions « control » et « alerts » sont automatiquement ajoutées à l'actionsequence par cfagent.
On peut accéder au contenu d'une variable n'importe où dans la configuration. La manière de le faire est la suivante:
${nom_de_variable}
Vous pouvez aussi ne pas utiliser les accolades, mais je vous le déconseille, car elles seraient mal interprétées lors des appels de vos commandes shell.
Il existe deux types de variable:
On définit une variable de la façon suivante:
control: site = ( production )
ATTENTION respectez scrupuleusement les espaces avant et après les parenthèses !
On peut utiliser des fonctions cfengine pour initialiser les variables. Voir Setting-variables-with-functions pour la liste complète des fonctions utilisables.
ExecShellResult est la fonction la plus utilisée, et elle comporte quelques pièges.
Exemple d'utilisation de ““ExecShellResult””:
control: admin_ip = ( ExecShellResult(/usr/bin/grep -- -adm /etc/hosts | awk ${quote}{print $1}${quote}) )
Les classes sont des conditions. Leur définition permet de controler ce qui sera fait par la suite. On peut définir une classe de différente manière:
prompt> /opt/cfengine/bin/cfagent -p -v | grep Defined Defined Classes = ( 192_168_180 192_168_180_14 192_168_180_5 32_bit August Day24 Hr17 Hr17_Q1 Min05 Min05_10 Q1 SUNW_UltraAX_i2 Wednesday Yr2005 any cfengine_2 cfengine_2_1 cfengine_2_1_14 compiled_on_solaris2_8 ipv4_192 ipv4_192_168 ipv4_192_168_180 ipv4_192_168_180_14 ipv4_192_168_180_5 loghost mom monitor net_iface_eri1 net_iface_eri1_1 net_iface_lo0 solaris sparc sun4u sunos_5_8 sunos_sun4u sunos_sun4u_5_8 sunos_sun4u_5_8_Generic_117000_03 )
groups: radius = ( Strcmp(${hostgroup},"radius") )
Ici, la classe « radius » sera définie si la variable ${hostgroup} est égale à « radius ». Comme avec les variables, il existe des fonctions cfengine qui permettent de définir les classes. La liste complète de ces fonctions.
packages: SUNWradius version=4.0.4 define=hasRadius elsedefine=needRadius
Dans cet exemple, si le package SUNWradius n'est pas installé ou n'a pas la version 4.0.4, la classe « needRadius » est définie. Si le package est bien installé et a la bonne version, la classe « hasRadius » est définie. Une fois cette étape passée, on pourra par exemple lancer dans la partie “shellcommands” l'installation/l'upgrade du package si needRadius est définie. Le nom d'une classe ne peut contenir ni des points (“.”) ni des tirets (“-”), qui sont remplacés par des underscores (« _ »). Les classes « utilisateur » doivent etre préalablement déclarées dans la variable spéciale « ““AddInstallable”” »:
control: AddInstallable = ( hasRadius needRadius )