Skip to content

Commit c8376e2

Browse files
committed
Implement get_port_type_virtual_and_parents method
This patch implements a method to determine if a LSP is virtual or not. In case the port is virtual, the method returns the type name, the virtual IP address and the parents (the ports that are using this virtual IP address as allowed address) The goal of this patch is to decouple this method from the ``_get_port_options`` method code. Conflicts: neutron/common/ovn/utils.py Related-Bug: #2018529 Change-Id: I58b213f79bad9de91a6181745da526500dc9c615 (cherry picked from commit ac24dbe)
1 parent 133af42 commit c8376e2

File tree

3 files changed

+92
-13
lines changed

3 files changed

+92
-13
lines changed

neutron/common/ovn/utils.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,3 +895,39 @@ def get_subnets_address_scopes(context, subnets, fixed_ips, ml2_plugin):
895895
pass
896896

897897
return address4_scope_id, address6_scope_id
898+
899+
900+
def get_port_type_virtual_and_parents(subnets, fixed_ips, network_id, port_id,
901+
nb_idl):
902+
"""Returns if a port is type virtual and its corresponding parents.
903+
904+
:param subnets: (list of dict) subnet dictionaries
905+
:param fixed_ips: (list of dict) fixed IPs of several subnets (usually
906+
belonging to a network but not mandatory)
907+
:param network_id: (string) network ID
908+
:param port_id: (string) port ID
909+
:param nb_idl: (``OvsdbNbOvnIdl``) OVN Northbound IDL
910+
:return: (tuple, three strings) (1) the virtual type ('' if not virtual),
911+
(2) the virtual IP address and (3) the virtual parents
912+
"""
913+
port_type, virtual_ip, virtual_parents = '', None, None
914+
if not subnets:
915+
return port_type, virtual_ip, virtual_parents
916+
917+
subnets_by_id = {subnet['id'] for subnet in subnets}
918+
for fixed_ip in fixed_ips:
919+
if fixed_ip.get('subnet_id') not in subnets_by_id:
920+
continue
921+
922+
# Check if the port being created is a virtual port
923+
parents = get_virtual_port_parents(
924+
nb_idl, fixed_ip['ip_address'], network_id, port_id)
925+
if not parents:
926+
continue
927+
928+
port_type = constants.LSP_TYPE_VIRTUAL
929+
virtual_ip = fixed_ip['ip_address']
930+
virtual_parents = ','.join(parents)
931+
break
932+
933+
return port_type, virtual_ip, virtual_parents

neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,20 @@ def _get_port_options(self, port):
341341
address4_scope_id, address6_scope_id = (
342342
utils.get_subnets_address_scopes(context, subnets, ip_subnets,
343343
self._plugin))
344+
p_type, virtual_ip, virtual_parents = (
345+
utils.get_port_type_virtual_and_parents(
346+
subnets, ip_subnets, port['network_id'], port['id'],
347+
self._nb_idl))
348+
if p_type:
349+
port_type = ovn_const.LSP_TYPE_VIRTUAL
350+
options[ovn_const.LSP_OPTIONS_VIRTUAL_IP_KEY] = virtual_ip
351+
options[ovn_const.LSP_OPTIONS_VIRTUAL_PARENTS_KEY] = (
352+
virtual_parents)
353+
344354
if subnets:
345355
for ip in ip_subnets:
346356
ip_addr = ip['ip_address']
347357
address += ' ' + ip_addr
348-
subnet = None
349358

350359
try:
351360
subnet = [
@@ -361,18 +370,6 @@ def _get_port_options(self, port):
361370
cidrs += ' {}/{}'.format(ip['ip_address'],
362371
subnet['cidr'].split('/')[1])
363372

364-
# Check if the port being created is a virtual port
365-
parents = utils.get_virtual_port_parents(
366-
self._nb_idl, ip_addr, port['network_id'], port['id'])
367-
if not parents:
368-
continue
369-
370-
port_type = ovn_const.LSP_TYPE_VIRTUAL
371-
options[ovn_const.LSP_OPTIONS_VIRTUAL_IP_KEY] = ip_addr
372-
options[ovn_const.LSP_OPTIONS_VIRTUAL_PARENTS_KEY] = (
373-
','.join(parents))
374-
break
375-
376373
# Metadata port.
377374
if port['device_owner'] == const.DEVICE_OWNER_DISTRIBUTED:
378375
port_type = ovn_const.LSP_TYPE_LOCALPORT

neutron/tests/unit/common/ovn/test_utils.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,3 +1003,49 @@ def test_address_scope(self):
10031003
address4, address6 = utils.get_subnets_address_scopes(
10041004
mock.ANY, subnets, fixed_ips, self.ml2_plugin)
10051005
self.assertEqual(('scope4', 'scope6'), (address4, address6))
1006+
1007+
1008+
class GetPortTypeVirtualAndParentsTestCase(base.BaseTestCase):
1009+
1010+
def test_no_subnets(self):
1011+
subnets = []
1012+
fixed_ips = []
1013+
port_type, virtual_ip, virtual_parents = (
1014+
utils.get_port_type_virtual_and_parents(subnets, fixed_ips, 'net1',
1015+
'port1', mock.ANY))
1016+
self.assertEqual(('', None, None),
1017+
(port_type, virtual_ip, virtual_parents))
1018+
1019+
@mock.patch.object(utils, 'get_virtual_port_parents', return_value=[])
1020+
def test_no_parents(self, *args):
1021+
subnets = [
1022+
{'id': 'subnet1'},
1023+
{'id': 'subnet2'},
1024+
]
1025+
fixed_ips = [
1026+
{'subnet_id': 'subnet1', 'ip_address': '1.2.3.4'},
1027+
{'subnet_id': 'subnet2', 'ip_address': '1.2.3.5'},
1028+
]
1029+
port_type, virtual_ip, virtual_parents = (
1030+
utils.get_port_type_virtual_and_parents(subnets, fixed_ips, 'net1',
1031+
'port1', mock.ANY))
1032+
self.assertEqual(('', None, None),
1033+
(port_type, virtual_ip, virtual_parents))
1034+
1035+
@mock.patch.object(utils, 'get_virtual_port_parents',
1036+
return_value=['parent1', 'parent2'])
1037+
def test_with_parents(self, *args):
1038+
subnets = [
1039+
{'id': 'subnet1'},
1040+
{'id': 'subnet2'},
1041+
]
1042+
fixed_ips = [
1043+
{'subnet_id': 'subnet1', 'ip_address': '1.2.3.4'},
1044+
{'subnet_id': 'subnet2', 'ip_address': '1.2.3.5'},
1045+
]
1046+
port_type, virtual_ip, virtual_parents = (
1047+
utils.get_port_type_virtual_and_parents(subnets, fixed_ips, 'net1',
1048+
'port1', mock.ANY))
1049+
self.assertEqual((constants.LSP_TYPE_VIRTUAL, '1.2.3.4',
1050+
'parent1,parent2'),
1051+
(port_type, virtual_ip, virtual_parents))

0 commit comments

Comments
 (0)