From: armando-migliaccio Date: Tue, 27 Aug 2013 19:53:58 +0000 (-0700) Subject: Make Neutron NVP plugin future-versions friendly X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=80df449aa5a4753705b64cb68492508c91efd580;p=openstack-build%2Fneutron-build.git Make Neutron NVP plugin future-versions friendly This patch enables the plugin to deal correctly with newer versions of the NVP platform; this is done by allowing the plugin to fall back to the closest known version of the NVP platform. This is acceptable behavior as L2/L3 operations implemented by the platform are most certainly backward compatible. This patch also improves test coverage for this part of the code, which is critical to the correct behavior of the plugin. Fixes bug #1217479 Change-Id: Ifcce47c6ee2bc2bc96ddfe9298d252700aceca3f --- diff --git a/neutron/plugins/nicira/nvplib.py b/neutron/plugins/nicira/nvplib.py index 6ad816b13..c4594f4d2 100644 --- a/neutron/plugins/nicira/nvplib.py +++ b/neutron/plugins/nicira/nvplib.py @@ -84,18 +84,7 @@ def version_dependent(wrapped_func): # should return the NVP version v = (wrapped_func(cluster, *args, **kwargs) or cluster.api_client.get_nvp_version()) - if v: - func = (NVPLIB_FUNC_DICT[func_name][v.major].get(v.minor) or - NVPLIB_FUNC_DICT[func_name][v.major]['default']) - if func is None: - LOG.error(_('NVP version %(ver)s does not support method ' - '%(fun)s.') % {'ver': v, 'fun': func_name}) - raise NotImplementedError() - else: - raise NvpApiClient.ServiceUnavailable('NVP version is not set. ' - 'Unable to complete request' - 'correctly. Check log for ' - 'NVP communication errors.') + func = get_function_by_version(func_name, v) func_kwargs = kwargs arg_spec = inspect.getargspec(func) if not arg_spec.keywords and not arg_spec.varargs: @@ -1197,30 +1186,50 @@ def update_lrouter_port_ips(cluster, lrouter_id, lport_id, raise nvp_exc.NvpPluginException(err_msg=msg) +DEFAULT = -1 NVPLIB_FUNC_DICT = { 'create_lrouter': { - 2: {'default': create_implicit_routing_lrouter, }, - 3: {'default': create_implicit_routing_lrouter, + 2: {DEFAULT: create_implicit_routing_lrouter, }, + 3: {DEFAULT: create_implicit_routing_lrouter, 2: create_explicit_routing_lrouter, }, }, 'update_lrouter': { - 2: {'default': update_implicit_routing_lrouter, }, - 3: {'default': update_implicit_routing_lrouter, + 2: {DEFAULT: update_implicit_routing_lrouter, }, + 3: {DEFAULT: update_implicit_routing_lrouter, 2: update_explicit_routing_lrouter, }, }, 'create_lrouter_dnat_rule': { - 2: {'default': create_lrouter_dnat_rule_v2, }, - 3: {'default': create_lrouter_dnat_rule_v3, }, }, + 2: {DEFAULT: create_lrouter_dnat_rule_v2, }, + 3: {DEFAULT: create_lrouter_dnat_rule_v3, }, }, 'create_lrouter_snat_rule': { - 2: {'default': create_lrouter_snat_rule_v2, }, - 3: {'default': create_lrouter_snat_rule_v3, }, }, + 2: {DEFAULT: create_lrouter_snat_rule_v2, }, + 3: {DEFAULT: create_lrouter_snat_rule_v3, }, }, 'create_lrouter_nosnat_rule': { - 2: {'default': create_lrouter_nosnat_rule_v2, }, - 3: {'default': create_lrouter_nosnat_rule_v3, }, }, + 2: {DEFAULT: create_lrouter_nosnat_rule_v2, }, + 3: {DEFAULT: create_lrouter_nosnat_rule_v3, }, }, 'get_default_route_explicit_routing_lrouter': { - 3: {2: get_default_route_explicit_routing_lrouter_v32, - 3: get_default_route_explicit_routing_lrouter_v33, }, }, + 3: {DEFAULT: get_default_route_explicit_routing_lrouter_v32, + 2: get_default_route_explicit_routing_lrouter_v32, }, }, } +def get_function_by_version(func_name, nvp_ver): + if nvp_ver: + if nvp_ver.major not in NVPLIB_FUNC_DICT[func_name]: + major = max(NVPLIB_FUNC_DICT[func_name].keys()) + minor = max(NVPLIB_FUNC_DICT[func_name][major].keys()) + if major > nvp_ver.major: + raise NotImplementedError(_("Operation may not be supported")) + else: + major = nvp_ver.major + minor = nvp_ver.minor + if nvp_ver.minor not in NVPLIB_FUNC_DICT[func_name][major]: + minor = DEFAULT + return NVPLIB_FUNC_DICT[func_name][major][minor] + else: + msg = _('NVP version is not set. Unable to complete request ' + 'correctly. Check log for NVP communication errors.') + raise NvpApiClient.ServiceUnavailable(message=msg) + + # ----------------------------------------------------------------------------- # QOS API Calls # ----------------------------------------------------------------------------- diff --git a/neutron/tests/unit/nicira/test_nvplib.py b/neutron/tests/unit/nicira/test_nvplib.py index 2734feb8d..7e416502c 100644 --- a/neutron/tests/unit/nicira/test_nvplib.py +++ b/neutron/tests/unit/nicira/test_nvplib.py @@ -1388,5 +1388,37 @@ class TestNvplibClusterManagement(NvplibTestCase): cluster=self.fake_cluster) +class TestNvplibVersioning(base.BaseTestCase): + + def test_function_handling_missing_minor(self): + version = NvpApiClient.NVPVersion('2.0') + function = nvplib.get_function_by_version('create_lrouter', version) + self.assertEqual(nvplib.create_implicit_routing_lrouter, + function) + + def test_function_handling_with_both_major_and_minor(self): + version = NvpApiClient.NVPVersion('3.2') + function = nvplib.get_function_by_version('create_lrouter', version) + self.assertEqual(nvplib.create_explicit_routing_lrouter, + function) + + def test_function_handling_with_newer_major(self): + version = NvpApiClient.NVPVersion('5.2') + function = nvplib.get_function_by_version('create_lrouter', version) + self.assertEqual(nvplib.create_explicit_routing_lrouter, + function) + + def test_function_handling_with_obsolete_major(self): + version = NvpApiClient.NVPVersion('1.2') + self.assertRaises(NotImplementedError, + nvplib.get_function_by_version, + 'create_lrouter', version) + + def test_function_handling_with_unknown_version(self): + self.assertRaises(NvpApiClient.ServiceUnavailable, + nvplib.get_function_by_version, + 'create_lrouter', None) + + def _nicira_method(method_name, module_name='nvplib'): return '%s.%s.%s' % ('neutron.plugins.nicira', module_name, method_name)