Allow update request with current segment_id

If the segment_id in the update request equals the segment_id
already associated with the subnet being updated, there is no
need for further update related segment validations.

Closes-Bug: #1793391
Change-Id: I65cd5b92b219c14dd07ae72457af243756c4ed02
(cherry picked from commit 3b5373b4ef)
This commit is contained in:
Harald Jensås 2018-09-19 15:36:27 +02:00
parent 3363e91bf0
commit 054e8e0572
3 changed files with 29 additions and 4 deletions

View File

@ -315,7 +315,8 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
pool_2=r_range,
subnet_cidr=subnet_cidr)
def _validate_segment(self, context, network_id, segment_id, action=None):
def _validate_segment(self, context, network_id, segment_id, action=None,
old_segment_id=None):
query = context.session.query(models_v2.Subnet.segment_id)
query = query.filter(models_v2.Subnet.network_id == network_id)
associated_segments = set(row.segment_id for row in query)
@ -323,7 +324,7 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
raise segment_exc.SubnetsNotAllAssociatedWithSegments(
network_id=network_id)
if action == 'update':
if action == 'update' and old_segment_id != segment_id:
# Check the current state of segments and subnets on the network
# before allowing migration from non-routed to routed network.
if query.count() > 1:

View File

@ -428,9 +428,12 @@ class IpamPluggableBackend(ipam_backend_mixin.IpamBackendMixin):
port['fixed_ips'])
def update_db_subnet(self, context, id, s, old_pools):
subnet = obj_subnet.Subnet.get_object(context, id=id)
old_segment_id = subnet.segment_id if subnet else None
if 'segment_id' in s:
self._validate_segment(context, s['network_id'], s['segment_id'],
action='update')
self._validate_segment(
context, s['network_id'], s['segment_id'], action='update',
old_segment_id=old_segment_id)
# 'allocation_pools' is removed from 's' in
# _update_subnet_allocation_pools (ipam_backend_mixin),
# so create unchanged copy for ipam driver

View File

@ -540,6 +540,27 @@ class TestSegmentSubnetAssociation(SegmentTestCase):
self.assertEqual(webob.exc.HTTPOk.code, response.status_int)
self.assertEqual(res['subnet']['segment_id'], segment['id'])
def test_update_subnet_with_current_segment_id(self):
with self.network() as network:
net = network['network']
segment1 = self._test_create_segment(network_id=net['id'],
physical_network='phys_net1',
segmentation_id=200)['segment']
self._test_create_segment(network_id=net['id'],
physical_network='phys_net2',
segmentation_id=200)['segment']
with self.subnet(network=network, segment_id=segment1['id']) as subnet:
subnet = subnet['subnet']
data = {'subnet': {'segment_id': segment1['id']}}
request = self.new_update_request('subnets', data, subnet['id'])
response = request.get_response(self.api)
res = self.deserialize(self.fmt, response)
self.assertEqual(webob.exc.HTTPOk.code, response.status_int)
self.assertEqual(res['subnet']['segment_id'], segment1['id'])
def test_associate_existing_subnet_fail_if_multiple_segments(self):
with self.network() as network:
net = network['network']