From c4aafdd3b34cd363b819b6d9b8a415ef6dcf7ef7 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Thu, 18 Sep 2014 14:21:03 -0400 Subject: [PATCH] Enable DVR + HA support Juno brings two new big features: - distributed routers - router high availability This patchs aims to allow the users to configure DVR and/or HA routers. Signed-off-by: Emilien Macchi Change-Id: Iaab5ab7e63f2627381ca1d5bb1cfd836433d734e --- manifests/agents/l3.pp | 39 ++++++- manifests/agents/ml2/ovs.pp | 47 ++++---- manifests/server.pp | 113 +++++++++++++------- spec/classes/neutron_agents_l3_spec.rb | 28 ++++- spec/classes/neutron_agents_ml2_ovs_spec.rb | 47 +++++--- spec/classes/neutron_server_spec.rb | 81 +++++++++++--- 6 files changed, 270 insertions(+), 85 deletions(-) diff --git a/manifests/agents/l3.pp b/manifests/agents/l3.pp index 5465d6118..1748c1217 100644 --- a/manifests/agents/l3.pp +++ b/manifests/agents/l3.pp @@ -76,6 +76,29 @@ # (optional) namespaces can be deleted cleanly on the host running the L3 agent # Defaults to False # +# [*ha_enabled*] +# (optional) Enabled or not HA for L3 agent. +# Defaults to false +# +# [*ha_vrrp_auth_type*] +# (optional) VRRP authentication type. Can be AH or PASS. +# Defaults to "PASS" +# +# [*ha_vrrp_auth_password*] +# (optional) VRRP authentication password. Required if ha_enabled = true. +# Defaults to undef +# +# [*ha_vrrp_advert_int*] +# (optional) The advertisement interval in seconds. +# Defaults to '2' +# +# [*agent_mode*] +# (optional) The working mode for the agent. +# 'legacy': default behavior (without DVR) +# 'dvr': enable DVR for an L3 agent running on compute node (DVR in production) +# 'dvr_snat': enable DVR with centralized SNAT support (DVR for single-host, for testing only) +# Defaults to 'legacy' +# class neutron::agents::l3 ( $package_ensure = 'present', $enabled = true, @@ -93,7 +116,12 @@ $periodic_fuzzy_delay = '5', $enable_metadata_proxy = true, $network_device_mtu = undef, - $router_delete_namespaces = false + $router_delete_namespaces = false, + $ha_enabled = false, + $ha_vrrp_auth_type = 'PASS', + $ha_vrrp_auth_password = undef, + $ha_vrrp_advert_int = '3', + $agent_mode = 'legacy', ) { include neutron::params @@ -101,6 +129,14 @@ Neutron_config<||> ~> Service['neutron-l3'] Neutron_l3_agent_config<||> ~> Service['neutron-l3'] + if $ha_enabled { + neutron_l3_agent_config { + 'DEFAULT/ha_vrrp_auth_type': value => $ha_vrrp_auth_type; + 'DEFAULT/ha_vrrp_auth_password': value => $ha_vrrp_auth_password; + 'DEFAULT/ha_vrrp_advert_int': value => $ha_vrrp_advert_int; + } + } + neutron_l3_agent_config { 'DEFAULT/debug': value => $debug; 'DEFAULT/external_network_bridge': value => $external_network_bridge; @@ -115,6 +151,7 @@ 'DEFAULT/periodic_fuzzy_delay': value => $periodic_fuzzy_delay; 'DEFAULT/enable_metadata_proxy': value => $enable_metadata_proxy; 'DEFAULT/router_delete_namespaces': value => $router_delete_namespaces; + 'DEFAULT/agent_mode': value => $agent_mode; } if $network_device_mtu { diff --git a/manifests/agents/ml2/ovs.pp b/manifests/agents/ml2/ovs.pp index 34c1ddbad..709a87fb7 100644 --- a/manifests/agents/ml2/ovs.pp +++ b/manifests/agents/ml2/ovs.pp @@ -83,21 +83,27 @@ # (optional) Firewall driver for realizing neutron security group function. # Defaults to 'neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver'. # +# [*enable_distributed_routing*] +# (optional) Set to True on L2 agents to enable support +# for distributed virtual routing. +# Defaults to false +# class neutron::agents::ml2::ovs ( - $package_ensure = 'present', - $enabled = true, - $bridge_uplinks = [], - $bridge_mappings = [], - $integration_bridge = 'br-int', - $enable_tunneling = false, - $tunnel_types = [], - $local_ip = false, - $tunnel_bridge = 'br-tun', - $vxlan_udp_port = 4789, - $polling_interval = 2, - $l2_population = false, - $arp_responder = false, - $firewall_driver = 'neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver' + $package_ensure = 'present', + $enabled = true, + $bridge_uplinks = [], + $bridge_mappings = [], + $integration_bridge = 'br-int', + $enable_tunneling = false, + $tunnel_types = [], + $local_ip = false, + $tunnel_bridge = 'br-tun', + $vxlan_udp_port = 4789, + $polling_interval = 2, + $l2_population = false, + $arp_responder = false, + $firewall_driver = 'neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver', + $enable_distributed_routing = false, ) { include neutron::params @@ -107,6 +113,10 @@ fail('Local ip for ovs agent must be set when tunneling is enabled') } + if $enable_distributed_routing and ! $l2_population { + fail('L2 population must be enabled when DVR is enabled') + } + Neutron_plugin_ml2<||> ~> Service['neutron-ovs-agent-service'] if ($bridge_mappings != []) { @@ -137,10 +147,11 @@ } neutron_plugin_ml2 { - 'agent/polling_interval': value => $polling_interval; - 'agent/l2_population': value => $l2_population; - 'agent/arp_responder': value => $arp_responder; - 'ovs/integration_bridge': value => $integration_bridge; + 'agent/polling_interval': value => $polling_interval; + 'agent/l2_population': value => $l2_population; + 'agent/arp_responder': value => $arp_responder; + 'agent/enable_distributed_routing': value => $enable_distributed_routing; + 'ovs/integration_bridge': value => $integration_bridge; } if ($firewall_driver) { diff --git a/manifests/server.pp b/manifests/server.pp index 5325150c6..98025ca81 100644 --- a/manifests/server.pp +++ b/manifests/server.pp @@ -153,44 +153,71 @@ # [*mysql_module*] # (optional) Deprecated. Does nothing. # +# [*router_distributed*] +# (optional) Setting the "router_distributed" flag to "True" will default to the creation +# of distributed tenant routers. +# Also can be the type of the router on the create request (admin-only attribute). +# Defaults to false +# +# [*l3_ha*] +# (optional) Enable high availability for virtual routers. +# Defaults to false +# +# [*max_l3_agents_per_router*] +# (optional) Maximum number of l3 agents which a HA router will be scheduled on. If set to '0', a router will be scheduled on every agent. +# Defaults to '3' +# +# [*min_l3_agents_per_router*] +# (optional) Minimum number of l3 agents which a HA router will be scheduled on. +# Defaults to '2' +# +# [*l3_ha_net_cidr*] +# (optional) CIDR of the administrative network if HA mode is enabled. +# Defaults to '169.254.192.0/18' +# class neutron::server ( - $package_ensure = 'present', - $enabled = true, - $manage_service = true, - $auth_password = false, - $auth_type = 'keystone', - $auth_host = 'localhost', - $auth_port = '35357', - $auth_admin_prefix = false, - $auth_tenant = 'services', - $auth_user = 'neutron', - $auth_protocol = 'http', - $auth_uri = false, - $database_connection = 'sqlite:////var/lib/neutron/ovs.sqlite', - $database_max_retries = 10, - $database_idle_timeout = 3600, - $database_retry_interval = 10, - $database_min_pool_size = 1, - $database_max_pool_size = 10, - $database_max_overflow = 20, - $sync_db = false, - $api_workers = $::processorcount, - $rpc_workers = $::processorcount, - $agent_down_time = '75', - $router_scheduler_driver = 'neutron.scheduler.l3_agent_scheduler.ChanceScheduler', + $package_ensure = 'present', + $enabled = true, + $manage_service = true, + $auth_password = false, + $auth_type = 'keystone', + $auth_host = 'localhost', + $auth_port = '35357', + $auth_admin_prefix = false, + $auth_tenant = 'services', + $auth_user = 'neutron', + $auth_protocol = 'http', + $auth_uri = false, + $database_connection = 'sqlite:////var/lib/neutron/ovs.sqlite', + $database_max_retries = 10, + $database_idle_timeout = 3600, + $database_retry_interval = 10, + $database_min_pool_size = 1, + $database_max_pool_size = 10, + $database_max_overflow = 20, + $sync_db = false, + $api_workers = $::processorcount, + $rpc_workers = $::processorcount, + $agent_down_time = '75', + $router_scheduler_driver = 'neutron.scheduler.l3_agent_scheduler.ChanceScheduler', + $router_distributed = false, + $l3_ha = false, + $max_l3_agents_per_router = 3, + $min_l3_agents_per_router = 2, + $l3_ha_net_cidr = '169.254.192.0/18', # DEPRECATED PARAMETERS - $mysql_module = undef, - $sql_connection = undef, - $connection = undef, - $sql_max_retries = undef, - $max_retries = undef, - $sql_idle_timeout = undef, - $idle_timeout = undef, - $sql_reconnect_interval = undef, - $retry_interval = undef, - $log_dir = undef, - $log_file = undef, - $report_interval = undef, + $mysql_module = undef, + $sql_connection = undef, + $connection = undef, + $sql_max_retries = undef, + $max_retries = undef, + $sql_idle_timeout = undef, + $idle_timeout = undef, + $sql_reconnect_interval = undef, + $retry_interval = undef, + $log_dir = undef, + $log_file = undef, + $report_interval = undef, ) { include neutron::params @@ -200,6 +227,19 @@ Neutron_config<||> ~> Service['neutron-server'] Neutron_api_config<||> ~> Service['neutron-server'] + if $l3_ha { + if $min_l3_agents_per_router <= $max_l3_agents_per_router or $max_l3_agents_per_router == '0' { + neutron_config { + 'DEFAULT/ha_enabled': value => true; + 'DEFAULT/max_l3_agents_per_router': value => $max_l3_agents_per_router; + 'DEFAULT/min_l3_agents_per_router': value => $min_l3_agents_per_router; + 'DEFAULT/l3_ha_net_cidr': value => $l3_ha_net_cidr; + } + } else { + fail('min_l3_agents_per_router should be less than or equal to max_l3_agents_per_router.') + } + } + if $mysql_module { warning('The mysql_module parameter is deprecated. The latest 2.x mysql module will be used.') } @@ -296,6 +336,7 @@ 'DEFAULT/rpc_workers': value => $rpc_workers; 'DEFAULT/agent_down_time': value => $agent_down_time; 'DEFAULT/router_scheduler_driver': value => $router_scheduler_driver; + 'DEFAULT/router_distributed': value => $router_distributed; 'database/connection': value => $database_connection_real, secret => true; 'database/idle_timeout': value => $database_idle_timeout_real; 'database/retry_interval': value => $database_retry_interval_real; diff --git a/spec/classes/neutron_agents_l3_spec.rb b/spec/classes/neutron_agents_l3_spec.rb index b3d773703..a7301fd7b 100644 --- a/spec/classes/neutron_agents_l3_spec.rb +++ b/spec/classes/neutron_agents_l3_spec.rb @@ -22,7 +22,12 @@ :periodic_fuzzy_delay => '5', :enable_metadata_proxy => true, :network_device_mtu => nil, - :router_delete_namespaces => false } + :router_delete_namespaces => false, + :ha_enabled => false, + :ha_vrrp_auth_type => 'PASS', + :ha_vrrp_auth_password => nil, + :ha_vrrp_advert_int => '3', + :agent_mode => 'legacy' } end let :params do @@ -83,6 +88,27 @@ should contain_service('neutron-l3').without_ensure end end + + context 'with DVR' do + before :each do + params.merge!(:agent_mode => 'dvr') + end + it 'should enable DVR mode' do + should contain_neutron_l3_agent_config('DEFAULT/agent_mode').with_value(p[:agent_mode]) + end + end + + context 'with HA routers' do + before :each do + params.merge!(:ha_enabled => true, + :ha_vrrp_auth_password => 'secrete') + end + it 'should configure VRRP' do + should contain_neutron_l3_agent_config('DEFAULT/ha_vrrp_auth_type').with_value(p[:ha_vrrp_auth_type]) + should contain_neutron_l3_agent_config('DEFAULT/ha_vrrp_auth_password').with_value(p[:ha_vrrp_auth_password]) + should contain_neutron_l3_agent_config('DEFAULT/ha_vrrp_advert_int').with_value(p[:ha_vrrp_advert_int]) + end + end end shared_examples_for 'neutron l3 agent with network_device_mtu specified' do diff --git a/spec/classes/neutron_agents_ml2_ovs_spec.rb b/spec/classes/neutron_agents_ml2_ovs_spec.rb index a4e9f77a1..d9c9dc539 100644 --- a/spec/classes/neutron_agents_ml2_ovs_spec.rb +++ b/spec/classes/neutron_agents_ml2_ovs_spec.rb @@ -7,18 +7,19 @@ end let :default_params do - { :package_ensure => 'present', - :enabled => true, - :bridge_uplinks => [], - :bridge_mappings => [], - :integration_bridge => 'br-int', - :enable_tunneling => false, - :local_ip => false, - :tunnel_bridge => 'br-tun', - :polling_interval => 2, - :l2_population => false, - :arp_responder => false, - :firewall_driver => 'neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver' } + { :package_ensure => 'present', + :enabled => true, + :bridge_uplinks => [], + :bridge_mappings => [], + :integration_bridge => 'br-int', + :enable_tunneling => false, + :local_ip => false, + :tunnel_bridge => 'br-tun', + :polling_interval => 2, + :l2_population => false, + :arp_responder => false, + :enable_distributed_routing => false, + :firewall_driver => 'neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver' } end let :params do @@ -90,6 +91,16 @@ end end + context 'when enabling DVR' do + before :each do + params.merge!(:enable_distributed_routing => true, + :l2_population => true ) + end + it 'should enable DVR' do + should contain_neutron_plugin_ml2('agent/enable_distributed_routing').with_value(true) + end + end + context 'when supplying bridge mappings for provider networks' do before :each do params.merge!(:bridge_uplinks => ['br-ex:eth2'],:bridge_mappings => ['default:br-ex']) @@ -151,6 +162,18 @@ should contain_neutron_plugin_ml2('agent/vxlan_udp_port').with_value(params[:vxlan_udp_port]) end end + + context 'when l2 population is disabled and DVR enabled' do + before :each do + params.merge!(:enable_distributed_routing => true, + :l2_population => false ) + end + it 'should fail' do + expect do + subject + end.to raise_error(Puppet::Error, /L2 population must be enabled when DVR is enabled/) + end + end end end diff --git a/spec/classes/neutron_server_spec.rb b/spec/classes/neutron_server_spec.rb index a3f14f21f..5e601ff6a 100644 --- a/spec/classes/neutron_server_spec.rb +++ b/spec/classes/neutron_server_spec.rb @@ -12,23 +12,28 @@ end let :default_params do - { :package_ensure => 'present', - :enabled => true, - :auth_type => 'keystone', - :auth_host => 'localhost', - :auth_port => '35357', - :auth_tenant => 'services', - :auth_user => 'neutron', - :database_connection => 'sqlite:////var/lib/neutron/ovs.sqlite', - :database_max_retries => '10', - :database_idle_timeout => '3600', - :database_retry_interval => '10', - :database_min_pool_size => '1', - :database_max_pool_size => '10', - :database_max_overflow => '20', - :sync_db => false, - :agent_down_time => '75', - :router_scheduler_driver => 'neutron.scheduler.l3_agent_scheduler.ChanceScheduler', + { :package_ensure => 'present', + :enabled => true, + :auth_type => 'keystone', + :auth_host => 'localhost', + :auth_port => '35357', + :auth_tenant => 'services', + :auth_user => 'neutron', + :database_connection => 'sqlite:////var/lib/neutron/ovs.sqlite', + :database_max_retries => '10', + :database_idle_timeout => '3600', + :database_retry_interval => '10', + :database_min_pool_size => '1', + :database_max_pool_size => '10', + :database_max_overflow => '20', + :sync_db => false, + :agent_down_time => '75', + :router_scheduler_driver => 'neutron.scheduler.l3_agent_scheduler.ChanceScheduler', + :router_distributed => false, + :l3_ha => false, + :max_l3_agents_per_router => '3', + :min_l3_agents_per_router => '2', + :l3_ha_net_cidr => '169.254.192.0/18' } end @@ -100,6 +105,48 @@ should contain_service('neutron-server').without_ensure end end + + context 'with DVR enabled' do + before :each do + params.merge!(:router_distributed => true) + end + it 'should enable DVR' do + should contain_neutron_config('DEFAULT/router_distributed').with_value(true) + end + end + + context 'with HA routers enabled' do + before :each do + params.merge!(:l3_ha => true) + end + it 'should enable HA routers' do + should contain_neutron_config('DEFAULT/ha_enabled').with_value(true) + should contain_neutron_config('DEFAULT/max_l3_agents_per_router').with_value('3') + should contain_neutron_config('DEFAULT/min_l3_agents_per_router').with_value('2') + should contain_neutron_config('DEFAULT/l3_ha_net_cidr').with_value('169.254.192.0/18') + end + end + + context 'with HA routers enabled with unlimited l3 agents per router' do + before :each do + params.merge!(:l3_ha => true, + :max_l3_agents_per_router => '0' ) + end + it 'should enable HA routers' do + should contain_neutron_config('DEFAULT/max_l3_agents_per_router').with_value('0') + end + end + + context 'with HA routers enabled and wrong parameters' do + before :each do + params.merge!(:l3_ha => true, + :max_l3_agents_per_router => '2', + :min_l3_agents_per_router => '3' ) + end + it 'should fail to configure HA routerd' do + expect { subject }.to raise_error(Puppet::Error, /min_l3_agents_per_router should be less than or equal to max_l3_agents_per_router./) + end + end end shared_examples_for 'a neutron server with auth_admin_prefix set' do