aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sys-cluster/empi/files/empi-0.5')
-rwxr-xr-xsys-cluster/empi/files/empi-0.5360
1 files changed, 360 insertions, 0 deletions
diff --git a/sys-cluster/empi/files/empi-0.5 b/sys-cluster/empi/files/empi-0.5
new file mode 100755
index 000000000..0ac1bd017
--- /dev/null
+++ b/sys-cluster/empi/files/empi-0.5
@@ -0,0 +1,360 @@
+#!/bin/bash
+VERSION=0.3
+
+source /etc/init.d/functions.sh
+
+# class (category) Implementation we're installing for. mpi-*
+# targets Packages to run action on. When creating, the implementation to use.
+# action create, add, update, remove.
+
+die(){
+ if [ -n "${1}" ]; then
+ echo; eerror $1; echo
+ fi
+ exit 1
+}
+
+usage(){
+ local rc=${1:-0}
+ shift
+cat <<-EOF
+empi-${VERSION}
+Usage: ${HILITE}empi${NORMAL} ${GOOD}[actions]${NORMAL} ${BRACKET}[options]${NORMAL}
+
+Actions:
+ ${GOOD}-c, --create${NORMAL} pkgspec (Re)Initialize setup for mpi class.
+ ${GOOD}-a, --add${NORMAL} pkgspec(s) Add packages using specified mpi class.
+ ${GOOD}-d, --delete${NORMAL} class Remove everything related to specified class.
+
+Options:
+ ${GOOD}-C, --class${NORMAL} class MPI class to use.
+ ${GOOD}-t, --tree${NORMAL} path Path to portage tree to use ebuilds from.
+ ${GOOD}-o, --overlaydir${NORMAL} path Directory to use for the empi portage overlay.
+ ${GOOD} --noemerge${NORMAL} Do not call emerge, only preform overlay setup.
+
+Notes:
+ ${HILITE}-${NORMAL} pkgspec is specified by a package string. Without a version, the
+ portageq best_visible is used. For example, all of the following
+ are valid: openmpi, sys-cluster/openmpi, =sys-cluster/openmpi-1.2.5.
+ ${HILITE}-${NORMAL} class (-c) is user defined but must be prefixed with "mpi-"
+
+Examples:
+${BRACKET}Create a new class based on openmpi.${NORMAL}
+ empi --create sys-cluster/openmpi --class mpi-ompi
+${BRACKET}Rebuild the above.${NORMAL}
+ emerge mpi-ompi/openmpi
+${BRACKET}Add hpl to mpi-ompi${NORMAL}
+ empi --class mpi-ompi --add sys-cluster/hpl
+EOF
+ [[ -n $* ]] && echo && eerror "Error: $*"
+ exit ${rc}
+}
+
+class_is_valid() {
+ [[ -z ${class} ]] && usage 1 "No class defined."
+ [[ ${class} != mpi-* ]] && usage 1 "Classes must be prefixed with mpi-"
+ [[ ${class//./} != ${class} ]] && usage 1 "Classes cannot contain . (period)"
+}
+
+is_class_category() {
+ local i
+ for i in $(eselect mpi list -p); do
+ [[ ${1} == ${i} ]] && return 0
+ done
+ return 1
+}
+
+split_atom() {
+ local cpv c pf pn pv
+ cpv=$(portageq best_visible / ${1})
+ if [[ -z ${cpv} || ${rc} -ne 0 ]]; then
+ cpv=$(portageq best_visible / =${1})
+ [[ -z ${cpv} || ${rc} -ne 0 ]] && return 1
+ fi
+ c=${cpv%/*}; pf=${cpv#${c}/}; pn=${pf%%-[0-9]*}; pv=${pf#${pn}-}
+ echo "${c} ${pn} ${pv}"
+}
+
+parse_pkgspecs() {
+ local atom i
+ for ((i=0; i<${#targets[@]}; i++)); do
+ atom=($(split_atom ${targets[i]}))
+ if [[ $? -ne 0 ]]; then
+ eerror "Unable to find a unique package or valid version for ${targets[i]}"
+ eerror "Is the package unmasked and unblocked normally?"
+ die ""
+ fi
+ targets[i]=${atom[0]}/${atom[1]}-${atom[2]}
+ done
+}
+
+# handle_etc_portage package_spec
+# parses /etc/portage/package.{keywords,use}. If ${class}/${pn} is seen, we don't
+# do a thing. Otherwise copy any lines that have ${cat}/${pn} inserting them again
+# with the new category.
+handle_etc_portage() {
+ local atom=( $(split_atom ${1}) )
+ local ext line gfiles f
+
+ for ext in "keywords" "use"; do
+ if [ -d /etc/portage/package.${ext} ]; then
+ gfiles="/etc/portage/package.${ext}/*"
+ f=/etc/portage/package.${ext}/${class}
+ else
+ gfiles="/etc/portage/package.${ext}"
+ f=/etc/portage/package.${ext}
+ fi
+
+ if ! grep "[>=<]*${class}/${atom[1]}" ${gfiles} &>/dev/null; then
+ grep "[>=<]*${atom[0]}/${atom[1]}" ${gfiles} 2>/dev/null \
+ | sed "s,.*:${atom[0]},${class}," \
+ | while read line; do
+ echo "${line}" >> ${f}
+ [[ ${VERBOSE} -ne 0 ]] \
+ && einfo "Addition to ${f}: ${line}"
+ done
+ elif [[ ${VERBOSE} -ne 0 ]]; then
+ ewarn "Keys for ${class}/${atom[1]} already exist in ${f}. Will not replicate them."
+ fi
+ done
+}
+
+
+
+get_ebuild_dir() {
+ local d a
+ local want_uses_mpi=${2:-0}
+ local found=0
+
+ a=($(split_atom ${1}))
+ [[ $? -ne 0 ]] && die "Unable to find a unique package or valid version for ${1}."
+ is_class_category ${a[0]} && die "It makes no sense to build a new mpi-class from a current one."
+
+ if [[ -z ${portage_tree} ]]; then
+ for d in $(portageq portdir_overlay) $(portageq portdir); do
+ if [[ ${want_uses_mpi} -ne 0 ]]; then
+ [[ -f "${d}/${a[0]}/${a[1]}/${a[1]}-${a[2]}.ebuild" ]] \
+ && ebuild_uses_mpi ${d}/${a[0]}/${a[1]} ${a[1]}-${a[2]} \
+ && found=1
+ else
+ [[ -f "${d}/${a[0]}/${a[1]}/${a[1]}-${a[2]}.ebuild" ]] && found=1
+ fi
+ [[ ${found} -ne 0 ]] && break
+ done
+ if [[ ${found} -ne 0 ]]; then
+ portage_tree=${d}
+ else
+ die "Could not find an ebuild for ${a[0]}/${a[1]}-${a[2]}."
+ fi
+ fi
+
+ ebuild_dir="${portage_tree}/${a[0]}/${a[1]}"
+}
+
+ebuild_uses_mpi() {
+ grep 'inherit .*mpi' "${1}/${2##*/}.ebuild" &>/dev/null
+}
+
+link_ebuild_dir() {
+ ln -snf "${ebuild_dir}" "${MPI_PORTDIR}"/${class}/${ebuild_dir##*/} \
+ || die "Failed to link ${ebuild_dir} to ${MPI_PORTDIR}/${class}/${ebuild_dir##*/}"
+}
+
+do_emerge() {
+ [[ ${DO_EMERGE} -eq 0 ]] && return 0
+ einfo "Emerging $*"
+ emerge ${emerge_opts} $* || die "emerge failed!"
+}
+
+# We should have only one target here.
+create_class() {
+ local mpi_class_pkg d mpi_class_pn
+
+ [[ ${#targets[@]} -ne 1 ]] && die "Can only create one class at a time."
+
+ for d in $(eselect mpi list -p); do
+ [ "${d}" == "${class}" ] && die "${class} has already been created."
+ done
+
+ # Prevent laziness
+ [[ ${targets[0]} == ${targets[0]##*/} ]] \
+ && targets[0]="sys-cluster/${targets[0]}"
+
+ parse_pkgspecs
+ get_ebuild_dir ${targets[0]} 1
+ mpi_class_pn=${ebuild_dir##*/}
+ mpi_class_pkg=${targets[0]}
+ handle_etc_portage ${targets[0]}
+ targets[0]="=${class}/${targets[0]##*/}"
+
+ # Refuse to break systems. If there is already a class
+ # installed in that directory, we're not going to add another one as
+ # the eclass doesn't fix one problem just to introduce a bigger one.
+ for d in $(find ${MPI_PORTDIR}/${class} -maxdepth 1 -mindepth 1 -type l 2>/dev/null);do
+ d=${d##*/}
+ [[ ${d} == ${mpi_class_pn} ]] && continue
+ for i in ${MPI_ALL_IMPS}; do
+ [[ ${i} == ${d} ]] \
+ && die "${class} already has MPI implementation ${d}, refusing to add ${mpi_class_pn}"
+ done
+ done
+
+ if [[ -d "${MPI_PORTDIR}"/${class} ]]; then
+ [[ ${VERBOSE} -ne 0 ]] && ewarn "Overlay for ${class} has already been created."
+ else
+ mkdir -p ${MPI_PORTDIR}/${class}
+ link_ebuild_dir
+ fi
+ if ! grep "^${class}$" /etc/portage/categories &>/dev/null; then
+ echo "${class}" >> /etc/portage/categories
+ fi
+
+
+cat << EOF
+Creating ${HILITE}${class}${NORMAL}
+ Class: ${GOOD}${class}${NORMAL}
+ MPI Implementation: ${GOOD}${mpi_class_pkg}${NORMAL}
+ Source: ${GOOD}${ebuild_dir}${NORMAL}
+ Destination: ${GOOD}${MPI_PORTDIR}/${class}${NORMAL}
+EOF
+ do_emerge ${targets[0]}
+}
+
+
+add_packages(){
+ local i j deps
+
+ [[ -d "${MPI_PORTDIR}"/${class} ]] || die "Class ${class} has not been created yet."
+ [[ ${#targets[@]} -lt 1 ]] && die "You need to specify at least one package"
+
+ parse_pkgspecs
+ for ((i=0;i<${#targets[@]};i++)); do
+ get_ebuild_dir ${targets[i]}
+ if ebuild_uses_mpi ${ebuild_dir} ${targets[i]}; then
+ link_ebuild_dir
+ handle_etc_portage ${targets[i]}
+ targets[i]="=${class}/${targets[i]##*/}"
+ else
+ targets[i]="=${targets[i]}"
+ fi
+
+ # I don't know about this, but do you have a better idea?
+ deps="$(emerge --color=n --onlydeps -p --quiet ${targets[i]})"
+ if [[ $? -ne 0 ]]; then
+ emerge --onlydeps -p ${targets[i]}
+ die "Unable to calculate deps for ${targets[i]}"
+ fi
+ deps=( $(echo ${deps} | sed -e 's:\[[a-z]* [A-Z] \] :=:g') )
+ for ((j=0;j<${#deps[@]};j++)); do
+ get_ebuild_dir ${deps[j]}
+ if ebuild_uses_mpi ${deps[i]}; then
+ link_ebuild_dir
+ fi
+ done
+ done
+cat << EOF
+Adding packages to ${HILIGHT}${class}${NORMAL}
+ Packages: ${GOOD}${targets[@]}${NORMAL}
+EOF
+ do_emerge ${targets[@]}
+}
+
+
+delete_class() {
+ local pkgs=( $(ls /var/db/pkg/${class}/ 2>/dev/null) )
+ local ext d i rc
+ [[ -d "${MPI_PORTDIR}"/${class} ]] || die "Class ${class} has not been created yet."
+ rc=0
+
+ for (( i=0; i<${#pkgs[@]}; i++)); do
+ pkgs[i]="=${class}/${pkgs[i]}"
+ done
+
+ if [[ ${#pkgs[@]} -gt 0 ]] && ! emerge -C ${emerge_opts/-u/} ${pkgs[@]}; then
+ die "Failed to unmerge ${pkgs[@]}"
+ fi
+
+ for ext in "keywords" "use"; do
+ if [ -d /etc/portage/package.${ext} ]; then
+ rm /etc/portage/package.${ext}/${class} &>/dev/null
+ rc=$((rc+$?))
+ elif [ -f /etc/portage/package.${ext} ]; then
+ sed -i -e "/${class}\//d" /etc/portage/package.${ext}
+ rc=$((rc+$?))
+ fi
+ done
+
+ [ ! -f /etc/portage/categories ] || sed -i -e "/^${class}$/d" /etc/portage/categories
+ rc=$((rc+$?))
+
+ for d in $(ls "${MPI_PORTDIR}"/${class}/ 2>/dev/null); do
+ rm "${MPI_PORTDIR}"/${class}/${d}
+ rc=$((rc+$?))
+ done
+
+ for d in "${MPI_PORTDIR}/${class}" /var/db/pkg/${class}; do
+ [ ! -d "${d}" ] || rmdir "${d}"
+ rc=$((rc+$?))
+ done
+
+ [[ ${rc} -ne 0 ]] \
+ && ewarn "Errors were encountered during delete_class()"
+ return ${rc}
+}
+
+
+[[ ${UID} -ne 0 ]] && die "You must be root."
+DO_EMERGE=1
+VERBOSE=0
+targets=""
+emerge_opts="-u" # Packages can be recompiled by hand if necessary.
+portage_tree=""
+action=""
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -h|--help)
+ usage;;
+ -c|--create)
+ action="${action}create";;
+ -a|--add)
+ action="${action}add";;
+ -d|--delete)
+ action="${action}delete"
+ shift; class=${1};;
+ -C|--class)
+ shift; class=${1};;
+ -t|--tree)
+ shift; portage_tree=${1};;
+ -o|--overlaydir)
+ shift; MPI_PORTDIR=${1};;
+ -v|--verbose)
+ VERBOSE=1;;
+ --noemerge)
+ DO_EMERGE=0;;
+ -*)
+ emerge_opts="${emerge_opts} ${1}";;
+ *)
+ targets=( $(echo ${targets[@]}) ${1} );;
+ esac
+ shift
+done
+
+if [ -z "${MPI_PORTDIR}" ]; then
+ MPI_PORTDIR="$(portageq portdir_overlay)"
+ MPI_PORTDIR="${MPI_PORTDIR%% *}"
+fi
+
+if [ ! -d "${MPI_PORTDIR}" ]; then
+ mkdir -p "${MPI_PORTDIR}" || die "Failed to mkdir ${MPI_PORTDIR}"
+fi
+
+export PORTDIR_OVERLAY="${MPI_PORTDIR} $(portageq portdir_overlay)"
+export PKGDIR="$(portageq envvar PKGDIR)/mpi/${class}"
+
+[[ -z ${action} ]] && usage 1 "No action defined."
+class_is_valid
+
+[[ ${action} == *create* ]] && create_class
+[[ ${action} == *add* ]] && add_packages
+[[ ${action} == *delete* ]] && delete_class