NSX|V: don't throw exception when same vnic is configured
In the event of a nova retry we should not throw an exception for for a port update Change-Id: Ic4df033952e3dddd170e0fb7b57499750a6155b0 Closes-bug: #1606809
This commit is contained in:
parent
91fecee67c
commit
e51421f5ca
@ -18,6 +18,7 @@ from sqlalchemy.orm import exc
|
||||
from neutron.api.v2 import attributes as attr
|
||||
from neutron.db import db_base_plugin_v2
|
||||
|
||||
from oslo_db import exception as db_exc
|
||||
from oslo_log import log as logging
|
||||
|
||||
from vmware_nsx.db import nsxv_models
|
||||
@ -47,7 +48,14 @@ class VnicIndexDbMixin(object):
|
||||
except exc.NoResultFound:
|
||||
LOG.debug("No record in DB for vnic-index of port %s", port_id)
|
||||
|
||||
def _set_port_vnic_index_mapping(self, context, port_id, device_id, index):
|
||||
def _get_mappings_for_device_id(self, context, device_id):
|
||||
session = context.session
|
||||
mappings = (session.query(nsxv_models.NsxvPortIndexMapping).
|
||||
filter_by(device_id=device_id))
|
||||
return mappings
|
||||
|
||||
def _create_port_vnic_index_mapping(self, context, port_id,
|
||||
device_id, index):
|
||||
"""Save the port vnic-index to DB."""
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
@ -55,6 +63,38 @@ class VnicIndexDbMixin(object):
|
||||
port_id=port_id, device_id=device_id, index=index)
|
||||
session.add(index_mapping_model)
|
||||
|
||||
def _update_port_vnic_index_mapping(self, context, port_id,
|
||||
device_id, index):
|
||||
session = context.session
|
||||
# delete original entry
|
||||
query = (session.query(nsxv_models.NsxvPortIndexMapping).
|
||||
filter_by(device_id=device_id, index=index))
|
||||
query.delete()
|
||||
# create a new one
|
||||
self._create_port_vnic_index_mapping(context, port_id, device_id,
|
||||
index)
|
||||
|
||||
def _set_port_vnic_index_mapping(self, context, port_id, device_id, index):
|
||||
"""Save the port vnic-index to DB."""
|
||||
try:
|
||||
self._create_port_vnic_index_mapping(context, port_id,
|
||||
device_id, index)
|
||||
except db_exc.DBDuplicateEntry:
|
||||
# A retry for the nova scheduling could result in this error.
|
||||
LOG.debug("Entry already exists for %s %s %s", port_id,
|
||||
device_id, index)
|
||||
mappings = self._get_mappings_for_device_id(context, device_id)
|
||||
for mapping in mappings:
|
||||
if (mapping['port_id'] != port_id and
|
||||
mapping['index'] == index):
|
||||
# a new port is using this device - update!
|
||||
self._update_port_vnic_index_mapping(context, port_id,
|
||||
device_id, index)
|
||||
return
|
||||
if (mapping['port_id'] == port_id and
|
||||
mapping['index'] != index):
|
||||
raise
|
||||
|
||||
def _delete_port_vnic_index_mapping(self, context, port_id):
|
||||
"""Delete the port vnic-index association."""
|
||||
session = context.session
|
||||
|
@ -93,16 +93,46 @@ class VnicIndexDbTestCase(test_db_plugin.NeutronDbPluginV2TestCase):
|
||||
self.assertRaises(d_exc.DBDuplicateEntry,
|
||||
plugin._set_port_vnic_index_mapping,
|
||||
context, port_id, device_id, 1)
|
||||
# Only one Port can be associated with a specific index on a device
|
||||
self.assertRaises(d_exc.DBDuplicateEntry,
|
||||
plugin._set_port_vnic_index_mapping,
|
||||
context, _uuid(), device_id, vnic_index)
|
||||
# Check that the call for _delete_port_vnic_index remove the row from
|
||||
# the table
|
||||
|
||||
# TODO(kobis): deletion was removed from port - fix this assert
|
||||
# self.assertIsNone(plugin._get_port_vnic_index(context, port_id))
|
||||
|
||||
def test_vnic_index_db_duplicate(self):
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
vnic_index = 2
|
||||
device_id = _uuid()
|
||||
context = neutron_context.get_admin_context()
|
||||
with self.port(device_id=device_id,
|
||||
device_owner='compute:None') as port:
|
||||
port_id = port['port']['id']
|
||||
res = self._port_index_update(port_id, vnic_index)
|
||||
self.assertEqual(res['port'][vnicidx.VNIC_INDEX], vnic_index)
|
||||
plugin._set_port_vnic_index_mapping(context, port_id, device_id,
|
||||
vnic_index)
|
||||
|
||||
def test_vnic_index_db_duplicate_new_port(self):
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
vnic_index = 2
|
||||
device_id = _uuid()
|
||||
context = neutron_context.get_admin_context()
|
||||
with self.port(device_id=device_id,
|
||||
device_owner='compute:None') as port:
|
||||
with self.port(device_id=device_id,
|
||||
device_owner='compute:None') as port1:
|
||||
port_id = port['port']['id']
|
||||
res = self._port_index_update(port_id, vnic_index)
|
||||
self.assertEqual(res['port'][vnicidx.VNIC_INDEX], vnic_index)
|
||||
port_id1 = port1['port']['id']
|
||||
plugin._set_port_vnic_index_mapping(context, port_id1,
|
||||
device_id, 2)
|
||||
self.assertIsNone(plugin._get_port_vnic_index(context,
|
||||
port_id))
|
||||
self.assertEqual(vnic_index,
|
||||
plugin._get_port_vnic_index(context,
|
||||
port_id1))
|
||||
|
||||
|
||||
class TestVnicIndex(VnicIndexDbTestCase):
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user