diff options
| author | Dan Smith <danms@us.ibm.com> | 2012-10-26 14:32:10 -0700 |
|---|---|---|
| committer | Dan Smith <danms@us.ibm.com> | 2012-10-26 14:32:10 -0700 |
| commit | 91fb1ce5c8b8c11fb6e35d8774b7df48da0786b3 (patch) | |
| tree | 45ae43b938fbce11af1eb3fb0a50fbf4f4a598a3 | |
| parent | 47e81951f7925ef506cd1ef8ba9262c127357d0c (diff) | |
| download | nova-91fb1ce5c8b8c11fb6e35d8774b7df48da0786b3.tar.gz nova-91fb1ce5c8b8c11fb6e35d8774b7df48da0786b3.tar.xz nova-91fb1ce5c8b8c11fb6e35d8774b7df48da0786b3.zip | |
Fix nova-network MAC collision logic
The exception being caught and transformed in sqlalchemy/api.py
was incorrect, causing nova-network to miss it in the MAC
collision retry loop.
This patch corrects that and adds a test of the collision logic.
Fixes bug 1059366
Change-Id: I6bf16c2f59f06c7e84441604b057afd8dfe6d709
| -rw-r--r-- | nova/db/sqlalchemy/api.py | 2 | ||||
| -rw-r--r-- | nova/tests/network/test_manager.py | 33 |
2 files changed, 34 insertions, 1 deletions
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 6dd57fc2f..c2ae1dc70 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1271,7 +1271,7 @@ def virtual_interface_create(context, values): vif_ref = models.VirtualInterface() vif_ref.update(values) vif_ref.save() - except IntegrityError: + except exception.DBError: raise exception.VirtualInterfaceCreateException() return vif_ref diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py index 988844883..f5ac26e0a 100644 --- a/nova/tests/network/test_manager.py +++ b/nova/tests/network/test_manager.py @@ -21,6 +21,7 @@ import tempfile from nova import context from nova import db +from nova.db.sqlalchemy import models from nova import exception from nova.network import linux_net from nova.network import manager as network_manager @@ -1843,6 +1844,38 @@ class FloatingIPTestCase(test.TestCase): self.network.delete_dns_domain(context_admin, domain1) self.network.delete_dns_domain(context_admin, domain2) + def test_mac_conflicts(self): + """Make sure MAC collisions are retried""" + self.flags(create_unique_mac_address_attempts=3) + ctxt = context.RequestContext('testuser', 'testproject', is_admin=True) + macs = ['bb:bb:bb:bb:bb:bb', 'aa:aa:aa:aa:aa:aa'] + + # Create a VIF with aa:aa:aa:aa:aa:aa + crash_test_dummy_vif = { + 'address': macs[1], + 'instance_uuid': 'fake_uuid', + 'network_id': 'fake_net', + 'uuid': 'fake_uuid', + } + self.network.db.virtual_interface_create(ctxt, crash_test_dummy_vif) + + # Hand out a collision first, then a legit MAC + def fake_gen_mac(): + return macs.pop() + self.stubs.Set(utils, 'generate_mac_address', fake_gen_mac) + + # SQLite doesn't seem to honor the uniqueness constraint on the + # address column, so fake the collision-avoidance here + def fake_vif_save(vif): + if vif.address == crash_test_dummy_vif['address']: + raise exception.DBError("If you're smart, you'll retry!") + self.stubs.Set(models.VirtualInterface, 'save', fake_vif_save) + + # Attempt to add another and make sure that both MACs are consumed + # by the retry loop + self.network.add_virtual_interface(ctxt, 'fake_uuid', 'fake_net') + self.assertEqual(macs, []) + class NetworkPolicyTestCase(test.TestCase): def setUp(self): |
