From: Roman Podolyaka Date: Tue, 7 May 2013 18:57:53 +0000 (+0300) Subject: Fix usage of NexusPortBindingNotFound exception X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=f8f2a7f39ce6067e737ee6c47dfee8500d27d57d;p=openstack-build%2Fneutron-build.git 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 --- diff --git a/quantum/plugins/cisco/common/cisco_exceptions.py b/quantum/plugins/cisco/common/cisco_exceptions.py index 2b27cc23d..f50e6050c 100644 --- a/quantum/plugins/cisco/common/cisco_exceptions.py +++ b/quantum/plugins/cisco/common/cisco_exceptions.py @@ -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): diff --git a/quantum/plugins/cisco/db/nexus_db_v2.py b/quantum/plugins/cisco/db/nexus_db_v2.py index fb331873b..a48a82795 100644 --- a/quantum/plugins/cisco/db/nexus_db_v2.py +++ b/quantum/plugins/cisco/db/nexus_db_v2.py @@ -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 diff --git a/quantum/plugins/cisco/nexus/cisco_nexus_plugin_v2.py b/quantum/plugins/cisco/nexus/cisco_nexus_plugin_v2.py index a5873965a..b0c17366b 100644 --- a/quantum/plugins/cisco/nexus/cisco_nexus_plugin_v2.py +++ b/quantum/plugins/cisco/nexus/cisco_nexus_plugin_v2.py @@ -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']) - - if not bindings: + try: + row = nxos_db.get_nexusvm_binding(vlan_id, device_id) + except cisco_exc.NexusPortBindingNotFound: + return + + 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 - - return row['instance_id'] + 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'] def update_port(self, tenant_id, net_id, port_id, port_state, **kwargs): """Update port. diff --git a/quantum/plugins/cisco/tests/unit/test_database.py b/quantum/plugins/cisco/tests/unit/test_database.py index 4ff9e8a9a..bf18c23af 100644 --- a/quantum/plugins/cisco/tests/unit/test_database.py +++ b/quantum/plugins/cisco/tests/unit/test_database.py @@ -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")