From: Dane LeBlanc Date: Tue, 18 Mar 2014 16:37:33 +0000 (-0400) Subject: Cisco plugin fails with ParseError no elem found X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=0049967a874a3dca7c6ab8e8e84ca7dea21dc0b2;p=openstack-build%2Fneutron-build.git 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 --- diff --git a/neutron/plugins/cisco/models/virt_phy_sw_v2.py b/neutron/plugins/cisco/models/virt_phy_sw_v2.py index 1e8d125e4..b7452f363 100644 --- a/neutron/plugins/cisco/models/virt_phy_sw_v2.py +++ b/neutron/plugins/cisco/models/virt_phy_sw_v2.py @@ -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. diff --git a/neutron/tests/unit/cisco/test_network_plugin.py b/neutron/tests/unit/cisco/test_network_plugin.py index fd3fac031..da8321b2a 100644 --- a/neutron/tests/unit/cisco/test_network_plugin.py +++ b/neutron/tests/unit/cisco/test_network_plugin.py @@ -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.