Merge "Introduce API definition for trunk/trunk_details extensions"

This commit is contained in:
Jenkins 2016-10-21 21:22:08 +00:00 committed by Gerrit Code Review
commit a0e7337425
25 changed files with 1164 additions and 0 deletions

View File

@ -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

View File

@ -111,6 +111,8 @@ attribute in responses, check that the ``project-id`` API extension is enabled
(see Extensions_).
.. _filtering:
Filtering and column selection
==============================

View File

@ -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

View File

@ -0,0 +1,9 @@
{
"sub_ports": [
{
"segmentation_id": 44,
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155",
"segmentation_type": "vlan"
}
]
}

View File

@ -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": ""
}

View File

@ -0,0 +1,7 @@
{
"trunk": {
"port_id": "8027c4da-772f-4e43-bfbf-023b4a4e63de",
"name": "test",
"admin_state_up": true
}
}

View File

@ -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": ""
}
}

View File

@ -0,0 +1,9 @@
{
"sub_ports": [
{
"segmentation_type": "vlan",
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155",
"segmentation_id": 44
}
]
}

View File

@ -0,0 +1,7 @@
{
"sub_ports": [
{
"port_id": "4b4c691b-086d-43d2-8a65-5487e9434155"
}
]
}

View File

@ -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": ""
}

View 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": ""
}
}

View File

@ -0,0 +1,6 @@
{
"trunk": {
"name": "foo",
"admin_state_up": true
}
}

View 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": ""
}
}

View 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": ""
}
}

View 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": ""
}
]
}

View 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
View 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

View File

View 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',
)

View 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

View 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

View 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.')

View 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,)

View 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,)