During my frenzy of package updating I also updated the Mathematica RPM package. Spec file below.
# Don't generate any debuginfo packages
%global debug_package %{nil}
# Post install checking of installed files is determined by three variables:
#
# __arch_install_post
# __os_install_post
# __spec_install_post
#
# each of which can be examined with rpm --eval %var. The last one
# is the catenation of the first two.
#
# At the least we want to disable rpath checking with
#
# define __arch_install_post /usr/lib/rpm/check-buildroot
#
# which keeps the check for occurences of $RPM_BUILD_ROOT in scripts -
# useful to do this sometimes, but very time consuming
#
#define __arch_install_post %{nil}
%define __arch_install_post /usr/lib/rpm/check-buildroot
%define __os_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: 9.0.1
Release: 1%{?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-mathematica9.desktop
sed -i -e '/MimeType/ s/$/;/' wolfram-mathematica9.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-mathematica9.desktop <<EOF
Categories=Development;
EOF
cp -a wolfram-mathematica9.desktop $RPM_BUILD_ROOT%{_datadir}/applications/wolfram-mathematica9.desktop
desktop-file-validate $RPM_BUILD_ROOT%{_datadir}/applications/wolfram-mathematica9.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
!my.license.server.host.name
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
export PATH=\$PATH:%{destdir}/bin
EOF
# Create directories for Mathematica system wide package installation
# (corresponding to $BaseDirectory etc)
install -d $RPM_BUILD_ROOT%{_datadir}/Mathematica/{Applications,Autoload}
%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}
%{_datadir}/Mathematica/Autoload
%{_datadir}/Mathematica/Applications
%{_sysconfdir}/profile.d/*
%{_datadir}/applications/*
%{_datadir}/icons/hicolor/128x128/apps/*
%{_datadir}/icons/hicolor/128x128/mimetypes/*
%{_datadir}/icons/hicolor/32x32/apps/*
/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}
%{_datadir}/Mathematica/Autoload
%{_datadir}/Mathematica/Applications
%{_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
* Thu Feb 21 2013 Jonathan G. Underwood <jonathan.underwood@gmail.com> - 9.0.1-1
- Update to 9.0.1
- Add /usr/share/Mathematica/{Applications,Autoload} directories to package
- Other cleanups
* Fri Feb 15 2013 Jonathan G. Underwood <jonathan.underwood@gmail.com> - 9.0.0-1
- Update to 9.0.0
* Fri Apr 27 2012 Jonathan G. Underwood <jonathan.underwood@gmail.com> - 8.0.4-3
- Fix up .desktop file to add an entry under Programming menu
* Fri Apr 27 2012 Jonathan G. Underwood <jonathan.underwood@gmail.com> - 8.0.4-2
- Properly install icons, desktop entries, mimetypes and manpages
- Re-enable the check-buildroot script in __arch_install_post, but
still disable rpath checking
- No longer set __spec_install_post to nil
* Fri Apr 27 2012 Jonathan G. Underwood <jonathan.underwood@gmail.com> - 8.0.4-1
- Update to 8.0.4
I recently got around to updating my RPM spec file for MATLAB. This was troublesome because:
- The install ISO image is now something like 4.8 GB in size. Simply tar and gzipping this up for the source RPM led to a SRPM that couldn’t subsequently be unpacked, giving an error message of “error: unpacking of archive failed on file … cpio: Digest mismatch”- this is because the largest (source) file size that can be accommodated by RPM/CPIO is 4 GB see this bug report for details.
- Even once the problem above was solved the resulting package build exploded with “Unable to create immutable header region” due to the large number of files in the package – see this bug report for details.
The first problem was solved with a simple trick – using the “split” command to break the tarball up into small pieces:
split -b 2G matlab-2012b.tar matlab-2012.tar-part
and include each of the split files as sources in the spec file:
Source0: matlab-%{version}.tar-partaa
Source1: matlab-%{version}.tar-partab
Source2: matlab-%{version}.tar-partac
such that the first part of %prep includes glueing the pieces back together:
cat %SOURCE0 %SOURCE1 %SOURCE2 > matlab.tar
Note that I didn’t bother gzipping the tarball for any of this.
The second issue was solved by splitting out the “help” and “toolbox” subdirectories into separate sub-packages and adding tight (and circular) dependencies between the main package and these sub-packages.
For your entertainment, the updated spec file is below, which now also includes a menu entry and icon.
# Don't generate any debuginfo packages
%global debug_package %{nil}
# Post install checking of installed files is determined by three variables:
#
# __arch_install_post
# __os_install_post
# __spec_install_post
#
# each of which can be examined with rpm --eval %var. The last one
# is the catenation of the first two.
#
# At the least we want to disable rpath checking with
#
# define __arch_install_post /usr/lib/rpm/check-buildroot
#
# which keeps the check for occurences of $RPM_BUILD_ROOT in scripts -
# useful to do this sometimes, but very time consuming
#
%define __arch_install_post %{nil}
%define __os_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: 2012b
Release: 1%{?dist}
Summary: A high-level technical computing language and environment
Group: Applications/Engineering
License: Proprietary
URL: http://www.mathworks.com
# Source0-3 are the tarred and split contents of the install CD iso by
# eg.
#
# mkdir ~/matlab
# mount -t iso9660 -o loop R2012b_UNIX.iso /mnt
# cd /mnt
# tar -cvf ~/matlab/matlab-2012b.tar .
# cd ~/matlab
# split -b 2G matlab-2012b.tar matlab-2012.tar-part
#
# It's necessary to split the tar archive up as the largest file that
# can be handled by rpm is 4G
#
# Also, it's now necessary to split the binary packages into several
# sub-packages - trying to place all files in the main package results
# in a rpm header greater than 16 MB in size due to the large number
# of files, and rpm gives up. See:
#
# https://bugzilla.redhat.com/show_bug.cgi?id=913099
#
# So, we split out the help and toolbox files into separate
# sub-packages and create tight (circular) dependencies between these
# packages and the main package to ensure they're all upgraded
# together.
Source0: matlab-%{version}.tar-partaa
Source1: matlab-%{version}.tar-partab
Source2: matlab-%{version}.tar-partac
Source10: network.lic
Source20: matlab.png
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: hicolor-icon-theme
BuildRequires: desktop-file-utils
BuildRequires: ImageMagick
Requires: %{name}-help = %{version}-%release
Requires: %{name}-toolbox = %{version}-%release
%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.
%package help
Summary: Help files for MATLAB
Requires: matlab = %{version}-%{release}
%description help
Help files for MATLAB.
%package toolbox
Summary: Toolbox files for MATLAB
Requires: matlab = %{version}-%{release}
%description toolbox
MATLAB bundled toolboxes
%prep
%setup -T -c %{name}-%{version}
cat %SOURCE0 %SOURCE1 %SOURCE2 > matlab.tar
tar -xf matlab.tar
chmod -Rf a+rX,u+w,g-w,o-w .
cp -a %SOURCE10 .
%define destdir /opt/MATLAB/R%{version}
cat > answerfile.txt <<EOF
destinationFolder=${RPM_BUILD_ROOT}/%{destdir}
fileInstallationKey=XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-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
# desktop file
install -d $RPM_BUILD_ROOT%{_datadir}/applications
cat > $RPM_BUILD_ROOT%{_datadir}/applications/matlab%{version}.desktop <<EOF
[Desktop Entry]
Version=1.0
Type=Application
Name=MATLAB %{version}
Comment=Technical Computing System
Exec=%{destdir}/bin/matlab -desktop
Icon=matlab
Categories=Development;
EOF
desktop-file-validate $RPM_BUILD_ROOT%{_datadir}/applications/matlab%{version}.desktop
# Icons
for i in "32" "64" "128" ; do
install -d $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/apps
convert -resize ${i}x${i} %SOURCE20 $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/apps/matlab.png
done
%clean
rm -rf $RPM_BUILD_ROOT
# Icons
for i in "32" "64" "128" ; do
install -d $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/apps
convert -resize ${i}x${i} %SOURCE20 $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/apps/matlab.png
done
%clean
rm -rf $RPM_BUILD_ROOT
%post
# Update icon cache with new icons
/bin/touch --no-create %{_datadir}/icons/hicolor &>/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
%posttrans
# Update icon cache to reflect removed icons
/usr/bin/gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%files
%defattr(-,root,root,-)
%{destdir}
%exclude %{destdir}/help
%exclude %{destdir}/toolbox
%{_sysconfdir}/profile.d/*
%{_datadir}/applications/matlab%{version}.desktop
%{_datadir}/icons/hicolor/32x32/apps/*
%{_datadir}/icons/hicolor/64x64/apps/*
%{_datadir}/icons/hicolor/128x128/apps/*
%files help
%{destdir}/help
%files toolbox
%{destdir}/toolbox
%changelog
* Thu Feb 21 2013 Jonathan G. Underwood <jonathan.underwood@gmail.com> - 2012b-1
- Update to version 2012b
- Add icons and desktop file
- Split package up so as not to overrun internal rpm header limit
- Split source tarball up
* Tue Jun 19 2012 Jonathan G. Underwood <jonathan.underwood@gmail.com> - 2012a-3
- Update to version 2012a
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
