summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Alvarez <dalvarez@redhat.com>2018-11-21 10:59:09 +0000
committerDaniel Alvarez <dalvarez@redhat.com>2018-11-27 10:57:59 +0000
commitd28495fe42ea9a940260e951b32e0a814c75ce70 (patch)
tree472278183397a5be4d632c080f805e01e7c85db5
parentb7385790e5ad7cb02fada69d232cd0347fcfa509 (diff)
Support ports belonging to Neutron DHCP agents
Before this patch, both the sync tool and the production code would assume that 'network:dhcp' owner ports would be for the OVN metadata service. However, since Neutron DHCP agents can be deployed as well on OVN environments, we need to support these ports as well. This change is doing several things: - Fixing sync tool so that Neutron DHCP ports are not deleted anymore (these ports are owned by DHCP and have a device_id as 'dhcp<host_uuid>-<network_id>'). Syncing these ports in OVN will no longer result in creating 'localport' ports but normal ports to allow non-local DHCP traffic. - Fixing networking-ovn code to skip such ports when looking for the metadata port on a specific network. - Newly created metadata ports will have a device_id such as 'ovnmeta-<network_id>'. Change-Id: I30181e1752f456f30f94818c5350f447c387cbb2 Related-Bug: #1804390 Signed-off-by: Daniel Alvarez <dalvarez@redhat.com>
Notes
Notes (review): Code-Review+2: Lucas Alvares Gomes <lucasagomes@gmail.com> Code-Review+2: Miguel Angel Ajo <mangelajo@redhat.com> Workflow+1: Miguel Angel Ajo <mangelajo@redhat.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Fri, 30 Nov 2018 06:10:02 +0000 Reviewed-on: https://review.openstack.org/619210 Project: openstack/networking-ovn Branch: refs/heads/master
-rw-r--r--networking_ovn/common/constants.py2
-rw-r--r--networking_ovn/common/ovn_client.py21
-rw-r--r--networking_ovn/ovn_db_sync.py8
-rw-r--r--networking_ovn/tests/functional/test_ovn_db_sync.py12
4 files changed, 29 insertions, 14 deletions
diff --git a/networking_ovn/common/constants.py b/networking_ovn/common/constants.py
index 2a89e03..e4aa4d6 100644
--- a/networking_ovn/common/constants.py
+++ b/networking_ovn/common/constants.py
@@ -52,8 +52,6 @@ OVN_DROP_PORT_GROUP_NAME = 'neutron_pg_drop'
52 52
53OVN_PROVNET_PORT_NAME_PREFIX = 'provnet-' 53OVN_PROVNET_PORT_NAME_PREFIX = 'provnet-'
54 54
55OVN_NEUTRON_OWNER_TO_PORT_TYPE = {const.DEVICE_OWNER_DHCP: 'localport'}
56
57# Agent extension constants 55# Agent extension constants
58OVN_AGENT_DESC_KEY = 'neutron:description' 56OVN_AGENT_DESC_KEY = 'neutron:description'
59OVN_AGENT_METADATA_SB_CFG_KEY = 'neutron:ovn-metadata-sb-cfg' 57OVN_AGENT_METADATA_SB_CFG_KEY = 'neutron:ovn-metadata-sb-cfg'
diff --git a/networking_ovn/common/ovn_client.py b/networking_ovn/common/ovn_client.py
index 2036d9d..fe363aa 100644
--- a/networking_ovn/common/ovn_client.py
+++ b/networking_ovn/common/ovn_client.py
@@ -196,6 +196,7 @@ class OVNClient(object):
196 qos_options = self._qos_driver.get_qos_options(port) 196 qos_options = self._qos_driver.get_qos_options(port)
197 vtep_physical_switch = binding_prof.get('vtep-physical-switch') 197 vtep_physical_switch = binding_prof.get('vtep-physical-switch')
198 198
199 port_type = ''
199 cidrs = '' 200 cidrs = ''
200 if vtep_physical_switch: 201 if vtep_physical_switch:
201 vtep_logical_switch = binding_prof.get('vtep-logical-switch') 202 vtep_logical_switch = binding_prof.get('vtep-logical-switch')
@@ -224,8 +225,12 @@ class OVNClient(object):
224 self._get_allowed_addresses_from_port(port) 225 self._get_allowed_addresses_from_port(port)
225 addresses = [address] 226 addresses = [address]
226 addresses.extend(new_macs) 227 addresses.extend(new_macs)
227 port_type = ovn_const.OVN_NEUTRON_OWNER_TO_PORT_TYPE.get( 228
228 port['device_owner'], '') 229 # Only adjust the OVN type if the port is not owned by Neutron
230 # DHCP agents.
231 if (port['device_owner'] == const.DEVICE_OWNER_DHCP and
232 not port['device_id'].startswith('dhcp')):
233 port_type = 'localport'
229 234
230 dhcpv4_options = self._get_port_dhcp_options(port, const.IP_VERSION_4) 235 dhcpv4_options = self._get_port_dhcp_options(port, const.IP_VERSION_4)
231 dhcpv6_options = self._get_port_dhcp_options(port, const.IP_VERSION_6) 236 dhcpv6_options = self._get_port_dhcp_options(port, const.IP_VERSION_6)
@@ -1740,9 +1745,12 @@ class OVNClient(object):
1740 1745
1741 ports = self._plugin.get_ports(context, filters=dict( 1746 ports = self._plugin.get_ports(context, filters=dict(
1742 network_id=[network_id], device_owner=[const.DEVICE_OWNER_DHCP])) 1747 network_id=[network_id], device_owner=[const.DEVICE_OWNER_DHCP]))
1743 # There should be only one metadata port per network 1748
1744 if len(ports) == 1: 1749 # Metadata ports are DHCP ports without a device_id starting by 'dhcp'
1745 return ports[0] 1750 # since those belong to Neutron DHCP agents.
1751 for port in ports:
1752 if not port['device_id'].startswith('dhcp'):
1753 return port
1746 1754
1747 def _find_metadata_port_ip(self, context, subnet): 1755 def _find_metadata_port_ip(self, context, subnet):
1748 metadata_port = self._find_metadata_port(context, subnet['network_id']) 1756 metadata_port = self._find_metadata_port(context, subnet['network_id'])
@@ -1766,7 +1774,8 @@ class OVNClient(object):
1766 port = {'port': 1774 port = {'port':
1767 {'network_id': network['id'], 1775 {'network_id': network['id'],
1768 'tenant_id': network['project_id'], 1776 'tenant_id': network['project_id'],
1769 'device_owner': const.DEVICE_OWNER_DHCP}} 1777 'device_owner': const.DEVICE_OWNER_DHCP,
1778 'device_id': 'ovnmeta-%s' % network['id']}}
1770 # TODO(boden): rehome create_port into neutron-lib 1779 # TODO(boden): rehome create_port into neutron-lib
1771 p_utils.create_port(self._plugin, context, port) 1780 p_utils.create_port(self._plugin, context, port)
1772 elif len(metadata_ports) > 1: 1781 elif len(metadata_ports) > 1:
diff --git a/networking_ovn/ovn_db_sync.py b/networking_ovn/ovn_db_sync.py
index 78033c2..0fa42b7 100644
--- a/networking_ovn/ovn_db_sync.py
+++ b/networking_ovn/ovn_db_sync.py
@@ -896,6 +896,14 @@ class OvnNbSynchronizer(OvnDbSynchronizer):
896 dhcp_ports = self.core_plugin.get_ports(ctx, filters=dict( 896 dhcp_ports = self.core_plugin.get_ports(ctx, filters=dict(
897 network_id=[net['id']], 897 network_id=[net['id']],
898 device_owner=[constants.DEVICE_OWNER_DHCP])) 898 device_owner=[constants.DEVICE_OWNER_DHCP]))
899
900 for port in dhcp_ports:
901 # Ports with a device_id like 'dhcp<host_id>-<network_id>'
902 # belong to Neutron DHCP agent so we'll skip those for OVN
903 # metadata.
904 if port['device_id'].startswith('dhcp'):
905 dhcp_ports.remove(port)
906
899 if not dhcp_ports: 907 if not dhcp_ports:
900 LOG.warning('Missing metadata port found in Neutron for ' 908 LOG.warning('Missing metadata port found in Neutron for '
901 'network %s', net['id']) 909 'network %s', net['id'])
diff --git a/networking_ovn/tests/functional/test_ovn_db_sync.py b/networking_ovn/tests/functional/test_ovn_db_sync.py
index 7c76acb..eaa9f4c 100644
--- a/networking_ovn/tests/functional/test_ovn_db_sync.py
+++ b/networking_ovn/tests/functional/test_ovn_db_sync.py
@@ -885,7 +885,8 @@ class TestOvnNbSync(base.TestOVNFunctionalBase):
885 db_metadata_ports_ids = [] 885 db_metadata_ports_ids = []
886 db_metadata_ports_nets = [] 886 db_metadata_ports_nets = []
887 for port in db_ports['ports']: 887 for port in db_ports['ports']:
888 if port['device_owner'] == constants.DEVICE_OWNER_DHCP: 888 if (port['device_owner'] == constants.DEVICE_OWNER_DHCP and
889 port['device_id'].startswith('ovnmeta')):
889 db_metadata_ports_ids.append(port['id']) 890 db_metadata_ports_ids.append(port['id'])
890 db_metadata_ports_nets.append(port['network_id']) 891 db_metadata_ports_nets.append(port['network_id'])
891 db_networks = self._list('networks') 892 db_networks = self._list('networks')
@@ -895,8 +896,7 @@ class TestOvnNbSync(base.TestOVNFunctionalBase):
895 _plugin_nb_ovn = self.mech_driver._nb_ovn 896 _plugin_nb_ovn = self.mech_driver._nb_ovn
896 plugin_metadata_ports = [row.name for row in ( 897 plugin_metadata_ports = [row.name for row in (
897 _plugin_nb_ovn._tables['Logical_Switch_Port'].rows.values()) 898 _plugin_nb_ovn._tables['Logical_Switch_Port'].rows.values())
898 if row.type == ovn_const.OVN_NEUTRON_OWNER_TO_PORT_TYPE.get( 899 if row.type == 'localport']
899 constants.DEVICE_OWNER_DHCP)]
900 900
901 if should_match: 901 if should_match:
902 # Check that metadata ports exist in both Neutron and OVN dbs. 902 # Check that metadata ports exist in both Neutron and OVN dbs.
@@ -1402,7 +1402,8 @@ class TestOvnNbSync(base.TestOVNFunctionalBase):
1402 db_ports = self._list('ports') 1402 db_ports = self._list('ports')
1403 db_metadata_ports = [port for port in db_ports['ports'] if 1403 db_metadata_ports = [port for port in db_ports['ports'] if
1404 port['device_owner'] == 1404 port['device_owner'] ==
1405 constants.DEVICE_OWNER_DHCP] 1405 constants.DEVICE_OWNER_DHCP and
1406 port['device_id'].startswith('ovnmeta')]
1406 lswitches = {} 1407 lswitches = {}
1407 ports_to_delete = len(db_metadata_ports) / 2 1408 ports_to_delete = len(db_metadata_ports) / 2
1408 for port in db_metadata_ports: 1409 for port in db_metadata_ports:
@@ -1414,8 +1415,7 @@ class TestOvnNbSync(base.TestOVNFunctionalBase):
1414 _plugin_nb_ovn = self.mech_driver._nb_ovn 1415 _plugin_nb_ovn = self.mech_driver._nb_ovn
1415 plugin_metadata_ports = [row.name for row in ( 1416 plugin_metadata_ports = [row.name for row in (
1416 _plugin_nb_ovn._tables['Logical_Switch_Port'].rows.values()) 1417 _plugin_nb_ovn._tables['Logical_Switch_Port'].rows.values())
1417 if row.type == ovn_const.OVN_NEUTRON_OWNER_TO_PORT_TYPE.get( 1418 if row.type == 'localport']
1418 constants.DEVICE_OWNER_DHCP)]
1419 1419
1420 with self.nb_api.transaction(check_error=True) as txn: 1420 with self.nb_api.transaction(check_error=True) as txn:
1421 for port in plugin_metadata_ports: 1421 for port in plugin_metadata_ports: