Skip to content

Commit ab1b10f

Browse files
committed
support forcing mixed vdev types
1 parent 8ee54fe commit ab1b10f

File tree

4 files changed

+55
-12
lines changed

4 files changed

+55
-12
lines changed

lib/puppet/provider/zpool/zpool.rb

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ def process_zpool_data(pool_array)
5858
end
5959
end
6060

61+
if pool.key?(:mirror) && pool.key?(:raidz)
62+
pool[:force] = true
63+
end
64+
6165
pool
6266
end
6367

@@ -113,27 +117,38 @@ def build_vdevs
113117
mirror = @resource[:mirror]
114118
raidz = @resource[:raidz]
115119

120+
vdevs = []
121+
116122
if disk
117-
disk.map { |d| d.split(' ') }.flatten
118-
elsif mirror
119-
handle_multi_arrays('mirror', mirror)
120-
elsif raidz
121-
handle_multi_arrays(raidzarity, raidz)
123+
vdevs << disk.map { |d| d.split(' ') }.flatten
124+
else
125+
if mirror
126+
vdevs << handle_multi_arrays('mirror', mirror)
127+
end
128+
if raidz
129+
vdevs << handle_multi_arrays(raidzarity, raidz)
130+
end
122131
end
132+
133+
vdevs
123134
end
124135

125136
def add_pool_properties
126137
properties = []
127-
[:ashift, :autoexpand, :failmode].each do |property|
138+
[:force, :ashift, :autoexpand, :failmode].each do |property|
128139
if (value = @resource[property]) && value != ''
129-
properties << '-o' << "#{property}=#{value}"
140+
if property == :force
141+
properties << '-f'
142+
else
143+
properties << '-o' << "#{property}=#{value}"
144+
end
130145
end
131146
end
132147
properties
133148
end
134149

135150
def create
136-
zpool(*([:create] + add_pool_properties + [@resource[:pool]] + build_vdevs + build_named('spare') + build_named('log') + build_named('cache')))
151+
zpool(*([:create] + add_pool_properties + [@resource[:pool]] + build_vdevs.flatten + build_named('spare') + build_named('log') + build_named('cache')))
137152
end
138153

139154
def destroy
@@ -148,7 +163,7 @@ def exists?
148163
end
149164
end
150165

151-
[:disk, :mirror, :raidz, :log, :spare, :cache, :raid_parity].each do |field|
166+
[:disk, :mirror, :raidz, :log, :spare, :cache, :raid_parity, :force].each do |field|
152167
define_method(field) do
153168
current_pool[field]
154169
end

lib/puppet/type/zpool.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,18 @@ def insync?(is)
119119
desc 'Determines parity when using the `raidz` parameter.'
120120
end
121121

122+
newproperty(:force, boolean: false) do
123+
desc "Forces use of vdevs, even if they appear in use or specify a conflicting replication level.
124+
Not all devices can be overridden in this manner.
125+
WARNING: this is an advanced option that should be used with caution! Ignores safety checks, may OVERWRITE DATA!"
126+
127+
defaultto false
128+
newvalues(:true, :false)
129+
end
130+
122131
validate do
123132
has_should = [:disk, :mirror, :raidz].select { |prop| should(prop) }
124-
raise _('You cannot specify %{multiple_props} on this type (only one)') % { multiple_props: has_should.join(' and ') } if has_should.length > 1
133+
raise _('You cannot specify %{multiple_props} on this type (only one)') % { multiple_props: has_should.join(' and ') } if has_should.length > 1 && !should(:force)
125134
end
126135
end
127136
end

spec/unit/provider/zpool/zpool_spec.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,15 @@
179179
expect(pool[:raid_parity]).to eq('raidz3')
180180
end
181181
end
182+
183+
describe 'when there are mixed vdev replication levels' do
184+
it 'calls create_multi_array with mirror and raidz1' do
185+
zpool_data = ['mirrorpool', 'mirror-0', 'disk1', 'disk2', 'raidz1-1', 'disk3', 'disk4']
186+
pool = provider.process_zpool_data(zpool_data)
187+
expect(pool[:mirror]).to eq(['disk1 disk2'])
188+
expect(pool[:raidz]).to eq(['disk3 disk4'])
189+
end
190+
end
182191
end
183192

184193
describe 'when calling the getters and setters for configurable options' do
@@ -218,7 +227,7 @@
218227
end
219228

220229
describe 'when calling the getters and setters' do
221-
[:disk, :mirror, :raidz, :log, :spare, :cache, :raid_parity].each do |field|
230+
[:disk, :mirror, :raidz, :log, :spare, :cache, :raid_parity, :force].each do |field|
222231
describe "when calling #{field}" do
223232
it "gets the #{field} value from the current_pool hash" do
224233
pool_hash = {}

spec/unit/type/zpool_spec.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require 'spec_helper'
22

33
describe 'zpool' do
4-
describe Puppet::Type.type(:zpool) do
4+
describe Puppet::Type.type(:zpool), type: :type do
55
properties = [:ensure, :disk, :mirror, :raidz, :spare, :log, :autoexpand, :failmode, :ashift, :cache, :raid_parity]
66
properties.each do |property|
77
it "has a #{property} property" do
@@ -15,6 +15,16 @@
1515
expect(described_class.attrclass(parameter).ancestors).to be_include(Puppet::Parameter)
1616
end
1717
end
18+
19+
it 'is invalid when multiple vdev replications specified' do
20+
expect {
21+
described_class.new(name: 'dummy', disk: 'disk1', mirror: 'disk2 disk3')
22+
}.to raise_error(RuntimeError, 'You cannot specify disk and mirror on this type (only one)')
23+
end
24+
25+
it 'is valid when multiple vdev replications are forced' do
26+
described_class.new(name: 'dummy', disk: 'disk1', mirror: 'disk2 disk3', force: true)
27+
end
1828
end
1929

2030
describe Puppet::Property::VDev do

0 commit comments

Comments
 (0)