modmanage.in 6.99 KB
Newer Older
1
#!@PMODULES_HOME@/bin/bash
2

3
shopt -s expand_aliases
4

5 6
declare -r bindir=$(cd $(dirname "$0") && pwd)
declare -r libdir=$(cd "${bindir}/../lib" && pwd)
7

8
source "${libdir}/libpmodules.bash"
9 10 11 12 13 14

print_version() {
	echo "
Pmodules ${version} using Tcl Environment Modules @MODULES_VERSION@
Copyright GNU GPL v2
" 1>&2
15 16
}

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
usage() {
	local -r prog=$(basename $0)
	print_version
	echo "
Usage: ${prog} [ switches ] [ subcommand ] [subcommand-args ]

Switches:
        --dry-run     do nothing
        --force       force overwrite

Available SubCommands and Args:
        init [--src=<src>] [--user=<user>] --dst=<dst>
                Initialize a new minimal Pmodule environment.
"
}
     
33 34

declare force='no'
35 36
declare dry_run='no'
declare DRY=''
37 38
declare subcommand=''
declare sargs=()
39

40 41 42 43 44 45 46 47
subcommand_help_init() {
	echo "
init [--src=<src>] [--user=<user>] <dst>
                Initialize a new minimal Pmodule environment in directory
                <dst>. The <user> parameter must only be present if
                 ${prog} is executed as root.
" 1>&2
}
48

49 50 51 52 53 54 55 56 57
subcommand_help() {
	if [[ $# == 0 ]]; then
	        usage
	elif typeset -F subcommand_help_$1 > /dev/null 2>&1 ; then
	        # help for sub-command
		subcommand_help_$1
	else
		usage
	fi
58 59
}

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
#
# Derive the relative module installation path
# from the relative modulefile path
#
# $1: relative module file path
#
get_module_prefix() {
	local -a comp=( ${1//\// } )    # split rel.path into components
	local path="${comp[0]}"		# result path
	local -i i
	for ((i=1; i<${#comp[@]}; i+=2)); do
		path+="/${comp[$((-i-1))]}/${comp[$((-i))]}"
	done
	echo "${path}"
}

#
# Derive the relative module release file path
# from the relative module file path
#
# $1: relative module file path
#
get_releasefile_name() {
	echo "$(dirname "$1")/.release-$(basename "$1")"
}

#
# Sync a module from one Pmodules environment to another:
# - sync module installation
# - sync modulefile
# - sync release file
#
# $1: relative modulefile path
# $2: source prefix of Pmodule environment
# $3: target prefix of Pmodule environment
#
sync_module() {
	local -r rel_modulefile=$1
	local -r src_prefix=$2
	local -r target_prefix=$3

	local -r rel_module_prefix=$( get_module_prefix "${rel_modulefile}" )
	local -r rel_releasefile=$( get_releasefile_name "${rel_modulefile}" )

104
	$DRY mkdir -p "${target_prefix}/${rel_module_prefix}" || return $?
105 106 107
	$DRY rsync --links --perms --recursive --delete \
	      "${src_prefix}/${rel_module_prefix}/" \
	      "${target_prefix}/${rel_module_prefix}/" || return $?
108 109 110 111 112 113 114 115

	local -r src_modulefile="${src_prefix}/${PSI_MODULES_ROOT}/${rel_modulefile}"
	local -r src_releasefile="${src_prefix}/${PSI_MODULES_ROOT}/${rel_releasefile}"
	local -r target_modulefile="${target_prefix}/${PSI_MODULES_ROOT}/${rel_modulefile}"
	local -r target_releasefile="${target_prefix}/${PSI_MODULES_ROOT}/${rel_releasefile}"

	if [[ -e "${src_modulefile}" ]] || [[ -e "${src_releasefile}" ]]; then
	        local dir=$( dirname "${target_modulefile}" )
116
		$DRY mkdir -p "${dir}" || return $?
117 118 119 120 121 122 123 124 125
	fi
	if [[ -e "${src_modulefile}" ]]; then
	        $DRY rsync --links --perms --recursive \
		     "${src_modulefile}" "${target_modulefile}" || return $?
	fi
	if [[ -e "${src_releasefile}" ]]; then
	        $DRY rsync --links --perms --recursive \
		     "${src_releasefile}" "${target_releasefile}" || return $?
	fi
126 127
}

128 129
subcommand_init() {
	local src=''
130
	local target_prefixes=()
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
	local user=''
	local opts=''
	opts=$(get_options -o h -l src: -l user: -l help -- "$@")
	if [[ $? != 0 ]]; then
		subcommand_help_init
		exit 1
	fi
	eval set --  "${opts}"
	while (($# > 0)); do
		case $1 in 
			--src )
				src=$2
				shift
				;;
			--user )
				user=$2
				shift
				;;
			-- )
				:
				;;
			-* | -h | --help )
				echo "$1: illegal option" 1>&2
				subcommand_help_init
				exit 1
				;;
			* )
158
				target_prefixes+=( "$1" )
159 160 161 162
				;;
		esac
		shift
	done
163
	(( ${#target_prefixes[@]} != 0 )) || die 1 "Error: no target directory specified!"
164

165 166
	if [[ -n "${src}" ]]; then
		[[ -d "${src}" ]] || die 1 "Error: ${src}: source directory does not exist!"
167 168
		[[ -r "${src}/config/profile.bash" ]] || \
		    die 1 "Error: ${src}: shell profile does not exist or is not readable!"
169 170 171 172
		source "${src}/config/profile.bash"
	fi
	local -i euid=$(id -u)
	if (( euid == 0 )); then
173
	        [[ -n "${user}" ]] || \
174
		    die 1 "Error: --user parameter is required!"
175 176
		id -u "${user}" > /dev/null 2>&1 || \
		    die 1 "Error: Unable to retrieve user id of user '${user}'"
177
	else
178
		[[ -z "${user}" ]] || \
179
		    die 1 "Error: --user option is only allowed if running as root!"
180
	fi
181 182 183
	
	check_pmodules_env || die 1 "Giving up ..."
	
184
	echo "
185 186 187 188
Attempting to create a minimal module environment from the
environment at '${PSI_PREFIX}'
"

189 190
	init_pmodules_environment() {
		local -r target_prefix=$1
191 192
		local src=''
		local dst=''
193 194 195 196
		echo "Initializing target directory '${target_prefix}' ..."
		echo
		if [[ -d "${target_prefix}" ]]  && [[ ${force} == no ]]; then
			echo "Warning: ${target_prefix} already exists."
197
			get_YN_answer "Do you really want to re-run the initialization? (y/N) " || \
198
				      die 1 "Abort ..."
199
		fi
200

201 202
		echo "Creating target directory '${target_prefix}'..."
		$DRY mkdir -p "${target_prefix}" || die 1 "Error: make directory failed!"
203
		echo
204 205

		src="${PSI_PREFIX}/${PSI_CONFIG_DIR}/"
206
		dst="${target_prefix}/${PSI_CONFIG_DIR}/"
207 208 209 210 211 212
		echo "Synching configuration from '${src}' to '${dst}'..."
		$DRY rsync --recursive --links --perms --delete \
		     "${src}" "${dst}" || die 1 "Error: synch operation failed!"
		echo
		
		src="${PSI_PREFIX}/${PSI_TEMPLATES_DIR}/"
213
		dst="${target_prefix}/${PSI_TEMPLATES_DIR}/"
214 215 216 217
		echo "Synching template files from '${src}' to '${dst}'..."
		$DRY rsync --recursive --links --perms --delete \
		     "${src}" "${dst}" || die 1 "Error: synch operation failed!"
		echo
218 219 220 221 222

		echo "Syncing Pmodules ..."
		sync_module "Tools/Pmodules/${PMODULES_VERSION}" \
			    "${PSI_PREFIX}" \
			    "${target_prefix}" || die 1 "Error: sync Pmodules failed!"
223 224
		echo
		
225 226 227 228
		if [[ -n "${user}" ]]; then
	                echo "Changing user of new module environment to '${user}'..."
                        $DRY chown -R "${user}" "${target_prefix}" || die 1 "Error: changing owner failed!"
                        echo
229
		fi
230
		echo "New minimal module environment created at '${target_prefix}'."
231
		echo "To use this environment, execute"
232 233
		echo "   sudo ln -fs ${target_prefix} /opt/psi"
		echo "   source /opt/psi/${PSI_CONFIG_DIR}/profile.bash"
234 235 236
	}

	umask 022
237 238
	for target_prefix in "${target_prefixes[@]}"; do
		init_pmodules_environment "${target_prefix}"
239 240
	done

241 242
}

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
while (($# > 0)); do
	case $1 in
		-h | -H | -\? | --help | -help )
			usage
			exit 1
			;;
		-V | --version )
			print_version
			exit 1
			;;
		-f | --force )
			force='yes'
			;;
		--dry-run )
			dry_run='yes'
			DRY='echo'
			;;
		-* )
			echo "$1: unknown switch.\n" 1>&2
			exit 1
			;;
		init|help )
			subcommand="subcommand_$1"
			shift
			sargs=( $* )
			shift $#
			;;
		* )
			echo "$1: unknown sub-command" 1>&2
			exit 1
	esac
	shift
275
done
276 277 278 279 280 281 282 283

$subcommand "${sargs[@]}"

# Local Variables:
# mode: sh
# sh-basic-offset: 8
# tab-width: 8
# End: