diff --git a/ML2.md b/ML2.md new file mode 100644 index 0000000..4c9e2b1 --- /dev/null +++ b/ML2.md @@ -0,0 +1,30 @@ +james.denton@rackspace.com +July 18, 2014 + +Attributes +========== + +Neutron Networking w/ ML2 & LinuxBridge +---- + +A new plugin attribute has been added. Valid options include ovs or ml2_linuxbridge. + +A set of attributes for LinuxBridge have been added. It is not necessary to create a bridge manually; LinuxBridge does this for you. Simply specify the physical interface to use in the bridge. + +```javascript + + "plugin": "ml2_linuxbridge", + "ml2_linuxbridge": { + "provider_networks": [ + { + "label": "ph-eth1", + "bridge": "eth1", + "vlans": "" + } + ], + "network_type": "vlan", + "external_bridge": "" + } +``` + +There is no vxlan support. diff --git a/attributes/default.rb b/attributes/default.rb index 5db1063..6e7bd9a 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -75,6 +75,14 @@ "nova.virt.libvirt.vif.LibvirtHybridOVSBridgeDriver" default["neutron"]["linuxnet_interface_driver"] = "nova.network.linux_net.LinuxOVSInterfaceDriver" + +if node["neutron"]["plugin"] == "ml2_linuxbridge" + default["neutron"]["libvirt_vif_driver"] = + "nova.virt.libvirt.vif.NeutronLinuxBridgeVIFDriver" + default["neutron"]["linuxnet_interface_driver"] = + "nova.network.linux_net.NeutronLinuxBridgeInterfaceDriver" +end + default["neutron"]["firewall_driver"] = "nova.virt.firewall.NoopFirewallDriver" default['neutron']["send_arp_for_ha"] = 3 @@ -104,6 +112,11 @@ default["neutron"]["services"]["api"]["wsgi_file"] = "neutron-server" default["neutron"]["db"]["name"] = "neutron" + +if node["neutron"]["plugin"] == "ml2_linuxbridge" + default["neutron"]["db"]["name"] = "neutron_ml2" +end + default["neutron"]["db"]["username"] = "neutron" default["neutron"]["service_tenant_name"] = "service" @@ -116,8 +129,13 @@ default["neutron"]["use_namespaces"] = "True" # should correspond to overlap_ips used for dhcp agent and l3 agent. # Manage plugins here, currently only supports openvswitch (ovs) + default["neutron"]["plugin"] = "ovs" +if node["neutron"]["plugin"] == "ml2_linuxbridge" + default["neutron"]["plugin"] = "ml2_linuxbridge" +end + # dhcp agent options default["neutron"]["dhcp_lease_time"] = "1440" default["neutron"]["dhcp_domain"] = "openstacklocal" @@ -264,6 +282,12 @@ "neutron-plugin-openvswitch", "neutron-plugin-openvswitch-agent" ], + "neutron_ml2_linuxbridge_packages" => [ + "neutron-plugin-linuxbridge", + "neutron-plugin-linuxbridge-agent", + "python-pip" + ], + "neutron_linuxbridge_service_name" => "neutron-plugin-linuxbridge-agent", "neutron_ovs_service_name" => "neutron-plugin-openvswitch-agent", "neutron_openvswitch_service_name" => "openvswitch-switch", "rpcdaemon" => "rpcdaemon" diff --git a/metadata.rb b/metadata.rb index ad895b5..647a37b 100644 --- a/metadata.rb +++ b/metadata.rb @@ -11,6 +11,7 @@ recipe "neutron-dhcp-agent", "" recipe "neutron-l3-agent", "" recipe "neutron-ovs-plugin", "" +recipe "neutron-linuxbridge-plugin", "" recipe "neutron-plugin", "" recipe "neutron-server", "" recipe "rpcdaemon", "" diff --git a/recipes/neutron-common.rb b/recipes/neutron-common.rb index b44c167..b07b734 100644 --- a/recipes/neutron-common.rb +++ b/recipes/neutron-common.rb @@ -55,21 +55,43 @@ # A comma-separated list of provider network vlan ranges # => "ph-eth1:1:1000,ph-eth0:1001:1024" -vlan_ranges = node["neutron"]["ovs"]["provider_networks"].map do |network| - if network.has_key?('vlans') and not network['vlans'].empty? - network['vlans'].split(',').each do |vlan_range| - vlan_range.prepend("#{network['label']}:") +if node["neutron"]["plugin"] == "ovs" + vlan_ranges = node["neutron"]["ovs"]["provider_networks"].map do |network| + if network.has_key?('vlans') and not network['vlans'].empty? + network['vlans'].split(',').each do |vlan_range| + vlan_range.prepend("#{network['label']}:") + end + else + network['label'] end - else - network['label'] - end -end.join(',') + end.join(',') +end + +if node["neutron"]["plugin"] == "ml2_linuxbridge" + vlan_ranges = node["neutron"]["ml2_linuxbridge"]["provider_networks"].map do |network| + if network.has_key?('vlans') and not network['vlans'].empty? + network['vlans'].split(',').each do |vlan_range| + vlan_range.prepend("#{network['label']}:") + end + else + network['label'] + end + end.join(',') +end # A comma-separated list of provider network to bridge mappings # => "ph-eth1:br-eth1,ph-eth0:br-eth0" -bridge_mappings = node["neutron"]["ovs"]["provider_networks"].map do |network| - "#{network['label']}:#{network['bridge']}" -end.join(',') +if node["neutron"]["plugin"] == "ovs" + bridge_mappings = node["neutron"]["ovs"]["provider_networks"].map do |network| + "#{network['label']}:#{network['bridge']}" + end.join(',') +end + +if node["neutron"]["plugin"] == "ml2_linuxbridge" + bridge_mappings = node["neutron"]["ml2_linuxbridge"]["provider_networks"].map do |network| + "#{network['label']}:#{network['bridge']}" + end.join(',') +end # Make sure our permissions are not too, well, permissive directory "/etc/neutron/" do @@ -89,6 +111,22 @@ recursive true end +directory "/etc/neutron/plugins/ml2" do + action :create + owner "root" + group "neutron" + mode "750" + recursive true +end + +directory "/etc/neutron/plugins/linuxbridge" do + action :create + owner "root" + group "neutron" + mode "750" + recursive true +end + notification_provider = node["neutron"]["notification"]["driver"] case notification_provider when "no_op" @@ -138,6 +176,17 @@ group "neutron" end +#Drop the config file for /etc/default/neutron-server +template "/etc/default/neutron-server" do + source "neutron-server.erb" + owner "root" + group "neutron" + mode "0640" + variables( + "neutron_plugin" => node["neutron"]["plugin"] + ) +end + template "/etc/neutron/neutron.conf" do source "neutron.conf.erb" owner "root" @@ -198,28 +247,65 @@ ) end -template "/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini" do - source "ovs_neutron_plugin.ini.erb" - owner "root" - group "neutron" - mode "0640" - variables( - "db_ip_address" => mysql_info["host"], - "db_user" => neutron_info["db"]["username"], - "db_password" => neutron_info["db"]["password"], - "db_name" => neutron_info["db"]["name"], - "ovs_firewall_driver" => node["neutron"]["ovs"]["firewall_driver"], - "ovs_network_type" => node["neutron"]["ovs"]["network_type"], - "ovs_tunnel_ranges" => node["neutron"]["ovs"]["tunnel_ranges"], - "ovs_integration_bridge" => node["neutron"]["ovs"]["integration_bridge"], - "ovs_tunnel_bridge" => node["neutron"]["ovs"]["tunnel_bridge"], - "sqlalchemy_pool_size" => node["neutron"]["database"]["sqlalchemy_pool_size"], - "ovs_vlan_range" => vlan_ranges, - "ovs_bridge_mapping" => bridge_mappings, - "ovs_debug" => node["neutron"]["debug"], - "ovs_verbose" => node["neutron"]["verbose"], - "ovs_local_ip" => local_ip - ) + +if node["neutron"]["plugin"] == "ovs" + template "/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini" do + source "ovs_neutron_plugin.ini.erb" + owner "root" + group "neutron" + mode "0640" + variables( + "db_ip_address" => mysql_info["host"], + "db_user" => neutron_info["db"]["username"], + "db_password" => neutron_info["db"]["password"], + "db_name" => neutron_info["db"]["name"], + "ovs_firewall_driver" => node["neutron"]["ovs"]["firewall_driver"], + "ovs_network_type" => node["neutron"]["ovs"]["network_type"], + "ovs_tunnel_ranges" => node["neutron"]["ovs"]["tunnel_ranges"], + "ovs_integration_bridge" => node["neutron"]["ovs"]["integration_bridge"], + "ovs_tunnel_bridge" => node["neutron"]["ovs"]["tunnel_bridge"], + "sqlalchemy_pool_size" => node["neutron"]["database"]["sqlalchemy_pool_size"], + "ovs_vlan_range" => vlan_ranges, + "ovs_bridge_mapping" => bridge_mappings, + "ovs_debug" => node["neutron"]["debug"], + "ovs_verbose" => node["neutron"]["verbose"], + "ovs_local_ip" => local_ip + ) + end +end + +if node["neutron"]["plugin"] == "ml2_linuxbridge" + template "/etc/neutron/plugins/linuxbridge/linuxbridge_conf.ini" do + source "linuxbridge_conf.ini.erb" + owner "root" + group "neutron" + mode "0640" + variables( + "neutron_plugin" => node["neutron"]["plugin"], + "lb_firewall_driver" => node["neutron"]["ml2_linuxbridge"]["firewall_driver"], + "lb_network_type" => node["neutron"]["ml2_linuxbridge"]["network_type"], + "lb_vlan_range" => vlan_ranges, + "lb_bridge_mapping" => bridge_mappings, + "lb_debug" => node["neutron"]["debug"], + "lb_verbose" => node["neutron"]["verbose"] + ) + end + + template "/etc/neutron/plugins/ml2/ml2_conf.ini" do + source "ml2_conf.ini.erb" + owner "root" + group "neutron" + mode "0640" + variables( + "neutron_plugin" => node["neutron"]["plugin"], + "db_ip_address" => mysql_info["host"], + "db_user" => neutron_info["db"]["username"], + "db_password" => neutron_info["db"]["password"], + "db_name" => neutron_info["db"]["name"], + "sqlalchemy_pool_size" => node["neutron"]["database"]["sqlalchemy_pool_size"], + "lb_vlan_range" => vlan_ranges + ) + end end case node['platform'] diff --git a/recipes/neutron-l3-agent.rb b/recipes/neutron-l3-agent.rb index ea6fa43..981cc8d 100644 --- a/recipes/neutron-l3-agent.rb +++ b/recipes/neutron-l3-agent.rb @@ -46,16 +46,16 @@ subscribes :restart, "template[/etc/neutron/l3-agent.ini]", :delayed end - -execute "create external bridge" do - command "ovs-vsctl add-br #{node["neutron"]["ovs"]["external_bridge"]}" - action :run - not_if "ovs-vsctl get bridge \"#{node["neutron"]["ovs"]["external_bridge"]}\" name" - not_if { node["neutron"]["ovs"]["external_bridge"].nil? } - not_if { node["neutron"]["ovs"]["external_bridge"].empty? } +if node["neutron"]["plugin"] == "ovs" + execute "create external bridge" do + command "ovs-vsctl add-br #{node["neutron"]["ovs"]["external_bridge"]}" + action :run + not_if "ovs-vsctl get bridge \"#{node["neutron"]["ovs"]["external_bridge"]}\" name" + not_if { node["neutron"]["ovs"]["external_bridge"].nil? } + not_if { node["neutron"]["ovs"]["external_bridge"].empty? } + end end - nova_info = get_access_endpoint("nova-api-os-compute", "nova", "api") metadata_ip = @@ -67,7 +67,7 @@ group "root" mode "0644" variables( - "neutron_external_bridge" => node["neutron"][plugin]["external_bridge"], + "neutron_external_bridge" => node["neutron"]["#{node["neutron"]["plugin"]}"]["external_bridge"], "nova_metadata_ip" => metadata_ip, "neutron_plugin" => node["neutron"]["plugin"], "send_arp_for_ha" => node["neutron"]["send_arp_for_ha"] diff --git a/recipes/neutron-linuxbridge-plugin.rb b/recipes/neutron-linuxbridge-plugin.rb new file mode 100644 index 0000000..0651fdf --- /dev/null +++ b/recipes/neutron-linuxbridge-plugin.rb @@ -0,0 +1,65 @@ +# Cookbook Name:: nova-network +# Recipe:: neutron-ovs-plugin +# +# Copyright 2012-2013, Rackspace US, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include_recipe "osops-utils" +include_recipe "nova-network::neutron-common" + +platform_options = node["neutron"]["platform"] +plugin = node["neutron"]["plugin"] + +return if node["neutron"]["plugin"] == "ovs" + +platform_options["neutron_#{plugin}_packages"].each do |pkg| + package pkg do + action node["osops"]["do_package_upgrades"] == true ? :upgrade : :install + options platform_options["package_options"] + end +end + +service "neutron-plugin-linuxbridge-agent" do + service_name platform_options["neutron_linuxbridge_service_name"] + supports :status => true, :restart => true + action :enable + subscribes :restart, "template[/etc/neutron/neutron.conf]", :delayed + subscribes :restart, "template[/etc/neutron/plugins/ml2/ml2_conf.ini]", :delayed + subscribes :restart, "template[/etc/neutron/plugins/linuxbridge/linuxbridge_conf.ini]", :delayed +end + +case node['platform'] +when 'redhat', 'centos' + platform_options['epel_openstack_packages'].each do |pkg| + package pkg do + # Since these packages are already installed from [base] and we want + # to replace them, we need action :upgrade to make chef install the + # alternate versions. + # XXX Assumes versions from [epel-openstack] > [base] + action :upgrade + + # Force yum to search the epel-openstack repo. + # FIXME(brett) Don't hardcode repo name (hardcoded in osops::packages). + # Maybe dynamically get name from `yum repolist'. + options '--disablerepo="*" --enablerepo=epel-openstack' + + # To protect ourselves from future chef runs, don't always upgrade + # packages when updates are available (maybe consider checking + # 'do_package_upgrades' though?). Unfortunately the release versioning + # convention isn't consistent across packages in this repo, so we can't + # simply grep 'openstack' or similar. + not_if "rpm -q --qf '%{RELEASE}\\n' #{pkg} |grep -E '\\.el6(ost|\\.gre)\\.'" + end + end +end diff --git a/recipes/neutron-ovs-plugin.rb b/recipes/neutron-ovs-plugin.rb index a5773c5..0e8fd97 100644 --- a/recipes/neutron-ovs-plugin.rb +++ b/recipes/neutron-ovs-plugin.rb @@ -21,6 +21,7 @@ platform_options = node["neutron"]["platform"] plugin = node["neutron"]["plugin"] +return if node["neutron"]["plugin"] == "ml2_linuxbridge" platform_options["neutron_#{plugin}_packages"].each do |pkg| package pkg do diff --git a/recipes/neutron-plugin.rb b/recipes/neutron-plugin.rb index c5512b1..ce19491 100644 --- a/recipes/neutron-plugin.rb +++ b/recipes/neutron-plugin.rb @@ -19,4 +19,6 @@ case node["neutron"]["plugin"] when "ovs" include_recipe "nova-network::neutron-ovs-plugin" +when "ml2_linuxbridge" + include_recipe "nova-network::neutron-linuxbridge-plugin" end diff --git a/recipes/neutron-server.rb b/recipes/neutron-server.rb index 8c8c7fc..8c8d6e9 100644 --- a/recipes/neutron-server.rb +++ b/recipes/neutron-server.rb @@ -91,7 +91,9 @@ action :enable subscribes :restart, "template[/etc/neutron/neutron.conf]", :delayed subscribes :restart, "template[/etc/neutron/api-paste.ini]", :delayed + subscribes :restart, "template[/etc/neutron/plugins/ml2/ml2_conf.ini]", :delayed subscribes :restart, "template[/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini]", :delayed + subscribes :restart, "template[/etc/neutron/plugins/linuxbridge/linuxbridge_conf.ini]", :delayed else action [ :disable, :stop ] end diff --git a/templates/default/dhcp_agent.ini.erb b/templates/default/dhcp_agent.ini.erb index 20ea30a..92d28df 100644 --- a/templates/default/dhcp_agent.ini.erb +++ b/templates/default/dhcp_agent.ini.erb @@ -29,3 +29,8 @@ dnsmasq_lease_max = <%= @dnsmasq_lease %> ##### OVS PLUGIN ##### interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver <% end %> + +<% if @neutron_plugin == "ml2_linuxbridge" %> +##### LINUXBRIDGE PLUGIN ##### +interface_driver = neutron.agent.linux.interface.BridgeInterfaceDriver +<% end %> diff --git a/templates/default/l3_agent.ini.erb b/templates/default/l3_agent.ini.erb index c2c9ce5..d587bf4 100644 --- a/templates/default/l3_agent.ini.erb +++ b/templates/default/l3_agent.ini.erb @@ -10,3 +10,8 @@ send_arp_for_ha = <%= @send_arp_for_ha %> # OVS interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver <% end %> + +<% if @neutron_plugin == "ml2_linuxbridge" %> +##### LINUXBRIDGE PLUGIN ##### +interface_driver = neutron.agent.linux.interface.BridgeInterfaceDriver +<% end %> diff --git a/templates/default/lbaas_agent.ini.erb b/templates/default/lbaas_agent.ini.erb index 679cb9f..b3443aa 100644 --- a/templates/default/lbaas_agent.ini.erb +++ b/templates/default/lbaas_agent.ini.erb @@ -4,6 +4,11 @@ interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver <% end %> +<% if @neutron_plugin == "ml2_linuxbridge" %> +##### LINUXBRIDGE PLUGIN ##### +interface_driver = neutron.agent.linux.interface.BridgeInterfaceDriver +<% end %> + <% if @device_driver %> # Device driver device_driver = <%= @device_driver %> diff --git a/templates/default/linuxbridge_conf.ini.erb b/templates/default/linuxbridge_conf.ini.erb new file mode 100644 index 0000000..2ff9898 --- /dev/null +++ b/templates/default/linuxbridge_conf.ini.erb @@ -0,0 +1,14 @@ +[vlans] +tenant_network_type = <%= @lb_network_type %> +<% if not @lb_vlan_range.empty? %> +network_vlan_ranges = <%= @lb_vlan_range %> +<% end %> + +[linux_bridge] +<% if not @lb_bridge_mapping.empty? %> +physical_interface_mappings = <%= @lb_bridge_mapping %> +<% end %> + +[securitygroup] +firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver + diff --git a/templates/default/ml2_conf.ini.erb b/templates/default/ml2_conf.ini.erb new file mode 100644 index 0000000..f5790c7 --- /dev/null +++ b/templates/default/ml2_conf.ini.erb @@ -0,0 +1,23 @@ +[ml2] +<% if @neutron_plugin == "ml2_linuxbridge" %> +mechanism_drivers = linuxbridge +type_drivers = vlan +tenant_network_types = vlan +<% end %> + +[agent] + +[ml2_type_vlan] +<% if @neutron_plugin == "ml2_linuxbridge" %> +network_vlan_ranges = <%= @lb_vlan_range %> +<% end %> + +[database] +sql_connection = mysql://<%= @db_user %>:<%= @db_password %>@<%= @db_ip_address %>/<%= @db_name %> +sqlalchemy_pool_size = <%= @sqlalchemy_pool_size %> +reconnect_interval = 2 + +[securitygroup] +<% if @neutron_plugin == "ml2_linuxbridge" %> +firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver +<% end %> diff --git a/templates/default/neutron-server.erb b/templates/default/neutron-server.erb new file mode 100644 index 0000000..99c7bdb --- /dev/null +++ b/templates/default/neutron-server.erb @@ -0,0 +1,12 @@ +# defaults for neutron-server + +# path to config file corresponding to the core_plugin specified in +# neutron.conf + +<% if @neutron_plugin == "ovs" %> +NEUTRON_PLUGIN_CONFIG="/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini" +<% end %> + +<% if @neutron_plugin == "ml2_linuxbridge" %> +NEUTRON_PLUGIN_CONFIG="/etc/neutron/plugins/ml2/ml2_conf.ini" +<% end %> diff --git a/templates/default/neutron.conf.erb b/templates/default/neutron.conf.erb index 7c7131f..6b76d28 100644 --- a/templates/default/neutron.conf.erb +++ b/templates/default/neutron.conf.erb @@ -10,6 +10,10 @@ bind_port = <%= @neutron_port %> core_plugin = neutron.plugins.openvswitch.ovs_neutron_plugin.OVSNeutronPluginV2 ovs_use_veth = <%= @neutron_ovs_use_veth %> <% end %> +<% if @neutron_plugin == "ml2_linuxbridge" %> +core_plugin = neutron.plugins.ml2.plugin.Ml2Plugin +service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin +<% end %> allow_overlapping_ips = <%= @overlapping_ips %> use_namespaces = <%= @neutron_namespace %> api_paste_config = /etc/neutron/api-paste.ini