From 12df44142f473796effd541d35f08b4067f883cb Mon Sep 17 00:00:00 2001 From: Alfredo Moralejo Date: Fri, 16 Jun 2017 19:00:07 +0000 Subject: [PATCH] Add support for OVN In the last OpenStack cycles Open Virtual Networking has quickly evolved, improving in features and maturity. This patch adds support to OVN as ml2 plugin so that packstack users can evaluate it easily. Change-Id: Ifaa1e93923e1b1bcc9458331bbe0c163053c695d --- Puppetfile | 4 + README.md | 41 ++-- docs/packstack.rst | 33 ++- packstack/plugins/neutron_350.py | 205 +++++++++++++++++- packstack/plugins/puppet_950.py | 6 +- .../packstack/manifests/neutron/ml2.pp | 8 + .../packstack/manifests/neutron/ovn_agent.pp | 54 +++++ .../packstack/manifests/neutron/ovn_northd.pp | 4 + .../modules/packstack/manifests/nova.pp | 7 + .../packstack/manifests/nova/compute.pp | 8 + .../packstack/manifests/provision/tempest.pp | 23 +- packstack/puppet/templates/compute.pp | 1 + packstack/puppet/templates/controller.pp | 3 + packstack/puppet/templates/network.pp | 14 +- ...rt-to-ovn-networking-ae6e0176270265c6.yaml | 20 ++ tests/scenario001.sh | 3 + 16 files changed, 386 insertions(+), 48 deletions(-) create mode 100644 packstack/puppet/modules/packstack/manifests/neutron/ovn_agent.pp create mode 100644 packstack/puppet/modules/packstack/manifests/neutron/ovn_northd.pp create mode 100644 releasenotes/notes/add-support-to-ovn-networking-ae6e0176270265c6.yaml diff --git a/Puppetfile b/Puppetfile index 54911c3e3..98499aa02 100755 --- a/Puppetfile +++ b/Puppetfile @@ -66,6 +66,10 @@ mod 'oslo', :git => 'https://github.com/openstack/puppet-oslo', :ref => 'master' +mod 'ovn', + :git => 'https://github.com/openstack/puppet-ovn', + :ref => 'master' + mod 'panko', :git => 'https://github.com/openstack/puppet-panko', :ref => 'master' diff --git a/README.md b/README.md index b0e79ebe0..4df87c881 100644 --- a/README.md +++ b/README.md @@ -181,26 +181,27 @@ reproduce these tests on your environment if you wish. This is the current matrix of available tests: -| - | scenario001 | scenario002 | scenario003 | -|:----------:|:-----------:|:-----------:|:------------: -| keystone | FERNET | UUID | FERNET | -| glance | file | swift | file | -| nova | X | X | X | -| neutron | X | X | X | -| lbaasv2 | | X | | -| vpnaas | | X | | -| cinder | X | | | -| ceilometer | | | X | -| aodh | | | X | -| gnocchi | | | X | -| panko | | | X | -| heat | | | X | -| swift | | X | | -| sahara | | X | | -| trove | | X | | -| horizon | X | | | -| manila | X | | | -| SSL | X | | | +| - | scenario001 | scenario002 | scenario003 | +|:--------------:|:-----------:|:-----------:|:------------: +| keystone | FERNET | UUID | FERNET | +| glance | file | swift | file | +| nova | X | X | X | +| neutron | X | X | X | +| neutron plugin | ovn | ovs | ovs | +| lbaasv2 | | X | | +| vpnaas | | X | | +| cinder | X | | | +| ceilometer | | | X | +| aodh | | | X | +| gnocchi | | | X | +| panko | | | X | +| heat | | | X | +| swift | | X | | +| sahara | | X | | +| trove | | X | | +| horizon | X | | | +| manila | X | | | +| SSL | X | | | To run these tests: diff --git a/docs/packstack.rst b/docs/packstack.rst index 99ea5fdae..3c50d87ff 100755 --- a/docs/packstack.rst +++ b/docs/packstack.rst @@ -796,13 +796,13 @@ Neutron ML2 plugin config ------------------------- **CONFIG_NEUTRON_ML2_TYPE_DRIVERS** - Comma-separated list of network-type driver entry points to be loaded from the neutron.ml2.type_drivers namespace. ['local', 'flat', 'vlan', 'gre', 'vxlan'] + Comma-separated list of network-type driver entry points to be loaded from the neutron.ml2.type_drivers namespace. ['local', 'flat', 'vlan', 'gre', 'vxlan', 'geneve'] **CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES** - Comma-separated, ordered list of network types to allocate as tenant networks. The 'local' value is only useful for single-box testing and provides no connectivity between hosts. ['local', 'vlan', 'gre', 'vxlan'] + Comma-separated, ordered list of network types to allocate as tenant networks. The 'local' value is only useful for single-box testing and provides no connectivity between hosts. ['local', 'vlan', 'gre', 'vxlan', 'geneve'] **CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS** - Comma-separated ordered list of networking mechanism driver entry points to be loaded from the neutron.ml2.mechanism_drivers namespace. ['logger', 'test', 'linuxbridge', 'openvswitch', 'hyperv', 'ncs', 'arista', 'cisco_nexus', 'mlnx', 'l2population', 'sriovnicswitch'] + Comma-separated ordered list of networking mechanism driver entry points to be loaded from the neutron.ml2.mechanism_drivers namespace. ['logger', 'test', 'linuxbridge', 'openvswitch', 'hyperv', 'ncs', 'arista', 'cisco_nexus', 'mlnx', 'l2population', 'sriovnicswitch', 'ovn'] **CONFIG_NEUTRON_ML2_FLAT_NETWORKS** Comma-separated list of physical_network names with which flat networks can be created. Use * to allow flat networks with arbitrary physical_network names. @@ -827,7 +827,7 @@ Neutron ML2 plugin config **CONFIG_NEUTRON_L2_AGENT** - Name of the L2 agent to be used with OpenStack Networking. ['linuxbridge', 'openvswitch'] + Name of the L2 agent to be used with OpenStack Networking. ['linuxbridge', 'openvswitch', 'ovn'] Neutron LB agent config ----------------------- @@ -865,6 +865,31 @@ Neutron OVS agent config for VXLAN **CONFIG_NEUTRON_OVS_VXLAN_UDP_PORT** VXLAN UDP port. +Neutron OVN agent config +------------------------ + +**CONFIG_NEUTRON_OVN_BRIDGE_MAPPINGS** + Comma-separated list of bridge mappings for the OpenStack Networking Open Virtual Network plugin. Each tuple in the list must be in the format :. Example: physnet1:br-eth1,physnet2:br-eth2,physnet3:br-eth3 + +**CONFIG_NEUTRON_OVN_BRIDGE_IFACES** + Comma-separated list of colon-separated Open vSwitch : pairs. The interface will be added to the associated bridge. If you desire the bridge to be persistent a value must be added to this directive, also CONFIG_NEUTRON_OVN_BRIDGE_MAPPINGS must be set in order to create the proper port. This can be achieved from the command line by issuing the following command: packstack --allinone --os-neutron-ovn-bridge-mappings=ext-net:br-ex --os-neutron-ovn-bridge-interfaces=br-ex:eth0 + +**CONFIG_NEUTRON_OVN_BRIDGES_COMPUTE** + Comma-separated list of Open vSwitch bridges that must be created and connected to interfaces in compute nodes when flat or vlan type drivers are enabled. These bridges must exist in CONFIG_NEUTRON_OVN_BRIDGE_MAPPINGS and CONFIG_NEUTRON_OVN_BRIDGE_IFACES. Example: --os-neutron-ovn-bridges-compute=br-vlan --os-neutron-ovn-bridge-mappings="extnet:br-ex,physnet1:br-vlan" --os-neutron-ovn-bridge-interfaces="br-ex:eth1,br-vlan:eth2" + +**CONFIG_NEUTRON_OVN_EXTERNAL_PHYSNET** + Name of physical network used for external network when enabling CONFIG_PROVISION_DEMO. Name must be one of the included in CONFIG_NEUTRON_OVN_BRIDGE_MAPPINGS. Example: --os-neutron-ovn-bridge-mappings="extnet:br-ex,physnet1:br-vlan" --os-neutron-ovn-bridge-interfaces="br-ex:eth1,br-vlan:eth2" --os-neutron-ovn-external-physnet="extnet" + +Neutron OVN agent config for tunnels +------------------------------------ + +**CONFIG_NEUTRON_OVN_TUNNEL_IF** + Interface for the Open vSwitch tunnel. Packstack overrides the IP address used for tunnels on this hypervisor to the IP found on the specified interface (for example, eth1). + +**CONFIG_NEUTRON_OVN_TUNNEL_SUBNETS** + Comma-separated list of subnets (for example, 192.168.10.0/24,192.168.11.0/24) used for sending tunneling packets. This is used to configure IP filtering to accept tunneling packets from these subnets instead of specific IP addresses of peer nodes. This is useful when you add existing nodes to EXCLUDE_SERVERS because, in this case, packstack cannot modify the IP filtering of the existing nodes. + + NOVACLIENT Config parameters ---------------------------- diff --git a/packstack/plugins/neutron_350.py b/packstack/plugins/neutron_350.py index 9b072539e..65b2fb2e1 100644 --- a/packstack/plugins/neutron_350.py +++ b/packstack/plugins/neutron_350.py @@ -252,12 +252,96 @@ def initConfig(controller): "CONDITION": False}, ], + "NEUTRON_OVN_AGENT": [ + {"CMD_OPTION": "os-neutron-ovn-bridge-mappings", + "PROMPT": ("Enter a comma separated list of bridge mappings for " + "the Neutron Open Virtual Network plugin"), + "OPTION_LIST": [], + "VALIDATORS": [], + "DEFAULT_VALUE": "extnet:br-ex", + "MASK_INPUT": False, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_NEUTRON_OVN_BRIDGE_MAPPINGS", + "USE_DEFAULT": False, + "NEED_CONFIRM": False, + "CONDITION": False}, + + {"CMD_OPTION": "os-neutron-ovn-bridge-interfaces", + "PROMPT": ("Enter a comma separated list of OVS bridge:interface " + "pairs for the Neutron Open Virtual Network plugin"), + "OPTION_LIST": [], + "VALIDATORS": [], + "DEFAULT_VALUE": "", + "MASK_INPUT": False, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_NEUTRON_OVN_BRIDGE_IFACES", + "USE_DEFAULT": False, + "NEED_CONFIRM": False, + "CONDITION": False}, + + {"CMD_OPTION": "os-neutron-ovn-bridges-compute", + "PROMPT": ("Enter a comma separated list of bridges for the " + "Neutron Open Virtual Network plugin in compute nodes." + "They must be included in os-neutron-ovs-bridge-mappings " + "and os-neutron-ovs-bridge-interfaces."), + "OPTION_LIST": [], + "VALIDATORS": [], + "DEFAULT_VALUE": "", + "MASK_INPUT": False, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_NEUTRON_OVN_BRIDGES_COMPUTE", + "USE_DEFAULT": False, + "NEED_CONFIRM": False, + "CONDITION": False}, + + {"CMD_OPTION": "os-neutron-ovn-external-physnet", + "PROMPT": ("Enter the name of the physical external network as" + "defined in bridge mappings"), + "OPTION_LIST": [], + "VALIDATORS": [], + "DEFAULT_VALUE": "extnet", + "MASK_INPUT": False, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_NEUTRON_OVN_EXTERNAL_PHYSNET", + "USE_DEFAULT": False, + "NEED_CONFIRM": False, + "CONDITION": False}, + ], + + "NEUTRON_OVN_AGENT_TUNNEL": [ + {"CMD_OPTION": "os-neutron-ovn-tunnel-if", + "PROMPT": ("Enter interface with IP to override the default " + "tunnel local IP"), + "OPTION_LIST": [], + "VALIDATORS": [], + "DEFAULT_VALUE": "", + "MASK_INPUT": False, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_NEUTRON_OVN_TUNNEL_IF", + "USE_DEFAULT": False, + "NEED_CONFIRM": False, + "CONDITION": False}, + + {"CMD_OPTION": "os-neutron-ovn-tunnel-subnets", + "PROMPT": ("Enter comma separated list of subnets used for " + "tunneling to make them allowed by IP filtering."), + "OPTION_LIST": [], + "VALIDATORS": [], + "DEFAULT_VALUE": "", + "MASK_INPUT": False, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_NEUTRON_OVN_TUNNEL_SUBNETS", + "USE_DEFAULT": False, + "NEED_CONFIRM": False, + "CONDITION": False}, + ], + "NEUTRON_ML2_PLUGIN": [ {"CMD_OPTION": "os-neutron-ml2-type-drivers", "CONF_NAME": "CONFIG_NEUTRON_ML2_TYPE_DRIVERS", "PROMPT": ("Enter a comma separated list of network type driver " "entrypoints"), - "OPTION_LIST": ["local", "flat", "vlan", "gre", "vxlan"], + "OPTION_LIST": ["local", "flat", "vlan", "gre", "vxlan", "geneve"], "VALIDATORS": [validators.validate_multi_options], "DEFAULT_VALUE": "vxlan,flat", "MASK_INPUT": False, @@ -270,7 +354,7 @@ def initConfig(controller): "CONF_NAME": "CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES", "PROMPT": ("Enter a comma separated ordered list of " "network_types to allocate as tenant networks"), - "OPTION_LIST": ["local", "vlan", "gre", "vxlan"], + "OPTION_LIST": ["local", "vlan", "gre", "vxlan", "geneve"], "VALIDATORS": [validators.validate_multi_options], "DEFAULT_VALUE": "vxlan", "MASK_INPUT": False, @@ -285,7 +369,7 @@ def initConfig(controller): "mechanism driver entrypoints"), "OPTION_LIST": ["logger", "test", "linuxbridge", "openvswitch", "hyperv", "ncs", "arista", "cisco_nexus", - "mlnx", "l2population", "sriovnicswitch"], + "mlnx", "l2population", "sriovnicswitch", "ovn"], "VALIDATORS": [validators.validate_multi_options], "DEFAULT_VALUE": "openvswitch", "MASK_INPUT": False, @@ -364,7 +448,7 @@ def initConfig(controller): {"CMD_OPTION": "os-neutron-l2-agent", "PROMPT": ("Enter the name of the L2 agent to be used " "with Neutron"), - "OPTION_LIST": ["linuxbridge", "openvswitch"], + "OPTION_LIST": ["linuxbridge", "openvswitch", "ovn"], "VALIDATORS": [validators.validate_options], "DEFAULT_VALUE": "openvswitch", "MASK_INPUT": False, @@ -372,7 +456,11 @@ def initConfig(controller): "CONF_NAME": "CONFIG_NEUTRON_L2_AGENT", "USE_DEFAULT": False, "NEED_CONFIRM": False, - "CONDITION": False}, + "CONDITION": False, + "MESSAGE": ("You have choosen OVN neutron backend. Note that this backend does not support LBaaS, VPNaaS or FWaaS services. " + "Geneve will be used as encapsulation method for tenant networks"), + "MESSAGE_VALUES": ["ovn"]}, + {"CMD_OPTION": "os-neutron-ml2-supported-pci-vendor-devs", "CONF_NAME": "CONFIG_NEUTRON_ML2_SUPPORTED_PCI_VENDOR_DEVS", "PROMPT": ("Enter a comma separated list of supported PCI " @@ -444,6 +532,20 @@ def initConfig(controller): "PRE_CONDITION_MATCH": True, "POST_CONDITION": False, "POST_CONDITION_MATCH": True}, + + {"GROUP_NAME": "NEUTRON_OVN_AGENT", + "DESCRIPTION": "Neutron OVN agent config", + "PRE_CONDITION": use_ml2_with_ovn, + "PRE_CONDITION_MATCH": True, + "POST_CONDITION": False, + "POST_CONDITION_MATCH": True}, + + {"GROUP_NAME": "NEUTRON_OVN_AGENT_TUNNEL", + "DESCRIPTION": "Neutron OVN agent config for tunnels", + "PRE_CONDITION": use_ml2_with_ovn, + "PRE_CONDITION_MATCH": True, + "POST_CONDITION": False, + "POST_CONDITION_MATCH": True}, ] for group in conf_groups: params = conf_params[group["GROUP_NAME"]] @@ -467,6 +569,40 @@ def initSequences(controller): config['CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS']): config['CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS'] += ', openvswitch' + if use_ml2_with_ovn(config): + if ('ovn' not in config['CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS']): + config['CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS'] = 'ovn' + # OVN only supports geneve encapsulation + if ('geneve' not in config['CONFIG_NEUTRON_ML2_TYPE_DRIVERS']): + config['CONFIG_NEUTRON_ML2_TYPE_DRIVERS'] += ', geneve' + config['CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES'] = 'geneve' + # VPNaaS, LBaaS and FWaaS are not supported with OVN + config['CONFIG_NEUTRON_FWAAS'] = 'n' + config['CONFIG_NEUTRON_VPNAAS'] = 'n' + config['CONFIG_LBAAS_INSTALL'] = 'n' + config['CONFIG_NEUTRON_METERING_AGENT_INSTALL'] = 'n' + # When using OVN we need to create the same L2 infrastucture as + # for OVS, so I'm copying value for required variables and use + # the same logic + ovs_tunnel_sub = 'CONFIG_NEUTRON_OVS_TUNNEL_SUBNETS' + ovn_tunnel_sub = 'CONFIG_NEUTRON_OVN_TUNNEL_SUBNETS' + config[ovs_tunnel_sub] = config[ovn_tunnel_sub] + ovs_tunnel_if = 'CONFIG_NEUTRON_OVS_TUNNEL_IF' + ovn_tunnel_if = 'CONFIG_NEUTRON_OVN_TUNNEL_IF' + config[ovs_tunnel_if] = config[ovn_tunnel_if] + ovs_mappings = 'CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS' + ovn_mappings = 'CONFIG_NEUTRON_OVN_BRIDGE_MAPPINGS' + config[ovs_mappings] = config[ovn_mappings] + ovs_ifaces = 'CONFIG_NEUTRON_OVS_BRIDGE_IFACES' + ovn_ifaces = 'CONFIG_NEUTRON_OVN_BRIDGE_IFACES' + config[ovs_ifaces] = config[ovn_ifaces] + ovs_compute = 'CONFIG_NEUTRON_OVS_BRIDGES_COMPUTE' + ovn_compute = 'CONFIG_NEUTRON_OVN_BRIDGES_COMPUTE' + config[ovs_compute] = config[ovn_compute] + ovs_external = 'CONFIG_NEUTRON_OVS_EXTERNAL_PHYSNET' + ovn_external = 'CONFIG_NEUTRON_OVN_EXTERNAL_PHYSNET' + config[ovs_external] = config[ovn_external] + plugin_db = 'neutron' plugin_path = 'neutron.plugins.ml2.plugin.Ml2Plugin' # values modification @@ -532,6 +668,11 @@ def use_ml2_with_ovs(config): config["CONFIG_NEUTRON_L2_AGENT"] == 'openvswitch') +def use_ml2_with_ovn(config): + return (neutron_install(config) and + config["CONFIG_NEUTRON_L2_AGENT"] == 'ovn') + + def use_openvswitch_vxlan(config): ml2_vxlan = ( use_ml2_with_ovs(config) and @@ -548,6 +689,14 @@ def use_openvswitch_gre(config): return ml2_vxlan +def use_ovn_geneve(config): + ml2_vxlan = ( + use_ml2_with_ovn(config) and + 'geneve' in config['CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES'] + ) + return ml2_vxlan + + def use_ml2_with_sriovnicswitch(config): ml2_sriovnic = ( use_ml2_with_ovs(config) and @@ -562,6 +711,9 @@ def get_if_driver(config): return 'neutron.agent.linux.interface.OVSInterfaceDriver' elif agent == 'linuxbridge': return 'neutron.agent.linux.interface.BridgeInterfaceDriver' + else: + # OVN does not provides a interface driver + return '' def find_mapping(haystack, needle): @@ -581,6 +733,9 @@ def tunnel_fw_details(config, host, src, fw_details): if use_openvswitch_vxlan(config): fw_details[key]['proto'] = 'udp' tun_port = ("%s" % config['CONFIG_NEUTRON_OVS_VXLAN_UDP_PORT']) + elif use_ovn_geneve(config): + fw_details[key]['proto'] = 'udp' + tun_port = "6081" else: fw_details[key]['proto'] = 'gre' tun_port = None @@ -602,8 +757,11 @@ def create_manifests(config, messages): 'plugin_driver.HaproxyOnHostPluginDriver:default') service_providers.append(lbaas_sp) - # ML2 uses the L3 Router service plugin to implement l3 agent - service_plugins.append('router') + if use_ml2_with_ovn(config): + service_plugins.append('ovn-router') + else: + # ML2 uses the L3 Router service plugin to implement l3 agent for linuxbridge and ovs + service_plugins.append('router') if config['CONFIG_NEUTRON_METERING_AGENT_INSTALL'] == 'y': service_plugins.append('metering') @@ -655,10 +813,26 @@ def create_manifests(config, messages): fw_details[key]['chain'] = "INPUT" fw_details[key]['ports'] = ['9696'] fw_details[key]['proto'] = "tcp" + if use_ml2_with_ovn(config): + key = "ovn_northd_%s" % host + fw_details.setdefault(key, {}) + fw_details[key]['host'] = "ALL" + fw_details[key]['service_name'] = "ovn northd" + fw_details[key]['chain'] = "INPUT" + fw_details[key]['ports'] = ['6641'] + fw_details[key]['proto'] = "tcp" + key = "ovn_southd_%s" % host + fw_details.setdefault(key, {}) + fw_details[key]['host'] = "ALL" + fw_details[key]['service_name'] = "ovn southd" + fw_details[key]['chain'] = "INPUT" + fw_details[key]['ports'] = ['6642'] + fw_details[key]['proto'] = "tcp" config['FIREWALL_NEUTRON_SERVER_RULES'] = fw_details # We also need to open VXLAN/GRE port for agent - if use_openvswitch_vxlan(config) or use_openvswitch_gre(config): + if (use_openvswitch_vxlan(config) or use_openvswitch_gre(config) or + use_ovn_geneve(config)): if config['CONFIG_IP_VERSION'] == 'ipv6': msg = output_messages.WARN_IPV6_OVS messages.append(utils.color_text(msg % host, 'red')) @@ -706,7 +880,8 @@ def create_l3_manifests(config, messages): config['CONFIG_NEUTRON_L3_HOST'] = host config['CONFIG_NEUTRON_L3_INTERFACE_DRIVER'] = get_if_driver(config) - if config['CONFIG_NEUTRON_L2_AGENT'] == 'openvswitch': + if (config['CONFIG_NEUTRON_L2_AGENT'] == 'openvswitch' or + config['CONFIG_NEUTRON_L2_AGENT'] == 'ovn'): ext_bridge = config['CONFIG_NEUTRON_L3_EXT_BRIDGE'] mapping = find_mapping( config['CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS'], @@ -721,8 +896,10 @@ def create_l3_manifests(config, messages): def create_dhcp_manifests(config, messages): - global network_hosts + if use_ml2_with_ovn(config): + return + global network_hosts for host in network_hosts: config["CONFIG_NEUTRON_DHCP_HOST"] = host config['CONFIG_NEUTRON_DHCP_INTERFACE_DRIVER'] = get_if_driver(config) @@ -751,6 +928,8 @@ def create_dhcp_manifests(config, messages): def create_lbaas_manifests(config, messages): + if use_ml2_with_ovn(config): + return global network_hosts if not config['CONFIG_LBAAS_INSTALL'] == 'y': @@ -761,6 +940,8 @@ def create_lbaas_manifests(config, messages): def create_metering_agent_manifests(config, messages): + if use_ml2_with_ovn(config): + return global network_hosts if not config['CONFIG_NEUTRON_METERING_AGENT_INSTALL'] == 'y': @@ -784,7 +965,7 @@ def create_l2_agent_manifests(config, messages): else: config['CONFIG_NEUTRON_USE_L2POPULATION'] = False - if agent == "openvswitch": + if agent in ["openvswitch", "ovn"]: ovs_type = 'CONFIG_NEUTRON_ML2_TYPE_DRIVERS' ovs_type = config.get(ovs_type, 'local') tunnel = use_openvswitch_vxlan(config) or use_openvswitch_gre(config) @@ -828,7 +1009,7 @@ def create_l2_agent_manifests(config, messages): # vlan, flat, vxlan or gre are enabled. For compute nodes, they are # only required if vlan or flat are enabled. if ( - agent == "openvswitch" and ( + agent in ["openvswitch", "ovn"] and ( (host in network_hosts and no_local_types) or no_tunnel_types) ): diff --git a/packstack/plugins/puppet_950.py b/packstack/plugins/puppet_950.py index fa8eb8c6e..f9e78407a 100755 --- a/packstack/plugins/puppet_950.py +++ b/packstack/plugins/puppet_950.py @@ -150,10 +150,10 @@ def copy_puppet_modules(config, messages): 'gnocchi', 'heat', 'horizon', 'inifile', 'ironic', 'keystone', 'magnum', 'manila', 'memcached', 'mongodb', 'mysql', 'neutron', 'nova', 'nssdb', 'openstack', - 'openstacklib', 'oslo', 'packstack', 'panko', 'rabbitmq', - 'redis', 'remote', 'rsync', 'sahara', 'ssh', + 'openstacklib', 'oslo', 'ovn', 'packstack', 'panko', + 'rabbitmq', 'redis', 'remote', 'rsync', 'sahara', 'ssh', 'stdlib', 'swift', 'sysctl', 'tempest', 'trove', - 'vcsrepo', 'vswitch', 'xinetd', )) + 'vcsrepo', 'vswitch', 'xinetd')) # write puppet manifest to disk manifestfiles.writeManifests() diff --git a/packstack/puppet/modules/packstack/manifests/neutron/ml2.pp b/packstack/puppet/modules/packstack/manifests/neutron/ml2.pp index cb3dee059..fcb045407 100644 --- a/packstack/puppet/modules/packstack/manifests/neutron/ml2.pp +++ b/packstack/puppet/modules/packstack/manifests/neutron/ml2.pp @@ -19,6 +19,14 @@ class packstack::neutron::ml2 () firewall_driver => hiera('FIREWALL_DRIVER'), supported_pci_vendor_devs => hiera_array('CONFIG_NEUTRON_ML2_SUPPORTED_PCI_VENDOR_DEVS'), extension_drivers => 'port_security', + max_header_size => 38, + } + + if hiera('CONFIG_NEUTRON_L2_AGENT') == 'ovn' { + class {'::neutron::plugins::ml2::ovn': + ovn_nb_connection => "tcp:${hiera('CONFIG_CONTROLLER_HOST')}:6641", + ovn_sb_connection => "tcp:${hiera('CONFIG_CONTROLLER_HOST')}:6642", + } } # For cases where "neutron-db-manage upgrade" command is called diff --git a/packstack/puppet/modules/packstack/manifests/neutron/ovn_agent.pp b/packstack/puppet/modules/packstack/manifests/neutron/ovn_agent.pp new file mode 100644 index 000000000..85a061dd0 --- /dev/null +++ b/packstack/puppet/modules/packstack/manifests/neutron/ovn_agent.pp @@ -0,0 +1,54 @@ +class packstack::neutron::ovn_agent () +{ + $my_ip = choose_my_ip(hiera('HOST_LIST')) + $neutron_tunnel_rule_name = "FIREWALL_NEUTRON_TUNNEL_RULES_${my_ip}" + create_resources(packstack::firewall, hiera($neutron_tunnel_rule_name, {})) + + $neutron_ovn_tunnel_if = hiera('CONFIG_NEUTRON_OVN_TUNNEL_IF', undef) + + $use_subnets_value = hiera('CONFIG_USE_SUBNETS') + $use_subnets = $use_subnets_value ? { + 'y' => true, + default => false, + } + + if $neutron_ovn_tunnel_if { + $ovn_agent_tunnel_cfg_neut_ovs_tun_if = force_interface($neutron_ovn_tunnel_if, $use_subnets) + } else { + $ovn_agent_tunnel_cfg_neut_ovs_tun_if = undef + } + + if $ovn_agent_tunnel_cfg_neut_ovs_tun_if != '' { + $iface = regsubst($ovn_agent_tunnel_cfg_neut_ovs_tun_if, '[\.\-\:]', '_', 'G') + $localip = inline_template("<%= scope.lookupvar('::ipaddress_${iface}') %>") + } else { + $localip = choose_my_ip(hiera('HOST_LIST')) + } + + $network_hosts = split(hiera('CONFIG_NETWORK_HOSTS'),',') + if member($network_hosts, choose_my_ip(hiera('HOST_LIST'))) { + $bridge_ifaces_param = 'CONFIG_NEUTRON_OVS_BRIDGE_IFACES' + $bridge_mappings_param = 'CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS' + } else { + $bridge_ifaces_param = 'CONFIG_NEUTRON_OVS_BRIDGE_IFACES_COMPUTE' + $bridge_mappings_param = 'CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS_COMPUTE' + } + + if hiera('CREATE_BRIDGES') == 'y' { + $bridge_uplinks = hiera_array($bridge_ifaces_param) + $bridge_mappings = hiera_array($bridge_mappings_param) + } else { + $bridge_uplinks = [] + $bridge_mappings = [] + } + + $ovn_southd = "tcp:${hiera('CONFIG_CONTROLLER_HOST')}:6642" + + class { '::ovn::controller': + ovn_remote => $ovn_southd, + ovn_bridge_mappings => $bridge_mappings, + bridge_interface_mappings => $bridge_uplinks, + ovn_encap_ip => force_ip($localip), + hostname => $::fqdn, + } +} diff --git a/packstack/puppet/modules/packstack/manifests/neutron/ovn_northd.pp b/packstack/puppet/modules/packstack/manifests/neutron/ovn_northd.pp new file mode 100644 index 000000000..c4911cfe7 --- /dev/null +++ b/packstack/puppet/modules/packstack/manifests/neutron/ovn_northd.pp @@ -0,0 +1,4 @@ +class packstack::neutron::ovn_northd () +{ + include ::ovn::northd +} diff --git a/packstack/puppet/modules/packstack/manifests/nova.pp b/packstack/puppet/modules/packstack/manifests/nova.pp index 4658fbbad..8dcf1e09f 100644 --- a/packstack/puppet/modules/packstack/manifests/nova.pp +++ b/packstack/puppet/modules/packstack/manifests/nova.pp @@ -41,6 +41,12 @@ class packstack::nova () $notify_on_state_change = undef } + if hiera('CONFIG_NEUTRON_L2_AGENT') == 'ovn' { + $novahost = $::fqdn + } else { + $novahost = undef + } + class { '::nova': glance_api_servers => "${nova_common_rabbitmq_cfg_storage_host}:9292", default_transport_url => "rabbit://${rabbit_userid}:${rabbit_password}@${rabbit_host}:${rabbit_port}/", @@ -58,5 +64,6 @@ class packstack::nova () placement_database_connection => "mysql+pymysql://nova_placement:${nova_db_pw}@${nova_mariadb_host}/nova_placement", cpu_allocation_ratio => hiera('CONFIG_NOVA_SCHED_CPU_ALLOC_RATIO'), ram_allocation_ratio => hiera('CONFIG_NOVA_SCHED_RAM_ALLOC_RATIO'), + host => $novahost, } } diff --git a/packstack/puppet/modules/packstack/manifests/nova/compute.pp b/packstack/puppet/modules/packstack/manifests/nova/compute.pp index 7cb8afc24..6dd8187a7 100644 --- a/packstack/puppet/modules/packstack/manifests/nova/compute.pp +++ b/packstack/puppet/modules/packstack/manifests/nova/compute.pp @@ -72,6 +72,13 @@ class packstack::nova::compute () $instance_usage_audit_period = 'month' } + # OVN neutron plugin doesn't support metadata + if hiera('CONFIG_NEUTRON_L2_AGENT') == 'ovn' { + $force_config_drive = true + } else { + $force_config_drive = false + } + class { '::nova::compute': enabled => true, vncproxy_host => hiera('CONFIG_KEYSTONE_HOST_URL'), @@ -81,6 +88,7 @@ class packstack::nova::compute () instance_usage_audit => $instance_usage_audit, instance_usage_audit_period => $instance_usage_audit_period, allow_resize_to_same_host => hiera('CONFIG_NOVA_ALLOW_RESIZE_TO_SAME'), + force_config_drive => $force_config_drive } class { '::nova::placement': diff --git a/packstack/puppet/modules/packstack/manifests/provision/tempest.pp b/packstack/puppet/modules/packstack/manifests/provision/tempest.pp index 38b8813e3..2680f404f 100644 --- a/packstack/puppet/modules/packstack/manifests/provision/tempest.pp +++ b/packstack/puppet/modules/packstack/manifests/provision/tempest.pp @@ -34,9 +34,6 @@ class packstack::provision::tempest () $image_source = hiera('CONFIG_PROVISION_IMAGE_URL') $image_format = hiera('CONFIG_PROVISION_IMAGE_FORMAT') - # clients should be able to ssh to instances - $run_ssh = true - # network name $public_network_name = 'public' @@ -91,6 +88,25 @@ class packstack::provision::tempest () $swift_available = str2bool(hiera('CONFIG_SWIFT_INSTALL')) $configure_tempest = str2bool(hiera('CONFIG_PROVISION_TEMPEST')) + # Metadata service is not supported with OVN plugin + # Some API extensions are not enabled by OVN plugin + $l2_agent = hiera('CONFIG_NEUTRON_L2_AGENT') + if $l2_agent == 'ovn' { + $neutron_api_extensions = 'ext-gw-mode,binding,agent,dhcp_agent_scheduler,external-net,quotas,provider,extraroute,router,extra_dhcp_opt,allowed-address-pairs,security-group' + # In last cirros version 0.3.5 there is an issue to use metadata from configdrive which make tempest to fail validation in some jobs. This is fixed in master + # but until a new version of cirros is published we have to disable run_validations. Note that connectivity validation is alwasys done by tempest even with + # run_ssh to false, but it doesn't do additional validation. + $run_ssh = false + tempest_config { 'compute-feature-enabled/metadata_service': + value => 'False', + path => "${tempest_workspace}/etc/tempest.conf", + } + } else { + $neutron_api_extensions = undef + # clients should be able to ssh to instances + $run_ssh = true + } + class { '::tempest': admin_domain_name => $admin_domain_name, admin_password => $admin_password, @@ -132,6 +148,7 @@ class packstack::provision::tempest () trove_available => $trove_available, username => $username, use_stderr => $use_stderr, + neutron_api_extensions => $neutron_api_extensions, } tempest_config { 'object-storage/operator_role': diff --git a/packstack/puppet/templates/compute.pp b/packstack/puppet/templates/compute.pp index 3d7bbeec0..081d78728 100644 --- a/packstack/puppet/templates/compute.pp +++ b/packstack/puppet/templates/compute.pp @@ -48,6 +48,7 @@ if hiera('CONFIG_NEUTRON_INSTALL') == 'y' { case hiera('CONFIG_NEUTRON_L2_AGENT') { 'openvswitch': { include '::packstack::neutron::ovs_agent' } 'linuxbridge': { include '::packstack::neutron::lb_agent' } + 'ovn': { include '::packstack::neutron::ovn_agent' } default: { include '::packstack::neutron::ovs_agent' } } include '::packstack::neutron::bridge' diff --git a/packstack/puppet/templates/controller.pp b/packstack/puppet/templates/controller.pp index 7b8497d9b..9ebf8da1a 100644 --- a/packstack/puppet/templates/controller.pp +++ b/packstack/puppet/templates/controller.pp @@ -93,6 +93,9 @@ if hiera('CONFIG_NEUTRON_INSTALL') == 'y' { include '::packstack::neutron::notifications' } include '::packstack::neutron::ml2' + if hiera('CONFIG_NEUTRON_L2_AGENT') == 'ovn' { + include '::packstack::neutron::ovn_northd' + } } if hiera('CONFIG_MANILA_INSTALL') == 'y' { diff --git a/packstack/puppet/templates/network.pp b/packstack/puppet/templates/network.pp index e30db29d0..88440d6ce 100644 --- a/packstack/puppet/templates/network.pp +++ b/packstack/puppet/templates/network.pp @@ -25,7 +25,9 @@ if hiera('CONFIG_NEUTRON_INSTALL') == 'y' { if hiera('CONFIG_LBAAS_INSTALL') == 'y' { include '::packstack::neutron::lbaas' } - include '::packstack::neutron::l3' + if hiera('CONFIG_NEUTRON_L2_AGENT') != 'ovn' { + include '::packstack::neutron::l3' + } if hiera('CONFIG_NEUTRON_OVS_BRIDGE_CREATE') == 'y' { include '::packstack::neutron::ovs_bridge' } @@ -33,17 +35,17 @@ if hiera('CONFIG_NEUTRON_INSTALL') == 'y' { case hiera('CONFIG_NEUTRON_L2_AGENT') { 'openvswitch': { include '::packstack::neutron::ovs_agent' } 'linuxbridge': { include '::packstack::neutron::lb_agent' } + 'ovn': { include '::packstack::neutron::ovn_agent' } default: { include '::packstack::neutron::ovs_agent' } } include '::packstack::neutron::bridge' - include '::packstack::neutron::dhcp' + if hiera('CONFIG_NEUTRON_L2_AGENT') != 'ovn' { + include '::packstack::neutron::dhcp' + include '::packstack::neutron::metadata' + } if hiera('CONFIG_NEUTRON_METERING_AGENT_INSTALL') == 'y' { include '::packstack::neutron::metering' } - if hiera('CONFIG_NOVA_INSTALL') == 'y' { - include '::packstack::neutron::metadata' - } - if hiera('CONFIG_PROVISION_DEMO') == 'y' or hiera('CONFIG_PROVISION_TEMPEST') == 'y' { include '::packstack::provision::bridge' } diff --git a/releasenotes/notes/add-support-to-ovn-networking-ae6e0176270265c6.yaml b/releasenotes/notes/add-support-to-ovn-networking-ae6e0176270265c6.yaml new file mode 100644 index 000000000..fe9964ebb --- /dev/null +++ b/releasenotes/notes/add-support-to-ovn-networking-ae6e0176270265c6.yaml @@ -0,0 +1,20 @@ +--- +features: + - | + Now packstack support using Open Virtual Network (ovn) as neutron + plugin. To enable it you need to set CONFIG_NEUTRON_L2_AGENT to ovn. + Additionally some options have been added to configure different options + and topologies: + + * CONFIG_NEUTRON_OVN_BRIDGE_MAPPINGS + * CONFIG_NEUTRON_OVN_BRIDGE_IFACES + * CONFIG_NEUTRON_OVN_BRIDGES_COMPUTE + * CONFIG_NEUTRON_OVN_EXTERNAL_PHYSNET + * CONFIG_NEUTRON_OVN_TUNNEL_IF + * CONFIG_NEUTRON_OVN_TUNNEL_SUBNETS + + Additionally, geneve has been included as an option to existing parameters + CONFIG_NEUTRON_ML2_TYPE_DRIVERS and CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES. + Note that OVN networking has still some limitations, as lack of support of + for LBaaS, FWaaS and VPNaaS. Consult networking-ovn documentation for + further details. diff --git a/tests/scenario001.sh b/tests/scenario001.sh index bd37a0832..54bf4cd84 100755 --- a/tests/scenario001.sh +++ b/tests/scenario001.sh @@ -27,6 +27,9 @@ $SUDO packstack ${ADDITIONAL_ARGS} \ --os-horizon-ssl=y \ --amqp-enable-ssl=y \ --glance-backend=file \ + --os-neutron-l2-agent=ovn \ + --os-neutron-ml2-type-drivers="geneve,flat" \ + --os-neutron-ml2-tenant-network-types="geneve" \ --provision-uec-kernel-url="/tmp/cirros/cirros-0.3.4-x86_64-vmlinuz" \ --provision-uec-ramdisk-url="/tmp/cirros/cirros-0.3.4-x86_64-initrd" \ --provision-uec-disk-url="/tmp/cirros/cirros-0.3.4-x86_64-disk.img" \