I recently found a bit of time to update my Mathematica RPMs to the new 8.0.4 release. In the process I also added a menu entry, icons, and mime-types. Updated spec file below:
# Don't generate any debuginfo packages
%global debug_package %{nil}
# Disable rpath checking
%define __arch_install_post /usr/lib/rpm/check-buildroot
#define __spec_install_post %{nil}
# Disable automatic dependency and provides information
%define __find_provides %{nil}
%define __find_requires %{nil}
%define _use_internal_dependency_generator 0
Autoprov: 0
Autoreq: 0
Name: Mathematica
Version: 8.0.4
Release: 3%{?dist}
Summary: A platform for scientific, engineering, and mathematical computation
Group: Applications/Engineering
License: Proprietary
URL: http://wwww.wolfram.com
Source0: %{name}_%{version}_LINUX.sh
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: prelink
BuildRequires: hicolor-icon-theme
BuildRequires: desktop-file-utils
%description
Mathematica is a computational software program used in scientific,
engineering, and mathematical fields and other areas of technical
computing.
%prep
%setup -T -c %{name}-%{version}
cp %SOURCE0 .
chmod +x %{name}_%{version}_LINUX.sh
%build
# Nothing to do
%install
rm -rf $RPM_BUILD_ROOT
%define destdir /opt/%{name}/%{version}
./%{name}_%{version}_LINUX.sh -- \
-auto -createdir=y -selinux=y -verbose \
-targetdir=$RPM_BUILD_ROOT%{destdir} \
-execdir=$RPM_BUILD_ROOT%{destdir}/bin
# Unfortunately the installer script creates absolute symlinks which
# break once files are moved out of the build root. So, we have to
# manually recreate them here as relative links
before=($(echo $RPM_BUILD_ROOT%{destdir}/bin/*))
rm -rf $RPM_BUILD_ROOT%{destdir}/bin/*
for i in `ls $RPM_BUILD_ROOT%{destdir}/Executables` ; do
ln -s %{destdir}/Executables/${i} $RPM_BUILD_ROOT%{destdir}/bin/${i}
done
ln -s %{destdir}/SystemFiles/Kernel/Binaries/Linux-x86-64/MathematicaScript $RPM_BUILD_ROOT%{destdir}/bin/MathematicaScript
after=($(echo $RPM_BUILD_ROOT%{destdir}/bin/*))
if [ "${before[*]}" != "${after[*]}" ] ; then
echo "$RPM_BUILD_ROOT%{destdir}/bin doesn't contain all required symlinks after relinking"
exit 1
fi
# Fix up prelink error
# prelink: # /home/jgu/rpmbuild/BUILDROOT/Mathematica-8.0.1-1.el6.x86_64/opt/Mathematica/8.0.1/SystemFiles/Libraries/Linux/libPHANToMIO.so.4:
# Could not find one of the dependencies)
# See eg. http://www.redhat.com/archives/rpm-list/2008-May/msg00011.html
prelink -u $RPM_BUILD_ROOT%{destdir}/SystemFiles/Libraries/Linux/libPHANToMIO.so.4
# Fix up hardcoded references to the buildroot in installed files -
# this silences the check-buildroot script that is ran by rpmbuild
# after %%install
for i in $RPM_BUILD_ROOT%{destdir}/SystemFiles/Installation/*.desktop ; do
sed -i -e "s|$RPM_BUILD_ROOT||g" $i
done
# Install menu and mimetype information
install -d $RPM_BUILD_ROOT%{_datadir}/applications
install -d $RPM_BUILD_ROOT%{_datadir}/mime/packages
pushd $RPM_BUILD_ROOT%{destdir}/SystemFiles/Installation
# The wolfram-mathematica8.desktop file has strange leading and
# trailing white space, so fix this, and also add a trailing semicolon
# to the MimeType entry to prevent desktop-file-validate from failing
# Note: wolfram-mathematica.desktop (without the 8) doesn't have the
# correct path for Exec etc
sed -i -e 's/^[ \t]*//;s/[ \t]*$//' wolfram-mathematica8.desktop
sed -i -e '/MimeType/ s/$/;/' wolfram-mathematica8.desktop
# We don't want to create a separate sub-menu just for Mathematica, so
# we'll add it to the Programming sub-menu
cat >> wolfram-mathematica8.desktop <<EOF
Categories=Development;
EOF
cp -a wolfram-mathematica8.desktop $RPM_BUILD_ROOT%{_datadir}/applications/wolfram-mathematica8.desktop
desktop-file-validate $RPM_BUILD_ROOT%{_datadir}/applications/wolfram-mathematica8.desktop
cp -a *.xml $RPM_BUILD_ROOT%{_datadir}/mime/packages/
popd
# Install icons
install -d $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/{32x32,64x64,128x128}/{apps,mimetypes}
pushd $RPM_BUILD_ROOT%{destdir}/SystemFiles/FrontEnd/SystemResources/X
for i in "32" "64" "128"; do
cp -a Mathematica-${i}.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/apps/wolfram-mathematica.png
cp -a MathematicaPlayer-${i}.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/apps/wolfram-mathematicaplayer.png
cp -a vnd.wolfram.cdf-${i}.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/mimetypes/application-vnd.wolfram.cdf.png
cp -a MathematicaDoc-${i}.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/mimetypes/application-mathematica.png
cp -a MathematicaPlayerDoc-${i}.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/mimetypes/application-mathematicaplayer.png
cp -a vnd.wolfram.cdfDoc-${i}.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/mimetypes/application-vnd.wolfram.cdf.png
cp -a MathematicaDoc-${i}.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/mimetypes/gnome-mime-application-mathematica.png
cp -a MathematicaPlayerDoc-${i}.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/mimetypes/gnome-mime-application-mathematicaplayer.png
cp -a vnd.wolfram.cdfDoc-${i}.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/mimetypes/gnome-mime-application-vnd.wolfram.cdf.png
done
popd
# Install man pages
mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1
pushd $RPM_BUILD_ROOT%{destdir}/SystemFiles/SystemDocumentation/Unix
cp -a *.1 $RPM_BUILD_ROOT%{_mandir}/man1
popd
# Create mathpass file specifying license server
cat > $RPM_BUILD_ROOT%{destdir}/Configuration/Licensing/mathpass << EOF
!mathlm-server.xxx.xxx.xxx.xxx
EOF
# Create file to add binaries to PATH
install -d $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
cat > $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/mathematica.sh << EOF
xport PATH=\$PATH:%{destdir}/bin
EOF
%clean
rm -rf $RPM_BUILD_ROOT
%post
# Update icon cache with new icons
/bin/touch --no-create %{_datadir}/icons/hicolor &>/dev/null || :
# Update mime database - needed because we install xml mime definitions
/usr/bin/update-mime-database %{_datadir}/mime &> /dev/null || :
# Update desktop database - needed because .desktop file has a Mimeinfo entry
/usr/bin/update-desktop-database &> /dev/null || :
%postun
# Update icon cache to reflect removed icons
if [ $1 -eq 0 ] ; then
/bin/touch --no-create %{_datadir}/icons/hicolor &>/dev/null
/usr/bin/gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
fi
# Update mime database - needed because we install xml mime definitions
/usr/bin/update-mime-database %{_datadir}/mime &> /dev/null || :
# Update desktop database - needed because .desktop file has a Mimeinfo entry
/usr/bin/update-desktop-database &> /dev/null || :
%posttrans
# Update icon cache to reflect removed icons
/usr/bin/gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%files
%defattr(-,root,root,-)
%{destdir}
%{_sysconfdir}/profile.d/*
%{_datadir}/applications/*
%{_datadir}/icons/hicolor/128x128/apps/*
%{_datadir}/icons/hicolor/128x128/mimetypes/*
%{_datadir}/icons/hicolor/32x32/apps/*
%{_datadir}/icons/hicolor/32x32/mimetypes/*
%{_datadir}/icons/hicolor/64x64/apps/*
%{_datadir}/icons/hicolor/64x64/mimetypes/*
%{_datadir}/mime/packages/*
%{_mandir}/man1/*
%changelog
I recently built a new puppet master server and wanted to migrate all of my systems from the old master server to the new master server. Googling a bit shows various migration strategies, all of which are fairly horrible hacks, and didn’t quite do what I wanted. So I came up with my own horrible hack, in the form of a puppet module to do the work.
So here’s the recipe. I’ll refer to the old puppet server to which all systems are subscribed as oldserver, and the server to which I want to migrate the systems to as newserver. In my case oldserver had a DNS CNAME of puppet, and so puppet.conf on the client machines didn’t contain any “server=foo” lines. However, I think the recipe below is entirely general.
On oldserver I created a new modules containing the following (this was stored in /etc/puppet/modules/puppet/manifests/init.pp):
class puppet::migrate ( $puppetmaster ) {
augeas {'puppet.conf.migrate':
context => '/files/etc/puppet/puppet.conf/main',
changes => ["set server ${puppet::migrate::puppetmaster}",
]
}
# These next two objects handle migration to a new puppet master
# server - if the value of $puppetmaster is updated, the
# puppet-clear-certs.sh script is executed.
file {'/var/lib/puppet/lib/puppet-clear-certs.sh':
owner => 'root',
group => 'root',
mode => 700,
source => 'puppet:///modules/puppet/puppet-clear-certs.sh',
}
exec {'/var/lib/puppet/lib/puppet-clear-certs.sh':
path => ['/usr/bin', '/bin', '/usr/sbin', '/sbin'],
require => [File ['/var/lib/puppet/lib/puppet-clear-certs.sh'],
Augeas ['puppet.conf.migrate'],
],
unless => ["openssl x509 -text -in /var/lib/puppet/ssl/certs/ca.pem | grep ${puppet::migrate::puppetmaster} >/dev/null 2>&1",
"openssl x509 -text -in /var/lib/puppet/ssl/certs/${fqdn}.pem | grep ${puppet::migrate::puppetmaster} >/dev/null 2>&1",
]
}
}
The magic ingredient here is the file puppet-clear-certs.sh which was inspired by this blog post by Ryan Uber. This script forks a shell on the client which waits until puppet has finished its catalogue run on the client and then deletes all the SSL certificates on the client, preparing the way for registration with the new server. This file looks like this:
#!/bin/bash
# This script is a hack to remove SSL certificates from a puppet
# client to prepare it for migration to a new puppet master server
# after puppet has altered the puppet.conf file to point to the new
# puppet master server.
#
# Normally, if you subscribe the puppet service to the puppet.conf
# file, the puppet service will be restarted too soon, interrupting
# the current puppet run. Various attempts at using
# configure_delayed_restart among other things have not proven to be
# 100% effective. This script will watch the puppetdlock file, which
# can determine whether or not there is a run in progress. If there is
# a run in progress, we sleep for a second and then test again until
# the process is unlocked. Once unlocked, we can safely delete
# certificates and call a puppet restart. The checker process itself
# gets forked into the background. If it were not forked into the
# background, the puppet run would sit and wait for the process to
# return, or for the exec timeout, whichever came first. This would
# cause serious trouble if timeouts were disabled or very long periods
# of time.
#
# This script was inspired by this blog post by Ryan Uber:
# http://www.ryanuber.com/puppet-self-management.html
#
# Begin waiting for the current puppet run to finish, then restart.
/bin/sh -c "
until [ ! -f /var/lib/puppet/state/puppetdlock ]
do
sleep 1
done
/sbin/service puppet stop
rm -f /var/lib/puppet/ssl/certs/*
rm -f /var/lib/puppet/ssl/certificate_requests/*
rm -r /var/lib/puppet/ssl/crl.pem
/sbin/service puppet start
" &
# Always return true, since this script just forks another process.
exit 0
# EOF
So, when this script is executed on the client after the puppet manifest delivered from oldserver modifies puppet.conf to point to newserver it waits until the puppet agent run finishes, then stops the puppet daemon, deletes all the SSL certs, and then restarts the puppet agent which will now connect to newserver and issue a certificate signing request.
So, having created that module, I rsync the puppet modules and manifests from oldserver onto newserver, and then edit the node entries on the oldserver to look like
node somenode.somewhere.com {
class {'puppet::migrate':
puppetmaster => 'newserver.somewhere.com',
}
}
Well, in actual fact I added that class to the basenode from which all other nodes inherit, but you get the idea. Once this is active, nodes migrate and generate signing requests at the next puppet run, and you should see the signing requests on the newserver. Job done!
I should also point out the “unless” guards on the exec in the above init.pp file. Since I rsynced across the migration module, I wanted to protect myself from inadvertently re-triggering a migration from newserver to newserver on every puppet run, so those are there as a safeguard.
Recently I wanted to deploy the libvirt/virt-manager/qemu-kvm virtualization stack on a bunch of Scientific Linux 6 workstations. This presented a number of requirements:
- Virtual machines need to be able to be installed and started by non-root users
- The workstations are multi-user, so we need to prevent users from running or modifying each other’s virtual machines
- On these machines home directories are mounted over NFS, but we want the VM disk images located on a local scratch disk for performance
- VMs will be considered to be scratch data – i.e. not backed up
Allowing non-root users to manage virtual machines
Fortunately the libvirt stack has support for PolicyKit, and so allowing non-root users is simply a matter of setting some policy. Placing the following in the file /etc/polkit-1/localauthority/50-local.d/50-virt.pkla will allow all users to manage virtual machines:
[Allow all users libvirt management permissions but require password] Identity=* Action=org.libvirt.unix.manage ResultAny=auth_self_keep ResultInactive=auth_self_keep ResultActive=auth_self_keep
With this file in place, a user starting virt-manager will be asked to enter their password (note: not root’s password), and can then proceed.
Setting up per-user storage pools
Now, at this point, the expectation made by libvirt/virt-manager is that virtual machine disk images are stored in /var/lib/libvirt/images, and indeed all users are able to create and manage virtual machines under this directory, as evidence by its permissions:
$ ls -ldZ /var/lib/libvirt/images drwx--x--x. root root system_u:object_r:virt_image_t:s0 /var/lib/libvirt/images/
However, we want to have private storage pools for each user, and we don’t want to have them stored under /var, but rather on a locally mounted scratch disk (mounted at /scratch). We could proceed by requiring each user to create a storage pool using the virt-manager (via the Edit->Connection Details menu entry and chosing the Storage tab). However, unfortunately doing so as a non-root user results in the storage pool directory having the wrong permissions. For example, if I create a storage pool while running virt-manager as user jgu under /scratch/test:
$ ls -ldZ /scratch/temp/ drwx------. root root unconfined_u:object_r:root_t:s0 /scratch/temp/
which unfortunately won’t actually be usable by the user jgu. Similarly using virsh will have the same problem:
$ virsh --connect qemu:///system "pool-define-as jgu-vmstore --type=dir --target=/scratch/virt/jgu/images ; pool-build jgu-vmstore ; pool-start jgu-vmstore ; pool-autostart jgu-vmstore" ... $ ls -ldZ /scratch/virt/jgu/images drwx------. root root unconfined_u:object_r:default_t:s0 /scratch/virt/jgu/images
I’ve reported this problem in the following bug reports:
Redhat Bugzilla #790038
Redhat Bugzilla #790045
Taking a look at the file /etc/libvirtd/storage/jgu-vmstore.xml that was created as a result of the virsh command above gives us a clue as to a solution to this problem:
<pool type='dir'>
<name>jgu-vmstore2</name>
<uuid>6a81e62f-5c42-fc94-c32b-18877e025c31</uuid>
<capacity>0</capacity>
<allocation>0</allocation>
<available>0</available>
<source>
</source>
<target>
<path>/scratch/virt/jgu/images</path>
<permissions>
<mode>0700</mode>
<owner>-1</owner>
<group>-1</group>
</permissions>
</target>
</pool>
Notice the permissions block – so it seems possible to specify user and group during storage pool creation with virsh using the -pool-define switch together with an xml file desribing the storage pool. The bash script below does exactly this:
#!/bin/bash
usage=$(cat <<EOF
USEAGE:
$0 ROOTDIR STORAGE-POOL
ROOTDIR directory under which to store virtual machine data
STORAGE-POOL name of storage pool for virtual machine images
This script will create a directory for storage of virtual machine images, and
register it as a storage pool with libvirt. The script creates the following
directories:
ROOTDIR/STORAGE-POOL for storage of virtual machine images
ROOTDIR/iso for storage of operating system install disk ISO
images
EOF
)
if [[ "$1" == "" || "$2" == "" ]] ; then
echo "${usage}"
exit 1
fi
ROOTDIR=$1
IMGSTORE=$2
USERNAME=`whoami`
GID=`id -g`
IMGDIR=${ROOTDIR}/${IMGSTORE}
if [[ ! -d ${ROOTDIR} || ! -w ${ROOTDIR} ]] ; then
echo "Can't write to ${ROOTDIR}."
exit 1
fi
# Create the storage pool. Here we could do something like the following:
#
# virsh --connect qemu:///system "\
# pool-define-as ${IMGSTORE} --type=dir --target=${IMGDIR} ; \
# pool-build ${IMGSTORE} ; \
# pool-start ${IMGSTORE} ; \
# pool-autostart ${IMGSTORE} \
# "
#
# however, then the storage pool will be owned by root, whereas we want it to
# be owned by the user. Unfortunately pool-define-as doesn't have arguments
# for user and group, but it is possible to specify owner and group in an xml
# description and use pool-define. So, we'll do that.
XMLFILE=`mktemp`
cat > ${XMLFILE} <<EOF
<pool type='dir'>
<name>${IMGSTORE}</name>
<target>
<path>${IMGDIR}</path>
<permissions>
<mode>0700</mode>
<owner>${UID}</owner>
<group>${GID}</group>
</permissions>
</target>
</pool>
EOF
echo "Creating storage pool ${IMGSTORE}:"
virsh --connect qemu:///system "\
pool-define ${XMLFILE} ; \
pool-build ${IMGSTORE} ; \
pool-start ${IMGSTORE} ; \
pool-autostart ${IMGSTORE} \
"
if [[ $? -ne 0 ]] ; then
rm -f ${XMLFILE}
echo "Could not create storage pool."
exit 1
else
rm -f ${XMLFILE}
echo "Storage pool \"${USERNAME}-vmstore\" created at ${IMGDIR}."
echo "Use this to store your virtual machine images."
echo
fi
# Create a directory for storing ISO images
ISODIR=${ROOTDIR}/iso
echo "Creating directory to store OS ISO images at ${ISODIR}:"
mkdir -p ${ISODIR}
if [[ $? -ne 0 ]] ; then
echo "Failed to create ${ISODIR}."
exit 1
else
chown ${UID}:${GID} ${ISODIR}
chmod 700 ${ISODIR}
echo "${ISODIR} created"
echo "Use this to store any ISO images of operating system installation disks"
fi
Just occasionally it’s useful to be able to run programs using openmpi inside of a mock chroot when building RPM packages. I just hit this problem myself while building MOLPRO – during the %build section the makefile tries to execute one of the resulting binaries, which bombs out. The reason it bombs out is actually discussed in detail in this mailing list post. This problem has also been reported in the Redhat bugzilla. Googling for “openmpi chroot” also brings up various reports. Anyway, the simple work around is to BuildRequire the rsh package. Or touch /usr/bin/rsh. This allows programs to run inside the %build and %check stages when building an RPM, and so is pretty useful.
Recently I had a need to ensure a specific version of a package (nfs-utils) was present on the systems under Puppet management. Unfortunately, Scientific Linux had pushed a broken update out for nfs-utils (1.2.3-15) and I wanted to ensure all machines had the previous version of the package (1.2.2-7). Puppet 2.6.x does allow you to specify a specific package version, but if the system already has a later version of the package installed, it doesn’t have the capability to downgrade the package. This is actually possible with puppet 2.7 – see this ticket for details.. Anyway, the following snippet demonstrates how to achieve this in puppet 2.6.x using a exec resource:
package {'nfs-utils':
ensure => '1.2.2-7.el6',
notify => Service ['rpcgssd'],
require => Exec ['downgrade-nfs-utils'],
}
exec {'downgrade-nfs-utils':
command => 'yum -y downgrade nfs-utils-1.2.2-7.el6',
path => ['/sbin', '/bin', '/usr/sbin', '/usr/bin'],
unless => 'rpm -qa | grep nfs-utils-1.2.2-7',
}
.. you need to switch off the geek and watch something tranquil and serene. This is what filled that need today.
Where I work we make extensive use of the Intel compiler suite and MKL. Intel makes the compiler and libraries available as rpm packages, which is very convenient. However, we need to use FlexLM running on a license server to serve up our floating licenses. Intel make available a tarball of the recommended (and very old!) version of FlexLM, but it’s far more handy to have an rpm to deploy. Also, it’s useful to have a proper SysV init file for the license daemon. Below you can find a spec file and an init file which I hacked together a while ago.
# Don't generate any debuginfo packages
%global debug_package %{nil}
# Disable rpath checking
%define __arch_install_post %{nil} #/usr/lib/rpm/check-buildroot
%define __spec_install_post %{nil}
Name: flexlm-intel
Version: 9.23
Release: 5%{?dist}
Summary: FlexLM license manager for Intel compilers
Group: Applications/System
License: Proprietary
URL: https://registrationcenter.intel.com/
Source0: flexlm.Linux.EL3.tar.gz
Source1: lmgrd.intel.init
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Requires(pre): shadow-utils
Requires(post): chkconfig
Requires(preun): chkconfig
Requires(preun): initscripts
%description
FlexLM license manager for Intel compilers.
%prep
%setup -q -n flexlm
%build
# Nothing to do.
%install
rm -rf $RPM_BUILD_ROOT
# Binaries
install -d ${RPM_BUILD_ROOT}%{_bindir}
install -m 755 lmgrd.intel ${RPM_BUILD_ROOT}%{_bindir}
install -m 755 INTEL ${RPM_BUILD_ROOT}%{_bindir}
install -m 755 lmutil ${RPM_BUILD_ROOT}%{_bindir}
install -m 755 chklic ${RPM_BUILD_ROOT}%{_bindir}
# init file
install -d ${RPM_BUILD_ROOT}%{_sysconfdir}/init.d
install -m 755 %SOURCE1 ${RPM_BUILD_ROOT}%{_sysconfdir}/init.d/lmgrd.intel
# License file
install -d ${RPM_BUILD_ROOT}%{_datadir}/intel
install -d ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig
cat > ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/lmgrd.intel <<EOF
LICENSE="/usr/share/intel/intel.lic"
EOF
%clean
rm -rf $RPM_BUILD_ROOT
%pre
getent group intel >/dev/null || groupadd -r intel
getent passwd intel >/dev/null || \
useradd -r -g intel -d %{_datadir}/intel -s /sbin/nologin \
-c "Intel license manager" intel
exit 0
%post
/sbin/chkconfig --add lmgrd.intel
%preun
if [ $1 -eq 0 ] ; then
/sbin/service lmgrd.intel stop >/dev/null 2>&1
/sbin/chkconfig --del lmgrd.intel
fi
%postun
if [ "$1" -ge "1" ] ; then
/sbin/service lmgrd.intel condrestart >/dev/null 2>&1 || :
fi
%files
%defattr(-,root,root,-)
%doc HowTo.html END_USER_LICENSE README enduser.pdf
%{_bindir}/*
%{_sysconfdir}/init.d/lmgrd.intel
%{_sysconfdir}/sysconfig/lmgrd.intel
%{_datadir}/intel
%changelog
And here is the init file:
#!/bin/sh
#
# lmgrd.intel FlexLM license manager for Intel compiler
#
# chkconfig: 345 99 1
# description: FlexLM license manager for Intel compiler
#
### BEGIN INIT INFO
# Provides: lmgrd.intel
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $network $local_fs
# Should-Start: $network $local_fs
# Should-Stop: $syslog
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: Start and stop FlexLM license manager for Intel compiler
# Description: Start and stop FlexLM license manager for Intel compiler
### END INIT INFO
# Source function library.
. /etc/init.d/functions
lmgrd="/usr/bin/lmgrd.intel"
lmutil="/usr//bin/lmutil"
prog="lmgrd.intel"
lockfile=/var/lock/subsys/$prog
LICENSE="/usr/share/intel/intel.lic"
LOGFILE="/var/log/lmgrd.intel"
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
lockfile=/var/lock/subsys/$prog
[ -x $lmgrd ] || exit 5
[ -x $lmutil ] || exit 5
[ -f $LICENSE ] || exit 6
checklog() {
[ -f $LOGFILE ] || /bin/touch $LOGFILE
/bin/chown intel:intel $LOGFILE
}
start() {
echo -n $"Starting $prog: "
checklog
daemon --user intel $lmgrd -c $LICENSE -l $LOGFILE
retval=$?
echo
if [ $retval -eq 0 ] ; then
touch $lockfile
fi
return $retval
}
stop() {
echo -n $"Stopping $prog: "
$lmutil lmdown -c $LICENSE -q >> $LOGFILE
retval=$?
echo
if [ $retval -eq 0 ] ; then
rm -f $lockfile
success
else
failure
fi
return $retval
}
restart() {
stop
start
}
reload() {
restart
}
force_reload() {
restart
}
rh_status() {
$lmutil lmstat -a -c $LICENSE
return $?
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
# rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
restart)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
restart
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2
esac
exit $?
Similarly to Mathematica, I need to deploy Matlab across a lot of machines, and wanted to automate this via a yum repository. The spec file below can be used to build an rpm of Mathematica.
# Don't generate any debuginfo packages
%global debug_package %{nil}
# Disable rpath checking
%define __arch_install_post %{nil} #/usr/lib/rpm/check-buildroot
%define __spec_install_post %{nil}
# Disable automatic dependency and provides information
%define __find_provides %{nil}
%define __find_requires %{nil}
%define _use_internal_dependency_generator 0
Autoprov: 0
Autoreq: 0
Name: matlab
Version: 2010b
Release: 3%{?dist}
Summary: A high-level technical computing language and environment
Group: Applications/Engineering
License: Proprietary
URL: http://www.mathworks.com
# Source0 is just the tar and gzipped contents of the install CD iso
Source0: matlab-2010b.tar.gz
Source1: network.lic
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
#BuildRequires:
#Requires:
%description
MATLAB is a high-level language and interactive environment that
enables you to perform computationally intensive tasks faster than
with traditional programming languages such as C, C++, and Fortran.
%prep
%setup -q
cp %SOURCE1 .
%define destdir /opt/MATLAB/R%{version}
cat > answerfile.txt <<EOF
destinationFolder=${RPM_BUILD_ROOT}/%{destdir}
fileInstallationKey=xxxxx-xxxxx-40427-xxxxx-32825-xxxxx-43181-09302-xxxxx-22930-38724-xxxxx
agreeToLicense=yes
outputFile=matlab_install.log
mode=silent
licensePath=./network.lic
EOF
%build
# Nothing to do - binary distribution
%install
rm -rf $RPM_BUILD_ROOT
./install -inputFile ./answerfile.txt
install -d $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
cat > $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/matlab.sh<<EOF
export PATH=\$PATH:%{destdir}/bin
EOF
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%{destdir}
%{_sysconfdir}/profile.d/*
%changelog
For various reasons I need to deploy Mathematica across a bunch of machines and don’t want to do this manually. Since I have a local yum repository for locally built software, it’s handy to be able to deploy an rpm. Of course, we don’t really want to use all the dependency generation facilities of rpm as this is nasty binary compiled software which pays no attention to packaging standards but just dumps everything into a directory. Anyhow, this is what seems to work for me:
# Don't generate any debuginfo packages
%global debug_package %{nil}
# Disable rpath checking
%define __arch_install_post %{nil}
%define __spec_install_post %{nil}
# Disable automatic dependency and provides information
%define __find_provides %{nil}
%define __find_requires %{nil}
%define _use_internal_dependency_generator 0
Autoprov: 0
Autoreq: 0
Name: Mathematica
Version: 8.0.1
Release: 3%{?dist}
Summary: A platform for scientific, engineering, and mathematical computation
Group: Applications/Engineering
License: Proprietary
URL: http://wwww.wolfram.com
Source0: %{name}_%{version}_LINUX.sh
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
#BuildRequires:
#Requires:
%description
Mathematica is a computational software program used in scientific,
engineering, and mathematical fields and other areas of technical
computing.
%prep
%setup -T -c %{name}-%{version}
cp %SOURCE0 .
%build
# Nothing to do
%install
rm -rf $RPM_BUILD_ROOT
%define destdir /opt/%{name}/%{version}
./%{name}_%{version}_LINUX.sh -- \
-auto -createdir=y -selinux=y -verbose \
-targetdir=$RPM_BUILD_ROOT%{destdir} \
-execdir=$RPM_BUILD_ROOT%{destdir}/bin
# Unfortunately the installer script creates absolute symlinks which
# break once files are moved out of the build root. So, we have to
# manually recreate them here as relative links
before=($(echo $RPM_BUILD_ROOT%{destdir}/bin/*))
rm -rf $RPM_BUILD_ROOT%{destdir}/bin/*
for i in `ls $RPM_BUILD_ROOT%{destdir}/Executables` ; do
ln -s %{destdir}/Executables/${i} $RPM_BUILD_ROOT%{destdir}/bin/${i}
done
ln -s %{destdir}/SystemFiles/Kernel/Binaries/Linux-x86-64/MathematicaScript $RPM_BUILD_ROOT%{destdir}/bin/MathematicaScript
after=($(echo $RPM_BUILD_ROOT%{destdir}/bin/*))
if [ "${before[*]}" != "${after[*]}" ] ; then
echo "$RPM_BUILD_ROOT%{destdir}/bin doesn't contain all required symlinks after relinking"
exit 1
fi
# Fix up prelink error
# prelink: # $BUILDROOT/Mathematica-8.0.1-1.el6.x86_64/opt/Mathematica/8.0.1/SystemFiles/Libraries/Linux/libPHANToMIO.so.4:
# Could not find one of the dependencies)
# See eg. http://www.redhat.com/archives/rpm-list/2008-May/msg00011.html
prelink -u $RPM_BUILD_ROOT%{destdir}/SystemFiles/Libraries/Linux/libPHANToMIO.so.4
# Create mathpass file specifying license server
cat > $RPM_BUILD_ROOT%{destdir}/Configuration/Licensing/mathpass << EOF
!mathlm-server.some.where.org
EOF
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%{destdir}
%{_sysconfdir}/profile.d/*
%changelog
Due to the large number of files being packaged, this takes quite a while to rpmbuild.
A little while ago I posted this entry about deploying SELinux modules with puppet. I wanted to add a new entry with an updated version of that module, as the originally posted module had a few problems which I resolved over the coming weeks. Posting this was spurred on by James who has posted this code on github using some similar ideas (and actually doing an even better job by the looks of it).
class semodloader ($moddir = '/usr/local/share/selinux') {
package { ['policycoreutils',
'checkpolicy',
]: ensure => latest}
file {$moddir:
ensure => directory,
owner => 'root',
group => 'root',
mode => 755,
require => [ Package['policycoreutils'],
Package['checkpolicy'],
],
}
define semodule ($source, $status = 'present') {
case $status {
present: {
file {"${semodloader::moddir}/${name}.te":
owner => 'root',
group => 'root',
mode => 644,
source => $source,
require => File ["${semodloader::moddir}"],
}
file {"${semodloader::moddir}/${name}.mod":
owner => 'root',
group => 'root',
mode => 644,
require => File ["${semodloader::moddir}"],
}
file {"${semodloader::moddir}/${name}.pp":
owner => 'root',
group => 'root',
mode => 644,
require => File ["${semodloader::moddir}"],
}
exec {"${name}-buildpp":
command => "checkmodule -M -m -o ${name}.mod ${name}.te ; semodule_package -m ${name}.mod -o ${name}.pp",
path => ['/sbin', '/usr/sbin', '/bin', '/usr/bin'],
cwd => "${semodloader::moddir}",
subscribe => File ["${semodloader::moddir}/${name}.te"],
require => File ["${semodloader::moddir}/${name}.te"],
refreshonly => true,
}
selmodule {$name:
ensure => present,
syncversion => true,
selmodulepath => "${semodloader::moddir}/${name}.pp",
require => Exec ["${name}-buildpp"],
}
}
absent: {
file {"${semodloader::moddir}/${name}.te":
ensure => absent,
}
file {"${semodloader::moddir}/${name}.mod":
ensure => absent,
}
file {"${semodloader::moddir}/${name}.pp":
ensure => absent,
}
exec {"${name}-remove":
command => "semodule -r ${name} > /dev/null 2>&1",
path => ['/sbin', '/usr/sbin', '/bin', '/usr/bin'],
}
}
default: {
fail("status variable not recognized")
}
}
}
