Files
ovn-octavia-provider/ovn_octavia_provider/tests/unit/test_maintenance.py
Vasyl Saienko ae1540bb1a Maintenance task: do not change IPv4 ip_port_mappings
IPv4 port mappings would get cleared by format_ip_port_mappings_ipv6(),
breaking load balancers with health monitors.

Change-Id: Ia29fd3c533b40f6eb13278a163ebb95465d77a99
Closes-Bug: #2072754
Co-Authored-By: Pierre Riteau <pierre@stackhpc.com>
2024-07-30 17:09:15 +02:00

189 lines
8.1 KiB
Python

# Copyright 2023 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from unittest import mock
from futurist import periodics
from neutron_lib import constants as n_const
from ovn_octavia_provider.common import config as ovn_conf
from ovn_octavia_provider.common import constants as ovn_const
from ovn_octavia_provider import maintenance
from ovn_octavia_provider.tests.unit import base as ovn_base
from ovn_octavia_provider.tests.unit import fakes
class TestDBInconsistenciesPeriodics(ovn_base.TestOvnOctaviaBase):
def setUp(self):
ovn_conf.register_opts()
super(TestDBInconsistenciesPeriodics, self).setUp()
self.maint = maintenance.DBInconsistenciesPeriodics()
self.ovn_nbdb_api = mock.patch.object(self.maint, 'ovn_nbdb_api')
self.ovn_nbdb_api.start()
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
def test_change_device_owner_lb_hm_ports(self, net_cli):
ovn_lb_hm_ports = [
fakes.FakePort.create_one_port(
attrs={
'id': 'foo',
'device_owner': n_const.DEVICE_OWNER_DISTRIBUTED,
'name': 'ovn-metadata-foo'}),
fakes.FakePort.create_one_port(
attrs={
'id': 'foo1',
'device_owner': n_const.DEVICE_OWNER_DISTRIBUTED,
'name': 'ovn-lb-hm-foo1'}),
fakes.FakePort.create_one_port(
attrs={
'id': 'foo2',
'device_owner': n_const.DEVICE_OWNER_DISTRIBUTED,
'name': 'ovn-lb-hm-foo2'})]
net_cli.return_value.ports.return_value = ovn_lb_hm_ports
self.assertRaises(periodics.NeverAgain,
self.maint.change_device_owner_lb_hm_ports)
expected_dict_1 = {
'device_owner': ovn_const.OVN_LB_HM_PORT_DISTRIBUTED,
'device_id': 'ovn-lb-hm-foo1',
}
expected_dict_2 = {
'device_owner': ovn_const.OVN_LB_HM_PORT_DISTRIBUTED,
'device_id': 'ovn-lb-hm-foo2',
}
expected_call = [
mock.call(),
mock.call().ports(device_owner=n_const.DEVICE_OWNER_DISTRIBUTED),
mock.call().update_port('foo1', **expected_dict_1),
mock.call().update_port('foo2', **expected_dict_2)]
net_cli.assert_has_calls(expected_call)
self.maint.ovn_nbdb_api.db_find_rows.assert_called_once_with(
"Logical_Switch_Port", ("name", "=", 'foo1'))
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
def test_change_device_owner_lb_hm_ports_neutron_version_doesnt_match(
self, net_cli):
ovn_lb_hm_ports = [
fakes.FakePort.create_one_port(
attrs={
'id': 'foo',
'device_owner': n_const.DEVICE_OWNER_DISTRIBUTED,
'name': 'ovn-metadata-foo'}),
fakes.FakePort.create_one_port(
attrs={
'id': 'foo1',
'device_owner': n_const.DEVICE_OWNER_DISTRIBUTED,
'name': 'ovn-lb-hm-foo1'}),
fakes.FakePort.create_one_port(
attrs={
'id': 'foo2',
'device_owner': n_const.DEVICE_OWNER_DISTRIBUTED,
'name': 'ovn-lb-hm-foo2'})]
net_cli.return_value.ports.return_value = ovn_lb_hm_ports
self.maint.ovn_nbdb_api.db_find_rows.return_value.\
execute.return_value = [
fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={
'id': 'uuid-foo',
'type': 'foo'})]
self.maint.change_device_owner_lb_hm_ports()
expected_dict_change = {
'device_owner': ovn_const.OVN_LB_HM_PORT_DISTRIBUTED,
'device_id': 'ovn-lb-hm-foo1',
}
expected_dict_rollback = {
'device_owner': n_const.DEVICE_OWNER_DISTRIBUTED,
'device_id': '',
}
expected_call = [
mock.call(),
mock.call().ports(device_owner=n_const.DEVICE_OWNER_DISTRIBUTED),
mock.call().update_port('foo1', **expected_dict_change),
mock.call().update_port('foo1', **expected_dict_rollback)]
net_cli.assert_has_calls(expected_call)
self.maint.ovn_nbdb_api.db_find_rows.assert_called_once_with(
"Logical_Switch_Port", ("name", "=", 'foo1'))
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
def test_change_device_owner_lb_hm_ports_no_ports_to_change(self, net_cli):
ovn_lb_hm_ports = []
net_cli.return_value.ports.return_value = ovn_lb_hm_ports
self.assertRaises(periodics.NeverAgain,
self.maint.change_device_owner_lb_hm_ports)
expected_call = [
mock.call(),
mock.call().ports(device_owner=n_const.DEVICE_OWNER_DISTRIBUTED),
]
net_cli.assert_has_calls(expected_call)
self.maint.ovn_nbdb_api.db_find_rows.assert_not_called()
def test_format_ip_port_mappings_ipv6_no_ip_port_mappings_to_change(self):
self.maint.ovn_nbdb_api.db_find_rows.return_value.\
execute.return_value = []
self.assertRaises(periodics.NeverAgain,
self.maint.format_ip_port_mappings_ipv6)
self.maint.ovn_nbdb_api.db_clear.assert_not_called()
self.maint.ovn_nbdb_api.db_set.assert_not_called()
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
def test_format_ip_port_mappings_ipv6(self, net_cli):
ovn_lbs = [
fakes.FakeOVNLB.create_one_lb(
attrs={
'uuid': 'foo1',
'ip_port_mappings': {
'fda2:918e:5869:0:f816:3eff:fe64:adf7':
'f2b97caf-da62-4db9-91da-bc11f2ac3934:'
'fda2:918e:5869:0:f816:3eff:fe81:61d0',
'fda2:918e:5869:0:f816:3eff:fe64:adf8':
'f2b97caf-da62-4db9-91da-bc11f2ac3935:'
'fda2:918e:5869:0:f816:3eff:fe81:61d0'}}),
fakes.FakeOVNLB.create_one_lb(
attrs={
'uuid': 'foo2',
'ip_port_mappings': {
'192.168.1.50':
'f2b97caf-da62-4db9-91da-bc11f2ac3934:'
'192.168.1.3'}}),
fakes.FakeOVNLB.create_one_lb(
attrs={
'uuid': 'foo3',
'ip_port_mappings': {
'[fda2:918e:5869:0:f816:3eff:fe64:adf7]':
'f2b97caf-da62-4db9-91da-bc11f2ac3934:'
'[fda2:918e:5869:0:f816:3eff:fe81:61d0]'}}),
]
self.maint.ovn_nbdb_api.db_find_rows.return_value.\
execute.return_value = ovn_lbs
self.assertRaises(periodics.NeverAgain,
self.maint.format_ip_port_mappings_ipv6)
mapping1 = {
'[fda2:918e:5869:0:f816:3eff:fe64:adf7]':
'f2b97caf-da62-4db9-91da-bc11f2ac3934:'
'[fda2:918e:5869:0:f816:3eff:fe81:61d0]',
'[fda2:918e:5869:0:f816:3eff:fe64:adf8]':
'f2b97caf-da62-4db9-91da-bc11f2ac3935:'
'[fda2:918e:5869:0:f816:3eff:fe81:61d0]'}
self.maint.ovn_nbdb_api.db_clear.assert_called_once_with(
'Load_Balancer', 'foo1', 'ip_port_mappings')
self.maint.ovn_nbdb_api.db_set.assert_called_once_with(
'Load_Balancer', 'foo1', ('ip_port_mappings', mapping1))