Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

New feature: resizing existing swapfiles #55

Merged
merged 1 commit into from
May 4, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions lib/puppet/parser/functions/difference_within_margin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# When given an array of two numbers and a margin, returns true
# if the difference is less than the margin. Basically statistical
# range with a margin.
#
# @example Difference between 150 and 100 is 50, margin is 60. So true
# $within_margin = difference_within_margin([100,150],60)
#
# @example Difference between 150 and 100 is 50, margin is 40. So false
# $within_margin = difference_within_margin([100,150],40)
#
# @return [Boolean] whether the difference between two numbers is within in a margin
#
# @param num_a [Array] array of two numbers to compare
# @param num_b [Float] the margin to compare the two numbers
module Puppet::Parser::Functions
newfunction(:difference_within_margin, :type => :rvalue, :doc => <<-EOS
Get's the difference between two numbers, with a third argument as a margin

*Example:*

compare_with_margin(100,150,60)

Would result in:

true

compare_with_margin(100,150,40)

Would result in:

false

EOS
) do |arguments|

# Check that more than 2 arguments have been given ...
raise(Puppet::ParseError, "compare_with_margin(): Wrong number of arguments " +
"given (#{arguments.size} for 2)") unless arguments.size == 2

# Check that the first parameter is an array
unless arguments[0].is_a?(Array)
raise(Puppet::ParseError, 'difference_within_margin(): Requires array to work with')
end

# Check that the first parameter is an array
if arguments[0].empty?
raise(Puppet::ParseError, 'difference_within_margin(): arg[0] array cannot be empty')
end

arguments[0].collect! { |i| i.to_f }

difference = arguments[0].minmax[1].to_f - arguments[0].minmax[0].to_f

if difference < arguments[1].to_f
return true
else
return false
end
end
end

# vim: set ts=2 sw=2 et :
24 changes: 24 additions & 0 deletions manifests/files.pp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
$options = 'defaults',
$timeout = 300,
$cmd = 'dd',
$resize_existing = false,
$resize_margin = '50MB',
$resize_verbose = false,
)
{
# Parameter validation
Expand All @@ -49,6 +52,27 @@
validate_bool($add_mount)

if $ensure == 'present' {

if ($resize_existing and $::swapfile_sizes) {

if (is_hash($::swapfile_sizes)) {

if (has_key($::swapfile_sizes,$swapfile)) {
::swap_file::resize { $swapfile:
swapfile_path => $swapfile,
margin => $resize_margin,
expected_swapfile_size => $swapfilesize,
actual_swapfile_size => $::swapfile_sizes[$swapfile],
verbose => $resize_verbose,
before => Exec["Create swap file ${swapfile}"],
}
}

} else {
fail('$resize_existing was set to true and stringify_facts was not false. This currently does not work, but will in the future. See https://github.com/petems/petems-swap_file/issues/57')
}
}

exec { "Create swap file ${swapfile}":
creates => $swapfile,
timeout => $timeout,
Expand Down
51 changes: 51 additions & 0 deletions manifests/resize.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# A defined type to resize an existing swapfile
#
# @example
# ::swap_file::resize { '/mnt/swap.1:
# swapfile_path => '/mnt/swap.1',
# margin => '500 MB',
# expected_swapfile_size => '1 GB,
# }
#
# @param [String] swapfile_path Path to the swapfile
# @param [String] expected_swapfile_size Expected size of the swapfile
# @param [String] actual_swapfile_size Actual size of the swapfile
# @param [String] margin Margin that is checked before resizing the swapfile
# @param [Boolean] verbose Adds a notify to explain why the change was made
#
# @author - Peter Souter
#
define swap_file::resize (
$swapfile_path,
$expected_swapfile_size,
$actual_swapfile_size,
$margin = '50MB',
$verbose = false,
)
{
$margin_bytes = to_bytes($margin)
$existing_swapfile_bytes = to_bytes("${actual_swapfile_size}kb")
$expected_swapfile_size_bytes = to_bytes($expected_swapfile_size)

if !($expected_swapfile_size_bytes == $existing_swapfile_bytes) {
if !(difference_within_margin([$existing_swapfile_bytes, $expected_swapfile_size_bytes],$margin_bytes)) {
if ($verbose) {
$alert_message = "Existing : ${existing_swapfile_bytes}B\nExpected: ${expected_swapfile_size_bytes}B\nMargin: ${margin_bytes}B"
notify{"Resizing Swapfile Alert ${swapfile_path}":
name => $alert_message,
}
}
exec { "Detach swap file ${swapfile_path} for resize":
command => "/sbin/swapoff ${swapfile_path}",
onlyif => "/sbin/swapon -s | grep ${swapfile_path}",
}
->
exec { "Purge ${swapfile_path} for resize":
command => "/bin/rm -f ${swapfile_path}",
onlyif => "test -f ${swapfile_path}",
path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/' ],
}
}
}

}
50 changes: 50 additions & 0 deletions spec/acceptance/swap_file_resizing_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'spec_helper_acceptance'

describe 'swap_file class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do

context 'disable stringify_facts' do
shell('puppet config set stringify_facts false --section=agent', { :acceptable_exit_codes => [0,1] })
shell('puppet config set stringify_facts false', { :acceptable_exit_codes => [0,1] })
end

context 'swap_file' do
context 'swapfilesize => 100' do
it 'should work with no errors' do
pp = <<-EOS
swap_file::files { 'default':
ensure => present,
swapfilesize => '100MB',
resize_existing => true,
}
EOS

# Run it twice and test for idempotency
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
it 'should contain the given swapfile with the correct size (102396/100MB)' do
shell('/sbin/swapon -s | grep /mnt/swap.1', :acceptable_exit_codes => [0])
shell('/bin/cat /proc/swaps | grep 102396', :acceptable_exit_codes => [0])
end
end
context 'resize swap file' do
it 'should work with no errors' do
pp = <<-EOS
swap_file::files { 'default':
ensure => present,
swapfilesize => '200MB',
resize_existing => true,
}
EOS

# Run it twice and test for idempotency
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
it 'should contain the given swapfile with the resized size (204796kb/200MB)' do
shell('/sbin/swapon -s | grep /mnt/swap.1', :acceptable_exit_codes => [0])
shell('/bin/cat /proc/swaps | grep 204796', :acceptable_exit_codes => [0])
end
end
end
end
48 changes: 48 additions & 0 deletions spec/acceptance/swap_file_resizing_stringify_true_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require 'spec_helper_acceptance'

describe 'swap_file class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do

context 'disable stringify_facts' do
shell('puppet config set stringify_facts true --section=agent', { :acceptable_exit_codes => [0,1] })
shell('puppet config set stringify_facts true', { :acceptable_exit_codes => [0,1] })
end

context 'swap_file' do
context 'swapfilesize => 100' do
it 'should work with no errors' do
pp = <<-EOS
swap_file::files { 'default':
ensure => present,
swapfilesize => '100MB',
resize_existing => true,
}
EOS

# Run it twice and test for idempotency
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
it 'should contain the given swapfile with the correct size (102396/100MB)' do
shell('/sbin/swapon -s | grep /mnt/swap.1', :acceptable_exit_codes => [0])
shell('/bin/cat /proc/swaps | grep 102396', :acceptable_exit_codes => [0])
end
end
context 'resize swap file' do
it 'errors out if stringify_facts is true and resize_existing is true' do
pp = <<-EOS
swap_file::files { 'default':
ensure => present,
swapfilesize => '100MB',
resize_existing => true,
}
EOS

# Run it twice and test for idempotency
apply_manifest(pp, :expect_failures => true) do |r|
expect(r.stderr).to match(/stringify_facts was true/)
end
end
end
end

end
Loading