Add OVN support
Install docs:
https://docs.openstack.org/networking-ovn/latest/install/index.html
Partial Prod: PROD-15003
Co-Authored-By: Elena Ezhova <eezhova@mirantis.com>
Change-Id: I0a7023f3e14aae6d5ec5efe8f117ebc9d0ed302d
diff --git a/.kitchen.yml b/.kitchen.yml
index 1051363..2481b6c 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -93,6 +93,11 @@
pillars-from-files:
neutron.sls: tests/pillar/compute_qos.sls
+ - name: compute_ovn
+ provisioner:
+ pillars-from-files:
+ neutron.sls: tests/pillar/compute_ovn.sls
+
- name: control_cluster
provisioner:
pillars-from-files:
@@ -128,6 +133,11 @@
pillars-from-files:
neutron.sls: tests/pillar/control_qos.sls
+ - name: control_ovn
+ provisioner:
+ pillars-from-files:
+ neutron.sls: tests/pillar/control_ovn.sls
+
- name: gateway_dvr
provisioner:
pillars-from-files:
diff --git a/.travis.yml b/.travis.yml
index 779286f..cc2ce87 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -32,6 +32,7 @@
- PLATFORM=trevorj/salty-whales:xenial SUITE=compute_qos_sriov
- PLATFORM=trevorj/salty-whales:trusty SUITE=compute_qos
- PLATFORM=trevorj/salty-whales:xenial SUITE=compute_qos
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=compute_ovn
- PLATFORM=trevorj/salty-whales:trusty SUITE=control_cluster
- PLATFORM=trevorj/salty-whales:xenial SUITE=control_cluster
- PLATFORM=trevorj/salty-whales:trusty SUITE=control_dvr
@@ -44,6 +45,7 @@
- PLATFORM=trevorj/salty-whales:xenial SUITE=control_fwaas_v1
- PLATFORM=trevorj/salty-whales:trusty SUITE=control_qos
- PLATFORM=trevorj/salty-whales:xenial SUITE=control_qos
+ - PLATFORM=trevorj/salty-whales:xenial SUITE=control_ovn
- PLATFORM=trevorj/salty-whales:trusty SUITE=gateway_dvr
- PLATFORM=trevorj/salty-whales:xenial SUITE=gateway_dvr
- PLATFORM=trevorj/salty-whales:trusty SUITE=gateway_legacy
diff --git a/README.rst b/README.rst
index 3b161e5..57153ed 100644
--- a/README.rst
+++ b/README.rst
@@ -591,6 +591,7 @@
driver: openvswitch
Advanced Neutron Features (DPDK, SR-IOV)
+----------------------------------------
Neutron OVS DPDK
@@ -648,6 +649,7 @@
driver: openvswitch
Neutron with VLAN-aware-VMs
+---------------------------
.. code-block:: yaml
@@ -661,6 +663,34 @@
gateway:
vlan_aware_vms: true
+Neutron with OVN
+----------------
+
+Control node:
+
+.. code-block:: yaml
+
+ neutron:
+ server:
+ backend:
+ engine: ovn
+ mechanism:
+ ovn:
+ driver: ovn
+ tenant_network_types: "geneve,flat"
+
+Compute node:
+
+.. code-block:: yaml
+
+ neutron:
+ compute:
+ local_ip: 10.2.0.105
+ controller_vip: 10.1.0.101
+ external_access: false
+ backend:
+ engine: ovn
+
Neutron Server
--------------
@@ -692,7 +722,6 @@
user: admin
password: password
-
Neutron Keystone region
.. code-block:: yaml
diff --git a/metadata/service/compute/ovn/single.yml b/metadata/service/compute/ovn/single.yml
new file mode 100644
index 0000000..9bfb54d
--- /dev/null
+++ b/metadata/service/compute/ovn/single.yml
@@ -0,0 +1,17 @@
+applications:
+- neutron
+classes:
+- service.neutron.support
+parameters:
+ _param:
+ ovn_external_bridge: br-floating
+ neutron:
+ compute:
+ enabled: true
+ version: ${_param:neutron_version}
+ local_ip: ${_param:tenant_address}
+ controller_vip: ${_param:cluster_vip_address}
+ external_access: true
+ external_bridge: ${_param:ovn_external_bridge}
+ backend:
+ engine: ovn
diff --git a/metadata/service/control/cluster.yml b/metadata/service/control/cluster.yml
index c69a8f8..701b367 100644
--- a/metadata/service/control/cluster.yml
+++ b/metadata/service/control/cluster.yml
@@ -11,6 +11,7 @@
dns_domain: novalocal
vlan_aware_vms: false
version: ${_param:neutron_version}
+ controller_vip: ${_param:cluster_vip_address}
bind:
address: ${_param:cluster_local_address}
port: 9696
diff --git a/metadata/service/control/single.yml b/metadata/service/control/single.yml
index a47f680..149d37a 100644
--- a/metadata/service/control/single.yml
+++ b/metadata/service/control/single.yml
@@ -15,6 +15,7 @@
qos: false
vlan_aware_vms: false
version: ${_param:neutron_version}
+ controller_vip: ${_param:single_address}
bind:
address: ${_param:single_address}
port: 9696
diff --git a/neutron/compute.sls b/neutron/compute.sls
index 6829780..c6a1df5 100644
--- a/neutron/compute.sls
+++ b/neutron/compute.sls
@@ -1,6 +1,7 @@
{% from "neutron/map.jinja" import compute, fwaas, system_cacerts_file with context %}
{%- if compute.enabled %}
+{% if compute.backend.engine == "ml2" %}
neutron_compute_packages:
pkg.installed:
- names: {{ compute.pkgs }}
@@ -132,4 +133,52 @@
{%- endif %}
{%- endif %}
+{%- elif compute.backend.engine == "ovn" %}
+
+ovn_packages:
+ pkg.installed:
+ - names: {{ compute.pkgs_ovn }}
+
+{%- if not grains.get('noservices', False) %}
+
+remote_ovsdb_access:
+ cmd.run:
+ - name: "ovs-vsctl set open .
+ external-ids:ovn-remote=tcp:{{ compute.controller_vip }}:6642"
+
+enable_overlays:
+ cmd.run:
+ - name: "ovs-vsctl set open . external-ids:ovn-encap-type=geneve,vxlan"
+
+configure_local_endpoint:
+ cmd.run:
+ - name: "ovs-vsctl set open .
+ external-ids:ovn-encap-ip={{ compute.local_ip }}"
+
+{%- if compute.get('external_access', True) %}
+
+set_bridge_external_id:
+ cmd.run:
+ - name: "ovs-vsctl --no-wait br-set-external-id
+ {{ compute.external_bridge }} bridge-id {{ compute.external_bridge }}"
+
+set_bridge_mapping:
+ cmd.run:
+ - name: "ovs-vsctl set open .
+ external-ids:ovn-bridge-mappings=physnet1:{{ compute.external_bridge }}"
+
+{%- endif %}
+
+ovn_services:
+ service.running:
+ - names: {{ compute.services_ovn }}
+ - enable: true
+ {%- if grains.get('noservices') %}
+ - onlyif: /bin/false
+ {%- endif %}
+ - require:
+ - pkg: ovn_packages
+
+{%- endif %}
+{%- endif %}
{%- endif %}
diff --git a/neutron/files/ocata/ml2_conf.ini b/neutron/files/ocata/ml2_conf.ini
index 8f5e8dd..3056ae5 100644
--- a/neutron/files/ocata/ml2_conf.ini
+++ b/neutron/files/ocata/ml2_conf.ini
@@ -120,7 +120,6 @@
# List of network type driver entrypoints to be loaded from the
# neutron.ml2.type_drivers namespace. (list value)
#type_drivers = local,flat,vlan,gre,vxlan,geneve
-type_drivers = local,flat,vlan,gre,vxlan
# Ordered list of network_types to allocate as tenant networks. The default
# value 'local' is useful for single-box testing but provides no connectivity
@@ -203,6 +202,7 @@
# Comma-separated list of <vni_min>:<vni_max> tuples enumerating ranges of
# Geneve VNI IDs that are available for tenant network allocation (list value)
#vni_ranges =
+vni_ranges = {{ server.get('geneve', {}).vni_ranges|default('1:65536') }}
# Geneve encapsulation header size is dynamic, this value is used to calculate
# the maximum MTU for the driver. This is the sum of the sizes of the outer ETH
@@ -210,6 +210,7 @@
# which is the size of the Geneve header without any additional option headers.
# (integer value)
#max_header_size = 30
+max_header_size = 38
[ml2_type_gre]
@@ -284,3 +285,10 @@
# Use ipset to speed-up the iptables based security groups. Enabling ipset
# support requires that ipset is installed on L2 agent node. (boolean value)
#enable_ipset = true
+
+{%- if server.backend.engine == "ovn" %}
+[ovn]
+ovn_nb_connection = tcp:{{ server.controller_vip }}:6641
+ovn_sb_connection = tcp:{{ server.controller_vip }}:6642
+ovn_l3_scheduler = leastloaded
+{%- endif %}
diff --git a/neutron/files/ocata/neutron-server b/neutron/files/ocata/neutron-server
index 54f6ceb..04830ca 100644
--- a/neutron/files/ocata/neutron-server
+++ b/neutron/files/ocata/neutron-server
@@ -7,7 +7,7 @@
# neutron.conf
#NEUTRON_PLUGIN_CONFIG="/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini"
-{%- if server.backend.engine == "ml2" %}
+{%- if server.backend.engine in ["ml2", "ovn"] %}
NEUTRON_PLUGIN_CONFIG="/etc/neutron/plugins/ml2/ml2_conf.ini"
{%- endif %}
diff --git a/neutron/files/ocata/neutron-server.conf.Debian b/neutron/files/ocata/neutron-server.conf.Debian
index 049544b..74e155c 100644
--- a/neutron/files/ocata/neutron-server.conf.Debian
+++ b/neutron/files/ocata/neutron-server.conf.Debian
@@ -39,11 +39,18 @@
core_plugin = neutron_plugin_contrail.plugins.opencontrail.contrail_plugin.NeutronPluginContrailCoreV2
service_plugins = neutron_plugin_contrail.plugins.opencontrail.loadbalancer.v2.plugin.LoadBalancerPluginV2
-{% elif server.backend.engine == "ml2" %}
+
+{% elif server.backend.engine in ["ml2", "ovn"] %}
core_plugin = neutron.plugins.ml2.plugin.Ml2Plugin
-service_plugins =neutron.services.l3_router.l3_router_plugin.L3RouterPlugin,neutron.services.metering.metering_plugin.MeteringPlugin
+{% if server.backend.engine == "ml2" %}
+{% set l3_plugin = 'neutron.services.l3_router.l3_router_plugin.L3RouterPlugin' %}
+{% elif server.backend.engine == "ovn" %}
+{% set l3_plugin = 'networking_ovn.l3.l3_ovn.OVNL3RouterPlugin' %}
+{% endif %}
+
+service_plugins ={{ l3_plugin }}, neutron.services.metering.metering_plugin.MeteringPlugin
{%- if server.lbaas is defined -%},lbaasv2{%- endif -%}
{%- if fwaas.get('enabled', False) -%},{{ fwaas[fwaas.api_version]['service_plugin'] }}{%- endif -%}
{%- if server.get('qos', 'True') -%},neutron.services.qos.qos_plugin.QoSPlugin{%- endif -%}
@@ -838,7 +845,7 @@
# Deprecated group/name - [DEFAULT]/sql_connection
# Deprecated group/name - [DATABASE]/sql_connection
# Deprecated group/name - [sql]/connection
-{% if server.backend.engine == "ml2" %}
+{% if server.backend.engine in ["ml2", "ovn"] %}
connection = {{ server.database.engine }}+pymysql://{{ server.database.user }}:{{ server.database.password }}@{{ server.database.host }}/{{ server.database.name }}?charset=utf8
{% else %}
connection = sqlite:////var/lib/neutron/neutron.sqlite
diff --git a/neutron/map.jinja b/neutron/map.jinja
index eef262f..9631d1b 100644
--- a/neutron/map.jinja
+++ b/neutron/map.jinja
@@ -6,7 +6,9 @@
{% set compute = salt['grains.filter_by']({
'Debian': {
'pkgs': ['neutron-openvswitch-agent', 'openvswitch-switch', 'python-pycadf'],
+ 'pkgs_ovn': ['ovn-common', 'ovn-host'],
'services': ['neutron-openvswitch-agent'],
+ 'services_ovn': ['ovn-host'],
'dpdk': false,
'audit': {
'enabled': false
@@ -14,7 +16,9 @@
},
'RedHat': {
'pkgs': ['openstack-neutron-openvswitch', 'openvswitch', 'python-pycadf'],
+ 'pkgs_ovn': ['openvswitch-ovn'],
'services': ['neutron-openvswitch-agent'],
+ 'services_ovn': ['ovn-host'],
'dpdk': false,
'audit': {
'enabled': false
@@ -38,8 +42,10 @@
{% set server = salt['grains.filter_by']({
'Debian': {
'pkgs': ['neutron-server','python-neutron-lbaas', 'gettext-base', 'python-pycadf'],
+ 'pkgs_ovn': ['python-networking-ovn', 'ovn-common', 'ovn-central'],
'pkgs_ml2': ['neutron-plugin-ml2'],
'services': ['neutron-server'],
+ 'services_ovn': ['ovn-central'],
'notification': False,
'dpdk': false,
'cors': {},
@@ -50,7 +56,9 @@
'RedHat': {
'pkgs_ml2': ['openstack-neutron-ml2', 'python-pycadf'],
'pkgs': ['openstack-neutron'],
+ 'pkgs_ovn': ['openvswitch-ovn', 'python-networking-ovn'],
'services': ['neutron-server'],
+ 'services_ovn': ['ovn-central'],
'notification': False,
'dpdk': false,
'cors': {},
diff --git a/neutron/server.sls b/neutron/server.sls
index 79e5aba..6de0f4a 100644
--- a/neutron/server.sls
+++ b/neutron/server.sls
@@ -72,7 +72,7 @@
{%- endif %}
-{% if server.backend.engine == "ml2" %}
+{% if server.backend.engine in ["ml2", "ovn"] %}
/etc/neutron/plugins/ml2/ml2_conf.ini:
file.managed:
@@ -154,6 +154,41 @@
{%- endif %}
+{%- if server.backend.engine == "ovn" %}
+
+ovn_packages:
+ pkg.installed:
+ - names: {{ server.pkgs_ovn }}
+
+{%- if not grains.get('noservices', False) %}
+
+remote_ovsdb_access:
+ cmd.run:
+ - name: "ovs-appctl -t ovsdb-server ovsdb-server/add-remote
+ ptcp:6640:{{ server.controller_vip }}"
+
+open_ovs_port:
+ iptables.append:
+ - table: filter
+ - chain: INPUT
+ - jump: ACCEPT
+ - dport: 6640
+ - proto: tcp
+ - save: True
+
+ovn_services:
+ service.running:
+ - names: {{ server.services_ovn }}
+ - enable: true
+ {%- if grains.get('noservices') %}
+ - onlyif: /bin/false
+ {%- endif %}
+ - require:
+ - pkg: ovn_packages
+
+{%- endif %}
+{%- endif %}
+
{%- if server.backend.engine == "midonet" %}
/etc/neutron/plugins/midonet/midonet.ini:
diff --git a/tests/pillar/compute_ovn.sls b/tests/pillar/compute_ovn.sls
new file mode 100644
index 0000000..0f4b580
--- /dev/null
+++ b/tests/pillar/compute_ovn.sls
@@ -0,0 +1,9 @@
+neutron:
+ compute:
+ enabled: true
+ version: ocata
+ local_ip: 10.2.0.105
+ controller_vip: 10.1.0.101
+ external_access: false
+ backend:
+ engine: ovn
diff --git a/tests/pillar/control_ovn.sls b/tests/pillar/control_ovn.sls
new file mode 100644
index 0000000..cd79174
--- /dev/null
+++ b/tests/pillar/control_ovn.sls
@@ -0,0 +1,57 @@
+neutron:
+ server:
+ enabled: true
+ version: ocata
+ backend:
+ engine: ovn
+ external_mtu: 1500
+ mechanism:
+ ovn:
+ driver: ovn
+ tenant_network_types: "geneve,flat"
+ controller_vip: 172.16.10.101
+ dvr: false
+ l3_ha: false
+ dns_domain: novalocal
+ global_physnet_mtu: 1500
+ bind:
+ address: 172.16.10.101
+ port: 9696
+ compute:
+ host: 127.0.0.1
+ password: workshop
+ region: RegionOne
+ tenant: service
+ user: nova
+ database:
+ engine: mysql
+ host: 127.0.0.1
+ name: neutron
+ password: workshop
+ port: 3306
+ user: neutron
+ identity:
+ engine: keystone
+ host: 127.0.0.1
+ password: workshop
+ port: 35357
+ region: RegionOne
+ tenant: service
+ user: neutron
+ endpoint_type: internal
+ message_queue:
+ engine: rabbitmq
+ host: 127.0.0.1
+ password: workshop
+ port: 5672
+ user: openstack
+ virtual_host: /openstack
+
+linux:
+ system:
+ enabled: true
+ repo:
+ mirantis_openstack_ocata:
+ source: "deb http://mirror.fuel-infra.org/mcp-repos/ocata/xenial ocata main"
+ architectures: amd64
+ key_url: "http://mirror.fuel-infra.org/mcp-repos/ocata/xenial/archive-mcpocata.key"