Remove Tap-as-a-service Support
The platform support will be changing so we will remove this in the mean time. The patch also remove false positives for test failures. Change-Id: I118010085d305883f521fa01a5fd341e775eea5a
This commit is contained in:
parent
c76464dac3
commit
3759da2874
@ -141,15 +141,3 @@ Enable trunk service and configure following flags in ``local.conf``::
|
||||
# Trunk plugin NSXv3 driver config
|
||||
ENABLED_SERVICES+=,q-trunk
|
||||
Q_SERVICE_PLUGIN_CLASSES=trunk
|
||||
|
||||
TaaS Driver
|
||||
~~~~~~~~~~~
|
||||
|
||||
Add tap-as-a-service repo as an external repository and configure following flags in ``local.conf``::
|
||||
|
||||
[[local]|[localrc]]
|
||||
# TaaS plugin NSXv3 driver config
|
||||
enable_plugin tap-as-a-service https://github.com/openstack/tap-as-a-service
|
||||
enable_service taas
|
||||
TAAS_SERVICE_DRIVER=TAAS:vmware_nsx_taas:vmware_nsx.services.neutron_taas.nsx_v3.driver.NsxV3Driver:default
|
||||
|
||||
|
@ -7,7 +7,6 @@ ${DIR}/tox_install_project.sh neutron neutron $*
|
||||
${DIR}/tox_install_project.sh networking-l2gw networking_l2gw $*
|
||||
${DIR}/tox_install_project.sh networking-sfc networking_sfc $*
|
||||
${DIR}/tox_install_project.sh neutron-lbaas neutron_lbaas $*
|
||||
${DIR}/tox_install_project.sh tap-as-a-service neutron_taas $*
|
||||
${DIR}/tox_install_project.sh vmware-nsxlib vmware_nsxlib $*
|
||||
|
||||
CONSTRAINTS_FILE=$1
|
||||
|
@ -1,375 +0,0 @@
|
||||
# Copyright 2016 VMware, Inc.
|
||||
#
|
||||
# All Rights Reserved
|
||||
#
|
||||
# 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.
|
||||
|
||||
import netaddr
|
||||
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron_taas.db import taas_db
|
||||
from neutron_taas.services.taas import service_drivers as base_driver
|
||||
|
||||
from oslo_db import exception as db_exc
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from vmware_nsx._i18n import _, _LE, _LW
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
|
||||
from vmware_nsxlib import v3 as nsxlib
|
||||
from vmware_nsxlib.v3 import exceptions as nsxlib_exc
|
||||
from vmware_nsxlib.v3 import resources as nsx_resources
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NsxV3Driver(base_driver.TaasBaseDriver,
|
||||
taas_db.Taas_db_Mixin):
|
||||
|
||||
"""Class to handle API calls for Port Mirroring and NSXv3 backend."""
|
||||
|
||||
def __init__(self, service_plugin):
|
||||
LOG.debug("Loading TaaS NsxV3Driver.")
|
||||
super(NsxV3Driver, self).__init__(service_plugin)
|
||||
|
||||
@property
|
||||
def _nsx_plugin(self):
|
||||
return directory.get_plugin()
|
||||
|
||||
def _validate_tap_flow(self, source_port, dest_port):
|
||||
# Verify whether the source port is not same as the destination port
|
||||
if source_port['id'] == dest_port['id']:
|
||||
msg = (_("Destination port %(dest)s is same as source port "
|
||||
"%(src)s") % {'dest': dest_port['id'],
|
||||
'src': source_port['id']})
|
||||
raise nsx_exc.NsxTaaSDriverException(msg=msg)
|
||||
|
||||
def create_tap_service_precommit(self, context):
|
||||
pass
|
||||
|
||||
def create_tap_service_postcommit(self, context):
|
||||
pass
|
||||
|
||||
def delete_tap_service_precommit(self, context):
|
||||
pass
|
||||
|
||||
def delete_tap_service_postcommit(self, context):
|
||||
pass
|
||||
|
||||
def create_tap_flow_precommit(self, context):
|
||||
"""Validate and create database entries for creation of tap flow."""
|
||||
tf = context.tap_flow
|
||||
# Retrieve source port details.
|
||||
source_port = self._get_port_details(
|
||||
context._plugin_context, tf.get('source_port'))
|
||||
# Retrieve tap service and destination port details.
|
||||
ts = self._get_tap_service(
|
||||
context._plugin_context, tf.get('tap_service_id'))
|
||||
dest_port = self._get_port_details(
|
||||
context._plugin_context, ts.get('port_id'))
|
||||
self._validate_tap_flow(source_port, dest_port)
|
||||
|
||||
def _convert_to_backend_direction(self, direction):
|
||||
nsx_direction = None
|
||||
if direction == 'BOTH':
|
||||
nsx_direction = 'BIDIRECTIONAL'
|
||||
elif direction == 'IN':
|
||||
nsx_direction = 'INGRESS'
|
||||
elif direction == 'OUT':
|
||||
nsx_direction = 'EGRESS'
|
||||
return nsx_direction
|
||||
|
||||
def _convert_to_backend_source_port(self, session, port_id):
|
||||
nsx_port_id = nsx_db.get_nsx_switch_and_port_id(session, port_id)[1]
|
||||
return [{"resource_type": "LogicalPortMirrorSource",
|
||||
"port_ids": [nsx_port_id]}]
|
||||
|
||||
def _convert_to_backend_dest_port(self, session, port_id):
|
||||
nsx_port_id = nsx_db.get_nsx_switch_and_port_id(session, port_id)[1]
|
||||
return {"resource_type": "LogicalPortMirrorDestination",
|
||||
"port_ids": [nsx_port_id]}
|
||||
|
||||
def _is_local_span(self, context, src_port_id, dest_port_id):
|
||||
"""Verify whether the mirror session is Local or L3SPAN."""
|
||||
# TODO(abhiraut): Create only L3SPAN until we find a way to
|
||||
# detect local SPAN support from backend.
|
||||
return False
|
||||
|
||||
def _update_port_at_backend(self, context, port_id, switching_profile,
|
||||
delete_profile):
|
||||
"""Update a logical port on the backend."""
|
||||
port = self._get_port_details(context._plugin_context,
|
||||
port_id)
|
||||
# Retrieve logical port ID based on neutron port ID.
|
||||
nsx_port_id = nsx_db.get_nsx_switch_and_port_id(
|
||||
session=context._plugin_context.session,
|
||||
neutron_id=port_id)[1]
|
||||
# Retrieve source logical port from the backend.
|
||||
nsx_port = self._nsx_plugin._port_client.get(nsx_port_id)
|
||||
if delete_profile:
|
||||
# Prepare switching profile resources retrieved from backend
|
||||
# and pop the port mirror switching profile.
|
||||
switching_profile_ids = self._prepare_switch_profiles(
|
||||
nsx_port.get('switching_profile_ids', []),
|
||||
switching_profile)
|
||||
else:
|
||||
# Prepare switching profile resources retrieved from backend.
|
||||
switching_profile_ids = self._prepare_switch_profiles(
|
||||
nsx_port.get('switching_profile_ids', []))
|
||||
# Update body with PortMirroring switching profile.
|
||||
switching_profile_ids.append(
|
||||
self._get_switching_profile_resource(
|
||||
switching_profile['id'],
|
||||
nsx_resources.SwitchingProfileTypes.PORT_MIRRORING))
|
||||
address_bindings = self._nsx_plugin._build_address_bindings(port)
|
||||
#NOTE(abhiraut): Consider passing attachment_type
|
||||
self._nsx_plugin._port_client.update(
|
||||
lport_id=nsx_port.get('id'),
|
||||
vif_uuid=port_id,
|
||||
name=nsx_port.get('display_name'),
|
||||
admin_state=nsx_port.get('admin_state'),
|
||||
address_bindings=address_bindings,
|
||||
switch_profile_ids=switching_profile_ids,)
|
||||
|
||||
def _prepare_switch_profiles(self, profiles, deleted_profile=None):
|
||||
switch_profile_ids = []
|
||||
if not deleted_profile:
|
||||
for profile in profiles:
|
||||
# profile is a dict of type {'key': profile_type,
|
||||
# 'value': profile_id}
|
||||
profile_resource = self._get_switching_profile_resource(
|
||||
profile_id=profile['value'],
|
||||
profile_type=profile['key'])
|
||||
switch_profile_ids.append(profile_resource)
|
||||
else:
|
||||
for profile in profiles:
|
||||
if profile['value'] == deleted_profile['id']:
|
||||
continue
|
||||
profile_resource = self._get_switching_profile_resource(
|
||||
profile_id=profile['value'],
|
||||
profile_type=profile['key'])
|
||||
switch_profile_ids.append(profile_resource)
|
||||
return switch_profile_ids
|
||||
|
||||
def _get_switching_profile_resource(self, profile_id, profile_type):
|
||||
return nsx_resources.SwitchingProfileTypeId(
|
||||
profile_type=profile_type,
|
||||
profile_id=profile_id)
|
||||
|
||||
def create_tap_flow_postcommit(self, context):
|
||||
"""Create tap flow and port mirror session on NSX backend."""
|
||||
tf = context.tap_flow
|
||||
# Retrieve tap service.
|
||||
ts = self._get_tap_service(context._plugin_context,
|
||||
tf.get('tap_service_id'))
|
||||
src_port_id = tf.get('source_port')
|
||||
dest_port_id = ts.get('port_id')
|
||||
nsxlib = v3_utils.get_nsxlib_wrapper()
|
||||
tags = nsxlib.build_v3_tags_payload(
|
||||
tf, resource_type='os-neutron-mirror-id',
|
||||
project_name=context._plugin_context.tenant_name)
|
||||
nsx_direction = self._convert_to_backend_direction(
|
||||
tf.get('direction'))
|
||||
# Create a port mirroring session object if local SPAN. Otherwise
|
||||
# create a port mirroring switching profile for L3SPAN.
|
||||
if self._is_local_span(context, src_port_id, dest_port_id):
|
||||
self._create_local_span(context, src_port_id, dest_port_id,
|
||||
nsx_direction, tags)
|
||||
else:
|
||||
self._create_l3span(context, src_port_id, dest_port_id,
|
||||
nsx_direction, tags)
|
||||
|
||||
def _create_l3span(self, context, src_port_id, dest_port_id, direction,
|
||||
tags):
|
||||
"""Create a PortMirroring SwitchingProfile for L3SPAN."""
|
||||
tf = context.tap_flow
|
||||
# Verify whether destination port is L3 reachable. i.e. destination
|
||||
# port has a floating IP address.
|
||||
fips = self._nsx_plugin.get_floatingips(
|
||||
context._plugin_context, filters={'port_id': [dest_port_id]})
|
||||
if not fips:
|
||||
msg = (_("Destination port %s must have a floating IP for "
|
||||
"L3 SPAN") % dest_port_id)
|
||||
raise nsx_exc.NsxTaaSDriverException(msg=msg)
|
||||
destinations = []
|
||||
# Retrieve destination port's IP addresses and add it to the list
|
||||
# since the backend expects a list of IP addresses.
|
||||
for fip in fips:
|
||||
# NOTE(abhiraut): nsx-v3 doesn't seem to handle ipv6 addresses
|
||||
# currently so for now we remove them here and do not pass
|
||||
# them to the backend which would raise an error.
|
||||
if netaddr.IPNetwork(fip['floating_ip_address']).version == 6:
|
||||
LOG.warning(_LW("Skipping IPv6 address %(ip)s for L3SPAN "
|
||||
"tap flow: %(tap_flow)s"),
|
||||
{'tap_flow': tf['id'],
|
||||
'ip': fip['floating_ip_address']})
|
||||
continue
|
||||
destinations.append(fip['floating_ip_address'])
|
||||
# Create a switch profile in the backend.
|
||||
try:
|
||||
port_mirror_profile = (self._nsx_plugin._switching_profiles.
|
||||
create_port_mirror_profile(
|
||||
display_name=tf.get('name'),
|
||||
description=tf.get('description'),
|
||||
direction=direction,
|
||||
destinations=destinations,
|
||||
tags=tags))
|
||||
except nsxlib_exc.ManagerError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Unable to create port mirror switch profile "
|
||||
"for tap flow %s on NSX backend, rolling back "
|
||||
"changes on neutron."), tf['id'])
|
||||
# Create internal mappings between tap flow and port mirror switch
|
||||
# profile. Ideally DB transactions must take place in precommit, but
|
||||
# we rely on the NSX backend to retrieve the port mirror profile UUID,
|
||||
# we perform the create action in postcommit.
|
||||
try:
|
||||
nsx_db.add_port_mirror_session_mapping(
|
||||
session=context._plugin_context.session,
|
||||
tf_id=tf['id'],
|
||||
pm_session_id=port_mirror_profile['id'])
|
||||
except db_exc.DBError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Unable to create port mirror session db "
|
||||
"mappings for tap flow %s. Rolling back "
|
||||
"changes in Neutron."), tf['id'])
|
||||
self._nsx_plugin._switching_profiles.delete(
|
||||
port_mirror_profile['id'])
|
||||
# Update the source port to include the port mirror switch profile.
|
||||
try:
|
||||
self._update_port_at_backend(context=context, port_id=src_port_id,
|
||||
switching_profile=port_mirror_profile,
|
||||
delete_profile=False)
|
||||
except nsxlib_exc.ManagerError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Unable to update source port %(port)s with "
|
||||
"switching profile %(profile) for tap flow "
|
||||
"%(tap_flow)s on NSX backend, rolling back "
|
||||
"changes on neutron."),
|
||||
{'tap_flow': tf['id'],
|
||||
'port': src_port_id,
|
||||
'profile': port_mirror_profile['id']})
|
||||
self._nsx_plugin._switching_profiles.delete(
|
||||
port_mirror_profile['id'])
|
||||
|
||||
def _create_local_span(self, context, src_port_id, dest_port_id,
|
||||
direction, tags):
|
||||
"""Create a PortMirroring session on the backend for local SPAN."""
|
||||
tf = context.tap_flow
|
||||
# Backend expects a list of source ports and destination ports.
|
||||
# Due to TaaS API requirements, we are only able to add one port
|
||||
# as a source port and one port as a destination port in a single
|
||||
# request. Hence we send a list of one port for source_ports
|
||||
# and dest_ports.
|
||||
nsx_src_ports = self._convert_to_backend_source_port(
|
||||
context._plugin_context.session, src_port_id)
|
||||
nsx_dest_ports = self._convert_to_backend_dest_port(
|
||||
context._plugin_context.session, dest_port_id)
|
||||
# Create port mirror session on the backend
|
||||
try:
|
||||
nsxlib = v3_utils.get_nsxlib_wrapper()
|
||||
pm_session = nsxlib.port_mirror.create_session(
|
||||
source_ports=nsx_src_ports,
|
||||
dest_ports=nsx_dest_ports,
|
||||
direction=direction,
|
||||
description=tf.get('description'),
|
||||
name=tf.get('name'),
|
||||
tags=tags)
|
||||
except nsxlib_exc.ManagerError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Unable to create port mirror session %s "
|
||||
"on NSX backend, rolling back "
|
||||
"changes on neutron."), tf['id'])
|
||||
# Create internal mappings between tap flow and port mirror session.
|
||||
# Ideally DB transactions must take place in precommit, but since we
|
||||
# rely on the NSX backend to retrieve the port session UUID, we perform
|
||||
# the create action in postcommit.
|
||||
try:
|
||||
nsx_db.add_port_mirror_session_mapping(
|
||||
session=context._plugin_context.session,
|
||||
tf_id=tf['id'],
|
||||
pm_session_id=pm_session['id'])
|
||||
except db_exc.DBError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Unable to create port mirror session db "
|
||||
"mappings for tap flow %s. Rolling back "
|
||||
"changes in Neutron."), tf['id'])
|
||||
nsxlib.port_mirror.delete_session(pm_session['id'])
|
||||
|
||||
def delete_tap_flow_precommit(self, context):
|
||||
pass
|
||||
|
||||
def delete_tap_flow_postcommit(self, context):
|
||||
"""Delete tap flow and port mirror session on NSX backend."""
|
||||
tf = context.tap_flow
|
||||
ts = self._get_tap_service(context._plugin_context,
|
||||
tf.get('tap_service_id'))
|
||||
# Retrieve port mirroring session mappings.
|
||||
pm_session_mapping = nsx_db.get_port_mirror_session_mapping(
|
||||
session=context._plugin_context.session,
|
||||
tf_id=tf['id'])
|
||||
src_port_id = tf.get('source_port')
|
||||
dest_port_id = ts.get('port_id')
|
||||
if self._is_local_span(context, src_port_id, dest_port_id):
|
||||
self._delete_local_span(
|
||||
context, pm_session_mapping['port_mirror_session_id'])
|
||||
else:
|
||||
self._delete_l3span(
|
||||
context, pm_session_mapping['port_mirror_session_id'])
|
||||
# Delete internal mappings between tap flow and port mirror session.
|
||||
# Ideally DB transactions must take place in precommit, but since we
|
||||
# rely on the DB mapping to retrieve NSX backend UUID for the port
|
||||
# session mapping, we perform the delete action in postcommit.
|
||||
try:
|
||||
nsx_db.delete_port_mirror_session_mapping(
|
||||
session=context._plugin_context.session,
|
||||
tf_id=tf['id'])
|
||||
except db_exc.DBError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Unable to delete port mirror session db "
|
||||
"mappings %(pm)s for tap flow %(tf)s"), tf['id'])
|
||||
|
||||
def _delete_l3span(self, context, pm_profile_id):
|
||||
tf = context.tap_flow
|
||||
src_port_id = tf.get('source_port')
|
||||
port_mirror_profile = self._nsx_plugin._switching_profiles.get(
|
||||
uuid=pm_profile_id)
|
||||
try:
|
||||
# Update source port and remove L3 switching profile.
|
||||
self._update_port_at_backend(context=context, port_id=src_port_id,
|
||||
switching_profile=port_mirror_profile,
|
||||
delete_profile=True)
|
||||
except nsxlib_exc.ManagerError:
|
||||
LOG.error(_LE("Unable to update source port %(port)s "
|
||||
"to delete port mirror profile %(pm)s on NSX "
|
||||
"backend."),
|
||||
{'pm': pm_profile_id,
|
||||
'port': src_port_id})
|
||||
try:
|
||||
# Delete port mirroring switching profile
|
||||
self._nsx_plugin._switching_profiles.delete(uuid=pm_profile_id)
|
||||
except nsxlib_exc.ManagerError:
|
||||
LOG.error(_LE("Unable to delete port mirror switching profile "
|
||||
"%s on NSX backend."), pm_profile_id)
|
||||
|
||||
def _delete_local_span(self, context, pm_session_id):
|
||||
# Delete port mirroring session on the backend
|
||||
try:
|
||||
nsxlib.port_mirror.delete_session(pm_session_id)
|
||||
except nsxlib_exc.ManagerError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Unable to delete port mirror session %s "
|
||||
"on NSX backend."), pm_session_id)
|
@ -384,9 +384,10 @@ class LsnManagerTestCase(base.BaseTestCase):
|
||||
|
||||
def test_lsn_port_get_lsn_not_found_silent_raise(self):
|
||||
with mock.patch.object(self.manager, 'lsn_get', return_value=None):
|
||||
expected = self.manager.lsn_port_get(
|
||||
result = self.manager.lsn_port_get(
|
||||
mock.ANY, self.net_id, self.sub_id, raise_on_err=False)
|
||||
self.assertEqual(expected, (None, None))
|
||||
expected = (None, None)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_lsn_port_get_port_not_found_on_raise(self):
|
||||
self.mock_lsn_api.lsn_port_by_subnet_get.side_effect = n_exc.NotFound
|
||||
@ -400,9 +401,10 @@ class LsnManagerTestCase(base.BaseTestCase):
|
||||
self.mock_lsn_api.lsn_port_by_subnet_get.side_effect = n_exc.NotFound
|
||||
with mock.patch.object(
|
||||
self.manager, 'lsn_get', return_value=self.lsn_id):
|
||||
expected = self.manager.lsn_port_get(
|
||||
result = self.manager.lsn_port_get(
|
||||
mock.ANY, self.net_id, self.sub_id, raise_on_err=False)
|
||||
self.assertEqual(expected, (self.lsn_id, None))
|
||||
expected = (self.lsn_id, None)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_lsn_port_create(self):
|
||||
self.mock_lsn_api.lsn_port_create.return_value = self.lsn_port_id
|
||||
@ -794,7 +796,8 @@ class PersistentLsnManagerTestCase(testlib_api.SqlTestCase):
|
||||
def test_lsn_port_get_silent_not_found(self):
|
||||
result = self.manager.lsn_port_get(
|
||||
self.context, self.net_id, self.sub_id, raise_on_err=False)
|
||||
self.assertEqual((None, None), result)
|
||||
expected = (None, None)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_lsn_port_get_sync_on_missing(self):
|
||||
return
|
||||
@ -830,7 +833,8 @@ class PersistentLsnManagerTestCase(testlib_api.SqlTestCase):
|
||||
def test_lsn_port_get_by_mac_silent_not_found(self):
|
||||
result = self.manager.lsn_port_get_by_mac(
|
||||
self.context, self.net_id, self.sub_id, raise_on_err=False)
|
||||
self.assertEqual((None, None), result)
|
||||
expected = (None, None)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_lsn_port_create(self):
|
||||
lsn_db.lsn_add(self.context, self.net_id, self.lsn_id)
|
||||
@ -860,7 +864,8 @@ class PersistentLsnManagerTestCase(testlib_api.SqlTestCase):
|
||||
self.sub_id, self.mac, self.lsn_id)
|
||||
self.manager.lsn_port_delete(
|
||||
self.context, self.lsn_id, self.lsn_port_id)
|
||||
self.assertEqual((None, None), self.manager.lsn_port_get(
|
||||
expected = (None, None)
|
||||
self.assertEqual(expected, self.manager.lsn_port_get(
|
||||
self.context, self.lsn_id, self.sub_id, raise_on_err=False))
|
||||
|
||||
def test_lsn_port_delete_not_existent(self):
|
||||
|
@ -1,189 +0,0 @@
|
||||
# Copyright (c) 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.
|
||||
import mock
|
||||
|
||||
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
|
||||
|
||||
from neutron_taas.extensions import taas
|
||||
from neutron_taas.services.taas import taas_plugin
|
||||
from neutron_taas.tests.unit.db import test_taas_db
|
||||
|
||||
from neutron_lib import context
|
||||
from oslo_utils import importutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.services.neutron_taas.nsx_v3 import driver as nsx_v3_driver
|
||||
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_nsx_v3_plugin
|
||||
|
||||
_uuid = uuidutils.generate_uuid
|
||||
NSX_V3_PLUGIN_CLASS = ('vmware_nsx.plugins.nsx_v3.plugin.NsxV3Plugin')
|
||||
|
||||
|
||||
class TestNsxV3TaaSDriver(test_taas_db.TaaSDbTestCase,
|
||||
test_nsx_v3_plugin.NsxV3PluginTestCaseMixin,
|
||||
test_plugin.NeutronDbPluginV2TestCase):
|
||||
def setUp(self):
|
||||
super(TestNsxV3TaaSDriver, self).setUp()
|
||||
self.driver = nsx_v3_driver.NsxV3Driver(mock.MagicMock())
|
||||
mock.patch('neutron.services.service_base.load_drivers',
|
||||
return_value=({'dummyprovider': self.driver},
|
||||
'dummyprovider')).start()
|
||||
mock.patch('neutron.db.servicetype_db.ServiceTypeManager.get_instance',
|
||||
return_value=mock.MagicMock()).start()
|
||||
self.taas_plugin = taas_plugin.TaasPlugin()
|
||||
self.core_plugin = importutils.import_object(NSX_V3_PLUGIN_CLASS)
|
||||
mock.patch(
|
||||
'vmware_nsx.plugins.nsx_v3.plugin.NsxV3Plugin.get_floatingips',
|
||||
return_value=([{'floating_ip_address': '172.10.10.10'}])).start()
|
||||
self.ctx = context.get_admin_context()
|
||||
|
||||
def test_validate_tap_flow_same_network_same_port_fail(self):
|
||||
with self.port() as src_port:
|
||||
self.assertRaises(nsx_exc.NsxTaaSDriverException,
|
||||
self.driver._validate_tap_flow,
|
||||
src_port['port'], src_port['port'])
|
||||
|
||||
def test_validate_tap_flow_same_network_different_port(self):
|
||||
with self.network() as network:
|
||||
with self.subnet(network=network) as subnet:
|
||||
with self.port(subnet=subnet) as src_port:
|
||||
with self.port(subnet=subnet) as dest_port:
|
||||
result = self.driver._validate_tap_flow(
|
||||
src_port['port'],
|
||||
dest_port['port'])
|
||||
# result = None signifies that the method returned
|
||||
# with no exceptions.
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_convert_to_backend_direction(self):
|
||||
direction = 'BOTH'
|
||||
nsx_direction = self.driver._convert_to_backend_direction(direction)
|
||||
self.assertEqual('BIDIRECTIONAL', nsx_direction)
|
||||
|
||||
direction = 'IN'
|
||||
nsx_direction = self.driver._convert_to_backend_direction(direction)
|
||||
self.assertEqual('INGRESS', nsx_direction)
|
||||
|
||||
direction = 'OUT'
|
||||
nsx_direction = self.driver._convert_to_backend_direction(direction)
|
||||
self.assertEqual('EGRESS', nsx_direction)
|
||||
|
||||
def test_convert_to_backend_source_port(self):
|
||||
nsx_id = _uuid()
|
||||
with mock.patch('vmware_nsx.db.db.get_nsx_switch_and_port_id',
|
||||
return_value=(_uuid(), nsx_id)):
|
||||
result = self.driver._convert_to_backend_source_port(
|
||||
self.ctx.session, _uuid())
|
||||
self.assertEqual(1, len(result))
|
||||
self.assertEqual('LogicalPortMirrorSource',
|
||||
result[0].get('resource_type'))
|
||||
self.assertEqual(1, len(result[0].get('port_ids')))
|
||||
self.assertEqual(nsx_id, result[0].get('port_ids')[0])
|
||||
|
||||
def test_convert_to_backend_dest_port(self):
|
||||
nsx_id = _uuid()
|
||||
with mock.patch('vmware_nsx.db.db.get_nsx_switch_and_port_id',
|
||||
return_value=(_uuid(), nsx_id)):
|
||||
result = self.driver._convert_to_backend_dest_port(
|
||||
self.ctx.session, _uuid())
|
||||
self.assertEqual('LogicalPortMirrorDestination',
|
||||
result.get('resource_type'))
|
||||
self.assertEqual(1, len(result.get('port_ids')))
|
||||
self.assertEqual(nsx_id, result.get('port_ids')[0])
|
||||
|
||||
def test_create_tap_service(self):
|
||||
ts_name = 'test-tap-service'
|
||||
with self.port(tenant_id=self.tenant_id) as port:
|
||||
ts_data = self._get_tap_service_data(
|
||||
name=ts_name, port_id=port['port']['id'])
|
||||
ts = self.taas_plugin.create_tap_service(self.ctx, ts_data)
|
||||
self.assertIsNotNone(ts)
|
||||
self.assertEqual(ts_name, ts['name'])
|
||||
self.assertEqual(port['port']['id'], ts['port_id'])
|
||||
|
||||
def test_delete_tap_service(self):
|
||||
with self.port(tenant_id=self.tenant_id) as port:
|
||||
ts_data = self._get_tap_service_data(port_id=port['port']['id'])
|
||||
ts = self.taas_plugin.create_tap_service(self.ctx, ts_data)
|
||||
self.assertIsNotNone(ts)
|
||||
self.taas_plugin.delete_tap_service(self.ctx, ts['id'])
|
||||
self.assertRaises(taas.TapServiceNotFound,
|
||||
self._get_tap_service, ts['id'])
|
||||
|
||||
def test_create_tap_flow(self):
|
||||
tf_name = 'test-tap-flow'
|
||||
with self.network() as network:
|
||||
with self.subnet(network=network) as subnet:
|
||||
with self.port(tenant_id=self.tenant_id,
|
||||
subnet=subnet) as dest_port:
|
||||
with self.port(tenant_id=self.tenant_id,
|
||||
subnet=subnet) as src_port:
|
||||
ts_data = self._get_tap_service_data(
|
||||
port_id=dest_port['port']['id'])
|
||||
ts = self.taas_plugin.create_tap_service(
|
||||
self.ctx, ts_data)
|
||||
tf_data = self._get_tap_flow_data(
|
||||
tap_service_id=ts['id'],
|
||||
source_port=src_port['port']['id'],
|
||||
name=tf_name)
|
||||
tf = self.taas_plugin.create_tap_flow(self.ctx,
|
||||
tf_data)
|
||||
self.assertIsNotNone(tf)
|
||||
self.assertEqual(tf_name, tf['name'])
|
||||
self.assertEqual(src_port['port']['id'],
|
||||
tf['source_port'])
|
||||
|
||||
def test_create_tap_flow_same_network_same_port_fail(self):
|
||||
tf_name = 'test-tap-flow'
|
||||
with self.network() as network:
|
||||
with self.subnet(network=network) as subnet:
|
||||
with self.port(tenant_id=self.tenant_id,
|
||||
subnet=subnet) as port:
|
||||
ts_data = self._get_tap_service_data(
|
||||
port_id=port['port']['id'])
|
||||
ts = self.taas_plugin.create_tap_service(
|
||||
self.ctx, ts_data)
|
||||
tf_data = self._get_tap_flow_data(
|
||||
tap_service_id=ts['id'],
|
||||
source_port=port['port']['id'],
|
||||
name=tf_name)
|
||||
self.assertRaises(nsx_exc.NsxTaaSDriverException,
|
||||
self.taas_plugin.create_tap_flow,
|
||||
self.ctx,
|
||||
tf_data)
|
||||
|
||||
def test_delete_tap_flow(self):
|
||||
tf_name = 'test-tap-flow'
|
||||
with self.network() as network:
|
||||
with self.subnet(network=network) as subnet:
|
||||
with self.port(tenant_id=self.tenant_id,
|
||||
subnet=subnet) as dest_port:
|
||||
with self.port(tenant_id=self.tenant_id,
|
||||
subnet=subnet) as src_port:
|
||||
ts_data = self._get_tap_service_data(
|
||||
port_id=dest_port['port']['id'])
|
||||
ts = self.taas_plugin.create_tap_service(
|
||||
self.ctx, ts_data)
|
||||
tf_data = self._get_tap_flow_data(
|
||||
tap_service_id=ts['id'],
|
||||
source_port=src_port['port']['id'],
|
||||
name=tf_name)
|
||||
tf = self.taas_plugin.create_tap_flow(self.ctx,
|
||||
tf_data)
|
||||
self.assertIsNotNone(tf)
|
||||
self.taas_plugin.delete_tap_flow(self.ctx, tf['id'])
|
||||
self.assertRaises(taas.TapFlowNotFound,
|
||||
self._get_tap_flow, tf['id'])
|
@ -1,109 +0,0 @@
|
||||
# Copyright 2016 VMware Inc
|
||||
# All Rights Reserved
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
from oslo_log import log
|
||||
|
||||
from tempest.lib.services.network import base
|
||||
|
||||
from vmware_nsx_tempest._i18n import _LI
|
||||
from vmware_nsx_tempest._i18n import _LW
|
||||
from vmware_nsx_tempest.services import network_client_base as base_client
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class TaaSClient(base.BaseNetworkClient):
|
||||
|
||||
"""
|
||||
Request resources via API for TapService and TapFlow
|
||||
|
||||
create request
|
||||
show request
|
||||
delete request
|
||||
list all request
|
||||
|
||||
"""
|
||||
|
||||
# Tap Service
|
||||
|
||||
def create_tap_service(self, **kwargs):
|
||||
uri = '/taas/tap_services'
|
||||
post_data = {'tap_service': kwargs}
|
||||
LOG.info(_LI("URI : %(uri)s, posting data : %(post_data)s") % {
|
||||
"uri": uri, "post_data": post_data})
|
||||
return self.create_resource(uri, post_data)
|
||||
|
||||
def list_tap_service(self, **filters):
|
||||
uri = '/taas/tap_services'
|
||||
LOG.info(_LI("URI : %(uri)s") % {"uri": uri})
|
||||
return self.list_resources(uri, **filters)
|
||||
|
||||
def show_tap_service(self, ts_id, **fields):
|
||||
uri = '/taas/tap_services' + "/" + ts_id
|
||||
LOG.info(_LI("URI : %(uri)s") % {"uri": uri})
|
||||
return self.show_resource(uri, **fields)
|
||||
|
||||
def delete_tap_service(self, ts_id):
|
||||
uri = '/taas/tap_services' + "/" + ts_id
|
||||
LOG.info(_LI("URI : %(uri)s") % {"uri": uri})
|
||||
return self.delete_resource(uri)
|
||||
|
||||
# Tap Flow
|
||||
|
||||
def create_tap_flow(self, **kwargs):
|
||||
uri = '/taas/tap_flows'
|
||||
post_data = {'tap_flow': kwargs}
|
||||
LOG.info(_LI("URI : %(uri)s, posting data : %(post_data)s") % {
|
||||
"uri": uri, "post_data": post_data})
|
||||
return self.create_resource(uri, post_data)
|
||||
|
||||
def list_tap_flow(self, **filters):
|
||||
uri = '/taas/tap_flows'
|
||||
LOG.info(_LI("URI : %(uri)s") % {"uri": uri})
|
||||
return self.list_resources(uri, **filters)
|
||||
|
||||
def show_tap_flow(self, tf_id, **fields):
|
||||
uri = '/taas/tap_flows' + "/" + tf_id
|
||||
LOG.info(_LI("URI : %(uri)s") % {"uri": uri})
|
||||
return self.show_resource(uri, **fields)
|
||||
|
||||
def delete_tap_flow(self, tf_id):
|
||||
uri = '/taas/tap_flows' + "/" + tf_id
|
||||
LOG.info(_LI("URI : %(uri)s") % {"uri": uri})
|
||||
return self.delete_resource(uri)
|
||||
|
||||
|
||||
def get_client(client_mgr):
|
||||
|
||||
"""
|
||||
Create a TaaS client from manager or networks_client
|
||||
|
||||
"""
|
||||
|
||||
try:
|
||||
manager = getattr(client_mgr, "manager", client_mgr)
|
||||
net_client = getattr(manager, "networks_client")
|
||||
_params = base_client.default_params_with_timeout_values.copy()
|
||||
except AttributeError as attribute_err:
|
||||
LOG.warning(_LW("Failed to locate the attribute, Error: %(err_msg)s") %
|
||||
{"err_msg": attribute_err.__str__()})
|
||||
_params = {}
|
||||
client = TaaSClient(net_client.auth_provider,
|
||||
net_client.service,
|
||||
net_client.region,
|
||||
net_client.endpoint_type,
|
||||
**_params)
|
||||
return client
|
@ -1,558 +0,0 @@
|
||||
# Copyright 2016 VMware Inc
|
||||
# All Rights Reserved
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tempest.api.network import base
|
||||
from tempest import config
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
from tempest import test
|
||||
|
||||
from vmware_nsx_tempest._i18n import _LI
|
||||
from vmware_nsx_tempest._i18n import _LW
|
||||
from vmware_nsx_tempest.services import nsxv3_client
|
||||
from vmware_nsx_tempest.services import taas_client
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TaaSJsonTest(base.BaseNetworkTest):
|
||||
|
||||
"""Tap Service and Tap Flow API's can be accessed using the TaaS Client .
|
||||
|
||||
Tap Service is created by associating floating ip to the destination
|
||||
port and Tap Flow is created by binding the Tap Service created with the
|
||||
source port .
|
||||
|
||||
CRUD Operations for Tap Service and Tap Flow are covered .
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(TaaSJsonTest, cls).skip_checks()
|
||||
if not test.is_extension_enabled('taas', 'network'):
|
||||
msg = "taas extension not enabled."
|
||||
raise cls.skipException(msg)
|
||||
if not CONF.network.public_network_id:
|
||||
msg = "Public network id not found."
|
||||
raise cls.skipException(msg)
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TaaSJsonTest, cls).resource_setup()
|
||||
cls.ext_net_id = CONF.network.public_network_id
|
||||
# Create the topology to test TaaS Client
|
||||
cls.network = cls.create_network()
|
||||
cls.subnet = cls.create_subnet(cls.network)
|
||||
cls.router = cls.create_router(data_utils.rand_name('router-'),
|
||||
external_network_id=cls.ext_net_id)
|
||||
cls.create_router_interface(cls.router['id'], cls.subnet['id'])
|
||||
for i in range(4):
|
||||
cls.create_port(cls.network)
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(TaaSJsonTest, cls).setup_clients()
|
||||
try:
|
||||
cls.tclient = taas_client.get_client(cls.manager)
|
||||
cls.nsx = nsxv3_client.NSXV3Client(CONF.nsxv3.nsx_manager,
|
||||
CONF.nsxv3.nsx_user,
|
||||
CONF.nsxv3.nsx_password)
|
||||
except AttributeError as attribute_err:
|
||||
LOG.warning(
|
||||
_LW("Failed to locate the attribute, Error: %(err_msg)s") %
|
||||
{"err_msg": attribute_err.__str__()})
|
||||
|
||||
def _create_floating_ip(self, port_index):
|
||||
# Create and associates floating ip to the port based on port index
|
||||
create_body = self.floating_ips_client.create_floatingip(
|
||||
floating_network_id=self.ext_net_id,
|
||||
port_id=self.ports[int(port_index)]['id'])
|
||||
fip = create_body['floatingip']
|
||||
return fip
|
||||
|
||||
def _create_tap_service_env(self, port_index):
|
||||
"""
|
||||
Creates floating ip and device_tap_service dict for
|
||||
Tap service environment
|
||||
"""
|
||||
fip = self._create_floating_ip(port_index)
|
||||
tap_service_name = data_utils.rand_name('tapservice-ch')
|
||||
device_tap_service = {
|
||||
"description": 'TAP1', "name": tap_service_name,
|
||||
"port_id": self.ports[port_index]['id'],
|
||||
"tenant_id": self.ports[0]['tenant_id']
|
||||
}
|
||||
return fip, device_tap_service
|
||||
|
||||
def _create_tap_flow_env(self, tap_service_id, tap_flow_direction,
|
||||
src_port_index):
|
||||
# Creates device_tap_flow dict for tap flow environment
|
||||
tap_flow_name = data_utils.rand_name('tapflow-ch')
|
||||
device_tap_flow = {
|
||||
"description": 'tapflow1', "direction": tap_flow_direction,
|
||||
"name": tap_flow_name, "source_port": self.ports[src_port_index][
|
||||
'id'], "tap_service_id": tap_service_id,
|
||||
"tenant_id": self.ports[0]['tenant_id']
|
||||
}
|
||||
return device_tap_flow
|
||||
|
||||
def _resource_cleanup(self, fip, tapservice_id, tapflow_id):
|
||||
# Cleans Tap Service and Tap Flow resources after each test
|
||||
if fip != 'null':
|
||||
self.addCleanup(self.floating_ips_client.delete_floatingip,
|
||||
fip['id'])
|
||||
if tapflow_id != 'null':
|
||||
self.tclient.delete_tap_flow(tapflow_id)
|
||||
if tapservice_id != 'null':
|
||||
self.tclient.delete_tap_service(tapservice_id)
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c1ec6-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_create_tap_service(self):
|
||||
"""
|
||||
Tap service create api is tested , Tap Service is created with
|
||||
destination port associated with floating ip
|
||||
"""
|
||||
LOG.info(_LI(
|
||||
"Testing Tap Service Create api with floating ip associated to "
|
||||
"destination port"))
|
||||
# Create tap service env
|
||||
fip, device_tap_service = self._create_tap_service_env(port_index=0)
|
||||
# Create Tap Service
|
||||
rsp = self.tclient.create_tap_service(**device_tap_service)
|
||||
LOG.info(_LI("response from tap serive create : %(rsp)s") %
|
||||
{"rsp": rsp})
|
||||
self.assertEqual('201',
|
||||
rsp.response["status"],
|
||||
"Response code is not 201 ")
|
||||
self.assertIn(self.ports[0]['id'], rsp['tap_service']['port_id'])
|
||||
self._resource_cleanup(fip, rsp['tap_service']['id'], 'null')
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c21f0-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_list_tap_service(self):
|
||||
"""
|
||||
Tap Service List api is tested
|
||||
"""
|
||||
LOG.info(_LI(
|
||||
"Testing Tap Service List api with floating ip associated "
|
||||
"to destination port "))
|
||||
# Create tap service env
|
||||
fip, device_tap_service = self._create_tap_service_env(port_index=0)
|
||||
# Create Tap Service
|
||||
rsp_create = self.tclient.create_tap_service(**device_tap_service)
|
||||
# List Tap Service
|
||||
rsp_list = self.tclient.list_tap_service()
|
||||
LOG.info(_LI("response from tap list : %(rsp)s") % {"rsp": rsp_list})
|
||||
self.assertEqual('200',
|
||||
rsp_list.response["status"],
|
||||
"Response code is not 200 ")
|
||||
self.assertIn(device_tap_service['name'],
|
||||
rsp_list['tap_services'][0]['name'])
|
||||
self.assertIn(self.ports[0]['id'], rsp_list[
|
||||
'tap_services'][0]['port_id'])
|
||||
self._resource_cleanup(fip, rsp_create['tap_service']['id'], 'null')
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c2394-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_show_tap_service(self):
|
||||
"""
|
||||
Tap Service Show api is tested
|
||||
"""
|
||||
LOG.info(_LI(
|
||||
"Testing Tap Service Show api with floating ip associated to "
|
||||
"destination port "))
|
||||
# Create tap service env
|
||||
fip, device_tap_service = self._create_tap_service_env(port_index=0)
|
||||
# Create Tap Service
|
||||
rsp_create = self.tclient.create_tap_service(**device_tap_service)
|
||||
# Show Tap Service
|
||||
rsp_show = self.tclient.show_tap_service(
|
||||
rsp_create['tap_service']['id'])
|
||||
LOG.info(_LI("response from tap list : %(rsp)s") % {"rsp": rsp_show})
|
||||
self.assertEqual('200',
|
||||
rsp_show.response["status"],
|
||||
"Response code is not 200 ")
|
||||
self.assertIn(device_tap_service['name'],
|
||||
rsp_show['tap_service']['name'])
|
||||
self.assertIn(self.ports[0]['id'],
|
||||
rsp_show['tap_service']['port_id'])
|
||||
self._resource_cleanup(fip, rsp_create['tap_service']['id'], 'null')
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c2538-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_delete_tap_service(self):
|
||||
"""
|
||||
Tap Service Delete api is tested
|
||||
"""
|
||||
LOG.info(
|
||||
_LI(
|
||||
"Testing Tap delete api with floating ip associated "
|
||||
"to destination port "))
|
||||
# Create tap service env
|
||||
fip, device_tap_service = self._create_tap_service_env(port_index=0)
|
||||
# Create Tap Service
|
||||
rsp_create = self.tclient.create_tap_service(**device_tap_service)
|
||||
LOG.info(_LI("response from tap list : %(rsp)s") % {"rsp": rsp_create})
|
||||
self.assertEqual('201',
|
||||
rsp_create.response["status"],
|
||||
"Response code is not 201 ")
|
||||
# Delete Tap Service
|
||||
rsp_delete = self.tclient.delete_tap_service(
|
||||
rsp_create['tap_service']['id'])
|
||||
self.assertEqual('204',
|
||||
rsp_delete.response["status"],
|
||||
"Response code is not 204 ")
|
||||
rsp_list = self.tclient.list_tap_service()
|
||||
LOG.info(_LI("response from tap list : %(rsp)s") % {"rsp": rsp_list})
|
||||
self._resource_cleanup(fip, 'null', 'null')
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c2a7e-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_create_tap_flow(self):
|
||||
"""
|
||||
Tap flow create api is tested , Tap Service is created with
|
||||
destination port associated with floating ip
|
||||
"""
|
||||
LOG.info(_LI(
|
||||
"Testing Tap flow create api with direction BOTH and "
|
||||
"floating ip associated to destination port "))
|
||||
# Create tap service env
|
||||
fip, device_tap_service = self._create_tap_service_env(port_index=0)
|
||||
# Create Tap Service
|
||||
rsp_tap_service = self.tclient.create_tap_service(**device_tap_service)
|
||||
LOG.info(_LI("response from tap service : %(rsp)s") %
|
||||
{"rsp": rsp_tap_service})
|
||||
self.assertEqual('201',
|
||||
rsp_tap_service.response["status"],
|
||||
"Response code is not 201 ")
|
||||
# Create Tap Flow env
|
||||
device_tap_flow = self._create_tap_flow_env(
|
||||
tap_service_id=rsp_tap_service['tap_service']['id'],
|
||||
tap_flow_direction='BOTH', src_port_index=1)
|
||||
# Create Tap flow
|
||||
rsp_tap_flow = self.tclient.create_tap_flow(**device_tap_flow)
|
||||
LOG.info(_LI("response from flow : %(rsp)s") % {"rsp": rsp_tap_flow})
|
||||
# NSX backend check for Switch Profile
|
||||
nsx_switch_profiles = self.nsx.get_logical_switch_profiles()
|
||||
switch_profile = []
|
||||
for ls in nsx_switch_profiles:
|
||||
if ls['display_name'] == device_tap_flow['name']:
|
||||
self.assertIn(ls['direction'], 'BIDIRECTIONAL')
|
||||
self.assertIn(ls['destinations'][0],
|
||||
fip['floating_ip_address'])
|
||||
switch_profile = [ls]
|
||||
self.assertNotEqual(len(switch_profile), 0, "Port mirror profile is "
|
||||
"not found in NSX ")
|
||||
self.assertEqual('201',
|
||||
rsp_tap_flow.response["status"],
|
||||
"Response code is not 201 ")
|
||||
self.assertIn(self.ports[1]['id'], rsp_tap_flow[
|
||||
'tap_flow']['source_port'])
|
||||
self.assertEqual(device_tap_flow['name'], rsp_tap_flow['tap_flow'][
|
||||
'name'])
|
||||
self.assertEqual(device_tap_flow['direction'], rsp_tap_flow[
|
||||
'tap_flow']['direction'])
|
||||
self.assertEqual(rsp_tap_service['tap_service'][
|
||||
'id'], rsp_tap_flow['tap_flow']['tap_service_id'])
|
||||
self._resource_cleanup(fip, rsp_tap_service['tap_service'][
|
||||
'id'], rsp_tap_flow['tap_flow']['id'])
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c2c5e-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_create_tap_flow_multiple(self):
|
||||
"""
|
||||
Multiple Tap flow's are created in with 'IN' and 'OUT' , Tap Service
|
||||
is created with destination port associated with floating ip's for
|
||||
each Tap Flow
|
||||
"""
|
||||
LOG.info(_LI(
|
||||
"Multiple Tap flow's created with direction IN and OUT and"
|
||||
"floating ip associated to destination port "))
|
||||
# Create tap service env
|
||||
fip1, device_tap_service1 = self._create_tap_service_env(port_index=0)
|
||||
# Create tap service env
|
||||
fip2, device_tap_service2 = self._create_tap_service_env(port_index=1)
|
||||
# Create Tap Service 1 and Tap Service 2
|
||||
rsp_tap_service1 = self.tclient.create_tap_service(
|
||||
**device_tap_service1)
|
||||
rsp_tap_service2 = self.tclient.create_tap_service(
|
||||
**device_tap_service2)
|
||||
LOG.info(_LI(
|
||||
"response from tap service1 and tap service2 : %(rsp1)s "
|
||||
"%(rsp2)s ") % {
|
||||
"rsp1": rsp_tap_service1, "rsp2": rsp_tap_service2
|
||||
})
|
||||
# Create Tap Flow env
|
||||
device_tap_flow1 = self._create_tap_flow_env(
|
||||
tap_service_id=rsp_tap_service1['tap_service']['id'],
|
||||
tap_flow_direction='IN', src_port_index=2)
|
||||
# Create Tap Flow env
|
||||
device_tap_flow2 = self._create_tap_flow_env(
|
||||
tap_service_id=rsp_tap_service2['tap_service']['id'],
|
||||
tap_flow_direction='OUT', src_port_index=3)
|
||||
# Create Tap Flow1 and Tap Flow2
|
||||
rsp_tap_flow1 = self.tclient.create_tap_flow(**device_tap_flow1)
|
||||
rsp_tap_flow2 = self.tclient.create_tap_flow(**device_tap_flow2)
|
||||
LOG.info(_LI(
|
||||
"response from tap flow1 and tap flow2 : %(rsp1)s %(rsp2)s ") % {
|
||||
"rsp1": rsp_tap_flow1,
|
||||
"rsp2": rsp_tap_flow2
|
||||
})
|
||||
# NSX backend check for Switch Profile
|
||||
nsx_switch_profiles = self.nsx.get_logical_switch_profiles()
|
||||
profile_count = 0
|
||||
for ls in nsx_switch_profiles:
|
||||
if ls['display_name'].startswith('tapflow-ch-'):
|
||||
if ls['direction'] == 'INGRESS' or 'EGRESS':
|
||||
profile_count += 1
|
||||
self.assertEqual(profile_count, 2, "Port mirror profile is "
|
||||
"not found in NSX ")
|
||||
self.assertEqual(device_tap_flow1['name'], rsp_tap_flow1['tap_flow'][
|
||||
'name'])
|
||||
self.assertEqual(device_tap_flow2['name'], rsp_tap_flow2['tap_flow'][
|
||||
'name'])
|
||||
self.assertEqual(device_tap_flow1['direction'], rsp_tap_flow1[
|
||||
'tap_flow']['direction'])
|
||||
self.assertEqual(device_tap_flow2['direction'], rsp_tap_flow2[
|
||||
'tap_flow']['direction'])
|
||||
self._resource_cleanup(fip1, rsp_tap_service1['tap_service'][
|
||||
'id'], rsp_tap_flow1['tap_flow']['id'])
|
||||
self._resource_cleanup(fip2, rsp_tap_service2['tap_service'][
|
||||
'id'], rsp_tap_flow2['tap_flow']['id'])
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c2dda-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_list_tap_flow(self):
|
||||
"""
|
||||
Tap flow list api is tested , Tap Service is created with
|
||||
destination port associated with floating ip
|
||||
"""
|
||||
LOG.info(
|
||||
_LI(
|
||||
"Testing Tap Flow list api with floating ip associated to "
|
||||
"destination port "))
|
||||
# Create tap service env
|
||||
fip, device_tap_service = self._create_tap_service_env(port_index=0)
|
||||
# Create Tap Service
|
||||
rsp_tap_service = self.tclient.create_tap_service(**device_tap_service)
|
||||
LOG.info(_LI("response from tap service : %(rsp)s") %
|
||||
{"rsp": rsp_tap_service})
|
||||
self.assertEqual('201',
|
||||
rsp_tap_service.response["status"],
|
||||
"Response code is not 201 ")
|
||||
# Create Tap Flow env
|
||||
device_tap_flow = self._create_tap_flow_env(
|
||||
tap_service_id=rsp_tap_service['tap_service']['id'],
|
||||
tap_flow_direction='BOTH', src_port_index=1)
|
||||
# Create Tap flow
|
||||
rsp_tap_flow = self.tclient.create_tap_flow(**device_tap_flow)
|
||||
LOG.info(_LI("response from flow : %(rsp)s") % {"rsp": rsp_tap_flow})
|
||||
self.assertEqual('201',
|
||||
rsp_tap_flow.response["status"],
|
||||
"Response code is not 201 ")
|
||||
self.assertIn(self.ports[1]['id'], rsp_tap_flow[
|
||||
'tap_flow']['source_port'])
|
||||
self.assertEqual(device_tap_flow['name'], rsp_tap_flow['tap_flow'][
|
||||
'name'])
|
||||
self.assertEqual(device_tap_flow['direction'], rsp_tap_flow[
|
||||
'tap_flow']['direction'])
|
||||
self.assertEqual(rsp_tap_service['tap_service'][
|
||||
'id'], rsp_tap_flow['tap_flow']['tap_service_id'])
|
||||
# List Tap Flow
|
||||
rsp_tap_list_flow = self.tclient.list_tap_flow()
|
||||
LOG.info(_LI("response from tap list : %(rsp)s") %
|
||||
{"rsp": rsp_tap_list_flow})
|
||||
self.assertEqual('200',
|
||||
rsp_tap_list_flow.response["status"],
|
||||
"Response code is not 200 ")
|
||||
self.assertIn(device_tap_flow['name'], rsp_tap_list_flow[
|
||||
'tap_flows'][0][
|
||||
'name'])
|
||||
self.assertIn(self.ports[1]['id'], rsp_tap_list_flow[
|
||||
'tap_flows'][0]['source_port'])
|
||||
self._resource_cleanup(fip, rsp_tap_service['tap_service'][
|
||||
'id'], rsp_tap_flow['tap_flow']['id'])
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c2f6a-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_show_tap_flow(self):
|
||||
"""
|
||||
Tap flow show api is tested , Tap Service is created with
|
||||
destination port associated with floating ip
|
||||
"""
|
||||
LOG.info(_LI(
|
||||
"Testing Tap Service Show api with floating ip associated "
|
||||
"to destination port "))
|
||||
# Create tap service env
|
||||
fip, device_tap_service = self._create_tap_service_env(port_index=0)
|
||||
# Create Tap Service
|
||||
rsp_tap_service = self.tclient.create_tap_service(**device_tap_service)
|
||||
LOG.info(_LI("response from tap service : %(rsp)s") %
|
||||
{"rsp": rsp_tap_service})
|
||||
self.assertEqual('201',
|
||||
rsp_tap_service.response["status"],
|
||||
"Response code is not 201 ")
|
||||
# Create Tap Flow env
|
||||
device_tap_flow = self._create_tap_flow_env(
|
||||
tap_service_id=rsp_tap_service['tap_service']['id'],
|
||||
tap_flow_direction='BOTH', src_port_index=1)
|
||||
# Create Tap flow
|
||||
rsp_tap_flow = self.tclient.create_tap_flow(**device_tap_flow)
|
||||
# Show Tap Flow
|
||||
rsp_tap_flow_show = self.tclient.show_tap_flow(
|
||||
rsp_tap_flow['tap_flow']['id'])
|
||||
LOG.info(_LI("response from tap list : %(rsp)s") %
|
||||
{"rsp": rsp_tap_flow_show})
|
||||
self.assertEqual('200',
|
||||
rsp_tap_flow_show.response["status"],
|
||||
"Response code is not 200 ")
|
||||
self.assertIn(device_tap_flow['name'], rsp_tap_flow_show['tap_flow'][
|
||||
'name'])
|
||||
self.assertIn(self.ports[1]['id'], rsp_tap_flow_show[
|
||||
'tap_flow']['source_port'])
|
||||
self._resource_cleanup(fip, rsp_tap_service['tap_service'][
|
||||
'id'], rsp_tap_flow['tap_flow']['id'])
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c310e-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_delete_tap_flow(self):
|
||||
"""
|
||||
Tap flow delete api is tested , Tap Service is created with
|
||||
destination port associated with floating ip
|
||||
"""
|
||||
LOG.info(_LI(
|
||||
"Testing Tap flow delete api with floating ip associated to "
|
||||
"destination port "))
|
||||
# Create tap service env
|
||||
fip, device_tap_service = self._create_tap_service_env(port_index=0)
|
||||
# Create Tap Service
|
||||
rsp_tap_service = self.tclient.create_tap_service(**device_tap_service)
|
||||
LOG.info(_LI("response from tap service : %(rsp)s") %
|
||||
{"rsp": rsp_tap_service})
|
||||
self.assertEqual('201',
|
||||
rsp_tap_service.response["status"],
|
||||
"Response code is not 201 ")
|
||||
# Create Tap Flow env
|
||||
device_tap_flow = self._create_tap_flow_env(
|
||||
tap_service_id=rsp_tap_service['tap_service']['id'],
|
||||
tap_flow_direction='BOTH', src_port_index=1)
|
||||
# Create Tap flow
|
||||
rsp_tap_flow = self.tclient.create_tap_flow(**device_tap_flow)
|
||||
|
||||
LOG.info(_LI("response from flow : %(rsp)s") % {"rsp": rsp_tap_flow})
|
||||
self.assertEqual('201',
|
||||
rsp_tap_flow.response["status"],
|
||||
"Response code is not 201 ")
|
||||
self.assertIn(self.ports[1]['id'], rsp_tap_flow[
|
||||
'tap_flow']['source_port'])
|
||||
self.assertEqual(device_tap_flow['name'], rsp_tap_flow['tap_flow'][
|
||||
'name'])
|
||||
self.assertEqual(device_tap_flow['direction'], rsp_tap_flow[
|
||||
'tap_flow']['direction'])
|
||||
self.assertEqual(rsp_tap_service['tap_service'][
|
||||
'id'], rsp_tap_flow['tap_flow']['tap_service_id'])
|
||||
rsp_tap_flow_delete = self.tclient.delete_tap_flow(
|
||||
rsp_tap_flow['tap_flow']['id'])
|
||||
LOG.info(_LI("response from tap list : %(rsp)s") %
|
||||
{"rsp": rsp_tap_flow_delete})
|
||||
self.assertEqual('204',
|
||||
rsp_tap_flow_delete.response["status"],
|
||||
"Response code is not 204 ")
|
||||
rsp_tap_list_flow = self.tclient.list_tap_flow()
|
||||
LOG.info(_LI("response from tap list : %(rsp)s") %
|
||||
{"rsp": rsp_tap_list_flow})
|
||||
self._resource_cleanup(fip, rsp_tap_service[
|
||||
'tap_service']['id'], 'null')
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c328a-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_create_tap_flow_negative_nofloatingip(self):
|
||||
"""
|
||||
Tap flow create api is tested , Tap Service is created with
|
||||
destination port associated to non floating ip
|
||||
"""
|
||||
LOG.info(_LI(
|
||||
"Testing Tap flow create api with non floating ip "
|
||||
"associated to destination port "))
|
||||
tap_service_name = data_utils.rand_name('tapservice-ch')
|
||||
device_tap_service = {
|
||||
"description": 'tapservice1', "name": tap_service_name,
|
||||
"port_id": self.ports[0]['id'],
|
||||
"tenant_id": self.ports[0]['tenant_id']
|
||||
}
|
||||
# Create Tap Service
|
||||
rsp_tap_service = self.tclient.create_tap_service(**device_tap_service)
|
||||
LOG.info(_LI("response from tap service : %(rsp)s") %
|
||||
{"rsp": rsp_tap_service})
|
||||
self.assertEqual('201',
|
||||
rsp_tap_service.response["status"],
|
||||
"Response code is not 201 ")
|
||||
tap_flow_name = data_utils.rand_name('tapflow-ch')
|
||||
device_tap_flow = {
|
||||
"description": 'tapflow1', "direction": "BOTH",
|
||||
"name": tap_flow_name, "source_port": self.ports[1]['id'],
|
||||
"tap_service_id": rsp_tap_service['tap_service']['id'],
|
||||
"tenant_id": self.ports[0]['tenant_id']
|
||||
}
|
||||
# Create Tap Flow with a non floating ip associated to destination port
|
||||
try:
|
||||
self.tclient.create_tap_flow(**device_tap_flow)
|
||||
except Exception as e:
|
||||
LOG.info(_LI("response from exception %(rsp)s") % {"rsp": e})
|
||||
self._resource_cleanup('null', rsp_tap_service[
|
||||
'tap_service']['id'], 'null')
|
||||
|
||||
@test.attr(type='nsxv3')
|
||||
@decorators.idempotent_id('dc5c3802-8c18-11e6-ae22-56b6b6499611')
|
||||
def test_create_tap_flow_negative_nosrcport(self):
|
||||
"""
|
||||
Tap flow create api is tested with non existent src port
|
||||
"""
|
||||
LOG.info(
|
||||
_LI("Testing Tap flow create api with non existent src port "))
|
||||
tap_service_name = data_utils.rand_name('tapservice-ch')
|
||||
device_tap_service = {
|
||||
"description": 'tapservice1', "name": tap_service_name,
|
||||
"port_id": self.ports[0]['id'],
|
||||
"tenant_id": self.ports[0]['tenant_id']
|
||||
}
|
||||
# Create Tap Service
|
||||
rsp_tap_service = self.tclient.create_tap_service(**device_tap_service)
|
||||
LOG.info(_LI("response from tap service : %(rsp)s") %
|
||||
{"rsp": rsp_tap_service})
|
||||
self.assertEqual('201',
|
||||
rsp_tap_service.response["status"],
|
||||
"Response code is not 201 ")
|
||||
tap_flow_name = data_utils.rand_name('tapflow-ch')
|
||||
device_tap_flow = {
|
||||
"description": 'tapflow1', "direction": "BOTH",
|
||||
"name": tap_flow_name,
|
||||
"source_port": '2ad76061-252e-xxxx-9d0f-dd94188be9cc',
|
||||
"tap_service_id": rsp_tap_service['tap_service']['id'],
|
||||
"tenant_id": self.ports[0]['tenant_id']
|
||||
}
|
||||
# Create Tap Flow with a dummy non existent source port
|
||||
try:
|
||||
self.tclient.create_tap_flow(**device_tap_flow)
|
||||
except Exception as e:
|
||||
LOG.info(_LI("response from exception %(rsp)s") % {"rsp": e})
|
||||
self._resource_cleanup('null', rsp_tap_service[
|
||||
'tap_service']['id'], 'null')
|
Loading…
Reference in New Issue
Block a user