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:
parent
29db26230a
commit
0e2fae7134
@ -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)
|
@ -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'
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user