Accept HA chassis group commands in HAChassisGroupAdd*
Now "HAChassisGroupAddChassisCommand" and "HAChassisGroupDelChassisCommand" accept "HAChassisGroupAddCommand" as input parameter. That allows to add and remove "HA_Chassis" from the "HA_Chassis_Group" register in the same transaction that has created the HA Chassis Group. Related-Bug: #1995078 Change-Id: I443796cc2fcd7eef46f968a8383d068bab6ae670
This commit is contained in:
parent
149d7db4a7
commit
c8e7e9f619
|
@ -33,6 +33,16 @@ class Command(object, metaclass=abc.ABCMeta):
|
|||
:param transaction_options: Options to pass to the transaction
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def result(self):
|
||||
"""Returned value from the command execution"""
|
||||
|
||||
@result.setter
|
||||
@abc.abstractmethod
|
||||
def result(self, value):
|
||||
"""Setter of the result property"""
|
||||
|
||||
|
||||
class Transaction(object, metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
import logging
|
||||
import uuid
|
||||
|
||||
from ovs.db import idl
|
||||
from ovsdbapp.backend.ovs_idl import command as cmd
|
||||
from ovsdbapp.backend.ovs_idl import idlutils
|
||||
from ovsdbapp.backend.ovs_idl import rowview
|
||||
from ovsdbapp.backend.ovs_idl import transaction
|
||||
from ovsdbapp import exceptions
|
||||
|
||||
|
@ -190,7 +192,11 @@ class Backend(object):
|
|||
|
||||
# Handle commands by simply returning its result
|
||||
if isinstance(record, cmd.BaseCommand):
|
||||
if isinstance(record.result, (rowview.RowView, idl.Row)):
|
||||
# In case the command (creation) returns an existing record.
|
||||
return record.result
|
||||
else:
|
||||
record = record.result
|
||||
|
||||
t = self.tables[table]
|
||||
if isinstance(record, uuid.UUID):
|
||||
|
|
|
@ -30,7 +30,15 @@ class BaseCommand(api.Command):
|
|||
|
||||
def __init__(self, api):
|
||||
self.api = api
|
||||
self.result = None
|
||||
self._result = None
|
||||
|
||||
@property
|
||||
def result(self):
|
||||
return self._result
|
||||
|
||||
@result.setter
|
||||
def result(self, value):
|
||||
self._result = value
|
||||
|
||||
def execute(self, check_error=False, log_errors=True, **kwargs):
|
||||
try:
|
||||
|
|
|
@ -1804,16 +1804,15 @@ class HAChassisGroupAddChassisCommand(cmd.AddCommand):
|
|||
|
||||
def __init__(self, api, hcg_id, chassis, priority, **columns):
|
||||
super().__init__(api)
|
||||
self.hcg_id = hcg_id
|
||||
self.hcg = 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)
|
||||
hc_group = self.api.lookup('HA_Chassis_Group', self.hcg)
|
||||
found = False
|
||||
hc = None
|
||||
for hc in hc_group.ha_chassis:
|
||||
for hc in getattr(hc_group, 'ha_chassis', []):
|
||||
if hc.chassis_name != self.chassis:
|
||||
continue
|
||||
found = True
|
||||
|
@ -1835,26 +1834,29 @@ class HAChassisGroupDelChassisCommand(cmd.BaseCommand):
|
|||
|
||||
def __init__(self, api, hcg_id, chassis, if_exists=False):
|
||||
super().__init__(api)
|
||||
self.hcg_id = hcg_id
|
||||
self.hcg = 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:
|
||||
hc_group = self.api.lookup('HA_Chassis_Group', self.hcg)
|
||||
except idlutils.RowNotFound as exc:
|
||||
if self.if_exists:
|
||||
return
|
||||
|
||||
raise RuntimeError('HA Chassis Group %s does not exist' %
|
||||
utils.get_uuid(self.hcg)) from exc
|
||||
|
||||
hc = None
|
||||
for hc in hc_group.ha_chassis:
|
||||
for hc in getattr(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)
|
||||
'HA Chassis %s does not exist' % utils.get_uuid(self.hcg))
|
||||
|
||||
hc_group.delvalue('ha_chassis', hc)
|
||||
hc.delete()
|
||||
|
|
|
@ -2192,6 +2192,37 @@ class TestHAChassisGroup(OvnNorthboundTest):
|
|||
check_error=True)
|
||||
self.assertEqual([], hcg.ha_chassis)
|
||||
|
||||
def test_ha_chassis_group_add_delete_chassis_within_txn(self):
|
||||
with self.api.create_transaction(check_error=True) as txn:
|
||||
hcg_cmd = txn.add(self.api.ha_chassis_group_add(self.hcg_name))
|
||||
priority = 20
|
||||
txn.add(self.api.ha_chassis_group_add_chassis(
|
||||
hcg_cmd, self.chassis, priority))
|
||||
|
||||
# Assert that the HA Chassis entry was created
|
||||
hcg = self.api.ha_chassis_group_get(self.hcg_name).execute(
|
||||
check_error=True)
|
||||
hc = self.api.db_find(
|
||||
'HA_Chassis',
|
||||
('chassis_name', '=', self.chassis)).execute(check_error=True)
|
||||
self.assertEqual(priority, hc[0]['priority'])
|
||||
ha_chassis_uuid_list = [hc.uuid for hc in hcg.ha_chassis]
|
||||
self.assertEqual(ha_chassis_uuid_list, [hc[0]['_uuid']])
|
||||
|
||||
with self.api.create_transaction(check_error=True) as txn:
|
||||
hcg_cmd = txn.add(self.api.ha_chassis_group_add(self.hcg_name,
|
||||
may_exist=True))
|
||||
txn.add(self.api.ha_chassis_group_del_chassis(hcg_cmd,
|
||||
self.chassis))
|
||||
|
||||
hcg = self.api.ha_chassis_group_get(self.hcg_name).execute(
|
||||
check_error=True)
|
||||
ha = self.api.db_find(
|
||||
'HA_Chassis',
|
||||
('chassis_name', '=', self.chassis)).execute(check_error=True)
|
||||
self.assertEqual([], ha)
|
||||
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(
|
||||
|
|
|
@ -50,11 +50,19 @@ class MockRow(object):
|
|||
|
||||
class MockCommand(api.Command):
|
||||
def __init__(self, result):
|
||||
self.result = result
|
||||
self._result = result
|
||||
|
||||
def execute(self, **kwargs):
|
||||
pass
|
||||
|
||||
@property
|
||||
def result(self):
|
||||
return self._result
|
||||
|
||||
@result.setter
|
||||
def result(self, value):
|
||||
self._result = value
|
||||
|
||||
|
||||
class TestIdlUtils(base.TestCase):
|
||||
def test_condition_match(self):
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
import uuid
|
||||
|
||||
import netaddr
|
||||
from ovs.db import idl
|
||||
|
||||
from ovsdbapp import api
|
||||
from ovsdbapp.backend.ovs_idl import rowview
|
||||
|
||||
|
||||
# NOTE(twilson) Clearly these are silly, but they are good enough for now
|
||||
# I'm happy for someone to replace them with better parsing
|
||||
|
@ -76,3 +81,15 @@ def is_uuid_like(val):
|
|||
return str(uuid.UUID(val)).replace('-', '') == _format_uuid_string(val)
|
||||
except (TypeError, ValueError, AttributeError):
|
||||
return False
|
||||
|
||||
|
||||
def get_uuid(reg_uuid_or_cmd):
|
||||
"""Return the UUID of a UUID itself or a BaseCommand"""
|
||||
if isinstance(reg_uuid_or_cmd, api.Command):
|
||||
reg_uuid = reg_uuid_or_cmd.result
|
||||
if isinstance(reg_uuid, (rowview.RowView, idl.Row)):
|
||||
reg_uuid = reg_uuid.uuid
|
||||
else:
|
||||
reg_uuid = reg_uuid_or_cmd
|
||||
|
||||
return reg_uuid
|
||||
|
|
Loading…
Reference in New Issue