From 0e2fae71341c8b512e8912bf21cee4694e0b2830 Mon Sep 17 00:00:00 2001 From: Abhishek Raut Date: Mon, 19 Aug 2013 21:20:11 -0700 Subject: [PATCH] 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 --- .../38fc1f6789f8_cisco_n1kv_overlay.py | 56 +++++++ .../plugins/cisco/common/cisco_constants.py | 5 +- neutron/plugins/cisco/db/n1kv_db_v2.py | 45 +++--- neutron/plugins/cisco/db/n1kv_models_v2.py | 6 +- .../plugins/cisco/extensions/credential.py | 2 + .../cisco/extensions/network_profile.py | 2 + neutron/plugins/cisco/n1kv/n1kv_client.py | 27 ++-- .../plugins/cisco/n1kv/n1kv_neutron_plugin.py | 143 ++++++++++-------- neutron/tests/unit/cisco/n1kv/test_n1kv_db.py | 7 +- 9 files changed, 191 insertions(+), 102 deletions(-) create mode 100644 neutron/db/migration/alembic_migrations/versions/38fc1f6789f8_cisco_n1kv_overlay.py diff --git a/neutron/db/migration/alembic_migrations/versions/38fc1f6789f8_cisco_n1kv_overlay.py b/neutron/db/migration/alembic_migrations/versions/38fc1f6789f8_cisco_n1kv_overlay.py new file mode 100644 index 0000000000..c13ebeaf21 --- /dev/null +++ b/neutron/db/migration/alembic_migrations/versions/38fc1f6789f8_cisco_n1kv_overlay.py @@ -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) diff --git a/neutron/plugins/cisco/common/cisco_constants.py b/neutron/plugins/cisco/common/cisco_constants.py index b64c0591b5..ca2b8b8ddb 100644 --- a/neutron/plugins/cisco/common/cisco_constants.py +++ b/neutron/plugins/cisco/common/cisco_constants.py @@ -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' diff --git a/neutron/plugins/cisco/db/n1kv_db_v2.py b/neutron/plugins/cisco/db/n1kv_db_v2.py index 6db40fff80..2f6cd33c89 100644 --- a/neutron/plugins/cisco/db/n1kv_db_v2.py +++ b/neutron/plugins/cisco/db/n1kv_db_v2.py @@ -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): """ diff --git a/neutron/plugins/cisco/db/n1kv_models_v2.py b/neutron/plugins/cisco/db/n1kv_models_v2.py index 98af252813..4933ff8391 100644 --- a/neutron/plugins/cisco/db/n1kv_models_v2.py +++ b/neutron/plugins/cisco/db/n1kv_models_v2.py @@ -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 - '-' multicast_ip_index - multicast_ip_range - '-' @@ -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, diff --git a/neutron/plugins/cisco/extensions/credential.py b/neutron/plugins/cisco/extensions/credential.py index cfce0f36d0..8838136c12 100644 --- a/neutron/plugins/cisco/extensions/credential.py +++ b/neutron/plugins/cisco/extensions/credential.py @@ -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, diff --git a/neutron/plugins/cisco/extensions/network_profile.py b/neutron/plugins/cisco/extensions/network_profile.py index e21773f5fd..aef5c925f9 100644 --- a/neutron/plugins/cisco/extensions/network_profile.py +++ b/neutron/plugins/cisco/extensions/network_profile.py @@ -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, diff --git a/neutron/plugins/cisco/n1kv/n1kv_client.py b/neutron/plugins/cisco/n1kv/n1kv_client.py index 7e25aa86ea..3f7b9bee65 100644 --- a/neutron/plugins/cisco/n1kv/n1kv_client.py +++ b/neutron/plugins/cisco/n1kv/n1kv_client.py @@ -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): """ diff --git a/neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py b/neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py index b3cb55f80c..61d603bcfa 100644 --- a/neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py +++ b/neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py @@ -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) diff --git a/neutron/tests/unit/cisco/n1kv/test_n1kv_db.py b/neutron/tests/unit/cisco/n1kv/test_n1kv_db.py index 35d291c30f..ef8ea11925 100644 --- a/neutron/tests/unit/cisco/n1kv/test_n1kv_db.py +++ b/neutron/tests/unit/cisco/n1kv/test_n1kv_db.py @@ -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,