Skip to content

Commit

Permalink
Add support for additional properties for Zpool.
Browse files Browse the repository at this point in the history
ashift (Only valid on linux)
autoexpand
failmode.
  • Loading branch information
KeithWard committed Jul 6, 2020
1 parent 6667e2a commit 230b86e
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 2 deletions.
51 changes: 50 additions & 1 deletion lib/puppet/provider/zpool/zpool.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ def self.instances
end
end

def get_zpool_property(prop)
zpool(:get, prop, @resource[:name]).split("\n").reverse.map { |line|
name, _property, value, _source = line.split("\s")
value if name == @resource[:name]
}.shift
end

def process_zpool_data(pool_array)
if pool_array == []
return Hash.new(:absent)
Expand Down Expand Up @@ -115,8 +122,18 @@ def build_vdevs
end
end

def add_pool_properties
properties = []
[:ashift, :autoexpand, :failmode].each do |property|
if (value = @resource[property]) && value != ''
properties << '-o' << "#{property}=#{value}"
end
end
properties
end

def create
zpool(*([:create, @resource[:pool]] + build_vdevs + build_named('spare') + build_named('log')))
zpool(*([:create] + add_pool_properties + [@resource[:pool]] + build_vdevs + build_named('spare') + build_named('log')))
end

def destroy
Expand All @@ -141,4 +158,36 @@ def exists?
fail "zpool #{field} can't be changed. should be #{should}, currently is #{current_pool[field]}"
end
end

[:autoexpand, :failmode].each do |field|
define_method(field) do
get_zpool_property(field)
end

define_method(field.to_s + '=') do |should|
zpool(:set, "#{field}=#{should}", @resource[:name])
end
end

# Borrow the code from the ZFS provider here so that we catch and return '-'
# as ashift is linux only.
# see lib/puppet/provider/zfs/zfs.rb

PARAMETER_UNSET_OR_NOT_AVAILABLE = '-'.freeze

define_method(:ashift) do
begin
get_zpool_property(:ashift)
rescue
PARAMETER_UNSET_OR_NOT_AVAILABLE
end
end

define_method('ashift=') do |should|
begin
zpool(:set, "ashift=#{should}", @resource[:name])
rescue
PARAMETER_UNSET_OR_NOT_AVAILABLE
end
end
end
16 changes: 16 additions & 0 deletions lib/puppet/type/zpool.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ def insync?(is)
desc 'Log disks for this pool. This type does not currently support mirroring of log disks.'
end

newproperty(:ashift) do
desc 'The Alignment Shift for the vdevs in the given pool.'

validate do |_value|
raise Puppet::Error _('This property is only supported on Linux and FreeBSD') unless Facter.value(:kernel) == 'Linux' || Facter.value(:kernel) == 'FreeBSD'
end
end

newproperty(:autoexpand) do
desc 'The autoexpand setting for the given pool. Valid values are `on` or `off`'
end

newproperty(:failmode) do
desc 'The failmode setting for the given pool. Valid values are `wait`, `continue` or `panic`'
end

newparam(:pool) do
desc 'The name for this pool.'
isnamevar
Expand Down
49 changes: 49 additions & 0 deletions spec/unit/provider/zpool/zpool_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,42 @@
end
end

describe 'when calling the getters and setters for configurable options' do
[:autoexpand, :failmode].each do |field|
it "should get the #{field} value from the pool" do
allow(provider).to receive(:zpool).with(:get, field, name).and_return("NAME PROPERTY VALUE SOURCE\n#{name} #{field} value local")
expect(provider.send(field)).to eq('value')
end
it "should set #{field}=value" do
expect(provider).to receive(:zpool).with(:set, "#{field}=value", name)
provider.send("#{field}=", 'value')
end
end
end
describe 'when calling the getters and setters for ashift' do
context 'when available' do
it "gets 'ashift' property" do
expect(provider).to receive(:zpool).with(:get, :ashift, name).and_return("NAME PROPERTY VALUE SOURCE\n#{name} ashift value local")
expect(provider.send('ashift')).to eq('value')
end
it 'sets ashift=value' do
expect(provider).to receive(:zpool).with(:set, 'ashift=value', name)
provider.send('ashift=', 'value')
end
end

context 'when not available' do
it "gets '-' for the ashift property" do
expect(provider).to receive(:zpool).with(:get, :ashift, name).and_raise(RuntimeError, 'not valid')
expect(provider.send('ashift')).to eq('-')
end
it 'does not error out when trying to set ashift' do
expect(provider).to receive(:zpool).with(:set, 'ashift=value', name).and_raise(RuntimeError, 'not valid')
expect { provider.send('ashift=', 'value') }.not_to raise_error
end
end
end

describe 'when calling the getters and setters' do
[:disk, :mirror, :raidz, :log, :spare].each do |field|
describe "when calling #{field}" do
Expand Down Expand Up @@ -234,6 +270,19 @@
provider.create
end
end

describe 'when creating a zpool with options' do
before(:each) do
resource[:disk] = 'disk1'
end
[:ashift, :autoexpand, :failmode].each do |field|
it "should include field #{field}" do
resource[field] = field
expect(provider).to receive(:zpool).with(:create, '-o', "#{field}=#{field}", name, 'disk1')
provider.create
end
end
end
end

context '#delete' do
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/type/zpool_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

describe 'zpool' do
describe Puppet::Type.type(:zpool) do
properties = [:ensure, :disk, :mirror, :raidz, :spare, :log]
properties = [:ensure, :disk, :mirror, :raidz, :spare, :log, :autoexpand, :failmode, :ashift]
properties.each do |property|
it "should have a #{property} property" do
expect(described_class.attrclass(property).ancestors).to be_include(Puppet::Property)
Expand Down

0 comments on commit 230b86e

Please sign in to comment.