From 07e3de1d4cde89432c3474330eff30b3c4e412ca Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Mon, 26 Jul 2021 18:01:06 +0300 Subject: [PATCH] Add Local IP API def Partial-Bug: #1930200 Related-Change: https://review.opendev.org/c/openstack/neutron-specs/+/797798 (spec) Change-Id: Ia259cd60f048f6c070a1d3a3dbb54b892d67ec30 --- api-ref/source/v2/local-ips.inc | 425 ++++++++++++++++++ api-ref/source/v2/parameters.yaml | 204 +++++++++ .../local-ip-list-associations-response.json | 18 + .../local_ips/local-ips-list-response.json | 30 ++ .../local_ips/local_ip-create-request.json | 9 + .../local_ips/local_ip-create-response.json | 15 + .../local_ips/local_ip-show-response.json | 15 + .../local_ips/local_ip-update-request.json | 6 + .../local_ips/local_ip-update-response.json | 15 + .../local_ip_association-create-request.json | 6 + .../local_ip_association-create-response.json | 9 + neutron_lib/api/definitions/__init__.py | 2 + neutron_lib/api/definitions/local_ip.py | 156 +++++++ .../unit/api/definitions/test_local_ip.py | 25 ++ ...d-local-ip-extension-fb4a18f5a6525f1f.yaml | 7 + 15 files changed, 942 insertions(+) create mode 100644 api-ref/source/v2/local-ips.inc create mode 100644 api-ref/source/v2/samples/local_ips/local-ip-list-associations-response.json create mode 100644 api-ref/source/v2/samples/local_ips/local-ips-list-response.json create mode 100644 api-ref/source/v2/samples/local_ips/local_ip-create-request.json create mode 100644 api-ref/source/v2/samples/local_ips/local_ip-create-response.json create mode 100644 api-ref/source/v2/samples/local_ips/local_ip-show-response.json create mode 100644 api-ref/source/v2/samples/local_ips/local_ip-update-request.json create mode 100644 api-ref/source/v2/samples/local_ips/local_ip-update-response.json create mode 100644 api-ref/source/v2/samples/local_ips/local_ip_association-create-request.json create mode 100644 api-ref/source/v2/samples/local_ips/local_ip_association-create-response.json create mode 100644 neutron_lib/api/definitions/local_ip.py create mode 100644 neutron_lib/tests/unit/api/definitions/test_local_ip.py create mode 100644 releasenotes/notes/add-local-ip-extension-fb4a18f5a6525f1f.yaml diff --git a/api-ref/source/v2/local-ips.inc b/api-ref/source/v2/local-ips.inc new file mode 100644 index 000000000..84f303cbd --- /dev/null +++ b/api-ref/source/v2/local-ips.inc @@ -0,0 +1,425 @@ +.. -*- rst -*- + +===================== +Local IPs (local_ips) +===================== + +Extension that allows users to create a virtual IP that can later be assigned +to multiple ports/VMs (similar to anycast IP) and is guaranteed to only be +reachable within the same physical server/node boundaries. + +Resource timestamps +=================== + +The ``standard-attr-timestamp`` extension adds the ``created_at`` and +``updated_at`` attributes to all resources that have standard attributes. + +List Local IPs +============== + +.. rest_method:: GET /v2.0/local_ips + +Lists Local IPs visible to the user. + +Default policy settings return only the Local IPs owned by the user's +project, unless the user has admin role. + +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 `Filtering +and Column Selection `__. + +Normal response codes: 200 + +Error response codes: 401 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - id: local_ip-id-query + - name: name-query + - description: description-query + - project_id: project_id-query + - local_port_id: local_ip-local_port_id-query + - network_id: network_id-query + - local_ip_address: local_ip_address-query + - ip_mode: local_ip-ip_mode-query + - revision_number: revision_number-query + - sort_dir: sort_dir + - sort_key: local_ip-sort_key + - fields: fields + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - local_ips: local_ips + - id: local_ip-id + - name: name + - description: description + - project_id: project_id + - local_port_id: local_ip-local_port_id + - network_id: network_id + - local_ip_address: local_ip_address + - ip_mode: local_ip-ip_mode + - created_at: created_at_resource + - updated_at: updated_at_resource + - revision_number: revision_number + +Response Example +---------------- + +.. literalinclude:: samples/local_ips/local-ips-list-response.json + :language: javascript + +Create Local IP +=============== + +.. rest_method:: POST /v2.0/local_ips + +Creates a Local IP, and, if you don't specify existing port ID, +allocates an internal port with IP address from specified network. + +The operation returns the ``Bad Request (400)`` response code for one of +reasons: + + - The requested local IP address does not fall in the subnet + range for the specified network. + + - The local IP address is not valid. + + - Specified local_port_id has no fixed IP address + + - Specified local_port_id has multiple fixed IP address and local_ip + was not specified + + - Specified ip_mode is not supported + +If the local_port_id or network_id is not valid, this operation returns +``404`` response code. + +The operation returns the ``Conflict (409)`` response code for one of +reasons: + + - Both local_port_id and network_id are specified in the request + + - Both local_port_id and local_ip are specified, but port has no such + local IP + + - Both network_id and local_ip_address are specified, but network has + no subnets to satisfy the IP requested + +Normal response codes: 201 + +Error response codes: 400, 401, 404, 409 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - local_ip: local_ip + - name: name-request + - description: description-request + - project_id: project_id-request + - local_port_ip: local_ip-local_port_id-request + - network_id: local_ip-network_id-request + - local_ip_address: local_ip_address-request + - ip_mode: local_ip-ip_mode-request + +Request Example +--------------- + +.. literalinclude:: samples/local_ips/local_ip-create-request.json + :language: javascript + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - local_ip: local_ip + - id: local_ip-id + - name: name + - description: description + - project_id: project_id + - local_port_id: local_ip-local_port_id + - network_id: local_ip-network_id + - local_ip_address: local_ip_address + - ip_mode: local_ip-ip_mode + - created_at: created_at_resource + - updated_at: updated_at_resource + - revision_number: revision_number + +Response Example +---------------- + +.. literalinclude:: samples/local_ips/local_ip-create-response.json + :language: javascript + +Show Local IP details +===================== + +.. rest_method:: GET /v2.0/local_ips/{local_ip_id} + +Shows details for a Local IP. + +Use the ``fields`` query parameter to control which fields are +returned in the response body. For information, see `Filtering and +Column Selection `__. + +Normal response codes: 200 + +Error response codes: 401, 403, 404 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - local_ip_id: local_ip-id-path + - fields: fields + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - local_ip: local_ip + - id: local_ip-id + - name: name + - description: description + - project_id: project_id + - local_port_id: local_ip-local_port_id + - network_id: local_ip-network_id + - local_ip_address: local_ip_address + - ip_mode: local_ip-ip_mode + - created_at: created_at_resource + - updated_at: updated_at_resource + - revision_number: revision_number + +Response Example +---------------- + +.. literalinclude:: samples/local_ips/local_ip-show-response.json + :language: javascript + +Update Local IP +=============== + +.. rest_method:: PUT /v2.0/local_ips/{local_ip_id} + +Updates a Local IP. + +Normal response codes: 200 + +Error response codes: 400, 401, 404, 409 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - local_ip: local_ip + - local_ip_id: local_ip-id-path + - name: name-request + - description: description-request + +Request Example +--------------- + +.. literalinclude:: samples/local_ips/local_ip-update-request.json + :language: javascript + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - local_ip: local_ip + - id: local_ip-id + - name: name + - description: description + - project_id: project_id + - local_port_id: local_ip-local_port_id + - network_id: local_ip-network_id + - local_ip_address: local_ip_address + - ip_mode: local_ip-ip_mode + - created_at: created_at_resource + - updated_at: updated_at_resource + - revision_number: revision_number + +Response Example +---------------- + +.. literalinclude:: samples/local_ips/local_ip-update-response.json + :language: javascript + +Delete Local IP +=============== + +.. rest_method:: DELETE /v2.0/local_ips/{local_ip_id} + +Deletes a Local IP and, if applicable, its underlying port. +Underlying port is deleted in case it was created specifically for this +Local IP, and has corresponding device_owner and device_id. + +The operation returns the ``Precondition Failed (412)`` response code for +the following reason: + + - The requested Local IP is still associated with some ports. + +Normal response codes: 204 + +Error response codes: 401, 404, 412 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - local_ip_id: local_ip-id-path + +Response +-------- + +There is no body content for the response of a successful DELETE request. + +========================================= +Local IP Associations (port_associations) +========================================= + +The resource lets users assign Local IPs to user Ports. +This is a sub-resource of the Local IP resource. + +List Local IP Associations +========================== + +.. rest_method:: GET /v2.0/local_ips/{local_ip_id}/port_associations + +Lists Associations for the given Local IP. + +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 `Filtering +and Column Selection `__. + +Normal response codes: 200 + +Error response codes: 401 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - local_ip_id: local_ip-id-path + - fixed_port_id: local_ip_association-fixed_port_id-query + - fixed_ip: local_ip_association-fixed_ip-query + - host: local_ip_association-host-query + - sort_dir: sort_dir + - sort_key: local_ip_association-sort_key + - fields: fields + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - local_ip_associations: local_ip_associations + - local_ip_id: local_ip-id + - local_ip_address: local_ip_address + - fixed_port_id: local_ip_association-fixed_port_id + - fixed_ip: local_ip_association-fixed_ip + - host: local_ip_association-host + +Response Example +---------------- + +.. literalinclude:: samples/local_ips/local-ip-list-associations-response.json + :language: javascript + +Create Local IP Association +=========================== + +.. rest_method:: POST /v2.0/local_ips/{local_ip_id}/port_associations + +Creates a Local IP association with a given Port. +If a Port has multiple fixed IPs user must specify which IP to use +for association. + +The operation returns the ``Conflict (409)`` response code for one of +reasons: + + - Specified fixed_port_id has multiple fixed IP addresses and fixed_ip + was not specified + + - Both fixed_port_id and fixed_ip are specified in the request, but port + has no such fixed IP + +Normal response codes: 201 + +Error response codes: 400, 401, 404, 409 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - local_ip_id: local_ip-id-path + - fixed_port_id: local_ip_association-fixed_port_id-request + - fixed_ip: local_ip_association-fixed_ip-request + +Request Example +--------------- + +.. literalinclude:: samples/local_ips/local_ip_association-create-request.json + :language: javascript + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - local_ip_association: local_ip_association + - local_ip_id: local_ip_id + - fixed_port_id: local_ip_association-fixed_port_id + - fixed_ip: local_ip_association-fixed_ip + - host: local_ip_association-host + +Response Example +---------------- + +.. literalinclude:: samples/local_ips/local_ip_association-create-response.json + :language: javascript + +Delete Local IP Association +=========================== + +.. rest_method:: DELETE /v2.0/local_ips/{local_ip_id}/port_associations/{fixed_port_id} + +Deletes a Local IP association. + +Normal response codes: 204 + +Error response codes: 400, 401, 403, 404 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - local_ip_id: local_ip-id-path + - fixed_port_id: local_ip_association-fixed_port_id-path + +Response +-------- + +There is no body content for the response of a successful DELETE request. diff --git a/api-ref/source/v2/parameters.yaml b/api-ref/source/v2/parameters.yaml index ddd27d93d..990a41736 100644 --- a/api-ref/source/v2/parameters.yaml +++ b/api-ref/source/v2/parameters.yaml @@ -169,6 +169,18 @@ ipsecpolicy_id-path: in: path required: true type: string +local_ip-id-path: + description: | + The ID of the Local IP + in: path + required: true + type: string +local_ip_association-fixed_port_id-path: + description: | + The ID of the port associated with the Local IP. + in: path + required: true + type: string log_id-path: description: | The ID of the log resource. @@ -693,6 +705,78 @@ ip_version-query: in: query required: false type: integer +local_ip-id-query: + description: | + Filter the Local IP list result by ID of Local IP + in: query + required: false + type: string +local_ip-ip_mode-query: + description: | + Filter the Local IP list result by IP mode. + Possible values are ``translate`` (DNAT) and ``passthrough`` (no DNAT) + in: query + required: false + type: string +local_ip-local_port_id-query: + description: | + Filter the Local IP list result by ID of underlying Neutron port + in: query + required: false + type: string +local_ip-sort_key: + description: | + Sorts by a Local IP attribute. You can specify multiple pairs of sort + key and sort direction query parameters. The sort keys are limited to: + + - ``id`` + - ``name`` + - ``description`` + - ``project_id`` + - ``local_port_id`` + - ``network_id`` + - ``local_ip_address`` + - ``ip_mode`` + in: query + required: false + type: string +local_ip_address-query: + description: | + Filter the Local IP list result by IP address + in: query + required: false + type: string +local_ip_association-fixed_ip-query: + description: | + Filter the Local IP Association list result by IP of associated ports + in: query + required: false + type: string +local_ip_association-fixed_port_id-query: + description: | + Filter the Local IP Association list result by ID of associated ports + in: query + required: false + type: string +local_ip_association-host-query: + description: | + Filter the Local IP Association list result by host of associated ports + in: query + required: false + type: string +local_ip_association-sort_key: + description: | + Sorts by a Local IP Association attribute. You can specify multiple pairs + of sort key and sort direction query parameters. + The sort keys are limited to: + + - ``local_ip_id`` + - ``fixed_port_id`` + - ``fixed_ip`` + - ``host`` + in: query + required: false + type: string log-sort_key: description: | Sorts by a log attribute. You can specify multiple pairs of sort key @@ -4089,6 +4173,126 @@ local_id: in: body required: false type: string +local_ip: + description: | + A ``local_ip`` object represents a Local IP that could be associated + with multiple ports + in: body + required: true + type: object +local_ip-id: + description: | + The ID of the Local IP. + in: body + required: true + type: string +local_ip-ip_mode: + description: | + The IP mode of the Local IP. + Possible values are ``translate`` (DNAT) and ``passthrough`` (no DNAT) + in: body + required: true + type: string +local_ip-ip_mode-request: + description: | + The requested IP mode of the Local IP. + Possible values are ``translate`` (DNAT) and ``passthrough`` (no DNAT) + in: body + required: false + type: string +local_ip-local_port_id: + description: | + The ID of underlying port of the Local IP. + in: body + required: true + type: string +local_ip-local_port_id-request: + description: | + The requested ID of the underlying port of the Local IP + in: body + required: true + type: string +local_ip-network_id: + description: | + The ID of the network of the Local IP. + in: body + required: true + type: string +local_ip-network_id-request: + description: | + The requested ID of the network of the Local IP + in: body + required: true + type: string +local_ip_address: + description: | + The actual IP address of the Local IP. + in: body + required: true + type: string +local_ip_address-request: + description: | + The requested actual IP address of the Local IP. + in: body + required: false + type: string +local_ip_association: + description: | + A ``local_ip_association`` object represents a Local IP Association + with a port + in: body + required: true + type: object +local_ip_association-fixed_ip: + description: | + The IP of the port associated with the Local IP. + in: body + required: false + type: string +local_ip_association-fixed_ip-request: + description: | + The requested IP of the port associated with the Local IP. + in: body + required: false + type: string +local_ip_association-fixed_port_id: + description: | + The ID of the port associated with the Local IP. + in: body + required: true + type: string +local_ip_association-fixed_port_id-request: + description: | + The requested ID of the port associated with the Local IP. + in: body + required: true + type: string +local_ip_association-host: + description: | + The host of the port associated with the Local IP. + in: body + required: false + type: string +local_ip_associations: + description: | + A list of ``local_ip_association`` objects. Each ``local_ip_association`` + object represents a Local IP Association with a port + in: body + required: true + type: array +local_ip_id: + description: | + The ID of the associated Local IP. + in: body + required: true + type: string +local_ips: + description: | + A list of ``local_ip`` objects. Each ``local_ip`` object represents a + Local IP that could be associated with multiple ports + in: body + required: true + type: array location: description: | Full URL to a service or server. diff --git a/api-ref/source/v2/samples/local_ips/local-ip-list-associations-response.json b/api-ref/source/v2/samples/local_ips/local-ip-list-associations-response.json new file mode 100644 index 000000000..0f91a69c8 --- /dev/null +++ b/api-ref/source/v2/samples/local_ips/local-ip-list-associations-response.json @@ -0,0 +1,18 @@ +{ + "port_associations": [ + { + "local_ip_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "local_ip_address": "172.24.4.228", + "fixed_port_id": "96227c78-6a0c-4d9d-b441-c4b8f6fb6c4a", + "fixed_ip": "10.0.0.5", + "host": "host1" + }, + { + "local_ip_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "local_ip_address": "172.24.4.228", + "fixed_port_id": "1b09fd12-c769-4be7-9c26-dececa474acf", + "fixed_ip": "10.0.0.6", + "host": "host2" + } + ] +} diff --git a/api-ref/source/v2/samples/local_ips/local-ips-list-response.json b/api-ref/source/v2/samples/local_ips/local-ips-list-response.json new file mode 100644 index 000000000..8291f8816 --- /dev/null +++ b/api-ref/source/v2/samples/local_ips/local-ips-list-response.json @@ -0,0 +1,30 @@ +{ + "local_ips": [ + { + "id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f", + "name": "test_local_ip1", + "description": "for test", + "project_id": "4969c491a3c74ee4af974e6d800c62de", + "local_port_id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7", + "network_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", + "local_ip_address": "100.100.100.100", + "ip_mode": "translate", + "created_at": "2021-12-21T10:55:50Z", + "updated_at": "2021-12-21T10:55:53Z", + "revision_number": 1 + }, + { + "id": "61cea855-49cb-4846-997d-801b70c71bdd", + "name": "test_local_ip2", + "description": "for test", + "project_id": "4969c491a3c74ee4af974e6d800c62de", + "local_port_id": "898b198e-49f7-47d6-a7e1-53f626a548e6", + "network_id": "376da547-b977-4cfe-9cba-275c80debf57", + "local_ip_address": "172.24.4.228", + "ip_mode": "passthrough", + "created_at": "2021-12-21T20:45:00Z", + "updated_at": "2021-12-21T20:45:00Z", + "revision_number": 1 + } + ] +} diff --git a/api-ref/source/v2/samples/local_ips/local_ip-create-request.json b/api-ref/source/v2/samples/local_ips/local_ip-create-request.json new file mode 100644 index 000000000..cd8980fd0 --- /dev/null +++ b/api-ref/source/v2/samples/local_ips/local_ip-create-request.json @@ -0,0 +1,9 @@ +{ + "local_ip": { + "name": "test_local_ip", + "description": "local ip for testing", + "network_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", + "local_ip_address": "172.24.4.228", + "ip_mode": "translate" + } +} diff --git a/api-ref/source/v2/samples/local_ips/local_ip-create-response.json b/api-ref/source/v2/samples/local_ips/local_ip-create-response.json new file mode 100644 index 000000000..8ef73cd6f --- /dev/null +++ b/api-ref/source/v2/samples/local_ips/local_ip-create-response.json @@ -0,0 +1,15 @@ +{ + "local_ip": { + "id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f", + "name": "test_local_ip", + "description": "local ip for testing", + "project_id": "4969c491a3c74ee4af974e6d800c62de", + "local_port_id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7", + "network_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", + "local_ip_address": "172.24.4.228", + "ip_mode": "translate", + "created_at": "2021-12-21T10:55:50Z", + "updated_at": "2021-12-21T10:55:53Z", + "revision_number": 1 + } +} \ No newline at end of file diff --git a/api-ref/source/v2/samples/local_ips/local_ip-show-response.json b/api-ref/source/v2/samples/local_ips/local_ip-show-response.json new file mode 100644 index 000000000..8ef73cd6f --- /dev/null +++ b/api-ref/source/v2/samples/local_ips/local_ip-show-response.json @@ -0,0 +1,15 @@ +{ + "local_ip": { + "id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f", + "name": "test_local_ip", + "description": "local ip for testing", + "project_id": "4969c491a3c74ee4af974e6d800c62de", + "local_port_id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7", + "network_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", + "local_ip_address": "172.24.4.228", + "ip_mode": "translate", + "created_at": "2021-12-21T10:55:50Z", + "updated_at": "2021-12-21T10:55:53Z", + "revision_number": 1 + } +} \ No newline at end of file diff --git a/api-ref/source/v2/samples/local_ips/local_ip-update-request.json b/api-ref/source/v2/samples/local_ips/local_ip-update-request.json new file mode 100644 index 000000000..8fe364e80 --- /dev/null +++ b/api-ref/source/v2/samples/local_ips/local_ip-update-request.json @@ -0,0 +1,6 @@ +{ + "local_ip": { + "name": "new_name", + "description": "new description" + } +} diff --git a/api-ref/source/v2/samples/local_ips/local_ip-update-response.json b/api-ref/source/v2/samples/local_ips/local_ip-update-response.json new file mode 100644 index 000000000..d616c61a6 --- /dev/null +++ b/api-ref/source/v2/samples/local_ips/local_ip-update-response.json @@ -0,0 +1,15 @@ +{ + "local_ip": { + "id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f", + "name": "new_name", + "description": "now in passthrough mode", + "project_id": "4969c491a3c74ee4af974e6d800c62de", + "local_port_id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7", + "network_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", + "local_ip_address": "172.24.4.228", + "ip_mode": "passthrough", + "created_at": "2021-12-21T10:55:50Z", + "updated_at": "2021-12-21T10:55:53Z", + "revision_number": 1 + } +} \ No newline at end of file diff --git a/api-ref/source/v2/samples/local_ips/local_ip_association-create-request.json b/api-ref/source/v2/samples/local_ips/local_ip_association-create-request.json new file mode 100644 index 000000000..073adb83b --- /dev/null +++ b/api-ref/source/v2/samples/local_ips/local_ip_association-create-request.json @@ -0,0 +1,6 @@ +{ + "port_association": { + "fixed_port_id": "96227c78-6a0c-4d9d-b441-c4b8f6fb6c4a", + "fixed_ip": "10.0.0.5" + } +} diff --git a/api-ref/source/v2/samples/local_ips/local_ip_association-create-response.json b/api-ref/source/v2/samples/local_ips/local_ip_association-create-response.json new file mode 100644 index 000000000..ea1056ffc --- /dev/null +++ b/api-ref/source/v2/samples/local_ips/local_ip_association-create-response.json @@ -0,0 +1,9 @@ +{ + "port_association": { + "local_ip_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "local_ip_address": "172.24.4.228", + "fixed_port_id": "96227c78-6a0c-4d9d-b441-c4b8f6fb6c4a", + "fixed_ip": "10.0.0.5", + "host": "host1" + } +} \ No newline at end of file diff --git a/neutron_lib/api/definitions/__init__.py b/neutron_lib/api/definitions/__init__.py index c057f72bd..8150ee7bb 100644 --- a/neutron_lib/api/definitions/__init__.py +++ b/neutron_lib/api/definitions/__init__.py @@ -70,6 +70,7 @@ from neutron_lib.api.definitions import l3_flavors from neutron_lib.api.definitions import l3_multi_ext_gw from neutron_lib.api.definitions import l3_ndp_proxy from neutron_lib.api.definitions import l3_port_ip_change_not_allowed +from neutron_lib.api.definitions import local_ip from neutron_lib.api.definitions import logging from neutron_lib.api.definitions import logging_resource from neutron_lib.api.definitions import metering @@ -204,6 +205,7 @@ _ALL_API_DEFINITIONS = { l3_multi_ext_gw, l3_ndp_proxy, l3_port_ip_change_not_allowed, + local_ip, logging, logging_resource, metering, diff --git a/neutron_lib/api/definitions/local_ip.py b/neutron_lib/api/definitions/local_ip.py new file mode 100644 index 000000000..ec76e42f8 --- /dev/null +++ b/neutron_lib/api/definitions/local_ip.py @@ -0,0 +1,156 @@ +# Copyright 2021 Huawei, Inc. +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from neutron_lib import constants +from neutron_lib.db import constants as db_const + +RESOURCE_NAME = 'local_ip' +COLLECTION_NAME = RESOURCE_NAME + 's' + +LOCAL_IP_ASSOCIATION = 'port_association' +LOCAL_IP_ASSOCIATIONS = LOCAL_IP_ASSOCIATION + 's' + +ALIAS = RESOURCE_NAME +IS_SHIM_EXTENSION = False +IS_STANDARD_ATTR_EXTENSION = False +NAME = 'Local IP' +DESCRIPTION = 'Support Node Local Virtual IP' +UPDATED_TIMESTAMP = '2021-07-26T10:00:00-00:00' + +IP_MODE_TRANSLATE = 'translate' +IP_MODE_PASSTHROUGH = 'passthrough' +VALID_IP_MODES = [IP_MODE_TRANSLATE, IP_MODE_PASSTHROUGH] + +RESOURCE_ATTRIBUTE_MAP = { + COLLECTION_NAME: { + 'id': { + 'allow_post': False, + 'allow_put': False, + 'validate': {'type:uuid': None}, + 'is_visible': True, + 'is_filter': True, + 'is_sort_key': True, + 'primary_key': True}, + 'name': { + 'allow_post': True, + 'allow_put': True, + 'default': '', + 'validate': {'type:string': db_const.NAME_FIELD_SIZE}, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + 'description': { + 'allow_post': True, + 'allow_put': True, + 'default': '', + 'validate': {'type:string': db_const.LONG_DESCRIPTION_FIELD_SIZE}, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + 'project_id': { + 'allow_post': True, + 'allow_put': False, + 'validate': {'type:string': db_const.PROJECT_ID_FIELD_SIZE}, + 'required_by_policy': True, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + 'local_port_id': { + 'allow_post': True, + 'allow_put': False, + 'validate': {'type:uuid': None}, + 'default': constants.ATTR_NOT_SPECIFIED, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + 'network_id': { + 'allow_post': True, + 'allow_put': False, + 'validate': {'type:uuid': None}, + 'default': constants.ATTR_NOT_SPECIFIED, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + 'local_ip_address': { + 'allow_post': True, + 'allow_put': False, + 'default': constants.ATTR_NOT_SPECIFIED, + 'validate': {'type:ip_address_or_none': None}, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True, + 'enforce_policy': True}, + 'ip_mode': { + 'allow_post': True, + 'allow_put': False, + 'default': IP_MODE_TRANSLATE, + 'validate': {'type:values': VALID_IP_MODES}, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + } +} + +SUB_RESOURCE_ATTRIBUTE_MAP = { + LOCAL_IP_ASSOCIATIONS: { + 'parent': {'collection_name': COLLECTION_NAME, + 'member_name': RESOURCE_NAME}, + 'parameters': { + 'local_ip_address': { + 'allow_post': False, + 'allow_put': False, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + 'fixed_port_id': { + 'allow_post': True, + 'allow_put': False, + 'validate': {'type:uuid': None}, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + 'fixed_ip': { + 'allow_post': True, + 'allow_put': False, + 'validate': {'type:ip_address_or_none': None}, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True, + 'default': None}, + 'host': { + 'allow_post': False, + 'allow_put': False, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + 'project_id': { + 'allow_post': True, + 'allow_put': False, + 'validate': {'type:string': db_const.PROJECT_ID_FIELD_SIZE}, + 'required_by_policy': True, + 'is_filter': True, + 'is_sort_key': True, + 'is_visible': True}, + } + } +} + +ACTION_MAP = {} + +ACTION_STATUS = {} + +REQUIRED_EXTENSIONS = [] + +OPTIONAL_EXTENSIONS = [] diff --git a/neutron_lib/tests/unit/api/definitions/test_local_ip.py b/neutron_lib/tests/unit/api/definitions/test_local_ip.py new file mode 100644 index 000000000..4ca81cc29 --- /dev/null +++ b/neutron_lib/tests/unit/api/definitions/test_local_ip.py @@ -0,0 +1,25 @@ +# Copyright 2021 Huawei, Inc. +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from neutron_lib.api.definitions import local_ip +from neutron_lib.tests.unit.api.definitions import base + + +class LocalIPDefinitionTestCase(base.DefinitionBaseTestCase): + extension_module = local_ip + extension_resources = (local_ip.COLLECTION_NAME,) + extension_subresources = (local_ip.LOCAL_IP_ASSOCIATIONS,) + extension_attributes = ('local_port_id', 'local_ip_address', 'ip_mode', + 'local_ip_id', 'fixed_port_id', 'fixed_ip', 'host') diff --git a/releasenotes/notes/add-local-ip-extension-fb4a18f5a6525f1f.yaml b/releasenotes/notes/add-local-ip-extension-fb4a18f5a6525f1f.yaml new file mode 100644 index 000000000..f27aa25fd --- /dev/null +++ b/releasenotes/notes/add-local-ip-extension-fb4a18f5a6525f1f.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Add an API extension ``local-ip`` that enables users to create Local IP + resource which is a shared virtual IP address that could be assigned to + multiple ports and is guaranteed to only be reachable within the same + physical server/node boundaries.