Sync puppet module lvm to v0.3.1 from upstream

v0.3.1 sha1: 71486f47598a397ee5c8e68b3cddc10dce86d0c4
Implements: blueprint merge-openstack-puppet-modules

Change-Id: Ic050594a2aae82076a321c6298cc5e7f541d4884
This commit is contained in:
Stanislaw Bogatkin 2014-06-24 14:58:00 +04:00
parent 8ec900a2bc
commit 29be2f2e4d
45 changed files with 1665 additions and 519 deletions

View File

@ -0,0 +1,53 @@
Autotest.add_hook :initialize do |at|
at.clear_mappings
# watch out: Ruby bug (1.8.6):
# %r(/) != /\//
at.add_mapping(%r%^spec/.*\.rb$%) { |filename, _|
filename
}
at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m|
["spec/#{m[1]}_spec.rb"]
}
at.add_mapping(%r%^spec/(spec_helper|shared/.*)\.rb$%) {
at.files_matching %r{^spec/.*_spec\.rb$}
}
# the libraries under lib/puppet
at.add_mapping(%r%^lib/(.*)\.rb$%) { |filename, m|
at.files_matching %r!spec/(unit|integration)/#{m[1]}.rb!
}
# the actual spec files themselves
at.add_mapping(%r%^spec/(unit|integration)/.*\.rb$%) { |filename, _|
filename
}
# force a complete re-run for all of these:
# main puppet lib
at.add_mapping(%r!^lib/puppet\.rb$!) { |filename, _|
at.files_matching %r!spec/(unit|integration)/.*\.rb!
}
# the spec_helper
at.add_mapping(%r!^spec/spec_helper\.rb$!) { |filename, _|
at.files_matching %r!spec/(unit|integration)/.*\.rb!
}
# the puppet test libraries
at.add_mapping(%r!^test/lib/puppettest/.*!) { |filename, _|
at.files_matching %r!spec/(unit|integration)/.*\.rb!
}
# the puppet spec libraries
at.add_mapping(%r!^spec/lib/spec.*!) { |filename, _|
at.files_matching %r!spec/(unit|integration)/.*\.rb!
}
# the monkey patches for rspec
at.add_mapping(%r!^spec/lib/monkey_patches/.*!) { |filename, _|
at.files_matching %r!spec/(unit|integration)/.*\.rb!
}
end

View File

@ -0,0 +1,5 @@
fixtures:
repositories:
"stdlib": "https://github.com/puppetlabs/puppetlabs-stdlib.git"
symlinks:
"lvm": "#{source_dir}"

View File

@ -1,5 +1,3 @@
*.swp
pkg/
.DS_Store
metadata.json
coverage/
.*.swp
Gemfile.lock

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>lvm</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.cloudsmith.geppetto.pp.dsl.ui.modulefileBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.cloudsmith.geppetto.pp.dsl.ui.puppetNature</nature>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,4 @@
--format
s
--color

View File

@ -0,0 +1,32 @@
---
branches:
only:
- master
language: ruby
bundler_args: --without development
script: 'bundle exec rake validate && bundle exec rake lint && SPEC_OPTS="--format documentation" bundle exec rake spec'
rvm:
- 1.8.7
- 1.9.3
- 2.0.0
env:
matrix:
- PUPPET_GEM_VERSION="~> 2.7.0"
- PUPPET_GEM_VERSION="~> 3.1.0"
- PUPPET_GEM_VERSION="~> 3.2.0"
- PUPPET_GEM_VERSION="~> 3.3.0"
- PUPPET_GEM_VERSION="~> 3.4.0"
global:
matrix:
fast_finish: true
exclude:
- rvm: 1.9.3
env: PUPPET_GEM_VERSION="~> 2.7.0"
- rvm: 2.0.0
env: PUPPET_GEM_VERSION="~> 2.7.0"
- rvm: 2.0.0
env: PUPPET_GEM_VERSION="~> 3.1.0"
- rvm: 1.8.7
env: PUPPET_GEM_VERSION="~> 3.2.0"
notifications:
email: false

View File

@ -0,0 +1,48 @@
2014-04-11 - Version 0.3.1
Summary:
This release simply adds metadata consumed by the forge for displaying
operating system compatibility. No other changes.
2014-04-10 - Version 0.3.0
Summary:
This release features a new base lvm class, and set of defines, that allows you
to express your volume groups through a `volume_groups` parameter. This makes
it easier to hiera backend your LVM configuration.
More information about this feature can be found in the README file.
2014-02-04 - Version 0.2.0
Summary:
It's been a long time since the previous release and the LVM module has seen a
lot of community development. It now supports AIX, thanks to Craig Dunn, and
grew an enormous number of facts, properties, and parameters. There's a
fistful of bugfixes too which should help RHEL5 users.
Features:
- A new `lvm_support` fact was added.
- A new `lvm_vgs` fact was added.
- A new `lvm_pvs` fact was added.
- Dynamic facts were added for lvm_vg_N and lvm_pv_N.
- Support for lvcreate -l argument (extents)
- Added AIX providers for logical_volume and filesystem types.
- Use ensure_resources to handle multiple physical_volume in a volume_group.
- Add XFS online resizing support.
- Add `initial_size` property.
- Add `extents` property.
- Add `stripes` property.
- Add `stripsize` property.
- Huge number of parameters were added, most AIX only.
Bugfixes:
- Fix messages with new_size variables in logical_volume/lvm.rb
- size 'undef' doesn't work when creating a new logical volume
- resize2fs isn't called during resizing on ruby>1.
- Allow for physical_volumes and volume_groups that change as system lives.
- On RHEL 5 family systems ext4 filesystems can not be resized using resize2fs.
- Suppress facter warnings on systems that don't support LVM.

View File

@ -0,0 +1,17 @@
source "https://rubygems.org"
group :development, :test do
gem 'rake'
gem 'rspec', "~> 2.11.0", :require => false
gem 'mocha', "~> 0.10.5", :require => false
gem 'puppetlabs_spec_helper', :require => false
end
if puppetversion = ENV['PUPPET_GEM_VERSION']
gem 'puppet', puppetversion, :require => false
else
gem 'puppet', :require => false
end
gem 'puppet-lint', '>= 0.3.2'
# vim:ft=ruby

View File

@ -1,5 +1,6 @@
name 'puppetlabs-lvm'
version '0.1.0'
version '0.3.1'
license 'GPLv2'
summary 'Puppet types and providers to manage LVM'
project_page 'https://github.com/puppetlabs/puppet-lvm'
project_page 'https://github.com/puppetlabs/puppetlabs-lvm'
dependency 'puppetlabs/stdlib', '4.1.x'

View File

@ -5,6 +5,10 @@ Provides Logical Resource Management (LVM) features for Puppet.
History
-------
2012-08-14 : rcoleman
* Version 0.1.1 : More style-guide compliant, fixed a closing } bug and updated README
2011-08-30 : matthaus
* Version 0.1.0 : Refactor tests, update readme, repackage for module forge
@ -37,35 +41,96 @@ looks something like:
Here's a simple working example:
physical_volume { "/dev/hdc":
ensure => present
}
volume_group { "myvg":
ensure => present,
physical_volumes => "/dev/hdc"
}
logical_volume { "mylv":
ensure => present,
volume_group => "myvg",
size => "20G"
}
filesystem { "/dev/myvg/mylv":
ensure => present,
fs_type => "ext3",
options => '-b 4096 -E stride=32,stripe-width=64'
}
```puppet
physical_volume { '/dev/hdc':
ensure => present,
}
volume_group { 'myvg':
ensure => present,
physical_volumes => '/dev/hdc',
}
logical_volume { 'mylv':
ensure => present,
volume_group => 'myvg',
size => '20G',
}
filesystem { '/dev/myvg/mylv':
ensure => present,
fs_type => 'ext3',
options => '-b 4096 -E stride=32,stripe-width=64',
}
```
This simple 1 physical volume, 1 volume group, 1 logical volume case
is provided as a simple `volume` definition, as well. The above could
be shortened to be:
lvm::volume { 'mylv':
ensure => present,
vg => 'myvg',
pv => '/dev/hdc',
fstype => 'ext3',
size => '20G',
}
```puppet
lvm::volume { 'mylv':
ensure => present,
vg => 'myvg',
pv => '/dev/hdc',
fstype => 'ext3',
size => '20G',
}
```
You can also describe your Volume Group like this:
```puppet
class { 'lvm':
volume_groups => {
'myvg' => {
physical_volumes => [ '/dev/sda2', '/dev/sda3', ],
logical_volumes => {
'opt' => {'size' => '20G'},
'tmp' => {'size' => '1G' },
'usr' => {'size' => '3G' },
'var' => {'size' => '15G'},
'home' => {'size' => '5G' },
'backup' => {
'size' => '5G',
'mountpath' => '/var/backups',
'mountpath_require' => true,
},
},
},
},
}
```
This could be really convenient when used with hiera:
```puppet
include ::lvm
```
and
```
---
lvm::volume_groups:
myvg:
physical_volumes:
- /dev/sda2
- /dev/sda3
logical_volumes:
opt:
size: 20G
tmp:
size: 1G
usr:
size: 3G
var:
size: 15G
home:
size: 5G
backup:
size: 5G
mountpath: /var/backups
mountpath_require: true
```
Except that in the latter case you cannot specify create options.
=======
@ -77,6 +142,26 @@ need to use a hash to pass the parameters to the definition.
If you need a more complex configuration, you'll need to build the
resources out yourself.
Optional Values
---------------
The `unless_vg` (physical_volume) and `createonly` (volume_group) will check
to see if "myvg" exists. If "myvg" does exist then they will not modify
the physical volume or volume_group. This is usefull if you environment
is build with certain disks but they change while the server grows, shrinks
or moves.
Example:
physical_volume { "/dev/hdc":
ensure => present,
unless_vg => "myvg"
}
volume_group { "myvg":
ensure => present,
physical_volumes => "/dev/hdc",
createonly => true
}
Limitations
-----------
@ -120,8 +205,20 @@ Tim Hawes <github@reductivelabs.com>
Yury V. Zaytsev <yury@shurup.com>
csschwe <github@reductivelabs.com>
root <root@localhost.localdomain>
csschwe <csschwe@gmail.com>
windowsrefund <windowsrefund@gmail.com>
Adam Gibbins <github@adamgibbins.com>
Steffen Zieger <github@saz.sh>
Jason A. Smith <smithj4@bnl.gov>
Mathieu Bornoz <mathieu.bornoz@camptocamp.com>
Cédric Jeanneret <cedric.jeanneret@camptocamp.com>
Raphaël Pinson <raphael.pinson@camptocamp.com>
Garrett Honeycutt <code@garretthoneycutt.com>

View File

@ -0,0 +1,12 @@
require 'rubygems'
require 'puppetlabs_spec_helper/rake_tasks'
require 'puppet-lint/tasks/puppet-lint'
PuppetLint.configuration.send('disable_80chars')
PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]
desc "Run puppet in noop mode and check for syntax errors."
task :validate do
Dir['manifests/**/*.pp'].each do |path|
sh "puppet parser validate --noop #{path}"
end
end

View File

@ -0,0 +1,50 @@
# lvm_support: true/nil
# Whether there is LVM support (based on the presence of the "vgs" command)
Facter.add('lvm_support') do
confine :kernel => :linux
setcode do
vgdisplay = Facter::Util::Resolution.which('vgs')
vgdisplay.nil? ? nil : true
end
end
# lvm_vgs: [0-9]+
# Number of VGs
vg_list = []
Facter.add('lvm_vgs') do
confine :lvm_support => true
vgs = Facter::Util::Resolution.exec('vgs -o name --noheadings 2>/dev/null')
if vgs.nil?
setcode { 0 }
else
vg_list = vgs.split
setcode { vg_list.length }
end
end
# lvm_vg_[0-9]+
# VG name by index
vg_list.each_with_index do |vg, i|
Facter.add("lvm_vg_#{i}") { setcode { vg } }
end
# lvm_pvs: [0-9]+
# Number of PVs
pv_list = []
Facter.add('lvm_pvs') do
confine :lvm_support => true
pvs = Facter::Util::Resolution.exec('pvs -o name --noheadings 2>/dev/null')
if pvs.nil?
setcode { 0 }
else
pv_list = pvs.split
setcode { pv_list.length }
end
end
# lvm_pv_[0-9]+
# PV name by index
pv_list.each_with_index do |pv, i|
Facter.add("lvm_pv_#{i}") { setcode { pv } }
end

View File

@ -0,0 +1,169 @@
require 'open3'
Puppet::Type.type(:filesystem).provide :aix do
desc "Manages logical volume filesystems on AIX"
confine :operatingsystem => :AIX
defaultfor :operatingsystem => :AIX
commands :crfs => 'crfs',
:chfs => 'chfs'
def exists?
Open3.popen3("lsfs #{@resource[:name]}")[3].value.success?
end
def create
args = []
attributes=[
:ag_size,
:large_files,
:compress,
:frag,
:nbpi,
:logname,
:size,
:initial_size,
:encrypted,
:isnapshot,
:logsize,
:maxext,
:mountguard,
:agblksize,
:extended_attributes,
:mount_options,
:vix
]
args.push(*add_attributes(*attributes))
args.push(*add_flag(:v, :fs_type))
args.push(*add_flag(:m, :name))
args.push(*add_flag(:d, :device))
args.push(*add_flag(:l, :log_partitions))
args.push(*add_flag(:g, :volume_group))
args.push(*add_flag(:A, :atboot))
args.push(*add_flag(:p, :perms))
crfs(*args)
# crfs on AIX will ignore -a size if the logical_volume already
# has a size and is specified as -d. So to be sure we sync the
# size property after creation
if @resource[:size]
if size != @resource[:size]
self.size= (@resource[:size])
end
end
end
def attribute_flag(pvalue)
{
:ag_size => 'ag',
:large_file => 'bf',
:initial_size => 'size',
:size => 'size',
:extended_attributes => 'ea',
:mount_options => 'options',
:encrypted => 'efs'
}[pvalue] || pvalue.to_s
end
def add_attributes(*args)
attr_args=[]
args.each do |arg|
if @resource[arg]
ans=parse_boolean(@resource[arg])
attr_args.push('-a', "#{attribute_flag(arg)}=#{@resource[arg]}")
end
end
attr_args
end
def add_flag(flag,param)
if @resource[param]
[ "-#{flag.to_s}", "#{parse_boolean(@resource[param])}" ]
end
end
def parse_boolean(param)
case param
when :true
'yes'
when :false
'no'
else
param
end
end
def size
cursize=0
reqsize=blk_roundup(val_to_blk(@resource[:size]))
Open3.popen3("lsfs -q #{@resource[:name]}") do |stdin, stdout, stderr|
stdout.each do |line|
elements=line.split(/\s+/)
if elements[2] == @resource[:name]
cursize=elements[4].to_i
end
end
end
if cursize == reqsize
@resource[:size]
else
blk_to_val(cursize,@resource[:size][-1,1])
end
end
def size=(newsize)
chfs('-a',"size=#{@resource[:size]}", @resource[:name])
end
def val_to_blk(val)
input = val.match(/(\d+)([^0-9]|)/).to_a
case input[2]
when 'M'
input[1].to_i*1024*2
when 'G'
input[1].to_i*1024*1024*2
else
input[1].to_i
end
end
def blk_to_val(blocks,units=nil)
case units
when 'M'
sprintf('%gM', Float(blocks.to_i/2/1024))
when 'G'
sprintf('%gM', Float(blocks.to_i/2/1024/1024))
else
blocks
end
end
def blk_roundup(blocks)
ppsize=Integer(pp_size*1024*2)
ppsize*Float(Float(blocks)/ppsize).ceil.to_i
end
def pp_size
vg = @resource[:volume_group] || 'rootvg'
Open3.capture2("lsvg #{vg} | /bin/grep 'PP SIZE'")[0].split(/\s+/)[5].to_i
end
def attribute_flag(pvalue)
{
:ag_size => 'ag',
:large_file => 'bf',
:initial_size => 'size',
:size => 'size',
:extended_attributes => 'ea',
:mount_options => 'options',
:encrypted => 'efs'
}[pvalue] || pvalue.to_s
end
end

View File

@ -1,7 +1,7 @@
Puppet::Type.type(:filesystem).provide :lvm do
desc "Manages filesystem of a logical volume"
commands :mount => 'mount'
commands :blkid => 'blkid'
def create
mkfs(@resource[:fs_type])
@ -16,7 +16,7 @@ Puppet::Type.type(:filesystem).provide :lvm do
end
def fstype
mount('-f', '--guess-fstype', @resource[:name]).strip
/TYPE=\"(\S+)\"/.match(blkid(@resource[:name]))[1]
rescue Puppet::ExecutionFailure
nil
end

View File

@ -0,0 +1,36 @@
require 'open3'
Puppet::Type.type(:logical_volume).provide :aix do
desc "Manages LVM logical volumes on AIX"
defaultfor :operatingsystem => :AIX
confine :operatingsystem => :AIX
commands :mklv => 'mklv'
def create
# Dont use auto-generated LG names as we need to know what resource
# we are managing
args = ['-y', @resource[:name]]
if @resource[:range]
args << '-e'
case @resource[:range]
when 'maximum'
args << 'x'
when 'minimum'
args << 'm'
end
end
if @resource[:type]
args.push('-t', @resource[:type])
end
args.push(@resource[:volume_group], @resource[:initial_size])
mklv(*args)
end
def exists?
Open3.popen3("lslv #{@resource[:name]}")[3].value.success?
end
end

View File

@ -1,14 +1,17 @@
Puppet::Type.type(:logical_volume).provide :lvm do
desc "Manages LVM logical volumes"
commands :lvcreate => 'lvcreate',
:lvremove => 'lvremove',
:lvextend => 'lvextend',
:lvs => 'lvs',
:resize2fs => 'resize2fs',
:umount => 'umount',
:mount => 'mount',
:dmsetup => 'dmsetup'
commands :lvcreate => 'lvcreate',
:lvremove => 'lvremove',
:lvextend => 'lvextend',
:lvs => 'lvs',
:resize2fs => 'resize2fs',
:umount => 'umount',
:blkid => 'blkid',
:dmsetup => 'dmsetup'
optional_commands :xfs_growfs => 'xfs_growfs',
:resize4fs => 'resize4fs'
def create
args = ['-n', @resource[:name]]
@ -17,6 +20,22 @@ Puppet::Type.type(:logical_volume).provide :lvm do
elsif @resource[:initial_size]
args.push('--size', @resource[:initial_size])
end
if @resource[:extents]
args.push('--extents', @resource[:extents])
end
if !@resource[:extents] and !@resource[:size]
args.push('--extents', '100%FREE')
end
if @resource[:stripes]
args.push('--stripes', @resource[:stripes])
end
if @resource[:stripesize]
args.push('--stripesize', @resource[:stripesize])
end
args << @resource[:volume_group]
lvcreate(*args)
end
@ -72,7 +91,7 @@ Puppet::Type.type(:logical_volume).provide :lvm do
if lvm_size_units[current_size_unit] < lvm_size_units[new_size_unit]
resizeable = true
elsif lvm_size_units[current_size_unit] > lvm_size_units[new_size_unit]
if (current_size_bytes / lvm_size_units[current_size_unit]) < (new_size_bytes / lvm_size_units[new_size_unit])
if (current_size_bytes * lvm_size_units[current_size_unit]) < (new_size_bytes * lvm_size_units[new_size_unit])
resizeable = true
end
elsif lvm_size_units[current_size_unit] == lvm_size_units[new_size_unit]
@ -82,17 +101,22 @@ Puppet::Type.type(:logical_volume).provide :lvm do
end
if not resizeable
fail( "Decreasing the size requires manual intervention (#{size} < #{current_size})" )
fail( "Decreasing the size requires manual intervention (#{new_size} < #{current_size})" )
else
## Check if new size fits the extend blocks
if new_size_bytes * lvm_size_units[new_size_unit] % vg_extent_size != 0
fail( "Cannot extend to size #{size} because VG extent size is #{vg_extent_size} KB" )
fail( "Cannot extend to size #{new_size} because VG extent size is #{vg_extent_size} KB" )
end
lvextend( '-L', new_size, path) || fail( "Cannot extend to size #{size} because lvextend failed." )
lvextend( '-L', new_size, path) || fail( "Cannot extend to size #{new_size} because lvextend failed." )
if mount( '-f', '--guess-fstype', path) =~ /ext[34]/
resize2fs( path) || fail( "Cannot resize file system to size #{size} because resize2fs failed." )
blkid_type = blkid(path)
if command(:resize4fs) and blkid_type =~ /\bTYPE=\"(ext4)\"/
resize4fs( path) || fail( "Cannot resize file system to size #{new_size} because resize2fs failed." )
elsif blkid_type =~ /\bTYPE=\"(ext[34])\"/
resize2fs( path) || fail( "Cannot resize file system to size #{new_size} because resize2fs failed." )
elsif blkid_type =~ /\bTYPE=\"(xfs)\"/
xfs_growfs( path) || fail( "Cannot resize filesystem to size #{new_size} because xfs_growfs failed." )
end
end

View File

@ -1,7 +1,7 @@
Puppet::Type.type(:physical_volume).provide(:lvm) do
desc "Manages LVM physical volumes"
commands :pvcreate => 'pvcreate', :pvremove => 'pvremove', :pvs => 'pvs'
commands :pvcreate => 'pvcreate', :pvremove => 'pvremove', :pvs => 'pvs', :vgs => 'vgs'
def create
pvcreate(@resource[:name])
@ -12,9 +12,30 @@ Puppet::Type.type(:physical_volume).provide(:lvm) do
end
def exists?
pvs(@resource[:name])
rescue Puppet::ExecutionFailure
false
# If unless_vg is set we need to see if
# the volume group exists
if @resource[:unless_vg]
begin
# Check to see if the volume group exists
# if it does set TRUE else FALSE
vgs(@resource[:unless_vg])
vg_exists = true
rescue Puppet::ExecutionFailure
vg_exists = false
end
end
# If vg exists FALSE
if ! vg_exists
begin
# Check to see if the PV already exists
pvs(@resource[:name])
rescue Puppet::ExecutionFailure
false
end
else
# If the VG exists return true
true
end
end
end

View File

@ -23,22 +23,28 @@ Puppet::Type.type(:volume_group).provide :lvm do
end
def physical_volumes=(new_volumes = [])
existing_volumes = physical_volumes
extraneous = existing_volumes - new_volumes
extraneous.each { |volume| reduce_with(volume) }
missing = new_volumes - existing_volumes
missing.each { |volume| extend_with(volume) }
# Only take action if createonly is false just to be safe
# this is really only here to enforce the createonly setting
# if something goes wrong in physical_volumes
if @resource[:createonly].to_s == "false"
existing_volumes = physical_volumes
extraneous = existing_volumes - new_volumes
extraneous.each { |volume| reduce_with(volume) }
missing = new_volumes - existing_volumes
missing.each { |volume| extend_with(volume) }
end
end
def physical_volumes
lines = pvs('-o', 'pv_name,vg_name', '--separator', ',')
lines.inject([]) do |memo, line|
pv, vg = line.split(',').map { |s| s.strip }
if vg == @resource[:name]
memo << pv
else
memo
end
if @resource[:createonly].to_s == "false" || ! vgs(@resource[:name])
lines = pvs('-o', 'pv_name,vg_name', '--separator', ',')
lines.split(/\n/).grep(/,#{@resource[:name]}$/).map { |s|
s.split(/,/)[0].strip
}
else
# Trick the check by setting the returned value to what is
# listed in the puppet catalog
@resource[:physical_volumes]
end
end

View File

@ -2,25 +2,147 @@ require 'pathname'
Puppet::Type.newtype(:filesystem) do
desc "The filesystem type"
desc "The filesystem type"
ensurable
ensurable
newparam(:fs_type) do
desc "The file system type. eg. ext3."
newparam(:fs_type) do
desc "The file system type. eg. ext3."
end
newparam(:name) do
isnamevar
validate do |value|
unless Pathname.new(value).absolute?
raise ArgumentError, "Filesystem names must be fully qualified"
end
end
end
newparam(:name) do
isnamevar
validate do |value|
unless Pathname.new(value).absolute?
raise ArgumentError, "Filesystem names must be fully qualified"
end
end
newparam(:options) do
desc "Params for the mkfs command. eg. -l internal,agcount=x"
end
newparam(:initial_size) do
desc "Initial size of the filesystem, Used only for resource creation, when using this option Puppet will not manage or maintain the size. To resize filesystems see the size property. AIX only."
end
newproperty(:size) do
desc "Configures the size of the filesystem. Supports filesystem resizing. The size will be rounded up to the nearest multiple of the partition size. AIX only."
end
newparam(:ag_size) do
desc "Specify the allocation group size in megabytes, AIX only."
newvalues(/\d+/)
end
newparam(:large_files) do
desc "Large file enabled file system. AIX only"
newvalues(:true, :false)
end
newparam(:compress) do
desc "Data compression, LZ or no. AIX only"
newvalues(:LG, :no)
end
newparam(:frag) do
desc "JFS fragment size in bytes. AIX only"
newvalues(/\d+/)
end
newparam(:nbpi) do
desc "Bytes per inode. AIX only"
newvalues(/\d+/)
end
newparam(:logname) do
desc "Configure the log logical volume. AIX only"
end
newparam(:logsize) do
desc "Size for an inline log in MB, AIX only"
newvalues(/\d+/)
end
newparam(:maxext) do
desc "Size of a file extent in file system blocks, AIX only"
newvalues(/\d+/)
end
newparam(:mountguard) do
desc "Enable the mountguard. AIX only"
newvalues(:true, :false)
end
newparam(:agblksize) do
desc "JFS2 block size in bytes, AIX only."
newvalues(/\d+/)
end
newparam(:extended_attributes) do
desc "Format to be used to store extended attributes. AIX only"
newvalues(:v1,:v2)
end
newparam(:encrypted) do
desc "Specify and encrypted filesystem. AIX only"
newvalues(:true,:false)
end
newparam(:isnapshot) do
desc "Specify whether the filesystem supports internal snapshots, AIX only"
newvalues(:true, :false)
end
newparam(:mount_options) do
desc "Specify the options to be passed to the mount command. AIX only"
end
newparam(:vix) do
desc "Specify that the file system can allocate inode extents smaller than the default, AIX only"
newvalues(:true, :false)
end
newparam(:log_partitions) do
desc "Specify the size of the log logical volume as number of logical partitions, AIX only"
end
newparam(:nodename) do
desc "Specify the remote host where the filesystem resides. AIX only"
end
newparam(:accounting) do
desc "Specify accounting subsystem support, AIX only"
newvalues(:true, :false)
end
newparam(:mountgroup) do
desc "Mount group for the filesystem, AIX only"
end
newparam(:atboot) do
desc "Specify whether the file system is mounted at boot time, AIX only"
newvalues(:true, :false)
end
newparam(:perms) do
desc "Permissions for the filesystem, AIX only"
newvalues(:ro, :rw)
end
newparam(:device) do
desc "Device to create the filesystem on, this can be a device or a logical volume. AIX only"
end
newparam(:volume_group) do
desc "Volume group that the file system should be greated on. AIX only."
end
autorequire(:logical_volume) do
if device = @parameters[:device]
device.value
else
@parameters[:name].value
end
newparam(:options) do
desc "Params for the mkfs command. eg. -l internal,agcount=x"
end
end
end

View File

@ -35,4 +35,48 @@ Puppet::Type.newtype(:logical_volume) do
end
end
end
newparam(:extents) do
desc "The number of logical extents to allocate for the new logical volume. Set to undef to use all available space"
validate do |value|
unless value =~ /^[0-9]+[%(vg|VG|pvs|PVS|free|FREE|origin|ORIGIN)]?/i
raise ArgumentError , "#{value} is not a valid logical volume extent"
end
end
end
newparam(:type) do
desc "Configures the logical volume type. AIX only"
end
newparam(:range) do
desc "Sets the inter-physical volume allocation policy. AIX only"
validate do |value|
unless ['maximum','minimum'].include?(value)
raise ArgumentError, "#{value} is not a valid range"
end
end
end
newparam(:stripes) do
desc "The number of stripes to allocate for the new logical volume."
validate do |value|
unless value =~ /^[0-9]+/i
raise ArgumentError , "#{value} is not a valid stripe count"
end
end
end
newparam(:stripesize) do
desc "The stripesize to use for the new logical volume."
validate do |value|
unless value =~ /^[0-9]+/i
raise ArgumentError , "#{value} is not a valid stripesize"
end
end
end
autorequire(:volume_group) do
@parameters[:volume_group].value
end
end

View File

@ -11,4 +11,13 @@ Puppet::Type.newtype(:physical_volume) do
end
end
end
newparam(:unless_vg) do
desc "Do not do anything if the VG already exists. The value should be the
name of the volume group to check for."
validate do |value|
unless value =~ /^[0-9A-Z]/i
raise ArgumentError , "#{value} is not a valid volume group name"
end
end
end
end

View File

@ -12,4 +12,13 @@ Puppet::Type.newtype(:volume_group) do
using the physical_volume resource type."
end
newparam(:createonly, :boolean => true) do
desc "If set to true the volume group will be created if it does not exist. If the
volume group does exist no action will be taken. Defaults to `false`."
newvalues(:true, :false)
aliasvalue(:yes, :true)
aliasvalue(:no, :false)
defaultto :false
end
end

View File

@ -1,39 +1,7 @@
class lvm(
$loopfile = undef,
$ensure = 'present',
$vg = 'volume-group-00',
$pv = undef,
$volume_groups = {},
) {
validate_hash($volume_groups)
if ! $pv and ! $loopfile {
fail('The pv (physical volume) or loopfile parameter is not defined')
}
package{ 'lvm2':
ensure => $ensure,
}
if $pv {
physical_volume { $pv:
ensure => $ensure,
require => Package['lvm2'],
}
volume_group { $vg:
ensure => $ensure,
physical_volumes => $pv,
require => Physical_volume[$pv],
}
}
else {
exec { 'volumes':
command => "/bin/dd if=/dev/zero of=${loopfile} bs=2M seek=20k count=0 && /sbin/vgcreate ${vg} `/sbin/losetup --show -f ${loopfile}`",
creates => "${loopfile}",
require => Package['lvm2'],
}
}
create_resources('lvm::volume_group', $volume_groups)
}

View File

@ -0,0 +1,59 @@
define lvm::logical_volume(
$volume_group,
$size,
$ensure = present,
$options = 'defaults',
$fs_type = 'ext4',
$mountpath = "/${name}",
$mountpath_require = false,
) {
validate_bool($mountpath_require)
if $mountpath_require {
Mount {
require => File[$mountpath],
}
}
$mount_ensure = $ensure ? {
'absent' => absent,
default => mounted,
}
if $ensure == 'present' {
Logical_volume[$name] ->
Filesystem["/dev/${volume_group}/${name}"] ->
Mount[$mountpath]
} else {
Mount[$mountpath] ->
Filesystem["/dev/${volume_group}/${name}"] ->
Logical_volume[$name]
}
logical_volume { $name:
ensure => $ensure,
volume_group => $volume_group,
size => $size,
}
filesystem {"/dev/${volume_group}/${name}":
ensure => $ensure,
fs_type => $fs_type,
}
exec { "ensure mountpoint '${mountpath}' exists":
path => [ '/bin', '/usr/bin' ],
command => "mkdir -p ${mountpath}",
unless => "test -d ${mountpath}",
} ->
mount {$mountpath:
ensure => $mount_ensure,
device => "/dev/${volume_group}/${name}",
fstype => $fs_type,
options => $options,
pass => 2,
dump => 1,
atboot => true,
}
}

View File

@ -0,0 +1,138 @@
# == Define: lvm::volume
#
# This defined type will create a <code>logical_volume</code> with the name of the define and ensure a <code>physical_volume</code>,
# <code>volume_group</code>, and <code>filesystem</code> resource have been created on the block device supplied.
#
# === Parameters
#
# [*ensure*]
# Can only be set to <code>cleaned</code>, <code>absent</code> or <code>present</code>. A value of <code>present</code> will
# ensure that the <code>physical_volume</code>, <code>volume_group</code>, <code>logical_volume</code>, and
# <code>filesystem</code> resources are present for the volume. A value of <code>cleaned</code> will ensure that all of the
# resources are <code>absent</code> <b>Warning this has a high potential for unexpected harm</b> use it with caution. A value of
# <code>absent</code> will remove only the <code>logical_volume</code> resource from the system.
# [*pv*]
# The block device to ensure a <code>physical_volume</code> has been created on.
# [*vg*]
# The <code>volume_group</code> to ensure is created on the <code>physical_volume</code> provided by the <code>pv</code>
# parameter.
# [*fstype*]
# The type of <code>filesystem</code> to create on the logical volume.
# [*size*]
# The size the <code>logical_voluem</code> should be.
#
# === Examples
#
# Provide some examples on how to use this type:
#
# lvm::volume { 'lv_example0':
# vg => 'vg_example0',
# pv => '/dev/sdd1',
# fstype => 'ext4',
# size => '100GB',
# }
#
# === Copyright
#
# See README.markdown for the module author information.
#
# === License
#
# This file is part of the puppetlabs/lvm puppet module.
#
# puppetlabs/lvm is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation, version 2 of the License.
#
# puppetlabs/lvm is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with puppetlabs/lvm. If not, see http://www.gnu.org/licenses/.
#
define lvm::volume (
$ensure,
$pv,
$vg,
$fstype = undef,
$size = undef,
$extents = undef,
$initial_size = undef
) {
case $ensure {
#
# Clean up the whole chain.
#
cleaned: {
# This may only need to exist once
if ! defined(Physical_volume[$pv]) {
physical_volume { $pv: ensure => present }
}
# This may only need to exist once
if ! defined(Volume_group[$vg]) {
volume_group { $vg:
ensure => present,
physical_volumes => $pv,
before => Physical_volume[$pv]
}
logical_volume { $name:
ensure => present,
volume_group => $vg,
size => $size,
initial_size => $initial_size,
before => Volume_group[$vg]
}
}
}
#
# Just clean up the logical volume
#
absent: {
logical_volume { $name:
ensure => absent,
volume_group => $vg,
size => $size
}
}
#
# Create the whole chain.
#
present: {
# This may only need to exist once. Requires stdlib 4.1 to
# handle $pv as an array.
ensure_resource('physical_volume', $pv, { 'ensure' => $ensure })
# This may only need to exist once
if ! defined(Volume_group[$vg]) {
volume_group { $vg:
ensure => present,
physical_volumes => $pv,
require => Physical_volume[$pv]
}
}
logical_volume { $name:
ensure => present,
volume_group => $vg,
size => $size,
extents => $extents,
require => Volume_group[$vg]
}
if $fstype != undef {
filesystem { "/dev/${vg}/${name}":
ensure => present,
fs_type => $fstype,
require => Logical_volume[$name]
}
}
}
default: {
fail ( 'puppet-lvm::volume: ensure parameter can only be set to cleaned, absent or present' )
}
}
}

View File

@ -0,0 +1,25 @@
define lvm::volume_group(
$physical_volumes,
$ensure = present,
$logical_volumes = {},
) {
validate_hash($logical_volumes)
physical_volume { $physical_volumes:
ensure => $ensure,
}
volume_group { $name:
ensure => $ensure,
physical_volumes => $physical_volumes,
}
create_resources(
'lvm::logical_volume',
$logical_volumes,
{
ensure => $ensure,
volume_group => $name,
}
)
}

View File

@ -1,3 +1,4 @@
require 'puppetlabs_spec_helper/module_spec_helper'
require 'pathname'
dir = Pathname.new(__FILE__).parent
$LOAD_PATH.unshift(dir, dir + 'lib', dir + '../lib')

View File

@ -0,0 +1,54 @@
require 'spec_helper'
describe 'lvm', :type => :class do
describe 'with no parameters' do
it { should compile.with_all_deps }
end
describe 'with volume groups' do
let(:params) do
{
:volume_groups => {
'myvg' => {
'physical_volumes' => [ '/dev/sda2', '/dev/sda3', ],
'logical_volumes' => {
'opt' => {'size' => '20G'},
'tmp' => {'size' => '1G' },
'usr' => {'size' => '3G' },
'var' => {'size' => '15G'},
'home' => {'size' => '5G' },
'backup' => {
'size' => '5G',
'mountpath' => '/var/backups',
'mountpath_require' => true
}
}
}
}
}
end
it { should contain_physical_volume('/dev/sda2') }
it { should contain_physical_volume('/dev/sda3') }
it { should contain_volume_group('myvg').with({
:ensure => 'present',
:physical_volumes => [ '/dev/sda2', '/dev/sda3', ]
}) }
it { should contain_logical_volume('opt').with( {
:volume_group => 'myvg',
:size => '20G'
}) }
it { should contain_filesystem('/dev/myvg/opt') }
it { should contain_mount('/opt') }
it { should contain_logical_volume('backup').with({
:volume_group => 'myvg',
:size => '5G'
}) }
it { should contain_filesystem('/dev/myvg/backup') }
it { should contain_mount('/var/backups') }
end
end

View File

@ -0,0 +1,111 @@
#!/usr/bin/env rspec
require 'spec_helper'
# Generic LVM support
describe 'lvm_support fact' do
before :each do
Facter.clear
end
context 'when not on Linux' do
it 'should be set to not' do
Facter.fact(:kernel).expects(:value).returns('SunOs')
Facter.value(:lvm_support).should be_nil
end
end
context 'when on Linux' do
before :each do
Facter.fact(:kernel).expects(:value).returns('Linux')
end
context 'when vgs is absent' do
it 'should be set to no' do
Facter::Util::Resolution.stubs('exec') # All other calls
Facter::Util::Resolution.expects('which').with('vgs').returns(nil)
Facter.value(:lvm_support).should be_nil
end
end
context 'when vgs is present' do
it 'should be set to yes' do
Facter::Util::Resolution.stubs('exec') # All other calls
Facter::Util::Resolution.expects('which').with('vgs').returns('/sbin/vgs')
Facter.value(:lvm_support).should be_true
end
end
end
end
# VGs
describe 'lvm_vgs facts' do
before :each do
Facter.clear
end
context 'when there is no lvm support' do
it 'should not exist' do
Facter.fact(:lvm_support).expects(:value).returns(nil)
Facter.value(:lvm_vgs).should be_nil
end
end
context 'when there is lvm support' do
context 'when there are no vgs' do
it 'should be set to 0' do
Facter::Util::Resolution.stubs('exec') # All other calls
Facter::Util::Resolution.expects('exec').with('vgs -o name --noheadings 2>/dev/null').returns(nil)
Facter.fact(:lvm_support).expects(:value).returns(true)
Facter.value(:lvm_vgs).should == 0
end
end
context 'when there are vgs' do
it 'should list vgs' do
Facter::Util::Resolution.stubs('exec') # All other calls
Facter::Util::Resolution.expects('exec').with('vgs -o name --noheadings 2>/dev/null').returns("vg0\nvg1")
Facter.fact(:lvm_support).expects(:value).returns(true)
Facter.value(:lvm_vgs).should == 2
Facter.value(:lvm_vg_0).should == 'vg0'
Facter.value(:lvm_vg_1).should == 'vg1'
end
end
end
end
# PVs
describe 'lvm_pvs facts' do
before :each do
Facter.clear
end
context 'when there is no lvm support' do
it 'should not exist' do
Facter.fact(:lvm_support).expects(:value).returns(nil)
Facter.value(:lvm_pvs).should be_nil
end
end
context 'when there is lvm support' do
context 'when there are no pvs' do
it 'should be set to 0' do
Facter::Util::Resolution.stubs('exec') # All other calls
Facter::Util::Resolution.expects('exec').with('pvs -o name --noheadings 2>/dev/null').returns(nil)
Facter.fact(:lvm_support).expects(:value).returns(true)
Facter.value(:lvm_pvs).should == 0
end
end
context 'when there are pvs' do
it 'should list pvs' do
Facter::Util::Resolution.stubs('exec') # All other calls
Facter::Util::Resolution.expects('exec').with('pvs -o name --noheadings 2>/dev/null').returns("pv0\npv1")
Facter.fact(:lvm_support).expects(:value).returns(true)
Facter.value(:lvm_pvs).should == 2
Facter.value(:lvm_pv_0).should == 'pv0'
Facter.value(:lvm_pv_1).should == 'pv1'
end
end
end
end

View File

@ -1,35 +0,0 @@
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
provider_class = Puppet::Type.type(:filesystem).provider(:lvm)
describe provider_class do
before do
@resource = stub("resource")
@provider = provider_class.new(@resource)
end
describe 'when creating' do
it "should execute the correct filesystem command" do
@resource.expects(:[]).with(:name).returns('/dev/myvg/mylv')
@resource.expects(:[]).with(:fs_type).returns('ext4')
@resource.expects(:[]).with(:options)
@provider.expects(:execute).with(['mkfs.ext4', '/dev/myvg/mylv'])
@provider.create
end
it "should include the supplied filesystem options" do
@resource.expects(:[]).with(:name).returns('/dev/myvg/mylv')
@resource.expects(:[]).with(:fs_type).returns('ext4')
@resource.expects(:[]).with(:options).returns('-b 4096 -E stride=32,stripe-width=64').twice
@provider.expects(:execute).with(['mkfs.ext4', '/dev/myvg/mylv', ['-b', '4096', '-E', 'stride=32,stripe-width=64']])
@provider.create
end
it "should include -q for reiserfs" do
@resource.expects(:[]).with(:name).returns('/dev/myvg/mylv')
@resource.expects(:[]).with(:fs_type).returns('reiserfs')
@resource.expects(:[]).with(:options).returns('-b 4096 -E stride=32,stripe-width=64').twice
@provider.expects(:execute).with(['mkfs.reiserfs', '/dev/myvg/mylv', '-q', ['-b', '4096', '-E', 'stride=32,stripe-width=64']])
@provider.create
end
end
end

View File

@ -0,0 +1,35 @@
require 'spec_helper'
provider_class = Puppet::Type.type(:filesystem).provider(:lvm)
describe provider_class do
before do
@resource = stub("resource")
@provider = provider_class.new(@resource)
end
describe 'when creating' do
it "should execute the correct filesystem command" do
@resource.expects(:[]).with(:name).returns('/dev/myvg/mylv')
@resource.expects(:[]).with(:fs_type).returns('ext4')
@resource.expects(:[]).with(:options)
@provider.expects(:execute).with(['mkfs.ext4', '/dev/myvg/mylv'])
@provider.create
end
it "should include the supplied filesystem options" do
@resource.expects(:[]).with(:name).returns('/dev/myvg/mylv')
@resource.expects(:[]).with(:fs_type).returns('ext4')
@resource.expects(:[]).with(:options).returns('-b 4096 -E stride=32,stripe-width=64').twice
@provider.expects(:execute).with(['mkfs.ext4', '/dev/myvg/mylv', ['-b', '4096', '-E', 'stride=32,stripe-width=64']])
@provider.create
end
it "should include -q for reiserfs" do
@resource.expects(:[]).with(:name).returns('/dev/myvg/mylv')
@resource.expects(:[]).with(:fs_type).returns('reiserfs')
@resource.expects(:[]).with(:options).returns('-b 4096 -E stride=32,stripe-width=64').twice
@provider.expects(:execute).with(['mkfs.reiserfs', '/dev/myvg/mylv', '-q', ['-b', '4096', '-E', 'stride=32,stripe-width=64']])
@provider.create
end
end
end

View File

@ -1,85 +0,0 @@
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
provider_class = Puppet::Type.type(:logical_volume).provider(:lvm)
describe provider_class do
before do
@resource = stub("resource")
@provider = provider_class.new(@resource)
end
describe 'when creating' do
context 'with size' do
it "should execute 'lvcreate' with a '--size' option" do
@resource.expects(:[]).with(:name).returns('mylv')
@resource.expects(:[]).with(:volume_group).returns('myvg')
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', 'myvg')
@provider.create
end
end
context 'without size' do
it "should execute 'lvcreate' without a '--size' option" do
@resource.expects(:[]).with(:name).returns('mylv')
@resource.expects(:[]).with(:volume_group).returns('myvg')
@resource.expects(:[]).with(:size).returns(nil).at_least_once
@resource.expects(:[]).with(:initial_size)
@provider.expects(:lvcreate).with('-n', 'mylv', 'myvg')
@provider.create
end
end
end
describe "when modifying" do
context "with a larger size" do
context "in extent portions" do
it "should execute 'lvextend'" do
@resource.expects(:[]).with(:name).returns('mylv').at_least_once
@resource.expects(:[]).with(:volume_group).returns('myvg').at_least_once
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', 'myvg')
@provider.create
@provider.expects(:lvs).with('--noheading', '--unit', 'g', '/dev/myvg/mylv').returns(' 1.00g').at_least_once
@provider.expects(:lvs).with('--noheading', '-o', 'vg_extent_size', '--units', 'k', '/dev/myvg/mylv').returns(' 1000.00k')
@provider.expects(:lvextend).with('-L', '2000000k', '/dev/myvg/mylv').returns(true)
@provider.expects(:mount).with('-f', '--guess-fstype', '/dev/myvg/mylv')
@provider.size = '2000000k'
end
end
context "not in extent portions" do
it "should raise an exception" do
@resource.expects(:[]).with(:name).returns('mylv').at_least_once
@resource.expects(:[]).with(:volume_group).returns('myvg').at_least_once
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', 'myvg')
@provider.create
@provider.expects(:lvs).with('--noheading', '--unit', 'g', '/dev/myvg/mylv').returns(' 1.00g').at_least_once
@provider.expects(:lvs).with('--noheading', '-o', 'vg_extent_size', '--units', 'k', '/dev/myvg/mylv').returns(' 1000.00k')
proc { @provider.size = '1.15g' }.should raise_error(Puppet::Error, /extent/)
end
end
end
context "with a smaller size" do
it "should raise an exception" do
@resource.expects(:[]).with(:name).returns('mylv').at_least_once
@resource.expects(:[]).with(:volume_group).returns('myvg').at_least_once
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', 'myvg')
@provider.create
@provider.expects(:lvs).with('--noheading', '--unit', 'g', '/dev/myvg/mylv').returns(' 1.00g').at_least_once
@provider.expects(:lvs).with('--noheading', '-o', 'vg_extent_size', '--units', 'k', '/dev/myvg/mylv').returns(' 1000.00k')
proc { @provider.size = '1m' }.should raise_error(Puppet::Error, /manual/)
end
end
end
describe 'when destroying' do
it "should execute 'dmsetup' and 'lvremove'" do
@resource.expects(:[]).with(:volume_group).returns('myvg').twice
@resource.expects(:[]).with(:name).returns('mylv').twice
@provider.expects(:dmsetup).with('remove', 'myvg-mylv')
@provider.expects(:lvremove).with('-f', '/dev/myvg/mylv')
@provider.destroy
end
end
end

View File

@ -0,0 +1,124 @@
require 'spec_helper'
provider_class = Puppet::Type.type(:logical_volume).provider(:lvm)
describe provider_class do
before do
@resource = stub("resource")
@provider = provider_class.new(@resource)
end
describe 'when creating' do
context 'with size' do
it "should execute 'lvcreate' with a '--size' option" do
@resource.expects(:[]).with(:name).returns('mylv')
@resource.expects(:[]).with(:volume_group).returns('myvg')
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@resource.expects(:[]).with(:extents).returns(nil).at_least_once
@resource.expects(:[]).with(:stripes).returns(nil).at_least_once
@resource.expects(:[]).with(:stripesize).returns(nil).at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', 'myvg')
@provider.create
end
end
context 'without size and without extents' do
it "should execute 'lvcreate' without a '--size' option or a '--extents' option" do
@resource.expects(:[]).with(:name).returns('mylv')
@resource.expects(:[]).with(:volume_group).returns('myvg')
@resource.expects(:[]).with(:size).returns(nil).at_least_once
@resource.expects(:[]).with(:initial_size)
@resource.expects(:[]).with(:extents).returns(nil).at_least_once
@resource.expects(:[]).with(:stripes).returns(nil).at_least_once
@resource.expects(:[]).with(:stripesize).returns(nil).at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--extents', '100%FREE', 'myvg')
@provider.create
end
end
context 'with extents' do
it "should execute 'lvcreate' with a '--extents' option" do
@resource.expects(:[]).with(:name).returns('mylv')
@resource.expects(:[]).with(:volume_group).returns('myvg')
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@resource.expects(:[]).with(:extents).returns('80%vg').at_least_once
@resource.expects(:[]).with(:stripes).returns(nil).at_least_once
@resource.expects(:[]).with(:stripesize).returns(nil).at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', '--extents', '80%vg', 'myvg')
@provider.create
end
end
context 'without extents' do
it "should execute 'lvcreate' without a '--extents' option" do
@resource.expects(:[]).with(:name).returns('mylv')
@resource.expects(:[]).with(:volume_group).returns('myvg')
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@resource.expects(:[]).with(:extents).returns(nil).at_least_once
@resource.expects(:[]).with(:stripes).returns(nil).at_least_once
@resource.expects(:[]).with(:stripesize).returns(nil).at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', 'myvg')
@provider.create
end
end
end
describe "when modifying" do
context "with a larger size" do
context "in extent portions" do
it "should execute 'lvextend'" do
@resource.expects(:[]).with(:name).returns('mylv').at_least_once
@resource.expects(:[]).with(:volume_group).returns('myvg').at_least_once
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@resource.expects(:[]).with(:extents).returns(nil).at_least_once
@resource.expects(:[]).with(:stripes).returns(nil).at_least_once
@resource.expects(:[]).with(:stripesize).returns(nil).at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', 'myvg')
@provider.create
@provider.expects(:lvs).with('--noheading', '--unit', 'g', '/dev/myvg/mylv').returns(' 1.00g').at_least_once
@provider.expects(:lvs).with('--noheading', '-o', 'vg_extent_size', '--units', 'k', '/dev/myvg/mylv').returns(' 1000.00k')
@provider.expects(:lvextend).with('-L', '2000000k', '/dev/myvg/mylv').returns(true)
@provider.expects(:blkid).with('/dev/myvg/mylv')
@provider.size = '2000000k'
end
end
context "not in extent portions" do
it "should raise an exception" do
@resource.expects(:[]).with(:name).returns('mylv').at_least_once
@resource.expects(:[]).with(:volume_group).returns('myvg').at_least_once
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@resource.expects(:[]).with(:extents).returns(nil).at_least_once
@resource.expects(:[]).with(:stripes).returns(nil).at_least_once
@resource.expects(:[]).with(:stripesize).returns(nil).at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', 'myvg')
@provider.create
@provider.expects(:lvs).with('--noheading', '--unit', 'g', '/dev/myvg/mylv').returns(' 1.00g').at_least_once
@provider.expects(:lvs).with('--noheading', '-o', 'vg_extent_size', '--units', 'k', '/dev/myvg/mylv').returns(' 1000.00k')
proc { @provider.size = '1.15g' }.should raise_error(Puppet::Error, /extent/)
end
end
end
context "with a smaller size" do
it "should raise an exception" do
@resource.expects(:[]).with(:name).returns('mylv').at_least_once
@resource.expects(:[]).with(:volume_group).returns('myvg').at_least_once
@resource.expects(:[]).with(:size).returns('1g').at_least_once
@resource.expects(:[]).with(:extents).returns(nil).at_least_once
@resource.expects(:[]).with(:stripes).returns(nil).at_least_once
@resource.expects(:[]).with(:stripesize).returns(nil).at_least_once
@provider.expects(:lvcreate).with('-n', 'mylv', '--size', '1g', 'myvg')
@provider.create
@provider.expects(:lvs).with('--noheading', '--unit', 'g', '/dev/myvg/mylv').returns(' 1.00g').at_least_once
@provider.expects(:lvs).with('--noheading', '-o', 'vg_extent_size', '--units', 'k', '/dev/myvg/mylv').returns(' 1000.00k')
proc { @provider.size = '1m' }.should raise_error(Puppet::Error, /manual/)
end
end
end
describe 'when destroying' do
it "should execute 'dmsetup' and 'lvremove'" do
@resource.expects(:[]).with(:volume_group).returns('myvg').twice
@resource.expects(:[]).with(:name).returns('mylv').twice
@provider.expects(:dmsetup).with('remove', 'myvg-mylv')
@provider.expects(:lvremove).with('-f', '/dev/myvg/mylv')
@provider.destroy
end
end
end

View File

@ -1,34 +0,0 @@
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
provider_class = Puppet::Type.type(:physical_volume).provider(:lvm)
describe provider_class do
before do
@resource = stub("resource")
@provider = provider_class.new(@resource)
end
describe 'when creating' do
it "should execute the 'pvcreate'" do
@resource.expects(:[]).with(:name).returns('/dev/hdx')
@provider.expects(:pvcreate).with('/dev/hdx')
@provider.create
end
end
describe 'when destroying' do
it "should execute 'pvdestroy'" do
@resource.expects(:[]).with(:name).returns('/dev/hdx')
@provider.expects(:pvremove).with('/dev/hdx')
@provider.destroy
end
end
describe "when checking existence" do
it "should execute 'pvs'" do
@resource.expects(:[]).with(:name).returns('/dev/sdb')
@provider.expects(:pvs).returns(true)
@provider.should be_exists
end
end
end

View File

@ -0,0 +1,41 @@
require 'spec_helper'
provider_class = Puppet::Type.type(:physical_volume).provider(:lvm)
describe provider_class do
before do
@resource = stub("resource")
@provider = provider_class.new(@resource)
end
describe 'when creating' do
it "should execute the 'pvcreate'" do
@resource.expects(:[]).with(:name).returns('/dev/hdx')
@provider.expects(:pvcreate).with('/dev/hdx')
@provider.create
end
end
describe 'when destroying' do
it "should execute 'pvdestroy'" do
@resource.expects(:[]).with(:name).returns('/dev/hdx')
@provider.expects(:pvremove).with('/dev/hdx')
@provider.destroy
end
end
describe "when checking existence" do
it "should execute 'pvs'" do
@resource.expects(:[]).with(:unless_vg).returns()
@resource.expects(:[]).with(:name).returns('/dev/sdb')
@provider.expects(:pvs).returns(true)
@provider.should be_exists
end
it "should not execute 'pvs' if unless_vg VG exists" do
@resource.expects(:[]).with(:unless_vg).returns('vg01')
@resource.expects(:[]).with(:unless_vg).returns('vg01')
@provider.expects(:vgs).returns(true)
@provider.should be_exists
end
end
end

View File

@ -1,27 +0,0 @@
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
provider_class = Puppet::Type.type(:volume_group).provider(:lvm)
describe provider_class do
before do
@resource = stub("resource")
@provider = provider_class.new(@resource)
end
describe 'when creating' do
it "should execute 'vgcreate'" do
@resource.expects(:[]).with(:name).returns('myvg')
@resource.expects(:should).with(:physical_volumes).returns(%w{/dev/hda})
@provider.expects(:vgcreate).with('myvg', '/dev/hda')
@provider.create
end
end
describe 'when destroying' do
it "should execute 'vgremove'" do
@resource.expects(:[]).with(:name).returns('myvg')
@provider.expects(:vgremove).with('myvg')
@provider.destroy
end
end
end

View File

@ -0,0 +1,27 @@
require 'spec_helper'
provider_class = Puppet::Type.type(:volume_group).provider(:lvm)
describe provider_class do
before do
@resource = stub("resource")
@provider = provider_class.new(@resource)
end
describe 'when creating' do
it "should execute 'vgcreate'" do
@resource.expects(:[]).with(:name).returns('myvg')
@resource.expects(:should).with(:physical_volumes).returns(%w{/dev/hda})
@provider.expects(:vgcreate).with('myvg', '/dev/hda')
@provider.create
end
end
describe 'when destroying' do
it "should execute 'vgremove'" do
@resource.expects(:[]).with(:name).returns('myvg')
@provider.expects(:vgremove).with('myvg')
@provider.destroy
end
end
end

View File

@ -1,40 +0,0 @@
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
describe Puppet::Type.type(:filesystem) do
before do
@type = Puppet::Type.type(:filesystem)
@valid_params = {
:name => '/dev/myvg/mylv',
:ensure => 'present'
}
stub_default_provider!
end
it "should exist" do
@type.should_not be_nil
end
describe "the name parameter" do
it "should exist" do
@type.attrclass(:name).should_not be_nil
end
it "should only allow fully qualified files" do
specifying(:name => 'myfs').should raise_error(Puppet::Error)
end
it "should support fully qualified names" do
@type.new(:name => valid_params[:name]) do |resource|
resource[:name].should == valid_params[:name]
end
end
end
describe "the 'ensure' parameter" do
it "should exist" do
@type.attrclass(:ensure).should_not be_nil
end
it "should support a filesystem type as a value" do
with(valid_params)[:ensure].should == :present
end
end
end

View File

@ -0,0 +1,40 @@
require 'spec_helper'
describe Puppet::Type.type(:filesystem) do
before do
@type = Puppet::Type.type(:filesystem)
@valid_params = {
:name => '/dev/myvg/mylv',
:ensure => 'present'
}
stub_default_provider!
end
it "should exist" do
@type.should_not be_nil
end
describe "the name parameter" do
it "should exist" do
@type.attrclass(:name).should_not be_nil
end
it "should only allow fully qualified files" do
specifying(:name => 'myfs').should raise_error(Puppet::Error)
end
it "should support fully qualified names" do
@type.new(:name => valid_params[:name]) do |resource|
resource[:name].should == valid_params[:name]
end
end
end
describe "the 'ensure' parameter" do
it "should exist" do
@type.attrclass(:ensure).should_not be_nil
end
it "should support a filesystem type as a value" do
with(valid_params)[:ensure].should == :present
end
end
end

View File

@ -1,62 +0,0 @@
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
describe Puppet::Type.type(:logical_volume) do
before do
@type = Puppet::Type.type(:logical_volume)
@valid_params = {
:name => 'mylv',
:volume_group => 'myvg',
:size => '1g',
:ensure => :present
}
stub_default_provider!
end
it "should exist" do
@type.should_not be_nil
end
describe "when specifying the 'name' parameter" do
it "should exist" do
@type.attrclass(:name).should_not be_nil
end
it "should not allow qualified files" do
lambda { @type.new :name => "my/lv" }.should raise_error(Puppet::Error)
end
it "should support unqualified names" do
@type.new(:name => "mylv")[:name].should == "mylv"
end
end
describe "when specifying the 'volume_group' parameter" do
it "should exist" do
@type.attrclass(:volume_group).should_not be_nil
end
end
describe "when specifying the 'size' parameter" do
it "should exist" do
@type.attrclass(:size).should_not be_nil
end
it 'should support setting a value' do
with(valid_params)[:size].should == valid_params[:size]
end
end
describe "when specifying the 'ensure' parameter" do
it "should exist" do
@type.attrclass(:ensure).should_not be_nil
end
it "should support 'present' as a value" do
with(valid_params)[:ensure].should == :present
end
it "should support 'absent' as a value" do
with(valid_params.merge(:ensure => :absent)) do |resource|
resource[:ensure].should == :absent
end
end
it "should not support other values" do
specifying(valid_params.merge(:ensure => :foobar)).should raise_error(Puppet::Error)
end
end
end

View File

@ -0,0 +1,72 @@
require 'spec_helper'
describe Puppet::Type.type(:logical_volume) do
before do
@type = Puppet::Type.type(:logical_volume)
@valid_params = {
:name => 'mylv',
:volume_group => 'myvg',
:size => '1g',
:extents => '80%vg',
:ensure => :present
}
stub_default_provider!
end
it "should exist" do
@type.should_not be_nil
end
describe "when specifying the 'name' parameter" do
it "should exist" do
@type.attrclass(:name).should_not be_nil
end
it "should not allow qualified files" do
lambda { @type.new :name => "my/lv" }.should raise_error(Puppet::Error)
end
it "should support unqualified names" do
@type.new(:name => "mylv")[:name].should == "mylv"
end
end
describe "when specifying the 'volume_group' parameter" do
it "should exist" do
@type.attrclass(:volume_group).should_not be_nil
end
end
describe "when specifying the 'size' parameter" do
it "should exist" do
@type.attrclass(:size).should_not be_nil
end
it 'should support setting a value' do
with(valid_params)[:size].should == valid_params[:size]
end
end
describe "when specifying the 'extents' parameter" do
it "should exist" do
@type.attrclass(:extents).should_not be_nil
end
it 'should support setting a value' do
with(valid_params)[:extents].should == valid_params[:extents]
end
end
describe "when specifying the 'ensure' parameter" do
it "should exist" do
@type.attrclass(:ensure).should_not be_nil
end
it "should support 'present' as a value" do
with(valid_params)[:ensure].should == :present
end
it "should support 'absent' as a value" do
with(valid_params.merge(:ensure => :absent)) do |resource|
resource[:ensure].should == :absent
end
end
it "should not support other values" do
specifying(valid_params.merge(:ensure => :foobar)).should raise_error(Puppet::Error)
end
end
end

View File

@ -1,43 +0,0 @@
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
describe Puppet::Type.type(:physical_volume) do
before do
@type = Puppet::Type.type(:physical_volume)
stub_default_provider!
end
it "should exist" do
Puppet::Type.type(:physical_volume).should_not be_nil
end
describe "the name parameter" do
it "should exist" do
@type.attrclass(:name).should_not be_nil
end
it "should only allow fully qualified files" do
lambda { @type.new :name => "mypv" }.should raise_error(Puppet::Error)
end
it "should support fully qualified names" do
@type.new(:name => "/my/pv")[:name].should == "/my/pv"
end
end
describe "the 'ensure' parameter" do
it "should exist" do
@type.attrclass(:ensure).should_not be_nil
end
it "should support 'present' as a value" do
with(:name => "/my/pv", :ensure => :present) do |resource|
resource[:ensure].should == :present
end
end
it "should support 'absent' as a value" do
with(:name => "/my/pv", :ensure => :absent) do |resource|
resource[:ensure].should == :absent
end
end
it "should not support other values" do
specifying(:name => "/my/pv", :ensure => :foobar).should raise_error(Puppet::Error)
end
end
end

View File

@ -0,0 +1,43 @@
require 'spec_helper'
describe Puppet::Type.type(:physical_volume) do
before do
@type = Puppet::Type.type(:physical_volume)
stub_default_provider!
end
it "should exist" do
Puppet::Type.type(:physical_volume).should_not be_nil
end
describe "the name parameter" do
it "should exist" do
@type.attrclass(:name).should_not be_nil
end
it "should only allow fully qualified files" do
lambda { @type.new :name => "mypv" }.should raise_error(Puppet::Error)
end
it "should support fully qualified names" do
@type.new(:name => "/my/pv")[:name].should == "/my/pv"
end
end
describe "the 'ensure' parameter" do
it "should exist" do
@type.attrclass(:ensure).should_not be_nil
end
it "should support 'present' as a value" do
with(:name => "/my/pv", :ensure => :present) do |resource|
resource[:ensure].should == :present
end
end
it "should support 'absent' as a value" do
with(:name => "/my/pv", :ensure => :absent) do |resource|
resource[:ensure].should == :absent
end
end
it "should not support other values" do
specifying(:name => "/my/pv", :ensure => :foobar).should raise_error(Puppet::Error)
end
end
end

View File

@ -1,53 +0,0 @@
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
describe Puppet::Type.type(:volume_group) do
before do
@type = Puppet::Type.type(:volume_group)
stub_default_provider!
end
it "should exist" do
Puppet::Type.type(:volume_group).should_not be_nil
end
describe "the name parameter" do
it "should exist" do
@type.attrclass(:name).should_not be_nil
end
end
describe "the 'ensure' parameter" do
it "should exist" do
@type.attrclass(:ensure).should_not be_nil
end
it "should support 'present' as a value" do
with(:name => "myvg", :ensure => :present) do |resource|
resource[:ensure].should == :present
end
end
it "should support 'absent' as a value" do
with(:name => "myvg", :ensure => :absent) do |resource|
resource[:ensure].should == :absent
end
end
it "should not support other values" do
specifying(:name => "myvg", :ensure => :foobar).should raise_error(Puppet::Error)
end
end
describe "the 'physical_volumes' parameter" do
it "should exist" do
@type.attrclass(:physical_volumes).should_not be_nil
end
it "should support a single value" do
with(:name => "myvg", :physical_volumes => 'mypv') do |resource|
resource.should(:physical_volumes).should == %w{mypv}
end
end
it "should support an array" do
with(:name => "myvg", :physical_volumes => %w{mypv otherpv}) do |resource|
resource.should(:physical_volumes).should == %w{mypv otherpv}
end
end
end
end

View File

@ -0,0 +1,53 @@
require 'spec_helper'
describe Puppet::Type.type(:volume_group) do
before do
@type = Puppet::Type.type(:volume_group)
stub_default_provider!
end
it "should exist" do
Puppet::Type.type(:volume_group).should_not be_nil
end
describe "the name parameter" do
it "should exist" do
@type.attrclass(:name).should_not be_nil
end
end
describe "the 'ensure' parameter" do
it "should exist" do
@type.attrclass(:ensure).should_not be_nil
end
it "should support 'present' as a value" do
with(:name => "myvg", :ensure => :present) do |resource|
resource[:ensure].should == :present
end
end
it "should support 'absent' as a value" do
with(:name => "myvg", :ensure => :absent) do |resource|
resource[:ensure].should == :absent
end
end
it "should not support other values" do
specifying(:name => "myvg", :ensure => :foobar).should raise_error(Puppet::Error)
end
end
describe "the 'physical_volumes' parameter" do
it "should exist" do
@type.attrclass(:physical_volumes).should_not be_nil
end
it "should support a single value" do
with(:name => "myvg", :physical_volumes => 'mypv') do |resource|
resource.should(:physical_volumes).should == %w{mypv}
end
end
it "should support an array" do
with(:name => "myvg", :physical_volumes => %w{mypv otherpv}) do |resource|
resource.should(:physical_volumes).should == %w{mypv otherpv}
end
end
end
end