Pros and cons using Puppet’s $::osfamily instead of $::operatingsystem Fact

Once you read the Puppet Style Guide, you should know how to write well structured manifests, with the modest indentation, spacing, arrow alignment, quoting and so on. Well, I think there are lots of other things you better should care. For this time, it’s about when to use $::osfamily and when better to stay with the $::operatingsystem fact.

Pros

The key benefit of using $::osfamily is that you don’t end up forking your favorite Puppet module on GitHub to add the eleventh RedHat derivate:

1
2
3
4
5
6
7
8
9
10
11
case $::operatingsystem {
   'RedHat', 'CentOS', 'Scientific', . . . , 'OracleLinux', 'OEL': {
     # do something RHEL specific
   }
   'ubuntu', 'debian': {
     # do something Debian specific 
   }
   default: {
     # ...
   }
}

Instead you would use:

1
2
3
4
5
6
7
8
9
10
11
case $::osfamily {
   'redhat': {
     # do something RHEL specific
   }
   'debian': {
     # do something Debian specific 
   }
   default: {
     # ...
   }
}

It allows you to write cleaner manifests and works well for common tasks. You still have the choice to handle details via $::operatingsystem the more complex your classes become.

Cons

There are disadvantages of course: You claim tosupport an Operating-System you might haven’t even heard of. But my experience is that most people are using the EPEL repositories anyway. So wouldn’t it be enough to test your modules against EPEL? And yes: you really should test your manifests!

Support for Facter < 1.6.1

The $::osfamily fact was introduced with Facter 1.6.1. There is a simple workaround for older versions. I found this solution in the description of the puppetlabs-mysql Module. Just put this into your site.pp (before any node definition):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if ! $::osfamily {
  case $::operatingsystem {
    'RedHat', 'Fedora', 'CentOS', 'Scientific', 'SLC', 'Ascendos', 'CloudLinux', 'PSBM', 'OracleLinux', 'OVS', 'OEL': {
      $osfamily = 'RedHat'
    }
    'ubuntu', 'debian': {
      $osfamily = 'Debian'
    }
    'SLES', 'SLED', 'OpenSuSE', 'SuSE': {
      $osfamily = 'Suse'
    }
    'Solaris', 'Nexenta': {
      $osfamily = 'Solaris'
    }
    default: {
      $osfamily = $::operatingsystem
    }
  }
}

It defines $::osfamily if not available.

Forwarding IPv6 Traffic from WAN to LAN with OpenWRT

We’re starting from the premise that you already enabled IPv6. If not so, this will help you to switch it on:

OpenWRT Attitude Adjustment 2012.09 warning: There is an ongoing discussion regarding the AICCU init script. If you can, stay with OpenWRT Backfire 2010.3.

I’m using SixxS tunnels to enable IPv6. My /etc/config/network looks like this:

1
2
3
4
5
6
7
config interface 'lan'
  # ...
  option ip6addr '2001:my:subnet:prefix::1/64'

config 'interface' 'wan6'
  # ...
  option 'ip6addr' '2001:my:end:point::2'

To enable that your local server is reachable via SSH (port 22) add this rule to /etc/config/firewall straight after the standard IPv6 rules:

1
2
3
4
5
6
7
8
config rule
       option 'src' 'wan6'
       option 'proto' 'tcp'
       option 'dest_port' '22'
       option 'dest_ip' '2001:your:servers:global:ipv6:address:####:####'
       option 'family' 'ipv6'
       option 'target' 'ACCEPT'
       option 'dest' 'lan' 

Also make sure that you installed the ip6tables Package, then restart the firewall with /etc/init.d/firewall restart and test your setup.

Run Puppet via Cron

While deploying Puppet on several Ubuntu machines, everything was fine until Nagios started sending out warnings about high memory and high CPU usage, caused by the Puppet agent process. Related Bug-reports are:

  • Bug #1395 puppet memory usage
  • Bug #12310 Significant slow down in 2.7.10 apply
  • Bug #995719 process_name.rb removed in 2.7.11 but still provided by puppet-common

A common workaround is to run the Puppet agent via Cron. Take a look at the Cron Patterns Wiki page, but don’t get too confused. Until Puppet 2.6, simply run:

1
/usr/sbin/puppetd --no-daemonize --onetime

With Puppet 2.7 it slightly changed to:

1
/usr/bin/puppet agent --no-daemonize --onetime

Furthermore you won’t run all the agents at the same time. So the next step is to plan the execution time. To run Puppet every 30 minutes, use fqdn_rand(30) to generate a value between 0 and 29 for the first, and add 30 more to get the second point of time:

1
2
$min1 = fqdn_rand(30)
$min2 = $min1 + 30

The fqdn_rand function will generate the same value each time you call it, dependent on the FQDN of the actual host. Finally, the file resource will look like this:

1
2
3
4
5
6
7
file { '/etc/cron.d/puppet-cron':
  ensure  => 'present',
  content => "$min1,$min2 * * * * root /usr/bin/puppet agent --no-daemonize --onetime\n",
  mode    => '0644',
  owner   => 'root',
  group   => 'root',
}

As a side effect, this will solve another problem for you. Have you ever tried to reconfigure Puppet via Puppet? Currently there is no way telling Puppet to stop, re-read it’s configuration and start again (e.g. via sending the SIGHUP signal). This related Bug-report was added two years ago:

  • Bug #7273 - Add additional signals for restarting Puppet agent runs