-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better detection of the module command #6451
Conversation
i don't know how modules are set up on HPC clusters, but this PR might fix #2563 (comment) |
I would like to work on this a bit more. |
Travis has some problems with testing on MacOs but the tests should pass. I think this is ready for merging. |
Restarted the tests on macOS. |
Is there any chance that this PR will be merged? |
I would need this PR as well. Being a relative spack noob, I'm not sure, though, how to deal with the code here, but I'd like to ask to accommodate the following use case for Modules-Tcl:
Background: This is from my HPC system where I use Modules-Tcl 1.962 (2017-08-09) and provide the functions above to my users. I implemented the |
@skosukhin any news on this? |
I'd like to sound a note of caution here about adding complexity to the existing (NB: I submitted #7536 which overlaps an edit with the present PR but does not address the same issues.) Trouble with current module interfaceSpack assumes one of the following:
Ideal(ized?) interfaceIdeally, Spack would interface with modules through the one and only interface that is documented and common across Modules-{C/Tcl} 3.x, Modules-4.x, Lmod, (others?), namely, the Variable expansion pitfalls.The motivation for the current PR seems to be to avoid evaluating the Consider the following example for how a $ cat /tmp/demo.sh
function module () {
local tcl=/usr/bin/tclsh
eval `$tcl /usr/share/Modules/libexec/modulecmd.tcl bash $*`
}
echo -e '\n== Demo =='
module -l avail dot
echo -e '\n== Definition, plain =='
typeset -f module
echo -e '\n== Definition, neutered =='
typeset -f module | envsubst Running this, we get:
The point is that trying to inspect the
In summary, the question is: Can and should(?) Spack interface with a locally active |
@mgsternberg, thank you for the analysis of the issue. Let me give a short history of the development of this feature. The function So, the first implementation was introduced with the assumption that Later the idea was implemented (#3250). Although I was quite sceptical in the beginning, it turned out that it just worked in many cases (I have an opportunity to test Spack on a comparably large number of machines). Now, there are cases, in which a really old version of Environment Modules is used. The first problem is that such old versions don't generate correct Python scripts. This PR targets this issue (not in the best way but I would be glad to learn about a better way). The second problem is related to the initialization script of Environment Modules. Depending on the mode, bash gets initialized by running different scripts: (it should be noted that there are cases, in which bash doesn't follow the documentation). In the ideal case, Another issue targeted by this PR is that we can't retrieve the definition of the I didn't change the approach that is already implemented in I admit that the number of cases when this won't work is large. Environment Modules are often configured in ways that just don't account for the scenarios, in which modules are loaded not from bash. Although I think that we should give users an option to specify a command that generates correct Python module loading scripts in Spack's configure file. |
Sergey, Thank you for illuminating the history! On interfacing with a module shell function
Not quite –
I have some quibbles with the code details (discussed at #7536), but the general approach is reasonable. That said, using Python to dump the environment could introduce an "observer effect". I'd rather prefer On the Module installation and versions landscapeAs you explain, to interface with Modules on different systems, Spack deals with the following issues: A. The Putting a grumpy hat on, I must say that this should not be Spack's problem to solve in the first place. But I realize that the cause may not be mere inexperience on the part of a local admin or user but could also be the need for a conservative or controlled approach in critical environments like handling beamline or accelerator data. That, of course, wouldn't help a user who has to work with an uncooperative B. Older Modules versions generate incorrect Python. OK; I'll review the implications of that.
|
@alalazo @adamjstewart do you think this PR has a chance to be merged? I admit that the approach suggested by @mgsternberg is definitely worth trying, but perfect is the enemy of the good. I believe that this PR already improves what we have in Take a look at my modifications of BTW, #7884 touches the same part of the code. |
I don't like to merge non-package PRs myself. A PR like this definitely requires a lot of testing and unit tests. I agree that a fix is much needed, and this has been a long-standing issue. I just don't know enough about it to merge it myself. |
@skosukhin I'm trying this out for the first time and I'm seeing the following error message: $ spack uninstall zlib
==> Warning: Failed to detect module function as a shell function in the current environment: Bash function 'module' is not defined or exported. Trying to detect in the interactive login shell.
Traceback (most recent call last):
File "/u/sciteam/stewart1/spack/bin/spack", line 80, in <module>
import spack.main # noqa
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/__init__.py", line 84, in <module>
import spack.repository
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/repository.py", line 52, in <module>
import spack.spec
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/spec.py", line 119, in <module>
import spack.compilers as compilers
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/compilers/__init__.py", line 36, in <module>
import spack.config
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/config.py", line 212, in <module>
_platform = spack.architecture.platform().name
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/llnl/util/lang.py", line 182, in __call__
self.cache[args] = self.func(*args)
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/architecture.py", line 499, in platform
return platform_cls()
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/platforms/cray.py", line 69, in __init__
for target in self._avail_targets():
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/platforms/cray.py", line 146, in _avail_targets
module = get_module_cmd()
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/util/module_cmd.py", line 88, in get_module_cmd
result(error=str)) is not None:
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/util/executable.py", line 184, in __call__
proc.returncode, cmd_line)
spack.util.executable.ProcessError: Command exited with status 1:
'/opt/modules/3.2.10.4/bin/modulecmd' 'python' |
@skosukhin @mgsternberg @adamjstewart I've submitted a fix with @mgsternberg's approach in #8570. Can you confirm that it fully obviates the need for this PR? |
Use new `module` function instead of `get_module_cmd` Previously, Spack relied on either examining the bash `module()` function or using the `which` command to find the underlying executable for modules. More complicated module systems do not allow for the sort of simple analysis we were doing (see #6451). Spack now uses the `module` function directly and copies environment changes from the resulting subprocess back into Spack. This should provide a future-proof implementation for changes to the logic underlying the module system on various HPC systems.
Some improvements for the
module
command detection and execution:get_module_cmd_from_bash()
is agnostic to the naming format of environment variables that are used for storing of shell functions (i.e.$BASH_FUNC_module()
or$BASH_FUNC_module%%
).module
is defined with shell variables that are set in the bash initialization scripts but not exported.exec '/tmp/modulescript_12345_00'
).bashopts
, which was used only for testing, is removed from the functionget_module_cmd_from_bash()
get_module_cmd()
.