Skip to content

Commit c7b5906

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into sort-list-toolchains
2 parents 92c9b90 + 7c1c288 commit c7b5906

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+3824
-447
lines changed

.github/workflows/unit_tests.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ jobs:
4949

5050
- name: install OS & Python packages
5151
run: |
52+
# disable apt-get update, we don't really need it,
53+
# and it does more harm than good (it's fairly expensive, and it results in flaky test runs)
54+
# sudo apt-get update
5255
# for modules tool
5356
sudo apt-get install lua5.2 liblua5.2-dev lua-filesystem lua-posix tcl tcl-dev
5457
# fix for lua-posix packaging issue, see https://bugs.launchpad.net/ubuntu/+source/lua-posix/+bug/1752082

.travis.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,18 @@ script:
5757
- if [ ! -z $MOD_INIT ] && [ ! -z $LMOD_VERSION ]; then alias ml=foobar; fi
5858
# set up environment for modules tool (if $MOD_INIT is defined)
5959
- if [ ! -z $MOD_INIT ]; then source $MOD_INIT; type module; fi
60-
# install GitHub token
60+
# install GitHub token;
61+
# unset $GITHUB_TOKEN environment variable after installing token,
62+
# to avoid that it is included in environment dump that is included in EasyBuild debug logs,
63+
# which causes test_from_pr_token_log to fail...
6164
- if [ ! -z $GITHUB_TOKEN ]; then
6265
if [ "x$TRAVIS_PYTHON_VERSION" == 'x2.6' ];
6366
then SET_KEYRING="keyring.set_keyring(keyring.backends.file.PlaintextKeyring())";
6467
else SET_KEYRING="import keyrings; keyring.set_keyring(keyrings.alt.file.PlaintextKeyring())";
6568
fi;
6669
python -c "import keyring; $SET_KEYRING; keyring.set_password('github_token', 'easybuild_test', '$GITHUB_TOKEN')";
67-
fi
70+
fi;
71+
unset GITHUB_TOKEN;
6872
- if [ ! -z $TEST_EASYBUILD_MODULES_TOOL ]; then export EASYBUILD_MODULES_TOOL=$TEST_EASYBUILD_MODULES_TOOL; fi
6973
- if [ ! -z $TEST_EASYBUILD_MODULE_SYNTAX ]; then export EASYBUILD_MODULE_SYNTAX=$TEST_EASYBUILD_MODULE_SYNTAX; fi
7074
# create 'source distribution' tarball, like we do when publishing a release to PyPI

RELEASE_NOTES

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,80 @@ For more detailed information, please see the git log.
33

44
These release notes can also be consulted at https://easybuild.readthedocs.io/en/latest/Release_notes.html.
55

6+
v4.2.0 (April 14th 2020)
7+
------------------------
8+
9+
feature release
10+
11+
- add support for --try-update-deps (experimental feature), to upgrade dependencies based on available easyconfigs (#2599)
12+
- adding locking to prevent two parallel builds of the same installation directory (#3009)
13+
- for more information, see https://easybuild.readthedocs.io/en/latest/Locks.html
14+
- significantly speed up -D/--dry-run by avoiding useless 'module show' (#3203)
15+
- add support for creating an index & using it when searching for easyconfigs (#3210)
16+
- for more information, see https://easybuild.readthedocs.io/en/latest/Easyconfigs_index.html
17+
- additional GitHub integration features:
18+
- add support for targeting easyblocks and framework repositories in --new-pr (#1876, #3189)
19+
- add support for --include-easyblocks-from-pr (#3206)
20+
- for more information, https://easybuild.readthedocs.io/en/latest/Integration_with_GitHub.html
21+
- various other enhancements, including:
22+
- add a contrib/hooks dir with some examples of hooks used (#2777)
23+
- also mention working directory + input passed via stdin (if any) in trace output of run_cmd (#3168)
24+
- probe external modules for missing metadata that is not provided via extermal module metadata file (#3174)
25+
- also update $CMAKE_PREFIX_PATH and $CMAKE_LIBRARY_PATH in generated module file (#3176)
26+
- optionally call log.warning in print_warning (#3195)
27+
- add an option to git_config to retain the .git directory (#3197)
28+
- allow use of SYSTEM as --try-toolchain option (#3213)
29+
- mention CPU arch name in comment for uploaded test report, if it's known by archspec (#3227)
30+
- make --merge-pr take into account --pr-target-branch (#3236)
31+
- make --check-contrib print a warning when None is used for checksums (#3244)
32+
- update install-EasyBuild-develop.sh script and create script for 2020a merge sprint (#3245)
33+
- add template for mpi_cmd_prefix (#3264)
34+
- update copy_dir to include option to merge directories (#3270)
35+
- support template name for CUDA version (#3274)
36+
- various bug fixes, including:
37+
- use correct module for errors_found_in_log (#3119)
38+
- fix EasyConfig.update code to handle both strings and lists as input (#3170)
39+
- fix removing temporary branch on --check-github (#3182)
40+
- fix shebang even if first line doesn't start with '#!' (#3183)
41+
- make boostrap script work with Python 3 (#3186)
42+
- read patch files as bytestring to avoid UnicodeDecodeError for patches that include funky characters (#3191)
43+
- fix online check in --check-github: try repeatedly and with different URLs to cater for HTTP issues (#3194)
44+
- don't crash when GitPython is not installed when using Python 3 (#3198)
45+
- fix os_name_map for RHEL8 (#3201)
46+
- don't add shebang to binary files (#3208)
47+
- use checkout@v2 in GitHub Actions to fix broken re-triggered tests (#3219)
48+
- don't filter out None values in to_checksums, leave them in place (#3225)
49+
- fix defining of $MPI_INC_* and $MPI_LIB_* environment variables for impi version 2019 and later (#3229)
50+
- use correct target account/repo when creating test report & posting comment in PR (#3234)
51+
- reorganize EasyBlock.extensions_step to ensure correct filtering of extensions (#3235)
52+
- also support %(installdir)s and %(builddir)s templates for extensions (#3237)
53+
- unset $GITHUB_TOKEN in Travis after installing token, to avoid failing test_from_pr_token_log (#3252)
54+
- fix reporting when skipping extensions (#3254)
55+
- avoid API rate limit errors on online check in --check-github (#3257)
56+
- show easyconfig filenames for parallel build (#3258)
57+
- make EasyConfig.dump aware of toolchain hierarchy, to avoid hardcoded subtoolchains in dependencies easyconfig parameters (#3261)
58+
- fix use of --copy-ec with a single argument, assume copy to current working directory (#3262)
59+
- fix posting of comment in PR with --upload-test-report (#3272)
60+
- take into account dependencies marked as external modules when composing template values like %(pyver)s (#3273)
61+
- other changes:
62+
- increase timeout & use api.github.com for connectivity check in check_github (#3192)
63+
- restore flake8 default ignores (#3193)
64+
- enable tracking of test suite coverage using coveralls (#3204)
65+
- make tests use easybuilders/testrepository rather than hpcugent/testrepository after it was moved (#3238)
66+
- improve raised error in remove_dir and deprecate rmtree2 (#3228)
67+
68+
69+
v4.1.2 (March 16th 2020)
70+
------------------------
71+
72+
bugfix release
73+
74+
- fix gitdb dependency on Python 2.6 in test configuration (#3212)
75+
- fix broken test for --review-pr by using different PR to test with (#3226)
76+
- censor authorization part of headers before logging ReST API request (#3248)
77+
- see also https://github.com/easybuilders/easybuild-framework/security/advisories/GHSA-2wx6-wc87-rmjm
78+
79+
680
v4.1.1 (January 16th 2020)
781
--------------------------
882

contrib/hooks/README.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Example implementations of EasyBuild hooks
2+
=================================
3+
4+
.. image:: https://easybuilders.github.io/easybuild/images/easybuild_logo_small.png
5+
:align: center
6+
7+
EasyBuild website: https://easybuilders.github.io/easybuild/
8+
docs: https://easybuild.readthedocs.io
9+
10+
This directory contain examples of implementations of EasyBuild hooks
11+
used at various sites, along with a couple of small examples with
12+
explanations.
13+
14+
See https://easybuild.readthedocs.io/en/latest/Hooks.html for
15+
documentation on hooks in EasyBuild.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Small example of how to add/delete a configure option.
2+
#
3+
# Author: Åke Sandgren, HPC2N
4+
5+
# We need to be able to distinguish between versions of OpenMPI
6+
from distutils.version import LooseVersion
7+
8+
9+
def pre_configure_hook(self, *args, **kwargs):
10+
# Check that we're dealing with the correct easyconfig file
11+
if self.name == 'OpenMPI':
12+
extra_opts = ""
13+
# Enable using pmi from slurm
14+
extra_opts += "--with-pmi=/lap/slurm "
15+
16+
# And enable munge for OpenMPI versions that knows about it
17+
if LooseVersion(self.version) >= LooseVersion('2'):
18+
extra_opts += "--with-munge "
19+
20+
# Now add the options
21+
self.log.info("[pre-configure hook] Adding %s" % extra_opts)
22+
self.cfg.update('configopts', extra_opts)
23+
24+
# Now we delete some options
25+
# For newer versions of OpenMPI we can re-enable ucx, i.e. delete the --without-ucx flag
26+
if LooseVersion(self.version) >= LooseVersion('2.1'):
27+
self.log.info("[pre-configure hook] Re-enabling ucx")
28+
self.cfg['configopts'] = self.cfg['configopts'].replace('--without-ucx', ' ')
29+
30+
# And we can remove the --disable-dlopen option from the easyconfig file
31+
self.log.info("[pre-configure hook] Re-enabling dlopen")
32+
self.cfg['configopts'] = self.cfg['configopts'].replace('--disable-dlopen', ' ')

contrib/hooks/hpc2n_hooks.py

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# Hooks for HPC2N site changes.
2+
#
3+
# Author: Ake Sandgren, HPC2N
4+
5+
import os
6+
7+
from distutils.version import LooseVersion
8+
from easybuild.framework.easyconfig.format.format import DEPENDENCY_PARAMETERS
9+
from easybuild.tools.filetools import apply_regex_substitutions
10+
from easybuild.tools.build_log import EasyBuildError
11+
from easybuild.tools.modules import get_software_root
12+
from easybuild.tools.systemtools import get_shared_lib_ext
13+
14+
# Add/remove dependencies and/or patches
15+
# Access to the raw values before templating and such.
16+
def parse_hook(ec, *args, **kwargs):
17+
18+
# Internal helper function
19+
def add_extra_dependencies(ec, dep_type, extra_deps):
20+
"""dep_type: must be in DEPENDENCY_PARAMETERS or 'osdependencies'"""
21+
ec.log.info("[parse hook] Adding %s: %s" % (dep_type, extra_deps))
22+
23+
if dep_type in DEPENDENCY_PARAMETERS:
24+
for dep in extra_deps:
25+
ec[dep_type].append(dep)
26+
elif dep_type == 'osdependencies':
27+
if isinstance(extra_deps, tuple):
28+
ec[dep_type].append(extra_deps)
29+
else:
30+
raise EasyBuildError("parse_hook: Type of extra_deps argument (%s), for 'osdependencies' must be "
31+
"tuple, found %s" % (extra_deps, type(extra_deps)))
32+
else:
33+
raise EasyBuildError("parse_hook: Incorrect dependency type in add_extra_dependencies: %s" % dep_type)
34+
35+
extra_deps = []
36+
37+
if ec.name == 'OpenMPI':
38+
if LooseVersion(ec.version) >= LooseVersion('2') and LooseVersion(ec.version) < LooseVersion('2.1.2'):
39+
ec.log.info("[parse hook] Adding pmi and lustre patches")
40+
if LooseVersion(ec.version) < LooseVersion('2.1.1'):
41+
ec['patches'].append('OpenMPI-2.0.0_fix_bad-include_of_pmi_h.patch')
42+
43+
if LooseVersion(ec.version) < LooseVersion('2.0.2'):
44+
ec['patches'].append('OpenMPI-2.0.1_fix_lustre.patch')
45+
elif LooseVersion(ec.version) < LooseVersion('2.1'):
46+
ec['patches'].append('OpenMPI-2.0.2_fix_lustre.patch')
47+
elif LooseVersion(ec.version) < LooseVersion('2.1.1'):
48+
ec['patches'].append('OpenMPI-2.1.0_fix_lustre.patch')
49+
else:
50+
ec['patches'].append('OpenMPI-2.1.1_fix_lustre.patch')
51+
52+
if LooseVersion(ec.version) == LooseVersion('4.0.0'):
53+
ec['patches'].append('OpenMPI-4.0.0_fix_configure_bug.patch')
54+
55+
if LooseVersion(ec.version) >= LooseVersion('2.1'):
56+
pmix_version = '1.2.5'
57+
ucx_version = '1.4.0'
58+
if LooseVersion(ec.version) >= LooseVersion('3'):
59+
pmix_version = '2.2.1'
60+
if LooseVersion(ec.version) >= LooseVersion('4'):
61+
pmix_version = '3.0.2' # OpenMPI 4.0.0 is not compatible with PMIx 3.1.x
62+
63+
extra_deps.append(('PMIx', pmix_version))
64+
# Use of external PMIx requires external libevent
65+
# But PMIx already has it as a dependency so we don't need
66+
# to explicitly set it.
67+
68+
extra_deps.append(('UCX', ucx_version))
69+
70+
if ec.name == 'impi':
71+
pmix_version = '3.1.1'
72+
extra_deps.append(('PMIx', pmix_version))
73+
74+
if extra_deps:
75+
add_extra_dependencies(ec, 'dependencies', extra_deps)
76+
77+
78+
def pre_configure_hook(self, *args, **kwargs):
79+
if self.name == 'GROMACS':
80+
# HPC2N always uses -DGMX_USE_NVML=ON on GPU builds
81+
if get_software_root('CUDA'):
82+
self.log.info("[pre-configure hook] Adding -DGMX_USE_NVML=ON")
83+
self.cfg.update('configopts', "-DGMX_USE_NVML=ON ")
84+
85+
if self.name == 'OpenMPI':
86+
extra_opts = ""
87+
# Old versions don't work with PMIx, use slurms PMI1
88+
if LooseVersion(self.version) < LooseVersion('2.1'):
89+
extra_opts += "--with-pmi=/lap/slurm "
90+
if LooseVersion(self.version) >= LooseVersion('2'):
91+
extra_opts += "--with-munge "
92+
93+
# Using PMIx dependency in easyconfig, see above
94+
if LooseVersion(self.version) >= LooseVersion('2.1'):
95+
if get_software_root('PMIx'):
96+
extra_opts += "--with-pmix=$EBROOTPMIX "
97+
# Use of external PMIx requires external libevent
98+
# We're using the libevent that comes from the PMIx dependency
99+
if get_software_root('libevent'):
100+
extra_opts += "--with-libevent=$EBROOTLIBEVENT "
101+
else:
102+
raise EasyBuildError("Error in pre_configure_hook for OpenMPI: External use of PMIx requires "
103+
"external libevent, which was not found. "
104+
"Check parse_hook for dependency settings.")
105+
else:
106+
raise EasyBuildError("Error in pre_configure_hook for OpenMPI: PMIx not defined in dependencies. "
107+
"Check parse_hook for dependency settings.")
108+
109+
if get_software_root('UCX'):
110+
extra_opts += "--with-ucx=$EBROOTUCX "
111+
112+
if LooseVersion(self.version) >= LooseVersion('2'):
113+
extra_opts += "--with-cma "
114+
extra_opts += "--with-lustre "
115+
116+
# We still need to fix the knem package to install its
117+
# pkg-config .pc file correctly, and we need a more generic
118+
# install dir.
119+
# extra_opts += "--with-knem=/opt/knem-1.1.2.90mlnx1 "
120+
121+
self.log.info("[pre-configure hook] Adding %s" % extra_opts)
122+
self.cfg.update('configopts', extra_opts)
123+
124+
if LooseVersion(self.version) >= LooseVersion('2.1'):
125+
self.log.info("[pre-configure hook] Re-enabling ucx")
126+
self.cfg['configopts'] = self.cfg['configopts'].replace('--without-ucx', ' ')
127+
128+
self.log.info("[pre-configure hook] Re-enabling dlopen")
129+
self.cfg['configopts'] = self.cfg['configopts'].replace('--disable-dlopen', ' ')
130+
131+
if self.name == 'PMIx':
132+
self.log.info("[pre-configure hook] Adding --with-munge")
133+
self.cfg.update('configopts', "--with-munge ")
134+
if LooseVersion(self.version) >= LooseVersion('2'):
135+
self.log.info("[pre-configure hook] Adding --with-tests-examples")
136+
self.cfg.update('configopts', "--with-tests-examples ")
137+
self.log.info("[pre-configure hook] Adding --disable-per-user-config-files")
138+
self.cfg.update('configopts', "--disable-per-user-config-files")
139+
140+
141+
def pre_build_hook(self, *args, **kwargs):
142+
if self.name == 'pyslurm':
143+
self.log.info("[pre-build hook] Adding --slurm=/lap/slurm")
144+
self.cfg.update('buildopts', "--slurm=/lap/slurm ")
145+
146+
147+
def post_install_hook(self, *args, **kwargs):
148+
if self.name == 'impi':
149+
# Fix mpirun from IntelMPI to explicitly unset I_MPI_PMI_LIBRARY
150+
# it can only be used with srun.
151+
self.log.info("[post-install hook] Unset I_MPI_PMI_LIBRARY in mpirun")
152+
apply_regex_substitutions(os.path.join(self.installdir, "intel64", "bin", "mpirun"), [
153+
(r'^(#!/bin/sh.*)$', r'\1\nunset I_MPI_PMI_LIBRARY'),
154+
])
155+
156+
157+
def pre_module_hook(self, *args, **kwargs):
158+
if self.name == 'impi':
159+
# Add I_MPI_PMI_LIBRARY to module for IntelMPI so it works with
160+
# srun.
161+
self.log.info("[pre-module hook] Set I_MPI_PMI_LIBRARY in impi module")
162+
# Must be done this way, updating self.cfg['modextravars']
163+
# directly doesn't work due to templating.
164+
en_templ = self.cfg.enable_templating
165+
self.cfg.enable_templating = False
166+
shlib_ext = get_shared_lib_ext()
167+
pmix_root = get_software_root('PMIx')
168+
if pmix_root:
169+
mpi_type = 'pmix_v3'
170+
self.cfg['modextravars'].update({
171+
'I_MPI_PMI_LIBRARY': os.path.join(pmix_root, "lib", "libpmi." + shlib_ext)
172+
})
173+
self.cfg['modextravars'].update({'SLURM_MPI_TYPE': mpi_type})
174+
# Unfortunately UCX doesn't yet work for unknown reasons. Make sure it is off.
175+
self.cfg['modextravars'].update({'SLURM_PMIX_DIRECT_CONN_UCX': 'false'})
176+
else:
177+
self.cfg['modextravars'].update({'I_MPI_PMI_LIBRARY': "/lap/slurm/lib/libpmi.so"})
178+
self.cfg.enable_templating = en_templ
179+
180+
if self.name == 'OpenBLAS':
181+
self.log.info("[pre-module hook] Set OMP_NUM_THREADS=1 in OpenBLAS module")
182+
self.cfg.update('modluafooter', 'if ((mode() == "load" and os.getenv("OMP_NUM_THREADS") == nil) '
183+
'or (mode() == "unload" and os.getenv("__OpenBLAS_set_OMP_NUM_THREADS") == "1")) then '
184+
'setenv("OMP_NUM_THREADS","1"); setenv("__OpenBLAS_set_OMP_NUM_THREADS", "1") end')
185+
186+
if self.name == 'OpenMPI':
187+
if LooseVersion(self.version) < LooseVersion('2.1'):
188+
mpi_type = 'openmpi'
189+
elif LooseVersion(self.version) < LooseVersion('3'):
190+
mpi_type = 'pmix_v1'
191+
elif LooseVersion(self.version) < LooseVersion('4'):
192+
mpi_type = 'pmix_v2'
193+
else:
194+
mpi_type = 'pmix_v3'
195+
196+
self.log.info("[pre-module hook] Set SLURM_MPI_TYPE=%s in OpenMPI module" % mpi_type)
197+
# Must be done this way, updating self.cfg['modextravars']
198+
# directly doesn't work due to templating.
199+
en_templ = self.cfg.enable_templating
200+
self.cfg.enable_templating = False
201+
self.cfg['modextravars'].update({'SLURM_MPI_TYPE': mpi_type})
202+
# Unfortunately UCX doesn't yet work for unknown reasons. Make sure it is off.
203+
self.cfg['modextravars'].update({'SLURM_PMIX_DIRECT_CONN_UCX': 'false'})
204+
self.cfg.enable_templating = en_templ
205+
206+
if self.name == 'PMIx':
207+
# This is a, hopefully, temporary workaround for https://github.com/pmix/pmix/issues/1114
208+
if LooseVersion(self.version) > LooseVersion('2') and LooseVersion(self.version) < LooseVersion('3'):
209+
self.log.info("[pre-module hook] Set PMIX_MCA_gds=^ds21 in PMIx module")
210+
en_templ = self.cfg.enable_templating
211+
self.cfg.enable_templating = False
212+
self.cfg['modextravars'].update({'PMIX_MCA_gds': '^ds21'})
213+
self.cfg.enable_templating = en_templ

easybuild/base/rest.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
:author: Jens Timmerman
3636
"""
3737
import base64
38+
import copy
3839
import json
3940
from functools import partial
4041

@@ -162,7 +163,13 @@ def request(self, method, url, body, headers, content_type=None):
162163
if self.auth_header is not None:
163164
headers['Authorization'] = self.auth_header
164165
headers['User-Agent'] = self.user_agent
165-
fancylogger.getLogger().debug('cli request: %s, %s, %s, %s', method, url, body, headers)
166+
167+
# censor contents of 'Authorization' part of header, to avoid leaking tokens or passwords in logs
168+
headers_censored = copy.deepcopy(headers)
169+
headers_censored['Authorization'] = '<actual authorization header censored>'
170+
171+
fancylogger.getLogger().debug('cli request: %s, %s, %s, %s', method, url, body, headers_censored)
172+
166173
# TODO: in recent python: Context manager
167174
conn = self.get_connection(method, url, body, headers)
168175
status = conn.code

0 commit comments

Comments
 (0)