diff --git a/lib/puppet/provider/ceph.rb b/lib/puppet/provider/ceph.rb new file mode 100644 index 00000000..470096e9 --- /dev/null +++ b/lib/puppet/provider/ceph.rb @@ -0,0 +1,18 @@ +require 'puppet' + +class Puppet::Provider::Ceph < Puppet::Provider + + initvars + commands :ceph => 'ceph' + + protected + + # NOTE(tkajinam): JSON outputs from ceph command includes garbage empty lines + def parse_json(value) + JSON.parse(value.gsub(/^$\n/, '').strip) + end + + def ceph_cmd(cluster, args) + ceph('--cluster', cluster, *args) + end +end diff --git a/lib/puppet/provider/ceph_fs/ceph.rb b/lib/puppet/provider/ceph_fs/ceph.rb new file mode 100644 index 00000000..88575321 --- /dev/null +++ b/lib/puppet/provider/ceph_fs/ceph.rb @@ -0,0 +1,58 @@ +require 'puppet' +require 'puppet/provider/ceph' + +Puppet::Type.type(:ceph_fs).provide( + :ceph, + :parent => Puppet::Provider::Ceph +) do + desc 'Provider for ceph filesystem' + + def create + ceph_cmd(@resource[:cluster], ['fs', 'new', @resource[:name], @resource[:metadata_pool_name], @resource[:data_pool_name]]) + end + + def destroy + ceph_cmd(@resource[:cluster], ['fs', 'rm', @resource[:name], '--yes-i-really-really-mean-it']) + end + + def exists? + fs = find_fs + if fs.nil? + return false + end + return true + end + + def metadata_pool_name + fs = find_fs + fs['metadata_pool'] + end + + def data_pool_name + fs = find_fs + # TODO(tkajinam): data pool is a list. Should we support multiple values ? + fs['data_pools'][0] + end + + [ + :metadata_pool_name, + :data_pool_name, + ].each do |attr| + define_method(attr.to_s + "=") do |value| + fail("Property #{attr.to_s} does not support being updated") + end + end + + private + + def find_fs + fs_list = parse_json( + ceph_cmd(@resource[:cluster], ['fs', 'ls', '-f', 'json'])) + fs_list.each do |fs| + if fs['name'] == @resource[:name] + return fs + end + end + return nil + end +end diff --git a/lib/puppet/provider/ceph_pool/ceph.rb b/lib/puppet/provider/ceph_pool/ceph.rb new file mode 100644 index 00000000..012005c5 --- /dev/null +++ b/lib/puppet/provider/ceph_pool/ceph.rb @@ -0,0 +1,81 @@ +require 'puppet' +require 'puppet/provider/ceph' + +Puppet::Type.type(:ceph_pool).provide( + :ceph, + :parent => Puppet::Provider::Ceph +) do + desc 'Provider for ceph pools' + + def create + args = [] + args << @resource[:pg_num] + if @resource[:pgp_num] + args << @resource[:pgp_num] + end + ceph_cmd(@resource[:cluster], ['osd', 'pool', 'create', @resource[:name], *args]) + + if @resource[:size] + set_pool_property('size', @resource[:size]) + end + if @resource[:application] + ceph_cmd(@resource[:cluster], ['osd', 'pool', 'application','enable', @resource[:name], @resource[:application]]) + end + end + + def destroy + ceph_cmd(@resource[:cluster], ['osd', 'pool', 'delete', @resource[:name], @resource[:name], '--yes-i-really-really-mean-it']) + end + + def exists? + pools = parse_json(ceph_cmd(@resource[:cluster], ['osd', 'pool', 'ls', '-f', 'json'])) + pools.include?(@resource[:name]) + end + + def size + get_pool_property('size') + end + + def size=(value) + set_pool_property('size', value) + end + + def pg_num + get_pool_property('pg_num') + end + + def pg_num=(value) + set_pool_property('pg_num', value) + end + + def pgp_num + get_pool_property('pgp_num') + end + + def pgp_num=(value) + set_pool_property('pgp_num', value) + end + + def application + val = parse_json(ceph_cmd(@resource[:cluster], ['osd', 'pool', 'application', 'get', @resource[:name], '-f', 'json'])) + val.keys[0] + end + + def application=(value) + if application.nil? + ceph_cmd(@resource[:cluster], ['osd', 'pool', 'application', 'enable', @resource[:name], value]) + else + raise Puppet::Error, "The pool #{@resource[:name]} already has application set" + end + end + + private + + def get_pool_property(key) + parse_json(ceph_cmd(@resource[:cluster], ['osd', 'pool', 'get', @resource[:name], key, '-f', 'json']))[key] + end + + def set_pool_property(key, value) + ceph_cmd(@resource[:cluster], ['osd', 'pool', 'set', @resource[:name], key, value]) + end +end diff --git a/lib/puppet/type/ceph_fs.rb b/lib/puppet/type/ceph_fs.rb new file mode 100644 index 00000000..522b66d1 --- /dev/null +++ b/lib/puppet/type/ceph_fs.rb @@ -0,0 +1,59 @@ +Puppet::Type.newtype(:ceph_fs) do + ensurable + + newparam(:name) do + isnamevar + desc 'Name of the file system' + newvalues(/.+/) + end + + newparam(:cluster) do + isnamevar + defaultto 'ceph' + desc 'Name of the cluster' + newvalues(/.+/) + end + + newproperty(:metadata_pool_name) do + desc 'Name of the metadata pool' + newvalues(/.+/) + end + + newproperty(:data_pool_name) do + desc 'Name of the data pool' + newvalues(/.+/) + end + + autorequire(:ceph_pool) do + [self[:metadata_pool_name], self[:data_pool_name]] + end + + validate do + if ! self[:metadata_pool_name] + raise(Puppet::Error, 'metadata_pool_name is required') + end + if ! self[:data_pool_name] + raise(Puppet::Error, 'data_pool_name is required') + end + end + + def self.title_patterns + cluster = Regexp.new(/[^\/]+/) + name = Regexp.new(/.+/) + [ + [ + /^(#{cluster})\/(#{name})$/, + [ + [:cluster], + [:name] + ] + ], + [ + /^(#{name})$/, + [ + [:name] + ] + ] + ] + end +end diff --git a/lib/puppet/type/ceph_pool.rb b/lib/puppet/type/ceph_pool.rb new file mode 100644 index 00000000..e12134aa --- /dev/null +++ b/lib/puppet/type/ceph_pool.rb @@ -0,0 +1,91 @@ +Puppet::Type.newtype(:ceph_pool) do + ensurable + + newparam(:name) do + isnamevar + desc 'Name of the pool' + newvalues(/.+/) + end + + newparam(:cluster) do + isnamevar + desc 'Name of the cluster' + newvalues(/.+/) + end + + newproperty(:pg_num) do + desc 'Number of PGs' + defaultto 64 + validate do |v| + if v.is_a?(Integer) + if v <= 0 + raise ArgumentError, "Invalid pg_num #{value}. Requires a positive value, not #{value.class}" + end + else + raise ArgumentError, "Invalid pg_num #{value}. Requires an Integer, not a #{value.class}" + end + return true + end + end + + newproperty(:pgp_num) do + desc 'Number of PGs for placement' + validate do |v| + if v.is_a?(Integer) + if v <= 0 + raise ArgumentError, "Invalid pgp_num #{value}. Requires a positive value, not #{value.class}" + end + else + raise ArgumentError, "Invalid pgp_num #{value}. Requires an Integer, not a #{value.class}" + end + return true + end + end + + newproperty(:size) do + desc 'Pool size' + validate do |v| + if v.is_a?(Integer) + if v <= 0 + raise ArgumentError, "Invalid size #{value}. Requires a positive value, not #{value.class}" + end + else + raise ArgumentError, "Invalid size #{value}. Requires an Integer, not a #{value.class}" + end + return true + end + end + + newproperty(:application) do + desc 'Associated application' + newvalues(/.+/) + end + + validate do + if self[:pgp_num] + if self[:pgp_num] > self[:pg_num] + raise(Puppet::Error, 'pgp_num should not exceed pg_num') + end + end + end + + def self.title_patterns + cluster = Regexp.new(/[^\/]+/) + name = Regexp.new(/.+/) + [ + [ + /^(#{cluster})\/(#{name})$/, + [ + [:cluster], + [:name] + ] + ], + [ + /^(#{name})$/, + [ + [:name] + ] + ] + ] + end +end diff --git a/manifests/fs.pp b/manifests/fs.pp index 21b81de6..7b5ae5e7 100644 --- a/manifests/fs.pp +++ b/manifests/fs.pp @@ -33,28 +33,38 @@ # [*data_pool*] Name of a pool used for storing data. # Mandatory. Get one with `ceph osd pool ls` # +# [*ensure*] Creates ( present ) or removes ( absent ) a file system. +# Optional. Defaults to present. +# If set to absent, it will drop the fs. +# +# [*cluster*] The ceph cluster +# Optional. Defaults to ceph. +# +# DEPRECATED PARAMETERS +# # [*exec_timeout*] The default exec resource timeout, in seconds # Optional. Defaults to $ceph::params::exec_timeout # define ceph::fs ( - $metadata_pool, - $data_pool, + String[1] $metadata_pool, + String[1] $data_pool, + Enum['present', 'absent'] $ensure = present, + String[1] $cluster = 'ceph', + # DEPRECATED PARAMETERS Optional[Float[0]] $exec_timeout = undef, ) { - include ceph::params - $exec_timeout_real = $exec_timeout ? { - undef => $ceph::params::exec_timeout, - default => $exec_timeout, + if $exec_timeout { + warning('The exec_timeout parameter is deprecated and has no effect') } - Ceph_config<||> -> Exec["create-fs-${name}"] - Ceph::Pool<||> -> Exec["create-fs-${name}"] + Ceph_config<||> -> Ceph_fs[$name] + Ceph::Pool<||> -> Ceph_fs[$name] - exec { "create-fs-${name}": - command => "ceph fs new ${name} ${metadata_pool} ${data_pool}", - unless => "ceph fs ls | grep 'name: ${name},'", - path => ['/bin', '/usr/bin'], - timeout => $exec_timeout_real, + ceph_fs { $name: + ensure => $ensure, + metadata_pool_name => $metadata_pool, + data_pool_name => $data_pool, + cluster => $cluster, } } diff --git a/manifests/pool.pp b/manifests/pool.pp index f87991ea..289241c1 100644 --- a/manifests/pool.pp +++ b/manifests/pool.pp @@ -30,6 +30,9 @@ # Optional. Defaults to present. # If set to absent, it will drop the pool and all its data. # +# [*cluster*] The ceph cluster +# Optional. Defaults to ceph. +# # [*pg_num*] Number of PGs for the pool. # Optional. Default is 64 ( but you probably want to pass a value here ). # Number of Placement Groups (PGs) for a pool, if the pool already @@ -47,84 +50,43 @@ # Optional. Default is undef. # cephfs,rbd,rgw or freeform for custom application. # +# DEPRECATED PARAMETERS +# # [*exec_timeout*] The default exec resource timeout, in seconds # Optional. Defaults to $ceph::params::exec_timeout # define ceph::pool ( Enum['present', 'absent'] $ensure = present, - $pg_num = 64, - $pgp_num = undef, - $size = undef, - $tag = undef, + String[1] $cluster = 'ceph', + Integer[0] $pg_num = 64, + Optional[Integer[0]] $pgp_num = undef, + Optional[Integer[0]] $size = undef, + Optional[String[1]] $tag = undef, + # DEPRECATED PARAMETERS Optional[Float[0]] $exec_timeout = undef, ) { include ceph::params - $exec_timeout_real = $exec_timeout ? { - undef => $ceph::params::exec_timeout, - default => $exec_timeout, + + if $exec_timeout { + warning('The exec_timeout parameter is deprecated and has no effect') } - if $ensure == present { - - Ceph_config<||> -> Exec["create-${name}"] - Ceph::Mon<||> -> Exec["create-${name}"] - Ceph::Key<||> -> Exec["create-${name}"] - Ceph::Osd<||> -> Exec["create-${name}"] - exec { "create-${name}": - command => "ceph osd pool create ${name} ${pg_num}", - unless => "ceph osd pool ls | grep -w '${name}'", - path => ['/bin', '/usr/bin'], - timeout => $exec_timeout_real, - } - - exec { "set-${name}-pg_num": - command => "ceph osd pool set ${name} pg_num ${pg_num}", - unless => "test $(ceph osd pool get ${name} pg_num | sed 's/.*:\s*//g') -ge ${pg_num}", - path => ['/bin', '/usr/bin'], - require => Exec["create-${name}"], - timeout => $exec_timeout_real, - } - - if $pgp_num { - exec { "set-${name}-pgp_num": - command => "ceph osd pool set ${name} pgp_num ${pgp_num}", - unless => "test $(ceph osd pool get ${name} pgp_num | sed 's/.*:\s*//g') -ge ${pgp_num}", - path => ['/bin', '/usr/bin'], - require => [Exec["create-${name}"], Exec["set-${name}-pg_num"]], - timeout => $exec_timeout_real, - } - } - - if $size { - exec { "set-${name}-size": - command => "ceph osd pool set ${name} size ${size}", - unless => "test $(ceph osd pool get ${name} size | sed 's/.*:\s*//g') -eq ${size}", - path => ['/bin', '/usr/bin'], - require => Exec["create-${name}"], - timeout => $exec_timeout_real, - } - } - - if $tag { - exec { "set-${name}-tag": - command => "ceph osd pool application enable ${name} ${tag}", - unless => "ceph osd pool application get ${name} ${tag}", - path => ['/bin', '/usr/bin'], - require => Exec["create-${name}"], - timeout => $exec_timeout_real, - } - } - - } else { - - exec { "delete-${name}": - command => "ceph osd pool delete ${name} ${name} --yes-i-really-really-mean-it", - onlyif => "ceph osd pool ls | grep -w '${name}'", - path => ['/bin', '/usr/bin'], - timeout => $exec_timeout_real, - } -> Ceph::Mon<| ensure == absent |> - + if $pgp_num and ($pgp_num > $pg_num) { + fail('pgp_num should not exceed pg_num') } + Ceph_config<||> -> Ceph_pool[$name] + Ceph::Mon<||> -> Ceph_pool[$name] + Ceph::Key<||> -> Ceph_pool[$name] + Ceph::Osd<||> -> Ceph_pool[$name] + + ceph_pool { $name: + ensure => $ensure, + pg_num => $pg_num, + pgp_num => $pgp_num, + size => $size, + cluster => $cluster, + application => $tag, + } } diff --git a/spec/defines/ceph_fs_spec.rb b/spec/defines/ceph_fs_spec.rb index ef2e61d3..bd0006ac 100644 --- a/spec/defines/ceph_fs_spec.rb +++ b/spec/defines/ceph_fs_spec.rb @@ -24,15 +24,15 @@ describe 'ceph::fs' do let :params do { - :metadata_pool => 'metadata_pool', - :data_pool => 'data_pool' + :metadata_pool => 'metadata', + :data_pool => 'data' } end - it { should contain_exec('create-fs-fsa').with( - :command => "ceph fs new fsa metadata_pool data_pool", - :unless => "ceph fs ls | grep 'name: fsa,'", - :path => ['/bin', '/usr/bin'], + it { should contain_ceph_fs('fsa').with( + :ensure => 'present', + :metadata_pool_name => 'metadata', + :data_pool_name => 'data', )} end end diff --git a/spec/defines/ceph_pool_spec.rb b/spec/defines/ceph_pool_spec.rb index 6f71fe29..7938cf82 100644 --- a/spec/defines/ceph_pool_spec.rb +++ b/spec/defines/ceph_pool_spec.rb @@ -20,51 +20,33 @@ require 'spec_helper' describe 'ceph::pool' do shared_examples 'ceph pool' do - describe "create with custom params" do - let :title do - 'volumes' - end + let :title do + 'volumes' + end + describe "create with custom params" do let :params do { :ensure => 'present', - :pg_num => 3, - :pgp_num => 4, + :pg_num => 4, + :pgp_num => 3, :size => 2, :tag => 'rbd', } end it { - should contain_exec('create-volumes').with( - :command => 'ceph osd pool create volumes 3', - :path => ['/bin', '/usr/bin'], + should contain_ceph_pool('volumes').with( + :ensure => 'present', + :pg_num => 4, + :pgp_num => 3, + :size => 2, + :application => 'rbd', ) - should contain_exec('set-volumes-pg_num').with( - :command => 'ceph osd pool set volumes pg_num 3', - :path => ['/bin', '/usr/bin'], - ) - should contain_exec('set-volumes-pgp_num').with( - :command => 'ceph osd pool set volumes pgp_num 4', - :path => ['/bin', '/usr/bin'], - ).that_requires('Exec[set-volumes-pg_num]') - should contain_exec('set-volumes-size').with( - :command => 'ceph osd pool set volumes size 2', - :path => ['/bin', '/usr/bin'], - ) - should contain_exec('set-volumes-tag').with( - :command => 'ceph osd pool application enable volumes rbd', - :path => ['/bin', '/usr/bin'], - ) - should_not contain_exec('delete-volumes') } end describe "delete with custom params" do - let :title do - 'volumes' - end - let :params do { :ensure => 'absent', @@ -72,10 +54,8 @@ describe 'ceph::pool' do end it { - should_not contain_exec('create-volumes') - should contain_exec('delete-volumes').with( - :command => 'ceph osd pool delete volumes volumes --yes-i-really-really-mean-it', - :path => ['/bin', '/usr/bin'], + should contain_ceph_pool('volumes').with( + :ensure => 'absent' ) } end diff --git a/spec/unit/provider/ceph_fs/ceph_spec.rb b/spec/unit/provider/ceph_fs/ceph_spec.rb new file mode 100644 index 00000000..f05025bd --- /dev/null +++ b/spec/unit/provider/ceph_fs/ceph_spec.rb @@ -0,0 +1,90 @@ +require 'puppet' +require 'spec_helper' +require 'puppet/provider/ceph_fs/ceph' + +provider_class = Puppet::Type.type(:ceph_fs).provider(:ceph) + +describe provider_class do + + describe 'manage fss' do + let :fs_name do + 'fs1' + end + + let :fs_attrs do + { + :cluster => 'ceph', + :name => fs_name, + :data_pool_name => 'data', + :metadata_pool_name => 'metadata', + } + end + + let :resource do + Puppet::Type::Ceph_fs.new(fs_attrs) + end + + let :provider do + provider_class.new(resource) + end + + describe '#create' do + context 'with defaults' do + it 'creates fs' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'fs', 'new', fs_name, 'metadata', 'data') + provider.create + end + end + end + + describe '#exists?' do + it 'detects existing fs' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'fs', 'ls', '-f', 'json') + .and_return(' + +[{"name":"fs1","metadata_pool":"metadata","metadata_pool_id":5,"data_pool_ids":[6],"data_pools":["data"]}]') + expect(provider.exists?).to be_truthy + end + it 'detects non-eisting fs' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'fs', 'ls', '-f', 'json') + .and_return(' + +[{"name":"fs2","metadata_pool":"metadata","metadata_pool_id":5,"data_pool_ids":[6],"data_pools":["data"]}]') + expect(provider.exists?).to be_falsey + end + end + + describe '#destroy' do + it 'removes fs' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'fs', 'rm', fs_name, '--yes-i-really-really-mean-it') + provider.destroy + end + end + + describe '#data_pool' do + it 'reads data_pool' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'fs', 'ls', '-f', 'json') + .and_return(' + +[{"name":"fs1","metadata_pool":"metadata","metadata_pool_id":5,"data_pool_ids":[6],"data_pools":["data"]}]') + expect(provider.data_pool_name).to eq('data') + end + end + + describe '#metadata_pool' do + it 'reads metadata_pool' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'fs', 'ls', '-f', 'json') + .and_return(' + +[{"name":"fs1","metadata_pool":"metadata","metadata_pool_id":5,"data_pool_ids":[6],"data_pools":["data"]}]') + expect(provider.metadata_pool_name).to eq('metadata') + end + end + end +end diff --git a/spec/unit/provider/ceph_pool/ceph_spec.rb b/spec/unit/provider/ceph_pool/ceph_spec.rb new file mode 100644 index 00000000..4c086dcd --- /dev/null +++ b/spec/unit/provider/ceph_pool/ceph_spec.rb @@ -0,0 +1,215 @@ +require 'puppet' +require 'spec_helper' +require 'puppet/provider/ceph_pool/ceph' + +provider_class = Puppet::Type.type(:ceph_pool).provider(:ceph) + +describe provider_class do + + describe 'manage pools' do + let :pool_name do + 'pool1' + end + + let :pool_attrs do + { + :cluster => 'ceph', + :name => pool_name, + :ensure => 'present', + :pg_num => 64, + } + end + + let :resource do + Puppet::Type::Ceph_pool.new(pool_attrs) + end + + let :provider do + provider_class.new(resource) + end + + describe '#create' do + context 'with defaults' do + it 'creates pool' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'create', pool_name, 64) + provider.create + end + end + + context 'with pgp_num' do + let :pool_attrs do + { + :cluster => 'ceph', + :name => pool_name, + :ensure => 'present', + :pg_num => 64, + :pgp_num => 32, + } + end + + it 'creates pool' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'create', pool_name, 64, 32) + provider.create + end + end + + context 'with size' do + let :pool_attrs do + { + :cluster => 'ceph', + :name => pool_name, + :ensure => 'present', + :pg_num => 64, + :size => 10, + } + end + + it 'creates pool' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'create', pool_name, 64) + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'set', pool_name, 'size', 10) + provider.create + end + end + + context 'with application' do + let :pool_attrs do + { + :cluster => 'ceph', + :name => pool_name, + :ensure => 'present', + :pg_num => 64, + :application => 'nova', + } + end + + it 'creates pool' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'create', pool_name, 64) + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'application', 'enable', pool_name, 'nova') + provider.create + end + end + end + + describe '#exists?' do + it 'detects existing pool' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'ls', '-f', 'json') + .and_return(' + +["pool1", "pool2"]') + expect(provider.exists?).to be_truthy + end + it 'detects non-eisting pool' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'ls', '-f', 'json') + .and_return(' + +["pool2", "pool3"]') + expect(provider.exists?).to be_falsey + end + end + + describe '#destroy' do + it 'removes pool' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'delete', pool_name, pool_name, '--yes-i-really-really-mean-it') + provider.destroy + end + end + + describe '#size' do + it 'reads size' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'get', pool_name, 'size', '-f', 'json') + .and_return(" + +{\"pool\":\"#{pool_name}\",\"pool_id\":4,\"size\":5}") + expect(provider.size).to eq(5) + end + end + + describe '#size=' do + it 'sets size' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'set', pool_name, 'size', 10) + provider.size = 10 + end + end + + describe '#pg_num' do + it 'reads pg_num' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'get', pool_name, 'pg_num', '-f', 'json') + .and_return(" + +{\"pool\":\"#{pool_name}\",\"pool_id\":4,\"pg_num\":64}") + expect(provider.pg_num).to eq(64) + end + end + + describe '#pg_num=' do + it 'sets pg_num' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'set', pool_name, 'pg_num', 128) + provider.pg_num = 128 + end + end + + describe '#pgp_num' do + it 'reads pgp_num' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'get', pool_name, 'pgp_num', '-f', 'json') + .and_return(" + +{\"pool\":\"#{pool_name}\",\"pool_id\":4,\"pgp_num\":64}") + expect(provider.pgp_num).to eq(64) + end + end + + describe '#pgp_num=' do + it 'sets pgp_num' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'set', pool_name, 'pgp_num', 128) + provider.pgp_num = 128 + end + end + + describe '#application' do + it 'reads empty application' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'application', 'get', pool_name, '-f', 'json') + .and_return(' + +{}') + expect(provider.application).to eq(nil) + end + it 'reads non-empty application' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'application', 'get', pool_name, '-f', 'json') + .and_return(' + +{"nova":{}}') + expect(provider.application).to eq('nova') + end + end + + describe '#aplication=' do + it 'sets application' do + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'application', 'get', pool_name, '-f', 'json') + .and_return(' + +{}') + expect(provider_class).to receive(:ceph) + .with('--cluster', 'ceph', 'osd', 'pool', 'application', 'enable', pool_name, 'nova') + provider.application = 'nova' + end + end + end +end diff --git a/spec/unit/type/ceph_pool_spec.rb b/spec/unit/type/ceph_pool_spec.rb new file mode 100644 index 00000000..ed875e28 --- /dev/null +++ b/spec/unit/type/ceph_pool_spec.rb @@ -0,0 +1,43 @@ +require 'puppet' +require 'puppet/type/ceph_pool' + +describe 'Puppet::Type.type(:neutron_subnet)' do + it 'should not allow non-positive values' do + expect{Puppet::Type.type(:ceph_pool).new( + :name => 'pool1', + :pg_num => 0, + )}.to raise_error(Puppet::ResourceError) + expect{Puppet::Type.type(:ceph_pool).new( + :name => 'pool1', + :pgp_num => 0, + )}.to raise_error(Puppet::ResourceError) + expect{Puppet::Type.type(:ceph_pool).new( + :name => 'pool1', + :size => 0, + )}.to raise_error(Puppet::ResourceError) + end + + it 'should not allow non-integer values' do + expect{Puppet::Type.type(:ceph_pool).new( + :name => 'pool1', + :pg_num => '64', + )}.to raise_error(Puppet::ResourceError) + expect{Puppet::Type.type(:ceph_pool).new( + :name => 'pool1', + :pgp_num => '64', + )}.to raise_error(Puppet::ResourceError) + expect{Puppet::Type.type(:ceph_pool).new( + :name => 'pool1', + :size => '123', + )}.to raise_error(Puppet::ResourceError) + end + + it 'should not allow pgp_num > pg_num' do + expect{Puppet::Type.type(:ceph_pool).new( + :name => 'pool1', + :pg_num => 64, + :pgp_num => 65, + )}.to raise_error(Puppet::ResourceError) + end +end +