From ed218a4a636071ac6f074a988fdcd37aac80318a Mon Sep 17 00:00:00 2001 From: Yossi Boaron Date: Sun, 16 Sep 2018 14:57:28 +0300 Subject: [PATCH] LBaaS driver: Add provider support The OVN provider was added lately to Octavia [1] in addition to the 'amphora' provider. In order to create a LB with a specific provider the provider name should be posted in load balancer creation request, in case the provider name is not specified, Octavia default provider will be used. This patch enhances LBaaS driver to support LB provider functionality. The functionality of translating K8S-services into Octavia-OVN load balancers will be based on this change. [1] https://github.com/openstack/networking-ovn/commit/66502f19f2994512fb89e6e453429e140da5fa4b Partially Implements: blueprint octavia-ovn-provider Change-Id: I07532c0fd93d9269f317eace53b4baaa70df9201 --- kuryr_kubernetes/controller/drivers/base.py | 3 +- .../controller/drivers/lbaasv2.py | 21 ++++++-- kuryr_kubernetes/objects/lbaas.py | 6 ++- .../unit/controller/drivers/test_lbaasv2.py | 53 +++++++++++++++++++ kuryr_kubernetes/tests/unit/test_object.py | 2 +- 5 files changed, 77 insertions(+), 8 deletions(-) diff --git a/kuryr_kubernetes/controller/drivers/base.py b/kuryr_kubernetes/controller/drivers/base.py index 411a480cc..05672daf2 100644 --- a/kuryr_kubernetes/controller/drivers/base.py +++ b/kuryr_kubernetes/controller/drivers/base.py @@ -423,7 +423,7 @@ class LBaaSDriver(DriverBase): @abc.abstractmethod def ensure_loadbalancer(self, name, project_id, subnet_id, ip, - security_groups_ids, service_type): + security_groups_ids, service_type, provider): """Get or create load balancer. :param name: LoadBlancer name @@ -433,6 +433,7 @@ class LBaaSDriver(DriverBase): :param security_groups_ids: security groups that should be allowed access to the load balancer :param service_type: K8s service type (ClusterIP or LoadBalancer) + :param provider: load balancer backend service """ raise NotImplementedError() diff --git a/kuryr_kubernetes/controller/drivers/lbaasv2.py b/kuryr_kubernetes/controller/drivers/lbaasv2.py index 16d75ead0..a7780e6bc 100644 --- a/kuryr_kubernetes/controller/drivers/lbaasv2.py +++ b/kuryr_kubernetes/controller/drivers/lbaasv2.py @@ -53,10 +53,11 @@ class LBaaSv2Driver(base.LBaaSDriver): return "%s/%s/%s" % (loadbalancer.name, namespace, svc_name) def ensure_loadbalancer(self, name, project_id, subnet_id, ip, - security_groups_ids=None, service_type=None): + security_groups_ids=None, service_type=None, + provider=None): request = obj_lbaas.LBaaSLoadBalancer( name=name, project_id=project_id, subnet_id=subnet_id, ip=ip, - security_groups=security_groups_ids) + security_groups=security_groups_ids, provider=provider) response = self._ensure(request, self._create_loadbalancer, self._find_loadbalancer) if not response: @@ -329,13 +330,25 @@ class LBaaSv2Driver(base.LBaaSDriver): def _create_loadbalancer(self, loadbalancer): lbaas = clients.get_loadbalancer_client() - response = lbaas.create_loadbalancer({'loadbalancer': { + + request = {'loadbalancer': { 'name': loadbalancer.name, 'project_id': loadbalancer.project_id, 'vip_address': str(loadbalancer.ip), - 'vip_subnet_id': loadbalancer.subnet_id}}) + 'vip_subnet_id': loadbalancer.subnet_id}} + + if loadbalancer.provider is not None: + request['loadbalancer']['provider'] = loadbalancer.provider + + response = lbaas.create_loadbalancer(request) loadbalancer.id = response['loadbalancer']['id'] loadbalancer.port_id = self._get_vip_port(loadbalancer).get("id") + if (loadbalancer.provider is not None and + loadbalancer.provider != response['loadbalancer']['provider']): + LOG.error("Request provider(%s) != Response provider(%s)", + loadbalancer.provider, + response['loadbalancer']['provider']) + return None loadbalancer.provider = response['loadbalancer']['provider'] return loadbalancer diff --git a/kuryr_kubernetes/objects/lbaas.py b/kuryr_kubernetes/objects/lbaas.py index 014b4e55c..7e59f9a52 100644 --- a/kuryr_kubernetes/objects/lbaas.py +++ b/kuryr_kubernetes/objects/lbaas.py @@ -25,7 +25,8 @@ class LBaaSLoadBalancer(k_obj.KuryrK8sObjectBase): # Version 1.0: Initial version # Version 1.1: Added provider field and security_groups field. # Version 1.2: Added support for security_groups=None - VERSION = '1.2' + # Version 1.3: Added support for provider=None + VERSION = '1.3' fields = { 'id': obj_fields.UUIDField(), @@ -34,7 +35,8 @@ class LBaaSLoadBalancer(k_obj.KuryrK8sObjectBase): 'ip': obj_fields.IPAddressField(), 'subnet_id': obj_fields.UUIDField(), 'port_id': obj_fields.UUIDField(), - 'provider': obj_fields.StringField(), + 'provider': obj_fields.StringField(nullable=True, + default=None), 'security_groups': k_fields.ListOfUUIDField(nullable=True, default=None), } diff --git a/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py b/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py index 915b56d3d..de191d030 100644 --- a/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py +++ b/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py @@ -256,6 +256,59 @@ class TestLBaaSv2Driver(test_base.TestCase): getattr(ret, attr)) self.assertEqual(loadbalancer_id, ret.id) + def test_create_loadbalancer_provider_defined(self): + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client + cls = d_lbaasv2.LBaaSv2Driver + 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', + security_groups=[], + provider='amphora') + loadbalancer_id = '00EE9E11-91C2-41CF-8FD4-7970579E5C4C' + req = {'loadbalancer': { + 'name': loadbalancer.name, + 'project_id': loadbalancer.project_id, + 'vip_address': str(loadbalancer.ip), + 'vip_subnet_id': loadbalancer.subnet_id, + 'provider': loadbalancer.provider, + }} + resp = {'loadbalancer': {'id': loadbalancer_id, 'provider': 'amphora'}} + lbaas.create_loadbalancer.return_value = resp + m_driver._get_vip_port.return_value = {'id': mock.sentinel.port_id} + + ret = cls._create_loadbalancer(m_driver, loadbalancer) + lbaas.create_loadbalancer.assert_called_once_with(req) + for attr in loadbalancer.obj_fields: + self.assertEqual(getattr(loadbalancer, attr), + getattr(ret, attr)) + self.assertEqual(loadbalancer_id, ret.id) + + def test_create_loadbalancer_provider_mismatch(self): + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client + cls = d_lbaasv2.LBaaSv2Driver + 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', + security_groups=[], + provider='amphora') + loadbalancer_id = '00EE9E11-91C2-41CF-8FD4-7970579E5C4C' + req = {'loadbalancer': { + 'name': loadbalancer.name, + 'project_id': loadbalancer.project_id, + 'vip_address': str(loadbalancer.ip), + 'vip_subnet_id': loadbalancer.subnet_id, + 'provider': loadbalancer.provider, + }} + resp = {'loadbalancer': {'id': loadbalancer_id, 'provider': 'haproxy'}} + lbaas.create_loadbalancer.return_value = resp + m_driver._get_vip_port.return_value = {'id': mock.sentinel.port_id} + + ret = cls._create_loadbalancer(m_driver, loadbalancer) + lbaas.create_loadbalancer.assert_called_once_with(req) + self.assertIsNone(ret) + def test_find_loadbalancer(self): lbaas = self.useFixture(k_fix.MockLBaaSClient()).client cls = d_lbaasv2.LBaaSv2Driver diff --git a/kuryr_kubernetes/tests/unit/test_object.py b/kuryr_kubernetes/tests/unit/test_object.py index c7fafd353..384875b00 100644 --- a/kuryr_kubernetes/tests/unit/test_object.py +++ b/kuryr_kubernetes/tests/unit/test_object.py @@ -25,7 +25,7 @@ object_data = { '1.0-3ac4fcd50a555f433a78c67cb6a4cd52', 'LBaaSL7Rule': '1.0-276d9d678e1a8fc4b53fdbf3b2ac39ec', 'LBaaSListener': '1.0-a9e2d5c73687f5edc66fdb2f48650e15', - 'LBaaSLoadBalancer': '1.2-d498ade2e705c3977eb66ff46133ed2b', + 'LBaaSLoadBalancer': '1.3-8bc0a9bdbd160da67572aa38784378d1', 'LBaaSMember': '1.0-a770c6884c27d6d8c21186b27d0e2ccb', 'LBaaSPool': '1.1-6e77370d7632a902445444249eb77b01', 'LBaaSPortSpec': '1.0-51dfa3436bec32db3614720056fcc83f',