Merge "HA_Chassis_Group create command with HA_Chassis assignation"

This commit is contained in:
Zuul 2025-05-05 10:26:07 +00:00 committed by Gerrit Code Review
commit ba4a68e385
3 changed files with 153 additions and 0 deletions

View File

@ -13,6 +13,7 @@
# under the License.
import abc
import copy
import uuid
from oslo_utils import timeutils
@ -103,6 +104,49 @@ def _add_gateway_chassis(api, txn, lrp_name, val):
return 'gateway_chassis', uuid_list
def _sync_ha_chassis_group(txn, nb_api, name, chassis_priority,
may_exist=False, table_name='HA_Chassis_Group',
**columns):
result = None
hcg = nb_api.lookup(table_name, name, default=None)
if hcg:
if not may_exist:
raise RuntimeError(_('HA_Chassis_Group %s exists' % name))
else:
hcg = txn.insert(nb_api._tables[table_name])
hcg.name = name
command.BaseCommand.set_columns(hcg, **columns)
result = hcg.uuid
# HA_Chassis registers handling.
# Remove the non-existing chassis in ``self.chassis_priority``
hc_to_remove = []
for hc in getattr(hcg, 'ha_chassis', []):
if hc.chassis_name not in chassis_priority:
hc_to_remove.append(hc)
for hc in hc_to_remove:
hcg.delvalue('ha_chassis', hc)
hc.delete()
# Update the priority of the existing chassis.
for hc in getattr(hcg, 'ha_chassis', []):
hc_priority = chassis_priority.pop(hc.chassis_name)
hc.priority = hc_priority
# Add the non-existing HA_Chassis registers.
for hc_name, priority in chassis_priority.items():
hc = txn.insert(nb_api.tables['HA_Chassis'])
hc.chassis_name = hc_name
hc.priority = priority
hcg.addvalue('ha_chassis', hc)
if not result:
result = rowview.RowView(hcg)
return result
class CheckLivenessCommand(command.BaseCommand):
def run_idl(self, txn):
# txn.pre_commit responsible for updating nb_global.nb_cfg, but
@ -1135,3 +1179,22 @@ class UnsetLSwitchPortToVirtualTypeCommand(command.BaseCommand):
virtual_parents)
setattr(lsp, 'options', options)
class HAChassisGroupWithHCAddCommand(command.AddCommand):
table_name = 'HA_Chassis_Group'
def __init__(self, api, name, chassis_priority, may_exist=False,
**columns):
super().__init__(api)
self.name = name
self.chassis_priority = copy.deepcopy(chassis_priority)
self.may_exist = may_exist
self.columns = columns
def run_idl(self, txn):
# HA_Chassis_Group register creation.
self.result = _sync_ha_chassis_group(
txn, self.api, self.name, self.chassis_priority,
may_exist=self.may_exist, table_name=self.table_name,
**self.columns)

View File

@ -912,6 +912,12 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend):
return cmd.SetLRouterMacAgeLimitCommand(
self, router, cfg.get_ovn_mac_binding_age_threshold())
def ha_chassis_group_with_hc_add(self, name, chassis_priority,
may_exist=False, **columns):
return cmd.HAChassisGroupWithHCAddCommand(
self, name, chassis_priority, may_exist=may_exist,
**columns)
class OvsdbSbOvnIdl(sb_impl_idl.OvnSbApiIdlImpl, Backend):
@n_utils.classproperty

View File

@ -12,6 +12,7 @@
# under the License.
#
from collections import abc
import copy
from unittest import mock
import uuid
@ -695,6 +696,89 @@ class TestNbApi(BaseOvnIdlTest):
self.assertEqual(external_ids, lr.static_routes[0].external_ids)
def _cleanup_delete_hcg(self, hcg_name):
if isinstance(hcg_name, str):
self.nbapi.db_destroy('HA_Chassis_Group', hcg_name).execute(
check_error=True)
elif isinstance(hcg_name, abc.Iterable):
for _hcg_name in hcg_name:
self.nbapi.db_destroy('HA_Chassis_Group', _hcg_name).execute(
check_error=True)
def _check_hcg(self, hcg, hcg_name, chassis_priority,
chassis_priority_deleted=None):
self.assertEqual(hcg_name, hcg.name)
self.assertEqual(len(chassis_priority), len(hcg.ha_chassis))
for hc in hcg.ha_chassis:
self.assertEqual(chassis_priority[hc.chassis_name], hc.priority)
if chassis_priority_deleted:
for hc_name in chassis_priority_deleted:
self.assertIsNone(
self.nbapi.lookup('HA_Chassis', hc_name, default=None))
def test_ha_chassis_group_with_hc_add_no_existing_hcg(self):
chassis_priority = {'ch1': 1, 'ch2': 2, 'ch3': 3, 'ch4': 4}
hcg_name = uuidutils.generate_uuid()
self.addCleanup(self._cleanup_delete_hcg, hcg_name)
hcg = self.nbapi.ha_chassis_group_with_hc_add(
hcg_name, chassis_priority).execute(check_error=True)
self._check_hcg(hcg, hcg_name, chassis_priority)
def test_ha_chassis_group_with_hc_add_existing_hcg(self):
chassis_priority = {'ch1': 1, 'ch2': 2, 'ch3': 3, 'ch4': 4}
hcg_name = uuidutils.generate_uuid()
self.addCleanup(self._cleanup_delete_hcg, hcg_name)
self.nbapi.ha_chassis_group_with_hc_add(
hcg_name, chassis_priority).execute(check_error=True)
cmd = self.nbapi.ha_chassis_group_with_hc_add(
hcg_name, chassis_priority)
self.assertRaises(RuntimeError, cmd.execute, check_error=True)
def test_ha_chassis_group_with_hc_add_existing_hcg_may_exist(self):
chassis_priority = {'ch1': 1, 'ch2': 2, 'ch3': 3, 'ch4': 4}
hcg_name = uuidutils.generate_uuid()
self.addCleanup(self._cleanup_delete_hcg, hcg_name)
hcg = None
for _ in range(2):
hcg = self.nbapi.ha_chassis_group_with_hc_add(
hcg_name, chassis_priority, may_exist=True).execute(
check_error=True)
self._check_hcg(hcg, hcg_name, chassis_priority)
def test_ha_chassis_group_with_hc_add_existing_hcg_update_chassis(self):
# This test:
# - adds new chassis: ch5, ch6
# - removes others: ch3, ch4
# - changes the priority of the existing ones ch1, ch2
chassis_priority = {'ch1': 1, 'ch2': 2, 'ch3': 3, 'ch4': 4}
hcg_name = uuidutils.generate_uuid()
self.addCleanup(self._cleanup_delete_hcg, hcg_name)
self.nbapi.ha_chassis_group_with_hc_add(
hcg_name, chassis_priority).execute(check_error=True)
chassis_priority = {'ch1': 2, 'ch2': 1, 'ch5': 3, 'ch6': 4}
hcg = self.nbapi.ha_chassis_group_with_hc_add(
hcg_name, chassis_priority, may_exist=True).execute(
check_error=True)
self._check_hcg(hcg, hcg_name, chassis_priority,
chassis_priority_deleted=['ch3', 'ch4'])
def test_ha_chassis_group_with_hc_add_two_hcg(self):
# Both HCG will have the same chassis priority (the same chassis
# names, that is something very common.
chassis_priority1 = {'ch1': 1, 'ch2': 2, 'ch3': 3, 'ch4': 4}
chassis_priority2 = {'ch1': 11, 'ch2': 12, 'ch3': 13, 'ch4': 14}
hcg_name1 = uuidutils.generate_uuid()
hcg_name2 = uuidutils.generate_uuid()
self.addCleanup(self._cleanup_delete_hcg, [hcg_name1, hcg_name2])
hcg1 = self.nbapi.ha_chassis_group_with_hc_add(
hcg_name1, chassis_priority1).execute(check_error=True)
hcg2 = self.nbapi.ha_chassis_group_with_hc_add(
hcg_name2, chassis_priority2).execute(check_error=True)
self._check_hcg(hcg1, hcg_name1, chassis_priority1)
self._check_hcg(hcg2, hcg_name2, chassis_priority2)
class TestIgnoreConnectionTimeout(BaseOvnIdlTest):
@classmethod