Add linuxbridge mechanism support for ML2 plugin

Add support for the Linux Bridge mechanism. It includes support
for VXLAN tunneling and L2 population.

Change-Id: I0faca3d4603c6eacbbaa61adef7b742b3a262641
This commit is contained in:
Mathieu Gagné 2014-07-04 18:11:43 -04:00
parent faff95b251
commit bddd060a28
4 changed files with 364 additions and 109 deletions

View File

@ -0,0 +1,156 @@
# == Class: neutron::agents::ml2::linuxbridge
#
# Setups Linuxbridge Neutron agent for ML2 plugin.
#
# === Parameters
#
# [*package_ensure*]
# (optional) Package ensure state.
# Defaults to 'present'.
#
# [*enabled*]
# (required) Whether or not to enable the agent.
# Defaults to true.
#
# [*tunnel_types*]
# (optional) List of types of tunnels to use when utilizing tunnels.
# Supported tunnel types are: vxlan.
# Defaults to an empty list.
#
# [*local_ip*]
# (optional) Local IP address to use for VXLAN endpoints.
# Required when enabling tunneling.
# Defaults to false.
#
# [*vxlan_group*]
# (optional) Multicast group for vxlan interface. If unset, disables VXLAN
# multicast mode. Should be an Multicast IP (v4 or v6) address.
# Default to '224.0.0.1'.
#
# [*vxlan_ttl*]
# (optional) TTL for vxlan interface protocol packets..
# Default to undef.
#
# [*vxlan_tos*]
# (optional) TOS for vxlan interface protocol packets..
# Defaults to undef.
#
# [*polling_interval*]
# (optional) The number of seconds the agent will wait between
# polling for local device changes.
# Defaults to 2.
#
# [*l2_population*]
# (optional) Extension to use alongside ml2 plugin's l2population
# mechanism driver. It enables the plugin to populate VXLAN forwarding table.
# Defaults to false.
#
# [*physical_interface_mappings*]
# (optional) List of <physical_network>:<physical_interface>
# tuples mapping physical network names to agent's node-specific physical
# network interfaces. Defaults to empty list.
#
# [*firewall_driver*]
# (optional) Firewall driver for realizing neutron security group function.
# Defaults to 'neutron.agent.linux.iptables_firewall.IptablesFirewallDriver'.
#
class neutron::agents::ml2::linuxbridge (
$package_ensure = 'present',
$enabled = true,
$tunnel_types = [],
$local_ip = false,
$vxlan_group = '224.0.0.1',
$vxlan_ttl = false,
$vxlan_tos = false,
$polling_interval = 2,
$l2_population = false,
$physical_interface_mappings = [],
$firewall_driver = 'neutron.agent.linux.iptables_firewall.IptablesFirewallDriver'
) {
validate_array($tunnel_types)
validate_array($physical_interface_mappings)
include neutron::params
Package['neutron-plugin-linuxbridge-agent'] -> Neutron_plugin_linuxbridge<||>
Neutron_plugin_linuxbridge<||> ~> Service['neutron-plugin-linuxbridge-agent']
if ('vxlan' in $tunnel_types) {
if ! $local_ip {
fail('The local_ip parameter is required when vxlan tunneling is enabled')
}
if $vxlan_group {
neutron_plugin_linuxbridge { 'vxlan/vxlan_group': value => $vxlan_group }
} else {
neutron_plugin_linuxbridge { 'vxlan/vxlan_group': ensure => absent }
}
if $vxlan_ttl {
neutron_plugin_linuxbridge { 'vxlan/vxlan_ttl': value => $vxlan_ttl }
} else {
neutron_plugin_linuxbridge { 'vxlan/vxlan_ttl': ensure => absent }
}
if $vxlan_tos {
neutron_plugin_linuxbridge { 'vxlan/vxlan_tos': value => $vxlan_tos }
} else {
neutron_plugin_linuxbridge { 'vxlan/vxlan_tos': ensure => absent }
}
neutron_plugin_linuxbridge {
'vxlan/enable_vxlan': value => true;
'vxlan/local_ip': value => $local_ip;
'vxlan/l2_population': value => $l2_population;
}
} else {
neutron_plugin_linuxbridge {
'vxlan/enable_vxlan': value => false;
'vxlan/local_ip': ensure => absent;
'vxlan/vxlan_group': ensure => absent;
'vxlan/l2_population': ensure => absent;
}
}
neutron_plugin_linuxbridge {
'agent/polling_interval': value => $polling_interval;
'linux_bridge/physical_interface_mappings': value => join($physical_interface_mappings, ',');
}
if $firewall_driver {
neutron_plugin_linuxbridge { 'securitygroup/firewall_driver': value => $firewall_driver }
} else {
neutron_plugin_linuxbridge { 'securitygroup/firewall_driver': ensure => absent }
}
if $::neutron::params::linuxbridge_agent_package {
package { 'neutron-plugin-linuxbridge-agent':
ensure => $package_ensure,
name => $::neutron::params::linuxbridge_agent_package,
}
} else {
# Some platforms (RedHat) do not provide a separate
# neutron plugin linuxbridge agent package.
if ! defined(Package['neutron-plugin-linuxbridge-agent']) {
package { 'neutron-plugin-linuxbridge-agent':
ensure => $package_ensure,
name => $::neutron::params::linuxbridge_server_package,
}
}
}
if $enabled {
$service_ensure = 'running'
} else {
$service_ensure = 'stopped'
}
service { 'neutron-plugin-linuxbridge-agent':
ensure => $service_ensure,
name => $::neutron::params::linuxbridge_agent_service,
enable => $enabled,
require => Class['neutron']
}
}

View File

@ -103,16 +103,15 @@ class neutron::plugins::ml2 (
include neutron::params
Neutron_plugin_ml2<||> ~> Service <| title == 'neutron-server' |>
Neutron_plugin_ml2<||> ~> Service<| title == 'neutron-server' |>
# test mechanism drivers
validate_array($mechanism_drivers)
if ! $mechanism_drivers {
warning('Without networking mechanism driver, ml2 will not communicate with L2 agents')
}
# In RH, the link is used to start Neutron process but in Debian,
# it's used only to manage database synchronization.
# In RH, the link is used to start Neutron process but in Debian, it's used only
# to manage database synchronization.
file {'/etc/neutron/plugin.ini':
ensure => link,
target => '/etc/neutron/plugins/ml2/ml2_conf.ini'
@ -138,32 +137,10 @@ class neutron::plugins::ml2 (
vxlan_group => $vxlan_group,
}
# Configure ml2_conf.ini
neutron_plugin_ml2 {
'ml2/type_drivers': value => join($type_drivers, ',');
'ml2/tenant_network_types': value => join($tenant_network_types, ',');
'ml2/mechanism_drivers': value => join($mechanism_drivers, ',');
'securitygroup/enable_security_group': value => $enable_security_group;
}
if ('linuxbridge' in $mechanism_drivers) {
if ($::osfamily == 'RedHat') {
package { 'neutron-plugin-linuxbridge':
ensure => present,
name => $::neutron::params::linuxbridge_server_package,
}
Package['neutron-plugin-linuxbridge'] -> Neutron_plugin_linuxbridge<||>
}
if ('l2population' in $mechanism_drivers) {
neutron_plugin_linuxbridge {
'vxlan/enable_vxlan': value => true;
'vxlan/l2_population': value => true;
}
} else {
neutron_plugin_linuxbridge {
'vxlan/l2_population': value => false;
}
}
}
}

View File

@ -0,0 +1,157 @@
require 'spec_helper'
describe 'neutron::agents::ml2::linuxbridge' do
let :pre_condition do
"class { 'neutron': rabbit_password => 'passw0rd' }"
end
let :default_params do
{ :package_ensure => 'present',
:enabled => true,
:tunnel_types => [],
:local_ip => false,
:vxlan_group => '224.0.0.1',
:vxlan_ttl => false,
:vxlan_tos => false,
:polling_interval => 2,
:l2_population => false,
:physical_interface_mappings => [],
:firewall_driver => 'neutron.agent.linux.iptables_firewall.IptablesFirewallDriver' }
end
let :params do
{}
end
shared_examples_for 'neutron plugin linuxbridge agent with ml2 plugin' do
context 'with default parameters' do
it { should contain_class('neutron::params') }
it 'configures ml2_conf.ini' do
should contain_neutron_plugin_linuxbridge('agent/polling_interval').with_value(default_params[:polling_interval])
should contain_neutron_plugin_linuxbridge('linux_bridge/physical_interface_mappings').with_value(default_params[:physical_interface_mappings].join(','))
should contain_neutron_plugin_linuxbridge('securitygroup/firewall_driver').with_value(default_params[:firewall_driver])
end
it 'installs neutron linuxbridge agent package' do
if platform_params.has_key?(:linuxbridge_agent_package)
linuxbridge_agent_package = platform_params[:linuxbridge_agent_package]
else
linuxbridge_agent_package = platform_params[:linuxbridge_server_package]
end
should contain_package('neutron-plugin-linuxbridge-agent').with(
:name => linuxbridge_agent_package,
:ensure => default_params[:package_ensure]
)
should contain_package('neutron-plugin-linuxbridge-agent').with_before(/Neutron_plugin_linuxbridge\[.+\]/)
end
it 'configures neutron linuxbridge agent service' do
should contain_service('neutron-plugin-linuxbridge-agent').with(
:name => platform_params[:linuxbridge_agent_service],
:enable => true,
:ensure => 'running',
:require => 'Class[Neutron]'
)
end
it 'does not configre VXLAN tunneling' do
should contain_neutron_plugin_linuxbridge('vxlan/enable_vxlan').with_value(false)
should contain_neutron_plugin_linuxbridge('vxlan/local_ip').with_ensure('absent')
should contain_neutron_plugin_linuxbridge('vxlan/vxlan_group').with_ensure('absent')
should contain_neutron_plugin_linuxbridge('vxlan/l2_population').with_ensure('absent')
end
end
context 'with VXLAN tunneling enabled' do
before do
params.merge!({
:tunnel_types => ['vxlan'],
:local_ip => '192.168.0.10'
})
end
context 'when providing all parameters' do
it 'configures ml2_conf.ini' do
should contain_neutron_plugin_linuxbridge('vxlan/enable_vxlan').with_value(true)
should contain_neutron_plugin_linuxbridge('vxlan/local_ip').with_value(params[:local_ip])
should contain_neutron_plugin_linuxbridge('vxlan/vxlan_group').with_value(default_params[:vxlan_group])
should contain_neutron_plugin_linuxbridge('vxlan/vxlan_ttl').with_ensure('absent')
should contain_neutron_plugin_linuxbridge('vxlan/vxlan_tos').with_ensure('absent')
should contain_neutron_plugin_linuxbridge('vxlan/l2_population').with_value(default_params[:l2_population])
end
end
context 'when not providing or overriding some parameters' do
before do
params.merge!({
:vxlan_group => '224.0.0.2',
:vxlan_ttl => 10,
:vxlan_tos => 2,
:l2_population => true,
})
end
it 'configures ml2_conf.ini' do
should contain_neutron_plugin_linuxbridge('vxlan/enable_vxlan').with_value(true)
should contain_neutron_plugin_linuxbridge('vxlan/local_ip').with_value(params[:local_ip])
should contain_neutron_plugin_linuxbridge('vxlan/vxlan_group').with_value(params[:vxlan_group])
should contain_neutron_plugin_linuxbridge('vxlan/vxlan_ttl').with_value(params[:vxlan_ttl])
should contain_neutron_plugin_linuxbridge('vxlan/vxlan_tos').with_value(params[:vxlan_tos])
should contain_neutron_plugin_linuxbridge('vxlan/l2_population').with_value(params[:l2_population])
end
end
end
context 'when providing the physical_interface_mappings parameter' do
before do
params.merge!(:physical_interface_mappings => ['physnet0:eth0', 'physnet1:eth1'])
end
it 'configures physical interface mappings' do
should contain_neutron_plugin_linuxbridge('linux_bridge/physical_interface_mappings').with_value(
params[:physical_interface_mappings].join(',')
)
end
end
context 'with firewall_driver parameter set to false' do
before :each do
params.merge!(:firewall_driver => false)
end
it 'removes firewall driver configuration' do
should contain_neutron_plugin_linuxbridge('securitygroup/firewall_driver').with_ensure('absent')
end
end
end
context 'on Debian platforms' do
let :facts do
{ :osfamily => 'Debian' }
end
let :platform_params do
{ :linuxbridge_agent_package => 'neutron-plugin-linuxbridge-agent',
:linuxbridge_agent_service => 'neutron-plugin-linuxbridge-agent' }
end
it_configures 'neutron plugin linuxbridge agent with ml2 plugin'
end
context 'on RedHat platforms' do
let :facts do
{ :osfamily => 'RedHat' }
end
let :platform_params do
{ :linuxbridge_server_package => 'openstack-neutron-linuxbridge',
:linuxbridge_agent_service => 'neutron-linuxbridge-agent' }
end
it_configures 'neutron plugin linuxbridge agent with ml2 plugin'
end
end

View File

@ -50,7 +50,7 @@ describe 'neutron::plugins::ml2' do
it { should contain_class('neutron::params') }
it 'configure neutron.conf' do
it 'configures neutron.conf' do
should contain_neutron_config('DEFAULT/core_plugin').with_value('neutron.plugins.ml2.plugin.Ml2Plugin')
end
@ -60,7 +60,7 @@ describe 'neutron::plugins::ml2' do
should contain_neutron_plugin_ml2('ml2/mechanism_drivers').with_value(p[:mechanism_drivers].join(','))
end
it 'should create plugin symbolic link' do
it 'creates plugin symbolic link' do
should contain_file('/etc/neutron/plugin.ini').with(
:ensure => 'link',
:target => '/etc/neutron/plugins/ml2/ml2_conf.ini'
@ -77,17 +77,12 @@ describe 'neutron::plugins::ml2' do
end
end
it 'configures linux bridge plugin' do
should_not contain_neutron_plugin_linuxbridge('vxlan/enable_vxlan').with('value' => true)
should_not contain_neutron_plugin_linuxbridge('vxlan/l2_population').with('value' => true)
end
context 'configure ml2 with bad driver value' do
before :each do
params.merge!(:type_drivers => ['foobar'])
end
it 'should fails to configure ml2 because foobar is not a valid driver' do
expect { subject }.to raise_error(Puppet::Error, /type_driver unknown./)
it 'fails to configure ml2 because foobar is not a valid driver' do
expect { subject }.to raise_error(Puppet::Error, /type_driver unknown./)
end
end
@ -95,7 +90,7 @@ describe 'neutron::plugins::ml2' do
before :each do
params.merge!(:flat_networks => ['eth1', 'eth2'])
end
it 'should configure flat_networks' do
it 'configures flat_networks' do
should contain_neutron_plugin_ml2('ml2_type_flat/flat_networks').with_value(p[:flat_networks].join(','))
end
end
@ -104,7 +99,7 @@ describe 'neutron::plugins::ml2' do
before :each do
params.merge!(:tunnel_id_ranges => ['0:20', '40:60'])
end
it 'should configure gre_networks with valid ranges' do
it 'configures gre_networks with valid ranges' do
should contain_neutron_plugin_ml2('ml2_type_gre/tunnel_id_ranges').with_value(p[:tunnel_id_ranges].join(','))
end
end
@ -113,8 +108,8 @@ describe 'neutron::plugins::ml2' do
before :each do
params.merge!(:tunnel_id_ranges => ['0:20', '40:100000000'])
end
it 'should fails to configure gre_networks because of too big range' do
expect { subject }.to raise_error(Puppet::Error, /tunnel id ranges are to large./)
it 'fails to configure gre_networks because of too big range' do
expect { subject }.to raise_error(Puppet::Error, /tunnel id ranges are to large./)
end
end
@ -122,83 +117,54 @@ describe 'neutron::plugins::ml2' do
before :each do
params.merge!(:network_vlan_ranges => ['1:20', '400:4094'])
end
it 'should configure vlan_networks with 1:20 and 400:4094 VLAN ranges' do
it 'configures vlan_networks with 1:20 and 400:4094 VLAN ranges' do
should contain_neutron_plugin_ml2('ml2_type_vlan/network_vlan_ranges').with_value(p[:network_vlan_ranges].join(','))
end
end
context 'when using vlan driver with invalid vlan id' do
before :each do
params.merge!(:network_vlan_ranges => ['1:20', '400:4099'])
end
it 'should fails to configure vlan_networks because of 400:4099 VLAN range' do
expect { subject }.to raise_error(Puppet::Error, /vlan id are invalid./)
end
end
context 'when using vlan driver with invalid vlan range' do
before :each do
params.merge!(:network_vlan_ranges => ['2938:1'])
end
it 'should fails to configure network_vlan_ranges with 2938:1 range' do
expect { subject }.to raise_error(Puppet::Error, /vlan ranges are invalid./)
end
end
context 'when using vxlan driver with valid values' do
before :each do
params.merge!(:vni_ranges => ['40:300', '500:1000'], :vxlan_group => '224.1.1.1')
end
it 'should configure vxlan_networks with 224.1.1.1 vxlan group' do
should contain_neutron_plugin_ml2('ml2_type_vxlan/vni_ranges').with_value(p[:vni_ranges].join(','))
should contain_neutron_plugin_ml2('ml2_type_vxlan/vxlan_group').with_value(p[:vxlan_group])
end
end
context 'when using vxlan driver with invalid vxlan group' do
before :each do
params.merge!(:vxlan_group => '192.1.1.1')
end
it 'should fails to configure vxlan_group with 192.1.1.1 vxlan group' do
expect { subject }.to raise_error(Puppet::Error, /is not valid for vxlan_group./)
end
end
context 'when using vxlan driver with invalid vni_range' do
before :each do
params.merge!(:vni_ranges => ['2938:1'])
end
it 'should fails to configure vni_ranges with 2938:1 range' do
expect { subject }.to raise_error(Puppet::Error, /vni ranges are invalid./)
end
end
context 'when using l2population with linuxbridge' do
before :each do
params.merge!(:mechanism_drivers => ['linuxbridge','l2population'])
end
it 'should set l2_population flag as true' do
should contain_neutron_plugin_linuxbridge('vxlan/enable_vxlan').with_value('true')
should contain_neutron_plugin_linuxbridge('vxlan/l2_population').with_value('true')
end
end
end
shared_examples_for 'neutron plugin ml2 on RedHat' do
let :p do
default_params.merge(params)
context 'when using vlan driver with invalid vlan id' do
before :each do
params.merge!(:network_vlan_ranges => ['1:20', '400:4099'])
end
it 'fails to configure vlan_networks because of 400:4099 VLAN range' do
expect { subject }.to raise_error(Puppet::Error, /vlan id are invalid./)
end
end
context 'when using linuxbridge' do
context 'when using vlan driver with invalid vlan range' do
before :each do
params.merge!(:mechanism_drivers => ['linuxbridge'])
params.merge!(:network_vlan_ranges => ['2938:1'])
end
it 'installs linuxbridge package' do
should contain_package('neutron-plugin-linuxbridge').with(
:ensure => 'present'
)
should contain_package('neutron-plugin-linuxbridge').with_before(/Neutron_plugin_linuxbridge\[.+\]/)
it 'fails to configure network_vlan_ranges with 2938:1 range' do
expect { subject }.to raise_error(Puppet::Error, /vlan ranges are invalid./)
end
end
context 'when using vxlan driver with valid values' do
before :each do
params.merge!(:vni_ranges => ['40:300', '500:1000'], :vxlan_group => '224.1.1.1')
end
it 'configures vxlan_networks with 224.1.1.1 vxlan group' do
should contain_neutron_plugin_ml2('ml2_type_vxlan/vni_ranges').with_value(p[:vni_ranges].join(','))
should contain_neutron_plugin_ml2('ml2_type_vxlan/vxlan_group').with_value(p[:vxlan_group])
end
end
context 'when using vxlan driver with invalid vxlan group' do
before :each do
params.merge!(:vxlan_group => '192.1.1.1')
end
it 'fails to configure vxlan_group with 192.1.1.1 vxlan group' do
expect { subject }.to raise_error(Puppet::Error, /is not valid for vxlan_group./)
end
end
context 'when using vxlan driver with invalid vni_range' do
before :each do
params.merge!(:vni_ranges => ['2938:1'])
end
it 'fails to configure vni_ranges with 2938:1 range' do
expect { subject }.to raise_error(Puppet::Error, /vni ranges are invalid./)
end
end
end
@ -225,7 +191,6 @@ describe 'neutron::plugins::ml2' do
end
it_configures 'neutron plugin ml2'
it_configures 'neutron plugin ml2 on RedHat'
end
end