Merge "Services: Set missing SGs for haproxy provider"

This commit is contained in:
Zuul 2018-02-21 14:04:30 +00:00 committed by Gerrit Code Review
commit 48baed57d9
4 changed files with 105 additions and 10 deletions

View File

@ -37,6 +37,7 @@ KURYR_PORT_NAME = 'kuryr-pool-port'
OCTAVIA_L2_MEMBER_MODE = "L2"
OCTAVIA_L3_MEMBER_MODE = "L3"
NEUTRON_LBAAS_HAPROXY_PROVIDER = 'haproxy'
VIF_POOL_POPULATE = '/populatePool'
VIF_POOL_FREE = '/freePool'

View File

@ -22,6 +22,7 @@ from oslo_utils import excutils
from oslo_utils import timeutils
from kuryr_kubernetes import clients
from kuryr_kubernetes import constants as const
from kuryr_kubernetes.controller.drivers import base
from kuryr_kubernetes import exceptions as k_exc
from kuryr_kubernetes.objects import lbaas as obj_lbaas
@ -48,8 +49,22 @@ class LBaaSv2Driver(base.LBaaSDriver):
# deleted externally between 'create' and 'find'
raise k_exc.ResourceNotReady(request)
# TODO(ivc): handle security groups
# We only handle SGs for legacy LBaaSv2, Octavia handles it dynamically
# according to listener ports.
if response.provider == const.NEUTRON_LBAAS_HAPROXY_PROVIDER:
vip_port_id = response.port_id
neutron = clients.get_neutron_client()
try:
neutron.update_port(
vip_port_id,
{'port': {'security_groups': security_groups_ids}})
except n_exc.NeutronClientException:
LOG.exception('Failed to set SG for LBaaS v2 VIP port %s.',
vip_port_id)
# NOTE(dulek): `endpoints` arguments on release_loadbalancer()
# is ignored for some reason, so just pass None.
self.release_loadbalancer(None, response)
raise
return response
def release_loadbalancer(self, endpoints, loadbalancer):
@ -136,6 +151,7 @@ class LBaaSv2Driver(base.LBaaSDriver):
'vip_subnet_id': loadbalancer.subnet_id}})
loadbalancer.id = response['loadbalancer']['id']
loadbalancer.port_id = self._get_vip_port_id(loadbalancer)
loadbalancer.provider = response['loadbalancer']['provider']
return loadbalancer
def _find_loadbalancer(self, loadbalancer):
@ -150,6 +166,7 @@ class LBaaSv2Driver(base.LBaaSDriver):
try:
loadbalancer.id = response['loadbalancers'][0]['id']
loadbalancer.port_id = self._get_vip_port_id(loadbalancer)
loadbalancer.provider = response['loadbalancers'][0]['provider']
except (KeyError, IndexError):
return None

View File

@ -22,7 +22,9 @@ from kuryr_kubernetes.objects import fields as k_fields
@obj_base.VersionedObjectRegistry.register
class LBaaSLoadBalancer(k_obj.KuryrK8sObjectBase):
VERSION = '1.0'
# Version 1.0: Initial version
# Version 1.1: Added provider field
VERSION = '1.1'
fields = {
'id': obj_fields.UUIDField(),
@ -31,6 +33,7 @@ class LBaaSLoadBalancer(k_obj.KuryrK8sObjectBase):
'ip': obj_fields.IPAddressField(),
'subnet_id': obj_fields.UUIDField(),
'port_id': obj_fields.UUIDField(),
'provider': obj_fields.StringField(),
}

View File

@ -17,6 +17,7 @@ import mock
from neutronclient.common import exceptions as n_exc
from kuryr_kubernetes import constants as const
from kuryr_kubernetes.controller.drivers import lbaasv2 as d_lbaasv2
from kuryr_kubernetes import exceptions as k_exc
from kuryr_kubernetes.objects import lbaas as obj_lbaas
@ -26,19 +27,21 @@ from kuryr_kubernetes.tests.unit import kuryr_fixtures as k_fix
class TestLBaaSv2Driver(test_base.TestCase):
def test_ensure_loadbalancer(self):
neutron = self.useFixture(k_fix.MockNeutronClient()).client
cls = d_lbaasv2.LBaaSv2Driver
m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver)
expected_resp = mock.sentinel.expected_resp
expected_resp = obj_lbaas.LBaaSLoadBalancer(
provider='octavia', port_id='D3FA400A-F543-4B91-9CD3-047AF0CE42E2')
namespace = 'TEST_NAMESPACE'
name = 'TEST_NAME'
project_id = 'TEST_PROJECT'
subnet_id = 'D3FA400A-F543-4B91-9CD3-047AF0CE42D1'
ip = '1.2.3.4'
# TODO(ivc): handle security groups
sg_ids = []
sg_ids = ['foo', 'bar']
endpoints = {'metadata': {'namespace': namespace, 'name': name}}
m_driver._ensure.return_value = expected_resp
neutron.update_port = mock.Mock()
resp = cls.ensure_loadbalancer(m_driver, endpoints, project_id,
subnet_id, ip, sg_ids)
m_driver._ensure.assert_called_once_with(mock.ANY,
@ -50,6 +53,74 @@ class TestLBaaSv2Driver(test_base.TestCase):
self.assertEqual(subnet_id, req.subnet_id)
self.assertEqual(ip, str(req.ip))
self.assertEqual(expected_resp, resp)
neutron.update_port.assert_not_called()
def test_ensure_loadbalancer_sg_updated(self):
neutron = self.useFixture(k_fix.MockNeutronClient()).client
cls = d_lbaasv2.LBaaSv2Driver
m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver)
expected_resp = obj_lbaas.LBaaSLoadBalancer(
provider=const.NEUTRON_LBAAS_HAPROXY_PROVIDER,
port_id='D3FA400A-F543-4B91-9CD3-047AF0CE42E2')
namespace = 'TEST_NAMESPACE'
name = 'TEST_NAME'
project_id = 'TEST_PROJECT'
subnet_id = 'D3FA400A-F543-4B91-9CD3-047AF0CE42D1'
ip = '1.2.3.4'
sg_ids = ['foo', 'bar']
endpoints = {'metadata': {'namespace': namespace, 'name': name}}
m_driver._ensure.return_value = expected_resp
neutron.update_port = mock.Mock()
resp = cls.ensure_loadbalancer(m_driver, endpoints, project_id,
subnet_id, ip, sg_ids)
m_driver._ensure.assert_called_once_with(mock.ANY,
m_driver._create_loadbalancer,
m_driver._find_loadbalancer)
req = m_driver._ensure.call_args[0][0]
self.assertEqual("%s/%s" % (namespace, name), req.name)
self.assertEqual(project_id, req.project_id)
self.assertEqual(subnet_id, req.subnet_id)
self.assertEqual(ip, str(req.ip))
self.assertEqual(expected_resp, resp)
neutron.update_port.assert_called_once_with(
'D3FA400A-F543-4B91-9CD3-047AF0CE42E2',
{'port': {'security_groups': ['foo', 'bar']}})
def test_ensure_loadbalancer_neutron_error(self):
neutron = self.useFixture(k_fix.MockNeutronClient()).client
cls = d_lbaasv2.LBaaSv2Driver
m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver)
expected_resp = obj_lbaas.LBaaSLoadBalancer(
provider=const.NEUTRON_LBAAS_HAPROXY_PROVIDER,
port_id='D3FA400A-F543-4B91-9CD3-047AF0CE42E2')
namespace = 'TEST_NAMESPACE'
name = 'TEST_NAME'
project_id = 'TEST_PROJECT'
subnet_id = 'D3FA400A-F543-4B91-9CD3-047AF0CE42D1'
ip = '1.2.3.4'
sg_ids = ['foo', 'bar']
endpoints = {'metadata': {'namespace': namespace, 'name': name}}
m_driver._ensure.return_value = expected_resp
neutron.update_port = mock.Mock(
side_effect=n_exc.NeutronClientException)
self.assertRaises(n_exc.NeutronClientException,
cls.ensure_loadbalancer, m_driver, endpoints,
project_id, subnet_id, ip, sg_ids)
m_driver._ensure.assert_called_once_with(mock.ANY,
m_driver._create_loadbalancer,
m_driver._find_loadbalancer)
req = m_driver._ensure.call_args[0][0]
self.assertEqual("%s/%s" % (namespace, name), req.name)
self.assertEqual(project_id, req.project_id)
self.assertEqual(subnet_id, req.subnet_id)
self.assertEqual(ip, str(req.ip))
neutron.update_port.assert_called_once_with(
'D3FA400A-F543-4B91-9CD3-047AF0CE42E2',
{'port': {'security_groups': ['foo', 'bar']}})
m_driver.release_loadbalancer.assert_called_once_with(None,
expected_resp)
def test_ensure_loadbalancer_not_ready(self):
cls = d_lbaasv2.LBaaSv2Driver
@ -227,8 +298,9 @@ class TestLBaaSv2Driver(test_base.TestCase):
'project_id': loadbalancer.project_id,
'tenant_id': loadbalancer.project_id,
'vip_address': str(loadbalancer.ip),
'vip_subnet_id': loadbalancer.subnet_id}}
resp = {'loadbalancer': {'id': loadbalancer_id}}
'vip_subnet_id': loadbalancer.subnet_id,
}}
resp = {'loadbalancer': {'id': loadbalancer_id, 'provider': 'haproxy'}}
neutron.create_loadbalancer.return_value = resp
ret = cls._create_loadbalancer(m_driver, loadbalancer)
@ -244,9 +316,11 @@ class TestLBaaSv2Driver(test_base.TestCase):
m_driver = mock.Mock(spec=d_lbaasv2.LBaaSv2Driver)
loadbalancer = obj_lbaas.LBaaSLoadBalancer(
name='TEST_NAME', project_id='TEST_PROJECT', ip='1.2.3.4',
subnet_id='D3FA400A-F543-4B91-9CD3-047AF0CE42D1')
subnet_id='D3FA400A-F543-4B91-9CD3-047AF0CE42D1',
provider='haproxy')
loadbalancer_id = '00EE9E11-91C2-41CF-8FD4-7970579E5C4C'
resp = {'loadbalancers': [{'id': loadbalancer_id}]}
resp = {'loadbalancers': [{'id': loadbalancer_id,
'provider': 'haproxy'}]}
neutron.list_loadbalancers.return_value = resp
ret = cls._find_loadbalancer(m_driver, loadbalancer)