From 91fc0afa8f0c6630775b985128c3ba72e52992c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dulko?= Date: Thu, 19 Dec 2019 17:26:08 +0100 Subject: [PATCH] Fix Octavia version detection For some reason openstacksdk/keystoneauth1 get_api_major_version() started to return the minimum version for the endpoint. Also trying to specify min_version makes the call to fail with string parsing exception. To fix it this commit uses get_all_version_data() instead and parses the results internally in Kuryr. Change-Id: I19823fa2164e6565ee6560706585abec1a88f16d Closes-Bug: 1857023 (cherry picked from commit c581a73be3a8d3d0cb6e7bc54162531de83372bf) --- .../controller/drivers/lbaasv2.py | 36 ++++++++++-- .../unit/controller/drivers/test_lbaasv2.py | 55 +++++++++++++++---- 2 files changed, 73 insertions(+), 18 deletions(-) diff --git a/kuryr_kubernetes/controller/drivers/lbaasv2.py b/kuryr_kubernetes/controller/drivers/lbaasv2.py index 58d644cbc..f6a7d0cb9 100644 --- a/kuryr_kubernetes/controller/drivers/lbaasv2.py +++ b/kuryr_kubernetes/controller/drivers/lbaasv2.py @@ -30,6 +30,7 @@ from openstack.load_balancer.v2 import pool as o_pool from oslo_config import cfg from oslo_log import log as logging from oslo_utils import timeutils +from oslo_utils import versionutils from kuryr_kubernetes import clients from kuryr_kubernetes import config @@ -64,21 +65,44 @@ class LBaaSv2Driver(base.LBaaSDriver): self._octavia_tags = False # Check if Octavia API supports tagging. - lbaas = clients.get_loadbalancer_client() - v = lbaas.get_api_major_version() + # TODO(dulek): *Maybe* this can be replaced with + # lbaas.get_api_major_version(version=_OCTAVIA_TAGGING_VERSION) + # if bug https://storyboard.openstack.org/#!/story/2007040 gets + # fixed one day. + v = self.get_octavia_version() if v >= _OCTAVIA_TAGGING_VERSION: LOG.info('Octavia supports resource tags.') self._octavia_tags = True else: - if v is None: - v_str = 'unknown' - else: - v_str = '%d.%d' % v + v_str = '%d.%d' % v LOG.warning('[neutron_defaults]resource_tags is set, but Octavia ' 'API %s does not support resource tagging. Kuryr ' 'will put requested tags in the description field of ' 'Octavia resources.', v_str) + def get_octavia_version(self): + lbaas = clients.get_loadbalancer_client() + region_name = getattr(CONF.neutron, 'region_name', None) + + regions = lbaas.get_all_version_data() + # If region was specified take it, otherwise just take first as default + endpoints = regions.get(region_name, list(regions.values())[0]) + # Take the first endpoint + services = list(endpoints.values())[0] + # Try load-balancer service, if not take the first + versions = services.get('load-balancer', list(services.values())[0]) + # Lookup the latest version. For safety, we won't look for + # version['status'] == 'CURRENT' and assume it's the maximum. Also we + # won't assume this dict is sorted. + max_ver = 0, 0 + for version in versions: + v_tuple = versionutils.convert_version_to_tuple(version['version']) + if v_tuple > max_ver: + max_ver = v_tuple + + LOG.debug("Detected Octavia version %d.%d", *max_ver) + return max_ver + def get_service_loadbalancer_name(self, namespace, svc_name): return "%s/%s" % (namespace, svc_name) diff --git a/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py b/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py index f5304ee8e..0ca7fbeac 100644 --- a/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py +++ b/kuryr_kubernetes/tests/unit/controller/drivers/test_lbaasv2.py @@ -34,33 +34,57 @@ from kuryr_kubernetes.tests.unit import kuryr_fixtures as k_fix CONF = cfg.CONF +OCTAVIA_VERSIONS = { + 'regionOne': { + 'public': { + 'load-balancer': [ + { + 'status': 'SUPPORTED', + 'version': '2.0', + 'raw_status': u'SUPPORTED', + }, + { + 'status': 'SUPPORTED', + 'version': '2.1', + 'raw_status': u'SUPPORTED', + }, + { + 'status': 'CURRENT', + 'version': '2.2', + 'raw_status': u'CURRENT', + }, + ], + }, + }, +} + class TestLBaaSv2Driver(test_base.TestCase): - def test_add_tags(self): + @mock.patch('kuryr_kubernetes.controller.drivers.lbaasv2.LBaaSv2Driver.' + 'get_octavia_version', return_value=(2, 5)) + def test_add_tags(self, _m_get): CONF.set_override('resource_tags', ['foo'], group='neutron_defaults') self.addCleanup(CONF.clear_override, 'resource_tags', group='neutron_defaults') - lbaas = self.useFixture(k_fix.MockLBaaSClient()).client - lbaas.get_api_major_version.return_value = (2, 5) d = d_lbaasv2.LBaaSv2Driver() req = {} d._add_tags('loadbalancer', req) self.assertEqual({'tags': ['foo']}, req) - def test_add_tags_no_tag(self): - lbaas = self.useFixture(k_fix.MockLBaaSClient()).client - lbaas.get_api_major_version.return_value = (2, 5) + @mock.patch('kuryr_kubernetes.controller.drivers.lbaasv2.LBaaSv2Driver.' + 'get_octavia_version', return_value=(2, 5)) + def test_add_tags_no_tag(self, _m_get): d = d_lbaasv2.LBaaSv2Driver() req = {} d._add_tags('loadbalancer', req) self.assertEqual({}, req) - def test_add_tags_no_support(self): + @mock.patch('kuryr_kubernetes.controller.drivers.lbaasv2.LBaaSv2Driver.' + 'get_octavia_version', return_value=(2, 4)) + def test_add_tags_no_support(self, _m_get): CONF.set_override('resource_tags', ['foo'], group='neutron_defaults') self.addCleanup(CONF.clear_override, 'resource_tags', group='neutron_defaults') - lbaas = self.useFixture(k_fix.MockLBaaSClient()).client - lbaas.get_api_major_version.return_value = (2, 4) d = d_lbaasv2.LBaaSv2Driver() for res in ('loadbalancer', 'listener', 'pool', 'l7policy'): req = {} @@ -68,12 +92,12 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual({'description': 'foo'}, req, 'No description added to resource %s' % res) - def test_add_tags_no_support_resource_no_description(self): + @mock.patch('kuryr_kubernetes.controller.drivers.lbaasv2.LBaaSv2Driver.' + 'get_octavia_version', return_value=(2, 4)) + def test_add_tags_no_support_resource_no_description(self, _m_get): CONF.set_override('resource_tags', ['foo'], group='neutron_defaults') self.addCleanup(CONF.clear_override, 'resource_tags', group='neutron_defaults') - lbaas = self.useFixture(k_fix.MockLBaaSClient()).client - lbaas.get_api_major_version.return_value = (2, 4) d = d_lbaasv2.LBaaSv2Driver() for res in ('member', 'rule'): req = {} @@ -81,6 +105,13 @@ class TestLBaaSv2Driver(test_base.TestCase): self.assertEqual({}, req, 'Unnecessary description added to ' 'resource %s' % res) + def test_get_octavia_version(self): + lbaas = self.useFixture(k_fix.MockLBaaSClient()).client + lbaas.get_all_version_data.return_value = OCTAVIA_VERSIONS + self.assertEqual((2, 2), + d_lbaasv2.LBaaSv2Driver.get_octavia_version( + d_lbaasv2.LBaaSv2Driver())) + def test_ensure_loadbalancer(self): neutron = self.useFixture(k_fix.MockNeutronClient()).client cls = d_lbaasv2.LBaaSv2Driver