Cisco plugin fails with ParseError no elem found

When the Cisco nexus plugin is configured on DevStack, the tempest
Neutron API test test_port_list_filter_by_router_id fails with the
following error:
     ParseError: no element found: line 1, column 0

The root cause is that the Cisco Nexus plugin model layer
is encapsulating each dictionary response from the OVS subplugin
into a list, whereas the WSGI layer is expecting a dictionary
response. The fix is not to encapsulate these responses into a list.

Change-Id: I4b589e8e5696c0eae43cafc46912b3d7f29bbdb6
Closes-Bug: #1284162
This commit is contained in:
Dane LeBlanc 2014-03-18 12:37:33 -04:00 committed by Gerrit Code Review
parent 0009e474e2
commit 0049967a87
2 changed files with 34 additions and 14 deletions

View File

@ -143,7 +143,7 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
'args': args})
else:
func = getattr(self._plugins[plugin_key], function_name)
return [func(*args, **kwargs)]
return func(*args, **kwargs)
def _get_segmentation_id(self, network_id):
binding_seg_id = odb.get_network_binding(None, network_id)
@ -175,14 +175,14 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
# The vswitch plugin did all the verification. If it's a provider
# vlan network, save it for the nexus plugin to use later.
if provider_vlan_id:
network_id = ovs_output[0][const.NET_ID]
network_id = ovs_output[const.NET_ID]
cdb.add_provider_network(network_id,
const.NETWORK_TYPE_VLAN,
provider_vlan_id)
LOG.debug(_("Provider network added to DB: %(network_id)s, "
"%(vlan_id)s"),
{'network_id': network_id, 'vlan_id': provider_vlan_id})
return ovs_output[0]
return ovs_output
def update_network(self, context, id, network):
"""Update network.
@ -207,10 +207,9 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
provider._raise_if_updates_provider_attributes(network['network'])
args = [context, id, network]
ovs_output = self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
return ovs_output[0]
return self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
def delete_network(self, context, id):
"""Delete network.
@ -224,7 +223,7 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
args)
if cdb.remove_provider_network(id):
LOG.debug(_("Provider network removed from DB: %s"), id)
return ovs_output[0]
return ovs_output
def get_network(self, context, id, fields=None):
"""Get network. This method is delegated to the vswitch plugin.
@ -307,7 +306,7 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
# to rollback the port creation on the VSwitch plugin.
exc_info = sys.exc_info()
try:
id = ovs_output[0]['id']
id = ovs_output['id']
args = [context, id]
ovs_output = self._invoke_plugin_per_device(
const.VSWITCH_PLUGIN,
@ -316,7 +315,7 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
finally:
# Re-raise the original exception
raise exc_info[0], exc_info[1], exc_info[2]
return ovs_output[0]
return ovs_output
def get_port(self, context, id, fields=None):
"""Get port. This method is delegated to the vswitch plugin.
@ -403,7 +402,7 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
if create_args:
self._invoke_nexus_for_net_create(context, *create_args)
return ovs_output[0]
return ovs_output
except Exception:
exc_info = sys.exc_info()
LOG.error(_("Unable to update port '%s' on Nexus switch"),
@ -411,7 +410,7 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
try:
# Roll back vSwitch plugin to original port attributes.
args = [context, id, {'port': old_port}]
ovs_output = self._invoke_plugin_per_device(
self._invoke_plugin_per_device(
const.VSWITCH_PLUGIN,
self._func_name(),
args)
@ -456,7 +455,7 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
# Raise the original exception.
raise exc_info[0], exc_info[1], exc_info[2]
return ovs_output[0]
return ovs_output
def add_router_interface(self, context, router_id, interface_info):
"""Add a router interface on a subnet.

View File

@ -1012,7 +1012,16 @@ class TestCiscoSubnetsV2(CiscoNetworkPluginV2TestCase,
class TestCiscoRouterInterfacesV2(CiscoNetworkPluginV2TestCase):
def setUp(self):
"""Configure an API extension manager."""
"""Configure a log exception counter and an API extension manager."""
self.log_exc_count = 0
def _count_exception_logs(*args, **kwargs):
self.log_exc_count += 1
mock.patch.object(logging.LoggerAdapter, 'exception',
autospec=True,
side_effect=_count_exception_logs,
wraps=logging.LoggerAdapter.exception).start()
super(TestCiscoRouterInterfacesV2, self).setUp()
ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
@ -1061,6 +1070,18 @@ class TestCiscoRouterInterfacesV2(CiscoNetworkPluginV2TestCase):
**kwargs) as response:
yield response
def test_port_list_filtered_by_router_id(self):
"""Test port list command filtered by router ID."""
with self._network_subnet_router() as (network, subnet, router):
with self._router_interface(router, subnet):
query_params = "device_id=%s" % router['router']['id']
req = self.new_list_request('ports', self.fmt, query_params)
res = self.deserialize(self.fmt, req.get_response(self.api))
self.assertEqual(len(res['ports']), 1)
self.assertEqual(res['ports'][0]['device_id'],
router['router']['id'])
self.assertFalse(self.log_exc_count)
def test_add_remove_router_intf_with_nexus_l3_enabled(self):
"""Verifies proper add/remove intf operation with Nexus L3 enabled.