Fix using subnets with host_routes in amphorav2 driver
When using subnets with host_routes in amphorav2, the host_routes attribute in the Subnet data structure was not correctly converted to a HostRoute data structure. It triggered exceptions and failed to provision the load balancer. Story 2008738 Task 42092 Change-Id: I39391070cea170a6039f901093f09fc89ba06123
This commit is contained in:
parent
6c54eab5b5
commit
d0ec3aaf23
@ -266,9 +266,17 @@ class AmphoraPostNetworkPlug(BaseAmphoraTask):
|
|||||||
for port in ports:
|
for port in ports:
|
||||||
net = data_models.Network(**port.pop(constants.NETWORK))
|
net = data_models.Network(**port.pop(constants.NETWORK))
|
||||||
ips = port.pop(constants.FIXED_IPS)
|
ips = port.pop(constants.FIXED_IPS)
|
||||||
fixed_ips = [data_models.FixedIP(
|
fixed_ips = []
|
||||||
subnet=data_models.Subnet(**ip.pop(constants.SUBNET)), **ip)
|
for ip in ips:
|
||||||
for ip in ips]
|
subnet_arg = ip.pop(constants.SUBNET)
|
||||||
|
host_routes = subnet_arg.get('host_routes')
|
||||||
|
if host_routes:
|
||||||
|
subnet_arg['host_routes'] = [
|
||||||
|
data_models.HostRoute(**hr)
|
||||||
|
for hr in host_routes
|
||||||
|
]
|
||||||
|
fixed_ips.append(data_models.FixedIP(
|
||||||
|
subnet=data_models.Subnet(**subnet_arg), **ip))
|
||||||
self.amphora_driver.post_network_plug(
|
self.amphora_driver.post_network_plug(
|
||||||
db_amp, data_models.Port(network=net, fixed_ips=fixed_ips,
|
db_amp, data_models.Port(network=net, fixed_ips=fixed_ips,
|
||||||
**port))
|
**port))
|
||||||
@ -329,6 +337,12 @@ class AmphoraPostVIPPlug(BaseAmphoraTask):
|
|||||||
vip_arg = amphorae_network_config[amphora.get(
|
vip_arg = amphorae_network_config[amphora.get(
|
||||||
constants.ID)][constants.VIP_SUBNET]
|
constants.ID)][constants.VIP_SUBNET]
|
||||||
if vip_arg:
|
if vip_arg:
|
||||||
|
host_routes = vip_arg.get('host_routes')
|
||||||
|
if host_routes:
|
||||||
|
vip_arg['host_routes'] = [
|
||||||
|
data_models.HostRoute(**hr)
|
||||||
|
for hr in host_routes
|
||||||
|
]
|
||||||
vip_subnet = data_models.Subnet(**vip_arg)
|
vip_subnet = data_models.Subnet(**vip_arg)
|
||||||
else:
|
else:
|
||||||
vip_subnet = data_models.Subnet()
|
vip_subnet = data_models.Subnet()
|
||||||
|
@ -381,8 +381,9 @@ class TestAmphoraDriverTasks(base.TestCase):
|
|||||||
amphora_post_network_plug_obj = (amphora_driver_tasks.
|
amphora_post_network_plug_obj = (amphora_driver_tasks.
|
||||||
AmphoraPostNetworkPlug())
|
AmphoraPostNetworkPlug())
|
||||||
mock_amphora_repo_get.return_value = _db_amphora_mock
|
mock_amphora_repo_get.return_value = _db_amphora_mock
|
||||||
|
fixed_ips = [{constants.SUBNET: {}}]
|
||||||
port_mock = {constants.NETWORK: mock.MagicMock(),
|
port_mock = {constants.NETWORK: mock.MagicMock(),
|
||||||
constants.FIXED_IPS: [mock.MagicMock()],
|
constants.FIXED_IPS: fixed_ips,
|
||||||
constants.ID: uuidutils.generate_uuid()}
|
constants.ID: uuidutils.generate_uuid()}
|
||||||
amphora_post_network_plug_obj.execute(_amphora_mock, [port_mock])
|
amphora_post_network_plug_obj.execute(_amphora_mock, [port_mock])
|
||||||
|
|
||||||
@ -416,6 +417,37 @@ class TestAmphoraDriverTasks(base.TestCase):
|
|||||||
failure.Failure.from_exception(Exception('boom')), _amphora_mock)
|
failure.Failure.from_exception(Exception('boom')), _amphora_mock)
|
||||||
repo.AmphoraRepository.update.assert_not_called()
|
repo.AmphoraRepository.update.assert_not_called()
|
||||||
|
|
||||||
|
def test_amphora_post_network_plug_with_host_routes(
|
||||||
|
self, mock_driver, mock_generate_uuid, mock_log, mock_get_session,
|
||||||
|
mock_listener_repo_get, mock_listener_repo_update,
|
||||||
|
mock_amphora_repo_get, mock_amphora_repo_update):
|
||||||
|
|
||||||
|
amphora_post_network_plug_obj = (amphora_driver_tasks.
|
||||||
|
AmphoraPostNetworkPlug())
|
||||||
|
mock_amphora_repo_get.return_value = _db_amphora_mock
|
||||||
|
host_routes = [{'destination': '10.0.0.0/16',
|
||||||
|
'nexthop': '192.168.10.3'},
|
||||||
|
{'destination': '10.2.0.0/16',
|
||||||
|
'nexthop': '192.168.10.5'}]
|
||||||
|
fixed_ips = [{constants.SUBNET: {'host_routes': host_routes}}]
|
||||||
|
|
||||||
|
port_mock = {constants.NETWORK: mock.MagicMock(),
|
||||||
|
constants.FIXED_IPS: fixed_ips,
|
||||||
|
constants.ID: uuidutils.generate_uuid()}
|
||||||
|
amphora_post_network_plug_obj.execute(_amphora_mock, [port_mock])
|
||||||
|
|
||||||
|
(mock_driver.post_network_plug.
|
||||||
|
assert_called_once_with)(_db_amphora_mock,
|
||||||
|
network_data_models.Port(**port_mock))
|
||||||
|
|
||||||
|
call_args = mock_driver.post_network_plug.call_args[0]
|
||||||
|
port_arg = call_args[1]
|
||||||
|
subnet_arg = port_arg.fixed_ips[0].subnet
|
||||||
|
self.assertEqual(2, len(subnet_arg.host_routes))
|
||||||
|
for hr1, hr2 in zip(host_routes, subnet_arg.host_routes):
|
||||||
|
self.assertEqual(hr1['destination'], hr2.destination)
|
||||||
|
self.assertEqual(hr1['nexthop'], hr2.nexthop)
|
||||||
|
|
||||||
@mock.patch('octavia.db.repositories.LoadBalancerRepository.get')
|
@mock.patch('octavia.db.repositories.LoadBalancerRepository.get')
|
||||||
def test_amphorae_post_network_plug(self, mock_lb_get,
|
def test_amphorae_post_network_plug(self, mock_lb_get,
|
||||||
mock_driver,
|
mock_driver,
|
||||||
@ -496,7 +528,14 @@ class TestAmphoraDriverTasks(base.TestCase):
|
|||||||
mock_amphora_repo_get,
|
mock_amphora_repo_get,
|
||||||
mock_amphora_repo_update):
|
mock_amphora_repo_update):
|
||||||
|
|
||||||
amphorae_net_config_mock = mock.MagicMock()
|
amphorae_net_config_mock = {
|
||||||
|
AMP_ID: {
|
||||||
|
constants.VIP_SUBNET: {
|
||||||
|
'host_routes': []
|
||||||
|
},
|
||||||
|
constants.VRRP_PORT: mock.MagicMock(),
|
||||||
|
}
|
||||||
|
}
|
||||||
mock_amphora_repo_get.return_value = _db_amphora_mock
|
mock_amphora_repo_get.return_value = _db_amphora_mock
|
||||||
mock_lb_get.return_value = _db_load_balancer_mock
|
mock_lb_get.return_value = _db_load_balancer_mock
|
||||||
amphora_post_vip_plug_obj = amphora_driver_tasks.AmphoraPostVIPPlug()
|
amphora_post_vip_plug_obj = amphora_driver_tasks.AmphoraPostVIPPlug()
|
||||||
@ -549,6 +588,48 @@ class TestAmphoraDriverTasks(base.TestCase):
|
|||||||
None)
|
None)
|
||||||
repo.AmphoraRepository.update.assert_not_called()
|
repo.AmphoraRepository.update.assert_not_called()
|
||||||
|
|
||||||
|
@mock.patch('octavia.db.repositories.LoadBalancerRepository.update')
|
||||||
|
@mock.patch('octavia.db.repositories.LoadBalancerRepository.get')
|
||||||
|
def test_amphora_post_vip_plug_with_host_routes(
|
||||||
|
self, mock_lb_get, mock_loadbalancer_repo_update, mock_driver,
|
||||||
|
mock_generate_uuid, mock_log, mock_get_session,
|
||||||
|
mock_listener_repo_get, mock_listener_repo_update,
|
||||||
|
mock_amphora_repo_get, mock_amphora_repo_update):
|
||||||
|
|
||||||
|
host_routes = [{'destination': '10.0.0.0/16',
|
||||||
|
'nexthop': '192.168.10.3'},
|
||||||
|
{'destination': '10.2.0.0/16',
|
||||||
|
'nexthop': '192.168.10.5'}]
|
||||||
|
amphorae_net_config_mock = {
|
||||||
|
AMP_ID: {
|
||||||
|
constants.VIP_SUBNET: {
|
||||||
|
'host_routes': host_routes
|
||||||
|
},
|
||||||
|
constants.VRRP_PORT: mock.MagicMock(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mock_amphora_repo_get.return_value = _db_amphora_mock
|
||||||
|
mock_lb_get.return_value = _db_load_balancer_mock
|
||||||
|
amphora_post_vip_plug_obj = amphora_driver_tasks.AmphoraPostVIPPlug()
|
||||||
|
amphora_post_vip_plug_obj.execute(_amphora_mock,
|
||||||
|
_LB_mock,
|
||||||
|
amphorae_net_config_mock)
|
||||||
|
vip_subnet = network_data_models.Subnet(
|
||||||
|
**amphorae_net_config_mock[AMP_ID]['vip_subnet'])
|
||||||
|
vrrp_port = network_data_models.Port(
|
||||||
|
**amphorae_net_config_mock[AMP_ID]['vrrp_port'])
|
||||||
|
|
||||||
|
mock_driver.post_vip_plug.assert_called_once_with(
|
||||||
|
_db_amphora_mock, _db_load_balancer_mock, amphorae_net_config_mock,
|
||||||
|
vip_subnet=vip_subnet, vrrp_port=vrrp_port)
|
||||||
|
|
||||||
|
call_kwargs = mock_driver.post_vip_plug.call_args[1]
|
||||||
|
vip_subnet_arg = call_kwargs.get(constants.VIP_SUBNET)
|
||||||
|
self.assertEqual(2, len(vip_subnet_arg.host_routes))
|
||||||
|
for hr1, hr2 in zip(host_routes, vip_subnet_arg.host_routes):
|
||||||
|
self.assertEqual(hr1['destination'], hr2.destination)
|
||||||
|
self.assertEqual(hr1['nexthop'], hr2.nexthop)
|
||||||
|
|
||||||
@mock.patch('octavia.db.repositories.LoadBalancerRepository.update')
|
@mock.patch('octavia.db.repositories.LoadBalancerRepository.update')
|
||||||
@mock.patch('octavia.db.repositories.LoadBalancerRepository.get')
|
@mock.patch('octavia.db.repositories.LoadBalancerRepository.get')
|
||||||
def test_amphorae_post_vip_plug(self, mock_lb_get,
|
def test_amphorae_post_vip_plug(self, mock_lb_get,
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fix load balancers that use customized host_routes in the VIP or the member
|
||||||
|
subnets in amphorav2.
|
Loading…
Reference in New Issue
Block a user