]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Cisco plugin fails with ParseError no elem found
authorDane LeBlanc <leblancd@cisco.com>
Tue, 18 Mar 2014 16:37:33 +0000 (12:37 -0400)
committerGerrit Code Review <review@openstack.org>
Wed, 19 Mar 2014 00:21:46 +0000 (00:21 +0000)
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

neutron/plugins/cisco/models/virt_phy_sw_v2.py
neutron/tests/unit/cisco/test_network_plugin.py

index 1e8d125e4fec83e781b7a8a19273ebe731869bdf..b7452f36383cb232b7d56110b07d91aac0b39ab6 100644 (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.
index fd3fac03106990f412bbabdfe89a27f3ffdef45f..da8321b2aed5a172d8c71c1bd60fff4b9ee8ad67 100644 (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.