Merge "Introduce API definition for trunk/trunk_details extensions"
This commit is contained in:
commit
a0e7337425
@ -29,6 +29,8 @@ Networking API v2.0
|
||||
.. include:: network-ip-availability.inc
|
||||
.. include:: qos.inc
|
||||
.. include:: metering.inc
|
||||
.. include:: trunk.inc
|
||||
.. include:: trunk-details.inc
|
||||
.. include:: lbaas-v2.inc
|
||||
.. include:: lbaas-v1.inc
|
||||
.. include:: fwaas.inc
|
||||
|
@ -111,6 +111,8 @@ attribute in responses, check that the ``project-id`` API extension is enabled
|
||||
(see Extensions_).
|
||||
|
||||
|
||||
.. _filtering:
|
||||
|
||||
Filtering and column selection
|
||||
==============================
|
||||
|
||||
|
@ -187,6 +187,12 @@ tag:
|
||||
in: path
|
||||
required: false
|
||||
type: string
|
||||
trunk_id:
|
||||
description: |
|
||||
The ID of the trunk.
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
vip_id_1:
|
||||
description: |
|
||||
The UUID for the VIP.
|
||||
@ -482,6 +488,13 @@ admin_state_up_9:
|
||||
in: body
|
||||
required: false
|
||||
type: boolean
|
||||
admin_state_up_trunk:
|
||||
description: |
|
||||
The administrative state of the trunk, which
|
||||
is up (``true``) or down (``false``).
|
||||
in: body
|
||||
required: false
|
||||
type: boolean
|
||||
alias:
|
||||
description: |
|
||||
The alias for the extension. For example,
|
||||
@ -642,6 +655,12 @@ created_at_1:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
created_at_resource:
|
||||
description: |
|
||||
Time at which the resource has been created (in UTC ISO8601 format).
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
default:
|
||||
description: |
|
||||
Defines whether the provider is the default for
|
||||
@ -983,6 +1002,12 @@ description_9:
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
description_resource:
|
||||
description: |
|
||||
The description for the resource.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
destination_ip_address:
|
||||
description: |
|
||||
The destination IPv4 or IPv6 address or CIDR. No
|
||||
@ -1700,6 +1725,12 @@ id_9:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
id_resource:
|
||||
description: |
|
||||
The ID for the resource.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
ike_version:
|
||||
description: |
|
||||
The IKE version. A valid value is ``v1`` or
|
||||
@ -2438,6 +2469,12 @@ name_9:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
name_resource:
|
||||
description: |
|
||||
The name of the resource.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
network:
|
||||
description: |
|
||||
A ``network`` object.
|
||||
@ -2715,6 +2752,12 @@ port_id_4:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
port_id_subport:
|
||||
description: |
|
||||
The ID of the subport.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
port_range_max:
|
||||
description: |
|
||||
The maximum port number in the range that is
|
||||
@ -3116,6 +3159,12 @@ resources:
|
||||
in: body
|
||||
required: true
|
||||
type: array
|
||||
revision_number:
|
||||
description: |
|
||||
The revision number of the resource.
|
||||
in: body
|
||||
required: true
|
||||
type: integer
|
||||
route_mode:
|
||||
description: |
|
||||
The route mode. A valid value is ``static``,
|
||||
@ -3447,6 +3496,18 @@ segment_id:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
segmentation_id:
|
||||
description: |
|
||||
The segmentation ID for the subport.
|
||||
in: body
|
||||
required: false
|
||||
type: integer
|
||||
segmentation_type:
|
||||
description: |
|
||||
The segmentation type for the subport.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
segments:
|
||||
description: |
|
||||
A list of provider ``segment`` objects.
|
||||
@ -3754,6 +3815,12 @@ status_description:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
sub_ports:
|
||||
description: |
|
||||
A list of ports associated with the trunk.
|
||||
in: body
|
||||
required: true
|
||||
type: array
|
||||
subnet_id:
|
||||
description: |
|
||||
If you specify only a subnet UUID, OpenStack
|
||||
@ -3900,6 +3967,25 @@ transform_protocol_1:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
trunk_details:
|
||||
description: |
|
||||
The details about the trunk.
|
||||
in: body
|
||||
required: false
|
||||
type: dict
|
||||
trunk_port_id:
|
||||
description: |
|
||||
The ID of the parent port.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
trunk_status:
|
||||
description: |
|
||||
The status for the trunk. Possible values are ``ACTIVE``,
|
||||
``DOWN``, ``BUILD``, ``DEGRADED``, and ``ERROR``.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
type:
|
||||
description: |
|
||||
The type of probe sent by the load balancer to
|
||||
@ -3973,6 +4059,12 @@ updated_at_2:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
updated_at_resource:
|
||||
description: |
|
||||
Time at which the resource has been updated (in UTC ISO8601 format).
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
url_path:
|
||||
description: |
|
||||
The HTTP path of the request sent by the monitor
|
||||
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"sub_ports": [
|
||||
{
|
||||
"segmentation_id": 44,
|
||||
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155",
|
||||
"segmentation_type": "vlan"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"status": "DOWN",
|
||||
"sub_ports": [
|
||||
{
|
||||
"segmentation_type": "vlan",
|
||||
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155",
|
||||
"segmentation_id": 44
|
||||
}
|
||||
],
|
||||
"name": "test",
|
||||
"admin_state_up": true,
|
||||
"project_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"tenant_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"created_at": "2016-10-05T22:31:37Z",
|
||||
"updated_at": "2016-10-05T22:52:04Z",
|
||||
"revision_number": 2,
|
||||
"port_id": "8027c4da-772f-4e43-bfbf-023b4a4e63de",
|
||||
"id": "114a26b1-d124-4835-bb4f-021d3d886023",
|
||||
"description": ""
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"trunk": {
|
||||
"port_id": "8027c4da-772f-4e43-bfbf-023b4a4e63de",
|
||||
"name": "test",
|
||||
"admin_state_up": true
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
{
|
||||
"port": {
|
||||
"status": "DOWN",
|
||||
"created_at": "2016-10-05T20:05:14Z",
|
||||
"description": "",
|
||||
"admin_state_up": true,
|
||||
"network_id": "1cf9e069-365f-4a78-8784-616bc12c4c5a",
|
||||
"project_id": "313be01bd0744cea86643c711c57012b",
|
||||
"tenant_id": "313be01bd0744cea86643c711c57012b",
|
||||
"extra_dhcp_opts": [],
|
||||
"updated_at": "2016-10-05T20:05:14Z",
|
||||
"name": "test",
|
||||
"device_owner": "",
|
||||
"trunk_details": {
|
||||
"trunk_id": "8905d084-010c-46e8-a863-f21cb4441ab1",
|
||||
"sub_ports": [
|
||||
{
|
||||
"segmentation_id": 33,
|
||||
"port_id": "70df9f3e-b409-4761-8304-ce029b2079f5",
|
||||
"segmentation_type": "vlan",
|
||||
"mac_address": "fa:16:3e:86:9b:dc"
|
||||
},
|
||||
{
|
||||
"segmentation_id": 44,
|
||||
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155",
|
||||
"segmentation_type": "vlan",
|
||||
"mac_address": "fa:16:3e:fe:29:97"
|
||||
}
|
||||
]
|
||||
},
|
||||
"revision_number": 5,
|
||||
"mac_address": "fa:16:3e:5c:e9:a3",
|
||||
"fixed_ips": [
|
||||
{
|
||||
"subnet_id": "76a059c0-b189-479f-882c-5e8bd464ea49",
|
||||
"ip_address": "40.0.0.3"
|
||||
}
|
||||
],
|
||||
"id": "8027c4da-772f-4e43-bfbf-023b4a4e63de",
|
||||
"security_groups": ["da88a249-12ac-4221-9565-c406b6feeb48"],
|
||||
"device_id": ""
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"sub_ports": [
|
||||
{
|
||||
"segmentation_type": "vlan",
|
||||
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155",
|
||||
"segmentation_id": 44
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"sub_ports": [
|
||||
{
|
||||
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
{
|
||||
"status": "DOWN",
|
||||
"sub_ports": [],
|
||||
"name": "test",
|
||||
"admin_state_up": true,
|
||||
"project_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"tenant_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"created_at": "2016-10-05T22:31:37Z",
|
||||
"updated_at": "2016-10-05T22:57:44Z",
|
||||
"revision_number": 3,
|
||||
"port_id": "8027c4da-772f-4e43-bfbf-023b4a4e63de",
|
||||
"id": "114a26b1-d124-4835-bb4f-021d3d886023",
|
||||
"description": ""
|
||||
}
|
22
api-ref/source/v2/samples/trunks/trunk-show-response.json
Normal file
22
api-ref/source/v2/samples/trunks/trunk-show-response.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"trunk": {
|
||||
"status": "DOWN",
|
||||
"sub_ports": [
|
||||
{
|
||||
"segmentation_type": "vlan",
|
||||
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155",
|
||||
"segmentation_id": 44
|
||||
}
|
||||
],
|
||||
"name": "foo",
|
||||
"admin_state_up": true,
|
||||
"project_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"tenant_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"created_at": "2016-10-05T22:31:37Z",
|
||||
"updated_at": "2016-10-05T23:28:17Z",
|
||||
"revision_number": 9,
|
||||
"port_id": "8027c4da-772f-4e43-bfbf-023b4a4e63de",
|
||||
"id": "114a26b1-d124-4835-bb4f-021d3d886023",
|
||||
"description": ""
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"trunk": {
|
||||
"name": "foo",
|
||||
"admin_state_up": true
|
||||
}
|
||||
}
|
22
api-ref/source/v2/samples/trunks/trunk-update-response.json
Normal file
22
api-ref/source/v2/samples/trunks/trunk-update-response.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"trunk": {
|
||||
"status": "DOWN",
|
||||
"sub_ports": [
|
||||
{
|
||||
"segmentation_type": "vlan",
|
||||
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155",
|
||||
"segmentation_id": 44
|
||||
}
|
||||
],
|
||||
"name": "foo",
|
||||
"admin_state_up": true,
|
||||
"project_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"tenant_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"created_at": "2016-10-05T22:31:37Z",
|
||||
"updated_at": "2016-10-05T23:28:17Z",
|
||||
"revision_number": 9,
|
||||
"port_id": "8027c4da-772f-4e43-bfbf-023b4a4e63de",
|
||||
"id": "114a26b1-d124-4835-bb4f-021d3d886023",
|
||||
"description": ""
|
||||
}
|
||||
}
|
16
api-ref/source/v2/samples/trunks/trunks-create-response.json
Normal file
16
api-ref/source/v2/samples/trunks/trunks-create-response.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"trunk": {
|
||||
"status": "DOWN",
|
||||
"sub_ports": [],
|
||||
"name": "test",
|
||||
"admin_state_up": true,
|
||||
"project_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"tenant_id": "145a14e4a64b49bf98baad8945dbd4f1",
|
||||
"created_at": "2016-10-05T22:31:37Z",
|
||||
"updated_at": "2016-10-05T22:31:37Z",
|
||||
"revision_number": 1,
|
||||
"port_id": "8027c4da-772f-4e43-bfbf-023b4a4e63de",
|
||||
"id": "114a26b1-d124-4835-bb4f-021d3d886023",
|
||||
"description": ""
|
||||
}
|
||||
}
|
18
api-ref/source/v2/samples/trunks/trunks-list-response.json
Normal file
18
api-ref/source/v2/samples/trunks/trunks-list-response.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"trunks": [
|
||||
{
|
||||
"status": "DOWN",
|
||||
"sub_ports": [],
|
||||
"name": "test",
|
||||
"admin_state_up": true,
|
||||
"project_id": "313be01bd0744cea86643c711c57012b",
|
||||
"tenant_id": "313be01bd0744cea86643c711c57012b",
|
||||
"created_at": "2016-10-05T20:11:16Z",
|
||||
"updated_at": "2016-10-05T20:11:16Z",
|
||||
"revision_number": 1,
|
||||
"port_id": "8027c4da-772f-4e43-bfbf-023b4a4e63de",
|
||||
"id": "ee98bdb4-a817-43af-943f-4318bff98f51",
|
||||
"description": ""
|
||||
}
|
||||
]
|
||||
}
|
43
api-ref/source/v2/trunk-details.inc
Normal file
43
api-ref/source/v2/trunk-details.inc
Normal file
@ -0,0 +1,43 @@
|
||||
.. -*- rst -*-
|
||||
|
||||
=========================================
|
||||
Trunk details extended attributes (ports)
|
||||
=========================================
|
||||
|
||||
The trunk_details extension attribute is available when showing a
|
||||
port resource that participates in a trunk as parent. The extension
|
||||
is useful for REST clients that may want to access trunk details
|
||||
when getting the parent port, and it allows them to avoid extra
|
||||
lookups.
|
||||
|
||||
Show trunk details
|
||||
==================
|
||||
|
||||
.. rest_method:: GET /v2.0/ports/{port_id}
|
||||
|
||||
Shows details for a port. The details available in the `trunk_details`
|
||||
attribute contain the trunk ID and the array showing information
|
||||
about the subports that belong to the trunk: the port UUID, the
|
||||
segmentation type, the segmentation ID, and the MAC address.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- port_id: port_id
|
||||
|
||||
Response Parameters
|
||||
-------------------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- trunk_details: trunk_details
|
||||
|
||||
Response Example
|
||||
----------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-details-show-response.json
|
||||
:language: javascript
|
386
api-ref/source/v2/trunk.inc
Normal file
386
api-ref/source/v2/trunk.inc
Normal file
@ -0,0 +1,386 @@
|
||||
.. -*- rst -*-
|
||||
|
||||
================
|
||||
Trunk networking
|
||||
================
|
||||
|
||||
The trunk extension can be used to multiplex packets coming from and going to
|
||||
multiple neutron logical networks using a single neutron logical port. A trunk
|
||||
is modeled in neutron as a collection of neutron logical ports. One port,
|
||||
called parent port, must be associated to a trunk and it is *the* port to
|
||||
be used to connect instances with neutron. A sequence of subports (or
|
||||
sub_ports) each typically belonging to distinct neutron networks, is also
|
||||
associated to a trunk, and each subport may have a segmentation type and ID
|
||||
used to mux/demux the traffic coming in and out of the parent port.
|
||||
|
||||
In more details, the extension introduces the following resources:
|
||||
|
||||
- **trunk**. A top level logical entity to model the group of neutron
|
||||
logical networks whose traffic flows through the trunk.
|
||||
|
||||
- **sub_port**. An association to a neutron logical port with attributes
|
||||
segmentation_id and segmentation_type.
|
||||
|
||||
|
||||
List trunks
|
||||
===========
|
||||
|
||||
.. rest_method:: GET /v2.0/trunks
|
||||
|
||||
Lists trunks that are accessible to the user who submits the request.
|
||||
|
||||
Default policy settings return only those trunks that are
|
||||
owned by the user who submits the request, unless an admin user
|
||||
submits the request.
|
||||
|
||||
Use the ``fields`` query parameter to control which fields are
|
||||
returned in the response body. Additionally, you can filter results
|
||||
by using query string parameters. For information, see the Filtering_
|
||||
section for more details.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: 401,404
|
||||
|
||||
Response Parameters
|
||||
-------------------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- admin_state_up: admin_state_up_trunk
|
||||
- created_at: created_at_resource
|
||||
- description: description_resource
|
||||
- id: id_resource
|
||||
- name: name_resource
|
||||
- port_id: trunk_port_id
|
||||
- revision_number: revision_number
|
||||
- status: trunk_status
|
||||
- tenant_id: project_id-request
|
||||
- project_id: project_id-request
|
||||
- sub_ports: sub_ports
|
||||
- updated_at: updated_at_resource
|
||||
|
||||
Response Example
|
||||
----------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunks-list-response.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Create trunk
|
||||
============
|
||||
|
||||
.. rest_method:: POST /v2.0/trunks
|
||||
|
||||
Error codes:
|
||||
|
||||
- ``400`` The operation returns this error code if the request is malformed,
|
||||
e.g. there are missing or invalid parameters in the request.
|
||||
|
||||
- ``401`` The operation is not authorized.
|
||||
|
||||
- ``404`` If the extension is not available or the port UUID of any of the
|
||||
specified ports is not found.
|
||||
|
||||
- ``409`` The operation returns this error code for one of these
|
||||
reasons:
|
||||
|
||||
- A port to be used as subport is in use by another trunk.
|
||||
|
||||
- The segmentation type and segmentation ID are already in use in the trunk.
|
||||
|
||||
- A port to be used as parent port is in use by another trunk or cannot be trunked.
|
||||
|
||||
- A system configuration prevents the operation from succeeding.
|
||||
|
||||
|
||||
Error response codes: 201,400,401,404,409
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- tenant_id: project_id
|
||||
- project_id: project_id
|
||||
- port_id: trunk_port_id
|
||||
- name: name_resource
|
||||
- description: description_resource
|
||||
- admin_state_up: admin_state_up_trunk
|
||||
- sub_ports: sub_ports
|
||||
|
||||
Request Example
|
||||
---------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-create-request.json
|
||||
:language: javascript
|
||||
|
||||
Response Parameters
|
||||
-------------------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- admin_state_up: admin_state_up_trunk
|
||||
- created_at: created_at_resource
|
||||
- description: description_resource
|
||||
- id: id_resource
|
||||
- name: name_resource
|
||||
- port_id: trunk_port_id
|
||||
- revision_number: revision_number
|
||||
- status: trunk_status
|
||||
- tenant_id: project_id
|
||||
- project_id: project_id
|
||||
- sub_ports: sub_ports
|
||||
- updated_at: updated_at_resource
|
||||
|
||||
|
||||
Add subports to trunk
|
||||
=====================
|
||||
|
||||
.. rest_method:: PUT /v2.0/trunks/{trunk_id}/add_subports
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: 400,401,404,409
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- trunk_id: trunk_id
|
||||
- segmentation_id: segmentation_id
|
||||
- segmentation_type: segmentation_type
|
||||
- port_id: port_id_subport
|
||||
|
||||
Request Example
|
||||
---------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-add-subports-request.json
|
||||
:language: javascript
|
||||
|
||||
Response Parameters
|
||||
-------------------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- admin_state_up: admin_state_up_trunk
|
||||
- created_at: created_at_resource
|
||||
- description: description_resource
|
||||
- id: id_resource
|
||||
- name: name_resource
|
||||
- port_id: trunk_port_id
|
||||
- revision_number: revision_number
|
||||
- status: trunk_status
|
||||
- tenant_id: project_id
|
||||
- project_id: project_id
|
||||
- sub_ports: sub_ports
|
||||
- updated_at: updated_at_resource
|
||||
|
||||
Response Example
|
||||
----------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-add-subports-response.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Delete subports from trunk
|
||||
==========================
|
||||
|
||||
.. rest_method:: PUT /v2.0/trunks/{trunk_id}/remove_subports
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: 400,401,404,409
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- trunk_id: trunk_id
|
||||
- port_id: port_id
|
||||
|
||||
Request Example
|
||||
---------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-remove-subports-request.json
|
||||
:language: javascript
|
||||
|
||||
Response Parameters
|
||||
-------------------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- admin_state_up: admin_state_up_trunk
|
||||
- created_at: created_at_resource
|
||||
- description: description_resource
|
||||
- id: id_resource
|
||||
- name: name_resource
|
||||
- port_id: trunk_port_id
|
||||
- revision_number: revision_number
|
||||
- status: trunk_status
|
||||
- tenant_id: project_id
|
||||
- project_id: project_id
|
||||
- sub_ports: sub_ports
|
||||
- updated_at: updated_at_resource
|
||||
|
||||
Response Example
|
||||
----------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-remove-subports-response.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
List subports for trunk
|
||||
=======================
|
||||
|
||||
.. rest_method:: GET /v2.0/trunks/{trunk_id}/get_subports
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: 401,404
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- trunk_id: trunk_id
|
||||
|
||||
Response Parameters
|
||||
-------------------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- port_id: port_id_subport
|
||||
- segmentation_type: segmentation_type
|
||||
- segmentation_id: segmentation_id
|
||||
|
||||
Response Example
|
||||
----------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-list-subports-response.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Update trunk
|
||||
============
|
||||
|
||||
.. rest_method:: PUT /v2.0/trunks/{trunk_id}
|
||||
|
||||
The update request is only for changing fields like name, description or
|
||||
admin_state_up. Setting the admin_state_up to False locks the trunk in
|
||||
that it prevents operations such as as adding/removing subports.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: 400,401,404,409
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- name_resource: name_resource
|
||||
- admin_state_up_trunk: admin_state_up
|
||||
- description_resource: description_resource
|
||||
|
||||
Request Example
|
||||
---------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-update-request.json
|
||||
:language: javascript
|
||||
|
||||
Response Parameters
|
||||
-------------------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
|
||||
- admin_state_up: admin_state_up_trunk
|
||||
- created_at: created_at_resource
|
||||
- description: description_resource
|
||||
- id: id_resource
|
||||
- name: name_resource
|
||||
- port_id: trunk_port_id
|
||||
- revision_number: revision_number
|
||||
- status: trunk_status
|
||||
- tenant_id: project_id
|
||||
- project_id: project_id
|
||||
- sub_ports: sub_ports
|
||||
- updated_at: updated_at_resource
|
||||
|
||||
Response Example
|
||||
----------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-update-response.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Show trunk
|
||||
==========
|
||||
|
||||
.. rest_method:: GET /v2.0/trunks/{trunk_id}
|
||||
|
||||
Shows details for a trunk.
|
||||
|
||||
Use the ``fields`` query parameter to control which fields are
|
||||
returned in the response body. For information, see `Filtering and
|
||||
Column Selection <http://specs.openstack.org/openstack/neutron-
|
||||
specs/specs/api/networking_general_api_information.html#filtering-
|
||||
and-column-selection>`__.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: 404,401
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- trunk_id: trunk_id
|
||||
|
||||
Response Parameters
|
||||
-------------------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- admin_state_up: admin_state_up_trunk
|
||||
- created_at: created_at_resource
|
||||
- description: description_resource
|
||||
- id: id_resource
|
||||
- name: name_resource
|
||||
- port_id: trunk_port_id
|
||||
- revision_number: revision_number
|
||||
- status: trunk_status
|
||||
- tenant_id: project_id
|
||||
- project_id: project_id
|
||||
- sub_ports: sub_ports
|
||||
- updated_at: updated_at_resource
|
||||
|
||||
Response Example
|
||||
----------------
|
||||
|
||||
.. literalinclude:: ../v2/samples/trunks/trunk-show-response.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Delete trunk
|
||||
============
|
||||
|
||||
.. rest_method:: DELETE /v2.0/trunks/{trunk_id}
|
||||
|
||||
Deletes a trunk, if its state allows it.
|
||||
|
||||
Normal response codes: 204
|
||||
|
||||
Error response codes: 401,404,409
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- trunk_id: trunk_id
|
0
neutron_lib/api/definitions/__init__.py
Normal file
0
neutron_lib/api/definitions/__init__.py
Normal file
108
neutron_lib/api/definitions/base.py
Normal file
108
neutron_lib/api/definitions/base.py
Normal file
@ -0,0 +1,108 @@
|
||||
# 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.
|
||||
|
||||
KNOWN_ATTRIBUTES = (
|
||||
'admin_state_up',
|
||||
'id',
|
||||
'description',
|
||||
'name',
|
||||
'network_id',
|
||||
'port_id',
|
||||
'project_id',
|
||||
'shared',
|
||||
'status',
|
||||
'tenant_id',
|
||||
)
|
||||
|
||||
KNOWN_RESOURCES = (
|
||||
'networks',
|
||||
'ports',
|
||||
'subnets',
|
||||
'routers',
|
||||
)
|
||||
|
||||
KNOWN_HTTP_ACTIONS = (
|
||||
'DELETE',
|
||||
'GET',
|
||||
'POST',
|
||||
'PUT',
|
||||
)
|
||||
|
||||
KNOWN_EXTENSIONS = (
|
||||
'address-scope',
|
||||
'agent',
|
||||
'allowed-address-pairs',
|
||||
'auto-allocated-topology',
|
||||
'availability_zone',
|
||||
'binding',
|
||||
'default-subnetpools',
|
||||
'dhcp_agent_scheduler',
|
||||
'dns-integration',
|
||||
'dvr',
|
||||
'ext-gw-mode',
|
||||
'external-net',
|
||||
'extra_dhcp_opt',
|
||||
'extraroute',
|
||||
'flavors',
|
||||
'l3-ha',
|
||||
'l3_agent_scheduler',
|
||||
'metering',
|
||||
'multi-provider',
|
||||
'net-mtu',
|
||||
'network-ip-availability',
|
||||
'network_availability_zone',
|
||||
'pagination',
|
||||
'port-security',
|
||||
'project-id',
|
||||
'provider',
|
||||
'qos',
|
||||
'quotas',
|
||||
'rbac-policies',
|
||||
'router',
|
||||
'router_availability_zone',
|
||||
'security-group',
|
||||
'service-type',
|
||||
'sorting',
|
||||
'standard-attr-description',
|
||||
'standard-attr-revisions',
|
||||
'standard-attr-timestamp',
|
||||
'subnet_allocation',
|
||||
'tag',
|
||||
'trunk',
|
||||
'trunk-details',
|
||||
)
|
||||
|
||||
# The following is a short reference for understanding attribute info:
|
||||
# allow_post: the attribute can be used on POST requests.
|
||||
# allow_put: the attribute can be used on PUT requests.
|
||||
# convert_to: transformation to apply to the value before it is returned
|
||||
# default: default value of the attribute (if missing, the attribute
|
||||
# becomes mandatory.
|
||||
# enforce_policy: the attribute is actively part of the policy enforcing
|
||||
# mechanism, ie: there might be rules which refer to this attribute.
|
||||
# is_visible: the attribute is returned in GET responses.
|
||||
# required_by_policy: the attribute is required by the policy engine and
|
||||
# should therefore be filled by the API layer even if not present in
|
||||
# request body.
|
||||
# validate: specifies rules for validating data in the attribute.
|
||||
KNOWN_KEYWORDS = (
|
||||
'allow_post',
|
||||
'allow_put',
|
||||
'convert_to',
|
||||
'convert_list_to',
|
||||
'default',
|
||||
'enforce_policy',
|
||||
'is_visible',
|
||||
'primary_key',
|
||||
'required_by_policy',
|
||||
'validate',
|
||||
)
|
97
neutron_lib/api/definitions/trunk.py
Normal file
97
neutron_lib/api/definitions/trunk.py
Normal file
@ -0,0 +1,97 @@
|
||||
# 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 neutron_lib.api import converters
|
||||
|
||||
|
||||
# The alias of the extension.
|
||||
ALIAS = 'trunk'
|
||||
|
||||
# Whether or not this extension is simply signaling behavior to the user
|
||||
# or it actively modifies the attribute map.
|
||||
IS_SHIM_EXTENSION = False
|
||||
|
||||
# Whether the extension is marking the adoption of standardattr model for
|
||||
# legacy resources, or introducing new standardattr attributes. False or
|
||||
# None if the standardattr model is adopted since the introduction of
|
||||
# resource extension.
|
||||
# If this is True, the alias for the extension should be prefixed with
|
||||
# 'standard-attr-'.
|
||||
IS_STANDARD_ATTR_EXTENSION = False
|
||||
|
||||
# The name of the extension.
|
||||
NAME = 'Trunk Extension'
|
||||
|
||||
# The description of the extension.
|
||||
DESCRIPTION = "Provides support for trunk ports"
|
||||
|
||||
# A timestamp of when the extension was introduced.
|
||||
UPDATED_TIMESTAMP = "2016-01-01T10:00:00-00:00"
|
||||
|
||||
# The specific resources and/or attributes for the extension (optional).
|
||||
TRUNK = 'trunk'
|
||||
TRUNKS = 'trunks'
|
||||
SUB_PORTS = 'sub_ports'
|
||||
|
||||
# The resource attribute map for the extension.
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
TRUNKS: {
|
||||
'admin_state_up': {'allow_post': True, 'allow_put': True,
|
||||
'default': True,
|
||||
'convert_to': converters.convert_to_boolean,
|
||||
'is_visible': True},
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True, 'primary_key': True},
|
||||
'name': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:string': 255},
|
||||
'default': '', 'is_visible': True},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': True,
|
||||
'validate':
|
||||
{'type:string': 255},
|
||||
'is_visible': True},
|
||||
'port_id': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': True,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True},
|
||||
'status': {'allow_post': False, 'allow_put': False,
|
||||
'is_visible': True},
|
||||
SUB_PORTS: {'allow_post': True, 'allow_put': False,
|
||||
'default': [],
|
||||
'convert_list_to': converters.convert_kvp_list_to_dict,
|
||||
'validate': {'type:subports': None},
|
||||
'enforce_policy': True,
|
||||
'is_visible': True}
|
||||
},
|
||||
}
|
||||
|
||||
# The action map.
|
||||
ACTION_MAP = {
|
||||
TRUNK: {
|
||||
'add_subports': 'PUT',
|
||||
'remove_subports': 'PUT',
|
||||
'get_subports': 'GET'
|
||||
}
|
||||
}
|
||||
|
||||
# The list of required extensions.
|
||||
REQUIRED_EXTENSIONS = [
|
||||
"binding",
|
||||
]
|
||||
|
||||
# The list of optional extensions.
|
||||
OPTIONAL_EXTENSIONS = None
|
||||
|
||||
# TODO(armax): add support for modeling custom queries
|
62
neutron_lib/api/definitions/trunk_details.py
Normal file
62
neutron_lib/api/definitions/trunk_details.py
Normal file
@ -0,0 +1,62 @@
|
||||
# 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 neutron_lib.api.definitions import trunk
|
||||
from neutron_lib import constants
|
||||
|
||||
|
||||
# The alias of the extension.
|
||||
ALIAS = 'trunk-details'
|
||||
|
||||
# Whether or not this extension is simply signaling behavior to the user
|
||||
# or it actively modifies the attribute map.
|
||||
IS_SHIM_EXTENSION = False
|
||||
|
||||
# Whether the extension is marking the adoption of standardattr model for
|
||||
# legacy resources, or introducing new standardattr attributes. False or
|
||||
# None if the standardattr model is adopted since the introduction of
|
||||
# resource extension.
|
||||
# If this is True, the alias for the extension should be prefixed with
|
||||
# 'standard-attr-'.
|
||||
IS_STANDARD_ATTR_EXTENSION = False
|
||||
|
||||
# The name of the extension.
|
||||
NAME = 'Trunk port details'
|
||||
|
||||
# The description of the extension.
|
||||
DESCRIPTION = "Expose trunk port details"
|
||||
|
||||
# A timestamp of when the extension was introduced.
|
||||
TIMESTAMP = "2016-01-01T10:00:00-00:00"
|
||||
|
||||
# The specific resources and/or attributes for the extension (optional).
|
||||
TRUNK_DETAILS = 'trunk_details'
|
||||
|
||||
# The resource attribute map for the extension.
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
'ports': {TRUNK_DETAILS: {'allow_post': False, 'allow_put': False,
|
||||
'default': constants.ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True,
|
||||
'enforce_policy': True,
|
||||
'required_by_policy': True}},
|
||||
}
|
||||
|
||||
# The action map.
|
||||
ACTION_MAP = None
|
||||
|
||||
# The list of required extensions.
|
||||
REQUIRED_EXTENSIONS = [trunk.ALIAS]
|
||||
|
||||
# The list of optional extensions.
|
||||
OPTIONAL_EXTENSIONS = None
|
0
neutron_lib/tests/unit/api/definitions/__init__.py
Normal file
0
neutron_lib/tests/unit/api/definitions/__init__.py
Normal file
140
neutron_lib/tests/unit/api/definitions/base.py
Normal file
140
neutron_lib/tests/unit/api/definitions/base.py
Normal file
@ -0,0 +1,140 @@
|
||||
# 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 neutron_lib.api.definitions import base
|
||||
from neutron_lib.api import validators
|
||||
from neutron_lib.tests import _base as test_base
|
||||
|
||||
|
||||
def assert_bool(tester, attribute, attribute_dict, keyword, value):
|
||||
tester.assertIsInstance(
|
||||
value, bool,
|
||||
'%s must be a boolean for %s.' % (keyword, attribute))
|
||||
|
||||
|
||||
def assert_converter(tester, attribute, attribute_dict, keyword, value):
|
||||
try:
|
||||
attribute_dict['convert_to'](attribute_dict['default'])
|
||||
except KeyError:
|
||||
try:
|
||||
attribute_dict['convert_list_to'](attribute_dict['default'])
|
||||
except KeyError:
|
||||
if validators.is_attr_set(value) and not isinstance(value, str):
|
||||
tester.fail("Default value '%s' cannot be converted for "
|
||||
"attribute %s." % (value, attribute))
|
||||
|
||||
|
||||
def assert_true(tester, attribute, attribute_dict, keyword, value):
|
||||
tester.assertTrue(
|
||||
value, '%s must be True for %s.' % (keyword, attribute))
|
||||
|
||||
|
||||
def assert_validator(tester, attribute, attribute_dict, keyword, value):
|
||||
tester.assertIn(list(value)[0], validators.validators,
|
||||
'%s is not a known validator for %s.' % (value, attribute))
|
||||
|
||||
ASSERT_FUNCTIONS = {
|
||||
'allow_post': assert_bool,
|
||||
'allow_put': assert_bool,
|
||||
'convert_to': assert_converter,
|
||||
'convert_list_to': assert_converter,
|
||||
'default': assert_converter,
|
||||
'enforce_policy': assert_bool,
|
||||
'is_visible': assert_bool,
|
||||
'primary_key': assert_true,
|
||||
'required_by_policy': assert_bool,
|
||||
'validate': assert_validator,
|
||||
}
|
||||
|
||||
|
||||
class DefinitionBaseTestCase(test_base.BaseTestCase):
|
||||
|
||||
extension_module = None
|
||||
extension_resources = ()
|
||||
extension_attributes = ()
|
||||
|
||||
def setUp(self):
|
||||
super(DefinitionBaseTestCase, self).setUp()
|
||||
if not self.extension_module:
|
||||
self.fail("Missing extension module definition.")
|
||||
self.alias = self.extension_module.ALIAS
|
||||
self.is_shim_extension = self.extension_module.IS_SHIM_EXTENSION
|
||||
self.is_standard_attr_extension = (
|
||||
self.extension_module.IS_STANDARD_ATTR_EXTENSION)
|
||||
self.name = self.extension_module.NAME
|
||||
self.description = self.extension_module.DESCRIPTION
|
||||
self.resource_map = self.extension_module.RESOURCE_ATTRIBUTE_MAP
|
||||
self.action_map = self.extension_module.ACTION_MAP
|
||||
self.required_extensions = self.extension_module.REQUIRED_EXTENSIONS
|
||||
self.optional_extensions = self.extension_module.OPTIONAL_EXTENSIONS
|
||||
|
||||
def test_shim_extension(self):
|
||||
if self.is_shim_extension is True:
|
||||
self.assertFalse(self.extension_resources)
|
||||
self.assertFalse(self.extension_attributes)
|
||||
self.assertFalse(self.resource_map)
|
||||
self.assertFalse(self.action_map)
|
||||
|
||||
def test_is_standard_attr_extension(self):
|
||||
if self.is_standard_attr_extension:
|
||||
self.assertIn('standard-attr-', self.alias)
|
||||
else:
|
||||
self.skipTest('API definition is not related to standardattr.')
|
||||
|
||||
def test_resource_map(self):
|
||||
if not self.resource_map and not self.is_shim_extension:
|
||||
self.fail('Missing resource map, what is this extension doing?')
|
||||
elif self.is_shim_extension:
|
||||
self.skipTest('Shim extension with no API changes.')
|
||||
|
||||
for resource in self.resource_map:
|
||||
self.assertIn(
|
||||
resource, base.KNOWN_RESOURCES + self.extension_resources,
|
||||
'Resource is unknown, check for typos.')
|
||||
for attribute in self.resource_map[resource].keys():
|
||||
self.assertIn(
|
||||
attribute,
|
||||
base.KNOWN_ATTRIBUTES + self.extension_attributes,
|
||||
'Attribute is unknown, check for typos.')
|
||||
for keyword in self.resource_map[resource][attribute]:
|
||||
self.assertIn(keyword, base.KNOWN_KEYWORDS,
|
||||
'Keyword is unknown, check for typos.')
|
||||
value = self.resource_map[resource][attribute][keyword]
|
||||
assert_f = ASSERT_FUNCTIONS[keyword]
|
||||
assert_f(self, attribute,
|
||||
self.resource_map[resource][attribute],
|
||||
keyword, value)
|
||||
|
||||
def test_action_map(self):
|
||||
if not self.action_map:
|
||||
self.skipTest('API definition has no action map.')
|
||||
|
||||
for key in self.action_map:
|
||||
for action in self.action_map[key].values():
|
||||
self.assertIn(action, base.KNOWN_HTTP_ACTIONS,
|
||||
'HTTP verb is unknown, check for typos.')
|
||||
|
||||
def test_required_extensions(self):
|
||||
if not self.required_extensions:
|
||||
self.skipTest('API definition has no required extensions.')
|
||||
|
||||
for ext in self.required_extensions:
|
||||
self.assertIn(ext, base.KNOWN_EXTENSIONS,
|
||||
'Required extension is unknown, check for typos.')
|
||||
|
||||
def test_optional_extensions(self):
|
||||
if not self.optional_extensions:
|
||||
self.skipTest('API definition has no optional extensions.')
|
||||
|
||||
for ext in self.optional_extensions:
|
||||
self.assertIn(ext, base.KNOWN_EXTENSIONS,
|
||||
'Optional extension is unknown, check for typos.')
|
20
neutron_lib/tests/unit/api/definitions/test_trunk.py
Normal file
20
neutron_lib/tests/unit/api/definitions/test_trunk.py
Normal file
@ -0,0 +1,20 @@
|
||||
# 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 neutron_lib.api.definitions import trunk
|
||||
from neutron_lib.tests.unit.api.definitions import base
|
||||
|
||||
|
||||
class TrunkDefinitionTestCase(base.DefinitionBaseTestCase):
|
||||
extension_module = trunk
|
||||
extension_resources = (trunk.TRUNKS,)
|
||||
extension_attributes = (trunk.SUB_PORTS,)
|
19
neutron_lib/tests/unit/api/definitions/test_trunk_details.py
Normal file
19
neutron_lib/tests/unit/api/definitions/test_trunk_details.py
Normal file
@ -0,0 +1,19 @@
|
||||
# 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 neutron_lib.api.definitions import trunk_details
|
||||
from neutron_lib.tests.unit.api.definitions import base
|
||||
|
||||
|
||||
class TrunkDetailsDefinitionTestCase(base.DefinitionBaseTestCase):
|
||||
extension_module = trunk_details
|
||||
extension_attributes = (trunk_details.TRUNK_DETAILS,)
|
Loading…
Reference in New Issue
Block a user