I really like the idea of using Puppet and similar tools for automating as much of server configuration as possible. As I slowly “puppet-ify” things I find the need to sometimes add custom facts to facter, the part of Puppet that provides information about the host system.
This would be easy were it not for the small problem that custom facts are written in Ruby, a language I’m not fluent in, although this gives me a reason to learn the basics. I’m familiar with various other languages so it shouldn’t be that hard, here’s what I’ve managed to cobble together so far…
The first fact returns a list of the Linux software RAID block devices on the host. This is just parsing the /proc/mdstat
file that should exist on any Linux distribution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Facter.add('software_raid') do confine :kernel => :linux setcode do devices = [] if FileTest.exists?('/proc/mdstat') File.open('/proc/mdstat', 'r') do |f| while line = f.gets if line =~ /^(md\d+)/ devices.push($1) end end end end devices.sort.join(',') end end |
This next recipe creates one fact per bonded network interface on Linux, containing the list of enslaved interfaces. This is specific to CentOS, Fedora, Red Hat or any other similar distributions that use the /etc/sysconfig
configuration files:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | require 'find' Facter.value(:interfaces).split(',').each do |interface| if interface =~ /^bond\d+$/ Facter.add("#{interface}_slaves") do confine :kernel => :linux, :operatingsystem => %w{CentOS Fedora RedHat} setcode do slaves = [] Find.find('/etc/sysconfig/network-scripts') do |path| if FileTest.directory?(path) next else if path =~ /ifcfg-(.+)$/ device = $1 File.open(path, 'r') do |f| while line = f.gets if line =~ /^MASTER\s*=\s*#{interface}$/ slaves.push(device) end end end end end end slaves.sort.join(',') end end end end |
I use these two facts within my Puppet manifests as the basis for configuring additional Nagios tests to make sure these two pieces of functionality are working correctly.
Tags: Custom Facts, Facter, Ruby
Hello,
Thank you for the nice post!
I decided to improve upon your bonding Facter fact to make it less dependent on a particular Linu distribution.
The code is available here:
https://github.com/kwilczynski/facter-facts/blob/master/bonding.rb
Let me know whether it works for you and what you think! 🙂
KW
Thanks for the reply.
Your code logic looks fine, although I don’t have a machine with bonding to hand to test it with. I think /sys is maybe preferred to /proc these days by the Linux people but /proc isn’t going to disappear anytime soon.
Matt
Hello,
You are right about /sys, although it is a little bit of a pain to work with an /proc was convenient.
I will look towards a possible re-factor.
Said that, /proc is a little bit like IPv4 — here to stay for some time 🙂
KW