<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>en.credativ blog: Category Howto</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/" />
    <link rel="self" type="application/atom+xml" href="http://blog.credativ.com/en/atom.xml" />
    <id>tag:blog.credativ.com,2010-03-05:/en//2</id>
    <updated>2010-07-23T11:09:59Z</updated>
    <subtitle>All about Linux and Open Source</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.34-en</generator>

<entry>
    <title>[Howto] Debian preseed with Netboot</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/2010/07/howto-debian-preseed-with-netboot.html" />
    <id>tag:blog.credativ.com,2010:/en//2.172</id>

    <published>2010-07-23T11:00:00Z</published>
    <updated>2010-07-23T11:09:59Z</updated>

    <summary>The vast majority of Debian installations are simplified with the use of Preseeding and Netboot. Friedrich Weber, a school student on a work experience placement with us at our German office has observed the process and captured it in a...</summary>
    <author>
        <name>Irenie White</name>
        <uri>http://www.credativ.co.uk</uri>
    </author>
    
        <category term="Debian" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="credativ" label="credativ" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="debian" label="Debian" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="howto" label="howto" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="linux" label="Linux" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="preseed" label="preseed" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.credativ.com/en/">
        <![CDATA[<p><img alt="debianlogo.png" src="http://blog.credativ.com/de/static/debianlogo.png" width="60" height="73" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>The vast majority of Debian installations are simplified with the use of Preseeding and Netboot. Friedrich Weber, a school student on a work experience placement with us at our German office has observed the process and captured it in a Howto here:</em></p>

<p>Imagine the following situation: you find yourself with ten to twenty brand new Notebooks and the opportunity to install them with Debian and customise to your own taste. In any case it would be great fun to manually perform the Debian installation and configuration on each Notebook. This is where <a href="http://d-i.alioth.debian.org/manual/en.i386/apb.html">Debian Preseed</a> comes into play.</p>

<p>The concept is simple and self-explanatory; usually, whoever is doing the installation will be faced with a number of issues during the process (e.g. language, partitioning, packages, Bootloader, etc.) In terms of Preseed, all of these issues can now be resolved. Only those which are not already accounted for in Preseed remain for the Debian installer.  In the ideal situation these would become apparent at the outset of the installation, where the solution would differ depending on the target system and which the administrator must deal with manually - only when these have been dealt with can the installation be left to run unattended. </p>

<p>Preseed functions on some simple inbuilt configuration data: <tt>preseed.cfg</tt>. It includes, as detailed above, the questions which must be answered during installation, and in <a href="http://en.wikipedia.org/wiki/Debconf_(software_package)">debconf</a>-format. Data such as this consists of several rows, each row of which defines a debconf configuration option - a response to a question - for example:<br />
 </p>
<pre class='brush: text'>
    d-i debian-installer/local	string de_DE.UTF-8
</pre><p></p>

<p>The first element of these lines is the name of the package, which is configured (d-i is here an abbreviation of debian installer), the second element is the name of the option, which is set, as the third element of the type of option (a string) and the rest is the value of the option. In this example, we set the language to German using UTF-8-coding.</p>

<p>You can put lines like this together yourself, even simpler with the tool <tt>debconf-get-selections</tt>: these commands provide straight forward and simple options, which can be set locally.  From the selection you can choose your desired settings, adjusted if necessary and copied into <tt>preseed.cfg</tt>.</p>

<p>Here is an example of <tt>preseed.cfg</tt>:<br />
</p>
<pre class='brush: text'>
    d-i debian-installer/locale string de_DE.UTF-8
    d-i debian-installer/keymap select de-latin1
    d-i console-keymaps-at/keymap select de
    d-i languagechooser/language-name-fb select German
    d-i countrychooser/country-name select Germany
    d-i console-setup/layoutcode string de_DE

    d-i clock-setup/utc boolean true
    d-i time/zone string Europe/Berlin
    d-i clock-setup/ntp boolean true
    d-i clock-setup/ntp-server string ntp1

    tasksel tasksel/first multiselect standard, desktop, gnome-desktop, laptop
    d-i pkgsel/include string openssh-client vim less rsync
</pre><p></p>

<p>In addition to language and timezone settings, selected tasks and packages are also set with these options.  If left competely unattended, the installation will not complete, but will make a good start.</p>

<p>Now onto the question of where Preseed pulls its data from. It is in fact possible to use Preseed with CD and DVD images or USB sticks, but generally more comfortable to use a Debian Netboot Image, essentially an installer, which is started across the network and which can cover its Preseed configuration. This boot across the network is implemented with <a href="http://wikipedia.org/wiki/Preboot_Execution_Environment">PXE</a> and requires a system that can boot from a network card.</p>

<p>Next,  the system depends on booting from the network card. It travels from a DHCO server to an IP address per broadcast. This DHCP server transmits not only a suitable IP, but also to the IP of a so-called Bootserver. A Bootserver is a <a href="http://wikipedia.org/wiki/Trivial_File_Transfer_Protocol">TFTP-Server</a>, which provides a Bootloader to assist the Administrator with the desired Debian Installer. At the same time the Debian Installer can be shared with the Boot options that Preseed should use and where he can find the Preseed configuration. Here is a snippet of the PXELINUX configuration data <tt>pxelinux.cfg/default</tt>:<br />
</p>
<pre class='brush: text'>
    label i386
        kernel debian-installer/i386/linux
        append vga=normal initrd=debian-installer/i386/initrd.gz netcfg/choose_interface=eth0 domain=example.com locale=de_DE debian-installer/country=DE debian-installer/language=de debian-installer/keymap=de-latin1-nodeadkeys console-keymaps-at/keymap=de-latin1-nodeadkeys auto-install/enable=false preseed/url=http://$server/preseed.cfg DEBCONF_DEBUG=5 -- quiet 
</pre><p></p>

<p>When the user types <tt>i386</tt>, the tt>debian-installer/i386/linux</tt> kernel (found on the TFTP server) is downloaded and run. This is in addition to a whole load of bootoptions given along the way. The debian installer allows the provision of debconf options as boot parameters. It is good practice for the installer to somehow communicate where to find the Preseed communication on the network (<tt>preseed/url</tt>). In order to download this Preseed configuration, it must also be somehow built into the network.  </p>

<p>The options for that will be handed over (the options for the hostnames would be deliberately omitted here, as every target system has its own Hostname). <tt>auto-install/enable</tt> would delay the language set up so that it is only enabled after the network configuration, in order that these installations are read through <tt>preseed.cfg</tt>. It is not necessary as the language set up will also be handed over to the kernel options to ensure that the network configuration is German.</p>

<p>The examples and configuration excerpts mentioned here are obviously summarised and shortened. Even so, this blog post should have given you a glimpse into the concept of Preseed in connection with netboot. Finally, here is a complete version of <tt>preseed.cfg</tt>:<br />
</p>
<pre class='brush: text'>
    d-i debian-installer/locale string de_DE.UTF-8
    d-i debian-installer/keymap select de-latin1
    d-i console-keymaps-at/keymap select de
    d-i languagechooser/language-name-fb select German
    d-i countrychooser/country-name select Germany
    d-i console-setup/layoutcode string de_DE

    # Network
    d-i netcfg/choose_interface select auto
    d-i netcfg/get_hostname string debian
    d-i netcfg/get_domain string example.com

    # Package mirror
    d-i mirror/protocol string http
    d-i mirror/country string manual
    d-i mirror/http/hostname string debian.example.com
    d-i mirror/http/directory string /debian
    d-i mirror/http/proxy string
    d-i mirror/suite string lenny

    # Timezone
    d-i clock-setup/utc boolean true
    d-i time/zone string Europe/Berlin
    d-i clock-setup/ntp boolean true
    d-i clock-setup/ntp-server string ntp.example.com

    # Root-Account
    d-i passwd/make-user boolean false
    d-i passwd/root-password password secretpassword
    d-i passwd/root-password-again password secretpassword

    # Further APT-Options
    d-i apt-setup/non-free boolean false
    d-i apt-setup/contrib boolean false
    d-i apt-setup/security-updates boolean true

    d-i apt-setup/local0/source boolean false
    d-i apt-setup/local1/source boolean false
    d-i apt-setup/local2/source boolean false

    # Tasks
    tasksel tasksel/first multiselect standard, desktop
    d-i pkgsel/include string openssh-client vim less rsync
    d-i pkgsel/upgrade select safe-upgrade

    # Popularity-Contest
    popularity-contest popularity-contest/participate boolean true

    # Command to be followed after the installation. `in-target` means that 
         the following
    # Command is followed in the installed environment, rather than in 
        the installation environment.
    # Here http://$server/skript.sh nach /tmp is downloaded, enabled and 
        implemented.
    d-i preseed/late_command string in-target wget -P /tmp/ http://$server/skript.sh; 
  in-target chmod +x /tmp/skript.sh; in-target /tmp/skript.sh
</pre><p></p>

<p>All Howtos of this blog are grouped together in the <a href="/en/howto/">Howto category</a> - and if you happen to be looking for <a href="http://www.credativ.co.uk/services/support/projects/linux-distributions/debian-gnulinux/">Support and Services for Debian</a> you've come to the right place at credativ.</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Code templates in vim</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/2010/06/howto-code-templates-in-vim.html" />
    <id>tag:blog.credativ.com,2010:/en//2.145</id>

    <published>2010-06-07T09:25:00Z</published>
    <updated>2010-06-07T09:19:36Z</updated>

    <summary>The text editor vim offers several tools for automation. This howto describes a way to auto-include text modules when creating new files. Often during programming or administration you need the same text modules again and again. The editor vim is...</summary>
    <author>
        <name>Martin Zobel-Helas</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="automation" label="automation" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="howto" label="howto" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="linux" label="Linux" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="vim" label="vim" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.credativ.com/en/">
        <![CDATA[<p><img alt="bash.png" src="/de/static/bash.png" width="90" height="72" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>The text editor <tt>vim</tt> offers several tools for automation. This howto describes a way to auto-include text modules when creating new files.</em></p>

<p>Often during programming or administration you need the same text modules again and again. The editor <tt>vim</tt> is very helpful here, as it can detect a file type while it is being created and insert pre-defined text modules accordingly. This behaviour can be configured in the file <tt>.vim/plugin/autoinsert.vim</tt>, for example with:<br />
</p>
<pre class='brush: plain'>
if has(&quot;autocmd&quot;)
augroup autoinsert
  au!
  autocmd BufNewFile *.c call s:Template(&quot;c&quot;)
  autocmd BufNewFile Makefile call s:Template(&quot;make&quot;)
  autocmd BufNewFile makefile call s:Template(&quot;make-simple&quot;)
augroup END
endif

function s:Template(argument)
        if (a:argument == &quot;help&quot;)
                echo &quot;Currently available templates:&quot;
                echo &quot; c                - Plain C Template&quot;
                echo &quot; make             - Makefile Template&quot;
                echo &quot; make-simple      - Simple Variant of the Makefile Template&quot;
        else
                &quot; First delete all in the current buffer
                %d

                &quot; The Makefile variants
                if (a:argument == &quot;make&quot;)
                        0r ~/.vim/skeletons/template.make
                        set ft=make
                elseif (a:argument == &quot;make-simple&quot;)
                        0r ~/.vim/skeletons/template.make_simple
                        set ft=make
                elseif (a:argument == &quot;make-simple-cpp&quot;)
                        0r ~/.vim/skeletons/template.make_simple_cpp
                        set ft=make

                &quot; Stuff for plain C
                elseif (a:argument == &quot;c&quot;)
                        0r ~/.vim/skeletons/template.c
                        set ft=c
                endif

                silent %!~/.vim/do_header %
        endif
endfunction

command! -nargs=1 Template call s:Template(&lt;f-args&gt;)
</pre><p></p>

<p>The lines 21-35 clearly show the template names and include the text modules. The template for <tt>make_simple</tt>, <tt>~/.vim/skeletons/template.make_simple</tt>, for example includes the compiler flags for building C/C++ programs with gcc:</p>
<pre class='brush: plain'>
CC := gcc
CFLAGS := -Wall -pedantic -O3
LDFLAGS :=

PROG := main
OBJS := main.o

all: $(PROG)

$(PROG): $(OBJS)
        $(CC) $(LDFLAGS) -o $@ $^

clean:
        rm -rf $(PROG) $(OBJS)

.PHONY: all clean
</pre><p></p>

<p>Another template is shown below: <tt>~/.vim/skeletons/template.c</tt> includes text modules for not only the obligatory GPL header but also includes a basic code structure:</p>
<pre class='brush: c'>
/*
 * %%FILENAME%% - description
 *
 * Copyright (C) %%YEAR%% %%AUTHOR%%
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
 */

#include &lt;stdio.h&gt;

int
main (int argc, char **argv)
{
  return 0;
}

/**This must remain at the end of the file.**********
 * vim600:set sw=2 ts=8 fdm=marker fmr=«««,»»»:     *
 * vim600:set cindent cinoptions={1s,&gt;2s,^-1s,n-1s: *
 ****************************************************/
</pre><p><br />
Variables like <tt>%%FILENAME%%</tt> or <tt>%%AUTHOR%%</tt> can also automatically be replaced by a small shell script running during file creation: the script <tt>~/.vim/do_header</tt> labelled with the file name as argument detects the full name with <tt>getent</tt> or <tt>/etc/passwd</tt>, respectively. Other variables are gathered using the default GNU tools as the listing shows:</p>
<pre class='brush: plain'>
#!/usr/bin/env zsh

if which getent &gt; /dev/null; then
        REALNAME=$(getent passwd $USER|awk -F : '{print $5}' | awk -F , '{print $1}')
else
        REALNAME=$(grep $USER /etc/passwd|awk -F : '{print $5}' | awk -F , '{print $1}')
        if which nidump &gt; /dev/null &amp;&amp; [ -z &quot;$REALNAME&quot; ]; then
                REALNAME=$(nidump passwd / | grep $USER|awk -F : '{print $8}')
        fi
fi
DATE=$(date)
YEAR=$(date +%Y)
FILENAME=$(echo $1 | sed 's/[^/]*\///')
FILE=$(echo $FILENAME | sed 's/\..*//')
FILEBIG=$(echo $FILE | tr '[:lower:]' '[:upper:]')
sed     &quot;s/%%AUTHOR%%/$REALNAME/g;
        s/%%DATE%%/$DATE/g;
        s/%%YEAR%%/$YEAR/g;
        s/%%FILENAME%%/$FILENAME/g;
        s/%%FILE%%/$FILE/g;
        s/%%FILEBIG%%/$FILEBIG/g;&quot;
</pre><p><br />
Besides the examples shown here other templates can be generated to deal with HTML files, python or whatnot, among others - the possibilities are endless.</p>

<p>This howto has just touched on one small aspect of the many <a href="http://www.vim.org/vimscriptlinks.php">automations possible with vim</a>. You can find other howtos in this blog in the <a href="/en/howto/">howtos</a> category, which has its own feed - if you need more in-depth <a href="http://www.credativ.co.uk/home/services/support/">support or services for GNU tools or Linux</a>, you've come to the right place at credativ.</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] RHCS: install on Debian</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/2010/05/howto-rhcs-install-on-debian.html" />
    <id>tag:blog.credativ.com,2010:/en//2.148</id>

    <published>2010-05-20T10:40:00Z</published>
    <updated>2010-05-25T10:10:26Z</updated>

    <summary>Following our earlier introduction to RHCS we now present a real world example: the installation of RHCS with Debian to provide certain virtual machines as services. Our RHCS overview already explained the basics of RHCS. This time we will take...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Debian" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="RHEL/CentOS" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.credativ.com/en/">
        <![CDATA[<p><img alt="tux.jpg" src="/de/static/tux.jpg" width="86" height="102" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Following our earlier introduction to RHCS we now present a real world example: the installation of RHCS with Debian to provide certain virtual machines as services.</em></p>

<p>Our <a href="/en/2010/03/rhcs-an-introduction.html">RHCS overview</a> already explained the basics of RHCS. This time we will take two hosts with shared storage and provide KVM guests as services.</p>

<h3>Installation of the nodes</h3>
In this setup the nodes are the machines which are running KVM. Each running KVM guest is a service managed by RHCS. While installing the KVM hosts you should make sure you comply with the following suggestions:
<ul><li><tt>/tmp/</tt> and <tt>/var/</tt> should be running on different partitions, this improves performance.</li>
<li>Activate Debian backports, especially for the Kernel.</li>
<li>Make sure all IP addresses can be resolved in both directions - <tt>/etc/hosts</tt> helps here in worst case.</li>
<li>The host name must not resolve to <tt>127.0.0.1</tt>! You would only get problems with the Cluster Management System CMAN.</li>
<li><tt>/etc/hosts/</tt> and <tt>/etc/resolv.conf</tt> should be the same on all nodes.</li>
<li>Create password free ssh keys for all nodes and distribute them.</li>
<li>For ultimate performance it is best to install the latest Debian Linux kernel. In our example we used <tt>linux-image-2.6.32-bpo.2-amd64</tt>, which crashes the guest kernels >= 2.6.30. However, a patch is available, see <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=573071">bug #573071</a>.</li>
<li>The network devices should be named in a way that makes sense, for example: <tt>rhcs-backbone</tt> and <tt>external</tt> instead of <tt>eth0</tt> and <tt>eth1</tt>.</li></ul>

<h3>Configuring the shared storage</h3>
As with almost any HA solution, a key element of RHCS is the shared storage which is accessed by all the nodes. In this example we take a "private" machine and install an iSCSI target on it:
<pre class='brush: plain'>
apt-get install iscsitarget iscsitarget-source 
echo 'ISCSITARGET_ENABLE=true' &gt; /etc/default/iscsitarget
m-a a-i iscsitarget
</pre><p><br />
Keep in mind that the iSCSI target must build properly, see <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=566740">bug #566740</a>. The configuration of the shared storage is done via <tt>/etc/ietd.conf</tt>:</p>
<pre class='brush: plain'>
IncomingUser discovery_in YourSecurePwd1
OutgoingUser discovery_out YourSecurePwd2
Target YOURMACHINE:clvm1
       IncomingUser node_in YourSecurePwd1
       OutgoingUser node_out YourSecurePwd2
       Lun 0 Path=/dev/sdx1,Type=blockio
</pre><p><br />
On the nodes the same target must be accessed, so make sure <tt>/etc/iscsi/iscsid.conf</tt> is correct:</p>
<pre class='brush: plain'>
discovery.sendtargets.auth.authmethod = CHAP
discovery.sendtargets.auth.username = discovery_in
discovery.sendtargets.auth.password = YourSecurePwd1
discovery.sendtargets.auth.username_in = discovery_out
discovery.sendtargets.auth.password_in = YourSecurePwd2
node.startup = automatic
node.session.auth.authmethod = CHAP
node.session.auth.username = node_in
node.session.auth.password = YourSecurePwd1
node.session.auth.username_in = node_out
node.session.auth.password_in = YourSecurePwd2
</pre><p><br />
The service is started with <tt>/etc/init.d/open-iscsi start</tt>. Existing targets can be searched, deleted or added by the following commands:</p>
<pre class='brush: plain'>
# discovering the targets
iscsiadm -m discovery -t st -p YOURMACHINE -P 1
# deleting target on wrong interface
iscsiadm -m node -p 192.168.0.100:3260,1 -o delete
# opening the portal
iscsiadm -m node --targetname &quot;iqn.2010-03.YOURMACHINE:clvm1&quot; --portal &quot;YOURMACHINE:3260&quot; --</pre><p></p>

<h3>VM setup</h3>
The virtual machines are provided by KVM. Thus the apropriate KVM software must be installed first:
<pre class='brush: plain'>
apt-get install linux-image-2.6.32-bpo.2-amd64 kvm libvirt-bin virtinst -t lenny-backports
</pre><p><br />
When configuring the bridge, make sure that the bridge name is the same on all nodes. Also the libvirt configuration must be the same on all hosts, so it makes sense to use <a href="/en/2010/03/howto-introduction-to-puppet.html">puppet</a> or similar techniques.<br />
Afterwards, bring up the guests with:</p>
<pre class='brush: plain'>
virt-install -n &lt;NAME&gt; -r 256 --vcpus=1 --disk path=/dev/vg_cluster#/&lt;LV&gt; \
  -c /root/debian-&lt;VERSION&gt;-amd64-netinst.iso --vnc --noautoconsole --os-type linux \
  --os-variant debianLenny --accelerate --network=bridge:bridge0 --hvm -k de
</pre><p><br />
To monitor the process use <tt>virt-viewer -c qemu+ssh://<node>:<port>/system <NAME></tt>.</p>

<h3>RHCS setup</h3>
The next step is the setup of RHCS itself. Again, first things first, the software: <tt>apt-get install redhat-cluster-suite</tt>. This pulls quite a number of services which are not needed in our example:
<pre class='brush: plain'>
invoke-rc.d nfs-kernel-server stop
invoke-rc.d nfs-common stop
invoke-rc.d portmap stop
update-rc.d -f nfs-kernel-server remove
update-rc.d -f nfs-common remove
update-rc.d -f portmap remove
</pre><p><br />
Btw., <tt>system-config-cluster</tt> is not available for Lenny, but our Philipp Hübner has created a backport:</p>
<pre class='brush: plain'>
wget --no-check-certificate https://www.credativ.com/~phu/lenny-backports/system-config-cluster/system-config-cluster_1.0.53-1_all.deb
dpkg -i system-config-cluster_1.0.53-1_all.deb
apt-get -f install
apt-get install xauth
</pre><p><br />
In order to have locking on the LVM cluster, you now need to modify <tt>/etc/lvm/lvm.conf</tt>: check for the <tt>global</tt> part.</p>
<pre class='brush: plain'>
 locking_type = 3
</pre><p><br />
With the newer kernels the module <tt>lock_dlm</tt> also vanished, so CMAN init script must be modified: comment out the line <tt>modprobe lock_dlm 2>&1 || return 1</tt>. Additionally, RHCS 2 only supports XEN, so for libvirt you need to load the resource handler  <tt>vm.sh</tt>.</p>
<pre class='brush: plain'>
wget --no-check-certificate https:///www.credativ.com/~phu/vm.sh -O /usr/share/cluster/vm.sh
chmod +x /usr/share/cluster/vm.sh
</pre><p></p>

<p>RHCS itself is called via</p>
<pre class='brush: plain'>
/etc/init.d/cman start
/etc/init.d/clvm start
/etc/init.d/rgmanager start
</pre><p></p>

<h3>Fencing</h3>
Fencing describes the automagical neutralization of nodes which cease to function properly. In our example we use a power plug which can be controlled via network, NETIO-230A. Currently there is no real fence agent available for the device, but the python library <a href="http://github.com/pklaus/netio230a">Python-Bibliothek</a> offers the necessary background to quickly write one.

<h3>Closing words</h3>
This howto has shown the setup of RHCS on Debian in easy steps - but of course, the correct steps depend very much on the targeted services, so this is just an example. If you need help just ask - <a href="http://www.credativ.co.uk/services/support/projects/high-availability-clustering/">Open Source HA solutions</a> are our speciality, and <a href="http://www.credativ.co.uk/services/support/projects/virtualisation/kvm/">we offer services and support  for KVM virtualization</a> as part of our day to day business.]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Language based rewrites with Lighttpd and mod_magnet</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/2010/04/tip-language-based-rewrites-with-lighttpd-and-mod-magnet.html" />
    <id>tag:blog.credativ.com,2010:/en//2.134</id>

    <published>2010-04-12T09:09:22Z</published>
    <updated>2010-05-05T13:56:12Z</updated>

    <summary>Lighttpd is a web server with a fast growing user base. This howto will demonstrate how redirects can be done based on the language of the user&apos;s browser. While migrating from our old blogging software to Movable Type we decided...</summary>
    <author>
        <name>Bernd Zeimetz</name>
        
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.credativ.com/en/">
        <![CDATA[<p><img alt="light_logo_170px.png" src="/en/static/light_logo_170px.png" width="100" height="80" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Lighttpd is a web server with a fast growing user base. This howto will demonstrate how redirects can be done based on the language of the user's browser.</em> </p>

<p>While migrating from our old blogging software to <a href="http://www.movabletype.org/opensource/">Movable Type</a> we decided it would be a good idea to show the blog's welcome message in English or German depending on the language setting of the user's browser. Since one of the reasons for the switch to the new blog engine was that Movable Type creates static html pages, we avoided cgi scripts or similar workarounds.</p>

<p>We are using <a href="http://www.lighttpd.net/">Lighttpd</a> to serve all pages, which means that our best option was the mighty <a href="http://redmine.lighttpd.net/wiki/1/Docs:ModMagnet">mod_magnet</a> module. This allows you to control request handling within Lighttpd by running <a href="http://www.lua.org/">Lua</a> scripts, which are able to modify most aspects of the way a request is handled. <a href="http://blog.credativ.com/">http://blog.credativ.com/</a> is now rewritten to the file in the correct language with the help of the following Lua snippet:<br />
</p>
<pre class='brush: lua'>
-- - make sure to configure the script here -----------------------------

language_targets = {}
language_targets[&quot;en&quot;] = &quot;/en/index.html&quot;
language_targets[&quot;de&quot;] = &quot;/de/index.html&quot;
default_language = &quot;en&quot;


-- - nothing to customize below this line -------------------------------
--

--[[ string:split function taken from http://lua-users.org/wiki/SplitJoin
      Thanks to Joan Ordinas
  ]]      
function string:split(sSeparator, nMax, bRegexp)
    assert(sSeparator ~= '')
    assert(nMax == nil or nMax &gt;= 1)

    local aRecord = {}

    if self:len() &gt; 0 then
        local bPlain = not bRegexp
        nMax = nMax or -1

        local nField=1 nStart=1
        local nFirst,nLast = self:find(sSeparator, nStart, bPlain)
        while nFirst and nMax ~= 0 do
            aRecord[nField] = self:sub(nStart, nFirst-1)
            nField = nField+1
            nStart = nLast+1
            nFirst,nLast = self:find(sSeparator, nStart, bPlain)
            nMax = nMax-1
        end
        aRecord[nField] = self:sub(nStart)
    end

    return aRecord
end

--[[ Based on trim14 from http://lua-users.org/wiki/StringTrim ]]
do
    require 're'
    require 'lpeg'

    local ptrim = re.compile&quot;%s* {(%s* %S+)*}&quot;
    local match = lpeg.match
    function string:trim()
        return match(ptrim, self)
    end
end


lang_header = lighty.request['Accept-Language']
lighty.env[&quot;uri.path&quot;] = language_targets[default_language]
if (lang_header) then
    lang_header = string.lower(lang_header)
    local lang_order = {}
    for i, language in ipairs(string.split(lang_header, &quot;,&quot;)) do
        language_configs = string.split(language, &quot;;&quot;)
        language = string.trim(language_configs[1])
        table.remove(language_configs, 1)
        if     ((#language == 2) and string.find(language, &quot;[a-z][a-z]&quot;))
            or ((#language == 5) and string.find(language, &quot;[a-z][a-z][-][a-z][a-z]&quot;))
        then
            local q = 1
            for i, config in ipairs(language_configs) do
                local config_data = string.split(config, &quot;=&quot;)
                if (#config_data == 2) then
                    local lvalue = string.trim(config_data[1])
                    local rvalue = string.trim(config_data[2])
                    if lvalue == &quot;q&quot; then
                        q = tonumber(rvalue)
                    end
                end
            end
            table.insert(lang_order, {language, q}) 
        end
    end
    table.sort(lang_order, function(a,b) return (a[2] &gt; b[2]) end)
    for i,v in ipairs(lang_order) do
        local lang = string.split(v[1], '-')[1]
        if language_targets[lang] then
            lighty.env[&quot;uri.path&quot;] = language_targets[lang]
            break
        end
    end
end

lighty.env[&quot;physical.rel-path&quot;] = lighty.env[&quot;uri.path&quot;]
lighty.env[&quot;physical.path&quot;] = lighty.env[&quot;physical.doc-root&quot;] .. lighty.env[&quot;physical.rel-path&quot;]
</pre><p></p>

<p>Of course, the Lighttpd configuration has to include <tt>mod_magnet</tt>. To actually rewrite any request to "/" the configuration must also include the following snippet:<br />
</p>
<pre class='brush: perl'>
$HTTP[&quot;url&quot;] =~ &quot;^/$&quot; {
	magnet.attract-physical-path-to = ( &quot;/path/to/your/script.lua&quot; )
}
</pre><p></p>

<p><tt>mod_magnet</tt> caches the compiled script and executes it within the core of Lighttpd so it shouldn't introduce any noticeable delay in the delivery of your webpages.</p>

<p><strong>Update:</strong> Some people asked for a script to parse the full Accepted-Language header. Although this was not really an issue for us as the two blogs are independent and people have to check which blog to read in any case, I've updated the script to parse the header properly. Also it should be easier to re-use for your own needs now.</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] PostgreSQL and Linux Memory Management</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/2010/03/postgresql-and-linux-memory-management.html" />
    <id>tag:blog.credativ.com,2010:/en//2.151</id>

    <published>2010-03-26T13:57:26Z</published>
    <updated>2010-03-26T14:53:42Z</updated>

    <summary>The OOM-Killer can cause nasty surprises on machines with a heavy memory load; processes are cancelled or terminated without warning. Fortunately, this behaviour can be adjusted with some clever kernel tweaks. Administrators of Linux machines with a very high RAM-Usage...</summary>
    <author>
        <name>Bernd Helmle</name>
        
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="PostgreSQL" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.credativ.com/en/">
        <![CDATA[<p><img alt="postgreslogo.png" src="/de/static/postgreslogo.png" width="97" height="100" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>The OOM-Killer can cause nasty surprises on machines with a heavy memory load; processes are cancelled or terminated without warning. Fortunately, this behaviour can be adjusted with some clever kernel tweaks.</em></p>

<p>Administrators of Linux machines with a very high RAM-Usage are sometimes faced with a terrifying scenario: the Linux <a href="http://linux-mm.org/OOM_Killer">OOM-Killer</a> (OOM = Out Of Memory). In situations such as a crashed PostgreSQL instance, the following entry can typically be found in the server log:<br />
</p>
<pre class='brush: text'>
Out of Memory: Killed process PID (Prozessname)
</pre><p></p>

<p>Why is this?</p>

<h3>Virtual Memory and Overcommit</h3>

<p>Virtual Memory used by Linux can be allocated in a number of ways: malloc(), mmap(), Swap, Shared Memory, to mention some examples. It is possible to overcommit virtual memory by allocating more than is actually available in the system. If this happens, a so-called "OOM-Condition" occurs; that is, your system no longer has any available space in the virtual memory area and cannot allocate any more. This is when the OOM-Killer is activated - and does what its name suggests: kills any processes which meet certain conditions in order to free memory.</p>

<p>If you have an environment where servers are running PostgreSQL in parallel with other memory-intensive processes on the same machine, it's likely that the OOM-Killer will kill certain PostgreSQL processes. Due to the amount of allocated shared memory and the memory usage of each backend, the OOM-Killer will target PostgreSQL by preference since it counts the complete addressed shared memory area of <strong>all</strong> backends into summary. </p>

<p>The amount of committed memory of your system at a given time can be examined with the <tt>/proc</tt>-Filesystem:<br />
</p>
<pre class='brush: text'>
$ grep Commit /proc/meminfo 
CommitLimit:    376176 kB
Committed_AS:   265476 kB
</pre><p></p>

<p>This example shows the current amount of committed memory at <tt>265476 kB</tt> (<tt>Committed_AS</tt>). Is this equal or even larger than the amount of <tt>Committed_AS</tt> the OOM-Killer is likely to be woken up.</p>

<p>However, the kernel provides some interfaces to adjust the behaviour of the OOM-Killer and Overcommit with regard to PostgreSQL installations.</p>

<h3>Turn off Overcommit</h3>

<p>A radical method is to turn overcommit off entirely, although this is only recommended on systems dedicated to PostgreSQL. The overcommit feature can be configured within three categories with the following kernel parameter:<br />
</p>
<pre class='brush: text'>
vm.overcommit_memory = 0
</pre><p></p>

<p>This can hold three different kinds of categories:</p>

<ul>
       <li><strong>0</strong>: Allow a careful strategy of overcommitting memory: small and reasonable amounts of overcommitting allocations are allowed, but heavy and wild allocations will be denied. In this mode, root can allocate more space than unprivileged users. This is also the kernel default setting.</li>
        <li><strong>1</strong>: Allow overcommit without any constraints</li>
        <li><strong>2</strong>: Turn off overcommit. The effective allocatable memory space cannot be larger than <tt>swap</tt> + a configurable percentage of physical RAM. 
</ul> 

<p>The fraction of physical RAM used by category <tt>2</tt> is defined by the parameter:<br />
</p>
<pre class='brush: text'>
vm.overcommit_ratio = 50
</pre><p></p>

<p>While <tt>vm.overcommit_memory=1</tt> is useful when tuning certain applications, the categories <tt>0</tt> or <tt>2</tt> are the best ones to use most of the time. If you turn off overcommit with <tt>vm.overcommit_memory=2</tt>, a process will get an "out of memory"-Exception (depending of <tt>vm_overcommit_ratio</tt>) if allocating memory when no more free space is available. Depending on the distribution you are using, we recommend that you save those settings in the configuration file <tt>/etc/sysctl.conf</tt> to ensure that they are activated on server reboot.<br />
</p>
<pre class='brush: text'>
$ echo &quot;vm.overcommit_memory=2 &gt;&gt; /etc/sysctl.conf
$ echo &quot;vm.overcommit_ratio=60 &gt;&gt; /etc/sysctl.conf
$ sysctl -p /etc/sysctl.conf
</pre><p></p>

<p>Changes to those parameters are activated immediately. You can recheck this by consulting  <tt>/proc/meminfo</tt>: <br />
</p>
<pre class='brush: text'>
$ grep Commit /proc/meminfo 
CommitLimit:    401440 kB
Committed_AS:   266456 kB
</pre><p></p>

<p>The machine has <tt>249848 kB</tt> of swap and <tt>252656 kB</tt> physical RAM. <br />
According to the formula <tt>swap + vm.overcommit_ratio * RAM</tt> this results in a <tt>CommitLimit</tt> of <tt>401440 kB</tt></p>

<h3>Configure OOM-Killer per process</h3>

<p>Where PostgreSQL is running without dedicated server hardware and in parallel with memory-intensive middleware (e.g. JBoss- or Tomcat-Installations), most admins would prefer to be able to control the OOM-Killer on a per-process basis and allow overcommitting of memory allocations. Since kernel 2.6.1, Linux has been providing an interface for tuning the OOM-Score of a process, which will in turn increase or decrease the affinity of the process to be killed when running in an OOM-Situation. This interface allows a very flexible configuration of processes in such environments regarding their memory requirements. The interface is exposed by the  <tt>/proc-Filesystem</tt>, for example here on a PostgreSQL-Installation on Debian:<br />
</p>
<pre class='brush: text'>
$ cat /proc/$(cat /var/run/postgresql/8.4-main.pid)/oom_adj
0
</pre><p></p>

<p>Values allowed range from -17 to +15, a negative value decreases, while a positive value increases the likelihood of being killed by the OOM-Killer. -17 is a special value and turns killing the process in an OOM-Situation off.<br />
The settings are inherited from parent to child processes; in PostgreSQL you'll have to set this one to the PostgreSQL master process:<br />
</p>
<pre class='brush: text'>
$ echo -17 &gt;&gt; /proc/$(cat /var/run/postgresql/8.4-main.pid)/oom_adj
$ psql -q postgres
test=# SELECT pg_backend_pid();
 pg_backend_pid 
----------------
           3429
(1 line)

test=# 
[1]+  Stopped                 psql -q test
$ cat /proc/3429/oom_adj
-17
</pre><p></p>

<p>The disadvantage of this method is that <strong>all</strong> child processes will now be excluded from the OOM-Killer, which is not generally what DBAs prefer. For example, where you want to protect the PostgreSQL system processes (like <tt>background writer</tt> oder <tt>autovacuum</tt>) from being killed by the OOM-Killer, but still kill ordinary database connections when running out of memory.</p>

<p>To set the OOM-Score you need to have a privileged user, so the best way to implement this setting is to put it into your PostgreSQL start script.</p>

<h3>Enhancements in PostgreSQL 9.0</h3>

<p><a href="/de/2010/02/postgresql-agenda-2010.html">PostgreSQL 9.0</a> will have additional <a href="http://archives.postgresql.org/pgsql-committers/2010-01/msg00169.php">support</a> for the pictured <tt>/proc</tt>-Interface. On one hand PostgreSQL 9.0 will come with a new <a href="http://git.postgresql.org/gitweb?p=postgresql.git;a=blob_plain;f=contrib/start-scripts/linux;hb=HEAD">Linux start script</a>, which supports setting the <tt>oom_adj</tt> value before starting up PostgreSQL; on the other hand it is possible to build PostgreSQL with the special C-Macro <tt>LINUX_OOM_ADJ</tt> defined, which will allow DBAs to limit the inheritance of the OOM-Score to backend childs as shown in this example:<br />
</p>
<pre class='brush: text'>
$ ./configure CC=&quot;ccache gcc&quot; CFLAGS=&quot;-DLINUX_OOM_ADJ=0&quot;
</pre><p></p>

<p>This method will save the PostgreSQL system process but will allow the OOM-Killer to kill database backend processes running amok.</p>

<h3>Alternatives</h3>

<p>An alternative solution is available by an <a href="http://www.cybertec.at/en/linux-kernel-patch">additional kernel patch</a>. This extends the existing <tt>/proc</tt>-Filesystem with a list of process names which should be excluded from the OOM-Killer. However, this patch is an unoffical extension to the Linux kernel and you may have to maintain your own builds of Linux kernels. In addition, it is not nearly as flexible as adjusting the OOM-Score and process names are not useful for uniquely identifying processes (e.g. Java- or Perlbased processes).</p>

<h3>Summary</h3>

<p>The Linuxkernel provides a comprehensive interface to adjust processes regarding their memory usage and the OOM-Killer. The most flexible method is the introduced <tt>/proc</tt>-Filesystem with the <tt>oom_adj</tt>-Interface. PostgreSQL 9.0 will have additional support for this interface. Dedicated PostgreSQL-Systems can be configured to avoid overcommit at all, but will need a deeper understanding of the number of memory resources the database system demands and the requirements of the VM of the kernel.</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Sys admin tool of the week: sysstat</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/2010/03/howto-sys-admin-tool-of-the-week-sysstat.html" />
    <id>tag:blog.credativ.com,2010:/en//2.88</id>

    <published>2010-03-19T11:20:07Z</published>
    <updated>2010-03-19T11:11:43Z</updated>

    <summary>The tool chain of a sys admin should always be comprised of effective tools. Today we are introducing the package sysstat. Sysstat is a collection of command line tools dedicated to providing the system administrator with a quick overview of...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Support" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.credativ.com/en/">
        <![CDATA[<img alt="bash.png" src="/en/static/bash.png" width="90" height="72" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>The tool chain of a sys admin should always be comprised of effective tools. Today we are introducing the package sysstat.</em>
<br />
<br />
<a href="http://pagesperso-orange.fr/sebastien.godard/">Sysstat</a> is a collection of command line tools dedicated to providing the system administrator with a quick overview of the performance of the system. They work as front-ends to the Kernel and therefore can never provide more data than the Kernel itself gathers, although the interface is much more user-friendly than querying Kernel parameters manually.

<h3>iostat</h3>
<tt>iostat</tt> is the way to go if there are problems with the throughput of a disk, NFS storages or the CPUs. For example, if your system is behaving strangely, iostat can be used to identify I/O waits:
<pre class='brush: plain'>
Linux 2.6.31-19-generic (mymachine)         04.03.2010      _x86_64_        (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          11,82    0,29    3,44    1,25    0,00   83,20

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda               9,39       161,19       168,44    4264806    4456696
</pre>
There are many options available for iostat but these are the most interesting, and they deal with specific outputs:
<dl>
 <dd><tt>-d</tt></dd> <dt>Just show the hard disk data.</dt>
<dd><tt>-c</tt></dd> <dt>Just show the CPU data.</dt>
<dd><tt>-p</tt></dd> <dt>Show the I/PO data for each partition.</dt>
<dd><tt>-n</tt></dd> <dt>Show the I/O data for the NFS partitions.</dt>
<dd><tt>-x</tt></dd> <dt>Extended information for the hard disks.</dt>
<dd><tt>-t $NUM1</tt></dd> <dt>Tells the program after how many seconds the result should be refreshed.</dt>
 </dl>

<h3>mpstat</h3>

<tt>mpstat</tt> is the next tool in the chain: it helps when analysing the CPU load. If you call it with no options, the default information will be shown, in the same way that the <tt>iostat</tt> results are.
<pre class='brush: plain'>
Linux 2.6.31-19-generic (mymachine)         04.03.2010      _x86_64_        (2 CPU)

17:01:52     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
17:01:52     all   11,96    0,29    3,26    1,23    0,10    0,11    0,00    0,00   83,06
</pre>
In contrast to <tt>iostat</tt>, you see the actual load on hard and software interrupts. The option <tt>-A</tt> extends this information further: for each processor, the statistics and interrupts per second are shown.
<br />
<br />
If you add an int $NUM after the command, the process runs without end and refreshes the output every $NUM seconds.

<h3>pidstat</h3>
<tt>pidstat</tt> concentrates on the processes itself: it shows a list of all processes. The option <tt>-C</tt> enables you to filter these by a given string:
<pre class='brush: plain'>
Linux 2.6.31-19-generic (mymachine)         04.03.2010      _x86_64_        (2 CPU)

17:02:32          PID    %usr %system  %guest    %CPU   CPU  Command
17:02:32            1    0,00    0,00    0,00    0,00     1  init
17:02:32         2888    0,00    0,00    0,00    0,00     0  start_kdeinit
17:02:32         2889    0,00    0,00    0,00    0,00     0  kdeinit4
</pre>
The additional option <tt>-d</tt> shows I/O statistics about the given processes, <tt>-p</tt> takes the PID as an argument to focus on known processes. Finally <tt>-r</tt> brings up an overview of the memory load.
<br />
<br />
Again, an int $NUM after the command lets the process run continuously, refreshing the output every $NUM seconds.

<h3>sar</h3>

All sysstat tools so far have had one flaw, only showing a snapshot of the current state and unable to look into the behaviour of the system in the past or during load time. Such information must be collected in the background, which is exactly what <tt>sar</tt> and its tools are all about: it collects the performance data of the system every ten minutes via cron job. If you call the tool with the default values you get a first impression:
<pre class='brush: plain'>
Linux 2.6.31-19-generic (mymachine)         04.03.2010      _x86_64_        (2 CPU)

09:30:30          LINUX RESTART

09:35:02        CPU     %user     %nice   %system   %iowait    %steal     %idle
09:45:01        all     17,38      1,02      5,10      3,87      0,00     72,63
09:55:01        all     11,90      0,27      2,86      0,75      0,00     84,23
10:05:01        all     10,20      3,52      3,46      2,55      0,00     80,27
10:15:02        all     12,96      0,32      3,18      0,65      0,00     82,89
10:25:01        all      7,94      0,18      3,17      2,42      0,00     86,30
10:35:01        all     12,41      0,89      4,55      0,56      0,00     81,60
10:45:02        all      8,97      0,09      3,51      0,89      0,00     86,55

</pre>
All possible information can be collected with <tt>sar -A</tt> although the amount of output will be too much for any screen size. There are too many options involved in decreasing the output with <tt>sar</tt> to cover here, but they are discussed in detail on the <a href="http://pagesperso-orange.fr/sebastien.godard/man_sar.html">man page</a>.]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Introduction to Puppet</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/2010/03/howto-introduction-to-puppet.html" />
    <id>tag:platon.credativ.com,2010:/en//2.126</id>

    <published>2010-03-02T11:29:47Z</published>
    <updated>2010-05-28T12:44:31Z</updated>

    <summary>The administration of a large number of servers can be quite tiresome without a central configuration management. This article gives a first introduction into the configuration management tool, Puppet. Introduction In our daily work at the Open Source Support Center...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Debian" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Support" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.credativ.com/en/">
        <![CDATA[<img alt="tux.jpg" src="/en/static/tux.jpg" width="86" height="102" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>The administration of a large number of servers can be quite tiresome without a central configuration management. This article gives a first introduction into the configuration management tool, <strong>Puppet</strong>.</em>
<br />
<br />

<h3>Introduction</h3>

In our daily work at the <a href="http://www.credativ.co.uk/services/support/">Open Source Support Center</a> we maintain a large number of servers. Managing larger clusters or setups means maintaining dozens of machines with an almost identical configuration and only slight variations, if any. Without central configuration management, making small changes to the configuration would mean repeating the same step on all machines. This is where <a href="http://reductivelabs.com/trac/puppet/">Puppet</a> comes into play.
<br />
<br />
As with all configuration management tools, Puppet uses a central server which manages the configuration. The clients query the server on a regular basis for new configuration via an encrypted connection. If a new configuration is found, it is imported as the server instructs: the client imports new files, modifies rights, starts services and executes commands, whatever the server says. The advantages are obvious:
<ul>
	<li>Each configuration change is done only once, regardless of the actual number of maintained servers. Unnecessary - and pretty boring - repetition is avoided, lucky us!</li>
	<li>The configuration is streamlined for all machines, which makes it much easier to maintain.</li>
	<li>A central infrastructure makes it easier to quickly get an overview about the setup - "running around" is not necessary anymore.</li>
	<li>Last but not least, a central configuration tree enables you to incorporate a simple version control of your configuration: for example, playing back the configuration "PRE-UPDATE" on all machines of an entire setup only takes a couple of commands!</li>
</ul>

<h3>Technical workflow</h3>

Puppet consists of a central server, called "Puppet Master", and the clients, called "Nodes". The nodes query the master for the current configuration. The master responds with a list of configuration and management items: files, services which have to be running, commands which need to be executed, and so on - the possibilities are practically endless:

<ul>
	<li>The master can hand over files which the node copies to a defined place - if it does not already exist.</li>
	<li>The node is asked to check certain file and directory permissions and to correct them if necessary.</li>
	<li>Depending upon the operating system, the node checks the state of services and starts or stops them. It can also check for installed packages and if they are up to date.</li>
	<li>The master can force the node to execute arbitrary commands</li>
</ul>

Of course, in general all tasks can be fulfilled by handing over files from the master to the client. However, in more complex setups this kind of behaviour is not easily arranged, nor does it simplify the setup. Puppet's strength is that it facilitates abstract system tasks (restart services, ensure installed packages, add users, etc.), regardless of the actual changed files in the background. You can even use the same statement in Puppet to configure different versions of Linux or Unix.

<h3>Installation</h3>

First, you need the master, the center of all the configuration you want to manage:
<code>apt-get install puppetmaster</code>
Puppet expects that all machines in the network have FQDNs - but that should be the case anyway in a well maintained network.
<br />
<br />
Other machines become a node by installing the Puppet client:
<code>apt-get install puppet</code>

<h3>Puppet, main configuration</h3>

The Puppet nodes do not need to be configured - they will check for a machine called "Puppet" in the local network. As long as that name points to the master you do not have to do anything else.
<br />
<br />
Since the master provides files to the nodes, the internal file server must be configured accordingly. There are different solutions for the internal file server, depending on the needs of your setup. For example, it might be better for your setup to store all files you provide to the nodes on one place, and the actual configuration you provide to the nodes somewhere else. However, in our example we keep the files and the configuration for the nodes close, as it is outlined in Puppet's <a href="http://reductivelabs.com/trac/puppet/wiki/PuppetBestPractice">Best Practice Guide</a> and in the <a href="http://reductivelabs.com/trac/puppet/wiki/ModuleOrganisation">Module Configuration</a> part of the Puppet documentation.Thus, it is enough to change the file <tt>/etc/puppet/fileserver.conf</tt> to:
<pre class='brush: plain'>[modules]
allow 192.168.0.1/24
allow *.credativ.de
</pre>

<h3>Configuration of the configuration - Modules</h3>
Puppet's way of managing configuration is to use sets of tasks grouped by topic. For example, all tasks related to SSH should go into the module "ssh", while all tasks related to apache should be placed in the module "apache" and so on. These sets of tasks are called <strong>"Modules"</strong> and are the core of Puppet - in a perfect Puppet setup everything is defined in modules! We will explain the structure of a SSH module  to highlight the basics and ideas behind Puppet's modules. We will also try to stay close to the Best Practise Guide to make it easier to check back against the Puppet documentation.
<br />
<br />
Please note, however, that this example is an example: in a real world setup the SSH configuration would be a bit more dynamic, but we focused on simple and easy-to-understand methods.

<h3>The SSH module</h3>

We have the following requirements:
<ol>
	<li>The package open-ssh must be installed and be the newest version.</li>
	<li>Each node's sshd_config file has to be the same as the one saved on the master.</li>
	<li>In the event that the sshd_config is changed on any node, the sshd service should be restarted.</li>
	<li>The user <tt>credativ</tt> needs to have certain files in his/her directory <tt>$HOME/.ssh</tt>.</li>
</ol>
To comply with these requirements we start by creating some necessary paths:
<pre class='brush: plain'>mkdir -p /etc/puppet/modules/ssh/manifests
mkdir -p /etc/puppet/modules/ssh/files
</pre>

The directory "<strong>manifests</strong>" contains the actual configuration instructions of the module and the directory "<strong>files</strong>" provides the files we hand over to the clients.
<br />
<br />
The instructions themselves are written down in <strong>init.pp</strong> in the "<strong>manifests</strong>" directory. The set of instructions to fulfil aims 1 - 4 are grouped in a so called "class". For each task a "class" has one subsection, a <a href="http://docs.reductivelabs.com/references/stable/type.html">type</a>. So in our case we have four types, one for each aim:
<pre class='brush: plain'>
class ssh{
        package { &quot;openssh-server&quot;:
                 ensure =&gt; latest,
        }
        file { &quot;/etc/ssh/sshd_config&quot;:
                owner   =&gt; root,
                group   =&gt; root,
                mode    =&gt; 644,
                source  =&gt; &quot;puppet:///ssh/sshd_config&quot;,
        }
        service { ssh:
                ensure          =&gt; running,
                hasrestart      =&gt; true,
                subscribe       =&gt; File[&quot;/etc/ssh/sshd_config&quot;],
        }
        file { &quot;/home/credativ/.ssh&quot;:
                path    =&gt; &quot;/home/credativ/.ssh&quot;,
                owner   =&gt; &quot;credativ&quot;,
                group   =&gt; &quot;credativ&quot;,
                mode    =&gt; 600,
                recurse =&gt; true,
                source  =&gt; &quot;puppet:///ssh/ssh&quot;,
                ensure  =&gt; [directory, present],
        }
}
</pre>
Each type is another task and calls another action on the node:
<dl>
 <dd>package</dd> <dt>Here we make sure that the package <em>openssh-server</em> is installed in the newest version.</dt>
 <dd>file</dd> <dt>A file on the node is compared with the version on the server and overwritten if necessary. Also, the rights are adjusted.</dt>
 <dd>service</dd> <dt>Well, as the name says, this deals with services: in our case the service <em>sshd</em> must be running on the node. Also, in case the file <em>/etc/ssh/sshd_config</em> is modified, the service is restarted automatically.</dt>
 <dd>file</dd> <dt>Here we have again the file type, but this time we do not compare a file, but an entire directory.</dt>
 </dl>

As mentioned above, the files and directories you configured so that the server provides them to the nodes must be available in the directory <tt>/etc/puppet/modules/ssh/files/</tt>.

<h3>Nodes and modules</h3>

We now have three parts: the master, the nodes and the modules. The next step is to tell the master which nodes are related to which modules. First, you must tell the master that this module exists in <tt>/etc/puppet/manifests/modules.pp</tt>:
<pre class='brush: plain'>
import &quot;ssh&quot;
</pre>
Next, you need to modify <tt>/etc/puppet/manifests/nodes.pp</tt>. This specifies which module is loaded for which node, and which modules should be loaded as default in the event that a node does not have a special entry. The entries for the nodes support inheritance.
<br />
<br />
So, for example, to have the module "rsyslog" ready for all nodes but the module "ssh" only ready for the node "external" you need the following entry:
<pre class='brush: plain'>
node default {
    include rsyslog
}
node 'external' inherits default {
    include ssh
}
</pre>
Puppet is now configured!

<h3>Certificates - secured communication between nodes and master</h3>

As mentioned above, the communication between master and node is encrypted. But that implies you have to verify the partners at least once. This can be done after a node queries the master for the first time. Whenever the master is queried by an unknown node it does not provide the default configuration but instead puts the node on a waiting list. You can check the waiting list with the command:

<code># puppetca --list</code>
<br />
<br />
To verify a node and incorporate it into the Puppet system you need to verify it:
<code># puppetca --sign external.example.com</code>

The entire process is explained in more detail in the <a href="http://reductivelabs.com/trac/puppet/wiki/CertificatesAndSecurity">puppet documentation</a>.

<h3>Closing words</h3>

The example introduced in this article is very simple - as I noted, a real world example would be more complex and dynamic. However, it is a good way to start with Puppet, and the documentation linked throughout this article will help the willing reader to dive deeper into the components of Puppet.
<br />
<br />
We, here at credativ's Open Source Support Center have gained considerable experience with Puppet in recent years and really like the framework. Also, in our day to day support and consulting work we see the market growing as more and more customers are interested in the framework. Right now, Puppet is in the fast lane and it will be interesting to see how more established solutions like <a href="http://www.cfengine.org/">cfengine</a> will react to this competition.]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Using dovecot with Sieve in RHEL/CentOS 5</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/2010/02/howto-using-dovecot-with-sieve-in-rhelcentos-5.html" />
    <id>tag:blog.credativ.com,2010:/en//2.97</id>

    <published>2010-02-02T15:06:11Z</published>
    <updated>2011-02-09T13:06:25Z</updated>

    <summary>The current RHEL/CentOS 5 package has one flaw: it was compiled without Sieve support. However, with a bit of rpm magic, the package can be rebuilt and produces an additional sieve package. The current RHEL/CentOS 5 version has a rather...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="RHEL/CentOS" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Support" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.credativ.com/en/">
        <![CDATA[<p><img alt="centos-logo.png" src="/en/static/centos-logo.png" width="80" height="80" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>The current RHEL/CentOS 5 package has one flaw: it was compiled without Sieve support. However, with a bit of rpm magic, the package can be rebuilt and produces an additional sieve package.</em><br />
The current RHEL/CentOS 5 version has a rather old <a href="http://www.dovecot.org/">dovecot</a>, 1.0.7. Even worse, the plugin for <a href="http://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)">Sieve</a> wasn't included in this build. Of course, given the old version of dovecot, an update to a newer version with Sieve is worth a thought; however, there are situations where that is simply not an option.</p>

<p>In such cases you can still rebuild the old package with a modified rpm file: download the <a href="http://mirror.netcologne.de/centos/5/os/SRPMS/dovecot-1.0.7-7.el5.src.rpm">source RPM</a>, install it with<br />
<code>rpm -Uvh dovecot-1.0.7-7.el5.src.rpm</code><br />
get the diff from below and apply it to the spec file:<br />
<code>patch < dovecot.diff</code><br />
Download the sources as given in the now modified spec file to your <tt>SOURCES</tt> directory, and rebuild the package:<br />
<code>rpmbuild -ba dovecot.spec</code><br />
and welcome the new sieve plugin <tt>dovecot-sieve-1.0.4-7.x86_64.rpm</tt>. Install it and <a href="http://wiki.dovecot.org/LDA/Sieve/CMU">continue as usual</a>. And as a small help for writing Sieve scripts: you can verify them on various online services like the one from the <a href="http://libsieve-php.exit0.net/">PHP Sieve library</a>.</p>

<p>Be careful, however: you have to maintain this package on your own - especially when a dovecot update comes along or when the sieve plugin code is updated. Do bear in mind, though, that this information, as with all howtos, should be followed at your own discretion; it comes with no warranty, and might eat your cats.</p>

<p>And here is the patch for the spec file:</p>
<pre class='brush: text'>
--- dovecot.old.spec    2010-03-11 09:59:38.598277799 +0100
+++ dovecot.spec        2010-03-11 09:58:08.639526842 +0100
@@ -1,7 +1,10 @@
 %define upstream 1.0.7
+%define sieve_upstream 1.0.4
 %define pkg_version 1.0.7
 %define my_release 7
 %define pkg_release %{my_release}%{?dist}
+%define pkg_sieve_version 1.0.4
+%define pkg_sieve_release %{my_release}%{?dist}
 
 Summary: Dovecot Secure imap server
 Name: dovecot

@@ -12,6 +15,7 @@
 
 %define build_postgres 1
 %define build_mysql 1
+%define sieve_name dovecot-sieve
 
 Source: http://dovecot.org/releases/%{name}-%{upstream}.tar.gz
 Source1: dovecot.init

@@ -22,6 +26,7 @@
 Source6: perfect_maildir.pl
 Source7: dovecot-REDHAT-FAQ.txt
 Source8: dovecot.sysconfig
+Source9: http://dovecot.org/releases/sieve/%{sieve_name}-%{sieve_upstream}.tar.gz
 Patch100: dovecot-1.0.7-default-settings.patch
 Patch102: dovecot-1.0.rc2-pam-setcred.patch
 Patch103: dovecot-1.0.beta2-mkcert-permissions.patch

@@ -80,6 +85,16 @@
 primarily in mind.  It also contains a small POP3 server.  It supports mail 
 in either of maildir or mbox formats.
 
+%package sieve
+Requires: %{name}
+Summary: CMU Sieve plugin for dovecot LDA
+Group: System Environment/Daemons
+Version: %{pkg_sieve_version}
+Release: %{pkg_sieve_release}
+
+%description sieve
+This package provides the CMU Sieve plugin for dovecot LDA.
+
 %prep
 %setup -q -n %{name}-%{upstream}

@@ -94,6 +109,8 @@
 %patch503 -p1 -b .CVE-2008-4577
 %patch504 -p1 -b .CVE-2008-4870
                               
+%setup -q -n %{name}-%{upstream} -D -T -a 9
+
 %build
 rm -f ./configure
 libtoolize -f

@@ -115,6 +132,16 @@
 
 make %{?_smp_mflags}
 
+cd %{sieve_name}-%{sieve_upstream}
+rm -f ./configure
+libtoolize -f
+autoreconf
+%configure                           \
+    INSTALL_DATA=&quot;install -c -p -m644&quot; \
+    --with-dovecot=../
+
+make %{?_smp_mflags}
+
 %install
 rm -rf $RPM_BUILD_ROOT
 make install DESTDIR=$RPM_BUILD_ROOT

@@ -169,6 +196,11 @@
 mv $RPM_BUILD_ROOT%{docdir} $RPM_BUILD_ROOT%{docdir}-%{version}
 mkdir -p $RPM_BUILD_ROOT/var/lib/dovecot
 
+# dovecot-sieve
+pushd %{sieve_name}-%{sieve_upstream}
+make install DESTDIR=$RPM_BUILD_ROOT
+popd
+
 %pre
 /usr/sbin/useradd -c &quot;dovecot&quot; -u %{dovecot_uid} -s /sbin/nologin -r -d /usr/libexec/dovecot dovecot 2&gt;/dev/null || :
 
@@ -243,6 +275,9 @@
 %attr(0750,root,dovecot) %{docdir}-%{version}/examples/mkcert.sh
 %attr(0750,dovecot,dovecot) %dir /var/lib/dovecot
 
+%files sieve
+%defattr(-,root,root)
+%{_libdir}/%{name}/lda/lib90_cmusieve_plugin.so
 
 %changelog
 * Mon Nov 24 2008 Michal Hlavinka &lt;mhlavink@redhat.com&gt; - 1.0.7-7
</pre>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Updating ClamAV Definitions Using Nagios Event Handlers</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/en/2009/07/updating-clamav-definitions-using-nagios-event-handlers.html" />
    <id>tag:platon.credativ.com,2009:/en//2.89</id>

    <published>2009-07-29T09:24:30Z</published>
    <updated>2010-03-05T10:57:41Z</updated>

    <summary> The Problem Both as part of our Open Security Filter and as a standalone service, we offer checking of emails for viruses using Clam AntiVirus. As the threat from viruses is constantly evolving, the ClamAV project provides ongoing updates...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Debian" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="antivirus" label="antivirus" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="clamantivirus" label="clam antivirus" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="clamav" label="clamav" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="freshclam" label="freshclam" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="monitoring" label="monitoring" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="nagios" label="nagios" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spam" label="spam" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sudo" label="sudo" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="virus" label="virus" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.credativ.com/en/">
        <![CDATA[<p><img alt="tux.jpg" src="/en/static/tux.jpg" width="86" height="102" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /></p>

<h3>The Problem</h3>

<p>Both as part of our <a title="credativ's Open Security Filter" href="http://www.credativ.co.uk/services/support/projects/spam-and-antivirus/open-security-filter/">Open Security Filter</a> and as a <a title="credativ's ClamAV support" href="http://www.credativ.co.uk/services/support/projects/spam-and-antivirus/clamav/">standalone service</a>, we offer checking of emails for viruses using Clam AntiVirus. As the threat from viruses is constantly evolving, the ClamAV project provides ongoing updates to its virus definitions, to ensure that users are as well-protected as is possible.</p>

<p>There are a number of different ways in which these updates can be installed on Debian. We chose to use freshclam, a daemon that checks for definition updates at a defined interval (48 times a day, or every 30 minutes, in our case). By and large, freshclam does what we need.  The virus definitions for our clients are kept up-to-date.</p>

<p>We know that the virus definitions are up-to-date because we have deployed Nagios, an enterprise-class monitoring solution for hosts, services, and networks.  As part of our <a title="Open Source Support Centre" href="http://www.credativ.co.uk/services/support/">OSSC</a> service, any of our clients can receive <a title="credativ's Nagios support" href="http://www.credativ.co.uk/services/support/projects/network/nagios/">Nagios support</a>, or make use of our Nagios hosting.  We have Nagios configured such that it checks that the virus definitions on the local machine are synchronised with those that the ClamAV project provide.  If they aren't, we receive an email notification.Now there are two problems with this solution. Firstly, Nagios checks for new virus definitions every 5 minutes, and freshclam updates the definitions every 30 minutes.  Secondly, freshclam has a habit of getting itself into a bind (normally as a result of a problem with mirrors.dat, the mirror cache) which means that updates stop altogether until we step in to fix the problem.</p>

<p>We can fix the first problem by setting Nagios to only check every 30 minutes.  That's not a problem. However, the second problem is harder to solve. Having to step in whenever there is a problem is fine (if inconvenient) during office hours, but what happens if the definition for a nasty new virus is released on Friday night, and freshclam is having a nutty? The client is unprotected for the weekend. What happens if there is also a problem with email, so we don't receive the notifications? We could end up with an unprotected network, perhaps even without ever knowing that this is the case.</p>

<h3>The Solution</h3>

<p>What we need is a way of updating the virus definitions as soon as we know that there are new ones, without needing to rely on freshclam to be working 100%. Nagios tells us when there are new definitions, so it would be really helpful if Nagios could do something to fix the problem.</p>

<p>The Nagios developers, in their wisdom, foresaw this exact use case, and included Event Handlers within the Nagios system.  These are commands, defined exactly as you would a normal command, that you can set to be called when the state of a host or service check changes. So our 'freshen_clamav' command definition looks something like:</p>
<pre class='brush: plain'>
define command {
        command_name    freshen_clamav
        command_line    sudo /root/nagios-plugins/update_clamav $SERVICESTATE$
}
</pre><p></p>

<p>There are a couple of interesting things here.  Firstly, the <tt>$SERVICESTATE$</tt> variable contains the state of the service that has changed (i.e. 'OK', 'WARNING', 'CRITICAL' or 'UNKNOWN').  Secondly, we are using 'sudo'.  The commands that we use to manipulate the ClamAV definitions (in /root/nagios-plugins/update_clamav) require root permissions and include 'rm'. Granting passwordless sudo access to 'rm' isn't a good idea, so granting it for this script is more secure.  Obviously this means that access to edit the script needs to be carefully limited.  For reference, the relevant line in the sudo configuration is:</p>

<p><code>nagios  ALL= NOPASSWD: /root/nagios-plugins/update_clamav</code></p>

<p>We use the above command definition in a service definition as follows:</p>
<pre class='brush: plain'>
define service {
        use                             generic-service
        host_name                       localhost
        service_description             ClamAV database freshness
        check_command                   check_clamav_freshness
        event_handler                   freshen_clamav
}
</pre><p><br />
The check_clamav_freshness command uses the check_clamav plugin.  The important line here is, of course, the event_handler line.  This is all that's needed to start using /root/nagios-plugins/update_clamav whenever the state of the service changes.</p>

<p>So now lets look at /root/nagios-plugins/update_clamav:</p>
<pre class='brush: plain'>
#!/bin/bash

set -eu

case $1 in
OK)
        ;;
WARNING)
        /etc/init.d/clamav-freshclam stop
        rm -f /var/lib/clamav/mirrors.dat
        freshclam || true
        /etc/init.d/clamav-freshclam start
        ;;
UNKNOWN)
        ;;
CRITICAL)
        /etc/init.d/clamav-freshclam stop
        rm -f /var/lib/clamav/mirrors.dat
        freshclam || true
        /etc/init.d/clamav-freshclam start
        ;;
esac
exit 0
</pre><p></p>

<p>This script is fairly simple. We use a bash case statement on the first argument (which you will recall is the value of $SERVICESTATE$) to do nothing if the service is OK or UNKNOWN.  If the service is WARNING or CRITICAL, we stop the freshclam daemon (so we can run freshclam ourselves), remove the mirrors database (as it is often the source of the problem), run freshclam ourselves and then restart the freshclam daemon.And now we have Nagios checking that the ClamAV definitions are up-to-date and, if they are not, updating them itself. This ensures that the client's machines are as secure as possible, with the latest virus definitions, whilst not requiring the attention of a credativ technician.</p>]]>
        
    </content>
</entry>

</feed>

