Skip to content

Commit d500101

Browse files
ralonsohmnasiadka
authored andcommitted
[OVN] Add a Logical_Router_Port HA_Chassis retrieval method
This method returns the name of the chassis assigned in the "HA_Chassis_Group" associated with the "Logical_Router_Port", ordered by the priority. Partial-Bug: #2092271 Change-Id: Ifbecf0f2699297a85e67299ce6d8ec98fd41fae4 Conflicts: neutron/common/ovn/utils.py
1 parent b922e6f commit d500101

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

neutron/common/ovn/utils.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,3 +1377,41 @@ def validate_port_forwarding_configuration():
13771377
if any(net_type in provider_network_types
13781378
for net_type in cfg.CONF.ml2.tenant_network_types):
13791379
raise ovn_exc.InvalidPortForwardingConfiguration()
1380+
1381+
1382+
def ovs_persist_uuid_supported(nb_idl):
1383+
# OVS 3.1+ contain the persist_uuid feature that allows choosing the UUID
1384+
# that will be stored in the DB. It was broken prior to 3.1.5/3.2.3/3.3.1
1385+
# so this will return True only for the fixed version. As actually testing
1386+
# the fix requires committing a transaction, an implementation detail is
1387+
# tested. This can be removed once a fixed version is required.
1388+
global _OVS_PERSIST_UUID
1389+
if _OVS_PERSIST_UUID is _SENTINEL:
1390+
_OVS_PERSIST_UUID = isinstance(
1391+
next(iter(nb_idl.tables["NB_Global"].rows.data.values())), list)
1392+
LOG.debug(f"OVS persist_uuid supported={_OVS_PERSIST_UUID}")
1393+
return _OVS_PERSIST_UUID
1394+
1395+
1396+
def get_logical_router_port_ha_chassis(nb_idl, lrp, priorities=None):
1397+
"""Get the list of chassis hosting this Logical_Router_Port.
1398+
1399+
:param nb_idl: (``OvsdbNbOvnIdl``) OVN Northbound IDL
1400+
:param lrp: Logical_Router_Port
1401+
:param priorities: (list of int) a list of HA_Chassis chassis priorities
1402+
to search for
1403+
:return: List of tuples (chassis_name, priority) sorted by priority. If
1404+
``priorities`` is set then only chassis matching of these
1405+
priorities are returned.
1406+
"""
1407+
chassis = []
1408+
lrp = nb_idl.lookup('Logical_Router_Port', lrp.name, default=None)
1409+
if not lrp or not lrp.ha_chassis_group:
1410+
return chassis
1411+
1412+
for hc in lrp.ha_chassis_group[0].ha_chassis:
1413+
if priorities and hc.priority not in priorities:
1414+
continue
1415+
chassis.append((hc.chassis_name, hc.priority))
1416+
1417+
return chassis

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# under the License.
1414

1515
import ddt
16+
from neutron_lib.api.definitions import external_net
1617
from neutron_lib.api.definitions import portbindings
1718
from oslo_utils import uuidutils
1819
from ovsdbapp.backend.ovs_idl import event
@@ -321,3 +322,76 @@ def test_without_transaction(self, method, _args, _kwargs):
321322
def test_needed_parameters(self, method):
322323
self.assertRaises(RuntimeError, method, uuidutils.generate_uuid(),
323324
None, None)
325+
326+
327+
class TestGetLogicalRouterPortHAChassis(base.TestOVNFunctionalBase):
328+
def _create_network_and_port(self):
329+
kwargs = {external_net.EXTERNAL: True, 'as_admin': True}
330+
net = self._make_network(self.fmt, 'n1', True, **kwargs)['network']
331+
port_data = {'port': {'network_id': net['id'],
332+
'tenant_id': self._tenant_id,}}
333+
port_req = self.new_create_request('ports', port_data, self.fmt)
334+
port_res = port_req.get_response(self.api)
335+
return self.deserialize(self.fmt, port_res)['port']
336+
337+
def _create_gw_chassis(self, num_chassis):
338+
chassis = []
339+
for _ in range(num_chassis):
340+
chassis.append(self.add_fake_chassis(
341+
uuidutils.generate_uuid(), azs=[],
342+
enable_chassis_as_gw=True))
343+
return chassis
344+
345+
def _create_router(self, network_id):
346+
gw_info = {'network_id': network_id}
347+
router = {'router': {'name': uuidutils.generate_uuid(),
348+
'admin_state_up': True,
349+
'tenant_id': self._tenant_id,
350+
'external_gateway_info': gw_info}}
351+
return self.l3_plugin.create_router(self.context, router)
352+
353+
def _set_lrp_hcg(self, gw_port_id, hcg):
354+
lrp_name = utils.ovn_lrouter_port_name(gw_port_id)
355+
self.nb_api.db_set(
356+
'Logical_Router_Port', lrp_name,
357+
('ha_chassis_group', hcg.uuid)).execute()
358+
return self.nb_api.lookup('Logical_Router_Port', lrp_name)
359+
360+
def _get_router_hcg(self, router_id):
361+
hcg_name = utils.ovn_name(router_id)
362+
return self.nb_api.lookup('HA_Chassis_Group', hcg_name)
363+
364+
def _check_chassis(self, ha_chassis, expected_chassis, priorities=None):
365+
length = len(priorities) if priorities else len(expected_chassis)
366+
self.assertEqual(length, len(ha_chassis))
367+
ch_priorities = set([])
368+
for hc in ha_chassis:
369+
self.assertIn(hc[0], expected_chassis)
370+
ch_priorities.add(hc[1])
371+
self.assertEqual(length, len(ch_priorities))
372+
if priorities:
373+
for ch_priority in ch_priorities:
374+
self.assertIn(ch_priority, priorities)
375+
376+
def test_get_ha_chassis(self):
377+
port = self._create_network_and_port()
378+
ch_list = self._create_gw_chassis(5)
379+
router = self._create_router(port['network_id'])
380+
hcg = self._get_router_hcg(router['id'])
381+
lrp = self._set_lrp_hcg(router['gw_port_id'], hcg)
382+
383+
ha_chassis = utils.get_logical_router_port_ha_chassis(self.nb_api, lrp)
384+
self._check_chassis(ha_chassis, ch_list)
385+
386+
def test_get_ha_chassis_priorities(self):
387+
port = self._create_network_and_port()
388+
ch_list = self._create_gw_chassis(5)
389+
router = self._create_router(port['network_id'])
390+
hcg = self._get_router_hcg(router['id'])
391+
lrp = self._set_lrp_hcg(router['gw_port_id'], hcg)
392+
393+
prio = [ovn_const.HA_CHASSIS_GROUP_HIGHEST_PRIORITY,
394+
ovn_const.HA_CHASSIS_GROUP_HIGHEST_PRIORITY - 1]
395+
ha_chassis = utils.get_logical_router_port_ha_chassis(
396+
self.nb_api, lrp, priorities=prio)
397+
self._check_chassis(ha_chassis, ch_list, priorities=prio)

0 commit comments

Comments
 (0)