Tuning File Systems Using a Custom Fact

Steve Maddison
04-01-2014

A project on which I was working required that any ext2, ext3 or ext4 file systems on Linux hosts be tuned in a particular way. Although this is easy enough for any file systems managed by Puppet itself, Puppet doesn’t know anything about file systems created during the installation of the OS.
One way to retrieve this information is to use a custom fact to examine the agent system. The following code does this by going through the contents of /proc/mounts and adding any block devices with file systems of the appropriate type to a list. This list is returned in the contents of the custom fact.
The code needs to be placed in a file named ext_filesystems.rb in the lib/facter subdirectory of a Puppet module. Assuming plugin sync is enabled for the agent, it will be distributed automatically on the next run.

#
# List mounted ext[234..n] file systems on Linux hosts. 
#
Facter.add(:ext_filesystems) do
    # It doesn't make sense to run this on non-Linux hosts.
    confine :kernel => 'Linux' 
    setcode do
        ext_filesystems = []
        if File.exists?('/proc/mounts')
            # Go through each line of the /proc/mounts (pseudo)file. 
            Facter::Util::Resolution.exec('cat /proc/mounts').each_line do |line|
                mount = line.split(' ')
                # If third field is ext add the first field to our list. 
                if mount[2].match(/^ext\d+$/)
                    ext_filesystems << mount[0]
                end 
            end
        end
        # Return the list, separated by commas.
        ext_filesystems.join(',') 
    end
end

The fact then appears, just as any other, like a variable in the top-level namespace. As the fact may only return a string, we need to split out the individual elements ourselves. If you then create a resource type to apply your specific tuning, this is easily applied to all file systems like this:

define tune_fs() {
    # Run tune2fs(8) with your specific tuning options. 
    exec { "/sbin/tune2fs [OPTIONS] ${title}":
        # An "unless" can be used to ensure the command isn't executed
        # unnecessarily. Adjust "Parameter" and "value" accordingly.
        unless => "/sbin/tune2fs -l ${title} | grep '^Parameter:' | grep value", 
    }
}
# Split out the fact string into an array.
$filesystems = split($::ext_filesystems, ',')
if $filesystems {
    # Define a tune_fs resource for each.
    tune_fs { [$filesystems]: }
}

Note that as facts are evaluated at the beginning of a run, file systems created during the run itself will not get tuned until they are mounted and another run is performed. This can be avoided by explicitly defining tune_fs resources for new file systems, although care must then be taken to prevent duplicate resources from being defined.

LEAVE A REPLY

you might also like