]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Make Neutron NVP plugin future-versions friendly
authorarmando-migliaccio <amigliaccio@nicira.com>
Tue, 27 Aug 2013 19:53:58 +0000 (12:53 -0700)
committerarmando-migliaccio <amigliaccio@nicira.com>
Tue, 27 Aug 2013 20:31:18 +0000 (13:31 -0700)
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

neutron/plugins/nicira/nvplib.py
neutron/tests/unit/nicira/test_nvplib.py

index 6ad816b133c7f9c8d52deb616a66a7acd8e8a028..c4594f4d2f62469f1d318069f133a94366b70461 100644 (file)
@@ -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
 # -----------------------------------------------------------------------------
index 2734feb8dda6f4564a682d93ca378a2096838d40..7e416502ce976a8b6ed0c27e653f1ffc1070b72c 100644 (file)
@@ -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)