From 4bd31f0da05570e94b4d17c4de8f5cfe75fa65ca Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 17 Mar 2016 06:44:29 +0100 Subject: environment-modules: import from RHEL --- el6/createmodule.py | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100755 el6/createmodule.py (limited to 'el6/createmodule.py') diff --git a/el6/createmodule.py b/el6/createmodule.py new file mode 100755 index 0000000..62c4d18 --- /dev/null +++ b/el6/createmodule.py @@ -0,0 +1,237 @@ +#!/usr/bin/python +# +# createmodule.py - Takes the name of a environment init script and +# produces a modulefile that duplicates the changes made by the init script +# +# Copyright (C) 2012 by Orion E. Poplawski +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +from __future__ import print_function + +from optparse import OptionParser +import os,sys,re +from subprocess import * + +# Handle options +usage = "Usage: %prog [-p prefix] [args]" +parser = OptionParser() +parser.set_usage(usage) +parser.add_option('-p', '--prefix', action='store', type='string', dest='prefix', help='Specify path prefix') +parser.add_option('--noprefix', action='store_true', dest='noprefix', default=False, help='Do not generate a prefix') +(options, args) = parser.parse_args() + +# Need a script name +if not args: + parser.print_usage() + exit(1) + +# Return environment after a command +def getenv(cmd = ':'): + env = {} + p = Popen(cmd + ";env", shell=True, stdout=PIPE, stderr=PIPE) + (stdout, stderr) = p.communicate() + if p.returncode != 0: + print("EROR: Could not execute initscript:") + print("%s returned exit code %d" % (cmd, p.returncode)) + print(stderr) + exit(1) + if stderr != '': + print("WARNING: initscript sent the following to stderr:") + print(stderr) + # Parse the output key=value pairs + skip = False + for line in stdout.splitlines(): + if skip: + if line == '}': + skip = False + continue + try: + (var,value) = line.split('=',1) + except ValueError: + print("ERROR: Could not parse output line:") + print(line) + exit(1) + # Exported functions - not handled + if value.find('() {') == 0: + skip = True + else: + env[var] = value + return env + +#Record initial environment +env1=getenv() + +#Record environment after sourcing the initscript +env2=getenv(". " + " ".join(args)) + +# Initialize our variables for storing modifications +chdir = None +appendpath = {} +prependpath = {} +unhandled = {} +setenv = {} +unsetenv = [] +pathnames = [] + +# Function to nomalize all paths in a list of paths and remove duplicate items +def normpaths(paths): + newpaths = [] + for path in paths: + normpath = os.path.normpath(path) + if normpath not in newpaths and normpath != '.': + newpaths.append(os.path.normpath(path)) + return newpaths + +# Start with existing keys and look for changes +for key in env1.keys(): + # Test for delete + if key not in env2: + unsetenv.append(key) + continue + # No change + if env1[key] == env2[key]: + del env2[key] + continue + #Working directory change + if key == 'PWD': + chdir=os.path.normpath(env2[key]) + pathnames.append(chdir) + del env2[key] + continue + # Determine modifcations to beginning and end of the string + try: + (prepend,append) = env2[key].split(env1[key]) + except ValueError: + continue + if prepend: + presep = prepend[-1:] + prependpaths = prepend.strip(presep).split(presep) + # LICENSE variables often include paths outside install directory + if 'LICENSE' not in key: + pathnames += prependpaths + if presep not in prependpath: + prependpath[presep] = {} + newpath = presep.join(normpaths(prependpaths)) + if newpath: + prependpath[presep][key] = newpath + else: + unhandled[key] = env2[key] + if append: + appsep = append[0:1] + appendpaths = append.strip(appsep).split(appsep) + # LICENSE variables often include paths outside install directory + if 'LICENSE' not in key: + pathnames += appendpaths + if appsep not in appendpath: + appendpath[appsep] = {} + newpath = appsep.join(normpaths(appendpaths)) + if newpath: + appendpath[appsep][key] = newpath + else: + unhandled[key] = env2[key] + del env2[key] + +# We're left with new keys in env2 +for key in env2.keys(): + # Use prepend-path for new paths + if (re.search('(DIRS|FILES|PATH)$',key)) or (':' in env2[key]): + prependpaths = env2[key].strip(':').split(':') + # MANPATH can have system defaults added it it wasn't previously set + # LICENSE variables often include paths outside install directory + if key != 'MANPATH' and 'LICENSE' not in key: + pathnames += prependpaths + if ':' not in prependpath: + prependpath[':'] = {} + prependpath[':'][key] = ':'.join(normpaths(prependpaths)) + continue + # Set new variables + setenv[key] = os.path.normpath(env2[key]) + if 'LICENSE' not in key: + pathnames.append(setenv[key]) + +# Report unhandled keys +for key in unhandled.keys(): + print("Unhandled change of", key, file=sys.stderr) + print("Before <%s>" % env1[key], file=sys.stderr) + print("After <%s>" % unhandled[key], file=sys.stderr) + for sepkey in appendpath.keys(): + appendpath[sepkey].pop(key, None) + for sepkey in prependpath.keys(): + prependpath[sepkey].pop(key, None) + +# Determine a prefix +prefix=None +if options.prefix: + prefix = options.prefix +elif not options.noprefix: + prefix = os.path.commonprefix(pathnames).rstrip('/') + if prefix == '': + prefix = None + +# Print out the modulefile +print("#%Module 1.0") + +# Prefix +if prefix is not None: + print("\nset prefix " + prefix + "\n") + +# Chdir +if chdir is not None: + print("chdir\t" + chdir) + +# Function to format output line with tabs and substituting prefix +def formatline(item, key, value=None): + print(item, end=' ') + print("\t"*(2-(len(item)+1)/8), end=' ') + print(key, end=' ') + if value is not None: + print("\t"*(3-(len(key)+1)/8), end=' ') + if prefix is not None: + print(value.replace(prefix,'$prefix')) + else: + print(value) + +# Paths first, grouped by variable name +for sepkey in prependpath.keys(): + pathkeys = prependpath[sepkey].keys() + pathkeys.sort() + for key in pathkeys: + if sepkey == ":": + formatline("prepend-path",key,prependpath[sepkey][key]) + else: + formatline("prepend-path --delim %s" % sepkey,key,prependpath[sepkey][key]) + +for sepkey in appendpath.keys(): + pathkeys = appendpath[sepkey].keys() + pathkeys.sort() + for key in pathkeys: + if sepkey == ":": + formatline("append-path",key,appendpath[sepkey][key]) + else: + formatline("append-path --delim %s" % sepkey,key,appendpath[sepkey][key]) + +# Setenv +setenvkeys = list(setenv.keys()) +setenvkeys.sort() +if setenvkeys: + print() +for key in setenvkeys: + formatline("setenv",key,setenv[key]) + +# Unsetenv +unsetenv.sort() +if unsetenv: + print() +for key in unsetenv: + formatline("unsetenv",key) -- cgit