Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
##
# Copyright 2009-2019 Ghent University
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# https://github.com/easybuilders/easybuild
#
# EasyBuild 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 v2.
#
# EasyBuild 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 EasyBuild. If not, see <http://www.gnu.org/licenses/>.
##
"""
EasyBuild support for building and installing DIRAC, implemented as an easyblock
"""
import os
import re
import shutil
import tempfile
import easybuild.tools.environment as env
import easybuild.tools.toolchain as toolchain
from easybuild.easyblocks.generic.cmakemake import CMakeMake
from easybuild.framework.easyconfig import CUSTOM, MANDATORY
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.config import build_option
from easybuild.tools.run import run_cmd
class EB_DIRAC(CMakeMake):
"""Support for building/installing DIRAC."""
def configure_step(self):
"""Custom configuration procedure for DIRAC."""
# make very sure the install directory isn't there yet, since it may cause problems if it used (forced rebuild)
if os.path.exists(self.installdir):
self.log.warning("Found existing install directory %s, removing it to avoid problems", self.installdir)
try:
shutil.rmtree(self.installdir)
except OSError as err:
raise EasyBuildError("Failed to remove existing install directory %s: %s", self.installdir, err)
self.cfg['separate_build_dir'] = True
#self.cfg.update('configopts', "-DENABLE_MPI=ON -DCMAKE_BUILD_TYPE=release")
self.cfg.update('configopts', "--fc=mpiifort --mpi --cc=mpiicc --cxx=mpicxx")
# complete configuration with configure_method of parent
super(EB_DIRAC, self).configure_step()
def test_step(self):
"""Custom built-in test procedure for DIRAC."""
if self.cfg['runtest']:
if not build_option('mpi_tests'):
self.log.info("Skipping testing of DIRAC since MPI testing is disabled")
return
# set up test environment
# see http://diracprogram.org/doc/release-14/installation/testing.html
env.setvar('DIRAC_TMPDIR', tempfile.mkdtemp(prefix='dirac-test-'))
env.setvar('DIRAC_MPI_COMMAND', self.toolchain.mpi_cmd_for('', self.cfg['parallel']))
# run tests (may take a while, especially if some tests take a while to time out)
self.log.info("Running tests may take a while, especially if some tests timeout (default timeout is 1500s)")
cmd = "make test"
out, ec = run_cmd(cmd, simple=False, log_all=False, log_ok=False)
# check that majority of tests pass
# some may fail due to timeout, but that's acceptable
# cfr. https://groups.google.com/forum/#!msg/dirac-users/zEd5-xflBnY/OQ1pSbuX810J
# over 90% of tests should pass
passed_regex = re.compile('^(9|10)[0-9.]+% tests passed', re.M)
if not passed_regex.search(out) and not self.dry_run:
raise EasyBuildError("Too many failed tests; '%s' not found in test output: %s",
passed_regex.pattern, out)
# extract test results
test_result_regex = re.compile(r'^\s*[0-9]+/[0-9]+ Test \s*#[0-9]+: .*', re.M)
test_results = test_result_regex.findall(out)
if test_results:
self.log.info("Found %d test results: %s", len(test_results), test_results)
elif self.dry_run:
# dummy test result
test_results = ["1/1 Test #1: dft_alda_xcfun ............................. Passed 72.29 sec"]
else:
raise EasyBuildError("Couldn't find *any* test results?")
test_count_regex = re.compile(r'^\s*[0-9]+/([0-9]+)')
res = test_count_regex.search(test_results[0])
if res:
test_count = int(res.group(1))
elif self.dry_run:
# a single dummy test result
test_count = 1
else:
raise EasyBuildError("Failed to determine total test count from %s using regex '%s'",
test_results[0], test_count_regex.pattern)
if len(test_results) != test_count:
raise EasyBuildError("Expected to find %s test results, but found %s", test_count, len(test_results))
# check test results, only 'Passed' or 'Timeout' are acceptable outcomes
faulty_tests = []
for test_result in test_results:
if ' Passed ' not in test_result:
self.log.warning("Found failed test: %s", test_result)
if '***Timeout' not in test_result:
faulty_tests.append(test_result)
if faulty_tests:
raise EasyBuildError("Found tests failing due to something else than timeout: %s", faulty_tests)
def sanity_check_step(self):
"""Custom sanity check for DIRAC."""
custom_paths = {
'files': ['bin/pam-dirac'],
'dirs': ['share/dirac'],
}
super(EB_DIRAC, self).sanity_check_step(custom_paths=custom_paths)