[NSX-v]: Add support for multiple DVS for VLAN network type
This patch proposes to use the physical_network attribute of provider network API for network type VLAN to consume comma ',' separated DVS-IDs. This way, admin can provide the multiple DVS-IDs associated with a single VLAN network in the provider net create command. This will result in creation of port groups on each of the DVSes. If no DVS-ID is provided, we pick the DVS-ID from conf file. If DVS-ID is provided in the physical network, in order for the instances on these networks to grab DHCP addresses, the DVS-ID of the edge/mgmt cluster must be explicitly provided in the CLI along with other DVS-IDs. Usage: neutron net-create fancy-network --provider:network_type=vlan --provider:segmentation_id=100 --provider:physical_network=dvs-10,dvs-20 Closes-Bug: #1559320 Change-Id: Ifb10e3f34bf0c55d2d7710e804b5de995ec954bd
This commit is contained in:
parent
c946784134
commit
c138dcfdda
@ -55,10 +55,12 @@ def add_network_binding(session, network_id, binding_type, phy_uuid, vlan_id):
|
|||||||
return binding
|
return binding
|
||||||
|
|
||||||
|
|
||||||
def add_neutron_nsx_network_mapping(session, neutron_id, nsx_switch_id):
|
def add_neutron_nsx_network_mapping(session, neutron_id, nsx_switch_id,
|
||||||
|
dvs_id=None):
|
||||||
with session.begin(subtransactions=True):
|
with session.begin(subtransactions=True):
|
||||||
mapping = nsx_models.NeutronNsxNetworkMapping(
|
mapping = nsx_models.NeutronNsxNetworkMapping(
|
||||||
neutron_id=neutron_id, nsx_id=nsx_switch_id)
|
neutron_id=neutron_id, nsx_id=nsx_switch_id,
|
||||||
|
dvs_id=dvs_id)
|
||||||
session.add(mapping)
|
session.add(mapping)
|
||||||
return mapping
|
return mapping
|
||||||
|
|
||||||
@ -120,6 +122,18 @@ def get_nsx_switch_ids(session, neutron_id):
|
|||||||
neutron_id=neutron_id)]
|
neutron_id=neutron_id)]
|
||||||
|
|
||||||
|
|
||||||
|
def get_nsx_switch_id_for_dvs(session, neutron_id, dvs_id):
|
||||||
|
"""Retrieve the NSX switch ID for a given DVS ID and neutron network."""
|
||||||
|
try:
|
||||||
|
mapping = (session.query(nsx_models.NeutronNsxNetworkMapping).
|
||||||
|
filter_by(neutron_id=neutron_id,
|
||||||
|
dvs_id=dvs_id).one())
|
||||||
|
return mapping['nsx_id']
|
||||||
|
except exc.NoResultFound:
|
||||||
|
LOG.debug("NSX switch for dvs-id: %s not yet stored in Neutron DB",
|
||||||
|
dvs_id)
|
||||||
|
|
||||||
|
|
||||||
def get_net_ids(session, nsx_id):
|
def get_net_ids(session, nsx_id):
|
||||||
return [mapping['neutron_id'] for mapping in
|
return [mapping['neutron_id'] for mapping in
|
||||||
session.query(nsx_models.NeutronNsxNetworkMapping).filter_by(
|
session.query(nsx_models.NeutronNsxNetworkMapping).filter_by(
|
||||||
|
@ -1 +1 @@
|
|||||||
3e4dccfe6fb4
|
967462f585e1
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
# Copyright 2016 VMware, Inc.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""add dvs_id column to neutron_nsx_network_mappings
|
||||||
|
|
||||||
|
Revision ID: 967462f585e1
|
||||||
|
Revises: 3e4dccfe6fb4
|
||||||
|
Create Date: 2016-02-23 18:22:01.998540
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '967462f585e1'
|
||||||
|
down_revision = '3e4dccfe6fb4'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('neutron_nsx_network_mappings',
|
||||||
|
sa.Column('dvs_id', sa.String(36), nullable=True))
|
@ -67,12 +67,18 @@ class NeutronNsxNetworkMapping(model_base.BASEV2):
|
|||||||
|
|
||||||
Because of chained logical switches more than one mapping might exist
|
Because of chained logical switches more than one mapping might exist
|
||||||
for a single Neutron network.
|
for a single Neutron network.
|
||||||
|
For a VLAN network, one neutron network may map to multiple logical
|
||||||
|
switches(port groups) created on multiple DVSes in the backend for
|
||||||
|
NSX-V plugin. DVS-ID will store the moref of the DVS where the nsx
|
||||||
|
id is being created. For other types and plugins, this value will
|
||||||
|
remain null.
|
||||||
"""
|
"""
|
||||||
__tablename__ = 'neutron_nsx_network_mappings'
|
__tablename__ = 'neutron_nsx_network_mappings'
|
||||||
neutron_id = sa.Column(sa.String(36),
|
neutron_id = sa.Column(sa.String(36),
|
||||||
sa.ForeignKey('networks.id', ondelete='CASCADE'),
|
sa.ForeignKey('networks.id', ondelete='CASCADE'),
|
||||||
primary_key=True)
|
primary_key=True)
|
||||||
nsx_id = sa.Column(sa.String(36), primary_key=True)
|
nsx_id = sa.Column(sa.String(36), primary_key=True)
|
||||||
|
dvs_id = sa.Column(sa.String(36), nullable=True)
|
||||||
|
|
||||||
|
|
||||||
class NeutronNsxSecurityGroupMapping(model_base.BASEV2):
|
class NeutronNsxSecurityGroupMapping(model_base.BASEV2):
|
||||||
|
@ -380,6 +380,14 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
raise n_exc.VlanIdInUse(
|
raise n_exc.VlanIdInUse(
|
||||||
vlan_id=segmentation_id,
|
vlan_id=segmentation_id,
|
||||||
physical_network=phy_uuid)
|
physical_network=phy_uuid)
|
||||||
|
# Verify whether the DVSes exist in the backend.
|
||||||
|
if physical_network_set:
|
||||||
|
dvs_ids = self._get_dvs_ids(physical_network)
|
||||||
|
for dvs_id in dvs_ids:
|
||||||
|
if not self.nsx_v.vcns.validate_dvs(dvs_id):
|
||||||
|
raise nsx_exc.NsxResourceNotFound(
|
||||||
|
res_name='dvs_id',
|
||||||
|
res_id=dvs_id)
|
||||||
|
|
||||||
elif network_type == c_utils.NsxVNetworkTypes.VXLAN:
|
elif network_type == c_utils.NsxVNetworkTypes.VXLAN:
|
||||||
# Currently unable to set the segmentation id
|
# Currently unable to set the segmentation id
|
||||||
@ -527,13 +535,52 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
else:
|
else:
|
||||||
self.nsx_v.delete_virtual_wire(moref)
|
self.nsx_v.delete_virtual_wire(moref)
|
||||||
|
|
||||||
def _get_vlan_network_name(self, net_data):
|
def _get_vlan_network_name(self, net_data, dvs_id):
|
||||||
|
if net_data.get('name') is None:
|
||||||
|
net_data['name'] = ''
|
||||||
if net_data['name'] == '':
|
if net_data['name'] == '':
|
||||||
return net_data['id']
|
# Include only the first 8 characters from the dvs-id.
|
||||||
|
return '%s-%s' % (dvs_id[:8], net_data['id'])
|
||||||
else:
|
else:
|
||||||
# Maximum name length is 80 characters. 'id' length is 36
|
# Maximum name length is 80 characters. 'id' length is 36
|
||||||
# maximum prefix for name is 43
|
# maximum prefix for name plus dvs-id is 43
|
||||||
return '%s-%s' % (net_data['name'][:43], net_data['id'])
|
return '%s-%s-%s' % (dvs_id[:8], net_data['name'][:35],
|
||||||
|
net_data['id'])
|
||||||
|
|
||||||
|
def _create_vlan_network_at_backend(self, net_data, dvs_id):
|
||||||
|
network_name = self._get_vlan_network_name(net_data, dvs_id)
|
||||||
|
segment = net_data[mpnet.SEGMENTS][0]
|
||||||
|
vlan_tag = 0
|
||||||
|
if (segment.get(pnet.NETWORK_TYPE) ==
|
||||||
|
c_utils.NsxVNetworkTypes.VLAN):
|
||||||
|
vlan_tag = segment.get(pnet.SEGMENTATION_ID, 0)
|
||||||
|
portgroup = {'vlanId': vlan_tag,
|
||||||
|
'networkBindingType': 'Static',
|
||||||
|
'networkName': network_name,
|
||||||
|
'networkType': 'Isolation'}
|
||||||
|
config_spec = {'networkSpec': portgroup}
|
||||||
|
try:
|
||||||
|
h, c = self.nsx_v.vcns.create_port_group(dvs_id,
|
||||||
|
config_spec)
|
||||||
|
return c
|
||||||
|
except Exception as e:
|
||||||
|
error = (_("Failed to create port group on DVS: %(dvs_id)s. "
|
||||||
|
"Reason: %(reason)s") % {'dvs_id': dvs_id,
|
||||||
|
'reason': e.response})
|
||||||
|
raise nsx_exc.NsxPluginException(err_msg=error)
|
||||||
|
|
||||||
|
def _get_dvs_ids(self, physical_network):
|
||||||
|
"""Extract DVS-IDs provided in the physical network field.
|
||||||
|
|
||||||
|
If physical network attribute is not set, return the pre configured
|
||||||
|
dvs-id from nsx.ini file, otherwise convert physical network string
|
||||||
|
to a list of unique DVS-IDs.
|
||||||
|
"""
|
||||||
|
if not attr.is_attr_set(physical_network):
|
||||||
|
return [self.dvs_id]
|
||||||
|
# Return unique DVS-IDs only and ignore duplicates
|
||||||
|
return list(set(
|
||||||
|
dvs.strip() for dvs in physical_network.split(',') if dvs))
|
||||||
|
|
||||||
def _get_default_security_group(self, context, tenant_id):
|
def _get_default_security_group(self, context, tenant_id):
|
||||||
return self._ensure_default_security_group(context, tenant_id)
|
return self._ensure_default_security_group(context, tenant_id)
|
||||||
@ -652,42 +699,41 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
res_id=vdn_scope_id)
|
res_id=vdn_scope_id)
|
||||||
h, c = self.nsx_v.vcns.create_virtual_wire(vdn_scope_id,
|
h, c = self.nsx_v.vcns.create_virtual_wire(vdn_scope_id,
|
||||||
config_spec)
|
config_spec)
|
||||||
net_moref = c
|
net_morefs = [c]
|
||||||
elif network_type == c_utils.NsxVNetworkTypes.PORTGROUP:
|
elif network_type == c_utils.NsxVNetworkTypes.PORTGROUP:
|
||||||
segment = net_data[mpnet.SEGMENTS][0]
|
segment = net_data[mpnet.SEGMENTS][0]
|
||||||
net_moref = segment.get(pnet.PHYSICAL_NETWORK)
|
net_morefs = [segment.get(pnet.PHYSICAL_NETWORK)]
|
||||||
else:
|
else:
|
||||||
network_name = self._get_vlan_network_name(net_data)
|
|
||||||
vlan_tag = 0
|
|
||||||
segment = net_data[mpnet.SEGMENTS][0]
|
segment = net_data[mpnet.SEGMENTS][0]
|
||||||
if (segment.get(pnet.NETWORK_TYPE) ==
|
|
||||||
c_utils.NsxVNetworkTypes.VLAN):
|
|
||||||
vlan_tag = segment.get(pnet.SEGMENTATION_ID, 0)
|
|
||||||
physical_network = segment.get(pnet.PHYSICAL_NETWORK)
|
physical_network = segment.get(pnet.PHYSICAL_NETWORK)
|
||||||
dvs_id = (physical_network if attr.is_attr_set(
|
# Retrieve the list of dvs-ids from physical network.
|
||||||
physical_network) else self.dvs_id)
|
# If physical_network attr is not set, retrieve a list
|
||||||
portgroup = {'vlanId': vlan_tag,
|
# consisting of a single dvs-id pre-configured in nsx.ini
|
||||||
'networkBindingType': 'Static',
|
dvs_ids = self._get_dvs_ids(physical_network)
|
||||||
'networkName': network_name,
|
# Save the list of netmorefs from the backend
|
||||||
'networkType': 'Isolation'}
|
net_morefs = []
|
||||||
config_spec = {'networkSpec': portgroup}
|
dvs_pg_mappings = {}
|
||||||
try:
|
for dvs_id in dvs_ids:
|
||||||
h, c = self.nsx_v.vcns.create_port_group(dvs_id,
|
try:
|
||||||
config_spec)
|
net_moref = self._create_vlan_network_at_backend(
|
||||||
net_moref = c
|
dvs_id=dvs_id,
|
||||||
except Exception as e:
|
net_data=net_data)
|
||||||
LOG.debug("Failed to create port group: %s",
|
except nsx_exc.NsxPluginException:
|
||||||
e.response)
|
with excutils.save_and_reraise_exception():
|
||||||
err_msg = (_("Physical network %s is not an existing DVS")
|
# Delete VLAN networks on other DVSes if it
|
||||||
% dvs_id)
|
# fails to be created on one DVS and reraise
|
||||||
raise n_exc.InvalidInput(error_message=err_msg)
|
# the original exception.
|
||||||
|
for net_moref in net_morefs:
|
||||||
|
self._delete_backend_network(net_moref)
|
||||||
|
dvs_pg_mappings[dvs_id] = net_moref
|
||||||
|
net_morefs.append(net_moref)
|
||||||
try:
|
try:
|
||||||
# Create SpoofGuard policy for network anti-spoofing
|
# Create SpoofGuard policy for network anti-spoofing
|
||||||
if cfg.CONF.nsxv.spoofguard_enabled and backend_network:
|
if cfg.CONF.nsxv.spoofguard_enabled and backend_network:
|
||||||
sg_policy_id = None
|
sg_policy_id = None
|
||||||
s, sg_policy_id = self.nsx_v.vcns.create_spoofguard_policy(
|
sg_policy_id = self.nsx_v.vcns.create_spoofguard_policy(
|
||||||
net_moref, net_data['id'], net_data[psec.PORTSECURITY])
|
net_morefs, net_data['id'],
|
||||||
|
net_data[psec.PORTSECURITY])[1]
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
new_net = super(NsxVPluginV2, self).create_network(context,
|
new_net = super(NsxVPluginV2, self).create_network(context,
|
||||||
network)
|
network)
|
||||||
@ -723,9 +769,20 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
net_bindings)
|
net_bindings)
|
||||||
if backend_network:
|
if backend_network:
|
||||||
# Save moref in the DB for future access
|
# Save moref in the DB for future access
|
||||||
nsx_db.add_neutron_nsx_network_mapping(
|
if network_type == c_utils.NsxVNetworkTypes.VLAN:
|
||||||
context.session, new_net['id'],
|
# Save netmoref to dvs id mappings for VLAN network
|
||||||
net_moref)
|
# type for future access.
|
||||||
|
for dvs_id, netmoref in six.iteritems(dvs_pg_mappings):
|
||||||
|
nsx_db.add_neutron_nsx_network_mapping(
|
||||||
|
session=context.session,
|
||||||
|
neutron_id=new_net['id'],
|
||||||
|
nsx_switch_id=netmoref,
|
||||||
|
dvs_id=dvs_id)
|
||||||
|
else:
|
||||||
|
for net_moref in net_morefs:
|
||||||
|
nsx_db.add_neutron_nsx_network_mapping(
|
||||||
|
context.session, new_net['id'],
|
||||||
|
net_moref)
|
||||||
if cfg.CONF.nsxv.spoofguard_enabled:
|
if cfg.CONF.nsxv.spoofguard_enabled:
|
||||||
nsxv_db.map_spoofguard_policy_for_network(
|
nsxv_db.map_spoofguard_policy_for_network(
|
||||||
context.session, new_net['id'], sg_policy_id)
|
context.session, new_net['id'], sg_policy_id)
|
||||||
@ -736,7 +793,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
if backend_network:
|
if backend_network:
|
||||||
if cfg.CONF.nsxv.spoofguard_enabled and sg_policy_id:
|
if cfg.CONF.nsxv.spoofguard_enabled and sg_policy_id:
|
||||||
self.nsx_v.vcns.delete_spoofguard_policy(sg_policy_id)
|
self.nsx_v.vcns.delete_spoofguard_policy(sg_policy_id)
|
||||||
self._delete_backend_network(net_moref)
|
for net_moref in net_morefs:
|
||||||
|
self._delete_backend_network(net_moref)
|
||||||
LOG.exception(_LE('Failed to create network'))
|
LOG.exception(_LE('Failed to create network'))
|
||||||
|
|
||||||
# this extra lookup is necessary to get the
|
# this extra lookup is necessary to get the
|
||||||
@ -816,7 +874,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
if cfg.CONF.nsxv.spoofguard_enabled and sg_policy_id:
|
if cfg.CONF.nsxv.spoofguard_enabled and sg_policy_id:
|
||||||
self.nsx_v.vcns.delete_spoofguard_policy(sg_policy_id)
|
self.nsx_v.vcns.delete_spoofguard_policy(sg_policy_id)
|
||||||
edge_utils.check_network_in_use_at_backend(context, id)
|
edge_utils.check_network_in_use_at_backend(context, id)
|
||||||
self._delete_backend_network(mappings[0])
|
for mapping in mappings:
|
||||||
|
self._delete_backend_network(mapping)
|
||||||
|
|
||||||
def get_network(self, context, id, fields=None):
|
def get_network(self, context, id, fields=None):
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
@ -875,10 +934,10 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
# old state
|
# old state
|
||||||
if cfg.CONF.nsxv.spoofguard_enabled and psec_update:
|
if cfg.CONF.nsxv.spoofguard_enabled and psec_update:
|
||||||
policy_id = nsxv_db.get_spoofguard_policy_id(context.session, id)
|
policy_id = nsxv_db.get_spoofguard_policy_id(context.session, id)
|
||||||
net_moref = nsx_db.get_nsx_switch_ids(context.session, id)
|
net_morefs = nsx_db.get_nsx_switch_ids(context.session, id)
|
||||||
try:
|
try:
|
||||||
self.nsx_v.vcns.update_spoofguard_policy(
|
self.nsx_v.vcns.update_spoofguard_policy(
|
||||||
policy_id, net_moref[0], id,
|
policy_id, net_morefs, id,
|
||||||
net_attrs[psec.PORTSECURITY])
|
net_attrs[psec.PORTSECURITY])
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
|
@ -29,6 +29,8 @@ def _xmldump(obj):
|
|||||||
This converts the dict to xml with following assumptions:
|
This converts the dict to xml with following assumptions:
|
||||||
Keys starting with _(underscore) are to be used as attributes and not
|
Keys starting with _(underscore) are to be used as attributes and not
|
||||||
element keys starting with @ so that dict can be made.
|
element keys starting with @ so that dict can be made.
|
||||||
|
Keys starting with __(double underscore) are to be skipped and its
|
||||||
|
value is processed.
|
||||||
The keys are not part of any xml schema.
|
The keys are not part of any xml schema.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -36,11 +38,15 @@ def _xmldump(obj):
|
|||||||
attr = ""
|
attr = ""
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
for key, value in six.iteritems(obj):
|
for key, value in six.iteritems(obj):
|
||||||
if (key.startswith('_')):
|
if key.startswith('__'):
|
||||||
|
# Skip the key and evaluate it's value.
|
||||||
|
a, x = _xmldump(value)
|
||||||
|
config += x
|
||||||
|
elif key.startswith('_'):
|
||||||
attr += ' %s="%s"' % (key[1:], value)
|
attr += ' %s="%s"' % (key[1:], value)
|
||||||
else:
|
else:
|
||||||
a, x = _xmldump(value)
|
a, x = _xmldump(value)
|
||||||
if (key.startswith('@')):
|
if key.startswith('@'):
|
||||||
cfg = "%s" % (x)
|
cfg = "%s" % (x)
|
||||||
else:
|
else:
|
||||||
cfg = "<%s%s>%s</%s>" % (key, a, x, key)
|
cfg = "<%s%s>%s</%s>" % (key, a, x, key)
|
||||||
|
@ -316,35 +316,34 @@ class EdgeManager(object):
|
|||||||
bindings = nsxv_db.get_network_bindings(context.session, network_id)
|
bindings = nsxv_db.get_network_bindings(context.session, network_id)
|
||||||
# Set the return value as global DVS-ID of the mgmt/edge cluster
|
# Set the return value as global DVS-ID of the mgmt/edge cluster
|
||||||
phys_net = self.dvs_id
|
phys_net = self.dvs_id
|
||||||
|
network_type = None
|
||||||
if bindings:
|
if bindings:
|
||||||
binding = bindings[0]
|
binding = bindings[0]
|
||||||
|
network_type = binding['binding_type']
|
||||||
|
if (network_type == c_utils.NsxVNetworkTypes.VLAN
|
||||||
|
and binding['phy_uuid'] != ''):
|
||||||
|
if ',' not in binding['phy_uuid']:
|
||||||
|
phys_net = binding['phy_uuid']
|
||||||
# Return user input physical network value for all network types
|
# Return user input physical network value for all network types
|
||||||
# except VXLAN networks. The DVS-ID of the mgmt/edge cluster must
|
# except VXLAN networks. The DVS-ID of the mgmt/edge cluster must
|
||||||
# be returned for VXLAN network types.
|
# be returned for VXLAN network types.
|
||||||
if (not binding['binding_type'] == c_utils.NsxVNetworkTypes.VXLAN
|
elif (not network_type == c_utils.NsxVNetworkTypes.VXLAN
|
||||||
and binding['phy_uuid'] != ''):
|
and binding['phy_uuid'] != ''):
|
||||||
phys_net = binding['phy_uuid']
|
phys_net = binding['phy_uuid']
|
||||||
return phys_net
|
return phys_net, network_type
|
||||||
|
|
||||||
def _create_sub_interface(self, context, network_id, network_name,
|
def _create_sub_interface(self, context, network_id, network_name,
|
||||||
tunnel_index, address_groups,
|
tunnel_index, address_groups,
|
||||||
port_group_id=None):
|
port_group_id=None):
|
||||||
# Get the physical port group /wire id of the network id
|
vcns_network_id = _retrieve_nsx_switch_id(context, network_id)
|
||||||
mappings = nsx_db.get_nsx_switch_ids(context.session, network_id)
|
|
||||||
if mappings:
|
|
||||||
vcns_network_id = mappings[0]
|
|
||||||
else:
|
|
||||||
LOG.error(_LE("Create sub interface failed since network %s not "
|
|
||||||
"found at the backend."), network_id)
|
|
||||||
raise nsx_exc.NsxPluginException(
|
|
||||||
err_msg=_("network %s not found at the backend") % network_id)
|
|
||||||
if port_group_id is None:
|
if port_group_id is None:
|
||||||
portgroup = {'vlanId': 0,
|
portgroup = {'vlanId': 0,
|
||||||
'networkName': network_name,
|
'networkName': network_name,
|
||||||
'networkBindingType': 'Static',
|
'networkBindingType': 'Static',
|
||||||
'networkType': 'Isolation'}
|
'networkType': 'Isolation'}
|
||||||
config_spec = {'networkSpec': portgroup}
|
config_spec = {'networkSpec': portgroup}
|
||||||
dvs_id = self._get_physical_provider_network(context, network_id)
|
dvs_id, network_type = self._get_physical_provider_network(
|
||||||
|
context, network_id)
|
||||||
pg, port_group_id = self.nsxv_manager.vcns.create_port_group(
|
pg, port_group_id = self.nsxv_manager.vcns.create_port_group(
|
||||||
dvs_id, config_spec)
|
dvs_id, config_spec)
|
||||||
|
|
||||||
@ -388,8 +387,8 @@ class EdgeManager(object):
|
|||||||
if port_group_id:
|
if port_group_id:
|
||||||
objuri = header['location']
|
objuri = header['location']
|
||||||
job_id = objuri[objuri.rfind("/") + 1:]
|
job_id = objuri[objuri.rfind("/") + 1:]
|
||||||
dvs_id = self._get_physical_provider_network(context,
|
dvs_id, net_type = self._get_physical_provider_network(
|
||||||
network_id)
|
context, network_id)
|
||||||
self.nsxv_manager.delete_portgroup(dvs_id,
|
self.nsxv_manager.delete_portgroup(dvs_id,
|
||||||
port_group_id,
|
port_group_id,
|
||||||
job_id)
|
job_id)
|
||||||
@ -1412,13 +1411,37 @@ def delete_lrouter(nsxv_manager, context, router_id, dist=False):
|
|||||||
LOG.warning(_LW("router binding for router: %s not found"), router_id)
|
LOG.warning(_LW("router binding for router: %s not found"), router_id)
|
||||||
|
|
||||||
|
|
||||||
|
def _retrieve_nsx_switch_id(context, network_id):
|
||||||
|
"""Helper method to retrieve backend switch ID."""
|
||||||
|
bindings = nsxv_db.get_network_bindings(context.session, network_id)
|
||||||
|
if bindings:
|
||||||
|
binding = bindings[0]
|
||||||
|
network_type = binding['binding_type']
|
||||||
|
if (network_type == c_utils.NsxVNetworkTypes.VLAN
|
||||||
|
and binding['phy_uuid'] != ''):
|
||||||
|
if ',' not in binding['phy_uuid']:
|
||||||
|
dvs_id = binding['phy_uuid']
|
||||||
|
else:
|
||||||
|
# If network is of type VLAN and multiple dvs associated with
|
||||||
|
# one neutron network, retrieve the logical network id for the
|
||||||
|
# edge/mgmt cluster's DVS.
|
||||||
|
dvs_id = cfg.CONF.nsxv.dvs_id
|
||||||
|
return nsx_db.get_nsx_switch_id_for_dvs(
|
||||||
|
context.session, network_id, dvs_id)
|
||||||
|
# Get the physical port group /wire id of the network id
|
||||||
|
mappings = nsx_db.get_nsx_switch_ids(context.session, network_id)
|
||||||
|
if mappings:
|
||||||
|
return mappings[0]
|
||||||
|
raise nsx_exc.NsxPluginException(
|
||||||
|
err_msg=_("Network %s not found at the backend") % network_id)
|
||||||
|
|
||||||
|
|
||||||
def create_dhcp_service(context, nsxv_manager, network):
|
def create_dhcp_service(context, nsxv_manager, network):
|
||||||
"""Create an Edge for dhcp service."""
|
"""Create an Edge for dhcp service."""
|
||||||
edge_name = "%s-%s" % (network['name'], network['id'])
|
edge_name = "%s-%s" % (network['name'], network['id'])
|
||||||
jobdata = {'network_id': network['id'], 'context': context}
|
jobdata = {'network_id': network['id'], 'context': context}
|
||||||
# port group id for vlan or virtual wire id for vxlan
|
# port group id for vlan or virtual wire id for vxlan
|
||||||
nsx_network_id = nsx_db.get_nsx_switch_ids(context.session,
|
nsx_network_id = _retrieve_nsx_switch_id(context, network['id'])
|
||||||
network['id'])[0]
|
|
||||||
# Deploy an Edge for dhcp service
|
# Deploy an Edge for dhcp service
|
||||||
return nsxv_manager.deploy_edge(
|
return nsxv_manager.deploy_edge(
|
||||||
network['id'], edge_name, nsx_network_id, jobdata=jobdata,
|
network['id'], edge_name, nsx_network_id, jobdata=jobdata,
|
||||||
@ -1476,10 +1499,7 @@ def query_dhcp_service_config(nsxv_manager, edge_id):
|
|||||||
def update_dhcp_internal_interface(context, nsxv_manager,
|
def update_dhcp_internal_interface(context, nsxv_manager,
|
||||||
network_id, address_groups, add=True):
|
network_id, address_groups, add=True):
|
||||||
# Get the physical port group /wire id of the network id
|
# Get the physical port group /wire id of the network id
|
||||||
mappings = nsx_db.get_nsx_switch_ids(context.session, network_id)
|
vcns_network_id = _retrieve_nsx_switch_id(context, network_id)
|
||||||
if mappings:
|
|
||||||
vcns_network_id = mappings[0]
|
|
||||||
|
|
||||||
# Get the DHCP Edge to update the internal interface
|
# Get the DHCP Edge to update the internal interface
|
||||||
binding = nsxv_db.get_dhcp_edge_network_binding(context.session,
|
binding = nsxv_db.get_dhcp_edge_network_binding(context.session,
|
||||||
network_id)
|
network_id)
|
||||||
@ -1635,9 +1655,7 @@ def update_internal_interface(nsxv_manager, context, router_id, int_net_id,
|
|||||||
def _update_internal_interface(nsxv_manager, context, router_id, int_net_id,
|
def _update_internal_interface(nsxv_manager, context, router_id, int_net_id,
|
||||||
address_groups, is_connected=True):
|
address_groups, is_connected=True):
|
||||||
# Get the pg/wire id of the network id
|
# Get the pg/wire id of the network id
|
||||||
mappings = nsx_db.get_nsx_switch_ids(context.session, int_net_id)
|
vcns_network_id = _retrieve_nsx_switch_id(context, int_net_id)
|
||||||
if mappings:
|
|
||||||
vcns_network_id = mappings[0]
|
|
||||||
LOG.debug("Network id %(network_id)s corresponding ref is : "
|
LOG.debug("Network id %(network_id)s corresponding ref is : "
|
||||||
"%(net_moref)s", {'network_id': int_net_id,
|
"%(net_moref)s", {'network_id': int_net_id,
|
||||||
'net_moref': vcns_network_id})
|
'net_moref': vcns_network_id})
|
||||||
@ -1671,9 +1689,7 @@ def add_vdr_internal_interface(nsxv_manager, context, router_id,
|
|||||||
def _add_vdr_internal_interface(nsxv_manager, context, router_id,
|
def _add_vdr_internal_interface(nsxv_manager, context, router_id,
|
||||||
int_net_id, address_groups, is_connected=True):
|
int_net_id, address_groups, is_connected=True):
|
||||||
# Get the pg/wire id of the network id
|
# Get the pg/wire id of the network id
|
||||||
mappings = nsx_db.get_nsx_switch_ids(context.session, int_net_id)
|
vcns_network_id = _retrieve_nsx_switch_id(context, int_net_id)
|
||||||
if mappings:
|
|
||||||
vcns_network_id = mappings[0]
|
|
||||||
LOG.debug("Network id %(network_id)s corresponding ref is : "
|
LOG.debug("Network id %(network_id)s corresponding ref is : "
|
||||||
"%(net_moref)s", {'network_id': int_net_id,
|
"%(net_moref)s", {'network_id': int_net_id,
|
||||||
'net_moref': vcns_network_id})
|
'net_moref': vcns_network_id})
|
||||||
@ -1706,9 +1722,7 @@ def _update_vdr_internal_interface(nsxv_manager, context, router_id,
|
|||||||
int_net_id, address_groups,
|
int_net_id, address_groups,
|
||||||
is_connected=True):
|
is_connected=True):
|
||||||
# Get the pg/wire id of the network id
|
# Get the pg/wire id of the network id
|
||||||
mappings = nsx_db.get_nsx_switch_ids(context.session, int_net_id)
|
vcns_network_id = _retrieve_nsx_switch_id(context, int_net_id)
|
||||||
if mappings:
|
|
||||||
vcns_network_id = mappings[0]
|
|
||||||
LOG.debug("Network id %(network_id)s corresponding ref is : "
|
LOG.debug("Network id %(network_id)s corresponding ref is : "
|
||||||
"%(net_moref)s", {'network_id': int_net_id,
|
"%(net_moref)s", {'network_id': int_net_id,
|
||||||
'net_moref': vcns_network_id})
|
'net_moref': vcns_network_id})
|
||||||
@ -1733,9 +1747,7 @@ def delete_interface(nsxv_manager, context, router_id, network_id,
|
|||||||
def _delete_interface(nsxv_manager, context, router_id, network_id,
|
def _delete_interface(nsxv_manager, context, router_id, network_id,
|
||||||
dist=False, is_wait=True):
|
dist=False, is_wait=True):
|
||||||
# Get the pg/wire id of the network id
|
# Get the pg/wire id of the network id
|
||||||
mappings = nsx_db.get_nsx_switch_ids(context.session, network_id)
|
vcns_network_id = _retrieve_nsx_switch_id(context, network_id)
|
||||||
if mappings:
|
|
||||||
vcns_network_id = mappings[0]
|
|
||||||
LOG.debug("Network id %(network_id)s corresponding ref is : "
|
LOG.debug("Network id %(network_id)s corresponding ref is : "
|
||||||
"%(net_moref)s", {'network_id': network_id,
|
"%(net_moref)s", {'network_id': network_id,
|
||||||
'net_moref': vcns_network_id})
|
'net_moref': vcns_network_id})
|
||||||
|
@ -640,23 +640,33 @@ class Vcns(object):
|
|||||||
|
|
||||||
return self.do_request(HTTP_GET, uri)
|
return self.do_request(HTTP_GET, uri)
|
||||||
|
|
||||||
|
def _get_enforcement_point_body(self, enforcement_points):
|
||||||
|
e_point_list = []
|
||||||
|
for enforcement_point in enforcement_points:
|
||||||
|
e_point_list.append({
|
||||||
|
'enforcementPoint': {
|
||||||
|
'id': enforcement_point,
|
||||||
|
'type': enforcement_point.split('-')[0]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {'__enforcementPoints': e_point_list}
|
||||||
|
|
||||||
@retry_upon_exception(exceptions.RequestBad)
|
@retry_upon_exception(exceptions.RequestBad)
|
||||||
def create_spoofguard_policy(self, enforcement_point, name, enable):
|
def create_spoofguard_policy(self, enforcement_points, name, enable):
|
||||||
uri = '%s/policies/' % SPOOFGUARD_PREFIX
|
uri = '%s/policies/' % SPOOFGUARD_PREFIX
|
||||||
|
|
||||||
body = {'spoofguardPolicy':
|
body = {'spoofguardPolicy':
|
||||||
{'name': name,
|
{'name': name,
|
||||||
'operationMode': 'MANUAL' if enable else 'DISABLE',
|
'operationMode': 'MANUAL' if enable else 'DISABLE',
|
||||||
'enforcementPoint':
|
|
||||||
{'id': enforcement_point,
|
|
||||||
'type': enforcement_point.split('-')[0]},
|
|
||||||
'allowLocalIPs': 'true'}}
|
'allowLocalIPs': 'true'}}
|
||||||
|
body['spoofguardPolicy'].update(
|
||||||
|
self._get_enforcement_point_body(enforcement_points))
|
||||||
return self.do_request(HTTP_POST, uri, body,
|
return self.do_request(HTTP_POST, uri, body,
|
||||||
format='xml', encode=True, decode=False)
|
format='xml', encode=True, decode=False)
|
||||||
|
|
||||||
@retry_upon_exception(exceptions.RequestBad)
|
@retry_upon_exception(exceptions.RequestBad)
|
||||||
def update_spoofguard_policy(self, policy_id,
|
def update_spoofguard_policy(self, policy_id,
|
||||||
enforcement_point, name, enable):
|
enforcement_points, name, enable):
|
||||||
update_uri = '%s/policies/%s' % (SPOOFGUARD_PREFIX, policy_id)
|
update_uri = '%s/policies/%s' % (SPOOFGUARD_PREFIX, policy_id)
|
||||||
publish_uri = '%s/%s?action=publish' % (SPOOFGUARD_PREFIX, policy_id)
|
publish_uri = '%s/%s?action=publish' % (SPOOFGUARD_PREFIX, policy_id)
|
||||||
|
|
||||||
@ -664,10 +674,9 @@ class Vcns(object):
|
|||||||
{'policyId': policy_id,
|
{'policyId': policy_id,
|
||||||
'name': name,
|
'name': name,
|
||||||
'operationMode': 'MANUAL' if enable else 'DISABLE',
|
'operationMode': 'MANUAL' if enable else 'DISABLE',
|
||||||
'enforcementPoint':
|
|
||||||
{'id': enforcement_point,
|
|
||||||
'type': enforcement_point.split('-')[0]},
|
|
||||||
'allowLocalIPs': 'true'}}
|
'allowLocalIPs': 'true'}}
|
||||||
|
body['spoofguardPolicy'].update(
|
||||||
|
self._get_enforcement_point_body(enforcement_points))
|
||||||
|
|
||||||
self.do_request(HTTP_PUT, update_uri, body,
|
self.do_request(HTTP_PUT, update_uri, body,
|
||||||
format='xml', encode=True, decode=False)
|
format='xml', encode=True, decode=False)
|
||||||
|
@ -125,23 +125,39 @@ class NsxVPluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
|
|||||||
|
|
||||||
def test_get_vlan_network_name(self):
|
def test_get_vlan_network_name(self):
|
||||||
p = manager.NeutronManager.get_plugin()
|
p = manager.NeutronManager.get_plugin()
|
||||||
id = uuidutils.generate_uuid()
|
net_id = uuidutils.generate_uuid()
|
||||||
|
dvs_id = 'dvs-10'
|
||||||
net = {'name': '',
|
net = {'name': '',
|
||||||
'id': id}
|
'id': net_id}
|
||||||
expected = id
|
# Empty net['name'] should yield dvs_id-net_id as a name for the
|
||||||
|
# port group.
|
||||||
|
expected = '%s-%s' % (dvs_id, net_id)
|
||||||
self.assertEqual(expected,
|
self.assertEqual(expected,
|
||||||
p._get_vlan_network_name(net))
|
p._get_vlan_network_name(net, dvs_id))
|
||||||
|
# If network name is provided then it should yield
|
||||||
|
# dvs_id-net_name-net_id as a name for the port group.
|
||||||
net = {'name': 'pele',
|
net = {'name': 'pele',
|
||||||
'id': id}
|
'id': net_id}
|
||||||
expected = '%s-%s' % ('pele', id)
|
expected = '%s-%s-%s' % (dvs_id, 'pele', net_id)
|
||||||
self.assertEqual(expected,
|
self.assertEqual(expected,
|
||||||
p._get_vlan_network_name(net))
|
p._get_vlan_network_name(net, dvs_id))
|
||||||
name = 'X' * 500
|
name = 'X' * 500
|
||||||
net = {'name': name,
|
net = {'name': name,
|
||||||
'id': id}
|
'id': net_id}
|
||||||
expected = '%s-%s' % (name[:43], id)
|
expected = '%s-%s-%s' % (dvs_id, name[:35], net_id)
|
||||||
self.assertEqual(expected,
|
self.assertEqual(expected,
|
||||||
p._get_vlan_network_name(net))
|
p._get_vlan_network_name(net, dvs_id))
|
||||||
|
|
||||||
|
def test_get_vlan_network_name_with_net_name_missing(self):
|
||||||
|
p = manager.NeutronManager.get_plugin()
|
||||||
|
net_id = uuidutils.generate_uuid()
|
||||||
|
dvs_id = 'dvs-10'
|
||||||
|
net = {'id': net_id}
|
||||||
|
# Missing net['name'] should yield dvs_id-net_id as a name for the
|
||||||
|
# port group.
|
||||||
|
expected = '%s-%s' % (dvs_id, net_id)
|
||||||
|
self.assertEqual(expected,
|
||||||
|
p._get_vlan_network_name(net, dvs_id))
|
||||||
|
|
||||||
def test_create_port_anticipating_allocation(self):
|
def test_create_port_anticipating_allocation(self):
|
||||||
with self.network(shared=True) as network:
|
with self.network(shared=True) as network:
|
||||||
@ -301,6 +317,114 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxVPluginV2TestCase):
|
|||||||
for k, v in expected_same_vlan:
|
for k, v in expected_same_vlan:
|
||||||
self.assertEqual(net1['network'][k], v)
|
self.assertEqual(net1['network'][k], v)
|
||||||
|
|
||||||
|
def test_create_vlan_network_with_multiple_dvs(self):
|
||||||
|
name = 'multi-dvs-vlan-net'
|
||||||
|
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
|
||||||
|
pnet.SEGMENTATION_ID: 100,
|
||||||
|
pnet.PHYSICAL_NETWORK: 'dvs-1, dvs-2, dvs-3'}
|
||||||
|
p = manager.NeutronManager.get_plugin()
|
||||||
|
with mock.patch.object(
|
||||||
|
p, '_create_vlan_network_at_backend',
|
||||||
|
# Return three netmorefs as side effect
|
||||||
|
side_effect=[_uuid(), _uuid(), _uuid()]) as vlan_net_call:
|
||||||
|
with self.network(name=name,
|
||||||
|
providernet_args=providernet_args,
|
||||||
|
arg_list=(pnet.NETWORK_TYPE,
|
||||||
|
pnet.SEGMENTATION_ID,
|
||||||
|
pnet.PHYSICAL_NETWORK)):
|
||||||
|
# _create_vlan_network_at_backend is expected to be called
|
||||||
|
# three times since we have three DVS IDs in the physical
|
||||||
|
# network attribute.
|
||||||
|
self.assertEqual(3, vlan_net_call.call_count)
|
||||||
|
|
||||||
|
def test_create_vlan_network_with_multiple_dvs_backend_failure(self):
|
||||||
|
net_data = {'name': 'vlan-net',
|
||||||
|
'tenant_id': self._tenant_id,
|
||||||
|
pnet.NETWORK_TYPE: 'vlan',
|
||||||
|
pnet.SEGMENTATION_ID: 100,
|
||||||
|
pnet.PHYSICAL_NETWORK: 'dvs-1, dvs-2, dvs-3'}
|
||||||
|
network = {'network': net_data}
|
||||||
|
p = manager.NeutronManager.get_plugin()
|
||||||
|
with mock.patch.object(
|
||||||
|
p, '_create_vlan_network_at_backend',
|
||||||
|
# Return two successful netmorefs and fail on the backend
|
||||||
|
# for the third netmoref creation as side effect.
|
||||||
|
side_effect=[_uuid(), _uuid(),
|
||||||
|
nsxv_exc.NsxPluginException(err_msg='')]):
|
||||||
|
with mock.patch.object(
|
||||||
|
p, '_delete_backend_network') as delete_net_call:
|
||||||
|
self.assertRaises(nsxv_exc.NsxPluginException,
|
||||||
|
p.create_network,
|
||||||
|
context.get_admin_context(),
|
||||||
|
network)
|
||||||
|
# Two successfully created port groups should be rolled back
|
||||||
|
# on the failure of third port group creation.
|
||||||
|
self.assertEqual(2, delete_net_call.call_count)
|
||||||
|
|
||||||
|
def test_create_vlan_network_with_multiple_dvs_not_found_failure(self):
|
||||||
|
net_data = {'name': 'vlan-net',
|
||||||
|
'tenant_id': self._tenant_id,
|
||||||
|
pnet.NETWORK_TYPE: 'vlan',
|
||||||
|
pnet.SEGMENTATION_ID: 100,
|
||||||
|
pnet.PHYSICAL_NETWORK: 'dvs-1, dvs-2, dvs-3'}
|
||||||
|
network = {'network': net_data}
|
||||||
|
p = manager.NeutronManager.get_plugin()
|
||||||
|
with mock.patch.object(
|
||||||
|
p, '_validate_provider_create',
|
||||||
|
side_effect=[nsxv_exc.NsxResourceNotFound(res_id='dvs-2',
|
||||||
|
res_name='dvs_id')]):
|
||||||
|
with mock.patch.object(
|
||||||
|
p, '_create_vlan_network_at_backend') as create_net_call:
|
||||||
|
self.assertRaises(nsxv_exc.NsxResourceNotFound,
|
||||||
|
p.create_network,
|
||||||
|
context.get_admin_context(),
|
||||||
|
network)
|
||||||
|
# Verify no port group is created on the backend.
|
||||||
|
self.assertEqual(0, create_net_call.call_count)
|
||||||
|
|
||||||
|
def test_create_vlan_network_with_multiple_dvs_ignore_duplicate_dvs(self):
|
||||||
|
name = 'multi-dvs-vlan-net'
|
||||||
|
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
|
||||||
|
pnet.SEGMENTATION_ID: 100,
|
||||||
|
pnet.PHYSICAL_NETWORK: 'dvs-1, dvs-2, dvs-1'}
|
||||||
|
p = manager.NeutronManager.get_plugin()
|
||||||
|
with mock.patch.object(
|
||||||
|
p, '_create_vlan_network_at_backend',
|
||||||
|
# Return two netmorefs as side effect
|
||||||
|
side_effect=[_uuid(), _uuid()]) as vlan_net_call:
|
||||||
|
with self.network(name=name,
|
||||||
|
providernet_args=providernet_args,
|
||||||
|
arg_list=(pnet.NETWORK_TYPE,
|
||||||
|
pnet.SEGMENTATION_ID,
|
||||||
|
pnet.PHYSICAL_NETWORK)):
|
||||||
|
# _create_vlan_network_at_backend is expected to be called
|
||||||
|
# two times since we have only two unique DVS IDs in the
|
||||||
|
# physical network attribute.
|
||||||
|
self.assertEqual(2, vlan_net_call.call_count)
|
||||||
|
|
||||||
|
def test_get_dvs_ids_for_multiple_dvs_vlan_network(self):
|
||||||
|
p = manager.NeutronManager.get_plugin()
|
||||||
|
# If no DVS-ID is provided as part of physical network, return
|
||||||
|
# global DVS-ID configured in nsx.ini
|
||||||
|
physical_network = attributes.ATTR_NOT_SPECIFIED
|
||||||
|
self.assertEqual(['fake_dvs_id'], p._get_dvs_ids(physical_network))
|
||||||
|
# If DVS-IDs are provided as part of physical network as a comma
|
||||||
|
# separated string, return them as a list of DVS-IDs.
|
||||||
|
physical_network = 'dvs-1,dvs-2, dvs-3'
|
||||||
|
expected_dvs_ids = ['dvs-1', 'dvs-2', 'dvs-3']
|
||||||
|
self.assertEqual(expected_dvs_ids,
|
||||||
|
sorted(p._get_dvs_ids(physical_network)))
|
||||||
|
# Ignore extra commas ',' in the physical_network attribute.
|
||||||
|
physical_network = ',,,dvs-1,dvs-2,, dvs-3,'
|
||||||
|
expected_dvs_ids = ['dvs-1', 'dvs-2', 'dvs-3']
|
||||||
|
self.assertEqual(expected_dvs_ids,
|
||||||
|
sorted(p._get_dvs_ids(physical_network)))
|
||||||
|
# Ignore duplicate DVS-IDs in the physical_network attribute.
|
||||||
|
physical_network = ',,,dvs-1,dvs-2,, dvs-2,'
|
||||||
|
expected_dvs_ids = ['dvs-1', 'dvs-2']
|
||||||
|
self.assertEqual(expected_dvs_ids,
|
||||||
|
sorted(p._get_dvs_ids(physical_network)))
|
||||||
|
|
||||||
def test_create_vxlan_with_tz_provider_network(self):
|
def test_create_vxlan_with_tz_provider_network(self):
|
||||||
name = 'provider_net_vxlan'
|
name = 'provider_net_vxlan'
|
||||||
expected = [('subnets', []), ('name', name), ('admin_state_up', True),
|
expected = [('subnets', []), ('name', name), ('admin_state_up', True),
|
||||||
|
@ -1028,18 +1028,18 @@ class FakeVcns(object):
|
|||||||
headers = {'status': 200}
|
headers = {'status': 200}
|
||||||
return (headers, response)
|
return (headers, response)
|
||||||
|
|
||||||
def create_spoofguard_policy(self, enforcement_point, name, enable):
|
def create_spoofguard_policy(self, enforcement_points, name, enable):
|
||||||
policy = {'name': name,
|
policy = {'name': name,
|
||||||
'enforcement_point': enforcement_point,
|
'enforcement_point': enforcement_points[0],
|
||||||
'operationMode': 'MANUAL' if enable else 'DISABLE'}
|
'operationMode': 'MANUAL' if enable else 'DISABLE'}
|
||||||
policy_id = len(self._spoofguard_policies)
|
policy_id = len(self._spoofguard_policies)
|
||||||
self._spoofguard_policies.append(policy)
|
self._spoofguard_policies.append(policy)
|
||||||
return None, policy_id
|
return None, policy_id
|
||||||
|
|
||||||
def update_spoofguard_policy(self, policy_id,
|
def update_spoofguard_policy(self, policy_id,
|
||||||
enforcement_point, name, enable):
|
enforcement_points, name, enable):
|
||||||
policy = {'name': name,
|
policy = {'name': name,
|
||||||
'enforcement_point': enforcement_point,
|
'enforcement_point': enforcement_points[0],
|
||||||
'operationMode': 'MANUAL' if enable else 'DISABLE'}
|
'operationMode': 'MANUAL' if enable else 'DISABLE'}
|
||||||
self._spoofguard_policies[int(policy_id)] = policy
|
self._spoofguard_policies[int(policy_id)] = policy
|
||||||
return None, ''
|
return None, ''
|
||||||
|
Loading…
Reference in New Issue
Block a user