Apr 102014
 

One thing that the Puppet language doesn’t do – and apparently this is entirely by design – is iteration. There’s no way to loop a block – no foreach, while or repeat. While this function would seem to be a natural language construct, Puppet is about prototyping, and configuration should be specific, rather than derived. However, there are ways of performing an iteration, should it become necessary, and this is one example.

This example pertains to the AMANDA backup server software. It requires a definition for a sequence of virtual tapes. These are just empty directories that need to be created and then registered using the AMANDA “amlabel” command. All I wanted to do was to say to Puppet, “Create me n virtual disks, where n is an integer variable”. If it was a simple matter of creating an array [ 1..n ] and then passing this to a define, there wouldn’t be a problem, but there’s no way in Puppet to create a variable-length array. One can only do something like this:

$array = [ 1,2,3,4,5 ]

which is no use when the number of elements is not known.

But one simple way to accomplish a variable length sequence is through recursion. Consider this puppet define:

define amanda_create_slot ($backup_set, $slot_path, $slot_num ) {
  if "${slot_num}" > '0' {
    exec { "slot${slot_num}":
      creates => "${slot_path}/slot${slot_num}",
      user => "amandabackup",
      command => "/bin/mkdir $slot_path/slot${slot_num};
	/usr/sbin/amlabel $backup_set $backup_set-${slot_num} slot $slot_num"
    }
    $decrement = inline_template('<%= @slot_num.to_i - 1 %>')
    $amanda_create_slot { "slots-${decrement}": backup_set => $backup_set,
		                                slot_num => $decrement,
			                        slot_path => $slot_path }
  }	
}

It checks that the slot number passed to it is greater than zero, and if so, creates a slot with that index. It then decrements the argument “slot_num”, and then invokes itself again. It will continue to do this until the variable slot_num is reduced to zero, at which point the if-block will fail and the recursive loop will collapse.

In a manifest, this function is initially invoked like this:

amanda_create_slot { "slots": backup_set => Daily,
			      slot_num => "10",
			      slot_path => "/var/amanda/slots" }

}

The result will be a nice series of virtual tape slots, all numbered from 1 to 10.


Matt Parsons is a freelance Linux specialist who has designed, built and supported Unix and Linux systems in the finance, telecommunications and media industries.

He lives and works in London.

Jan 042013
 

Puppet configuration can quickly become very large, interrelated and unwieldy. Even the most restrained and discplined architect can easily let it get away from itself. As its spread out over numerous disparate files, often an overview of how everything’s interconnected can be useful. Fortunately, the Puppet agent has the ability to create .dot files, viewable with Graphwiz, which allows a node’s configuration to be visualized, and hopefully, to be understood.

To set this up, edit /etc/puppet/puppet.conf, [agent] section:

   graph = true
   graphdir = /var/lib/puppet/state/graphs

Run a puppet update:

   # puppetd -t --noop

This time, three “.dot” files will be written to the graphdir location:

   expanded_relationships.dot
   relationships.dot
   resources.dot

This .dot format is a text file readable by the Graphviz program. It’s available from the standard Ubuntu and Fedora repositories. Install it (preferably on your workstation), copy across the generated Puppet agent .dot files and convert the dot files into pretty PNG image files like with the dot program which is installed as part of Graphviz:

   # dot -Tpng resources.dot -o resources.png

And similarly for the other two files. The generated image contains a map of all the configuration resources and/or relationships of the Puppet client.

One can also view the .dot files directly, as they are text. In fact, one could also trawl the Puppet configuration root and generate .dot files manually, as described in this example on this blog.

After using Graphviz to create pretty configuration visualizations, these maps may bring about some clarity regarding the Puppet config, or possibly identify a circular dependency. Equally, the map may be convoluted and unreadable, which may be a reason to overhaul one’s Puppet configuration.


Matt Parsons is a freelance Linux specialist who has designed, built and supported Unix and Linux systems in the finance, telecommunications and media industries.

He lives and works in London.

May 022012
 

There’s an annoying and confusing error that can come up from time to time when performing a Puppet update from the client. In particular when running the update for the first time.

It looks like this:

# puppetd --test
err: Could not retrieve catalog from remote server: 
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: 
certificate verify failed
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
 

This is saying that the verification check of the certificate against the keys has failed.

Solution

This could mean one of two things. The most common reason, particularly with a newly kickstarted host is that the discrepancy is too large between the time on the client and Puppet server. Or, the certificate on the client just needs to be regenerated.

Check the Date

Simply confirm this with the date command on both :

  # date
  Wed May 2 12:34:00 BST 2012

And either update manually, or using the ntpdate command.

The second reason is that the certificate on the client doesn’t match that on the server. The easiest way to remedy this is to clear both certificates and start again like this:

Remove client certificate

Remove all SSL information from the Puppet client configuration:

  # find /var/lib/puppet -type f -print0 |xargs -0r rm

Clean from server the client certificate

Where the fully-qualified domain name of the problematic client is “client.example.com”:

  # puppetca --clean 
 

Re-execute client Puppet run

Rerun the Puppet client update:

  # puppetd --test

If all goes well, the Puppet client should successfully verify its certificate and accept the updates, as it should.


Matt Parsons is a freelance Linux specialist who has designed, built and supported Unix and Linux systems in the finance, telecommunications and media industries.

He lives and works in London.