Add HA Chassis Group related commands

This patch is introducing new commands to ovsdbapp to work with the new
HA_Chassis_Group and HA_Chassis tables in OVN Northbound database.

These tables were introduced by the commit [0] in core OVN which created
a new type of port called "external" that can be used for various things
including but not limited to: SR-IOV and baremetal booting support.

[0]
b31c76000b

Change-Id: I77ad33223607bee63a96e548f308bbffc1c9de52
Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com>
This commit is contained in:
Lucas Alvares Gomes 2019-08-21 13:31:59 +01:00
parent 68d462d355
commit 74b52bb349
4 changed files with 292 additions and 0 deletions

View File

@ -968,3 +968,70 @@ class API(api.API):
:type pg_id: string or uuid.UUID
:returns: :class:`Command` with RowView result
"""
@abc.abstractmethod
def ha_chassis_group_add(self, name, may_exist=False, **columns):
"""Create a HA Chassis Group
:param name: The name of the ha chassis group
:type name: string
:param may_exist: If True, don't fail if the ha chassis group
already exists
:type may_exist: bool
:param columns: Additional columns to directly set on the ha
chassis group (e.g external_ids)
:type columns: dictionary
:returns: :class:`Command` with RowView result
"""
@abc.abstractmethod
def ha_chassis_group_del(self, name, if_exists=False):
"""Delete a HA Chassis Group
:param name: The name of the ha chassis group
:type name: string
:param if_exists: If True, don't fail if the ha chassis group
doesn't exist
:type if_exists: boolean
:returns: :class:`Command` with no result
"""
@abc.abstractmethod
def ha_chassis_group_get(self, name):
"""Get HA Chassis Group
:param name: The name or uuid of the ha chassis group
:type name: string or uuid.UUID
:returns: :class:`Command` with RowView result
"""
@abc.abstractmethod
def ha_chassis_group_add_chassis(self, hcg_id, chassis, priority,
**columns):
"""Add a HA Chassis to a HA Chassis Group
:param hcg_id: The name or uuid of the ha chassis group
:type hcg_id: string or uuid.UUID
:param chassis: The name of the ha chassis
:type chassis: string
:param priority: The priority of the ha chassis
:type priority: int
:param columns: Additional columns to directly set on the ha
chassis (e.g external_ids)
:type columns: dictionary
:returns: :class:`Command` with RowView result
"""
@abc.abstractmethod
def ha_chassis_group_del_chassis(self, hcg_id, chassis, if_exists=False):
"""Delete a HA Chassis from a HA Chassis Group
:param hcg_id: The name or uuid of the ha chassis group
:type hcg_id: string or uuid.UUID
:param chassis: The name of the ha chassis
:type chassis: string
:param if_exists: If True, don't fail if the ha chassis
doesn't exist
:type if_exists: boolean
:returns: :class:`Command` with no result
"""

View File

@ -1344,3 +1344,111 @@ class GatewayChassisAddCommand(cmd.AddCommand):
gwc.priority = self.priority
self.set_columns(gwc, **self.columns)
self.result = gwc
class HAChassisGroupAddCommand(cmd.AddCommand):
table_name = 'HA_Chassis_Group'
def __init__(self, api, name, may_exist=False, **columns):
super(HAChassisGroupAddCommand, self).__init__(api)
self.name = name
self.may_exist = may_exist
self.columns = columns
def run_idl(self, txn):
if self.may_exist:
try:
hcg = self.api.lookup(self.table_name, self.name)
self.result = rowview.RowView(hcg)
return
except idlutils.RowNotFound:
pass
hcg = txn.insert(self.api._tables[self.table_name])
hcg.name = self.name
self.set_columns(hcg, **self.columns)
self.result = hcg.uuid
class HAChassisGroupDelCommand(cmd.BaseCommand):
table_name = 'HA_Chassis_Group'
def __init__(self, api, name, if_exists=False):
super(HAChassisGroupDelCommand, self).__init__(api)
self.name = name
self.if_exists = if_exists
def run_idl(self, txn):
try:
hcg = self.api.lookup(self.table_name, self.name)
hcg.delete()
except idlutils.RowNotFound:
if self.if_exists:
return
raise RuntimeError(
'HA Chassis Group %s does not exist' % self.name)
class HAChassisGroupGetCommand(cmd.BaseGetRowCommand):
table = 'HA_Chassis_Group'
class HAChassisGroupAddChassisCommand(cmd.AddCommand):
table_name = 'HA_Chassis'
def __init__(self, api, hcg_id, chassis, priority, **columns):
super(HAChassisGroupAddChassisCommand, self).__init__(api)
self.hcg_id = hcg_id
self.chassis = chassis
self.priority = priority
self.columns = columns
def run_idl(self, txn):
hc_group = self.api.lookup('HA_Chassis_Group', self.hcg_id)
found = False
hc = None
for hc in hc_group.ha_chassis:
if hc.chassis_name != self.chassis:
continue
found = True
break
else:
hc = txn.insert(self.api.tables[self.table_name])
hc.chassis_name = self.chassis
hc.priority = self.priority
self.set_columns(hc, **self.columns)
if not found:
hc_group.addvalue('ha_chassis', hc)
self.result = hc.uuid
class HAChassisGroupDelChassisCommand(cmd.BaseCommand):
table_name = 'HA_Chassis'
def __init__(self, api, hcg_id, chassis, if_exists=False):
super(HAChassisGroupDelChassisCommand, self).__init__(api)
self.hcg_id = hcg_id
self.chassis = chassis
self.if_exists = if_exists
def run_idl(self, txn):
try:
hc_group = self.api.lookup('HA_Chassis_Group', self.hcg_id)
except idlutils.RowNotFound:
if self.if_exists:
return
hc = None
for hc in hc_group.ha_chassis:
if hc.chassis_name == self.chassis:
break
else:
if self.if_exists:
return
raise RuntimeError(
'HA Chassis %s does not exist' % self.hcg_id)
hc_group.delvalue('ha_chassis', hc)
hc.delete()

View File

@ -296,3 +296,22 @@ class OvnNbApiIdlImpl(ovs_idl.Backend, api.API):
def pg_get(self, pg):
return cmd.PgGetCommand(self, pg)
def ha_chassis_group_add(self, name, may_exist=False, **columns):
return cmd.HAChassisGroupAddCommand(
self, name, may_exist=may_exist, **columns)
def ha_chassis_group_del(self, name, if_exists=False):
return cmd.HAChassisGroupDelCommand(self, name, if_exists=if_exists)
def ha_chassis_group_get(self, name):
return cmd.HAChassisGroupGetCommand(self, name)
def ha_chassis_group_add_chassis(self, hcg_id, chassis, priority,
**columns):
return cmd.HAChassisGroupAddChassisCommand(
self, hcg_id, chassis, priority, **columns)
def ha_chassis_group_del_chassis(self, hcg_id, chassis, if_exists=False):
return cmd.HAChassisGroupDelChassisCommand(
self, hcg_id, chassis, if_exists=if_exists)

View File

@ -1448,3 +1448,101 @@ class TestPortGroup(OvnNorthboundTest):
# Assert that if if_exists is True it won't raise an error
self.api.pg_del_ports(self.pg_name, non_existent_res,
if_exists=True).execute(check_error=True)
class TestHAChassisGroup(OvnNorthboundTest):
def setUp(self):
super(TestHAChassisGroup, self).setUp()
self.hcg_name = 'ha-group-%s' % ovsdb_utils.generate_uuid()
self.chassis = 'chassis-%s' % ovsdb_utils.generate_uuid()
def test_ha_chassis_group(self):
# Assert the HA Chassis Group was added
self.api.ha_chassis_group_add(self.hcg_name).execute(check_error=True)
hcg = self.api.ha_chassis_group_get(self.hcg_name).execute(
check_error=True)
self.assertEqual(self.hcg_name, hcg.name)
# Assert the HA Chassis Group was deleted
self.api.ha_chassis_group_del(self.hcg_name).execute(check_error=True)
cmd = self.api.ha_chassis_group_get(self.hcg_name)
self.assertRaises(idlutils.RowNotFound, cmd.execute, check_error=True)
def test_ha_chassis_group_add_delete_chassis(self):
self.api.ha_chassis_group_add(self.hcg_name).execute(check_error=True)
priority = 20
self.api.ha_chassis_group_add_chassis(
self.hcg_name, self.chassis, priority).execute(check_error=True)
# Assert that the HA Chassis entry was created
row = self.api.db_find(
'HA_Chassis',
('chassis_name', '=', self.chassis)).execute(check_error=True)
self.assertEqual(priority, row[0]['priority'])
# Assert that the HA Chassis entry was associated with
# the HA Chassis Group
hcg = self.api.ha_chassis_group_get(self.hcg_name).execute(
check_error=True)
self.assertEqual(self.chassis, hcg.ha_chassis[0].chassis_name)
# Deletes the HA Chassis entry
self.api.ha_chassis_group_del_chassis(
self.hcg_name, self.chassis).execute(check_error=True)
row = self.api.db_find(
'HA_Chassis',
('chassis_name', '=', self.chassis)).execute(check_error=True)
self.assertEqual([], row)
# Assert that the deleted HA Chassis entry was dissociated from
# the HA Chassis Group
hcg = self.api.ha_chassis_group_get(self.hcg_name).execute(
check_error=True)
self.assertEqual([], hcg.ha_chassis)
def test_ha_chassis_group_if_exists(self):
self.api.ha_chassis_group_add(self.hcg_name).execute(check_error=True)
self.api.ha_chassis_group_add_chassis(
self.hcg_name, self.chassis, priority=10).execute(check_error=True)
# Deletes the HA Chassis entry
self.api.ha_chassis_group_del_chassis(
self.hcg_name, self.chassis).execute(check_error=True)
row = self.api.db_find(
'HA_Chassis',
('chassis_name', '=', self.chassis)).execute(check_error=True)
self.assertEqual([], row)
# Tries to delete it again, since if_exists=True it shouldn't raise
# any errors
self.api.ha_chassis_group_del_chassis(
self.hcg_name, self.chassis, if_exists=True).execute(
check_error=True)
# Tries to delete it again with if_exists=False, now it should raise
# a RuntimeError
cmd = self.api.ha_chassis_group_del_chassis(
self.hcg_name, self.chassis, if_exists=False)
self.assertRaises(RuntimeError, cmd.execute, check_error=True)
# Deletes the HA Chassis Group entry
self.api.ha_chassis_group_del(self.hcg_name).execute(check_error=True)
cmd = self.api.ha_chassis_group_get(self.hcg_name)
self.assertRaises(idlutils.RowNotFound, cmd.execute, check_error=True)
# Tries to delete it again, since if_exists=True it shouldn't raise
# any errors
self.api.ha_chassis_group_del(
self.hcg_name, if_exists=True).execute(check_error=True)
# Tries to delete it again with if_exists=False, now it should raise
# a RuntimeError
cmd = self.api.ha_chassis_group_del(self.hcg_name)
self.assertRaises(RuntimeError, cmd.execute, check_error=True)
def test_ha_chassis_group_may_exist(self):
cmd = self.api.ha_chassis_group_add(self.hcg_name, may_exist=True)
hcg1 = cmd.execute(check_error=True)
hcg2 = cmd.execute(check_error=True)
self.assertEqual(hcg1, hcg2)