The value of the promisee in cfengine promises

blog-cfengine-logoA lesson I learnt today is: use promisees in cfengine promises, and you won’t regret it. In fact, I had a proof today that specifying a promisee is a very useful thing.

Let’s take a step back: a promisee is introduced by a -> sign, and according to the documentation the promisee is the abstract object to whom the promise is made. When CFEngine made its way in our trouble ticket, I started including a ticket number as a promisee every time a promise was created to address a reported issue.

Today I found out that, every time I deployed a change that caused firewall rules to be reloaded, ntpd was also restarted. I couldn’t understand why, so I checked the policies and found this:

      "/etc/init.d/ntp" -> "CLO-2313"
	  args       => "restart",
          ifvarclass => "ntp",
	  comment    => "Restart ntpd when the firewall is restarted" ;

CLO-2313 was a resolved ticket, and there I found out why I made such a decision more than one month ago, and why it was a good thing.

So… use promisees!

Welcome to syslog.me

This blog was originally part of my personal blog on My Opera. As time passed, I felt more and more the need to separate the two contents. Finally, here we are: syslog.me moves on from the Sysadmin-tagged content on My Opera.

This blog is hosted on WordPress. I tried hard to find a theme that was both good-looking and able to support technical content (like: not wrapping long lines of unformatted text, like source code). I ended up with the SemPress theme I am not really fond about, but was the bests compromise I could get. If you happen to spot a different theme that works better than this one, just tell me.

…and promise_summary.log met Solarized

Inspired by the blog post at nanard.org, I’ve spent a few days hacking on promise_summary.log and rrdtool, and I have finally something to show.

Let’s recap quickly: a file promise_summary.log in cfengine’s workdir (usually /var/cfengine) contains a summary of every agent run: when the run started and finished, which version of the policy has run, and how many promises (in percentage) were kept, repaired, and not repaired. The first thing I wanted were graphs for these metrics; a medium-term goal is to bring these metrics into some well known tool like Munin or Cacti — that will come later.

I chose to use RRDtool for many reasons; among all:

  • it takes care for both saving the data and making the graphs;
  • it saves the data at different resolutions, automatically;
  • all aspects of a graph are customizable, and different type of graphs can be embedded in the same picture

I had previous experience with RRDtool, and I knew the downsides of course, mainly: the odd, cryptic syntax. What I had forgotten since such a long time was that it’s actually easier than it looks 🙂 … Continue reading

Parsing promise_summary.log

In CFEngine's work directory there is a log file called promise_summary.log. Unsurprisingly, it contains a summary of how agent runs went in the past: how many promises were kept, how many repaired, and how many failed to be repaired. Some weeks ago a blog post on nanard.org showed how this file can be parsed to graph cfengine's activity, and I thought it could be a nice thing to do the same thing in Perl.

For those who never had a peek, the file looks like this:

bronto@murray:/var/cfengine$ tail promise_summary.log 
1367869877,1367869877: Outcome of version Community Failsafe.cf 1.0.0 (agent-0): Promises observed to be kept 95%, Promises repaired 0%, Promises not repaired 5%
1367869877,1367869905: Outcome of version MyOwnPC 1.0.16-1 (agent-0): Promises observed to be kept 97%, Promises repaired 3%, Promises not repaired 0%
1367870164,1367870164: Outcome of version Community Failsafe.cf 1.0.0 (agent-0): Promises observed to be kept 95%, Promises repaired 0%, Promises not repaired 5%
1367870164,1367870191: Outcome of version MyOwnPC 1.0.16-1 (agent-0): Promises observed to be kept 97%, Promises repaired 3%, Promises not repaired 0%
1367870450,1367870450: Outcome of version Community Failsafe.cf 1.0.0 (agent-0): Promises observed to be kept 95%, Promises repaired 0%, Promises not repaired 5%
1367870450,1367870475: Outcome of version MyOwnPC 1.0.16-1 (agent-0): Promises observed to be kept 97%, Promises repaired 3%, Promises not repaired 0%
1367870797,1367870797: Outcome of version Community Failsafe.cf 1.0.0 (agent-0): Promises observed to be kept 95%, Promises repaired 0%, Promises not repaired 5%
1367870797,1367870825: Outcome of version MyOwnPC 1.0.16-1 (agent-0): Promises observed to be kept 97%, Promises repaired 3%, Promises not repaired 0%
1367871083,1367871084: Outcome of version Community Failsafe.cf 1.0.0 (agent-0): Promises observed to be kept 95%, Promises repaired 0%, Promises not repaired 5%
1367871084,1367871111: Outcome of version MyOwnPC 1.0.16-1 (agent-0): Promises observed to be kept 97%, Promises repaired 3%, Promises not repaired 0%

The first thing, and I did it in some ten minutes, is to parse the file to extract the relevant information. Check this one-liner:

perl -F: -alne 'next if m{failsafe.cf}i ; my ($start,$finish) = split(",",$F[0],2) ; my $duration = $finish-$start ; my ($version) = m{version (.+) (} ; my ($kept,$rep,$notrep) = m{Promises observed to be kept (d+)%, Promises repaired (d+)%, Promises not repaired (d+)%} ; print join("t",$start,$duration,$version,$kept,$rep,$notrep)' promise_summary.log

Or, reformatted:

#!/usr/bin/perl -F: -aln

next if m{failsafe.cf}i ;

my ($start,$finish) = split(",",$F[0],2) ;
my $duration = $finish-$start ;
my ($version) = m{version (.+) (} ;
my ($kept,$rep,$notrep) = m{Promises observed to be kept (d+)%, Promises repaired (d+)%, Promises not repaired (d+)%} ;

print join("t",$start,$duration,$version,$kept,$rep,$notrep)

This parses the file and outputs the relevant information tab-separated.

The command line explained

  • -a turns on the "autosplit" feature, where the input is split (normally at spaces) and the chunks are put in the @F array; in this specific case however, the "-F:" switch will make Perl split at colons ":";
  • -l will make it so that newlines are added after each print;
  • -n will wrap the code around a while loop, reading from the file(s) given as argument, and put each line in the $_ "default" variable;
  • -e will execute the code given on the command line;

The code explained

  • we skip the lines generated by the failsafe policy
  • we split the first field (timestamps), and calculate the difference (that is: the duration of the run)
  • we match the version string
  • we match the percentage for kept, repaired, and not repaired promises;
  • we print the bunch in tab-separated format

This is just the start, of course. E.g.: rather than tab-separated values one could print the values in a format suitable to rrdtool, and then use rrdgraph to create the graphs… But that's for later, take care for now. Ciao!

A story of faulty hard disks, kernel panics, and broken pins

When I got a new laptop from my employer, I decided I wanted to use a pure GNOME 3 desktop. The only distribution to offer it out of the box was Fedora, which I didn't really want to use, so I took a completely different path: install Linux Mint Debian Edition with Cinammon, and install GNOME 3 on top of it.

And it is working great! On "my" Dell Latitude 6430u everything works but the Bluetooth adapter. I had some freezes from time to time, which I suspect are due to some bug in the video drivers, but it happened so rarely that it wasn't really a problem. Until yesterday. … Continue reading

Disabling SSL checks in recent versions of WWW::Mechanize

I've been scratching my head for a while: a script using WWW::Mechanize, that works perfectly on my workstation's Ubuntu 10.04 LTS, didn't want to work on my new laptop's Linux Mint Debian Edition. The scripts fetches content via HTTPS from an internal site of ours, that uses a certificate from our internal CA.

After checking some obvious stuff, I suspected that the reason was the SSL certificate issued by an unknown certification authority. A quick capture with wireshark confirmed that: "TLSv1 Record Layer: Alert (Level: Fatal, Description: Unknown CA)".

I needed to make WWW::Mechanize's less picky, but the man page didn't say anything about the problem, nor did the FAQ. Some more google'ing showed that the problem was one layer down: LWP::UserAgent (a fundamental component in WWW::Mechanize). As the man page puts it:

           "verify_hostname" => $bool
               When TRUE LWP will for secure protocol schemes ensure
               it connects to servers that have a valid certificate
               matching the expected hostname.  If FALSE no checks are
               made and you can't be sure that you communicate with
               the expected peer.  The no checks behaviour was the
               default for libwww-perl-5.837 and earlier releases.

               This option is initialized from the
               PERL_LWP_SSL_VERIFY_HOSTNAME environment variable.  If
               this environment variable isn't set; then
               "verify_hostname" defaults to 1.

So: the default behaviour has changed, and LWP::UserAgent, now defaults to be picky when it comes to SSL verifications. It's a good thing, but in my case it was breaking my toy.

The fix? Quick and simple: switch from:

my $mech = WWW::Mechanize->new( autocheck => 0 ) ;

to

my $mech = WWW::Mechanize->new( autocheck => 0, ssl_opts => { verify_hostname => 0 } ) ;

Enjoy!

How to create a debian package for Riak on Wheezy

Riak is a distributed database that we use in a project of ours. The project is being migrated from a difficult setup on Debian Squeeze to a easier one on Debian Wheezy; unfortunately, while an official Debian package for squeeze is available, one for Wheezy is not. None of the ubuntu packages works on Wheezy either, due to dependencies.

I have searched a lot to see if there was a way to create a Debian package for Riak 1.3.0 on Wheezy. I found a few references, but not a complete one. I finally succeeded in creating the package, and I am writing a four step guide here.

Step 1: install an handful of prerequisites:
As root (or via sudo, if it's already installed) run:

apt-get install libc6-dev build-essential debhelper git sudo devscripts erlang-nox erlang-reltool erlang-dev

Step 2: clone the git repository and checkout 1.3:

cd /usr/local/src
git clone git://github.com/basho/riak.git
cd riak
git checkout 1.3

Step 3: compile

make package RELEASE=1

Step 4: fetch the package
You'll find the package in package/packages. Now you can install it using dpkg.

Enjoy!