NSX|P add port security support
Adding segment profiles to the backend port Including mac learning support, port security & spoofguard. In addition - adding the exclude port tag for ports without port security Change-Id: Ief4a3989316f7b7097c5be6145aae169cde87e8e
This commit is contained in:
parent
ee46de95c3
commit
1f8ac3e9f6
@ -206,6 +206,10 @@ class NSXClient(object):
|
|||||||
segment_ports = self.get_os_nsx_segment_ports(segment_id)
|
segment_ports = self.get_os_nsx_segment_ports(segment_id)
|
||||||
for p in segment_ports:
|
for p in segment_ports:
|
||||||
try:
|
try:
|
||||||
|
self.nsxpolicy.segment_port_security_profiles.delete(
|
||||||
|
segment_id, p['id'])
|
||||||
|
self.nsxpolicy.segment_port_discovery_profiles.delete(
|
||||||
|
segment_id, p['id'])
|
||||||
self.nsxpolicy.segment_port.delete(segment_id, p['id'])
|
self.nsxpolicy.segment_port.delete(segment_id, p['id'])
|
||||||
except exceptions.ManagerError as e:
|
except exceptions.ManagerError as e:
|
||||||
print("Failed to delete segment port %s: %s" % (p['id'], e))
|
print("Failed to delete segment port %s: %s" % (p['id'], e))
|
||||||
|
@ -400,6 +400,16 @@ class NsxPluginV3Base(plugin.NsxPluginBase,
|
|||||||
LOG.warning(err_msg)
|
LOG.warning(err_msg)
|
||||||
raise n_exc.InvalidInput(error_message=err_msg)
|
raise n_exc.InvalidInput(error_message=err_msg)
|
||||||
|
|
||||||
|
def _assert_on_port_admin_state(self, port_data, device_owner):
|
||||||
|
"""Do not allow changing the admin state of some ports"""
|
||||||
|
if (device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF or
|
||||||
|
device_owner == l3_db.DEVICE_OWNER_ROUTER_GW):
|
||||||
|
if port_data.get("admin_state_up") is False:
|
||||||
|
err_msg = _("admin_state_up=False router ports are not "
|
||||||
|
"supported")
|
||||||
|
LOG.warning(err_msg)
|
||||||
|
raise n_exc.InvalidInput(error_message=err_msg)
|
||||||
|
|
||||||
def _validate_update_port(self, context, id, original_port, port_data):
|
def _validate_update_port(self, context, id, original_port, port_data):
|
||||||
qos_selected = validators.is_attr_set(port_data.get
|
qos_selected = validators.is_attr_set(port_data.get
|
||||||
(qos_consts.QOS_POLICY_ID))
|
(qos_consts.QOS_POLICY_ID))
|
||||||
@ -1174,3 +1184,13 @@ class NsxPluginV3Base(plugin.NsxPluginBase,
|
|||||||
super(NsxPluginV3Base, self).delete_port(context, port_id)
|
super(NsxPluginV3Base, self).delete_port(context, port_id)
|
||||||
if nsx_port_id:
|
if nsx_port_id:
|
||||||
self.nsxlib.logical_port.delete(nsx_port_id)
|
self.nsxlib.logical_port.delete(nsx_port_id)
|
||||||
|
|
||||||
|
def _is_excluded_port(self, device_owner, port_security):
|
||||||
|
if device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF:
|
||||||
|
return False
|
||||||
|
if device_owner == constants.DEVICE_OWNER_DHCP:
|
||||||
|
if not self._has_native_dhcp_metadata():
|
||||||
|
return True
|
||||||
|
elif not port_security:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
@ -68,6 +68,7 @@ from vmware_nsx.common import utils
|
|||||||
from vmware_nsx.db import db as nsx_db
|
from vmware_nsx.db import db as nsx_db
|
||||||
from vmware_nsx.db import extended_security_group_rule as extend_sg_rule
|
from vmware_nsx.db import extended_security_group_rule as extend_sg_rule
|
||||||
from vmware_nsx.db import maclearning as mac_db
|
from vmware_nsx.db import maclearning as mac_db
|
||||||
|
from vmware_nsx.extensions import maclearning as mac_ext
|
||||||
from vmware_nsx.extensions import projectpluginmap
|
from vmware_nsx.extensions import projectpluginmap
|
||||||
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
||||||
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as sg_prefix
|
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as sg_prefix
|
||||||
@ -80,6 +81,7 @@ from vmware_nsxlib.v3 import exceptions as nsx_lib_exc
|
|||||||
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
||||||
from vmware_nsxlib.v3 import policy_constants
|
from vmware_nsxlib.v3 import policy_constants
|
||||||
from vmware_nsxlib.v3 import policy_defs
|
from vmware_nsxlib.v3 import policy_defs
|
||||||
|
from vmware_nsxlib.v3 import security
|
||||||
from vmware_nsxlib.v3 import utils as nsxlib_utils
|
from vmware_nsxlib.v3 import utils as nsxlib_utils
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
@ -97,7 +99,8 @@ NSX_P_PROVIDER_SECTION_CATEGORY = policy_constants.CATEGORY_INFRASTRUCTURE
|
|||||||
SPOOFGUARD_PROFILE_UUID = 'neutron-spoofguard-profile'
|
SPOOFGUARD_PROFILE_UUID = 'neutron-spoofguard-profile'
|
||||||
NO_SPOOFGUARD_PROFILE_UUID = policy_defs.SpoofguardProfileDef.DEFAULT_PROFILE
|
NO_SPOOFGUARD_PROFILE_UUID = policy_defs.SpoofguardProfileDef.DEFAULT_PROFILE
|
||||||
MAC_DISCOVERY_PROFILE_UUID = 'neutron-mac-discovery-profile'
|
MAC_DISCOVERY_PROFILE_UUID = 'neutron-mac-discovery-profile'
|
||||||
NO_SEG_SECURITY_PROFILE_UUID = (
|
NO_SEG_SECURITY_PROFILE_UUID = 'neutron-no-segment-security-profile'
|
||||||
|
SEG_SECURITY_PROFILE_UUID = (
|
||||||
policy_defs.SegmentSecurityProfileDef.DEFAULT_PROFILE)
|
policy_defs.SegmentSecurityProfileDef.DEFAULT_PROFILE)
|
||||||
|
|
||||||
|
|
||||||
@ -141,7 +144,8 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
"security-group-logging",
|
"security-group-logging",
|
||||||
"provider-security-group",
|
"provider-security-group",
|
||||||
"port-security-groups-filtering",
|
"port-security-groups-filtering",
|
||||||
"vlan-transparent"]
|
"vlan-transparent",
|
||||||
|
'mac-learning']
|
||||||
|
|
||||||
@resource_registry.tracked_resources(
|
@resource_registry.tracked_resources(
|
||||||
network=models_v2.Network,
|
network=models_v2.Network,
|
||||||
@ -284,14 +288,32 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
mac_learning_enabled=True,
|
mac_learning_enabled=True,
|
||||||
tags=self.nsxpolicy.build_v3_api_version_tag())
|
tags=self.nsxpolicy.build_v3_api_version_tag())
|
||||||
|
|
||||||
# No Port security segment-security profile
|
# No Port security segment-security profile (find it or create)
|
||||||
# (default NSX profile. just verify it exists)
|
|
||||||
try:
|
try:
|
||||||
self.nsxpolicy.segment_security_profile.get(
|
self.nsxpolicy.segment_security_profile.get(
|
||||||
NO_SEG_SECURITY_PROFILE_UUID)
|
NO_SEG_SECURITY_PROFILE_UUID)
|
||||||
|
except nsx_lib_exc.ResourceNotFound:
|
||||||
|
self.nsxpolicy.segment_security_profile.create_or_overwrite(
|
||||||
|
NO_SEG_SECURITY_PROFILE_UUID,
|
||||||
|
profile_id=NO_SEG_SECURITY_PROFILE_UUID,
|
||||||
|
bpdu_filter_enable=False,
|
||||||
|
dhcp_client_block_enabled=False,
|
||||||
|
dhcp_client_block_v6_enabled=False,
|
||||||
|
dhcp_server_block_enabled=False,
|
||||||
|
dhcp_server_block_v6_enabled=False,
|
||||||
|
non_ip_traffic_block_enabled=False,
|
||||||
|
ra_guard_enabled=False,
|
||||||
|
rate_limits_enabled=False,
|
||||||
|
tags=self.nsxpolicy.build_v3_api_version_tag())
|
||||||
|
|
||||||
|
# Port security segment-security profile
|
||||||
|
# (default NSX profile. just verify it exists)
|
||||||
|
try:
|
||||||
|
self.nsxpolicy.segment_security_profile.get(
|
||||||
|
SEG_SECURITY_PROFILE_UUID)
|
||||||
except nsx_lib_exc.ResourceNotFound:
|
except nsx_lib_exc.ResourceNotFound:
|
||||||
msg = (_("Cannot find segment security profile %s") %
|
msg = (_("Cannot find segment security profile %s") %
|
||||||
NO_SEG_SECURITY_PROFILE_UUID)
|
SEG_SECURITY_PROFILE_UUID)
|
||||||
raise nsx_exc.NsxPluginException(err_msg=msg)
|
raise nsx_exc.NsxPluginException(err_msg=msg)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -613,10 +635,9 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
|
|
||||||
return tags
|
return tags
|
||||||
|
|
||||||
def _create_port_on_backend(self, context, port_data):
|
def _create_port_on_backend(self, context, port_data, is_psec_on):
|
||||||
# TODO(annak): admin_state not supported by policy
|
# TODO(annak): admin_state not supported by policy
|
||||||
# TODO(annak): handle exclude list
|
# TODO(annak): handle exclude list
|
||||||
# TODO(annak): switching profiles when supported
|
|
||||||
name = self._build_port_name(context, port_data)
|
name = self._build_port_name(context, port_data)
|
||||||
address_bindings = self._build_port_address_bindings(
|
address_bindings = self._build_port_address_bindings(
|
||||||
context, port_data)
|
context, port_data)
|
||||||
@ -632,6 +653,10 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
tags.extend(self.nsxpolicy.build_v3_api_version_project_tag(
|
tags.extend(self.nsxpolicy.build_v3_api_version_project_tag(
|
||||||
context.tenant_name))
|
context.tenant_name))
|
||||||
|
|
||||||
|
if self._is_excluded_port(device_owner, is_psec_on):
|
||||||
|
tags.append({'scope': security.PORT_SG_SCOPE,
|
||||||
|
'tag': nsxlib_consts.EXCLUDE_PORT})
|
||||||
|
|
||||||
segment_id = self._get_network_nsx_segment_id(
|
segment_id = self._get_network_nsx_segment_id(
|
||||||
context, port_data['network_id'])
|
context, port_data['network_id'])
|
||||||
self.nsxpolicy.segment_port.create_or_overwrite(
|
self.nsxpolicy.segment_port.create_or_overwrite(
|
||||||
@ -643,6 +668,34 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
attachment_type=attachment_type,
|
attachment_type=attachment_type,
|
||||||
tags=tags)
|
tags=tags)
|
||||||
|
|
||||||
|
# add the security profiles to the port
|
||||||
|
if is_psec_on:
|
||||||
|
spoofguard_profile = SPOOFGUARD_PROFILE_UUID
|
||||||
|
seg_sec_profile = SEG_SECURITY_PROFILE_UUID
|
||||||
|
else:
|
||||||
|
spoofguard_profile = NO_SPOOFGUARD_PROFILE_UUID
|
||||||
|
seg_sec_profile = NO_SEG_SECURITY_PROFILE_UUID
|
||||||
|
self.nsxpolicy.segment_port_security_profiles.create_or_overwrite(
|
||||||
|
name, segment_id, port_data['id'],
|
||||||
|
spoofguard_profile_id=spoofguard_profile,
|
||||||
|
segment_security_profile_id=seg_sec_profile)
|
||||||
|
|
||||||
|
# add the mac discovery profile to the port
|
||||||
|
mac_discovery_profile = None
|
||||||
|
mac_disc_profile_must = False
|
||||||
|
if is_psec_on:
|
||||||
|
address_pairs = port_data.get(addr_apidef.ADDRESS_PAIRS)
|
||||||
|
if validators.is_attr_set(address_pairs) and address_pairs:
|
||||||
|
mac_disc_profile_must = True
|
||||||
|
mac_learning_enabled = (
|
||||||
|
validators.is_attr_set(port_data.get(mac_ext.MAC_LEARNING)) and
|
||||||
|
port_data.get(mac_ext.MAC_LEARNING) is True)
|
||||||
|
if mac_disc_profile_must or mac_learning_enabled:
|
||||||
|
mac_discovery_profile = MAC_DISCOVERY_PROFILE_UUID
|
||||||
|
self.nsxpolicy.segment_port_discovery_profiles.create_or_overwrite(
|
||||||
|
name, segment_id, port_data['id'],
|
||||||
|
mac_discovery_profile_id=mac_discovery_profile)
|
||||||
|
|
||||||
def base_create_port(self, context, port):
|
def base_create_port(self, context, port):
|
||||||
neutron_db = super(NsxPolicyPlugin, self).create_port(context, port)
|
neutron_db = super(NsxPolicyPlugin, self).create_port(context, port)
|
||||||
self._extension_manager.process_create_port(
|
self._extension_manager.process_create_port(
|
||||||
@ -680,11 +733,25 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
self._process_port_create_security_group(context, port_data, sgids)
|
self._process_port_create_security_group(context, port_data, sgids)
|
||||||
self._process_port_create_provider_security_group(
|
self._process_port_create_provider_security_group(
|
||||||
context, port_data, psgids)
|
context, port_data, psgids)
|
||||||
#TODO(asarfaty): Handle mac learning
|
|
||||||
|
# Handle port mac learning
|
||||||
|
if validators.is_attr_set(port_data.get(mac_ext.MAC_LEARNING)):
|
||||||
|
# Make sure mac_learning and port sec are not both enabled
|
||||||
|
if port_data.get(mac_ext.MAC_LEARNING) and is_psec_on:
|
||||||
|
msg = _('Mac learning requires that port security be '
|
||||||
|
'disabled')
|
||||||
|
LOG.error(msg)
|
||||||
|
raise n_exc.InvalidInput(error_message=msg)
|
||||||
|
# save the mac learning value in the DB
|
||||||
|
self._create_mac_learning_state(context, port_data)
|
||||||
|
elif mac_ext.MAC_LEARNING in port_data:
|
||||||
|
# This is due to the fact that the default is
|
||||||
|
# ATTR_NOT_SPECIFIED
|
||||||
|
port_data.pop(mac_ext.MAC_LEARNING)
|
||||||
|
|
||||||
if not is_external_net:
|
if not is_external_net:
|
||||||
try:
|
try:
|
||||||
self._create_port_on_backend(context, port_data)
|
self._create_port_on_backend(context, port_data, is_psec_on)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
LOG.error('Failed to create port %(id)s on NSX '
|
LOG.error('Failed to create port %(id)s on NSX '
|
||||||
@ -721,17 +788,22 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
if not self._network_is_external(context, net_id):
|
if not self._network_is_external(context, net_id):
|
||||||
try:
|
try:
|
||||||
segment_id = self._get_network_nsx_segment_id(context, net_id)
|
segment_id = self._get_network_nsx_segment_id(context, net_id)
|
||||||
self.nsxpolicy.segment_port.delete(segment_id, port_data['id'])
|
self.nsxpolicy.segment_port_security_profiles.delete(
|
||||||
|
segment_id, port_id)
|
||||||
|
self.nsxpolicy.segment_port_discovery_profiles.delete(
|
||||||
|
segment_id, port_id)
|
||||||
|
self.nsxpolicy.segment_port.delete(segment_id, port_id)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
LOG.error("Failed to delete port %(id)s on NSX backend "
|
LOG.error("Failed to delete port %(id)s on NSX backend "
|
||||||
"due to %(e)s", {'id': port_id, 'e': ex})
|
"due to %(e)s", {'id': port_id, 'e': ex})
|
||||||
# Do not fail the neutron action
|
# Do not fail the neutron action
|
||||||
|
|
||||||
def _update_port_on_backend(self, context, lport_id,
|
def _update_port_on_backend(self, context, lport_id,
|
||||||
original_port, updated_port):
|
original_port, updated_port,
|
||||||
|
is_psec_on):
|
||||||
# For now port create and update are the same
|
# For now port create and update are the same
|
||||||
# Update might evolve with more features
|
# Update might evolve with more features
|
||||||
return self._create_port_on_backend(context, updated_port)
|
return self._create_port_on_backend(context, updated_port, is_psec_on)
|
||||||
|
|
||||||
def update_port(self, context, port_id, port):
|
def update_port(self, context, port_id, port):
|
||||||
with db_api.CONTEXT_WRITER.using(context):
|
with db_api.CONTEXT_WRITER.using(context):
|
||||||
@ -740,6 +812,8 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
original_port = super(NsxPolicyPlugin, self).get_port(
|
original_port = super(NsxPolicyPlugin, self).get_port(
|
||||||
context, port_id)
|
context, port_id)
|
||||||
port_data = port['port']
|
port_data = port['port']
|
||||||
|
self._validate_update_port(context, port_id, original_port,
|
||||||
|
port_data)
|
||||||
validate_port_sec = self._should_validate_port_sec_on_update_port(
|
validate_port_sec = self._should_validate_port_sec_on_update_port(
|
||||||
port_data)
|
port_data)
|
||||||
is_external_net = self._network_is_external(
|
is_external_net = self._network_is_external(
|
||||||
@ -784,14 +858,23 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
vif_type=self._vif_type_by_vnic_type(direct_vnic_type))
|
vif_type=self._vif_type_by_vnic_type(direct_vnic_type))
|
||||||
self._extend_nsx_port_dict_binding(context, updated_port)
|
self._extend_nsx_port_dict_binding(context, updated_port)
|
||||||
|
|
||||||
#TODO(asarfaty): Handle mac learning
|
mac_learning_state = updated_port.get(mac_ext.MAC_LEARNING)
|
||||||
|
if mac_learning_state is not None:
|
||||||
|
if port_security and mac_learning_state:
|
||||||
|
msg = _('Mac learning requires that port security be '
|
||||||
|
'disabled')
|
||||||
|
LOG.error(msg)
|
||||||
|
raise n_exc.InvalidInput(error_message=msg)
|
||||||
|
self._update_mac_learning_state(context, port_id,
|
||||||
|
mac_learning_state)
|
||||||
|
|
||||||
# update the port in the backend, only if it exists in the DB
|
# update the port in the backend, only if it exists in the DB
|
||||||
# (i.e not external net)
|
# (i.e not external net)
|
||||||
if not is_external_net:
|
if not is_external_net:
|
||||||
try:
|
try:
|
||||||
self._update_port_on_backend(context, port_id,
|
self._update_port_on_backend(context, port_id,
|
||||||
original_port, updated_port)
|
original_port, updated_port,
|
||||||
|
port_security)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.error('Failed to update port %(id)s on NSX '
|
LOG.error('Failed to update port %(id)s on NSX '
|
||||||
'backend. Exception: %(e)s',
|
'backend. Exception: %(e)s',
|
||||||
|
@ -1842,16 +1842,6 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
LOG.error(err_msg)
|
LOG.error(err_msg)
|
||||||
raise n_exc.InvalidInput(error_message=err_msg)
|
raise n_exc.InvalidInput(error_message=err_msg)
|
||||||
|
|
||||||
def _is_excluded_port(self, device_owner, port_security):
|
|
||||||
if device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF:
|
|
||||||
return False
|
|
||||||
if device_owner == const.DEVICE_OWNER_DHCP:
|
|
||||||
if not cfg.CONF.nsx_v3.native_dhcp_metadata:
|
|
||||||
return True
|
|
||||||
elif not port_security:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _create_port_at_the_backend(self, context, port_data,
|
def _create_port_at_the_backend(self, context, port_data,
|
||||||
l2gw_port_check, psec_is_on,
|
l2gw_port_check, psec_is_on,
|
||||||
is_ens_tz_port):
|
is_ens_tz_port):
|
||||||
@ -2077,16 +2067,6 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
LOG.warning(err_msg)
|
LOG.warning(err_msg)
|
||||||
raise n_exc.InvalidInput(error_message=err_msg)
|
raise n_exc.InvalidInput(error_message=err_msg)
|
||||||
|
|
||||||
def _assert_on_port_admin_state(self, port_data, device_owner):
|
|
||||||
"""Do not allow changing the admin state of some ports"""
|
|
||||||
if (device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF or
|
|
||||||
device_owner == l3_db.DEVICE_OWNER_ROUTER_GW):
|
|
||||||
if port_data.get("admin_state_up") is False:
|
|
||||||
err_msg = _("admin_state_up=False router ports are not "
|
|
||||||
"supported")
|
|
||||||
LOG.warning(err_msg)
|
|
||||||
raise n_exc.InvalidInput(error_message=err_msg)
|
|
||||||
|
|
||||||
def _filter_ipv4_dhcp_fixed_ips(self, context, fixed_ips):
|
def _filter_ipv4_dhcp_fixed_ips(self, context, fixed_ips):
|
||||||
ips = []
|
ips = []
|
||||||
for fixed_ip in fixed_ips:
|
for fixed_ip in fixed_ips:
|
||||||
|
@ -34,6 +34,7 @@ from neutron_lib.callbacks import registry
|
|||||||
from neutron_lib.callbacks import resources
|
from neutron_lib.callbacks import resources
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
from neutron_lib import context
|
from neutron_lib import context
|
||||||
|
from neutron_lib import exceptions as n_exc
|
||||||
from neutron_lib.plugins import directory
|
from neutron_lib.plugins import directory
|
||||||
|
|
||||||
from vmware_nsx.common import utils
|
from vmware_nsx.common import utils
|
||||||
@ -402,6 +403,141 @@ class NsxPTestPorts(test_db_base_plugin_v2.TestPortsV2,
|
|||||||
self.assertEqual(res['port']['fixed_ips'],
|
self.assertEqual(res['port']['fixed_ips'],
|
||||||
data['port']['fixed_ips'])
|
data['port']['fixed_ips'])
|
||||||
|
|
||||||
|
def test_create_port_with_mac_learning_true(self):
|
||||||
|
plugin = directory.get_plugin()
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
with self.network() as network:
|
||||||
|
data = {'port': {
|
||||||
|
'network_id': network['network']['id'],
|
||||||
|
'tenant_id': self._tenant_id,
|
||||||
|
'name': 'qos_port',
|
||||||
|
'admin_state_up': True,
|
||||||
|
'device_id': 'fake_device',
|
||||||
|
'device_owner': 'fake_owner',
|
||||||
|
'fixed_ips': [],
|
||||||
|
'port_security_enabled': False,
|
||||||
|
'mac_address': '00:00:00:00:00:01',
|
||||||
|
'mac_learning_enabled': True}
|
||||||
|
}
|
||||||
|
port = plugin.create_port(ctx, data)
|
||||||
|
self.assertTrue(port['mac_learning_enabled'])
|
||||||
|
|
||||||
|
def test_create_port_with_mac_learning_false(self):
|
||||||
|
plugin = directory.get_plugin()
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
with self.network() as network:
|
||||||
|
data = {'port': {
|
||||||
|
'network_id': network['network']['id'],
|
||||||
|
'tenant_id': self._tenant_id,
|
||||||
|
'name': 'qos_port',
|
||||||
|
'admin_state_up': True,
|
||||||
|
'device_id': 'fake_device',
|
||||||
|
'device_owner': 'fake_owner',
|
||||||
|
'fixed_ips': [],
|
||||||
|
'port_security_enabled': False,
|
||||||
|
'mac_address': '00:00:00:00:00:01',
|
||||||
|
'mac_learning_enabled': False}
|
||||||
|
}
|
||||||
|
port = plugin.create_port(ctx, data)
|
||||||
|
self.assertFalse(port['mac_learning_enabled'])
|
||||||
|
|
||||||
|
def test_update_port_with_mac_learning_true(self):
|
||||||
|
plugin = directory.get_plugin()
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
with self.network() as network:
|
||||||
|
data = {'port': {
|
||||||
|
'network_id': network['network']['id'],
|
||||||
|
'tenant_id': self._tenant_id,
|
||||||
|
'name': 'qos_port',
|
||||||
|
'admin_state_up': True,
|
||||||
|
'device_id': 'fake_device',
|
||||||
|
'device_owner': 'fake_owner',
|
||||||
|
'fixed_ips': [],
|
||||||
|
'port_security_enabled': False,
|
||||||
|
'mac_address': '00:00:00:00:00:01'}
|
||||||
|
}
|
||||||
|
port = plugin.create_port(ctx, data)
|
||||||
|
data['port']['mac_learning_enabled'] = True
|
||||||
|
update_res = plugin.update_port(ctx, port['id'], data)
|
||||||
|
self.assertTrue(update_res['mac_learning_enabled'])
|
||||||
|
|
||||||
|
def test_update_port_with_mac_learning_false(self):
|
||||||
|
plugin = directory.get_plugin()
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
with self.network() as network:
|
||||||
|
data = {'port': {
|
||||||
|
'network_id': network['network']['id'],
|
||||||
|
'tenant_id': self._tenant_id,
|
||||||
|
'name': 'qos_port',
|
||||||
|
'admin_state_up': True,
|
||||||
|
'device_id': 'fake_device',
|
||||||
|
'device_owner': 'fake_owner',
|
||||||
|
'fixed_ips': [],
|
||||||
|
'port_security_enabled': False,
|
||||||
|
'mac_address': '00:00:00:00:00:01'}
|
||||||
|
}
|
||||||
|
port = plugin.create_port(ctx, data)
|
||||||
|
data['port']['mac_learning_enabled'] = False
|
||||||
|
update_res = plugin.update_port(ctx, port['id'], data)
|
||||||
|
self.assertFalse(update_res['mac_learning_enabled'])
|
||||||
|
|
||||||
|
def test_update_port_with_mac_learning_failes(self):
|
||||||
|
plugin = directory.get_plugin()
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
with self.network() as network:
|
||||||
|
data = {'port': {
|
||||||
|
'network_id': network['network']['id'],
|
||||||
|
'tenant_id': self._tenant_id,
|
||||||
|
'name': 'qos_port',
|
||||||
|
'admin_state_up': True,
|
||||||
|
'device_id': 'fake_device',
|
||||||
|
'device_owner': constants.DEVICE_OWNER_FLOATINGIP,
|
||||||
|
'fixed_ips': [],
|
||||||
|
'port_security_enabled': False,
|
||||||
|
'mac_address': '00:00:00:00:00:01'}
|
||||||
|
}
|
||||||
|
port = plugin.create_port(ctx, data)
|
||||||
|
data['port']['mac_learning_enabled'] = True
|
||||||
|
self.assertRaises(
|
||||||
|
n_exc.InvalidInput,
|
||||||
|
plugin.update_port, ctx, port['id'], data)
|
||||||
|
|
||||||
|
def _create_l3_ext_network(
|
||||||
|
self, physical_network=DEFAULT_TIER0_ROUTER_UUID):
|
||||||
|
name = 'l3_ext_net'
|
||||||
|
net_type = utils.NetworkTypes.L3_EXT
|
||||||
|
providernet_args = {pnet.NETWORK_TYPE: net_type,
|
||||||
|
pnet.PHYSICAL_NETWORK: physical_network}
|
||||||
|
return self.network(name=name,
|
||||||
|
router__external=True,
|
||||||
|
providernet_args=providernet_args,
|
||||||
|
arg_list=(pnet.NETWORK_TYPE,
|
||||||
|
pnet.PHYSICAL_NETWORK))
|
||||||
|
|
||||||
|
def test_fail_create_port_with_ext_net(self):
|
||||||
|
expected_error = 'InvalidInput'
|
||||||
|
with self._create_l3_ext_network() as network:
|
||||||
|
with self.subnet(network=network, cidr='10.0.0.0/24'):
|
||||||
|
device_owner = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'X'
|
||||||
|
res = self._create_port(self.fmt,
|
||||||
|
network['network']['id'],
|
||||||
|
exc.HTTPBadRequest.code,
|
||||||
|
device_owner=device_owner)
|
||||||
|
data = self.deserialize(self.fmt, res)
|
||||||
|
self.assertEqual(expected_error, data['NeutronError']['type'])
|
||||||
|
|
||||||
|
def test_fail_update_port_with_ext_net(self):
|
||||||
|
with self._create_l3_ext_network() as network:
|
||||||
|
with self.subnet(network=network, cidr='10.0.0.0/24') as subnet:
|
||||||
|
with self.port(subnet=subnet) as port:
|
||||||
|
device_owner = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'X'
|
||||||
|
data = {'port': {'device_owner': device_owner}}
|
||||||
|
req = self.new_update_request('ports',
|
||||||
|
data, port['port']['id'])
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
self.assertEqual(exc.HTTPBadRequest.code,
|
||||||
|
res.status_int)
|
||||||
|
|
||||||
|
|
||||||
class NsxPTestSecurityGroup(NsxPPluginTestCaseMixin,
|
class NsxPTestSecurityGroup(NsxPPluginTestCaseMixin,
|
||||||
test_securitygroup.TestSecurityGroups,
|
test_securitygroup.TestSecurityGroups,
|
||||||
|
Loading…
Reference in New Issue
Block a user