diff --git a/api-ref/source/v2/ports.inc b/api-ref/source/v2/ports.inc index 4c6875f89..45509f4d0 100644 --- a/api-ref/source/v2/ports.inc +++ b/api-ref/source/v2/ports.inc @@ -25,6 +25,14 @@ is optional and will be taken from the port if not specified. with source IP address restrictions for all ports which use the same security group. +Allowed address pairs (atomic) extension +======================================== + +The Allowed address pairs (atomic) extension (``allowedaddresspairs-atomic``) +extends the ``port`` resource by adding two member actions +(``add_allowed_address_pairs``/ ``remove_allowed_address_pairs``) to edit the set +of Allowed address pairs atomically on the server side. + Data plane status extension =========================== @@ -772,3 +780,157 @@ Response Example .. literalinclude:: samples/ports/ports-bulk-create-response.json :language: javascript + +Add allowed_address_pairs to port +================================= + +.. rest_method:: PUT /v2.0/ports/{port_id}/add_allowed_address_pairs + +Atomically adds a set of allowed_address_pairs to the port's already +existing allowed_address_pairs. + +Normal response codes: 200 + +Error response codes: 400, 401, 404, 412 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - port_id: port_id-path + - port: port + - allowed_address_pairs: allowed_address_pairs-request + +Request Example +--------------- + +.. literalinclude:: samples/ports/port-add-allowed-address-pairs-request.json + :language: javascript + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - port: port + - admin_state_up: admin_state_up + - allowed_address_pairs: allowed_address_pairs + - binding:host_id: binding:host_id + - binding:profile: binding:profile + - binding:vif_details: binding:vif_details + - binding:vif_type: binding:vif_type + - binding:vnic_type: binding:vnic_type + - created_at: created_at_resource + - data_plane_status: data_plane_status + - description: description + - device_id: device_id + - device_owner: device_owner + - dns_assignment: dns_assignment + - dns_domain: dns_domain + - dns_name: dns_name + - extra_dhcp_opts: extra_dhcp_opts + - fixed_ips: fixed_ips + - hints: hints + - id: id + - ip_allocation: ip_allocation + - mac_address: mac_address + - name: name + - network_id: network_id + - numa_affinity_policy: numa_affinity_policy + - port_security_enabled: port_security_enabled + - project_id: project_id + - qos_network_policy_id: qos_network_policy_id-port-response + - qos_policy_id: qos_policy_id-port-response + - revision_number: revision_number + - resource_request: port-resource + - security_groups: port-security_groups + - status: port-status + - tags: tags + - tenant_id: project_id + - updated_at: updated_at_resource + - propagate_uplink_status: propagate_uplink_status + - mac_learning_enabled: mac_learning_enabled + +Response Example +---------------- + +.. literalinclude:: samples/ports/port-add-allowed-address-pairs-response.json + :language: javascript + +Remove allowed_address_pairs from port +====================================== + +.. rest_method:: PUT /v2.0/ports/{port_id}/remove_allowed_address_pairs + +Atomically removes a set of allowed_address_pairs from the port's already +existing allowed_address_pairs. + +Normal response codes: 200 + +Error response codes: 400, 401, 404, 412 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - port_id: port_id-path + - port: port + - allowed_address_pairs: allowed_address_pairs-request + +Request Example +--------------- + +.. literalinclude:: samples/ports/port-remove-allowed-address-pairs-request.json + :language: javascript + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - port: port + - admin_state_up: admin_state_up + - allowed_address_pairs: allowed_address_pairs + - binding:host_id: binding:host_id + - binding:profile: binding:profile + - binding:vif_details: binding:vif_details + - binding:vif_type: binding:vif_type + - binding:vnic_type: binding:vnic_type + - created_at: created_at_resource + - data_plane_status: data_plane_status + - description: description + - device_id: device_id + - device_owner: device_owner + - dns_assignment: dns_assignment + - dns_domain: dns_domain + - dns_name: dns_name + - extra_dhcp_opts: extra_dhcp_opts + - fixed_ips: fixed_ips + - hints: hints + - id: id + - ip_allocation: ip_allocation + - mac_address: mac_address + - name: name + - network_id: network_id + - numa_affinity_policy: numa_affinity_policy + - port_security_enabled: port_security_enabled + - project_id: project_id + - qos_network_policy_id: qos_network_policy_id-port-response + - qos_policy_id: qos_policy_id-port-response + - revision_number: revision_number + - resource_request: port-resource + - security_groups: port-security_groups + - status: port-status + - tags: tags + - tenant_id: project_id + - updated_at: updated_at_resource + - propagate_uplink_status: propagate_uplink_status + - mac_learning_enabled: mac_learning_enabled + +Response Example +---------------- + +.. literalinclude:: samples/ports/port-remove-allowed-address-pairs-response.json + :language: javascript diff --git a/api-ref/source/v2/samples/ports/port-add-allowed-address-pairs-request.json b/api-ref/source/v2/samples/ports/port-add-allowed-address-pairs-request.json new file mode 100644 index 000000000..327e0fb0c --- /dev/null +++ b/api-ref/source/v2/samples/ports/port-add-allowed-address-pairs-request.json @@ -0,0 +1,10 @@ +{ + "port" : { + "allowed_address_pairs": [ + { + "ip_address": "192.168.13.7", + "mac_address": "fa:16:3e:09:1f:b2" + } + ] + } +} diff --git a/api-ref/source/v2/samples/ports/port-add-allowed-address-pairs-response.json b/api-ref/source/v2/samples/ports/port-add-allowed-address-pairs-response.json new file mode 100644 index 000000000..0fc58ef4b --- /dev/null +++ b/api-ref/source/v2/samples/ports/port-add-allowed-address-pairs-response.json @@ -0,0 +1,51 @@ +{ + "port": { + "admin_state_up": true, + "allowed_address_pairs": [ + { + "ip_address": "192.168.13.7", + "mac_address": "fa:16:3e:09:1f:b2" + } + ], + "binding:host_id": "", + "binding:profile": {}, + "binding:vif_details": {}, + "binding:vif_type": "unbound", + "binding:vnic_type": "normal", + "created_at": "2023-04-20T02:32:41", + "data_plane_status": null, + "description": "", + "device_id": "", + "device_owner": "", + "dns_assignment": [], + "dns_domain": "", + "dns_name": "", + "extra_dhcp_opts": [], + "fixed_ips": [ + { + "ip_address": "192.168.13.6", + "subnet_id": "a4c3b506-2110-4929-a70a-bda534bc0b07" + } + ], + "id": "dc67ee67-7acd-464d-98fd-4abef6d8759d", + "ip_allocation": "immediate", + "mac_address": "fa:16:3e:09:1f:b2", + "mac_learning_enabled": false, + "name": "test-port", + "network_id": "99b8e526-e943-4463-aa28-a22395bed154", + "port_security_enabled": true, + "project_id": "294b394e8f454cc8b26bbe342bc210d3", + "revision_number": 1, + "security_groups": [ + "751d740a-b52b-46d9-bca8-a21e75c8a727" + ], + "status": "DOWN", + "tags": [], + "tenant_id": "294b394e8f454cc8b26bbe342bc210d3", + "updated_at": "2023-04-20T02:32:41", + "qos_network_policy_id": null, + "qos_policy_id": null, + "resource_request": null, + "propagate_uplink_status": false + } +} diff --git a/api-ref/source/v2/samples/ports/port-remove-allowed-address-pairs-request.json b/api-ref/source/v2/samples/ports/port-remove-allowed-address-pairs-request.json new file mode 100644 index 000000000..327e0fb0c --- /dev/null +++ b/api-ref/source/v2/samples/ports/port-remove-allowed-address-pairs-request.json @@ -0,0 +1,10 @@ +{ + "port" : { + "allowed_address_pairs": [ + { + "ip_address": "192.168.13.7", + "mac_address": "fa:16:3e:09:1f:b2" + } + ] + } +} diff --git a/api-ref/source/v2/samples/ports/port-remove-allowed-address-pairs-response.json b/api-ref/source/v2/samples/ports/port-remove-allowed-address-pairs-response.json new file mode 100644 index 000000000..9023184de --- /dev/null +++ b/api-ref/source/v2/samples/ports/port-remove-allowed-address-pairs-response.json @@ -0,0 +1,46 @@ +{ + "port": { + "admin_state_up": true, + "allowed_address_pairs": [], + "binding:host_id": "", + "binding:profile": {}, + "binding:vif_details": {}, + "binding:vif_type": "unbound", + "binding:vnic_type": "normal", + "created_at": "2023-04-20T02:32:41", + "data_plane_status": null, + "description": "", + "device_id": "", + "device_owner": "", + "dns_assignment": [], + "dns_domain": "", + "dns_name": "", + "extra_dhcp_opts": [], + "fixed_ips": [ + { + "ip_address": "192.168.13.6", + "subnet_id": "a4c3b506-2110-4929-a70a-bda534bc0b07" + } + ], + "id": "dc67ee67-7acd-464d-98fd-4abef6d8759d", + "ip_allocation": "immediate", + "mac_address": "fa:16:3e:09:1f:b2", + "mac_learning_enabled": false, + "name": "test-port", + "network_id": "99b8e526-e943-4463-aa28-a22395bed154", + "port_security_enabled": true, + "project_id": "294b394e8f454cc8b26bbe342bc210d3", + "revision_number": 1, + "security_groups": [ + "751d740a-b52b-46d9-bca8-a21e75c8a727" + ], + "status": "DOWN", + "tags": [], + "tenant_id": "294b394e8f454cc8b26bbe342bc210d3", + "updated_at": "2023-04-20T02:32:41", + "qos_network_policy_id": null, + "qos_policy_id": null, + "resource_request": null, + "propagate_uplink_status": false + } +} diff --git a/neutron_lib/api/definitions/__init__.py b/neutron_lib/api/definitions/__init__.py index e5883c9be..42699fe3b 100644 --- a/neutron_lib/api/definitions/__init__.py +++ b/neutron_lib/api/definitions/__init__.py @@ -16,6 +16,7 @@ from neutron_lib.api.definitions import agent from neutron_lib.api.definitions import agent_resources_synced from neutron_lib.api.definitions import agent_sort_key from neutron_lib.api.definitions import allowedaddresspairs +from neutron_lib.api.definitions import allowedaddresspairs_atomic from neutron_lib.api.definitions import auto_allocated_topology from neutron_lib.api.definitions import availability_zone from neutron_lib.api.definitions import availability_zone_filter @@ -165,6 +166,7 @@ _ALL_API_DEFINITIONS = { agent_resources_synced, agent_sort_key, allowedaddresspairs, + allowedaddresspairs_atomic, auto_allocated_topology, availability_zone, availability_zone_filter, diff --git a/neutron_lib/api/definitions/allowedaddresspairs_atomic.py b/neutron_lib/api/definitions/allowedaddresspairs_atomic.py new file mode 100644 index 000000000..a54a69e85 --- /dev/null +++ b/neutron_lib/api/definitions/allowedaddresspairs_atomic.py @@ -0,0 +1,38 @@ +# Copyright 2023 EasyStack Limited. 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 allowedaddresspairs +from neutron_lib.api.definitions import port + + +ALIAS = 'allowed-address-pairs-atomic' +IS_SHIM_EXTENSION = False +IS_STANDARD_ATTR_EXTENSION = False +NAME = 'Atomically add/remove allowed address pairs' +DESCRIPTION = ('Edit allowed address pairs of a port on server side by ' + 'atomically adding/removing allowed address pairs') +UPDATED_TIMESTAMP = '2023-04-17T00:00:00+00:00' +RESOURCE_ATTRIBUTE_MAP = { + port.COLLECTION_NAME: {} +} +SUB_RESOURCE_ATTRIBUTE_MAP = None +ACTION_MAP = { + port.RESOURCE_NAME: { + 'add_allowed_address_pairs': 'PUT', + 'remove_allowed_address_pairs': 'PUT', + } +} +REQUIRED_EXTENSIONS = [allowedaddresspairs.ALIAS] +OPTIONAL_EXTENSIONS = [] +ACTION_STATUS = {} diff --git a/neutron_lib/api/definitions/base.py b/neutron_lib/api/definitions/base.py index e63556f00..abb5c069e 100644 --- a/neutron_lib/api/definitions/base.py +++ b/neutron_lib/api/definitions/base.py @@ -83,6 +83,7 @@ KNOWN_EXTENSIONS = ( 'agent', 'agent-resources-synced', 'allowed-address-pairs', + 'allowed-address-pairs-atomic', 'auto-allocated-topology', 'availability_zone', 'binding', diff --git a/neutron_lib/tests/unit/api/definitions/test_allowedaddresspairs_atomic.py b/neutron_lib/tests/unit/api/definitions/test_allowedaddresspairs_atomic.py new file mode 100644 index 000000000..ef290351e --- /dev/null +++ b/neutron_lib/tests/unit/api/definitions/test_allowedaddresspairs_atomic.py @@ -0,0 +1,20 @@ +# Copyright 2023 EasyStack Limited. 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 allowedaddresspairs_atomic +from neutron_lib.tests.unit.api.definitions import base + + +class AllowedAddressPairsDefinitionTestCase(base.DefinitionBaseTestCase): + extension_module = allowedaddresspairs_atomic diff --git a/releasenotes/notes/allowedaddresspairs-atomic-apidef-6f9d6865854vwfrs b/releasenotes/notes/allowedaddresspairs-atomic-apidef-6f9d6865854vwfrs new file mode 100644 index 000000000..8fc5478cc --- /dev/null +++ b/releasenotes/notes/allowedaddresspairs-atomic-apidef-6f9d6865854vwfrs @@ -0,0 +1,6 @@ +--- +features: + - | + New API definition: ``allowedaddresspairs-atomic``. It adds + ``add_allowed_address_pairs`` and ``remove_allowed_address_pairs`` + API endpoints.