diff options
Diffstat (limited to 'sys-cluster/empi/files/empi-0.5')
-rwxr-xr-x | sys-cluster/empi/files/empi-0.5 | 360 |
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 |