Fix duplicate entry catch for allowed address pairs
If None is submitted as a MAC address in an allowed_address_pair, the port MAC will be used. So if two entries are submitted with the same IP and one's MAC is None while the others is the port's MAC, they will pass the API duplication check and fail to insert into the DB due to a unique constraint violation. This patch catches the db error and turns it into the same exception the API uses on duplicate entries. Closes-bug: #1373756 Change-Id: Ide995810d6fe0481d3add206bf0674cbbde7f05f
This commit is contained in:
parent
043f6c3091
commit
1025baec55
|
@ -14,6 +14,8 @@
|
|||
#
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from oslo_db import exception as db_exc
|
||||
from sqlalchemy import orm
|
||||
|
||||
from neutron.api.v2 import attributes as attr
|
||||
|
@ -43,16 +45,21 @@ class AllowedAddressPairsMixin(object):
|
|||
allowed_address_pairs):
|
||||
if not attr.is_attr_set(allowed_address_pairs):
|
||||
return []
|
||||
with context.session.begin(subtransactions=True):
|
||||
for address_pair in allowed_address_pairs:
|
||||
# use port.mac_address if no mac address in address pair
|
||||
if 'mac_address' not in address_pair:
|
||||
address_pair['mac_address'] = port['mac_address']
|
||||
db_pair = AllowedAddressPair(
|
||||
port_id=port['id'],
|
||||
mac_address=address_pair['mac_address'],
|
||||
ip_address=address_pair['ip_address'])
|
||||
context.session.add(db_pair)
|
||||
try:
|
||||
with context.session.begin(subtransactions=True):
|
||||
for address_pair in allowed_address_pairs:
|
||||
# use port.mac_address if no mac address in address pair
|
||||
if 'mac_address' not in address_pair:
|
||||
address_pair['mac_address'] = port['mac_address']
|
||||
db_pair = AllowedAddressPair(
|
||||
port_id=port['id'],
|
||||
mac_address=address_pair['mac_address'],
|
||||
ip_address=address_pair['ip_address'])
|
||||
context.session.add(db_pair)
|
||||
except db_exc.DBDuplicateEntry:
|
||||
raise addr_pair.DuplicateAddressPairInRequest(
|
||||
mac_address=address_pair['mac_address'],
|
||||
ip_address=address_pair['ip_address'])
|
||||
|
||||
return allowed_address_pairs
|
||||
|
||||
|
|
|
@ -279,6 +279,21 @@ class TestAllowedAddressPairs(AllowedAddressPairDBTestCase):
|
|||
res = req.get_response(self.api)
|
||||
self.assertEqual(409, res.status_int)
|
||||
|
||||
def test_update_with_none_and_own_mac_for_duplicate_ip(self):
|
||||
with self.network() as net:
|
||||
res = self._create_port(self.fmt, net['network']['id'])
|
||||
port = self.deserialize(self.fmt, res)
|
||||
mac_address = port['port']['mac_address']
|
||||
address_pairs = [{'ip_address': '10.0.0.1'},
|
||||
{'mac_address': mac_address,
|
||||
'ip_address': '10.0.0.1'}]
|
||||
update_port = {'port': {addr_pair.ADDRESS_PAIRS:
|
||||
address_pairs}}
|
||||
req = self.new_update_request('ports', update_port,
|
||||
port['port']['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_create_port_remove_allowed_address_pairs(self):
|
||||
with self.network() as net:
|
||||
address_pairs = [{'mac_address': '00:00:00:00:00:01',
|
||||
|
|
Loading…
Reference in New Issue