Merge "Fixes enable taas id reuse"
This commit is contained in:
commit
a69e2f47fa
@ -1 +1 @@
|
||||
4086b3cffc01
|
||||
bac61f603e39
|
||||
|
@ -0,0 +1,50 @@
|
||||
# Copyright 2016-17
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Alter TapIdAssociations to support tap id reuse
|
||||
|
||||
Revision ID: bac61f603e39
|
||||
Revises: 4086b3cffc01
|
||||
Create Date: 2016-07-27 09:31:54.200165
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'bac61f603e39'
|
||||
down_revision = '4086b3cffc01'
|
||||
|
||||
from alembic import op
|
||||
from sqlalchemy.engine import reflection
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
TABLE_NAME = 'tap_id_associations'
|
||||
|
||||
|
||||
def upgrade():
|
||||
inspector = reflection.Inspector.from_engine(op.get_bind())
|
||||
fk_constraints = inspector.get_foreign_keys(TABLE_NAME)
|
||||
for fk in fk_constraints:
|
||||
op.drop_constraint(fk['name'], TABLE_NAME, type_='foreignkey')
|
||||
|
||||
op.create_foreign_key('fk_tap_id_assoc_tap_service', TABLE_NAME,
|
||||
'tap_services', ['tap_service_id'], ['id'],
|
||||
ondelete='SET NULL')
|
||||
|
||||
op.alter_column(TABLE_NAME, 'taas_id', autoincrement=False,
|
||||
existing_type=sa.INTEGER, nullable=False)
|
||||
op.alter_column(TABLE_NAME, 'tap_service_id',
|
||||
existing_type=sa.String(36), nullable=True)
|
||||
op.create_unique_constraint('unique_taas_id', TABLE_NAME,
|
||||
['taas_id'])
|
@ -23,10 +23,10 @@ from neutron_lib import constants
|
||||
from neutron_lib.db import model_base
|
||||
from neutron_lib.plugins import directory
|
||||
from neutron_taas.extensions import taas
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -68,12 +68,13 @@ class TapIdAssociation(model_base.BASEV2):
|
||||
__tablename__ = 'tap_id_associations'
|
||||
tap_service_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey("tap_services.id",
|
||||
ondelete='CASCADE'))
|
||||
taas_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
||||
ondelete='SET NULL'),
|
||||
nullable=True)
|
||||
taas_id = sa.Column(sa.Integer, primary_key=True, unique=True)
|
||||
tap_service = orm.relationship(
|
||||
TapService,
|
||||
backref=orm.backref("tap_service_id",
|
||||
lazy="joined", cascade="delete"),
|
||||
lazy="joined"),
|
||||
primaryjoin='TapService.id==TapIdAssociation.tap_service_id')
|
||||
|
||||
|
||||
@ -147,14 +148,47 @@ class Taas_db_Mixin(taas.TaasPluginBase, base_db.CommonDbMixin):
|
||||
|
||||
return self._make_tap_service_dict(tap_service_db)
|
||||
|
||||
def _rebuild_taas_id_allocation_range(self, context):
|
||||
query = context.session.query(
|
||||
TapIdAssociation).all()
|
||||
|
||||
allocate_taas_id_list = [_q.taas_id for _q in query]
|
||||
first_taas_id = cfg.CONF.taas.vlan_range_start
|
||||
# Exclude range end
|
||||
last_taas_id = cfg.CONF.taas.vlan_range_end
|
||||
all_taas_id_set = set(range(first_taas_id, last_taas_id))
|
||||
vaild_taas_id_set = all_taas_id_set - set(allocate_taas_id_list)
|
||||
|
||||
for _id in vaild_taas_id_set:
|
||||
# new taas id
|
||||
context.session.add(TapIdAssociation(
|
||||
taas_id=_id))
|
||||
|
||||
def _allocate_taas_id_with_tap_service_id(self, context, tap_service_id):
|
||||
query = context.session.query(TapIdAssociation).filter_by(
|
||||
tap_service_id=None).first()
|
||||
if not query:
|
||||
self._rebuild_taas_id_allocation_range(context)
|
||||
# try again
|
||||
query = context.session.query(TapIdAssociation).filter_by(
|
||||
tap_service_id=None).first()
|
||||
|
||||
if query:
|
||||
query.update({"tap_service_id": tap_service_id})
|
||||
return query
|
||||
# not found
|
||||
raise taas.TapServiceLimitReached()
|
||||
|
||||
def create_tap_id_association(self, context, tap_service_id):
|
||||
LOG.debug("create_tap_id_association() called")
|
||||
# create the TapIdAssociation object
|
||||
with context.session.begin(subtransactions=True):
|
||||
tap_id_association_db = TapIdAssociation(
|
||||
tap_service_id=tap_service_id
|
||||
)
|
||||
context.session.add(tap_id_association_db)
|
||||
# allocate Taas id.
|
||||
# if conflict happened, it will raise db.DBDuplicateEntry.
|
||||
# this will be retry request again in neutron controller framework.
|
||||
# so we just make sure TapIdAssociation field taas_id is unique
|
||||
tap_id_association_db = self._allocate_taas_id_with_tap_service_id(
|
||||
context, tap_service_id)
|
||||
|
||||
return self._make_tap_id_association_dict(tap_id_association_db)
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
from neutron.common import rpc as n_rpc
|
||||
from neutron_lib import exceptions as n_exc
|
||||
from neutron_taas.common import topics
|
||||
from neutron_taas.extensions import taas as taas_ex
|
||||
from neutron_taas.services.taas import service_drivers
|
||||
from neutron_taas.services.taas.service_drivers import taas_agent_api
|
||||
|
||||
@ -52,8 +51,7 @@ class TaasRpcDriver(service_drivers.TaasBaseDriver):
|
||||
tf['tap_service_id'])
|
||||
taas_id = (self.service_plugin.get_tap_id_association(
|
||||
context,
|
||||
tap_service_id=ts['id'])['taas_id'] +
|
||||
cfg.CONF.taas.vlan_range_start)
|
||||
tap_service_id=ts['id']))['taas_id']
|
||||
return taas_id
|
||||
|
||||
def create_tap_service_precommit(self, context):
|
||||
@ -71,15 +69,11 @@ class TaasRpcDriver(service_drivers.TaasBaseDriver):
|
||||
# Get taas id associated with the Tap Service
|
||||
ts = context.tap_service
|
||||
tap_id_association = context.tap_id_association
|
||||
taas_vlan_id = (tap_id_association['taas_id'] +
|
||||
cfg.CONF.taas.vlan_range_start)
|
||||
taas_vlan_id = tap_id_association['taas_id']
|
||||
port = self.service_plugin._get_port_details(context._plugin_context,
|
||||
ts['port_id'])
|
||||
host = port['binding:host_id']
|
||||
|
||||
if taas_vlan_id > cfg.CONF.taas.vlan_range_end:
|
||||
raise taas_ex.TapServiceLimitReached()
|
||||
|
||||
rpc_msg = {'tap_service': ts,
|
||||
'taas_id': taas_vlan_id,
|
||||
'port': port}
|
||||
@ -99,8 +93,8 @@ class TaasRpcDriver(service_drivers.TaasBaseDriver):
|
||||
"""
|
||||
ts = context.tap_service
|
||||
tap_id_association = context.tap_id_association
|
||||
taas_vlan_id = (tap_id_association['taas_id'] +
|
||||
cfg.CONF.taas.vlan_range_start)
|
||||
taas_vlan_id = tap_id_association['taas_id']
|
||||
|
||||
try:
|
||||
port = self.service_plugin._get_port_details(
|
||||
context._plugin_context,
|
||||
|
@ -20,6 +20,7 @@ import testtools
|
||||
|
||||
from neutron_lib import context
|
||||
from neutron_lib.utils import net as n_utils
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
import neutron.common.rpc as n_rpc
|
||||
@ -130,6 +131,33 @@ class TestTaasPlugin(testlib_api.SqlTestCase):
|
||||
with self.tap_service():
|
||||
pass
|
||||
|
||||
def test_verify_taas_id_reused(self):
|
||||
# make small range id
|
||||
cfg.CONF.set_override("vlan_range_start", 1, group="taas")
|
||||
cfg.CONF.set_override("vlan_range_end", 3, group="taas")
|
||||
with self.tap_service() as ts_1, self.tap_service() as ts_2, \
|
||||
self.tap_service() as ts_3, self.tap_service() as ts_4:
|
||||
ts_id_1 = ts_1['id']
|
||||
ts_id_2 = ts_2['id']
|
||||
ts_id_3 = ts_3['id']
|
||||
tap_id_assoc_1 = self._plugin.create_tap_id_association(
|
||||
self._context, ts_id_1)
|
||||
tap_id_assoc_2 = self._plugin.create_tap_id_association(
|
||||
self._context, ts_id_2)
|
||||
self.assertEqual(set([1, 2]), set([tap_id_assoc_1['taas_id'],
|
||||
tap_id_assoc_2['taas_id']]))
|
||||
with testtools.ExpectedException(taas_ext.TapServiceLimitReached):
|
||||
self._plugin.create_tap_id_association(
|
||||
self._context,
|
||||
ts_4['id']
|
||||
)
|
||||
# free an tap_id and verify could reallocate same taas id
|
||||
self._plugin.delete_tap_service(self._context, ts_id_1)
|
||||
tap_id_assoc_3 = self._plugin.create_tap_id_association(
|
||||
self._context, ts_id_3)
|
||||
self.assertEqual(set([1, 2]), set([tap_id_assoc_3['taas_id'],
|
||||
tap_id_assoc_2['taas_id']]))
|
||||
|
||||
def test_create_tap_service_wrong_tenant_id(self):
|
||||
self._port_details['tenant_id'] = 'other-tenant'
|
||||
with testtools.ExpectedException(taas_ext.PortDoesNotBelongToTenant), \
|
||||
|
Loading…
x
Reference in New Issue
Block a user