cookbooks/aws-parallelcluster-environment/spec/unit/resources/efa_spec.rb (198 lines of code) (raw):

require 'spec_helper' # parallelcluster default source dir defined in attributes source_dir = '/opt/parallelcluster/sources' efa_version = '1.38.1' efa_checksum = '83923374afd388b1cfcf4b3a21a2b1ba7cf46a01a587f7b519b8386cb95e4f81' class ConvergeEfa def self.setup(chef_run, efa_version: nil, efa_checksum: nil) chef_run.converge_dsl('aws-parallelcluster-environment') do efa 'setup' do efa_version efa_version efa_checksum efa_checksum action :setup end end end # Converge efa:configure def self.configure(chef_run) chef_run.converge_dsl('aws-parallelcluster-environment') do efa 'configure' do action :configure end end end end describe 'efa:property' do cached(:old_efa_version) { 'old_efa_version' } cached(:old_efa_checksum) { 'old_efa_checksum' } cached(:chef_run) do ChefSpec::SoloRunner.new(step_into: ['efa']) do |node| node.override['cluster']['efa']['version'] = old_efa_version node.override['cluster']['efa']['sha256'] = old_efa_checksum end end context 'when efa version and checksum property is overriden' do cached(:resource) do ConvergeEfa.setup(chef_run, efa_version: old_efa_version, efa_checksum: old_efa_checksum) chef_run.find_resource('efa', 'setup') end it 'takes the value from efa property' do expect(resource.efa_version).to eq(old_efa_version) expect(resource.efa_checksum).to eq(old_efa_checksum) end end end describe 'efa:setup' do for_all_oses do |platform, version| context "on #{platform}#{version}" do cached(:prerequisites) do if %(redhat rocky).include?(platform) || platform == 'amazon' && version == '2023' %w(environment-modules libibverbs-utils librdmacm-utils rdma-core-devel) elsif platform == 'amazon' && version == '2' %w(environment-modules libibverbs-utils librdmacm-utils) else "environment-modules" end end let(:chef_run) do runner(platform: platform, version: version, step_into: ['efa']) do |node| if platform == 'redhat'; node.automatic['platform_version'] = "8.7" end node.override['cluster']['efa']['version'] = efa_version node.override['cluster']['efa']['sha256'] = efa_checksum node.override['cluster']['sources_dir'] = source_dir end end context 'when efa installed' do before do stubs_for_provider('efa') do |resource| allow(resource).to receive(:efa_installed?).and_return(true) end end context 'and installer tarball does not exist' do before do mock_file_exists("#{source_dir}/aws-efa-installer.tar.gz", false) ConvergeEfa.setup(chef_run) end it 'exits with warning' do is_expected.to write_log('efa installed') .with(message: 'Existing EFA version differs from the one shipped with ParallelCluster. Skipping ParallelCluster EFA installation and configuration.') .with(level: :warn) end end context 'and installer tarball exists' do before do mock_file_exists("#{source_dir}/aws-efa-installer.tar.gz", true) ConvergeEfa.setup(chef_run) end it 'installs EFA' do is_expected.not_to write_log('efa installed') is_expected.not_to remove_package(%w(openmpi-devel openmpi)) is_expected.to update_package_repos('update package repos') is_expected.to install_package(prerequisites) is_expected.to create_if_missing_remote_file("#{source_dir}/aws-efa-installer.tar.gz") is_expected.not_to run_bash('install efa') end end end context 'when efa not installed' do before do stubs_for_provider('efa') do |resource| allow(resource).to receive(:efa_installed?).and_return(false) end end context 'when efa supported' do before do allow_any_instance_of(Object).to receive(:arm_instance?).and_return(false) ConvergeEfa.setup(chef_run) end it 'installs EFA without skipping kmod' do is_expected.to create_directory(source_dir) is_expected.to setup_efa('setup') is_expected.not_to write_log('efa installed') is_expected.to remove_package(platform == 'ubuntu' ? ['libopenmpi-dev'] : %w(openmpi-devel openmpi)) is_expected.to update_package_repos('update package repos') is_expected.to install_package(prerequisites) is_expected.to create_if_missing_remote_file("#{source_dir}/aws-efa-installer.tar.gz") .with(source: "https://efa-installer.amazonaws.com/aws-efa-installer-#{efa_version}.tar.gz") .with(mode: '0644') .with(retries: 3) .with(retry_delay: 5) .with(checksum: efa_checksum) is_expected.to run_bash('install efa') .with(code: %( set -e tar -xzf #{source_dir}/aws-efa-installer.tar.gz cd aws-efa-installer ./efa_installer.sh -y rm -rf #{source_dir}/aws-efa-installer )) end end end end end context 'when rhel version is older than 8.4' do cached(:chef_run) do runner = ChefSpec::Runner.new( # Create a runner for the given platform/version platform: "redhat", step_into: ['efa'] ) do |node| node.automatic['platform_version'] = "8.3" end ConvergeEfa.setup(runner) end it "logs EFA not supported message" do is_expected.to write_log('EFA is not supported in this RHEL version 8.3, supported versions are >= 8.4').with_level(:warn) end it "doesn't install EFA kmod" do is_expected.to run_bash('install efa').with_code(%r{./efa_installer.sh -y -k}) end end end describe 'efa:configure' do for_all_oses do |platform, version| context "on #{platform}#{version}" do let(:chef_run) do runner(platform: platform, version: version, step_into: ['efa']) end if %w(amazon centos redhat rocky).include?(platform) it 'does nothing' do ConvergeEfa.configure(chef_run) is_expected.to configure_efa('configure') is_expected.to write_node_attributes('dump node attributes') is_expected.not_to apply_sysctl('kernel.yama.ptrace_scope') end elsif platform == 'ubuntu' context 'when efa enabled on compute node' do before do chef_run.node.override['cluster']['enable_efa'] = 'efa' chef_run.node.override['cluster']['node_type'] = 'ComputeFleet' ConvergeEfa.configure(chef_run) end it 'disables ptrace protection on compute nodes' do is_expected.to apply_sysctl('kernel.yama.ptrace_scope').with(value: "0") end end context 'when efa not enabled on compute node' do before do chef_run.node.override['cluster']['enable_efa'] = 'other' chef_run.node.override['cluster']['node_type'] = 'ComputeFleet' ConvergeEfa.configure(chef_run) end it 'does not disable ptrace protection' do is_expected.not_to apply_sysctl('kernel.yama.ptrace_scope') end end context 'when it is not a compute node' do before do chef_run.node.override['cluster']['enable_efa'] = 'efa' chef_run.node.override['cluster']['node_type'] = 'other' ConvergeEfa.configure(chef_run) end it 'does not disable ptrace protection' do is_expected.not_to apply_sysctl('kernel.yama.ptrace_scope') end end else pending "Implement for #{platform}" end end end end