Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial VLAN support refactor #98

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
doc
Gemfile.local
Gemfile.lock
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ gem 'facter', '>= 1.6.2'
group :test, :development do
gem 'rspec', '~> 2.10.0'
gem 'mocha', '~> 0.10.5'
gem 'rspec-puppet', :git => 'https://github.com/rodjek/rspec-puppet'
gem 'rspec-puppet'
gem 'rake'
end

Expand Down
43 changes: 27 additions & 16 deletions lib/puppet/provider/network_config/interfaces.rb
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,18 @@ def self.parse_file(filename, contents)
#Instance[name].name = name
Instance[name].family = family
Instance[name].method = method
Instance[name].mode = :raw

# for the vlan naming conventions (a mess), see
# man 5 vlan-interfaces
case name
# 'vlan22'
when /^vlan/
Instance[name].mode = :vlan
# 'eth2.0003' or 'br1.2'
when /^[a-z]{1,}[0-9]{1,}\.[0-9]{1,4}/
Instance[name].mode = :vlan
else
Instance[name].mode = :raw
end
else
# If we match on a string with a leading iface, but it isn't in the
# expected format, malformed blar blar
Expand Down Expand Up @@ -225,7 +235,6 @@ def self.parse_file(filename, contents)
when 'address'; Instance[name].ipaddress = val
when 'netmask'; Instance[name].netmask = val
when 'mtu'; Instance[name].mtu = val
when 'vlan-raw-device'; Instance[name].mode = :vlan
else Instance[name].options[key] << val
end
else
Expand Down Expand Up @@ -272,18 +281,6 @@ def self.format_file(filename, providers)
stanza = []
stanza << %{iface #{provider.name} #{provider.family} #{provider.method}}

if provider.mode == :vlan
# if this is a :vlan mode interface than the name of the
# `vlan-raw-device` is implied by the `iface` name in the format
# fooX.<vlan>

# The valid vlan ID range is 0-4095; 4096 is out of range
vlan_range_regex = %r[\d{1,3}|40[0-9][0-5]]
raw_device = provider.name.match(%r[\A([a-z]+\d+)(?::\d+|\.#{vlan_range_regex})?\Z])[1]

stanza << %{vlan-raw-device #{raw_device}}
end

[
[:ipaddress, 'address'],
[:netmask, 'netmask'],
Expand All @@ -292,10 +289,24 @@ def self.format_file(filename, providers)
stanza << "#{section} #{provider.send property}" if provider.send(property) and provider.send(property) != :absent
end

if provider.mode == :vlan
if provider.options["vlan-raw-device"]
stanza << "vlan-raw-device #{provider.options["vlan-raw-device"]}"
else
vlan_range_regex = %r[\d{1,3}|40[0-9][0-5]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vide can you explain this regex? If I'm reading it right it looks for three consecutive digits or four in a weird range between 4000-4095, excepting when the last digit is 6-9. Vlan 4006 should be valid, for instance. Then in your test you use vlan 4500 as an ID. What am I missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was the regexp used before #116 was fixed, I didn't write it :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume your fork has that updated regex then, but the rest remains the same? If we take it in now, it would be nice to know it matches your fork, since you've given that a field test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rnelson0 well my fork is quite old and it needs a rebase against current master to be useful at all. If thwere's real interesting in accepting this feature and merging it, I could work on it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vide Yes, we are definitely interested in moving this module forward and would appreciate any and all help!

if ! provider.name.match(%r[\A([a-z]+\d+)(?::\d+|\.#{vlan_range_regex})\Z])
raise Puppet::Error, "Interface #{provider.name}: missing vlan-raw-device or wrong VLAN ID in the iface name"
end
end
end

if provider.options and provider.options != :absent
provider.options.each_pair do |key, val|
if val.is_a? String
stanza << " #{key} #{val}"
# dont print property because we've already added it to the stanza
if key != "vlan-raw-device"
stanza << " #{key} #{val}"
end
elsif val.is_a? Array
val.each { |entry| stanza << " #{key} #{entry}" }
else
Expand Down
70 changes: 60 additions & 10 deletions spec/unit/provider/network_config/interfaces_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ def fixture_data(file)
:mtu => "1500",
:mode => :vlan,
:options => {
"broadcast" => "172.16.0.255",
"gateway" => "172.16.0.1",
"broadcast" => "172.16.0.255",
"gateway" => "172.16.0.1",
"vlan-raw-device" => "eth0",
}
}
end
Expand Down Expand Up @@ -174,9 +175,9 @@ def fixture_data(file)
)
end

let(:eth0_1_provider) do
stub('eth0_1_provider',
:name => "eth0.1",
let(:vlan20_provider) do
stub('vlan20_provider',
:name => "vlan20",
:ensure => :present,
:onboot => true,
:hotplug => true,
Expand All @@ -186,10 +187,45 @@ def fixture_data(file)
:netmask => "255.255.0.0",
:mtu => "1500",
:mode => :vlan,
:options => nil
:options => {
'vlan-raw-device' => 'eth1'
}
)
end

let(:vlan10_provider) do
stub('vlan10_provider',
:name => "vlan10",
:ensure => :present,
:onboot => true,
:hotplug => true,
:family => "inet",
:method => "dhcp",
:ipaddress => nil,
:netmask => nil,
:mtu => nil,
:mode => :vlan,
:options => {}
)
end

let(:eth1_4500_provider) do
stub('eth1_4500_provider',
:name => "eth1.4500",
:ensure => :present,
:onboot => true,
:hotplug => true,
:family => "inet",
:method => "dhcp",
:ipaddress => nil,
:netmask => nil,
:mtu => nil,
:mode => :vlan,
:options => {}
)
end


let(:eth1_provider) do
stub('eth1_provider',
:name => "eth1",
Expand Down Expand Up @@ -300,17 +336,31 @@ def fixture_data(file)
end

describe "writing vlan iface blocks" do
let(:content) { described_class.format_file('', [eth0_1_provider]) }
let(:content) { described_class.format_file('', [vlan20_provider]) }

it "should add all options following the iface block" do
block = [
"iface eth0.1 inet static",
"vlan-raw-device eth0",
"iface vlan20 inet static",
"address 169.254.0.1",
"netmask 255.255.0.0",
"mtu 1500",
"vlan-raw-device eth1",
].join("\n")
content.split('\n').find {|line| line.match(/iface eth0/)}.should match(block)
content.split('\n').find {|line| line.match(/iface vlan20/)}.should match(block)
end
end

describe "writing wrong vlan iface blocks" do
let(:content) { described_class.format_file('', [eth1_4500_provider]) }
it "should fail with wrong VLAN ID" do
expect { content }.to raise_error(Puppet::Error, /Interface eth1.4500: missing vlan-raw-device or wrong VLAN ID in the iface name/)
end
end

describe "writing wrong vlanNN iface blocks" do
let(:content) { described_class.format_file('', [vlan10_provider]) }
it "should fail with missing vlan-raw-device" do
expect { content }.to raise_error(Puppet::Error, /Interface vlan10: missing vlan-raw-device or wrong VLAN ID in the iface name/)
end
end

Expand Down