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
This commit is contained in:
armando-migliaccio 2013-08-27 12:53:58 -07:00
parent 6ae42583eb
commit 80df449aa5
2 changed files with 65 additions and 24 deletions

View 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
# -----------------------------------------------------------------------------

View 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)