Merge "Fix segment allocation tables in Cisco N1kv plugin"

This commit is contained in:
Jenkins 2014-03-28 20:37:46 +00:00 committed by Gerrit Code Review
commit 7c92626dd8
8 changed files with 322 additions and 376 deletions

View File

@ -0,0 +1,83 @@
# Copyright 2014 OpenStack Foundation
#
# 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.
#
"""n1kv segment allocs for cisco n1kv plugin
Revision ID: 5ac1c354a051
Revises: 538732fa21e1
Create Date: 2014-03-05 17:36:52.952608
"""
# revision identifiers, used by Alembic.
revision = '5ac1c354a051'
down_revision = '538732fa21e1'
# Change to ['*'] if this migration applies to all plugins
migration_for_plugins = [
'neutron.plugins.cisco.network_plugin.PluginV2'
]
from alembic import op
import sqlalchemy as sa
from neutron.db import migration
def upgrade(active_plugins=None, options=None):
if not migration.should_run(active_plugins, migration_for_plugins):
return
op.add_column(
'cisco_n1kv_vlan_allocations',
sa.Column('network_profile_id',
sa.String(length=36),
nullable=False)
)
op.create_foreign_key(
'cisco_n1kv_vlan_allocations_ibfk_1',
source='cisco_n1kv_vlan_allocations',
referent='cisco_network_profiles',
local_cols=['network_profile_id'], remote_cols=['id'],
ondelete='CASCADE'
)
op.add_column(
'cisco_n1kv_vxlan_allocations',
sa.Column('network_profile_id',
sa.String(length=36),
nullable=False)
)
op.create_foreign_key(
'cisco_n1kv_vxlan_allocations_ibfk_1',
source='cisco_n1kv_vxlan_allocations',
referent='cisco_network_profiles',
local_cols=['network_profile_id'], remote_cols=['id'],
ondelete='CASCADE'
)
def downgrade(active_plugins=None, options=None):
if not migration.should_run(active_plugins, migration_for_plugins):
return
op.drop_constraint('cisco_n1kv_vxlan_allocations_ibfk_1',
'cisco_n1kv_vxlan_allocations',
'foreignkey')
op.drop_column('cisco_n1kv_vxlan_allocations', 'network_profile_id')
op.drop_constraint('cisco_n1kv_vlan_allocations_ibfk_1',
'cisco_n1kv_vlan_allocations',
'foreignkey')
op.drop_column('cisco_n1kv_vlan_allocations', 'network_profile_id')

View File

@ -1 +1 @@
538732fa21e1
5ac1c354a051

View File

@ -180,12 +180,23 @@ class VMNetworkNotFound(exceptions.NotFound):
message = _("VM Network %(name)s could not be found.")
class VxlanIdInUse(exceptions.InUse):
class VxlanIDInUse(exceptions.InUse):
"""VXLAN ID is in use."""
message = _("Unable to create the network. "
"The VXLAN ID %(vxlan_id)s is in use.")
class VxlanIDNotFound(exceptions.NotFound):
"""VXLAN ID cannot be found."""
message = _("Vxlan ID %(vxlan_id)s not found.")
class VxlanIDOutsidePool(exceptions.NeutronException):
"""VXLAN ID cannot be allocated, as it is outside the configured pool."""
message = _("Unable to complete operation. VXLAN ID exists outside of the "
"configured network segment range.")
class VSMConnectionFailed(exceptions.ServiceUnavailable):
"""Connection to VSM failed."""
message = _("Connection to VSM failed: %(reason)s.")

View File

@ -21,7 +21,6 @@
import netaddr
import re
from six.moves import xrange
from sqlalchemy.orm import exc
from sqlalchemy.sql import and_
@ -395,69 +394,28 @@ def add_port_binding(db_session, port_id, policy_profile_id):
db_session.add(binding)
def _get_sorted_vlan_ids(vlan_ranges):
"""Return sorted allocatable VLAN IDs."""
vlan_ids = set()
for vlan_range in vlan_ranges:
vlan_ids |= set(xrange(vlan_range[0], vlan_range[1] + 1))
return sorted(vlan_ids)
def sync_vlan_allocations(db_session, network_vlan_ranges):
def sync_vlan_allocations(db_session, net_p):
"""
Synchronize vlan_allocations table with configured VLAN ranges.
Sync the network profile range with the vlan_allocations table for each
physical network.
:param db_session: database session
:param network_vlan_ranges: dictionary of network vlan ranges with the
physical network name as key.
:param net_p: network profile dictionary
"""
with db_session.begin():
# process vlan ranges for each physical network separately
for physical_network, vlan_ranges in network_vlan_ranges.items():
# determine current configured allocatable vlans for this
# physical network
vlan_ids = _get_sorted_vlan_ids(vlan_ranges)
# add missing allocatable vlans to table
for vlan_id in vlan_ids:
try:
alloc = get_vlan_allocation(db_session,
physical_network,
vlan_id)
except c_exc.VlanIDNotFound:
alloc = n1kv_models_v2.N1kvVlanAllocation(
physical_network=physical_network, vlan_id=vlan_id)
db_session.add(alloc)
def delete_vlan_allocations(db_session, network_vlan_ranges):
"""
Delete vlan_allocations for deleted network profile range.
:param db_session: database session
:param network_vlan_ranges: dictionary of network vlan ranges with the
physical network name as key.
"""
with db_session.begin():
# process vlan ranges for each physical network separately
for physical_network, vlan_ranges in network_vlan_ranges.items():
# Determine the set of vlan ids which need to be deleted.
vlan_ids = _get_sorted_vlan_ids(vlan_ranges)
allocs = (db_session.query(n1kv_models_v2.N1kvVlanAllocation).
filter_by(physical_network=physical_network).
filter_by(allocated=False))
for alloc in allocs:
if alloc.vlan_id in vlan_ids:
LOG.debug(_("Removing vlan %(vlan)s on physical "
"network %(network)s from pool"),
{"vlan": alloc.vlan_id,
"network": physical_network})
db_session.delete(alloc)
with db_session.begin(subtransactions=True):
seg_min, seg_max = get_segment_range(net_p)
for vlan_id in range(seg_min, seg_max + 1):
try:
get_vlan_allocation(db_session,
net_p['physical_network'],
vlan_id)
except c_exc.VlanIDNotFound:
alloc = n1kv_models_v2.N1kvVlanAllocation(
physical_network=net_p['physical_network'],
vlan_id=vlan_id,
network_profile_id=net_p['id'])
db_session.add(alloc)
def get_vlan_allocation(db_session, physical_network, vlan_id):
@ -578,25 +536,19 @@ def reserve_specific_vlan(db_session, physical_network, vlan_id):
LOG.debug(_("Reserving specific vlan %(vlan)s on physical "
"network %(network)s from pool"),
{"vlan": vlan_id, "network": physical_network})
except exc.NoResultFound:
LOG.debug(_("Reserving specific vlan %(vlan)s on physical "
"network %(network)s outside pool"),
{"vlan": vlan_id, "network": physical_network})
alloc = n1kv_models_v2.N1kvVlanAllocation(
physical_network=physical_network, vlan_id=vlan_id)
alloc.allocated = True
db_session.add(alloc)
alloc.allocated = True
except exc.NoResultFound:
raise c_exc.VlanIDOutsidePool
def release_vlan(db_session, physical_network, vlan_id, network_vlan_ranges):
def release_vlan(db_session, physical_network, vlan_id):
"""
Release a given VLAN ID.
:param db_session: database session
:param physical_network: string representing the name of physical network
:param vlan_id: integer value of the segmentation ID to be released
:param network_vlan_ranges: dictionary of network vlan ranges with the
physical network name as key.
"""
with db_session.begin(subtransactions=True):
try:
@ -605,70 +557,34 @@ def release_vlan(db_session, physical_network, vlan_id, network_vlan_ranges):
vlan_id=vlan_id).
one())
alloc.allocated = False
for vlan_range in network_vlan_ranges.get(physical_network, []):
if vlan_range[0] <= vlan_id <= vlan_range[1]:
msg = _("Releasing vlan %(vlan)s on physical "
"network %(network)s to pool")
break
else:
db_session.delete(alloc)
msg = _("Releasing vlan %(vlan)s on physical "
"network %(network)s outside pool")
LOG.debug(msg, {"vlan": vlan_id, "network": physical_network})
except exc.NoResultFound:
LOG.warning(_("vlan_id %(vlan)s on physical network %(network)s "
"not found"),
{"vlan": vlan_id, "network": physical_network})
def _get_sorted_vxlan_ids(vxlan_id_ranges):
"""Return sorted VXLAN IDs."""
vxlan_ids = set()
for vxlan_min, vxlan_max in vxlan_id_ranges:
if vxlan_max + 1 - vxlan_min > c_const.MAX_VXLAN_RANGE:
LOG.error(_("Skipping unreasonable vxlan ID range %(vxlan_min)s - "
"%(vxlan_max)s"),
{"vxlan_min": vxlan_min, "vxlan_max": vxlan_max})
else:
vxlan_ids |= set(xrange(vxlan_min, vxlan_max + 1))
return sorted(vxlan_ids)
def sync_vxlan_allocations(db_session, vxlan_id_ranges):
def sync_vxlan_allocations(db_session, net_p):
"""
Synchronize vxlan_allocations table with configured vxlan ranges.
:param db_session: database session
:param vxlan_id_ranges: list of segment range tuples
:param net_p: network profile dictionary
"""
vxlan_ids = _get_sorted_vxlan_ids(vxlan_id_ranges)
with db_session.begin():
for vxlan_id in vxlan_ids:
alloc = get_vxlan_allocation(db_session, vxlan_id)
if not alloc:
alloc = n1kv_models_v2.N1kvVxlanAllocation(vxlan_id=vxlan_id)
seg_min, seg_max = get_segment_range(net_p)
if seg_max + 1 - seg_min > c_const.MAX_VXLAN_RANGE:
msg = (_("Unreasonable vxlan ID range %(vxlan_min)s - %(vxlan_max)s"),
{"vxlan_min": seg_min, "vxlan_max": seg_max})
raise n_exc.InvalidInput(error_message=msg)
with db_session.begin(subtransactions=True):
for vxlan_id in range(seg_min, seg_max + 1):
try:
get_vxlan_allocation(db_session, vxlan_id)
except c_exc.VxlanIDNotFound:
alloc = n1kv_models_v2.N1kvVxlanAllocation(
network_profile_id=net_p['id'], vxlan_id=vxlan_id)
db_session.add(alloc)
def delete_vxlan_allocations(db_session, vxlan_id_ranges):
"""
Delete vxlan_allocations for deleted network profile range.
:param db_session: database session
:param vxlan_id_ranges: list of segment range tuples
"""
vxlan_ids = _get_sorted_vxlan_ids(vxlan_id_ranges)
with db_session.begin():
allocs = (db_session.query(n1kv_models_v2.N1kvVxlanAllocation).
filter_by(allocated=False))
for alloc in allocs:
if alloc.vxlan_id in vxlan_ids:
LOG.debug(_("Removing vxlan %s from pool"),
alloc.vxlan_id)
db_session.delete(alloc)
def get_vxlan_allocation(db_session, vxlan_id):
"""
Retrieve VXLAN allocation for the given VXLAN ID.
@ -677,8 +593,11 @@ def get_vxlan_allocation(db_session, vxlan_id):
:param vxlan_id: integer value representing the segmentation ID
:returns: allocation object
"""
return (db_session.query(n1kv_models_v2.N1kvVxlanAllocation).
filter_by(vxlan_id=vxlan_id).first())
try:
return (db_session.query(n1kv_models_v2.N1kvVxlanAllocation).
filter_by(vxlan_id=vxlan_id).one())
except exc.NoResultFound:
raise c_exc.VxlanIDNotFound(vxlan_id=vxlan_id)
def reserve_specific_vxlan(db_session, vxlan_id):
@ -694,22 +613,20 @@ def reserve_specific_vxlan(db_session, vxlan_id):
filter_by(vxlan_id=vxlan_id).
one())
if alloc.allocated:
raise c_exc.VxlanIdInUse(vxlan_id=vxlan_id)
raise c_exc.VxlanIDInUse(vxlan_id=vxlan_id)
LOG.debug(_("Reserving specific vxlan %s from pool"), vxlan_id)
except exc.NoResultFound:
LOG.debug(_("Reserving specific vxlan %s outside pool"), vxlan_id)
alloc = n1kv_models_v2.N1kvVxlanAllocation(vxlan_id=vxlan_id)
alloc.allocated = True
db_session.add(alloc)
alloc.allocated = True
except exc.NoResultFound:
raise c_exc.VxlanIDOutsidePool
def release_vxlan(db_session, vxlan_id, vxlan_id_ranges):
def release_vxlan(db_session, vxlan_id):
"""
Release a given VXLAN ID.
:param db_session: database session
:param vxlan_id: integer value representing the segmentation ID
:param vxlan_id_ranges: list of the segment range tuples.
"""
with db_session.begin(subtransactions=True):
try:
@ -717,14 +634,6 @@ def release_vxlan(db_session, vxlan_id, vxlan_id_ranges):
filter_by(vxlan_id=vxlan_id).
one())
alloc.allocated = False
for vxlan_id_range in vxlan_id_ranges:
if vxlan_id_range[0] <= vxlan_id <= vxlan_id_range[1]:
msg = _("Releasing vxlan %s to pool")
break
else:
db_session.delete(alloc)
msg = _("Releasing vxlan %s outside pool")
LOG.debug(msg, vxlan_id)
except exc.NoResultFound:
LOG.warning(_("vxlan_id %s not found"), vxlan_id)
@ -1087,15 +996,20 @@ class NetworkProfile_db_mixin(object):
self._replace_fake_tenant_id_with_real(context)
p = network_profile["network_profile"]
self._validate_network_profile_args(context, p)
net_profile = create_network_profile(context.session, p)
create_profile_binding(context.session,
context.tenant_id,
net_profile.id,
c_const.NETWORK)
if p.get("add_tenant"):
self.add_network_profile_tenant(context.session,
net_profile.id,
p["add_tenant"])
with context.session.begin(subtransactions=True):
net_profile = create_network_profile(context.session, p)
if net_profile.segment_type == c_const.NETWORK_TYPE_VLAN:
sync_vlan_allocations(context.session, net_profile)
elif net_profile.segment_type == c_const.NETWORK_TYPE_OVERLAY:
sync_vxlan_allocations(context.session, net_profile)
create_profile_binding(context.session,
context.tenant_id,
net_profile.id,
c_const.NETWORK)
if p.get("add_tenant"):
self.add_network_profile_tenant(context.session,
net_profile.id,
p["add_tenant"])
return self._make_network_profile_dict(net_profile)
def delete_network_profile(self, context, id):

View File

@ -39,6 +39,10 @@ class N1kvVlanAllocation(model_base.BASEV2):
vlan_id = sa.Column(sa.Integer, nullable=False, primary_key=True,
autoincrement=False)
allocated = sa.Column(sa.Boolean, nullable=False, default=False)
network_profile_id = sa.Column(sa.String(36),
sa.ForeignKey('cisco_network_profiles.id',
ondelete="CASCADE"),
nullable=False)
class N1kvVxlanAllocation(model_base.BASEV2):
@ -49,6 +53,10 @@ class N1kvVxlanAllocation(model_base.BASEV2):
vxlan_id = sa.Column(sa.Integer, nullable=False, primary_key=True,
autoincrement=False)
allocated = sa.Column(sa.Boolean, nullable=False, default=False)
network_profile_id = sa.Column(sa.String(36),
sa.ForeignKey('cisco_network_profiles.id',
ondelete="CASCADE"),
nullable=False)
class N1kvPortBinding(model_base.BASEV2):

View File

@ -117,7 +117,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
portbindings.CAP_PORT_FILTER:
'security-group' in self.supported_extension_aliases}}
c_cred.Store.initialize()
self._initialize_network_ranges()
self._setup_vsm()
self._setup_rpc()
@ -214,28 +213,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
cisco_exceptions.VSMConnectionFailed):
LOG.warning(_('No policy profile updated from VSM'))
def _initialize_network_ranges(self):
self.network_vlan_ranges = {}
self.vxlan_id_ranges = []
network_profiles = n1kv_db_v2._get_network_profiles()
for network_profile in network_profiles:
seg_min, seg_max = self._get_segment_range(
network_profile['segment_range'])
if network_profile['segment_type'] == c_const.NETWORK_TYPE_VLAN:
self._add_network_vlan_range(network_profile[
'physical_network'], int(seg_min), int(seg_max))
elif network_profile['segment_type'] == (c_const.
NETWORK_TYPE_OVERLAY):
self.vxlan_id_ranges.append((int(seg_min), int(seg_max)))
def _add_network_vlan_range(self, physical_network, vlan_min, vlan_max):
self._add_network(physical_network)
self.network_vlan_ranges[physical_network].append((vlan_min, vlan_max))
def _add_network(self, physical_network):
if physical_network not in self.network_vlan_ranges:
self.network_vlan_ranges[physical_network] = []
def _extend_network_dict_provider(self, context, network):
"""Add extended network parameters."""
binding = n1kv_db_v2.get_network_binding(context.session,
@ -301,12 +278,15 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
if network_type == c_const.NETWORK_TYPE_VLAN:
if physical_network_set:
if physical_network not in self.network_vlan_ranges:
msg = (_("Unknown provider:physical_network %s") %
network_profiles = n1kv_db_v2.get_network_profiles()
for network_profile in network_profiles:
if physical_network == network_profile[
'physical_network']:
break
else:
msg = (_("Unknown provider:physical_network %s"),
physical_network)
raise n_exc.InvalidInput(error_message=msg)
elif 'default' in self.network_vlan_ranges:
physical_network = 'default'
else:
msg = _("provider:physical_network required")
raise n_exc.InvalidInput(error_message=msg)
@ -1113,23 +1093,16 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
msg = _("Cannot delete network '%s' that is a member of a "
"multi-segment network") % network['name']
raise n_exc.InvalidInput(error_message=msg)
if self.agent_vsm:
try:
self._send_delete_network_request(context, network)
except(cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed):
LOG.debug(_('Delete failed in VSM'))
super(N1kvNeutronPluginV2, self).delete_network(context, id)
if binding.network_type == c_const.NETWORK_TYPE_OVERLAY:
n1kv_db_v2.release_vxlan(session, binding.segmentation_id,
self.vxlan_id_ranges)
n1kv_db_v2.release_vxlan(session, binding.segmentation_id)
elif binding.network_type == c_const.NETWORK_TYPE_VLAN:
n1kv_db_v2.release_vlan(session, binding.physical_network,
binding.segmentation_id,
self.network_vlan_ranges)
# the network_binding record is deleted via cascade from
# the network record, so explicit removal is not necessary
LOG.debug(_("Deleted network: %s"), id)
binding.segmentation_id)
# the network_binding record is deleted via cascade from
# the network record, so explicit removal is not necessary
self._send_delete_network_request(context, network)
super(N1kvNeutronPluginV2, self).delete_network(context, id)
LOG.debug(_("Deleted network: %s"), id)
def get_network(self, context, id, fields=None):
"""
@ -1390,40 +1363,27 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
:returns: network profile object
"""
self._replace_fake_tenant_id_with_real(context)
_network_profile = super(
N1kvNeutronPluginV2, self).create_network_profile(context,
network_profile)
if _network_profile['segment_type'] in [c_const.NETWORK_TYPE_VLAN,
c_const.NETWORK_TYPE_OVERLAY]:
seg_min, seg_max = self._get_segment_range(
_network_profile['segment_range'])
if _network_profile['segment_type'] == c_const.NETWORK_TYPE_VLAN:
self._add_network_vlan_range(
_network_profile['physical_network'], int(seg_min),
int(seg_max))
n1kv_db_v2.sync_vlan_allocations(context.session,
self.network_vlan_ranges)
else:
self.vxlan_id_ranges = [(int(seg_min), int(seg_max))]
n1kv_db_v2.sync_vxlan_allocations(context.session,
self.vxlan_id_ranges)
try:
self._send_create_logical_network_request(_network_profile,
context.tenant_id)
except(cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed):
super(N1kvNeutronPluginV2, self).delete_network_profile(
context, _network_profile['id'])
try:
self._send_create_network_profile_request(context,
_network_profile)
except(cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed):
self._send_delete_logical_network_request(_network_profile)
super(N1kvNeutronPluginV2, self).delete_network_profile(
context, _network_profile['id'])
else:
return _network_profile
with context.session.begin(subtransactions=True):
net_p = super(N1kvNeutronPluginV2,
self).create_network_profile(context,
network_profile)
try:
self._send_create_logical_network_request(net_p,
context.tenant_id)
except(cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed):
n1kv_db_v2.delete_profile_binding(context.session,
context.tenant_id,
net_p['id'])
try:
self._send_create_network_profile_request(context, net_p)
except(cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed):
n1kv_db_v2.delete_profile_binding(context.session,
context.tenant_id,
net_p['id'])
self._send_delete_logical_network_request(net_p)
return net_p
def delete_network_profile(self, context, id):
"""
@ -1433,22 +1393,11 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
:param id: UUID of the network profile to delete
:returns: deleted network profile object
"""
_network_profile = super(
N1kvNeutronPluginV2, self).delete_network_profile(context, id)
seg_min, seg_max = self._get_segment_range(
_network_profile['segment_range'])
if _network_profile['segment_type'] == c_const.NETWORK_TYPE_VLAN:
self._add_network_vlan_range(_network_profile['physical_network'],
int(seg_min),
int(seg_max))
n1kv_db_v2.delete_vlan_allocations(context.session,
self.network_vlan_ranges)
elif _network_profile['segment_type'] == c_const.NETWORK_TYPE_OVERLAY:
self.delete_vxlan_ranges = []
self.delete_vxlan_ranges.append((int(seg_min), int(seg_max)))
n1kv_db_v2.delete_vxlan_allocations(context.session,
self.delete_vxlan_ranges)
self._send_delete_network_profile_request(_network_profile)
with context.session.begin(subtransactions=True):
net_p = super(N1kvNeutronPluginV2,
self).delete_network_profile(context, id)
self._send_delete_network_profile_request(net_p)
self._send_delete_logical_network_request(net_p)
def update_network_profile(self, context, net_profile_id, network_profile):
"""

View File

@ -38,13 +38,8 @@ PHYS_NET = 'physnet1'
PHYS_NET_2 = 'physnet2'
VLAN_MIN = 10
VLAN_MAX = 19
VLAN_RANGES = {PHYS_NET: [(VLAN_MIN, VLAN_MAX)]}
UPDATED_VLAN_RANGES = {PHYS_NET: [(VLAN_MIN + 20, VLAN_MAX + 20)],
PHYS_NET_2: [(VLAN_MIN + 40, VLAN_MAX + 40)]}
VXLAN_MIN = 5000
VXLAN_MAX = 5009
VXLAN_RANGES = [(VXLAN_MIN, VXLAN_MAX)]
UPDATED_VXLAN_RANGES = [(VXLAN_MIN + 20, VXLAN_MAX + 20)]
SEGMENT_RANGE = '200-220'
SEGMENT_RANGE_MIN_OVERLAP = '210-230'
SEGMENT_RANGE_MAX_OVERLAP = '190-209'
@ -103,7 +98,8 @@ class VlanAllocationsTest(base.BaseTestCase):
super(VlanAllocationsTest, self).setUp()
db.configure_db()
self.session = db.get_session()
n1kv_db_v2.sync_vlan_allocations(self.session, VLAN_RANGES)
self.net_p = _create_test_network_profile_if_not_there(self.session)
n1kv_db_v2.sync_vlan_allocations(self.session, self.net_p)
self.addCleanup(db.clear_db)
def test_sync_vlan_allocations_outside_segment_range(self):
@ -117,28 +113,6 @@ class VlanAllocationsTest(base.BaseTestCase):
self.session,
PHYS_NET,
VLAN_MAX + 1)
n1kv_db_v2.sync_vlan_allocations(self.session, UPDATED_VLAN_RANGES)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET,
VLAN_MIN + 20 - 1)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET,
VLAN_MAX + 20 + 1)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET_2,
VLAN_MIN + 40 - 1)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET_2,
VLAN_MAX + 40 + 1)
n1kv_db_v2.sync_vlan_allocations(self.session, VLAN_RANGES)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
@ -170,45 +144,12 @@ class VlanAllocationsTest(base.BaseTestCase):
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
VLAN_MAX).allocated)
n1kv_db_v2.sync_vlan_allocations(self.session, UPDATED_VLAN_RANGES)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
VLAN_MIN + 20).
allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
VLAN_MIN + 20 + 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
VLAN_MAX + 20 - 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session, PHYS_NET,
VLAN_MAX + 20).
allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET_2,
VLAN_MIN + 40).
allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET_2,
VLAN_MIN + 40 + 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET_2,
VLAN_MAX + 40 - 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET_2,
VLAN_MAX + 40).
allocated)
def test_vlan_pool(self):
vlan_ids = set()
p = _create_test_network_profile_if_not_there(self.session)
for x in xrange(VLAN_MIN, VLAN_MAX + 1):
(physical_network, seg_type,
vlan_id, m_ip) = n1kv_db_v2.reserve_vlan(self.session, p)
vlan_id, m_ip) = n1kv_db_v2.reserve_vlan(self.session, self.net_p)
self.assertEqual(physical_network, PHYS_NET)
self.assertThat(vlan_id, matchers.GreaterThan(VLAN_MIN - 1))
self.assertThat(vlan_id, matchers.LessThan(VLAN_MAX + 1))
@ -217,20 +158,18 @@ class VlanAllocationsTest(base.BaseTestCase):
self.assertRaises(n_exc.NoNetworkAvailable,
n1kv_db_v2.reserve_vlan,
self.session,
p)
self.net_p)
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_ids.pop(),
VLAN_RANGES)
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_ids.pop())
physical_network, seg_type, vlan_id, m_ip = (n1kv_db_v2.reserve_vlan(
self.session, p))
self.session, self.net_p))
self.assertEqual(physical_network, PHYS_NET)
self.assertThat(vlan_id, matchers.GreaterThan(VLAN_MIN - 1))
self.assertThat(vlan_id, matchers.LessThan(VLAN_MAX + 1))
vlan_ids.add(vlan_id)
for vlan_id in vlan_ids:
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_id,
VLAN_RANGES)
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_id)
def test_specific_vlan_inside_pool(self):
vlan_id = VLAN_MIN + 5
@ -248,7 +187,7 @@ class VlanAllocationsTest(base.BaseTestCase):
PHYS_NET,
vlan_id)
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_id, VLAN_RANGES)
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_id)
self.assertFalse(n1kv_db_v2.get_vlan_allocation(self.session,
PHYS_NET,
vlan_id).allocated)
@ -260,23 +199,12 @@ class VlanAllocationsTest(base.BaseTestCase):
self.session,
PHYS_NET,
vlan_id)
n1kv_db_v2.reserve_specific_vlan(self.session, PHYS_NET, vlan_id)
self.assertTrue(n1kv_db_v2.get_vlan_allocation(self.session, PHYS_NET,
vlan_id).allocated)
self.assertRaises(n_exc.VlanIdInUse,
self.assertRaises(c_exc.VlanIDOutsidePool,
n1kv_db_v2.reserve_specific_vlan,
self.session,
PHYS_NET,
vlan_id)
n1kv_db_v2.release_vlan(self.session, PHYS_NET, vlan_id, VLAN_RANGES)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
self.session,
PHYS_NET,
vlan_id)
class VxlanAllocationsTest(base.BaseTestCase,
n1kv_db_v2.NetworkProfile_db_mixin):
@ -285,19 +213,20 @@ class VxlanAllocationsTest(base.BaseTestCase,
super(VxlanAllocationsTest, self).setUp()
db.configure_db()
self.session = db.get_session()
n1kv_db_v2.sync_vxlan_allocations(self.session, VXLAN_RANGES)
self.net_p = _create_test_network_profile_if_not_there(
self.session, TEST_NETWORK_PROFILE_VXLAN)
n1kv_db_v2.sync_vxlan_allocations(self.session, self.net_p)
self.addCleanup(db.clear_db)
def test_sync_vxlan_allocations_outside_segment_range(self):
self.assertIsNone(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MIN - 1))
self.assertIsNone(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MAX + 1))
n1kv_db_v2.sync_vxlan_allocations(self.session, UPDATED_VXLAN_RANGES)
self.assertIsNone(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MIN + 20 - 1))
self.assertIsNone(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MAX + 20 + 1))
self.assertRaises(c_exc.VxlanIDNotFound,
n1kv_db_v2.get_vxlan_allocation,
self.session,
VXLAN_MIN - 1)
self.assertRaises(c_exc.VxlanIDNotFound,
n1kv_db_v2.get_vxlan_allocation,
self.session,
VXLAN_MAX + 1)
def test_sync_vxlan_allocations_unallocated_vxlans(self):
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
@ -310,26 +239,11 @@ class VxlanAllocationsTest(base.BaseTestCase,
allocated)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MAX).allocated)
n1kv_db_v2.sync_vxlan_allocations(self.session, UPDATED_VXLAN_RANGES)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MIN + 20).
allocated)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MIN + 20 + 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MAX + 20 - 1).
allocated)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
VXLAN_MAX + 20).
allocated)
def test_vxlan_pool(self):
vxlan_ids = set()
profile = n1kv_db_v2.create_network_profile(self.session,
TEST_NETWORK_PROFILE_VXLAN)
for x in xrange(VXLAN_MIN, VXLAN_MAX + 1):
vxlan = n1kv_db_v2.reserve_vxlan(self.session, profile)
vxlan = n1kv_db_v2.reserve_vxlan(self.session, self.net_p)
vxlan_id = vxlan[2]
self.assertThat(vxlan_id, matchers.GreaterThan(VXLAN_MIN - 1))
self.assertThat(vxlan_id, matchers.LessThan(VXLAN_MAX + 1))
@ -338,17 +252,17 @@ class VxlanAllocationsTest(base.BaseTestCase,
self.assertRaises(n_exc.NoNetworkAvailable,
n1kv_db_v2.reserve_vxlan,
self.session,
profile)
n1kv_db_v2.release_vxlan(self.session, vxlan_ids.pop(), VXLAN_RANGES)
vxlan = n1kv_db_v2.reserve_vxlan(self.session, profile)
self.net_p)
n1kv_db_v2.release_vxlan(self.session, vxlan_ids.pop())
vxlan = n1kv_db_v2.reserve_vxlan(self.session, self.net_p)
vxlan_id = vxlan[2]
self.assertThat(vxlan_id, matchers.GreaterThan(VXLAN_MIN - 1))
self.assertThat(vxlan_id, matchers.LessThan(VXLAN_MAX + 1))
vxlan_ids.add(vxlan_id)
for vxlan_id in vxlan_ids:
n1kv_db_v2.release_vxlan(self.session, vxlan_id, VXLAN_RANGES)
n1kv_db_v2.delete_network_profile(self.session, profile.id)
n1kv_db_v2.release_vxlan(self.session, vxlan_id)
n1kv_db_v2.delete_network_profile(self.session, self.net_p.id)
def test_specific_vxlan_inside_pool(self):
vxlan_id = VXLAN_MIN + 5
@ -358,32 +272,26 @@ class VxlanAllocationsTest(base.BaseTestCase,
self.assertTrue(n1kv_db_v2.get_vxlan_allocation(self.session,
vxlan_id).allocated)
self.assertRaises(c_exc.VxlanIdInUse,
self.assertRaises(c_exc.VxlanIDInUse,
n1kv_db_v2.reserve_specific_vxlan,
self.session,
vxlan_id)
n1kv_db_v2.release_vxlan(self.session, vxlan_id, VXLAN_RANGES)
n1kv_db_v2.release_vxlan(self.session, vxlan_id)
self.assertFalse(n1kv_db_v2.get_vxlan_allocation(self.session,
vxlan_id).allocated)
def test_specific_vxlan_outside_pool(self):
vxlan_id = VXLAN_MAX + 5
self.assertIsNone(n1kv_db_v2.get_vxlan_allocation(self.session,
vxlan_id))
n1kv_db_v2.reserve_specific_vxlan(self.session, vxlan_id)
self.assertTrue(n1kv_db_v2.get_vxlan_allocation(self.session,
vxlan_id).allocated)
self.assertRaises(c_exc.VxlanIdInUse,
self.assertRaises(c_exc.VxlanIDNotFound,
n1kv_db_v2.get_vxlan_allocation,
self.session,
vxlan_id)
self.assertRaises(c_exc.VxlanIDOutsidePool,
n1kv_db_v2.reserve_specific_vxlan,
self.session,
vxlan_id)
n1kv_db_v2.release_vxlan(self.session, vxlan_id, VXLAN_RANGES)
self.assertIsNone(n1kv_db_v2.get_vxlan_allocation(self.session,
vxlan_id))
class NetworkBindingsTest(test_plugin.NeutronDbPluginV2TestCase):
@ -943,8 +851,7 @@ class ProfileBindingTests(base.BaseTestCase,
test_profile_id,
test_profile_type)
network_profile = {"network_profile": TEST_NETWORK_PROFILE}
test_network_profile = self.create_network_profile(ctx,
network_profile)
self.create_network_profile(ctx, network_profile)
binding = n1kv_db_v2.get_profile_binding(self.session,
ctx.tenant_id,
test_profile_id)
@ -954,5 +861,3 @@ class ProfileBindingTests(base.BaseTestCase,
test_profile_id))
self.assertNotEqual(binding.tenant_id,
cisco_constants.TENANT_ID_NOT_SET)
n1kv_db_v2.delete_network_profile(self.session,
test_network_profile['id'])

View File

@ -24,6 +24,7 @@ from neutron.api.v2 import attributes
from neutron import context
import neutron.db.api as db
from neutron.extensions import portbindings
from neutron.plugins.cisco.common import cisco_exceptions as c_exc
from neutron.plugins.cisco.db import n1kv_db_v2
from neutron.plugins.cisco.db import network_db_v2 as cdb
from neutron.plugins.cisco import extensions
@ -36,6 +37,11 @@ from neutron.tests.unit import test_api_v2
from neutron.tests.unit import test_db_plugin as test_plugin
PHYS_NET = 'some-phys-net'
VLAN_MIN = 100
VLAN_MAX = 110
class FakeResponse(object):
"""
@ -105,23 +111,27 @@ class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
'name': name}
return n1kv_db_v2.create_policy_profile(profile)
def _make_test_profile(self, name='default_network_profile'):
def _make_test_profile(self,
name='default_network_profile',
segment_range='386-400'):
"""
Create a profile record for testing purposes.
:param name: string representing the name of the network profile to
create. Default argument value chosen to correspond to the
default name specified in config.py file.
:param segment_range: string representing the segment range for network
profile.
"""
db_session = db.get_session()
profile = {'name': name,
'segment_type': 'vlan',
'physical_network': 'phsy1',
'segment_range': '3968-4047'}
self.network_vlan_ranges = {profile[
'physical_network']: [(3968, 4047)]}
n1kv_db_v2.sync_vlan_allocations(db_session, self.network_vlan_ranges)
return n1kv_db_v2.create_network_profile(db_session, profile)
'physical_network': PHYS_NET,
'tenant_id': self.tenant_id,
'segment_range': segment_range}
net_p = n1kv_db_v2.create_network_profile(db_session, profile)
n1kv_db_v2.sync_vlan_allocations(db_session, net_p)
return net_p
def setUp(self):
"""
@ -244,8 +254,8 @@ class TestN1kvNetworkProfiles(N1kvPluginTestCase):
'segment_type': segment_type,
'tenant_id': self.tenant_id}}
if segment_type == 'vlan':
netp['network_profile']['segment_range'] = '100-180'
netp['network_profile']['physical_network'] = 'phys1'
netp['network_profile']['segment_range'] = '100-110'
netp['network_profile']['physical_network'] = PHYS_NET
elif segment_type == 'overlay':
netp['network_profile']['segment_range'] = '10000-10010'
netp['network_profile']['sub_type'] = 'enhanced' or 'native_vxlan'
@ -253,15 +263,40 @@ class TestN1kvNetworkProfiles(N1kvPluginTestCase):
"224.1.1.10")
return netp
def test_create_network_profile_plugin(self):
def test_create_network_profile_vlan(self):
data = self._prepare_net_profile_data('vlan')
net_p_req = self.new_create_request('network_profiles', data)
res = net_p_req.get_response(self.ext_api)
self.assertEqual(res.status_int, 201)
def test_create_network_profile_overlay(self):
data = self._prepare_net_profile_data('overlay')
net_p_req = self.new_create_request('network_profiles', data)
res = net_p_req.get_response(self.ext_api)
self.assertEqual(res.status_int, 201)
def test_create_network_profile_overlay_unreasonable_seg_range(self):
data = self._prepare_net_profile_data('overlay')
data['network_profile']['segment_range'] = '10000-100000000001'
net_p_req = self.new_create_request('network_profiles', data)
res = net_p_req.get_response(self.ext_api)
self.assertEqual(res.status_int, 400)
def test_update_network_profile_plugin(self):
net_p_dict = self._prepare_net_profile_data('overlay')
net_p_req = self.new_create_request('network_profiles', net_p_dict)
net_p = self.deserialize(self.fmt,
net_p_req.get_response(self.ext_api))
data = {'network_profile': {'name': 'netp2'}}
update_req = self.new_update_request('network_profiles',
data,
net_p['network_profile']['id'])
update_res = update_req.get_response(self.ext_api)
self.assertEqual(update_res.status_int, 200)
def test_update_network_profile_physical_network_fail(self):
net_p = self._make_test_profile(name='netp1')
data = {'network_profile': {'physical_network': 'some-phys-net'}}
data = {'network_profile': {'physical_network': PHYS_NET}}
net_p_req = self.new_update_request('network_profiles',
data,
net_p['id'])
@ -343,6 +378,47 @@ class TestN1kvNetworkProfiles(N1kvPluginTestCase):
res = net_p_req.get_response(self.ext_api)
self.assertEqual(res.status_int, 201)
def test_create_network_profile_populate_vlan_segment_pool(self):
db_session = db.get_session()
net_p_dict = self._prepare_net_profile_data('vlan')
net_p_req = self.new_create_request('network_profiles', net_p_dict)
self.deserialize(self.fmt,
net_p_req.get_response(self.ext_api))
for vlan in range(VLAN_MIN, VLAN_MAX + 1):
self.assertIsNotNone(n1kv_db_v2.get_vlan_allocation(db_session,
PHYS_NET,
vlan))
self.assertFalse(n1kv_db_v2.get_vlan_allocation(db_session,
PHYS_NET,
vlan).allocated)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
db_session,
PHYS_NET,
VLAN_MIN - 1)
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
db_session,
PHYS_NET,
VLAN_MAX + 1)
def test_delete_network_profile_deallocate_vlan_segment_pool(self):
db_session = db.get_session()
net_p_dict = self._prepare_net_profile_data('vlan')
net_p_req = self.new_create_request('network_profiles', net_p_dict)
net_p = self.deserialize(self.fmt,
net_p_req.get_response(self.ext_api))
self.assertIsNotNone(n1kv_db_v2.get_vlan_allocation(db_session,
PHYS_NET,
VLAN_MIN))
self._delete('network_profiles', net_p['network_profile']['id'])
for vlan in range(VLAN_MIN, VLAN_MAX + 1):
self.assertRaises(c_exc.VlanIDNotFound,
n1kv_db_v2.get_vlan_allocation,
db_session,
PHYS_NET,
vlan)
class TestN1kvBasicGet(test_plugin.TestBasicGet,
N1kvPluginTestCase):