Browse files

Merge branch 'bonding'

This partially addresses GH-17.
  • Loading branch information...
2 parents 139f274 + 1a2dad5 commit 01c52ba2105042283139d2547d12754a7fcad4b4 @adrienthebo adrienthebo committed Mar 11, 2013
View
7 .fixtures.yml
@@ -0,0 +1,7 @@
+---
+fixtures:
+ repositories:
+ kmod: 'https://github.com/camptocamp/puppet-kmod'
+ stdlib: 'https://github.com/puppetlabs/puppetlabs-stdlib'
+ boolean: 'https://github.com/adrienthebo/puppet-boolean'
+ filemapper: 'https://github.com/adrienthebo/puppet-filemapper'
View
6 .travis.yml
@@ -1,9 +1,7 @@
---
language: ruby
-before_script:
- - "bundle exec puppet module install adrien/boolean"
- - "bundle exec puppet module install adrien/filemapper"
-script: "spec/travis_rspec.rb --color --format documentation"
+before_script: 'bundle exec rake fixture:prepare'
+script: 'SPEC_OPTS="--format documentation" bundle exec rake spec'
notifications:
email: false
rvm:
View
3 Gemfile
@@ -1,4 +1,4 @@
-source :rubygems
+source 'https://rubygems.org'
gem 'puppet', '>= 2.7.0'
gem 'facter', '>= 1.6.2'
@@ -7,6 +7,7 @@ group :test, :development do
gem 'rspec', '~> 2.10.0'
gem 'mocha', '~> 0.10.5'
gem 'rspec-puppet', '>= 0.1.5'
+ gem 'puppetlabs_spec_helper'
end
if File.exists? "#{__FILE__}.local"
View
4 Modulefile
@@ -9,5 +9,7 @@ description 'Manage persistent network interface configuration'
source 'https://github.com/adrienthebo/puppet-network'
project_page 'https://github.com/adrienthebo/puppet-network'
+dependency 'puppetlabs/stdlib', '>= 2.3.0'
dependency 'adrien/filemapper', '>= 1.0.0'
-dependency 'adrien/boolean', '0.9.x'
+dependency 'adrien/boolean', '0.9.x'
+dependency 'camptocamp/kmod', '0.0.x'
View
48 Rakefile
@@ -0,0 +1,48 @@
+require 'rake'
+require 'yaml'
+require 'rspec/core/rake_task'
+
+def fixtures(category)
+ root = File.dirname(__FILE__)
+ yaml = YAML.load_file(File.expand_path('.fixtures.yml', root))
+
+ fixtures = yaml["fixtures"]
+
+ if fixtures.nil?
+ raise ".fixtures.yml contained no top level 'fixtures' key"
+ end
+
+ fixtures[category] || {}
+rescue => e
+ raise e, "Could not load fixture data: #{e}"
+end
+
+namespace :fixture do
+
+ desc "Prepare all fixture repositories"
+ task :prepare do
+ fixtures("repositories").each_pair do |name, remote|
+ fixture_target = "spec/fixtures/modules/#{name}"
+ sh "git clone '#{remote}' '#{fixture_target}'" unless File.exist? fixture_target
+ end
+ end
+
+ desc "Remove all fixture repositories"
+ task :remove do
+ fixtures["repositories"].each_pair do |name, remote|
+ fixture_target = "spec/fixtures/modules/#{name}"
+ FileUtils.rm_rf fixture_target if File.exist? fixture_target
+ end
+ end
+end
+
+desc "Run spec tests on an existing fixtures directory"
+RSpec::Core::RakeTask.new(:spec) do |t|
+ t.rspec_opts = ['--color']
+ t.pattern = 'spec/{classes,defines,unit,functions,hosts}/**/*_spec.rb'
+end
+
+desc "Display the list of available rake tasks"
+task :help do
+ system("rake -T")
+end
View
27 lib/puppet/parser/functions/compact_hash.rb
@@ -0,0 +1,27 @@
+Puppet::Parser::Functions.newfunction(:compact_hash,
+ :type => :rvalue,
+ :arity => 1,
+ :doc => <<-EOD) do |args|
+ compact_hash
+ ============
+
+ Compresses a hash to remove all elements whose values are nil or undef.
+
+ Examples
+ --------
+
+ $example = {
+ 'one' => 'two',
+ 'red' => undef,
+ 'blue' => nil,
+ }
+
+ compact_hash($example)
+ # => { 'one => 'two' }
+
+ EOD
+
+ hash = args[0]
+
+ hash.reject { |_, val| val.nil? or val == :undef }
+end
View
96 manifests/bond.pp
@@ -0,0 +1,96 @@
+# = Define: network::bond
+#
+# Instantiate cross-platform bonded interfaces
+#
+# == Parameters
+#
+#
+# == Examples
+#
+# network::bond { 'bond0':
+# ipaddress => '172.16.1.2',
+# netmask => '255.255.128.0',
+# ensure => present,
+# slaves => ['eth0', 'eth1'],
+# }
+#
+# == See also
+#
+# * Linux Ethernet Bonding Driver HOWTO, Section 2 "Bonding Driver Options" http://www.kernel.org/doc/Documentation/networking/bonding.txt
+#
+define network::bond(
+ $slaves,
+ $ensure = present,
+ $ipaddress = undef,
+ $netmask = undef,
+ $method = undef,
+ $family = undef,
+ $onboot = undef,
+
+ $mode = "active-backup",
+ $miimon = "100",
+ $downdelay = "200",
+ $updelay = "200",
+ $lacp_rate = "slow",
+ $primary = $slaves[0],
+ $primary_reselect = "always",
+ $xmit_hash_policy = "layer2",
+) {
+
+ require network::bond::setup
+
+ kmod::alias { $name:
+ source => 'bonding',
+ ensure => $ensure,
+ }
+
+ case $osfamily {
+ Debian: {
+ network::bond::debian { $name:
+ slaves => $slaves,
+ ensure => $ensure,
+ ipaddress => $ipaddress,
+ netmask => $netmask,
+ method => $method,
+ family => $family,
+ onboot => $onboot,
+
+ mode => $mode,
+ miimon => $miimon,
+ downdelay => $downdelay,
+ updelay => $updelay,
+ lacp_rate => $lacp_rate,
+ primary => $primary,
+ primary_reselect => $primary_reselect,
+ xmit_hash_policy => $xmit_hash_policy,
+
+ require => Kmod::Alias[$name],
+ }
+ }
+ RedHat: {
+ network::bond::redhat { $name:
+ slaves => $slaves,
+ ensure => $ensure,
+ ipaddress => $ipaddress,
+ netmask => $netmask,
+ family => $family,
+ method => $method,
+ onboot => $onboot,
+
+ mode => $mode,
+ miimon => $miimon,
+ downdelay => $downdelay,
+ updelay => $updelay,
+ lacp_rate => $lacp_rate,
+ primary => $primary,
+ primary_reselect => $primary_reselect,
+ xmit_hash_policy => $xmit_hash_policy,
+
+ require => Kmod::Alias[$name],
+ }
+ }
+ default: {
+ fail("network::bond does not support osfamily '${osfamily}'")
+ }
+ }
+}
View
56 manifests/bond/debian.pp
@@ -0,0 +1,56 @@
+# = Define: network::bond::debian
+#
+# Instantiate bonded interfaces on Debian based systems.
+#
+# == See also
+#
+# * Debian Network Bonding http://wiki.debian.org/Bonding
+define network::bond::debian(
+ $slaves,
+ $ensure = present,
+ $ipaddress = undef,
+ $netmask = undef,
+ $method = undef,
+ $family = undef,
+ $onboot = undef,
+
+ $mode = undef,
+ $miimon = undef,
+ $downdelay = undef,
+ $updelay = undef,
+ $lacp_rate = undef,
+ $primary = undef,
+ $primary_reselect = undef,
+ $xmit_hash_policy = undef,
+) {
+
+ $raw = {
+ 'bond-slaves' => join($slaves, ' '),
+ 'bond-mode' => $mode,
+ 'bond-miimon' => $miimon,
+ 'bond-downdelay' => $downdelay,
+ 'bond-updelay' => $updelay,
+ 'bond-lacp-rate' => $lacp_rate,
+ 'bond-primary' => $primary,
+ 'bond-primary-reselect' => $primary_reselect,
+ 'bond-xmit-hash-policy' => $xmit_hash_policy,
+ }
+
+ $opts = compact_hash($raw)
+
+ network_config { $name:
+ ensure => $ensure,
+ ipaddress => $ipaddress,
+ netmask => $netmask,
+ family => $family,
+ method => $method,
+ onboot => $onboot,
+ options => $opts,
+ }
+
+ network_config { $slaves:
+ ensure => absent,
+ reconfigure => true,
+ before => Network_config[$name],
+ }
+}
View
52 manifests/bond/redhat.pp
@@ -0,0 +1,52 @@
+# = Define: network::bond::redhat
+#
+# Instantiate bonded interfaces on Redhat based systems.
+#
+# == See also
+#
+# * Red Hat Deployment Guide 25.7.2 "Using Channel Bonding" https://access.redhat.com/knowledge/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/sec-Using_Channel_Bonding.html
+#
+define network::bond::redhat(
+ $slaves,
+ $ensure = present,
+ $ipaddress = undef,
+ $netmask = undef,
+ $method = undef,
+ $family = undef,
+ $onboot = undef,
+
+ $mode = undef,
+ $miimon = undef,
+ $downdelay = undef,
+ $updelay = undef,
+ $lacp_rate = undef,
+ $primary = undef,
+ $primary_reselect = undef,
+ $xmit_hash_policy = undef,
+) {
+
+ $bonding_opts = template("network/bond/opts-redhat.erb")
+
+ network_config { $name:
+ ensure => $ensure,
+ method => $method,
+ ipaddress => $ipaddress,
+ netmask => $netmask,
+ family => $family,
+ onboot => $onboot,
+ options => {
+ 'BONDING_OPTS' => $bonding_opts,
+ }
+ }
+
+ network_config { $slaves:
+ ensure => $ensure,
+ method => static,
+ onboot => true,
+ options => {
+ 'MASTER' => $name,
+ 'SLAVE' => 'yes',
+ }
+ }
+}
+
View
14 manifests/bond/setup.pp
@@ -0,0 +1,14 @@
+class network::bond::setup {
+
+ case $osfamily {
+ RedHat: {
+ # Redhat installs the ifenslave command with the iputils package which
+ # is available by default
+ }
+ Debian: {
+ package { 'ifenslave':
+ ensure => present,
+ }
+ }
+ }
+}
View
9 spec/classes/bond/setup_spec.rb
@@ -0,0 +1,9 @@
+require 'spec_helper'
+
+describe 'network::bond::setup', :type => :class do
+ describe 'on Debian' do
+ let(:facts) {{:osfamily => 'Debian'}}
+
+ it { should contain_package('ifenslave') }
+ end
+end
View
96 spec/defines/bond/debian_spec.rb
@@ -0,0 +1,96 @@
+require 'spec_helper'
+
+describe 'network::bond::debian', :type => :define do
+ let(:title) { 'bond0' }
+
+ describe "with default bonding params" do
+ let(:params) do
+ {
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'ipaddress' => '172.18.1.2',
+ 'netmask' => '255.255.128.0',
+ 'slaves' => ['eth0', 'eth1'],
+
+ 'mode' => 'active-backup',
+ 'miimon' => '100',
+ 'downdelay' => '200',
+ 'updelay' => '200',
+ 'lacp_rate' => 'slow',
+ 'primary' => 'eth0',
+ 'primary_reselect' => 'always',
+ 'xmit_hash_policy' => 'layer2',
+ }
+ end
+
+ ['eth0', 'eth1'].each do |slave|
+ it "should add a network_config resource for #{slave}" do
+ should contain_network_config(slave).with_ensure('absent')
+ end
+ end
+
+ it "should add a network_config resource for bond0" do
+ pending "rspec-puppet support for unordered hash matching"
+ should contain_network_config('bond0').with({
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'ipaddress' => '172.18.1.2',
+ 'netmask' => '255.255.128.0',
+ 'options' => {
+ 'bond-slaves' => 'eth0 eth1',
+ 'bond-mode' => 'active-backup',
+ 'bond-miimon' => '100',
+ 'bond-downdelay' => '200',
+ 'bond-updelay' => '200',
+ 'bond-lacp-rate' => 'slow',
+ 'bond-primary' => 'eth0',
+ 'bond-primary-reselect' => 'always',
+ 'bond-xmit-hash-policy' => 'layer2',
+ },
+ })
+ end
+ end
+
+ describe "with non-default bonding params" do
+ let(:params) do
+ {
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'ipaddress' => '10.20.2.1',
+ 'netmask' => '255.255.255.192',
+ 'slaves' => ['eth0', 'eth1', 'eth2'],
+
+ 'mode' => 'balance-rr',
+ 'miimon' => '50',
+ 'downdelay' => '100',
+ 'updelay' => '100',
+ 'lacp_rate' => 'fast',
+ 'xmit_hash_policy' => 'layer3+4',
+ }
+ end
+ ['eth0', 'eth1', 'eth2'].each do |slave|
+ it "should add a network_config resource for #{slave}" do
+ should contain_network_config(slave).with_ensure('absent')
+ end
+ end
+
+ it "should add a network_config resource for bond0" do
+ pending "rspec-puppet support for unordered hash matching"
+ should contain_network_config('bond0').with({
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'ipaddress' => '10.20.2.1',
+ 'netmask' => '255.255.255.192',
+ 'options' => {
+ 'bond-slaves' => 'eth0 eth1 eth2',
+ 'bond-mode' => 'balance-rr',
+ 'bond-miimon' => '50',
+ 'bond-downdelay' => '100',
+ 'bond-updelay' => '100',
+ 'bond-lacp-rate' => 'fast',
+ 'bond-xmit-hash-policy' => 'layer3+4',
+ },
+ })
+ end
+ end
+end
View
96 spec/defines/bond/redhat_spec.rb
@@ -0,0 +1,96 @@
+require 'spec_helper'
+
+describe 'network::bond::redhat', :type => :define do
+ let(:title) { 'bond0' }
+
+ describe "with default bonding params" do
+ let(:params) do
+ {
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'ipaddress' => '172.18.1.2',
+ 'netmask' => '255.255.128.0',
+ 'slaves' => ['eth0', 'eth1'],
+
+ 'mode' => 'active-backup',
+ 'miimon' => '100',
+ 'downdelay' => '200',
+ 'updelay' => '200',
+ 'lacp_rate' => 'slow',
+ 'primary' => 'eth0',
+ 'primary_reselect' => 'always',
+ 'xmit_hash_policy' => 'layer2',
+ }
+ end
+
+ ['eth0', 'eth1'].each do |slave|
+ it "should add a network_config resource for #{slave}" do
+ should contain_network_config(slave).with({
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'onboot' => true,
+ 'options' => {
+ 'MASTER' => 'bond0',
+ 'SLAVE' => 'yes',
+ },
+ })
+ end
+ end
+
+ it "should add a network_config resource for bond0" do
+ should contain_network_config('bond0').with({
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'ipaddress' => '172.18.1.2',
+ 'netmask' => '255.255.128.0',
+ 'options' => {
+ 'BONDING_OPTS' => 'mode=active-backup miimon=100 downdelay=200 updelay=200 lacp_rate=slow primary=eth0 primary_reselect=always xmit_hash_policy=layer2',
+ },
+ })
+ end
+ end
+
+ describe "with non-default bonding params" do
+ let(:params) do
+ {
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'ipaddress' => '10.20.2.1',
+ 'netmask' => '255.255.255.192',
+ 'slaves' => ['eth0', 'eth1', 'eth2'],
+
+ 'mode' => 'balance-rr',
+ 'miimon' => '50',
+ 'downdelay' => '100',
+ 'updelay' => '100',
+ 'lacp_rate' => 'fast',
+ 'xmit_hash_policy' => 'layer3+4',
+ }
+ end
+ ['eth0', 'eth1', 'eth2'].each do |slave|
+ it "should add a network_config resource for #{slave}" do
+ should contain_network_config(slave).with({
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'onboot' => true,
+ 'options' => {
+ 'MASTER' => 'bond0',
+ 'SLAVE' => 'yes',
+ },
+ })
+ end
+ end
+
+ it "should add a network_config resource for bond0" do
+ should contain_network_config('bond0').with({
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'ipaddress' => '10.20.2.1',
+ 'netmask' => '255.255.255.192',
+ 'options' => {
+ 'BONDING_OPTS' => 'mode=balance-rr miimon=50 downdelay=100 updelay=100 lacp_rate=fast xmit_hash_policy=layer3+4',
+ },
+ })
+ end
+ end
+end
View
71 spec/defines/bond_spec.rb
@@ -0,0 +1,71 @@
+require 'spec_helper'
+
+describe 'network::bond', :type => :define do
+ let(:title) { 'bond0' }
+
+ let(:params) do
+ {
+ 'ensure' => 'present',
+ 'method' => 'static',
+ 'ipaddress' => '172.18.1.2',
+ 'netmask' => '255.255.128.0',
+ 'slaves' => ['eth0', 'eth1'],
+
+ 'mode' => 'active-backup',
+ 'miimon' => '100',
+ 'downdelay' => '200',
+ 'updelay' => '200',
+ 'lacp_rate' => 'slow',
+ 'primary' => 'eth0',
+ 'primary_reselect' => 'always',
+ 'xmit_hash_policy' => 'layer2',
+ }
+ end
+
+ describe 'on platform' do
+ describe 'RedHat' do
+ let(:facts) {{:osfamily => 'RedHat'}}
+
+ it "should create 'network::bond::redhat'" do
+ should contain_network__bond__redhat('bond0')
+ end
+
+ it "should forward all options to 'network::bond::redhat'" do
+ should contain_network__bond__redhat('bond0').with(params)
+ end
+ end
+
+ describe 'Debian' do
+ let(:facts) {{:osfamily => 'Debian'}}
+
+ it "should create 'network::bond::debian'" do
+ should contain_network__bond__debian('bond0')
+ end
+
+ it "should forward all options to 'network::bond::debian'" do
+ should contain_network__bond__debian('bond0').with(params)
+ end
+ end
+
+ describe 'on an unsupported osfamily' do
+ let(:facts) {{:osfamily => 'SparrowOS'}}
+
+ it "should fail to compile" do
+ expect { subject }.to raise_error Puppet::Error, /network::bond does not support osfamily 'SparrowOS'/
+ end
+ end
+ end
+
+ describe 'configuring the kernel bonding device' do
+ let(:facts) {{:osfamily => 'Debian'}}
+
+ it { should include_class('network::bond::setup') }
+
+ it "should add a kernel module alias for the bonded device" do
+ should contain_kmod__alias('bond0').with({
+ :source => 'bonding',
+ :ensure => 'present',
+ })
+ end
+ end
+end
View
0 spec/fixtures/manifests/site.pp
No changes.
View
1 spec/fixtures/modules/network/files
View
1 spec/fixtures/modules/network/lib
View
1 spec/fixtures/modules/network/manifests
View
1 spec/fixtures/modules/network/templates
View
11 spec/fixtures/provider/network_config/interfaces_spec/single_interface_options
@@ -0,0 +1,11 @@
+# This file describes the network interfaces available on your system
+# and how to activate them. For more information, see interfaces(5).
+
+# The loopback network interface
+auto lo
+iface lo inet loopback
+
+iface eth0 inet dhcp
+pre-up /bin/touch /tmp/eth0-up
+post-down /bin/touch /tmp/eth0-down1
+post-down /bin/touch /tmp/eth0-down2
View
17 spec/spec_helper.rb
@@ -1,9 +1,24 @@
+require 'rspec'
require 'puppet'
+require 'rspec-puppet'
require 'mocha'
-PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), ".."))
+PROJECT_ROOT = File.expand_path('..', File.dirname(__FILE__))
$LOAD_PATH.unshift(File.join(PROJECT_ROOT, "lib"))
+fixture_path = File.expand_path(File.join('spec', 'fixtures'), PROJECT_ROOT)
+
RSpec.configure do |config|
config.mock_with :mocha
+
+ # ---
+ # Configuration for puppet-rspec
+
+ config.module_path = File.join(fixture_path, 'modules')
+ config.manifest_dir = File.join(fixture_path, 'manifests')
end
+
+# ---
+# Add the fixture module libdirs to the modulepath
+
+$LOAD_PATH.concat(Dir.glob(File.join(fixture_path, 'modules', '*', 'lib')))
View
27 spec/unit/provider/network_config/interfaces_spec.rb
@@ -9,7 +9,10 @@ def fixture_data(file)
end
after :each do
- described_class::Instance.reset!
+ v_level = $VERBOSE
+ $VERBOSE = nil
+ Puppet::Type::Network_config::ProviderInterfaces::Instance.reset!
+ $VERBOSE = v_level
end
describe 'provider features' do
@@ -79,10 +82,26 @@ def fixture_data(file)
}
end
- it "should parse out mapping lines"
- it "should parse out lines following mapping lines"
+ # mapping sections aren't support, and might not ever be supported.
+ # it "should parse out mapping lines"
+ # it "should parse out lines following mapping lines"
- it "should allow for multiple pre and post up sections"
+ it "should allow for multiple options sections" do
+ fixture = fixture_data('single_interface_options')
+ data = described_class.parse_file('', fixture)
+ data.find { |h| h[:name] == "eth0" }.should == {
+ :name => "eth0",
+ :family => "inet",
+ :method => "dhcp",
+ :options => {
+ "pre-up" => "/bin/touch /tmp/eth0-up",
+ "post-down" => [
+ "/bin/touch /tmp/eth0-down1",
+ "/bin/touch /tmp/eth0-down2",
+ ],
+ }
+ }
+ end
describe "when reading an invalid interfaces" do
View
1 templates/bond/opts-redhat.erb
@@ -0,0 +1 @@
+<%= %w[mode miimon downdelay updelay lacp_rate primary primary_reselect xmit_hash_policy].reject { |thing| scope[thing] == :undef }.map {|thing| "#{thing}=#{scope[thing]}"}.join(' ') -%>

0 comments on commit 01c52ba

Please sign in to comment.