--- /dev/null
+# 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=''))
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',
import operator
import netaddr
+from oslo_db import exception as db_exc
from oslo_utils import uuidutils
from neutron.api.v2 import attributes
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)