From 9f9bc9630a653b326459c20bad4629c66a10531d Mon Sep 17 00:00:00 2001 From: Michael Johnson Date: Tue, 14 Aug 2018 18:50:37 -0700 Subject: [PATCH] Fix neutron "tenat_id" compatibility Octavia had a regression where it was not longer compatible with older versions of neutron due to a change for the VIP port ownership. This patch fixes that regression by checking if the project-id extension to neutron is persent. Change-Id: Iee405ceaee91f58d6163679b4c8809d1d27f855b Story: 2003278 Task: 24219 --- .../drivers/neutron/allowed_address_pairs.py | 10 ++++- .../neutron/test_allowed_address_pairs.py | 41 ++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/octavia/network/drivers/neutron/allowed_address_pairs.py b/octavia/network/drivers/neutron/allowed_address_pairs.py index f125feeba5..7846697c2d 100644 --- a/octavia/network/drivers/neutron/allowed_address_pairs.py +++ b/octavia/network/drivers/neutron/allowed_address_pairs.py @@ -33,6 +33,7 @@ from octavia.network.drivers.neutron import utils LOG = logging.getLogger(__name__) AAP_EXT_ALIAS = 'allowed-address-pairs' +PROJECT_ID_ALIAS = 'project-id' VIP_SECURITY_GRP_PREFIX = 'lb-' OCTAVIA_OWNER = 'Octavia' @@ -396,13 +397,20 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): fixed_ip['subnet_id'] = load_balancer.vip.subnet_id if load_balancer.vip.ip_address: fixed_ip['ip_address'] = load_balancer.vip.ip_address + + # Make sure we are backward compatible with older neutron + if self._check_extension_enabled(PROJECT_ID_ALIAS): + project_id_key = 'project_id' + else: + project_id_key = 'tenant_id' + # It can be assumed that network_id exists port = {'port': {'name': 'octavia-lb-' + load_balancer.id, 'network_id': load_balancer.vip.network_id, 'admin_state_up': False, 'device_id': 'lb-{0}'.format(load_balancer.id), 'device_owner': OCTAVIA_OWNER, - 'project_id': load_balancer.project_id}} + project_id_key: load_balancer.project_id}} if fixed_ip: port['port']['fixed_ips'] = [fixed_ip] diff --git a/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py b/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py index eca09dab3a..84d9e71024 100644 --- a/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +++ b/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py @@ -459,7 +459,9 @@ class TestAllowedAddressPairsDriver(base.TestCase): self.assertRaises(network_base.AllocateVIPException, self.driver.allocate_vip, fake_lb) - def test_allocate_vip_when_no_port_provided(self): + @mock.patch('octavia.network.drivers.neutron.base.BaseNeutronDriver.' + '_check_extension_enabled', return_value=True) + def test_allocate_vip_when_no_port_provided(self, mock_check_ext): port_create_dict = copy.deepcopy(t_constants.MOCK_NEUTRON_PORT) port_create_dict['port']['device_owner'] = ( allowed_address_pairs.OCTAVIA_OWNER) @@ -494,6 +496,43 @@ class TestAllowedAddressPairsDriver(base.TestCase): self.assertEqual(t_constants.MOCK_PORT_ID, vip.port_id) self.assertEqual(fake_lb.id, vip.load_balancer_id) + @mock.patch('octavia.network.drivers.neutron.base.BaseNeutronDriver.' + '_check_extension_enabled', return_value=False) + def test_allocate_vip_when_no_port_provided_tenant(self, mock_check_ext): + port_create_dict = copy.deepcopy(t_constants.MOCK_NEUTRON_PORT) + port_create_dict['port']['device_owner'] = ( + allowed_address_pairs.OCTAVIA_OWNER) + port_create_dict['port']['device_id'] = 'lb-1' + create_port = self.driver.neutron_client.create_port + create_port.return_value = port_create_dict + show_subnet = self.driver.neutron_client.show_subnet + show_subnet.return_value = {'subnet': { + 'id': t_constants.MOCK_SUBNET_ID, + 'network_id': t_constants.MOCK_NETWORK_ID + }} + fake_lb_vip = data_models.Vip(subnet_id=t_constants.MOCK_SUBNET_ID, + network_id=t_constants.MOCK_NETWORK_ID) + fake_lb = data_models.LoadBalancer(id='1', vip=fake_lb_vip, + project_id='test-project') + vip = self.driver.allocate_vip(fake_lb) + exp_create_port_call = { + 'port': { + 'name': 'octavia-lb-1', + 'network_id': t_constants.MOCK_NETWORK_ID, + 'device_id': 'lb-1', + 'device_owner': allowed_address_pairs.OCTAVIA_OWNER, + 'admin_state_up': False, + 'tenant_id': 'test-project', + 'fixed_ips': [{'subnet_id': t_constants.MOCK_SUBNET_ID}] + } + } + create_port.assert_called_once_with(exp_create_port_call) + self.assertIsInstance(vip, data_models.Vip) + self.assertEqual(t_constants.MOCK_IP_ADDRESS, vip.ip_address) + self.assertEqual(t_constants.MOCK_SUBNET_ID, vip.subnet_id) + self.assertEqual(t_constants.MOCK_PORT_ID, vip.port_id) + self.assertEqual(fake_lb.id, vip.load_balancer_id) + def test_unplug_vip_errors_when_update_port_cant_find_port(self): lb = dmh.generate_load_balancer_tree() list_ports = self.driver.neutron_client.list_ports