Thursday, January 5, 2012

32-bit Puppet RPM's & SRPM's For AIX - Howto Build

Background:

This document will cover some suggestions for how to get puppet running on an AIX system.  We will create an environment on AIX 6.1 TL6 that will allow us to compile and or package in RPM zlib, openssl, ruby, facter, and finally puppet.   This recipe yielded working packages on my test systems but your mileage my vary.  This is my first adventure into the AIX world, so I really can't guarantee that these RPMS will work anywhere else, but I hope they do.  If nothing else I hope someone can benefit from the SPEC files and SRPM's for their own environment.

I was unable to find much information on howto get puppet running on AIX, so hopefully this helps someone who is interested in running the puppet agent on AIX and was having similar struggles getting puppet working.

My goal was to try to separate puppet from the rest of the filesystem with all application dependencies (where possible and practical) living in /opt/puppet except for the configuration files which would live in /etc/puppet.  I was only interested in running the puppet agent and had no interest in an AIX pupetmaster.

I also wanted to stick with GCC, and much thanks goes to Michael Perzl for his excellent documents about how-to setup a sane compiler environment for GCC on AIX.  And also thanks to the man for maintaining a diverse set of GNU and open source packages on AIX.



For the impatient:

  32-bit RPM's Compiled on AIX6.1

        32-bit SRPM's Used To Compile The Above RPM's




      Prerequisite Packages and Software:


      Here is the OS level I started out with:
      $ oslevel -r
      6100-06

      $ oslevel -s
      6100-06-06-1140

      We need to install the libm package:

      $ lslpp -l | grep -i bos.adt.libm
       bos.adt.libm               6.1.6.0  APPLIED    Base Application Development

      We also need to install this APAR or bring your system up to AIX 6.1 TL6 SP6 so we don't suffer from a GCC assembler error:
      http://www.perzl.org/aix/index.php?n=Main.GCCAssemblerError

      My fresh install of AIX 6.1 had the following RPM's on it;
      $ rpm -qa
      cdrecord-1.9-7
      mkisofs-1.13-4
      tcl-8.4.7-3
      tk-8.4.7-3
      expect-5.42.1-3
      TWeagent-7.7.0-0
      AIX-rpm-6.1.6.15-2


      Next we need to install the following RPM's:


      $ rpm -ivh make-3.80-1.aix5.1.ppc.rpm
      $ rpm -ivh gcc-4.2.0-3.aix6.1.ppc.rpm
      $ rpm -ivh libgcc-4.2.0-3.aix6.1.ppc.rpm
      $ rpm -ivh db-3.3.11-4.aix5.1.ppc.rpm

      I was able to download the above rpms from IBM here:
      http://www-03.ibm.com/systems/power/software/aix/linux/toolbox/ezinstall.html



      The Build Environment:

      First we setup topdir in our rpmmacros file like normal
      $ cat ~/.rpmmacros
      %_topdir   /home/nbausc0/rpmbuild

      The RPM error messages from the default version of RPM were not very helpful.  If you get an error like this:

      $ rpm -ba zlib-1.2.5-1.shc.spec
      Unable to open temp file.

      Then take a look at your rc environment for RPM with the following:
      $ rpm --showrc | grep tmp
      -14: _tmppath   %{_var}/tmp


      I tried to include the required compiler/linking environment variables in the SRPM spec files that would yield me with a usable package. If you are dealing with another environment and what I have done does not make sense, I encourage you to read the following page from perzl.org and adjust things to meet your needs.
      http://www.perzl.org/aix/index.php?n=Main.Instructions#sourcecode


      Because of differences in the rpm spec files from Linux environments and the environment we have on AIX it is sometimes nice to extract the final RPM to make sure there are no files going to a location you had not intended.
      $ rpm -ivh cpio-2.5-1.aix5.1.ppc.rpm
      $ rpm2cpio zlib-1.2.5-1.puppet.local.aix6.1.ppc.rpm | /opt/freeware/bin/cpio -idmv


      OpenSSL Linking - rpath and -blibpath

      I was curious how others had linked the openssl binaries in the other packages for openssl on AIX and I found this:

      $ ldd /usr/bin/openssl
      /usr/bin/openssl needs:
               /usr/lib/libc.a(shr.o)
               /usr/lib/libpthreads.a(shr_comm.o)
               /usr/lib/libpthreads.a(shr_xpg5.o)
               /usr/lib/libcrypto.a(libcrypto.so.0.9.8)
               /usr/lib/libssl.a(libssl.so.0.9.8)
               /unix
               /usr/lib/libcrypt.a(shr.o)

      $ ldd /opt/freeware/bin/openssl
      /opt/freeware/bin/openssl needs:
               /usr/lib/threads/libc.a(shr.o)
               /usr/lib/libpthreads.a(shr_comm.o)
               /usr/lib/libpthreads.a(shr_xpg5.o)
               /opt/freeware/lib/libcrypto.a(libcrypto.so.1.0.0)
               /opt/freeware/lib/libssl.a(libssl.so.1.0.0)
               /unix
               /usr/lib/libcrypt.a(shr.o)
               /usr/lib/threads/libc.a(shr_64.o)
               /usr/lib/libpthreads.a(shr_xpg5_64.o)
               /usr/lib/libcrypt.a(shr_64.o)

       
      I experimented with 64-bit and 32-bit builds but ran into an unknown issue somewhere between openssl and ruby so I dropped 64-bit for now.  I learned about "-blibpath:<colon separated path>" which is the Linux equivalent of -rpath to force my application to look for dynamic libraries in a specific directory.  This posting from the postfix mailing list was very helpful in understanding linking differences between linking on AIX and Linux.

      The final openssl binary looks like this:

      $ ldd /opt/puppet/pup-openssl/bin/openssl
      /opt/puppet/pup-openssl/bin/openssl needs:
               /usr/lib/libc.a(shr.o)
               /usr/lib/libpthreads.a(shr_xpg5.o)
               /unix
               /usr/lib/libcrypt.a(shr.o)
               /usr/lib/libpthreads.a(shr_comm.o)



      Ruby Linking - and libgcc_s.a

      My goal was to compartmentalise puppet so that changes to the system's openssl/zlib/etc. would not cause any adverse effects on puppet's operation.  I did not however pull libgcc_s.a into my configuration.  Many examples I saw online suggested creating a symlink for libgcc_s.a in /opt/freeware/lib but I decided against this.

      To try to keep from changing anything in /opt/freeware, yet still allowing ruby to reference libgcc_s.a I have the pup-openssl RPM create symbolic link where the ruby apps and libraries are already setup to look for libs /opt/puppet/pup-openssl/lib/.


      The spec file for pup-openssl does something like this:

      $ ln -s /opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.2.0/libgcc_s.a /opt/puppet/pup-openssl/lib/libgcc_s.a



      My thinking here was that if my version of libgcc changed I could correct this by removing/reinstalling the pup-openssl RPM or modifying the symlink.  Maybe this was a really bad idea and I guess time will tell.

      Below we can see that ruby's openssl.so library is looking at /opt/puppet/pup-openssl/lib/libgcc_s.a



      $ ldd /opt/puppet/pup-puppet/lib/ruby/1.8/rs6000-aix/openssl.so
      /opt/puppet/pup-puppet/lib/ruby/1.8/rs6000-aix/openssl.so needs:
               /usr/lib/libdl.a(shr.o)
               /usr/lib/libc.a(shr.o)
               /opt/puppet/pup-openssl/lib/libgcc_s.a(shr.o)
               /unix
               /usr/lib/libcrypt.a(shr.o)



      Puppet Configuration File

      The pup-puppet package does not install a puppet.conf file. I decided to create my own pup-puppet-conf RPM to distribute my puppet.conf.  Below is what the puppet config file looks like.

      $ cat /etc/puppet/puppet.conf
      [main]
      vardir = /opt/puppet/var
      logdir = /opt/puppet/log
      rundir = /opt/puppet/run
      modulepath = /etc/puppet/modules:/opt/puppet/share/modules
      archive_files = true
      archive_file_server = archiveserver.local

      [agent]
      certname = localhost.local
      server = puppetmaster.local
      report = true
      classfile = $vardir/classes.txt
      localconfig = $vardir/localconfig
      graph = true
      pluginsync = true