taas OSC commands
Add possibility to tap-as-a-service to use openstack commands instead of deprecated neutron commands. Closes-Bug: #1874701 Change-Id: I339f42a63789a946011700902724a58647c80b9d
This commit is contained in:
parent
51b36d9c9c
commit
62b8bb7213
@ -236,6 +236,42 @@ extension
|
||||
|
||||
TaaS CLI Reference
|
||||
==================
|
||||
|
||||
Openstack CLI
|
||||
-------------
|
||||
|
||||
OpenStackClient provides
|
||||
`the basic network commands <https://docs.openstack.org/python-openstackclient/latest/cli/command-list.html>`__
|
||||
and tap-as-a-service has an extension for taas related commands.
|
||||
|
||||
* Create tap service: **openstack tap service create** --name <name of the tap service> --port <name or ID of the port on which the traffic is delivered>
|
||||
|
||||
* List tap services: **openstack tap service list**
|
||||
|
||||
* Show tap service: **openstack tap service show** <tap service id/tap service name>
|
||||
|
||||
* Delete tap service: **openstack tap service delete** <tap service id/tap service name>
|
||||
|
||||
* Update tap service: **openstack tap service update** <tap service id/tap service name> --name <new name of the tap service> --description <new description of the tap service>
|
||||
|
||||
* Create tap flow: **openstack tap flow create** --name <name of the tap flow> --port <name or ID of the Source port to which the Tap Flow is connected> --tap-service <name or ID of the tap service> --direction <Direction of the Tap flow. Possible options are: IN, OUT, BOTH> --vlan-filter <LAN Ids to be mirrored in the form of range string>
|
||||
|
||||
* List tap flows **openstack tap flow list**
|
||||
|
||||
* Show tap flow **openstack tap flow show** <tap flow id/tap flow name>
|
||||
|
||||
* Delete tap flow **openstack tap flow delete** <tap flow id/tap flow name>
|
||||
|
||||
* Update tap flow **openstack tap flow update** <tap flow id/tap flow name> --name <new name of the tap flow> --description <new description of the tap flow>
|
||||
|
||||
Neutron CLI
|
||||
-----------
|
||||
|
||||
.. warning::
|
||||
|
||||
neutron CLI is now deprecated, and will be removed in the future.
|
||||
Use openstack CLI instead.
|
||||
|
||||
The TaaS commands can be executed using TaaS CLI, which is integrated with neutron.
|
||||
It can be used to send REST request and interact with the TaaS
|
||||
extension. Given below are the detail of the CLIs:
|
||||
|
0
neutron_taas/taas_client/osc/__init__.py
Normal file
0
neutron_taas/taas_client/osc/__init__.py
Normal file
234
neutron_taas/taas_client/osc/tap_flow.py
Normal file
234
neutron_taas/taas_client/osc/tap_flow.py
Normal file
@ -0,0 +1,234 @@
|
||||
# All Rights Reserved 2020
|
||||
#
|
||||
# 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 logging
|
||||
|
||||
from osc_lib.cli import format_columns
|
||||
from osc_lib.command import command
|
||||
from osc_lib import exceptions
|
||||
from osc_lib import utils as osc_utils
|
||||
from osc_lib.utils import columns as column_util
|
||||
|
||||
from neutronclient._i18n import _
|
||||
from neutronclient.common import utils
|
||||
from neutronclient.osc import utils as nc_osc_utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
TAP_FLOW = 'tap_flow'
|
||||
TAP_FLOWS = '%ss' % TAP_FLOW
|
||||
|
||||
path = 'taas'
|
||||
object_path = '/%s/' % path
|
||||
resource_path = '/%s/%%s/%%s' % path
|
||||
|
||||
_attr_map = (
|
||||
('id', 'ID', column_util.LIST_BOTH),
|
||||
('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY),
|
||||
('name', 'Name', column_util.LIST_BOTH),
|
||||
('status', 'Status', column_util.LIST_BOTH),
|
||||
('source_port', 'source_port', column_util.LIST_BOTH),
|
||||
('tap_service_id', 'tap_service_id', column_util.LIST_BOTH),
|
||||
('direction', 'Direction', column_util.LIST_BOTH),
|
||||
)
|
||||
|
||||
_formatters = {
|
||||
'vlan_filter': format_columns.ListColumn,
|
||||
}
|
||||
|
||||
|
||||
def _add_updatable_args(parser):
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
help=_('Name of this Tap service.'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Description for this Tap service.'))
|
||||
|
||||
|
||||
class CreateTapFlow(command.ShowOne):
|
||||
_description = _("Create a tap flow")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateTapFlow, self).get_parser(prog_name)
|
||||
nc_osc_utils.add_project_owner_option_to_parser(parser)
|
||||
_add_updatable_args(parser)
|
||||
parser.add_argument(
|
||||
'--port',
|
||||
required=True,
|
||||
metavar="SOURCE_PORT",
|
||||
help=_('Source port to which the Tap Flow is connected.'))
|
||||
parser.add_argument(
|
||||
'--tap-service',
|
||||
required=True,
|
||||
metavar="TAP_SERVICE",
|
||||
help=_('Tap Service to which the Tap Flow belongs.'))
|
||||
parser.add_argument(
|
||||
'--direction',
|
||||
required=True,
|
||||
metavar="DIRECTION",
|
||||
choices=['IN', 'OUT', 'BOTH'],
|
||||
type=utils.convert_to_uppercase,
|
||||
help=_('Direction of the Tap flow. Possible options are: '
|
||||
'IN, OUT, BOTH'))
|
||||
parser.add_argument(
|
||||
'--vlan-filter',
|
||||
required=False,
|
||||
metavar="VLAN_FILTER",
|
||||
help=_('VLAN Ids to be mirrored in the form of range string.'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
attrs = {}
|
||||
if parsed_args.name is not None:
|
||||
attrs['name'] = str(parsed_args.name)
|
||||
if parsed_args.description is not None:
|
||||
attrs['description'] = str(parsed_args.description)
|
||||
if parsed_args.port is not None:
|
||||
source_port = client.find_resource('port',
|
||||
parsed_args.port)['id']
|
||||
attrs['source_port'] = source_port
|
||||
if parsed_args.tap_service is not None:
|
||||
tap_service_id = client.find_resource(
|
||||
'tap_service', parsed_args.tap_service)['id']
|
||||
attrs['tap_service_id'] = tap_service_id
|
||||
if parsed_args.direction is not None:
|
||||
attrs['direction'] = parsed_args.direction
|
||||
if parsed_args.vlan_filter is not None:
|
||||
attrs['vlan_filter'] = parsed_args.vlan_filter
|
||||
if 'project' in parsed_args and parsed_args.project is not None:
|
||||
project_id = nc_osc_utils.find_project(
|
||||
self.app.client_manager.identity,
|
||||
parsed_args.project,
|
||||
parsed_args.project_domain,
|
||||
).id
|
||||
attrs['tenant_id'] = project_id
|
||||
body = {TAP_FLOW: attrs}
|
||||
obj = client.post('%s%s' % (object_path, TAP_FLOWS),
|
||||
body=body)[TAP_FLOW]
|
||||
columns, display_columns = column_util.get_columns(obj, _attr_map)
|
||||
data = osc_utils.get_dict_properties(obj, columns)
|
||||
return display_columns, data
|
||||
|
||||
|
||||
class ListTapFlow(command.Lister):
|
||||
_description = _("List tap flows that belong to a given tenant")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListTapFlow, self).get_parser(prog_name)
|
||||
nc_osc_utils.add_project_owner_option_to_parser(parser)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
params = {}
|
||||
if parsed_args.project is not None:
|
||||
project_id = nc_osc_utils.find_project(
|
||||
self.app.client_manager.identity,
|
||||
parsed_args.project,
|
||||
parsed_args.project_domain,
|
||||
).id
|
||||
params['tenant_id'] = project_id
|
||||
objs = client.list(TAP_FLOWS, '%s%s' % (object_path, TAP_FLOWS),
|
||||
retrieve_all=True, params=params)[TAP_FLOWS]
|
||||
headers, columns = column_util.get_column_definitions(
|
||||
_attr_map, long_listing=True)
|
||||
print('XXXXX headers=%s ' % headers)
|
||||
print('XXXXX columns=%s ' % columns)
|
||||
print('XXXXX objs=%s ' % objs)
|
||||
return (headers, (osc_utils.get_dict_properties(
|
||||
s, columns, formatters=_formatters) for s in objs))
|
||||
|
||||
|
||||
class ShowTapFlow(command.ShowOne):
|
||||
_description = _("Show information of a given tap flow")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowTapFlow, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
TAP_FLOW,
|
||||
metavar="<%s>" % TAP_FLOW,
|
||||
help=_("ID or name of tap flow to look up."),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
id = client.find_resource(TAP_FLOW, parsed_args.tap_flow)['id']
|
||||
obj = client.get(resource_path % (TAP_FLOWS, id))[TAP_FLOW]
|
||||
columns, display_columns = column_util.get_columns(obj, _attr_map)
|
||||
data = osc_utils.get_dict_properties(obj, columns)
|
||||
return display_columns, data
|
||||
|
||||
|
||||
class DeleteTapFlow(command.Command):
|
||||
_description = _("Delete a tap flow")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteTapFlow, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
TAP_FLOW,
|
||||
metavar="<%s>" % TAP_FLOW,
|
||||
nargs="+",
|
||||
help=_("ID(s) or name(s) of tap flow to delete."),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
fails = 0
|
||||
for id_or_name in parsed_args.tap_flow:
|
||||
try:
|
||||
id = client.find_resource(TAP_FLOW, id_or_name)['id']
|
||||
client.delete(resource_path % (TAP_FLOWS, id))
|
||||
LOG.warning("Tap flow %(id)s deleted", {'id': id})
|
||||
except Exception as e:
|
||||
fails += 1
|
||||
LOG.error("Failed to delete tap flow with name or ID "
|
||||
"'%(id_or_name)s': %(e)s",
|
||||
{'id_or_name': id_or_name, 'e': e})
|
||||
if fails > 0:
|
||||
msg = (_("Failed to delete %(fails)s of %(total)s tap flow.") %
|
||||
{'fails': fails, 'total': len(parsed_args.tap_service)})
|
||||
raise exceptions.CommandError(msg)
|
||||
|
||||
|
||||
class UpdateTapFlow(command.ShowOne):
|
||||
_description = _("Update a tap flow.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(UpdateTapFlow, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
TAP_FLOW,
|
||||
metavar="<%s>" % TAP_FLOW,
|
||||
help=_("ID or name of tap flow to update."),
|
||||
)
|
||||
_add_updatable_args(parser)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
id = client.find_resource(TAP_FLOW, parsed_args.tap_flow)['id']
|
||||
attrs = {}
|
||||
if parsed_args.name is not None:
|
||||
attrs['name'] = str(parsed_args.name)
|
||||
if parsed_args.description is not None:
|
||||
attrs['description'] = str(parsed_args.description)
|
||||
body = {TAP_FLOW: attrs}
|
||||
obj = client.put(resource_path % (TAP_FLOWS, id), body)[TAP_FLOW]
|
||||
columns, display_columns = column_util.get_columns(obj, _attr_map)
|
||||
data = osc_utils.get_dict_properties(obj, columns)
|
||||
return display_columns, data
|
203
neutron_taas/taas_client/osc/tap_service.py
Normal file
203
neutron_taas/taas_client/osc/tap_service.py
Normal file
@ -0,0 +1,203 @@
|
||||
# All Rights Reserved 2020
|
||||
#
|
||||
# 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 logging
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import exceptions
|
||||
from osc_lib import utils as osc_utils
|
||||
from osc_lib.utils import columns as column_util
|
||||
|
||||
from neutronclient._i18n import _
|
||||
from neutronclient.neutron import v2_0 as neutronv20
|
||||
from neutronclient.osc import utils as nc_osc_utils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
TAP_SERVICE = 'tap_service'
|
||||
TAP_SERVICES = '%ss' % TAP_SERVICE
|
||||
|
||||
path = 'taas'
|
||||
object_path = '/%s/' % path
|
||||
resource_path = '/%s/%%s/%%s' % path
|
||||
|
||||
_attr_map = (
|
||||
('id', 'ID', column_util.LIST_BOTH),
|
||||
('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY),
|
||||
('name', 'Name', column_util.LIST_BOTH),
|
||||
('port_id', 'Port', column_util.LIST_BOTH),
|
||||
('status', 'Status', column_util.LIST_BOTH),
|
||||
)
|
||||
|
||||
|
||||
def _add_updatable_args(parser):
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
help=_('Name of this Tap service.'))
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
help=_('Description for this Tap service.'))
|
||||
|
||||
|
||||
def _updatable_args2body(parsed_args, body):
|
||||
neutronv20.update_dict(parsed_args, body, ['name', 'description'])
|
||||
|
||||
|
||||
class CreateTapService(command.ShowOne):
|
||||
_description = _("Create a tap service")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateTapService, self).get_parser(prog_name)
|
||||
nc_osc_utils.add_project_owner_option_to_parser(parser)
|
||||
_add_updatable_args(parser)
|
||||
parser.add_argument(
|
||||
'--port',
|
||||
dest='port_id',
|
||||
required=True,
|
||||
metavar="PORT",
|
||||
help=_('Port to which the Tap service is connected.'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
attrs = {}
|
||||
if parsed_args.name is not None:
|
||||
attrs['name'] = str(parsed_args.name)
|
||||
if parsed_args.description is not None:
|
||||
attrs['description'] = str(parsed_args.description)
|
||||
if parsed_args.port_id is not None:
|
||||
port_id = client.find_resource('port', parsed_args.port_id)['id']
|
||||
attrs['port_id'] = port_id
|
||||
if 'project' in parsed_args and parsed_args.project is not None:
|
||||
project_id = nc_osc_utils.find_project(
|
||||
self.app.client_manager.identity,
|
||||
parsed_args.project,
|
||||
parsed_args.project_domain,
|
||||
).id
|
||||
attrs['tenant_id'] = project_id
|
||||
body = {TAP_SERVICE: attrs}
|
||||
obj = client.post('%s%s' % (object_path, TAP_SERVICES),
|
||||
body=body)[TAP_SERVICE]
|
||||
columns, display_columns = column_util.get_columns(obj, _attr_map)
|
||||
data = osc_utils.get_dict_properties(obj, columns)
|
||||
return display_columns, data
|
||||
|
||||
|
||||
class ListTapService(command.Lister):
|
||||
_description = _("List tap services that belong to a given tenant")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListTapService, self).get_parser(prog_name)
|
||||
nc_osc_utils.add_project_owner_option_to_parser(parser)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
params = {}
|
||||
if parsed_args.project is not None:
|
||||
project_id = nc_osc_utils.find_project(
|
||||
self.app.client_manager.identity,
|
||||
parsed_args.project,
|
||||
parsed_args.project_domain,
|
||||
).id
|
||||
params['tenant_id'] = project_id
|
||||
objs = client.list(TAP_SERVICES, '%s%s' % (object_path, TAP_SERVICES),
|
||||
retrieve_all=True, params=params)[TAP_SERVICES]
|
||||
headers, columns = column_util.get_column_definitions(
|
||||
_attr_map, long_listing=True)
|
||||
return (headers, (osc_utils.get_dict_properties(
|
||||
s, columns) for s in objs))
|
||||
|
||||
|
||||
class ShowTapService(command.ShowOne):
|
||||
_description = _("Show information of a given tap service")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowTapService, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
TAP_SERVICE,
|
||||
metavar="<%s>" % TAP_SERVICE,
|
||||
help=_("ID or name of tap service to look up."),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
id = client.find_resource(TAP_SERVICE, parsed_args.tap_service)['id']
|
||||
obj = client.get(resource_path % (TAP_SERVICES, id))[TAP_SERVICE]
|
||||
columns, display_columns = column_util.get_columns(obj, _attr_map)
|
||||
data = osc_utils.get_dict_properties(obj, columns)
|
||||
return display_columns, data
|
||||
|
||||
|
||||
class DeleteTapService(command.Command):
|
||||
_description = _("Delete a tap service")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteTapService, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
TAP_SERVICE,
|
||||
metavar="<%s>" % TAP_SERVICE,
|
||||
nargs="+",
|
||||
help=_("ID(s) or name(s) of tap service to delete."),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
fails = 0
|
||||
for id_or_name in parsed_args.tap_service:
|
||||
try:
|
||||
id = client.find_resource(TAP_SERVICE, id_or_name)['id']
|
||||
client.delete(resource_path % (TAP_SERVICES, id))
|
||||
LOG.warning("Tap service %(id)s deleted", {'id': id})
|
||||
except Exception as e:
|
||||
fails += 1
|
||||
LOG.error("Failed to delete tap service with name or ID "
|
||||
"'%(id_or_name)s': %(e)s",
|
||||
{'id_or_name': id_or_name, 'e': e})
|
||||
if fails > 0:
|
||||
msg = (_("Failed to delete %(fails)s of %(total)s tap service.") %
|
||||
{'fails': fails, 'total': len(parsed_args.tap_service)})
|
||||
raise exceptions.CommandError(msg)
|
||||
|
||||
|
||||
class UpdateTapService(command.ShowOne):
|
||||
_description = _("Update a tap service.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(UpdateTapService, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
TAP_SERVICE,
|
||||
metavar="<%s>" % TAP_SERVICE,
|
||||
help=_("ID or name of tap service to update."),
|
||||
)
|
||||
_add_updatable_args(parser)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.neutronclient
|
||||
id = client.find_resource(TAP_SERVICE, parsed_args.tap_service)['id']
|
||||
attrs = {}
|
||||
if parsed_args.name is not None:
|
||||
attrs['name'] = str(parsed_args.name)
|
||||
if parsed_args.description is not None:
|
||||
attrs['description'] = str(parsed_args.description)
|
||||
body = {TAP_SERVICE: attrs}
|
||||
obj = client.put(resource_path % (TAP_SERVICES, id), body)[TAP_SERVICE]
|
||||
columns, display_columns = column_util.get_columns(obj, _attr_map)
|
||||
data = osc_utils.get_dict_properties(obj, columns)
|
||||
return display_columns, data
|
0
neutron_taas/tests/unit/taas_client/osc/__init__.py
Normal file
0
neutron_taas/tests/unit/taas_client/osc/__init__.py
Normal file
86
neutron_taas/tests/unit/taas_client/osc/fakes.py
Normal file
86
neutron_taas/tests/unit/taas_client/osc/fakes.py
Normal file
@ -0,0 +1,86 @@
|
||||
# All Rights Reserved 2020
|
||||
#
|
||||
# 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 copy
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron_taas.taas_client.osc import tap_flow as osc_tap_flow
|
||||
from neutron_taas.taas_client.osc import tap_service as osc_tap_service
|
||||
|
||||
|
||||
class FakeTapService(object):
|
||||
|
||||
@staticmethod
|
||||
def create_tap_service(attrs=None):
|
||||
"""Create a fake tap service."""
|
||||
attrs = attrs or {}
|
||||
tap_service_attrs = {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'tenant_id': uuidutils.generate_uuid(),
|
||||
'name': 'test_tap_service' + uuidutils.generate_uuid(),
|
||||
'status': 'ACTIVE',
|
||||
}
|
||||
tap_service_attrs.update(attrs)
|
||||
return copy.deepcopy(tap_service_attrs)
|
||||
|
||||
@staticmethod
|
||||
def create_tap_services(attrs=None, count=1):
|
||||
"""Create multiple fake tap services."""
|
||||
|
||||
tap_services = []
|
||||
for i in range(0, count):
|
||||
if attrs is None:
|
||||
attrs = {'id': 'fake_id%d' % i}
|
||||
elif getattr(attrs, 'id', None) is None:
|
||||
attrs['id'] = 'fake_id%d' % i
|
||||
tap_services.append(FakeTapService.create_tap_service(
|
||||
attrs=attrs))
|
||||
|
||||
return {osc_tap_service.TAP_SERVICES: tap_services}
|
||||
|
||||
|
||||
class FakeTapFlow(object):
|
||||
|
||||
@staticmethod
|
||||
def create_tap_flow(attrs=None):
|
||||
"""Create a fake tap service."""
|
||||
attrs = attrs or {}
|
||||
tap_flow_attrs = {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'tenant_id': uuidutils.generate_uuid(),
|
||||
'name': 'test_tap_flow' + uuidutils.generate_uuid(),
|
||||
'status': 'ACTIVE',
|
||||
'direction': 'BOTH',
|
||||
}
|
||||
tap_flow_attrs.update(attrs)
|
||||
return copy.deepcopy(tap_flow_attrs)
|
||||
|
||||
@staticmethod
|
||||
def create_tap_flows(attrs=None, count=1):
|
||||
"""Create multiple fake tap flows."""
|
||||
|
||||
tap_flows = []
|
||||
for i in range(0, count):
|
||||
if attrs is None:
|
||||
attrs = {
|
||||
'id': 'fake_id%d' % i,
|
||||
'source_port': uuidutils.generate_uuid(),
|
||||
'tap_service_id': uuidutils.generate_uuid()
|
||||
}
|
||||
elif getattr(attrs, 'id', None) is None:
|
||||
attrs['id'] = 'fake_id%d' % i
|
||||
tap_flows.append(FakeTapFlow.create_tap_flow(attrs=attrs))
|
||||
|
||||
return {osc_tap_flow.TAP_FLOWS: tap_flows}
|
257
neutron_taas/tests/unit/taas_client/osc/test_osc_tap_flow.py
Normal file
257
neutron_taas/tests/unit/taas_client/osc/test_osc_tap_flow.py
Normal file
@ -0,0 +1,257 @@
|
||||
# All Rights Reserved 2020
|
||||
#
|
||||
# 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 copy
|
||||
import operator
|
||||
from unittest import mock
|
||||
|
||||
from neutronclient.tests.unit.osc.v2 import fakes as test_fakes
|
||||
from osc_lib import utils as osc_utils
|
||||
from osc_lib.utils import columns as column_util
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron_taas.taas_client.osc import tap_flow as osc_tap_flow
|
||||
from neutron_taas.tests.unit.taas_client.osc import fakes
|
||||
|
||||
|
||||
columns_long = tuple(col for col, _, listing_mode in osc_tap_flow._attr_map
|
||||
if listing_mode in (column_util.LIST_BOTH,
|
||||
column_util.LIST_LONG_ONLY))
|
||||
headers_long = tuple(head for _, head, listing_mode in
|
||||
osc_tap_flow._attr_map if listing_mode in
|
||||
(column_util.LIST_BOTH, column_util.LIST_LONG_ONLY))
|
||||
sorted_attr_map = sorted(osc_tap_flow._attr_map, key=operator.itemgetter(1))
|
||||
sorted_columns = tuple(col for col, _, _ in sorted_attr_map)
|
||||
sorted_headers = tuple(head for _, head, _ in sorted_attr_map)
|
||||
|
||||
|
||||
def _get_data(attrs, columns=sorted_columns):
|
||||
return osc_utils.get_dict_properties(attrs, columns)
|
||||
|
||||
|
||||
class TestCreateTapService(test_fakes.TestNeutronClientOSCV2):
|
||||
|
||||
columns = (
|
||||
'Direction',
|
||||
'ID',
|
||||
'Name',
|
||||
'Status',
|
||||
'Tenant',
|
||||
'source_port',
|
||||
'tap_service_id',
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(TestCreateTapService, self).setUp()
|
||||
self.cmd = osc_tap_flow.CreateTapFlow(self.app, self.namespace)
|
||||
|
||||
def test_create_tap_flow(self):
|
||||
"""Test Create Tap Flow."""
|
||||
fake_tap_flow = fakes.FakeTapFlow.create_tap_flow(
|
||||
attrs={
|
||||
'source_port': uuidutils.generate_uuid(),
|
||||
'tap_service_id': uuidutils.generate_uuid()
|
||||
}
|
||||
)
|
||||
|
||||
self.neutronclient.post = mock.Mock(
|
||||
return_value={osc_tap_flow.TAP_FLOW: fake_tap_flow})
|
||||
arg_list = [
|
||||
'--name', fake_tap_flow['name'],
|
||||
'--port', fake_tap_flow['source_port'],
|
||||
'--tap-service', fake_tap_flow['tap_service_id'],
|
||||
'--direction', fake_tap_flow['direction'],
|
||||
]
|
||||
|
||||
verify_list = [
|
||||
('name', fake_tap_flow['name']),
|
||||
('port', fake_tap_flow['source_port']),
|
||||
('tap_service', fake_tap_flow['tap_service_id']),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
with mock.patch.object(self.neutronclient, 'find_resource') as nc_find:
|
||||
nc_find.side_effect = [
|
||||
{'id': fake_tap_flow['source_port']},
|
||||
{'id': fake_tap_flow['tap_service_id']}
|
||||
]
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.neutronclient.post.assert_called_once_with(
|
||||
'/taas/tap_flows',
|
||||
body={
|
||||
osc_tap_flow.TAP_FLOW:
|
||||
{
|
||||
'name': fake_tap_flow['name'],
|
||||
'source_port': fake_tap_flow['source_port'],
|
||||
'tap_service_id': fake_tap_flow['tap_service_id'],
|
||||
'direction': fake_tap_flow['direction']
|
||||
}
|
||||
}
|
||||
)
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertItemEqual(_get_data(fake_tap_flow), data)
|
||||
|
||||
|
||||
class TestListTapFlow(test_fakes.TestNeutronClientOSCV2):
|
||||
def setUp(self):
|
||||
super(TestListTapFlow, self).setUp()
|
||||
self.cmd = osc_tap_flow.ListTapFlow(self.app, self.namespace)
|
||||
|
||||
def test_list_tap_flows(self):
|
||||
"""Test List Tap Flow."""
|
||||
fake_tap_flows = fakes.FakeTapFlow.create_tap_flows(
|
||||
attrs={
|
||||
'source_port': uuidutils.generate_uuid(),
|
||||
'tap_service_id': uuidutils.generate_uuid(),
|
||||
},
|
||||
count=2)
|
||||
self.neutronclient.list = mock.Mock(return_value=fake_tap_flows)
|
||||
arg_list = []
|
||||
verify_list = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
|
||||
headers, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.neutronclient.list.assert_called_once()
|
||||
self.assertEqual(headers, list(headers_long))
|
||||
self.assertListItemEqual(
|
||||
list(data),
|
||||
[_get_data(fake_tap_flow, columns_long) for fake_tap_flow
|
||||
in fake_tap_flows[osc_tap_flow.TAP_FLOWS]]
|
||||
)
|
||||
|
||||
|
||||
class TestDeleteTapFlow(test_fakes.TestNeutronClientOSCV2):
|
||||
def setUp(self):
|
||||
super(TestDeleteTapFlow, self).setUp()
|
||||
self.neutronclient.find_resource = mock.Mock(
|
||||
side_effect=lambda _, name_or_id: {'id': name_or_id})
|
||||
self.cmd = osc_tap_flow.DeleteTapFlow(self.app, self.namespace)
|
||||
|
||||
def test_delete_tap_flow(self):
|
||||
"""Test Delete tap flow."""
|
||||
|
||||
fake_tap_flow = fakes.FakeTapFlow.create_tap_flow(
|
||||
attrs={
|
||||
'source_port': uuidutils.generate_uuid(),
|
||||
'tap_service_id': uuidutils.generate_uuid(),
|
||||
}
|
||||
)
|
||||
self.neutronclient.delete = mock.Mock()
|
||||
|
||||
arg_list = [
|
||||
fake_tap_flow['id'],
|
||||
]
|
||||
verify_list = [
|
||||
(osc_tap_flow.TAP_FLOW, [fake_tap_flow['id']]),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.neutronclient.delete.assert_called_once_with(
|
||||
osc_tap_flow.resource_path % ('tap_flows',
|
||||
fake_tap_flow['id']))
|
||||
self.assertIsNone(result)
|
||||
|
||||
|
||||
class TestShowTapFlow(test_fakes.TestNeutronClientOSCV2):
|
||||
def setUp(self):
|
||||
super(TestShowTapFlow, self).setUp()
|
||||
self.neutronclient.find_resource = mock.Mock(
|
||||
side_effect=lambda _, name_or_id: {'id': name_or_id})
|
||||
self.cmd = osc_tap_flow.ShowTapFlow(self.app, self.namespace)
|
||||
|
||||
def test_show_tap_flow(self):
|
||||
"""Test Show tap flow."""
|
||||
|
||||
fake_tap_flow = fakes.FakeTapFlow.create_tap_flow(
|
||||
attrs={
|
||||
'source_port': uuidutils.generate_uuid(),
|
||||
'tap_service_id': uuidutils.generate_uuid(),
|
||||
}
|
||||
)
|
||||
self.neutronclient.get = mock.Mock(
|
||||
return_value={osc_tap_flow.TAP_FLOW: fake_tap_flow})
|
||||
arg_list = [
|
||||
fake_tap_flow['id'],
|
||||
]
|
||||
verify_list = [
|
||||
(osc_tap_flow.TAP_FLOW, fake_tap_flow['id']),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
|
||||
headers, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.neutronclient.get.assert_called_once_with(
|
||||
osc_tap_flow.resource_path % ('tap_flows',
|
||||
fake_tap_flow['id']))
|
||||
self.assertEqual(sorted_headers, headers)
|
||||
self.assertItemEqual(_get_data(fake_tap_flow), data)
|
||||
|
||||
|
||||
class TestUpdateTapFlow(test_fakes.TestNeutronClientOSCV2):
|
||||
|
||||
_new_name = 'new_name'
|
||||
|
||||
columns = (
|
||||
'Direction',
|
||||
'ID',
|
||||
'Name',
|
||||
'Status',
|
||||
'Tenant',
|
||||
'source_port',
|
||||
'tap_service_id',
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(TestUpdateTapFlow, self).setUp()
|
||||
self.cmd = osc_tap_flow.UpdateTapFlow(self.app, self.namespace)
|
||||
self.neutronclient.find_resource = mock.Mock(
|
||||
side_effect=lambda _, name_or_id: {'id': name_or_id})
|
||||
|
||||
def test_update_tap_flow(self):
|
||||
"""Test update tap service"""
|
||||
fake_tap_flow = fakes.FakeTapFlow.create_tap_flow(
|
||||
attrs={
|
||||
'source_port': uuidutils.generate_uuid(),
|
||||
'tap_service_id': uuidutils.generate_uuid(),
|
||||
}
|
||||
)
|
||||
new_tap_flow = copy.deepcopy(fake_tap_flow)
|
||||
new_tap_flow['name'] = self._new_name
|
||||
|
||||
self.neutronclient.put = mock.Mock(
|
||||
return_value={osc_tap_flow.TAP_FLOW: new_tap_flow})
|
||||
|
||||
arg_list = [
|
||||
fake_tap_flow['id'],
|
||||
'--name', self._new_name,
|
||||
]
|
||||
verify_list = [('name', self._new_name)]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
attrs = {'name': self._new_name}
|
||||
|
||||
self.neutronclient.put.assert_called_once_with(
|
||||
osc_tap_flow.resource_path % ('tap_flows',
|
||||
new_tap_flow['id']),
|
||||
{osc_tap_flow.TAP_FLOW: attrs})
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertItemEqual(_get_data(new_tap_flow), data)
|
229
neutron_taas/tests/unit/taas_client/osc/test_osc_tap_service.py
Normal file
229
neutron_taas/tests/unit/taas_client/osc/test_osc_tap_service.py
Normal file
@ -0,0 +1,229 @@
|
||||
# All Rights Reserved 2020
|
||||
#
|
||||
# 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 copy
|
||||
import operator
|
||||
from unittest import mock
|
||||
|
||||
from neutronclient.tests.unit.osc.v2 import fakes as test_fakes
|
||||
from osc_lib import utils as osc_utils
|
||||
from osc_lib.utils import columns as column_util
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron_taas.taas_client.osc import tap_service as osc_tap_service
|
||||
from neutron_taas.tests.unit.taas_client.osc import fakes
|
||||
|
||||
|
||||
columns_long = tuple(col for col, _, listing_mode in osc_tap_service._attr_map
|
||||
if listing_mode in (column_util.LIST_BOTH,
|
||||
column_util.LIST_LONG_ONLY))
|
||||
headers_long = tuple(head for _, head, listing_mode in
|
||||
osc_tap_service._attr_map if listing_mode in
|
||||
(column_util.LIST_BOTH, column_util.LIST_LONG_ONLY))
|
||||
sorted_attr_map = sorted(osc_tap_service._attr_map, key=operator.itemgetter(1))
|
||||
sorted_columns = tuple(col for col, _, _ in sorted_attr_map)
|
||||
sorted_headers = tuple(head for _, head, _ in sorted_attr_map)
|
||||
|
||||
|
||||
def _get_data(attrs, columns=sorted_columns):
|
||||
return osc_utils.get_dict_properties(attrs, columns)
|
||||
|
||||
|
||||
class TestCreateTapService(test_fakes.TestNeutronClientOSCV2):
|
||||
|
||||
columns = (
|
||||
'ID',
|
||||
'Name',
|
||||
'Port',
|
||||
'Status',
|
||||
'Tenant',
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(TestCreateTapService, self).setUp()
|
||||
self.cmd = osc_tap_service.CreateTapService(self.app, self.namespace)
|
||||
|
||||
def test_create_tap_service(self):
|
||||
"""Test Create Tap Service."""
|
||||
fake_tap_service = fakes.FakeTapService.create_tap_service(
|
||||
attrs={'port_id': uuidutils.generate_uuid()}
|
||||
)
|
||||
|
||||
self.neutronclient.post = mock.Mock(
|
||||
return_value={osc_tap_service.TAP_SERVICE: fake_tap_service})
|
||||
arg_list = [
|
||||
'--name', fake_tap_service['name'],
|
||||
'--port', fake_tap_service['port_id'],
|
||||
]
|
||||
|
||||
verify_list = [
|
||||
('name', fake_tap_service['name']),
|
||||
('port_id', fake_tap_service['port_id']),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
self.neutronclient.find_resource = mock.Mock(
|
||||
return_value={'id': fake_tap_service['port_id']})
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.neutronclient.post.assert_called_once_with(
|
||||
'/taas/tap_services',
|
||||
body={
|
||||
osc_tap_service.TAP_SERVICE:
|
||||
{
|
||||
'name': fake_tap_service['name'],
|
||||
'port_id': fake_tap_service['port_id']
|
||||
}
|
||||
}
|
||||
)
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertItemEqual(_get_data(fake_tap_service), data)
|
||||
|
||||
|
||||
class TestListTapService(test_fakes.TestNeutronClientOSCV2):
|
||||
def setUp(self):
|
||||
super(TestListTapService, self).setUp()
|
||||
self.cmd = osc_tap_service.ListTapService(self.app, self.namespace)
|
||||
|
||||
def test_list_tap_service(self):
|
||||
"""Test List Tap Service."""
|
||||
fake_tap_services = fakes.FakeTapService.create_tap_services(
|
||||
attrs={'port_id': uuidutils.generate_uuid()},
|
||||
count=4)
|
||||
self.neutronclient.list = mock.Mock(return_value=fake_tap_services)
|
||||
arg_list = []
|
||||
verify_list = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
|
||||
headers, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.neutronclient.list.assert_called_once()
|
||||
self.assertEqual(headers, list(headers_long))
|
||||
self.assertListItemEqual(
|
||||
list(data),
|
||||
[_get_data(fake_tap_service, columns_long) for fake_tap_service
|
||||
in fake_tap_services[osc_tap_service.TAP_SERVICES]]
|
||||
)
|
||||
|
||||
|
||||
class TestDeleteTapService(test_fakes.TestNeutronClientOSCV2):
|
||||
def setUp(self):
|
||||
super(TestDeleteTapService, self).setUp()
|
||||
self.neutronclient.find_resource = mock.Mock(
|
||||
side_effect=lambda _, name_or_id: {'id': name_or_id})
|
||||
self.cmd = osc_tap_service.DeleteTapService(self.app, self.namespace)
|
||||
|
||||
def test_delete_tap_service(self):
|
||||
"""Test Delete tap service."""
|
||||
|
||||
fake_tap_service = fakes.FakeTapService.create_tap_service(
|
||||
attrs={'port_id': uuidutils.generate_uuid()}
|
||||
)
|
||||
self.neutronclient.delete = mock.Mock()
|
||||
|
||||
arg_list = [
|
||||
fake_tap_service['id'],
|
||||
]
|
||||
verify_list = [
|
||||
(osc_tap_service.TAP_SERVICE, [fake_tap_service['id']]),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.neutronclient.delete.assert_called_once_with(
|
||||
osc_tap_service.resource_path % ('tap_services',
|
||||
fake_tap_service['id']))
|
||||
self.assertIsNone(result)
|
||||
|
||||
|
||||
class TestShowTapService(test_fakes.TestNeutronClientOSCV2):
|
||||
def setUp(self):
|
||||
super(TestShowTapService, self).setUp()
|
||||
self.neutronclient.find_resource = mock.Mock(
|
||||
side_effect=lambda _, name_or_id: {'id': name_or_id})
|
||||
self.cmd = osc_tap_service.ShowTapService(self.app, self.namespace)
|
||||
|
||||
def test_show_tap_service(self):
|
||||
"""Test Show tap service."""
|
||||
|
||||
fake_tap_service = fakes.FakeTapService.create_tap_service(
|
||||
attrs={'port_id': uuidutils.generate_uuid()}
|
||||
)
|
||||
self.neutronclient.get = mock.Mock(
|
||||
return_value={osc_tap_service.TAP_SERVICE: fake_tap_service})
|
||||
arg_list = [
|
||||
fake_tap_service['id'],
|
||||
]
|
||||
verify_list = [
|
||||
(osc_tap_service.TAP_SERVICE, fake_tap_service['id']),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
|
||||
headers, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.neutronclient.get.assert_called_once_with(
|
||||
osc_tap_service.resource_path % ('tap_services',
|
||||
fake_tap_service['id']))
|
||||
self.assertEqual(sorted_headers, headers)
|
||||
self.assertItemEqual(_get_data(fake_tap_service), data)
|
||||
|
||||
|
||||
class TestUpdateTapService(test_fakes.TestNeutronClientOSCV2):
|
||||
|
||||
_new_name = 'new_name'
|
||||
|
||||
columns = (
|
||||
'ID',
|
||||
'Name',
|
||||
'Port',
|
||||
'Status',
|
||||
'Tenant',
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(TestUpdateTapService, self).setUp()
|
||||
self.cmd = osc_tap_service.UpdateTapService(self.app, self.namespace)
|
||||
self.neutronclient.find_resource = mock.Mock(
|
||||
side_effect=lambda _, name_or_id: {'id': name_or_id})
|
||||
|
||||
def test_update_tap_service(self):
|
||||
"""Test update tap service"""
|
||||
fake_tap_service = fakes.FakeTapService.create_tap_service(
|
||||
attrs={'port_id': uuidutils.generate_uuid()}
|
||||
)
|
||||
new_tap_service = copy.deepcopy(fake_tap_service)
|
||||
new_tap_service['name'] = self._new_name
|
||||
|
||||
self.neutronclient.put = mock.Mock(
|
||||
return_value={osc_tap_service.TAP_SERVICE: new_tap_service})
|
||||
|
||||
arg_list = [
|
||||
fake_tap_service['id'],
|
||||
'--name', self._new_name,
|
||||
]
|
||||
verify_list = [('name', self._new_name)]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
attrs = {'name': self._new_name}
|
||||
|
||||
self.neutronclient.put.assert_called_once_with(
|
||||
osc_tap_service.resource_path % ('tap_services',
|
||||
new_tap_service['id']),
|
||||
{osc_tap_service.TAP_SERVICE: attrs})
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertItemEqual(_get_data(new_tap_service), data)
|
11
setup.cfg
11
setup.cfg
@ -76,6 +76,17 @@ oslo.policy.policies =
|
||||
tap-as-a-service = neutron_taas.policies:list_rules
|
||||
neutron.policies =
|
||||
tap-as-a-service = neutron_taas.policies:list_rules
|
||||
openstack.neutronclient.v2 =
|
||||
tap_service_create = neutron_taas.taas_client.osc.tap_service:CreateTapService
|
||||
tap_service_list = neutron_taas.taas_client.osc.tap_service:ListTapService
|
||||
tap_service_show = neutron_taas.taas_client.osc.tap_service:ShowTapService
|
||||
tap_service_delete = neutron_taas.taas_client.osc.tap_service:DeleteTapService
|
||||
tap_service_update = neutron_taas.taas_client.osc.tap_service:UpdateTapService
|
||||
tap_flow_create = neutron_taas.taas_client.osc.tap_flow:CreateTapFlow
|
||||
tap_flow_list = neutron_taas.taas_client.osc.tap_flow:ListTapFlow
|
||||
tap_flow_show = neutron_taas.taas_client.osc.tap_flow:ShowTapFlow
|
||||
tap_flow_delete = neutron_taas.taas_client.osc.tap_flow:DeleteTapFlow
|
||||
tap_flow_update = neutron_taas.taas_client.osc.tap_flow:UpdateTapFlow
|
||||
|
||||
|
||||
[pbr]
|
||||
|
@ -9,6 +9,7 @@ python-subunit>=1.4.0 # Apache-2.0/BSD
|
||||
psycopg2>=2.8.5 # LGPL/ZPL
|
||||
PyMySQL>=0.10.0 # MIT License
|
||||
oslotest>=4.4.1 # Apache-2.0
|
||||
requests_mock>=1.5.0 # Apache-2.0
|
||||
stestr>=3.0.1 # Apache-2.0
|
||||
testresources>=2.0.1 # Apache-2.0/BSD
|
||||
testscenarios>=0.5.0 # Apache-2.0/BSD
|
||||
|
Loading…
Reference in New Issue
Block a user