Fix usage of NexusPortBindingNotFound exception

Currently the required keyword argument (port_id)
is not passed when the exception is raised. In fact
this exception has never been raised before due to
another bug (1173131) so this change also has to
ensure it doesn't break any existing code using
functions which can possibly raise this exception.

Fixes bug 1174323.

Change-Id: I81f0b0def7db163fb0fbb5e03be511113c8d0be5
This commit is contained in:
Roman Podolyaka 2013-05-07 21:57:53 +03:00
parent f94126739a
commit f8f2a7f39c
4 changed files with 127 additions and 62 deletions

View File

@ -96,7 +96,11 @@ class NexusConfigFailed(exceptions.QuantumException):
class NexusPortBindingNotFound(exceptions.QuantumException):
"""NexusPort Binding is not present."""
message = _("Nexus Port Binding %(port_id)s is not present.")
message = _("Nexus Port Binding (%(filters)s) is not present")
def __init__(self, **kwargs):
filters = ','.join('%s=%s' % i for i in kwargs.items())
super(NexusPortBindingNotFound, self).__init__(filters=filters)
class PortVnicBindingAlreadyExists(exceptions.QuantumException):

View File

@ -41,11 +41,14 @@ def get_nexusport_binding(port_id, vlan_id, switch_ip, instance_id):
LOG.debug(_("get_nexusport_binding() called"))
session = db.get_session()
# FIXME(rpodolyaka): https://bugs.launchpad.net/quantum/+bug/1174323
return (session.query(nexus_models_v2.NexusPortBinding).
filter_by(vlan_id=vlan_id).filter_by(switch_ip=switch_ip).
filter_by(port_id=port_id).
filter_by(instance_id=instance_id).all())
filters = dict(port_id=port_id, vlan_id=vlan_id, switch_ip=switch_ip,
instance_id=instance_id)
bindings = (session.query(nexus_models_v2.NexusPortBinding).
filter_by(**filters).all())
if not bindings:
raise c_exc.NexusPortBindingNotFound(**filters)
return bindings
def get_nexusvlan_binding(vlan_id, switch_ip):
@ -53,10 +56,13 @@ def get_nexusvlan_binding(vlan_id, switch_ip):
LOG.debug(_("get_nexusvlan_binding() called"))
session = db.get_session()
# FIXME(rpodolyaka): https://bugs.launchpad.net/quantum/+bug/1174323
return (session.query(nexus_models_v2.NexusPortBinding).
filter_by(vlan_id=vlan_id).filter_by(switch_ip=switch_ip).
all())
filters = dict(vlan_id=vlan_id, switch_ip=switch_ip)
bindings = (session.query(nexus_models_v2.NexusPortBinding).
filter_by(**filters).all())
if not bindings:
raise c_exc.NexusPortBindingNotFound(**filters)
return bindings
def add_nexusport_binding(port_id, vlan_id, switch_ip, instance_id):
@ -98,20 +104,21 @@ def update_nexusport_binding(port_id, new_vlan_id):
session.flush()
return binding
except exc.NoResultFound:
raise c_exc.NexusPortBindingNotFound()
raise c_exc.NexusPortBindingNotFound(port_id=port_id)
def get_nexusvm_binding(vlan_id, instance_id):
"""Lists nexusvm bindings."""
LOG.debug(_("get_nexusvm_binding() called"))
session = db.get_session()
try:
binding = (session.query(nexus_models_v2.NexusPortBinding).
filter_by(instance_id=instance_id).
filter_by(vlan_id=vlan_id).first())
return binding
except exc.NoResultFound:
raise c_exc.NexusPortBindingNotFound(vlan_id=vlan_id)
filters = dict(instance_id=instance_id, vlan_id=vlan_id)
binding = (session.query(nexus_models_v2.NexusPortBinding).
filter_by(**filters).first())
if not binding:
raise c_exc.NexusPortBindingNotFound(**filters)
return binding
def get_port_vlan_switch_binding(port_id, vlan_id, switch_ip):
@ -119,7 +126,10 @@ def get_port_vlan_switch_binding(port_id, vlan_id, switch_ip):
LOG.debug(_("get_port_vlan_switch_binding() called"))
session = db.get_session()
# FIXME(rpodolyaka): https://bugs.launchpad.net/quantum/+bug/1174323
return (session.query(nexus_models_v2.NexusPortBinding).
filter_by(port_id=port_id).filter_by(switch_ip=switch_ip).
filter_by(vlan_id=vlan_id).all())
filters = dict(port_id=port_id, switch_ip=switch_ip, vlan_id=vlan_id)
bindings = (session.query(nexus_models_v2.NexusPortBinding).
filter_by(**filters).all())
if not bindings:
raise c_exc.NexusPortBindingNotFound(**filters)
return bindings

View File

@ -87,11 +87,12 @@ class NexusPlugin(L2DevicePluginBase):
raise cisco_exc.NexusComputeHostNotConfigured(host=host)
# Check if this network is already in the DB
binding = nxos_db.get_port_vlan_switch_binding(
port_id, vlan_id, switch_ip)
vlan_created = False
vlan_enabled = False
if not binding:
try:
nxos_db.get_port_vlan_switch_binding(port_id, vlan_id, switch_ip)
except cisco_exc.NexusPortBindingNotFound:
_nexus_ip = switch_ip
_nexus_ports = (port_id,)
_nexus_ssh_port = \
@ -100,8 +101,9 @@ class NexusPlugin(L2DevicePluginBase):
_nexus_username = _nexus_creds['username']
_nexus_password = _nexus_creds['password']
# Check for vlan/switch binding
vbinding = nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)
if not vbinding:
try:
nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)
except cisco_exc.NexusPortBindingNotFound:
# Create vlan and trunk vlan on the port
self._client.create_vlan(
vlan_name, str(vlan_id), _nexus_ip,
@ -188,44 +190,46 @@ class NexusPlugin(L2DevicePluginBase):
"""
LOG.debug(_("NexusPlugin:delete_port() called"))
# Delete DB row for this port
row = nxos_db.get_nexusvm_binding(vlan_id, device_id)
if row:
nxos_db.remove_nexusport_binding(row['port_id'], row['vlan_id'],
row['switch_ip'],
row['instance_id'])
# Check for any other bindings with the same vlan_id and switch_ip
bindings = nxos_db.get_nexusvlan_binding(
row['vlan_id'], row['switch_ip'])
try:
row = nxos_db.get_nexusvm_binding(vlan_id, device_id)
except cisco_exc.NexusPortBindingNotFound:
return
if not bindings:
nxos_db.remove_nexusport_binding(row['port_id'], row['vlan_id'],
row['switch_ip'],
row['instance_id'])
# Check for any other bindings with the same vlan_id and switch_ip
try:
nxos_db.get_nexusvlan_binding(row['vlan_id'], row['switch_ip'])
except cisco_exc.NexusPortBindingNotFound:
try:
# Delete this vlan from this switch
_nexus_ip = row['switch_ip']
_nexus_ports = (row['port_id'],)
_nexus_ssh_port = (self._nexus_switches[_nexus_ip,
'ssh_port'])
_nexus_creds = self.get_credential(_nexus_ip)
_nexus_username = _nexus_creds['username']
_nexus_password = _nexus_creds['password']
self._client.delete_vlan(
str(row['vlan_id']), _nexus_ip,
_nexus_username, _nexus_password,
_nexus_ports, _nexus_ssh_port)
except Exception as e:
# The delete vlan operation on the Nexus failed,
# so this delete_port request has failed. For
# consistency, roll back the Nexus database to what
# it was before this request.
try:
# Delete this vlan from this switch
_nexus_ip = row['switch_ip']
_nexus_ports = (row['port_id'],)
_nexus_ssh_port = (self._nexus_switches[_nexus_ip,
'ssh_port'])
_nexus_creds = self.get_credential(_nexus_ip)
_nexus_username = _nexus_creds['username']
_nexus_password = _nexus_creds['password']
self._client.delete_vlan(
str(row['vlan_id']), _nexus_ip,
_nexus_username, _nexus_password,
_nexus_ports, _nexus_ssh_port)
except Exception as e:
# The delete vlan operation on the Nexus failed,
# so this delete_port request has failed. For
# consistency, roll back the Nexus database to what
# it was before this request.
try:
nxos_db.add_nexusport_binding(row['port_id'],
row['vlan_id'],
row['switch_ip'],
row['instance_id'])
finally:
# Raise the original exception
raise e
nxos_db.add_nexusport_binding(row['port_id'],
row['vlan_id'],
row['switch_ip'],
row['instance_id'])
finally:
# Raise the original exception
raise e
return row['instance_id']
return row['instance_id']
def update_port(self, tenant_id, net_id, port_id, port_state, **kwargs):
"""Update port.

View File

@ -20,7 +20,11 @@ test_database.py is an independent test suite
that tests the database api method calls
"""
import mock
import sqlalchemy
from quantum.openstack.common import log as logging
import quantum.plugins.cisco.common.cisco_exceptions as c_exc
import quantum.plugins.cisco.db.api as db
import quantum.plugins.cisco.db.l2network_db as l2network_db
import quantum.plugins.cisco.db.nexus_db_v2 as nexus_db
@ -397,6 +401,49 @@ class NexusDBTest(base.BaseTestCase):
self.assertTrue(count == 1)
self.tearDown_nexusportbinding()
def test_get_nexusport_binding_no_result_found_handling(self):
with mock.patch('sqlalchemy.orm.Query.all') as mock_all:
mock_all.return_value = []
with self.assertRaises(c_exc.NexusPortBindingNotFound):
nexus_db.get_nexusport_binding(port_id=10,
vlan_id=20,
switch_ip='10.0.0.1',
instance_id=1)
def test_get_nexusvlan_binding_no_result_found_handling(self):
with mock.patch('sqlalchemy.orm.Query.all') as mock_all:
mock_all.return_value = []
with self.assertRaises(c_exc.NexusPortBindingNotFound):
nexus_db.get_nexusvlan_binding(vlan_id=10,
switch_ip='10.0.0.1')
def test_update_nexusport_binding_no_result_found_handling(self):
with mock.patch('sqlalchemy.orm.Query.one') as mock_one:
mock_one.side_effect = sqlalchemy.orm.exc.NoResultFound
with self.assertRaises(c_exc.NexusPortBindingNotFound):
nexus_db.update_nexusport_binding(port_id=10,
vlan_id=20,
switch_ip='10.0.0.1',
instance_id=1)
def test_get_nexusvm_binding_no_result_found_handling(self):
with mock.patch('sqlalchemy.orm.Query.first') as mock_first:
mock_first.return_value = None
with self.assertRaises(c_exc.NexusPortBindingNotFound):
nexus_db.get_nexusvm_binding(port_id=10,
vlan_id=20,
switch_ip='10.0.0.1')
def test_nexusport_binding_not_found_exception_message_formatting(self):
try:
raise c_exc.NexusPortBindingNotFound(a=1, b='test')
except c_exc.NexusPortBindingNotFound as e:
self.assertIn('(a=1,b=test)', str(e))
def tearDown_nexusportbinding(self):
"""Tear down nexus port binding table."""
LOG.debug("Tearing Down Nexus port Bindings")