Add sub-type field to VXLAN network profiles for Cisco N1KV plugin

Rename VXLAN type of network profiles to Overlay network profiles.
Add a new sub type column to Overlay network profiles. Support
enhanced VXLAN and native VXLAN as Overlay sub types. Allow plugin to
be flexible to support newer sub types.

Change-Id: I3899b01f316902d1139e47b153a9db7ecb3ff982
Implements: blueprint cisco-plugin-n1k-enh-vxlan-support
This commit is contained in:
Abhishek Raut 2013-08-19 21:20:11 -07:00 committed by Mark McClain
parent 29db26230a
commit 0e2fae7134
9 changed files with 191 additions and 102 deletions

View File

@ -0,0 +1,56 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2013 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.
#
"""Cisco N1KV overlay support
Revision ID: 38fc1f6789f8
Revises: 1efb85914233
Create Date: 2013-08-20 18:31:16.158387
"""
revision = '38fc1f6789f8'
down_revision = '1efb85914233'
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.alter_column('cisco_network_profiles', 'segment_type',
existing_type=sa.Enum('vlan', 'overlay', 'trunk',
'multi-segment'),
existing_nullable=False)
def downgrade(active_plugins=None, options=None):
if not migration.should_run(active_plugins, migration_for_plugins):
return
op.alter_column('cisco_network_profiles', 'segment_type',
existing_type=sa.Enum('vlan', 'vxlan', 'trunk',
'multi-segment'),
existing_nullable=False)

View File

@ -81,12 +81,15 @@ NETWORK_TYPE_TRUNK = 'trunk'
NETWORK_TYPE_MULTI_SEGMENT = 'multi-segment'
# Values for network sub_type
NETWORK_TYPE_OVERLAY = 'overlay'
NETWORK_SUBTYPE_NATIVE_VXLAN = 'native_vxlan'
NETWORK_SUBTYPE_TRUNK_VLAN = NETWORK_TYPE_VLAN
NETWORK_SUBTYPE_TRUNK_VXLAN = NETWORK_TYPE_VXLAN
NETWORK_SUBTYPE_TRUNK_VXLAN = NETWORK_TYPE_OVERLAY
# Prefix for VM Network name
VM_NETWORK_NAME_PREFIX = 'vmn_'
DEFAULT_HTTP_TIMEOUT = 15
SET = 'set'
INSTANCE = 'instance'
PROPERTIES = 'properties'

View File

@ -289,15 +289,15 @@ def add_network_binding(db_session, network_id, network_type,
:param db_session: database session
:param network_id: UUID representing the network
:param network_type: string representing type of network (VLAN, VXLAN,
:param network_type: string representing type of network (VLAN, OVERLAY,
MULTI_SEGMENT or TRUNK)
:param physical_network: Only applicable for VLAN networks. It
represents a L2 Domain
:param segmentation_id: integer representing VLAN or VXLAN ID
:param multicast_ip: VXLAN technology needs a multicast IP to be associated
with every VXLAN ID to deal with broadcast packets. A
single multicast IP can be shared by multiple VXLAN
IDs.
:param multicast_ip: Native VXLAN technology needs a multicast IP to be
associated with every VXLAN ID to deal with broadcast
packets. A single multicast IP can be shared by
multiple VXLAN IDs.
:param network_profile_id: network profile ID based on which this network
is created
:param add_segments: List of segment UUIDs in pairs to be added to either a
@ -516,7 +516,7 @@ def reserve_vxlan(db_session, network_profile):
:param network_profile: network profile object
"""
seg_min, seg_max = get_segment_range(network_profile)
segment_type = c_const.NETWORK_TYPE_VXLAN
segment_type = c_const.NETWORK_TYPE_OVERLAY
physical_network = ""
with db_session.begin(subtransactions=True):
@ -531,10 +531,13 @@ def reserve_vxlan(db_session, network_profile):
if alloc:
segment_id = alloc.vxlan_id
alloc.allocated = True
return (physical_network, segment_type,
segment_id, get_multicast_ip(network_profile))
raise c_exc.NoMoreNetworkSegments(
network_profile_name=network_profile.name)
if network_profile.sub_type == (c_const.
NETWORK_SUBTYPE_NATIVE_VXLAN):
return (physical_network, segment_type,
segment_id, get_multicast_ip(network_profile))
else:
return (physical_network, segment_type, segment_id, "0.0.0.0")
raise q_exc.NoNetworkAvailable()
def alloc_network(db_session, network_profile_id):
@ -549,7 +552,7 @@ def alloc_network(db_session, network_profile_id):
network_profile_id)
if network_profile.segment_type == c_const.NETWORK_TYPE_VLAN:
return reserve_vlan(db_session, network_profile)
if network_profile.segment_type == c_const.NETWORK_TYPE_VXLAN:
if network_profile.segment_type == c_const.NETWORK_TYPE_OVERLAY:
return reserve_vxlan(db_session, network_profile)
return (None, network_profile.segment_type, 0, "0.0.0.0")
@ -841,7 +844,7 @@ def create_network_profile(db_session, network_profile):
if network_profile["segment_type"] == c_const.NETWORK_TYPE_VLAN:
kwargs["physical_network"] = network_profile["physical_network"]
kwargs["segment_range"] = network_profile["segment_range"]
elif network_profile["segment_type"] == c_const.NETWORK_TYPE_VXLAN:
elif network_profile["segment_type"] == c_const.NETWORK_TYPE_OVERLAY:
kwargs["multicast_ip_index"] = 0
kwargs["multicast_ip_range"] = network_profile[
"multicast_ip_range"]
@ -1234,10 +1237,10 @@ class NetworkProfile_db_mixin(object):
raise q_exc.InvalidInput(error_message=msg)
segment_type = net_p["segment_type"].lower()
if segment_type not in [c_const.NETWORK_TYPE_VLAN,
c_const.NETWORK_TYPE_VXLAN,
c_const.NETWORK_TYPE_OVERLAY,
c_const.NETWORK_TYPE_TRUNK,
c_const.NETWORK_TYPE_MULTI_SEGMENT]:
msg = _("segment_type should either be vlan, vxlan, "
msg = _("segment_type should either be vlan, overlay, "
"multi-segment or trunk")
LOG.exception(msg)
raise q_exc.InvalidInput(error_message=msg)
@ -1247,22 +1250,26 @@ class NetworkProfile_db_mixin(object):
"for network profile")
LOG.exception(msg)
raise q_exc.InvalidInput(error_message=msg)
if segment_type == c_const.NETWORK_TYPE_TRUNK:
if segment_type in [c_const.NETWORK_TYPE_TRUNK,
c_const.NETWORK_TYPE_OVERLAY]:
if "sub_type" not in net_p:
msg = _("argument sub_type missing "
"for trunk network profile")
"for network profile")
LOG.exception(msg)
raise q_exc.InvalidInput(error_message=msg)
if segment_type in [c_const.NETWORK_TYPE_VLAN,
c_const.NETWORK_TYPE_VXLAN]:
c_const.NETWORK_TYPE_OVERLAY]:
if "segment_range" not in net_p:
msg = _("argument segment_range missing "
"for network profile")
LOG.exception(msg)
raise q_exc.InvalidInput(error_message=msg)
self._validate_segment_range(net_p)
if segment_type != c_const.NETWORK_TYPE_VXLAN:
net_p["multicast_ip_range"] = "0.0.0.0"
if segment_type == c_const.NETWORK_TYPE_OVERLAY:
if net_p['sub_type'] != c_const.NETWORK_SUBTYPE_NATIVE_VXLAN:
net_p['multicast_ip_range'] = '0.0.0.0'
else:
net_p['multicast_ip_range'] = '0.0.0.0'
def _validate_segment_range_uniqueness(self, context, net_p):
"""

View File

@ -96,8 +96,8 @@ class NetworkProfile(model_base.BASEV2, models_v2.HasId):
"""
Nexus1000V Network Profiles
segment_type - VLAN, VXLAN, TRUNK, MULTI_SEGMENT
sub_type - TRUNK_VLAN, TRUNK_VXLAN
segment_type - VLAN, OVERLAY, TRUNK, MULTI_SEGMENT
sub_type - TRUNK_VLAN, TRUNK_VXLAN, native_vxlan, enhanced_vxlan
segment_range - '<integer>-<integer>'
multicast_ip_index - <integer>
multicast_ip_range - '<ip>-<ip>'
@ -107,7 +107,7 @@ class NetworkProfile(model_base.BASEV2, models_v2.HasId):
name = sa.Column(sa.String(255))
segment_type = sa.Column(sa.Enum(cisco_constants.NETWORK_TYPE_VLAN,
cisco_constants.NETWORK_TYPE_VXLAN,
cisco_constants.NETWORK_TYPE_OVERLAY,
cisco_constants.NETWORK_TYPE_TRUNK,
cisco_constants.
NETWORK_TYPE_MULTI_SEGMENT,

View File

@ -31,6 +31,8 @@ RESOURCE_ATTRIBUTE_MAP = {
'is_visible': True},
'credential_name': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
'tenant_id': {'allow_post': True, 'allow_put': False,
'is_visible': False, 'default': ''},
'type': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
'user_name': {'allow_post': True, 'allow_put': True,

View File

@ -39,6 +39,8 @@ RESOURCE_ATTRIBUTE_MAP = {
'default': attributes.ATTR_NOT_SPECIFIED},
'segment_range': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
'sub_type': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''},
'multicast_ip_range': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': '0.0.0.0'},
'multicast_ip_index': {'allow_post': False, 'allow_put': False,

View File

@ -150,6 +150,7 @@ class Client(object):
self.format = 'json'
self.hosts = self._get_vsm_hosts()
self.action_prefix = 'http://%s/api/n1k' % self.hosts[0]
self.timeout = c_const.DEFAULT_HTTP_TIMEOUT
def list_port_profiles(self):
"""
@ -171,15 +172,18 @@ class Client(object):
self.events_path = self.events_path + '?type=' + event_type
return self._get(self.events_path)
def create_bridge_domain(self, network):
def create_bridge_domain(self, network, overlay_subtype):
"""
Create a bridge domain on VSM.
:param network: network dict
:param overlay_subtype: string representing subtype of overlay network
"""
body = {'name': network['name'] + c_const.BRIDGE_DOMAIN_SUFFIX,
'segmentId': network[providernet.SEGMENTATION_ID],
'groupIp': network[n1kv_profile.MULTICAST_IP], }
'subType': overlay_subtype}
if overlay_subtype == c_const.NETWORK_SUBTYPE_NATIVE_VXLAN:
body['groupIp'] = network[n1kv_profile.MULTICAST_IP]
return self._post(self.bridge_domains_path,
body=body)
@ -198,13 +202,12 @@ class Client(object):
:param network: network dict
:param network_profile: network profile dict
"""
LOG.debug(_("seg id %s\n"), network_profile['name'])
body = {'name': network['name'],
'id': network['id'],
'networkSegmentPool': network_profile['name'], }
if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_VLAN:
body['vlan'] = network[providernet.SEGMENTATION_ID]
elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_VXLAN:
elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_OVERLAY:
body['bridgeDomain'] = (network['name'] +
c_const.BRIDGE_DOMAIN_SUFFIX)
if network_profile['segment_type'] == c_const.NETWORK_TYPE_TRUNK:
@ -427,20 +430,22 @@ class Client(object):
if body:
body = self._serialize(body)
LOG.debug(_("req: %s"), body)
resp, replybody = httplib2.Http().request(action,
method,
body=body,
headers=headers)
try:
resp, replybody = (httplib2.Http(timeout=self.timeout).
request(action,
method,
body=body,
headers=headers))
except Exception as e:
raise c_exc.VSMConnectionFailed(reason=e)
LOG.debug(_("status_code %s"), resp.status)
if resp.status == 200:
if 'application/xml' in resp['content-type']:
return self._deserialize(replybody, resp.status)
elif 'text/plain' in resp['content-type']:
LOG.debug(_("VSM: %s"), replybody)
elif resp.status == 500:
else:
raise c_exc.VSMError(reason=replybody)
elif resp.status == 503:
raise c_exc.VSMConnectionFailed
def _serialize(self, data):
"""

View File

@ -159,7 +159,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
"""
n1kv_db_v2.initialize()
c_cred.Store.initialize()
self._initialize_network_vlan_ranges()
self._initialize_network_ranges()
# If no api_extensions_path is provided set the following
if not q_conf.CONF.api_extensions_path:
q_conf.CONF.set_override(
@ -212,56 +212,69 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
tenant-ids.
"""
LOG.debug(_('_populate_policy_profiles'))
n1kvclient = n1kv_client.Client()
policy_profiles = n1kvclient.list_port_profiles()
LOG.debug(_('_populate_policy_profiles %s'), policy_profiles)
if policy_profiles:
for profile in policy_profiles['body'][c_const.SET]:
if c_const.ID and c_const.NAME in profile:
profile_id = profile[c_const.PROPERTIES][c_const.ID]
profile_name = profile[c_const.PROPERTIES][c_const.NAME]
self._add_policy_profile(profile_name, profile_id)
else:
try:
n1kvclient = n1kv_client.Client()
policy_profiles = n1kvclient.list_port_profiles()
LOG.debug(_('_populate_policy_profiles %s'), policy_profiles)
if policy_profiles:
for profile in policy_profiles['body'][c_const.SET]:
if c_const.ID and c_const.NAME in profile:
profile_id = profile[c_const.PROPERTIES][c_const.ID]
profile_name = profile[c_const.
PROPERTIES][c_const.NAME]
self._add_policy_profile(profile_name, profile_id)
self._remove_all_fake_policy_profiles()
except (cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed):
LOG.warning(_('No policy profile populated from VSM'))
self._remove_all_fake_policy_profiles()
def _poll_policies(self, event_type=None, epoch=None, tenant_id=None):
"""
Poll for Policy Profiles from Cisco Nexus1000V for any update/delete.
"""
LOG.debug(_('_poll_policies'))
n1kvclient = n1kv_client.Client()
policy_profiles = n1kvclient.list_events(event_type, epoch)
if policy_profiles:
for profile in policy_profiles['body'][c_const.SET]:
if c_const.NAME in profile:
# Extract commands from the events XML.
cmd = profile[c_const.PROPERTIES]['cmd']
cmds = cmd.split(';')
cmdwords = cmds[1].split()
profile_name = profile[c_const.PROPERTIES][c_const.NAME]
# Delete the policy profile from db if it's deleted on VSM
if 'no' in cmdwords[0]:
p = self._get_policy_profile_by_name(profile_name)
if p:
self._delete_policy_profile(p['id'])
# Add policy profile to neutron DB idempotently
elif c_const.ID in profile[c_const.PROPERTIES]:
profile_id = profile[c_const.PROPERTIES][c_const.ID]
self._add_policy_profile(
profile_name, profile_id, tenant_id)
# Replace tenant-id for profile bindings with admin's tenant-id
self._remove_all_fake_policy_profiles()
try:
n1kvclient = n1kv_client.Client()
policy_profiles = n1kvclient.list_events(event_type, epoch)
if policy_profiles:
for profile in policy_profiles['body'][c_const.SET]:
if c_const.NAME in profile:
# Extract commands from the events XML.
cmd = profile[c_const.PROPERTIES]['cmd']
cmds = cmd.split(';')
cmdwords = cmds[1].split()
profile_name = profile[c_const.
PROPERTIES][c_const.NAME]
# Delete the policy profile from db if deleted on VSM
if 'no' in cmdwords[0]:
p = self._get_policy_profile_by_name(profile_name)
if p:
self._delete_policy_profile(p['id'])
# Add policy profile to neutron DB idempotently
elif c_const.ID in profile[c_const.PROPERTIES]:
profile_id = profile[c_const.
PROPERTIES][c_const.ID]
self._add_policy_profile(
profile_name, profile_id, tenant_id)
# Replace tenant-id for profile bindings with admin's tenant-id
self._remove_all_fake_policy_profiles()
except (cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed):
LOG.warning(_('No policy profile updated from VSM'))
def _initialize_network_vlan_ranges(self):
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:
seg_min, seg_max = self._get_segment_range(
network_profile['segment_range'])
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)
@ -276,7 +289,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
binding = n1kv_db_v2.get_network_binding(context.session,
network['id'])
network[providernet.NETWORK_TYPE] = binding.network_type
if binding.network_type == c_const.NETWORK_TYPE_VXLAN:
if binding.network_type == c_const.NETWORK_TYPE_OVERLAY:
network[providernet.PHYSICAL_NETWORK] = None
network[providernet.SEGMENTATION_ID] = binding.segmentation_id
network[n1kv_profile.MULTICAST_IP] = binding.multicast_ip
@ -316,9 +329,9 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
msg = _("provider:segmentation_id out of range "
"(1 through 4094)")
raise q_exc.InvalidInput(error_message=msg)
elif network_type == c_const.NETWORK_TYPE_VXLAN:
elif network_type == c_const.NETWORK_TYPE_OVERLAY:
if physical_network_set:
msg = _("provider:physical_network specified for VXLAN "
msg = _("provider:physical_network specified for Overlay "
"network")
raise q_exc.InvalidInput(error_message=msg)
else:
@ -387,8 +400,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
def _extend_mapping_dict(self, context, mapping_dict, segment):
"""
Extends a mapping dictionary by populating dot1q tag and
bridge-domain name.
Extend a mapping dictionary with dot1q tag and bridge-domain name.
:param context: neutron api request context
:param mapping_dict: dictionary to populate values
@ -536,7 +548,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
def _parse_multi_segments(self, context, attrs, param):
"""
Parse the multi-segment network attributes
Parse the multi-segment network attributes.
:param context: neutron api request context
:param attrs: Attributes of the network
@ -546,7 +558,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
"""
pair_list = []
valid_seg_types = [c_const.NETWORK_TYPE_VLAN,
c_const.NETWORK_TYPE_VXLAN]
c_const.NETWORK_TYPE_OVERLAY]
segments = attrs.get(param)
if not attributes.is_attr_set(segments):
return pair_list
@ -574,7 +586,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
def _parse_trunk_segments(self, context, attrs, param, physical_network,
sub_type):
"""
Parse the trunk network attributes
Parse the trunk network attributes.
:param context: neutron api request context
:param attrs: Attributes of the network
@ -600,7 +612,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
"another trunk segment") % segment
raise q_exc.InvalidInput(error_message=msg)
elif binding.network_type == c_const.NETWORK_TYPE_VLAN:
if sub_type == c_const.NETWORK_TYPE_VXLAN:
if sub_type == c_const.NETWORK_TYPE_OVERLAY:
msg = _("Cannot add vlan segment '%s' as a member of "
"a vxlan trunk segment") % segment
raise q_exc.InvalidInput(error_message=msg)
@ -610,7 +622,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
msg = _("Network UUID '%s' belongs to a different "
"physical network") % segment
raise q_exc.InvalidInput(error_message=msg)
elif binding.network_type == c_const.NETWORK_TYPE_VXLAN:
elif binding.network_type == c_const.NETWORK_TYPE_OVERLAY:
if sub_type == c_const.NETWORK_TYPE_VLAN:
msg = _("Cannot add vxlan segment '%s' as a member of "
"a vlan trunk segment") % segment
@ -726,7 +738,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
"""
Send create network request to VSM.
Create a bridge domain for network of type VXLAN.
Create a bridge domain for network of type Overlay.
:param context: neutron api request context
:param network: network dictionary
:param segment_pairs: List of segments in UUID pairs
@ -736,13 +748,13 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
profile = self.get_network_profile(context,
network[n1kv_profile.PROFILE_ID])
n1kvclient = n1kv_client.Client()
if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_VXLAN:
n1kvclient.create_bridge_domain(network)
if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_OVERLAY:
n1kvclient.create_bridge_domain(network, profile['sub_type'])
if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_TRUNK:
self._populate_member_segments(context, network, segment_pairs,
n1kv_profile.SEGMENT_ADD)
network['del_segment_list'] = []
if profile['sub_type'] == c_const.NETWORK_TYPE_VXLAN:
if profile['sub_type'] == c_const.NETWORK_TYPE_OVERLAY:
encap_dict = {'name': (network['name'] +
c_const.ENCAPSULATION_PROFILE_SUFFIX),
'add_segment_list': (
@ -788,7 +800,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
body['delSegments'] = network['del_segment_list']
LOG.debug(_('add_segments=%s'), body['addSegments'])
LOG.debug(_('del_segments=%s'), body['delSegments'])
if profile['sub_type'] == c_const.NETWORK_TYPE_VXLAN:
if profile['sub_type'] == c_const.NETWORK_TYPE_OVERLAY:
encap_profile = (network['name'] +
c_const.ENCAPSULATION_PROFILE_SUFFIX)
encap_dict = {'name': encap_profile,
@ -806,21 +818,21 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
"""
Send delete network request to VSM.
Delete bridge domain if network is of type VXLAN.
Delete encapsulation profile if network is of type VXLAN Trunk.
Delete bridge domain if network is of type Overlay.
Delete encapsulation profile if network is of type OVERLAY Trunk.
:param context: neutron api request context
:param network: network dictionary
"""
LOG.debug(_('_send_delete_network_request: %s'), network['id'])
n1kvclient = n1kv_client.Client()
session = context.session
if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_VXLAN:
if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_OVERLAY:
name = network['name'] + c_const.BRIDGE_DOMAIN_SUFFIX
n1kvclient.delete_bridge_domain(name)
elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_TRUNK:
profile = self.get_network_profile(
context, network[n1kv_profile.PROFILE_ID])
if profile['sub_type'] == c_const.NETWORK_TYPE_VXLAN:
if profile['sub_type'] == c_const.NETWORK_TYPE_OVERLAY:
profile_name = (network['name'] +
c_const.ENCAPSULATION_PROFILE_SUFFIX)
n1kvclient.delete_encapsulation_profile(profile_name)
@ -1126,12 +1138,12 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
binding = n1kv_db_v2.get_network_binding(session, id)
network = self.get_network(context, id)
if n1kv_db_v2.is_trunk_member(session, id):
msg = _("Cannot delete a network "
"that is a member of a trunk segment")
msg = _("Cannot delete network '%s' "
"that is member of a trunk segment") % network['name']
raise q_exc.InvalidInput(error_message=msg)
if n1kv_db_v2.is_multi_segment_member(session, id):
msg = _("Cannot delete a network "
"that is a member of a multi-segment network")
msg = _("Cannot delete network '%s' that is a member of a "
"multi-segment network") % network['name']
raise q_exc.InvalidInput(error_message=msg)
if self.agent_vsm:
try:
@ -1140,7 +1152,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
cisco_exceptions.VSMConnectionFailed):
LOG.debug(_('Delete failed in VSM'))
super(N1kvNeutronPluginV2, self).delete_network(context, id)
if binding.network_type == c_const.NETWORK_TYPE_VXLAN:
if binding.network_type == c_const.NETWORK_TYPE_OVERLAY:
n1kv_db_v2.release_vxlan(session, binding.segmentation_id,
self.vxlan_id_ranges)
elif binding.network_type == c_const.NETWORK_TYPE_VLAN:
@ -1394,7 +1406,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
Create a network profile.
Create a network profile, which represents a pool of networks
belonging to one type (VLAN or VXLAN). On creation of network
belonging to one type (VLAN or Overlay). On creation of network
profile, we retrieve the admin tenant-id which we use to replace
the previously stored fake tenant-id in tenant-profile bindings.
:param context: neutron api request context
@ -1406,7 +1418,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
N1kvNeutronPluginV2, self).create_network_profile(context,
network_profile)
if _network_profile['segment_type'] in [c_const.NETWORK_TYPE_VLAN,
c_const.NETWORK_TYPE_VXLAN]:
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:
@ -1454,8 +1466,9 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
int(seg_max))
n1kv_db_v2.delete_vlan_allocations(context.session,
self.network_vlan_ranges)
elif _network_profile['segment_type'] == c_const.NETWORK_TYPE_VXLAN:
self.delete_vxlan_ranges = [(int(seg_min), int(seg_max))]
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)

View File

@ -60,7 +60,8 @@ TEST_NETWORK_PROFILE_2 = {'name': 'test_profile_2',
'physical_network': 'physnet1',
'segment_range': SEGMENT_RANGE}
TEST_NETWORK_PROFILE_VXLAN = {'name': 'test_profile',
'segment_type': 'vxlan',
'segment_type': 'overlay',
'sub_type': 'native_vxlan',
'segment_range': '5000-5009',
'multicast_ip_range': '239.0.0.70-239.0.0.80'}
TEST_POLICY_PROFILE = {'id': '4a417990-76fb-11e2-bcfd-0800200c9a66',
@ -72,7 +73,7 @@ TEST_NETWORK_PROFILE_VLAN_TRUNK = {'name': 'test_profile',
'sub_type': 'vlan'}
TEST_NETWORK_PROFILE_VXLAN_TRUNK = {'name': 'test_profile',
'segment_type': 'trunk',
'sub_type': 'vxlan'}
'sub_type': 'overlay'}
def _create_test_network_profile_if_not_there(session,
@ -600,7 +601,7 @@ class NetworkBindingsTest(test_plugin.NeutronDbPluginV2TestCase):
p_v = _create_test_network_profile_if_not_there(
self.session, TEST_NETWORK_PROFILE_VXLAN_TRUNK)
n1kv_db_v2.add_network_binding(
self.session, TEST_NETWORK_ID2, 'vxlan',
self.session, TEST_NETWORK_ID2, 'overlay',
None, 5100, '224.10.10.10', p_v.id, None)
p = _create_test_network_profile_if_not_there(
self.session,