Deploying SaltStack to SLES 10 from source, using puppet

Daniel Schutterop
01-05-2014

SuSe Linux Enterprise Server 10 (Sles10 from hereon) is old, ancient even, and therefor absolete. Or is it?
Unortunately there are still a few companies running Sles10, and I suspect that will be the case for the near future. The only thing we can do is to make an icky situation bareable. Hence the deployment of SaltStack on Sles10, using puppet as the deplopyment mechanism of choice.

Of course I would love to ensure => ‘installed’ all the required packages, about as much as I would like my coffee to teleport itself to my desk on monday mornings. The reality however dictates it’s own terms (and leaves me waiting in line at the coffee machine each monday morning). Anyway, since it’s impossible to use the package manager to install the software for us, we need to build each dependency by hand. No biggie, if it weren’t for puppet that is.

Since puppet is a declarative language and we define the state in which we would like to encounter the machine after a puppet run, we can’t just tell it to unpack sources, configure it, make it and finally make install the stuff we want. Well, we could, but not without making the recipies looking way too complex and violating a buch of best-practices (which we will do anyway 😉 ).

If by any chance you really, really, really want to build the software by hand, without the intervention of puppet or any other deployment mechanism, here are the sources I used:

  • Python-2.7.5
  • setuptools-3.3
  • Jinja2-2.6
  • PyYAML-3.10
  • msgpack-pure-0.1.3
  • msgpack-python-0.4.1
  • zeromq-4.0.4
  • pyzmq-14.0.1
  • pyasn1-0.1.7
  • rsa-3.1.4
  • swig-3.0.0 (using the option –without-pcre at ./configure time)
  • M2Crypto-0.22.3
  • pycrypto-2.6.1
  • salt-develop

But since we’re using puppet, we have already done this using the following recipes:

  • init.pp
  • buildsource.pp
  • buildpython.pp

The init.pp contains the saltstack class, the buildsource.pp and buildpython.pp both contain defines to be able to construct the software without creating a mile-long init.pp

saltstack class

Heads up: in the init.pp (Sles10 part) we feed the source modules to the saltstack::buildsource define, which handles the build process by using a few execs (which are evil, by the way). The define checks if it’s allowed to execute by checking if the target file exists.
For example

$packageFile = 'salt_sles10'
$buildDir = '/tmp/saltstack'
$packageDir = "${buildDir}/${packageFile}"
$zeroMQSource = 'zeromq-4.0.4'
$zeroMQOut = '/usr/local/lib/libzmq.a'
saltstack::buildsource { "${packageDir}/${zeroMQSource}" :
result => $zeroMQOut,
} ->

tries to build zeroMQ by feeding /tmp/saltstack/salt_sles10/zeromq-4.04 (source directory) and /usr/local/lib/libzmq.a (one of the files created in the build process) to the saltstack::buildsource define. If the result file exists, there’s nothing to be done. If it’s not there, it’ll be built. We do this for each module we need built.

init.pp

# == Class: saltstack
#
# == Version: v1.13
#
# SaltStack puppet module.
#
# Example module to deploy a saltstack minion
# to a SLES machine
#
# However icky; it builds the modules from source
# for SLES 10 since we don't have a package manager
# Available
#
# This module relies on two defines:
# buildsource.pp (To build a module from source)
# buildpython.pp (To build a python module from source)
#
# === Parameters
# No external parameters
#
# === Variables
#
# $::salt_master 
# $::operatingsystem
# $::operatingsystemrelease
# $::fqdn
#
# === Authors
#
# D. Schutterop
#
# === Copyright
#
# Copyright 2014
#
class saltstack {
include repositories
if (!$::salt_master) {
fail('Top scope variable salt_master undefined!')
}
if ($::operatingsystem == 'SLES') {
if ($::fqdn == $::salt_master) {
package { 'salt':
ensure => 'installed',
}
package { 'salt-minion':
ensure => 'absent',
}
package { 'salt-master':
ensure => 'installed',
require => Package['salt'],
}
service { 'salt-master' :
ensure => 'running',
enable => true,
}
}
else {
if ($::operatingsystemrelease =~ /11/) {
package { 'salt':
ensure => 'installed',
}
package { 'salt-minion':
ensure => 'installed',
require => Package['salt'],
}
file { '/etc/salt/minion' :
ensure => 'present',
content => template("${module_name}/minion.erb"),
require => Package['salt-minion'],
notify => Service['salt-minion'],
}
service { 'salt-minion' :
ensure => 'running',
enable => true,
require => File['/etc/salt/minion'],
}
} else {
$buildDir = '/tmp/saltstack'
$configDir = '/etc/salt'
$pythonLibDir = '/usr/local/lib/python2.7/site-packages/'
$packageFile = 'salt_sles10'
$packageType = 'tar.gz'
$packageDir = "${buildDir}/${packageFile}"
$pythonSource = 'Python-2.7.5'
$pythonOut = '/usr/local/bin/python'
$setupToolsSource = 'setuptools-3.3'
$setupToolsOut = "${pythonLibDir}/setuptools.pth"
$Jinja2Source = 'Jinja2-2.6'
$Jinja2Out = "${pythonLibDir}/Jinja2-2.6-py2.7.egg/jinja2/tests.py"
$pyYamlSource = 'PyYAML-3.10'
$pyYamlOut = "${pythonLibDir}/PyYAML-3.10-py2.7.egg-info"
$msgPackPureSource = 'msgpack-pure-0.1.3'
$msgPackPureOut = "${pythonLibDir}/msgpack_pure-0.1.3-py2.7.egg"
$msgPackPySource = 'msgpack-python-0.4.1'
$msgPackPyOut = "${pythonLibDir}/\
msgpack_python-0.4.1-py2.7-linux-x86_64.egg"
$zeroMQSource = 'zeromq-4.0.4'
$zeroMQOut = '/usr/local/lib/libzmq.a'
$pyzmqSource = 'pyzmq-14.0.1'
$pyzmqOut = "${pythonLibDir}/pyzmq-14.0.1-py2.7.egg-info"
$pyasn1Source = 'pyasn1-0.1.7'
$pyasn1Out = "${pythonLibDir}/pyasn1-0.1.7-py2.7.egg"
$rsaSource = 'rsa-3.1.4'
$rsaOut = "${pythonLibDir}/rsa-3.1.4-py2.7.egg"
$swigSource = 'swig-3.0.0'
$swigOut = '/usr/local/bin/swig'
$m2cryptoSource = 'M2Crypto-0.22.3'
$m2cryptoOut = "${pythonLibDir}/M2Crypto-0.22.3-py2.7-linux-x86_64.egg"
$pyCryptoSource = 'pycrypto-2.6.1'
$pyCryptoOut = "${pythonLibDir}/pycrypto-2.6.1-py2.7.egg-info"
$saltSource = 'salt-develop'
$saltOut = '/usr/local/bin/salt'
file { [$buildDir ,$configDir] :
ensure => 'directory',
} ->
file { "${buildDir}/${packageFile}.${packageType}" :
ensure => 'present',
source => "puppet:///modules/${module_name}/${packageFile}.${packageType}",
} ->
exec { "unpack ${packageFile}" :
cwd => $buildDir,
path => ['/bin','/usr/bin'],
command => "tar -xzvf ${buildDir}/${packageFile}.${packageType}",
unless => ['test -f /usr/local/bin/salt']
} ->
saltstack::buildsource { "${packageDir}/${pythonSource}":
result => $pythonOut,
} ->
saltstack::buildpython { "${packageDir}/${setupToolsSource}":
result => $setupToolsOut,
} ->
saltstack::buildpython { "${packageDir}/${Jinja2Source}":
result => $Jinja2Out,
} ->
saltstack::buildpython { "${packageDir}/${pyYamlSource}":
result => $pyYamlOut,
} ->
saltstack::buildpython { "${packageDir}/${msgPackPureSource}":
result => $msgPackPureOut,
} ->
saltstack::buildpython { "${packageDir}/${msgPackPySource}" :
result => $msgPackPyOut,
} ->
saltstack::buildsource { "${packageDir}/${zeroMQSource}" :
result => $zeroMQOut,
} ->
saltstack::buildpython { "${packageDir}/${pyzmqSource}" :
result => $pyzmqOut,
} ->
saltstack::buildpython { "${packageDir}/${pyasn1Source}" :
result => $pyasn1Out,
} ->
saltstack::buildpython { "${packageDir}/${rsaSource}" :
result => $rsaOut,
} ->
saltstack::buildsource { "${packageDir}/${swigSource}" :
result => $swigOut,
options => '--without-pcre',
} ->
saltstack::buildpython { "${packageDir}/${m2cryptoSource}" :
result => $m2cryptoOut,
} ->
saltstack::buildpython { "${packageDir}/${pyCryptoSource}" :
result => $pyCryptoOut,
} ->
saltstack::buildpython { "${packageDir}/${saltSource}" :
result => $saltOut,
} ->
file { '/etc/salt/minion' :
ensure => 'present',
content => template("${module_name}/minion.erb"),
notify => Service['salt-minion'],
} ->
file { '/etc/init.d/salt-minion' :
ensure => 'present',
source => "puppet:///modules/${module_name}/salt-minion",
mode => '0755'
} ->
exec { 'Install minion service':
path => ['/sbin', '/bin', '/usr/bin'],
command => 'chkconfig --add salt-minion',
require => File['/etc/init.d/salt-minion'],
onlyif => 'test `/sbin/chkconfig --list | \
/bin/grep salt-minion | /usr/bin/wc -l` -eq 0',
} ->
service { 'salt-minion' :
ensure => 'running',
enable => true,
require => [ File['/etc/init.d/salt-minion'],
Exec['Install minion service'] ],
}
}
} # fi salt_master
} # fi operating system
} # End class

buildsource.pp

# == Class: saltstack
# == Define: buildsource
#
# == Version: v1.14
#
# Buildsource builds software from source
#
# Normally, we wouldn't build modules in puppet
# but this desperate case calls for a
# desperate measure
#
# === Parameters
#
# === Variables
#
# === Authors
#
# D. Schutterop
#
# === Copyright
#
# Copyright 2014
#
define saltstack::buildsource(
$dir = $title,
$result = $creates,
$user = 'root',
$path = '/usr/bin:/bin',
$timeout = 0,
$options = ''
) {
$options_real = join([$options], ' ')
Exec {
user => $user,
cwd => $dir,
timeout => $timeout,
path => $path,
}
exec { "./configure in ${dir}":
command => "${dir}/configure ${options_real}",
unless => "test -f ${result}"
} ->
exec { "make in ${dir}":
cwd => $dir,
unless => "test -f ${result}",
command => 'make',
} ->
exec { "make install in ${dir}":
cwd => $dir,
unless => "test -f ${result}",
command => 'make install',
}
}

buildpython.pp

# == Class: saltstack
# == Define: buildpython
#
# == Version: v1.13
#
# Buildpython module builds, well, python modules
#
# Normally, we wouldn't build modules in puppet
# but this desperate case calls for a
# desperate measure
#
# === Parameters
#
# === Variables
#
# === Authors
#
# D. Schutterop
#
# === Copyright
#
# Copyright 2014
#
define saltstack::buildpython(
$dir = $title,
$result = $creates,
$user = 'root',
$path = '/usr/bin:/bin',
$timeout = '0',
$options = '',
) {
Exec {
user => $user,
cwd => $dir,
timeout => $timeout,
path => $path,
}
exec { "Python build in ${dir}":
path => ['/usr/local/bin', '/usr/bin', '/bin'],
cwd => $dir,
command => 'python setup.py install',
unless => "test -f ${result}",
}
}

Notes for Editor, PLEASE DELETE BEFORE PUBLISHING!

Hi folks,
Here’s my contribution for the month of may, deploying saltstack on Sles10. Since nobody ‘ll ever catch this, just let me point out that all included code passed all possible validity checks and is sane.

LEAVE A REPLY

you might also like