cookbooks/aws-parallelcluster-environment/spec/unit/resources/volume_spec.rb (294 lines of code) (raw):
require 'spec_helper'
describe 'volume:mount' do
for_all_oses do |platform, version|
context "on #{platform}#{version}" do
context "when not yet mounted" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['volume'])
runner.converge_dsl('aws-parallelcluster-environment') do
volume 'mount' do
shared_dir 'SHARED_DIR'
device 'DEVICE'
fstype 'FSTYPE'
options %w(option1 option2)
device_type :uuid
retries 100
retry_delay 200
action :mount
end
end
end
before do
stub_command("mount | grep ' /SHARED_DIR '").and_return(false)
end
it 'mounts volume' do
is_expected.to mount_volume('mount')
end
it 'creates shared directory' do
is_expected.to create_directory('/SHARED_DIR')
.with(owner: 'root')
.with(group: 'root')
.with(mode: '1777')
# .with(recursive: true) # even if we set recursive a true, the test fails
end
it 'mounts shared dir' do
is_expected.to mount_mount('mount /SHARED_DIR')
.with(mount_point: '/SHARED_DIR')
.with(device: 'DEVICE')
.with(fstype: 'FSTYPE')
.with(device_type: :uuid)
.with(dump: 0)
.with(pass: 0)
.with(options: %w(option1 option2))
.with(retries: 100)
.with(retry_delay: 200)
end
it 'does not enable shared dir' do
is_expected.not_to enable_mount('mount /SHARED_DIR')
end
it 'changes permissions' do
is_expected.to create_directory('/SHARED_DIR')
.with(path: '/SHARED_DIR')
.with(owner: 'root')
.with(group: 'root')
.with(mode: '1777')
end
end
context "when mounted and some properties are not set" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['volume'])
runner.converge_dsl('aws-parallelcluster-environment') do
volume 'mount' do
shared_dir '/SHARED_DIR'
device 'DEVICE'
fstype 'FSTYPE'
options %w(option1 option2)
action :mount
end
end
end
before do
stub_command("mount | grep ' /SHARED_DIR '").and_return(true)
end
it 'creates shared directory' do
is_expected.to create_directory('/SHARED_DIR')
.with(owner: 'root')
.with(group: 'root')
.with(mode: '1777')
# .with(recursive: true) # even if we set recursive a true, the test fails
end
it 'does not mount shared dir with default values' do
is_expected.not_to mount_mount('mount /SHARED_DIR')
end
it 'enables shared dir' do
is_expected.to enable_mount('enable /SHARED_DIR')
.with(mount_point: '/SHARED_DIR')
.with(device: 'DEVICE')
.with(fstype: 'FSTYPE')
.with(device_type: :device)
.with(dump: 0)
.with(pass: 0)
.with(options: %w(option1 option2))
.with(retries: 0)
.with(retry_delay: 2)
end
it 'changes permissions' do
is_expected.to create_directory('/SHARED_DIR')
.with(path: '/SHARED_DIR')
.with(owner: 'root')
.with(group: 'root')
.with(mode: '1777')
end
end
end
end
end
describe 'volume:unmount' do
for_all_oses do |platform, version|
context "on #{platform}#{version}" do
context "when not mounted" do
[true, false].each do |is_dir_empty|
context "when shared dir #{is_dir_empty ? 'is' : 'is not'} empty" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['volume'])
runner.converge_dsl('aws-parallelcluster-environment') do
volume 'unmount' do
shared_dir 'SHARED_DIR'
action :unmount
end
end
end
before do
stub_command("mount | grep ' /SHARED_DIR '").and_return(false)
allow(Dir).to receive(:exist?).with("/SHARED_DIR").and_return(true)
allow(Dir).to receive(:empty?).with("/SHARED_DIR").and_return(is_dir_empty)
end
it 'does not unmount volume' do
is_expected.not_to run_execute('unmount volume')
end
it 'checks active processes' do
is_expected.to check_active_processes_file_utils('check active processes on /SHARED_DIR')
.with(file: '/SHARED_DIR')
end
it "removes volume /SHARED_DIR from /etc/fstab" do
is_expected.to edit_delete_lines("remove volume /SHARED_DIR from /etc/fstab")
.with(path: "/etc/fstab")
.with(pattern: " /SHARED_DIR ")
end
it "deletes shared dir only if it exists and it is empty" do
if is_dir_empty
is_expected.to delete_directory('/SHARED_DIR')
.with(recursive: false)
else
is_expected.not_to delete_directory('/SHARED_DIR')
end
end
end
end
end
context "when mounted" do
[true, false].each do |is_dir_empty|
context "when shared dir #{is_dir_empty ? 'is' : 'is not'} empty" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['volume'])
runner.converge_dsl('aws-parallelcluster-environment') do
volume 'unmount' do
shared_dir '/SHARED_DIR'
action :unmount
end
end
end
before do
stub_command("mount | grep ' /SHARED_DIR '").and_return(true)
allow(Dir).to receive(:exist?).with("/SHARED_DIR").and_return(true)
allow(Dir).to receive(:empty?).with("/SHARED_DIR").and_return(is_dir_empty)
end
it 'checks active processes' do
is_expected.to check_active_processes_file_utils('check active processes on /SHARED_DIR')
.with(file: '/SHARED_DIR')
end
it 'unmounts volume' do
is_expected.to unmount_volume('unmount')
is_expected.to run_execute('unmount volume /SHARED_DIR')
.with(command: "umount -fl /SHARED_DIR")
end
it "removes volume /SHARED_DIR from /etc/fstab" do
is_expected.to edit_delete_lines("remove volume /SHARED_DIR from /etc/fstab")
.with(path: "/etc/fstab")
.with(pattern: " /SHARED_DIR ")
end
it "deletes shared dir only if it exists and it is empty" do
if is_dir_empty
is_expected.to delete_directory('/SHARED_DIR')
.with(recursive: false)
else
is_expected.not_to delete_directory('/SHARED_DIR')
end
end
end
end
end
end
end
end
describe 'volume:attach' do
for_all_oses do |platform, version|
context "on #{platform}#{version}" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['volume'])
allow_any_instance_of(Object).to receive(:cookbook_virtualenv_path).and_return('/cookbook_venv')
runner.converge_dsl('aws-parallelcluster-environment') do
volume 'attach' do
volume_id 'volumeid'
action :attach
end
end
end
it 'creates ruby block waiting for the volume' do
is_expected.to nothing_ruby_block('sleeping_for_volume_volumeid')
end
it 'waits for the block device to be ready to attach the volume' do
block = chef_run.find_resource('ruby_block', 'sleeping_for_volume_volumeid')
expect(block).to receive(:wait_for_block_dev).with('/dev/disk/by-ebs-volumeid/volumeid')
block.block.call
expect(block).to subscribe_to('execute[attach_volume_volumeid]').on(:run).immediately
end
it 'attaches the volume' do
is_expected.to attach_volume('attach')
is_expected.to run_execute('attach_volume_volumeid')
.with(command: "/cookbook_venv/bin/python /usr/local/sbin/manageVolume.py --volume-id volumeid --attach")
.with(creates: '/dev/disk/by-ebs-volumeid/volumeid')
end
end
end
end
describe 'volume:detach' do
for_all_oses do |platform, version|
context "on #{platform}#{version}" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['volume'])
allow_any_instance_of(Object).to receive(:cookbook_virtualenv_path).and_return('/cookbook_venv')
runner.converge_dsl('aws-parallelcluster-environment') do
volume 'detach' do
volume_id 'volumeid'
action :detach
end
end
end
it 'detaches the volume' do
is_expected.to detach_volume('detach')
is_expected.to run_execute('detach_volume_volumeid')
.with(command: "/cookbook_venv/bin/python /usr/local/sbin/manageVolume.py --volume-id volumeid --detach")
end
end
end
end
describe 'volume:export' do
for_all_oses do |platform, version|
context "on #{platform}#{version}" do
cached(:vpc_cidr_list) { 'vpc_cidr_list' }
cached(:chef_run) do
allow_any_instance_of(Object).to receive(:get_vpc_cidr_list).and_return(vpc_cidr_list)
runner = runner(platform: platform, version: version, step_into: ['volume'])
runner.converge_dsl('aws-parallelcluster-environment') do
volume 'export' do
shared_dir 'raid_shared_dir '
action :export
end
end
end
it 'exports volume' do
is_expected.to export_volume('export')
end
it 'exports shared dir' do
is_expected.to create_nfs_export("/raid_shared_dir")
.with(network: vpc_cidr_list)
.with(writeable: true)
.with(options: %w(no_root_squash))
end
end
end
end
describe 'volume:unexport' do
for_all_oses do |platform, version|
context "on #{platform}#{version}" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['volume'])
runner.converge_dsl('aws-parallelcluster-environment') do
volume 'unexport' do
shared_dir 'shared_dir '
action :unexport
end
end
end
it 'deletes shared dir from /etc/exports' do
is_expected.to edit_delete_lines("remove volume /shared_dir from /etc/exports")
.with(path: "/etc/exports")
.with(pattern: "^/shared_dir *")
end
it 'unexports volume' do
is_expected.to unexport_volume('unexport')
is_expected.to run_execute("unexport volume")
.with(command: "exportfs -ra")
end
end
end
end