]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
VMware NSX: Fix db integrity error on dhcp port operations
authorarmando-migliaccio <armamig@gmail.com>
Mon, 6 Jan 2014 12:42:30 +0000 (04:42 -0800)
committerarmando-migliaccio <armamig@gmail.com>
Mon, 6 Jan 2014 14:21:18 +0000 (06:21 -0800)
If the dhcp port and network disappear, ensure that
the integrity constraint violation that results from
inserting the neutron/nsx port mapping to the DB does
not propagate the exception all the way through, but
instead is caught and handled correctly.

Closes-bug: #1265472

Change-Id: I3ae072729d579def0bd9658241eda1011a3dcfa0

neutron/plugins/nicira/NeutronPlugin.py
neutron/tests/unit/nicira/test_nicira_plugin.py

index 671f6743d1f598e9c6cf0cbc6f8eeff6e3e6b946..a44b73d8df25c032b90d4db6b22fc91ce3ec6ba5 100644 (file)
@@ -24,6 +24,7 @@ import logging
 import os
 
 from oslo.config import cfg
+from sqlalchemy import exc as sql_exc
 from sqlalchemy.orm import exc as sa_exc
 import webob.exc
 
@@ -56,6 +57,7 @@ from neutron.extensions import portbindings as pbin
 from neutron.extensions import portsecurity as psec
 from neutron.extensions import providernet as pnet
 from neutron.extensions import securitygroup as ext_sg
+from neutron.openstack.common.db import exception as db_exc
 from neutron.openstack.common import excutils
 from neutron.openstack.common import lockutils
 from neutron.plugins.common import constants as plugin_const
@@ -490,6 +492,22 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
                 context, port_data['id'],
                 selected_lswitch and selected_lswitch['uuid'],
                 lport and lport['uuid'])
+        except db_exc.DBError as e:
+            if (port_data['device_owner'] == constants.DEVICE_OWNER_DHCP and
+                isinstance(e.inner_exception, sql_exc.IntegrityError)):
+                msg = (_("Concurrent network deletion detected; Back-end Port "
+                         "%(nsx_id)s creation to be rolled back for Neutron "
+                         "port: %(neutron_id)s")
+                       % {'nsx_id': lport['uuid'],
+                          'neutron_id': port_data['id']})
+                LOG.warning(msg)
+                if selected_lswitch and lport:
+                    try:
+                        nvplib.delete_port(self.cluster,
+                                           selected_lswitch['uuid'],
+                                           lport['uuid'])
+                    except q_exc.NotFound:
+                        LOG.debug(_("NSX Port %s already gone"), lport['uuid'])
 
     def _nvp_delete_port(self, context, port_data):
         # FIXME(salvatore-orlando): On the NVP platform we do not really have
index 544cbd586864f3bb70f74d2cc68278d9c0c99977..075a3501fd331563bfe1f55b2fe5f66c94c56a6a 100644 (file)
@@ -20,6 +20,7 @@ import contextlib
 import mock
 import netaddr
 from oslo.config import cfg
+from sqlalchemy import exc as sql_exc
 import webob.exc
 
 from neutron.api.v2 import attributes
@@ -36,6 +37,7 @@ from neutron.extensions import providernet as pnet
 from neutron.extensions import securitygroup as secgrp
 from neutron import manager
 from neutron.manager import NeutronManager
+from neutron.openstack.common.db import exception as db_exc
 from neutron.openstack.common import uuidutils
 from neutron.plugins.nicira.common import exceptions as nvp_exc
 from neutron.plugins.nicira.common import sync
@@ -251,6 +253,17 @@ class TestNiciraPortsV2(NiciraPluginV2TestCase,
                                   webob.exc.HTTPInternalServerError.code)
                 self._verify_no_orphan_left(net_id)
 
+    def test_create_port_db_error_no_orphan_left(self):
+        db_exception = db_exc.DBError(
+            inner_exception=sql_exc.IntegrityError(mock.ANY,
+                                                   mock.ANY,
+                                                   mock.ANY))
+        with mock.patch.object(nicira_db, 'add_neutron_nsx_port_mapping',
+                               side_effect=db_exception):
+            with self.network() as net:
+                with self.port(device_owner='network:dhcp'):
+                    self._verify_no_orphan_left(net['network']['id'])
+
     def test_create_port_maintenance_returns_503(self):
         with self.network() as net:
             with mock.patch.object(nvplib, 'do_request',