Ensure non-overlapping cidrs in subnetpools with galera
This change enables galera support in _lock_subnetpool[1]. It uses an update to disallow 2 transactions performing concurrent subnet allocation in the same subnetpool to succeed: the 2 transactions will conflict because they update the same row so the db (including Galera multi-writer cluster) will discard the last transaction and Controller.create[2] will catch and retry the "discarded" allocation. This change adds the "hash" attribute in "subnetpools" table to enable previous update. [1] neutron.ipam.subnet_alloc.SubnetAllocator [2] neutron.api.v2.base Change-Id: I74f7100a6fd9b7787be693adffec15ec468d0018 Closes-Bug: #1451576
This commit is contained in:
parent
53bc7162e1
commit
03b70b1094
|
@ -1,3 +1,3 @@
|
|||
1c844d1677f7
|
||||
45f955889773
|
||||
26c371498592
|
||||
kilo
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# Copyright (c) 2015 Thales Services SAS
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
"""subnetpool hash
|
||||
|
||||
Revision ID: 26c371498592
|
||||
Revises: 45f955889773
|
||||
Create Date: 2015-06-02 21:18:19.942076
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '26c371498592'
|
||||
down_revision = '45f955889773'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column(
|
||||
'subnetpools',
|
||||
sa.Column('hash', sa.String(36), nullable=False, server_default=''))
|
|
@ -244,6 +244,7 @@ class SubnetPool(model_base.BASEV2, HasId, HasTenant):
|
|||
max_prefixlen = sa.Column(sa.Integer, nullable=False)
|
||||
shared = sa.Column(sa.Boolean, nullable=False)
|
||||
default_quota = sa.Column(sa.Integer, nullable=True)
|
||||
hash = sa.Column(sa.String(36), nullable=False, server_default='')
|
||||
prefixes = orm.relationship(SubnetPoolPrefix,
|
||||
backref='subnetpools',
|
||||
cascade='all, delete, delete-orphan',
|
||||
|
|
|
@ -17,6 +17,7 @@ import math
|
|||
import operator
|
||||
|
||||
import netaddr
|
||||
from oslo_db import exception as db_exc
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron.api.v2 import attributes
|
||||
|
@ -46,10 +47,23 @@ class SubnetAllocator(driver.Pool):
|
|||
subnetpool, it's required to ensure non-overlapping cidrs in the same
|
||||
subnetpool.
|
||||
"""
|
||||
# FIXME(cbrandily): not working with Galera
|
||||
(self._context.session.query(models_v2.SubnetPool.id).
|
||||
filter_by(id=self._subnetpool['id']).
|
||||
with_lockmode('update').first())
|
||||
|
||||
current_hash = (self._context.session.query(models_v2.SubnetPool.hash)
|
||||
.filter_by(id=self._subnetpool['id']).scalar())
|
||||
if current_hash is None:
|
||||
# NOTE(cbrandily): subnetpool has been deleted
|
||||
raise n_exc.SubnetPoolNotFound(
|
||||
subnetpool_id=self._subnetpool['id'])
|
||||
new_hash = uuidutils.generate_uuid()
|
||||
|
||||
# NOTE(cbrandily): the update disallows 2 concurrent subnet allocation
|
||||
# to succeed: at most 1 transaction will succeed, others will be
|
||||
# rollbacked and be caught in neutron.db.v2.base
|
||||
query = self._context.session.query(models_v2.SubnetPool).filter_by(
|
||||
id=self._subnetpool['id'], hash=current_hash)
|
||||
count = query.update({'hash': new_hash})
|
||||
if not count:
|
||||
raise db_exc.RetryRequest()
|
||||
|
||||
def _get_allocated_cidrs(self):
|
||||
query = self._context.session.query(models_v2.Subnet)
|
||||
|
|
Loading…
Reference in New Issue