Client File Access

The infrastructures.org folks list two primary goals of what they call “client file access“: first, consistent access to users’ home directories, and second, consistent access to end-user applications. Some of the things they warn against, such as automounters and the /net directory, we never thought of using to begin with. Their need to consider systems with limited disk space and a need to mount a software share via NFS is less of an issue with us, too: disks large enough to hold our regular software load are relatively cheap, so there shouldn’t be much of a problem there. And since we’re supposed to be deploying applications consistently via Puppet, there shouldn’t be any inconsistency in where an application is installed. As far as consistent access to the home directories, we accomplish this with a two-pronged solution in Puppet — one on the file server, and one on the clients:

On the Debian file server, we include the following class:

class nfs-server {
  package { nfs-kernel-server: ensure => installed }

  file { exports:
    path => $operatingsystem ? {
      default => "/etc/exports"
    },
    owner => root, group => root, mode => 644,
    source => "puppet://gold.cae.tntech.edu/files/apps/nfs-server/exports",
    require => Package[nfs-kernel-server]
  }

  service { nfs-kernel-server:
    ensure => running,
    enable => true,
    hasstatus => true,
    subscribe => [Package[nfs-kernel-server], File[exports]]
  }
  service { portmap:
    ensure => running,
    enable => true,
  }
}

We also include the following in its node definition:

    file {
        "/etc/exports.d":
        source  => "puppet:///files/apps/nfs-kernel-server/exports.d",
        ensure  => directory,
        ignore  => ".svn",
        purge   => true,
        recurse => inf;
    }

    concatenated_file {
        "/etc/exports":
            dir => "/etc/exports.d";
    }

Each file dropped in /etc/exports.d is a fragment of /etc/exports. Right now, we’re using one fragment per exported filesystem. As an example, here’s /etc/exports.d/_opt_solaris_stow:

/opt/solaris/stow \\
        149.149.254.12(rw,sync,no_root_squash) \\
        149.149.254.13(rw,sync,no_root_squash) \\
        149.149.254.14(rw,sync,no_root_squash) \\
        149.149.254.15(rw,sync,no_root_squash) \\
        149.149.254.220(rw,sync,no_root_squash)

David Schmitt’s concatenated_file definition combines all the export fragments into one /etc/exports file:

define concatenated_file ($dir, $mode = 0644, $owner = root, $group = root)
{
    file {
        $name:
            ensure   => present,
            checksum => md5,
            mode     => $mode,
            owner    => $owner,
            group => $group;
    }
    exec { "find ${dir} -maxdepth 1 -type f ! -name '*puppettmp' -print0 | sort -z | xargs -0 cat > ${name}":
        refreshonly => true,
        subscribe   => File[$dir],
        alias       => "concat_${name}",
    }
}
define concatenated_file_part ($dir, $content = '', $ensure = present,
                               $mode = 0644, $owner = root, $group = root) {
    file { "${dir}/${name}":
        ensure  => $ensure,
        content => $content,
        mode    => $mode,
        owner   => $owner,
        group   => $group,
        alias   => "cf_part_${name}",
    }
}

On the client side, we just make sure we can mount the NFS share. For example:

    file {
        "/home/CAE":
            ensure => directory,
            owner  => root,
            group  => root,
            mode   => 755,
    }
    mount { "/home/CAE":
        require => File["/home/CAE"],
        atboot  => true,
        fstype  => "nfs",
        device  => "files.cae.tntech.edu:/home/CAE",
        ensure  => mounted,
        options => "defaults",
        dump    => "0",
        pass    => "0",
    }
    package { "nfs-common": ensure => installed }

Leave a comment

Your email address will not be published. Required fields are marked *