Fix OVN DB sync when syncing an OVN LB from scratch

When running octavia-ovn-db-sync-tool over a OVN LB that doesn't
exist on OVN NB DB the tool is reporting error status to Octavia API
on the last step.

This patch is fixing the dict reported to Octavia API that
was nested by error.

Closes-Bug: #2103518
Change-Id: Iac6ce4ed93e2c080050df87f81777bacb6b507c6
This commit is contained in:
Fernando Royo
2025-03-20 17:54:49 +01:00
parent 9bbc7d346a
commit 406665b2ae
2 changed files with 147 additions and 4 deletions

View File

@ -692,20 +692,23 @@ class OvnProviderDriver(driver_base.ProviderDriver):
for listener in loadbalancer.listeners:
status_listener = self._ovn_helper.listener_create(
self._get_listener_request_info(listener))
status[constants.LISTENERS].append(status_listener)
status[constants.LISTENERS].append(
status_listener[constants.LISTENERS][0])
if not isinstance(loadbalancer.pools, o_datamodels.UnsetType):
status[constants.POOLS] = []
for pool in loadbalancer.pools:
status_pool = self._ovn_helper.pool_create(
self._get_pool_request_info(pool))
status[constants.POOLS].append(status_pool)
status[constants.POOLS].append(
status_pool[constants.POOLS][0])
for member in pool.members:
status[constants.MEMBERS] = []
if not member.subnet_id:
member.subnet_id = loadbalancer.vip_subnet_id
status_member = self._ovn_helper.member_create(
self._get_member_request_info(member))
status[constants.MEMBERS].append(status_member)
status[constants.MEMBERS].append(
status_member[constants.MEMBERS][0])
if pool.healthmonitor is not None and not isinstance(
pool.healthmonitor, o_datamodels.UnsetType):
status[constants.HEALTHMONITORS] = []
@ -717,7 +720,8 @@ class OvnProviderDriver(driver_base.ProviderDriver):
status_hm = self._ovn_helper.hm_create(
self._get_healthmonitor_request_info(
pool.healthmonitor))
status[constants.HEALTHMONITORS].append(status_hm)
status[constants.HEALTHMONITORS].append(
status_hm[constants.HEALTHMONITORS][0])
self._ovn_helper._update_status_to_octavia(status)
else:
# Load Balancer found, check LB and listener/pool/member/hms

View File

@ -1623,6 +1623,14 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
mock_member_create, mock_update_status):
self.mock_find_ovn_lbs_with_retry.side_effect = [
idlutils.RowNotFound]
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_listener_create.return_value = {constants.LISTENERS: [
{'id': self.listener_id}]}
mock_pool_create.return_value = {constants.POOLS: [
{'id': self.pool_id}]}
mock_member_create.return_value = {constants.MEMBERS: [
{'id': self.member_id}]}
self.driver._ensure_loadbalancer(self.ref_lb_fully_populated)
mock_lb_create.assert_called_once_with(
self.driver._get_loadbalancer_request_info(
@ -1640,6 +1648,13 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.driver._get_member_request_info(
self.ref_lb_fully_populated.pools[0].members[0]),
)
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}],
constants.LISTENERS: [{'id': self.listener_id}],
constants.POOLS: [{'id': self.pool_id}],
constants.MEMBERS: [{'id': self.member_id}]
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')
@ -1653,6 +1668,12 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
idlutils.RowNotFound]
self.ref_lb_fully_populated.listeners = data_models.UnsetType()
self.ref_lb_fully_populated.pools = data_models.UnsetType()
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_listener_create.return_value = {}
mock_pool_create.return_value = {}
self.driver._ensure_loadbalancer(self.ref_lb_fully_populated)
mock_lb_create.assert_called_once_with(
self.driver._get_loadbalancer_request_info(
@ -1660,6 +1681,10 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
)
mock_listener_create.assert_not_called()
mock_pool_create.assert_not_called()
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}]
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')
@ -1672,6 +1697,14 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
mock_member_create, mock_update_status):
self.mock_find_ovn_lbs_with_retry.side_effect = [
idlutils.RowNotFound]
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_listener_create.return_value = {constants.LISTENERS: [
{'id': self.listener_id}]}
mock_pool_create.return_value = {constants.POOLS: [
{'id': self.pool_id}]}
mock_member_create.return_value = {constants.MEMBERS: [
{'id': self.member_id}]}
self.ref_lb_fully_populated.listeners = []
self.ref_lb_fully_populated.pools[0].members[0].subnet_id = None
self.driver._ensure_loadbalancer(self.ref_lb_fully_populated)
@ -1679,6 +1712,13 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.driver._get_member_request_info(
self.ref_lb_fully_populated.pools[0].members[0]),
)
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}],
constants.LISTENERS: [],
constants.POOLS: [{'id': self.pool_id}],
constants.MEMBERS: [{'id': self.member_id}]
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')
@ -1692,6 +1732,16 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
mock_member_create, mock_hm_create, mock_update_status):
self.mock_find_ovn_lbs_with_retry.side_effect = [
idlutils.RowNotFound]
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_listener_create.return_value = {constants.LISTENERS: [
{'id': self.listener_id}]}
mock_pool_create.return_value = {constants.POOLS: [
{'id': self.pool_id}]}
mock_member_create.return_value = {constants.MEMBERS: [
{'id': self.member_id}]}
with mock.patch.object(
ovn_helper.OvnProviderHelper, '_find_ovn_lb_from_hm_id') \
as mock_find_ovn_lb_from_hm_id:
@ -1700,6 +1750,15 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.driver._ensure_loadbalancer(self.ref_lb_fully_populated)
mock_hm_create.assert_not_called()
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}],
constants.LISTENERS: [{'id': self.listener_id}],
constants.POOLS: [{'id': self.pool_id}],
constants.MEMBERS: [{'id': self.member_id}],
constants.HEALTHMONITORS: []
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')
@mock.patch.object(ovn_helper.OvnProviderHelper, 'hm_create')
@ -1712,6 +1771,16 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
mock_member_create, mock_hm_create, mock_update_status):
self.mock_find_ovn_lbs_with_retry.side_effect = [
idlutils.RowNotFound]
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_listener_create.return_value = {constants.LISTENERS: [
{'id': self.listener_id}]}
mock_pool_create.return_value = {constants.POOLS: [
{'id': self.pool_id}]}
mock_member_create.return_value = {constants.MEMBERS: [
{'id': self.member_id}]}
mock_hm_create.return_value = {constants.HEALTHMONITORS: [
{'id': self.healthmonitor_id}]}
with mock.patch.object(
ovn_helper.OvnProviderHelper, '_find_ovn_lb_from_hm_id') \
as mock_find_ovn_lb_from_hm_id:
@ -1722,6 +1791,14 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.driver._get_healthmonitor_request_info(
self.ref_lb_fully_populated.pools[0].healthmonitor),
)
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}],
constants.LISTENERS: [{'id': self.listener_id}],
constants.POOLS: [{'id': self.pool_id}],
constants.MEMBERS: [{'id': self.member_id}],
constants.HEALTHMONITORS: [{'id': self.healthmonitor_id}]
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')
@ -1735,6 +1812,10 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.mock_find_ovn_lbs_with_retry.side_effect = [
idlutils.RowNotFound]
self.ref_lb_fully_populated.pools = data_models.Unset
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_listener_create.return_value = {constants.LISTENERS: [
{'id': self.listener_id}]}
self.driver._ensure_loadbalancer(self.ref_lb_fully_populated)
mock_lb_create.assert_called_once_with(
self.driver._get_loadbalancer_request_info(
@ -1745,6 +1826,11 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.ref_lb_fully_populated.listeners[0]),
)
mock_pool_create.assert_not_called()
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}],
constants.LISTENERS: [{'id': self.listener_id}]
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')
@ -1758,6 +1844,13 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.mock_find_ovn_lbs_with_retry.side_effect = [
idlutils.RowNotFound]
self.ref_lb_fully_populated.pools[0].members = []
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_listener_create.return_value = {constants.LISTENERS: [
{'id': self.listener_id}]}
mock_pool_create.return_value = {constants.POOLS: [
{'id': self.pool_id}]}
self.driver._ensure_loadbalancer(self.ref_lb_fully_populated)
mock_lb_create.assert_called_once_with(
self.driver._get_loadbalancer_request_info(
@ -1772,6 +1865,12 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.ref_lb_fully_populated.pools[0]),
)
mock_member_create.assert_not_called()
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}],
constants.LISTENERS: [{'id': self.listener_id}],
constants.POOLS: [{'id': self.pool_id}]
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')
@ -1787,6 +1886,16 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
idlutils.RowNotFound]
self.ref_lb_fully_populated.pools[0].members = []
self.ref_pool.healthmonitor = self.ref_health_monitor
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_listener_create.return_value = {constants.LISTENERS: [
{'id': self.listener_id}]}
mock_pool_create.return_value = {constants.POOLS: [
{'id': self.pool_id}]}
mock_member_create.return_value = {constants.MEMBERS: [
{'id': self.member_id}]}
mock_hm_create.return_value = {constants.HEALTHMONITORS: [
{'id': self.healthmonitor_id}]}
self.driver._ensure_loadbalancer(self.ref_lb_fully_populated)
mock_lb_create.assert_called_once_with(
self.driver._get_loadbalancer_request_info(
@ -1805,6 +1914,13 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.driver._get_healthmonitor_request_info(
self.ref_lb_fully_populated.pools[0].healthmonitor),
)
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}],
constants.LISTENERS: [{'id': self.listener_id}],
constants.POOLS: [{'id': self.pool_id}],
constants.HEALTHMONITORS: [{'id': self.healthmonitor_id}]
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')
@ -1818,6 +1934,12 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.mock_find_ovn_lbs_with_retry.side_effect = [
idlutils.RowNotFound]
self.ref_lb_fully_populated.listeners = []
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_pool_create.return_value = {constants.POOLS: [
{'id': self.pool_id}]}
mock_member_create.return_value = {constants.MEMBERS: [
{'id': self.member_id}]}
self.driver._ensure_loadbalancer(self.ref_lb_fully_populated)
mock_lb_create.assert_called_once_with(
self.driver._get_loadbalancer_request_info(
@ -1832,6 +1954,13 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.driver._get_member_request_info(
self.ref_lb_fully_populated.pools[0].members[0]),
)
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}],
constants.LISTENERS: [],
constants.POOLS: [{'id': self.pool_id}],
constants.MEMBERS: [{'id': self.member_id}],
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')
@ -1845,6 +1974,10 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.mock_find_ovn_lbs_with_retry.side_effect = [
idlutils.RowNotFound]
self.ref_lb_fully_populated.pools = []
mock_lb_create.return_value = {constants.LOADBALANCERS: [
{'id': self.loadbalancer_id}]}
mock_listener_create.return_value = {constants.LISTENERS: [
{'id': self.listener_id}]}
self.driver._ensure_loadbalancer(self.ref_lb_fully_populated)
mock_lb_create.assert_called_once_with(
self.driver._get_loadbalancer_request_info(
@ -1856,6 +1989,12 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
)
mock_pool_create.assert_not_called()
mock_member_create.assert_not_called()
expected_status = {
constants.LOADBALANCERS: [{'id': self.loadbalancer_id}],
constants.LISTENERS: [{'id': self.listener_id}],
constants.POOLS: []
}
mock_update_status.assert_called_once_with(expected_status)
@mock.patch.object(ovn_helper.OvnProviderHelper,
'_update_status_to_octavia')