From 6f35d1adf4f76edde06bf98ede1c4dbba7b204b4 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Wed, 11 Jun 2025 18:33:32 +0200 Subject: [PATCH 1/4] remove scripts & co that have been relocated to `EESSI/software-layer-scripts` repository --- .github/workflows/modules/fake_module.lua | 3 - .../workflows/scripts/test_init_scripts.sh | 50 - .../workflows/test_eessi_container_script.yml | 141 -- .github/workflows/test_licenses.yml | 23 - .github/workflows/tests.yml | 34 - .github/workflows/tests_archdetect.yml | 80 - .../workflows/tests_archdetect_nvidia_gpu.yml | 124 -- .github/workflows/tests_eessi_module.yml | 207 --- .github/workflows/tests_init.yml | 45 - .github/workflows/tests_init_module.yml | 43 - .../tests_link_nvidia_host_libraries.yml | 199 --- .github/workflows/tests_scripts.yml | 121 -- EESSI-extend-easybuild.eb | 189 --- EESSI-install-software.sh | 443 ------ EESSI-remove-software.sh | 151 -- bot/build.sh | 344 ---- bot/check-build.sh | 579 ------- bot/check-result.sh | 1 - bot/check-test.sh | 238 --- bot/inspect.sh | 448 ------ bot/test.sh | 257 --- check_missing_installations.sh | 61 - configure_easybuild | 65 - create_directory_tarballs.sh | 49 - create_lmodrc.py | 54 - create_lmodsitepackage.py | 307 ---- create_tarball.sh | 115 -- eb_hooks.py | 1402 ----------------- eessi_container.sh | 917 ----------- eessi_software_subdir.py | 53 - init/Magic_Castle/bash | 39 - init/Magic_Castle/eessi_python3 | 21 - init/README.md | 29 - init/arch_specs/eessi_arch_arm.spec | 13 - init/arch_specs/eessi_arch_ppc.spec | 3 - init/arch_specs/eessi_arch_riscv.spec | 1 - init/arch_specs/eessi_arch_x86.spec | 11 - init/bash | 46 - init/eessi_archdetect.sh | 221 --- init/eessi_defaults | 27 - init/eessi_environment_variables | 166 -- init/eessi_software_subdir_for_host.py | 139 -- init/lmod/bash | 18 - init/lmod/csh | 18 - init/lmod/fish | 17 - init/lmod/ksh | 18 - init/lmod/zsh | 18 - init/lmod_eessi_archdetect_wrapper.sh | 2 - init/lmod_eessi_archdetect_wrapper_accel.sh | 2 - init/minimal_eessi_env | 28 - init/modules/EESSI/2023.06.lua | 155 -- init/modules/EESSI/20240402.lua | 1 - init/test.py | 82 - install_apptainer_ubuntu.sh | 14 - install_scripts.sh | 185 --- install_software_layer.sh | 4 - licenses/README.md | 3 - licenses/licenses.json | 10 - licenses/spdx.py | 100 -- load_easybuild_module.sh | 131 -- load_eessi_extend_module.sh | 123 -- run_in_compat_layer_env.sh | 61 - run_tests.sh | 30 - scripts/cfg_files.sh | 167 -- ...06-eb-4.9.4-2023a-CUDA-host-injections.yml | 9 - ...06-eb-4.9.4-2023b-CUDA-host-injections.yml | 4 - .../nvidia/install_cuda_and_libraries.sh | 265 ---- .../nvidia/install_cuda_host_injections.sh | 211 --- .../nvidia/link_nvidia_host_libraries.sh | 691 -------- scripts/utils.sh | 149 -- test_suite.sh | 241 --- .../OpenFOAM-8_motorBike_2M-cells_2cores.sh | 97 -- .../a64fx/Deucalion-Rocky85.all.output | 1 - .../aarch64/a64fx/Deucalion-Rocky85.cpuinfo | 8 - .../aarch64/a64fx/Deucalion-Rocky85.output | 1 - .../aarch64/google/axion/GCP-axion.all.output | 1 - .../aarch64/google/axion/GCP-axion.cpuinfo | 8 - .../aarch64/google/axion/GCP-axion.output | 1 - .../AWS-awslinux-graviton2.all.output | 1 - .../AWS-awslinux-graviton2.cpuinfo | 8 - .../neoverse_n1/AWS-awslinux-graviton2.output | 1 - .../Azure-Ubuntu20-Altra.all.output | 1 - .../neoverse_n1/Azure-Ubuntu20-Altra.cpuinfo | 30 - .../neoverse_n1/Azure-Ubuntu20-Altra.output | 1 - .../AWS-awslinux-graviton3.all.output | 1 - .../AWS-awslinux-graviton3.cpuinfo | 8 - .../neoverse_v1/AWS-awslinux-graviton3.output | 1 - .../nvidia/grace/Jureca-Rocky95.all.output | 1 - .../nvidia/grace/Jureca-Rocky95.cpuinfo | 8 - .../nvidia/grace/Jureca-Rocky95.output | 1 - tests/archdetect/nvidia-smi/1xa100.output | 1 - tests/archdetect/nvidia-smi/1xa100.sh | 5 - tests/archdetect/nvidia-smi/2xa100.output | 1 - tests/archdetect/nvidia-smi/2xa100.sh | 6 - tests/archdetect/nvidia-smi/4xa100.output | 1 - tests/archdetect/nvidia-smi/4xa100.sh | 8 - tests/archdetect/nvidia-smi/cc01.output | 1 - tests/archdetect/nvidia-smi/cc01.sh | 6 - tests/archdetect/nvidia-smi/no_devices.output | 1 - tests/archdetect/nvidia-smi/no_devices.sh | 3 - tests/archdetect/nvidia-smi/none.output | 1 - .../power9le/unknown-power9le.all.output | 1 - .../ppc64le/power9le/unknown-power9le.cpuinfo | 4 - .../ppc64le/power9le/unknown-power9le.output | 1 - .../amd/zen2/Azure-CentOS7-7V12.all.output | 1 - .../amd/zen2/Azure-CentOS7-7V12.cpuinfo | 27 - .../x86_64/amd/zen2/Azure-CentOS7-7V12.output | 1 - .../amd/zen3/Azure-CentOS7-7V73X.all.output | 1 - .../amd/zen3/Azure-CentOS7-7V73X.cpuinfo | 27 - .../amd/zen3/Azure-CentOS7-7V73X.output | 1 - .../amd/zen4/Azure-Alma8-9V33X.all.output | 1 - .../x86_64/amd/zen4/Azure-Alma8-9V33X.cpuinfo | 27 - .../x86_64/amd/zen4/Azure-Alma8-9V33X.output | 1 - .../amd/zen4/Shinx-RHEL8-9654.all.output | 1 - .../x86_64/amd/zen4/Shinx-RHEL8-9654.cpuinfo | 27 - .../x86_64/amd/zen4/Shinx-RHEL8-9654.output | 1 - .../cascadelake/AWS-Rocky8-8259CL.all.output | 1 - .../cascadelake/AWS-Rocky8-8259CL.cpuinfo | 24 - .../cascadelake/AWS-Rocky8-8259CL.output | 1 - .../archspec-linux-E5-2680-v3.all.output | 1 - .../haswell/archspec-linux-E5-2680-v3.cpuinfo | 25 - .../haswell/archspec-linux-E5-2680-v3.output | 1 - .../intel/icelake/AWS-Rocky8-8375C.all.output | 1 - .../intel/icelake/AWS-Rocky8-8375C.cpuinfo | 24 - .../intel/icelake/AWS-Rocky8-8375C.output | 1 - .../AWS-Rocky8-8488C.all.output | 1 - .../sapphirerapids/AWS-Rocky8-8488C.cpuinfo | 26 - .../sapphirerapids/AWS-Rocky8-8488C.output | 1 - .../archspec-linux-6132.all.output | 1 - .../archspec-linux-6132.cpuinfo | 25 - .../skylake_avx512/archspec-linux-6132.output | 1 - .../map_software_to_test.py | 95 -- .../eessi_test_mapping/software_to_tests.yml | 35 - tests/nvidia-libs/mock-nvidia-libs.sh | 87 - tests/nvidia-libs/mock-nvidia-smi.sh | 35 - update_lmod_cache.sh | 37 - versions/2021.06/init/Magic_Castle/bash | 3 - versions/2021.06/init/bash | 3 - .../2021.06/init/print_deprecation_warning.sh | 19 - 139 files changed, 10999 deletions(-) delete mode 100644 .github/workflows/modules/fake_module.lua delete mode 100755 .github/workflows/scripts/test_init_scripts.sh delete mode 100644 .github/workflows/test_eessi_container_script.yml delete mode 100644 .github/workflows/test_licenses.yml delete mode 100644 .github/workflows/tests.yml delete mode 100644 .github/workflows/tests_archdetect.yml delete mode 100644 .github/workflows/tests_archdetect_nvidia_gpu.yml delete mode 100644 .github/workflows/tests_eessi_module.yml delete mode 100644 .github/workflows/tests_init.yml delete mode 100644 .github/workflows/tests_init_module.yml delete mode 100644 .github/workflows/tests_link_nvidia_host_libraries.yml delete mode 100644 .github/workflows/tests_scripts.yml delete mode 100644 EESSI-extend-easybuild.eb delete mode 100755 EESSI-install-software.sh delete mode 100755 EESSI-remove-software.sh delete mode 100755 bot/build.sh delete mode 100755 bot/check-build.sh delete mode 120000 bot/check-result.sh delete mode 100755 bot/check-test.sh delete mode 100755 bot/inspect.sh delete mode 100755 bot/test.sh delete mode 100755 check_missing_installations.sh delete mode 100644 configure_easybuild delete mode 100755 create_directory_tarballs.sh delete mode 100755 create_lmodrc.py delete mode 100755 create_lmodsitepackage.py delete mode 100755 create_tarball.sh delete mode 100644 eb_hooks.py delete mode 100755 eessi_container.sh delete mode 100755 eessi_software_subdir.py delete mode 100644 init/Magic_Castle/bash delete mode 100755 init/Magic_Castle/eessi_python3 delete mode 100644 init/README.md delete mode 100755 init/arch_specs/eessi_arch_arm.spec delete mode 100755 init/arch_specs/eessi_arch_ppc.spec delete mode 100644 init/arch_specs/eessi_arch_riscv.spec delete mode 100755 init/arch_specs/eessi_arch_x86.spec delete mode 100644 init/bash delete mode 100755 init/eessi_archdetect.sh delete mode 100644 init/eessi_defaults delete mode 100644 init/eessi_environment_variables delete mode 100755 init/eessi_software_subdir_for_host.py delete mode 100644 init/lmod/bash delete mode 100644 init/lmod/csh delete mode 100644 init/lmod/fish delete mode 100644 init/lmod/ksh delete mode 100644 init/lmod/zsh delete mode 100644 init/lmod_eessi_archdetect_wrapper.sh delete mode 100644 init/lmod_eessi_archdetect_wrapper_accel.sh delete mode 100644 init/minimal_eessi_env delete mode 100644 init/modules/EESSI/2023.06.lua delete mode 120000 init/modules/EESSI/20240402.lua delete mode 100644 init/test.py delete mode 100755 install_apptainer_ubuntu.sh delete mode 100755 install_scripts.sh delete mode 100755 install_software_layer.sh delete mode 100644 licenses/README.md delete mode 100644 licenses/licenses.json delete mode 100644 licenses/spdx.py delete mode 100755 load_easybuild_module.sh delete mode 100755 load_eessi_extend_module.sh delete mode 100755 run_in_compat_layer_env.sh delete mode 100755 run_tests.sh delete mode 100644 scripts/cfg_files.sh delete mode 100644 scripts/gpu_support/nvidia/easystacks/eessi-2023.06-eb-4.9.4-2023a-CUDA-host-injections.yml delete mode 100644 scripts/gpu_support/nvidia/easystacks/eessi-2023.06-eb-4.9.4-2023b-CUDA-host-injections.yml delete mode 100755 scripts/gpu_support/nvidia/install_cuda_and_libraries.sh delete mode 100755 scripts/gpu_support/nvidia/install_cuda_host_injections.sh delete mode 100755 scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh delete mode 100644 scripts/utils.sh delete mode 100755 test_suite.sh delete mode 100755 tests/OpenFOAM/OpenFOAM-8_motorBike_2M-cells_2cores.sh delete mode 100644 tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.all.output delete mode 100644 tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.cpuinfo delete mode 100644 tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.output delete mode 100644 tests/archdetect/aarch64/google/axion/GCP-axion.all.output delete mode 100644 tests/archdetect/aarch64/google/axion/GCP-axion.cpuinfo delete mode 100644 tests/archdetect/aarch64/google/axion/GCP-axion.output delete mode 100644 tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.all.output delete mode 100644 tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.cpuinfo delete mode 100644 tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.output delete mode 100644 tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.all.output delete mode 100644 tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.cpuinfo delete mode 100644 tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.output delete mode 100644 tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.all.output delete mode 100644 tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.cpuinfo delete mode 100644 tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.output delete mode 100644 tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.all.output delete mode 100644 tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.cpuinfo delete mode 100644 tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.output delete mode 100644 tests/archdetect/nvidia-smi/1xa100.output delete mode 100755 tests/archdetect/nvidia-smi/1xa100.sh delete mode 100644 tests/archdetect/nvidia-smi/2xa100.output delete mode 100755 tests/archdetect/nvidia-smi/2xa100.sh delete mode 100644 tests/archdetect/nvidia-smi/4xa100.output delete mode 100755 tests/archdetect/nvidia-smi/4xa100.sh delete mode 100644 tests/archdetect/nvidia-smi/cc01.output delete mode 100755 tests/archdetect/nvidia-smi/cc01.sh delete mode 100644 tests/archdetect/nvidia-smi/no_devices.output delete mode 100755 tests/archdetect/nvidia-smi/no_devices.sh delete mode 100644 tests/archdetect/nvidia-smi/none.output delete mode 100644 tests/archdetect/ppc64le/power9le/unknown-power9le.all.output delete mode 100644 tests/archdetect/ppc64le/power9le/unknown-power9le.cpuinfo delete mode 100644 tests/archdetect/ppc64le/power9le/unknown-power9le.output delete mode 100644 tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.all.output delete mode 100644 tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.cpuinfo delete mode 100644 tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.output delete mode 100644 tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.all.output delete mode 100644 tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.cpuinfo delete mode 100644 tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.output delete mode 100644 tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.all.output delete mode 100644 tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.cpuinfo delete mode 100644 tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.output delete mode 100644 tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.all.output delete mode 100644 tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.cpuinfo delete mode 100644 tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.output delete mode 100644 tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.all.output delete mode 100644 tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.cpuinfo delete mode 100644 tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.output delete mode 100644 tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.all.output delete mode 100644 tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.cpuinfo delete mode 100644 tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.output delete mode 100644 tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.all.output delete mode 100644 tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.cpuinfo delete mode 100644 tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.output delete mode 100644 tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.all.output delete mode 100644 tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.cpuinfo delete mode 100644 tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.output delete mode 100644 tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.all.output delete mode 100644 tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.cpuinfo delete mode 100644 tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.output delete mode 100644 tests/eessi_test_mapping/map_software_to_test.py delete mode 100644 tests/eessi_test_mapping/software_to_tests.yml delete mode 100644 tests/nvidia-libs/mock-nvidia-libs.sh delete mode 100644 tests/nvidia-libs/mock-nvidia-smi.sh delete mode 100755 update_lmod_cache.sh delete mode 100644 versions/2021.06/init/Magic_Castle/bash delete mode 100644 versions/2021.06/init/bash delete mode 100755 versions/2021.06/init/print_deprecation_warning.sh diff --git a/.github/workflows/modules/fake_module.lua b/.github/workflows/modules/fake_module.lua deleted file mode 100644 index e45cb640d6..0000000000 --- a/.github/workflows/modules/fake_module.lua +++ /dev/null @@ -1,3 +0,0 @@ -setenv("INSIDE_GITHUB_ACTIONS", "true") --- Interfere with PATH so Lmod keeps a record -prepend_path("PATH", "/snap/bin") diff --git a/.github/workflows/scripts/test_init_scripts.sh b/.github/workflows/scripts/test_init_scripts.sh deleted file mode 100755 index 048fba81f5..0000000000 --- a/.github/workflows/scripts/test_init_scripts.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -EESSI_VERSION="2023.06" -export LMOD_PAGER=cat - -# initialize assert framework -if [ ! -d assert.sh ]; then - echo "assert.sh not cloned." - echo "" - echo "run \`git clone https://github.com/lehmannro/assert.sh.git\`" - exit 1 -fi -. assert.sh/assert.sh - -TEST_SHELLS=("bash" "zsh" "fish" "ksh") -SHELLS=$@ - -for shell in ${SHELLS[@]}; do - echo = | awk 'NF += (OFS = $_) + 100' - echo RUNNING TESTS FOR SHELL: $shell - echo = | awk 'NF += (OFS = $_) + 100' - if [[ ! " ${TEST_SHELLS[*]} " =~ [[:space:]]${shell}[[:space:]] ]]; then - ### EXCEPTION FOR CSH ### - echo -e "\033[33mWe don't now how to test the shell '$shell', PRs are Welcome.\033[0m" - else - # TEST 1: Source Script and check Module Output - assert "$shell -c 'source init/lmod/$shell' 2>&1 " "EESSI/$EESSI_VERSION loaded successfully" - # TEST 2: Check if module overviews first section is the loaded EESSI module - MODULE_SECTIONS=($($shell -c "source init/lmod/$shell 2>/dev/null; module ov 2>&1 | grep -e '---'")) - PATTERN="/cvmfs/software\.eessi\.io/versions/$EESSI_VERSION/software/linux/x86_64/(intel/haswell|amd/zen3)/modules/all" - assert_raises 'echo "${MODULE_SECTIONS[1]}" | grep -E "$PATTERN"' - # TEST 3: Check if module overviews second section is the EESSI init module - assert "echo ${MODULE_SECTIONS[4]}" "/cvmfs/software.eessi.io/versions/$EESSI_VERSION/init/modules" - # Test 4: Load Python module and check version - command="$shell -c 'source init/lmod/$shell 2>/dev/null; module load Python/3.10.8-GCCcore-12.2.0; python --version'" - expected="Python 3.10.8" - assert "$command" "$expected" - # Test 5: Load Python module and check path - PYTHON_PATH=$($shell -c "source init/lmod/$shell 2>/dev/null; module load Python/3.10.8-GCCcore-12.2.0; which python") - PATTERN="/cvmfs/software\.eessi\.io/versions/$EESSI_VERSION/software/linux/x86_64/(intel/haswell|amd/zen3)/software/Python/3\.10\.8-GCCcore-12\.2\.0/bin/python" - echo "$PYTHON_PATH" | grep -E "$PATTERN" - assert_raises 'echo "$PYTHON_PATH" | grep -E "$PATTERN"' - - #End Test Suite - assert_end "source_eessi_$shell" - fi -done - - -# RESET PAGER -export LMOD_PAGER= diff --git a/.github/workflows/test_eessi_container_script.yml b/.github/workflows/test_eessi_container_script.yml deleted file mode 100644 index 6f7055a546..0000000000 --- a/.github/workflows/test_eessi_container_script.yml +++ /dev/null @@ -1,141 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Tests for eessi_container.sh script -on: - push: - branches: [ "*-software.eessi.io" ] - pull_request: - workflow_dispatch: -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - eessi_container_script: - runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - SCRIPT_TEST: - - help - - listrepos_default - - listrepos_custom - - run - - shell - - container - - resume - # FIXME disabled because '--access rw' is not working in CI environment - #- readwrite - #- save - steps: - - name: Check out software-layer repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: install Apptainer - run: | - ./install_apptainer_ubuntu.sh - - - name: Collect info on test environment - run: | - mount - df -h - - - name: Test eessi_container.sh script - run: | - test_cmd="cat /etc/os-release" - out_pattern="Debian GNU/Linux 11" - - if [[ ${{matrix.SCRIPT_TEST}} == 'help' ]]; then - ./eessi_container.sh --help - - # test use of --list-repos without custom repos.cfg - elif [[ ${{matrix.SCRIPT_TEST}} == 'listrepos_default' ]]; then - outfile=out_listrepos.txt - ./eessi_container.sh --verbose --list-repos | tee ${outfile} - # make sure that the default EESSI software repository is available - grep "software.eessi.io" ${outfile} - - # test use of --list-repos with custom repos.cfg - elif [[ ${{matrix.SCRIPT_TEST}} == 'listrepos_custom' ]]; then - outfile=out_listrepos.txt - outfile2=out_listrepos_2.txt - mkdir -p ${PWD}/cfg - echo "[EESSI/20AB.CD]" > cfg/repos.cfg - echo "repo_version = 20AB.CD" >> cfg/repos.cfg - echo "[EESSI/20HT.TP]" >> cfg/repos.cfg - echo "repo_version = 20HT.TP" >> cfg/repos.cfg - ./eessi_container.sh --verbose --list-repos | tee ${outfile} - # make sure that the default EESSI software repository is available - grep "software.eessi.io" ${outfile} - - export EESSI_REPOS_CFG_DIR_OVERRIDE=${PWD}/cfg - ./eessi_container.sh --verbose --list-repos | tee ${outfile2} - grep "EESSI/20AB.CD" ${outfile2} - - # test use of --mode run - elif [[ ${{matrix.SCRIPT_TEST}} == 'run' ]]; then - outfile=out_run.txt - echo "${test_cmd}" > test_script.sh - chmod u+x test_script.sh - export SINGULARITY_BIND="$PWD:/test" - ./eessi_container.sh --verbose --mode run /test/test_script.sh | tee ${outfile} - grep "${out_pattern}" ${outfile} - - # test use of --mode shell - elif [[ ${{matrix.SCRIPT_TEST}} == 'shell' ]]; then - outfile=out_shell.txt - ./eessi_container.sh --verbose --mode shell <<< "${test_cmd}" 2>&1 | tee ${outfile} - grep "${out_pattern}" ${outfile} - - # test use of --container option, using a totally different container; - # cfr. https://github.com/easybuilders/easybuild-containers - elif [[ ${{matrix.SCRIPT_TEST}} == 'container' ]]; then - outfile=out_container.txt - container="docker://ghcr.io/eessi/build-node:debian10" - ./eessi_container.sh --verbose --container ${container} --mode shell <<< "${test_cmd}" 2>&1 | tee ${outfile} - grep "Debian GNU/Linux 10" ${outfile} - - # test use of '--access rw' to get write access in container - elif [[ ${{matrix.SCRIPT_TEST}} == 'readwrite' ]]; then - outfile=out_readwrite.txt - fn="test_${RANDOM}.txt" - echo "touch /cvmfs/software.eessi.io/${fn}" > test_script.sh - chmod u+x test_script.sh - export SINGULARITY_BIND="$PWD:/test" - ./eessi_container.sh --verbose --access rw --mode run /test/test_script.sh > ${outfile} - - tmpdir=$(grep "\-\-resume" ${outfile} | sed "s/.*--resume \([^']*\).*/\1/g") - # note: must use '--access rw' again here, since touched file is in overlay upper dir - ./eessi_container.sh --verbose --resume ${tmpdir} --access rw --mode shell <<< "ls -l /cvmfs/software.eessi.io/${fn}" > ${outfile} - grep "/cvmfs/software.eessi.io/${fn}$" $outfile - - # test use of --resume - elif [[ ${{matrix.SCRIPT_TEST}} == 'resume' ]]; then - outfile=out_resume.txt - ./eessi_container.sh --verbose --mode shell <<< "${test_cmd}" > ${outfile} - - tmpdir=$(grep "\-\-resume" ${outfile} | sed "s/.*--resume \([^']*\).*/\1/g") - rm -f ${outfile} - - # make sure that container image exists - test -f ${tmpdir}/ghcr.io_eessi_build_node_debian11.sif || (echo "Container image not found in ${tmpdir}" >&2 && ls ${tmpdir} && exit 1) - - ./eessi_container.sh --verbose --resume ${tmpdir} --mode shell <<< "${test_cmd}" > ${outfile} - cat ${outfile} - grep "Resuming from previous run using temporary storage at ${tmpdir}" ${outfile} - grep "${out_pattern}" ${outfile} - - # test use of --save (+ --resume) - elif [[ ${{matrix.SCRIPT_TEST}} == 'save' ]]; then - outfile=out_save.txt - fn="test_${RANDOM}.txt" - test_cmd="touch /cvmfs/software.eessi.io/${fn}" - ./eessi_container.sh --verbose --mode shell --access rw --save test-save.tar <<< "${test_cmd}" 2>&1 | tee ${outfile} - rm -f ${outfile} - - ./eessi_container.sh --verbose --mode shell --access rw --resume test-save.tar <<< "ls -l /cvmfs/software.eessi.io/${fn}" > ${outfile} - grep "/cvmfs/software.eessi.io/${fn}$" $outfile - - tar tfv test-save.tar | grep "overlay-upper/${fn}" - - else - echo "Unknown test case: ${{matrix.SCRIPT_TEST}}" >&2 - exit 1 - fi diff --git a/.github/workflows/test_licenses.yml b/.github/workflows/test_licenses.yml deleted file mode 100644 index 1770d8719a..0000000000 --- a/.github/workflows/test_licenses.yml +++ /dev/null @@ -1,23 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Test software licenses -on: - push: - branches: [ "*-software.eessi.io" ] - pull_request: -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - build: - runs-on: ubuntu-24.04 - steps: - - name: Check out software-layer repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: set up Python - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 - with: - python-version: '3.9' - - - name: Check software licenses - run: | - python licenses/spdx.py licenses/licenses.json diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index ecfa9a7ba5..0000000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,34 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Tests -on: - push: - branches: [ "*-software.eessi.io" ] - pull_request: -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - build: - runs-on: ubuntu-24.04 - strategy: - matrix: - python: [3.8, 3.9, '3.10'] - fail-fast: false - steps: - - name: checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: set up Python - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 - with: - python-version: ${{matrix.python}} - architecture: x64 - - - name: install Python packages - run: | - pip install archspec==0.2.2 - - - name: test eessi_software_subdir.py script - run: | - ./eessi_software_subdir.py | tee out - grep '^x86_64/' out - egrep '/intel/|/amd/' out diff --git a/.github/workflows/tests_archdetect.yml b/.github/workflows/tests_archdetect.yml deleted file mode 100644 index 18d08a9023..0000000000 --- a/.github/workflows/tests_archdetect.yml +++ /dev/null @@ -1,80 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Tests for eessi_archdetect.sh -on: - push: - branches: [ "*-software.eessi.io" ] - pull_request: -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - build: - runs-on: ubuntu-24.04 - strategy: - matrix: - proc_cpuinfo: - - x86_64/intel/haswell/archspec-linux-E5-2680-v3 - - x86_64/intel/sapphirerapids/AWS-Rocky8-8488C - - x86_64/intel/skylake_avx512/archspec-linux-6132 - - x86_64/amd/zen2/Azure-CentOS7-7V12 - - x86_64/amd/zen3/Azure-CentOS7-7V73X - - x86_64/amd/zen4/Azure-Alma8-9V33X - - x86_64/amd/zen4/Shinx-RHEL8-9654 - - aarch64/a64fx/Deucalion-Rocky85 - - aarch64/neoverse_n1/Azure-Ubuntu20-Altra - - aarch64/neoverse_n1/AWS-awslinux-graviton2 - - aarch64/neoverse_v1/AWS-awslinux-graviton3 - - aarch64/nvidia/grace/Jureca-Rocky95 - - aarch64/google/axion/GCP-axion - # commented out since these targets are currently not supported in software.eessi.io repo - # (and some tests assume that the corresponding subdirectory in software layer is there) - # - ppc64le/power9le/unknown-power9le - fail-fast: false - steps: - - name: checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Mount EESSI CernVM-FS pilot repository - uses: cvmfs-contrib/github-action-cvmfs@55899ca74cf78ab874bdf47f5a804e47c198743c # v4.0 - with: - cvmfs_config_package: https://github.com/EESSI/filesystem-layer/releases/download/latest/cvmfs-config-eessi_latest_all.deb - cvmfs_http_proxy: DIRECT - cvmfs_repositories: software.eessi.io - - - name: test eessi_archdetect.sh - run: | - export EESSI_MACHINE_TYPE=${{matrix.proc_cpuinfo}} - export EESSI_MACHINE_TYPE=${EESSI_MACHINE_TYPE%%/*} - export EESSI_PROC_CPUINFO=./tests/archdetect/${{matrix.proc_cpuinfo}}.cpuinfo - # check that printing of best match works correctly - CPU_ARCH=$(./init/eessi_archdetect.sh cpupath) - if [[ $CPU_ARCH == "$( cat ./tests/archdetect/${{matrix.proc_cpuinfo}}.output )" ]]; then - echo "Test for ${{matrix.proc_cpuinfo}} PASSED: $CPU_ARCH" - else - echo "Test for ${{matrix.proc_cpuinfo}} FAILED: $CPU_ARCH" >&2 - exit 1 - fi - # check that $EESSI_SOFTWARE_SUBDIR_OVERRIDE is honored - export EESSI_SOFTWARE_SUBDIR_OVERRIDE='dummy/cpu' - CPU_ARCH=$(./init/eessi_archdetect.sh cpupath) - if [[ $CPU_ARCH == "${EESSI_SOFTWARE_SUBDIR_OVERRIDE}" ]]; then - echo "Test for picking up on \$EESSI_SOFTWARE_SUBDIR_OVERRIDE PASSED" - else - echo "Test for picking up on \$EESSI_SOFTWARE_SUBDIR_OVERRIDE FAILED" >&2 - exit 1 - fi - unset EESSI_SOFTWARE_SUBDIR_OVERRIDE - # check that printing of all matches works correctly (-a option for cpupath action) - CPU_ARCHES=$(./init/eessi_archdetect.sh -a cpupath) - if [[ $CPU_ARCHES == "$( cat ./tests/archdetect/${{matrix.proc_cpuinfo}}.all.output )" ]]; then - echo "Test for ${{matrix.proc_cpuinfo}} PASSED: $CPU_ARCHES" - else - echo "Test for ${{matrix.proc_cpuinfo}} FAILED: $CPU_ARCHES" >&2 - exit 1 - fi - # Check all those architectures actually exist (if this EESSI version has been populated already) - if [ -d ${EESSI_PREFIX}/software/linux ]; then - for dir in $(echo "$CPU_ARCHES" | tr ':' '\n'); do - # Search all EESSI versions as we may drop support at some point - ls -d ${EESSI_PREFIX}/software/linux/${dir} - done - fi diff --git a/.github/workflows/tests_archdetect_nvidia_gpu.yml b/.github/workflows/tests_archdetect_nvidia_gpu.yml deleted file mode 100644 index 54827eccad..0000000000 --- a/.github/workflows/tests_archdetect_nvidia_gpu.yml +++ /dev/null @@ -1,124 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Tests for accelerator detection (NVIDIA GPU) -on: - push: - pull_request: -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - build: - runs-on: ubuntu-24.04 - strategy: - matrix: - fake_nvidia_smi_script: - - none # no nvidia-smi command - - no_devices # nvidia-smi command works, but no GPUs available - - 1xa100 # cc80, supported with (atleast) zen2 CPU - - 2xa100 # cc80, supported with (atleast) zen2 CPU - - 4xa100 # cc80, supported with (atleast) zen2 CPU - - cc01 # non-existing GPU - fail-fast: false - steps: - - name: checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - - # we deliberately do not use the eessi/github-action-eessi action, - # because we want to control when the EESSI environment is initialized - - name: Mount EESSI CernVM-FS repository - uses: cvmfs-contrib/github-action-cvmfs@55899ca74cf78ab874bdf47f5a804e47c198743c # v4.0 - with: - cvmfs_config_package: https://github.com/EESSI/filesystem-layer/releases/download/latest/cvmfs-config-eessi_latest_all.deb - cvmfs_http_proxy: DIRECT - cvmfs_repositories: software.eessi.io - - - name: test accelerator detection - run: | - export EESSI_SOFTWARE_SUBDIR_OVERRIDE='x86_64/amd/zen2' - - # put fake nvidia-smi command in place (unless we don't want to) - if [[ "${{matrix.fake_nvidia_smi_script}}" != "none" ]]; then - tmpdir=$(mktemp -d) - ln -s $PWD/tests/archdetect/nvidia-smi/${{matrix.fake_nvidia_smi_script}}.sh $tmpdir/nvidia-smi - export PATH=$tmpdir:$PATH - fi - - # first run with debugging enabled, just to show the output - ./init/eessi_archdetect.sh -d accelpath || echo "non-zero exit code: $?" - - # verify output (or exit code if non-zero) - out=$(./init/eessi_archdetect.sh accelpath || echo "non-zero exit code: $?") - - if [[ $out == "$( cat ./tests/archdetect/nvidia-smi/${{matrix.fake_nvidia_smi_script}}.output )" ]]; then - - echo "Test for '${{matrix.fake_nvidia_smi_script}}' PASSED: '$out'" - - # run full EESSI init script, which pick up on the accelerator (if available) - echo - . init/bash 2>&1 | tee init.out - echo "-----------------------------------------------------------------------------" - - if [[ "${{matrix.fake_nvidia_smi_script}}" == "none" ]] || [[ "${{matrix.fake_nvidia_smi_script}}" == "no_devices" ]]; then - - pattern="archdetect could not detect any accelerators" - echo ">>> checking for pattern '${pattern}' in init output..." - grep "${pattern}" init.out || (echo "FAILED 1" || exit 1) - - pattern="archdetect found supported accelerator" - echo ">>> checking for lack of pattern '${pattern}' in init output..." - match=$(grep "${pattern}" init.out || true) - test "x${match}" = "x" || (echo "unexpected match found for '${pattern}' in init output" && exit 1) - - pattern="Prepending /cvmfs/software.eessi.io/versions/2023.06/software/linux/.*/accel/.*/modules/all to \$MODULEPATH" - echo ">>> checking for lack of pattern '${pattern}' in init output..." - match=$(grep "${pattern}" init.out || true) - test "x${match}" = "x" || (echo "unexpected match found for '${pattern}' in init output" && exit 1) - - elif [[ "${{matrix.fake_nvidia_smi_script}}" == "cc01" ]]; then - - pattern="No matching path found in x86_64/amd/zen2 for accelerator detected by archdetect (accel/nvidia/cc01)" - echo ">>> checking for pattern '${pattern}' in init output..." - grep "${pattern}" init.out || (echo "FAILED 1" || exit 1) - - pattern="Prepending /cvmfs/software.eessi.io/versions/2023.06/software/linux/.*/accel/.*/modules/all to \$MODULEPATH" - echo ">>> checking for lack of pattern '${pattern}' in init output..." - match=$(grep "${pattern}" init.out || true) - test "x${match}" = "x" || (echo "unexpected match found for '${pattern}' in init output" && exit 1) - - else - echo ">>> checking for 'accel/nvidia/cc80' in init output..." - grep "archdetect found supported accelerator for CPU target x86_64/amd/zen2: accel/nvidia/cc80" init.out || (echo "FAILED 2" && exit 1) - grep "Prepending /cvmfs/software.eessi.io/versions/2023.06/software/linux/x86_64/amd/zen2/accel/nvidia/cc80/modules/all to \$MODULEPATH" init.out || (echo "FAILED 3" && exit 1) - fi - - echo ">>> checking last line of init output..." - tail -1 init.out | grep "Environment set up to use EESSI (2023.06), have fun!" || (echo "FAILED, full init utput:" && cat init.out && exit 1) - - echo "All checks on init output PASSED" - else - echo "Test for '${{matrix.fake_nvidia_smi_script}}' FAILED: '$out'" >&2 - exit 1 - fi - - - name: test accelerator detection under $EESSI_ACCEL_SOFTWARE_SUBDIR_OVERRIDE + $EESSI_ACCELERATOR_TARGET_OVERRIDE - run: | - export EESSI_SOFTWARE_SUBDIR_OVERRIDE='x86_64/amd/zen2' - export EESSI_ACCEL_SOFTWARE_SUBDIR_OVERRIDE='x86_64/amd/zen3' - export EESSI_ACCELERATOR_TARGET_OVERRIDE='accel/nvidia/cc80' - - # first run with debugging enabled, just to show the output - ./init/eessi_archdetect.sh -d accelpath || echo "non-zero exit code: $?" - - # verify output (or exit code if non-zero) - out=$(./init/eessi_archdetect.sh accelpath || echo "non-zero exit code: $?") - - echo - . init/bash 2>&1 | tee init.out - echo "-----------------------------------------------------------------------------" - - echo ">>> checking for 'accel/nvidia/cc80' in init output..." - grep "archdetect found supported accelerator for CPU target x86_64/amd/zen3: accel/nvidia/cc80" init.out || (echo "FAILED 1" && exit 1) - grep "Using x86_64/amd/zen2 as software subdirectory" init.out || (echo "FAILED 2" && exit 1) - grep "Prepending /cvmfs/software.eessi.io/versions/2023.06/software/linux/x86_64/amd/zen2/modules/all to \$MODULEPATH" init.out || (echo "FAILED 3" && exit 1) - grep "Prepending /cvmfs/software.eessi.io/versions/2023.06/software/linux/x86_64/amd/zen3/accel/nvidia/cc80/modules/all to \$MODULEPATH" init.out || (echo "FAILED 4" && exit 1) - - echo "All checks on init output PASSED" diff --git a/.github/workflows/tests_eessi_module.yml b/.github/workflows/tests_eessi_module.yml deleted file mode 100644 index a7b38e2205..0000000000 --- a/.github/workflows/tests_eessi_module.yml +++ /dev/null @@ -1,207 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Tests for eessi_module_functionality in software.eessi.io -on: - push: - branches: [ "*-software.eessi.io" ] - pull_request: -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - basic_checks: - runs-on: ubuntu-22.04 - strategy: - fail-fast: false - matrix: - EESSI_VERSION: - - 2023.06 - steps: - - name: Check out software-layer repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Mount EESSI CernVM-FS pilot repository - uses: cvmfs-contrib/github-action-cvmfs@55899ca74cf78ab874bdf47f5a804e47c198743c # v4.0 - with: - cvmfs_config_package: https://github.com/EESSI/filesystem-layer/releases/download/latest/cvmfs-config-eessi_latest_all.deb - cvmfs_http_proxy: DIRECT - cvmfs_repositories: software.eessi.io - - - name: Test for making sure spider cache is being used and not being rebuilt - run: | - . /cvmfs/software.eessi.io/versions/${{matrix.EESSI_VERSION}}/compat/linux/$(uname -m)/usr/share/Lmod/init/bash # Initialise Lmod - export MODULEPATH=init/modules - configfile="configfile.txt" - module -T load EESSI/${{matrix.EESSI_VERSION}} - module --config > "${configfile}" 2>&1 - grep cache "${configfile}" | grep software | grep -v compat - if timeout 10s bash -c "LMOD_PAGER=none module --terse avail" && grep cache "${configfile}" | grep software | grep -v compat; then - echo "EESSI spider cache is being used" - else - echo "EESSI spider cache is being rebuilt" >&2 - exit 1 - fi - env | grep LMOD - module purge - unset MODULEPATH - - - name: Test for archdetect_cpu functionality with invalid path - run: | - # Initialise Lmod - . /cvmfs/software.eessi.io/versions/${{matrix.EESSI_VERSION}}/compat/linux/$(uname -m)/usr/share/Lmod/init/bash - export MODULEPATH=init/modules - set +e # Do not exit immediately if a command exits with a non-zero status - export EESSI_ARCHDETECT_OPTIONS_OVERRIDE="dummy/cpu" - outfile="outfile.txt" - module load EESSI/${{matrix.EESSI_VERSION}} > "${outfile}" 2>&1 - cat "${outfile}" - if grep -q "Software directory check" "${outfile}"; then - echo "Test for picking up invalid path on \${archdetect_cpu} PASSED" - else - echo "Test for picking up invalid path on \${archdetect_cpu} FAILED" >&2 - exit 1 - fi - unset EESSI_ARCHDETECT_OPTIONS_OVERRIDE - set -e # Re-enable exit on non-zero status - - lmod_and_init_script_comparison: - runs-on: ubuntu-22.04 - strategy: - fail-fast: false - matrix: - EESSI_VERSION: - - 2023.06 - EESSI_SOFTWARE_SUBDIR_OVERRIDE: - - x86_64/amd/zen3 - - x86_64/amd/zen4 - EESSI_ACCELERATOR_TARGET_OVERRIDE: - - accel/nvidia/cc80 - steps: - - name: Check out software-layer repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Mount EESSI CernVM-FS pilot repository - uses: cvmfs-contrib/github-action-cvmfs@55899ca74cf78ab874bdf47f5a804e47c198743c # v4.0 - with: - cvmfs_config_package: https://github.com/EESSI/filesystem-layer/releases/download/latest/cvmfs-config-eessi_latest_all.deb - cvmfs_http_proxy: DIRECT - cvmfs_repositories: software.eessi.io - - - name: Test for expected variables match between Lmod init script and original bash script - run: | - # Initialise Lmod - . /cvmfs/software.eessi.io/versions/${{matrix.EESSI_VERSION}}/compat/linux/$(uname -m)/usr/share/Lmod/init/bash - - # Set our path overrides according to our matrix - export EESSI_SOFTWARE_SUBDIR_OVERRIDE=${{matrix.EESSI_SOFTWARE_SUBDIR_OVERRIDE}} - export EESSI_ACCELERATOR_TARGET_OVERRIDE=${{matrix.EESSI_ACCELERATOR_TARGET_OVERRIDE}} - - moduleoutfile="moduleout.txt" - sourceoutfile="sourceout.txt" - - # First do (and undo) the Lmod initialisation - export MODULEPATH=init/modules - # Turn on debug output in case we want to take a look - export EESSI_DEBUG_INIT=true - CPU_ARCH=$(./init/eessi_archdetect.sh -a cpupath) - export EESSI_ARCHDETECT_OPTIONS_OVERRIDE="dummy/cpu:${CPU_ARCH}:dummy1/cpu1" - module load EESSI/${{matrix.EESSI_VERSION}} - # EESSI_ARCHDETECT_OPTIONS_OVERRIDE/EESSI_DEBUG_INIT only relevant for Lmod init - unset EESSI_ARCHDETECT_OPTIONS_OVERRIDE - unset EESSI_DEBUG_INIT - # Store all relevant environment variables - env | grep -E '(^EESSI_|^LMOD_RC|^LMOD_PACKAGE_PATH)' | sort > "${moduleoutfile}" - module unload EESSI/${{matrix.EESSI_VERSION}} - - # Now do the init script initialisation - source ./init/bash - # source script version sets environment variables to force archdetect, ignore these - unset EESSI_USE_ARCHSPEC - unset EESSI_USE_ARCHDETECT - env | grep -E '(^EESSI_|^LMOD_RC|^LMOD_PACKAGE_PATH)' | sort > "${sourceoutfile}" - - # Now compare the two results - echo "" - echo "Lmod initialisation:" - cat "${moduleoutfile}" - echo "" - echo "Source script initialisation:" - cat "${sourceoutfile}" - echo "" - echo "" - if (diff "${moduleoutfile}" "${sourceoutfile}" > /dev/null); then - echo "Test for checking env variables PASSED" - else - echo "Test for checking env variables FAILED" >&2 - diff --unified=0 "${moduleoutfile}" "${sourceoutfile}" - exit 1 - fi - - make_sure_load_and_unload_work: - runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - EESSI_VERSION: - - 2023.06 - EESSI_SOFTWARE_SUBDIR_OVERRIDE: - - none - - x86_64/amd/zen2 - - x86_64/amd/zen4 - EESSI_ACCELERATOR_TARGET_OVERRIDE: - - none - - accel/nvidia/cc80 - steps: - - name: Check out software-layer repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Mount EESSI CernVM-FS pilot repository - uses: cvmfs-contrib/github-action-cvmfs@55899ca74cf78ab874bdf47f5a804e47c198743c # v4.0 - with: - cvmfs_config_package: https://github.com/EESSI/filesystem-layer/releases/download/latest/cvmfs-config-eessi_latest_all.deb - cvmfs_http_proxy: DIRECT - cvmfs_repositories: software.eessi.io - - - name: Test for identical environment after loading and unloading the EESSI module - run: | - # Initialise Lmod - . /cvmfs/software.eessi.io/versions/${{matrix.EESSI_VERSION}}/compat/linux/$(uname -m)/usr/share/Lmod/init/bash - - # Set our cpu path overrides according to our matrix - if [[ "${{matrix.EESSI_SOFTWARE_SUBDIR_OVERRIDE}}" != "none" ]]; then - export EESSI_SOFTWARE_SUBDIR_OVERRIDE=${{matrix.EESSI_SOFTWARE_SUBDIR_OVERRIDE}} - fi - - # Set our accelerator path overrides according to our matrix - if [[ "${{matrix.EESSI_ACCELERATOR_TARGET_OVERRIDE}}" != "none" ]]; then - export EESSI_ACCELERATOR_TARGET_OVERRIDE=${{matrix.EESSI_ACCELERATOR_TARGET_OVERRIDE}} - fi - - # Turn on debug output in case we want to take a look - export EESSI_DEBUG_INIT=true - - initial_env_file="initial_env.txt" - module_cycled_file="load_unload_cycle.txt" - - # prepare Lmod, resetting it in a roundabout given we don't want defaults set - export MODULEPATH=init/modules:.github/workflows/modules - module load fake_module - module purge - module unuse .github/workflows/modules - module avail - - # Store the initial environment (ignoring Lmod tables) - env | grep -v _ModuleTable | sort > "${initial_env_file}" - - # Do (and undo) loading the EESSI module - CPU_ARCH=$(./init/eessi_archdetect.sh -a cpupath) - module load EESSI/${{matrix.EESSI_VERSION}} - module unload EESSI/${{matrix.EESSI_VERSION}} - env | grep -v _ModuleTable | sort > "${module_cycled_file}" - - # Now compare the two results (do not expose the files, as they contain the full environment!) - if (diff "${initial_env_file}" "${module_cycled_file}" > /dev/null); then - echo "Test for checking env variables PASSED" - else - echo "Test for checking env variables FAILED" >&2 - diff --unified=0 "${initial_env_file}" "${module_cycled_file}" - exit 1 - fi diff --git a/.github/workflows/tests_init.yml b/.github/workflows/tests_init.yml deleted file mode 100644 index 9ab373eec0..0000000000 --- a/.github/workflows/tests_init.yml +++ /dev/null @@ -1,45 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Tests for init scripts -on: - push: - branches: [ "*-software.eessi.io" ] - pull_request: -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - build: - runs-on: ubuntu-24.04 - strategy: - matrix: - python: [3.8, 3.9, '3.10'] - fail-fast: false - steps: - - name: checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: set up Python - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 - with: - python-version: ${{matrix.python}} - architecture: x64 - - - name: install Python packages - run: | - pip install archspec==0.2.2 pytest - - - name: unit tests for eessi_software_subdir_for_host.py script - run: - pytest -v init/test.py - - - name: test eessi_software_subdir_for_host.py script - env: - EESSI_X86_64: /tmp/EESSI/software/linux/x86_64 - run: | - mkdir -p ${EESSI_X86_64}/intel/{pentium4,sandybridge,haswell,skylake_avx512} ${EESSI_X86_64}/generic - python3 ./init/eessi_software_subdir_for_host.py /tmp/EESSI > out.txt - grep '^x86_64/' out.txt - - # check override via $EESSI_SOFTWARE_SUBDIR_OVERRIDE - export EESSI_SOFTWARE_SUBDIR_OVERRIDE=x86_64/intel/pentium4 - python3 ./init/eessi_software_subdir_for_host.py /tmp/EESSI > out.txt - grep '^x86_64/intel/pentium4$' out.txt diff --git a/.github/workflows/tests_init_module.yml b/.github/workflows/tests_init_module.yml deleted file mode 100644 index d30da61c84..0000000000 --- a/.github/workflows/tests_init_module.yml +++ /dev/null @@ -1,43 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Check for EESSI init shell scripts to load eessi software module in software.eessi.io -on: - push: - branches: [ "*-software.eessi.io" ] - pull_request: - workflow_dispatch: -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - build: - runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - EESSI_VERSION: - - 2023.06 - EESSI_SOFTWARE_SUBDIR_OVERRIDE: - - x86_64/intel/haswell - steps: - - name: Check out software-layer repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Mount EESSI CernVM-FS pilot repository - uses: cvmfs-contrib/github-action-cvmfs@55899ca74cf78ab874bdf47f5a804e47c198743c # v4.0 - with: - cvmfs_config_package: https://github.com/EESSI/filesystem-layer/releases/download/latest/cvmfs-config-eessi_latest_all.deb - cvmfs_http_proxy: DIRECT - cvmfs_repositories: software.eessi.io - - - name: Clone assert.sh script - run: git clone https://github.com/lehmannro/assert.sh.git - - - name: Install missing shells - run: | - sudo apt update - sudo apt install zsh ksh fish - echo "# INIT ZSH" > ~/.zshrc - - - name: Run tests for available shells - run: | - .github/workflows/scripts/test_init_scripts.sh "bash" "zsh" "ksh" "fish" "csh" - diff --git a/.github/workflows/tests_link_nvidia_host_libraries.yml b/.github/workflows/tests_link_nvidia_host_libraries.yml deleted file mode 100644 index 22ebc21084..0000000000 --- a/.github/workflows/tests_link_nvidia_host_libraries.yml +++ /dev/null @@ -1,199 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Test NVIDIA Host Libraries Linking -on: - push: - branches: - - '*-software.eessi.io' # Matches any branch ending with '-software.eessi.io' - pull_request: - paths: - - 'scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh' # PR changes only relevant for this specific file - - '.github/workflows/tests_link_nvidia_host_libraries.yml' # Also test when changing the tests themselves -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - build: - runs-on: ubuntu-24.04 - steps: - - name: checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - - - name: Initialize EESSI - uses: eessi/github-action-eessi@v3 - - - name: Setup mock NVIDIA libraries - run: | - # Run the script to create mock libraries - chmod +x ./tests/nvidia-libs/mock-nvidia-libs.sh - echo ">>> Running ./tests/nvidia-libs/mock-nvidia-libs.sh" - ./tests/nvidia-libs/mock-nvidia-libs.sh - - # Create symlink to override host's ldconfig, since the script tries to use /sbin/ldconfig first. - echo "Symlinking ldconfig to /sbin/ldconfig" - sudo ln -sf /tmp/ldconfig/ldconfig /sbin/ldconfig - - # Verify the symlink was created correctly - ls -la /sbin/ldconfig - - - name: Setup mock nvidia-smi - run: | - # Create directory for mock nvidia-smi - mkdir -p /tmp/nvidia-bin - - # Copy the mock script - chmod +x ./tests/nvidia-libs/mock-nvidia-smi.sh - echo ">>> Copying ./tests/nvidia-libs/mock-nvidia-smi.sh" - cp ./tests/nvidia-libs/mock-nvidia-smi.sh /tmp/nvidia-bin/nvidia-smi - - # Add to PATH - echo "Updating PATH" - echo "PATH=/tmp/nvidia-bin:$PATH" >> $GITHUB_ENV - - - name: Test LD_PRELOAD mode - run: | - echo ">>> Testing LD_PRELOAD mode" - - # Run the script with LD_PRELOAD option (shouldn't create symlinks) - output=$(./scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh --show-ld-preload || { echo "Script returned non-zero: $?"; echo $output; exit 1; }) - - echo "$output" - - echo ">>> Running checks" - - # Check for expected outputs - echo "$output" | grep "export EESSI_GPU_COMPAT_LD_PRELOAD=" || { echo "EESSI_GPU_COMPAT_LD_PRELOAD not found in output"; exit 1; } - echo "$output" | grep "export EESSI_GPU_LD_PRELOAD=" || { echo "EESSI_GPU_LD_PRELOAD not found in output"; exit 1; } - echo "$output" | grep "export EESSI_OVERRIDE_GPU_CHECK=" || { echo "EESSI_OVERRIDE_GPU_CHECK not found in output"; exit 1; } - - # Verify that no symlinks were created - if [ -e "/opt/eessi/nvidia/x86_64/host/driver_version.txt" ]; then - echo "Error: symlinks were created in LD_PRELOAD mode" - exit 1 - fi - - echo "LD_PRELOAD mode test passed." - - - name: Test normal run (first time) - run: | - echo ">>> Testing normal run - first time" - - # Run with verbose mode - output=$(./scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh --verbose || { echo "Script returned non-zero: $?"; echo $output; exit 1; }) - - echo "$output" - - echo ">>> Running checks" - - # Check if NVIDIA GPU was detected - Driver version and CUDA version are hardcoded in `tests/nvidia-libs/mock-nvidia-smi.sh` - echo "$output" | grep "Found NVIDIA GPU driver version 535.129.03" || { echo "Failed to detect NVIDIA driver version"; exit 1; } - echo "$output" | grep "Found host CUDA version 8.0" || { echo "Failed to detect CUDA version"; exit 1; } - - # Check if libraries were found - echo "$output" | grep "Matched.*CUDA Libraries" || { echo "Failed to match CUDA libraries"; exit 1; } - - # Verify symlinks were created - if [ ! -d "/opt/eessi/nvidia/x86_64/host" ]; then - echo "Error: host directory wasn't created" - exit 1 - fi - - # Check if version files were created - if [ ! -f "/opt/eessi/nvidia/x86_64/host/driver_version.txt" ]; then - echo "Error: driver_version.txt wasn't created" - exit 1 - fi - - # Check driver version content - grep "535.129.03" "/opt/eessi/nvidia/x86_64/host/driver_version.txt" || { echo "Incorrect driver version"; exit 1; } - - # Check if latest symlink was created - if [ ! -L "/opt/eessi/nvidia/x86_64/latest" ]; then - echo "Error: 'latest' symlink wasn't created" - exit 1 - fi - - # Check if latest points to host - readlink "/opt/eessi/nvidia/x86_64/latest" | grep "host" || { echo "latest doesn't point to host"; exit 1; } - - # Check if symlinks to libraries were created and point to correct files - echo ">>> Checking library symlinks" - - # List dir with libraries - echo "Showing content of /tmp/nvidia_libs" - echo "$(ls -l /tmp/nvidia_libs)" - echo "Showing content of /tmp/nvidia_libs_duplicate" - echo "$(ls -l /tmp/nvidia_libs_duplicate)" - echo "Showing content of /opt/eessi/nvidia/x86_64/host" - echo "$(ls -l /opt/eessi/nvidia/x86_64/host)" - - # List expected library names - list of libraries is hardcoded in `tests/nvidia-libs/mock-nvidia-libs.sh` - libraries=( - "libcuda.so" - "libcuda.so.1" - "libnvidia-ml.so" - "libnvidia-ml.so.1" - "libnvidia-ptxjitcompiler.so" - "libnvidia-ptxjitcompiler.so.1" - "libcudadebugger.so" - "libcudadebugger.so.1" - ) - - # Check each expected library symlink - for lib in "${libraries[@]}"; do - lib_path="/opt/eessi/nvidia/x86_64/host/$lib" - - # Check if the symlink exists - if [ ! -L "$lib_path" ]; then - echo "Error: Symlink for $lib was not created" - exit 1 - fi - - # Check if symlink target exists - target=$(readlink "$lib_path") - if [ ! -e "$target" ]; then - echo "Error: Symlink $lib_path points to non-existent file: $target" - exit 1 - fi - - # Verify it points to our mock library in /tmp/nvidia_libs or /tmp/nvidia_libs_duplicate - if [[ "$target" != "/tmp/nvidia_libs/$lib"* && "$target" != "/tmp/nvidia_libs_duplicate/$lib"* ]]; then - echo "Error: Symlink $lib_path points to $target, which is not in our mock directories" - exit 1 - fi - - echo ">>> Verified symlink: $lib -> $target" - done - - echo "First normal run test passed" - - - name: Test normal run (second time) - run: | - echo ">>> Testing normal run - second time - should be idempotent" - # Remove all write permissions on /opt/eessi so any attempts to write files fail - chmod -R a-w /opt/eessi - - # Store file timestamps before second run (ignoring access time) - stat_before=$(stat --format="%n %s %y %U %G %m %i" "/opt/eessi/nvidia/x86_64/host/driver_version.txt") - - # Run script again - output=$(./scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh || { echo "Script returned non-zero: $?"; echo $output; exit 1; }) - - echo "$output" - - echo ">>> Running checks" - - # Store file timestamps after second run (ignoring access time) - stat_after=$(stat --format="%n %s %y %U %G %m %i" "/opt/eessi/nvidia/x86_64/host/driver_version.txt") - - # Compare timestamps - should be the same (files shouldn't be modified) - if [[ "$stat_before" != "$stat_after" ]]; then - echo "Error: files were modified on second run when they shouldn't have been" - echo "Before: $stat_before" - echo "After: $stat_after" - exit 1 - fi - - # Check for message indicating that libraries are already linked - echo "$output" | grep "have already been linked" || { echo "Missing 'already linked' message"; exit 1; } - - echo "Second normal run test passed" - \ No newline at end of file diff --git a/.github/workflows/tests_scripts.yml b/.github/workflows/tests_scripts.yml deleted file mode 100644 index de227dfc25..0000000000 --- a/.github/workflows/tests_scripts.yml +++ /dev/null @@ -1,121 +0,0 @@ -# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Tests for scripts -on: - push: - paths: - - create_directory_tarballs.sh - - create_lmodsitepackage.py - - eessi_container.sh - - EESSI-install-software.sh - - install_software_layer.sh - - load_easybuild_module.sh - - run_in_compat_layer_env.sh - - scripts/utils.sh - - update_lmod_cache.sh - - pull_request: - paths: - - create_directory_tarballs.sh - - create_lmodsitepackage.py - - eessi_container.sh - - EESSI-install-software.sh - - install_software_layer.sh - - load_easybuild_module.sh - - run_in_compat_layer_env.sh - - scripts/utils.sh - - update_lmod_cache.sh -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - build: - runs-on: ubuntu-24.04 - steps: - - name: checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: install Apptainer - run: | - ./install_apptainer_ubuntu.sh - - - name: test load_easybuild_module.sh script - run: | - # bind current directory into container as /software-layer - export SINGULARITY_BIND="${PWD}:/software-layer" - - # can't test with EasyBuild versions older than v4.5.2 when using EESSI 2023.06, - # since Python in compat layer is Python 3.11.x; - # testing with a single EasyBuild version takes a while in GitHub Actions, so stick to a single sensible version - for EB_VERSION in '4.6.0'; do - # Create script that uses load_easybuild_module.sh which we can run in compat layer environment - # note: Be careful with single vs double quotes below! - # ${EB_VERSION} should be expanded, so use double quotes; - # For statements using variables that are only defined in the script, like ${EASYBUILD_INSTALLPATH}, - # use single quotes to avoid expansion while creating the script. - test_script="${PWD}/eb-${EB_VERSION}.sh" - echo '#!/bin/bash' > ${test_script} - # both $EB and $TMPDIR environment must be set, required by load_easybuild_module.sh script - echo 'export EB="eb"' >> ${test_script} - echo 'export TMPDIR=$(mktemp -d)' >> ${test_script} - # set up environment to have utility functions in place that load_easybuild_module.sh script relies on, - # along with $EESSI_* environment variables, and Lmod - echo 'ls -l /software-layer/' >> ${test_script} - echo 'source /software-layer/scripts/utils.sh' >> ${test_script} - echo 'source /software-layer/init/eessi_environment_variables' >> ${test_script} - echo 'source ${EPREFIX}/usr/share/Lmod/init/bash' >> ${test_script} - # minimal configuration for EasyBuild so we can test installation aspect of load_easybuild_module.sh script - echo "export EASYBUILD_INSTALLPATH=/tmp/eb-${EB_VERSION}" >> ${test_script} - echo 'module use ${EASYBUILD_INSTALLPATH}/modules/all' >> ${test_script} - echo '' >> ${test_script} - echo "source /software-layer/load_easybuild_module.sh ${EB_VERSION}" >> ${test_script} - echo 'module list' >> ${test_script} - echo 'eb --version' >> ${test_script} - - chmod u+x ${test_script} - - # run wrapper script + capture & check output - out="${PWD}/eb-${EB_VERSION}.out" - ./eessi_container.sh --access rw --mode run --verbose /software-layer/run_in_compat_layer_env.sh /software-layer/eb-${EB_VERSION}.sh 2>&1 | tee ${out} - pattern="^This is EasyBuild ${EB_VERSION} " - grep "${pattern}" ${out} || (echo "Pattern '${pattern}' not found in output!" && exit 1) - done - - - name: test install_software_layer.sh script - run: | - # bind current directory into container as /software-layer - export SINGULARITY_BIND="${PWD}:/software-layer" - # force using x86_64/generic, to avoid triggering an installation from scratch - sed -i "s@./EESSI-install-software.sh@\"export EESSI_SOFTWARE_SUBDIR_OVERRIDE='x86_64/generic'; ./EESSI-install-software.sh\"@g" install_software_layer.sh - # skip installation of CUDA SDKs, since this is too heavy for CI - sed -i "s@./EESSI-install-software.sh@./EESSI-install-software.sh --skip-cuda-install@g" install_software_layer.sh - ./eessi_container.sh --mode run --verbose /software-layer/install_software_layer.sh - - - name: test create_directory_tarballs.sh script - run: | - # bind current directory into container as /software-layer - export SINGULARITY_BIND="${PWD}:/software-layer" - # scripts need to be copied to /tmp, - # since create_directory_tarballs.sh must be accessible from within build container - ./eessi_container.sh --mode run --verbose /software-layer/create_directory_tarballs.sh 2023.06 - # check if tarballs have been produced - ls -l *.tar.gz - - - name: test create_lmodsitepackage.py script - run: | - # bind current directory into container as /software-layer - export SINGULARITY_BIND="${PWD}:/software-layer" - - # Creates .lmod/SitePackage.lua in current dir, which then gets bind-mounted into /software-layer - python3 create_lmodsitepackage.py . - # run some commands to make sure that generated Lmod SitePackage file works - test_script="${PWD}/test_lmod_sitepackage.sh" - echo '#!/bin/bash' > ${test_script} - echo 'export LMOD_PACKAGE_PATH="/software-layer/.lmod"' > ${test_script} - echo 'ml --config' >> ${test_script} - - chmod u+x ${test_script} - - out="${PWD}/test_create_lmodsitepackage.out" - ./eessi_container.sh --mode run --verbose /software-layer/run_in_compat_layer_env.sh /software-layer/test_lmod_sitepackage.sh 2>&1 | tee ${out} - for pattern in "^Site Pkg location.*/software-layer/.lmod/SitePackage.lua" "LMOD_SITEPACKAGE_LOCATION.*/software-layer/.lmod/SitePackage.lua"; do - grep "${pattern}" ${out} || (echo "Pattern '${pattern}' not found in output!" && exit 1) - done diff --git a/EESSI-extend-easybuild.eb b/EESSI-extend-easybuild.eb deleted file mode 100644 index f74f36aca7..0000000000 --- a/EESSI-extend-easybuild.eb +++ /dev/null @@ -1,189 +0,0 @@ -easyblock = 'Bundle' - -name = 'EESSI-extend' -import os -version = os.getenv('EESSI_VERSION', '2023.06') -# May have different ways to extend EESSI in future (manually, other tools,...) -versionsuffix = '-easybuild' - -homepage = 'https://eessi.io/docs/' - -description = """ - The goal of the European Environment for Scientific Software Installations - (EESSI, pronounced as "easy") is to build a common stack of scientific - software installations for HPC systems and beyond, including laptops, - personal workstations and cloud infrastructure. - - This module allows you to extend EESSI using the same configuration for - EasyBuild as EESSI itself uses. A number of environment variables control the - behaviour of the module: - - EESSI_USER_INSTALL can be set to a location to install modules for use by - the user only. The location must already exist on the filesystem. - - EESSI_PROJECT_INSTALL can be set to a location to install modules for use by - a project. The location must already exist on the filesystem and you should - ensure that the location has the correct Linux group and the SGID permission - is set on that directory (`chmod g+s $EESSI_PROJECT_INSTALL`) so that all - members of the group have permission to read and write installations. - - EESSI_SITE_INSTALL is either defined or not and cannot be used with another - environment variable. A site installation is done in a defined location and - any installations there are (by default) world readable. - - EESSI_CVMFS_INSTALL is either defined or not and cannot be used with another - environment variable. A CVMFS installation targets a defined location which - will be ingested into CVMFS and is only useful for CVMFS administrators. - - If none of the environment variables above are defined, an EESSI_USER_INSTALL - is assumed with a value of $HOME/EESSI - If both EESSI_USER_INSTALL and EESSI_PROJECT_INSTALL are defined, both sets of - installations are exposed, but new installations are created as user - installations. -""" - -toolchain = SYSTEM - -# All the dependencies we filter in EESSI -local_deps_to_filter = "Autoconf,Automake,Autotools,binutils,bzip2,DBus,flex,gettext,gperf,help2man,intltool,libreadline,libtool,M4,makeinfo,ncurses,util-linux,XZ,zlib" -local_arch_specific_deps_to_filter = {'aarch64': ',Yasm', 'riscv64': ',Yasm', 'x86_64': ''} -local_deps_to_filter += local_arch_specific_deps_to_filter[ARCH] - -# Set the universal EasyBuild variables -modextravars = { - 'EASYBUILD_FILTER_DEPS': local_deps_to_filter, - 'EASYBUILD_IGNORE_OSDEPS': '1', - 'EASYBUILD_DEBUG': '1', - 'EASYBUILD_TRACE': '1', - 'EASYBUILD_ZIP_LOGS': 'bzip2', - 'EASYBUILD_RPATH': '1', - 'EASYBUILD_FILTER_ENV_VARS': 'LD_LIBRARY_PATH', - 'EASYBUILD_READ_ONLY_INSTALLDIR': '1', - 'EASYBUILD_MODULE_EXTENSIONS': '1', - 'EASYBUILD_EXPERIMENTAL': '1', -} - -# Need a few other variables, but they are more dynamic -# EASYBUILD_SYSROOT=${EPREFIX} -# EASYBUILD_PREFIX=${WORKDIR}/easybuild -# EASYBUILD_HOOKS=${EESSI_PREFIX}/init/easybuild/eb_hooks.py -# EASYBUILD_INSTALLPATH=${EESSI_PREFIX}/software/${EESSI_OS_TYPE}/${EESSI_SOFTWARE_SUBDIR} -# EASYBUILD_SOURCEPATH=${WORKDIR}/easybuild/sources:${EESSI_SOURCEPATH} -# -# And also some optional ones based on the kind of installation -# EASYBUILD_SET_GID_BIT -# EASYBUILD_GROUP_WRITABLE_INSTALLDIR -# EASYBUILD_UMASK -# EASYBUILD_STICKY_BIT -modluafooter = """ -if (mode() == "load") then - -- Use a working directory for temporary build files - if (os.getenv("WORKING_DIR") == nil) then - LmodMessage("-- Using /tmp/$USER as a temporary working directory for installations, you can override this by setting the environment variable WORKING_DIR and reloading the module (e.g., /dev/shm is a common option)") - end -end -working_dir = os.getenv("WORKING_DIR") or pathJoin("/tmp", os.getenv("USER")) --- Gather the EPREFIX to use as a sysroot -sysroot = os.getenv("EESSI_EPREFIX") --- Use an installation prefix that we _should_ have write access to -if (os.getenv("EESSI_CVMFS_INSTALL") ~= nil) then - -- Make sure no other EESSI install environment variables are set - if ((os.getenv("EESSI_SITE_INSTALL") ~= nil) or (os.getenv("EESSI_PROJECT_INSTALL") ~= nil) or (os.getenv("EESSI_USER_INSTALL") ~= nil)) then - LmodError("You cannot use EESSI_CVMFS_INSTALL in combination with any other EESSI_*_INSTALL environment variables") - end - eessi_cvmfs_install = true - easybuild_installpath = os.getenv("EESSI_SOFTWARE_PATH") - eessi_accelerator_target = os.getenv("EESSI_ACCELERATOR_TARGET") - if (eessi_accelerator_target ~= nil) then - cuda_compute_capability = string.match(eessi_accelerator_target, "^nvidia/cc([0-9][0-9])$") - if (cuda_compute_capability ~= nil) then - easybuild_installpath = pathJoin(easybuild_installpath, 'accel', eessi_accelerator_target) - easybuild_cuda_compute_capabilities = cuda_compute_capability:sub(1, 1) .. "." .. cuda_compute_capability:sub(2, 2) - else - LmodError("Incorrect value for $EESSI_ACCELERATOR_TARGET: " .. eessi_accelerator_target) - end - end -elseif (os.getenv("EESSI_SITE_INSTALL") ~= nil) then - -- Make sure no other EESSI install environment variables are set - if ((os.getenv("EESSI_PROJECT_INSTALL") ~= nil) or (os.getenv("EESSI_USER_INSTALL") ~= nil)) then - LmodError("You cannot use EESSI_SITE_INSTALL in combination with any other EESSI_*_INSTALL environment variables") - end - easybuild_installpath = os.getenv("EESSI_SITE_SOFTWARE_PATH") -else - -- Deal with user and project installs - project_install = os.getenv("EESSI_PROJECT_INSTALL") - project_modulepath = nil - if (project_install ~= nil) then - -- Check the folder exists - if not isDir(project_install) then - LmodError("The location of EESSI_PROJECT_INSTALL (" .. project_install .. ") does not exist or is not a folder") - end - if (mode() == "load") then - LmodMessage("Configuring for use of EESSI_PROJECT_INSTALL under " .. project_install) - end - easybuild_installpath = string.gsub(os.getenv("EESSI_SOFTWARE_PATH"), os.getenv("EESSI_CVMFS_REPO"), project_install) - project_modulepath = pathJoin(easybuild_installpath, 'modules', 'all') - end - user_install = os.getenv("EESSI_USER_INSTALL") - user_modulepath = nil - if (user_install ~= nil) then - -- Check the folder exists - if not isDir(user_install) then - LmodError("The location of EESSI_USER_INSTALL (" .. user_install .. ") does not exist or is not a folder") - end - elseif (user_install == nil) and (project_install == nil) then - -- No need to check for existence when we use a HOME subdir - user_install = pathJoin(os.getenv("HOME"), "eessi") - end - if (user_install ~= nil) then - if (mode() == "load") then - LmodMessage("Configuring for use of EESSI_USER_INSTALL under " .. user_install) - end - easybuild_installpath = string.gsub(os.getenv("EESSI_SOFTWARE_PATH"), os.getenv("EESSI_CVMFS_REPO"), user_install) - user_modulepath = pathJoin(easybuild_installpath, 'modules', 'all') - end -end -if (mode() == "load") then - LmodMessage("-- To create installations for EESSI, you _must_ have write permissions to " .. easybuild_installpath) - -- Advise them to reuse sources - if (os.getenv("EASYBUILD_SOURCEPATH") == nil) then - LmodMessage("-- You may wish to configure a sources directory for EasyBuild (for example, via setting the environment variable EASYBUILD_SOURCEPATH) to allow you to reuse existing sources for packages.") - end -end --- Set the relevant universal environment variables for EasyBuild -setenv ("EASYBUILD_SYSROOT", sysroot) -setenv ("EASYBUILD_PREFIX", pathJoin(working_dir, "easybuild")) -setenv ("EASYBUILD_INSTALLPATH", easybuild_installpath) -setenv ("EASYBUILD_HOOKS", pathJoin(os.getenv("EESSI_PREFIX"), "init", "easybuild", "eb_hooks.py")) - --- Make sure to use the general umask that allows a global read -setenv ("EASYBUILD_UMASK", "022") - --- Allow this module to be loaded when running EasyBuild -setenv ("EASYBUILD_ALLOW_LOADED_MODULES", "EasyBuild,EESSI-extend") - --- Set environment variables if building for CUDA compute capabilities -if (easybuild_cuda_compute_capabilities ~= nil) then - setenv ("EASYBUILD_CUDA_COMPUTE_CAPABILITIES", easybuild_cuda_compute_capabilities) -end - --- Set all related environment variables if we have project or user installations (including extending MODULEPATH) -if (user_modulepath ~= nil) then - -- Use a more restrictive umask for this case - setenv ("EASYBUILD_UMASK", "077") - setenv ("EASYBUILD_STICKY_BIT", "1") - -- configure MODULEPATH - if (project_modulepath ~= nil) then - prepend_path("MODULEPATH", project_modulepath) - end - prepend_path("MODULEPATH", user_modulepath) -elseif (project_modulepath ~= nil) then - setenv ("EASYBUILD_SET_GID_BIT", "1") - setenv ("EASYBUILD_GROUP_WRITABLE_INSTALLDIR", "1") - setenv ("EASYBUILD_STICKY_BIT", "0") - setenv ("EASYBUILD_UMASK", "002") - -- configure MODULEPATH - prepend_path("MODULEPATH", project_modulepath) -end --- Make sure EasyBuild itself is loaded -if not ( isloaded("EasyBuild") ) then - load(latest("EasyBuild")) -end -""" - -moduleclass = 'devel' diff --git a/EESSI-install-software.sh b/EESSI-install-software.sh deleted file mode 100755 index 60613fed6f..0000000000 --- a/EESSI-install-software.sh +++ /dev/null @@ -1,443 +0,0 @@ -#!/bin/bash -# -# Script to install EESSI software stack (version set through init/eessi_defaults) - -# see example parsing of command line arguments at -# https://wiki.bash-hackers.org/scripting/posparams#using_a_while_loop -# https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash - -display_help() { - echo "usage: $0 [OPTIONS]" - echo " --build-logs-dir - location to copy EasyBuild logs to for failed builds" - echo " -g | --generic - instructs script to build for generic architecture target" - echo " -h | --help - display this usage information" - echo " -x | --http-proxy URL - provides URL for the environment variable http_proxy" - echo " -y | --https-proxy URL - provides URL for the environment variable https_proxy" - echo " --shared-fs-path - path to directory on shared filesystem that can be used" - echo " --skip-cuda-install - disable installing a full CUDA SDK in the host_injections prefix (e.g. in CI)" -} - -# Function to check if a command exists -function command_exists() { - command -v "$1" >/dev/null 2>&1 -} - -function copy_build_log() { - # copy specified build log to specified directory, with some context added - build_log=${1} - build_logs_dir=${2} - - # also copy to build logs directory, if specified - if [ ! -z "${build_logs_dir}" ]; then - log_filename="$(basename ${build_log})" - if [ ! -z "${SLURM_JOB_ID}" ]; then - # use subdirectory for build log in context of a Slurm job - build_log_path="${build_logs_dir}/jobs/${SLURM_JOB_ID}/${log_filename}" - else - build_log_path="${build_logs_dir}/non-jobs/${log_filename}" - fi - mkdir -p $(dirname ${build_log_path}) - cp -a ${build_log} ${build_log_path} - chmod 0644 ${build_log_path} - - # add context to end of copied log file - echo >> ${build_log_path} - echo "Context from which build log was copied:" >> ${build_log_path} - echo "- original path of build log: ${build_log}" >> ${build_log_path} - echo "- working directory: ${PWD}" >> ${build_log_path} - echo "- Slurm job ID: ${SLURM_OUT}" >> ${build_log_path} - echo "- EasyBuild version: ${eb_version}" >> ${build_log_path} - echo "- easystack file: ${easystack_file}" >> ${build_log_path} - - echo "EasyBuild log file ${build_log} copied to ${build_log_path} (with context appended)" - fi -} - -function safe_module_use { - # add a given non-empty directory to $MODULEPATH if and only if it is not yet in - directory=${1} - - if [[ -z ${directory+x} ]]; then - echo "safe_module_use: given directory unset or empty; not adding it to \$MODULEPATH (${MODULEPATH})" - return - fi - if [[ ":${MODULEPATH}:" == *":${directory}:"* ]]; then - echo "safe_module_use: directory '${directory}' is already in \$MODULEPATH (${MODULEPATH}); not adding it again" - return - else - echo "safe_module_use: directory '${directory}' is not yet in \$MODULEPATH (${MODULEPATH}); adding it" - module use ${directory} - fi -} - -POSITIONAL_ARGS=() - -while [[ $# -gt 0 ]]; do - case $1 in - -g|--generic) - EASYBUILD_OPTARCH="GENERIC" - shift - ;; - -h|--help) - display_help # Call your function - # no shifting needed here, we're done. - exit 0 - ;; - -x|--http-proxy) - export http_proxy="$2" - shift 2 - ;; - -y|--https-proxy) - export https_proxy="$2" - shift 2 - ;; - --build-logs-dir) - export build_logs_dir="${2}" - shift 2 - ;; - --shared-fs-path) - export shared_fs_path="${2}" - shift 2 - ;; - --skip-cuda-install) - export skip_cuda_install=True - shift 1 - ;; - -*|--*) - echo "Error: Unknown option: $1" >&2 - exit 1 - ;; - *) # No more options - POSITIONAL_ARGS+=("$1") # save positional arg - shift - ;; - esac -done - -set -- "${POSITIONAL_ARGS[@]}" - -TOPDIR=$(dirname $(realpath $0)) - -source $TOPDIR/scripts/utils.sh - -# honor $TMPDIR if it is already defined, use /tmp otherwise -if [ -z $TMPDIR ]; then - export WORKDIR=/tmp/$USER -else - export WORKDIR=$TMPDIR/$USER -fi - -TMPDIR=$(mktemp -d) - - -# Get override subdir -DETECTION_PARAMETERS='' -GENERIC=0 -EB='eb' -if [[ "$EASYBUILD_OPTARCH" == "GENERIC" ]]; then - echo_yellow ">> GENERIC build requested, taking appropriate measures!" - DETECTION_PARAMETERS="$DETECTION_PARAMETERS --generic" - GENERIC=1 - EB='eb --optarch=GENERIC' -fi - -echo ">> Determining software subdirectory to use for current build host..." -if [ -z $EESSI_SOFTWARE_SUBDIR_OVERRIDE ]; then - export EESSI_SOFTWARE_SUBDIR_OVERRIDE=$(python3 $TOPDIR/eessi_software_subdir.py $DETECTION_PARAMETERS) - echo ">> Determined \$EESSI_SOFTWARE_SUBDIR_OVERRIDE via 'eessi_software_subdir.py $DETECTION_PARAMETERS' script" -else - echo ">> Picking up pre-defined \$EESSI_SOFTWARE_SUBDIR_OVERRIDE: ${EESSI_SOFTWARE_SUBDIR_OVERRIDE}" - # Run in a subshell, so that minimal_eessi_env doesn't change the shell environment for the rest of this script - ( - # Make sure EESSI_PREFIX and EESSI_OS_TYPE are set - source $TOPDIR/init/minimal_eessi_env - - # make sure the the software and modules directory exist - # (since it's expected by init/eessi_environment_variables when using archdetect and by the EESSI module) - mkdir -p ${EESSI_PREFIX}/software/${EESSI_OS_TYPE}/${EESSI_SOFTWARE_SUBDIR_OVERRIDE}/{modules,software} - ) -fi - -echo ">> Setting up environment..." - -# If EESSI_VERSION is not set, source the defaults script to set it -if [ -z ${EESSI_VERSION} ]; then - source $TOPDIR/init/eessi_defaults -fi - -# If module command does not exist, use the one from the compat layer -command -v module -module_cmd_exists=$? -if [[ "$module_cmd_exists" -ne 0 ]]; then - echo_green "No module command found, initializing lmod from the compatibility layer" - # Minimal initalization of the lmod from the compat layer - source $TOPDIR/init/lmod/bash -else - echo_green "Module command found" -fi -ml_version_out=$TMPDIR/ml.out -ml --version &> $ml_version_out -if [[ $? -eq 0 ]]; then - echo_green ">> Found Lmod ${LMOD_VERSION}" -else - fatal_error "Failed to initialize Lmod?! (see output in ${ml_version_out}" -fi - -# Make sure we start with no modules and clean $MODULEPATH -echo ">> Setting up \$MODULEPATH..." -module --force purge -module unuse $MODULEPATH - -# Initialize the EESSI environment -module use $TOPDIR/init/modules -module load EESSI/$EESSI_VERSION - -# make sure we're in Prefix environment by checking $SHELL -# We can only do this after loading the EESSI module, as we need ${EPREFIX} -if [[ ${SHELL} = ${EPREFIX}/bin/bash ]]; then - echo_green ">> It looks like we're in a Gentoo Prefix environment, good!" -else - fatal_error "Not running in Gentoo Prefix environment, run '${EPREFIX}/startprefix' first!" -fi - -if [ -d $EESSI_CVMFS_REPO ]; then - echo_green "$EESSI_CVMFS_REPO available, OK!" -else - fatal_error "$EESSI_CVMFS_REPO is not available!" -fi - -# Check that EESSI_SOFTWARE_SUBDIR now matches EESSI_SOFTWARE_SUBDIR_OVERRIDE -if [[ -z ${EESSI_SOFTWARE_SUBDIR} ]]; then - fatal_error "Failed to determine software subdirectory?!" -elif [[ "${EESSI_SOFTWARE_SUBDIR}" != "${EESSI_SOFTWARE_SUBDIR_OVERRIDE}" ]]; then - fatal_error "Values for EESSI_SOFTWARE_SUBDIR_OVERRIDE (${EESSI_SOFTWARE_SUBDIR_OVERRIDE}) and EESSI_SOFTWARE_SUBDIR (${EESSI_SOFTWARE_SUBDIR}) differ!" -else - echo_green ">> Using ${EESSI_SOFTWARE_SUBDIR} as software subdirectory!" -fi - -# avoid that pyc files for EasyBuild are stored in EasyBuild installation directory -export PYTHONPYCACHEPREFIX=$TMPDIR/pycache - -# if we run the script for the first time, e.g., to start building for a new -# stack, we need to ensure certain files are present in -# ${EESSI_PREFIX}/software/${EESSI_OS_TYPE}/${EESSI_SOFTWARE_SUBDIR_OVERRIDE} -# - .lmod/lmodrc.lua -# - .lmod/SitePackage.lua -_eessi_software_path=${EESSI_PREFIX}/software/${EESSI_OS_TYPE}/${EESSI_SOFTWARE_SUBDIR_OVERRIDE} -_lmod_cfg_dir=${_eessi_software_path}/.lmod -_lmod_rc_file=${_lmod_cfg_dir}/lmodrc.lua -if [ ! -f ${_lmod_rc_file} ]; then - echo "Lmod file '${_lmod_rc_file}' does not exist yet; creating it..." - command -V python3 - python3 ${TOPDIR}/create_lmodrc.py ${_eessi_software_path} -fi -_lmod_sitepackage_file=${_lmod_cfg_dir}/SitePackage.lua -if [ ! -f ${_lmod_sitepackage_file} ]; then - echo "Lmod file '${_lmod_sitepackage_file}' does not exist yet; creating it..." - command -V python3 - python3 ${TOPDIR}/create_lmodsitepackage.py ${_eessi_software_path} -fi - -# install any additional required scripts -# order is important: these are needed to install a full CUDA SDK in host_injections -# for now, this just reinstalls all scripts. Note the most elegant, but works - -# the install_scripts.sh script relies on knowing the location of the PR diff -# assume there's only one diff file that corresponds to the PR patch file -pr_diff=$(ls [0-9]*.diff | head -1) -export PR_DIFF="$PWD/$pr_diff" - -# Only run install_scripts.sh if not in dev.eessi.io for security -if [[ -z ${EESSI_DEV_PROJECT} ]]; then - ${TOPDIR}/install_scripts.sh --prefix ${EESSI_PREFIX} -fi - -echo ">> Configuring EasyBuild..." - -# Make sure EESSI-extend is not loaded, and configure location variables for a -# CVMFS installation -module unload EESSI-extend -unset EESSI_USER_INSTALL -unset EESSI_PROJECT_INSTALL -unset EESSI_SITE_INSTALL -export EESSI_CVMFS_INSTALL=1 - -# We now run 'source load_eessi_extend_module.sh' to load or install and load the -# EESSI-extend module which sets up all build environment settings. -# The script requires the EESSI_VERSION given as argument, a couple of -# environment variables set (TMPDIR, EB and EASYBUILD_INSTALLPATH) and the -# function check_exit_code defined. -# NOTE 1, the script exits if those variables/functions are undefined. -# NOTE 2, loading the EESSI-extend module may adjust the value of EASYBUILD_INSTALLPATH, -# e.g., to point to the installation directory for accelerators. -# NOTE 3, we have to set a default for EASYBUILD_INSTALLPATH here in cases the -# EESSI-extend module itself needs to be installed. -export EASYBUILD_INSTALLPATH=${EESSI_PREFIX}/software/${EESSI_OS_TYPE}/${EESSI_SOFTWARE_SUBDIR_OVERRIDE} - -# If in dev.eessi.io, allow building on top of software.eessi.io via EESSI-extend -if [[ ! -z ${EESSI_DEV_PROJECT} ]]; then - # We keep track of the old install path for settings paths to SitePackage.lua and .lmodrc later - EASYBUILD_INSTALLPATH_STANDARD=${EASYBUILD_INSTALLPATH} - # Need to unset $EESSI_CVMFS_INSTALL to use $EESSI_PROJECT_INSTALL - unset EESSI_CVMFS_INSTALL - export EESSI_PROJECT_INSTALL=${EESSI_CVMFS_REPO_OVERRIDE} - echo ">> \$EESSI_PROJECT_INSTALL set to ${EESSI_PROJECT_INSTALL}" -fi - -echo "DEBUG: before loading EESSI-extend // EASYBUILD_INSTALLPATH='${EASYBUILD_INSTALLPATH}'" -source $TOPDIR/load_eessi_extend_module.sh ${EESSI_VERSION} -echo "DEBUG: after loading EESSI-extend // EASYBUILD_INSTALLPATH='${EASYBUILD_INSTALLPATH}'" - -# Install full CUDA SDK and cu* libraries in host_injections -# Hardcode this for now, see if it works -# TODO: We should make a nice yaml and loop over all CUDA versions in that yaml to figure out what to install -# Allow skipping CUDA SDK install in e.g. CI environments -echo "Going to install full CUDA SDK and cu* libraries under host_injections if necessary" -temp_install_storage=${TMPDIR}/temp_install_storage -mkdir -p ${temp_install_storage} -if [ -z "${skip_cuda_install}" ] || [ ! "${skip_cuda_install}" ]; then - ${EESSI_PREFIX}/scripts/gpu_support/nvidia/install_cuda_and_libraries.sh \ - -t ${temp_install_storage} \ - --accept-cuda-eula \ - --accept-cudnn-eula -else - echo "Skipping installation of CUDA SDK and cu* libraries in host_injections, since the --skip-cuda-install flag was passed" -fi - -# Install NVIDIA drivers in host_injections (if they exist) -if command_exists "nvidia-smi"; then - export LD_LIBRARY_PATH="/.singularity.d/libs:${LD_LIBRARY_PATH}" - nvidia-smi --version - ec=$? - if [ ${ec} -eq 0 ]; then - echo "Command 'nvidia-smi' found. Installing NVIDIA drivers for use in prefix shell..." - ${EESSI_PREFIX}/scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh - else - echo "Warning: command 'nvidia-smi' found, but 'nvidia-smi --version' did not run succesfully." - echo "This script now assumes this is NOT a GPU node." - echo "If, and only if, the current node actually does contain Nvidia GPUs, this should be considered an error." - fi -fi - -if [ ! -z "${shared_fs_path}" ]; then - shared_eb_sourcepath=${shared_fs_path}/easybuild/sources - echo ">> Using ${shared_eb_sourcepath} as shared EasyBuild source path" - export EASYBUILD_SOURCEPATH=${shared_eb_sourcepath}:${EASYBUILD_SOURCEPATH} -fi - -# if an accelerator target is specified, we need to make sure that the CPU-only modules are also still available -if [ ! -z ${EESSI_ACCELERATOR_TARGET} ]; then - CPU_ONLY_MODULES_PATH=$(echo $EASYBUILD_INSTALLPATH | sed "s@/accel/${EESSI_ACCELERATOR_TARGET}@@g")/modules/all - if [ -d ${CPU_ONLY_MODULES_PATH} ]; then - module use ${CPU_ONLY_MODULES_PATH} - else - fatal_error "Derived path to CPU-only modules does not exist: ${CPU_ONLY_MODULES_PATH}" - fi -fi - -echo "DEBUG: adding path '$EASYBUILD_INSTALLPATH/modules/all' to MODULEPATH='${MODULEPATH}'" -#module use $EASYBUILD_INSTALLPATH/modules/all -safe_module_use $EASYBUILD_INSTALLPATH/modules/all -echo "DEBUG: after adding module path // MODULEPATH='${MODULEPATH}'" - -if [[ -z ${MODULEPATH} ]]; then - fatal_error "Failed to set up \$MODULEPATH?!" -else - echo_green ">> MODULEPATH set up: ${MODULEPATH}" -fi - -# use PR patch file to determine in which easystack files stuff was added -changed_easystacks=$(cat ${pr_diff} | grep '^+++' | cut -f2 -d' ' | sed 's@^[a-z]/@@g' | grep 'easystacks/.*yml$' | egrep -v 'known-issues|missing') -if [ -z "${changed_easystacks}" ]; then - echo "No missing installations, party time!" # Ensure the bot report success, as there was nothing to be build here -else - - # first process rebuilds, if any, then easystack files for new installations - # "|| true" is used to make sure that the grep command always returns success - rebuild_easystacks=$(echo "${changed_easystacks}" | (grep "/rebuilds/" || true)) - new_easystacks=$(echo "${changed_easystacks}" | (grep -v "/rebuilds/" || true)) - for easystack_file in ${rebuild_easystacks} ${new_easystacks}; do - - echo -e "Processing easystack file ${easystack_file}...\n\n" - - # determine version of EasyBuild module to load based on EasyBuild version included in name of easystack file - eb_version=$(echo ${easystack_file} | sed 's/.*eb-\([0-9.]*\).*.yml/\1/g') - - # load EasyBuild module (will be installed if it's not available yet) - source ${TOPDIR}/load_easybuild_module.sh ${eb_version} - - ${EB} --show-config - - echo_green "All set, let's start installing some software with EasyBuild v${eb_version} in ${EASYBUILD_INSTALLPATH}..." - - if [ -f ${easystack_file} ]; then - echo_green "Feeding easystack file ${easystack_file} to EasyBuild..." - - if [[ ${easystack_file} == *"/rebuilds/"* ]]; then - # the removal script should have removed the original directory and created a new and empty one - # to work around permission issues: - # https://github.com/EESSI/software-layer/issues/556 - echo_yellow "This is a rebuild, so using --try-amend=keeppreviousinstall=True to reuse the already created directory" - ${EB} --easystack ${easystack_file} --robot --try-amend=keeppreviousinstall=True - else - ${EB} --easystack ${easystack_file} --robot - fi - ec=$? - - # copy EasyBuild log file if EasyBuild exited with an error - if [ ${ec} -ne 0 ]; then - eb_last_log=$(unset EB_VERBOSE; eb --last-log) - # copy to current working directory - cp -a ${eb_last_log} . - echo "Last EasyBuild log file copied from ${eb_last_log} to ${PWD}" - # copy to build logs dir (with context added) - copy_build_log "${eb_last_log}" "${build_logs_dir}" - fi - - $TOPDIR/check_missing_installations.sh ${easystack_file} ${pr_diff} - else - fatal_error "Easystack file ${easystack_file} not found!" - fi - - done -fi - -echo "DEBUG: before creating/updating lmod config files // EASYBUILD_INSTALLPATH='${EASYBUILD_INSTALLPATH}'" -if [[ ! -z ${EESSI_DEV_PROJECT} ]]; then - # Make sure .lmod files are not checked for dev.eeessi.io - export LMOD_CONFIG_DIR="${EASYBUILD_INSTALLPATH_STANDARD}/.lmod" - export LMOD_PACKAGE_PATH="${EASYBUILD_INSTALLPATH_STANDARD}/.lmod" -else - export LMOD_CONFIG_DIR="${EASYBUILD_INSTALLPATH}/.lmod" - export LMOD_PACKAGE_PATH="${EASYBUILD_INSTALLPATH}/.lmod" -fi - -lmod_rc_file="$LMOD_CONFIG_DIR/lmodrc.lua" -echo "DEBUG: lmod_rc_file='${lmod_rc_file}'" -if [[ ! -z ${EESSI_ACCELERATOR_TARGET} ]]; then - # EESSI_ACCELERATOR_TARGET is set, so let's remove the accelerator path from $lmod_rc_file - lmod_rc_file=$(echo ${lmod_rc_file} | sed "s@/accel/${EESSI_ACCELERATOR_TARGET}@@") - echo "Path to lmodrc.lua changed to '${lmod_rc_file}'" -fi -lmodrc_changed=$(cat ${pr_diff} | grep '^+++' | cut -f2 -d' ' | sed 's@^[a-z]/@@g' | grep '^create_lmodrc.py$' > /dev/null; echo $?) -if [ ! -f $lmod_rc_file ] || [ ${lmodrc_changed} == '0' ]; then - echo ">> Creating/updating Lmod RC file (${lmod_rc_file})..." - python3 $TOPDIR/create_lmodrc.py ${EASYBUILD_INSTALLPATH} - check_exit_code $? "$lmod_rc_file created" "Failed to create $lmod_rc_file" -fi - -lmod_sitepackage_file="$LMOD_PACKAGE_PATH/SitePackage.lua" -if [[ ! -z ${EESSI_ACCELERATOR_TARGET} ]]; then - # EESSI_ACCELERATOR_TARGET is set, so let's remove the accelerator path from $lmod_sitepackage_file - lmod_sitepackage_file=$(echo ${lmod_sitepackage_file} | sed "s@/accel/${EESSI_ACCELERATOR_TARGET}@@") - echo "Path to SitePackage.lua changed to '${lmod_sitepackage_file}'" -fi -sitepackage_changed=$(cat ${pr_diff} | grep '^+++' | cut -f2 -d' ' | sed 's@^[a-z]/@@g' | grep '^create_lmodsitepackage.py$' > /dev/null; echo $?) -if [ ! -f "$lmod_sitepackage_file" ] || [ "${sitepackage_changed}" == '0' ]; then - echo ">> Creating/updating Lmod SitePackage.lua (${lmod_sitepackage_file})..." - python3 $TOPDIR/create_lmodsitepackage.py ${EASYBUILD_INSTALLPATH} - check_exit_code $? "$lmod_sitepackage_file created" "Failed to create $lmod_sitepackage_file" -fi - -echo ">> Cleaning up ${TMPDIR}..." -rm -r ${TMPDIR} diff --git a/EESSI-remove-software.sh b/EESSI-remove-software.sh deleted file mode 100755 index 47edaa8bfc..0000000000 --- a/EESSI-remove-software.sh +++ /dev/null @@ -1,151 +0,0 @@ -#!/bin/bash -# -# Script to remove part of the EESSI software stack (version set through init/eessi_defaults) - -# see example parsing of command line arguments at -# https://wiki.bash-hackers.org/scripting/posparams#using_a_while_loop -# https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash - -display_help() { - echo "usage: $0 [OPTIONS]" - echo " -g | --generic - instructs script to build for generic architecture target" - echo " -h | --help - display this usage information" -} - -POSITIONAL_ARGS=() - -while [[ $# -gt 0 ]]; do - case $1 in - -g|--generic) - DETECTION_PARAMETERS="--generic" - shift - ;; - -h|--help) - display_help # Call your function - # no shifting needed here, we're done. - exit 0 - ;; - -*|--*) - echo "Error: Unknown option: $1" >&2 - exit 1 - ;; - *) # No more options - POSITIONAL_ARGS+=("$1") # save positional arg - shift - ;; - esac -done - -set -- "${POSITIONAL_ARGS[@]}" - -TOPDIR=$(dirname $(realpath $0)) - -export TMPDIR=$(mktemp -d /tmp/eessi-remove.XXXXXXXX) - -source $TOPDIR/scripts/utils.sh - -echo ">> Determining software subdirectory to use for current build host..." -if [ -z $EESSI_SOFTWARE_SUBDIR_OVERRIDE ]; then - export EESSI_SOFTWARE_SUBDIR_OVERRIDE=$(python3 $TOPDIR/eessi_software_subdir.py $DETECTION_PARAMETERS) - echo ">> Determined \$EESSI_SOFTWARE_SUBDIR_OVERRIDE via 'eessi_software_subdir.py $DETECTION_PARAMETERS' script" -else - echo ">> Picking up pre-defined \$EESSI_SOFTWARE_SUBDIR_OVERRIDE: ${EESSI_SOFTWARE_SUBDIR_OVERRIDE}" -fi - -echo ">> Setting up environment..." - -source $TOPDIR/init/bash - -if [ -d $EESSI_CVMFS_REPO ]; then - echo_green "$EESSI_CVMFS_REPO available, OK!" -else - fatal_error "$EESSI_CVMFS_REPO is not available!" -fi - -if [[ -z ${EESSI_SOFTWARE_SUBDIR} ]]; then - fatal_error "Failed to determine software subdirectory?!" -elif [[ "${EESSI_SOFTWARE_SUBDIR}" != "${EESSI_SOFTWARE_SUBDIR_OVERRIDE}" ]]; then - fatal_error "Values for EESSI_SOFTWARE_SUBDIR_OVERRIDE (${EESSI_SOFTWARE_SUBDIR_OVERRIDE}) and EESSI_SOFTWARE_SUBDIR (${EESSI_SOFTWARE_SUBDIR}) differ!" -else - echo_green ">> Using ${EESSI_SOFTWARE_SUBDIR} as software subdirectory!" -fi - -echo ">> Configuring EasyBuild..." -EB="eb" -source $TOPDIR/configure_easybuild - -echo ">> Setting up \$MODULEPATH..." -# make sure no modules are loaded -module --force purge -# ignore current $MODULEPATH entirely -module unuse $MODULEPATH - -# if an accelerator target is specified, we need to make sure that the CPU-only modules are also still available -if [ ! -z ${EESSI_ACCELERATOR_TARGET} ]; then - CPU_ONLY_MODULES_PATH=$(echo $EASYBUILD_INSTALLPATH | sed "s@/accel/${EESSI_ACCELERATOR_TARGET}@@g")/modules/all - if [ -d ${CPU_ONLY_MODULES_PATH} ]; then - module use ${CPU_ONLY_MODULES_PATH} - else - fatal_error "Derived path to CPU-only modules does not exist: ${CPU_ONLY_MODULES_PATH}" - fi -fi - -module use $EASYBUILD_INSTALLPATH/modules/all -if [[ -z ${MODULEPATH} ]]; then - fatal_error "Failed to set up \$MODULEPATH?!" -else - echo_green ">> MODULEPATH set up: ${MODULEPATH}" -fi - -# assume there's only one diff file that corresponds to the PR patch file -pr_diff=$(ls [0-9]*.diff | head -1) - -# if this script is run as root, use PR patch file to determine if software needs to be removed first -if [ $EUID -eq 0 ]; then - changed_easystacks_rebuilds=$(cat ${pr_diff} | grep '^+++' | cut -f2 -d' ' | sed 's@^[a-z]/@@g' | grep 'easystacks/.*yml$' | egrep -v 'known-issues|missing' | grep "/rebuilds/") - if [ -z ${changed_easystacks_rebuilds} ]; then - echo "No software needs to be removed." - else - for easystack_file in ${changed_easystacks_rebuilds}; do - # determine version of EasyBuild module to load based on EasyBuild version included in name of easystack file - eb_version=$(echo ${easystack_file} | sed 's/.*eb-\([0-9.]*\).*.yml/\1/g') - - # load EasyBuild module (will be installed if it's not available yet) - source ${TOPDIR}/load_easybuild_module.sh ${eb_version} - - if [ -f ${easystack_file} ]; then - echo_green "Software rebuild(s) requested in ${easystack_file}, so determining which existing installation have to be removed..." - # we need to remove existing installation directories first, - # so let's figure out which modules have to be rebuilt by doing a - # dry-run and grepping "someapp/someversion" for the relevant - # lines (with [R] or [F]) - # * [F] $CFGS/s/someapp/someapp-someversion.eb (module: someapp/someversion) - # * [R] $CFGS/s/someapp/someapp-someversion.eb (module: someapp/someversion) - rebuild_apps=$(eb --allow-use-as-root-and-accept-consequences --dry-run-short --rebuild --easystack ${easystack_file} | grep "^ \* \[[FR]\]" | grep -o "module: .*[^)]" | awk '{print $2}') - for app in ${rebuild_apps}; do - # Returns e.g. /cvmfs/software.eessi.io/versions/2023.06/software/linux/x86_64/amd/zen2/modules/all: - app_modulepath=$(module --terse av ${app} 2>&1 | head -n 1 | sed 's/://') - # Two dirname invocations, so returns e.g. /cvmfs/software.eessi.io/versions/2023.06/software/linux/x86_64/amd/zen2 - app_installprefix=$(dirname $(dirname ${app_modulepath})) - app_dir=${app_installprefix}/software/${app} - app_subdirs=$(find ${app_dir} -mindepth 1 -maxdepth 1 -type d) - app_module=${app_installprefix}/modules/all/${app}.lua - echo_yellow "Removing ${app_dir} and ${app_module}..." - rm -rf ${app_dir} - rm -rf ${app_module} - # recreate the installation directory and do an ls on the first-level subdirectories to work around - # permission issues when reinstalling the application (see https://github.com/EESSI/software-layer/issues/556) - echo_yellow "Recreating an empty ${app_dir}..." - mkdir -p ${app_dir} - # these subdirs don't (and shouldn't) exist, but we need to do the ls anyway as a workaround, - # so redirect to /dev/null and ignore the exit code - ls ${app_subdirs} >& /dev/null || true - done - else - fatal_error "Easystack file ${easystack_file} not found!" - fi - done - fi -else - fatal_error "This script can only be run by root!" -fi diff --git a/bot/build.sh b/bot/build.sh deleted file mode 100755 index 2bba0cba55..0000000000 --- a/bot/build.sh +++ /dev/null @@ -1,344 +0,0 @@ -#!/usr/bin/env bash -# -# script to build the EESSI software layer. Intended use is that it is called -# by a (batch) job running on a compute node. -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Thomas Roeblitz (@trz42) -# -# license: GPLv2 -# - -# ASSUMPTIONs: -# - working directory has been prepared by the bot with a checkout of a -# pull request (OR by some other means) -# - the working directory contains a directory 'cfg' where the main config -# file 'job.cfg' has been deposited -# - the directory may contain any additional files referenced in job.cfg - -# stop as soon as something fails -set -e - -# Make sure we are referring to software-layer as working directory -software_layer_dir=$(dirname $(dirname $(realpath $0))) -# source utils.sh and cfg_files.sh -source $software_layer_dir/scripts/utils.sh -source $software_layer_dir/scripts/cfg_files.sh - -# defaults -export JOB_CFG_FILE="${JOB_CFG_FILE_OVERRIDE:=cfg/job.cfg}" -HOST_ARCH=$(uname -m) - -# check if ${JOB_CFG_FILE} exists -if [[ ! -r "${JOB_CFG_FILE}" ]]; then - fatal_error "job config file (JOB_CFG_FILE=${JOB_CFG_FILE}) does not exist or not readable" -fi -echo "bot/build.sh: showing ${JOB_CFG_FILE} from software-layer side" -cat ${JOB_CFG_FILE} - -echo "bot/build.sh: obtaining configuration settings from '${JOB_CFG_FILE}'" -cfg_load ${JOB_CFG_FILE} - -# if http_proxy is defined in ${JOB_CFG_FILE} use it, if not use env var $http_proxy -HTTP_PROXY=$(cfg_get_value "site_config" "http_proxy") -HTTP_PROXY=${HTTP_PROXY:-${http_proxy}} -echo "bot/build.sh: HTTP_PROXY='${HTTP_PROXY}'" - -# if https_proxy is defined in ${JOB_CFG_FILE} use it, if not use env var $https_proxy -HTTPS_PROXY=$(cfg_get_value "site_config" "https_proxy") -HTTPS_PROXY=${HTTPS_PROXY:-${https_proxy}} -echo "bot/build.sh: HTTPS_PROXY='${HTTPS_PROXY}'" - -LOCAL_TMP=$(cfg_get_value "site_config" "local_tmp") -echo "bot/build.sh: LOCAL_TMP='${LOCAL_TMP}'" -# TODO should local_tmp be mandatory? --> then we check here and exit if it is not provided - -# check if path to copy build logs to is specified, so we can copy build logs for failing builds there -BUILD_LOGS_DIR=$(cfg_get_value "site_config" "build_logs_dir") -echo "bot/build.sh: BUILD_LOGS_DIR='${BUILD_LOGS_DIR}'" -# if $BUILD_LOGS_DIR is set, add it to $SINGULARITY_BIND so the path is available in the build container -if [[ ! -z ${BUILD_LOGS_DIR} ]]; then - mkdir -p ${BUILD_LOGS_DIR} - if [[ -z ${SINGULARITY_BIND} ]]; then - export SINGULARITY_BIND="${BUILD_LOGS_DIR}" - else - export SINGULARITY_BIND="${SINGULARITY_BIND},${BUILD_LOGS_DIR}" - fi -fi - -# check if path to directory on shared filesystem is specified, -# and use it as location for source tarballs used by EasyBuild if so -SHARED_FS_PATH=$(cfg_get_value "site_config" "shared_fs_path") -echo "bot/build.sh: SHARED_FS_PATH='${SHARED_FS_PATH}'" -# if $SHARED_FS_PATH is set, add it to $SINGULARITY_BIND so the path is available in the build container -if [[ ! -z ${SHARED_FS_PATH} ]]; then - mkdir -p ${SHARED_FS_PATH} - if [[ -z ${SINGULARITY_BIND} ]]; then - export SINGULARITY_BIND="${SHARED_FS_PATH}" - else - export SINGULARITY_BIND="${SINGULARITY_BIND},${SHARED_FS_PATH}" - fi -fi - -SINGULARITY_CACHEDIR=$(cfg_get_value "site_config" "container_cachedir") -echo "bot/build.sh: SINGULARITY_CACHEDIR='${SINGULARITY_CACHEDIR}'" -if [[ ! -z ${SINGULARITY_CACHEDIR} ]]; then - # make sure that separate directories are used for different CPU families - SINGULARITY_CACHEDIR=${SINGULARITY_CACHEDIR}/${HOST_ARCH} - export SINGULARITY_CACHEDIR -fi - -if [[ -z "${TMPDIR}" ]]; then - echo -n "setting \$STORAGE by replacing any var in '${LOCAL_TMP}' -> " - # replace any env variable in ${LOCAL_TMP} with its - # current value (e.g., a value that is local to the job) - STORAGE=$(envsubst <<< ${LOCAL_TMP}) -else - STORAGE=${TMPDIR} -fi -echo "bot/build.sh: STORAGE='${STORAGE}'" - -# make sure ${STORAGE} exists -mkdir -p ${STORAGE} - -# make sure the base tmp storage is unique -JOB_STORAGE=$(mktemp --directory --tmpdir=${STORAGE} bot_job_tmp_XXX) -echo "bot/build.sh: created unique base tmp storage directory at ${JOB_STORAGE}" - -# obtain list of modules to be loaded -LOAD_MODULES=$(cfg_get_value "site_config" "load_modules") -echo "bot/build.sh: LOAD_MODULES='${LOAD_MODULES}'" - -# singularity/apptainer settings: CONTAINER, HOME, TMPDIR, BIND -CONTAINER=$(cfg_get_value "repository" "container") -export SINGULARITY_HOME="${PWD}:/eessi_bot_job" -export SINGULARITY_TMPDIR="${JOB_STORAGE}/singularity_tmpdir" -mkdir -p ${SINGULARITY_TMPDIR} - -# load modules if LOAD_MODULES is not empty -if [[ ! -z ${LOAD_MODULES} ]]; then - IFS=',' read -r -a modules <<< "$(echo "${LOAD_MODULES}")" - for mod in "${modules[@]}"; - do - echo "bot/build.sh: loading module '${mod}'" - module load ${mod} - done -else - echo "bot/build.sh: no modules to be loaded" -fi - -# determine repository to be used from entry .repository in ${JOB_CFG_FILE} -REPOSITORY_ID=$(cfg_get_value "repository" "repo_id") -REPOSITORY_NAME=$(cfg_get_value "repository" "repo_name") -REPOSITORY_VERSION=$(cfg_get_value "repository" "repo_version") -EESSI_REPOS_CFG_DIR_OVERRIDE=$(cfg_get_value "repository" "repos_cfg_dir") -export EESSI_REPOS_CFG_DIR_OVERRIDE=${EESSI_REPOS_CFG_DIR_OVERRIDE:-${PWD}/cfg} -echo "bot/build.sh: EESSI_REPOS_CFG_DIR_OVERRIDE='${EESSI_REPOS_CFG_DIR_OVERRIDE}'" - -# determine EESSI version to be used from .repository.repo_version in ${JOB_CFG_FILE} -# here, just set & export EESSI_VERSION_OVERRIDE -# next script (eessi_container.sh) makes use of it via sourcing init scripts -# (e.g., init/eessi_defaults or init/minimal_eessi_env) -export EESSI_VERSION_OVERRIDE=${REPOSITORY_VERSION} -echo "bot/build.sh: EESSI_VERSION_OVERRIDE='${EESSI_VERSION_OVERRIDE}'" - -# determine CVMFS repo to be used from .repository.repo_name in ${JOB_CFG_FILE} -# here, just set EESSI_CVMFS_REPO_OVERRIDE, a bit further down -# "source init/eessi_defaults" via sourcing init/minimal_eessi_env -# Note: iff ${EESSI_DEV_PROJECT} is defined (building for dev.eessi.io), then we -# append the project subdirectory to ${EESSI_CVMFS_REPO_OVERRIDE} -export EESSI_CVMFS_REPO_OVERRIDE=/cvmfs/${REPOSITORY_NAME}${EESSI_DEV_PROJECT:+/$EESSI_DEV_PROJECT} -echo "bot/build.sh: EESSI_CVMFS_REPO_OVERRIDE='${EESSI_CVMFS_REPO_OVERRIDE}'" - -# determine CPU architecture to be used from entry .architecture in ${JOB_CFG_FILE} -# fallbacks: -# - ${CPU_TARGET} handed over from bot -# - left empty to let downstream script(s) determine subdir to be used -EESSI_SOFTWARE_SUBDIR_OVERRIDE=$(cfg_get_value "architecture" "software_subdir") -EESSI_SOFTWARE_SUBDIR_OVERRIDE=${EESSI_SOFTWARE_SUBDIR_OVERRIDE:-${CPU_TARGET}} -export EESSI_SOFTWARE_SUBDIR_OVERRIDE -echo "bot/build.sh: EESSI_SOFTWARE_SUBDIR_OVERRIDE='${EESSI_SOFTWARE_SUBDIR_OVERRIDE}'" - -# determine accelerator target (if any) from .architecture in ${JOB_CFG_FILE} -export EESSI_ACCELERATOR_TARGET=$(cfg_get_value "architecture" "accelerator") -echo "bot/build.sh: EESSI_ACCELERATOR_TARGET='${EESSI_ACCELERATOR_TARGET}'" - -# get EESSI_OS_TYPE from .architecture.os_type in ${JOB_CFG_FILE} (default: linux) -EESSI_OS_TYPE=$(cfg_get_value "architecture" "os_type") -export EESSI_OS_TYPE=${EESSI_OS_TYPE:-linux} -echo "bot/build.sh: EESSI_OS_TYPE='${EESSI_OS_TYPE}'" - -# prepare arguments to eessi_container.sh common to build and tarball steps -declare -a COMMON_ARGS=() -COMMON_ARGS+=("--verbose") -COMMON_ARGS+=("--access" "rw") -COMMON_ARGS+=("--mode" "run") -[[ ! -z ${CONTAINER} ]] && COMMON_ARGS+=("--container" "${CONTAINER}") -[[ ! -z ${HTTP_PROXY} ]] && COMMON_ARGS+=("--http-proxy" "${HTTP_PROXY}") -[[ ! -z ${HTTPS_PROXY} ]] && COMMON_ARGS+=("--https-proxy" "${HTTPS_PROXY}") -[[ ! -z ${REPOSITORY_ID} ]] && COMMON_ARGS+=("--repository" "${REPOSITORY_ID}") - -# Also expose software.eessi.io when configured for dev.eessi.io -# Need software.eessi.io for the compat layer -if [[ "${REPOSITORY_NAME}" == "dev.eessi.io" ]]; then - COMMON_ARGS+=("--repository" "software.eessi.io,access=ro") -fi - -# add $software_layer_dir and /dev as extra bind paths -# - $software_layer_dir is needed because it is used as prefix for running scripts -# - /dev is needed to access /dev/fuse -COMMON_ARGS+=("--extra-bind-paths" "${software_layer_dir},/dev") - -# pass through '--contain' to avoid leaking in scripts into the container session -# note, --pass-through can be used multiple times if needed -COMMON_ARGS+=("--pass-through" "--contain") - -# make sure to use the same parent dir for storing tarballs of tmp -PREVIOUS_TMP_DIR=${PWD}/previous_tmp - -# prepare arguments to install_software_layer.sh (specific to build step) -declare -a BUILD_STEP_ARGS=() -declare -a INSTALL_SCRIPT_ARGS=() -declare -a REMOVAL_SCRIPT_ARGS=() -if [[ ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} =~ .*/generic$ ]]; then - INSTALL_SCRIPT_ARGS+=("--generic") - REMOVAL_SCRIPT_ARGS+=("--generic") -fi -[[ ! -z ${BUILD_LOGS_DIR} ]] && INSTALL_SCRIPT_ARGS+=("--build-logs-dir" "${BUILD_LOGS_DIR}") -[[ ! -z ${SHARED_FS_PATH} ]] && INSTALL_SCRIPT_ARGS+=("--shared-fs-path" "${SHARED_FS_PATH}") - -# Skip CUDA installation for riscv.eessi.io -if [[ "${REPOSITORY_NAME}" == "riscv.eessi.io" ]]; then - echo "bot/build.sh: disabling CUDA installation for RISC-V repository (${REPOSITORY_NAME})" - INSTALL_SCRIPT_ARGS+=("--skip-cuda-install") -fi - -# determine if the removal step has to be run -# assume there's only one diff file that corresponds to the PR patch file -pr_diff=$(ls [0-9]*.diff | head -1) -# the true at the end of the next command is important: grep will expectedly return 1 if there is no easystack file being added under rebuilds, -# but due to "set -e" the entire script would otherwise fail -changed_easystacks_rebuilds=$(cat ${pr_diff} | grep '^+++' | cut -f2 -d' ' | sed 's@^[a-z]/@@g' | grep 'easystacks/.*yml$' | (grep "/rebuilds/" || true)) -if [[ -z "${changed_easystacks_rebuilds}" ]]; then - echo "This PR does not add any easystack files in a rebuilds subdirectory, so let's skip the removal step." -else - # prepare directory to store tarball of tmp for removal and build steps - TARBALL_TMP_REMOVAL_STEP_DIR=${PREVIOUS_TMP_DIR}/removal_step - mkdir -p ${TARBALL_TMP_REMOVAL_STEP_DIR} - - # prepare arguments to eessi_container.sh specific to remove step - declare -a REMOVAL_STEP_ARGS=() - REMOVAL_STEP_ARGS+=("--save" "${TARBALL_TMP_REMOVAL_STEP_DIR}") - REMOVAL_STEP_ARGS+=("--storage" "${STORAGE}") - - # add fakeroot option in order to be able to remove software, see: - # https://github.com/EESSI/software-layer/issues/312 - REMOVAL_STEP_ARGS+=("--fakeroot") - - # create tmp file for output of removal step - removal_outerr=$(mktemp remove.outerr.XXXX) - - echo "Executing command to remove software:" - echo "$software_layer_dir/eessi_container.sh ${COMMON_ARGS[@]} ${REMOVAL_STEP_ARGS[@]}" - echo " -- $software_layer_dir/EESSI-remove-software.sh \"${REMOVAL_SCRIPT_ARGS[@]}\" \"$@\" 2>&1 | tee -a ${removal_outerr}" - $software_layer_dir/eessi_container.sh "${COMMON_ARGS[@]}" "${REMOVAL_STEP_ARGS[@]}" \ - -- $software_layer_dir/EESSI-remove-software.sh "${REMOVAL_SCRIPT_ARGS[@]}" "$@" 2>&1 | tee -a ${removal_outerr} - - # make sure that the build step resumes from the same temporary directory - # this is important, as otherwise the removed software will still be there - REMOVAL_TMPDIR=$(grep ' as tmp directory ' ${removal_outerr} | cut -d ' ' -f 2) - BUILD_STEP_ARGS+=("--resume" "${REMOVAL_TMPDIR}") -fi - -# prepare directory to store tarball of tmp for build step -TARBALL_TMP_BUILD_STEP_DIR=${PREVIOUS_TMP_DIR}/build_step -mkdir -p ${TARBALL_TMP_BUILD_STEP_DIR} - -# prepare arguments to eessi_container.sh specific to build step -BUILD_STEP_ARGS+=("--save" "${TARBALL_TMP_BUILD_STEP_DIR}") -BUILD_STEP_ARGS+=("--storage" "${STORAGE}") - -# add options required to handle NVIDIA support -if command_exists "nvidia-smi"; then - # Accept that this may fail - set +e - nvidia-smi --version - ec=$? - set -e - if [ ${ec} -eq 0 ]; then - echo "Command 'nvidia-smi' found, using available GPU" - BUILD_STEP_ARGS+=("--nvidia" "all") - else - echo "Warning: command 'nvidia-smi' found, but 'nvidia-smi --version' did not run succesfully." - echo "This script now assumes this is NOT a GPU node." - echo "If, and only if, the current node actually does contain Nvidia GPUs, this should be considered an error." - BUILD_STEP_ARGS+=("--nvidia" "install") - fi -else - echo "No 'nvidia-smi' found, no available GPU but allowing overriding this check" - BUILD_STEP_ARGS+=("--nvidia" "install") -fi - -# Retain location for host injections so we don't reinstall CUDA -# (Always need to run the driver installation as available driver may change) -if [[ ! -z ${SHARED_FS_PATH} ]]; then - BUILD_STEP_ARGS+=("--host-injections" "${SHARED_FS_PATH}/host-injections") -fi - -# create tmp file for output of build step -build_outerr=$(mktemp build.outerr.XXXX) - -echo "Executing command to build software:" -echo "$software_layer_dir/eessi_container.sh ${COMMON_ARGS[@]} ${BUILD_STEP_ARGS[@]}" -echo " -- $software_layer_dir/install_software_layer.sh \"${INSTALL_SCRIPT_ARGS[@]}\" \"$@\" 2>&1 | tee -a ${build_outerr}" -$software_layer_dir/eessi_container.sh "${COMMON_ARGS[@]}" "${BUILD_STEP_ARGS[@]}" \ - -- $software_layer_dir/install_software_layer.sh "${INSTALL_SCRIPT_ARGS[@]}" "$@" 2>&1 | tee -a ${build_outerr} - -# prepare directory to store tarball of tmp for tarball step -TARBALL_TMP_TARBALL_STEP_DIR=${PREVIOUS_TMP_DIR}/tarball_step -mkdir -p ${TARBALL_TMP_TARBALL_STEP_DIR} - -# create tmp file for output of tarball step -tar_outerr=$(mktemp tar.outerr.XXXX) - -# prepare arguments to eessi_container.sh specific to tarball step -declare -a TARBALL_STEP_ARGS=() -TARBALL_STEP_ARGS+=("--save" "${TARBALL_TMP_TARBALL_STEP_DIR}") - -# determine temporary directory to resume from -if [[ -z ${REMOVAL_TMPDIR} ]]; then - # no rebuild step was done, so the tarball step should resume from the build directory - BUILD_TMPDIR=$(grep ' as tmp directory ' ${build_outerr} | cut -d ' ' -f 2) - TARBALL_STEP_ARGS+=("--resume" "${BUILD_TMPDIR}") -else - # a removal step was done, so resume from its temporary directory (which was also used for the build step) - TARBALL_STEP_ARGS+=("--resume" "${REMOVAL_TMPDIR}") -fi - -timestamp=$(date +%s) -# to set EESSI_VERSION we need to source init/eessi_defaults now -source $software_layer_dir/init/eessi_defaults -# Note: iff ${EESSI_DEV_PROJECT} is defined (building for dev.eessi.io), then we -# append the project (subdirectory) name to the end tarball name. This is information -# then used at the ingestion stage. If ${EESSI_DEV_PROJECT} is not defined, nothing is -# appended -export TGZ=$(printf "eessi-%s-software-%s-%s-%b%d.tar.gz" ${EESSI_VERSION} ${EESSI_OS_TYPE} ${EESSI_SOFTWARE_SUBDIR_OVERRIDE//\//-} ${EESSI_DEV_PROJECT:+$EESSI_DEV_PROJECT-} ${timestamp}) - -# Export EESSI_DEV_PROJECT to use it (if needed) when making tarball -echo "bot/build.sh: EESSI_DEV_PROJECT='${EESSI_DEV_PROJECT}'" -export EESSI_DEV_PROJECT=${EESSI_DEV_PROJECT} - -# value of first parameter to create_tarball.sh - TMP_IN_CONTAINER - needs to be -# synchronised with setting of TMP_IN_CONTAINER in eessi_container.sh -# TODO should we make this a configurable parameter of eessi_container.sh using -# /tmp as default? -TMP_IN_CONTAINER=/tmp -echo "Executing command to create tarball:" -echo "$software_layer_dir/eessi_container.sh ${COMMON_ARGS[@]} ${TARBALL_STEP_ARGS[@]}" -echo " -- $software_layer_dir/create_tarball.sh ${TMP_IN_CONTAINER} ${EESSI_VERSION} ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} \"${EESSI_ACCELERATOR_TARGET}\" /eessi_bot_job/${TGZ} 2>&1 | tee -a ${tar_outerr}" -$software_layer_dir/eessi_container.sh "${COMMON_ARGS[@]}" "${TARBALL_STEP_ARGS[@]}" \ - -- $software_layer_dir/create_tarball.sh ${TMP_IN_CONTAINER} ${EESSI_VERSION} ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} "${EESSI_ACCELERATOR_TARGET}" /eessi_bot_job/${TGZ} 2>&1 | tee -a ${tar_outerr} - -exit 0 diff --git a/bot/check-build.sh b/bot/check-build.sh deleted file mode 100755 index a3c3a3a1d2..0000000000 --- a/bot/check-build.sh +++ /dev/null @@ -1,579 +0,0 @@ -#!/bin/bash -# -# Script to check the result of building the EESSI software layer. -# Intended use is that it is called by a (batch) job running on a compute -# node. -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Thomas Roeblitz (@trz42) -# author: Samuel Moors (@smoors) -# -# license: GPLv2 -# - -# result cases - -# - SUCCESS (all of) -# - working directory contains slurm-JOBID.out file -# - working directory contains eessi*tar.gz -# - no message FATAL -# - no message ERROR -# - no message FAILED -# - no message ' required modules missing:' -# - one or more of 'No missing installations' -# - message regarding created tarball -# - FAILED (one of ... implemented as NOT SUCCESS) -# - no slurm-JOBID.out file -# - no tarball -# - message with FATAL -# - message with ERROR -# - message with FAILED -# - message with ' required modules missing:' -# - no message regarding created tarball - -# stop as soon as something fails -# set -e - -TOPDIR=$(dirname $(realpath $0)) - -source ${TOPDIR}/../scripts/utils.sh -source ${TOPDIR}/../scripts/cfg_files.sh - -# defaults -export JOB_CFG_FILE="${JOB_CFG_FILE_OVERRIDE:=./cfg/job.cfg}" - -# check if ${JOB_CFG_FILE} exists -if [[ ! -r "${JOB_CFG_FILE}" ]]; then - echo_red "job config file (JOB_CFG_FILE=${JOB_CFG_FILE}) does not exist or not readable" -else - echo "bot/check-build.sh: showing ${JOB_CFG_FILE} from software-layer side" - cat ${JOB_CFG_FILE} - - echo "bot/check-build.sh: obtaining configuration settings from '${JOB_CFG_FILE}'" - cfg_load ${JOB_CFG_FILE} -fi - -display_help() { - echo "usage: $0 [OPTIONS]" - echo " OPTIONS:" - echo " -h | --help - display this usage information [default: false]" - echo " -v | --verbose - display more information [default: false]" - echo " --use-check-build-artefacts-script - alternative build artefacts check (sources file check-build-artefacts.sh if exists) [default: false]" -} - -# set defaults for command line arguments -VERBOSE=0 -USE_CHECK_BUILD_ARTEFACTS_SCRIPT=0 - -POSITIONAL_ARGS=() - -while [[ $# -gt 0 ]]; do - case $1 in - -h|--help) - display_help - exit 0 - ;; - -v|--verbose) - VERBOSE=1 - shift 1 - ;; - --use-check-build-artefacts-script) - USE_CHECK_BUILD_ARTEFACTS_SCRIPT=1 - shift 1 - ;; - --) - shift - POSITIONAL_ARGS+=("$@") # save positional args - break - ;; - -*|--*) - fatal_error "Unknown option: $1" "${CMDLINE_ARG_UNKNOWN_EXITCODE}" - ;; - *) # No more options - POSITIONAL_ARGS+=("$1") # save positional arg - shift - ;; - esac -done - -set -- "${POSITIONAL_ARGS[@]}" - -job_dir=${PWD} - -[[ ${VERBOSE} -ne 0 ]] && echo ">> analysing job in directory ${job_dir}" - -job_out="slurm-${SLURM_JOB_ID}.out" -[[ ${VERBOSE} -ne 0 ]] && echo ">> searching for job output file(s) matching '"${job_out}"'" -if [[ -f ${job_out} ]]; then - SLURM_OUTPUT_FOUND=1 - [[ ${VERBOSE} -ne 0 ]] && echo " found slurm output file '"${job_out}"'" -else - SLURM_OUTPUT_FOUND=0 - [[ ${VERBOSE} -ne 0 ]] && echo " Slurm output file '"${job_out}"' NOT found" -fi - -FATAL=-1 -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - GP_fatal='FATAL: ' - grep_out=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_fatal}") - [[ $? -eq 0 ]] && FATAL=1 || FATAL=0 - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_fatal}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_out}" -fi - -ERROR=-1 -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - GP_error='ERROR: ' - grep_out=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_error}") - [[ $? -eq 0 ]] && ERROR=1 || ERROR=0 - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_error}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_out}" -fi - -FAILED=-1 -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - GP_failed='FAILED: ' - grep_out=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_failed}") - [[ $? -eq 0 ]] && FAILED=1 || FAILED=0 - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_failed}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_out}" -fi - -MISSING=-1 -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - GP_req_missing=' required modules missing:' - grep_out=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_req_missing}") - [[ $? -eq 0 ]] && MISSING=1 || MISSING=0 - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_req_missing}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_out}" -fi - -NO_MISSING=-1 -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - GP_no_missing='No missing installations' - grep_out=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_no_missing}") - [[ $? -eq 0 ]] && NO_MISSING=1 || NO_MISSING=0 - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_no_missing}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_out}" -fi - -if [[ $USE_CHECK_BUILD_ARTEFACTS_SCRIPT -eq 0 ]]; then - TGZ=-1 - TARBALL= - if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - GP_tgz_created="\.tar\.gz created!" - grep_out=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_tgz_created}" | sort -u) - if [[ $? -eq 0 ]]; then - TGZ=1 - TARBALL=$(echo ${grep_out} | sed -e 's@^.*/\(eessi[^/ ]*\) .*$@\1@') - else - TGZ=0 - fi - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_tgz_created}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_out}" - fi -fi - -[[ ${VERBOSE} -ne 0 ]] && echo "SUMMARY: ${job_dir}/${job_out}" -[[ ${VERBOSE} -ne 0 ]] && echo " : ()" -[[ ${VERBOSE} -ne 0 ]] && echo " FATAL......: $([[ $FATAL -eq 1 ]] && echo 'yes' || echo 'no') (no)" -[[ ${VERBOSE} -ne 0 ]] && echo " ERROR......: $([[ $ERROR -eq 1 ]] && echo 'yes' || echo 'no') (no)" -[[ ${VERBOSE} -ne 0 ]] && echo " FAILED.....: $([[ $FAILED -eq 1 ]] && echo 'yes' || echo 'no') (no)" -[[ ${VERBOSE} -ne 0 ]] && echo " REQ_MISSING: $([[ $MISSING -eq 1 ]] && echo 'yes' || echo 'no') (no)" -[[ ${VERBOSE} -ne 0 ]] && echo " NO_MISSING.: $([[ $NO_MISSING -eq 1 ]] && echo 'yes' || echo 'no') (yes)" -if [[ $USE_CHECK_BUILD_ARTEFACTS_SCRIPT -eq 0 ]]; then - [[ ${VERBOSE} -ne 0 ]] && echo " TGZ_CREATED: $([[ $TGZ -eq 1 ]] && echo 'yes' || echo 'no') (yes)" -fi - -# Here, we try to do some additional analysis on the output file -# to see if we can print a more clear 'reason' for the failure -# For now, we only analyse unmerged EasyConfigs as potential cause, but we can easily add checks for other -# specific scenarios below - -# Check for the pattern being added here by check_missing_installations.sh to the output to -# see if EasyConfigs might have been unmerged, and that's causing a failure -UNMERGED_EASYCONFIG=-1 -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - gp_unmerged="are you sure all PRs referenced have been merged in EasyBuild" - grep_unmerged=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${gp_unmerged}") - [[ $? -eq 0 ]] && UNMERGED_EASYCONFIG=1 || UNMERGED_EASYCONFIG=0 - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${gp_unmerged}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_unmerged}" -fi - -job_result_file=_bot_job${SLURM_JOB_ID}.result - -# Default reason: -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]] && \ - [[ ${FATAL} -eq 0 ]] && \ - [[ ${ERROR} -eq 0 ]] && \ - [[ ${FAILED} -eq 0 ]] && \ - [[ ${MISSING} -eq 0 ]] && \ - [[ ${NO_MISSING} -eq 1 ]] && \ - [[ $USE_CHECK_BUILD_ARTEFACTS_SCRIPT -ne 0 || ${TGZ} -eq 1 ]] && \ - [[ $USE_CHECK_BUILD_ARTEFACTS_SCRIPT -ne 0 || -n ${TARBALL} ]]; then - # SUCCESS - status="SUCCESS" - reason="" - summary=":grin: SUCCESS" -elif [[ ${UNMERGED_EASYCONFIG} -eq 1 ]]; then - status="FAILURE" - reason="EasyConfig not found during missing installation check. Are you sure all PRs referenced have been merged in EasyBuild?" - summary=":cry: FAILURE" -else - # FAILURE - status="FAILURE" - # General failure, we don't know a more specific reason - reason="" - summary=":cry: FAILURE" -fi - -### Example details/descriptions -# Note, final string must not contain any line breaks. Below example include -# line breaks for the sake of readability. In case of FAILURE, the structure is -# very similar (incl. information about Artefacts if any was produced), however, -# under Details some lines will be marked with :x: -#
-# :grin: SUCCESS _(click triangle for details)_ -#
-#
_Details_
-#
-# :white_check_mark: job output file slurm-4682.out
-# :white_check_mark: no message matching FATAL:
-# :white_check_mark: no message matching ERROR:
-# :white_check_mark: no message matching FAILED:
-# :white_check_mark: no message matching required modules missing:
-# :white_check_mark: found message(s) matching No missing installations
-# :white_check_mark: found message matching tar.gz created!
-#
-#
_Artefacts_
-#
-#
-# eessi-2023.06-software-linux-x86_64-generic-1682696567.tar.gz -# size: 234 MiB (245366784 bytes)
-# entries: 1234
-# modules under _2023.06/software/linux/x86_64/generic/modules/all/_
-#
-#           GCC/9.3.0.lua
-# GCC/10.3.0.lua
-# OpenSSL/1.1.lua -#
-# software under _2023.06/software/linux/x86_64/generic/software/_ -#
-#           GCC/9.3.0/
-# CMake/3.20.1-GCCcore-10.3.0/
-# OpenMPI/4.1.1-GCC-10.3.0/ -#
-# other under _2023.06/software/linux/x86_64/generic/_ -#
-#           .lmod/cache/spiderT.lua
-# .lmod/cache/spiderT.luac_5.1
-# .lmod/cache/timestamp -#
-#
-#
-#
-#
-# -#
-# :cry: FAILURE _(click triangle for details)_ -#
-#
_Details_
-#
-# :white_check_mark: job output file slurm-4682.out
-# :x: no message matching FATAL:
-# :x: no message matching ERROR:
-# :white_check_mark: no message matching FAILED:
-# :x: no message matching required modules missing:
-# :white_check_mark: found message(s) matching No missing installations
-# :white_check_mark: found message matching tar.gz created!
-#
-#
_Artefacts_
-#
-# No artefacts were created or found. -#
-#
-#
-### - - -function print_br_item() { - format="${1}" - item="${2}" - echo -n "${format//__ITEM__/${item}}
" -} - -function print_br_item2() { - format="${1}" - item="${2}" - item2="${3}" - format1="${format//__ITEM__/${item}}" - echo -n "${format1//__ITEM2__/${item2}}
" -} - -function print_code_item() { - format="${1}" - item="${2}" - echo -n "${format//__ITEM__/${item}}" -} - -function print_dd_item() { - format="${1}" - item="${2}" - echo -n "
${format//__ITEM__/${item}}
" -} - -function print_list_item() { - format="${1}" - item="${2}" - echo -n "
  • ${format//__ITEM__/${item}}
  • " -} - -function print_pre_item() { - format="${1}" - item="${2}" - echo -n "
    ${format//__ITEM__/${item}}
    " -} - -function success() { - format="${comment_success_item_fmt}" - item="$1" - print_br_item "${format}" "${item}" -} - -function failure() { - format="${comment_failure_item_fmt}" - item="$1" - print_br_item "${format}" "${item}" -} - -function add_detail() { - actual=${1} - expected=${2} - success_msg="${3}" - failure_msg="${4}" - if [[ ${actual} -eq ${expected} ]]; then - success "${success_msg}" - else - failure "${failure_msg}" - fi -} - -echo "[RESULT]" > ${job_result_file} -echo -n "comment_description = " >> ${job_result_file} - -# construct values for placeholders in comment_template: -# - __SUMMARY_FMT__ -> variable $comment_summary -# - __DETAILS_FMT__ -> variable $comment_details -# - __ARTEFACTS_FMT__ -> variable $comment_artefacts - -# construct and write complete PR comment details: implements third alternative -comment_template="
    __SUMMARY_FMT__
    __REASON_FMT____DETAILS_FMT____ARTEFACTS_FMT__
    " -comment_success_item_fmt=":white_check_mark: __ITEM__" -comment_failure_item_fmt=":x: __ITEM__" - -# Initialize comment_description -comment_description=${comment_template} - -# Now, start replacing template items one by one -# Replace the summary template (__SUMMARY_FMT__) -comment_summary_fmt="__SUMMARY__ _(click triangle for details)_" -comment_summary="${comment_summary_fmt/__SUMMARY__/${summary}}" -comment_description=${comment_template/__SUMMARY_FMT__/${comment_summary}} - -# Only add if there is a reason (e.g. no reason for successful runs) -if [[ ! -z ${reason} ]]; then - comment_reason_fmt="
    _Reason_
    __REASONS__
    " - reason_details="${comment_reason_fmt/__REASONS__/${reason}}" - comment_description=${comment_description/__REASON_FMT__/${reason_details}} -else - comment_description=${comment_description/__REASON_FMT__/""} -fi - -# Replace the details template (__DETAILS_FMT__) -# first construct comment_details_list, abbreviated comment_details_list -# then use it to set comment_details -comment_details_list="" - -success_msg="job output file ${job_out}" -failure_msg="no job output file ${job_out}" -comment_details_list=${comment_details_list}$(add_detail ${SLURM_OUTPUT_FOUND} 1 "${success_msg}" "${failure_msg}") - -success_msg="no message matching ${GP_fatal}" -failure_msg="found message matching ${GP_fatal}" -comment_details_list=${comment_details_list}$(add_detail ${FATAL} 0 "${success_msg}" "${failure_msg}") - -success_msg="no message matching ${GP_error}" -failure_msg="found message matching ${GP_error}" -comment_details_list=${comment_details_list}$(add_detail ${ERROR} 0 "${success_msg}" "${failure_msg}") - -success_msg="no message matching ${GP_failed}" -failure_msg="found message matching ${GP_failed}" -comment_details_list=${comment_details_list}$(add_detail ${FAILED} 0 "${success_msg}" "${failure_msg}") - -success_msg="no message matching ${GP_req_missing}" -failure_msg="found message matching ${GP_req_missing}" -comment_details_list=${comment_details_list}$(add_detail ${MISSING} 0 "${success_msg}" "${failure_msg}") - -success_msg="found message(s) matching ${GP_no_missing}" -failure_msg="no message matching ${GP_no_missing}" -comment_details_list=${comment_details_list}$(add_detail ${NO_MISSING} 1 "${success_msg}" "${failure_msg}") - -if [[ $USE_CHECK_BUILD_ARTEFACTS_SCRIPT -eq 0 ]]; then - success_msg="found message matching ${GP_tgz_created}" - failure_msg="no message matching ${GP_tgz_created}" - comment_details_list=${comment_details_list}$(add_detail ${TGZ} 1 "${success_msg}" "${failure_msg}") -fi - -# Now, do the actual replacement of __DETAILS_FMT__ -comment_details_fmt="
    _Details_
    __DETAILS_LIST__
    " -comment_details="${comment_details_fmt/__DETAILS_LIST__/${comment_details_list}}" -comment_description=${comment_description/__DETAILS_FMT__/${comment_details}} - -if [[ $USE_CHECK_BUILD_ARTEFACTS_SCRIPT -eq 0 ]]; then - # first construct comment_artefacts_list - # then use it to set comment_artefacts - comment_artifacts_list="" - - # TARBALL should only contain a single tarball - if [[ ! -z ${TARBALL} ]]; then - # Example of the detailed information for a tarball. The actual result MUST be a - # single line (no '\n') or it would break the structure of the markdown table - # that holds status updates of a bot job. - # - #
    - #
    - # eessi-2023.06-software-linux-x86_64-generic-1682696567.tar.gz - # size: 234 MiB (245366784 bytes)
    - # entries: 1234
    - # modules under _2023.06/software/linux/x86_64/intel/cascadelake/modules/all/_
    - #
    -        #       GCC/9.3.0.lua
    - # GCC/10.3.0.lua
    - # OpenSSL/1.1.lua - #
    - # software under _2023.06/software/linux/x86_64/intel/cascadelake/software/_ - #
    -        #       GCC/9.3.0/
    - # CMake/3.20.1-GCCcore-10.3.0/
    - # OpenMPI/4.1.1-GCC-10.3.0/ - #
    - # other under _2023.06/software/linux/x86_64/intel/cascadelake/_ - #
    -        #       .lmod/cache/spiderT.lua
    - # .lmod/cache/spiderT.luac_5.1
    - # .lmod/cache/timestamp - #
    - #
    - #
    - size="$(stat --dereference --printf=%s ${TARBALL})" - size_mib=$((${size} >> 20)) - tmpfile=$(mktemp --tmpdir=. tarfiles.XXXX) - tar tf ${TARBALL} > ${tmpfile} - entries=$(cat ${tmpfile} | wc -l) - # determine prefix from job config: VERSION/software/OS_TYPE/CPU_FAMILY/ARCHITECTURE - # e.g., 2023.06/software/linux/x86_64/intel/skylake_avx512 - # cfg/job.cfg contains (only the attributes to be used are shown below): - # [repository] - # repo_version = 2023.06 - # [architecture] - # os_type = linux - # software_subdir = x86_64/intel/skylake_avx512 - repo_version=$(cfg_get_value "repository" "repo_version") - os_type=$(cfg_get_value "architecture" "os_type") - software_subdir=$(cfg_get_value "architecture" "software_subdir") - accelerator=$(cfg_get_value "architecture" "accelerator") - prefix="${repo_version}/software/${os_type}/${software_subdir}" - - # if we build for an accelerator, the prefix is different - if [[ ! -z ${accelerator} ]]; then - prefix="${prefix}/accel/${accelerator}" - fi - - # extract directories/entries from tarball content - modules_entries=$(grep "${prefix}/modules" ${tmpfile}) - software_entries=$(grep "${prefix}/software" ${tmpfile}) - other_entries=$(cat ${tmpfile} | grep -v "${prefix}/modules" | grep -v "${prefix}/software") - other_shortened=$(echo "${other_entries}" | sed -e "s@^.*${prefix}/@@" | sort -u) - modules=$(echo "${modules_entries}" | grep "/all/.*/.*lua$" | sed -e 's@^.*/\([^/]*/[^/]*.lua\)$@\1@' | sort -u) - software_pkgs=$(echo "${software_entries}" | sed -e "s@${prefix}/software/@@" | awk -F/ '{if (NR >= 2) {print $1 "/" $2}}' | sort -u) - - artefact_summary="$(print_code_item '__ITEM__' ${TARBALL})" - comment_artifacts_list="" - comment_artifacts_list="${comment_artifacts_list}$(print_br_item2 'size: __ITEM__ MiB (__ITEM2__ bytes)' ${size_mib} ${size})" - comment_artifacts_list="${comment_artifacts_list}$(print_br_item 'entries: __ITEM__' ${entries})" - comment_artifacts_list="${comment_artifacts_list}$(print_br_item 'modules under ___ITEM___' ${prefix}/modules/all)" - comment_artifacts_list="${comment_artifacts_list}
    "
    -        if [[ ! -z ${modules} ]]; then
    -            while IFS= read -r mod ; do
    -                comment_artifacts_list="${comment_artifacts_list}$(print_br_item '__ITEM__' ${mod})"
    -            done <<< "${modules}"
    -        else
    -            comment_artifacts_list="${comment_artifacts_list}$(print_br_item '__ITEM__' 'no module files in tarball')"
    -        fi
    -        comment_artifacts_list="${comment_artifacts_list}
    " - comment_artifacts_list="${comment_artifacts_list}$(print_br_item 'software under ___ITEM___' ${prefix}/software)" - comment_artifacts_list="${comment_artifacts_list}
    "
    -        if [[ ! -z ${software_pkgs} ]]; then
    -            while IFS= read -r sw_pkg ; do
    -                comment_artifacts_list="${comment_artifacts_list}$(print_br_item '__ITEM__' ${sw_pkg})"
    -            done <<< "${software_pkgs}"
    -        else
    -            comment_artifacts_list="${comment_artifacts_list}$(print_br_item '__ITEM__' 'no software packages in tarball')"
    -        fi
    -        comment_artifacts_list="${comment_artifacts_list}
    " - comment_artifacts_list="${comment_artifacts_list}$(print_br_item 'other under ___ITEM___' ${prefix})" - comment_artifacts_list="${comment_artifacts_list}
    "
    -        if [[ ! -z ${other_shortened} ]]; then
    -            while IFS= read -r other ; do
    -                comment_artifacts_list="${comment_artifacts_list}$(print_br_item '__ITEM__' ${other})"
    -            done <<< "${other_shortened}"
    -        else
    -            comment_artifacts_list="${comment_artifacts_list}$(print_br_item '__ITEM__' 'no other files in tarball')"
    -        fi
    -        comment_artifacts_list="${comment_artifacts_list}
    " - else - comment_artifacts_list="${comment_artifacts_list}$(print_dd_item 'No artefacts were created or found.' '')" - fi - - comment_artefact_details_fmt="
    __ARTEFACT_SUMMARY____ARTEFACT_DETAILS__
    " - comment_artefacts_details="${comment_artefact_details_fmt/__ARTEFACT_SUMMARY__/${artefact_summary}}" - comment_artefacts_details="${comment_artefacts_details/__ARTEFACT_DETAILS__/${comment_artifacts_list}}" - - comment_artefacts_fmt="
    _Artefacts_
    __ARTEFACTS_LIST__
    " - comment_artefacts="${comment_artefacts_fmt/__ARTEFACTS_LIST__/${comment_artefacts_details}}" - comment_description=${comment_description/__ARTEFACTS_FMT__/${comment_artefacts}} - - echo "${comment_description}" >> ${job_result_file} - - # add overall result: SUCCESS, FAILURE, UNKNOWN + artefacts - # - this should make use of subsequent steps such as deploying a tarball more - # efficient - echo "status = ${status}" >> ${job_result_file} - echo "artefacts = " >> ${job_result_file} - echo "${TARBALL}" | sed -e 's/^/ /g' >> ${job_result_file} - - # remove tmpfile - if [[ -f ${tmpfile} ]]; then - rm ${tmpfile} - fi - -elif [[ -f "$TOPDIR/check-build-artefacts.sh" ]]; then - source "$TOPDIR/check-build-artefacts.sh" -else - echo "ERROR: Required script $TOPDIR/check-build-artefacts.sh not found!" >&2 - exit 1 -fi - -# exit script with value that reflects overall job result: SUCCESS (0), FAILURE (1) -test "${status}" == "SUCCESS" -exit $? diff --git a/bot/check-result.sh b/bot/check-result.sh deleted file mode 120000 index 02f753db50..0000000000 --- a/bot/check-result.sh +++ /dev/null @@ -1 +0,0 @@ -check-build.sh \ No newline at end of file diff --git a/bot/check-test.sh b/bot/check-test.sh deleted file mode 100755 index 2731e75464..0000000000 --- a/bot/check-test.sh +++ /dev/null @@ -1,238 +0,0 @@ -#!/bin/bash -# -# Dummy script that only creates test result file for the bot, without actually checking anything -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Kenneth Hoste (HPC-UGent) -# -# license: GPLv2 -# -job_dir=${PWD} -job_out="slurm-${SLURM_JOB_ID}.out" -job_test_result_file="_bot_job${SLURM_JOB_ID}.test" - -# Check that job output file is found -[[ ${VERBOSE} -ne 0 ]] && echo ">> searching for job output file(s) matching '"${job_out}"'" -if [[ -f ${job_out} ]]; then - SLURM_OUTPUT_FOUND=1 - [[ ${VERBOSE} -ne 0 ]] && echo " found slurm output file '"${job_out}"'" -else - SLURM_OUTPUT_FOUND=0 - [[ ${VERBOSE} -ne 0 ]] && echo " Slurm output file '"${job_out}"' NOT found" -fi - -# ReFrame prints e.g. -#[----------] start processing checks -#[ RUN ] GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=2_nodes %module_name=GROMACS/2021.3-foss-2021a /d597cff4 @snellius:rome+default -#[ RUN ] GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=2_nodes %module_name=GROMACS/2021.3-foss-2021a /d597cff4 @snellius:genoa+default -#[ RUN ] GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=1_cpn_2_nodes %module_name=GROMACS/2021.3-foss-2021a /f4194106 @snellius:genoa+default -#[ FAIL ] (1/3) GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=2_nodes %module_name=GROMACS/2021.3-foss-2021a /d597cff4 @snellius:genoa+default -#==> test failed during 'sanity': test staged in '/scratch-shared/casparl/reframe_output/staging/snellius/genoa/default/GROMACS_EESSI_d597cff4' -#[ OK ] (2/3) GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=2_nodes %module_name=GROMACS/2021.3-foss-2021a /d597cff4 @snellius:rome+default -#P: perf: 8.441 ns/day (r:0, l:None, u:None) -#[ FAIL ] (3/3) GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=1_cpn_2_nodes %module_name=GROMACS/2021.3-foss-2021a /f4194106 @snellius:genoa+default -#==> test failed during 'sanity': test staged in '/scratch-shared/casparl/reframe_output/staging/snellius/genoa/default/GROMACS_EESSI_f4194106' -#[----------] all spawned checks have finished -#[ FAILED ] Ran 3/3 test case(s) from 2 check(s) (2 failure(s), 0 skipped, 0 aborted) - -# We will grep for the last and final line, since this reflects the overall result -# Specifically, we grep for FAILED, since this is also what we print if a step in the test script itself fails -FAILED=-1 -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - GP_failed='\[\s*FAILED\s*\].*Ran .* test case' - grep_reframe_failed=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_failed}") - [[ $? -eq 0 ]] && FAILED=1 || FAILED=0 - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_failed}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_reframe_failed}" -fi - -# Here, we grep for 'ERROR:', which is printed if a fatal_error is encountered when executing the test step -# I.e. this is an error in execution of the run_tests.sh itself, NOT in running the actual tests -ERROR=-1 -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - GP_error='ERROR: ' - grep_out=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_error}") - [[ $? -eq 0 ]] && ERROR=1 || ERROR=0 - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_error}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_out}" -fi - -SUCCESS=-1 -# Grep for the success pattern, so we can report the amount of tests run -if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then - GP_success='\[\s*PASSED\s*\].*Ran .* test case' - grep_reframe_success=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_success}") - [[ $? -eq 0 ]] && SUCCESS=1 || SUCCESS=0 - # have to be careful to not add searched for pattern into slurm out file - [[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_success}"'" - [[ ${VERBOSE} -ne 0 ]] && echo "${grep_reframe_success}" -fi - -if [[ ! -z ${grep_reframe_failed} ]]; then - grep_reframe_result=${grep_reframe_failed} -else - # Grep the entire output of ReFrame, so that we can report it in the foldable section of the test report - GP_success_full='(?s)\[----------\] start processing checks.*?\[==========\] Finished on [a-zA-Z0-9 ]*' - # Grab the full ReFrame report, than cut the irrelevant parts - # Note that the character limit for messages in github is around 65k, so cutting is important - grep_reframe_success_full=$( \ - grep -v "^>> searching for " ${job_dir}/${job_out} | \ - # Use -z - grep -Pzo "${GP_success_full}" | \ - # Replace null character with newline, to undo the -z option - sed 's/\x00/\n/g' | \ - # Remove the [ RUN ] lines from reframe, they are not very informative - grep -v -P '\[\s*RUN\s*]' | \ - # Remove the line '[----------] all spawned checks have finished' - grep -v '\[-*\]' | \ - # Remove the line '[==========] Finished on Mon Oct 7 21' - grep -v '\[=*\]' | \ - # Remove blank line(s) from the report - grep -v '^$' | \ - # Remove warnings about the local spawner not supporting memory requests - grep -v 'WARNING\: hooks\.req_memory_per_node does not support the scheduler you configured .local.*$' | \ - # Strip color coding characters - sed 's/\x1B\[[0-9;]*m//g' | \ - # Replace all newline characters with
    - sed ':a;N;$!ba;s/\n//g' | \ - # Replace % with %%. Use \%\% to interpret both %% as (non-special) characters - sed 's/\%/\%\%/g' \ - ) - # TODO (optional): we could impose a character limit here, and truncate if too long - # (though we should do that before inserting the
    statements). - # If we do, we should probably re-append the final summary, e.g. - # [ PASSED ] Ran 10/10 test case(s) from 10 check(s) (0 failure(s), 0 skipped, 0 aborted) - # so that that is always displayed - # However, that's not implemented yet - let's see if this ever even becomes an issue - grep_reframe_result=${grep_reframe_success_full} -fi -echo "grep_reframe_result: ${grep_reframe_result}" - -echo "[TEST]" > ${job_test_result_file} -if [[ ${SLURM_OUTPUT_FOUND} -eq 0 ]]; then - summary=":cry: FAILURE" - reason="Job output file not found, cannot check test results." - status="FAILURE" -# Should come before general errors: if SUCCESS==1, it indicates the test suite ran succesfully -# regardless of other things that might have gone wrong -elif [[ ${SUCCESS} -eq 1 ]]; then - summary=":grin: SUCCESS" - reason="" - status="SUCCESS" -# Should come before general errors: if FAILED==1, it indicates the test suite ran -# otherwise the pattern wouldn't have been there -elif [[ ${FAILED} -eq 1 ]]; then - summary=":cry: FAILURE" - reason="EESSI test suite produced failures." - status="FAILURE" -elif [[ ${ERROR} -eq 1 ]]; then - summary=":cry: FAILURE" - reason="EESSI test suite was not run, test step itself failed to execute." - status="FAILURE" -else - summary=":cry: FAILURE" - reason="Failed for unknown reason" - status="FAILURE" -fi - - -echo "[TEST]" > ${job_test_result_file} -echo -n "comment_description = " >> ${job_test_result_file} - -# Use template for writing PR comment with details -# construct and write complete PR comment details: implements third alternative -comment_template="
    __SUMMARY_FMT__
    __REASON_FMT____REFRAME_FMT____DETAILS_FMT__
    " -comment_success_item_fmt=":white_check_mark: __ITEM__" -comment_failure_item_fmt=":x: __ITEM__" - -# Initialize comment_description -comment_description=${comment_template} - -# Now, start replacing template items one by one -comment_summary_fmt="__SUMMARY__ _(click triangle for details)_" -comment_summary="${comment_summary_fmt/__SUMMARY__/${summary}}" -comment_description=${comment_description/__SUMMARY_FMT__/${comment_summary}} - - -# Only add if there is a reason (e.g. no reason for successful runs) -if [[ ! -z ${reason} ]]; then - comment_reason_fmt="
    _Reason_
    __REASONS__
    " - reason_details="${comment_reason_fmt/__REASONS__/${reason}}" - comment_description=${comment_description/__REASON_FMT__/${reason_details}} -else - comment_description=${comment_description/__REASON_FMT__/""} -fi - -# Only add if there is a reframe summary (e.g. no reframe summary if reframe wasn't launched succesfully) -echo "ReFrame result:" -echo "${grep_reframe_result}" -if [[ ! -z ${grep_reframe_result} ]]; then - comment_reframe_fmt="
    _ReFrame Summary_
    __REFRAME_SUMMARY__
    " - reframe_summary=${comment_reframe_fmt/__REFRAME_SUMMARY__/${grep_reframe_result}} - comment_description=${comment_description/__REFRAME_FMT__/${reframe_summary}} -else - comment_description=${comment_description/__REFRAME_FMT__/""} -fi - -# Declare functions -function print_br_item() { - format="${1}" - item="${2}" - echo -n "${format//__ITEM__/${item}}
    " -} - -function success() { - format="${comment_success_item_fmt}" - item="$1" - print_br_item "${format}" "${item}" -} - -function failure() { - format="${comment_failure_item_fmt}" - item="$1" - print_br_item "${format}" "${item}" -} - -function add_detail() { - actual=${1} - expected=${2} - success_msg="${3}" - failure_msg="${4}" - if [[ ${actual} -eq ${expected} ]]; then - success "${success_msg}" - else - failure "${failure_msg}" - fi -} - -# first construct comment_details_list, abbreviated comment_details_list -# then use it to set comment_details -comment_details_list="" - -success_msg="job output file ${job_out}" -failure_msg="no job output file ${job_out}" -comment_details_list=${comment_details_list}$(add_detail ${SLURM_OUTPUT_FOUND} 1 "${success_msg}" "${failure_msg}") - -success_msg="no message matching ${GP_error}" -failure_msg="found message matching ${GP_error}" -comment_details_list=${comment_details_list}$(add_detail ${ERROR} 0 "${success_msg}" "${failure_msg}") - -# Add an escape character to every *, for it to be printed correctly in the comment on GitHub -GP_failed="${GP_failed//\*/\\*}" -success_msg="no message matching ""${GP_failed}""" -failure_msg="found message matching ""${GP_failed}""" -comment_details_list=${comment_details_list}$(add_detail ${FAILED} 0 "${success_msg}" "${failure_msg}") - -comment_details_fmt="
    _Details_
    __DETAILS_LIST__
    " -comment_details="${comment_details_fmt/__DETAILS_LIST__/${comment_details_list}}" -comment_description=${comment_description/__DETAILS_FMT__/${comment_details}} - -# Actually writing the comment description to the result file -echo "${comment_description}" >> ${job_test_result_file} -echo "status = ${status}" >> ${job_test_result_file} - -exit 0 diff --git a/bot/inspect.sh b/bot/inspect.sh deleted file mode 100755 index 6ffd227b59..0000000000 --- a/bot/inspect.sh +++ /dev/null @@ -1,448 +0,0 @@ -#!/usr/bin/env bash -# -# Script to inspect result of a build job for the EESSI software layer. -# Intended use is that it is called with a path to a job directory. -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Thomas Roeblitz (@trz42) -# -# license: GPLv2 -# - -# ASSUMPTIONs: -# - Script is executed on the same architecture the job was running on. -# - Initially, we also assume that is run on the same resource with the -# same (compute) node setup (local disk space, HTTP proxies, etc.) -# - The job directory being supplied has been prepared by the bot with a -# checkout of a pull request (OR by some other means) -# - The job directory contains a directory 'cfg' where the main config -# file 'job.cfg' has been deposited. -# - The 'cfg' directory may contain any additional files referenced in -# 'job.cfg' (repos.cfg, etc.). -# - The job produced some tarballs for its state (tmp disk for overlayfs, -# CVMFS cache, etc.) under 'previous_tmp/{build,tarball}_step'. - -# stop as soon as something fails -set -e - -# script_dir is the directory that contains THIS (inspect.sh) script, usually -# stored in the directory '.../bot' -script_dir=$(dirname $(realpath $BASH_SOURCE)) - -display_help() { - echo "usage: $0 [OPTIONS]" - echo " -h | --help - display this usage information" - echo " -r | --resume TGZ - inspect job saved in tarball path TGZ; note, we assume the path" - echo " to be something like JOB_DIR/previous_tmp/{build,tarball}_step/TARBALL.tgz" - echo " and thus determine JOB_DIR from the given path" - echo " [default: none]" - echo " -c | --command COMMAND - command to execute inside the container, in the prefix environment" - echo " -x | --http-proxy URL - provides URL for the environment variable http_proxy" - echo " -y | --https-proxy URL - provides URL for the environment variable https_proxy" -} - -resume_tgz= -http_proxy= -https_proxy= - -POSITIONAL_ARGS=() - -while [[ $# -gt 0 ]]; do - case ${1} in - -h|--help) - display_help - exit 0 - ;; - -r|--resume) - export resume_tgz="${2}" - shift 2 - ;; - -x|--http-proxy) - export http_proxy="${2}" - shift 2 - ;; - -y|--https-proxy) - export https_proxy="${2}" - shift 2 - ;; - -c|--command) - export run_in_prefix="${2}" - shift 2 - ;; - -*|--*) - echo "Error: Unknown option: ${1}" >&2 - exit 1 - ;; - *) # No more options - POSITIONAL_ARGS+=("${1}") # save positional arg - shift - ;; - esac -done - -set -- "${POSITIONAL_ARGS[@]}" - -# source utils.sh and cfg_files.sh -source ${script_dir}/../scripts/utils.sh -source ${script_dir}/../scripts/cfg_files.sh - -if [[ -z ${resume_tgz} ]]; then - echo_red "path to tarball for resuming build job is missing" - display_help - exit 1 -fi - -job_dir=$(dirname $(dirname $(dirname ${resume_tgz}))) - -if [[ -z ${job_dir} ]]; then - # job directory could be determined - echo_red "job directory could not be determined from '${resume_tgz}'" - display_help - exit 2 -fi - -# defaults -export JOB_CFG_FILE="${job_dir}/cfg/job.cfg" -HOST_ARCH=$(uname -m) - -# check if ${JOB_CFG_FILE} exists -if [[ ! -r "${JOB_CFG_FILE}" ]]; then - fatal_error "job config file (JOB_CFG_FILE=${JOB_CFG_FILE}) does not exist or not readable" -fi -echo "bot/inspect.sh: showing ${JOB_CFG_FILE} from software-layer side" -cat ${JOB_CFG_FILE} - -echo "bot/inspect.sh: obtaining configuration settings from '${JOB_CFG_FILE}'" -cfg_load ${JOB_CFG_FILE} - -# if http_proxy is defined in ${JOB_CFG_FILE} use it, if not use env var $http_proxy -HTTP_PROXY=$(cfg_get_value "site_config" "http_proxy") -HTTP_PROXY=${HTTP_PROXY:-${http_proxy}} -echo "bot/inspect.sh: HTTP_PROXY='${HTTP_PROXY}'" - -# if https_proxy is defined in ${JOB_CFG_FILE} use it, if not use env var $https_proxy -HTTPS_PROXY=$(cfg_get_value "site_config" "https_proxy") -HTTPS_PROXY=${HTTPS_PROXY:-${https_proxy}} -echo "bot/inspect.sh: HTTPS_PROXY='${HTTPS_PROXY}'" - -LOCAL_TMP=$(cfg_get_value "site_config" "local_tmp") -echo "bot/inspect.sh: LOCAL_TMP='${LOCAL_TMP}'" -# TODO should local_tmp be mandatory? --> then we check here and exit if it is not provided - -# check if path to copy build logs to is specified, so we can copy build logs for failing builds there -BUILD_LOGS_DIR=$(cfg_get_value "site_config" "build_logs_dir") -echo "bot/inspect.sh: BUILD_LOGS_DIR='${BUILD_LOGS_DIR}'" -# if $BUILD_LOGS_DIR is set, add it to $SINGULARITY_BIND so the path is available in the build container -if [[ ! -z ${BUILD_LOGS_DIR} ]]; then - mkdir -p ${BUILD_LOGS_DIR} - if [[ -z ${SINGULARITY_BIND} ]]; then - export SINGULARITY_BIND="${BUILD_LOGS_DIR}" - else - export SINGULARITY_BIND="${SINGULARITY_BIND},${BUILD_LOGS_DIR}" - fi -fi - -SINGULARITY_CACHEDIR=$(cfg_get_value "site_config" "container_cachedir") -echo "bot/inspect.sh: SINGULARITY_CACHEDIR='${SINGULARITY_CACHEDIR}'" -if [[ ! -z ${SINGULARITY_CACHEDIR} ]]; then - # make sure that separate directories are used for different CPU families - SINGULARITY_CACHEDIR=${SINGULARITY_CACHEDIR}/${HOST_ARCH} - export SINGULARITY_CACHEDIR -fi - -echo -n "setting \$STORAGE by replacing any var in '${LOCAL_TMP}' -> " -# replace any env variable in ${LOCAL_TMP} with its -# current value (e.g., a value that is local to the job) -STORAGE=$(envsubst <<< ${LOCAL_TMP}) -echo "'${STORAGE}'" - -# make sure ${STORAGE} exists -mkdir -p ${STORAGE} - -# make sure the base tmp storage is unique -JOB_STORAGE=$(mktemp --directory --tmpdir=${STORAGE} bot_job_tmp_XXX) -echo "bot/inspect.sh: created unique base tmp storage directory at ${JOB_STORAGE}" - -# obtain list of modules to be loaded -LOAD_MODULES=$(cfg_get_value "site_config" "load_modules") -echo "bot/inspect.sh: LOAD_MODULES='${LOAD_MODULES}'" - -# singularity/apptainer settings: CONTAINER, HOME, TMPDIR, BIND -CONTAINER=$(cfg_get_value "repository" "container") -echo "bot/inspect.sh: CONTAINER='${CONTAINER}'" -# instead of using ${PWD} as HOME in the container, we use the job directory -# to have access to output files of the job -export SINGULARITY_HOME="${job_dir}:/eessi_bot_job" -echo "bot/inspect.sh: SINGULARITY_HOME='${SINGULARITY_HOME}'" -export SINGULARITY_TMPDIR="${PWD}/singularity_tmpdir" -echo "bot/inspect.sh: SINGULARITY_TMPDIR='${SINGULARITY_TMPDIR}'" -mkdir -p ${SINGULARITY_TMPDIR} - -# load modules if LOAD_MODULES is not empty -if [[ ! -z ${LOAD_MODULES} ]]; then - for mod in $(echo ${LOAD_MODULES} | tr ',' '\n') - do - echo "bot/inspect.sh: loading module '${mod}'" - module load ${mod} - done -else - echo "bot/inspect.sh: no modules to be loaded" -fi - -# determine repository to be used from entry .repository in ${JOB_CFG_FILE} -REPOSITORY=$(cfg_get_value "repository" "repo_id") -echo "bot/inspect.sh: REPOSITORY='${REPOSITORY}'" -# TODO better to read this from tarball??? -EESSI_REPOS_CFG_DIR_OVERRIDE=$(cfg_get_value "repository" "repos_cfg_dir") -export EESSI_REPOS_CFG_DIR_OVERRIDE=${EESSI_REPOS_CFG_DIR_OVERRIDE:-${PWD}/cfg} -echo "bot/inspect.sh: EESSI_REPOS_CFG_DIR_OVERRIDE='${EESSI_REPOS_CFG_DIR_OVERRIDE}'" - -# determine EESSI version to be used from .repository.repo_version in ${JOB_CFG_FILE} -# here, just set & export EESSI_VERSION_OVERRIDE -# next script (eessi_container.sh) makes use of it via sourcing init scripts -# (e.g., init/eessi_defaults or init/minimal_eessi_env) -export EESSI_VERSION_OVERRIDE=$(cfg_get_value "repository" "repo_version") -echo "bot/inspect.sh: EESSI_VERSION_OVERRIDE='${EESSI_VERSION_OVERRIDE}'" - -# determine CVMFS repo to be used from .repository.repo_name in ${JOB_CFG_FILE} -# here, just set EESSI_CVMFS_REPO_OVERRIDE, a bit further down -# "source init/eessi_defaults" via sourcing init/minimal_eessi_env -export EESSI_CVMFS_REPO_OVERRIDE="/cvmfs/$(cfg_get_value 'repository' 'repo_name')${EESSI_DEV_PROJECT:+/$EESSI_DEV_PROJECT}" -echo "bot/inspect.sh: EESSI_CVMFS_REPO_OVERRIDE='${EESSI_CVMFS_REPO_OVERRIDE}'" - -# determine architecture to be used from entry .architecture in ${JOB_CFG_FILE} -# fallbacks: -# - ${CPU_TARGET} handed over from bot -# - left empty to let downstream script(s) determine subdir to be used -EESSI_SOFTWARE_SUBDIR_OVERRIDE=$(cfg_get_value "architecture" "software_subdir") -EESSI_SOFTWARE_SUBDIR_OVERRIDE=${EESSI_SOFTWARE_SUBDIR_OVERRIDE:-${CPU_TARGET}} -export EESSI_SOFTWARE_SUBDIR_OVERRIDE -echo "bot/inspect.sh: EESSI_SOFTWARE_SUBDIR_OVERRIDE='${EESSI_SOFTWARE_SUBDIR_OVERRIDE}'" - -# get EESSI_OS_TYPE from .architecture.os_type in ${JOB_CFG_FILE} (default: linux) -EESSI_OS_TYPE=$(cfg_get_value "architecture" "os_type") -export EESSI_OS_TYPE=${EESSI_OS_TYPE:-linux} -echo "bot/inspect.sh: EESSI_OS_TYPE='${EESSI_OS_TYPE}'" - -# prepare arguments to eessi_container.sh common to build and tarball steps -declare -a CMDLINE_ARGS=() -CMDLINE_ARGS+=("--verbose") -CMDLINE_ARGS+=("--access" "rw") -CMDLINE_ARGS+=("--mode" "run") -[[ ! -z ${CONTAINER} ]] && CMDLINE_ARGS+=("--container" "${CONTAINER}") -[[ ! -z ${HTTP_PROXY} ]] && CMDLINE_ARGS+=("--http-proxy" "${HTTP_PROXY}") -[[ ! -z ${HTTPS_PROXY} ]] && CMDLINE_ARGS+=("--https-proxy" "${HTTPS_PROXY}") -[[ ! -z ${REPOSITORY} ]] && CMDLINE_ARGS+=("--repository" "${REPOSITORY}") - -[[ ! -z ${resume_tgz} ]] && CMDLINE_ARGS+=("--resume" "${resume_tgz}") - -# create a directory for creating temporary data and scripts for the inspection -INSPECT_DIR=$(mktemp --directory --tmpdir=${PWD} inspect.XXX) -if [[ -z ${SINGULARITY_BIND} ]]; then - export SINGULARITY_BIND="${INSPECT_DIR}:/inspect_eessi_build_job" -else - export SINGULARITY_BIND="${SINGULARITY_BIND},${INSPECT_DIR}:/inspect_eessi_build_job" -fi - -# add arguments for temporary storage and storing a tarball of tmp -CMDLINE_ARGS+=("--save" "${INSPECT_DIR}") -CMDLINE_ARGS+=("--storage" "${JOB_STORAGE}") - -# # prepare arguments to install_software_layer.sh (specific to build step) -# declare -a INSTALL_SCRIPT_ARGS=() -# if [[ ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} =~ .*/generic$ ]]; then -# INSTALL_SCRIPT_ARGS+=("--generic") -# fi -# [[ ! -z ${BUILD_LOGS_DIR} ]] && INSTALL_SCRIPT_ARGS+=("--build-logs-dir" "${BUILD_LOGS_DIR}") - -# make sure some environment settings are available inside the shell started via -# startprefix -# TODO better use script from tarball??? -source ${script_dir}/../init/eessi_defaults - -if [ -z $EESSI_VERSION ]; then - echo "ERROR: \$EESSI_VERSION must be set!" >&2 - exit 1 -fi -EESSI_COMPAT_LAYER_DIR="${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/compat/linux/$(uname -m)" - -# NOTE The below requires access to the CVMFS repository. We could make a first -# test run with a container. For now we skip the test. -# if [ ! -d ${EESSI_COMPAT_LAYER_DIR} ]; then -# echo "ERROR: ${EESSI_COMPAT_LAYER_DIR} does not exist!" >&2 -# exit 1 -# fi - -# When we want to run a script with arguments, the next line is ensures to retain -# these arguments. -# INPUT=$(echo "$@") -mkdir -p ${INSPECT_DIR}/scripts -RESUME_SCRIPT=${INSPECT_DIR}/scripts/resume_env.sh -echo "bot/inspect.sh: creating script '${RESUME_SCRIPT}' to resume environment settings" - -cat << EOF > ${RESUME_SCRIPT} -#!${EESSI_COMPAT_LAYER_DIR}/bin/bash -echo "Sourcing '\$BASH_SOURCE' to init bot environment of build job" -EOF -if [ ! -z ${SLURM_JOB_ID} ]; then - # TODO do we need the value at all? if so which one: current or of the job to - # inspect? - echo "export CURRENT_SLURM_JOB_ID=${SLURM_JOB_ID}" >> ${RESUME_SCRIPT} -fi -if [ ! -z ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} ]; then - echo "export EESSI_SOFTWARE_SUBDIR_OVERRIDE=${EESSI_SOFTWARE_SUBDIR_OVERRIDE}" >> ${RESUME_SCRIPT} -fi -if [ ! -z ${EESSI_CVMFS_REPO_OVERRIDE} ]; then - echo "export EESSI_CVMFS_REPO_OVERRIDE=${EESSI_CVMFS_REPO_OVERRIDE}" >> ${RESUME_SCRIPT} -fi -if [ ! -z ${EESSI_VERSION_OVERRIDE} ]; then - echo "export EESSI_VERSION_OVERRIDE=${EESSI_VERSION_OVERRIDE}" >> ${RESUME_SCRIPT} -fi -if [ ! -z ${http_proxy} ]; then - echo "export http_proxy=${http_proxy}" >> ${RESUME_SCRIPT} -fi -if [ ! -z ${https_proxy} ]; then - echo "export https_proxy=${https_proxy}" >> ${RESUME_SCRIPT} -fi -cat << 'EOF' >> ${RESUME_SCRIPT} -TOPDIR=$(dirname $(realpath $BASH_SOURCE)) - -source ${TOPDIR}/scripts/utils.sh - -# honor $TMPDIR if it is already defined, use /tmp otherwise -if [ -z $TMPDIR ]; then - export WORKDIR=/tmp/$USER -else - export WORKDIR=$TMPDIR/$USER -fi - -TMPDIR=$(mktemp -d) - -echo ">> Setting up environment..." - -source $TOPDIR/init/minimal_eessi_env - -if [ -d $EESSI_CVMFS_REPO ]; then - echo_green "$EESSI_CVMFS_REPO available, OK!" -else - fatal_error "$EESSI_CVMFS_REPO is not available!" -fi - -# make sure we're in Prefix environment by checking $SHELL -if [[ ${SHELL} = ${EPREFIX}/bin/bash ]]; then - echo_green ">> It looks like we're in a Gentoo Prefix environment, good!" -else - fatal_error "Not running in Gentoo Prefix environment, run '${EPREFIX}/startprefix' first!" -fi - -# avoid that pyc files for EasyBuild are stored in EasyBuild installation directory -export PYTHONPYCACHEPREFIX=$TMPDIR/pycache - -DETECTION_PARAMETERS='' -GENERIC=0 -EB='eb' -if [[ "$EASYBUILD_OPTARCH" == "GENERIC" || "$EESSI_SOFTWARE_SUBDIR_OVERRIDE" == *"/generic" ]]; then - echo_yellow ">> GENERIC build requested, taking appropriate measures!" - DETECTION_PARAMETERS="$DETECTION_PARAMETERS --generic" - GENERIC=1 - export EASYBUILD_OPTARCH=GENERIC - EB='eb --optarch=GENERIC' -fi - -echo ">> Determining software subdirectory to use for current build host..." -if [ -z $EESSI_SOFTWARE_SUBDIR_OVERRIDE ]; then - export EESSI_SOFTWARE_SUBDIR_OVERRIDE=$(python3 $TOPDIR/eessi_software_subdir.py $DETECTION_PARAMETERS) - echo ">> Determined \$EESSI_SOFTWARE_SUBDIR_OVERRIDE via 'eessi_software_subdir.py $DETECTION_PARAMETERS' script" -else - echo ">> Picking up pre-defined \$EESSI_SOFTWARE_SUBDIR_OVERRIDE: ${EESSI_SOFTWARE_SUBDIR_OVERRIDE}" -fi - -# Set all the EESSI environment variables (respecting $EESSI_SOFTWARE_SUBDIR_OVERRIDE) -# $EESSI_SILENT - don't print any messages -# $EESSI_BASIC_ENV - give a basic set of environment variables -EESSI_SILENT=1 EESSI_BASIC_ENV=1 source $TOPDIR/init/eessi_environment_variables - -if [[ -z ${EESSI_SOFTWARE_SUBDIR} ]]; then - fatal_error "Failed to determine software subdirectory?!" -elif [[ "${EESSI_SOFTWARE_SUBDIR}" != "${EESSI_SOFTWARE_SUBDIR_OVERRIDE}" ]]; then - fatal_error "Values for EESSI_SOFTWARE_SUBDIR_OVERRIDE (${EESSI_SOFTWARE_SUBDIR_OVERRIDE}) and EESSI_SOFTWARE_SUBDIR (${EESSI_SOFTWARE_SUBDIR}) differ!" -else - echo_green ">> Using ${EESSI_SOFTWARE_SUBDIR} as software subdirectory!" -fi - -echo ">> Initializing Lmod..." -source $EPREFIX/usr/share/Lmod/init/bash -ml_version_out=$TMPDIR/ml.out -ml --version &> $ml_version_out -if [[ $? -eq 0 ]]; then - echo_green ">> Found Lmod ${LMOD_VERSION}" -else - fatal_error "Failed to initialize Lmod?! (see output in ${ml_version_out}" -fi - -echo ">> Configuring EasyBuild..." -source $TOPDIR/configure_easybuild - -echo ">> Setting up \$MODULEPATH..." -# make sure no modules are loaded -module --force purge -# ignore current $MODULEPATH entirely -module unuse $MODULEPATH -module use $EASYBUILD_INSTALLPATH/modules/all -if [[ -z ${MODULEPATH} ]]; then - fatal_error "Failed to set up \$MODULEPATH?!" -else - echo_green ">> MODULEPATH set up: ${MODULEPATH}" -fi - -echo -echo_green "Build environment set up with install path ${EASYBUILD_INSTALLPATH}." -echo -echo "The build job can be inspected with the following resources:" -echo " - job directory is $HOME (\$HOME), check for slurm-*.out file" -echo " - temporary data of the job is available at /tmp" -echo " - note, the prefix $EESSI_PREFIX is writable" -echo -echo "You may want to load an EasyBuild module. The inspect.sh script does not load" -echo "that automatically, because multiple versions might have been used by the job." -echo "Choose an EasyBuild version (see installed versions with 'module avail EasyBuild')" -echo "and simply run" -echo -echo "module load EasyBuild/_VERSION_" -echo -echo "Replace _VERSION_ with the version you want to use." -echo - -EOF -chmod u+x ${RESUME_SCRIPT} - -# try to map it into the container's $HOME/.profile instead -# TODO check if script already exists, if so change its name and source it at the beginning of the RESUME_SCRIPT -if [[ -z ${SINGULARITY_BIND} ]]; then - export SINGULARITY_BIND="${RESUME_SCRIPT}:/eessi_bot_job/.profile" -else - export SINGULARITY_BIND="${SINGULARITY_BIND},${RESUME_SCRIPT}:/eessi_bot_job/.profile" -fi - -echo "Executing command to start interactive session to inspect build job:" -# TODO possibly add information on how to init session after the prefix is -# entered, initialization consists of -# - environment variable settings (see 'run_in_compat_layer_env.sh') -# - setup steps run in 'EESSI-install-software.sh' -# These initializations are combined into a single script that is executed when -# the shell in startprefix is started. We set the env variable BASH_ENV here. -if [[ -z ${run_in_prefix} ]]; then - echo "${script_dir}/../eessi_container.sh ${CMDLINE_ARGS[@]}" - echo " -- ${EESSI_COMPAT_LAYER_DIR}/startprefix" - ${script_dir}/../eessi_container.sh "${CMDLINE_ARGS[@]}" \ - -- ${EESSI_COMPAT_LAYER_DIR}/startprefix -else - echo "${script_dir}/../eessi_container.sh ${CMDLINE_ARGS[@]}" - echo " -- ${EESSI_COMPAT_LAYER_DIR}/startprefix <<< ${run_in_prefix}" - ${script_dir}/../eessi_container.sh "${CMDLINE_ARGS[@]}" \ - -- ${EESSI_COMPAT_LAYER_DIR}/startprefix <<< ${run_in_prefix} -fi - -exit 0 diff --git a/bot/test.sh b/bot/test.sh deleted file mode 100755 index b615be0020..0000000000 --- a/bot/test.sh +++ /dev/null @@ -1,257 +0,0 @@ -#!/usr/bin/env bash -# -# script to run tests or the test suite for the whole EESSI software layer or -# just what has been built in a job. Intended use is that it is called -# at the end of a (batch) job running on a compute node. -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Thomas Roeblitz (@trz42) -# author: Caspar van Leeuwen (@casparvl) -# -# license: GPLv2 -# - -# ASSUMPTIONs: -# + assumption for the build step (as run through bot/build.sh which is provided -# in this repository too) -# - working directory has been prepared by the bot with a checkout of a -# pull request (OR by some other means) -# - the working directory contains a directory 'cfg' where the main config -# file 'job.cfg' has been deposited -# - the directory may contain any additional files referenced in job.cfg -# + assumptions for the test step -# - temporary storage is still available -# example -# Using /localscratch/9640860/NESSI/eessi.x765Dd8mFh as tmp directory (to resume session add '--resume /localscratch/9640860/NESSI/eessi.x765Dd8mFh'). -# - run test-suite.sh inside build container using tmp storage from build step -# plus possibly additional settings (repo, etc.) -# - needed setup steps may be similar to bot/inspect.sh (PR#317) - -# stop as soon as something fails -set -e - -# source utils.sh and cfg_files.sh -source scripts/utils.sh -source scripts/cfg_files.sh - -# defaults -export JOB_CFG_FILE="${JOB_CFG_FILE_OVERRIDE:=./cfg/job.cfg}" -HOST_ARCH=$(uname -m) - -# check if ${JOB_CFG_FILE} exists -if [[ ! -r "${JOB_CFG_FILE}" ]]; then - fatal_error "job config file (JOB_CFG_FILE=${JOB_CFG_FILE}) does not exist or not readable" -fi -echo "bot/test.sh: showing ${JOB_CFG_FILE} from software-layer side" -cat ${JOB_CFG_FILE} - -echo "bot/test.sh: obtaining configuration settings from '${JOB_CFG_FILE}'" -cfg_load ${JOB_CFG_FILE} - -# if http_proxy is defined in ${JOB_CFG_FILE} use it, if not use env var $http_proxy -HTTP_PROXY=$(cfg_get_value "site_config" "http_proxy") -HTTP_PROXY=${HTTP_PROXY:-${http_proxy}} -echo "bot/test.sh: HTTP_PROXY='${HTTP_PROXY}'" - -# if https_proxy is defined in ${JOB_CFG_FILE} use it, if not use env var $https_proxy -HTTPS_PROXY=$(cfg_get_value "site_config" "https_proxy") -HTTPS_PROXY=${HTTPS_PROXY:-${https_proxy}} -echo "bot/test.sh: HTTPS_PROXY='${HTTPS_PROXY}'" - -LOCAL_TMP=$(cfg_get_value "site_config" "local_tmp") -echo "bot/test.sh: LOCAL_TMP='${LOCAL_TMP}'" -# TODO should local_tmp be mandatory? --> then we check here and exit if it is not provided - -# check if path to copy build logs to is specified, so we can copy build logs for failing builds there -BUILD_LOGS_DIR=$(cfg_get_value "site_config" "build_logs_dir") -echo "bot/test.sh: BUILD_LOGS_DIR='${BUILD_LOGS_DIR}'" -# if $BUILD_LOGS_DIR is set, add it to $SINGULARITY_BIND so the path is available in the build container -if [[ ! -z ${BUILD_LOGS_DIR} ]]; then - mkdir -p ${BUILD_LOGS_DIR} - if [[ -z ${SINGULARITY_BIND} ]]; then - export SINGULARITY_BIND="${BUILD_LOGS_DIR}" - else - export SINGULARITY_BIND="${SINGULARITY_BIND},${BUILD_LOGS_DIR}" - fi -fi - -# check if path to directory on shared filesystem is specified, -# and use it as location for source tarballs used by EasyBuild if so -SHARED_FS_PATH=$(cfg_get_value "site_config" "shared_fs_path") -echo "bot/test.sh: SHARED_FS_PATH='${SHARED_FS_PATH}'" -# if $SHARED_FS_PATH is set, add it to $SINGULARITY_BIND so the path is available in the build container -if [[ ! -z ${SHARED_FS_PATH} ]]; then - mkdir -p ${SHARED_FS_PATH} - if [[ -z ${SINGULARITY_BIND} ]]; then - export SINGULARITY_BIND="${SHARED_FS_PATH}" - else - export SINGULARITY_BIND="${SINGULARITY_BIND},${SHARED_FS_PATH}" - fi -fi - -SINGULARITY_CACHEDIR=$(cfg_get_value "site_config" "container_cachedir") -echo "bot/test.sh: SINGULARITY_CACHEDIR='${SINGULARITY_CACHEDIR}'" -if [[ ! -z ${SINGULARITY_CACHEDIR} ]]; then - # make sure that separate directories are used for different CPU families - SINGULARITY_CACHEDIR=${SINGULARITY_CACHEDIR}/${HOST_ARCH} - export SINGULARITY_CACHEDIR -fi - -# try to determine tmp directory from build job -RESUME_DIR=$(grep 'Using .* as tmp directory' slurm-${SLURM_JOBID}.out | head -1 | awk '{print $2}') - -if [[ -z ${RESUME_DIR} ]]; then - RESUME_TGZ=${PWD}/previous_tmp/build_step/$(ls previous_tmp/build_step) - if [[ -z ${RESUME_TGZ} ]]; then - echo "bot/test.sh: no information about tmp directory and tarball of build step; --> giving up" - exit 2 - fi -fi - -echo -n "setting \$STORAGE by replacing any var in '${LOCAL_TMP}' -> " -# replace any env variable in ${LOCAL_TMP} with its -# current value (e.g., a value that is local to the job) -STORAGE=$(envsubst <<< ${LOCAL_TMP}) -echo "'${STORAGE}'" - -# make sure ${STORAGE} exists -mkdir -p ${STORAGE} - -# make sure the base tmp storage is unique -JOB_STORAGE=$(mktemp --directory --tmpdir=${STORAGE} bot_job_tmp_XXX) -echo "bot/test.sh: created unique base tmp storage directory at ${JOB_STORAGE}" - -# obtain list of modules to be loaded -LOAD_MODULES=$(cfg_get_value "site_config" "load_modules") -echo "bot/test.sh: LOAD_MODULES='${LOAD_MODULES}'" - -# singularity/apptainer settings: CONTAINER, HOME, TMPDIR, BIND -CONTAINER=$(cfg_get_value "repository" "container") -export SINGULARITY_HOME="${PWD}:/eessi_bot_job" -export SINGULARITY_TMPDIR="${JOB_STORAGE:-${PWD}}/singularity_tmpdir" -mkdir -p ${SINGULARITY_TMPDIR} - -# load modules if LOAD_MODULES is not empty -if [[ ! -z ${LOAD_MODULES} ]]; then - IFS=',' read -r -a modules <<< "$(echo "${LOAD_MODULES}")" - for mod in "${modules[@]}"; - do - echo "bot/test.sh: loading module '${mod}'" - module load ${mod} - done -else - echo "bot/test.sh: no modules to be loaded" -fi - -# determine repository to be used from entry .repository in ${JOB_CFG_FILE} -REPOSITORY=$(cfg_get_value "repository" "repo_id") -EESSI_REPOS_CFG_DIR_OVERRIDE=$(cfg_get_value "repository" "repos_cfg_dir") -export EESSI_REPOS_CFG_DIR_OVERRIDE=${EESSI_REPOS_CFG_DIR_OVERRIDE:-${PWD}/cfg} -echo "bot/test.sh: EESSI_REPOS_CFG_DIR_OVERRIDE='${EESSI_REPOS_CFG_DIR_OVERRIDE}'" - -# determine pilot version to be used from .repository.repo_version in ${JOB_CFG_FILE} -# here, just set & export EESSI_PILOT_VERSION_OVERRIDE -# next script (eessi_container.sh) makes use of it via sourcing init scripts -# (e.g., init/eessi_defaults or init/minimal_eessi_env) -export EESSI_PILOT_VERSION_OVERRIDE=$(cfg_get_value "repository" "repo_version") -echo "bot/test.sh: EESSI_PILOT_VERSION_OVERRIDE='${EESSI_PILOT_VERSION_OVERRIDE}'" - -# determine CVMFS repo to be used from .repository.repo_name in ${JOB_CFG_FILE} -# here, just set EESSI_CVMFS_REPO_OVERRIDE, a bit further down -# "source init/eessi_defaults" via sourcing init/minimal_eessi_env -export EESSI_CVMFS_REPO_OVERRIDE=/cvmfs/$(cfg_get_value "repository" "repo_name") -echo "bot/test.sh: EESSI_CVMFS_REPO_OVERRIDE='${EESSI_CVMFS_REPO_OVERRIDE}'" - -# determine architecture to be used from entry .architecture in ${JOB_CFG_FILE} -# fallbacks: -# - ${CPU_TARGET} handed over from bot -# - left empty to let downstream script(s) determine subdir to be used -EESSI_SOFTWARE_SUBDIR_OVERRIDE=$(cfg_get_value "architecture" "software_subdir") -EESSI_SOFTWARE_SUBDIR_OVERRIDE=${EESSI_SOFTWARE_SUBDIR_OVERRIDE:-${CPU_TARGET}} -export EESSI_SOFTWARE_SUBDIR_OVERRIDE -echo "bot/test.sh: EESSI_SOFTWARE_SUBDIR_OVERRIDE='${EESSI_SOFTWARE_SUBDIR_OVERRIDE}'" - -# determine accelerator target (if any) from .architecture in ${JOB_CFG_FILE} -export EESSI_ACCELERATOR_TARGET=$(cfg_get_value "architecture" "accelerator") -echo "bot/test.sh: EESSI_ACCELERATOR_TARGET='${EESSI_ACCELERATOR_TARGET}'" - -# get EESSI_OS_TYPE from .architecture.os_type in ${JOB_CFG_FILE} (default: linux) -EESSI_OS_TYPE=$(cfg_get_value "architecture" "os_type") -export EESSI_OS_TYPE=${EESSI_OS_TYPE:-linux} -echo "bot/test.sh: EESSI_OS_TYPE='${EESSI_OS_TYPE}'" - -# prepare arguments to eessi_container.sh common to build and tarball steps -declare -a COMMON_ARGS=() -COMMON_ARGS+=("--verbose") -COMMON_ARGS+=("--access" "ro") -COMMON_ARGS+=("--mode" "run") -[[ ! -z ${CONTAINER} ]] && COMMON_ARGS+=("--container" "${CONTAINER}") -[[ ! -z ${HTTP_PROXY} ]] && COMMON_ARGS+=("--http-proxy" "${HTTP_PROXY}") -[[ ! -z ${HTTPS_PROXY} ]] && COMMON_ARGS+=("--https-proxy" "${HTTPS_PROXY}") -[[ ! -z ${REPOSITORY} ]] && COMMON_ARGS+=("--repository" "${REPOSITORY}") - -# pass through '--contain' to avoid leaking in scripts into the container session -# note, --pass-through can be used multiple times if needed -COMMON_ARGS+=("--pass-through" "--contain") - -# make sure to use the same parent dir for storing tarballs of tmp -PREVIOUS_TMP_DIR=${PWD}/previous_tmp - -# prepare directory to store tarball of tmp for test step -TARBALL_TMP_TEST_STEP_DIR=${PREVIOUS_TMP_DIR}/test_step -mkdir -p ${TARBALL_TMP_TEST_STEP_DIR} - -# prepare arguments to eessi_container.sh specific to test step -declare -a TEST_STEP_ARGS=() -TEST_STEP_ARGS+=("--save" "${TARBALL_TMP_TEST_STEP_DIR}") - -if [[ -z ${RESUME_DIR} ]]; then - TEST_STEP_ARGS+=("--storage" "${STORAGE}") - TEST_STEP_ARGS+=("--resume" "${RESUME_TGZ}") -else - TEST_STEP_ARGS+=("--resume" "${RESUME_DIR}") -fi -# Bind mount /sys/fs/cgroup so that we can determine the amount of memory available in our cgroup for -# Reframe configuration -TEST_STEP_ARGS+=("--extra-bind-paths" "/sys/fs/cgroup:/hostsys/fs/cgroup:ro") - -# add options required to handle NVIDIA support -if command_exists "nvidia-smi"; then - # Accept that this may fail - set +e - nvidia-smi --version - ec=$? - set -e - if [ ${ec} -eq 0 ]; then - echo "Command 'nvidia-smi' found, using available GPU" - TEST_STEP_ARGS+=("--nvidia" "run") - else - echo "Warning: command 'nvidia-smi' found, but 'nvidia-smi --version' did not run succesfully." - echo "This script now assumes this is NOT a GPU node." - echo "If, and only if, the current node actually does contain Nvidia GPUs, this should be considered an error." - fi -fi - -# prepare arguments to test_suite.sh (specific to test step) -declare -a TEST_SUITE_ARGS=() -if [[ ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} =~ .*/generic$ ]]; then - TEST_SUITE_ARGS+=("--generic") -fi -if [[ ${SHARED_FS_PATH} ]]; then - TEST_SUITE_ARGS+=("--shared-fs-path" "${SHARED_FS_PATH}") -fi -# [[ ! -z ${BUILD_LOGS_DIR} ]] && TEST_SUITE_ARGS+=("--build-logs-dir" "${BUILD_LOGS_DIR}") -# [[ ! -z ${SHARED_FS_PATH} ]] && TEST_SUITE_ARGS+=("--shared-fs-path" "${SHARED_FS_PATH}") - -# create tmp file for output of build step -test_outerr=$(mktemp test.outerr.XXXX) - -echo "Executing command to test software:" -echo "./eessi_container.sh ${COMMON_ARGS[@]} ${TEST_STEP_ARGS[@]}" -echo " -- ./run_tests.sh \"${TEST_SUITE_ARGS[@]}\" \"$@\" 2>&1 | tee -a ${test_outerr}" -./eessi_container.sh "${COMMON_ARGS[@]}" "${TEST_STEP_ARGS[@]}" \ - -- ./run_tests.sh "${TEST_SUITE_ARGS[@]}" "$@" 2>&1 | tee -a ${test_outerr} - -exit 0 diff --git a/check_missing_installations.sh b/check_missing_installations.sh deleted file mode 100755 index 79f6acc733..0000000000 --- a/check_missing_installations.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash -# -# Script to check for missing installations in EESSI software stack -# -# author: Kenneth Hoste (@boegel) -# author: Thomas Roeblitz (@trz42) -# -# license: GPLv2 -# - -TOPDIR=$(dirname $(realpath $0)) - -if [ "$#" -eq 1 ]; then - true -elif [ "$#" -eq 2 ]; then - echo "Using $2 to give create exceptions for PR filtering of easystack" - # Find lines that are added and use from-pr, make them unique, grab the - # PR numbers and use them to construct something we can use within awk - pr_exceptions=$(grep ^+ $2 | grep from-pr | uniq | awk '{print $3}' | xargs -i echo " || /'{}'/") -else - echo "ERROR: Usage: $0 ()" >&2 - exit 1 -fi -easystack=$1 - -LOCAL_TMPDIR=$(mktemp -d) - -source $TOPDIR/scripts/utils.sh - -source $TOPDIR/configure_easybuild - -echo ">> Active EasyBuild configuration when checking for missing installations:" -${EB:-eb} --show-config - -echo ">> Checking for missing installations in ${EASYBUILD_INSTALLPATH}..." -eb_missing_out=$LOCAL_TMPDIR/eb_missing.out -${EB:-eb} --easystack ${easystack} --missing 2>&1 | tee ${eb_missing_out} -exit_code=${PIPESTATUS[0]} - -ok_msg="Command 'eb --missing ...' succeeded, analysing output..." -fail_msg="Command 'eb --missing ...' failed, check log '${eb_missing_out}'" - -check_exit_code ${exit_code} "${ok_msg}" "${fail_msg}" - -# the above assesses the installed software for each easyconfig provided in -# the easystack file and then print messages such as -# `No missing modules!` -# or -# `2 out of 3 required modules missing:` -# depending on the result of the assessment. Hence, we need to check if the -# output does not contain any line with ` required modules missing:` - -grep " required modules missing:" ${eb_missing_out} > /dev/null -exit_code=$? - -# if grep returns 1 (` required modules missing:` was NOT found), we set -# MODULES_MISSING to 0, otherwise (it was found or another error) we set it to 1 -[[ ${exit_code} -eq 1 ]] && MODULES_MISSING=0 || MODULES_MISSING=1 -ok_msg="No missing installations, party time!" -fail_msg="On no, some installations are still missing, how did that happen?!" -check_exit_code ${MODULES_MISSING} "${ok_msg}" "${fail_msg}" diff --git a/configure_easybuild b/configure_easybuild deleted file mode 100644 index 3b6d40cd96..0000000000 --- a/configure_easybuild +++ /dev/null @@ -1,65 +0,0 @@ -# if $WORKDIR is not defined, use a local temporary directory -if [ -z ${WORKDIR} ]; then - WORKDIR=$(mktemp -d) -fi - -export EASYBUILD_PREFIX=${WORKDIR}/easybuild -export EASYBUILD_INSTALLPATH=${EESSI_PREFIX}/software/${EESSI_OS_TYPE}/${EESSI_SOFTWARE_SUBDIR} -export EASYBUILD_SOURCEPATH=${WORKDIR}/easybuild/sources:${EESSI_SOURCEPATH} - -# take into account accelerator target (if specified via $EESSI_ACCELERATOR_TARGET) -if [ ! -z ${EESSI_ACCELERATOR_TARGET} ]; then - if [[ "${EESSI_ACCELERATOR_TARGET}" =~ ^nvidia/cc[0-9][0-9]$ ]]; then - # tweak path to installation directories used by EasyBuild - export EASYBUILD_INSTALLPATH=${EASYBUILD_INSTALLPATH}/accel/${EESSI_ACCELERATOR_TARGET} - # nvidia/cc80 should result in setting $EASYBUILD_CUDA_COMPUTE_CAPABILITIES to '8.0' - export EASYBUILD_CUDA_COMPUTE_CAPABILITIES=$(echo ${EESSI_ACCELERATOR_TARGET} | cut -f2 -d/ | sed 's/^cc\([0-9]\)\([0-9]\)/\1.\2/g') - else - fatal_error "Incorrect value for \$EESSI_ACCELERATOR_TARGET: ${EESSI_ACCELERATOR_TARGET}" - fi -else - echo_yellow "(configure_easybuild) \$EESSI_ACCELERATOR_TARGET not defined" -fi - -# just ignore OS dependencies for now, see https://github.com/easybuilders/easybuild-framework/issues/3430 -export EASYBUILD_IGNORE_OSDEPS=1 - -export EASYBUILD_SYSROOT=${EPREFIX} - -export EASYBUILD_DEBUG=1 -export EASYBUILD_TRACE=1 -export EASYBUILD_ZIP_LOGS=bzip2 - -export EASYBUILD_RPATH=1 -export EASYBUILD_FILTER_ENV_VARS=LD_LIBRARY_PATH -export EASYBUILD_READ_ONLY_INSTALLDIR=1 - -# assume that eb_hooks.py is located in same directory as this script (configure_easybuild) -TOPDIR=$(dirname $(realpath $BASH_SOURCE)) -export EASYBUILD_HOOKS=$(realpath ${TOPDIR}/eb_hooks.py) -# make sure hooks are available, so we can produce a clear error message -if [ ! -f $EASYBUILD_HOOKS ]; then - fatal_error "$EASYBUILD_HOOKS does not exist!" -fi - -# note: filtering Bison may break some installations, like Qt5 (see https://github.com/EESSI/software-layer/issues/49) -# filtering pkg-config breaks R-bundle-Bioconductor installation (see also https://github.com/easybuilders/easybuild-easyconfigs/pull/11104) -DEPS_TO_FILTER=Autoconf,Automake,Autotools,binutils,bzip2,DBus,flex,gettext,gperf,help2man,intltool,libreadline,libtool,M4,makeinfo,ncurses,util-linux,XZ,zlib -# For aarch64 we need to also filter out Yasm. -# See https://github.com/easybuilders/easybuild-easyconfigs/issues/11190 -if [[ "$EESSI_CPU_FAMILY" == "aarch64" ]]; then - DEPS_TO_FILTER="${DEPS_TO_FILTER},Yasm" -fi - -# Version 23.06 of EESSI ships PSM2 in the compat layer, so we can filter this out while retaining support for OFA fabric -# (longer term this is probably not the right move as PSM2 should be configured with accelerator support, hence the restricted version) -if [[ "$EESSI_VERSION" == "2023.06" ]]; then - DEPS_TO_FILTER="${DEPS_TO_FILTER},PSM2" -fi - -export EASYBUILD_FILTER_DEPS=$DEPS_TO_FILTER - -export EASYBUILD_MODULE_EXTENSIONS=1 - -# need to enable use of experimental features, since we're using easystack files -export EASYBUILD_EXPERIMENTAL=1 diff --git a/create_directory_tarballs.sh b/create_directory_tarballs.sh deleted file mode 100755 index 0270719a73..0000000000 --- a/create_directory_tarballs.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -set -eo pipefail - -if [ $# -ne 1 ]; then - echo "Usage: $0 " >&2 - exit 1 -fi - -version=$1 - -SOFTWARE_LAYER_TARBALL_URL="https://github.com/EESSI/software-layer/tarball/${version}-software.eessi.io" - -TOPDIR=$(dirname $(realpath $0)) - -source $TOPDIR/scripts/utils.sh - -# Check if the EESSI version number encoded in the filename -# is valid, i.e. matches the format YYYY.DD -if ! echo "${version}" | egrep -q '^20[0-9][0-9]\.(0[0-9]|1[0-2])$' -then - fatal_error "${version} is not a valid EESSI version." -fi - -# Create tarball of init directory -tartmp=$(mktemp -t -d init.XXXXX) -mkdir "${tartmp}/${version}" -tarname="eessi-${version}-init-$(date +%s).tar.gz" -curl -Ls ${SOFTWARE_LAYER_TARBALL_URL} | tar xzf - -C "${tartmp}/${version}" --strip-components=1 --no-wildcards-match-slash --wildcards '*/init/' -source "${tartmp}/${version}/init/minimal_eessi_env" -if [ "${EESSI_VERSION}" != "${version}" ] -then - fatal_error "Specified version ${version} does not match version ${EESSI_VERSION} in the init files!" -fi -tar czf "${tarname}" -C "${tartmp}" "${version}" -rm -rf "${tartmp}" - -echo_green "Done! Created tarball ${tarname}." - -# Create tarball of scripts directory -# Version check has already been performed and would have caused script to exit at this point in case of problems -tartmp=$(mktemp -t -d scripts.XXXXX) -mkdir "${tartmp}/${version}" -tarname="eessi-${version}-scripts-$(date +%s).tar.gz" -curl -Ls ${SOFTWARE_LAYER_TARBALL_URL} | tar xzf - -C "${tartmp}/${version}" --strip-components=1 --no-wildcards-match-slash --wildcards '*/scripts/' -tar czf "${tarname}" -C "${tartmp}" "${version}" -rm -rf "${tartmp}" - -echo_green "Done! Created tarball ${tarname}." diff --git a/create_lmodrc.py b/create_lmodrc.py deleted file mode 100755 index 1720b762f0..0000000000 --- a/create_lmodrc.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 -# -# Create lmodrc.lua configuration file for Lmod. -# -import os -import sys - -DOT_LMOD = '.lmod' - -# LMOD_RC file is the place to define properties, see https://lmod.readthedocs.io/en/latest/145_properties.html -TEMPLATE_LMOD_RC = """propT = { -} -scDescriptT = { - { - ["dir"] = "%(prefix)s/%(dot_lmod)s/cache", - ["timestamp"] = "%(prefix)s/%(dot_lmod)s/cache/timestamp", - }, -} -""" - - -def error(msg): - sys.stderr.write("ERROR: %s\n" % msg) - sys.exit(1) - - -if len(sys.argv) != 2: - error("Usage: %s " % sys.argv[0]) - -prefix = sys.argv[1] - -if not os.path.exists(prefix): - error("Prefix directory %s does not exist!" % prefix) - -lmodrc_path = os.path.join(prefix, DOT_LMOD, 'lmodrc.lua') -# Lmod itself doesn't care about the accelerator subdir so remove this duplication from -# the target path (if it exists) -accel_subdir = os.getenv("EESSI_ACCELERATOR_TARGET") -if accel_subdir: - lmodrc_path = lmodrc_path.replace("/accel/%s" % accel_subdir, '') - -lmodrc_txt = TEMPLATE_LMOD_RC % { - 'dot_lmod': DOT_LMOD, - 'prefix': prefix, -} -try: - os.makedirs(os.path.dirname(lmodrc_path), exist_ok=True) - with open(lmodrc_path, 'w') as fp: - fp.write(lmodrc_txt) - -except (IOError, OSError) as err: - error("Failed to create %s: %s" % (lmodrc_path, err)) - -print(lmodrc_path) diff --git a/create_lmodsitepackage.py b/create_lmodsitepackage.py deleted file mode 100755 index f3d11aebe0..0000000000 --- a/create_lmodsitepackage.py +++ /dev/null @@ -1,307 +0,0 @@ -#!/usr/bin/env python3 -# -# Create SitePackage.lua configuration file for Lmod. -# -import os -import sys -from stat import S_IREAD, S_IWRITE, S_IRGRP, S_IWGRP, S_IROTH - -DOT_LMOD = '.lmod' - -hook_prologue = """require("strict") -local hook = require("Hook") -local open = io.open - -""" - -hook_txt = """ -local function read_file(path) - local file = open(path, "rb") -- r read mode and b binary mode - if not file then return nil end - local content = file:read "*a" -- *a or *all reads the whole file - file:close() - return content -end - -local function from_eessi_prefix(t) - -- eessi_prefix is the prefix with official EESSI modules - -- e.g. /cvmfs/software.eessi.io/versions/2023.06 - local eessi_prefix = os.getenv("EESSI_PREFIX") - - -- If EESSI_PREFIX wasn't defined, we cannot check if this module was from the EESSI environment - -- In that case, we assume it isn't, otherwise EESSI_PREFIX would (probably) have been set - if eessi_prefix == nil then - return false - else - -- NOTE: exact paths for site so may need to be updated later. - -- See https://github.com/EESSI/software-layer/pull/371 - - -- eessi_prefix_host_injections is the prefix with site-extensions (i.e. additional modules) - -- to the official EESSI modules, e.g. /cvmfs/software.eessi.io/host_injections/2023.06 - local eessi_prefix_host_injections = string.gsub(eessi_prefix, 'versions', 'host_injections') - - -- Check if the full modulepath starts with the eessi_prefix_* - return string.find(t.fn, "^" .. eessi_prefix) ~= nil or string.find(t.fn, "^" .. eessi_prefix_host_injections) ~= nil - end -end - -local function load_site_specific_hooks() - -- This function will be run after the EESSI hooks are registered - -- It will load a local SitePackage.lua that is architecture independent (if it exists) from e.g. - -- /cvmfs/software.eessi.io/host_injections/2023.06/.lmod/SitePackage.lua - -- That can define a new hook - -- - -- function site_specific_load_hook(t) - -- - -- end - -- - -- And the either append to the existing hook: - -- - -- local function final_load_hook(t) - -- eessi_load_hook(t) - -- site_specific_load_hook(t) - -- end - -- - -- Over overwrite the EESSI hook entirely: - -- - -- hook.register("load", final_load_hook) - -- - -- Note that the appending procedure can be simplified once we have an lmod >= 8.7.36 - -- See https://github.com/TACC/Lmod/pull/696#issuecomment-1998765722 - -- - -- Subsequently, this function will look for an architecture-specific SitePackage.lua, e.g. from - -- /cvmfs/software.eessi.io/host_injections/2023.06/software/linux/x86_64/amd/zen2/.lmod/SitePackage.lua - -- This can then register an additional hook, e.g. - -- - -- function arch_specific_load_hook(t) - -- - -- end - -- - -- local function final_load_hook(t) - -- eessi_load_hook(t) - -- site_specific_load_hook(t) - -- arch_specific_load_hook(t) - -- end - -- - -- hook.register("load", final_load_hook) - -- - -- Again, the host site could also decide to overwrite by simply doing - -- - -- hook.register("load", arch_specific_load_hook) - - -- get path to to architecture independent SitePackage.lua - local prefixHostInjections = string.gsub(os.getenv('EESSI_PREFIX') or "", 'versions', 'host_injections') - local hostSitePackage = prefixHostInjections .. "/.lmod/SitePackage.lua" - - -- If the file exists, run it - if isFile(hostSitePackage) then - dofile(hostSitePackage) - end - - -- build the full architecture specific path in host_injections - local archHostInjections = string.gsub(os.getenv('EESSI_SOFTWARE_PATH') or "", 'versions', 'host_injections') - local archSitePackage = archHostInjections .. "/.lmod/SitePackage.lua" - - -- If the file exists, run it - if isFile(archSitePackage) then - dofile(archSitePackage) - end - -end - - -local function eessi_cuda_and_libraries_enabled_load_hook(t) - local frameStk = require("FrameStk"):singleton() - local mt = frameStk:mt() - local simpleName = string.match(t.modFullName, "(.-)/") - local packagesList = { ["CUDA"] = true, ["cuDNN"] = true } - -- If we try to load any of the modules in packagesList, we check if the - -- full package was installed on the host in host_injections. - -- This is required for end users to build additional software that depends - -- on the package. If the full SDK isn't present, refuse - -- to load the module and print an informative message on how to set up GPU support for EESSI - local refer_to_docs = "For more information on how to do this, see https://www.eessi.io/docs/site_specific_config/gpu/.\\n" - if packagesList[simpleName] then - -- simpleName is a module in packagesList - -- get the full host_injections path - local hostInjections = string.gsub(os.getenv('EESSI_SOFTWARE_PATH') or "", 'versions', 'host_injections') - - -- build final path where the software should be installed - local packageEasyBuildDir = hostInjections .. "/software/" .. t.modFullName .. "/easybuild" - local packageDirExists = isDir(packageEasyBuildDir) - if not packageDirExists then - local advice = "but while the module file exists, the actual software is not entirely shipped with EESSI " - advice = advice .. "due to licencing. You will need to install a full copy of the " .. simpleName .. " package where EESSI " - advice = advice .. "can find it.\\n" - advice = advice .. refer_to_docs - LmodError("\\nYou requested to load ", simpleName, " ", advice) - end - end - -- when loading CUDA (and cu*) enabled modules check if the necessary driver libraries are accessible to the EESSI linker, - -- otherwise, refuse to load the requested module and print error message - local checkGpu = mt:haveProperty(simpleName,"arch","gpu") - local overrideGpuCheck = os.getenv("EESSI_OVERRIDE_GPU_CHECK") - if checkGpu and (overrideGpuCheck == nil) then - local arch = os.getenv("EESSI_CPU_FAMILY") or "" - local cvmfs_repo = os.getenv("EESSI_CVMFS_REPO") or "" - local cudaVersionFile = cvmfs_repo .. "/host_injections/nvidia/" .. arch .. "/latest/cuda_version.txt" - local cudaDriverFile = cvmfs_repo .. "/host_injections/nvidia/" .. arch .. "/latest/libcuda.so" - local cudaDriverExists = isFile(cudaDriverFile) - local singularityCudaExists = isFile("/.singularity.d/libs/libcuda.so") - if not (cudaDriverExists or singularityCudaExists) then - local advice = "which relies on the CUDA runtime environment and driver libraries. " - advice = advice .. "In order to be able to use the module, you will need " - advice = advice .. "to make sure EESSI can find the GPU driver libraries on your host system. You can " - advice = advice .. "override this check by setting the environment variable EESSI_OVERRIDE_GPU_CHECK but " - advice = advice .. "the loaded application will not be able to execute on your system.\\n" - advice = advice .. refer_to_docs - LmodError("\\nYou requested to load ", simpleName, " ", advice) - else - -- CUDA driver exists, now we check its version to see if an update is needed - if cudaDriverExists then - local cudaVersion = read_file(cudaVersionFile) - local cudaVersion_req = os.getenv("EESSICUDAVERSION") - -- driver CUDA versions don't give a patch version for CUDA - local major, minor = string.match(cudaVersion, "(%d+)%.(%d+)") - local major_req, minor_req, patch_req = string.match(cudaVersion_req, "(%d+)%.(%d+)%.(%d+)") - local driver_libs_need_update = false - if major < major_req then - driver_libs_need_update = true - elseif major == major_req then - if minor < minor_req then - driver_libs_need_update = true - end - end - if driver_libs_need_update == true then - local advice = "but the module you want to load requires CUDA " .. cudaVersion_req .. ". " - advice = advice .. "Please update your CUDA driver libraries and then " - advice = advice .. "let EESSI know about the update.\\n" - advice = advice .. refer_to_docs - LmodError("\\nYour driver CUDA version is ", cudaVersion, " ", advice) - end - end - end - end -end - -local function eessi_espresso_deprecated_message(t) - local frameStk = require("FrameStk"):singleton() - local mt = frameStk:mt() - local simpleName = string.match(t.modFullName, "(.-)/") - local version = string.match(t.modFullName, "%d.%d.%d") - if simpleName == 'ESPResSo' and version == '4.2.1' then - -- Print a message on loading ESPreSso v <= 4.2.1 recommending using v 4.2.2 and above. - -- A message and not a warning as the exit code would break CI runs otherwise. - local advice = 'Prefer versions >= 4.2.2 which include important bugfixes.\\n' - advice = advice .. 'For details see https://github.com/espressomd/espresso/releases/tag/4.2.2\\n' - advice = advice .. 'Use version 4.2.1 at your own risk!\\n' - LmodMessage("\\nESPResSo v4.2.1 has known issues and has been deprecated. ", advice) - end -end - -local function eessi_scipy_2022b_test_failures_message(t) - local cpuArch = os.getenv("EESSI_SOFTWARE_SUBDIR") - local graceArch = 'aarch64/nvidia/grace' - local fullModuleName = 'SciPy-bundle/2023.02-gfbf-2022b' - local moduleVersionArchMatch = t.modFullName == fullModuleName and cpuArch == graceArch - if moduleVersionArchMatch and not os.getenv("EESSI_IGNORE_MODULE_WARNINGS") then - -- Print a message on loading SciPy-bundle version == 2023.02 informing about the higher number of - -- test failures and recommend using other versions available via EESSI. - -- A message and not a warning as the exit code would break CI runs otherwise. - local simpleName = string.match(t.modFullName, "(.-)/") - local advice = 'The module ' .. t.modFullName .. ' will be loaded. However, note that\\n' - advice = advice .. 'during its building for the CPU microarchitecture ' .. graceArch .. ' from a\\n' - advice = advice .. 'total of 52.730 unit tests a larger number (46) than usually (2-4) failed. If\\n' - advice = advice .. 'you encounter issues while using ' .. t.modFullName .. ', please,\\n' - advice = advice .. 'consider using one of the other versions of ' .. simpleName .. ' that are also provided\\n' - advice = advice .. 'for the same CPU microarchitecture.\\n' - LmodMessage("\\n", advice) - end -end - --- Combine both functions into a single one, as we can only register one function as load hook in lmod --- Also: make it non-local, so it can be imported and extended by other lmodrc files if needed -function eessi_load_hook(t) - eessi_espresso_deprecated_message(t) - eessi_scipy_2022b_test_failures_message(t) - -- Only apply CUDA and cu*-library hooks if the loaded module is in the EESSI prefix - -- This avoids getting an Lmod Error when trying to load a CUDA or cu* module from a local software stack - if from_eessi_prefix(t) then - eessi_cuda_and_libraries_enabled_load_hook(t) - end -end - -hook.register("load", eessi_load_hook) - -""" - -hook_epilogue = """ --- Note that this needs to happen at the end, so that any EESSI specific hooks can be overwritten by the site -load_site_specific_hooks() -""" - - -# This hook is only for zen4. -hook_txt_zen4 = """ -local function hide_2022b_modules(modT) - -- modT is a table with: fullName, sn, fn and isVisible - -- The latter is a boolean to determine if a module is visible or not - - local tcver = modT.fullName:match("gfbf%-(20[0-9][0-9][ab])") or - modT.fullName:match("gompi%-(20[0-9][0-9][ab])") or - modT.fullName:match("foss%-(20[0-9][0-9][ab])") or - modT.fullName:match("GCC%-([0-9]*.[0-9]*.[0-9]*)") or - modT.fullName:match("GCCcore%-([0-9]*.[0-9]*.[0-9]*)") - - -- if nothing matches, return - if tcver == nil then return end - - -- if we have matches, check if the toolchain version is either 2022b or 12.2.0 - if parseVersion(tcver) == parseVersion("2022b") or parseVersion(tcver) == parseVersion("12.2.0") then - modT.isVisible = false - end -end - -hook.register("isVisibleHook", hide_2022b_modules) -""" - -# Append conditionally for zen4 -eessi_software_subdir_override = os.getenv("EESSI_SOFTWARE_SUBDIR_OVERRIDE") -if eessi_software_subdir_override == "x86_64/amd/zen4": - hook_txt = hook_txt + hook_txt_zen4 - -# Concatenate hook prologue, body and epilogue -# Note that this has to happen after any conditional items have been added to the hook_txt -hook_txt = hook_prologue + hook_txt + hook_epilogue - -def error(msg): - sys.stderr.write("ERROR: %s\n" % msg) - sys.exit(1) - - -if len(sys.argv) != 2: - error("Usage: %s " % sys.argv[0]) - -prefix = sys.argv[1] - -if not os.path.exists(prefix): - error("Prefix directory %s does not exist!" % prefix) - -sitepackage_path = os.path.join(prefix, DOT_LMOD, 'SitePackage.lua') - -# Lmod itself doesn't care about compute capability so remove this duplication from -# the install path (if it exists) -accel_subdir = os.getenv("EESSI_ACCELERATOR_TARGET") -if accel_subdir: - sitepackage_path = sitepackage_path.replace("/accel/%s" % accel_subdir, '') -try: - os.makedirs(os.path.dirname(sitepackage_path), exist_ok=True) - with open(sitepackage_path, 'w') as fp: - fp.write(hook_txt) - # Make sure that the created Lmod file has "read/write" for the user/group and "read" permissions for others - os.chmod(sitepackage_path, S_IREAD | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH) - -except (IOError, OSError) as err: - error("Failed to create %s: %s" % (sitepackage_path, err)) - -print(sitepackage_path) diff --git a/create_tarball.sh b/create_tarball.sh deleted file mode 100755 index bae66fb836..0000000000 --- a/create_tarball.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/bash - -set -e - -base_dir=$(dirname $(realpath $0)) - -if [ $# -ne 5 ]; then - echo "ERROR: Usage: $0 " >&2 - exit 1 -fi -eessi_tmpdir=$1 -eessi_version=$2 -cpu_arch_subdir=$3 -accel_subdir=$4 -target_tgz=$5 - -tmpdir=`mktemp -d` -echo ">> tmpdir: $tmpdir" - -os="linux" -source ${base_dir}/init/eessi_defaults -cvmfs_repo=${EESSI_CVMFS_REPO} -software_dir="${cvmfs_repo}/versions/${eessi_version}/software/${os}/${cpu_arch_subdir}" -if [ ! -d ${software_dir} ]; then - echo "Software directory ${software_dir} does not exist?!" >&2 - exit 2 -fi - -# Need to extract the cvmfs_repo_name from the cvmfs_repo variable -# - remove /${EESSI_DEV_PROJECT} from the end (if it exists) -# - remove /cvmfs/ from the beginning -cvmfs_repo_name=${cvmfs_repo%"/${EESSI_DEV_PROJECT}"} -cvmfs_repo_name=${cvmfs_repo_name#/cvmfs/} -overlay_upper_dir="${eessi_tmpdir}/${cvmfs_repo_name}/overlay-upper${EESSI_DEV_PROJECT:+/$EESSI_DEV_PROJECT}" - -software_dir_overlay="${overlay_upper_dir}/versions/${eessi_version}" -if [ ! -d ${software_dir_overlay} ]; then - echo "Software directory overlay ${software_dir_overlay} does not exist?!" >&2 - exit 3 -fi - -current_workdir=${PWD} -cd ${overlay_upper_dir}/versions/ -echo ">> Collecting list of files/directories to include in tarball via ${PWD}..." - -files_list=${tmpdir}/files.list.txt -module_files_list=${tmpdir}/module_files.list.txt - -if [ -d ${eessi_version}/software/${os}/${cpu_arch_subdir}/.lmod ]; then - # include Lmod cache and configuration file (lmodrc.lua), - # skip whiteout files and backup copies of Lmod cache (spiderT.old.*) - find ${eessi_version}/software/${os}/${cpu_arch_subdir}/.lmod -type f | egrep -v '/\.wh\.|spiderT.old' >> ${files_list} -fi - -# include scripts that were copied by install_scripts.sh, which we want to ship in EESSI repository -if [ -d ${eessi_version}/scripts ]; then - find ${eessi_version}/scripts -type f | grep -v '/\.wh\.' >> ${files_list} -fi - -# also include init, which is also copied by install_scripts.sh -if [ -d ${eessi_version}/init ]; then - find ${eessi_version}/init -type f | grep -v '/\.wh\.' >> ${files_list} -fi - -# consider both CPU-only and accelerator subdirectories -for subdir in ${cpu_arch_subdir} ${cpu_arch_subdir}/accel/${accel_subdir}; do - - if [ -d ${eessi_version}/software/${os}/${subdir}/modules ]; then - # module files - find ${eessi_version}/software/${os}/${subdir}/modules -type f | grep -v '/\.wh\.' >> ${files_list} || true # Make sure we don't exit because of set -e if grep doesn't return a match - # module symlinks - find ${eessi_version}/software/${os}/${subdir}/modules -type l | grep -v '/\.wh\.' >> ${files_list} || true # Make sure we don't exit because of set -e if grep doesn't return a match - # module files and symlinks - find ${eessi_version}/software/${os}/${subdir}/modules/all -type f -o -type l \ - | grep -v '/\.wh\.' | grep -v '/\.modulerc\.lua' | sed -e 's/.lua$//' | sed -e 's@.*/modules/all/@@g' | sort -u \ - >> ${module_files_list} - fi - - if [ -d ${eessi_version}/software/${os}/${subdir}/software -a -r ${module_files_list} ]; then - # installation directories but only those for which module files were created - # Note, we assume that module names (as defined by 'PACKAGE_NAME/VERSION.lua' - # using EasyBuild's standard module naming scheme) match the name of the - # software installation directory (expected to be 'PACKAGE_NAME/VERSION/'). - # If either side changes (module naming scheme or naming of software - # installation directories), the procedure will likely not work. - for package_version in $(cat ${module_files_list}); do - echo "handling ${package_version}" - ls -d ${eessi_version}/software/${os}/${subdir}/software/${package_version} \ - | grep -v '/\.wh\.' >> ${files_list} || true # Make sure we don't exit because of set -e if grep doesn't return a match - done - fi -done - -# add a bit debug output -if [ -r ${files_list} ]; then - echo "wrote file list to ${files_list}" - cat ${files_list} -fi -if [ -r ${module_files_list} ]; then - echo "wrote module file list to ${module_files_list}" - cat ${module_files_list} - - # Copy the module files list to current workindg dir for later use in the test step - cp ${module_files_list} ${current_workdir}/module_files.list.txt -fi - -topdir=${cvmfs_repo}/versions/ - -echo ">> Creating tarball ${target_tgz} from ${topdir}..." -tar cfvz ${target_tgz} -C ${topdir} --files-from=${files_list} - -echo ${target_tgz} created! - -echo ">> Cleaning up tmpdir ${tmpdir}..." -rm -r ${tmpdir} diff --git a/eb_hooks.py b/eb_hooks.py deleted file mode 100644 index 482ade4c20..0000000000 --- a/eb_hooks.py +++ /dev/null @@ -1,1402 +0,0 @@ -# Hooks to customize how EasyBuild installs software in EESSI -# see https://docs.easybuild.io/en/latest/Hooks.html -import glob -import os -import re - -import easybuild.tools.environment as env -from easybuild.easyblocks.generic.configuremake import obtain_config_guess -from easybuild.framework.easyconfig.constants import EASYCONFIG_CONSTANTS -from easybuild.tools.build_log import EasyBuildError, print_msg -from easybuild.tools.config import build_option, update_build_option -from easybuild.tools.filetools import apply_regex_substitutions, copy_file, remove_file, symlink, which -from easybuild.tools.run import run_cmd -from easybuild.tools.systemtools import AARCH64, POWER, X86_64, get_cpu_architecture, get_cpu_features -from easybuild.tools.toolchain.compiler import OPTARCH_GENERIC -from easybuild.tools.version import VERSION as EASYBUILD_VERSION -from easybuild.tools.modules import get_software_root_env_var_name - -# prefer importing LooseVersion from easybuild.tools, but fall back to distuils in case EasyBuild <= 4.7.0 is used -try: - from easybuild.tools import LooseVersion -except ImportError: - from distutils.version import LooseVersion - - -CPU_TARGET_NEOVERSE_N1 = 'aarch64/neoverse_n1' -CPU_TARGET_NEOVERSE_V1 = 'aarch64/neoverse_v1' -CPU_TARGET_AARCH64_GENERIC = 'aarch64/generic' -CPU_TARGET_A64FX = 'aarch64/a64fx' -CPU_TARGET_NVIDIA_GRACE = 'aarch64/nvidia/grace' - -CPU_TARGET_CASCADELAKE = 'x86_64/intel/cascadelake' -CPU_TARGET_ICELAKE = 'x86_64/intel/icelake' -CPU_TARGET_SAPPHIRE_RAPIDS = 'x86_64/intel/sapphirerapids' -CPU_TARGET_ZEN4 = 'x86_64/amd/zen4' - -EESSI_RPATH_OVERRIDE_ATTR = 'orig_rpath_override_dirs' -EESSI_MODULE_ONLY_ATTR = 'orig_module_only' -EESSI_FORCE_ATTR = 'orig_force' - -SYSTEM = EASYCONFIG_CONSTANTS['SYSTEM'][0] - -EESSI_INSTALLATION_REGEX = r"^/cvmfs/[^/]*.eessi.io/versions/" -HOST_INJECTIONS_LOCATION = "/cvmfs/software.eessi.io/host_injections/" - -# Make sure a single environment variable name is used for this throughout the hooks -EESSI_IGNORE_ZEN4_GCC1220_ENVVAR="EESSI_IGNORE_LMOD_ERROR_ZEN4_GCC1220" - -def is_gcccore_1220_based(**kwargs): -# ecname, ecversion, tcname, tcversion): - """ - Checks if this easyconfig either _is_ or _uses_ a GCCcore-12.2.0 based toolchain. - This function is, for example, used to generate errors in GCCcore-12.2.0 based modules for the zen4 architecture - since zen4 is not fully supported with that toolchain. - - :param str ecname: Name of the software specified in the EasyConfig - :param str ecversion: Version of the software specified in the EasyConfig - :param str tcname: Toolchain name specified in the EasyConfig - :param str tcversion: Toolchain version specified in the EasyConfig - """ - ecname = kwargs.get('ecname', None) - ecversion = kwargs.get('ecversion', None) - tcname = kwargs.get('tcname', None) - tcversion = kwargs.get('tcversion', None) - - gcccore_based_names = ['GCCcore', 'GCC'] - foss_based_names = ['gfbf', 'gompi', 'foss'] - return ( - (tcname in foss_based_names and tcversion == '2022b') or - (tcname in gcccore_based_names and LooseVersion(tcversion) == LooseVersion('12.2.0')) or - (ecname in foss_based_names and ecversion == '2022b') or - (ecname in gcccore_based_names and LooseVersion(ecversion) == LooseVersion('12.2.0')) - ) - - -def get_eessi_envvar(eessi_envvar): - """Get an EESSI environment variable from the environment""" - - eessi_envvar_value = os.getenv(eessi_envvar) - if eessi_envvar_value is None: - raise EasyBuildError("$%s is not defined!", eessi_envvar) - - return eessi_envvar_value - - -def get_rpath_override_dirs(software_name): - # determine path to installations in software layer via $EESSI_SOFTWARE_PATH - eessi_software_path = get_eessi_envvar('EESSI_SOFTWARE_PATH') - - # construct the rpath override directory stub - rpath_injection_stub = os.path.join( - # Make sure we are looking inside the `host_injections` directory - eessi_software_path.replace('versions', 'host_injections', 1), - # Add the subdirectory for the specific software - 'rpath_overrides', - software_name, - # We can't know the version, but this allows the use of a symlink - # to facilitate version upgrades without removing files - 'system', - ) - - # Allow for libraries in lib or lib64 - rpath_injection_dirs = [os.path.join(rpath_injection_stub, x) for x in ('lib', 'lib64')] - - return rpath_injection_dirs - - -def parse_hook(ec, *args, **kwargs): - """Main parse hook: trigger custom functions based on software name.""" - - # determine path to Prefix installation in compat layer via $EPREFIX - eprefix = get_eessi_envvar('EPREFIX') - - if ec.name in PARSE_HOOKS: - PARSE_HOOKS[ec.name](ec, eprefix) - - # Always trigger this one, regardless of ec.name - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if cpu_target == CPU_TARGET_ZEN4: - parse_hook_zen4_module_only(ec, eprefix) - - # inject the GPU property (if required) - ec = inject_gpu_property(ec) - - -def post_ready_hook(self, *args, **kwargs): - """ - Post-ready hook: limit parallellism for selected builds based on software name and CPU target. - parallelism needs to be limited because some builds require a lot of memory per used core. - """ - # 'parallel' (EB4) or 'max_parallel' (EB5) easyconfig parameter is set via EasyBlock.set_parallel in ready step - # based on available cores. - - # Check whether we have EasyBuild 4 or 5 - parallel_param = 'parallel' - if EASYBUILD_VERSION >= '5': - parallel_param = 'max_parallel' - # get current parallelism setting - parallel = self.cfg[parallel_param] - if parallel == 1: - return # no need to limit if already using 1 core - - # get CPU target - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - - # check if we have limits defined for this software - if self.name in PARALLELISM_LIMITS: - limits = PARALLELISM_LIMITS[self.name] - - # first check for CPU-specific limit - if cpu_target in limits: - operation_func, operation_args = limits[cpu_target] - new_parallel = operation_func(parallel, operation_args) - # then check for generic limit (applies to all CPU targets) - elif '*' in limits: - operation_func, operation_args = limits['*'] - new_parallel = operation_func(parallel, operation_args) - else: - return # no applicable limits found - - # apply the limit if it's different from current - if new_parallel != parallel: - self.cfg[parallel_param] = new_parallel - msg = "limiting parallelism to %s (was %s) for %s on %s to avoid out-of-memory failures during building/testing" - print_msg(msg % (new_parallel, parallel, self.name, cpu_target), log=self.log) - - -def pre_prepare_hook(self, *args, **kwargs): - """Main pre-prepare hook: trigger custom functions.""" - - # Check if we have an MPI family in the toolchain (returns None if there is not) - mpi_family = self.toolchain.mpi_family() - - # Inject an RPATH override for MPI (if needed) - if mpi_family: - # Get list of override directories - mpi_rpath_override_dirs = get_rpath_override_dirs(mpi_family) - - # update the relevant option (but keep the original value so we can reset it later) - if hasattr(self, EESSI_RPATH_OVERRIDE_ATTR): - raise EasyBuildError("'self' already has attribute %s! Can't use pre_prepare hook.", - EESSI_RPATH_OVERRIDE_ATTR) - - setattr(self, EESSI_RPATH_OVERRIDE_ATTR, build_option('rpath_override_dirs')) - if getattr(self, EESSI_RPATH_OVERRIDE_ATTR): - # self.EESSI_RPATH_OVERRIDE_ATTR is (already) a colon separated string, let's make it a list - orig_rpath_override_dirs = [getattr(self, EESSI_RPATH_OVERRIDE_ATTR)] - rpath_override_dirs = ':'.join(orig_rpath_override_dirs + mpi_rpath_override_dirs) - else: - rpath_override_dirs = ':'.join(mpi_rpath_override_dirs) - update_build_option('rpath_override_dirs', rpath_override_dirs) - print_msg("Updated rpath_override_dirs (to allow overriding MPI family %s): %s", - mpi_family, rpath_override_dirs) - - if self.name in PRE_PREPARE_HOOKS: - PRE_PREPARE_HOOKS[self.name](self, *args, **kwargs) - - # Always trigger this one, regardless of ec.name - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if cpu_target == CPU_TARGET_ZEN4: - pre_prepare_hook_ignore_zen4_gcccore1220_error(self, *args, **kwargs) - - -def post_prepare_hook_gcc_prefixed_ld_rpath_wrapper(self, *args, **kwargs): - """ - Post-configure hook for GCCcore: - - copy RPATH wrapper script for linker commands to also have a wrapper in - place with system type prefix like 'x86_64-pc-linux-gnu' - """ - if self.name == 'GCCcore': - config_guess = obtain_config_guess() - system_type, _ = run_cmd(config_guess, log_all=True) - cmd_prefix = '%s-' % system_type.strip() - for cmd in ('ld', 'ld.gold', 'ld.bfd'): - wrapper = which(cmd) - self.log.info("Path to %s wrapper: %s" % (cmd, wrapper)) - wrapper_dir = os.path.dirname(wrapper) - prefix_wrapper = os.path.join(wrapper_dir, cmd_prefix + cmd) - copy_file(wrapper, prefix_wrapper) - self.log.info("Path to %s wrapper with '%s' prefix: %s" % (cmd, cmd_prefix, which(prefix_wrapper))) - - # we need to tweak the copied wrapper script, so that: - regex_subs = [ - # - CMD in the script is set to the command name without prefix, because EasyBuild's rpath_args.py - # script that is used by the wrapper script only checks for 'ld', 'ld.gold', etc. - # when checking whether or not to use -Wl - ('^CMD=.*', 'CMD=%s' % cmd), - # - the path to the correct actual binary is logged and called - ('/%s ' % cmd, '/%s ' % (cmd_prefix + cmd)), - ] - apply_regex_substitutions(prefix_wrapper, regex_subs) - else: - raise EasyBuildError("GCCcore-specific hook triggered for non-GCCcore easyconfig?!") - - -def post_prepare_hook(self, *args, **kwargs): - """Main post-prepare hook: trigger custom functions.""" - - if hasattr(self, EESSI_RPATH_OVERRIDE_ATTR): - # Reset the value of 'rpath_override_dirs' now that we are finished with it - update_build_option('rpath_override_dirs', getattr(self, EESSI_RPATH_OVERRIDE_ATTR)) - print_msg("Resetting rpath_override_dirs to original value: %s", getattr(self, EESSI_RPATH_OVERRIDE_ATTR)) - delattr(self, EESSI_RPATH_OVERRIDE_ATTR) - - if self.name in POST_PREPARE_HOOKS: - POST_PREPARE_HOOKS[self.name](self, *args, **kwargs) - - # Always trigger this one, regardless of ec.name - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if cpu_target == CPU_TARGET_ZEN4: - post_prepare_hook_ignore_zen4_gcccore1220_error(self, *args, **kwargs) - - -def parse_hook_casacore_disable_vectorize(ec, eprefix): - """ - Disable 'vectorize' toolchain option for casacore 3.5.0 on aarch64/neoverse_v1 - Compiling casacore 3.5.0 with GCC 13.2.0 (foss-2023b) gives an error when building for aarch64/neoverse_v1. - See also, https://github.com/EESSI/software-layer/pull/479 - """ - if ec.name == 'casacore': - tcname, tcversion = ec['toolchain']['name'], ec['toolchain']['version'] - if ( - LooseVersion(ec.version) == LooseVersion('3.5.0') and - tcname == 'foss' and tcversion == '2023b' - ): - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if cpu_target == CPU_TARGET_NEOVERSE_V1: - # Make sure the toolchainopts key exists, and the value is a dict, - # before we add the option to disable vectorization - if 'toolchainopts' not in ec or ec['toolchainopts'] is None: - ec['toolchainopts'] = {} - ec['toolchainopts']['vectorize'] = False - print_msg("Changed toochainopts for %s: %s", ec.name, ec['toolchainopts']) - else: - print_msg("Not changing option vectorize for %s on non-neoverse_v1", ec.name) - else: - print_msg("Not changing option vectorize for %s %s %s", ec.name, ec.version, ec.toolchain) - else: - raise EasyBuildError("casacore-specific hook triggered for non-casacore easyconfig?!") - - -def parse_hook_cgal_toolchainopts_precise(ec, eprefix): - """Enable 'precise' rather than 'strict' toolchain option for CGAL on POWER.""" - if ec.name == 'CGAL': - if get_cpu_architecture() == POWER: - # 'strict' implies '-mieee-fp', which is not supported on POWER - # see https://github.com/easybuilders/easybuild-framework/issues/2077 - ec['toolchainopts']['strict'] = False - ec['toolchainopts']['precise'] = True - print_msg("Tweaked toochainopts for %s: %s", ec.name, ec['toolchainopts']) - else: - raise EasyBuildError("CGAL-specific hook triggered for non-CGAL easyconfig?!") - - -def parse_hook_fontconfig_add_fonts(ec, eprefix): - """Inject --with-add-fonts configure option for fontconfig.""" - if ec.name == 'fontconfig': - # make fontconfig aware of fonts included with compat layer - with_add_fonts = '--with-add-fonts=%s' % os.path.join(eprefix, 'usr', 'share', 'fonts') - ec.update('configopts', with_add_fonts) - print_msg("Added '%s' configure option for %s", with_add_fonts, ec.name) - else: - raise EasyBuildError("fontconfig-specific hook triggered for non-fontconfig easyconfig?!") - - -def parse_hook_grpcio_zlib(ec, ecprefix): - """Adjust preinstallopts to use ZLIB from compat layer.""" - if ec.name == 'grpcio' and ec.version in ['1.57.0']: - exts_list = ec['exts_list'] - original_preinstallopts = (exts_list[0][2])['preinstallopts'] - original_option = "GRPC_PYTHON_BUILD_SYSTEM_ZLIB=True" - new_option = "GRPC_PYTHON_BUILD_SYSTEM_ZLIB=False" - (exts_list[0][2])['preinstallopts'] = original_preinstallopts.replace(original_option, new_option, 1) - print_msg("Modified the easyconfig to use compat ZLIB with GRPC_PYTHON_BUILD_SYSTEM_ZLIB=False") - else: - raise EasyBuildError("grpcio-specific hook triggered for a non-grpcio easyconfig?!") - - -def parse_hook_openblas_relax_lapack_tests_num_errors(ec, eprefix): - """Relax number of failing numerical LAPACK tests for aarch64/neoverse_v1 CPU target for OpenBLAS < 0.3.23""" - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if ec.name == 'OpenBLAS': - if LooseVersion(ec.version) < LooseVersion('0.3.23'): - # relax maximum number of failed numerical LAPACK tests for aarch64/neoverse_v1 CPU target - # since the default setting of 150 that works well on other aarch64 targets and x86_64 is a bit too strict - # See https://github.com/EESSI/software-layer/issues/314 - cfg_option = 'max_failing_lapack_tests_num_errors' - if cpu_target == CPU_TARGET_NEOVERSE_V1: - orig_value = ec[cfg_option] - ec[cfg_option] = 400 - print_msg("Maximum number of failing LAPACK tests with numerical errors for %s relaxed to %s (was %s)", - ec.name, ec[cfg_option], orig_value) - else: - print_msg("Not changing option %s for %s on non-AARCH64", cfg_option, ec.name) - else: - raise EasyBuildError("OpenBLAS-specific hook triggered for non-OpenBLAS easyconfig?!") - - -def parse_hook_pybind11_replace_catch2(ec, eprefix): - """ - Replace Catch2 build dependency in pybind11 easyconfigs with one that doesn't use system toolchain. - cfr. https://github.com/easybuilders/easybuild-easyconfigs/pull/19270 - """ - # this is mainly necessary to avoid that --missing keeps reporting Catch2/2.13.9 is missing, - # and to avoid that we need to use "--from-pr 19270" for every easyconfigs that (indirectly) depends on pybind11 - if ec.name == 'pybind11' and ec.version in ['2.10.3', '2.11.1']: - build_deps = ec['builddependencies'] - catch2_build_dep = None - catch2_name, catch2_version = ('Catch2', '2.13.9') - for idx, build_dep in enumerate(build_deps): - if build_dep[0] == catch2_name and build_dep[1] == catch2_version: - catch2_build_dep = build_dep - break - if catch2_build_dep and len(catch2_build_dep) == 4 and catch2_build_dep[3] == SYSTEM: - build_deps[idx] = (catch2_name, catch2_version) - - -def parse_hook_qt5_check_qtwebengine_disable(ec, eprefix): - """ - Disable check for QtWebEngine in Qt5 as workaround for problem with determining glibc version. - """ - if ec.name == 'Qt5': - # workaround for glibc version being reported as "UNKNOWN" in Gentoo Prefix environment by EasyBuild v4.7.2, - # see also https://github.com/easybuilders/easybuild-framework/pull/4290 - ec['check_qtwebengine'] = False - print_msg("Checking for QtWebEgine in Qt5 installation has been disabled") - else: - raise EasyBuildError("Qt5-specific hook triggered for non-Qt5 easyconfig?!") - - -def parse_hook_ucx_eprefix(ec, eprefix): - """Make UCX aware of compatibility layer via additional configuration options.""" - if ec.name == 'UCX': - ec.update('configopts', '--with-sysroot=%s' % eprefix) - ec.update('configopts', '--with-rdmacm=%s' % os.path.join(eprefix, 'usr')) - print_msg("Using custom configure options for %s: %s", ec.name, ec['configopts']) - else: - raise EasyBuildError("UCX-specific hook triggered for non-UCX easyconfig?!") - - -def parse_hook_freeimage_aarch64(ec, *args, **kwargs): - """ - Make sure to build with -fPIC on ARM to avoid - https://github.com/EESSI/software-layer/pull/736#issuecomment-2373261889 - """ - if ec.name == 'FreeImage' and ec.version in ('3.18.0',): - if os.getenv('EESSI_CPU_FAMILY') == 'aarch64': - # Make sure the toolchainopts key exists, and the value is a dict, - # before we add the option to enable PIC and disable PNG_ARM_NEON_OPT - if 'toolchainopts' not in ec or ec['toolchainopts'] is None: - ec['toolchainopts'] = {} - ec['toolchainopts']['pic'] = True - ec['toolchainopts']['extra_cflags'] = '-DPNG_ARM_NEON_OPT=0' - print_msg("Changed toolchainopts for %s: %s", ec.name, ec['toolchainopts']) - - -def parse_hook_zen4_module_only(ec, eprefix): - """ - Use --force --module-only if building a foss-2022b-based EasyConfig for Zen4. - This toolchain will not be supported on Zen4, so we will generate a modulefile - and have it print an LmodError. - """ - if is_gcccore_1220_based(ecname=ec['name'], ecversion=ec['version'], tcname=ec['toolchain']['name'], - tcversion=ec['toolchain']['version']): - env_varname = EESSI_IGNORE_ZEN4_GCC1220_ENVVAR - # TODO: create a docs page to which we can refer for more info here - # TODO: then update the link to the known issues page to the _specific_ issue - # Need to escape newline character so that the newline character actually ends up in the module file - # (otherwise, it splits the string, and a 2-line string ends up in the modulefile, resulting in syntax error) - errmsg = "EasyConfigs using toolchains based on GCCcore-12.2.0 are not supported for the Zen4 architecture.\\n" - errmsg += "See https://www.eessi.io/docs/known_issues/eessi-2023.06/#gcc-1220-and-foss-2022b-based-modules-cannot-be-loaded-on-zen4-architecture" - ec['modluafooter'] = 'if (not os.getenv("%s")) then LmodError("%s") end' % (env_varname, errmsg) - - -def pre_fetch_hook(self, *args, **kwargs): - """Main pre fetch hook: trigger custom functions based on software name.""" - if self.name in PRE_FETCH_HOOKS: - PRE_FETCH_HOOKS[ec.name](self, *args, **kwargs) - - # Always trigger this one, regardless of self.name - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if cpu_target == CPU_TARGET_ZEN4: - pre_fetch_hook_zen4_gcccore1220(self, *args, **kwargs) - - # Always check the software installation path - pre_fetch_hook_check_installation_path(self, *args, **kwargs) - - -# Check the installation path so we verify that accelerator software always gets installed into the correct location -def pre_fetch_hook_check_installation_path(self, *args, **kwargs): - # When we know the CUDA status, we will need to verify the installation path - # if we are doing an EESSI or host_injections installation - accelerator_deps = ['CUDA'] - strict_eessi_installation = ( - bool(re.search(EESSI_INSTALLATION_REGEX, self.installdir)) or - self.installdir.startswith(HOST_INJECTIONS_LOCATION)) - if strict_eessi_installation: - dependency_names = self.cfg.dependency_names() - if self.cfg.name in accelerator_deps or any(dep in dependency_names for dep in accelerator_deps): - # Make sure the path is an accelerator location - if "/accel/" not in self.installdir: - raise EasyBuildError( - f"It seems you are trying to install an accelerator package {self.cfg.name} into a " - f"non-accelerator location {self.installdir}. You need to reconfigure your installation to target " - "the correct location." - ) - else: - # If we don't have an accelerator dependency then we should be in a CPU installation path - if "/accel/" in self.installdir: - raise EasyBuildError( - f"It seems you are trying to install a CPU-only package {self.cfg.name} into accelerator location " - f"{self.installdir}. If this is a dependency of the package you are really interested in you will " - "need to first install the CPU-only dependencies of that package." - ) - - -def pre_fetch_hook_zen4_gcccore1220(self, *args, **kwargs): - """Use --force --module-only if building a foss-2022b-based EasyConfig for Zen4. - This toolchain will not be supported on Zen4, so we will generate a modulefile - and have it print an LmodError. - """ - if is_gcccore_1220_based(ecname=self.name, ecversion=self.version, tcname=self.toolchain.name, - tcversion=self.toolchain.version): - if hasattr(self, EESSI_MODULE_ONLY_ATTR): - raise EasyBuildError("'self' already has attribute %s! Can't use pre_fetch hook.", - EESSI_MODULE_ONLY_ATTR) - setattr(self, EESSI_MODULE_ONLY_ATTR, build_option('module_only')) - update_build_option('module_only', 'True') - print_msg("Updated build option 'module-only' to 'True'") - - if hasattr(self, EESSI_FORCE_ATTR): - raise EasyBuildError("'self' already has attribute %s! Can't use pre_fetch hook.", - EESSI_FORCE_ATTR) - setattr(self, EESSI_FORCE_ATTR, build_option('force')) - update_build_option('force', 'True') - print_msg("Updated build option 'force' to 'True'") - - -def pre_module_hook_zen4_gcccore1220(self, *args, **kwargs): - """Make module load-able during module step""" - if is_gcccore_1220_based(ecname=self.name, ecversion=self.version, tcname=self.toolchain.name, - tcversion=self.toolchain.version): - if hasattr(self, 'initial_environ'): - # Allow the module to be loaded in the module step (which uses initial environment) - print_msg(f"Setting {EESSI_IGNORE_ZEN4_GCC1220_ENVVAR} in initial environment") - self.initial_environ[EESSI_IGNORE_ZEN4_GCC1220_ENVVAR] = "1" - - -def post_module_hook_zen4_gcccore1220(self, *args, **kwargs): - """Revert changes from pre_fetch_hook_zen4_gcccore1220""" - if is_gcccore_1220_based(ecname=self.name, ecversion=self.version, tcname=self.toolchain.name, - tcversion=self.toolchain.version): - if hasattr(self, EESSI_MODULE_ONLY_ATTR): - update_build_option('module_only', getattr(self, EESSI_MODULE_ONLY_ATTR)) - print_msg("Restored original build option 'module_only' to %s" % getattr(self, EESSI_MODULE_ONLY_ATTR)) - else: - raise EasyBuildError("Cannot restore module_only to it's original value: 'self' is missing attribute %s.", - EESSI_MODULE_ONLY_ATTR) - - if hasattr(self, EESSI_FORCE_ATTR): - update_build_option('force', getattr(self, EESSI_FORCE_ATTR)) - print_msg("Restored original build option 'force' to %s" % getattr(self, EESSI_FORCE_ATTR)) - else: - raise EasyBuildError("Cannot restore force to it's original value: 'self' is misisng attribute %s.", - EESSI_FORCE_ATTR) - - # If the variable to allow loading is set, remove it - if hasattr(self, 'initial_environ'): - if self.initial_environ.get(EESSI_IGNORE_ZEN4_GCC1220_ENVVAR, False): - print_msg(f"Removing {EESSI_IGNORE_ZEN4_GCC1220_ENVVAR} in initial environment") - del self.initial_environ[EESSI_IGNORE_ZEN4_GCC1220_ENVVAR] - - -# Modules for dependencies are loaded in the prepare step. Thus, that's where we need this variable to be set -# so that the modules can be succesfully loaded without printing the error (so that we can create a module -# _with_ the warning for the current software being installed) -def pre_prepare_hook_ignore_zen4_gcccore1220_error(self, *args, **kwargs): - """Set environment variable to ignore the LmodError from parse_hook_zen4_module_only during build phase""" - if is_gcccore_1220_based(ecname=self.name, ecversion=self.version, tcname=self.toolchain.name, - tcversion=self.toolchain.version): - os.environ[EESSI_IGNORE_ZEN4_GCC1220_ENVVAR] = "1" - - -def post_prepare_hook_ignore_zen4_gcccore1220_error(self, *args, **kwargs): - """Unset environment variable to ignore the LmodError from parse_hook_zen4_module_only during build phase""" - if is_gcccore_1220_based(ecname=self.name, ecversion=self.version, tcname=self.toolchain.name, - tcversion=self.toolchain.version): - del os.environ[EESSI_IGNORE_ZEN4_GCC1220_ENVVAR] - - -def pre_prepare_hook_highway_handle_test_compilation_issues(self, *args, **kwargs): - """ - Solve issues with compiling or running the tests on both - neoverse_n1 and neoverse_v1 with Highway 1.0.4 and GCC 12.3.0: - - for neoverse_n1 we set optarch to GENERIC - - for neoverse_v1 and a64fx we completely disable the tests - cfr. https://github.com/EESSI/software-layer/issues/469 - """ - if self.name == 'Highway': - tcname, tcversion = self.toolchain.name, self.toolchain.version - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - # note: keep condition in sync with the one used in - # post_prepare_hook_highway_handle_test_compilation_issues - if self.version in ['1.0.4'] and tcname == 'GCCcore' and tcversion == '12.3.0': - if cpu_target in [CPU_TARGET_A64FX, CPU_TARGET_NEOVERSE_V1, CPU_TARGET_NVIDIA_GRACE]: - self.cfg.update('configopts', '-DHWY_ENABLE_TESTS=OFF') - if cpu_target == CPU_TARGET_NEOVERSE_N1: - self.orig_optarch = build_option('optarch') - update_build_option('optarch', OPTARCH_GENERIC) - else: - raise EasyBuildError("Highway-specific hook triggered for non-Highway easyconfig?!") - - -def post_prepare_hook_highway_handle_test_compilation_issues(self, *args, **kwargs): - """ - Post-prepare hook for Highway to reset optarch build option. - """ - if self.name == 'Highway': - tcname, tcversion = self.toolchain.name, self.toolchain.version - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - # note: keep condition in sync with the one used in - # pre_prepare_hook_highway_handle_test_compilation_issues - if self.version in ['1.0.4'] and tcname == 'GCCcore' and tcversion == '12.3.0': - if cpu_target == CPU_TARGET_NEOVERSE_N1: - update_build_option('optarch', self.orig_optarch) - - -def pre_configure_hook(self, *args, **kwargs): - """Main pre-configure hook: trigger custom functions based on software name.""" - if self.name in PRE_CONFIGURE_HOOKS: - PRE_CONFIGURE_HOOKS[self.name](self, *args, **kwargs) - - -def pre_configure_hook_BLIS_a64fx(self, *args, **kwargs): - """ - Pre-configure hook for BLIS when building for A64FX: - - add -DCACHE_SECTOR_SIZE_READONLY to $CFLAGS for BLIS 0.9.0, cfr. https://github.com/flame/blis/issues/800 - """ - if self.name == 'BLIS': - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if self.version == '0.9.0' and cpu_target == CPU_TARGET_A64FX: - # last argument of BLIS' configure command is configuration target (usually 'auto' for auto-detect), - # specifying of variables should be done before that - config_opts = self.cfg['configopts'].split(' ') - cflags_var = 'CFLAGS="$CFLAGS -DCACHE_SECTOR_SIZE_READONLY"' - config_target = config_opts[-1] - self.cfg['configopts'] = ' '.join(config_opts[:-1] + [cflags_var, config_target]) - else: - raise EasyBuildError("BLIS-specific hook triggered for non-BLIS easyconfig?!") - - -def pre_configure_hook_CUDA_Samples_test_remove(self, *args, **kwargs): - """skip immaTensorCoreGemm in CUDA-Samples for compute capability 7.0.""" - if self.name == 'CUDA-Samples' and self.version in ['12.1']: - # Get compute capability from build option - cuda_caps = build_option('cuda_compute_capabilities') - # Check if compute capability 7.0 is in the list - if cuda_caps and '7.0' in cuda_caps: - print_msg("Applying hook for CUDA-Samples %s with compute capability 7.0", self.version) - # local_filters is set by the easyblock, remove path to the Makefile instead - makefile_path = os.path.join(self.start_dir, 'Samples/3_CUDA_Features/immaTensorCoreGemm/Makefile') - if os.path.exists(makefile_path): - remove_file(makefile_path) - print_msg("Removed Makefile at %s to skip immaTensorCoreGemm build", makefile_path) - else: - print_msg("Makefile not found at %s", makefile_path) - else: - raise EasyBuildError("CUDA-Samples-specific hook triggered for non-CUDA-Samples easyconfig?!") - - -def pre_configure_hook_score_p(self, *args, **kwargs): - """ - Pre-configure hook for Score-p - - specify correct path to binutils (in compat layer) - """ - if self.name == 'Score-P': - - # determine path to Prefix installation in compat layer via $EPREFIX - eprefix = get_eessi_envvar('EPREFIX') - - binutils_lib_path_glob_pattern = os.path.join(eprefix, 'usr', 'lib*', 'binutils', '*-linux-gnu', '2.*') - binutils_lib_path = glob.glob(binutils_lib_path_glob_pattern) - if len(binutils_lib_path) == 1: - self.cfg.update('configopts', '--with-libbfd-lib=' + binutils_lib_path[0]) - self.cfg.update('configopts', '--with-libbfd-include=' + os.path.join(binutils_lib_path[0], 'include')) - else: - raise EasyBuildError("Failed to isolate path for binutils libraries using %s, got %s", - binutils_lib_path_glob_pattern, binutils_lib_path) - - else: - raise EasyBuildError("Score-P-specific hook triggered for non-Score-P easyconfig?!") - - -def pre_configure_hook_vsearch(self, *args, **kwargs): - """ - Pre-configure hook for VSEARCH - - Workaround for a Zlib macro being renamed in Gentoo, see https://bugs.gentoo.org/383179 - (solves "expected initializer before 'OF'" errors) - """ - if self.name == 'VSEARCH': - self.cfg.update('configopts', 'CPPFLAGS="-DOF=_Z_OF ${CPPFLAGS}"') - else: - raise EasyBuildError("VSEARCH-specific hook triggered for non-VSEARCH easyconfig?!") - - -def pre_configure_hook_extrae(self, *args, **kwargs): - """ - Pre-configure hook for Extrae - - avoid use of 'which' in configure script - - specify correct path to binutils/zlib (in compat layer) - """ - if self.name == 'Extrae': - - # determine path to Prefix installation in compat layer via $EPREFIX - eprefix = get_eessi_envvar('EPREFIX') - - binutils_lib_path_glob_pattern = os.path.join(eprefix, 'usr', 'lib*', 'binutils', '*-linux-gnu', '2.*') - binutils_lib_path = glob.glob(binutils_lib_path_glob_pattern) - if len(binutils_lib_path) == 1: - self.cfg.update('configopts', '--with-binutils=' + binutils_lib_path[0]) - else: - raise EasyBuildError("Failed to isolate path for binutils libraries using %s, got %s", - binutils_lib_path_glob_pattern, binutils_lib_path) - - # zlib is a filtered dependency, so we need to manually specify it's location to avoid the host version - self.cfg.update('configopts', '--with-libz=' + eprefix) - - # replace use of 'which' with 'command -v', since 'which' is broken in EESSI build container; - # this must be done *after* running configure script, because initial configuration re-writes configure script, - # and problem due to use of which only pops up when running make ?! - self.cfg.update( - 'prebuildopts', - "cp config/mpi-macros.m4 config/mpi-macros.m4.orig && " - "sed -i 's/`which /`command -v /g' config/mpi-macros.m4 && " - ) - else: - raise EasyBuildError("Extrae-specific hook triggered for non-Extrae easyconfig?!") - - -def pre_configure_hook_gobject_introspection(self, *args, **kwargs): - """ - pre-configure hook for GObject-Introspection: - - prevent GObject-Introspection from setting $LD_LIBRARY_PATH if EasyBuild is configured to filter it, see: - https://github.com/EESSI/software-layer/issues/196 - """ - if self.name == 'GObject-Introspection': - # inject a line that removes all items from runtime_path_envvar that are in $EASYBUILD_FILTER_ENVVARS - sed_cmd = r'sed -i "s@\(^\s*runtime_path_envvar = \)\(.*\)@' - sed_cmd += r'\1\2\n\1 [x for x in runtime_path_envvar if not x in os.environ.get(\'EASYBUILD_FILTER_ENV_VARS\', \'\').split(\',\')]@g"' - sed_cmd += ' %(start_dir)s/giscanner/ccompiler.py && ' - self.cfg.update('preconfigopts', sed_cmd) - else: - raise EasyBuildError("GObject-Introspection-specific hook triggered for non-GObject-Introspection easyconfig?!") - - -def pre_configure_hook_gromacs(self, *args, **kwargs): - """ - Pre-configure hook for GROMACS: - - avoid building with SVE instructions on Neoverse V1 as workaround for failing tests, - see https://gitlab.com/gromacs/gromacs/-/issues/5057 + https://gitlab.com/eessi/support/-/issues/47 - """ - if self.name == 'GROMACS': - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if ( - (LooseVersion(self.version) <= LooseVersion('2024.1') and cpu_target == CPU_TARGET_NEOVERSE_V1) or - (LooseVersion(self.version) <= LooseVersion('2024.4') and cpu_target == CPU_TARGET_NVIDIA_GRACE) - ): - self.cfg.update('configopts', '-DGMX_SIMD=ARM_NEON_ASIMD') - print_msg( - "Avoiding use of SVE instructions for GROMACS %s by using ARM_NEON_ASIMD as GMX_SIMD value", - self.version - ) - else: - raise EasyBuildError("GROMACS-specific hook triggered for non-GROMACS easyconfig?!") - - -def pre_configure_hook_llvm(self, *args, **kwargs): - """Adjust internal configure options for the LLVM EasyBlock to reinstate filtered out dependencies. - In the LLVM EasyBlock, most checks concerning loaded modules are performed at the configure_step. - The EB uses a global `general_opts` dict to keep track of options that needs to be reused across stages. - The way the EB is structured does allow to inject a CMAKE option through `self._cfgopts` which is a splitted list - of the `configure_opts` passed through the EC, but does not allow to override as the `general_opts` dict will - take precedence over the `self._cfgopts` list. - - We can instead set the environment variable that EasyBuild uses for `get_software_root` to trick the EB into - into pointing to the compat layer. - """ - if self.name in ['LLVM', 'ROCm-LLVM']: - eprefix = get_eessi_envvar('EPREFIX') - - for software in ('zlib', 'ncurses'): - var_name = get_software_root_env_var_name(software) - env.setvar(var_name, os.path.join(eprefix, 'usr')) - else: - raise EasyBuildError("LLVM-specific hook triggered for non-LLVM easyconfig?!") - - -def pre_configure_hook_openblas_optarch_generic(self, *args, **kwargs): - """ - Pre-configure hook for OpenBLAS: add DYNAMIC_ARCH=1 to build/test/install options when using --optarch=GENERIC - """ - # note: OpenBLAS easyblock was updated in https://github.com/easybuilders/easybuild-easyblocks/pull/3492 - # to take care of this already, so at some point this hook can be removed... - if self.name == 'OpenBLAS': - if build_option('optarch') == OPTARCH_GENERIC: - dynamic_arch = 'DYNAMIC_ARCH=1' - for step in ('build', 'test', 'install'): - if dynamic_arch not in self.cfg[f'{step}opts']: - self.cfg.update(f'{step}opts', dynamic_arch) - - if get_cpu_architecture() == AARCH64: - # when building for aarch64/generic, we also need to set TARGET=ARMV8 to make sure - # that the driver parts of OpenBLAS are compiled generically; - # see also https://github.com/OpenMathLib/OpenBLAS/issues/4945 - target_armv8 = 'TARGET=ARMV8' - for step in ('build', 'test', 'install'): - if target_armv8 not in self.cfg[f'{step}opts']: - self.cfg.update(f'{step}opts', target_armv8) - - # use -mtune=generic rather than -mcpu=generic in $CFLAGS for aarch64/generic, - # because -mcpu=generic implies a particular -march=armv* which clashes with those used by OpenBLAS - # when building with DYNAMIC_ARCH=1 - mcpu_generic = '-mcpu=generic' - cflags = os.getenv('CFLAGS') - if mcpu_generic in cflags: - cflags = cflags.replace(mcpu_generic, '-mtune=generic') - self.log.info("Replaced -mcpu=generic with -mtune=generic in $CFLAGS") - env.setvar('CFLAGS', cflags) - else: - raise EasyBuildError("OpenBLAS-specific hook triggered for non-OpenBLAS easyconfig?!") - - -def pre_configure_hook_libfabric_disable_psm3_x86_64_generic(self, *args, **kwargs): - """Add --disable-psm3 to libfabric configure options when building with --optarch=GENERIC on x86_64.""" - if self.name == 'libfabric': - if get_cpu_architecture() == X86_64: - generic = build_option('optarch') == OPTARCH_GENERIC - no_avx = 'avx' not in get_cpu_features() - if generic or no_avx: - self.cfg.update('configopts', '--disable-psm3') - print_msg("Using custom configure options for %s: %s", self.name, self.cfg['configopts']) - else: - raise EasyBuildError("libfabric-specific hook triggered for non-libfabric easyconfig?!") - - -def pre_configure_hook_metabat_filtered_zlib_dep(self, *args, **kwargs): - """ - Pre-configure hook for MetaBAT: - - take into account that zlib is a filtered dependency, - and that there's no libz.a in the EESSI compat layer - """ - if self.name == 'MetaBAT': - configopts = self.cfg['configopts'] - regex = re.compile(r"\$EBROOTZLIB/lib/libz.a") - self.cfg['configopts'] = regex.sub('$EPREFIX/usr/lib64/libz.so', configopts) - else: - raise EasyBuildError("MetaBAT-specific hook triggered for non-MetaBAT easyconfig?!") - - -def pre_configure_hook_wrf_aarch64(self, *args, **kwargs): - """ - Pre-configure hook for WRF: - - patch arch/configure_new.defaults so building WRF with foss toolchain works on aarch64 - """ - if self.name == 'WRF': - if get_cpu_architecture() == AARCH64: - pattern = "Linux x86_64 ppc64le, gfortran" - repl = "Linux x86_64 aarch64 ppc64le, gfortran" - if LooseVersion(self.version) <= LooseVersion('3.9.0'): - self.cfg.update('preconfigopts', "sed -i 's/%s/%s/g' arch/configure_new.defaults && " % (pattern, repl)) - print_msg("Using custom preconfigopts for %s: %s", self.name, self.cfg['preconfigopts']) - - if LooseVersion('4.0.0') <= LooseVersion(self.version) <= LooseVersion('4.2.1'): - self.cfg.update('preconfigopts', "sed -i 's/%s/%s/g' arch/configure.defaults && " % (pattern, repl)) - print_msg("Using custom preconfigopts for %s: %s", self.name, self.cfg['preconfigopts']) - else: - raise EasyBuildError("WRF-specific hook triggered for non-WRF easyconfig?!") - - -def pre_configure_hook_LAMMPS_zen4(self, *args, **kwargs): - """ - pre-configure hook for LAMMPS: - - set kokkos_arch on x86_64/amd/zen4 - """ - - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if self.name == 'LAMMPS': - if self.version in ('2Aug2023_update2', '2Aug2023_update4', '29Aug2024'): - if get_cpu_architecture() == X86_64: - if cpu_target == CPU_TARGET_ZEN4: - # There is no support for ZEN4 in LAMMPS yet so falling back to ZEN3 - self.cfg['kokkos_arch'] = 'ZEN3' - else: - raise EasyBuildError("LAMMPS-specific hook triggered for non-LAMMPS easyconfig?!") - - -def pre_test_hook(self, *args, **kwargs): - """Main pre-test hook: trigger custom functions based on software name.""" - if self.name in PRE_TEST_HOOKS: - PRE_TEST_HOOKS[self.name](self, *args, **kwargs) - - -def pre_test_hook_exclude_failing_test_Highway(self, *args, **kwargs): - """ - Pre-test hook for Highway: exclude failing TestAllShiftRightLanes/SVE_256 test on neoverse_v1 - cfr. https://github.com/EESSI/software-layer/issues/469 - and exclude failing tests - HwyReductionTestGroup/HwyReductionTest.TestAllSumOfLanes/SVE2_128 - HwyReductionTestGroup/HwyReductionTest.TestAllSumOfLanes/SVE2 - HwyReductionTestGroup/HwyReductionTest.TestAllSumOfLanes/SVE - on nvidia/grace - """ - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if self.name == 'Highway' and self.version in ['1.0.3'] and cpu_target == CPU_TARGET_NEOVERSE_V1: - self.cfg['runtest'] += ' ARGS="-E TestAllShiftRightLanes/SVE_256"' - if self.name == 'Highway' and self.version in ['1.0.3'] and cpu_target == CPU_TARGET_NVIDIA_GRACE: - self.cfg['runtest'] += ' ARGS="-E TestAllSumOfLanes"' - - -def pre_test_hook_ignore_failing_tests_ESPResSo(self, *args, **kwargs): - """ - Pre-test hook for ESPResSo: skip failing tests, tests frequently timeout due to known bugs in ESPResSo v4.2.1 - cfr. https://github.com/EESSI/software-layer/issues/363 - """ - if self.name == 'ESPResSo' and self.version == '4.2.1': - self.cfg['testopts'] = "|| echo 'ignoring failing tests (probably due to timeouts)'" - - -def pre_test_hook_ignore_failing_tests_FFTWMPI(self, *args, **kwargs): - """ - Pre-test hook for FFTW.MPI: skip failing tests for FFTW.MPI 3.3.10 on neoverse_v1 - cfr. https://github.com/EESSI/software-layer/issues/325 - """ - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if self.name == 'FFTW.MPI' and self.version == '3.3.10' and cpu_target == CPU_TARGET_NEOVERSE_V1: - self.cfg['testopts'] = "|| echo ignoring failing tests" - - -def pre_test_hook_ignore_failing_tests_SciPybundle(self, *args, **kwargs): - """ - Pre-test hook for SciPy-bundle: skip failing tests for selected SciPy-bundle versions - In version 2021.10 on neoverse_v1, 2 failing tests in scipy 1.6.3: - FAILED optimize/tests/test_linprog.py::TestLinprogIPSparse::test_bug_6139 - A... - FAILED optimize/tests/test_linprog.py::TestLinprogIPSparsePresolve::test_bug_6139 - = 2 failed, 30554 passed, 2064 skipped, 10992 deselected, 76 xfailed, 7 xpassed, 40 warnings in 380.27s (0:06:20) = - In versions 2023.02 + 2023.07 + 2023.11 on neoverse_v1, 2 failing tests in scipy (versions 1.10.1, 1.11.1, 1.11.4): - FAILED scipy/spatial/tests/test_distance.py::TestPdist::test_pdist_correlation_iris - FAILED scipy/spatial/tests/test_distance.py::TestPdist::test_pdist_correlation_iris_float32 - = 2 failed, 54409 passed, 3016 skipped, 223 xfailed, 13 xpassed, 10917 warnings in 892.04s (0:14:52) = - In version 2023.07 on a64fx, 4 failing tests in scipy 1.11.1: - FAILED scipy/optimize/tests/test_linprog.py::TestLinprogIPSparse::test_bug_6139 - FAILED scipy/optimize/tests/test_linprog.py::TestLinprogIPSparsePresolve::test_bug_6139 - FAILED scipy/spatial/tests/test_distance.py::TestPdist::test_pdist_correlation_iris - FAILED scipy/spatial/tests/test_distance.py::TestPdist::test_pdist_correlation_iris_float32 - = 4 failed, 54407 passed, 3016 skipped, 223 xfailed, 13 xpassed, 10917 warnings in 6068.43s (1:41:08) = - In version 2023.07 + 2023.11 on grace, 2 failing tests in scipy (versions 1.11.1, 1.11.4): - FAILED scipy/optimize/tests/test_linprog.py::TestLinprogIPSparse::test_bug_6139 - FAILED scipy/optimize/tests/test_linprog.py::TestLinprogIPSparsePresolve::test_bug_6139 - = 2 failed, 54876 passed, 3021 skipped, 223 xfailed, 13 xpassed in 581.85s (0:09:41) = - In version 2023.02 on grace, 46 failing tests in scipy (versions 1.10.1): - FAILED ../../linalg/tests/test_basic.py::TestOverwrite::test_pinv - RuntimeWa... - FAILED ../../linalg/tests/test_basic.py::TestOverwrite::test_pinvh - RuntimeW... - FAILED ../../linalg/tests/test_matfuncs.py::TestExpM::test_2x2_input - Runtim... - FAILED ../../optimize/tests/test_linprog.py::TestLinprogIPSparse::test_bug_6139 - FAILED ../../optimize/tests/test_linprog.py::TestLinprogIPSparsePresolve::test_bug_6139 - FAILED ../../optimize/tests/test_zeros.py::test_gh_9608_preserve_array_shape - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[True-True-True-coo_matrix-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[True-True-False-array-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[True-True-False-csr_matrix-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[True-True-False-coo_matrix-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[False-True-True-array-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[False-True-True-csr_matrix-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[False-True-True-coo_matrix-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[True-True-True-array-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-True-False-True-float32-asarray] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[False-True-False-array-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[True-True-True-csr_matrix-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-True-False-True-float32-csr_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-True-True-True-float32-asarray] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-True-True-True-float32-csr_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-True-False-True-float32-coo_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[False-True-False-csr_matrix-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-True-True-True-float32-coo_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-True-False-True-float32-asarray] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-False-False-True-float32-asarray] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-False-False-True-float32-csr_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-False-False-True-float32-coo_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_asymmetric_laplacian[False-True-False-coo_matrix-float32] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-True-False-True-float32-csr_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-True-False-True-float32-coo_matrix] - FAILED ../../sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py::test_tolerance_float32 - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-True-True-True-float32-asarray] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-False-False-True-float32-asarray] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-False-False-True-float32-csr_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-False-False-True-float32-coo_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-True-True-True-float32-csr_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-True-True-True-float32-coo_matrix] - FAILED ../../sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py::test_random_initial_float32 - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-False-True-True-float32-asarray] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-False-True-True-float32-csr_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[function-False-True-True-float32-coo_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-False-True-True-float32-asarray] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-False-True-True-float32-csr_matrix] - FAILED ../../sparse/csgraph/tests/test_graph_laplacian.py::test_format[lo-False-True-True-float32-coo_matrix] - FAILED ../../sparse/linalg/_isolve/tests/test_iterative.py::test_precond_dummy - FAILED ../../sparse/linalg/_eigen/arpack/tests/test_arpack.py::test_symmetric_modes - = 46 failed, 49971 passed, 2471 skipped, 231 xfailed, 11 xpassed in 65.91s (0:01:05) = - (in previous versions we were not as strict yet on the numpy/SciPy tests) - """ - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - scipy_bundle_versions_nv1 = ('2021.10', '2023.02', '2023.07', '2023.11') - scipy_bundle_versions_a64fx = ('2023.07', '2023.11') - scipy_bundle_versions_nvidia_grace = ('2023.02', '2023.07', '2023.11') - if self.name == 'SciPy-bundle': - if cpu_target == CPU_TARGET_NEOVERSE_V1 and self.version in scipy_bundle_versions_nv1: - self.cfg['testopts'] = "|| echo ignoring failing tests" - elif cpu_target == CPU_TARGET_A64FX and self.version in scipy_bundle_versions_a64fx: - self.cfg['testopts'] = "|| echo ignoring failing tests" - elif cpu_target == CPU_TARGET_NVIDIA_GRACE and self.version in scipy_bundle_versions_nvidia_grace: - self.cfg['testopts'] = "|| echo ignoring failing tests" - - -def pre_test_hook_ignore_failing_tests_netCDF(self, *args, **kwargs): - """ - Pre-test hook for netCDF: skip failing tests for selected netCDF versions on neoverse_v1 - cfr. https://github.com/EESSI/software-layer/issues/425 - The following tests are problematic: - 163 - nc_test4_run_par_test (Timeout) - 190 - h5_test_run_par_tests (Timeout) - A few other tests are skipped in the easyconfig and patches for similar issues, see above issue for details. - """ - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if self.name == 'netCDF' and self.version == '4.9.2' and cpu_target == CPU_TARGET_NEOVERSE_V1: - self.cfg['testopts'] = "|| echo ignoring failing tests" - - -def pre_test_hook_increase_max_failed_tests_arm_PyTorch(self, *args, **kwargs): - """ - Pre-test hook for PyTorch: increase the number of max failing tests - See https://github.com/EESSI/software-layer/issues/461 - """ - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if self.name == 'PyTorch' and self.version == '2.1.2': - if get_cpu_architecture() == AARCH64: - self.cfg['max_failed_tests'] = 10 - if cpu_target in [CPU_TARGET_CASCADELAKE, CPU_TARGET_ICELAKE, CPU_TARGET_SAPPHIRE_RAPIDS]: - self.cfg['max_failed_tests'] = 4 - - -def pre_single_extension_hook(ext, *args, **kwargs): - """Main pre-extension: trigger custom functions based on software name.""" - if ext.name in PRE_SINGLE_EXTENSION_HOOKS: - PRE_SINGLE_EXTENSION_HOOKS[ext.name](ext, *args, **kwargs) - - -def post_single_extension_hook(ext, *args, **kwargs): - """Main post-extension hook: trigger custom functions based on software name.""" - if ext.name in POST_SINGLE_EXTENSION_HOOKS: - POST_SINGLE_EXTENSION_HOOKS[ext.name](ext, *args, **kwargs) - - -def pre_single_extension_isoband(ext, *args, **kwargs): - """ - Pre-extension hook for isoband R package, to fix build on top of recent glibc. - """ - if ext.name == 'isoband' and LooseVersion(ext.version) < LooseVersion('0.2.5'): - # use constant value instead of SIGSTKSZ for stack size in vendored testthat included in isoband sources, - # cfr. https://github.com/r-lib/isoband/commit/6984e6ce8d977f06e0b5ff73f5d88e5c9a44c027 - ext.cfg['preinstallopts'] = "sed -i 's/SIGSTKSZ/32768/g' src/testthat/vendor/catch.h && " - - -def pre_single_extension_numpy(ext, *args, **kwargs): - """ - Pre-extension hook for numpy, to change -march=native to -march=armv8.4-a for numpy 1.24.2 - when building for aarch64/neoverse_v1 CPU target. - """ - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if ext.name == 'numpy' and ext.version == '1.24.2' and cpu_target == CPU_TARGET_NEOVERSE_V1: - # note: this hook is called before build environment is set up (by calling toolchain.prepare()), - # so environment variables like $CFLAGS are not defined yet - # unsure which of these actually matter for numpy, so changing all of them - ext.orig_optarch = build_option('optarch') - update_build_option('optarch', 'march=armv8.4-a') - - -def post_single_extension_numpy(ext, *args, **kwargs): - """ - Post-extension hook for numpy, to reset 'optarch' build option. - """ - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if ext.name == 'numpy' and ext.version == '1.24.2' and cpu_target == CPU_TARGET_NEOVERSE_V1: - update_build_option('optarch', ext.orig_optarch) - - -def pre_single_extension_testthat(ext, *args, **kwargs): - """ - Pre-extension hook for testthat R package, to fix build on top of recent glibc. - """ - if ext.name == 'testthat' and LooseVersion(ext.version) < LooseVersion('3.1.0'): - # use constant value instead of SIGSTKSZ for stack size, - # cfr. https://github.com/r-lib/testthat/issues/1373 + https://github.com/r-lib/testthat/pull/1403 - ext.cfg['preinstallopts'] = "sed -i 's/SIGSTKSZ/32768/g' inst/include/testthat/vendor/catch.h && " - - -def post_postproc_hook(self, *args, **kwargs): - """Main post-postprocessing hook: trigger custom functions based on software name.""" - if self.name in POST_POSTPROC_HOOKS: - POST_POSTPROC_HOOKS[self.name](self, *args, **kwargs) - - -def post_postproc_cuda(self, *args, **kwargs): - """ - Remove files from CUDA installation that we are not allowed to ship, - and replace them with a symlink to a corresponding installation under host_injections. - """ - if self.name == 'CUDA': - # This hook only acts on an installation under repositories that _we_ ship (*.eessi.io/versions) - eessi_installation = bool(re.search(EESSI_INSTALLATION_REGEX, self.installdir)) - - if eessi_installation: - print_msg("Replacing files in CUDA installation that we can not ship with symlinks to host_injections...") - - # read CUDA EULA, construct allowlist based on section 2.6 that specifies list of files that can be shipped - eula_path = os.path.join(self.installdir, 'EULA.txt') - relevant_eula_lines = [] - with open(eula_path) as infile: - copy = False - for line in infile: - if line.strip() == "2.6. Attachment A": - copy = True - continue - elif line.strip() == "2.7. Attachment B": - copy = False - continue - elif copy: - relevant_eula_lines.append(line) - - # create list without file extensions, they're not really needed and they only complicate things - allowlist = ['EULA', 'README'] - file_extensions = ['.so', '.a', '.h', '.bc'] - for line in relevant_eula_lines: - for word in line.split(): - if any(ext in word for ext in file_extensions): - allowlist.append(os.path.splitext(word)[0]) - # The EULA of CUDA 12.4 introduced a typo (confirmed by NVIDIA): - # libnvrtx-builtins_static.so should be libnvrtc-builtins_static.so - if 'libnvrtx-builtins_static' in allowlist: - allowlist.remove('libnvrtx-builtins_static') - allowlist.append('libnvrtc-builtins_static') - allowlist = sorted(set(allowlist)) - self.log.info( - "Allowlist for files in CUDA installation that can be redistributed: " + ', '.join(allowlist) - ) - - # Do some quick sanity checks for things we should or shouldn't have in the list - if 'nvcc' in allowlist: - raise EasyBuildError("Found 'nvcc' in allowlist: %s" % allowlist) - if 'libcudart' not in allowlist: - raise EasyBuildError("Did not find 'libcudart' in allowlist: %s" % allowlist) - - # replace files that are not distributable with symlinks into - # host_injections - replace_non_distributable_files_with_symlinks(self.log, self.installdir, self.name, allowlist) - else: - print_msg(f"EESSI hook to respect CUDA license not triggered for installation path {self.installdir}") - else: - raise EasyBuildError("CUDA-specific hook triggered for non-CUDA easyconfig?!") - - -def post_postproc_cudnn(self, *args, **kwargs): - """ - Remove files from cuDNN installation that we are not allowed to ship, - and replace them with a symlink to a corresponding installation under host_injections. - """ - - if self.name == 'cuDNN': - # This hook only acts on an installation under repositories that _we_ ship (*.eessi.io/versions) - eessi_installation = bool(re.search(EESSI_INSTALLATION_REGEX, self.installdir)) - - if eessi_installation: - print_msg("Replacing files in cuDNN installation that we can not ship with symlinks to host_injections...") - - allowlist = ['LICENSE'] - - # read cuDNN LICENSE, construct allowlist based on section "2. Distribution" that specifies list of files that can be shipped - license_path = os.path.join(self.installdir, 'LICENSE') - search_string = "2. Distribution. The following portions of the SDK are distributable under the Agreement:" - found_search_string = False - with open(license_path) as infile: - for line in infile: - if line.strip().startswith(search_string): - found_search_string = True - # remove search string, split into words, remove trailing - # dots '.' and only retain words starting with a dot '.' - distributable = line[len(search_string):] - # distributable looks like ' the runtime files .so and .dll.' - # note the '.' after '.dll' - for word in distributable.split(): - if word[0] == '.': - # rstrip is used to remove the '.' after '.dll' - allowlist.append(word.rstrip('.')) - if not found_search_string: - # search string wasn't found in LICENSE file - raise EasyBuildError("search string '%s' was not found in license file '%s';" - "hence installation may be replaced by symlinks only", - search_string, license_path) - - allowlist = sorted(set(allowlist)) - self.log.info("Allowlist for files in cuDNN installation that can be redistributed: " + ', '.join(allowlist)) - - # replace files that are not distributable with symlinks into - # host_injections - replace_non_distributable_files_with_symlinks(self.log, self.installdir, self.name, allowlist) - else: - print_msg(f"EESSI hook to respect cuDDN license not triggered for installation path {self.installdir}") - else: - raise EasyBuildError("cuDNN-specific hook triggered for non-cuDNN easyconfig?!") - - -def replace_non_distributable_files_with_symlinks(log, install_dir, pkg_name, allowlist): - """ - Replace files that cannot be distributed with symlinks into host_injections - """ - # Different packages use different ways to specify which files or file - # 'types' may be redistributed. For CUDA, the 'EULA.txt' lists full file - # names. For cuDNN, the 'LICENSE' lists file endings/suffixes (e.g., '.so') - # that can be redistributed. - # The map 'extension_based' defines which of these two ways are employed. If - # full file names are used it maps a package name (key) to False (value). If - # endings/suffixes are used, it maps a package name to True. Later we can - # easily use this data structure to employ the correct method for - # postprocessing an installation. - extension_based = { - "CUDA": False, - "cuDNN": True, - } - if not pkg_name in extension_based: - raise EasyBuildError("Don't know how to strip non-distributable files from package %s.", pkg_name) - - # iterate over all files in the package installation directory - for dir_path, _, files in os.walk(install_dir): - for filename in files: - full_path = os.path.join(dir_path, filename) - # we only really care about real files, i.e. not symlinks - if not os.path.islink(full_path): - check_by_extension = extension_based[pkg_name] and '.' in filename - if check_by_extension: - # if the allowlist only contains extensions, we have to - # determine that from filename. we assume the extension is - # the second element when splitting the filename at dots - # (e.g., for 'libcudnn_adv_infer.so.8.9.2' the extension - # would be '.so') - extension = '.' + filename.split('.')[1] - # check if the current file name stub or its extension is part of the allowlist - basename = filename.split('.')[0] - if basename in allowlist: - log.debug("%s is found in allowlist, so keeping it: %s", basename, full_path) - elif check_by_extension and extension in allowlist: - log.debug("%s is found in allowlist, so keeping it: %s", extension, full_path) - else: - print_name = filename if extension_based[pkg_name] else basename - log.debug("%s is not found in allowlist, so replacing it with symlink: %s", - print_name, full_path) - # the host_injections path is under a fixed repo/location for CUDA or cuDNN - host_inj_path = re.sub(EESSI_INSTALLATION_REGEX, HOST_INJECTIONS_LOCATION, full_path) - # CUDA and cu* libraries themselves don't care about compute capability so remove this - # duplication from under host_injections (symlink to a single CUDA or cu* library - # installation for all compute capabilities) - accel_subdir = os.getenv("EESSI_ACCELERATOR_TARGET") - if accel_subdir: - host_inj_path = host_inj_path.replace("/accel/%s" % accel_subdir, '') - # make sure source and target of symlink are not the same - if full_path == host_inj_path: - raise EasyBuildError("Source (%s) and target (%s) are the same location, are you sure you " - "are using this hook for an EESSI installation?", - full_path, host_inj_path) - remove_file(full_path) - symlink(host_inj_path, full_path) - - -def inject_gpu_property(ec): - """ - Add 'gpu' property and EESSIVERSION envvars via modluafooter - easyconfig parameter, and drop dependencies to build dependencies - """ - ec_dict = ec.asdict() - # Check if CUDA, cuDNN, you-name-it is in the dependencies, if so - # - drop dependency to build dependency - # - add 'gpu' Lmod property - # - add envvar with package version - pkg_names = ( "CUDA", "cuDNN" ) - pkg_versions = { } - add_gpu_property = '' - - for pkg_name in pkg_names: - # Check if pkg_name is in the dependencies, if so drop dependency to build - # dependency and set variable for later adding the 'gpu' Lmod property - # to '.remove' dependencies from ec_dict['dependencies'] we make a copy, - # iterate over the copy and can then savely use '.remove' on the original - # ec_dict['dependencies']. - deps = ec_dict['dependencies'][:] - if (pkg_name in [dep[0] for dep in deps]): - add_gpu_property = 'add_property("arch","gpu")' - for dep in deps: - if pkg_name == dep[0]: - # make pkg_name a build dependency only (rpathing saves us from link errors) - ec.log.info("Dropping dependency on %s to build dependency" % pkg_name) - ec_dict['dependencies'].remove(dep) - if dep not in ec_dict['builddependencies']: - ec_dict['builddependencies'].append(dep) - # take note of version for creating the modluafooter - pkg_versions[pkg_name] = dep[1] - if add_gpu_property: - ec.log.info("Injecting gpu as Lmod arch property and envvars for dependencies with their version") - modluafooter = 'modluafooter' - extra_mod_footer_lines = [add_gpu_property] - for pkg_name, version in pkg_versions.items(): - envvar = "EESSI%sVERSION" % pkg_name.upper() - extra_mod_footer_lines.append('setenv("%s","%s")' % (envvar, version)) - # take into account that modluafooter may already be set - if modluafooter in ec_dict: - value = ec_dict[modluafooter] - for line in extra_mod_footer_lines: - if not line in value: - value = '\n'.join([value, line]) - ec[modluafooter] = value - else: - ec[modluafooter] = '\n'.join(extra_mod_footer_lines) - - return ec - - -def pre_module_hook(self, *args, **kwargs): - """Main pre module hook: trigger custom functions based on software name.""" - if self.name in PRE_MODULE_HOOKS: - PRE_MODULE_HOOKS[self.name](self, *args, **kwargs) - - # Always trigger this one, regardless of self.name - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if cpu_target == CPU_TARGET_ZEN4: - pre_module_hook_zen4_gcccore1220(self, *args, **kwargs) - - -def post_module_hook(self, *args, **kwargs): - """Main post module hook: trigger custom functions based on software name.""" - if self.name in POST_MODULE_HOOKS: - POST_MODULE_HOOKS[self.name](self, *args, **kwargs) - - # Always trigger this one, regardless of self.name - cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR') - if cpu_target == CPU_TARGET_ZEN4: - post_module_hook_zen4_gcccore1220(self, *args, **kwargs) - - -PARSE_HOOKS = { - 'casacore': parse_hook_casacore_disable_vectorize, - 'CGAL': parse_hook_cgal_toolchainopts_precise, - 'fontconfig': parse_hook_fontconfig_add_fonts, - 'FreeImage': parse_hook_freeimage_aarch64, - 'grpcio': parse_hook_grpcio_zlib, - 'OpenBLAS': parse_hook_openblas_relax_lapack_tests_num_errors, - 'pybind11': parse_hook_pybind11_replace_catch2, - 'Qt5': parse_hook_qt5_check_qtwebengine_disable, - 'UCX': parse_hook_ucx_eprefix, -} - -PRE_FETCH_HOOKS = {} - -PRE_PREPARE_HOOKS = { - 'Highway': pre_prepare_hook_highway_handle_test_compilation_issues, -} - -POST_PREPARE_HOOKS = { - 'GCCcore': post_prepare_hook_gcc_prefixed_ld_rpath_wrapper, - 'Highway': post_prepare_hook_highway_handle_test_compilation_issues, -} - -PRE_CONFIGURE_HOOKS = { - 'BLIS': pre_configure_hook_BLIS_a64fx, - 'CUDA-Samples': pre_configure_hook_CUDA_Samples_test_remove, - 'GObject-Introspection': pre_configure_hook_gobject_introspection, - 'Extrae': pre_configure_hook_extrae, - 'GROMACS': pre_configure_hook_gromacs, - 'libfabric': pre_configure_hook_libfabric_disable_psm3_x86_64_generic, - 'LLVM': pre_configure_hook_llvm, - 'ROCm-LLVM': pre_configure_hook_llvm, - 'MetaBAT': pre_configure_hook_metabat_filtered_zlib_dep, - 'OpenBLAS': pre_configure_hook_openblas_optarch_generic, - 'WRF': pre_configure_hook_wrf_aarch64, - 'LAMMPS': pre_configure_hook_LAMMPS_zen4, - 'Score-P': pre_configure_hook_score_p, - 'VSEARCH': pre_configure_hook_vsearch, -} - -PRE_TEST_HOOKS = { - 'ESPResSo': pre_test_hook_ignore_failing_tests_ESPResSo, - 'FFTW.MPI': pre_test_hook_ignore_failing_tests_FFTWMPI, - 'Highway': pre_test_hook_exclude_failing_test_Highway, - 'SciPy-bundle': pre_test_hook_ignore_failing_tests_SciPybundle, - 'netCDF': pre_test_hook_ignore_failing_tests_netCDF, - 'PyTorch': pre_test_hook_increase_max_failed_tests_arm_PyTorch, -} - -PRE_SINGLE_EXTENSION_HOOKS = { - 'isoband': pre_single_extension_isoband, - 'numpy': pre_single_extension_numpy, - 'testthat': pre_single_extension_testthat, -} - -POST_SINGLE_EXTENSION_HOOKS = { - 'numpy': post_single_extension_numpy, -} - -POST_POSTPROC_HOOKS = { - 'CUDA': post_postproc_cuda, - 'cuDNN': post_postproc_cudnn, -} - -PRE_MODULE_HOOKS = {} - -POST_MODULE_HOOKS = {} - -# Define parallelism limit operations -def divide_by_factor(parallel, factor): - """Divide parallelism by given factor""" - return max(1, parallel // factor) - -def set_maximum(parallel, max_value): - """Set parallelism to maximum value""" - return min(parallel, max_value) - -# Data structure defining parallelism limits for different software and CPU targets -# Format: {software_name: {cpu_target: (operation_function, operation_args)}} -# '*' for a CPU target means the operation applies to all CPU targets -# Information is processed in the post_ready_hook function. First it checks if the -# specific CPU target is defined in the data structure below. If not, it checks for -# the generic '*' entry. -PARALLELISM_LIMITS = { - 'libxc': { - '*': (divide_by_factor, 2), - CPU_TARGET_A64FX: (set_maximum, 12), - }, - 'nodejs': { - CPU_TARGET_A64FX: (divide_by_factor, 2), - }, - 'MBX': { - '*': (divide_by_factor, 2), - }, - 'PyTorch': { - CPU_TARGET_A64FX: (divide_by_factor, 4), - }, - 'TensorFlow': { - '*': (divide_by_factor, 2), - CPU_TARGET_A64FX: (set_maximum, 8), - }, - 'Qt5': { - CPU_TARGET_A64FX: (set_maximum, 8), - }, - 'ROOT': { - CPU_TARGET_A64FX: (divide_by_factor, 2), - }, -} diff --git a/eessi_container.sh b/eessi_container.sh deleted file mode 100755 index 906eb2cbc2..0000000000 --- a/eessi_container.sh +++ /dev/null @@ -1,917 +0,0 @@ -#!/bin/bash -# -# unified script to access EESSI in different scenarios: read-only -# for just using EESSI, read & write for building software to be -# added to the software stack -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Thomas Roeblitz (@trz42) -# -# license: GPLv2 -# - -# -e: stop script as soon as any command has non-zero exit code -# -u: treat usage of undefined variables as errors -# FIXME commented out because it's OK (?) if some environment variables are not set (like $SINGULARITY_HOME) -# set -e -u - -# script overview -# -. initial settings & exit codes -# 0. parse args -# 1. check if argument values are valid -# 2. set up host storage/tmp -# 3. set up common vars and directories -# 4. set up vars specific to a scenario -# 5. run container -# 6. save tmp (if requested) - -# -. initial settings & exit codes -TOPDIR=$(dirname $(realpath $0)) - -source "${TOPDIR}"/scripts/utils.sh -source "${TOPDIR}"/scripts/cfg_files.sh - -# exit codes: bitwise shift codes to allow for combination of exit codes -# ANY_ERROR_EXITCODE is sourced from ${TOPDIR}/scripts/utils.sh -CMDLINE_ARG_UNKNOWN_EXITCODE=$((${ANY_ERROR_EXITCODE} << 1)) -ACCESS_UNKNOWN_EXITCODE=$((${ANY_ERROR_EXITCODE} << 2)) -CONTAINER_ERROR_EXITCODE=$((${ANY_ERROR_EXITCODE} << 3)) -HOST_STORAGE_ERROR_EXITCODE=$((${ANY_ERROR_EXITCODE} << 4)) -MODE_UNKNOWN_EXITCODE=$((${ANY_ERROR_EXITCODE} << 5)) -REPOSITORY_ERROR_EXITCODE=$((${ANY_ERROR_EXITCODE} << 6)) -RESUME_ERROR_EXITCODE=$((${ANY_ERROR_EXITCODE} << 7)) -SAVE_ERROR_EXITCODE=$((${ANY_ERROR_EXITCODE} << 8)) -HTTP_PROXY_ERROR_EXITCODE=$((${ANY_ERROR_EXITCODE} << 9)) -HTTPS_PROXY_ERROR_EXITCODE=$((${ANY_ERROR_EXITCODE} << 10)) -RUN_SCRIPT_MISSING_EXITCODE=$((${ANY_ERROR_EXITCODE} << 11)) -NVIDIA_MODE_UNKNOWN_EXITCODE=$((${ANY_ERROR_EXITCODE} << 12)) - -# CernVM-FS settings -CVMFS_VAR_LIB="var-lib-cvmfs" -CVMFS_VAR_RUN="var-run-cvmfs" - -# directory for tmp used inside container -export TMP_IN_CONTAINER=/tmp - -# repository cfg directory and file -# directory: default $PWD or EESSI_REPOS_CFG_DIR_OVERRIDE if set -# file: directory + '/repos.cfg' -export EESSI_REPOS_CFG_DIR="${EESSI_REPOS_CFG_DIR_OVERRIDE:=${PWD}}" -export EESSI_REPOS_CFG_FILE="${EESSI_REPOS_CFG_DIR}/repos.cfg" - - -# 0. parse args -# see example parsing of command line arguments at -# https://wiki.bash-hackers.org/scripting/posparams#using_a_while_loop -# https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash - -display_help() { - echo "usage: $0 [OPTIONS] [[--] SCRIPT or COMMAND]" - echo " OPTIONS:" - echo " -a | --access {ro,rw} - sets access globally for all CVMFS repositories:" - echo " ro (read-only), rw (read & write) [default: ro]" - echo " -b | --extra-bind-paths - specify extra paths to be bound into the container." - echo " To specify multiple bind paths, separate by comma." - echo " Example: '/src:/dest:ro,/src2:/dest2:rw'" - echo " -c | --container IMG - image file or URL defining the container to use" - echo " [default: docker://ghcr.io/eessi/build-node:debian11]" - echo " -f | --fakeroot - run the container with --fakeroot [default: false]" - echo " -g | --storage DIR - directory space on host machine (used for" - echo " temporary data) [default: 1. TMPDIR, 2. /tmp]" - echo " -h | --help - display this usage information [default: false]" - echo " -i | --host-injections - directory to link to for host_injections " - echo " [default: /..storage../opt-eessi]" - echo " -l | --list-repos - list available repository identifiers [default: false]" - echo " -m | --mode MODE - with MODE==shell (launch interactive shell) or" - echo " MODE==run (run a script or command) [default: shell]" - echo " -n | --nvidia MODE - configure the container to work with NVIDIA GPUs," - echo " MODE==install for a CUDA installation, MODE==run to" - echo " attach a GPU, MODE==all for both [default: false]" - echo " -p | --pass-through ARG - argument to pass through to the launch of the" - echo " container; can be given multiple times [default: not set]" - echo " -r | --repository CFG - configuration file or identifier defining the" - echo " repository to use; can be given multiple times;" - echo " CFG may include a suffix ',access={ro,rw}' to" - echo " overwrite the global access mode for this repository" - echo " [default: software.eessi.io via CVMFS config available" - echo " via default container, see --container]" - echo " -u | --resume DIR/TGZ - resume a previous run from a directory or tarball," - echo " where DIR points to a previously used tmp directory" - echo " (check for output 'Using DIR as tmp ...' of a previous" - echo " run) and TGZ is the path to a tarball which is" - echo " unpacked the tmp dir stored on the local storage space" - echo " (see option --storage above) [default: not set]" - echo " -s | --save DIR/TGZ - save contents of tmp directory to a tarball in" - echo " directory DIR or provided with the fixed full path TGZ" - echo " when a directory is provided, the format of the" - echo " tarball's name will be {REPO_ID}-{TIMESTAMP}.tgz" - echo " [default: not set]" - echo " -v | --verbose - display more information [default: false]" - echo " -x | --http-proxy URL - provides URL for the env variable http_proxy" - echo " [default: not set]; uses env var \$http_proxy if set" - echo " -y | --https-proxy URL - provides URL for the env variable https_proxy" - echo " [default: not set]; uses env var \$https_proxy if set" - echo - echo " If value for --mode is 'run', the SCRIPT/COMMAND provided is executed. If" - echo " arguments to the script/command start with '-' or '--', use the flag terminator" - echo " '--' to let eessi_container.sh stop parsing arguments." -} - -# set defaults for command line arguments -ACCESS="ro" -CONTAINER="docker://ghcr.io/eessi/build-node:debian11" -#DRY_RUN=0 -FAKEROOT=0 -VERBOSE=0 -STORAGE= -LIST_REPOS=0 -MODE="shell" -PASS_THROUGH=() -SETUP_NVIDIA=0 -REPOSITORIES=() -RESUME= -SAVE= -HTTP_PROXY=${http_proxy:-} -HTTPS_PROXY=${https_proxy:-} - -POSITIONAL_ARGS=() - -while [[ $# -gt 0 ]]; do - case $1 in - -a|--access) - ACCESS="$2" - shift 2 - ;; - -b|--extra-bind-paths) - EXTRA_BIND_PATHS="$2" - shift 2 - ;; - -c|--container) - CONTAINER="$2" - shift 2 - ;; -# -d|--dry-run) -# DRY_RUN=1 -# shift 1 -# ;; - -f|--fakeroot) - FAKEROOT=1 - shift 1 - ;; - -g|--storage) - STORAGE="$2" - shift 2 - ;; - -h|--help) - display_help - exit 0 - ;; - -i|--host-injections) - USER_HOST_INJECTIONS="$2" - shift 2 - ;; - -l|--list-repos) - LIST_REPOS=1 - shift 1 - ;; - -m|--mode) - MODE="$2" - shift 2 - ;; - -n|--nvidia) - SETUP_NVIDIA=1 - NVIDIA_MODE="$2" - shift 2 - ;; - -p|--pass-through) - PASS_THROUGH+=("$2") - shift 2 - ;; - -r|--repository) - REPOSITORIES+=("$2") - shift 2 - ;; - -s|--save) - SAVE="$2" - shift 2 - ;; - -u|--resume) - RESUME="$2" - shift 2 - ;; - -v|--verbose) - VERBOSE=1 - shift 1 - ;; - -x|--http-proxy) - HTTP_PROXY="$2" - export http_proxy=${HTTP_PROXY} - shift 2 - ;; - -y|--https-proxy) - HTTPS_PROXY="$2" - export https_proxy=${HTTPS_PROXY} - shift 2 - ;; - --) - shift - POSITIONAL_ARGS+=("$@") # save positional args - break - ;; - -*|--*) - fatal_error "Unknown option: $1" "${CMDLINE_ARG_UNKNOWN_EXITCODE}" - ;; - *) # No more options - POSITIONAL_ARGS+=("$1") # save positional arg - shift - ;; - esac -done - -set -- "${POSITIONAL_ARGS[@]}" - -# define a list of CVMFS repositories that are accessible via the -# CVMFS config repository which is always mounted -# TODO instead of hard-coding the 'extra' and 'default' repositories here one -# could have another script in the GitHub and/or CVMFS repository which -# provides this "configuration" -declare -A eessi_cvmfs_repos=(["dev.eessi.io"]="extra", ["riscv.eessi.io"]="extra", ["software.eessi.io"]="default") -eessi_default_cvmfs_repo="software.eessi.io,access=${ACCESS}" - -# define a list of CVMFS repositories that are accessible via the -# configuration file provided via $EESSI_REPOS_CFG_FILE -declare -A cfg_cvmfs_repos=() -if [[ -r ${EESSI_REPOS_CFG_FILE} ]]; then - cfg_load ${EESSI_REPOS_CFG_FILE} - sections=$(cfg_sections) - while IFS= read -r repo_id - do - cfg_cvmfs_repos[${repo_id}]=${EESSI_REPOS_CFG_FILE} - done <<< "${sections}" -fi - -if [[ ${LIST_REPOS} -eq 1 ]]; then - echo "Listing available repositories with format 'name [source[, 'default']]'." - echo "Note, without argument '--repository' the one labeled 'default' will be mounted." - for cvmfs_repo in "${!eessi_cvmfs_repos[@]}" - do - if [[ ${eessi_cvmfs_repos[${cvmfs_repo}]} == "default" ]] ; then - default_label=", default" - else - default_label="" - fi - echo " ${cvmfs_repo} [CVMFS config repo${default_label}]" - done - for cfg_repo in "${!cfg_cvmfs_repos[@]}" - do - echo " ${cfg_repo} [${cfg_cvmfs_repos[$cfg_repo]}]" - done - exit 0 -fi - -# if REPOSITORIES is empty add default repository given above -if [[ ${#REPOSITORIES[@]} -eq 0 ]]; then - REPOSITORIES+=(${eessi_default_cvmfs_repo}) -fi - -# 1. check if argument values are valid -# (arg -a|--access) check if ACCESS is supported -# use the value as global setting, suffix to --repository can specify an access mode per repository -if [[ "${ACCESS}" != "ro" && "${ACCESS}" != "rw" ]]; then - fatal_error "unknown access method '${ACCESS}'" "${ACCESS_UNKNOWN_EXITCODE}" -fi - -# TODO (arg -c|--container) check container (is it a file or URL & access those) -# CONTAINER_ERROR_EXITCODE - -# TODO (arg -g|--storage) check if it exists, if user has write permission, -# if it contains no data, etc. -# HOST_STORAGE_ERROR_EXITCODE - -# (arg -m|--mode) check if MODE is known -if [[ "${MODE}" != "shell" && "${MODE}" != "run" ]]; then - fatal_error "unknown execution mode '${MODE}'" "${MODE_UNKNOWN_EXITCODE}" -fi - -# Also validate the NVIDIA GPU mode (if present) -if [[ ${SETUP_NVIDIA} -eq 1 ]]; then - if [[ "${NVIDIA_MODE}" != "run" && "${NVIDIA_MODE}" != "install" && "${NVIDIA_MODE}" != "all" ]]; then - fatal_error "unknown NVIDIA mode '${NVIDIA_MODE}'" "${NVIDIA_MODE_UNKNOWN_EXITCODE}" - fi -fi - -# TODO (arg -r|--repository) check if all explicitly listed repositories are known -# REPOSITORY_ERROR_EXITCODE -# iterate over entries in REPOSITORIES and check if they are known -for cvmfs_repo in "${REPOSITORIES[@]}" -do - # split into name and access mode if ',access=' in $cvmfs_repo - if [[ ${cvmfs_repo} == *",access="* ]] ; then - cvmfs_repo_name=${cvmfs_repo/,access=*/} # remove access mode specification - else - cvmfs_repo_name="${cvmfs_repo}" - fi - if [[ ! -n "${eessi_cvmfs_repos[${cvmfs_repo_name}]}" && ! -n ${cfg_cvmfs_repos[${cvmfs_repo_name}]} ]]; then - fatal_error "The repository '${cvmfs_repo_name}' is not an EESSI CVMFS repository or it is not known how to mount it (could be due to a typo or missing configuration). Run '$0 -l' to obtain a list of available repositories." "${REPOSITORY_ERROR_EXITCODE}" - fi -done - -# make sure each repository is only listed once -declare -A listed_repos=() -for cvmfs_repo in "${REPOSITORIES[@]}" -do - cvmfs_repo_name=${cvmfs_repo/,access=*/} # remove access mode - [[ ${VERBOSE} -eq 1 ]] && echo "checking for duplicates: '${cvmfs_repo}' and '${cvmfs_repo_name}'" - # if cvmfs_repo_name is not in eessi_cvmfs_repos, assume it's in cfg_cvmfs_repos - # and obtain actual repo_name from config - cfg_repo_id='' - if [[ ! -n "${eessi_cvmfs_repos[${cvmfs_repo_name}]}" ]] ; then - [[ ${VERBOSE} -eq 1 ]] && echo "repo '${cvmfs_repo_name}' is not an EESSI CVMFS repository..." - # cvmfs_repo_name is actually a repository ID, use that to obtain - # the actual name from the EESSI_REPOS_CFG_FILE - cfg_repo_id=${cvmfs_repo_name} - cvmfs_repo_name=$(cfg_get_value ${cfg_repo_id} "repo_name") - fi - if [[ -n "${listed_repos[${cvmfs_repo_name}]}" ]] ; then - via_cfg="" - if [[ -n "${cfg_repo_id}" ]] ; then - via_cfg=" (via repository ID '${cfg_repo_id}')" - fi - fatal_error "CVMFS repository '${cvmfs_repo_name}'${via_cfg} listed multiple times" - fi - listed_repos+=([${cvmfs_repo_name}]=true) -done - -# TODO (arg -u|--resume) check if it exists, if user has read permission, -# if it contains data from a previous run -# RESUME_ERROR_EXITCODE - -# TODO (arg -s|--save) check if DIR exists, if user has write permission, -# if TGZ already exists, if user has write permission to directory to which -# TGZ should be written -# SAVE_ERROR_EXITCODE - -# TODO (arg -x|--http-proxy) check if http proxy is accessible -# HTTP_PROXY_ERROR_EXITCODE - -# TODO (arg -y|--https-proxy) check if https proxy is accessible -# HTTPS_PROXY_ERROR_EXITCODE - -# check if a script is provided if mode is 'run' -if [[ "${MODE}" == "run" ]]; then - if [[ $# -eq 0 ]]; then - fatal_error "no command specified to run?!" "${RUN_SCRIPT_MISSING_EXITCODE}" - fi -fi - - -# 2. set up host storage/tmp if necessary -# if session to be resumed from a previous one (--resume ARG) and ARG is a directory -# just reuse ARG, define environment variables accordingly and skip creating a new -# tmp storage -if [[ ! -z ${RESUME} && -d ${RESUME} ]]; then - # resume from directory ${RESUME} - # skip creating a new tmp directory, just set environment variables - echo "Resuming from previous run using temporary storage at ${RESUME}" - EESSI_HOST_STORAGE=${RESUME} -else - # we need a tmp location (and possibly init it with ${RESUME} if it was not - # a directory - - # as location for temporary data use in the following order - # a. command line argument -l|--host-storage - # b. env var TMPDIR - # c. /tmp - # note, we ensure that (a) takes precedence by setting TMPDIR to STORAGE - # if STORAGE is not empty - # note, (b) & (c) are automatically ensured by using 'mktemp -d --tmpdir' to - # create a temporary directory - if [[ ! -z ${STORAGE} ]]; then - export TMPDIR=${STORAGE} - # mktemp fails if TMPDIR does not exist, so let's create it - mkdir -p ${TMPDIR} - fi - if [[ ! -z ${TMPDIR} ]]; then - # TODO check if TMPDIR already exists - # mktemp fails if TMPDIR does not exist, so let's create it - mkdir -p ${TMPDIR} - fi - if [[ -z ${TMPDIR} ]]; then - # mktemp falls back to using /tmp if TMPDIR is empty - # TODO check if /tmp is writable, large enough and usable (different - # features for ro-access and rw-access) - [[ ${VERBOSE} -eq 1 ]] && echo "skipping sanity checks for /tmp" - fi - EESSI_HOST_STORAGE=$(mktemp -d --tmpdir eessi.XXXXXXXXXX) - echo "Using ${EESSI_HOST_STORAGE} as tmp directory (to resume session add '--resume ${EESSI_HOST_STORAGE}')." -fi - -# if ${RESUME} is a file, unpack it into ${EESSI_HOST_STORAGE} -if [[ ! -z ${RESUME} && -f ${RESUME} ]]; then - if [[ "${RESUME}" == *.tgz ]]; then - tar xf ${RESUME} -C ${EESSI_HOST_STORAGE} - # Add support for resuming from zstd-compressed tarballs - elif [[ "${RESUME}" == *.zst && -x "$(command -v zstd)" ]]; then - zstd -dc ${RESUME} | tar -xf - -C ${EESSI_HOST_STORAGE} - elif [[ "${RESUME}" == *.zst && ! -x "$(command -v zstd)" ]]; then - fatal_error "Trying to resume from tarball ${RESUME} which was compressed using zstd, but zstd command not found" - fi - echo "Resuming from previous run using temporary storage ${RESUME} unpacked into ${EESSI_HOST_STORAGE}" -fi - -# if ${RESUME} is a file (assume a tgz), unpack it into ${EESSI_HOST_STORAGE} -if [[ ! -z ${RESUME} && -f ${RESUME} ]]; then - tar xf ${RESUME} -C ${EESSI_HOST_STORAGE} - echo "Resuming from previous run using temporary storage ${RESUME} unpacked into ${EESSI_HOST_STORAGE}" -fi - -# 3. set up common vars and directories -# directory structure should be: -# ${EESSI_HOST_STORAGE} -# |-singularity_cache -# |-home -# |-repos_cfg -# |-${CVMFS_VAR_LIB} -# |-${CVMFS_VAR_RUN} -# |-CVMFS_REPO_1 -# | |-repo_settings.sh (name, id, access, host_injections) -# | |-overlay-upper -# | |-overlay-work -# | |-opt-eessi (unless otherwise specificed for host_injections) -# |-CVMFS_REPO_n -# |-repo_settings.sh (name, id, access, host_injections) -# |-overlay-upper -# |-overlay-work -# |-opt-eessi (unless otherwise specificed for host_injections) - -# tmp dir for EESSI -EESSI_TMPDIR=${EESSI_HOST_STORAGE} -mkdir -p ${EESSI_TMPDIR} -[[ ${VERBOSE} -eq 1 ]] && echo "EESSI_TMPDIR=${EESSI_TMPDIR}" - -# TODO make this specific to repository? -# TODO move this code to when we already know which repositories we want to access -# actually we should know this already here, but we should rather move this to -# where repository args are being processed -# Set host_injections directory and ensure it is a writable directory (if user provided) -if [ -z ${USER_HOST_INJECTIONS+x} ]; then - # Not set, so use our default - HOST_INJECTIONS=${EESSI_TMPDIR}/opt-eessi - mkdir -p $HOST_INJECTIONS -else - # Make sure the host_injections directory specified exists and is a folder - mkdir -p ${USER_HOST_INJECTIONS} || fatal_error "host_injections directory ${USER_HOST_INJECTIONS} is either not a directory or cannot be created" - HOST_INJECTIONS=${USER_HOST_INJECTIONS} -fi -[[ ${VERBOSE} -eq 1 ]] && echo "HOST_INJECTIONS=${HOST_INJECTIONS}" - -# configure Singularity: if SINGULARITY_CACHEDIR is already defined, use that -# a global SINGULARITY_CACHEDIR would ensure that we don't consume -# storage space again and again for the container & also speed-up -# launch times across different sessions -if [[ -z ${SINGULARITY_CACHEDIR} ]]; then - export SINGULARITY_CACHEDIR=${EESSI_TMPDIR}/singularity_cache - mkdir -p ${SINGULARITY_CACHEDIR} -fi -[[ ${VERBOSE} -eq 1 ]] && echo "SINGULARITY_CACHEDIR=${SINGULARITY_CACHEDIR}" - -# if VERBOSE is set to 0 (no arg --verbose), add argument '-q' -if [[ ${VERBOSE} -eq 0 ]]; then - RUN_QUIET='-q' -else - RUN_QUIET='' -fi - -# we try our best to make sure that we retain access to the container image in -# a subsequent session ("best effort" only because pulling or copying operations -# can fail ... in those cases the script may still succeed, but it is not -# guaranteed that we have access to the same container when resuming later on) -# - if CONTAINER references an image in a registry, pull & convert image -# and store it in ${EESSI_TMPDIR} -# + however, only pull image if there is no matching image in ${EESSI_TMPDIR} yet -# - if CONTAINER references an image file, copy it to ${EESSI_TMPDIR} -# + however, only copy it if its base name does not yet exist in ${EESSI_TMPDIR} -# - if the image file created (pulled or copied) or resumed exists in -# ${EESSI_TMPDIR}, let CONTAINER point to it -# + thus subsequent singularity commands in this script would just use the -# image file in EESSI_TMPDIR or the originally given source (some URL or -# path to an image file) -CONTAINER_IMG= -CONTAINER_URL_FMT=".*://(.*)" -if [[ ${CONTAINER} =~ ${CONTAINER_URL_FMT} ]]; then - # replace ':', '-', '/' with '_' in match (everything after ://) and append .sif - CONTAINER_IMG="$(echo ${BASH_REMATCH[1]} | sed 's/[:\/-]/_/g').sif" - # pull container to ${EESSI_TMPDIR} if it is not there yet (i.e. when - # resuming from a previous session) - if [[ ! -x ${EESSI_TMPDIR}/${CONTAINER_IMG} ]]; then - echo "Pulling container image from ${CONTAINER} to ${EESSI_TMPDIR}/${CONTAINER_IMG}" - singularity ${RUN_QUIET} pull ${EESSI_TMPDIR}/${CONTAINER_IMG} ${CONTAINER} - else - echo "Reusing existing container image ${EESSI_TMPDIR}/${CONTAINER_IMG}" - fi -else - # determine file name as basename of CONTAINER - CONTAINER_IMG=$(basename ${CONTAINER}) - # copy image file to ${EESSI_TMPDIR} if it is not there yet (i.e. when - # resuming from a previous session) - if [[ ! -x ${EESSI_TMPDIR}/${CONTAINER_IMG} ]]; then - echo "Copying container image from ${CONTAINER} to ${EESSI_TMPDIR}/${CONTAINER_IMG}" - cp -a ${CONTAINER} ${EESSI_TMPDIR}/. - else - echo "Reusing existing container image ${EESSI_TMPDIR}/${CONTAINER_IMG}" - fi -fi -# let CONTAINER point to the pulled, copied or resumed image file -if [[ -x ${EESSI_TMPDIR}/${CONTAINER_IMG} ]]; then - CONTAINER="${EESSI_TMPDIR}/${CONTAINER_IMG}" -fi -[[ ${VERBOSE} -eq 1 ]] && echo "CONTAINER=${CONTAINER}" - -# set env vars and create directories for CernVM-FS -EESSI_CVMFS_VAR_LIB=${EESSI_TMPDIR}/${CVMFS_VAR_LIB} -EESSI_CVMFS_VAR_RUN=${EESSI_TMPDIR}/${CVMFS_VAR_RUN} -mkdir -p ${EESSI_CVMFS_VAR_LIB} -mkdir -p ${EESSI_CVMFS_VAR_RUN} -[[ ${VERBOSE} -eq 1 ]] && echo "EESSI_CVMFS_VAR_LIB=${EESSI_CVMFS_VAR_LIB}" -[[ ${VERBOSE} -eq 1 ]] && echo "EESSI_CVMFS_VAR_RUN=${EESSI_CVMFS_VAR_RUN}" - -# allow that SINGULARITY_HOME is defined before script is run -if [[ -z ${SINGULARITY_HOME} ]]; then - export SINGULARITY_HOME="${EESSI_TMPDIR}/home:/home/${USER}" - mkdir -p ${EESSI_TMPDIR}/home -fi -[[ ${VERBOSE} -eq 1 ]] && echo "SINGULARITY_HOME=${SINGULARITY_HOME}" - -# define paths to add to SINGULARITY_BIND (added later when all BIND mounts are defined) -BIND_PATHS="${EESSI_CVMFS_VAR_LIB}:/var/lib/cvmfs,${EESSI_CVMFS_VAR_RUN}:/var/run/cvmfs,${HOST_INJECTIONS}:/opt/eessi" - -# provide a '/tmp' inside the container -BIND_PATHS="${BIND_PATHS},${EESSI_TMPDIR}:${TMP_IN_CONTAINER}" - -# if TMPDIR is not empty and if TMP_IN_CONTAINER is not a prefix of TMPDIR, we need to add a bind mount for TMPDIR -if [[ ! -z ${TMPDIR} && ${TMP_IN_CONTAINER} != ${TMPDIR}* ]]; then - msg="TMPDIR is not empty (${TMPDIR}) and TMP_IN_CONTAINER (${TMP_IN_CONTAINER}) is not a prefix of TMPDIR:" - msg="${msg} adding bind mount for TMPDIR" - echo "${msg}" - BIND_PATHS="${BIND_PATHS},${TMPDIR}" -fi - -if [[ ! -z ${EXTRA_BIND_PATHS} ]]; then - BIND_PATHS="${BIND_PATHS},${EXTRA_BIND_PATHS}" -fi - -[[ ${VERBOSE} -eq 1 ]] && echo "BIND_PATHS=${BIND_PATHS}" - -declare -a ADDITIONAL_CONTAINER_OPTIONS=() - -# Configure anything we need for NVIDIA GPUs and CUDA installation -if [[ ${SETUP_NVIDIA} -eq 1 ]]; then - if [[ "${NVIDIA_MODE}" == "run" || "${NVIDIA_MODE}" == "all" ]]; then - # Give singularity the appropriate flag - ADDITIONAL_CONTAINER_OPTIONS+=("--nv") - [[ ${VERBOSE} -eq 1 ]] && echo "ADDITIONAL_CONTAINER_OPTIONS=${ADDITIONAL_CONTAINER_OPTIONS[@]}" - fi - if [[ "${NVIDIA_MODE}" == "install" || "${NVIDIA_MODE}" == "all" ]]; then - # Add additional bind mounts to allow CUDA to install within a container - # (Experience tells us that these are necessary, but we don't know _why_ - # as the CUDA installer is a black box. The suspicion is that the CUDA - # installer gets confused by the permissions on these directories when - # inside a container) - EESSI_VAR_LOG=${EESSI_TMPDIR}/var-log - EESSI_USR_LOCAL_CUDA=${EESSI_TMPDIR}/usr-local-cuda - mkdir -p ${EESSI_VAR_LOG} - mkdir -p ${EESSI_USR_LOCAL_CUDA} - BIND_PATHS="${BIND_PATHS},${EESSI_VAR_LOG}:/var/log,${EESSI_USR_LOCAL_CUDA}:/usr/local/cuda" - [[ ${VERBOSE} -eq 1 ]] && echo "BIND_PATHS=${BIND_PATHS}" - if [[ "${NVIDIA_MODE}" == "install" ]] ; then - # No GPU so we need to "trick" Lmod to allow us to load CUDA modules even without a CUDA driver - # (this variable means EESSI_OVERRIDE_GPU_CHECK=1 will be set inside the container) - export SINGULARITYENV_EESSI_OVERRIDE_GPU_CHECK=1 - fi - fi -fi - -# Configure the fakeroot setting for the container -if [[ ${FAKEROOT} -eq 1 ]]; then - ADDITIONAL_CONTAINER_OPTIONS+=("--fakeroot") -fi - -# set up repository config (always create directory repos_cfg and populate it with info when -# arg -r|--repository is used) -mkdir -p ${EESSI_TMPDIR}/repos_cfg -[[ ${VERBOSE} -eq 1 ]] && echo -[[ ${VERBOSE} -eq 1 ]] && echo -e "BIND_PATHS before processing REPOSITORIES\n BIND_PATHS=${BIND_PATHS}" -[[ ${VERBOSE} -eq 1 ]] && echo -# iterate over repositories in array REPOSITORIES -for cvmfs_repo in "${REPOSITORIES[@]}" -do - [[ ${VERBOSE} -eq 1 ]] && echo "process CVMFS repo spec '${cvmfs_repo}'" - # split into name and access mode if ',access=' in $cvmfs_repo - if [[ ${cvmfs_repo} == *",access="* ]] ; then - cvmfs_repo_name=${cvmfs_repo/,access=*/} # remove access mode specification - cvmfs_repo_access=${cvmfs_repo/*,access=/} # remove repo name part - else - cvmfs_repo_name="${cvmfs_repo}" - cvmfs_repo_access="${ACCESS}" # use globally defined access mode - fi - # if cvmfs_repo_name is in cfg_cvmfs_repos, it is a "repository ID" and was - # derived from information in EESSI_REPOS_CFG_FILE, namely the section - # names in that .ini-type file - # in the if-block below, we'll use cfg_repo_id to refer to that ID - # we need to process/provide the config from EESSI_REPOS_CFG_FILE, such - # that the necessary information for accessing a CVMFS repository is made - # available inside the container - if [[ -n "${cfg_cvmfs_repos[${cvmfs_repo_name}]}" ]] ; then - cfg_repo_id=${cvmfs_repo_name} - - # obtain CVMFS repository name from section for the given ID - cfg_repo_name=$(cfg_get_value ${cfg_repo_id} "repo_name") - # derive domain part from (cfg_)repo_name (everything after first '.') - repo_name_domain=${repo_name#*.} - - # cfg_cvmfs_repos is populated through reading the file pointed to by - # EESSI_REPOS_CFG_FILE. We need to copy that file and data it needs - # into the job's working directory. - - # copy repos.cfg to job directory --> makes it easier to inspect the job - cp -a ${EESSI_REPOS_CFG_FILE} ${EESSI_TMPDIR}/repos_cfg/. - - # cfg file should include sections (one per CVMFS repository to be mounted) - # with each section containing the settings: - # - repo_name, - # - repo_version, - # - config_bundle, and - # - a map { filepath_in_bundle -> container_filepath } - # - # The config_bundle includes the files which are mapped ('->') to a target - # location in container: - # - default.local -> /etc/cvmfs/default.local - # contains CVMFS settings, e.g., CVMFS_HTTP_PROXY, CVMFS_QUOTA_LIMIT, ... - # - ${repo_name_domain}.conf -> /etc/cvmfs/domain.d/${repo_name_domain}.conf - # contains CVMFS settings, e.g., CVMFS_SERVER_URL (Stratum 1s), - # CVMFS_KEYS_DIR, CVMFS_USE_GEOAPI, ... - # - ${repo_name_domain}/ -> /etc/cvmfs/keys/${repo_name_domain} - # a directory that contains the public key to access the repository, key - # itself then doesn't need to be BIND mounted - # - ${repo_name_domain}/${cfg_repo_name}.pub - # (-> /etc/cvmfs/keys/${repo_name_domain}/${cfg_repo_name}.pub - # the public key to access the repository, key itself is BIND mounted - # via directory ${repo_name_domain} - cfg_repo_version=$(cfg_get_value ${cfg_repo_id} "repo_version") - cfg_config_bundle=$(cfg_get_value ${cfg_repo_id} "config_bundle") - cfg_config_map=$(cfg_get_value ${cfg_repo_id} "config_map") - - # convert cfg_config_map into associative array cfg_file_map - cfg_init_file_map "${cfg_config_map}" - [[ ${VERBOSE} -eq 1 ]] && cfg_print_map - - # use information to set up dir ${EESSI_TMPDIR}/repos_cfg and define - # BIND mounts - # check if config_bundle exists, if so, unpack it into - # ${EESSI_TMPDIR}/repos_cfg; if it doesn't, exit with an error - # if config_bundle is relative path (no '/' at start) prepend it with - # EESSI_REPOS_CFG_DIR - config_bundle_path= - if [[ ! "${cfg_config_bundle}" =~ ^/ ]]; then - config_bundle_path=${EESSI_REPOS_CFG_DIR}/${cfg_config_bundle} - else - config_bundle_path=${cfg_config_bundle} - fi - - if [[ ! -r ${config_bundle_path} ]]; then - fatal_error "config bundle '${config_bundle_path}' is not readable" ${REPOSITORY_ERROR_EXITCODE} - fi - - # only unpack cfg_config_bundle if we're not resuming from a previous run - if [[ -z ${RESUME} ]]; then - tar xf ${config_bundle_path} -C ${EESSI_TMPDIR}/repos_cfg - fi - - for src in "${!cfg_file_map[@]}" - do - target=${cfg_file_map[${src}]} - # if target is alreay BIND mounted, exit with an error - if [[ ${BIND_PATHS} =~ "${target}" ]]; then - fatal_error "target '${target}' is already listed in paths to bind mount into the container ('${BIND_PATHS}')" ${REPOSITORY_ERROR_EXITCODE} - fi - BIND_PATHS="${BIND_PATHS},${EESSI_TMPDIR}/repos_cfg/${src}:${target}" - done - fi - [[ ${VERBOSE} -eq 1 ]] && echo -e "BIND_PATHS after processing '${cvmfs_repo}'\n BIND_PATHS=${BIND_PATHS}" - [[ ${VERBOSE} -eq 1 ]] && echo -done - -# if http_proxy is not empty, we assume that the machine accesses internet -# via a proxy. then we need to add CVMFS_HTTP_PROXY to -# ${EESSI_TMPDIR}/repos_cfg/default.local on the host (and possibly add a BIND -# MOUNT if it was not yet in BIND_PATHS) -if [[ ! -z ${http_proxy} ]]; then - # TODO tolerate other formats for proxy URLs, for now assume format is - # http://SOME_HOSTNAME:SOME_PORT/ - [[ ${VERBOSE} -eq 1 ]] && echo "http_proxy='${http_proxy}'" - PROXY_HOST=$(get_host_from_url ${http_proxy}) - [[ ${VERBOSE} -eq 1 ]] && echo "PROXY_HOST='${PROXY_HOST}'" - PROXY_PORT=$(get_port_from_url ${http_proxy}) - [[ ${VERBOSE} -eq 1 ]] && echo "PROXY_PORT='${PROXY_PORT}'" - HTTP_PROXY_IPV4=$(get_ipv4_address ${PROXY_HOST}) - [[ ${VERBOSE} -eq 1 ]] && echo "HTTP_PROXY_IPV4='${HTTP_PROXY_IPV4}'" - echo "CVMFS_HTTP_PROXY=\"${http_proxy}|http://${HTTP_PROXY_IPV4}:${PROXY_PORT}\"" \ - >> ${EESSI_TMPDIR}/repos_cfg/default.local - [[ ${VERBOSE} -eq 1 ]] && echo "contents of default.local" - [[ ${VERBOSE} -eq 1 ]] && cat ${EESSI_TMPDIR}/repos_cfg/default.local - - # if default.local is not BIND mounted into container, add it to BIND_PATHS - src=${EESSI_TMPDIR}/repos_cfg/default.local - target=/etc/cvmfs/default.local - if [[ ${BIND_PATHS} =~ "${target}" ]]; then - fatal_error "BIND target in '${src}:${target}' is already in paths to be bind mounted into the container ('${BIND_PATHS}')" ${REPOSITORY_ERROR_EXITCODE} - fi - BIND_PATHS="${BIND_PATHS},${src}:${target}" -fi - -# 4. set up vars and dirs specific to a scenario - -declare -a EESSI_FUSE_MOUNTS=() - -# mount cvmfs-config repo (to get access to EESSI repositories such as software.eessi.io) unless env var -# EESSI_DO_NOT_MOUNT_CVMFS_CONFIG_CERN_CH is defined -if [ -z ${EESSI_DO_NOT_MOUNT_CVMFS_CONFIG_CERN_CH+x} ]; then - EESSI_FUSE_MOUNTS+=("--fusemount" "container:cvmfs2 cvmfs-config.cern.ch /cvmfs/cvmfs-config.cern.ch") -fi - - -# iterate over REPOSITORIES and either use repository-specific access mode or global setting (possibly a global default) -for cvmfs_repo in "${REPOSITORIES[@]}" -do - unset cfg_repo_id - [[ ${VERBOSE} -eq 1 ]] && echo "add fusemount options for CVMFS repo '${cvmfs_repo}'" - # split into name and access mode if ',access=' in $cvmfs_repo - if [[ ${cvmfs_repo} == *",access="* ]] ; then - cvmfs_repo_name=${cvmfs_repo/,access=*/} # remove access mode specification - cvmfs_repo_access=${cvmfs_repo/*,access=/} # remove repo name part - else - cvmfs_repo_name="${cvmfs_repo}" - cvmfs_repo_access="${ACCESS}" # use globally defined access mode - fi - # obtain cvmfs_repo_name from EESSI_REPOS_CFG_FILE if cvmfs_repo is in cfg_cvmfs_repos - if [[ ${cfg_cvmfs_repos[${cvmfs_repo_name}]} ]]; then - [[ ${VERBOSE} -eq 1 ]] && echo "repo '${cvmfs_repo_name}' is not an EESSI CVMFS repository..." - # cvmfs_repo_name is actually a repository ID, use that to obtain - # the actual name from the EESSI_REPOS_CFG_FILE - cfg_repo_id=${cvmfs_repo_name} - cvmfs_repo_name=$(cfg_get_value ${cfg_repo_id} "repo_name") - fi - # remove project subdir in container - cvmfs_repo_name=${cvmfs_repo_name%"/${EESSI_DEV_PROJECT}"} - - # always create a directory for the repository (e.g., to store settings, ...) - mkdir -p ${EESSI_TMPDIR}/${cvmfs_repo_name} - - # add fusemount options depending on requested access mode ('ro' - read-only; 'rw' - read & write) - if [[ ${cvmfs_repo_access} == "ro" ]] ; then - # need to distinguish between basic "ro" access and "ro" after a "rw" session - if [[ -d ${EESSI_TMPDIR}/${cvmfs_repo_name}/overlay-upper ]]; then - # the overlay-upper directory is only created in a read-write-session, thus - # we are resuming from such a session here (otherwise there shouldn't be such - # directory yet as it is only created for read-write-sessions a bit further - # below); the overlay-upper directory can only exist because it is part of - # the ${RESUME} directory or tarball - # to be able to see the contents of the read-write session we have to mount - # the fuse-overlayfs (in read-only mode) on top of the CernVM-FS repository - - echo "While processing '${cvmfs_repo_name}' to be mounted 'read-only' we detected an overlay-upper" - echo " directory (${EESSI_TMPDIR}/${cvmfs_repo_name}/overlay-upper) likely from a previous" - echo " session. Will use it as left-most directory in 'lowerdir' argument for fuse-overlayfs." - - # make the target CernVM-FS repository available under /cvmfs_ro - export EESSI_READONLY="container:cvmfs2 ${cvmfs_repo_name} /cvmfs_ro/${cvmfs_repo_name}" - - EESSI_FUSE_MOUNTS+=("--fusemount" "${EESSI_READONLY}") - - # now, put the overlay-upper read-only on top of the repo and make it available under the usual prefix /cvmfs - EESSI_READONLY_OVERLAY="container:fuse-overlayfs" - # The contents of the previous session are available under - # ${EESSI_TMPDIR} which is bind mounted to ${TMP_IN_CONTAINER}. - # Hence, we have to use ${TMP_IN_CONTAINER}/${cvmfs_repo_name}/overlay-upper - # the left-most directory given for the lowerdir argument is put on top, - # and with no upperdir=... the whole overlayfs is made available read-only - EESSI_READONLY_OVERLAY+=" -o lowerdir=${TMP_IN_CONTAINER}/${cvmfs_repo_name}/overlay-upper:/cvmfs_ro/${cvmfs_repo_name}" - EESSI_READONLY_OVERLAY+=" /cvmfs/${cvmfs_repo_name}" - export EESSI_READONLY_OVERLAY - - EESSI_FUSE_MOUNTS+=("--fusemount" "${EESSI_READONLY_OVERLAY}") - export EESSI_FUSE_MOUNTS - else - # basic "ro" access that doesn't require any fuseoverlay-fs - echo "Mounting '${cvmfs_repo_name}' 'read-only' without fuse-overlayfs." - - export EESSI_READONLY="container:cvmfs2 ${cvmfs_repo_name} /cvmfs/${cvmfs_repo_name}" - - EESSI_FUSE_MOUNTS+=("--fusemount" "${EESSI_READONLY}") - export EESSI_FUSE_MOUNTS - fi - elif [[ ${cvmfs_repo_access} == "rw" ]] ; then - # use repo-specific overlay directories - mkdir -p ${EESSI_TMPDIR}/${cvmfs_repo_name}/overlay-upper${EESSI_DEV_PROJECT:+/$EESSI_DEV_PROJECT} - mkdir -p ${EESSI_TMPDIR}/${cvmfs_repo_name}/overlay-work${EESSI_DEV_PROJECT:+/$EESSI_DEV_PROJECT} - - [[ ${VERBOSE} -eq 1 ]] && echo -e "TMP directory contents:\n$(ls -l ${EESSI_TMPDIR})" - - # set environment variables for fuse mounts in Singularity container - export EESSI_READONLY="container:cvmfs2 ${cvmfs_repo_name} /cvmfs_ro/${cvmfs_repo_name}" - - EESSI_FUSE_MOUNTS+=("--fusemount" "${EESSI_READONLY}") - - EESSI_WRITABLE_OVERLAY="container:fuse-overlayfs" - EESSI_WRITABLE_OVERLAY+=" -o lowerdir=/cvmfs_ro/${cvmfs_repo_name}" - EESSI_WRITABLE_OVERLAY+=" -o upperdir=${TMP_IN_CONTAINER}/${cvmfs_repo_name}/overlay-upper" - EESSI_WRITABLE_OVERLAY+=" -o workdir=${TMP_IN_CONTAINER}/${cvmfs_repo_name}/overlay-work" - EESSI_WRITABLE_OVERLAY+=" /cvmfs/${cvmfs_repo_name}" - export EESSI_WRITABLE_OVERLAY - - EESSI_FUSE_MOUNTS+=("--fusemount" "${EESSI_WRITABLE_OVERLAY}") - export EESSI_FUSE_MOUNTS - else - echo -e "ERROR: access mode '${cvmfs_repo_access}' for CVMFS repository\n '${cvmfs_repo_name}' is not known" - exit ${REPOSITORY_ERROR_EXITCODE} - fi - # create repo_settings.sh file in ${EESSI_TMPDIR}/${cvmfs_repo_name} to store - # (intention is that the file could be just sourced to obtain the settings) - # repo_name = ${cvmfs_repo_name} - # repo_id = ${cfg_repo_id} # empty if not an EESSI repo - # repo_access = ${cvmfs_repo_access} - # repo_host_injections = [ {"src_path":"target_path"}... ] # TODO - settings= - #[[ -n ${cfg_repo_id} ]] && settings="[${cvmfs_repo_name}]\n" || settings="[${cfg_repo_id}]\n" - settings="${settings}repo_name = ${cvmfs_repo_name}\n" - settings="${settings}repo_id = ${cfg_repo_id}\n" - settings="${settings}repo_access = ${cvmfs_repo_access}\n" - # TODO iterate over host_injections (first need means to define them (globally and/or per repository) - # settings="${settings}repo_host_injections = ${host_injections}\n" - echo -e "${settings}" > ${EESSI_TMPDIR}/${cvmfs_repo_name}/repo_settings.sh -done - -# 5. run container -# final settings -if [[ -z ${SINGULARITY_BIND} ]]; then - export SINGULARITY_BIND="${BIND_PATHS}" -else - export SINGULARITY_BIND="${SINGULARITY_BIND},${BIND_PATHS}" -fi -[[ ${VERBOSE} -eq 1 ]] && echo "SINGULARITY_BIND=${SINGULARITY_BIND}" - -# pass $EESSI_SOFTWARE_SUBDIR_OVERRIDE into build container (if set) -if [ ! -z ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} ]; then - export SINGULARITYENV_EESSI_SOFTWARE_SUBDIR_OVERRIDE=${EESSI_SOFTWARE_SUBDIR_OVERRIDE} - # also specify via $APPTAINERENV_* (future proof, cfr. https://apptainer.org/docs/user/latest/singularity_compatibility.html#singularity-environment-variable-compatibility) - export APPTAINERENV_EESSI_SOFTWARE_SUBDIR_OVERRIDE=${EESSI_SOFTWARE_SUBDIR_OVERRIDE} -fi - -# add pass through arguments -for arg in "${PASS_THROUGH[@]}"; do - ADDITIONAL_CONTAINER_OPTIONS+=(${arg}) -done - -echo "Launching container with command (next line):" -echo "singularity ${RUN_QUIET} ${MODE} ${ADDITIONAL_CONTAINER_OPTIONS[@]} ${EESSI_FUSE_MOUNTS[@]} ${CONTAINER} $@" -singularity ${RUN_QUIET} ${MODE} "${ADDITIONAL_CONTAINER_OPTIONS[@]}" "${EESSI_FUSE_MOUNTS[@]}" ${CONTAINER} "$@" -exit_code=$? - -# 6. save tmp if requested (arg -s|--save) -if [[ ! -z ${SAVE} ]]; then - # Note, for now we don't try to be smart and record in any way the OS and - # ARCH which might have been used internally, eg, when software packages - # were built ... we rather keep the script here "stupid" and leave the handling - # of these aspects to where the script is used - # Compression with zlib may be quite slow. On some systems, the pipeline takes ~20 mins for a 2 min build because of this. - # Check if zstd is present for faster compression and decompression - if [[ -d ${SAVE} ]]; then - # assume SAVE is name of a directory to which tarball shall be written to - # name format: tmp_storage-{TIMESTAMP}.tgz - ts=$(date +%s) - if [[ -x "$(command -v zstd)" ]]; then - TARBALL=${SAVE}/tmp_storage-${ts}.zst - tar -cf - -C ${EESSI_TMPDIR} . | zstd -T0 > ${TARBALL} - else - TARBALL=${SAVE}/tmp_storage-${ts}.tgz - tar czf ${TARBALL} -C ${EESSI_TMPDIR} . - fi - else - # assume SAVE is the full path to a tarball's name - TARBALL=${SAVE} - # if zstd is present and a .zst extension is asked for, use it - if [[ "${SAVE}" == *.zst && -x "$(command -v zstd)" ]]; then - tar -cf - -C ${EESSI_TMPDIR} . | zstd -T0 > ${TARBALL} - else - tar czf ${TARBALL} -C ${EESSI_TMPDIR} - fi - fi - echo "Saved contents of tmp directory '${EESSI_TMPDIR}' to tarball '${TARBALL}' (to resume session add '--resume ${TARBALL}')" -fi - -# TODO clean up tmp by default? only retain if another option provided (--retain-tmp) - -# use exit code of container command -exit ${exit_code} diff --git a/eessi_software_subdir.py b/eessi_software_subdir.py deleted file mode 100755 index af9df722d9..0000000000 --- a/eessi_software_subdir.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 -# -# Determine EESSI software subdirectory to use for current build host, using archspec -# -import os -import argparse -from archspec.cpu.detect import compatible_microarchitectures, raw_info_dictionary - -software_subdir = os.getenv('EESSI_SOFTWARE_SUBDIR_OVERRIDE') -if software_subdir is None: - - parser = argparse.ArgumentParser(description='Determine EESSI software subdirectory to use for current build host.') - parser.add_argument('--generic', dest='generic', action='store_true', - default=False, help='Use generic for CPU name.') - args = parser.parse_args() - - # we can't directly use archspec.cpu.host(), because we may get back a virtual microarchitecture like x86_64_v3... - def sorting_fn(item): - """Helper function to sort compatible microarchitectures.""" - return len(item.ancestors), len(item.features) - - raw_cpu_info = raw_info_dictionary() - compat_targets = compatible_microarchitectures(raw_cpu_info) - - # filter out generic targets - non_generic_compat_targets = [t for t in compat_targets if t.vendor != "generic"] - - # Filter the candidates to be descendant of the best generic candidate - best_generic = max([t for t in compat_targets if t.vendor == "generic"], key=sorting_fn) - best_compat_targets = [t for t in non_generic_compat_targets if t > best_generic] - - if best_compat_targets: - host_cpu = max(best_compat_targets, key=sorting_fn) - else: - host_cpu = max(non_generic_compat_targets, key=sorting_fn) - - vendors = { - 'GenuineIntel': 'intel', - 'AuthenticAMD': 'amd', - } - - vendor = vendors.get(host_cpu.vendor) - - if args.generic: - parts = (host_cpu.family.name, 'generic') - elif vendor: - parts = (host_cpu.family.name, vendor, host_cpu.name) - else: - parts = (host_cpu.family.name, host_cpu.name) - - software_subdir = os.path.join(*parts) - -print(software_subdir) diff --git a/init/Magic_Castle/bash b/init/Magic_Castle/bash deleted file mode 100644 index bf625e7e7b..0000000000 --- a/init/Magic_Castle/bash +++ /dev/null @@ -1,39 +0,0 @@ -# Let's make other scripts silent -EESSI_SILENT=1 - -# The following method should be safe, but might break if file is a symlink -# (could switch to $(dirname "$(readlink -f "$BASH_SOURCE")") in that case) -source $(dirname "$BASH_SOURCE")/../eessi_environment_variables - -# Don't change the default prompt -# export PS1="[EESSI $EESSI_VERSION] $ " - -# Provide a clean MODULEPATH -export MODULEPATH_ROOT=$EESSI_MODULEPATH -export MODULEPATH=$EESSI_SITE_MODULEPATH:$EESSI_MODULEPATH - -# Extensions are too many, let's not print them by default (requires Lmod 8.4.12) -export LMOD_AVAIL_EXTENSIONS=no - -# add location of commands provided by compat layer to $PATH; -# see https://github.com/EESSI/software-layer/issues/52 -export PATH=$EPREFIX/usr/bin:$EPREFIX/bin:$PATH - -# init Lmod -source $EESSI_EPREFIX/usr/share/Lmod/init/bash - -if [ -z "$__Init_Default_Modules" ]; then - export __Init_Default_Modules=1; - - ## ability to predefine elsewhere the default list - LMOD_SYSTEM_DEFAULT_MODULES=${LMOD_SYSTEM_DEFAULT_MODULES:-""} - if [ ! -z ${LMOD_SYSTEM_DEFAULT_MODULES+x} ]; then - # We have a non-empty value - export LMOD_SYSTEM_DEFAULT_MODULES - module --initial_load --no_redirect restore - fi -else - module reload -fi - -echo "Environment set up to use EESSI (${EESSI_VERSION}), have fun!" diff --git a/init/Magic_Castle/eessi_python3 b/init/Magic_Castle/eessi_python3 deleted file mode 100755 index b2f7fd4d66..0000000000 --- a/init/Magic_Castle/eessi_python3 +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -# This script can be used to configure JupyterHub with a hardware-optimised python -# installation from EasyBuild, and is required since EasyBuild uses a site.cfg for Python -# extensions which the JupyterHub kernel should be aware of. - -# Make EESSI environment script silent -export EESSI_SILENT=1 - -# Gather all the EESSI environment variables -# (we are careful with the path as this file may be symlinked, the below will not work -# for MacOS due to the use of `readlink`) -source $(dirname "$(readlink -f "$BASH_SOURCE")")/../eessi_environment_variables - -eessi_python=$(ls ${EESSI_SOFTWARE_PATH}/software/Python/3*GCCcore*/bin/python | sed 1q) -if [ -f "$eessi_python" ]; then - $eessi_python "$@" -else - echo "ERROR: No EESSI Python 3 available." - false -fi diff --git a/init/README.md b/init/README.md deleted file mode 100644 index c253dc4ce1..0000000000 --- a/init/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Bash initialisation for EESSI - -This directory contains the default initialisation script for a bash shell used to -configure Lmod and use the EESSI software modules. The (bash) -file `eessi_environment_variables` is used to set and export the full set of EESSI -environment variables: - -- `EESSI_PREFIX`: The base directory of the entire software stack. -- `EESSI_EPREFIX`: The location of Gentoo Prefix compatability layer (for the architecture). -- `EESSI_EPREFIX_PYTHON`: Path to `python3` in the Gentoo Prefix layer. -- `EESSI_SOFTWARE_SUBDIR`: Hardware specific software subdirectory. -- `EESSI_SOFTWARE_PATH`: Full path to EESSI software stack. -- `EESSI_MODULEPATH`: Path to be added to the `MODULEPATH`. This can be influenced by two - externally defined environment varialbes: - - `EESSI_CUSTOM_MODULEPATH`: defines a fully custom directory to be added to - `MODULEPATH`, the end user is entirely responsible for what this directory contains. - - `EESSI_MODULE_SUBDIR`: EESSI may ship with a number of possible module naming schemes. - This variable can be used to point to a non-default module naming scheme. - -All scripts respect the environment variable `EESSI_SILENT` which, if defined to any -value, will make them produce no (non-error) output. - -## `Magic_Castle` subdirectory - -The `Magic_Castle` subdirectory is home to the bash initialisation that we use for -[Magic Castle](https://github.com/ComputeCanada/magic_castle). - -It also contains a wrapper for a hardware optimised EESSI Python 3 installation that is used -by Magic Castle to properly configure JupyterHub. diff --git a/init/arch_specs/eessi_arch_arm.spec b/init/arch_specs/eessi_arch_arm.spec deleted file mode 100755 index 5e5e1fd3f2..0000000000 --- a/init/arch_specs/eessi_arch_arm.spec +++ /dev/null @@ -1,13 +0,0 @@ -# ARM CPU architecture specifications (see https://gpages.juszkiewicz.com.pl/arm-socs-table/arm-socs.html for guidance) -# CPU implementers: 0x41 (ARM), 0x46 (Fujitsu) - also see https://github.com/hrw/arm-socs-table/blob/main/data/socs.yml -# To ensure that archdetect produces the correct ordering, CPU targets should be listed from the most specific -# to the most general. In particular, if CPU target A is a subset of CPU target B, then A must be listed before B - -# Software path in EESSI | 'Vendor ID' or 'CPU implementer' | List of defining CPU features -"aarch64/a64fx" "0x46" "asimdhp sve" # Fujitsu A64FX -"aarch64/neoverse_n1" "ARM" "asimddp" # Ampere Altra -"aarch64/neoverse_n1" "0x41" "asimddp" # AWS Graviton2 -"aarch64/neoverse_v1" "ARM" "asimddp svei8mm" -"aarch64/neoverse_v1" "0x41" "asimddp svei8mm" # AWS Graviton3 -"aarch64/nvidia/grace" "0x41" "sve2 sm3 sm4 svesm4" # NVIDIA Grace -"aarch64/google/axion" "0x41" "sve2 rng sm3 sm4 svesm4" # Google Axion diff --git a/init/arch_specs/eessi_arch_ppc.spec b/init/arch_specs/eessi_arch_ppc.spec deleted file mode 100755 index 0932925046..0000000000 --- a/init/arch_specs/eessi_arch_ppc.spec +++ /dev/null @@ -1,3 +0,0 @@ -# POWER CPU architecture specifications -# Software path in EESSI | Vendor ID | List of defining CPU features -"ppc64le/power9le" "" "POWER9" # IBM Power9 diff --git a/init/arch_specs/eessi_arch_riscv.spec b/init/arch_specs/eessi_arch_riscv.spec deleted file mode 100644 index 430dd2e72d..0000000000 --- a/init/arch_specs/eessi_arch_riscv.spec +++ /dev/null @@ -1 +0,0 @@ -# Software path in EESSI | Vendor ID | List of defining CPU features diff --git a/init/arch_specs/eessi_arch_x86.spec b/init/arch_specs/eessi_arch_x86.spec deleted file mode 100755 index 4515db610a..0000000000 --- a/init/arch_specs/eessi_arch_x86.spec +++ /dev/null @@ -1,11 +0,0 @@ -# x86_64 CPU architecture specifications -# The overview at https://github.com/InstLatx64/InstLatX64_Misc/tree/main/SIMD_Euler may be helpful in defining this list -# Software path in EESSI | Vendor ID | List of defining CPU features -"x86_64/intel/haswell" "GenuineIntel" "avx2 fma" # Intel Haswell, Broadwell -"x86_64/intel/skylake_avx512" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl" # Intel Skylake -"x86_64/intel/cascadelake" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_vnni" # Intel Cascade Lake -"x86_64/intel/icelake" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_vnni avx512_vbmi2" # Intel Icelake Lake -"x86_64/intel/sapphirerapids" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_bf16 amx_tile" # Intel Sapphire/Emerald Rapids -"x86_64/amd/zen2" "AuthenticAMD" "avx2 fma" # AMD Rome -"x86_64/amd/zen3" "AuthenticAMD" "avx2 fma vaes" # AMD Milan, Milan-X -"x86_64/amd/zen4" "AuthenticAMD" "avx2 fma vaes avx512f avx512ifma" # AMD Genoa, Genoa-X diff --git a/init/bash b/init/bash deleted file mode 100644 index 928ac6efdf..0000000000 --- a/init/bash +++ /dev/null @@ -1,46 +0,0 @@ -function show_msg { - # only echo msg if EESSI_SILENT is unset - msg=$1 - if [[ -z ${EESSI_SILENT+x} ]]; then - echo "$msg" - fi -} - -# The following method should be safe, but might break if file is a symlink -# (could switch to $(dirname "$(readlink -f "$BASH_SOURCE")") in that case) -source $(dirname "$BASH_SOURCE")/eessi_environment_variables - -# only continue if setting EESSI environment variables worked fine -if [ $? -eq 0 ]; then - - export PS1="{EESSI $EESSI_VERSION} $PS1" - - # add location of commands provided by compat layer to $PATH; - # see https://github.com/EESSI/software-layer/issues/52 - export PATH=$EPREFIX/usr/bin:$EPREFIX/bin:$PATH - - # init Lmod - show_msg "Initializing Lmod..." - source $EESSI_EPREFIX/usr/share/Lmod/init/bash - - # prepend location of modules for EESSI software stack to $MODULEPATH - show_msg "Prepending $EESSI_MODULEPATH to \$MODULEPATH..." - module use $EESSI_MODULEPATH - show_msg "Prepending site path $EESSI_SITE_MODULEPATH to \$MODULEPATH..." - module use $EESSI_SITE_MODULEPATH - - if [ ! -z ${EESSI_MODULEPATH_ACCEL} ]; then - show_msg "Prepending $EESSI_MODULEPATH_ACCEL to \$MODULEPATH..." - module use $EESSI_MODULEPATH_ACCEL - fi - - #show_msg "" - #show_msg "*** Known problems in the ${EESSI_VERSION} software stack ***" - #show_msg "" - #show_msg "1) ..." - #show_msg "" - #show_msg "" - - echo "Environment set up to use EESSI (${EESSI_VERSION}), have fun!" - -fi diff --git a/init/eessi_archdetect.sh b/init/eessi_archdetect.sh deleted file mode 100755 index 4fd979cea5..0000000000 --- a/init/eessi_archdetect.sh +++ /dev/null @@ -1,221 +0,0 @@ -#!/usr/bin/env bash - -# Confirm the current shell is Bash >= 4 -# (works for sh, bash, dash, zsh, ksh, but not fish, tcsh, elvish) -if [ -n "$BASH_VERSION" ]; then - # Extract the major version numbers - bash_version=$(echo "$BASH_VERSION" | grep -oP '^\d+\.\d+') - major_version=$(echo "$bash_version" | cut -d. -f1) - - # Check if the major version is 4 or higher - if [ "$major_version" -lt 4 ]; then - echo "Error: This script must be run with Bash >= 4, you have $BASH_VERSION." >&2 - exit 1 - fi -else - echo "Error: This script must be run with Bash." >&2 - exit 1 -fi - -VERSION="1.2.0" - -# default log level: only emit warnings or errors -LOG_LEVEL="WARN" -# Default result type is a best match -CPUPATH_RESULT="best" - -timestamp () { - date "+%Y-%m-%d %H:%M:%S" -} - -log () { - # Simple logger function - declare -A levels=([DEBUG]=0 [INFO]=1 [WARN]=2 [ERROR]=3) - msg_type="${1:-INFO}" - msg_body="${2:-'null'}" - - [ ${levels[$msg_type]} ] || log "ERROR" "Unknown log level $msg_type" - - # ignore messages below log level - [ ${levels[$msg_type]} -lt ${levels[$LOG_LEVEL]} ] && return 0 - # print log message to standard error - echo "$(timestamp) [$msg_type] $msg_body" >&2 - # exit after any error message - [ $msg_type == "ERROR" ] && exit 1 -} - -# Supported CPU specifications -update_arch_specs(){ - # Add contents of given spec file into an array - # 1: spec file with the additional specs - - [ ! -f "$1" ] && echo "[ERROR] update_arch_specs: spec file not found: $1" >&2 && exit 1 - local spec_file="$1" - while read spec_line; do - # format spec line as an array and append it to array with all CPU arch specs - cpu_arch_spec+=("(${spec_line})") - # remove comments from spec file - done < <(sed -E 's/(^|[\s\t])#.*$//g;/^\s*$/d' "$spec_file") -} - -# CPU specification of host system -get_cpuinfo(){ - # Return the value from cpuinfo for the matching key - # 1: string with key pattern - - [ -z "$1" ] && log "ERROR" "get_cpuinfo: missing key pattern in argument list" - cpuinfo_pattern="^${1}\s*:\s*" - - # case insensitive match of key pattern and delete key pattern from result - grep -i "$cpuinfo_pattern" ${EESSI_PROC_CPUINFO:-/proc/cpuinfo} | tail -n 1 | sed "s/$cpuinfo_pattern//i" -} - -check_allinfirst(){ - # Return true if all given arguments after the first are found in the first one - # 1: reference string of space separated values - # 2,3..: each additional argument is a single value to be found in the reference string - - [ -z "$1" ] && log "ERROR" "check_allinfirst: missing argument with reference string" - reference="$1" - shift - - for candidate in "$@"; do - [[ " $reference " == *" $candidate "* ]] || return 1 - done - return 0 -} - -cpupath(){ - # If EESSI_SOFTWARE_SUBDIR_OVERRIDE is set, use it - log "DEBUG" "cpupath: Override variable set as '$EESSI_SOFTWARE_SUBDIR_OVERRIDE' " - [ $EESSI_SOFTWARE_SUBDIR_OVERRIDE ] && echo ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} && exit - - # Identify the best matching CPU architecture from a list of supported specifications for the host CPU - # Return the path to the installation files in EESSI of the best matching architecture - local cpu_arch_spec=() - - # Identify the host CPU architecture - local machine_type=${EESSI_MACHINE_TYPE:-$(uname -m)} - log "DEBUG" "cpupath: Host CPU architecture identified as '$machine_type'" - - # Populate list of supported specs for this architecture - case $machine_type in - "x86_64") local spec_file="eessi_arch_x86.spec";; - "aarch64") local spec_file="eessi_arch_arm.spec";; - "ppc64le") local spec_file="eessi_arch_ppc.spec";; - "riscv64") local spec_file="eessi_arch_riscv.spec";; - *) log "ERROR" "cpupath: Unsupported CPU architecture $machine_type" - esac - # spec files are located in a subfolder with this script - local base_dir=$(dirname $(readlink -f $0)) - update_arch_specs "$base_dir/arch_specs/${spec_file}" - - # Identify the host CPU vendor - local cpu_vendor=$(get_cpuinfo "vendor[ _]id") - if [ "${cpu_vendor}" == "" ]; then - cpu_vendor=$(get_cpuinfo "cpu[ _]implementer") - fi - log "DEBUG" "cpupath: CPU vendor of host system: '$cpu_vendor'" - - # Identify the host CPU flags or features - # cpuinfo systems print different line identifiers, eg features, instead of flags - local cpu_flag_tag; - if [ "${cpu_vendor}" == "ARM" ]; then - # if CPU vendor field is ARM, then we should be able to determine CPU microarchitecture based on 'flags' field - cpu_flag_tag='flags' - # if 64-bit Arm CPU without "ARM" as vendor ID, we need to take into account 'features' field - elif [ "${machine_type}" == "aarch64" ]; then - cpu_flag_tag='features' - # on 64-bit POWER, we need to look at 'cpu' field - elif [ "${machine_type}" == "ppc64le" ]; then - cpu_flag_tag='cpu' - else - cpu_flag_tag='flags' - fi - - local cpu_flags=$(get_cpuinfo "$cpu_flag_tag") - log "DEBUG" "cpupath: CPU flags of host system: '$cpu_flags'" - - # Default to generic CPU - local best_arch_match="$machine_type/generic" - local all_arch_matches=$best_arch_match - - # Iterate over the supported CPU specifications to find the best match for host CPU - # Order of the specifications matters, the last one to match will be selected - for arch in "${cpu_arch_spec[@]}"; do - eval "arch_spec=$arch" - if [ "${cpu_vendor}x" == "${arch_spec[1]}x" ]; then - # each flag in this CPU specification must be found in the list of flags of the host - check_allinfirst "${cpu_flags[*]}" ${arch_spec[2]} && best_arch_match=${arch_spec[0]} && \ - all_arch_matches="$best_arch_match:$all_arch_matches" && \ - log "DEBUG" "cpupath: host CPU best match updated to $best_arch_match" - fi - done - - if [ "allx" == "${CPUPATH_RESULT}x" ]; then - log "INFO" "cpupath: all matches for host CPU: $all_arch_matches" - echo "$all_arch_matches" - else - log "INFO" "cpupath: best match for host CPU: $best_arch_match" - echo "$best_arch_match" - fi -} - -accelpath() { - # If EESSI_ACCELERATOR_TARGET_OVERRIDE is set, use it - log "DEBUG" "accelpath: Override variable set as '$EESSI_ACCELERATOR_TARGET_OVERRIDE' " - if [ ! -z $EESSI_ACCELERATOR_TARGET_OVERRIDE ]; then - if [[ "$EESSI_ACCELERATOR_TARGET_OVERRIDE" =~ ^accel/nvidia/cc[0-9][0-9]$ ]]; then - echo ${EESSI_ACCELERATOR_TARGET_OVERRIDE} - return 0 - else - log "ERROR" "Value of \$EESSI_ACCELERATOR_TARGET_OVERRIDE should match 'accel/nvidia/cc[0-9[0-9]', but it does not: '$EESSI_ACCELERATOR_TARGET_OVERRIDE'" - fi - return 0 - fi - - # check for NVIDIA GPUs via nvidia-smi command - nvidia_smi=$(command -v nvidia-smi) - if [[ $? -eq 0 ]]; then - log "DEBUG" "accelpath: nvidia-smi command found @ ${nvidia_smi}" - nvidia_smi_out=$(mktemp -p /tmp nvidia_smi_out.XXXXX) - nvidia-smi --query-gpu=gpu_name,count,driver_version,compute_cap --format=csv,noheader 2>&1 > $nvidia_smi_out - if [[ $? -eq 0 ]]; then - nvidia_smi_info=$(head -1 $nvidia_smi_out) - cuda_cc=$(echo $nvidia_smi_info | sed 's/, /,/g' | cut -f4 -d, | sed 's/\.//g') - log "DEBUG" "accelpath: CUDA compute capability '${cuda_cc}' derived from nvidia-smi output '${nvidia_smi_info}'" - res="accel/nvidia/cc${cuda_cc}" - log "DEBUG" "accelpath: result: ${res}" - echo $res - rm -f $nvidia_smi_out - else - log "DEBUG" "accelpath: nvidia-smi command failed, see output in $nvidia_smi_out" - exit 3 - fi - else - log "DEBUG" "accelpath: nvidia-smi command not found" - exit 2 - fi -} - -# Parse command line arguments -USAGE="Usage: eessi_archdetect.sh [-h][-d][-a] " - -while getopts 'hdva' OPTION; do - case "$OPTION" in - h) echo "$USAGE"; exit 0;; - d) LOG_LEVEL="DEBUG";; - v) echo "eessi_archdetect.sh v$VERSION"; exit 0;; - a) CPUPATH_RESULT="all";; - ?) echo "$USAGE"; exit 1;; - esac -done -shift "$(($OPTIND -1))" - -ARGUMENT=${1:-none} - -case "$ARGUMENT" in - "cpupath") cpupath; exit;; - "accelpath") accelpath; exit;; - *) echo "$USAGE"; log "ERROR" "Missing argument (possible actions: 'cpupath', 'accelpath')";; -esac diff --git a/init/eessi_defaults b/init/eessi_defaults deleted file mode 100644 index 654a829425..0000000000 --- a/init/eessi_defaults +++ /dev/null @@ -1,27 +0,0 @@ -# define default values for some EESSI_* environment variables -# -# This file is part of the EESSI software layer, -# see https://github.com/EESSI/software-layer -# -# author: Thomas Roeblitz (@trz42) -# -# license: GPLv2 -# - -# use different defaults for RISC-V, as we want to redirect to the riscv.eessi.io repo -if [[ $(uname -m) == "riscv64" ]]; then - export EESSI_CVMFS_REPO="${EESSI_CVMFS_REPO_OVERRIDE:=/cvmfs/riscv.eessi.io}" - export EESSI_VERSION="${EESSI_VERSION_OVERRIDE:=20240402}" - if [[ -z ${EESSI_SILENT+x} ]]; then - echo "RISC-V architecture detected, but there is no RISC-V support yet in the production repository." - echo "Automatically switching to version ${EESSI_VERSION} of the RISC-V development repository ${EESSI_CVMFS_REPO}." - echo "For more details about this repository, see https://www.eessi.io/docs/repositories/riscv.eessi.io/." - echo "" - fi -else - export EESSI_CVMFS_REPO="${EESSI_CVMFS_REPO_OVERRIDE:=/cvmfs/software.eessi.io}" - export EESSI_VERSION="${EESSI_VERSION_OVERRIDE:=2023.06}" -fi -# use archdetect by default, unless otherwise specified -export EESSI_USE_ARCHDETECT="${EESSI_USE_ARCHDETECT:=1}" -export EESSI_USE_ARCHSPEC="${EESSI_USE_ARCHSPEC:=0}" diff --git a/init/eessi_environment_variables b/init/eessi_environment_variables deleted file mode 100644 index 0f13b1493a..0000000000 --- a/init/eessi_environment_variables +++ /dev/null @@ -1,166 +0,0 @@ -# this script is *sourced*, not executed, so can't rely on $0 to determine path to self -# $BASH_SOURCE points to correct path, see also http://mywiki.wooledge.org/BashFAQ/028 -EESSI_INIT_DIR_PATH=$(dirname $(readlink -f $BASH_SOURCE)) - -function error() { - echo -e "\e[31mERROR: $1\e[0m" >&2 - false -} - -function show_msg { - # only echo msg if EESSI_SILENT is unset - msg=$1 - if [[ -z ${EESSI_SILENT+x} ]]; then - echo "$msg" - fi -} - -# set up minimal environment: $EESSI_PREFIX, $EESSI_VERSION, $EESSI_OS_TYPE, $EESSI_CPU_FAMILY, $EPREFIX -source $EESSI_INIT_DIR_PATH/minimal_eessi_env - -if [ -d $EESSI_PREFIX ]; then - show_msg "Found EESSI repo @ $EESSI_PREFIX!" - - export EESSI_EPREFIX=$EPREFIX - if [ -d $EESSI_EPREFIX ]; then - - # determine subdirectory in software layer - if [ "$EESSI_USE_ARCHDETECT" == "1" ]; then - # if archdetect is enabled, use internal code - all_cpupaths=$(${EESSI_INIT_DIR_PATH}/eessi_archdetect.sh -a cpupath) - # iterate over colon-separated list verifying if the architecture is present - # under $EESSI_PREFIX/software/$EESSI_OS_TYPE; if so use the architecture as best match - IFS=: read -r -a archs <<< "${all_cpupaths}" - for arch in "${archs[@]}"; do - if [ -d ${EESSI_PREFIX}/software/${EESSI_OS_TYPE}/${arch} ]; then - export EESSI_SOFTWARE_SUBDIR=${arch} - show_msg "archdetect says ${EESSI_SOFTWARE_SUBDIR}" - break - fi - done - - # we need to make sure that errexit shell option (set -e) is not enabled, - # since archdetect will produce non-zero exit code if no accelerator was found - if [[ "$-" =~ e ]]; then - errexit_shell_option_set='yes' - set +e - else - errexit_shell_option_set='no' - fi - - # to be able to grab exit code of archdetect trying to detect accelerators, - # we can not run it via $(...), so we have to redirect the output to a temporary file - tmpout=$(mktemp) - ${EESSI_INIT_DIR_PATH}/eessi_archdetect.sh accelpath 2>&1 > $tmpout - accelpath_exit_code=$? - - if [[ "$errexit_shell_option_set" == "yes" ]]; then - set -e - fi - - if [[ $accelpath_exit_code -eq 0 ]]; then - export EESSI_ACCEL_SUBDIR=$(tail -1 $tmpout && rm -f $tmpout) - if [ -z ${EESSI_ACCEL_SUBDIR} ]; then - error "accelerator detection with archdetect worked, but no result was returned?!" - else - # allow specifying different parent directory for accel/* subdirectory via $EESSI_ACCEL_SOFTWARE_SUBDIR_OVERRIDE - EESSI_ACCEL_SOFTWARE_SUBDIR=${EESSI_ACCEL_SOFTWARE_SUBDIR_OVERRIDE:-$EESSI_SOFTWARE_SUBDIR} - # path to where accel/* subdirectory is located - EESSI_ACCEL_SOFTWARE_PATH=${EESSI_PREFIX}/software/${EESSI_OS_TYPE}/${EESSI_ACCEL_SOFTWARE_SUBDIR} - if [ -d $EESSI_ACCEL_SOFTWARE_PATH/${EESSI_ACCEL_SUBDIR} ]; then - show_msg "archdetect found supported accelerator for CPU target ${EESSI_ACCEL_SOFTWARE_SUBDIR}: ${EESSI_ACCEL_SUBDIR}" - else - show_msg "No matching path found in ${EESSI_ACCEL_SOFTWARE_SUBDIR} for accelerator detected by archdetect (${EESSI_ACCEL_SUBDIR})" - fi - fi - else - show_msg "archdetect could not detect any accelerators" - rm -f $tmpout - fi - elif [ "$EESSI_USE_ARCHSPEC" == "1" ]; then - # note: eessi_software_subdir_for_host.py will pick up value from $EESSI_SOFTWARE_SUBDIR_OVERRIDE if it's defined! - export EESSI_EPREFIX_PYTHON=$EESSI_EPREFIX/usr/bin/python3 - export EESSI_SOFTWARE_SUBDIR=$($EESSI_EPREFIX_PYTHON ${EESSI_INIT_DIR_PATH}/eessi_software_subdir_for_host.py $EESSI_PREFIX) - show_msg "archspec says ${EESSI_SOFTWARE_SUBDIR}" - else - error "Don't know how to detect host CPU, giving up!" - fi - if [ ! -z $EESSI_SOFTWARE_SUBDIR ]; then - - show_msg "Using ${EESSI_SOFTWARE_SUBDIR} as software subdirectory." - export EESSI_SOFTWARE_PATH=$EESSI_PREFIX/software/$EESSI_OS_TYPE/$EESSI_SOFTWARE_SUBDIR - - # Configure our LMOD - export LMOD_CONFIG_DIR="$EESSI_SOFTWARE_PATH/.lmod" - lmod_rc_file="$LMOD_CONFIG_DIR/lmodrc.lua" - if [ -f $lmod_rc_file ]; then - show_msg "Found Lmod configuration file at $lmod_rc_file" - else - error "Lmod configuration file not found at $lmod_rc_file" - fi - - export LMOD_PACKAGE_PATH="$EESSI_SOFTWARE_PATH/.lmod" - lmod_sitepackage_file="$LMOD_PACKAGE_PATH/SitePackage.lua" - if [ -f $lmod_sitepackage_file ]; then - show_msg "Found Lmod SitePackage.lua file at $lmod_sitepackage_file" - else - error "Lmod SitePackage.lua file not found at $lmod_sitepackage_file" - fi - - if [ ! -z $EESSI_BASIC_ENV ]; then - show_msg "Only setting up basic environment, so we're done" - elif [ -d $EESSI_SOFTWARE_PATH ]; then - export EESSI_SITE_SOFTWARE_PATH=${EESSI_SOFTWARE_PATH/versions/host_injections} - show_msg "Using ${EESSI_SITE_SOFTWARE_PATH} as the site extension directory for installations." - # Allow for use of alternative module tree shipped with EESSI - if [ -z ${EESSI_MODULE_SUBDIR+x} ]; then - # EESSI_MODULE_SUBDIR not set - EESSI_MODULE_SUBDIR="modules/all" - fi - # Allow for the use of a custom MNS - if [ -z ${EESSI_CUSTOM_MODULEPATH+x} ]; then - # EESSI_CUSTOM_MODULEPATH not set so we use our defaults - - EESSI_MODULEPATH=$EESSI_SOFTWARE_PATH/$EESSI_MODULE_SUBDIR - else - show_msg "Using defined environment variable \$EESSI_CUSTOM_MODULEPATH to set EESSI_MODULEPATH." - EESSI_MODULEPATH=$EESSI_CUSTOM_MODULEPATH - fi - - if [ -d $EESSI_MODULEPATH ]; then - export EESSI_MODULEPATH=$EESSI_MODULEPATH - show_msg "Using ${EESSI_MODULEPATH} as the directory to be added to MODULEPATH." - export EESSI_SITE_MODULEPATH=$EESSI_SITE_SOFTWARE_PATH/$EESSI_MODULE_SUBDIR - show_msg "Using ${EESSI_SITE_MODULEPATH} as the site extension directory to be added to MODULEPATH." - else - error "EESSI module path at $EESSI_MODULEPATH not found!" - false - fi - - if [ -d ${EESSI_ACCEL_SOFTWARE_PATH}/${EESSI_ACCEL_SUBDIR}/${EESSI_MODULE_SUBDIR} ]; then - export EESSI_MODULEPATH_ACCEL=${EESSI_ACCEL_SOFTWARE_PATH}/${EESSI_ACCEL_SUBDIR}/${EESSI_MODULE_SUBDIR} - show_msg "Using ${EESSI_MODULEPATH_ACCEL} as additional directory (for accelerators) to be added to MODULEPATH." - fi - - # Fix wrong path for RHEL >=8 libcurl - # This is required here because we ship curl in our compat layer. If we only provided - # curl as a module file we could instead do this via a `modluafooter` in an EasyBuild - # hook (or via an Lmod hook) - rhel_libcurl_file="/etc/pki/tls/certs/ca-bundle.crt" - if [ -f $rhel_libcurl_file ]; then - show_msg "Found libcurl CAs file at RHEL location, setting CURL_CA_BUNDLE" - export CURL_CA_BUNDLE=$rhel_libcurl_file - fi - - else - error "EESSI software layer at $EESSI_SOFTWARE_PATH not found!" - fi - else - error "no value set for \$EESSI_SOFTWARE_SUBDIR" - fi - else - error "Compatibility layer directory $EESSI_EPREFIX not found!" - fi -else - error "EESSI repository at $EESSI_PREFIX not found!" -fi diff --git a/init/eessi_software_subdir_for_host.py b/init/eessi_software_subdir_for_host.py deleted file mode 100755 index 58e9cfd2e6..0000000000 --- a/init/eessi_software_subdir_for_host.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python3 -# -# Determine EESSI software subdirectory to use for current build host, using archspec -# -import glob -import os -import platform -import sys -import archspec.cpu -from archspec.cpu.detect import compatible_microarchitectures, raw_info_dictionary - -VENDOR_MAP = { - 'GenuineIntel': 'intel', - 'AuthenticAMD': 'amd', -} - -GENERIC = 'generic' -X86_64 = 'x86_64' - -KNOWN_CPU_UARCHS = archspec.cpu.TARGETS - - -def error(msg): - sys.stderr.write('ERROR: ' + msg + '\n') - sys.exit(1) - - -def warning(msg): - sys.stderr.write('WARNING: ' + msg + '\n') - - -def det_host_triple(): - """ - Determine host triple: (, , ). - may be None if there's no match in VENDOR_MAP. - """ - # we can't directly use archspec.cpu.host(), because we may get back a virtual microarchitecture like x86_64_v3... - def sorting_fn(item): - """Helper function to sort compatible microarchitectures.""" - return len(item.ancestors), len(item.features) - - raw_cpu_info = raw_info_dictionary() - compat_targets = compatible_microarchitectures(raw_cpu_info) - - # filter out generic targets - non_generic_compat_targets = [t for t in compat_targets if t.vendor != "generic"] - - # Filter the candidates to be descendant of the best generic candidate - best_generic = max([t for t in compat_targets if t.vendor == "generic"], key=sorting_fn) - best_compat_targets = [t for t in non_generic_compat_targets if t > best_generic] - - if best_compat_targets: - host_cpu = max(best_compat_targets, key=sorting_fn) - else: - host_cpu = max(non_generic_compat_targets, key=sorting_fn) - - host_vendor = VENDOR_MAP.get(host_cpu.vendor) - host_cpu_family = host_cpu.family.name - host_cpu_name = host_cpu.name - - return (host_cpu_family, host_vendor, host_cpu_name) - - -def find_best_target(eessi_prefix): - - os_type = platform.system() - eessi_os_type = { - 'Darwin': 'macos', - 'Linux': 'linux', - }[os_type] - - eessi_software_layer_path = os.path.join(eessi_prefix, 'software', eessi_os_type) - if not os.path.exists(eessi_software_layer_path): - error('Specified prefix "%s" does not exist!' % eessi_software_layer_path) - - host_cpu_family, host_vendor, host_cpu_name = det_host_triple() - - # determine available targets in 'software' subdirectory of specified prefix (only for host CPU family/vendor) - if host_cpu_family == X86_64: - paths = glob.glob(os.path.join(eessi_software_layer_path, host_cpu_family, host_vendor, '*')) - # also consider x86_64/generic - generic_path = os.path.join(eessi_software_layer_path, host_cpu_family, GENERIC) - if os.path.exists(generic_path): - paths.append(generic_path) - else: - paths = glob.glob(os.path.join(eessi_software_layer_path, host_cpu_family, '*')) - - if not paths: - if host_cpu_family == X86_64: - host_target = host_cpu_family + '/' + host_vendor + '/' + host_cpu_name - else: - host_target = host_cpu_family + '/' + host_cpu_name - error('No compatible targets found for ' + host_target) - - targets = [os.path.basename(p) for p in paths] - - # retain only targets compatible with host, and sort them - target_uarchs = [] - for uarch in targets: - if uarch == GENERIC: - continue - if uarch in KNOWN_CPU_UARCHS: - target_uarchs.append(KNOWN_CPU_UARCHS[uarch]) - - host_uarch = KNOWN_CPU_UARCHS[host_cpu_name] - compat_target_uarchs = sorted([x for x in target_uarchs if x <= host_uarch]) - - if not compat_target_uarchs: - if GENERIC in targets: - compat_target_uarchs = [GENERIC] - else: - error('No targets compatible with %s found!' % host_uarch) - - # last target is best pick for current host - selected_uarch = str(compat_target_uarchs[-1]) - - if host_vendor and selected_uarch != GENERIC: - parts = (host_cpu_family, host_vendor, selected_uarch) - else: - parts = (host_cpu_family, selected_uarch) - - return os.path.join(*parts) - - -def main(): - if len(sys.argv) == 2: - eessi_prefix = sys.argv[1] - else: - error('Usage: %s ' % sys.argv[0]) - - target = os.getenv('EESSI_SOFTWARE_SUBDIR_OVERRIDE') - if target is None: - target = find_best_target(eessi_prefix) - - print(target) - - -if __name__ == '__main__': - main() diff --git a/init/lmod/bash b/init/lmod/bash deleted file mode 100644 index b2db9a8802..0000000000 --- a/init/lmod/bash +++ /dev/null @@ -1,18 +0,0 @@ -# Choose an EESSI CVMFS repository -EESSI_CVMFS_REPO="${EESSI_CVMFS_REPO:-/cvmfs/software.eessi.io}" -# Choose an EESSI version -EESSI_VERSION="${EESSI_VERSION:-2023.06}" -# Path to top-level module tree -export MODULEPATH="${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/init/modules" -. "${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/compat/linux/$(uname -m)/usr/share/Lmod/init/bash" - -if [ -z "$__Init_Default_Modules" ]; then - export __Init_Default_Modules=1; - - ## ability to predefine elsewhere the default list - LMOD_SYSTEM_DEFAULT_MODULES=${LMOD_SYSTEM_DEFAULT_MODULES:-"EESSI/$EESSI_VERSION"} - export LMOD_SYSTEM_DEFAULT_MODULES - module --initial_load --no_redirect restore -else - module refresh -fi diff --git a/init/lmod/csh b/init/lmod/csh deleted file mode 100644 index f2e9100255..0000000000 --- a/init/lmod/csh +++ /dev/null @@ -1,18 +0,0 @@ -# Choose an EESSI CVMFS repository -if (! $?EESSI_CVMFS_REPO) then; set EESSI_CVMFS_REPO = "/cvmfs/software.eessi.io"; endif -# Choose an EESSI version -if (! $?EESSI_VERSION) then; set EESSI_VERSION = "2023.06"; endif -# Path to top-level module tree -setenv MODULEPATH "${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/init/modules" -source "${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/compat/linux/$(uname -m)/usr/share/Lmod/init/csh" - -if (! $?__Init_Default_Modules ) then - setenv __Init_Default_Modules 1; - - ## ability to predefine elsewhere the default list - if (! $?LMOD_SYSTEM_DEFAULT_MODULES) then; setenv LMOD_SYSTEM_DEFAULT_MODULES "EESSI/$EESSI_VERSION"; endif - module --initial_load --no_redirect restore -else - module refresh -endif - diff --git a/init/lmod/fish b/init/lmod/fish deleted file mode 100644 index 46cd7cacf4..0000000000 --- a/init/lmod/fish +++ /dev/null @@ -1,17 +0,0 @@ -# Choose an EESSI CVMFS repository -set EESSI_CVMFS_REPO (set -q EESSI_CVMFS_REPO; and echo "$EESSI_CVMFS_REPO"; or echo "/cvmfs/software.eessi.io") -# Choose an EESSI version -set EESSI_VERSION (set -q EESSI_VERSION; and echo "$EESSI_VERSION"; or echo "2023.06") -# Path to top-level module tree -set -x MODULEPATH "$EESSI_CVMFS_REPO"/versions/"$EESSI_VERSION"/init/modules -. "$EESSI_CVMFS_REPO"/versions/"$EESSI_VERSION"/compat/linux/(uname -m)/usr/share/Lmod/init/fish - -if test -z "$__Init_Default_Modules" - export __Init_Default_Modules=1; - - ## ability to predefine elsewhere the default list - set -x LMOD_SYSTEM_DEFAULT_MODULES (set -q LMOD_SYSTEM_DEFAULT_MODULE; and echo "$LMOD_SYSTEM_DEFAULT_MODULE"; or echo "EESSI/$EESSI_VERSION") - module --initial_load --no_redirect restore -else - module refresh -end diff --git a/init/lmod/ksh b/init/lmod/ksh deleted file mode 100644 index 7d9a05d688..0000000000 --- a/init/lmod/ksh +++ /dev/null @@ -1,18 +0,0 @@ -# Choose an EESSI CVMFS repository -EESSI_CVMFS_REPO="${EESSI_CVMFS_REPO:-/cvmfs/software.eessi.io}" -# Choose an EESSI version -EESSI_VERSION="${EESSI_VERSION:-2023.06}" -# Path to top-level module tree -export MODULEPATH="${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/init/modules" -. "${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/compat/linux/$(uname -m)/usr/share/Lmod/init/ksh" - -if [ -z "$__Init_Default_Modules" ]; then - export __Init_Default_Modules=1; - - ## ability to predefine elsewhere the default list - LMOD_SYSTEM_DEFAULT_MODULES=${LMOD_SYSTEM_DEFAULT_MODULES:-"EESSI/$EESSI_VERSION"} - export LMOD_SYSTEM_DEFAULT_MODULES - module --initial_load --no_redirect restore -else - module refresh -fi diff --git a/init/lmod/zsh b/init/lmod/zsh deleted file mode 100644 index bc6e8e4deb..0000000000 --- a/init/lmod/zsh +++ /dev/null @@ -1,18 +0,0 @@ -# Choose an EESSI CVMFS repository -EESSI_CVMFS_REPO="${EESSI_CVMFS_REPO:-/cvmfs/software.eessi.io}" -# Choose an EESSI version -EESSI_VERSION="${EESSI_VERSION:-2023.06}" -# Path to top-level module tree -export MODULEPATH="${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/init/modules" -. "${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/compat/linux/$(uname -m)/usr/share/Lmod/init/zsh" - -if [ -z "$__Init_Default_Modules" ]; then - export __Init_Default_Modules=1; - - ## ability to predefine elsewhere the default list - LMOD_SYSTEM_DEFAULT_MODULES=${LMOD_SYSTEM_DEFAULT_MODULES:-"EESSI/$EESSI_VERSION"} - export LMOD_SYSTEM_DEFAULT_MODULES - module --initial_load --no_redirect restore -else - module refresh -fi diff --git a/init/lmod_eessi_archdetect_wrapper.sh b/init/lmod_eessi_archdetect_wrapper.sh deleted file mode 100644 index c12452c71d..0000000000 --- a/init/lmod_eessi_archdetect_wrapper.sh +++ /dev/null @@ -1,2 +0,0 @@ -# This can be leveraged by the source_sh() feature of Lmod -export EESSI_ARCHDETECT_OPTIONS=$($(dirname $(readlink -f $BASH_SOURCE))/eessi_archdetect.sh -a cpupath) diff --git a/init/lmod_eessi_archdetect_wrapper_accel.sh b/init/lmod_eessi_archdetect_wrapper_accel.sh deleted file mode 100644 index d4a0038cb5..0000000000 --- a/init/lmod_eessi_archdetect_wrapper_accel.sh +++ /dev/null @@ -1,2 +0,0 @@ -# This can be leveraged by the source_sh() feature of Lmod -export EESSI_ACCEL_SUBDIR=$($(dirname $(readlink -f $BASH_SOURCE))/eessi_archdetect.sh accelpath) diff --git a/init/minimal_eessi_env b/init/minimal_eessi_env deleted file mode 100644 index 5e513c3c9f..0000000000 --- a/init/minimal_eessi_env +++ /dev/null @@ -1,28 +0,0 @@ -# define minimal EESSI environment, without relying on external scripts -# -# this script is *sourced*, not executed, so can't rely on $0 to determine path to self -# $BASH_SOURCE points to correct path, see also http://mywiki.wooledge.org/BashFAQ/028 -EESSI_INIT_DIR_PATH=$(dirname $(readlink -f $BASH_SOURCE)) - -# set up defaults: EESSI_CVMFS_REPO, EESSI_VERSION -# script takes *_OVERRIDEs into account -source ${EESSI_INIT_DIR_PATH}/eessi_defaults - -export EESSI_PREFIX=$EESSI_CVMFS_REPO/versions/$EESSI_VERSION - -if [[ $(uname -s) == 'Linux' ]]; then - export EESSI_OS_TYPE='linux' -else - export EESSI_OS_TYPE='macos' -fi - -# aarch64 (Arm 64-bit), riscv64 (RISC-V 64-bit), x86_64 (x86 64-bit) -export EESSI_CPU_FAMILY=$(uname -m) - -# set $EPREFIX since that is basically a standard in Gentoo Prefix -# if $EESSI_COMPAT_LAYER_DIR is defined (for example by run_in_compat_layer_env.sh script), we use that value -if [ ! -z ${EESSI_COMPAT_LAYER_DIR} ]; then - export EPREFIX=$EESSI_COMPAT_LAYER_DIR -else - export EPREFIX=$EESSI_PREFIX/compat/$EESSI_OS_TYPE/$EESSI_CPU_FAMILY -fi diff --git a/init/modules/EESSI/2023.06.lua b/init/modules/EESSI/2023.06.lua deleted file mode 100644 index d5105e89fc..0000000000 --- a/init/modules/EESSI/2023.06.lua +++ /dev/null @@ -1,155 +0,0 @@ -help([[ -Description -=========== -The European Environment for Scientific Software Installations (EESSI, pronounced as easy) is a collaboration between different European partners in HPC community.The goal of this project is to build a common stack of scientific software installations for HPC systems and beyond, including laptops, personal workstations and cloud infrastructure. - -More information -================ - - URL: https://www.eessi.io/docs/ -]]) -whatis("Description: The European Environment for Scientific Software Installations (EESSI, pronounced as easy) is a collaboration between different European partners in HPC community. The goal of this project is to build a common stack of scientific software installations for HPC systems and beyond, including laptops, personal workstations and cloud infrastructure.") -whatis("URL: https://www.eessi.io/docs/") -conflict("EESSI") -local eessi_version = myModuleVersion() -local eessi_repo = "/cvmfs/software.eessi.io" -if (subprocess("uname -m"):gsub("\n$","") == "riscv64") then - eessi_version = os.getenv("EESSI_VERSION_OVERRIDE") or "20240402" - eessi_repo = "/cvmfs/riscv.eessi.io" - LmodMessage("RISC-V architecture detected, but there is no RISC-V support yet in the production repository.\n" .. - "Automatically switching to version " .. eessi_version .. " of the RISC-V development repository " .. eessi_repo .. ".\n" .. - "For more details about this repository, see https://www.eessi.io/docs/repositories/riscv.eessi.io/.") -end -local eessi_prefix = pathJoin(eessi_repo, "versions", eessi_version) -local eessi_os_type = "linux" -setenv("EESSI_VERSION", eessi_version) -setenv("EESSI_CVMFS_REPO", eessi_repo) -setenv("EESSI_OS_TYPE", eessi_os_type) -function eessiDebug(text) - if (mode() == "load" and os.getenv("EESSI_DEBUG_INIT")) then - LmodMessage(text) - end -end -function archdetect_cpu() - local script = pathJoin(eessi_prefix, 'init', 'lmod_eessi_archdetect_wrapper.sh') - -- make sure that we grab the value for architecture before the module unsets the environment variable (in unload mode) - local archdetect_options = os.getenv("EESSI_ARCHDETECT_OPTIONS") or (os.getenv("EESSI_ARCHDETECT_OPTIONS_OVERRIDE") or "") - if not os.getenv("EESSI_ARCHDETECT_OPTIONS_OVERRIDE") then - if convertToCanonical(LmodVersion()) < convertToCanonical("8.6") then - LmodError("Loading this modulefile requires using Lmod version >= 8.6, but you can export EESSI_ARCHDETECT_OPTIONS_OVERRIDE to the available cpu architecture in the form of: x86_64/intel/haswell:x86_64/generic or aarch64/neoverse_v1:aarch64/generic") - end - source_sh("bash", script) - end - -- EESSI_ARCHDETECT_OPTIONS is set by the script (_if_ it was called) - archdetect_options = os.getenv("EESSI_ARCHDETECT_OPTIONS") or archdetect_options - if archdetect_options then - eessiDebug("Got archdetect CPU options: " .. archdetect_options) - -- archdetect_options is a colon-separated list of CPU architectures that are compatible with - -- the host CPU and ordered from most specific to least specific, e.g., - -- x86_64/intel/skylake_avx512:x86_64/intel/haswell:x86_64/generic - -- We loop over the list, and return the highest matching arch for which a directory exists for this EESSI version - for archdetect_filter_cpu in string.gmatch(archdetect_options, "([^" .. ":" .. "]+)") do - if isDir(pathJoin(eessi_prefix, "software", eessi_os_type, archdetect_filter_cpu, "software")) then - eessiDebug("Selected archdetect CPU: " .. archdetect_filter_cpu) - return archdetect_filter_cpu - end - end - LmodError("Software directory check for the detected architecture failed") - else - -- Still need to return something - return nil - end -end -function archdetect_accel() - local script = pathJoin(eessi_prefix, 'init', 'lmod_eessi_archdetect_wrapper_accel.sh') - -- for unload mode, we need to grab the value before it is unset - local archdetect_accel = os.getenv("EESSI_ACCEL_SUBDIR") or (os.getenv("EESSI_ACCELERATOR_TARGET_OVERRIDE") or "") - if not os.getenv("EESSI_ACCELERATOR_TARGET_OVERRIDE ") then - if convertToCanonical(LmodVersion()) < convertToCanonical("8.6") then - LmodError("Loading this modulefile requires using Lmod version >= 8.6, but you can export EESSI_ACCELERATOR_TARGET_OVERRIDE to the available accelerator architecture in the form of: accel/nvidia/cc80") - end - source_sh("bash", script) - end - archdetect_accel = os.getenv("EESSI_ACCEL_SUBDIR") or archdetect_accel - eessiDebug("Got archdetect accel option: " .. archdetect_accel) - return archdetect_accel -end --- archdetect finds the best compatible architecture, e.g., x86_64/amd/zen3 -local archdetect = archdetect_cpu() --- archdetect_accel() attempts to identify an accelerator, e.g., accel/nvidia/cc80 -local archdetect_accel = archdetect_accel() --- eessi_cpu_family is derived from the archdetect match, e.g., x86_64 -local eessi_cpu_family = archdetect:match("([^/]+)") -local eessi_software_subdir = archdetect --- eessi_eprefix is the base location of the compat layer, e.g., /cvmfs/software.eessi.io/versions/2023.06/compat/linux/x86_64 -local eessi_eprefix = pathJoin(eessi_prefix, "compat", eessi_os_type, eessi_cpu_family) --- eessi_software_path is the location of the software installations, e.g., --- /cvmfs/software.eessi.io/versions/2023.06/software/linux/x86_64/amd/zen3 -local eessi_software_path = pathJoin(eessi_prefix, "software", eessi_os_type, eessi_software_subdir) -local eessi_modules_subdir = pathJoin("modules", "all") --- eessi_module_path is the location of the _CPU_ module files, e.g., --- /cvmfs/software.eessi.io/versions/2023.06/software/linux/x86_64/amd/zen3/modules/all -local eessi_module_path = pathJoin(eessi_software_path, eessi_modules_subdir) -local eessi_site_software_path = string.gsub(eessi_software_path, "versions", "host_injections") --- Site module path is the same as the EESSI one, but with `versions` changed to `host_injections`, e.g., --- /cvmfs/software.eessi.io/host_injections/2023.06/software/linux/x86_64/amd/zen3/modules/all -local eessi_site_module_path = pathJoin(eessi_site_software_path, eessi_modules_subdir) -setenv("EPREFIX", eessi_eprefix) -eessiDebug("Setting EPREFIX to " .. eessi_eprefix) -setenv("EESSI_CPU_FAMILY", eessi_cpu_family) -eessiDebug("Setting EESSI_CPU_FAMILY to " .. eessi_cpu_family) -setenv("EESSI_SITE_SOFTWARE_PATH", eessi_site_software_path) -eessiDebug("Setting EESSI_SITE_SOFTWARE_PATH to " .. eessi_site_software_path) -setenv("EESSI_SITE_MODULEPATH", eessi_site_module_path) -eessiDebug("Setting EESSI_SITE_MODULEPATH to " .. eessi_site_module_path) -setenv("EESSI_SOFTWARE_SUBDIR", eessi_software_subdir) -eessiDebug("Setting EESSI_SOFTWARE_SUBDIR to " .. eessi_software_subdir) -setenv("EESSI_PREFIX", eessi_prefix) -eessiDebug("Setting EESSI_PREFIX to " .. eessi_prefix) -setenv("EESSI_EPREFIX", eessi_eprefix) -eessiDebug("Setting EPREFIX to " .. eessi_eprefix) -prepend_path("PATH", pathJoin(eessi_eprefix, "bin")) -eessiDebug("Adding " .. pathJoin(eessi_eprefix, "bin") .. " to PATH") -prepend_path("PATH", pathJoin(eessi_eprefix, "usr", "bin")) -eessiDebug("Adding " .. pathJoin(eessi_eprefix, "usr", "bin") .. " to PATH") -setenv("EESSI_SOFTWARE_PATH", eessi_software_path) -eessiDebug("Setting EESSI_SOFTWARE_PATH to " .. eessi_software_path) -setenv("EESSI_MODULEPATH", eessi_module_path) -eessiDebug("Setting EESSI_MODULEPATH to " .. eessi_module_path) --- We ship our spider cache, so this location does not need to be spider-ed -if ( mode() ~= "spider" ) then - prepend_path("MODULEPATH", eessi_module_path) - eessiDebug("Adding " .. eessi_module_path .. " to MODULEPATH") -end -prepend_path("LMOD_RC", pathJoin(eessi_software_path, ".lmod", "lmodrc.lua")) -eessiDebug("Adding " .. pathJoin(eessi_software_path, ".lmod", "lmodrc.lua") .. " to LMOD_RC") --- Use pushenv for LMOD_PACKAGE_PATH as this may be set locally by the site -pushenv("LMOD_PACKAGE_PATH", pathJoin(eessi_software_path, ".lmod")) -eessiDebug("Setting LMOD_PACKAGE_PATH to " .. pathJoin(eessi_software_path, ".lmod")) - --- the accelerator may have an empty value and we need to give some flexibility --- * construct the path we expect to find --- * then check it exists --- * then update the modulepath -if not (archdetect_accel == nil or archdetect_accel == '') then - -- The CPU subdirectory of the accelerator installations is _usually_ the same as host CPU, but this can be overridden - eessi_accel_software_subdir = os.getenv("EESSI_ACCEL_SOFTWARE_SUBDIR_OVERRIDE") or eessi_software_subdir - -- CPU location of the accelerator installations, e.g., - -- /cvmfs/software.eessi.io/versions/2023.06/software/linux/x86_64/amd/zen3 - eessi_accel_software_path = pathJoin(eessi_prefix, "software", eessi_os_type, eessi_accel_software_subdir) - -- location of the accelerator modules, e.g., - -- /cvmfs/software.eessi.io/versions/2023.06/software/linux/x86_64/amd/zen3/accel/nvidia/cc80/modules/all - eessi_module_path_accel = pathJoin(eessi_accel_software_path, archdetect_accel, eessi_modules_subdir) - eessiDebug("Checking if " .. eessi_module_path_accel .. " exists") - if isDir(eessi_module_path_accel) then - setenv("EESSI_MODULEPATH_ACCEL", eessi_module_path_accel) - prepend_path("MODULEPATH", eessi_module_path_accel) - eessiDebug("Using acclerator modules at: " .. eessi_module_path_accel) - end -end - --- prepend the site module path last so it has priority -prepend_path("MODULEPATH", eessi_site_module_path) -eessiDebug("Adding " .. eessi_site_module_path .. " to MODULEPATH") -if mode() == "load" then - LmodMessage("EESSI/" .. eessi_version .. " loaded successfully") -end diff --git a/init/modules/EESSI/20240402.lua b/init/modules/EESSI/20240402.lua deleted file mode 120000 index cbf80d1fcd..0000000000 --- a/init/modules/EESSI/20240402.lua +++ /dev/null @@ -1 +0,0 @@ -2023.06.lua \ No newline at end of file diff --git a/init/test.py b/init/test.py deleted file mode 100644 index f10be5e66e..0000000000 --- a/init/test.py +++ /dev/null @@ -1,82 +0,0 @@ -import os -import pytest -import re - -import eessi_software_subdir_for_host -from eessi_software_subdir_for_host import find_best_target - - -def prep_tmpdir(tmpdir, subdirs): - for subdir in subdirs: - os.makedirs(os.path.join(tmpdir, 'software', 'linux', subdir), exist_ok=True) - - -def test_prefix_does_not_exist(capsys, tmpdir): - """Test whether non-existing prefix results in error.""" - - with pytest.raises(SystemExit): - find_best_target(tmpdir) - - captured = capsys.readouterr() - assert captured.out == '' - assert re.match('^ERROR: Specified prefix ".*/software/linux" does not exist!$', captured.err) - - -def test_no_targets(tmpdir, capsys): - """Test case where no compatible targets are found for host CPU.""" - prep_tmpdir(tmpdir, ['']) - with pytest.raises(SystemExit): - find_best_target(tmpdir) - - captured = capsys.readouterr() - assert captured.out == '' - assert re.match('^ERROR: No compatible targets found for .*', captured.err) - - -def test_broadwell_host(tmpdir, capsys, monkeypatch): - """Test selecting of target on a Broadwell host.""" - - def broadwell_host_triple(): - return ('x86_64', 'intel', 'broadwell') - - monkeypatch.setattr(eessi_software_subdir_for_host, 'det_host_triple', broadwell_host_triple) - - # if generic is there, that's always a match - prep_tmpdir(tmpdir, ['x86_64/generic']) - assert find_best_target(tmpdir) == 'x86_64/generic' - - # targets from other CPU familues have no impact on target picked for Intel host CPU - prep_tmpdir(tmpdir, ['x86_64/amd/zen2', 'aarch64/graviton2', 'ppc64le/power9']) - assert find_best_target(tmpdir) == 'x86_64/generic' - - # incompatible targets are not picked - prep_tmpdir(tmpdir, ['x86_64/intel/skylake', 'x86_64/intel/cascadelake']) - assert find_best_target(tmpdir) == 'x86_64/generic' - - # compatible targets are picked if no better match is available - prep_tmpdir(tmpdir, ['x86_64/intel/nehalem']) - assert find_best_target(tmpdir) == 'x86_64/intel/nehalem' - - prep_tmpdir(tmpdir, ['x86_64/intel/ivybridge']) - assert find_best_target(tmpdir) == 'x86_64/intel/ivybridge' - - # unknown targets don't cause trouble - prep_tmpdir(tmpdir, ['x86_64/intel/no_such_intel_cpu']) - assert find_best_target(tmpdir) == 'x86_64/intel/ivybridge' - captured = capsys.readouterr() - assert captured.out == '' - assert captured.err == '' - - # older targets have to no impact on best target (sandybridge < ivybridge) - prep_tmpdir(tmpdir, ['x86_64/intel/sandybridge']) - assert find_best_target(tmpdir) == 'x86_64/intel/ivybridge' - - prep_tmpdir(tmpdir, ['x86_64/intel/haswell']) - assert find_best_target(tmpdir) == 'x86_64/intel/haswell' - - expected = ['cascadelake', 'haswell', 'ivybridge', 'nehalem', 'no_such_intel_cpu', 'sandybridge', 'skylake'] - assert sorted(os.listdir(os.path.join(tmpdir, 'software', 'linux', 'x86_64', 'intel'))) == expected - - # exact match, no better target than this - prep_tmpdir(tmpdir, ['x86_64/intel/broadwell']) - assert find_best_target(tmpdir) == 'x86_64/intel/broadwell' diff --git a/install_apptainer_ubuntu.sh b/install_apptainer_ubuntu.sh deleted file mode 100755 index e7997cad3d..0000000000 --- a/install_apptainer_ubuntu.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -set -e - -sudo apt update -sudo apt install -y software-properties-common - -sudo add-apt-repository -y ppa:apptainer/ppa -sudo apt update -sudo apt install -y apptainer-suid - -apptainer --version -# also check whether 'singularity' command is still provided by Apptainer installation -singularity --version diff --git a/install_scripts.sh b/install_scripts.sh deleted file mode 100755 index f4863686fc..0000000000 --- a/install_scripts.sh +++ /dev/null @@ -1,185 +0,0 @@ -#!/bin/bash -# -# Script to install scripts from the software-layer repo into the EESSI software stack - -display_help() { - echo "usage: $0 [OPTIONS]" - echo " -p | --prefix - prefix to copy the scripts to" - echo " -h | --help - display this usage information" -} - -file_changed_in_pr() { - local full_path="$1" - - # Make sure file exists - [[ -f "$full_path" ]] || return 1 - - # Check if the file is in a Git repo (it should be) - local repo_root - repo_root=$(git -C "$(dirname "$full_path")" rev-parse --show-toplevel 2>/dev/null) - if [[ -z "$repo_root" ]]; then - return 2 # Not in a git repository - fi - - # Compute relative path to the repo root - local rel_path - rel_path=$(realpath --relative-to="$repo_root" "$full_path") - - # Check if the file changed in the PR diff file that we have - ( - cd "$repo_root" || return 2 - # $PR_DIFF should be set by the calling script - if [[ ! -z ${PR_DIFF} ]] && [[ -f "$PR_DIFF" ]]; then - grep -q "b/$rel_path" "$PR_DIFF" # Add b/ to match diff patterns - else - return 3 - fi - ) && return 0 || return 1 -} - -compare_and_copy() { - if [ "$#" -ne 2 ]; then - echo "Usage of function: compare_and_copy " - return 1 - fi - - source_file="$1" - destination_file="$2" - - if [ ! -f "$destination_file" ] || ! diff -q "$source_file" "$destination_file" ; then - echo "Files $source_file and $destination_file differ, checking if we should copy or not" - # We only copy if the file is part of the PR - if file_changed_in_pr "$source_file"; then - echo "File has changed in the PR" - cp "$source_file" "$destination_file" - echo "File $source_file copied to $destination_file" - else - case $? in - 1) echo "❌ File has NOT changed in PR" ;; - 2) echo "🚫 Not in Git repository" ;; - 3) echo "🚫 No PR diff file found" ;; - *) echo "⚠️ Unknown error" ;; - esac - fi - else - echo "Files $1 and $2 are identical. No copy needed." - fi -} - -copy_files_by_list() { -# Compares and copies listed files from a source to a target directory - if [ ! "$#" -ge 3 ]; then - echo "Usage of function: copy_files_by_list " - echo "Here, file_list is an (expanded) bash array" - echo "Example:" - echo "my_files=(file1 file2)" - echo 'copy_files_by_list /my/source /my/target "${my_files[@]}"' - return 1 - fi - source_dir="$1" - target_dir="$2" - # Need to shift all arguments to the left twice. Then, rebuild the array with the rest of the arguments - shift - shift - file_list=("$@") - - # Create target dir - mkdir -p ${target_dir} - - # Copy from source to target - echo "Copying files: ${file_list[@]}" - echo "From directory: ${source_dir}" - echo "To directory: ${target_dir}" - - for file in ${file_list[@]}; do - compare_and_copy ${source_dir}/${file} ${target_dir}/${file} - done -} - -POSITIONAL_ARGS=() - -while [[ $# -gt 0 ]]; do - case $1 in - -p|--prefix) - INSTALL_PREFIX="$2" - shift 2 - ;; - -h|--help) - display_help # Call your function - # no shifting needed here, we're done. - exit 0 - ;; - -*|--*) - echo "Error: Unknown option: $1" >&2 - exit 1 - ;; - *) # No more options - POSITIONAL_ARGS+=("$1") # save positional arg - shift - ;; - esac -done - -set -- "${POSITIONAL_ARGS[@]}" - -TOPDIR=$(dirname $(realpath $0)) - -# Copy for init directory -init_files=( - bash eessi_archdetect.sh eessi_defaults eessi_environment_variables eessi_software_subdir_for_host.py - minimal_eessi_env README.md test.py lmod_eessi_archdetect_wrapper.sh lmod_eessi_archdetect_wrapper_accel.sh - -) -copy_files_by_list ${TOPDIR}/init ${INSTALL_PREFIX}/init "${init_files[@]}" - -# Copy for the init/arch_specs directory -arch_specs_files=( - eessi_arch_arm.spec eessi_arch_ppc.spec eessi_arch_riscv.spec eessi_arch_x86.spec -) -copy_files_by_list ${TOPDIR}/init/arch_specs ${INSTALL_PREFIX}/init/arch_specs "${arch_specs_files[@]}" - -# Copy for init/Magic_castle directory -mc_files=( - bash eessi_python3 -) -copy_files_by_list ${TOPDIR}/init/Magic_Castle ${INSTALL_PREFIX}/init/Magic_Castle "${mc_files[@]}" - -# Copy for init/modules/EESSI directory -mc_files=( - 2023.06.lua -) -copy_files_by_list ${TOPDIR}/init/modules/EESSI ${INSTALL_PREFIX}/init/modules/EESSI "${mc_files[@]}" - -# Copy for init/lmod directory -init_script_files=( - bash zsh ksh fish csh -) -copy_files_by_list ${TOPDIR}/init/lmod ${INSTALL_PREFIX}/init/lmod "${init_script_files[@]}" - -# Copy for the scripts directory -script_files=( - utils.sh -) -copy_files_by_list ${TOPDIR}/scripts ${INSTALL_PREFIX}/scripts "${script_files[@]}" - -# Copy files for the scripts/gpu_support/nvidia directory -nvidia_files=( - install_cuda_and_libraries.sh - install_cuda_host_injections.sh - link_nvidia_host_libraries.sh -) -copy_files_by_list ${TOPDIR}/scripts/gpu_support/nvidia ${INSTALL_PREFIX}/scripts/gpu_support/nvidia "${nvidia_files[@]}" - -# Easystacks to be used to install software in host injections -host_injections_easystacks=( - eessi-2023.06-eb-4.9.4-2023a-CUDA-host-injections.yml - eessi-2023.06-eb-4.9.4-2023b-CUDA-host-injections.yml -) -copy_files_by_list ${TOPDIR}/scripts/gpu_support/nvidia/easystacks \ -${INSTALL_PREFIX}/scripts/gpu_support/nvidia/easystacks "${host_injections_easystacks[@]}" - -# Copy over EasyBuild hooks file used for installations -hook_files=( - eb_hooks.py -) -copy_files_by_list ${TOPDIR} ${INSTALL_PREFIX}/init/easybuild "${hook_files[@]}" diff --git a/install_software_layer.sh b/install_software_layer.sh deleted file mode 100755 index 8b88e75713..0000000000 --- a/install_software_layer.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -base_dir=$(dirname $(realpath $0)) -source ${base_dir}/init/eessi_defaults -$base_dir/run_in_compat_layer_env.sh $base_dir/EESSI-install-software.sh "$@" diff --git a/licenses/README.md b/licenses/README.md deleted file mode 100644 index 36a7615b21..0000000000 --- a/licenses/README.md +++ /dev/null @@ -1,3 +0,0 @@ -see https://spdx.org/licenses - -Python function to download SPDX list of licenses is available in `spdx.py` diff --git a/licenses/licenses.json b/licenses/licenses.json deleted file mode 100644 index 8831ed368c..0000000000 --- a/licenses/licenses.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "EasyBuild": { - "spdx": "GPL-2.0-only", - "license_url": "https://easybuild.io" - }, - "GCCcore": { - "spdx": "GPL-2.0-with-GCC-exception", - "license_url": "https://github.com/gcc-mirror/gcc/blob/master/COPYING" - } -} diff --git a/licenses/spdx.py b/licenses/spdx.py deleted file mode 100644 index 06c3edb4e6..0000000000 --- a/licenses/spdx.py +++ /dev/null @@ -1,100 +0,0 @@ -import json -import logging -import sys -import urllib.request - -SPDX_LICENSE_LIST_URL = 'https://raw.githubusercontent.com/spdx/license-list-data/main/json/licenses.json' - -LICENSE_URL = 'license_url' -SPDX = 'spdx' - -spdx_license_list = None - -# Configure the logging module -logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") - - -def get_spdx_license_list(): - """ - Download JSON file with current list of SPDX licenses, parse it, and return it as a Python dictionary. - """ - global spdx_license_list - - if spdx_license_list is None: - with urllib.request.urlopen(SPDX_LICENSE_LIST_URL) as fp: - spdx_license_list = json.load(fp) - version, release_date = spdx_license_list['licenseListVersion'], spdx_license_list['releaseDate'] - logging.info(f"Downloaded version {version} of SPDX license list (release date: {release_date})") - licenses = spdx_license_list['licenses'] - logging.info(f"Found info on {len(licenses)} licenses!") - - return spdx_license_list - - -def license_info(spdx_id): - """Find license with specified SPDX identifier.""" - - spdx_license_list = get_spdx_license_list() - - licenses = spdx_license_list['licenses'] - for lic in licenses: - if lic['licenseId'] == spdx_id: - return lic - - # if no match is found, return None as result - return None - - -def read_licenses(path): - """ - Read software project to license mapping from specified path - """ - with open(path) as fp: - licenses = json.loads(fp.read()) - - return licenses - - -def check_licenses(licenses): - """ - Check mapping of software licenses: make sure SPDX identifiers are valid. - """ - faulty_licenses = {} - - for software_name in licenses: - spdx_lic_id = licenses[software_name][SPDX] - lic_info = license_info(spdx_lic_id) - if lic_info: - lic_url = licenses[software_name][LICENSE_URL] - logging.info(f"License for software '{software_name}': {lic_info['name']} (see {lic_url})") - else: - logging.warning(f"Found faulty SPDX license ID for {software_name}: {spdx_lic_id}") - faulty_licenses[software_name] = spdx_lic_id - - if faulty_licenses: - logging.warning(f"Found {len(faulty_licenses)} faulty SPDIX license IDs (out of {len(licenses)})!") - result = False - else: - logging.info(f"License check passed for {len(licenses)} licenses!") - result = True - - return result - - -def main(args): - if len(args) == 1: - licenses_path = args[0] - else: - logging.error("Usage: python spdx.py ") - sys.exit(1) - - licenses = read_licenses(licenses_path) - if check_licenses(licenses): - logging.info("All license checks PASSED!") - else: - logging.error("One or more licence checks failed!") - sys.exit(2) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/load_easybuild_module.sh b/load_easybuild_module.sh deleted file mode 100755 index d1bfd18bb5..0000000000 --- a/load_easybuild_module.sh +++ /dev/null @@ -1,131 +0,0 @@ -# Script to load the environment module for a specific version of EasyBuild. -# If that module is not available yet, the current latest EasyBuild version of EasyBuild will be installed, -# and used to install the specific EasyBuild version being specified. -# -# This script must be sourced, since it makes changes in the current environment, like loading an EasyBuild module. -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Kenneth Hosye (@boegel, HPC-UGent) -# -# license: GPLv2 -# -# -set -o pipefail - -if [ $# -ne 1 ]; then - echo "Usage: $0 " >&2 - exit 1 -fi - -# don't use $EASYBUILD_VERSION, since that enables always running 'eb --version' -EB_VERSION=${1} - -# make sure that environment variables that we expect to be set are indeed set -if [ -z "${TMPDIR}" ]; then - echo "\$TMPDIR is not set" >&2 - exit 2 -fi - -# ${EB} is used to specify which 'eb' command should be used; -# can potentially be more than just 'eb', for example when using 'eb --optarch=GENERIC' -if [ -z "${EB}" ]; then - echo "\$EB is not set" >&2 - exit 2 -fi - -# make sure that utility functions are defined (cfr. scripts/utils.sh script in EESSI/software-layer repo) -type check_exit_code -if [ $? -ne 0 ]; then - echo "check_exit_code function is not defined" >&2 - exit 3 -fi - -echo ">> Checking for EasyBuild module..." - -ml_av_easybuild_out=${TMPDIR}/ml_av_easybuild.out -module avail 2>&1 | grep -i easybuild/${EB_VERSION} &> ${ml_av_easybuild_out} - -if [[ $? -eq 0 ]]; then - echo_green ">> Module for EasyBuild v${EB_VERSION} found!" -else - echo_yellow ">> No module yet for EasyBuild v${EB_VERSION}, installing it..." - - EB_TMPDIR=${TMPDIR}/ebtmp - echo ">> Temporary installation (in ${EB_TMPDIR})..." - pip_install_out=${TMPDIR}/pip_install.out - pip3 install --prefix ${EB_TMPDIR} easybuild &> ${pip_install_out} - - # keep track of original $PATH and $PYTHONPATH values, so we can restore them - ORIG_PATH=${PATH} - ORIG_PYTHONPATH=${PYTHONPATH} - - echo ">> Final installation in ${EASYBUILD_INSTALLPATH}..." - export PATH=${EB_TMPDIR}/bin:${PATH} - export PYTHONPATH=$(ls -d ${EB_TMPDIR}/lib/python*/site-packages):${PYTHONPATH} - eb_install_out=${TMPDIR}/eb_install.out - ok_msg="Latest EasyBuild release installed, let's go!" - fail_msg="Installing latest EasyBuild release failed, that's not good... (output: ${eb_install_out})" - ${EB} --install-latest-eb-release 2>&1 | tee ${eb_install_out} - check_exit_code $? "${ok_msg}" "${fail_msg}" - - # maybe the module obtained with --install-latest-eb-release is exactly the EasyBuild version we wanted? - IGNORE_CACHE='' - module avail 2>&1 | grep -i easybuild/${EB_VERSION} &> ${ml_av_easybuild_out} - if [[ $? -eq 0 ]]; then - echo_green ">> Module for EasyBuild v${EB_VERSION} found!" - else - module --ignore_cache avail 2>&1 | grep -i easybuild/${EB_VERSION} &> ${ml_av_easybuild_out} - if [[ $? -eq 0 ]]; then - echo_green ">> Module for EasyBuild v${EB_VERSION} found!" - IGNORE_CACHE='--ignore_cache' - else - eb_ec=EasyBuild-${EB_VERSION}.eb - echo_yellow ">> Still no module for EasyBuild v${EB_VERSION}, trying with easyconfig ${eb_ec}..." - ${EB} --search ${eb_ec} | grep ${eb_ec} > /dev/null - if [[ $? -eq 0 ]]; then - echo "Easyconfig ${eb_ec} found for EasyBuild v${EB_VERSION}, so installing it..." - ok_msg="EasyBuild v${EB_VERSION} installed, alright!" - fail_msg="Installing EasyBuild v${EB_VERSION}, yikes! (output: ${eb_install_out})" - ${EB} EasyBuild-${EB_VERSION}.eb 2>&1 | tee -a ${eb_install_out} - check_exit_code $? "${ok_msg}" "${fail_msg}" - else - fatal_error "No easyconfig found for EasyBuild v${EB_VERSION}" - fi - fi - fi - - # restore origin $PATH and $PYTHONPATH values, and clean up environment variables that are no longer needed - export PATH=${ORIG_PATH} - export PYTHONPATH=${ORIG_PYTHONPATH} - unset EB_TMPDIR ORIG_PATH ORIG_PYTHONPATH - - module avail easybuild/${EB_VERSION} &> ${ml_av_easybuild_out} - if [[ $? -eq 0 ]]; then - echo_green ">> EasyBuild/${EB_VERSION} module installed!" - else - fatal_error "EasyBuild/${EB_VERSION} module failed to install?! (output of 'pip install' in ${pip_install_out}, output of 'eb' in ${eb_install_out}, output of 'module avail easybuild' in ${ml_av_easybuild_out})" - fi -fi - -echo ">> Loading EasyBuild v${EB_VERSION} module..." -module ${IGNORE_CACHE} load EasyBuild/${EB_VERSION} -eb_show_system_info_out=${TMPDIR}/eb_show_system_info.out -${EB} --show-system-info > ${eb_show_system_info_out} -if [[ $? -eq 0 ]]; then - echo_green ">> EasyBuild seems to be working!" - ${EB} --version | grep "${EB_VERSION}" - if [[ $? -eq 0 ]]; then - echo_green "Found EasyBuild version ${EB_VERSION}, looking good!" - else - ${EB} --version - fatal_error "Expected to find EasyBuild version ${EB_VERSION}, giving up here..." - fi - ${EB} --show-config -else - cat ${eb_show_system_info_out} - fatal_error "EasyBuild not working?!" -fi - -unset EB_VERSION diff --git a/load_eessi_extend_module.sh b/load_eessi_extend_module.sh deleted file mode 100755 index b5ad47de4e..0000000000 --- a/load_eessi_extend_module.sh +++ /dev/null @@ -1,123 +0,0 @@ -# Script to load the environment module for EESSI-extend. -# If that module is not available yet, a specific version will be installed using the latest EasyBuild. -# -# This script must be sourced, since it makes changes in the current environment, like loading an EESSI-extend module. -# -# Assumptions (if one is not satisfied the script prints a message and exits) -# - EESSI version is given as first argument -# - TMPDIR is set -# - EB is set -# - EASYBUILD_INSTALLPATH needs to be set -# - Function check_exit_code is defined; -# scripts/utils.sh in EESSI/software-layer repository defines this function, hence -# scripts/utils.sh shall be sourced before this script is run -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Kenneth Hoste (@boegel, HPC-UGent) -# author: Alan O'Cais (@ocaisa, CECAM) -# author: Thomas Roeblitz (@trz42, University of Bergen) -# -# license: GPLv2 -# -# -set -o pipefail - -# this script is *sourced*, not executed, so can't rely on $0 to determine path to self or script name -# $BASH_SOURCE points to correct path or script name, see also http://mywiki.wooledge.org/BashFAQ/028 -if [ $# -ne 1 ]; then - echo "Usage: source ${BASH_SOURCE} " >&2 - exit 1 -fi - -EESSI_EXTEND_VERSION="${1}-easybuild" - -# make sure that environment variables that we expect to be set are indeed set -if [ -z "${TMPDIR}" ]; then - echo "\$TMPDIR is not set; exiting" >&2 - exit 2 -fi - -# ${EB} is used to specify which 'eb' command should be used; -# can potentially be more than just 'eb', for example when using 'eb --optarch=GENERIC' -if [ -z "${EB}" ]; then - echo "\$EB is not set; exiting" >&2 - exit 2 -fi - -# ${EASYBUILD_INSTALLPATH} points to the installation path and needs to be set -if [ -z "${EASYBUILD_INSTALLPATH}" ]; then - echo "\$EASYBUILD_INSTALLPATH is not set; exiting" >&2 - exit 2 -fi - -# make sure that utility functions are defined (cfr. scripts/utils.sh script in EESSI/software-layer repo) -type check_exit_code -if [ $? -ne 0 ]; then - echo "check_exit_code function is not defined; exiting" >&2 - exit 3 -fi - -echo ">> Checking for EESSI-extend module..." - -ml_av_eessi_extend_out=${TMPDIR}/ml_av_eessi_extend.out -# need to use --ignore_cache to avoid the case that the module was removed (to be -# rebuilt) but it is still in the cache -module --ignore_cache avail 2>&1 | grep -i EESSI-extend/${EESSI_EXTEND_VERSION} &> ${ml_av_eessi_extend_out} - -if [[ $? -eq 0 ]]; then - echo_green ">> Module for EESSI-extend/${EESSI_EXTEND_VERSION} found!" -else - echo_yellow ">> No module yet for EESSI-extend/${EESSI_EXTEND_VERSION}, installing it..." - - EB_TMPDIR=${TMPDIR}/ebtmp - echo ">> Using temporary installation of EasyBuild (in ${EB_TMPDIR})..." - pip_install_out=${TMPDIR}/pip_install.out - pip3 install --prefix ${EB_TMPDIR} easybuild &> ${pip_install_out} - - # keep track of original $PATH and $PYTHONPATH values, so we can restore them - ORIG_PATH=${PATH} - ORIG_PYTHONPATH=${PYTHONPATH} - - # source configure_easybuild to use correct eb settings - ( - export EASYBUILD_PREFIX=${TMPDIR}/easybuild - export EASYBUILD_READ_ONLY_INSTALLDIR=1 - - echo ">> Final installation in ${EASYBUILD_INSTALLPATH}..." - export PATH=${EB_TMPDIR}/bin:${PATH} - export PYTHONPATH=$(ls -d ${EB_TMPDIR}/lib/python*/site-packages):${PYTHONPATH} - # EESSI-extend also needs EasyBuild to be installed as a module, so install the latest release - eb_install_out=${TMPDIR}/eb_install.out - ok_msg="Latest EasyBuild installed, let's go!" - fail_msg="Installing latest EasyBuild failed, that's not good... (output: ${eb_install_out})" - ${EB} --install-latest-eb-release 2>&1 | tee ${eb_install_out} - check_exit_code $? "${ok_msg}" "${fail_msg}" - # Now install EESSI-extend - eessi_install_out=${TMPDIR}/eessi_install.out - ok_msg="EESSI-extend/${EESSI_EXTEND_VERSION} installed, let's go!" - fail_msg="Installing EESSI-extend/${EESSI_EXTEND_VERSION} failed, that's not good... (output: ${eessi_install_out})" - # while always adding --try-amend=keep... may do no harm, we could make - # an attempt to figure out if it is needed, e.g., when we are rebuilding - ${EB} "EESSI-extend-easybuild.eb" --try-amend=keeppreviousinstall=True 2>&1 | tee ${eessi_install_out} - check_exit_code $? "${ok_msg}" "${fail_msg}" - ) - - # restore origin $PATH and $PYTHONPATH values, and clean up environment variables that are no longer needed - export PATH=${ORIG_PATH} - export PYTHONPATH=${ORIG_PYTHONPATH} - unset EB_TMPDIR ORIG_PATH ORIG_PYTHONPATH - - module --ignore_cache avail EESSI-extend/${EESSI_EXTEND_VERSION} &> ${ml_av_eessi_extend_out} - if [[ $? -eq 0 ]]; then - echo_green ">> EESSI-extend/${EESSI_EXTEND_VERSION} module installed!" - else - fatal_error "EESSI-extend/${EESSI_EXTEND_VERSION} module failed to install?! (output of 'pip install' in ${pip_install_out}, output of 'eb' in ${eb_install_out}, output of 'module avail EESSI-extend' in ${ml_av_eessi_extend_out})" - fi -fi - -echo ">> Loading EESSI-extend/${EESSI_EXTEND_VERSION} module..." -module --ignore_cache load EESSI-extend/${EESSI_EXTEND_VERSION} - -unset EESSI_EXTEND_VERSION diff --git a/run_in_compat_layer_env.sh b/run_in_compat_layer_env.sh deleted file mode 100755 index e9a49cbe3d..0000000000 --- a/run_in_compat_layer_env.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -base_dir=$(dirname $(realpath $0)) -source ${base_dir}/init/eessi_defaults - -if [ -z $EESSI_VERSION ]; then - echo "ERROR: \$EESSI_VERSION must be set!" >&2 - exit 1 -fi - -echo "EESSI_COMPAT_LAYER_DIR_OVERRIDE: ${EESSI_COMPAT_LAYER_DIR_OVERRIDE}" - -if [ ! -z ${EESSI_COMPAT_LAYER_DIR_OVERRIDE} ]; then - echo "EESSI_COMPAT_LAYER_DIR_OVERRIDE found. Setting EESSI_COMPAT_LAYER_DIR to ${EESSI_COMPAT_LAYER_DIR_OVERRIDE}" - EESSI_COMPAT_LAYER_DIR=${EESSI_COMPAT_LAYER_DIR_OVERRIDE} -else - EESSI_COMPAT_LAYER_DIR="${EESSI_CVMFS_REPO}/versions/${EESSI_VERSION}/compat/linux/$(uname -m)" -fi - -if [ ! -d ${EESSI_COMPAT_LAYER_DIR} ]; then - echo "ERROR: ${EESSI_COMPAT_LAYER_DIR} does not exist!" >&2 - exit 1 -fi - -INPUT=$(echo "$@") -if [ ! -z ${SLURM_JOB_ID} ]; then - INPUT="export SLURM_JOB_ID=${SLURM_JOB_ID}; ${INPUT}" -fi -if [ ! -z ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} ]; then - INPUT="export EESSI_SOFTWARE_SUBDIR_OVERRIDE=${EESSI_SOFTWARE_SUBDIR_OVERRIDE}; ${INPUT}" -fi -if [ ! -z ${EESSI_ACCELERATOR_TARGET} ]; then - INPUT="export EESSI_ACCELERATOR_TARGET=${EESSI_ACCELERATOR_TARGET}; ${INPUT}" -fi -if [ ! -z ${EESSI_CVMFS_REPO_OVERRIDE} ]; then - INPUT="export EESSI_CVMFS_REPO_OVERRIDE=${EESSI_CVMFS_REPO_OVERRIDE}; ${INPUT}" -fi -if [ ! -z ${EESSI_DEV_PROJECT} ]; then - INPUT="export EESSI_DEV_PROJECT=${EESSI_DEV_PROJECT}; ${INPUT}" -fi -if [ ! -z ${EESSI_VERSION_OVERRIDE} ]; then - INPUT="export EESSI_VERSION_OVERRIDE=${EESSI_VERSION_OVERRIDE}; ${INPUT}" -fi -if [ ! -z ${EESSI_COMPAT_LAYER_DIR} ]; then - INPUT="export EESSI_COMPAT_LAYER_DIR=${EESSI_COMPAT_LAYER_DIR}; ${INPUT}" -fi -if [ ! -z ${EESSI_OVERRIDE_GPU_CHECK} ]; then - INPUT="export EESSI_OVERRIDE_GPU_CHECK=${EESSI_OVERRIDE_GPU_CHECK}; ${INPUT}" -fi -if [ ! -z ${http_proxy} ]; then - INPUT="export http_proxy=${http_proxy}; ${INPUT}" -fi -if [ ! -z ${https_proxy} ]; then - INPUT="export https_proxy=${https_proxy}; ${INPUT}" -fi -if [ ! -z ${EASYBUILD_ROBOT_PATHS} ]; then - INPUT="export EASYBUILD_ROBOT_PATHS=${EASYBUILD_ROBOT_PATHS}; ${INPUT}" -fi - -echo "Running '${INPUT}' in EESSI (${EESSI_CVMFS_REPO}) ${EESSI_VERSION} compatibility layer environment..." -${EESSI_COMPAT_LAYER_DIR}/startprefix <<< "${INPUT}" diff --git a/run_tests.sh b/run_tests.sh deleted file mode 100755 index f6264c3cc8..0000000000 --- a/run_tests.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# -# This script gets invoked by the bot/test.sh script to run within the EESSI container -# Thus, this script defines all of the steps that should run for the tests. -# Note that, unless we have good reason, we don't run test steps in the prefix environment: -# users also typically don't run in the prefix environment, and we want to check if the -# software works well in that specific setup. -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Caspar van Leeuwen (@casparvl) -# -# license: GPLv2 -# - -base_dir=$(dirname $(realpath $0)) -source ${base_dir}/init/eessi_defaults - -# Make sure we clone the latest version. This assumes versions are of the format "v1.2.3", then picks the latest -# then checks it out -TEST_CLONE="git clone https://github.com/EESSI/test-suite EESSI-test-suite && cd EESSI-test-suite" -LATEST_VERSION="VERSION=\$(git tag | grep '^v[0-9]\+\.[0-9]\+\.[0-9]\+$' | sort -t. -k 1,1n -k 2,2n -k 3,3n | tail -1)" -CHECKOUT_LATEST="git checkout \${VERSION}" - -# Git clone has to be run in compat layer, to make the git command available -./run_in_compat_layer_env.sh "${TEST_CLONE} && ${LATEST_VERSION} && ${CHECKOUT_LATEST}" - -# Run the test suite -./test_suite.sh "$@" diff --git a/scripts/cfg_files.sh b/scripts/cfg_files.sh deleted file mode 100644 index 57ea2f7c03..0000000000 --- a/scripts/cfg_files.sh +++ /dev/null @@ -1,167 +0,0 @@ -# functions for working with ini/cfg files -# -# This file is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Thomas Roeblitz (@trz42) -# -# license: GPLv2 -# - - -# global variables -# -a -> indexed array -# -A -> associative array -declare -A cfg_repos -declare -A cfg_file_map - - -# functions -function cfg_get_section { - if [[ "$1" =~ ^(\[)(.*)(\])$ ]]; then - echo ${BASH_REMATCH[2]} - else - echo "" - fi -} - -function cfg_get_key_value { - if [[ "$1" =~ ^([^=]+)=([^=]+)$ ]]; then - echo "${BASH_REMATCH[1]}=${BASH_REMATCH[2]}" - else - echo "" - fi -} - -function cfg_load { - local cur_section="" - local cur_key="" - local cur_val="" - IFS= - while read -r line; do - new_section=$(cfg_get_section $line) - # got a new section - if [[ -n "$new_section" ]]; then - cur_section=$new_section - # not a section, try a key value - else - val=$(cfg_get_key_value $line) - # trim leading and trailing spaces as well - cur_key=$(echo $val | cut -f1 -d'=' | cfg_trim_spaces) - cur_val=$(echo $val | cut -f2 -d'=' | cfg_trim_spaces) - if [[ -n "$cur_key" ]]; then - # section + key is the associative in bash array, the field separator is space - cfg_repos[${cur_section} ${cur_key}]=$cur_val - fi - fi - done <$1 -} - -function cfg_print { - for index in "${!cfg_repos[@]}" - do - # split the associative key in to section and key - echo -n "section : $(echo $index | cut -f1 -d ' ');" - echo -n "key : $(echo $index | cut -f2 -d ' ');" - echo "value: ${cfg_repos[$index]}" - done -} - -function cfg_sections { - declare -A sections - for key in "${!cfg_repos[@]}" - do - # extract section from the associative key - section=$(echo $key | cut -f1 -d ' ') - sections[${section}]=1 - done - for repo in "${!sections[@]}" - do - echo "${repo}" - done -} - -function cfg_get_value { - section=$1 - key=$2 - echo "${cfg_repos[$section $key]}" -} - -function cfg_trim_spaces { - # reads from argument $1 or stdin - if [[ $# -gt 0 ]]; then - sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< ${1} - else - sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' < /dev/stdin - fi -} - -function cfg_trim_quotes { - # reads from argument $1 or stdin - if [[ $# -gt 0 ]]; then - sed -e 's/^"*//' -e 's/"*$//' <<< ${1} - else - sed -e 's/^"*//' -e 's/"*$//' < /dev/stdin - fi -} - -function cfg_trim_curly_brackets { - # reads from argument $1 or stdin - if [[ $# -gt 0 ]]; then - sed -e 's/^{*//' -e 's/}*$//' <<< ${1} - else - sed -e 's/^{*//' -e 's/}*$//' < /dev/stdin - fi -} - -function cfg_get_all_sections { - # first field in keys - # 1. get first field in all keys, 2. filter duplicates, 3. return them as string - declare -A all_sections - for key in "${!cfg_repos[@]}" - do - section=$(echo "$key" | cut -f1 -d' ') - all_sections[${section}]=1 - done - sections= - for sec_key in "${!all_sections[@]}" - do - sections="${sections} ${sec_key}" - done - echo "${sections}" | cfg_trim_spaces -} - -function cfg_init_file_map { - # strip '{' and '}' from config_map - # split config_map at ',' - # for each item: split at ':' use first as key, second as value - - # reset global variable - cfg_file_map=() - - # expects a string containing the config_map from the cfg file - # trim leading and trailing curly brackets - cm_trimmed=$(cfg_trim_curly_brackets "$1") - - # split into elements along ',' - declare -a cm_mappings - IFS=',' read -r -a cm_mappings <<< "${cm_trimmed}" - - for index in "${!cm_mappings[@]}" - do - # split mapping into key and value - map_key=$(echo ${cm_mappings[index]} | cut -f1 -d':') - map_value=$(echo ${cm_mappings[index]} | cut -f2 -d':') - # trim spaces and double quotes at start and end - tr_key=$(cfg_trim_spaces "${map_key}" | cfg_trim_quotes) - tr_value=$(cfg_trim_spaces "${map_value}" | cfg_trim_quotes) - cfg_file_map[${tr_key}]=${tr_value} - done -} - -function cfg_print_map { - for index in "${!cfg_file_map[@]}" - do - echo "${index} --> ${cfg_file_map[${index}]}" - done -} diff --git a/scripts/gpu_support/nvidia/easystacks/eessi-2023.06-eb-4.9.4-2023a-CUDA-host-injections.yml b/scripts/gpu_support/nvidia/easystacks/eessi-2023.06-eb-4.9.4-2023a-CUDA-host-injections.yml deleted file mode 100644 index 83e68077a2..0000000000 --- a/scripts/gpu_support/nvidia/easystacks/eessi-2023.06-eb-4.9.4-2023a-CUDA-host-injections.yml +++ /dev/null @@ -1,9 +0,0 @@ -# This EasyStack provides a list of all the EasyConfigs that should be installed in host_injections -# for nvidia GPU support, because they cannot (fully) be shipped as part of EESSI due to license constraints -easyconfigs: - - CUDA-12.1.1.eb - - cuDNN-8.9.2.26-CUDA-12.1.1.eb: - options: - # needed to enforce acceptance of EULA in cuDNN easyblock, - # see https://github.com/easybuilders/easybuild-easyblocks/pull/3473 - include-easyblocks-from-commit: 11afb88ec55e0ca431cbe823696aa43e2a9bfca8 diff --git a/scripts/gpu_support/nvidia/easystacks/eessi-2023.06-eb-4.9.4-2023b-CUDA-host-injections.yml b/scripts/gpu_support/nvidia/easystacks/eessi-2023.06-eb-4.9.4-2023b-CUDA-host-injections.yml deleted file mode 100644 index 5cfec813f6..0000000000 --- a/scripts/gpu_support/nvidia/easystacks/eessi-2023.06-eb-4.9.4-2023b-CUDA-host-injections.yml +++ /dev/null @@ -1,4 +0,0 @@ -# This EasyStack provides a list of all the EasyConfigs that should be installed in host_injections -# for nvidia GPU support, because they cannot (fully) be shipped as part of EESSI due to license constraints -easyconfigs: - - CUDA-12.4.0.eb diff --git a/scripts/gpu_support/nvidia/install_cuda_and_libraries.sh b/scripts/gpu_support/nvidia/install_cuda_and_libraries.sh deleted file mode 100755 index 8b87f630e0..0000000000 --- a/scripts/gpu_support/nvidia/install_cuda_and_libraries.sh +++ /dev/null @@ -1,265 +0,0 @@ -#!/usr/bin/env bash - -# This script can be used to install CUDA and other libraries by NVIDIA under -# the `.../host_injections` directory. -# -# This provides the parts of the CUDA installation and other libriaries that -# cannot be redistributed as part of EESSI due to license limitations. While -# GPU-based software from EESSI will _run_ without these, installation of -# additional software that builds upon CUDA or other libraries requires that -# these installation are present under `host_injections`. -# -# The `host_injections` directory is a variant symlink that by default points to -# `/opt/eessi`, unless otherwise defined in the local CVMFS configuration (see -# https://cvmfs.readthedocs.io/en/stable/cpt-repo.html#variant-symlinks). For the -# installation to be successful, this directory needs to be writeable by the user -# executing this script. - -# Initialise our bash functions -TOPDIR=$(dirname $(realpath $BASH_SOURCE)) -source "$TOPDIR"/../../utils.sh - -# Function to display help message -show_help() { - echo "Usage: $0 [OPTIONS]" - echo "Options:" - echo " --help Display this help message" - echo " --accept-cuda-eula You _must_ accept the CUDA EULA to install" - echo " CUDA, see the EULA at" - echo " https://docs.nvidia.com/cuda/eula/index.html" - echo " --accept-cudnn-eula You _must_ accept the cuDNN EULA to install" - echo " cuDNN, see the EULA at" - echo " https://docs.nvidia.com/deeplearning/cudnn/latest/reference/eula.html" - echo " -t, --temp-dir /path/to/tmpdir Specify a location to use for temporary" - echo " storage during the installation of CUDA" - echo " and/or other libraries (must have" - echo " several GB available; depends on the number of installations)" -} - -# Initialize variables -cuda_eula_accepted=0 -cudnn_eula_accepted=0 -EASYSTACK_FILE= -TEMP_DIR= - -# Parse command-line options -while [[ $# -gt 0 ]]; do - case "$1" in - --help) - show_help - exit 0 - ;; - --accept-cuda-eula) - cuda_eula_accepted=1 - shift 1 - ;; - --accept-cudnn-eula) - cudnn_eula_accepted=1 - shift 1 - ;; - -t|--temp-dir) - if [ -n "$2" ]; then - TEMP_DIR="$2" - shift 2 - else - echo "Error: Argument required for $1" - show_help - exit 1 - fi - ;; - *) - show_help - fatal_error "Error: Unknown option: $1" - ;; - esac -done - -# Make sure EESSI is initialised -check_eessi_initialised - -# we need a directory we can use for temporary storage -if [[ -z "${TEMP_DIR}" ]]; then - tmpdir=$(mktemp -d) -else - mkdir -p ${TEMP_DIR} - tmpdir=$(mktemp -d --tmpdir=${TEMP_DIR} cuda_n_co.XXX) - if [[ ! -d "$tmpdir" ]] ; then - fatal_error "Could not create directory ${tmpdir}" - fi -fi -echo "Created temporary directory '${tmpdir}'" - -# Store MODULEPATH so it can be restored at the end of each loop iteration -SAVE_MODULEPATH=${MODULEPATH} - -for EASYSTACK_FILE in ${TOPDIR}/easystacks/eessi-*CUDA*.yml; do - echo -e "Processing easystack file ${easystack_file}...\n\n" - - # determine version of EasyBuild module to load based on EasyBuild version included in name of easystack file - eb_version=$(echo ${EASYSTACK_FILE} | sed 's/.*eb-\([0-9.]*\).*.yml/\1/g') - - # Load EasyBuild version for this easystack file _before_ loading EESSI-extend - module_avail_out=${tmpdir}/ml.out - module avail 2>&1 | grep EasyBuild/${eb_version} &> ${module_avail_out} - if [[ $? -eq 0 ]]; then - echo_green ">> Found an EasyBuild/${eb_version} module" - else - echo_yellow ">> No EasyBuild/${eb_version} module found: skipping step to install easystack file ${easystack_file} (see output in ${module_avail_out})" - continue - fi - module load EasyBuild/${eb_version} - - # Make sure EESSI-extend does a site install here - # We need to reload it with the current environment variables set - unset EESSI_CVMFS_INSTALL - unset EESSI_PROJECT_INSTALL - unset EESSI_USER_INSTALL - export EESSI_SITE_INSTALL=1 - module unload EESSI-extend - ml_av_eessi_extend_out=${tmpdir}/ml_av_eessi_extend.out - # need to use --ignore_cache to avoid the case that the module was removed (to be - # rebuilt) but it is still in the cache and the rebuild failed - EESSI_EXTEND_VERSION=${EESSI_VERSION}-easybuild - module --ignore_cache avail 2>&1 | grep -i EESSI-extend/${EESSI_EXTEND_VERSION} &> ${ml_av_eessi_extend_out} - if [[ $? -eq 0 ]]; then - echo_green ">> Module for EESSI-extend/${EESSI_EXTEND_VERSION} found!" - else - error="\nNo module for EESSI-extend/${EESSI_EXTEND_VERSION} found\nwhile EESSI has been initialised to use software under ${EESSI_SOFTWARE_PATH}\n" - fatal_error "${error}" - fi - module --ignore_cache load EESSI-extend/${EESSI_EXTEND_VERSION} - unset EESSI_EXTEND_VERSION - - # Install modules in hidden .modules dir to keep track of what was installed before - # (this action is temporary, and we do not call Lmod again within the current shell context, but in EasyBuild - # subshells, so loaded modules are not automatically unloaded) - MODULEPATH=${EESSI_SITE_SOFTWARE_PATH}/.modules/all - echo "set MODULEPATH=${MODULEPATH}" - - # We don't want hooks used in this install, we need vanilla installations - touch "${tmpdir}"/none.py - export EASYBUILD_HOOKS="${tmpdir}/none.py" - - # show EasyBuild configuration - echo "Show EasyBuild configuration" - eb --show-config - - # do a 'eb --dry-run-short' with the EASYSTACK_FILE and determine list of packages - # to be installed - echo ">> Determining if packages specified in ${EASYSTACK_FILE} are missing under ${EESSI_SITE_SOFTWARE_PATH}" - eb_dry_run_short_out=${tmpdir}/eb_dry_run_short.out - eb --dry-run-short --easystack ${EASYSTACK_FILE} 2>&1 | tee ${eb_dry_run_short_out} - ret=$? - - # Check if CUDA shall be installed - cuda_install_needed=0 - cat ${eb_dry_run_short_out} | grep "^ \* \[[ ]\]" | grep "module: CUDA/" > /dev/null - ret=$? - if [ "${ret}" -eq 0 ]; then - cuda_install_needed=1 - fi - - # Make sure the CUDA EULA is accepted if it shall be installed - if [ "${cuda_install_needed}" -eq 1 ] && [ "${cuda_eula_accepted}" -ne 1 ]; then - show_help - error="\nCUDA shall be installed. However, the CUDA EULA has not been accepted\nYou _must_ accept the CUDA EULA via the appropriate command line option.\n" - fatal_error "${error}" - fi - - # Check if cdDNN shall be installed - cudnn_install_needed=0 - cat ${eb_dry_run_short_out} | grep "^ \* \[[ ]\]" | grep "module: cuDNN/" > /dev/null - ret=$? - if [ "${ret}" -eq 0 ]; then - cudnn_install_needed=1 - fi - - # Make sure the cuDNN EULA is accepted if it shall be installed - if [ "${cudnn_install_needed}" -eq 1 ] && [ "${cudnn_eula_accepted}" -ne 1 ]; then - show_help - error="\ncuDNN shall be installed. However, the cuDNN EULA has not been accepted\nYou _must_ accept the cuDNN EULA via the appropriate command line option.\n" - fatal_error "${error}" - fi - - # determine the number of packages to be installed (assume 5 GB + num_packages * - # 3GB space needed). Both CUDA and cuDNN are about this size - number_of_packages=$(cat ${eb_dry_run_short_out} | grep "^ \* \[[ ]\]" | sed -e 's/^.*module: //' | sort -u | wc -l) - echo "number of packages to be (re-)installed: '${number_of_packages}'" - base_storage_space=$((5000000 + ${number_of_packages} * 3000000)) - - required_space_in_tmpdir=${base_storage_space} - # Let's see if we have sources and build locations defined if not, we use the temporary space - if [[ -z "${EASYBUILD_BUILDPATH}" ]]; then - export EASYBUILD_BUILDPATH=${tmpdir}/build - required_space_in_tmpdir=$((required_space_in_tmpdir + ${base_storage_space})) - fi - if [[ -z "${EASYBUILD_SOURCEPATH}" ]]; then - export EASYBUILD_SOURCEPATH=${tmpdir}/sources - required_space_in_tmpdir=$((required_space_in_tmpdir + ${base_storage_space})) - fi - - # The install is pretty fat, you need lots of space for download/unpack/install - # (~3*${base_storage_space}*1000 Bytes), - # need to do a space check before we proceed - avail_space=$(df --output=avail "${EESSI_SITE_SOFTWARE_PATH}"/ | tail -n 1 | awk '{print $1}') - min_disk_storage=$((3 * ${base_storage_space})) - if (( avail_space < ${min_disk_storage} )); then - fatal_error "Need at least $(echo "${min_disk_storage} / 1000000" | bc) GB disk space to install CUDA and other libraries under ${EESSI_SITE_SOFTWARE_PATH}, exiting now..." - fi - avail_space=$(df --output=avail "${tmpdir}"/ | tail -n 1 | awk '{print $1}') - if (( avail_space < required_space_in_tmpdir )); then - error="Need at least $(echo "${required_space_in_tmpdir} / 1000000" | bc) temporary disk space under ${tmpdir}.\n" - error="${error}Set the environment variable TEMP_DIR to a location with adequate space to pass this check." - error="${error}You can alternatively set EASYBUILD_BUILDPATH and/or EASYBUILD_SOURCEPATH" - error="${error}to reduce this requirement. Exiting now..." - fatal_error "${error}" - fi - - # Brief explanation of parameters: - # - prefix: using $tmpdir as default base directory for several EB settings - # - installpath-modules: We install the module in a hidden .modules, so that next time this script - # is run, it is not reinstalled. - # - ${accept_eula_opt}: We only set the --accept-eula-for=CUDA option if CUDA will be installed and if - # this script was called with the argument --accept-cuda-eula. - # - hooks: We don't want hooks used in this install, we need vanilla - # installations of CUDA and/or other libraries - # - easystack: Path to easystack file that defines which packages shall be - # installed - accept_eula_opt= - if [[ ${cuda_eula_accepted} -eq 1 ]]; then - accept_eula_opt="CUDA" - fi - if [[ ${cudnn_eula_accepted} -eq 1 ]]; then - if [[ -z ${accept_eula_opt} ]]; then - accept_eula_opt="cuDNN" - else - accept_eula_opt="${accept_eula_opt},cuDNN" - fi - fi - touch "$tmpdir"/none.py - eb_args="--prefix=$tmpdir" - eb_args="$eb_args --installpath-modules=${EASYBUILD_INSTALLPATH}/.modules" - eb_args="$eb_args --hooks="$tmpdir"/none.py" - eb_args="$eb_args --easystack ${EASYSTACK_FILE}" - if [[ ! -z ${accept_eula_opt} ]]; then - eb_args="$eb_args --accept-eula-for=$accept_eula_opt" - fi - echo "Running eb $eb_args" - eb $eb_args - ret=$? - if [ $ret -ne 0 ]; then - eb_last_log=$(unset EB_VERBOSE; eb --last-log) - cp -a ${eb_last_log} . - fatal_error "some installation failed, please check EasyBuild logs ${PWD}/$(basename ${eb_last_log})..." - else - echo_green "all installations at ${EESSI_SITE_SOFTWARE_PATH}/software/... succeeded!" - fi - - # clean up tmpdir content - rm -rf "${tmpdir}"/* - - # Restore MODULEPATH for next loop iteration - MODULEPATH=${SAVE_MODULEPATH} -done -# Remove the temporary directory -rm -rf "${tmpdir}" diff --git a/scripts/gpu_support/nvidia/install_cuda_host_injections.sh b/scripts/gpu_support/nvidia/install_cuda_host_injections.sh deleted file mode 100755 index 954cf45cf7..0000000000 --- a/scripts/gpu_support/nvidia/install_cuda_host_injections.sh +++ /dev/null @@ -1,211 +0,0 @@ -#!/usr/bin/env bash - -# This script can be used to install CUDA under the `.../host_injections` directory. -# This provides the parts of the CUDA installation that cannot be redistributed as -# part of EESSI due to license limitations. While GPU-based software from EESSI will -# _run_ without these, installation of additional CUDA software requires the CUDA -# installation(s) under `host_injections` to be present. -# -# The `host_injections` directory is a variant symlink that by default points to -# `/opt/eessi`, unless otherwise defined in the local CVMFS configuration (see -# https://cvmfs.readthedocs.io/en/stable/cpt-repo.html#variant-symlinks). For the -# installation to be successful, this directory needs to be writeable by the user -# executing this script. - -# Initialise our bash functions -TOPDIR=$(dirname $(realpath $BASH_SOURCE)) -source "$TOPDIR"/../../utils.sh - -# Function to display help message -show_help() { - echo "Usage: $0 [OPTIONS]" - echo "Options:" - echo " --help Display this help message" - echo " --accept-cuda-eula You _must_ accept the CUDA EULA to install" - echo " CUDA, see the EULA at" - echo " https://docs.nvidia.com/cuda/eula/index.html" - echo " -c, --cuda-version CUDA_VERSION Specify a version o CUDA to install (must" - echo " have a corresponding easyconfig in the" - echo " EasyBuild release)" - echo " -t, --temp-dir /path/to/tmpdir Specify a location to use for temporary" - echo " storage during the CUDA install" - echo " (must have >10GB available)" -} - -# Initialize variables -install_cuda_version="" -eula_accepted=0 - -# Parse command-line options -while [[ $# -gt 0 ]]; do - case "$1" in - --help) - show_help - exit 0 - ;; - -c|--cuda-version) - if [ -n "$2" ]; then - install_cuda_version="$2" - shift 2 - else - echo "Error: Argument required for $1" - show_help - exit 1 - fi - ;; - --accept-cuda-eula) - eula_accepted=1 - shift 1 - ;; - -t|--temp-dir) - if [ -n "$2" ]; then - CUDA_TEMP_DIR="$2" - shift 2 - else - echo "Error: Argument required for $1" - show_help - exit 1 - fi - ;; - *) - show_help - fatal_error "Error: Unknown option: $1" - ;; - esac -done - -# Make sure EESSI is initialised -check_eessi_initialised - -# Make sure the CUDA version supplied is a semantic version -is_semantic_version() { - local version=$1 - local regex='^[0-9]+\.[0-9]+\.[0-9]+$' - - if [[ $version =~ $regex ]]; then - return 0 # Return success (0) if it's a semantic version - else - return 1 # Return failure (1) if it's not a semantic version - fi -} -if ! is_semantic_version "$install_cuda_version"; then - show_help - error="\nYou must provide a semantic version for CUDA (e.g., 12.1.1) via the appropriate\n" - error="${error}command line option. This script is intended for use with EESSI so the 'correct'\n" - error="${error}version to provide is probably one of those available under\n" - error="${error}$EESSI_SOFTWARE_PATH/software/CUDA\n" - fatal_error "${error}" -fi - -# Make sure they have accepted the CUDA EULA -if [ "$eula_accepted" -ne 1 ]; then - show_help - error="\nYou _must_ accept the CUDA EULA via the appropriate command line option.\n" - fatal_error "${error}" -fi - -# As an installation location just use $EESSI_SOFTWARE_PATH but replacing `versions` with `host_injections` -# (CUDA is a binary installation so no need to worry too much about the EasyBuild setup) -cuda_install_parent=${EESSI_SOFTWARE_PATH/versions/host_injections} - -# Only install CUDA if specified version is not found. -# (existence of easybuild subdir implies a successful install) -if [ -d "${cuda_install_parent}"/software/CUDA/"${install_cuda_version}"/easybuild ]; then - echo_green "CUDA software found! No need to install CUDA again." -else - # We need to be able write to the installation space so let's make sure we can - if ! create_directory_structure "${cuda_install_parent}"/software/CUDA ; then - fatal_error "No write permissions to directory ${cuda_install_parent}/software/CUDA" - fi - - # we need a directory we can use for temporary storage - if [[ -z "${CUDA_TEMP_DIR}" ]]; then - tmpdir=$(mktemp -d) - else - tmpdir="${CUDA_TEMP_DIR}"/temp - if ! mkdir -p "$tmpdir" ; then - fatal_error "Could not create directory ${tmpdir}" - fi - fi - - required_space_in_tmpdir=50000 - # Let's see if we have sources and build locations defined if not, we use the temporary space - if [[ -z "${EASYBUILD_BUILDPATH}" ]]; then - export EASYBUILD_BUILDPATH=${tmpdir}/build - required_space_in_tmpdir=$((required_space_in_tmpdir + 5000000)) - fi - if [[ -z "${EASYBUILD_SOURCEPATH}" ]]; then - export EASYBUILD_SOURCEPATH=${tmpdir}/sources - required_space_in_tmpdir=$((required_space_in_tmpdir + 5000000)) - fi - - # The install is pretty fat, you need lots of space for download/unpack/install (~3*5GB), - # need to do a space check before we proceed - avail_space=$(df --output=avail "${cuda_install_parent}"/ | tail -n 1 | awk '{print $1}') - if (( avail_space < 5000000 )); then - fatal_error "Need at least 5GB disk space to install CUDA under ${cuda_install_parent}, exiting now..." - fi - avail_space=$(df --output=avail "${tmpdir}"/ | tail -n 1 | awk '{print $1}') - if (( avail_space < required_space_in_tmpdir )); then - error="Need at least ${required_space_in_tmpdir}GB disk space under ${tmpdir}.\n" - error="${error}Set the environment variable CUDA_TEMP_DIR to a location with adequate space to pass this check.\n" - error="${error}You can alternatively set EASYBUILD_BUILDPATH and/or EASYBUILD_SOURCEPATH\n" - error="${error}to reduce this requirement. Exiting now..." - fatal_error "${error}" - fi - - if ! command -v "eb" &>/dev/null; then - echo_yellow "Attempting to load an EasyBuild module to do actual install" - module load EasyBuild - # There are some scenarios where this may fail - if [ $? -ne 0 ]; then - error="'eb' command not found in your environment and\n" - error="${error} module load EasyBuild\n" - error="${error}failed for some reason.\n" - error="${error}Please re-run this script with the 'eb' command available." - fatal_error "${error}" - fi - fi - - cuda_easyconfig="CUDA-${install_cuda_version}.eb" - - # Check the easyconfig file is available in the release - # (eb search always returns 0, so we need a grep to ensure a usable exit code) - eb --search ^${cuda_easyconfig}|grep CUDA > /dev/null 2>&1 - # Check the exit code - if [ $? -ne 0 ]; then - eb_version=$(eb --version) - available_cuda_easyconfigs=$(eb --search "^CUDA-.*.eb"|grep CUDA) - - error="The easyconfig ${cuda_easyconfig} was not found in EasyBuild version:\n" - error="${error} ${eb_version}\n" - error="${error}You either need to give a different version of CUDA to install _or_ \n" - error="${error}use a different version of EasyBuild for the installation.\n" - error="${error}\nThe versions of CUDA available with the current eb command are:\n" - error="${error}${available_cuda_easyconfigs}" - fatal_error "${error}" - fi - - # We need the --rebuild option, as the CUDA module may or may not be on the - # `MODULEPATH` yet. Even if it is, we still want to redo this installation - # since it will provide the symlinked targets for the parts of the CUDA - # installation in the `.../versions/...` prefix - # We install the module in our `tmpdir` since we do not need the modulefile, - # we only care about providing the targets for the symlinks. - extra_args="--rebuild --installpath-modules=${tmpdir}" - - # We don't want hooks used in this install, we need a vanilla CUDA installation - touch "$tmpdir"/none.py - # shellcheck disable=SC2086 # Intended splitting of extra_args - eb --prefix="$tmpdir" ${extra_args} --accept-eula-for=CUDA --hooks="$tmpdir"/none.py --installpath="${cuda_install_parent}"/ "${cuda_easyconfig}" - ret=$? - if [ $ret -ne 0 ]; then - eb_last_log=$(unset EB_VERBOSE; eb --last-log) - cp -a ${eb_last_log} . - fatal_error "CUDA installation failed, please check EasyBuild logs $(basename ${eb_last_log})..." - else - echo_green "CUDA installation at ${cuda_install_parent}/software/CUDA/${install_cuda_version} succeeded!" - fi - # clean up tmpdir - rm -rf "${tmpdir}" -fi diff --git a/scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh b/scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh deleted file mode 100755 index 27447341fd..0000000000 --- a/scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh +++ /dev/null @@ -1,691 +0,0 @@ -#!/bin/bash - -# NVIDIA Host Libraries Linking Script for EESSI -# ============================================ -# Overview: -# 1. Initialize environment and source utility functions -# All function definitions be here. -# 2. Check prerequisites: -# - EESSI environment initialization -# - nvidia-smi availability -# - Proper umask settings for global read permissions -# 3. Gather NVIDIA information: -# - Detect GPU driver version -# - Get CUDA version -# 4. Library detection and matching: -# - Download/use default NVIDIA library list -# - Find host libraries using ldconfig -# - Match required NVIDIA libraries -# 5. Handle two operation modes: -# a) Show LD_PRELOAD mode: Displays environment variables for preloading -# Suggest exports for following variables: -# EESSI_GPU_COMPAT_LD_PRELOAD (Minimal LD_PRELOAD) -# EESSI_GPU_LD_PRELOAD (Full LD_PRELOAD) -# EESSI_OVERRIDE_GPU_CHECK -# b) Symlink mode: Create directory structure and link libraries -# Create necessary symlinks in EESSI directory structure -# -# Error Handling: -# - nvidia-smi detection: Exits if NVIDIA drivers not found -# - Library matching: Reports missing libraries -# - Permission issues: Checks write access and umask settings -# - Symlink conflicts: Validates existing symlinks -# - Directory creation: Ensures proper structure exists -# -# Note: This script is part of EESSI (European Environment for Scientific -# Software Installations) and manages the linking of host NVIDIA libraries -# to make them accessible within the EESSI environment. - -# ###################################################### # -# 1. Initialize environment and source utility functions # -# ###################################################### # - -TOPDIR=$(dirname "$(realpath "${BASH_SOURCE[0]}")") -source "$TOPDIR"/../../utils.sh - -# Command line help function -show_help() { - echo "Usage: $0 [OPTIONS]" - echo "Options:" - echo " --help Display this help message" - echo " --show-ld-preload Enable recommendations for LD_PRELOAD mode" - echo " --no-download Don't download list of Nvidia libraries from URL," - echo " but use hardcoded list here in get_nvlib_list()" - echo " -v, --verbose Display debugging messages," - echo " actions taken, commands being run." -} - -# Initialize global variables (These are accessed or set from functions) -LD_PRELOAD_MODE=0 # Trigger show-ld-preload mode T/F -LIBS_LIST="" # Command line argument for get_nvlib_list -VERBOSE=0 # Set verbosity logging T/F -HOST_GPU_DRIVER_VERSION="" # GPU Driver version () -HOST_GPU_CUDA_VERSION="" # GPU CUDA version () -MATCHED_LIBRARIES=() # List of found CUDA libraries based on get_nvlib_list() -MISSING_LIBRARIES=() # Complementary to Matched libraries. - - -# Locates the host system's ldconfig, avoiding CVMFS paths -# Returns path to first valid ldconfig found, prioritizing /sbin -get_host_ldconfig() { - local command_name="ldconfig" # Set command to find - local exclude_prefix="/cvmfs" # Set excluded prefix (paths to ignore) - local found_paths=() # Initialize an array to store found paths - - # Always attempt to use /sbin/ldconfig - if [ -x "/sbin/${command_name}" ]; then - found_paths+=("/sbin/${command_name}") - fi - - # Split the $PATH and iterate over each directory - IFS=':' read -ra path_dirs <<< "$PATH" - for dir in "${path_dirs[@]}"; do - if [ "$dir" = "/sbin" ]; then - continue # Skip /sbin since it's already checked - fi - - # Check if directory does not start with the exclude prefix - if [[ ! "$dir" =~ ^$exclude_prefix ]]; then - if [ -x "${dir}/${command_name}" ]; then - found_paths+=("${dir}/${command_name}") - fi - fi - done - - # Check if any paths were found - if [ ${#found_paths[@]} -gt 0 ]; then - # echo the first version we found and return success - echo "${found_paths[0]}" - return 0 - else - fatal_error "$command_name not found in PATH or only found in paths starting with $exclude_prefix." - fi -} - -# Downloads or provides default list of required NVIDIA libraries. -# As echo to stdout! Don't print any messages inside this function. -# Returns 0 if download successful, 1 if using default list -get_nvlib_list() { - local nvliblist_url="https://raw.githubusercontent.com/apptainer/apptainer/main/etc/nvliblist.conf" - - # see https://apptainer.org/docs/admin/1.0/configfiles.html#nvidia-gpus-cuda - # https://github.com/apptainer/apptainer/commits/main/etc/nvliblist.conf - # This default_nvlib_list is based on this commit on Oct 1, 2024: - # https://github.com/apptainer/apptainer/commit/a19fa01527a8914839b8d1649688f83c61ba9ad2 - # TODO: driver version which corresponds to? - local default_nvlib_list=( - "libcuda.so" - "libcudadebugger.so" - "libEGL_installertest.so" - "libEGL_nvidia.so" - "libEGL.so" - "libGLdispatch.so" - "libGLESv1_CM_nvidia.so" - "libGLESv1_CM.so" - "libGLESv2_nvidia.so" - "libGLESv2.so" - "libGL.so" - "libGLX_installertest.so" - "libGLX_nvidia.so" - "libglx.so" - "libGLX.so" - "libnvcuvid.so" - "libnvidia-cbl.so" - "libnvidia-cfg.so" - "libnvidia-compiler.so" - "libnvidia-eglcore.so" - "libnvidia-egl-wayland.so" - "libnvidia-encode.so" - "libnvidia-fatbinaryloader.so" - "libnvidia-fbc.so" - "libnvidia-glcore.so" - "libnvidia-glsi.so" - "libnvidia-glvkspirv.so" - "libnvidia-gpucomp.so" - "libnvidia-gtk2.so" - "libnvidia-gtk3.so" - "libnvidia-ifr.so" - "libnvidia-ml.so" - "libnvidia-nvvm.so" - "libnvidia-opencl.so" - "libnvidia-opticalflow.so" - "libnvidia-ptxjitcompiler.so" - "libnvidia-rtcore.so" - "libnvidia-tls.so" - "libnvidia-wfb.so" - "libnvoptix.so" - "libOpenCL.so" - "libOpenGL.so" - "libvdpau_nvidia.so" - "nvidia_drv.so" - "tls_test_.so" - ) - - # Check if the function was called with the "default" argument - if [[ "$1" == "default" ]]; then - printf "%s\n" "${default_nvlib_list[@]}" - return 1 - fi - - # Try to download the nvliblist.conf file with curl - nvliblist_content=$(curl --silent "$nvliblist_url") - - # Check if curl failed (i.e., the content is empty) - if [ -z "$nvliblist_content" ]; then - # Failed to download nvliblist.conf, using default list instead - # We can't echo here - # echo_yellow "Download failed, using default list of libraries instead" - printf "%s\n" "${default_nvlib_list[@]}" - return 1 - fi - - # If curl succeeded, filter and return the libraries from the downloaded content - echo "$nvliblist_content" | grep '.so$' - - # We can't echo here - # echo "Using downloaded list of libraries" - return 0 -} - -# Verifies if current umask allows global read access -# Exits with error if permissions are too restrictive -check_global_read() { - # Get the current umask value - local current_umask - current_umask=$(umask) - log_verbose "current umask: ${current_umask}" - - # Convert umask to decimal to analyze - local umask_octal - umask_octal=$(printf '%03o\n' "$current_umask") - - # Check if umask allows global read - if [ "$umask_octal" -gt 022 ]; then - fatal_error "The current umask ($current_umask) does not allow global read permissions, you'll want everyone to be able to read the created directory." - fi - # TODO: Option to set $UMASK here? - # https://github.com/EESSI/software-layer/pull/754#discussion_r1950643598 -} - -# Checks for nvidia-smi command and extracts GPU information -# Sets HOST_GPU_CUDA_VERSION and HOST_GPU_DRIVER_VERSION variables -check_nvidia_smi_info() { - - if command -v nvidia-smi - then - log_verbose "Found nvidia-smi at: $(which nvidia-smi)" - - # Create temporary file for nvidia-smi output - nvidia_smi_out=$(mktemp -p /tmp nvidia_smi_out.XXXXX) - log_verbose "Creating temporary output file: ${nvidia_smi_out}" - - # Query GPU information and parse versions - - if nvidia-smi --query-gpu=gpu_name,count,driver_version,compute_cap --format=csv,noheader > "$nvidia_smi_out" 2>&1 - then - nvidia_smi_info=$(head -1 "${nvidia_smi_out}") - HOST_GPU_CUDA_VERSION=$(echo "${nvidia_smi_info}" | sed 's/, /,/g' | cut -f4 -d,) - HOST_GPU_DRIVER_VERSION=$(echo "${nvidia_smi_info}" | sed 's/, /,/g' | cut -f3 -d,) - echo_green "Found host CUDA version ${HOST_GPU_CUDA_VERSION}" - echo_green "Found NVIDIA GPU driver version ${HOST_GPU_DRIVER_VERSION}" - rm -f "$nvidia_smi_out" - else - fatal_error "nvidia-smi command failed, see output in $nvidia_smi_out. Please remove the file afterwards." - fi - else - fatal_error "nvidia-smi command not found" - exit 2 - fi -} - -# Suggests configurations for LD_PRELOAD environment for CUDA libraries -# Filters libraries and configures both minimal and full preload options -show_ld_preload() { - - echo - echo_yellow "When attempting to use LD_PRELOAD we exclude anything related to graphics" - - # Define core CUDA libraries needed for compute - cuda_compat_nvlib_list=( - "libcuda.so" - "libcudadebugger.so" - "libnvidia-nvvm.so" - "libnvidia-ptxjitcompiler.so" - ) - - # Filter out all symlinks and libraries that have missing library dependencies under EESSI - filtered_libraries=() - compat_filtered_libraries=() - - for library in "${MATCHED_LIBRARIES[@]}"; do - - # Run ldd on the given binary and filter for "not found" libraries - # not_found_libs=$(ldd "${library}" 2>/dev/null | grep "not found" | awk '{print $1}') - # Trim multiple spaces then use cut - not_found_libs=$(ldd "${library}" 2>/dev/null | grep "not found" | tr -s ' ' | cut -d' ' -f1) - # Check if it is missing an so dep under EESSI - if [[ -z "$not_found_libs" ]]; then - # Resolve any symlink - realpath_library=$(realpath "$library") - if [[ ! " ${filtered_libraries[@]} " =~ " $realpath_library " ]]; then - filtered_libraries+=("${realpath_library}") - # Also prepare compat only libraries for the short list - for item in "${cuda_compat_nvlib_list[@]}"; do - # Check if the current item is a substring of $library - if [[ "$realpath_library" == *"$item"* ]]; then - echo "Match found for $item for CUDA compat libraries" - if [[ ! " ${compat_filtered_libraries[@]} " =~ " $realpath_library " ]]; then - compat_filtered_libraries+=("$realpath_library") - fi - break - fi - done - fi - else - # Iterate over "not found" libraries and check if they are in the array - all_found=true - for lib in $not_found_libs; do - found=false - for listed_lib in "${MATCHED_LIBRARIES[@]}"; do - # Matching to the .so or a symlink target is enough - realpath_lib=$(realpath "${listed_lib}") - if [[ "$lib" == "$listed_lib"* || "$realpath_lib" == *"$lib" ]]; then - found=true - break - fi - done - - if [[ "$found" == false ]]; then - echo "$lib is NOT in the provided preload list, filtering $library" - all_found=false - break - fi - done - - # If we find all the missing libs in our list include it - if [[ "$all_found" == true ]]; then - # Resolve any symlink - realpath_library=$(realpath "${library}") - if [[ ! " ${filtered_libraries[@]} " =~ " $realpath_library " ]]; then - filtered_libraries+=("${realpath_library}") - # Also prepare compat only libraries for the short list - for item in "${cuda_compat_nvlib_list[@]}"; do - # Check if the current item is a substring of $library - if [[ "$realpath_library" == *"$item"* ]]; then - echo "Match found for $item for CUDA compat libraries" - if [[ ! " ${compat_filtered_libraries[@]} " =~ " $realpath_library " ]]; then - compat_filtered_libraries+=("${realpath_library}") - fi - break - fi - done - fi - fi - fi - done - - # Set EESSI_GPU_LD_PRELOAD with the matched libraries - if [ ${#filtered_libraries[@]} -gt 0 ]; then - echo - echo_yellow "The recommended way to use LD_PRELOAD is to only use it when you need to." - echo - - # Set up MINIMAL preload for common cases - EESSI_GPU_COMPAT_LD_PRELOAD=$(printf "%s\n" "${compat_filtered_libraries[@]}" | tr '\n' ':') - # Remove the trailing colon from LD_PRELOAD if it exists - EESSI_GPU_COMPAT_LD_PRELOAD=${EESSI_GPU_COMPAT_LD_PRELOAD%:} - export EESSI_GPU_COMPAT_LD_PRELOAD - - echo_yellow "A minimal preload which should work in most cases:" - echo_green "export EESSI_GPU_COMPAT_LD_PRELOAD=\"$EESSI_GPU_COMPAT_LD_PRELOAD\"" - echo - - # Set up FULL preload for corner cases - EESSI_GPU_LD_PRELOAD=$(printf "%s\n" "${filtered_libraries[@]}" | tr '\n' ':') - # Remove the trailing colon from LD_PRELOAD if it exists - EESSI_GPU_LD_PRELOAD=${EESSI_GPU_LD_PRELOAD%:} - export EESSI_GPU_LD_PRELOAD - export EESSI_OVERRIDE_GPU_CHECK=1 - - echo_yellow "A corner-case full preload (which is hard on memory) for exceptional use:" - - # Display usage instructions - echo_green "export EESSI_GPU_LD_PRELOAD=\"$EESSI_GPU_LD_PRELOAD\"" - echo_green "export EESSI_OVERRIDE_GPU_CHECK=\"$EESSI_OVERRIDE_GPU_CHECK\"" - echo - echo_yellow "Then you can set LD_PRELOAD only when you want to run a GPU application," - echo_yellow "e.g. deviceQuery command from CUDA-Samples module:" - echo_yellow " LD_PRELOAD=\"\$EESSI_GPU_COMPAT_LD_PRELOAD\" deviceQuery" - echo_yellow "or LD_PRELOAD=\"\$EESSI_GPU_LD_PRELOAD\" deviceQuery" - else - echo "No libraries matched, LD_PRELOAD not set." - fi - [[ "${BASH_SOURCE[0]}" != "${0}" ]] && return 1 -} - -# Check host's ldconfig, gathers library paths, and filters them on matching. -# Sets MATCHED_LIBRARIES and MISSING_LIBRARIES -find_cuda_libraries_on_host() { - # First let's see what driver libraries are there - # then extract the ones we need for CUDA - - # Find the host ldconfig - host_ldconfig=$(get_host_ldconfig) - log_verbose "Found host ldconfig: ${host_ldconfig}" - - # Gather all libraries on the host (_must_ be host ldconfig). - # host_libraries=$("${host_ldconfig}" -p | awk '{print $NF}') - # Trim multiple spaces then use cut - host_libraries=$("${host_ldconfig}" -p | tr -s ' ' | cut -d' ' -f4) - # This is only for the scenario where the script is being run inside a container, if it fails the list is empty. - singularity_libs=$(ls /.singularity.d/libs/* 2>/dev/null) - - # Now gather the list of possible CUDA libraries and make them into an array - # https://www.shellcheck.net/wiki/SC2207 - cuda_candidate_libraries=($(get_nvlib_list "${LIBS_LIST}")) - # Check if the function returned an error (e.g., curl failed) - # Echo here, we take stdout from function as list of libraries. - if [ $? -ne 0 ]; then - echo "Using default list of libraries" - else - echo "Using downloaded list of libraries" - fi - - # Search for CUDA Libraries in system paths - echo "Searching for CUDA Libraries" - for library in "${cuda_candidate_libraries[@]}"; do - - # Match libraries for current CPU architecture - # "contains" matching - (eg. 'libcuda.so' matches both 'libcuda.so' and 'libcuda.so.1') - # The `grep -v "i386"` is done to exclude i386 libraries, which could be installed in parallel with 64 libs. - matched=$(echo "$host_libraries $singularity_libs" | grep -v "i386" | grep "$library") - - if [ -n "$matched" ]; then - log_verbose "Found matches for ${library}: $matched" - - # Process each matched library and avoid duplicates by filename - # Used `while - read <<< $matched`` to handle whitespaces and special characters. - while IFS= read -r lib_path; do - # Skip empty lines - [ -z "$lib_path" ] && continue - - # Extract just the filename from the path - lib_name=$(basename "$lib_path") - echo "Checking library $lib_name for duplicates" - - # Check if we already have this library filename in our matched libraries - duplicate_found=0 - for existing_lib in "${MATCHED_LIBRARIES[@]}"; do - existing_name=$(basename "$existing_lib") - if [ "$existing_name" = "$lib_name" ]; then - log_verbose "Duplicate library found: $lib_name (existing: $existing_lib, currently processed: $lib_path)" - log_verbose "Discarting $lib_path" - duplicate_found=1 - break - fi - done - - # If no duplicate found, add this library - if [ "$duplicate_found" -eq 0 ]; then - MATCHED_LIBRARIES+=("$lib_path") - fi - done <<< "$matched" - else - # There are some libraries, that weren't matched/found on the system - log_verbose "No matches found for ${library}" - MISSING_LIBRARIES+=("$library") - fi - done - - - # Report matching results - echo_green "Matched ${#MATCHED_LIBRARIES[@]} CUDA Libraries" - - if [ ${#MISSING_LIBRARIES[@]} -gt 0 ]; then - echo_yellow "The following libraries were not found (based on 'get_nvlib_list')" - printf '%s\n' "${MISSING_LIBRARIES[@]}" - fi -} - -# Actually symlinks the Matched libraries to correct folders. -# Then also creates "host" and "latest" folder symlinks -symlink_mode () { - # First let's make sure the driver libraries are not already in place - # Have to link drivers = True - link_drivers=1 - - # Make sure that target of host_injections variant symlink is an existing directory - echo "Ensure host_injections directory" - host_injections_target=$(realpath -m "${EESSI_CVMFS_REPO}/host_injections") - log_verbose "host_injections_target: ${host_injections_target}" - if [ ! -d "$host_injections_target" ]; then - check_global_read - create_directory_structure "$host_injections_target" - fi - - # Define proper nvidia directory structure for host_injections in EESSI - host_injections_nvidia_dir="${EESSI_CVMFS_REPO}/host_injections/nvidia/${EESSI_CPU_FAMILY}" - host_injection_driver_dir="${host_injections_nvidia_dir}/host" - host_injection_driver_version_file="${host_injection_driver_dir}/driver_version.txt" - log_verbose "host_injections_nvidia_dir: ${host_injections_nvidia_dir}" - log_verbose "host_injection_driver_dir: ${host_injection_driver_dir}" - log_verbose "host_injection_driver_version_file: ${host_injection_driver_version_file}" - - # Check if drivers are already linked with correct version - # This is done by comparing host_injection_driver_version_file (driver_version.txt) - # This is needed when updating GPU drivers. - if [ -e "$host_injection_driver_version_file" ]; then - if grep -q "$HOST_GPU_DRIVER_VERSION" "$host_injection_driver_version_file"; then - echo_green "The host GPU driver libraries (v${HOST_GPU_DRIVER_VERSION}) have already been linked! (based on ${host_injection_driver_version_file})" - # The GPU libraries were already linked for this version of CUDA driver - # Have to link drivers = False - link_drivers=0 - else - # There's something there but it is out of date - echo_yellow "The host GPU driver libraries version have changed. Now its: (v${HOST_GPU_DRIVER_VERSION})" - echo_yellow "Cleaning out outdated symlinks." - rm "${host_injection_driver_dir}"/* || fatal_error "Unable to remove files under '${host_injection_driver_dir}'." - fi - fi - - # Link all matched_libraries from Nvidia to correct host_injection folder - # This step is only run, when linking of drivers is needed (eg. link_drivers==1) - # Setup variable to track if some drivers were actually linked this run. - drivers_linked=0 - - # Have to link drivers - if [ "$link_drivers" -eq 1 ]; then - # Link the matched libraries - - echo_green "Linking drivers to the host_injection folder" - check_global_read - if ! create_directory_structure "${host_injection_driver_dir}" ; then - fatal_error "No write permissions to directory ${host_injection_driver_dir}" - fi - - cd "${host_injection_driver_dir}" || fatal_error "Failed to cd to ${host_injection_driver_dir}" - log_verbose "Changed directory to: $PWD" - - # Make symlinks to all the interesting libraries - # Loop over each matched library - for library in "${MATCHED_LIBRARIES[@]}"; do - log_verbose "Linking library: ${library}" - - # Get just the library filename - lib_name=$(basename "$library") - - # Check if the symlink already exists - if [ -L "$lib_name" ]; then - # Check if it's pointing to the same target - target=$(readlink "$lib_name") - if [ "$target" = "$library" ]; then - log_verbose "Symlink for $lib_name already exists and points to correct target" - continue - else - log_verbose "Symlink for $lib_name exists but points to wrong target: $target, updating..." - rm "$lib_name" - fi - fi - - # Create a symlink in the current directory - # and check if the symlink was created successfully - if ! ln -s "$library" . - then - fatal_error "Error: Failed to create symlink for library $library in $PWD" - fi - done - - # Inject driver and CUDA versions into the directory - echo "$HOST_GPU_DRIVER_VERSION" > driver_version.txt - echo "$HOST_GPU_CUDA_VERSION" > cuda_version.txt - - drivers_linked=1 - fi - - # Make latest symlink for NVIDIA drivers - cd "$host_injections_nvidia_dir" || fatal_error "Failed to cd to $host_injections_nvidia_dir" - log_verbose "Changed directory to: $PWD" - symlink="latest" - - # Check if the symlink exists - if [ -L "$symlink" ]; then - # If the drivers were linked this run - relink the symlink! - if [ "$drivers_linked" -eq 1 ]; then - # Force relinking the current link. - # Need to remove the link first, otherwise this will follow existing symlink - # and create host directory one level down ! - rm "$symlink" || fatal_error "Failed to remove symlink ${symlink}" - - if ln -sf host "$symlink" - then - echo "Successfully force recreated symlink between $symlink and host in $PWD" - else - fatal_error "Failed to force recreate symlink between $symlink and host in $PWD" - fi - fi - else - # If the symlink doesn't exists, create normal one. - if ln -s host "$symlink" - then - echo "Successfully created symlink between $symlink and host in $PWD" - else - fatal_error "Failed to create symlink between $symlink and host in $PWD" - fi - fi - - # Make sure the libraries can be found by the EESSI linker - host_injection_linker_dir=${EESSI_EPREFIX/versions/host_injections} - if [ -L "$host_injection_linker_dir/lib" ]; then - # Use readlink without -f to get direct symlink target - # using -f option will create "lastest" symlink one dir deeper (inside host) - target_path=$(readlink "$host_injection_linker_dir/lib") - expected_target="$host_injections_nvidia_dir/latest" - - log_verbose "Checking symlink target for EESSI linker:" - log_verbose "Current target: $target_path" - log_verbose "Expected target: $expected_target" - - # Update symlink if needed - if [ "$target_path" != "$expected_target" ]; then - cd "$host_injection_linker_dir" || fatal_error "Failed to cd to $host_injection_linker_dir" - log_verbose "Changed directory to: $PWD" - - - if ln -sf "$expected_target" lib - then - echo "Successfully force created symlink between $expected_target and lib in $PWD" - else - fatal_error "Failed to force create symlink between $expected_target and lib in $PWD" - fi - else - log_verbose "Symlink already points to correct target" - fi - else - # Just start from scratch, symlink doesn't exists. - check_global_read - create_directory_structure "$host_injection_linker_dir" - cd "$host_injection_linker_dir" || fatal_error "Failed to cd to $host_injection_linker_dir" - log_verbose "Changed directory to: $PWD" - - if ln -s "$host_injections_nvidia_dir/latest" lib - then - echo "Successfully created symlink between $host_injections_nvidia_dir/latest and lib in $PWD" - else - fatal_error "Failed to create symlink between $host_injections_nvidia_dir/latest and lib in $PWD" - fi - fi - -} - -# Logging function for verbose mode -# TODO: move to utils? -log_verbose() { - if [ "$VERBOSE" -eq 1 ]; then - echo "[VERBOSE] $*" - fi -} - - -# ############################################### -# 2. Check prerequisites # -# ############################################### - -# Make sure EESSI is initialised (doesn't matter what version) -check_eessi_initialised - -# Verify nvidia-smi availability -log_verbose "Checking for nvidia-smi command..." -command -v nvidia-smi >/dev/null 2>&1 || { echo_yellow "nvidia-smi not found, this script won't do anything useful"; return 1; } - -# Parse command line arguments -while [[ "$#" -gt 0 ]]; do - case "$1" in - --help) - show_help - exit 0 - ;; # Show help - --show-ld-preload) LD_PRELOAD_MODE=1 ;; # Enable LD_PRELOAD mode - --no-download) LIBS_LIST="default" ;; # Download latest list of CUDA libraries - --verbose|-v) VERBOSE=1 ;; # Enable verbose output - *) - show_help - fatal_error "Unknown option: $1" - ;; - esac - shift -done - -# ############################################### -# 3. Gather NVIDIA information # -# ############################################### - -# Gather information about NVIDIA drivers (even if we are inside a Gentoo Prefix in a container) -export LD_LIBRARY_PATH="/.singularity.d/libs:${LD_LIBRARY_PATH}" - -# Check for NVIDIA GPUs via nvidia-smi command -check_nvidia_smi_info - -# ############################################### -# 4. Library detection and matching # -# ############################################### - -# Gather any CUDA related driver libraries from the host -# Sets MATCHED_LIBRARIES and MISSING_LIBRARIES array variables -find_cuda_libraries_on_host - -# ############################################### -# 5. Handle operation modes # -# ############################################### - -# === 5a. LD_PRELOAD Mode === -if [ "$LD_PRELOAD_MODE" -eq 1 ]; then - show_ld_preload - exit 0 -fi - -# === 5b. Symlink Mode === -# If we haven't already exited, we may need to create the symlinks -symlink_mode - -# If everything went OK, show success message -echo_green "Host NVIDIA GPU drivers linked successfully for EESSI" diff --git a/scripts/utils.sh b/scripts/utils.sh deleted file mode 100644 index 962decd20e..0000000000 --- a/scripts/utils.sh +++ /dev/null @@ -1,149 +0,0 @@ -function echo_green() { - echo -e "\e[32m$1\e[0m" -} - -function echo_red() { - echo -e "\e[31m$1\e[0m" -} - -function echo_yellow() { - echo -e "\e[33m$1\e[0m" -} - -ANY_ERROR_EXITCODE=1 -function fatal_error() { - echo_red "ERROR: $1" >&2 - if [[ $# -gt 1 ]]; then - exit "$2" - else - exit "${ANY_ERROR_EXITCODE}" - fi -} - -function check_exit_code { - ec=$1 - ok_msg=$2 - fail_msg=$3 - - if [[ $ec -eq 0 ]]; then - echo_green "${ok_msg}" - else - fatal_error "${fail_msg}" - fi -} - -function check_eessi_initialised() { - if [[ -z "${EESSI_SOFTWARE_PATH}" ]]; then - fatal_error "EESSI has not been initialised!" - else - return 0 - fi -} - -function check_in_prefix_shell() { - # Make sure EPREFIX is defined - if [[ -z "${EPREFIX}" ]]; then - fatal_error "This script cannot be used without having first defined EPREFIX" - fi - if [[ ! ${SHELL} = ${EPREFIX}/bin/bash ]]; then - fatal_error "Not running in Gentoo Prefix environment, run '${EPREFIX}/startprefix' first!" - fi -} - -function create_directory_structure() { - # Ensure we are given a single path argument - if [ $# -ne 1 ]; then - echo_red "Function requires a single (relative or absolute) path argument" >&2 - return $ANY_ERROR_EXITCODE - fi - dir_structure="$1" - - # Attempt to create the directory structure - error_message=$(mkdir -p "$dir_structure" 2>&1) - return_code=$? - # If it fails be explicit about the error - if [ ${return_code} -ne 0 ]; then - real_dir=$(realpath -m "$dir_structure") - echo_red "Creating ${dir_structure} (real path ${real_dir}) failed with:\n ${error_message}" >&2 - else - # If we're creating it, our use case is that we want to be able to write there - # (this is a check in case the directory already existed) - if [ ! -w "${dir_structure}" ]; then - real_dir=$(realpath -m "$dir_structure") - echo_red "You do not have (required) write permissions to ${dir_structure} (real path ${real_dir})!" - return_code=$ANY_ERROR_EXITCODE - fi - fi - - return $return_code -} - -# Function to check if a command exists -function command_exists() { - command -v "$1" >/dev/null 2>&1 -} - -function get_path_for_tool { - tool_name=$1 - tool_envvar_name=$2 - - which_out=$(which "${tool_name}" 2>&1) - exit_code=$? - if [[ ${exit_code} -eq 0 ]]; then - echo "INFO: found tool ${tool_name} in PATH (${which_out})" >&2 - echo "${which_out}" - return 0 - fi - if [[ -z "${tool_envvar_name}" ]]; then - msg="no env var holding the full path to tool '${tool_name}' provided" - echo "${msg}" >&2 - return 1 - else - tool_envvar_value=${!tool_envvar_name} - if [[ -x "${tool_envvar_value}" ]]; then - msg="INFO: found tool ${tool_envvar_value} via env var ${tool_envvar_name}" - echo "${msg}" >&2 - echo "${tool_envvar_value}" - return 0 - else - msg="ERROR: tool '${tool_name}' not in PATH\n" - msg+="ERROR: tool '${tool_envvar_value}' via '${tool_envvar_name}' not in PATH" - echo "${msg}" >&2 - echo "" - return 2 - fi - fi -} - -function get_host_from_url { - url=$1 - re="(http|https)://([^/:]+)" - if [[ $url =~ $re ]]; then - echo "${BASH_REMATCH[2]}" - return 0 - else - echo "" - return 1 - fi -} - -function get_port_from_url { - url=$1 - re="(http|https)://[^:]+:([0-9]+)" - if [[ $url =~ $re ]]; then - echo "${BASH_REMATCH[2]}" - return 0 - else - echo "" - return 1 - fi -} - -function get_ipv4_address { - hname=$1 - hipv4=$(grep "${hname}" /etc/hosts | grep -v '^[[:space:]]*#' | cut -d ' ' -f 1) - # TODO try other methods if the one above does not work --> tool that verifies - # what method can be used? - echo "${hipv4}" - return 0 -} diff --git a/test_suite.sh b/test_suite.sh deleted file mode 100755 index f5f3255841..0000000000 --- a/test_suite.sh +++ /dev/null @@ -1,241 +0,0 @@ -#!/bin/bash -# -# This script creates a ReFrame config file from a template, in which CPU properties get replaced -# based on where this script is run (typically: a build node). Then, it runs the EESSI test suite. -# -# This script is part of the EESSI software layer, see -# https://github.com/EESSI/software-layer.git -# -# author: Caspar van Leeuwen (@casparvl) -# -# license: GPLv2 - -display_help() { - echo "usage: $0 [OPTIONS]" - echo " -g | --generic - instructs script to test for generic architecture target" - echo " -h | --help - display this usage information" - echo " -x | --http-proxy URL - provides URL for the environment variable http_proxy" - echo " -y | --https-proxy URL - provides URL for the environment variable https_proxy" -} - -POSITIONAL_ARGS=() - -while [[ $# -gt 0 ]]; do - case $1 in - -g|--generic) - DETECTION_PARAMETERS="--generic" - shift - ;; - -h|--help) - display_help # Call your function - # no shifting needed here, we're done. - exit 0 - ;; - -x|--http-proxy) - export http_proxy="$2" - shift 2 - ;; - -y|--https-proxy) - export https_proxy="$2" - shift 2 - ;; - --build-logs-dir) - export build_logs_dir="${2}" - shift 2 - ;; - --shared-fs-path) - export shared_fs_path="${2}" - shift 2 - ;; - -*|--*) - echo "Error: Unknown option: $1" >&2 - exit 1 - ;; - *) # No more options - POSITIONAL_ARGS+=("$1") # save positional arg - shift - ;; - esac -done - -set -- "${POSITIONAL_ARGS[@]}" - -TOPDIR=$(dirname $(realpath $0)) - -source $TOPDIR/scripts/utils.sh - -# honor $TMPDIR if it is already defined, use /tmp otherwise -if [ -z $TMPDIR ]; then - export WORKDIR=/tmp/$USER -else - export WORKDIR=$TMPDIR/$USER -fi - -TMPDIR=$(mktemp -d) - -echo ">> Setting up environment..." -# For this call to be succesful, it needs to be able to import archspec (which is part of EESSI) -# Thus, we execute it in a subshell where EESSI is already initialized (a bit like a bootstrap) -export EESSI_SOFTWARE_SUBDIR_OVERRIDE=$(source $TOPDIR/init/bash > /dev/null 2>&1; python3 $TOPDIR/eessi_software_subdir.py $DETECTION_PARAMETERS) -echo "EESSI_SOFTWARE_SUBDIR_OVERRIDE: $EESSI_SOFTWARE_SUBDIR_OVERRIDE" - -source $TOPDIR/init/bash - -# We have to ignore the LMOD cache, otherwise the software that is built in the build step cannot be found/loaded -# Reason is that the LMOD cache is normally only updated on the Stratum 0, once everything is ingested -export LMOD_IGNORE_CACHE=1 - -# Load the ReFrame module -# Currently, we load the default version. Maybe we should somehow make this configurable in the future? -module load ReFrame -if [[ $? -eq 0 ]]; then - echo_green ">> Loaded ReFrame module" -else - fatal_error "Failed to load the ReFrame module" -fi - -# Check that a system python3 is available -python3_found=$(command -v python3) -if [ -z ${python3_found} ]; then - fatal_error "No system python3 found" -else - echo_green "System python3 found:" - python3 -V -fi - -# Check ReFrame came with the hpctestlib and we can import it -reframe_import="hpctestlib.sciapps.gromacs" -python3 -c "import ${reframe_import}" -if [[ $? -eq 0 ]]; then - echo_green "Succesfully found and imported ${reframe_import}" -else - fatal_error "Failed to import ${reframe_import}" -fi - -# Cloning should already be done in run_tests.sh before test_suite.sh is invoked -# Check if that succeeded -export TESTSUITEPREFIX=$PWD/EESSI-test-suite -if [ -d $TESTSUITEPREFIX ]; then - echo_green "Clone of the test suite $TESTSUITEPREFIX available, OK!" -else - fatal_error "Clone of the test suite $TESTSUITEPREFIX is not available!" -fi -export PYTHONPATH=$TESTSUITEPREFIX:$PYTHONPATH - -# Check that we can import from the testsuite -testsuite_import="eessi.testsuite" -python3 -c "import ${testsuite_import}" -if [[ $? -eq 0 ]]; then - echo_green "Succesfully found and imported ${testsuite_import}" -else - fatal_error "Failed to import ${testsuite_import}" -fi - -# Configure ReFrame, see https://www.eessi.io/docs/test-suite/installation-configuration -# RFM_CONFIG_FILES _has_ to be set by the site hosting the bot, so that it knows where to find the ReFrame -# config file that matches the bot config. See https://gitlab.com/eessi/support/-/issues/114#note_2293660921 -if [ -z "$RFM_CONFIG_FILES" ]; then - if [ -z "${shared_fs_path}" ]; then - fatal_error "Environment variable 'shared_fs_path' was expected, but was not set" - fi - # Try to find a config file at $shared_fs_path/reframe_config.py - export RFM_CONFIG_FILES="${shared_fs_path}/reframe_config.py" - if [ ! -f "${RFM_CONFIG_FILES}" ]; then - # If we haven't found the ReFrame config, print an informative error - err_msg="Please put a ReFrame configuration file in ${shared_fs_path}/reframe_config.py" - err_msg="${err_msg} or set RFM_CONFIG_FILES in the environment of this bot instance to point to a valid" - err_msg="${err_msg} ReFrame configuration file that matches the bot config." - err_msg="${err_msg} For more information, see https://gitlab.com/eessi/support/-/issues/114#note_2293660921" - fatal_error "${err_msg}" - fi -fi -export RFM_CHECK_SEARCH_PATH=$TESTSUITEPREFIX/eessi/testsuite/tests -export RFM_CHECK_SEARCH_RECURSIVE=1 -export RFM_PREFIX=$PWD/reframe_runs - -# Get the correct partition name -REFRAME_PARTITION_NAME=${EESSI_SOFTWARE_SUBDIR//\//_} -if [ ! -z "$EESSI_ACCELERATOR_TARGET" ]; then - REFRAME_PARTITION_NAME=${REFRAME_PARTITION_NAME}_${EESSI_ACCELERATOR_TARGET//\//_} -fi -echo "Constructed partition name based on EESSI_SOFTWARE_SUBDIR and EESSI_ACCELERATOR_TARGET: ${REFRAME_PARTITION_NAME}" - -# Set the reframe system name, including partition -export RFM_SYSTEM="BotBuildTests:${REFRAME_PARTITION_NAME}" - -echo "Configured reframe with the following environment variables:" -env | grep "RFM_" - -# Make debugging easier by printing the final config file: -echo "ReFrame config file used:" -cat "${RFM_CONFIG_FILES}" - -# Workaround for https://github.com/EESSI/software-layer/pull/467#issuecomment-1973341966 -export PSM3_DEVICES='self,shm' # this is enough, since we only run single node for now - -# Check we can run reframe -reframe --version -if [[ $? -eq 0 ]]; then - echo_green "Succesfully ran 'reframe --version'" -else - fatal_error "Failed to run 'reframe --version'" -fi - -# Get the subset of test names based on the test mapping and tags (e.g. CI, 1_node) -module_list="module_files.list.txt" -mapping_config="tests/eessi_test_mapping/software_to_tests.yml" -if [[ ! -f "$module_list" ]]; then - echo_green "File ${module_list} not found, so only running the default set of tests from ${mapping_config}" - # Run with --debug for easier debugging in case there are issues: - python3 tests/eessi_test_mapping/map_software_to_test.py --mapping-file "${mapping_config}" --debug --defaults-only - REFRAME_NAME_ARGS=$(python3 tests/eessi_test_mapping/map_software_to_test.py --mapping-file "${mapping_config}" --defaults-only) - test_selection_exit_code=$? -else - # Run with --debug for easier debugging in case there are issues: - python3 tests/eessi_test_mapping/map_software_to_test.py --module-list "${module_list}" --mapping-file "${mapping_config}" --debug - REFRAME_NAME_ARGS=$(python3 tests/eessi_test_mapping/map_software_to_test.py --module-list "${module_list}" --mapping-file "${mapping_config}") - test_selection_exit_code=$? -fi -# Check exit status -if [[ ${test_selection_exit_code} -eq 0 ]]; then - echo_green "Succesfully extracted names of tests to run: ${REFRAME_NAME_ARGS}" -else - fatal_error "Failed to extract names of tests to run: ${REFRAME_NAME_ARGS}" - exit ${test_selection_exit_code} -fi -# Allow people deploying the bot to override this -if [ -z "$REFRAME_SCALE_TAG" ]; then - REFRAME_SCALE_TAG="--tag 1_node" -fi -if [ -z "$REFRAME_CI_TAG" ]; then - REFRAME_CI_TAG="--tag CI" -fi -# Allow bot-deployers to add additional args through the environment -if [ -z "$REFRAME_ADDITIONAL_ARGS" ]; then - REFRAME_ADDITIONAL_ARGS="" -fi -export REFRAME_ARGS="${REFRAME_CI_TAG} ${REFRAME_SCALE_TAG} ${REFRAME_ADDITIONAL_ARGS} --nocolor ${REFRAME_NAME_ARGS}" - -# List the tests we want to run -echo "Listing tests: reframe ${REFRAME_ARGS} --list" -reframe ${REFRAME_ARGS} --list -if [[ $? -eq 0 ]]; then - echo_green "Succesfully listed ReFrame tests with command: reframe ${REFRAME_ARGS} --list" -else - fatal_error "Failed to list ReFrame tests with command: reframe ${REFRAME_ARGS} --list" -fi - -# Run all tests -echo "Running tests: reframe ${REFRAME_ARGS} --run" -reframe ${REFRAME_ARGS} --run -reframe_exit_code=$? -if [[ ${reframe_exit_code} -eq 0 ]]; then - echo_green "ReFrame runtime ran succesfully with command: reframe ${REFRAME_ARGS} --run." -else - fatal_error "ReFrame runtime failed to run with command: reframe ${REFRAME_ARGS} --run." -fi - -echo ">> Cleaning up ${TMPDIR}..." -rm -r ${TMPDIR} - -exit ${reframe_exit_code} diff --git a/tests/OpenFOAM/OpenFOAM-8_motorBike_2M-cells_2cores.sh b/tests/OpenFOAM/OpenFOAM-8_motorBike_2M-cells_2cores.sh deleted file mode 100755 index fdbd1a4c15..0000000000 --- a/tests/OpenFOAM/OpenFOAM-8_motorBike_2M-cells_2cores.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/bash - -module load OpenFOAM/8-foss-2020a - -# unset $LD_LIBRARY_PATH to avoid breaking system tools (like 'sed') -# for the software in the EESSI software stack $LD_LIBRARY_PATH is irrelevant (because of RPATH linking) -unset LD_LIBRARY_PATH - -which ssh &> /dev/null -if [ $? -ne 0 ]; then - # if ssh is not available, set plm_rsh_agent to empty value to avoid OpenMPI failing over it - # that's OK, because this is a single-node run - export OMPI_MCA_plm_rsh_agent='' -fi - -source $FOAM_BASH - -if [ -z $EBROOTOPENFOAM ]; then - echo "ERROR: OpenFOAM module not loaded?" >&2 - exit 1 -fi - -export WORKDIR=/tmp/$USER/$$ -echo "WORKDIR: $WORKDIR" -mkdir -p $WORKDIR -cd $WORKDIR -pwd - -# motorBike, 2M cells -BLOCKMESH_DIMENSIONS="100 40 40" -# motorBike, 150M cells -#BLOCKMESH_DIMENSIONS="200 80 80" - -# X*Y*Z should be equal to total number of available cores (across all nodes) -X=2 -Y=1 -Z=1 -# number of nodes -NODES=1 -# total number of cores -NP=$((X * Y * Z)) -# cores per node -PPN=$(((NP + NODES -1)/NODES)) - -CASE_NAME=motorBike - -if [ -d $CASE_NAME ]; then - echo "$CASE_NAME already exists in $PWD!" >&2 - exit 1 -fi - -cp -r $WM_PROJECT_DIR/tutorials/incompressible/simpleFoam/motorBike $CASE_NAME -cd $CASE_NAME -pwd - -# generate mesh -echo "generating mesh..." -foamDictionary -entry castellatedMeshControls.maxGlobalCells -set 200000000 system/snappyHexMeshDict -foamDictionary -entry blocks -set "( hex ( 0 1 2 3 4 5 6 7 ) ( $BLOCKMESH_DIMENSIONS ) simpleGrading ( 1 1 1 ) )" system/blockMeshDict -foamDictionary -entry numberOfSubdomains -set $NP system/decomposeParDict -foamDictionary -entry hierarchicalCoeffs.n -set "($X $Y $Z)" system/decomposeParDict - -cp $WM_PROJECT_DIR/tutorials/resources/geometry/motorBike.obj.gz constant/triSurface/ -surfaceFeatures 2>&1 | tee log.surfaceFeatures -blockMesh 2>&1 | tee log.blockMesh -decomposePar -copyZero 2>&1 | tee log.decomposePar -mpirun -np $NP -ppn $PPN -hostfile hostlist snappyHexMesh -parallel -overwrite 2>&1 | tee log.snappyHexMesh -reconstructParMesh -constant -rm -rf ./processor* -renumberMesh -constant -overwrite 2>&1 | tee log.renumberMesh - -# decompose mesh -echo "decomposing..." -foamDictionary -entry numberOfSubdomains -set $NP system/decomposeParDict -foamDictionary -entry method -set multiLevel system/decomposeParDict -foamDictionary -entry multiLevelCoeffs -set "{}" system/decomposeParDict -foamDictionary -entry scotchCoeffs -set "{}" system/decomposeParDict -foamDictionary -entry multiLevelCoeffs.level0 -set "{}" system/decomposeParDict -foamDictionary -entry multiLevelCoeffs.level0.numberOfSubdomains -set $NODES system/decomposeParDict -foamDictionary -entry multiLevelCoeffs.level0.method -set scotch system/decomposeParDict -foamDictionary -entry multiLevelCoeffs.level1 -set "{}" system/decomposeParDict -foamDictionary -entry multiLevelCoeffs.level1.numberOfSubdomains -set $PPN system/decomposeParDict -foamDictionary -entry multiLevelCoeffs.level1.method -set scotch system/decomposeParDict - -decomposePar -copyZero 2>&1 | tee log.decomposeParMultiLevel - -# run simulation -echo "running..." -foamDictionary -entry writeInterval -set 1000 system/controlDict -foamDictionary -entry runTimeModifiable -set "false" system/controlDict -foamDictionary -entry functions -set "{}" system/controlDict - -mpirun --oversubscribe -np $NP potentialFoam -parallel 2>&1 | tee log.potentialFoam -time mpirun --oversubscribe -np $NP simpleFoam -parallel 2>&1 | tee log.simpleFoam - -echo "cleanup..." -rm -rf $WORKDIR diff --git a/tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.all.output b/tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.all.output deleted file mode 100644 index f6f97c2aaa..0000000000 --- a/tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.all.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/a64fx:aarch64/generic diff --git a/tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.cpuinfo b/tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.cpuinfo deleted file mode 100644 index 2484dbe3e7..0000000000 --- a/tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.cpuinfo +++ /dev/null @@ -1,8 +0,0 @@ -processor : 0 -BogoMIPS : 200.00 -Features : fp asimd evtstrm sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma dcpop sve -CPU implementer : 0x46 -CPU architecture: 8 -CPU variant : 0x1 -CPU part : 0x001 -CPU revision : 0 diff --git a/tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.output b/tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.output deleted file mode 100644 index 13b6c575c1..0000000000 --- a/tests/archdetect/aarch64/a64fx/Deucalion-Rocky85.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/a64fx diff --git a/tests/archdetect/aarch64/google/axion/GCP-axion.all.output b/tests/archdetect/aarch64/google/axion/GCP-axion.all.output deleted file mode 100644 index 66bc16c804..0000000000 --- a/tests/archdetect/aarch64/google/axion/GCP-axion.all.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/google/axion:aarch64/nvidia/grace:aarch64/neoverse_v1:aarch64/neoverse_n1:aarch64/generic diff --git a/tests/archdetect/aarch64/google/axion/GCP-axion.cpuinfo b/tests/archdetect/aarch64/google/axion/GCP-axion.cpuinfo deleted file mode 100644 index 86924d55f6..0000000000 --- a/tests/archdetect/aarch64/google/axion/GCP-axion.cpuinfo +++ /dev/null @@ -1,8 +0,0 @@ -processor : 0 -BogoMIPS : 2000.00 -Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm ssbs sb dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng -CPU implementer : 0x41 -CPU architecture: 8 -CPU variant : 0x0 -CPU part : 0xd4f -CPU revision : 1 diff --git a/tests/archdetect/aarch64/google/axion/GCP-axion.output b/tests/archdetect/aarch64/google/axion/GCP-axion.output deleted file mode 100644 index bb5a3a1ee7..0000000000 --- a/tests/archdetect/aarch64/google/axion/GCP-axion.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/google/axion diff --git a/tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.all.output b/tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.all.output deleted file mode 100644 index 340aaa5d02..0000000000 --- a/tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.all.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/neoverse_n1:aarch64/generic diff --git a/tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.cpuinfo b/tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.cpuinfo deleted file mode 100644 index 17f1615825..0000000000 --- a/tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.cpuinfo +++ /dev/null @@ -1,8 +0,0 @@ -processor : 0 -BogoMIPS : 243.75 -Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs -CPU implementer : 0x41 -CPU architecture: 8 -CPU variant : 0x3 -CPU part : 0xd0c -CPU revision : 1 diff --git a/tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.output b/tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.output deleted file mode 100644 index a9bd49c75c..0000000000 --- a/tests/archdetect/aarch64/neoverse_n1/AWS-awslinux-graviton2.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/neoverse_n1 diff --git a/tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.all.output b/tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.all.output deleted file mode 100644 index 340aaa5d02..0000000000 --- a/tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.all.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/neoverse_n1:aarch64/generic diff --git a/tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.cpuinfo b/tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.cpuinfo deleted file mode 100644 index 49824722f2..0000000000 --- a/tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.cpuinfo +++ /dev/null @@ -1,30 +0,0 @@ -Architecture: aarch64 -CPU op-mode(s): 32-bit, 64-bit -Byte Order: Little Endian -CPU(s): 64 -On-line CPU(s) list: 0-63 -Thread(s) per core: 1 -Core(s) per socket: 64 -Socket(s): 1 -NUMA node(s): 1 -Vendor ID: ARM -Model: 1 -Model name: Neoverse-N1 -Stepping: r3p1 -BogoMIPS: 50.00 -L1d cache: 4 MiB -L1i cache: 4 MiB -L2 cache: 64 MiB -L3 cache: 32 MiB -NUMA node0 CPU(s): 0-63 -Vulnerability Itlb multihit: Not affected -Vulnerability L1tf: Not affected -Vulnerability Mds: Not affected -Vulnerability Meltdown: Mitigation; PTI -Vulnerability Mmio stale data: Not affected -Vulnerability Spec store bypass: Not affected -Vulnerability Spectre v1: Mitigation; __user pointer sanitization -Vulnerability Spectre v2: Mitigation; CSV2, BHB -Vulnerability Srbds: Not affected -Vulnerability Tsx async abort: Not affected -Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp diff --git a/tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.output b/tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.output deleted file mode 100644 index a9bd49c75c..0000000000 --- a/tests/archdetect/aarch64/neoverse_n1/Azure-Ubuntu20-Altra.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/neoverse_n1 diff --git a/tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.all.output b/tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.all.output deleted file mode 100644 index 920d5f9996..0000000000 --- a/tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.all.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/neoverse_v1:aarch64/neoverse_n1:aarch64/generic diff --git a/tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.cpuinfo b/tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.cpuinfo deleted file mode 100644 index 01246f99da..0000000000 --- a/tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.cpuinfo +++ /dev/null @@ -1,8 +0,0 @@ -processor : 0 -BogoMIPS : 2100.00 -Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm ssbs paca pacg dcpodp svei8mm svebf16 i8mm bf16 dgh rng -CPU implementer : 0x41 -CPU architecture: 8 -CPU variant : 0x1 -CPU part : 0xd40 -CPU revision : 1 diff --git a/tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.output b/tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.output deleted file mode 100644 index a8e072a9c6..0000000000 --- a/tests/archdetect/aarch64/neoverse_v1/AWS-awslinux-graviton3.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/neoverse_v1 diff --git a/tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.all.output b/tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.all.output deleted file mode 100644 index 9a516a963f..0000000000 --- a/tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.all.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/nvidia/grace:aarch64/neoverse_v1:aarch64/neoverse_n1:aarch64/generic diff --git a/tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.cpuinfo b/tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.cpuinfo deleted file mode 100644 index cd5024170f..0000000000 --- a/tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.cpuinfo +++ /dev/null @@ -1,8 +0,0 @@ -processor : 0 -BogoMIPS : 2000.00 -Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm ssbs sb dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh -CPU implementer : 0x41 -CPU architecture: 8 -CPU variant : 0x0 -CPU part : 0xd4f -CPU revision : 0 diff --git a/tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.output b/tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.output deleted file mode 100644 index 5878b25414..0000000000 --- a/tests/archdetect/aarch64/nvidia/grace/Jureca-Rocky95.output +++ /dev/null @@ -1 +0,0 @@ -aarch64/nvidia/grace diff --git a/tests/archdetect/nvidia-smi/1xa100.output b/tests/archdetect/nvidia-smi/1xa100.output deleted file mode 100644 index 5eb3aaff18..0000000000 --- a/tests/archdetect/nvidia-smi/1xa100.output +++ /dev/null @@ -1 +0,0 @@ -accel/nvidia/cc80 diff --git a/tests/archdetect/nvidia-smi/1xa100.sh b/tests/archdetect/nvidia-smi/1xa100.sh deleted file mode 100755 index ead191418b..0000000000 --- a/tests/archdetect/nvidia-smi/1xa100.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -# output from NVIDIA A100 system, -# produced by: nvidia-smi --query-gpu=gpu_name,count,driver_version,compute_cap --format=csv,noheader -echo "NVIDIA A100-SXM4-80GB, 1, 545.23.08, 8.0" -exit 0 diff --git a/tests/archdetect/nvidia-smi/2xa100.output b/tests/archdetect/nvidia-smi/2xa100.output deleted file mode 100644 index 5eb3aaff18..0000000000 --- a/tests/archdetect/nvidia-smi/2xa100.output +++ /dev/null @@ -1 +0,0 @@ -accel/nvidia/cc80 diff --git a/tests/archdetect/nvidia-smi/2xa100.sh b/tests/archdetect/nvidia-smi/2xa100.sh deleted file mode 100755 index 5539607fbe..0000000000 --- a/tests/archdetect/nvidia-smi/2xa100.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -# output from NVIDIA A100 system, -# produced by: nvidia-smi --query-gpu=gpu_name,count,driver_version,compute_cap --format=csv,noheader -echo "NVIDIA A100-SXM4-80GB, 2, 545.23.08, 8.0" -echo "NVIDIA A100-SXM4-80GB, 2, 545.23.08, 8.0" -exit 0 diff --git a/tests/archdetect/nvidia-smi/4xa100.output b/tests/archdetect/nvidia-smi/4xa100.output deleted file mode 100644 index 5eb3aaff18..0000000000 --- a/tests/archdetect/nvidia-smi/4xa100.output +++ /dev/null @@ -1 +0,0 @@ -accel/nvidia/cc80 diff --git a/tests/archdetect/nvidia-smi/4xa100.sh b/tests/archdetect/nvidia-smi/4xa100.sh deleted file mode 100755 index 45458ea7bd..0000000000 --- a/tests/archdetect/nvidia-smi/4xa100.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -# output from NVIDIA A100 system, -# produced by: nvidia-smi --query-gpu=gpu_name,count,driver_version,compute_cap --format=csv,noheader -echo "NVIDIA A100-SXM4-80GB, 4, 545.23.08, 8.0" -echo "NVIDIA A100-SXM4-80GB, 4, 545.23.08, 8.0" -echo "NVIDIA A100-SXM4-80GB, 4, 545.23.08, 8.0" -echo "NVIDIA A100-SXM4-80GB, 4, 545.23.08, 8.0" -exit 0 diff --git a/tests/archdetect/nvidia-smi/cc01.output b/tests/archdetect/nvidia-smi/cc01.output deleted file mode 100644 index 9cbf66a131..0000000000 --- a/tests/archdetect/nvidia-smi/cc01.output +++ /dev/null @@ -1 +0,0 @@ -accel/nvidia/cc01 diff --git a/tests/archdetect/nvidia-smi/cc01.sh b/tests/archdetect/nvidia-smi/cc01.sh deleted file mode 100755 index 81011a1d16..0000000000 --- a/tests/archdetect/nvidia-smi/cc01.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -# output from non-existing NVIDIA GPU system, -# to test handling of unknown GPU model -# (supposedly) produced by: nvidia-smi --query-gpu=gpu_name,count,driver_version,compute_cap --format=csv,noheader -echo "NVIDIA does-not-exist, 1, 000.00.00, 0.1" -exit 0 diff --git a/tests/archdetect/nvidia-smi/no_devices.output b/tests/archdetect/nvidia-smi/no_devices.output deleted file mode 100644 index b251bfc837..0000000000 --- a/tests/archdetect/nvidia-smi/no_devices.output +++ /dev/null @@ -1 +0,0 @@ -non-zero exit code: 3 diff --git a/tests/archdetect/nvidia-smi/no_devices.sh b/tests/archdetect/nvidia-smi/no_devices.sh deleted file mode 100755 index 0bc26dcddc..0000000000 --- a/tests/archdetect/nvidia-smi/no_devices.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -echo "No devices were found" -exit 6 diff --git a/tests/archdetect/nvidia-smi/none.output b/tests/archdetect/nvidia-smi/none.output deleted file mode 100644 index e287574cc3..0000000000 --- a/tests/archdetect/nvidia-smi/none.output +++ /dev/null @@ -1 +0,0 @@ -non-zero exit code: 2 diff --git a/tests/archdetect/ppc64le/power9le/unknown-power9le.all.output b/tests/archdetect/ppc64le/power9le/unknown-power9le.all.output deleted file mode 100644 index 7ecf79d0a7..0000000000 --- a/tests/archdetect/ppc64le/power9le/unknown-power9le.all.output +++ /dev/null @@ -1 +0,0 @@ -ppc64le/power9le:ppc64le/generic \ No newline at end of file diff --git a/tests/archdetect/ppc64le/power9le/unknown-power9le.cpuinfo b/tests/archdetect/ppc64le/power9le/unknown-power9le.cpuinfo deleted file mode 100644 index 4e6bdbb97b..0000000000 --- a/tests/archdetect/ppc64le/power9le/unknown-power9le.cpuinfo +++ /dev/null @@ -1,4 +0,0 @@ -processor : 0 -cpu : POWER9 (architected), altivec supported -clock : 2200.000000MHz -revision : 2.2 (pvr 004e 1202) diff --git a/tests/archdetect/ppc64le/power9le/unknown-power9le.output b/tests/archdetect/ppc64le/power9le/unknown-power9le.output deleted file mode 100644 index 8decf544ea..0000000000 --- a/tests/archdetect/ppc64le/power9le/unknown-power9le.output +++ /dev/null @@ -1 +0,0 @@ -ppc64le/power9le diff --git a/tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.all.output b/tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.all.output deleted file mode 100644 index 180de26f0e..0000000000 --- a/tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.all.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/amd/zen2:x86_64/generic \ No newline at end of file diff --git a/tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.cpuinfo b/tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.cpuinfo deleted file mode 100644 index edf9c3e15b..0000000000 --- a/tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.cpuinfo +++ /dev/null @@ -1,27 +0,0 @@ -Architecture: x86_64 -CPU op-mode(s): 32-bit, 64-bit -Byte Order: Little Endian -CPU(s): 120 -On-line CPU(s) list: 0-119 -Thread(s) per core: 1 -Core(s) per socket: 60 -Socket(s): 2 -NUMA node(s): 4 -Vendor ID: AuthenticAMD -CPU family: 23 -Model: 49 -Model name: AMD EPYC 7V12 64-Core Processor -Stepping: 0 -CPU MHz: 2445.424 -BogoMIPS: 4890.84 -Hypervisor vendor: Microsoft -Virtualization type: full -L1d cache: 32K -L1i cache: 32K -L2 cache: 512K -L3 cache: 16384K -NUMA node0 CPU(s): 0-29 -NUMA node1 CPU(s): 30-59 -NUMA node2 CPU(s): 60-89 -NUMA node3 CPU(s): 90-119 -Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm art rep_good nopl extd_apicid aperfmperf eagerfpu pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext retpoline_amd ssbd vmmcall fsgsbase bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat umip diff --git a/tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.output b/tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.output deleted file mode 100644 index 9e4da0c5d6..0000000000 --- a/tests/archdetect/x86_64/amd/zen2/Azure-CentOS7-7V12.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/amd/zen2 diff --git a/tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.all.output b/tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.all.output deleted file mode 100644 index 798a0aa565..0000000000 --- a/tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.all.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/amd/zen3:x86_64/amd/zen2:x86_64/generic \ No newline at end of file diff --git a/tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.cpuinfo b/tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.cpuinfo deleted file mode 100644 index 24961c80c3..0000000000 --- a/tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.cpuinfo +++ /dev/null @@ -1,27 +0,0 @@ -Architecture: x86_64 -CPU op-mode(s): 32-bit, 64-bit -Byte Order: Little Endian -CPU(s): 120 -On-line CPU(s) list: 0-119 -Thread(s) per core: 1 -Core(s) per socket: 60 -Socket(s): 2 -NUMA node(s): 4 -Vendor ID: AuthenticAMD -CPU family: 25 -Model: 1 -Model name: AMD EPYC 7V73X 64-Core Processor -Stepping: 2 -CPU MHz: 1846.550 -BogoMIPS: 3693.10 -Hypervisor vendor: Microsoft -Virtualization type: full -L1d cache: 32K -L1i cache: 32K -L2 cache: 512K -L3 cache: 98304K -NUMA node0 CPU(s): 0-29 -NUMA node1 CPU(s): 30-59 -NUMA node2 CPU(s): 60-89 -NUMA node3 CPU(s): 90-119 -Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm art rep_good nopl extd_apicid aperfmperf eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext perfctr_core invpcid_single retpoline_amd vmmcall fsgsbase bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat umip vaes vpclmulqdq diff --git a/tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.output b/tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.output deleted file mode 100644 index 341c027cc2..0000000000 --- a/tests/archdetect/x86_64/amd/zen3/Azure-CentOS7-7V73X.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/amd/zen3 diff --git a/tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.all.output b/tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.all.output deleted file mode 100644 index e1bbd79e4a..0000000000 --- a/tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.all.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/amd/zen4:x86_64/amd/zen3:x86_64/amd/zen2:x86_64/generic diff --git a/tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.cpuinfo b/tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.cpuinfo deleted file mode 100644 index 4a97da862c..0000000000 --- a/tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.cpuinfo +++ /dev/null @@ -1,27 +0,0 @@ -processor : 0 -vendor_id : AuthenticAMD -cpu family : 25 -model : 17 -model name : AMD EPYC 9V33X 96-Core Processor -stepping : 1 -microcode : 0xffffffff -cpu MHz : 3705.853 -cache size : 1024 KB -physical id : 0 -siblings : 88 -core id : 0 -cpu cores : 88 -apicid : 0 -initial apicid : 0 -fpu : yes -fpu_exception : yes -cpuid level : 13 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl tsc_reliable nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy svm cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext perfctr_core invpcid_single vmmcall fsgsbase bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves avx512_bf16 clzero xsaveerptr arat npt nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold v_vmsave_vmload avx512vbmi umip avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid fsrm -bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass -bogomips : 5100.08 -TLB size : 3584 4K pages -clflush size : 64 -cache_alignment : 64 -address sizes : 48 bits physical, 48 bits virtual -power management: diff --git a/tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.output b/tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.output deleted file mode 100644 index 950740a78c..0000000000 --- a/tests/archdetect/x86_64/amd/zen4/Azure-Alma8-9V33X.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/amd/zen4 diff --git a/tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.all.output b/tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.all.output deleted file mode 100644 index e1bbd79e4a..0000000000 --- a/tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.all.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/amd/zen4:x86_64/amd/zen3:x86_64/amd/zen2:x86_64/generic diff --git a/tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.cpuinfo b/tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.cpuinfo deleted file mode 100644 index f28381d7a2..0000000000 --- a/tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.cpuinfo +++ /dev/null @@ -1,27 +0,0 @@ -processor : 0 -vendor_id : AuthenticAMD -cpu family : 25 -model : 17 -model name : AMD EPYC 9654 96-Core Processor -stepping : 1 -microcode : 0xa10113e -cpu MHz : 3699.993 -cache size : 1024 KB -physical id : 0 -siblings : 96 -core id : 0 -cpu cores : 96 -apicid : 0 -initial apicid : 0 -fpu : yes -fpu_exception : yes -cpuid level : 16 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb cat_l3 cdp_l3 invpcid_single hw_pstate ssbd mba perfmon_v2 ibrs ibpb stibp vmmcall fsgsbase bmi1 avx2 smep bmi2 erms invpcid cqm rdt_a avx512f avx512dq rdseed adx avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local avx512_bf16 clzero irperf xsaveerptr wbnoinvd amd_ppin cppc arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif v_spec_ctrl avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq la57 rdpid overflow_recov succor smca fsrm flush_l1d -bugs : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass -bogomips : 4799.99 -TLB size : 3584 4K pages -clflush size : 64 -cache_alignment : 64 -address sizes : 52 bits physical, 57 bits virtual -power management: ts ttp tm hwpstate cpb eff_freq_ro [13] [14] diff --git a/tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.output b/tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.output deleted file mode 100644 index 950740a78c..0000000000 --- a/tests/archdetect/x86_64/amd/zen4/Shinx-RHEL8-9654.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/amd/zen4 diff --git a/tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.all.output b/tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.all.output deleted file mode 100644 index b34dcc1506..0000000000 --- a/tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.all.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/cascadelake:x86_64/intel/skylake_avx512:x86_64/intel/haswell:x86_64/generic diff --git a/tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.cpuinfo b/tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.cpuinfo deleted file mode 100644 index 6bac63795e..0000000000 --- a/tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.cpuinfo +++ /dev/null @@ -1,24 +0,0 @@ -Architecture: x86_64 -CPU op-mode(s): 32-bit, 64-bit -Byte Order: Little Endian -CPU(s): 16 -On-line CPU(s) list: 0-15 -Thread(s) per core: 2 -Core(s) per socket: 8 -Socket(s): 1 -NUMA node(s): 1 -Vendor ID: GenuineIntel -CPU family: 6 -Model: 85 -Model name: Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz -Stepping: 7 -CPU MHz: 2500.000 -BogoMIPS: 5000.00 -Hypervisor vendor: KVM -Virtualization type: full -L1d cache: 32K -L1i cache: 32K -L2 cache: 1024K -L3 cache: 36608K -NUMA node0 CPU(s): 0-15 -Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves ida arat pku ospke avx512_vnni diff --git a/tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.output b/tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.output deleted file mode 100644 index b6f68edac7..0000000000 --- a/tests/archdetect/x86_64/intel/cascadelake/AWS-Rocky8-8259CL.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/cascadelake diff --git a/tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.all.output b/tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.all.output deleted file mode 100644 index a047dd42cc..0000000000 --- a/tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.all.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/haswell:x86_64/generic \ No newline at end of file diff --git a/tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.cpuinfo b/tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.cpuinfo deleted file mode 100644 index 7bb5aa958f..0000000000 --- a/tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.cpuinfo +++ /dev/null @@ -1,25 +0,0 @@ -processor : 0 -vendor_id : GenuineIntel -cpu family : 6 -model : 63 -model name : Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz -stepping : 2 -microcode : 0x3c -cpu MHz : 1757.910 -cache size : 30720 KB -physical id : 0 -siblings : 12 -core id : 0 -cpu cores : 12 -apicid : 0 -initial apicid : 0 -fpu : yes -fpu_exception : yes -cpuid level : 15 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm epb invpcid_single tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm xsaveopt cqm_llc cqm_occup_llc ibpb ibrs stibp dtherm arat pln pts spec_ctrl intel_stibp -bogomips : 4987.97 -clflush size : 64 -cache_alignment : 64 -address sizes : 46 bits physical, 48 bits virtual -power management: diff --git a/tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.output b/tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.output deleted file mode 100644 index 5af6120686..0000000000 --- a/tests/archdetect/x86_64/intel/haswell/archspec-linux-E5-2680-v3.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/haswell diff --git a/tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.all.output b/tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.all.output deleted file mode 100644 index 07303e013a..0000000000 --- a/tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.all.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/icelake:x86_64/intel/cascadelake:x86_64/intel/skylake_avx512:x86_64/intel/haswell:x86_64/generic diff --git a/tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.cpuinfo b/tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.cpuinfo deleted file mode 100644 index d089b56aee..0000000000 --- a/tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.cpuinfo +++ /dev/null @@ -1,24 +0,0 @@ -Architecture: x86_64 -CPU op-mode(s): 32-bit, 64-bit -Byte Order: Little Endian -CPU(s): 16 -On-line CPU(s) list: 0-15 -Thread(s) per core: 2 -Core(s) per socket: 8 -Socket(s): 1 -NUMA node(s): 1 -Vendor ID: GenuineIntel -CPU family: 6 -Model: 106 -Model name: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz -Stepping: 6 -CPU MHz: 2899.930 -BogoMIPS: 5799.86 -Hypervisor vendor: KVM -Virtualization type: full -L1d cache: 48K -L1i cache: 32K -L2 cache: 1280K -L3 cache: 55296K -NUMA node0 CPU(s): 0-15 -Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves wbnoinvd ida arat avx512vbmi pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg tme avx512_vpopcntdq rdpid md_clear flush_l1d arch_capabilities diff --git a/tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.output b/tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.output deleted file mode 100644 index ea242161b3..0000000000 --- a/tests/archdetect/x86_64/intel/icelake/AWS-Rocky8-8375C.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/icelake diff --git a/tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.all.output b/tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.all.output deleted file mode 100644 index 8f8df1be7e..0000000000 --- a/tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.all.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/sapphirerapids:x86_64/intel/icelake:x86_64/intel/cascadelake:x86_64/intel/skylake_avx512:x86_64/intel/haswell:x86_64/generic diff --git a/tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.cpuinfo b/tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.cpuinfo deleted file mode 100644 index d94e7a85fc..0000000000 --- a/tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.cpuinfo +++ /dev/null @@ -1,26 +0,0 @@ -processor : 0 -vendor_id : GenuineIntel -cpu family : 6 -model : 143 -model name : Intel(R) Xeon(R) Platinum 8488C -stepping : 8 -microcode : 0x2b000620 -cpu MHz : 2400.000 -cache size : 107520 KB -physical id : 0 -siblings : 16 -core id : 0 -cpu cores : 8 -apicid : 0 -initial apicid : 0 -fpu : yes -fpu_exception : yes -cpuid level : 31 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq monitor ssse3 fma cx16 pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves avx_vnni avx512_bf16 wbnoinvd ida arat avx512vbmi umip pku ospke waitpkg avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg tme avx512_vpopcntdq rdpid cldemote movdiri movdir64b md_clear serialize amx_bf16 avx512_fp16 amx_tile amx_int8 flush_l1d arch_capabilities -bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb bhi -bogomips : 4800.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 46 bits physical, 48 bits virtual -power management: diff --git a/tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.output b/tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.output deleted file mode 100644 index f01af0e930..0000000000 --- a/tests/archdetect/x86_64/intel/sapphirerapids/AWS-Rocky8-8488C.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/sapphirerapids diff --git a/tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.all.output b/tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.all.output deleted file mode 100644 index c9fa524ea6..0000000000 --- a/tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.all.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/skylake_avx512:x86_64/intel/haswell:x86_64/generic \ No newline at end of file diff --git a/tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.cpuinfo b/tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.cpuinfo deleted file mode 100644 index e9ab1987dd..0000000000 --- a/tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.cpuinfo +++ /dev/null @@ -1,25 +0,0 @@ -processor : 0 -vendor_id : GenuineIntel -cpu family : 6 -model : 85 -model name : Intel(R) Xeon(R) Gold 6132 CPU @ 2.60GHz -stepping : 4 -microcode : 0x200004d -cpu MHz : 2600.000 -cache size : 19712 KB -physical id : 0 -siblings : 14 -core id : 0 -cpu cores : 14 -apicid : 0 -initial apicid : 0 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 invpcid_single intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm mpx rdt_a avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local ibpb ibrs stibp dtherm ida arat pln pts spec_ctrl intel_stibp ssbd -bogomips : 5200.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 46 bits physical, 48 bits virtual -power management: diff --git a/tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.output b/tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.output deleted file mode 100644 index 918c33245c..0000000000 --- a/tests/archdetect/x86_64/intel/skylake_avx512/archspec-linux-6132.output +++ /dev/null @@ -1 +0,0 @@ -x86_64/intel/skylake_avx512 diff --git a/tests/eessi_test_mapping/map_software_to_test.py b/tests/eessi_test_mapping/map_software_to_test.py deleted file mode 100644 index a0da6258c8..0000000000 --- a/tests/eessi_test_mapping/map_software_to_test.py +++ /dev/null @@ -1,95 +0,0 @@ -import yaml -import re -import os -import argparse - -def load_mappings(file_path): - """Load the YAML mappings from a file.""" - if not os.path.exists(file_path): - raise FileNotFoundError(f"Error: {file_path} does not exist.") - with open(file_path, 'r') as file: - config = yaml.safe_load(file) - return config['mappings'] - -def read_software_names(file_path): - """Read software names from the module_files.list.txt file.""" - if not os.path.exists(file_path): - raise FileNotFoundError(f"Error: {file_path} does not exist.") - with open(file_path, 'r') as file: - software_names = [line.strip() for line in file if line.strip()] - return software_names - -def get_tests_for_software(software_name, mappings): - """Get the list of tests for a given software name based on the first matching regex pattern.""" - - # Iterate over patterns in the order they appear in the YAML file - for pattern, tests in mappings.items(): - if re.match(pattern, software_name): - return tests - - # If no matches are found, return the default tests if they exist - if 'default_tests' in mappings: - return mappings['default_tests'] - - return [] - -def main(yaml_file, module_file, debug, defaults_only): - """Main function to process software names and their tests.""" - mappings = load_mappings(yaml_file) - if debug: - print(f"Loaded mappings from '{yaml_file}'") - - if not defaults_only: - software_names = read_software_names(module_file) - if debug: - print(f"Read software names from '{module_file}'") - - tests_to_run = [] - arg_string = "" - - if not defaults_only: - # For each module name, get the relevant set of tests - for software_name in software_names: - additional_tests = get_tests_for_software(software_name, mappings) - for test in additional_tests: - if test not in tests_to_run: - tests_to_run.append(test) - - if additional_tests and debug: - print(f"Software: {software_name} -> Tests: {additional_tests}") - elif debug: - print(f"Software: {software_name} -> No tests found") - - # Always add the default set of tests, if default_tests is specified - if 'default_tests' in mappings: - additional_tests = mappings['default_tests'] - for test in additional_tests: - if test not in tests_to_run: - tests_to_run.append(test) - - if additional_tests and debug: - print(f"Adding default set of tests: {additional_tests}") - - # Create argument string out of the list of tests to run - if tests_to_run: - arg_string = " ".join([f"-n {test_name}" for test_name in tests_to_run]) - - # Print final lists & argument string - if debug: - print(f"Full list of tests to run: {tests_to_run}") - print(f"Argument string: {arg_string}") - else: - # This is the only thing this script should print, unless run with --debug - print(f"{arg_string}") - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Map software names to their tests based on a YAML configuration.") - parser.add_argument('--mapping-file', type=str, help='Path to the YAML file containing the test mappings.') - parser.add_argument('--module-list', type=str, help='Path to the file containing the list of software names.') - defaults_help = "Don't consider the module-list file, only return the default tests from the mapping file" - parser.add_argument('--defaults-only', action='store_true', default=False, help=defaults_help) - parser.add_argument('--debug', action='store_true', default=False, help='Enable debug output.') - - args = parser.parse_args() - - main(args.mapping_file, args.module_list, args.debug, args.defaults_only) diff --git a/tests/eessi_test_mapping/software_to_tests.yml b/tests/eessi_test_mapping/software_to_tests.yml deleted file mode 100644 index 3a162666fc..0000000000 --- a/tests/eessi_test_mapping/software_to_tests.yml +++ /dev/null @@ -1,35 +0,0 @@ -# This file creates a mapping between (regular expressions for) module names and test names from the EESSI test suite -# If a module name matches one of the regular expressions, the listed set of tests will be run in the test step -# For a given module name, the test list for the first matching regular expression is returned -# E.g. for -# mappings: -# foo-v1: -# - bar -# foo-* -# - bar2 -# only the bar test will be run for foo-v1 (even though it also matches the pattern (foo-*) -# If a module name does not match anything, the default_tests will be run -# Note that to list all available tests by name, one can do execute -# reframe -R -c /path/to/eessi/test-suite/ --list | grep -Po "\bEESSI_\S+?(?=[\s'])" | uniq -# Note that this regular expression is a bit sensitive to changes in the structure of ReFrame's output, -# but is confirmed to work for ReFrame version 4.6.1 -mappings: - PyTorch-Bundle/*: - - EESSI_PyTorch_torchvision - QuantumESPRESSO/*: - - EESSI_QuantumESPRESSO - CP2K/*: - - EESSI_CP2K - ESPResSo/*: - - EESSI_ESPRESSO - LAMMPS/*: - - EESSI_LAMMPS - OSU-Micro-Benchmarks/*: - - EESSI_OSU - GROMACS/*: - - EESSI_GROMACS - default_tests: - # Low level tests - - EESSI_OSU - # A very quick-to-run high level application test - - EESSI_LAMMPS diff --git a/tests/nvidia-libs/mock-nvidia-libs.sh b/tests/nvidia-libs/mock-nvidia-libs.sh deleted file mode 100644 index cdf5f5ca9a..0000000000 --- a/tests/nvidia-libs/mock-nvidia-libs.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash -# Setup script to create fake NVIDIA libraries for testing - -# Create directories for fake NVIDIA libraries -mkdir -p /tmp/nvidia_libs -mkdir -p /tmp/nvidia_libs_duplicate - -# Create common NVIDIA libraries with minimal content -libraries=( - "libcuda.so.1" - "libnvidia-ml.so.1" - "libnvidia-ptxjitcompiler.so.1" - "libOpenCL.so.1" - "libnvidia-fatbinaryloader.so.1" - "libnvidia-opencl.so.1" - "libcudadebugger.so.1" - "libnvidia-compiler.so.1" - "libnvidia-nvvm.so.1" -) - -for lib in "${libraries[@]}"; do - # Create fake library file with some minimal content - echo "This is a fake $lib for testing purposes" > "/tmp/nvidia_libs/$lib" - # Make it executable to pass potential file type checks - chmod +x "/tmp/nvidia_libs/$lib" - # Create a symlink for libraries without version number (if the library has one) - if [[ "$lib" == *".so."* ]]; then - base_lib=$(echo "$lib" | sed 's/\.so\.[0-9]*/.so/') - ln -sf "/tmp/nvidia_libs/$lib" "/tmp/nvidia_libs/$base_lib" - fi - - # Create duplicate libraries in a different location - if [[ "$lib" == "libcuda.so.1" || "$lib" == "libnvidia-ml.so.1" ]]; then - echo "This is a duplicate $lib for testing purposes" > "/tmp/nvidia_libs_duplicate/$lib" - chmod +x "/tmp/nvidia_libs_duplicate/$lib" - if [[ "$lib" == *".so."* ]]; then - base_lib=$(echo "$lib" | sed 's/\.so\.[0-9]*/.so/') - ln -sf "/tmp/nvidia_libs_duplicate/$lib" "/tmp/nvidia_libs_duplicate/$base_lib" - fi - fi -done - -# Create a fake ldconfig cache that points to our fake libraries -mkdir -p /tmp/ldconfig - -# Create a wrapper script for ldconfig -cat > /tmp/ldconfig/ldconfig << 'EOF' -#!/bin/bash -# Fake ldconfig command that returns our fake libraries - -if [ "$1" = "-p" ]; then - # Simulate ldconfig -p output with duplicate entries - echo "libcuda.so.1 (libc6,x86-64) => /tmp/nvidia_libs/libcuda.so.1" - echo "libcuda.so.1 (libc6,x86-64) => /tmp/nvidia_libs_duplicate/libcuda.so.1" - echo "libcuda.so (libc6,x86-64) => /tmp/nvidia_libs/libcuda.so" - echo "libcuda.so (libc6,x86-64) => /tmp/nvidia_libs_duplicate/libcuda.so" - echo "libnvidia-ml.so.1 (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-ml.so.1" - echo "libnvidia-ml.so.1 (libc6,x86-64) => /tmp/nvidia_libs_duplicate/libnvidia-ml.so.1" - echo "libnvidia-ml.so (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-ml.so" - echo "libnvidia-ml.so (libc6,x86-64) => /tmp/nvidia_libs_duplicate/libnvidia-ml.so" - echo "libnvidia-ptxjitcompiler.so.1 (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-ptxjitcompiler.so.1" - echo "libnvidia-ptxjitcompiler.so (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-ptxjitcompiler.so" - echo "libOpenCL.so.1 (libc6,x86-64) => /tmp/nvidia_libs/libOpenCL.so.1" - echo "libOpenCL.so (libc6,x86-64) => /tmp/nvidia_libs/libOpenCL.so" - echo "libnvidia-fatbinaryloader.so.1 (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-fatbinaryloader.so.1" - echo "libnvidia-fatbinaryloader.so (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-fatbinaryloader.so" - echo "libnvidia-opencl.so.1 (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-opencl.so.1" - echo "libnvidia-opencl.so (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-opencl.so" - echo "libcudadebugger.so.1 (libc6,x86-64) => /tmp/nvidia_libs/libcudadebugger.so.1" - echo "libcudadebugger.so (libc6,x86-64) => /tmp/nvidia_libs/libcudadebugger.so" - echo "libnvidia-compiler.so.1 (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-compiler.so.1" - echo "libnvidia-compiler.so (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-compiler.so" - echo "libnvidia-nvvm.so.1 (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-nvvm.so.1" - echo "libnvidia-nvvm.so (libc6,x86-64) => /tmp/nvidia_libs/libnvidia-nvvm.so" -fi -EOF -chmod +x /tmp/ldconfig/ldconfig - -# Create a wrapper for ldd that returns minimal dependency info for our libraries -cat > /tmp/ldconfig/ldd << 'EOF' -#!/bin/bash -# Fake ldd command that doesn't show any missing dependencies -echo "linux-vdso.so.1 => (0x00007ffca39ed000)" -echo "libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2ace77e000)" -echo "/lib64/ld-linux-x86-64.so.2 (0x00007f2aceb41000)" -EOF -chmod +x /tmp/ldconfig/ldd diff --git a/tests/nvidia-libs/mock-nvidia-smi.sh b/tests/nvidia-libs/mock-nvidia-smi.sh deleted file mode 100644 index 313e71e2bf..0000000000 --- a/tests/nvidia-libs/mock-nvidia-smi.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -# This is a standard fake nvidia-smi script for testing purposes -# Using driver version 535.129.03 and CUDA version 8.0 - -# Check if --query-gpu flag is used -if [[ "$1" == "--query-gpu=gpu_name,count,driver_version,compute_cap" && "$2" == "--format=csv,noheader" ]]; then - # Simulate output for a system with an NVIDIA A100 GPU - echo "NVIDIA A100, 1, 535.129.03, 8.0" - exit 0 -else - # Default output (similar to nvidia-smi with no arguments) - cat << EOF -Mon Feb 26 10:30:45 2024 -+-----------------------------------------------------------------------------+ -| NVIDIA-SMI 535.129.03 Driver Version: 535.129.03 CUDA Version: 12.2 | -|-------------------------------+----------------------+----------------------+ -| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | -| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | -| | | MIG M. | -|===============================+======================+======================| -| 0 NVIDIA A100 On | 00000000:00:00.0 Off | 0 | -| N/A 34C P0 69W / 400W | 0MiB / 40960MiB | 0% Default | -| | | Disabled | -+-------------------------------+----------------------+----------------------+ - -+-----------------------------------------------------------------------------+ -| Processes: | -| GPU GI CI PID Type Process name GPU Memory | -| ID ID Usage | -|=============================================================================| -| No running processes found | -+-----------------------------------------------------------------------------+ -EOF - exit 0 -fi diff --git a/update_lmod_cache.sh b/update_lmod_cache.sh deleted file mode 100755 index 814bb2dae0..0000000000 --- a/update_lmod_cache.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# -# Script to update Lmod cache in EESSI -# - -TOPDIR=$(dirname $(realpath $0)) - -source $TOPDIR/scripts/utils.sh - -if [ $# -ne 2 ]; then - echo "Usage: $0 " >&2 - exit 1 -fi -EPREFIX=$1 -EASYBUILD_INSTALLPATH=$2 - -if [ ! -d $EPREFIX ]; then - echo "\$EPREFIX does not exist!" >&2 - exit 2 -fi -if [ ! -d $EASYBUILD_INSTALLPATH ]; then - echo "\$EASYBUILD_INSTALLPATH does not exist!" >&2 - exit 2 -fi - -source $EPREFIX/usr/share/Lmod/init/bash - -# we need to specify the path to the Lmod cache dir + timestamp file to ensure -# that update_lmod_system_cache_files updates correct Lmod cache -lmod_cache_dir=${EASYBUILD_INSTALLPATH}/.lmod/cache -lmod_cache_timestamp_file=${EASYBUILD_INSTALLPATH}/.lmod/cache/timestamp -modpath=${EASYBUILD_INSTALLPATH}/modules/all - -${LMOD_DIR}/update_lmod_system_cache_files -d ${lmod_cache_dir} -t ${lmod_cache_timestamp_file} ${modpath} -check_exit_code $? "Lmod cache updated" "Lmod cache update failed!" - -ls -lrt ${EASYBUILD_INSTALLPATH}/.lmod/cache diff --git a/versions/2021.06/init/Magic_Castle/bash b/versions/2021.06/init/Magic_Castle/bash deleted file mode 100644 index 5f149c817f..0000000000 --- a/versions/2021.06/init/Magic_Castle/bash +++ /dev/null @@ -1,3 +0,0 @@ -/cvmfs/pilot.eessi-hpc.org/versions/2021.06/init/print_deprecation_warning.sh - -source /cvmfs/pilot.eessi-hpc.org/versions/2021.12/init/Magic_Castle/bash diff --git a/versions/2021.06/init/bash b/versions/2021.06/init/bash deleted file mode 100644 index 82a078849a..0000000000 --- a/versions/2021.06/init/bash +++ /dev/null @@ -1,3 +0,0 @@ -/cvmfs/pilot.eessi-hpc.org/versions/2021.06/init/print_deprecation_warning.sh - -source /cvmfs/pilot.eessi-hpc.org/versions/2021.12/init/bash diff --git a/versions/2021.06/init/print_deprecation_warning.sh b/versions/2021.06/init/print_deprecation_warning.sh deleted file mode 100755 index b721ed2f71..0000000000 --- a/versions/2021.06/init/print_deprecation_warning.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -function echo_yellow_stderr() { - echo -e "\e[33m${1}\e[0m" >&2 -} - -echo_yellow_stderr -echo_yellow_stderr "WARNING: Version 2021.06 of the EESSI pilot repository has been removed since 16 May 2023." -echo_yellow_stderr -echo_yellow_stderr "Version 2021.12 of the EESSI pilot repository can be used as a drop-in replacement, " -echo_yellow_stderr "so we have prepared your environment to use that instead." -echo_yellow_stderr -echo_yellow_stderr "In the future, please run" -echo_yellow_stderr -echo_yellow_stderr " source /cvmfs/pilot.eessi-hpc.org/latest/init/bash" -echo_yellow_stderr -echo_yellow_stderr "to prepare your start using the EESSI pilot repository." -echo_yellow_stderr -echo_yellow_stderr "See also https://eessi.github.io/docs/using_eessi/setting_up_environment ." -echo_yellow_stderr From 6046377a770d76b3be796ebfaa26be5ad781bd6f Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Wed, 11 Jun 2025 18:49:25 +0200 Subject: [PATCH 2/4] clone EESSI/software-layer-scripts repository in CI workflow to check README --- .github/workflows/tests_readme.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests_readme.yml b/.github/workflows/tests_readme.yml index 1a838e06d6..333266baab 100644 --- a/.github/workflows/tests_readme.yml +++ b/.github/workflows/tests_readme.yml @@ -19,12 +19,16 @@ jobs: - name: Check out software-layer repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Clone EESSI/software-layer-scripts repository + run: | + git clone https://github.com/EESSI/software-layer-scripts + - name: verify if README.md is consistent with EESSI_VERSION from init/eessi_defaults run: | - source init/eessi_defaults + source software-layer-scripts/init/eessi_defaults grep "${EESSI_VERSION}" README.md - name: verify if README.md is consistent with EESSI_CVMFS_REPO from init/eessi_defaults run: | - source init/eessi_defaults + source software-layer-scripts/init/eessi_defaults grep "${EESSI_CVMFS_REPO}" README.md From 27bde7b613b14e0f66afe1e26fd871be643d7968 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Wed, 11 Jun 2025 18:56:19 +0200 Subject: [PATCH 3/4] clone EESSI/software-layer-scripts repository in CI workflow to check for missing installations + remove check whether eb_hooks.py is up-to-date (that belongs in EESSI/software-layer-scripts repo) --- .github/workflows/test-software.eessi.io.yml | 37 +++++--------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/.github/workflows/test-software.eessi.io.yml b/.github/workflows/test-software.eessi.io.yml index b517246b07..2a58f790e8 100644 --- a/.github/workflows/test-software.eessi.io.yml +++ b/.github/workflows/test-software.eessi.io.yml @@ -55,6 +55,10 @@ jobs: with: fetch-depth: 0 # Fetch all history for all branches and tags + - name: Clone EESSI/software-layer-scripts repository + run: | + git clone https://github.com/EESSI/software-layer-scripts + - name: Show host system info run: | echo "/proc/cpuinfo:" @@ -70,7 +74,7 @@ jobs: cvmfs_http_proxy: DIRECT cvmfs_repositories: software.eessi.io - - name: Test check_missing_installations.sh script + - name: Check for missing installlations run: | export EESSI_SOFTWARE_SUBDIR_OVERRIDE=${{matrix.EESSI_SOFTWARE_SUBDIR_OVERRIDE}} source /cvmfs/software.eessi.io/versions/${EESSI_VERSION}/init/bash @@ -90,7 +94,7 @@ jobs: module load EasyBuild/${eb_version} which eb eb --version - ./check_missing_installations.sh ${easystack_file} + software-layer-scripts/check_missing_installations.sh ${easystack_file} ec=$? if [[ ${ec} -ne 0 ]]; then echo "missing installations found for ${easystack_file}!" >&2; exit ${ec}; fi done @@ -110,7 +114,7 @@ jobs: module load EasyBuild/${eb_version} which eb eb --version - ./check_missing_installations.sh ${easystack_file} + software-layer-scripts/check_missing_installations.sh ${easystack_file} ec=$? if [[ ${ec} -ne 0 ]]; then echo "missing installations found for ${easystack_file}!" >&2; exit ${ec}; fi done @@ -145,35 +149,10 @@ jobs: # boolean logic), hence when the script exits 0 if no package was # missing it is interpreted as true, thus the test did not capture # the missing package - if ./check_missing_installations.sh ${easystack_file}; then + if software-layer-scripts/check_missing_installations.sh ${easystack_file}; then echo "did NOT capture missing package; test FAILED" exit 1 else echo "captured missing package; test PASSED" exit 0 fi - - - name: Check that EasyBuild hook is up to date - if: ${{ github.event_name == 'pull_request' }} - run: | - FILE="eb_hooks.py" - TEMP_FILE="$(mktemp)" - - # Fetch base branch - git fetch origin ${{ github.base_ref }} - - # Check if the hooks has changed in the PR - if git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -q "^$FILE$"; then - echo "Hooks changed in PR. Using PR version." - cp "$FILE" "$TEMP_FILE" - else - echo "File not changed in PR. Using default branch version." - git show origin/${{ github.base_ref }}:$FILE > "$TEMP_FILE" - fi - - # Compare the hooks to what is shipped in the repository - # (it is overkill, but harmless, to do this for every architecture) - export EESSI_SOFTWARE_SUBDIR_OVERRIDE=${{matrix.EESSI_SOFTWARE_SUBDIR_OVERRIDE}} - source /cvmfs/software.eessi.io/versions/${EESSI_VERSION}/init/bash - module load EESSI-extend - diff "$TEMP_FILE" "$EASYBUILD_HOOKS" From 55d72108331c693884ae8694a6abb3b86d9c6254 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Wed, 11 Jun 2025 19:01:28 +0200 Subject: [PATCH 4/4] fix typo in name of CI workflow --- .github/workflows/test_compare_stacks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_compare_stacks.yml b/.github/workflows/test_compare_stacks.yml index f57a70aa6c..6f73fb9873 100644 --- a/.github/workflows/test_compare_stacks.yml +++ b/.github/workflows/test_compare_stacks.yml @@ -1,5 +1,5 @@ # documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Check for discrepencies between software stacks in software.eessi.io +name: Check for discrepancies between software stacks in software.eessi.io on: push: branches: [ "*-software.eessi.io" ]