Multiple API cleanup changes
This microversion implements below API cleanups: 1. 400 for unknown param for query param and for request body. 2. Making server representation always consistent among all APIs returning the complete server representation. 3. Change the default return value of ``swap`` field from the empty string to 0 (integer) in flavor APIs. 4. Return ``servers`` field always in the response of GET hypervisors API even there are no servers on hypervisor Details: https://specs.openstack.org/openstack/nova-specs/specs/train/approved/api-consistency-cleanup.html Partial-Implements: blueprint api-consistency-cleanup Change-Id: I9d257a003d315b84b937dcef91f3cb41f3e24b53
This commit is contained in:
parent
52b9359d6c
commit
b26bc7fd7a
|
@ -108,9 +108,9 @@ Response
|
|||
- extra_specs: extra_specs_2_61
|
||||
|
||||
|
||||
**Example Create Flavor (v2.61)**
|
||||
**Example Create Flavor (v2.75)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.61/flavor-create-post-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.75/flavor-create-post-resp.json
|
||||
:language: javascript
|
||||
|
||||
List Flavors With Details
|
||||
|
@ -158,9 +158,9 @@ Response
|
|||
- os-flavor-access:is_public: flavor_is_public
|
||||
- extra_specs: extra_specs_2_61
|
||||
|
||||
**Example List Flavors With Details (v2.61)**
|
||||
**Example List Flavors With Details (v2.75)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/v2.61/flavors-detail-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/v2.75/flavors-detail-resp.json
|
||||
:language: javascript
|
||||
|
||||
Show Flavor Details
|
||||
|
@ -201,9 +201,9 @@ Response
|
|||
- os-flavor-access:is_public: flavor_is_public
|
||||
- extra_specs: extra_specs_2_61
|
||||
|
||||
**Example Show Flavor Details (v2.61)**
|
||||
**Example Show Flavor Details (v2.75)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/v2.61/flavor-get-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/v2.75/flavor-get-resp.json
|
||||
:language: javascript
|
||||
|
||||
Update Flavor Description
|
||||
|
@ -258,9 +258,9 @@ Response
|
|||
- extra_specs: extra_specs_2_61
|
||||
|
||||
|
||||
**Example Update Flavor Description (v2.61)**
|
||||
**Example Update Flavor Description (v2.75)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.61/flavor-update-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.75/flavor-update-resp.json
|
||||
:language: javascript
|
||||
|
||||
Delete Flavor
|
||||
|
|
|
@ -3074,6 +3074,8 @@ flavor_swap:
|
|||
The size of a dedicated swap disk that will be allocated, in
|
||||
MiB. If 0 (the default), no dedicated swap disk will be created.
|
||||
Currently, the empty string ('') is used to represent 0.
|
||||
As of microversion 2.75 default return value of swap is 0
|
||||
instead of empty string.
|
||||
in: body
|
||||
required: true
|
||||
type: integer
|
||||
|
@ -3519,6 +3521,20 @@ host_status_body_in:
|
|||
in: body
|
||||
required: false
|
||||
type: string
|
||||
host_status_update_rebuild:
|
||||
description: |
|
||||
The host status. Values where next value in list can override the previous:
|
||||
- ``UP`` if nova-compute up.
|
||||
- ``UNKNOWN`` if nova-compute not reported by servicegroup driver.
|
||||
- ``DOWN`` if nova-compute forced down.
|
||||
- ``MAINTENANCE`` if nova-compute is disabled.
|
||||
- Empty string indicates there is no host for server.
|
||||
This attribute appears in the response only if the policy permits.
|
||||
By default, only administrators can get this parameter.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
min_version: 2.75
|
||||
host_zone:
|
||||
description: |
|
||||
The available zone of the host.
|
||||
|
@ -3650,8 +3666,10 @@ hypervisor_os_diagnostics:
|
|||
hypervisor_servers:
|
||||
description: |
|
||||
A list of ``server`` objects.
|
||||
This field has become mandatory in microversion 2.75. If no servers is on hypervisor
|
||||
then empty list is returned.
|
||||
in: body
|
||||
required: false
|
||||
required: true
|
||||
type: array
|
||||
min_version: 2.53
|
||||
hypervisor_servers_name:
|
||||
|
@ -4140,6 +4158,13 @@ key_name_resp:
|
|||
in: body
|
||||
required: true
|
||||
type: string
|
||||
key_name_resp_update:
|
||||
description: |
|
||||
The name of associated key pair, if any.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
key_pairs: &key_pairs
|
||||
description: |
|
||||
The number of allowed key pairs for each user.
|
||||
|
@ -4730,6 +4755,13 @@ name_server_group:
|
|||
in: body
|
||||
required: true
|
||||
type: string
|
||||
name_update_rebuild:
|
||||
description: |
|
||||
The security group name.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
namespace:
|
||||
description: |
|
||||
A URL pointing to the namespace for this extension.
|
||||
|
@ -4970,6 +5002,13 @@ OS-EXT-AZ:availability_zone_optional:
|
|||
in: body
|
||||
required: false
|
||||
type: string
|
||||
OS-EXT-AZ:availability_zone_update_rebuild:
|
||||
description: |
|
||||
The availability zone name.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
OS-EXT-SRV-ATTR:host:
|
||||
description: |
|
||||
The name of the compute host on which this instance is running.
|
||||
|
@ -4977,6 +5016,14 @@ OS-EXT-SRV-ATTR:host:
|
|||
in: body
|
||||
required: true
|
||||
type: string
|
||||
OS-EXT-SRV-ATTR:host_update_rebuild:
|
||||
description: |
|
||||
The name of the compute host on which this instance is running.
|
||||
Appears in the response for administrative users only.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
OS-EXT-SRV-ATTR:hypervisor_hostname:
|
||||
description: |
|
||||
The hypervisor host name provided by the Nova virt driver. For the Ironic driver,
|
||||
|
@ -4984,6 +5031,14 @@ OS-EXT-SRV-ATTR:hypervisor_hostname:
|
|||
in: body
|
||||
required: true
|
||||
type: string
|
||||
OS-EXT-SRV-ATTR:hypervisor_hostname_update_rebuild:
|
||||
description: |
|
||||
The hypervisor host name provided by the Nova virt driver. For the Ironic driver,
|
||||
it is the Ironic node uuid. Appears in the response for administrative users only.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
OS-EXT-SRV-ATTR:instance_name:
|
||||
description: |
|
||||
The instance name. The Compute API generates the instance name from the instance
|
||||
|
@ -4991,6 +5046,14 @@ OS-EXT-SRV-ATTR:instance_name:
|
|||
in: body
|
||||
required: true
|
||||
type: string
|
||||
OS-EXT-SRV-ATTR:instance_name_update_rebuild:
|
||||
description: |
|
||||
The instance name. The Compute API generates the instance name from the instance
|
||||
name template. Appears in the response for administrative users only.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
OS-EXT-STS:power_state:
|
||||
description: |
|
||||
The power state of the instance. This is an enum value that is mapped as::
|
||||
|
@ -5004,18 +5067,46 @@ OS-EXT-STS:power_state:
|
|||
in: body
|
||||
required: true
|
||||
type: integer
|
||||
OS-EXT-STS:power_state_update_rebuild:
|
||||
description: |
|
||||
The power state of the instance. This is an enum value that is mapped as::
|
||||
|
||||
0: NOSTATE
|
||||
1: RUNNING
|
||||
3: PAUSED
|
||||
4: SHUTDOWN
|
||||
6: CRASHED
|
||||
7: SUSPENDED
|
||||
in: body
|
||||
required: true
|
||||
type: integer
|
||||
min_version: 2.75
|
||||
OS-EXT-STS:task_state:
|
||||
description: |
|
||||
The task state of the instance.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
OS-EXT-STS:task_state_update_rebuild:
|
||||
description: |
|
||||
The task state of the instance.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
OS-EXT-STS:vm_state:
|
||||
description: |
|
||||
The VM state.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
OS-EXT-STS:vm_state_update_rebuild:
|
||||
description: |
|
||||
The VM state.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
os-extended-volumes:volumes_attached:
|
||||
description: |
|
||||
The attached volumes, if any.
|
||||
|
@ -5032,12 +5123,36 @@ os-extended-volumes:volumes_attached.delete_on_termination:
|
|||
required: true
|
||||
type: boolean
|
||||
min_version: 2.3
|
||||
os-extended-volumes:volumes_attached.delete_on_termination_update_rebuild:
|
||||
description: |
|
||||
A flag indicating if the attached volume will be deleted
|
||||
when the server is deleted. By default this is False and
|
||||
can only be set when creating a volume while creating a
|
||||
server, which is commonly referred to as boot from volume.
|
||||
in: body
|
||||
required: true
|
||||
type: boolean
|
||||
min_version: 2.75
|
||||
os-extended-volumes:volumes_attached.id:
|
||||
description: |
|
||||
The attached volume ID.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
os-extended-volumes:volumes_attached.id_update_rebuild:
|
||||
description: |
|
||||
The attached volume ID.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
os-extended-volumes:volumes_attached_update_rebuild:
|
||||
description: |
|
||||
The attached volumes, if any.
|
||||
in: body
|
||||
required: true
|
||||
type: array
|
||||
min_version: 2.75
|
||||
os-getConsoleOutput:
|
||||
description: |
|
||||
The action to get console output of the server.
|
||||
|
@ -5151,6 +5266,24 @@ OS-SRV-USG:launched_at:
|
|||
in: body
|
||||
required: true
|
||||
type: string
|
||||
OS-SRV-USG:launched_at_update_rebuild:
|
||||
description: |
|
||||
The date and time when the server was launched.
|
||||
|
||||
The date and time stamp format is `ISO 8601 <https://en.wikipedia.org/wiki/ISO_8601>`_:
|
||||
|
||||
::
|
||||
|
||||
CCYY-MM-DDThh:mm:ss±hh:mm
|
||||
|
||||
For example, ``2015-08-27T09:49:58-05:00``.
|
||||
|
||||
The ``hh±:mm`` value, if included, is the time zone as an offset from UTC.
|
||||
If the ``deleted_at`` date and time stamp is not set, its value is ``null``.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
OS-SRV-USG:terminated_at:
|
||||
description: |
|
||||
The date and time when the server was deleted.
|
||||
|
@ -5167,6 +5300,23 @@ OS-SRV-USG:terminated_at:
|
|||
in: body
|
||||
required: true
|
||||
type: string
|
||||
OS-SRV-USG:terminated_at_update_rebuild:
|
||||
description: |
|
||||
The date and time when the server was deleted.
|
||||
|
||||
The date and time stamp format is `ISO 8601 <https://en.wikipedia.org/wiki/ISO_8601>`_:
|
||||
|
||||
::
|
||||
|
||||
CCYY-MM-DDThh:mm:ss±hh:mm
|
||||
|
||||
For example, ``2015-08-27T09:49:58-05:00``.
|
||||
The ``±hh:mm`` value, if included, is the time zone as an offset from UTC.
|
||||
If the ``deleted_at`` date and time stamp is not set, its value is ``null``.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.75
|
||||
os-start:
|
||||
description: |
|
||||
The action to start a stopped server.
|
||||
|
@ -5852,6 +6002,13 @@ security_groups_obj:
|
|||
in: body
|
||||
required: true
|
||||
type: array
|
||||
security_groups_obj_update_rebuild:
|
||||
description: |
|
||||
One or more security groups objects.
|
||||
in: body
|
||||
required: true
|
||||
type: array
|
||||
min_version: 2.75
|
||||
security_groups_quota:
|
||||
description: |
|
||||
The number of allowed security groups for each tenant.
|
||||
|
@ -6002,6 +6159,14 @@ server_hostname:
|
|||
The hostname set on the instance when it is booted.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.3
|
||||
server_hostname_update_rebuild:
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
description: |
|
||||
The hostname set on the instance when it is booted.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.75
|
||||
# This is the hypervisor_hostname in a POST (create instance) request body.
|
||||
server_hypervisor_hostname_create:
|
||||
description: |
|
||||
|
@ -6032,6 +6197,14 @@ server_kernel_id:
|
|||
The UUID of the kernel image when using an AMI. Will be null if not.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.3
|
||||
server_kernel_id_update_rebuild:
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
description: |
|
||||
The UUID of the kernel image when using an AMI. Will be null if not.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.75
|
||||
server_launch_index:
|
||||
in: body
|
||||
required: false
|
||||
|
@ -6041,6 +6214,15 @@ server_launch_index:
|
|||
sequence in which the servers were launched.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.3
|
||||
server_launch_index_update_rebuild:
|
||||
in: body
|
||||
required: false
|
||||
type: integer
|
||||
description: |
|
||||
When servers are launched via multiple create, this is the
|
||||
sequence in which the servers were launched.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.75
|
||||
server_links:
|
||||
description: |
|
||||
Links pertaining to the server. See `API Guide / Links and
|
||||
|
@ -6070,6 +6252,14 @@ server_ramdisk_id:
|
|||
The UUID of the ramdisk image when using an AMI. Will be null if not.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.3
|
||||
server_ramdisk_id_update_rebuild:
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
description: |
|
||||
The UUID of the ramdisk image when using an AMI. Will be null if not.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.75
|
||||
server_reservation_id:
|
||||
in: body
|
||||
required: false
|
||||
|
@ -6080,6 +6270,16 @@ server_reservation_id:
|
|||
create, that will all have the same reservation_id.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.3
|
||||
server_reservation_id_update_rebuild:
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
description: |
|
||||
The reservation id for the server. This is an id that can
|
||||
be useful in tracking groups of servers created with multiple
|
||||
create, that will all have the same reservation_id.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.75
|
||||
server_root_device_name:
|
||||
in: body
|
||||
required: false
|
||||
|
@ -6088,6 +6288,14 @@ server_root_device_name:
|
|||
The root device name for the instance
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.3
|
||||
server_root_device_name_update_rebuild:
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
description: |
|
||||
The root device name for the instance
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.75
|
||||
server_status:
|
||||
description: |
|
||||
The server status.
|
||||
|
@ -6169,6 +6377,14 @@ server_user_data:
|
|||
The user_data the instance was created with.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.3
|
||||
server_user_data_update:
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
description: |
|
||||
The user_data the instance was created with.
|
||||
By default, it appears in the response for administrative users only.
|
||||
min_version: 2.75
|
||||
server_uuid:
|
||||
description: |
|
||||
The UUID of the server instance to which the API dispatches the event. You must
|
||||
|
|
|
@ -634,10 +634,31 @@ Response
|
|||
- trusted_image_certificates: server_trusted_image_certificates_resp
|
||||
- server_groups: server_groups_2_71
|
||||
- locked_reason: locked_reason_resp
|
||||
- OS-EXT-AZ:availability_zone: OS-EXT-AZ:availability_zone_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:host: OS-EXT-SRV-ATTR:host_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:hypervisor_hostname: OS-EXT-SRV-ATTR:hypervisor_hostname_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:instance_name: OS-EXT-SRV-ATTR:instance_name_update_rebuild
|
||||
- OS-EXT-STS:power_state: OS-EXT-STS:power_state_update_rebuild
|
||||
- OS-EXT-STS:task_state: OS-EXT-STS:task_state_update_rebuild
|
||||
- OS-EXT-STS:vm_state: OS-EXT-STS:vm_state_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:hostname: server_hostname_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:reservation_id: server_reservation_id_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:launch_index: server_launch_index_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:kernel_id: server_kernel_id_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:ramdisk_id: server_ramdisk_id_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:root_device_name: server_root_device_name_update_rebuild
|
||||
- os-extended-volumes:volumes_attached: os-extended-volumes:volumes_attached_update_rebuild
|
||||
- os-extended-volumes:volumes_attached.id: os-extended-volumes:volumes_attached.id_update_rebuild
|
||||
- os-extended-volumes:volumes_attached.delete_on_termination: os-extended-volumes:volumes_attached.delete_on_termination_update_rebuild
|
||||
- OS-SRV-USG:launched_at: OS-SRV-USG:launched_at_update_rebuild
|
||||
- OS-SRV-USG:terminated_at: OS-SRV-USG:terminated_at_update_rebuild
|
||||
- security_groups: security_groups_obj_update_rebuild
|
||||
- security_group.name: name_update_rebuild
|
||||
- host_status: host_status_update_rebuild
|
||||
|
||||
**Example Rebuild Server (rebuild Action) (v2.73)**
|
||||
**Example Rebuild Server (rebuild Action) (v2.75)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/servers/v2.73/server-action-rebuild-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/servers/v2.75/server-action-rebuild-resp.json
|
||||
:language: javascript
|
||||
|
||||
Remove (Disassociate) Floating Ip (removeFloatingIp Action) (DEPRECATED)
|
||||
|
|
|
@ -877,10 +877,33 @@ Response
|
|||
- trusted_image_certificates: server_trusted_image_certificates_resp
|
||||
- server_groups: server_groups_2_71
|
||||
- locked_reason: locked_reason_resp
|
||||
- OS-EXT-AZ:availability_zone: OS-EXT-AZ:availability_zone_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:host: OS-EXT-SRV-ATTR:host_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:hypervisor_hostname: OS-EXT-SRV-ATTR:hypervisor_hostname_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:instance_name: OS-EXT-SRV-ATTR:instance_name_update_rebuild
|
||||
- OS-EXT-STS:power_state: OS-EXT-STS:power_state_update_rebuild
|
||||
- OS-EXT-STS:task_state: OS-EXT-STS:task_state_update_rebuild
|
||||
- OS-EXT-STS:vm_state: OS-EXT-STS:vm_state_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:hostname: server_hostname_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:reservation_id: server_reservation_id_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:launch_index: server_launch_index_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:kernel_id: server_kernel_id_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:ramdisk_id: server_ramdisk_id_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:root_device_name: server_root_device_name_update_rebuild
|
||||
- OS-EXT-SRV-ATTR:user_data: server_user_data_update
|
||||
- os-extended-volumes:volumes_attached: os-extended-volumes:volumes_attached_update_rebuild
|
||||
- os-extended-volumes:volumes_attached.id: os-extended-volumes:volumes_attached.id_update_rebuild
|
||||
- os-extended-volumes:volumes_attached.delete_on_termination: os-extended-volumes:volumes_attached.delete_on_termination_update_rebuild
|
||||
- OS-SRV-USG:launched_at: OS-SRV-USG:launched_at_update_rebuild
|
||||
- OS-SRV-USG:terminated_at: OS-SRV-USG:terminated_at_update_rebuild
|
||||
- security_groups: security_groups_obj_update_rebuild
|
||||
- security_group.name: name_update_rebuild
|
||||
- host_status: host_status_update_rebuild
|
||||
- key_name: key_name_resp_update
|
||||
|
||||
**Example Update Server (2.73)**
|
||||
**Example Update Server (2.75)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/servers/v2.73/server-update-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/servers/v2.75/server-update-resp.json
|
||||
:language: javascript
|
||||
|
||||
Delete Server
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"flavor": {
|
||||
"name": "test_flavor",
|
||||
"ram": 1024,
|
||||
"vcpus": 2,
|
||||
"disk": 10,
|
||||
"id": "10",
|
||||
"rxtx_factor": 2.0,
|
||||
"description": "test description"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"flavor": {
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 10,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "10",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/10",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/10",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "test_flavor",
|
||||
"ram": 1024,
|
||||
"swap": 0,
|
||||
"rxtx_factor": 2.0,
|
||||
"vcpus": 2,
|
||||
"description": "test description",
|
||||
"extra_specs": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"flavor": {
|
||||
"description": "updated description"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"flavor": {
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 1,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "updated description",
|
||||
"extra_specs": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"flavor": {
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 20,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "7",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/7",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/7",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small.description",
|
||||
"ram": 2048,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "test description",
|
||||
"extra_specs": {
|
||||
"key1": "value1",
|
||||
"key2": "value2"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
{
|
||||
"flavors": [
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 1,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 20,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "2",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/2",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/2",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small",
|
||||
"ram": 2048,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 40,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "3",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/3",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/3",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.medium",
|
||||
"ram": 4096,
|
||||
"swap": 0,
|
||||
"vcpus": 2,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 80,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "4",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/4",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/4",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.large",
|
||||
"ram": 8192,
|
||||
"swap": 0,
|
||||
"vcpus": 4,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 160,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "5",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/5",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/5",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.xlarge",
|
||||
"ram": 16384,
|
||||
"swap": 0,
|
||||
"vcpus": 8,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 1,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "6",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/6",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/6",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny.specs",
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {
|
||||
"hw:mem_page_size": "2048",
|
||||
"hw:cpu_policy": "dedicated"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 20,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "7",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/7",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/7",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small.description",
|
||||
"ram": 2048,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "test description",
|
||||
"extra_specs": {
|
||||
"key1": "value1",
|
||||
"key2": "value2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
"flavors": [
|
||||
{
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/2",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/2",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/3",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/3",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.medium",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/4",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/4",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.large",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/5",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/5",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.xlarge",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/6",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/6",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny.specs",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "7",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/flavors/7",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/7",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small.description",
|
||||
"description": "test description"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
"server": {
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"OS-EXT-AZ:availability_zone": "us-west",
|
||||
"OS-EXT-SRV-ATTR:host": "compute",
|
||||
"OS-EXT-SRV-ATTR:hostname": "new-server-test",
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini",
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
"OS-EXT-SRV-ATTR:kernel_id": "",
|
||||
"OS-EXT-SRV-ATTR:launch_index": 0,
|
||||
"OS-EXT-SRV-ATTR:ramdisk_id": "",
|
||||
"OS-EXT-SRV-ATTR:reservation_id": "r-t61j9da6",
|
||||
"OS-EXT-SRV-ATTR:root_device_name": "/dev/sda",
|
||||
"OS-EXT-STS:power_state": 1,
|
||||
"OS-EXT-STS:task_state": null,
|
||||
"OS-EXT-STS:vm_state": "active",
|
||||
"OS-SRV-USG:launched_at": "2019-04-23T15:19:10.855016",
|
||||
"OS-SRV-USG:terminated_at": null,
|
||||
"accessIPv4": "1.2.3.4",
|
||||
"accessIPv6": "80fe::",
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||
"OS-EXT-IPS:type": "fixed",
|
||||
"addr": "192.168.0.3",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"adminPass": "seekr3t",
|
||||
"config_drive": "",
|
||||
"created": "2019-04-23T17:10:22Z",
|
||||
"description": null,
|
||||
"flavor": {
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"extra_specs": {},
|
||||
"original_name": "m1.tiny",
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
},
|
||||
"hostId": "2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6",
|
||||
"host_status": "UP",
|
||||
"id": "0c37a84a-c757-4f22-8c7f-0bf8b6970886",
|
||||
"image": {
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/0c37a84a-c757-4f22-8c7f-0bf8b6970886",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/0c37a84a-c757-4f22-8c7f-0bf8b6970886",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"locked": false,
|
||||
"locked_reason": null,
|
||||
"metadata": {
|
||||
"meta_var": "meta_val"
|
||||
},
|
||||
"name": "foobar",
|
||||
"os-extended-volumes:volumes_attached": [],
|
||||
"progress": 0,
|
||||
"security_groups": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
],
|
||||
"server_groups": [],
|
||||
"status": "ACTIVE",
|
||||
"tags": [],
|
||||
"tenant_id": "6f70656e737461636b20342065766572",
|
||||
"trusted_image_certificates": null,
|
||||
"updated": "2019-04-23T17:10:24Z",
|
||||
"user_data": "ZWNobyAiaGVsbG8gd29ybGQi",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"rebuild" : {
|
||||
"accessIPv4" : "1.2.3.4",
|
||||
"accessIPv6" : "80fe::",
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"imageRef" : "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"name" : "foobar",
|
||||
"adminPass" : "seekr3t",
|
||||
"metadata" : {
|
||||
"meta_var" : "meta_val"
|
||||
},
|
||||
"user_data": "ZWNobyAiaGVsbG8gd29ybGQi"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"server": {
|
||||
"accessIPv4": "1.2.3.4",
|
||||
"accessIPv6": "80fe::",
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"name": "new-server-test",
|
||||
"description": "Sample description"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"server": {
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"OS-EXT-AZ:availability_zone": "us-west",
|
||||
"OS-EXT-SRV-ATTR:host": "compute",
|
||||
"OS-EXT-SRV-ATTR:hostname": "new-server-test",
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini",
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
"OS-EXT-SRV-ATTR:kernel_id": "",
|
||||
"OS-EXT-SRV-ATTR:launch_index": 0,
|
||||
"OS-EXT-SRV-ATTR:ramdisk_id": "",
|
||||
"OS-EXT-SRV-ATTR:reservation_id": "r-t61j9da6",
|
||||
"OS-EXT-SRV-ATTR:root_device_name": "/dev/sda",
|
||||
"OS-EXT-SRV-ATTR:user_data": "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==",
|
||||
"OS-EXT-STS:power_state": 1,
|
||||
"OS-EXT-STS:task_state": null,
|
||||
"OS-EXT-STS:vm_state": "active",
|
||||
"OS-SRV-USG:launched_at": "2019-04-23T15:19:10.855016",
|
||||
"OS-SRV-USG:terminated_at": null,
|
||||
"accessIPv4": "1.2.3.4",
|
||||
"accessIPv6": "80fe::",
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||
"OS-EXT-IPS:type": "fixed",
|
||||
"addr": "192.168.0.3",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"config_drive": "",
|
||||
"created": "2012-12-02T02:11:57Z",
|
||||
"description": "Sample description",
|
||||
"flavor": {
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"extra_specs": {},
|
||||
"original_name": "m1.tiny",
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
},
|
||||
"hostId": "6e84af987b4e7ec1c039b16d21f508f4a505672bd94fb0218b668d07",
|
||||
"host_status": "UP",
|
||||
"id": "324dfb7d-f4a9-419a-9a19-237df04b443b",
|
||||
"image": {
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/6f70656e737461636b20342065766572/servers/324dfb7d-f4a9-419a-9a19-237df04b443b",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/324dfb7d-f4a9-419a-9a19-237df04b443b",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"locked": false,
|
||||
"locked_reason": null,
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"os-extended-volumes:volumes_attached": [],
|
||||
"progress": 0,
|
||||
"security_groups": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
],
|
||||
"server_groups": [],
|
||||
"status": "ACTIVE",
|
||||
"tags": [],
|
||||
"tenant_id": "6f70656e737461636b20342065766572",
|
||||
"trusted_image_certificates": null,
|
||||
"updated": "2012-12-02T02:11:58Z",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
}
|
||||
],
|
||||
"status": "CURRENT",
|
||||
"version": "2.74",
|
||||
"version": "2.75",
|
||||
"min_version": "2.1",
|
||||
"updated": "2013-07-23T11:33:21Z"
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
}
|
||||
],
|
||||
"status": "CURRENT",
|
||||
"version": "2.74",
|
||||
"version": "2.75",
|
||||
"min_version": "2.1",
|
||||
"updated": "2013-07-23T11:33:21Z"
|
||||
}
|
||||
|
|
|
@ -188,6 +188,14 @@ REST_API_VERSION_HISTORY = """REST API Version History:
|
|||
in request body to ``POST /servers``. Allow users to specify which
|
||||
host/node they want their servers to land on and still be
|
||||
validated by the scheduler.
|
||||
* 2.75 - Multiple API cleanup listed below:
|
||||
- 400 for unknown param for query param and for request body.
|
||||
- Making server representation always consistent among GET, PUT
|
||||
and Rebuild serevr APIs response.
|
||||
- Change the default return value of swap field from the empty
|
||||
string to 0 (integer) in flavor APIs.
|
||||
- Return ``servers`` field always in the response of GET
|
||||
hypervisors API even there are no servers on hypervisor.
|
||||
"""
|
||||
|
||||
# The minimum and maximum versions of the API supported
|
||||
|
@ -196,7 +204,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
|
|||
# Note(cyeoh): This only applies for the v2.1 API once microversions
|
||||
# support is fully merged. It does not affect the V2 API.
|
||||
_MIN_API_VERSION = "2.1"
|
||||
_MAX_API_VERSION = "2.74"
|
||||
_MAX_API_VERSION = "2.75"
|
||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||
|
||||
# Almost all proxy APIs which are related to network, images and baremetal
|
||||
|
|
|
@ -46,7 +46,8 @@ class AgentController(wsgi.Controller):
|
|||
http://wiki.openstack.org/GuestAgent
|
||||
http://wiki.openstack.org/GuestAgentXenStoreCommunication
|
||||
"""
|
||||
@validation.query_schema(schema.index_query)
|
||||
@validation.query_schema(schema.index_query_275, '2.75')
|
||||
@validation.query_schema(schema.index_query, '2.0', '2.74')
|
||||
@wsgi.expected_errors(())
|
||||
def index(self, req):
|
||||
"""Return a list of all agent builds. Filter by hypervisor."""
|
||||
|
|
|
@ -62,7 +62,10 @@ class AssistedVolumeSnapshotsController(wsgi.Controller):
|
|||
raise exc.HTTPBadRequest(explanation=e.format_message())
|
||||
|
||||
@wsgi.response(204)
|
||||
@validation.query_schema(assisted_volume_snapshots.delete_query)
|
||||
@validation.query_schema(assisted_volume_snapshots.delete_query_275,
|
||||
'2.75')
|
||||
@validation.query_schema(assisted_volume_snapshots.delete_query, '2.0',
|
||||
'2.74')
|
||||
@wsgi.expected_errors((400, 404))
|
||||
def delete(self, req, id):
|
||||
"""Delete a snapshot."""
|
||||
|
|
|
@ -35,14 +35,16 @@ class FlavorsController(wsgi.Controller):
|
|||
|
||||
_view_builder_class = flavors_view.ViewBuilder
|
||||
|
||||
@validation.query_schema(schema.index_query)
|
||||
@validation.query_schema(schema.index_query_275, '2.75')
|
||||
@validation.query_schema(schema.index_query, '2.0', '2.74')
|
||||
@wsgi.expected_errors(400)
|
||||
def index(self, req):
|
||||
"""Return all flavors in brief."""
|
||||
limited_flavors = self._get_flavors(req)
|
||||
return self._view_builder.index(req, limited_flavors)
|
||||
|
||||
@validation.query_schema(schema.index_query)
|
||||
@validation.query_schema(schema.index_query_275, '2.75')
|
||||
@validation.query_schema(schema.index_query, '2.0', '2.74')
|
||||
@wsgi.expected_errors(400)
|
||||
def detail(self, req):
|
||||
"""Return all flavors in detail."""
|
||||
|
|
|
@ -50,7 +50,7 @@ class HypervisorsController(wsgi.Controller):
|
|||
self.servicegroup_api = servicegroup.API()
|
||||
|
||||
def _view_hypervisor(self, hypervisor, service, detail, req, servers=None,
|
||||
**kwargs):
|
||||
with_servers=False, **kwargs):
|
||||
alive = self.servicegroup_api.service_is_up(service)
|
||||
# The 2.53 microversion returns the compute node uuid rather than id.
|
||||
uuid_for_id = api_version_request.is_supported(
|
||||
|
@ -89,6 +89,12 @@ class HypervisorsController(wsgi.Controller):
|
|||
if servers:
|
||||
hyp_dict['servers'] = [dict(name=serv['name'], uuid=serv['uuid'])
|
||||
for serv in servers]
|
||||
# The 2.75 microversion adds 'servers' field always in response.
|
||||
# Empty list if there are no servers on hypervisors and it is
|
||||
# requested in request.
|
||||
elif with_servers and api_version_request.is_supported(
|
||||
req, min_version='2.75'):
|
||||
hyp_dict['servers'] = []
|
||||
|
||||
# Add any additional info
|
||||
if kwargs:
|
||||
|
@ -169,7 +175,8 @@ class HypervisorsController(wsgi.Controller):
|
|||
context, hyp.host)
|
||||
hypervisors_list.append(
|
||||
self._view_hypervisor(
|
||||
hyp, service, detail, req, servers=instances))
|
||||
hyp, service, detail, req, servers=instances,
|
||||
with_servers=with_servers))
|
||||
except (exception.ComputeHostNotFound,
|
||||
exception.HostMappingNotFound):
|
||||
# The compute service could be deleted which doesn't delete
|
||||
|
@ -312,7 +319,7 @@ class HypervisorsController(wsgi.Controller):
|
|||
msg = _("Hypervisor with ID '%s' could not be found.") % id
|
||||
raise webob.exc.HTTPNotFound(explanation=msg)
|
||||
return dict(hypervisor=self._view_hypervisor(
|
||||
hyp, service, True, req, instances))
|
||||
hyp, service, True, req, instances, with_servers))
|
||||
|
||||
@wsgi.expected_errors((400, 404, 501))
|
||||
def uptime(self, req, id):
|
||||
|
|
|
@ -160,7 +160,8 @@ class KeypairController(wsgi.Controller):
|
|||
self._delete(req, id)
|
||||
|
||||
@wsgi.Controller.api_version("2.10") # noqa
|
||||
@validation.query_schema(keypairs.delete_query_schema_v210)
|
||||
@validation.query_schema(keypairs.delete_query_schema_v275, '2.75')
|
||||
@validation.query_schema(keypairs.delete_query_schema_v210, '2.10', '2.74')
|
||||
@wsgi.response(204)
|
||||
@wsgi.expected_errors(404)
|
||||
def delete(self, req, id):
|
||||
|
@ -187,7 +188,8 @@ class KeypairController(wsgi.Controller):
|
|||
return user_id
|
||||
|
||||
@wsgi.Controller.api_version("2.10")
|
||||
@validation.query_schema(keypairs.show_query_schema_v210)
|
||||
@validation.query_schema(keypairs.show_query_schema_v275, '2.75')
|
||||
@validation.query_schema(keypairs.show_query_schema_v210, '2.10', '2.74')
|
||||
@wsgi.expected_errors(404)
|
||||
def show(self, req, id):
|
||||
# handle optional user-id for admin only
|
||||
|
@ -230,7 +232,8 @@ class KeypairController(wsgi.Controller):
|
|||
return {'keypair': keypair}
|
||||
|
||||
@wsgi.Controller.api_version("2.35")
|
||||
@validation.query_schema(keypairs.index_query_schema_v235)
|
||||
@validation.query_schema(keypairs.index_query_schema_v275, '2.75')
|
||||
@validation.query_schema(keypairs.index_query_schema_v235, '2.35', '2.74')
|
||||
@wsgi.expected_errors(400)
|
||||
def index(self, req):
|
||||
user_id = self._get_user_id(req)
|
||||
|
|
|
@ -66,7 +66,8 @@ class LimitsController(wsgi.Controller):
|
|||
|
||||
@wsgi.Controller.api_version('2.57') # noqa
|
||||
@wsgi.expected_errors(())
|
||||
@validation.query_schema(limits.limits_query_schema)
|
||||
@validation.query_schema(limits.limits_query_schema_275, '2.75')
|
||||
@validation.query_schema(limits.limits_query_schema, '2.57', '2.74')
|
||||
def index(self, req):
|
||||
return self._index(req, FILTERED_LIMITS_2_57, max_image_meta=False)
|
||||
|
||||
|
|
|
@ -120,7 +120,8 @@ class QuotaSetsController(wsgi.Controller):
|
|||
def show(self, req, id):
|
||||
return self._show(req, id, FILTERED_QUOTAS_2_57)
|
||||
|
||||
@validation.query_schema(quota_sets.query_schema)
|
||||
@validation.query_schema(quota_sets.query_schema_275, '2.75')
|
||||
@validation.query_schema(quota_sets.query_schema, '2.0', '2.74')
|
||||
def _show(self, req, id, filtered_quotas):
|
||||
context = req.environ['nova.context']
|
||||
context.can(qs_policies.POLICY_ROOT % 'show', {'project_id': id})
|
||||
|
@ -148,7 +149,8 @@ class QuotaSetsController(wsgi.Controller):
|
|||
def detail(self, req, id):
|
||||
return self._detail(req, id, FILTERED_QUOTAS_2_57)
|
||||
|
||||
@validation.query_schema(quota_sets.query_schema)
|
||||
@validation.query_schema(quota_sets.query_schema_275, '2.75')
|
||||
@validation.query_schema(quota_sets.query_schema, '2.0', '2.74')
|
||||
def _detail(self, req, id, filtered_quotas):
|
||||
context = req.environ['nova.context']
|
||||
context.can(qs_policies.POLICY_ROOT % 'detail', {'project_id': id})
|
||||
|
@ -179,7 +181,8 @@ class QuotaSetsController(wsgi.Controller):
|
|||
def update(self, req, id, body):
|
||||
return self._update(req, id, body, FILTERED_QUOTAS_2_57)
|
||||
|
||||
@validation.query_schema(quota_sets.query_schema)
|
||||
@validation.query_schema(quota_sets.query_schema_275, '2.75')
|
||||
@validation.query_schema(quota_sets.query_schema, '2.0', '2.74')
|
||||
def _update(self, req, id, body, filtered_quotas):
|
||||
context = req.environ['nova.context']
|
||||
context.can(qs_policies.POLICY_ROOT % 'update', {'project_id': id})
|
||||
|
@ -267,7 +270,8 @@ class QuotaSetsController(wsgi.Controller):
|
|||
# +microversions because the resource quota-set has been deleted completely
|
||||
# when returning a response.
|
||||
@wsgi.expected_errors(())
|
||||
@validation.query_schema(quota_sets.query_schema)
|
||||
@validation.query_schema(quota_sets.query_schema_275, '2.75')
|
||||
@validation.query_schema(quota_sets.query_schema, '2.0', '2.74')
|
||||
@wsgi.response(202)
|
||||
def delete(self, req, id):
|
||||
context = req.environ['nova.context']
|
||||
|
|
|
@ -955,3 +955,22 @@ be raised.
|
|||
There will be also a new policy named
|
||||
``compute:servers:create:requested_destination``. By default,
|
||||
it can be specified by administrators only.
|
||||
|
||||
2.75
|
||||
----
|
||||
|
||||
Multiple API cleanups is done in API microversion 2.75:
|
||||
|
||||
* 400 for unknown param for query param and for request body.
|
||||
|
||||
* Making server representation always consistent among GET, PUT
|
||||
and Rebuild serevr APIs response. ``PUT /servers/{server_id}``
|
||||
and ``POST /servers/{server_id}/action {rebuild}`` API response
|
||||
is modified to add all the missing fields which are return
|
||||
by ``GET /servers/{server_id}``.
|
||||
|
||||
* Change the default return value of swap field from the empty
|
||||
string to 0 (integer) in flavor APIs.
|
||||
|
||||
* Return ``servers`` field always in the response of GET
|
||||
hypervisors API even there are no servers on hypervisor.
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from nova.api.validation import parameter_types
|
||||
|
||||
create = {
|
||||
|
@ -88,7 +91,10 @@ index_query = {
|
|||
},
|
||||
# NOTE(gmann): This is kept True to keep backward compatibility.
|
||||
# As of now Schema validation stripped out the additional parameters and
|
||||
# does not raise 400. In the future, we may block the additional parameters
|
||||
# by bump in Microversion.
|
||||
# does not raise 400. In microversion 2.75, we have blocked the additional
|
||||
# parameters.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
index_query_275 = copy.deepcopy(index_query)
|
||||
index_query_275['additionalProperties'] = False
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from nova.api.validation import parameter_types
|
||||
|
||||
snapshots_create = {
|
||||
|
@ -58,7 +60,10 @@ delete_query = {
|
|||
},
|
||||
# NOTE(gmann): This is kept True to keep backward compatibility.
|
||||
# As of now Schema validation stripped out the additional parameters and
|
||||
# does not raise 400. In the future, we may block the additional parameters
|
||||
# by bump in Microversion.
|
||||
# does not raise 400. In microversion 2.75, we have blocked the additional
|
||||
# parameters.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
delete_query_275 = copy.deepcopy(delete_query)
|
||||
delete_query_275['additionalProperties'] = False
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from nova.api.validation import parameter_types
|
||||
|
||||
# NOTE(takashin): The following sort keys are defined for backward
|
||||
|
@ -39,7 +42,10 @@ index_query = {
|
|||
},
|
||||
# NOTE(gmann): This is kept True to keep backward compatibility.
|
||||
# As of now Schema validation stripped out the additional parameters and
|
||||
# does not raise 400. In the future, we may block the additional parameters
|
||||
# by bump in Microversion.
|
||||
# does not raise 400. In microversion 2.75, we have blocked the additional
|
||||
# parameters.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
index_query_275 = copy.deepcopy(index_query)
|
||||
index_query_275['additionalProperties'] = False
|
||||
|
|
|
@ -44,7 +44,7 @@ index_query = {
|
|||
},
|
||||
# NOTE(gmann): This is kept True to keep backward compatibility.
|
||||
# As of now Schema validation stripped out the additional parameters and
|
||||
# does not raise 400. In the future, we may block the additional parameters
|
||||
# by bump in Microversion.
|
||||
# does not raise 400. This API is deprecated in microversion 2.43 so we
|
||||
# do not to update the additionalProperties to False.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
|
|
@ -105,3 +105,10 @@ show_query_schema_v20 = index_query_schema_v20
|
|||
show_query_schema_v210 = index_query_schema_v210
|
||||
delete_query_schema_v20 = index_query_schema_v20
|
||||
delete_query_schema_v210 = index_query_schema_v210
|
||||
|
||||
index_query_schema_v275 = copy.deepcopy(index_query_schema_v235)
|
||||
index_query_schema_v275['additionalProperties'] = False
|
||||
show_query_schema_v275 = copy.deepcopy(show_query_schema_v210)
|
||||
show_query_schema_v275['additionalProperties'] = False
|
||||
delete_query_schema_v275 = copy.deepcopy(delete_query_schema_v210)
|
||||
delete_query_schema_v275['additionalProperties'] = False
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from nova.api.validation import parameter_types
|
||||
|
||||
|
||||
|
@ -20,5 +22,10 @@ limits_query_schema = {
|
|||
'tenant_id': parameter_types.common_query_param,
|
||||
},
|
||||
# For backward compatible changes
|
||||
# In microversion 2.75, we have blocked the additional
|
||||
# parameters.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
limits_query_schema_275 = copy.deepcopy(limits_query_schema)
|
||||
limits_query_schema_275['additionalProperties'] = False
|
||||
|
|
|
@ -85,7 +85,10 @@ query_schema = {
|
|||
},
|
||||
# NOTE(gmann): This is kept True to keep backward compatibility.
|
||||
# As of now Schema validation stripped out the additional parameters and
|
||||
# does not raise 400. In the future, we may block the additional parameters
|
||||
# by bump in Microversion.
|
||||
# does not raise 400. In microversion 2.75, we have blocked the additional
|
||||
# parameters.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
query_schema_275 = copy.deepcopy(query_schema)
|
||||
query_schema_275['additionalProperties'] = False
|
||||
|
|
|
@ -25,7 +25,7 @@ index_query = {
|
|||
},
|
||||
# NOTE(gmann): This is kept True to keep backward compatibility.
|
||||
# As of now Schema validation stripped out the additional parameters and
|
||||
# does not raise 400. In the future, we may block the additional parameters
|
||||
# by bump in Microversion.
|
||||
# does not raise 400. This API is deprecated in microversion 2.36 so we
|
||||
# do not to update the additionalProperties to False.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
|
|
@ -80,6 +80,10 @@ server_groups_query_param = {
|
|||
'offset': parameter_types.multi_params(
|
||||
parameter_types.non_negative_integer),
|
||||
},
|
||||
# For backward compatible changes
|
||||
# For backward compatible changes. In microversion 2.75, we have
|
||||
# blocked the additional parameters.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
server_groups_query_param_275 = copy.deepcopy(server_groups_query_param)
|
||||
server_groups_query_param_275['additionalProperties'] = False
|
||||
|
|
|
@ -625,6 +625,8 @@ query_params_v21 = {
|
|||
# For backward-compatible additionalProperties is set to be True here.
|
||||
# And we will either strip the extra params out or raise HTTP 400
|
||||
# according to the params' value in the later process.
|
||||
# This has been changed to False in microversion 2.75. From
|
||||
# microversion 2.75, no additional unknown parameter will be allowed.
|
||||
'additionalProperties': True,
|
||||
# Prevent internal-attributes that are started with underscore from
|
||||
# being striped out in schema validation, and raise HTTP 400 in API.
|
||||
|
@ -659,3 +661,22 @@ query_params_v273['properties'].update({
|
|||
'sort_key': multi_params(VALID_SORT_KEYS_V273),
|
||||
'locked': parameter_types.common_query_param,
|
||||
})
|
||||
|
||||
# Microversion 2.75 makes query schema to disallow any invalid or unknown
|
||||
# query parameters (filter or sort keys).
|
||||
# *****Schema updates for microversion 2.75 start here*******
|
||||
query_params_v275 = copy.deepcopy(query_params_v273)
|
||||
# 1. Update sort_keys to allow only valid sort keys:
|
||||
# NOTE(gmann): Remove the ignored sort keys now because 'additionalProperties'
|
||||
# is Flase for query schema. Starting from miceoversion 2.75, API will
|
||||
# raise 400 for any not-allowed sort keys instead of ignoring them.
|
||||
VALID_SORT_KEYS_V275 = copy.deepcopy(VALID_SORT_KEYS_V273)
|
||||
VALID_SORT_KEYS_V275['enum'] = list(
|
||||
set(VALID_SORT_KEYS_V273["enum"]) - set(
|
||||
SERVER_LIST_IGNORE_SORT_KEY_V273))
|
||||
query_params_v275['properties'].update({
|
||||
'sort_key': multi_params(VALID_SORT_KEYS_V275),
|
||||
})
|
||||
# 2. Make 'additionalProperties' False.
|
||||
query_params_v275['additionalProperties'] = False
|
||||
# *****Schema updates for microversion 2.75 end here*******
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from nova.api.validation import parameter_types
|
||||
|
||||
service_update = {
|
||||
|
@ -76,3 +78,6 @@ index_query_schema = {
|
|||
# For backward compatible changes
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
index_query_schema_275 = copy.deepcopy(index_query_schema)
|
||||
index_query_schema_275['additionalProperties'] = False
|
||||
|
|
|
@ -25,8 +25,8 @@ index_query = {
|
|||
},
|
||||
# NOTE(gmann): This is kept True to keep backward compatibility.
|
||||
# As of now Schema validation stripped out the additional parameters and
|
||||
# does not raise 400. In the future, we may block the additional parameters
|
||||
# by bump in Microversion.
|
||||
# does not raise 400. In microversion 2.75, we have blocked the additional
|
||||
# parameters.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,8 @@ show_query = {
|
|||
},
|
||||
# NOTE(gmann): This is kept True to keep backward compatibility.
|
||||
# As of now Schema validation stripped out the additional parameters and
|
||||
# does not raise 400. In the future, we may block the additional parameters
|
||||
# by bump in Microversion.
|
||||
# does not raise 400. In microversion 2.75, we have blocked the additional
|
||||
# parameters.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
|
@ -50,3 +50,9 @@ index_query_v240['properties'].update(
|
|||
show_query_v240 = copy.deepcopy(show_query)
|
||||
show_query_v240['properties'].update(
|
||||
parameter_types.pagination_parameters)
|
||||
|
||||
index_query_275 = copy.deepcopy(index_query_v240)
|
||||
index_query_275['additionalProperties'] = False
|
||||
|
||||
show_query_275 = copy.deepcopy(show_query_v240)
|
||||
show_query_275['additionalProperties'] = False
|
||||
|
|
|
@ -101,9 +101,12 @@ index_query = {
|
|||
},
|
||||
# NOTE(gmann): This is kept True to keep backward compatibility.
|
||||
# As of now Schema validation stripped out the additional parameters and
|
||||
# does not raise 400. In the future, we may block the additional parameters
|
||||
# by bump in Microversion.
|
||||
# does not raise 400. In microversion 2.75, we have blocked the additional
|
||||
# parameters.
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
detail_query = index_query
|
||||
|
||||
index_query_275 = copy.deepcopy(index_query)
|
||||
index_query_275['additionalProperties'] = False
|
||||
|
|
|
@ -148,7 +148,8 @@ class ServerGroupController(wsgi.Controller):
|
|||
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
||||
|
||||
@wsgi.expected_errors(())
|
||||
@validation.query_schema(schema.server_groups_query_param)
|
||||
@validation.query_schema(schema.server_groups_query_param_275, '2.75')
|
||||
@validation.query_schema(schema.server_groups_query_param, '2.0', '2.74')
|
||||
def index(self, req):
|
||||
"""Returns a list of server groups."""
|
||||
context = _authorize_context(req, 'index')
|
||||
|
|
|
@ -108,7 +108,8 @@ class ServersController(wsgi.Controller):
|
|||
self.network_api = network_api.API()
|
||||
|
||||
@wsgi.expected_errors((400, 403))
|
||||
@validation.query_schema(schema_servers.query_params_v273, '2.73')
|
||||
@validation.query_schema(schema_servers.query_params_v275, '2.75')
|
||||
@validation.query_schema(schema_servers.query_params_v273, '2.73', '2.74')
|
||||
@validation.query_schema(schema_servers.query_params_v266, '2.66', '2.72')
|
||||
@validation.query_schema(schema_servers.query_params_v226, '2.26', '2.65')
|
||||
@validation.query_schema(schema_servers.query_params_v21, '2.1', '2.25')
|
||||
|
@ -123,7 +124,8 @@ class ServersController(wsgi.Controller):
|
|||
return servers
|
||||
|
||||
@wsgi.expected_errors((400, 403))
|
||||
@validation.query_schema(schema_servers.query_params_v273, '2.73')
|
||||
@validation.query_schema(schema_servers.query_params_v275, '2.75')
|
||||
@validation.query_schema(schema_servers.query_params_v273, '2.73', '2.74')
|
||||
@validation.query_schema(schema_servers.query_params_v266, '2.66', '2.72')
|
||||
@validation.query_schema(schema_servers.query_params_v226, '2.26', '2.65')
|
||||
@validation.query_schema(schema_servers.query_params_v21, '2.1', '2.25')
|
||||
|
@ -828,19 +830,38 @@ class ServersController(wsgi.Controller):
|
|||
try:
|
||||
instance = self.compute_api.update_instance(ctxt, instance,
|
||||
update_dict)
|
||||
|
||||
# NOTE(gmann): Starting from microversion 2.75, PUT and Rebuild
|
||||
# API response will show all attributes like GET /servers API.
|
||||
show_all_attributes = api_version_request.is_supported(
|
||||
req, min_version='2.75')
|
||||
extend_address = show_all_attributes
|
||||
show_AZ = show_all_attributes
|
||||
show_config_drive = show_all_attributes
|
||||
show_keypair = show_all_attributes
|
||||
show_srv_usg = show_all_attributes
|
||||
show_sec_grp = show_all_attributes
|
||||
show_extended_status = show_all_attributes
|
||||
show_extended_volumes = show_all_attributes
|
||||
# NOTE(gmann): Below attributes need to be added in response
|
||||
# if respective policy allows.So setting these as None
|
||||
# to perform the policy check in view builder.
|
||||
show_extended_attr = None if show_all_attributes else False
|
||||
show_host_status = None if show_all_attributes else False
|
||||
|
||||
return self._view_builder.show(
|
||||
req, instance,
|
||||
extend_address=False,
|
||||
show_AZ=False,
|
||||
show_config_drive=False,
|
||||
show_extended_attr=False,
|
||||
show_host_status=False,
|
||||
show_keypair=False,
|
||||
show_srv_usg=False,
|
||||
show_sec_grp=False,
|
||||
show_extended_status=False,
|
||||
show_extended_volumes=False,
|
||||
show_server_groups=show_server_groups)
|
||||
req, instance,
|
||||
extend_address=extend_address,
|
||||
show_AZ=show_AZ,
|
||||
show_config_drive=show_config_drive,
|
||||
show_extended_attr=show_extended_attr,
|
||||
show_host_status=show_host_status,
|
||||
show_keypair=show_keypair,
|
||||
show_srv_usg=show_srv_usg,
|
||||
show_sec_grp=show_sec_grp,
|
||||
show_extended_status=show_extended_status,
|
||||
show_extended_volumes=show_extended_volumes,
|
||||
show_server_groups=show_server_groups)
|
||||
except exception.InstanceNotFound:
|
||||
msg = _("Instance could not be found")
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
|
@ -1118,17 +1139,40 @@ class ServersController(wsgi.Controller):
|
|||
show_server_groups = api_version_request.is_supported(
|
||||
req, min_version='2.71')
|
||||
|
||||
view = self._view_builder.show(req, instance, extend_address=False,
|
||||
show_AZ=False,
|
||||
show_config_drive=False,
|
||||
show_extended_attr=False,
|
||||
show_host_status=False,
|
||||
show_keypair=show_keypair,
|
||||
show_srv_usg=False,
|
||||
show_sec_grp=False,
|
||||
show_extended_status=False,
|
||||
show_extended_volumes=False,
|
||||
show_server_groups=show_server_groups)
|
||||
# NOTE(gmann): Starting from microversion 2.75, PUT and Rebuild
|
||||
# API response will show all attributes like GET /servers API.
|
||||
show_all_attributes = api_version_request.is_supported(
|
||||
req, min_version='2.75')
|
||||
extend_address = show_all_attributes
|
||||
show_AZ = show_all_attributes
|
||||
show_config_drive = show_all_attributes
|
||||
show_srv_usg = show_all_attributes
|
||||
show_sec_grp = show_all_attributes
|
||||
show_extended_status = show_all_attributes
|
||||
show_extended_volumes = show_all_attributes
|
||||
# NOTE(gmann): Below attributes need to be added in response
|
||||
# if respective policy allows.So setting these as None
|
||||
# to perform the policy check in view builder.
|
||||
show_extended_attr = None if show_all_attributes else False
|
||||
show_host_status = None if show_all_attributes else False
|
||||
|
||||
view = self._view_builder.show(
|
||||
req, instance,
|
||||
extend_address=extend_address,
|
||||
show_AZ=show_AZ,
|
||||
show_config_drive=show_config_drive,
|
||||
show_extended_attr=show_extended_attr,
|
||||
show_host_status=show_host_status,
|
||||
show_keypair=show_keypair,
|
||||
show_srv_usg=show_srv_usg,
|
||||
show_sec_grp=show_sec_grp,
|
||||
show_extended_status=show_extended_status,
|
||||
show_extended_volumes=show_extended_volumes,
|
||||
show_server_groups=show_server_groups,
|
||||
# NOTE(gmann): user_data has been added in response (by code at
|
||||
# the end of this API method) since microversion 2.57 so tell
|
||||
# view builder not to include it.
|
||||
show_user_data=False)
|
||||
|
||||
# Add on the admin_password attribute since the view doesn't do it
|
||||
# unless instance passwords are disabled
|
||||
|
|
|
@ -292,7 +292,8 @@ class ServiceController(wsgi.Controller):
|
|||
explanation = _("Service id %s refers to multiple services.") % id
|
||||
raise webob.exc.HTTPBadRequest(explanation=explanation)
|
||||
|
||||
@validation.query_schema(services.index_query_schema)
|
||||
@validation.query_schema(services.index_query_schema_275, '2.75')
|
||||
@validation.query_schema(services.index_query_schema, '2.0', '2.74')
|
||||
@wsgi.expected_errors(())
|
||||
def index(self, req):
|
||||
"""Return a list of all running services. Filter by host & service
|
||||
|
|
|
@ -263,7 +263,8 @@ class SimpleTenantUsageController(wsgi.Controller):
|
|||
return (period_start, period_stop, detailed)
|
||||
|
||||
@wsgi.Controller.api_version("2.40")
|
||||
@validation.query_schema(schema.index_query_v240)
|
||||
@validation.query_schema(schema.index_query_275, '2.75')
|
||||
@validation.query_schema(schema.index_query_v240, '2.40', '2.74')
|
||||
@wsgi.expected_errors(400)
|
||||
def index(self, req):
|
||||
"""Retrieve tenant_usage for all tenants."""
|
||||
|
@ -277,7 +278,8 @@ class SimpleTenantUsageController(wsgi.Controller):
|
|||
return self._index(req)
|
||||
|
||||
@wsgi.Controller.api_version("2.40")
|
||||
@validation.query_schema(schema.show_query_v240)
|
||||
@validation.query_schema(schema.show_query_275, '2.75')
|
||||
@validation.query_schema(schema.show_query_v240, '2.40', '2.74')
|
||||
@wsgi.expected_errors(400)
|
||||
def show(self, req, id):
|
||||
"""Retrieve tenant_usage for a specified tenant."""
|
||||
|
|
|
@ -70,6 +70,9 @@ class ViewBuilder(common.ViewBuilder):
|
|||
if include_extra_specs:
|
||||
flavor_dict['flavor']['extra_specs'] = flavor.extra_specs
|
||||
|
||||
if api_version_request.is_supported(request, '2.75'):
|
||||
flavor_dict['flavor']['swap'] = flavor["swap"] or 0
|
||||
|
||||
return flavor_dict
|
||||
|
||||
def index(self, request, flavors):
|
||||
|
|
|
@ -88,13 +88,15 @@ class ViewBuilder(common.ViewBuilder):
|
|||
'AUTO' if instance.get('auto_disk_config') else 'MANUAL'),
|
||||
},
|
||||
}
|
||||
self._add_security_grps(request, [server["server"]], [instance])
|
||||
self._add_security_grps(request, [server["server"]], [instance],
|
||||
create_request=True)
|
||||
|
||||
return server
|
||||
|
||||
def basic(self, request, instance, show_extra_specs=False,
|
||||
show_extended_attr=None, show_host_status=None,
|
||||
show_sec_grp=None, bdms=None, cell_down_support=False):
|
||||
show_sec_grp=None, bdms=None, cell_down_support=False,
|
||||
show_user_data=False):
|
||||
"""Generic, non-detailed view of an instance."""
|
||||
if cell_down_support and 'display_name' not in instance:
|
||||
# NOTE(tssurya): If the microversion is >= 2.69, this boolean will
|
||||
|
@ -187,7 +189,8 @@ class ViewBuilder(common.ViewBuilder):
|
|||
show_extended_attr=None, show_host_status=None,
|
||||
show_keypair=True, show_srv_usg=True, show_sec_grp=True,
|
||||
show_extended_status=True, show_extended_volumes=True,
|
||||
bdms=None, cell_down_support=False, show_server_groups=False):
|
||||
bdms=None, cell_down_support=False, show_server_groups=False,
|
||||
show_user_data=True):
|
||||
"""Detailed view of a single instance."""
|
||||
if show_extra_specs is None:
|
||||
# detail will pre-calculate this for us. If we're doing show,
|
||||
|
@ -284,7 +287,15 @@ class ViewBuilder(common.ViewBuilder):
|
|||
# the OS-EXT-SRV-ATTR prefix.
|
||||
properties += ['reservation_id', 'launch_index',
|
||||
'hostname', 'kernel_id', 'ramdisk_id',
|
||||
'root_device_name', 'user_data']
|
||||
'root_device_name']
|
||||
# NOTE(gmann): Since microversion 2.75, PUT and Rebuild
|
||||
# response include all the server attributes including these
|
||||
# extended attributes also. But microversion 2.57 already
|
||||
# adding the 'user_data' in Rebuild response in API method.
|
||||
# so we will skip adding the user data attribute for rebuild
|
||||
# case. 'show_user_data' is false only in case of rebuild.
|
||||
if show_user_data:
|
||||
properties += ['user_data']
|
||||
for attr in properties:
|
||||
if attr == 'name':
|
||||
key = "OS-EXT-SRV-ATTR:instance_%s" % attr
|
||||
|
@ -585,7 +596,8 @@ class ViewBuilder(common.ViewBuilder):
|
|||
if server['id'] in host_statuses:
|
||||
server['host_status'] = host_statuses[server['id']]
|
||||
|
||||
def _add_security_grps(self, req, servers, instances):
|
||||
def _add_security_grps(self, req, servers, instances,
|
||||
create_request=False):
|
||||
if not len(servers):
|
||||
return
|
||||
if not openstack_driver.is_neutron_security_groups():
|
||||
|
@ -597,11 +609,14 @@ class ViewBuilder(common.ViewBuilder):
|
|||
server['security_groups'] = [{"name": group.name}
|
||||
for group in groups]
|
||||
else:
|
||||
# If method is a POST we get the security groups intended for an
|
||||
# instance from the request. The reason for this is if using
|
||||
# neutron security groups the requested security groups for the
|
||||
# instance are not in the db and have not been sent to neutron yet.
|
||||
if req.method != 'POST':
|
||||
# If request is a POST create server we get the security groups
|
||||
# intended for an instance from the request. The reason for this
|
||||
# is if using neutron security groups the requested security
|
||||
# groups for the instance are not in the db and have not been
|
||||
# sent to neutron yet.
|
||||
# Starting from microversion 2.75, security groups is returned in
|
||||
# PUT and POST Rebuild response also.
|
||||
if not create_request:
|
||||
context = req.environ['nova.context']
|
||||
sg_instance_bindings = (
|
||||
self.security_group_api
|
||||
|
@ -612,8 +627,8 @@ class ViewBuilder(common.ViewBuilder):
|
|||
if groups:
|
||||
server['security_groups'] = groups
|
||||
|
||||
# This section is for POST request. There can be only one security
|
||||
# group for POST request.
|
||||
# This section is for POST create server request. There can be
|
||||
# only one security group for POST create server request.
|
||||
else:
|
||||
# try converting to json
|
||||
req_obj = jsonutils.loads(req.body)
|
||||
|
|
|
@ -267,7 +267,8 @@ class VolumeAttachmentController(wsgi.Controller):
|
|||
super(VolumeAttachmentController, self).__init__()
|
||||
|
||||
@wsgi.expected_errors(404)
|
||||
@validation.query_schema(volumes_schema.index_query)
|
||||
@validation.query_schema(volumes_schema.index_query_275, '2.75')
|
||||
@validation.query_schema(volumes_schema.index_query, '2.0', '2.74')
|
||||
def index(self, req, server_id):
|
||||
"""Returns the list of volume attachments for a given instance."""
|
||||
context = req.environ['nova.context']
|
||||
|
|
|
@ -186,8 +186,8 @@ def query_schema(query_params_schema, min_version=None,
|
|||
# out when `additionalProperties=True`. This is for backward
|
||||
# compatible with v2.1 API and legacy v2 API. But it makes the
|
||||
# system more safe for no more unexpected parameters pass down
|
||||
# to the system. In the future, we may block all of those
|
||||
# additional parameters by Microversion.
|
||||
# to the system. In microversion 2.75, we have blocked all of
|
||||
# those additional parameters.
|
||||
_strip_additional_query_parameters(query_params_schema, req)
|
||||
return func(*args, **kwargs)
|
||||
return wrapper
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"flavor": {
|
||||
"name": "%(flavor_name)s",
|
||||
"ram": 1024,
|
||||
"vcpus": 2,
|
||||
"disk": 10,
|
||||
"id": "%(flavor_id)s",
|
||||
"rxtx_factor": 2.0,
|
||||
"description": "test description"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"flavor": {
|
||||
"disk": 10,
|
||||
"id": "%(flavor_id)s",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/%(flavor_id)s",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/%(flavor_id)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "%(flavor_name)s",
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 1024,
|
||||
"vcpus": 2,
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"swap": 0,
|
||||
"rxtx_factor": 2.0,
|
||||
"description": "test description",
|
||||
"extra_specs": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"flavor": {
|
||||
"description": "updated description"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"flavor": {
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 1,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "updated description",
|
||||
"extra_specs": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"flavor": {
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 20,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"id": "%(flavorid)s",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/%(flavorid)s",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/%(flavorid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small.description",
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 2048,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "test description",
|
||||
"extra_specs": {
|
||||
"key1": "value1",
|
||||
"key2": "value2"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
{
|
||||
"flavors": [
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 1,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/1",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 20,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"id": "2",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/2",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/2",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small",
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 2048,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 40,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"id": "3",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/3",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/3",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.medium",
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 4096,
|
||||
"swap": 0,
|
||||
"vcpus": 2,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 80,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"id": "4",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/4",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/4",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.large",
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 8192,
|
||||
"swap": 0,
|
||||
"vcpus": 4,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 160,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"id": "5",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/5",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/5",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.xlarge",
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 16384,
|
||||
"swap": 0,
|
||||
"vcpus": 8,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 1,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"id": "6",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/6",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/6",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny.specs",
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null,
|
||||
"extra_specs": {
|
||||
"hw:mem_page_size": "2048",
|
||||
"hw:cpu_policy": "dedicated"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OS-FLV-DISABLED:disabled": false,
|
||||
"disk": 20,
|
||||
"OS-FLV-EXT-DATA:ephemeral": 0,
|
||||
"id": "%(flavorid)s",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/%(flavorid)s",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/%(flavorid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small.description",
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 2048,
|
||||
"swap": 0,
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "test description",
|
||||
"extra_specs": {
|
||||
"key1": "value1",
|
||||
"key2": "value2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
"flavors": [
|
||||
{
|
||||
"description": null,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny"
|
||||
},
|
||||
{
|
||||
"description": null,
|
||||
"id": "2",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/flavors/2",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/2",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small"
|
||||
},
|
||||
{
|
||||
"description": null,
|
||||
"id": "3",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/flavors/3",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/3",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.medium"
|
||||
},
|
||||
{
|
||||
"description": null,
|
||||
"id": "4",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/flavors/4",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/4",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.large"
|
||||
},
|
||||
{
|
||||
"description": null,
|
||||
"id": "5",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/flavors/5",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/5",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.xlarge"
|
||||
},
|
||||
{
|
||||
"description": null,
|
||||
"id": "6",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/flavors/6",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/6",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny.specs"
|
||||
},
|
||||
{
|
||||
"description": "test description",
|
||||
"id": "7",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/flavors/7",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/flavors/7",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small.description"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
"server": {
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"OS-EXT-AZ:availability_zone": "us-west",
|
||||
"OS-EXT-SRV-ATTR:host": "compute",
|
||||
"OS-EXT-SRV-ATTR:hostname": "new-server-test",
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini",
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
"OS-EXT-SRV-ATTR:kernel_id": "",
|
||||
"OS-EXT-SRV-ATTR:launch_index": 0,
|
||||
"OS-EXT-SRV-ATTR:ramdisk_id": "",
|
||||
"OS-EXT-SRV-ATTR:reservation_id": "%(reservation_id)s",
|
||||
"OS-EXT-SRV-ATTR:root_device_name": "/dev/sda",
|
||||
"OS-EXT-STS:power_state": 1,
|
||||
"OS-EXT-STS:task_state": null,
|
||||
"OS-EXT-STS:vm_state": "active",
|
||||
"OS-SRV-USG:launched_at": "%(strtime)s",
|
||||
"OS-SRV-USG:terminated_at": null,
|
||||
"accessIPv4": "1.2.3.4",
|
||||
"accessIPv6": "80fe::",
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||
"OS-EXT-IPS:type": "fixed",
|
||||
"addr": "192.168.0.3",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"adminPass": "seekr3t",
|
||||
"config_drive": "",
|
||||
"created": "%(isotime)s",
|
||||
"description": null,
|
||||
"flavor": {
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"extra_specs": {},
|
||||
"original_name": "m1.tiny",
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
},
|
||||
"hostId": "2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6",
|
||||
"host_status": "UP",
|
||||
"id": "%(id)s",
|
||||
"image": {
|
||||
"id": "%(uuid)s",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(compute_endpoint)s/images/%(uuid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/servers/%(uuid)s",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/servers/%(id)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"locked": false,
|
||||
"locked_reason": null,
|
||||
"metadata": {
|
||||
"meta_var": "meta_val"
|
||||
},
|
||||
"name": "foobar",
|
||||
"os-extended-volumes:volumes_attached": [],
|
||||
"progress": 0,
|
||||
"security_groups": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
],
|
||||
"server_groups": [],
|
||||
"status": "ACTIVE",
|
||||
"tags": [],
|
||||
"tenant_id": "6f70656e737461636b20342065766572",
|
||||
"trusted_image_certificates": null,
|
||||
"updated": "%(isotime)s",
|
||||
"user_data": "ZWNobyAiaGVsbG8gd29ybGQi",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"rebuild" : {
|
||||
"accessIPv4" : "%(access_ip_v4)s",
|
||||
"accessIPv6" : "%(access_ip_v6)s",
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"imageRef" : "%(uuid)s",
|
||||
"name" : "%(name)s",
|
||||
"adminPass" : "%(pass)s",
|
||||
"metadata" : {
|
||||
"meta_var" : "meta_val"
|
||||
},
|
||||
"user_data": "ZWNobyAiaGVsbG8gd29ybGQi"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"server": {
|
||||
"accessIPv4": "%(access_ip_v4)s",
|
||||
"accessIPv6": "%(access_ip_v6)s",
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"name": "new-server-test",
|
||||
"description": "Sample description"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"server": {
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"OS-EXT-AZ:availability_zone": "us-west",
|
||||
"OS-EXT-SRV-ATTR:host": "compute",
|
||||
"OS-EXT-SRV-ATTR:hostname": "new-server-test",
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini",
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
"OS-EXT-SRV-ATTR:kernel_id": "",
|
||||
"OS-EXT-SRV-ATTR:launch_index": 0,
|
||||
"OS-EXT-SRV-ATTR:ramdisk_id": "",
|
||||
"OS-EXT-SRV-ATTR:reservation_id": "%(reservation_id)s",
|
||||
"OS-EXT-SRV-ATTR:root_device_name": "/dev/sda",
|
||||
"OS-EXT-SRV-ATTR:user_data": "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==",
|
||||
"OS-EXT-STS:power_state": 1,
|
||||
"OS-EXT-STS:task_state": null,
|
||||
"OS-EXT-STS:vm_state": "active",
|
||||
"OS-SRV-USG:launched_at": "%(strtime)s",
|
||||
"OS-SRV-USG:terminated_at": null,
|
||||
"accessIPv4": "%(access_ip_v4)s",
|
||||
"accessIPv6": "%(access_ip_v6)s",
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||
"OS-EXT-IPS:type": "fixed",
|
||||
"addr": "192.168.0.3",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"config_drive": "",
|
||||
"created": "%(isotime)s",
|
||||
"description": "Sample description",
|
||||
"flavor": {
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"extra_specs": {},
|
||||
"original_name": "m1.tiny",
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
},
|
||||
"hostId": "%(hostid)s",
|
||||
"host_status": "UP",
|
||||
"id": "%(id)s",
|
||||
"image": {
|
||||
"id": "%(uuid)s",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(compute_endpoint)s/images/%(uuid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/servers/%(id)s",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/servers/%(id)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"locked": false,
|
||||
"locked_reason": null,
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"os-extended-volumes:volumes_attached": [],
|
||||
"progress": 0,
|
||||
"security_groups": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
],
|
||||
"server_groups": [],
|
||||
"status": "ACTIVE",
|
||||
"tags": [],
|
||||
"tenant_id": "6f70656e737461636b20342065766572",
|
||||
"trusted_image_certificates": null,
|
||||
"updated": "%(isotime)s",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
|
@ -46,3 +46,8 @@ class FlavorManageSampleJsonTests2_55(FlavorManageSampleJsonTests):
|
|||
def test_update_flavor_description(self):
|
||||
response = self._do_put("flavors/1", "flavor-update-req", {})
|
||||
self._verify_response("flavor-update-resp", {}, response, 200)
|
||||
|
||||
|
||||
class FlavorManageSampleJsonTests2_75(FlavorManageSampleJsonTests2_55):
|
||||
microversion = '2.75'
|
||||
scenarios = [('v2_75', {'api_major_version': 'v2.1'})]
|
||||
|
|
|
@ -125,3 +125,11 @@ class FlavorsSampleJsonTest2_61(FlavorsSampleJsonTest):
|
|||
new_flavor.create()
|
||||
self.flavor_show_id = new_flavor_id
|
||||
self.subs = {'flavorid': new_flavor_id}
|
||||
|
||||
|
||||
class FlavorsSampleJsonTest2_75(FlavorsSampleJsonTest2_61):
|
||||
microversion = '2.75'
|
||||
scenarios = [('v2_75', {'api_major_version': 'v2.1'})]
|
||||
|
||||
def test_flavors_list(self):
|
||||
pass
|
||||
|
|
|
@ -623,6 +623,29 @@ class ServersUpdateSampleJson247Test(ServersUpdateSampleJsonTest):
|
|||
scenarios = [('v2_47', {'api_major_version': 'v2.1'})]
|
||||
|
||||
|
||||
class ServersSampleJson275Test(ServersUpdateSampleJsonTest):
|
||||
microversion = '2.75'
|
||||
scenarios = [('v2_75', {'api_major_version': 'v2.1'})]
|
||||
|
||||
def test_server_rebuild(self):
|
||||
uuid = self._post_server()
|
||||
image = fake.get_valid_image_id()
|
||||
params = {
|
||||
'uuid': image,
|
||||
'name': 'foobar',
|
||||
'pass': 'seekr3t',
|
||||
'hostid': '[a-f0-9]+',
|
||||
'access_ip_v4': '1.2.3.4',
|
||||
'access_ip_v6': '80fe::',
|
||||
}
|
||||
|
||||
resp = self._do_post('servers/%s/action' % uuid,
|
||||
'server-action-rebuild', params)
|
||||
subs = params.copy()
|
||||
del subs['uuid']
|
||||
self._verify_response('server-action-rebuild-resp', subs, resp, 202)
|
||||
|
||||
|
||||
class ServerSortKeysJsonTests(ServersSampleBase):
|
||||
sample_dir = 'servers-sort'
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ def fake_agent_build_create(context, values):
|
|||
class AgentsTestV21(test.NoDBTestCase):
|
||||
controller = agents_v21.AgentController()
|
||||
validation_error = exception.ValidationError
|
||||
microversion = '2.1'
|
||||
|
||||
def setUp(self):
|
||||
super(AgentsTestV21, self).setUp()
|
||||
|
@ -93,7 +94,7 @@ class AgentsTestV21(test.NoDBTestCase):
|
|||
self.req = self._get_http_request()
|
||||
|
||||
def _get_http_request(self):
|
||||
return fakes.HTTPRequest.blank('')
|
||||
return fakes.HTTPRequest.blank('', version=self.microversion)
|
||||
|
||||
def test_agents_create(self):
|
||||
body = {'agent': {'hypervisor': 'kvm',
|
||||
|
@ -210,7 +211,8 @@ class AgentsTestV21(test.NoDBTestCase):
|
|||
|
||||
def _test_agents_list(self, query_string=None):
|
||||
req = fakes.HTTPRequest.blank('', use_admin_context=True,
|
||||
query_string=query_string)
|
||||
query_string=query_string,
|
||||
version=self.microversion)
|
||||
res_dict = self.controller.index(req)
|
||||
agents_list = [{'hypervisor': 'kvm', 'os': 'win',
|
||||
'architecture': 'x86',
|
||||
|
@ -244,7 +246,8 @@ class AgentsTestV21(test.NoDBTestCase):
|
|||
|
||||
def test_agents_list_with_hypervisor(self):
|
||||
req = fakes.HTTPRequest.blank('', use_admin_context=True,
|
||||
query_string='hypervisor=kvm')
|
||||
query_string='hypervisor=kvm',
|
||||
version=self.microversion)
|
||||
res_dict = self.controller.index(req)
|
||||
response = [{'hypervisor': 'kvm', 'os': 'win',
|
||||
'architecture': 'x86',
|
||||
|
@ -264,7 +267,8 @@ class AgentsTestV21(test.NoDBTestCase):
|
|||
def test_agents_list_with_multi_hypervisor_filter(self):
|
||||
query_string = 'hypervisor=xen&hypervisor=kvm'
|
||||
req = fakes.HTTPRequest.blank('', use_admin_context=True,
|
||||
query_string=query_string)
|
||||
query_string=query_string,
|
||||
version=self.microversion)
|
||||
res_dict = self.controller.index(req)
|
||||
response = [{'hypervisor': 'kvm', 'os': 'win',
|
||||
'architecture': 'x86',
|
||||
|
@ -283,13 +287,15 @@ class AgentsTestV21(test.NoDBTestCase):
|
|||
|
||||
def test_agents_list_query_allow_negative_int_as_string(self):
|
||||
req = fakes.HTTPRequest.blank('', use_admin_context=True,
|
||||
query_string='hypervisor=-1')
|
||||
query_string='hypervisor=-1',
|
||||
version=self.microversion)
|
||||
res_dict = self.controller.index(req)
|
||||
self.assertEqual(res_dict, {'agents': []})
|
||||
|
||||
def test_agents_list_query_allow_int_as_string(self):
|
||||
req = fakes.HTTPRequest.blank('', use_admin_context=True,
|
||||
query_string='hypervisor=1')
|
||||
query_string='hypervisor=1',
|
||||
version=self.microversion)
|
||||
res_dict = self.controller.index(req)
|
||||
self.assertEqual(res_dict, {'agents': []})
|
||||
|
||||
|
@ -300,7 +306,8 @@ class AgentsTestV21(test.NoDBTestCase):
|
|||
def test_agents_list_with_hypervisor_and_additional_filter(self):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'', use_admin_context=True,
|
||||
query_string='hypervisor=kvm&additional_filter=abc')
|
||||
query_string='hypervisor=kvm&additional_filter=abc',
|
||||
version=self.microversion)
|
||||
res_dict = self.controller.index(req)
|
||||
response = [{'hypervisor': 'kvm', 'os': 'win',
|
||||
'architecture': 'x86',
|
||||
|
@ -397,6 +404,33 @@ class AgentsTestV21(test.NoDBTestCase):
|
|||
self.controller.update, self.req, 1, body=body)
|
||||
|
||||
|
||||
class AgentsTestV275(AgentsTestV21):
|
||||
microversion = '2.75'
|
||||
|
||||
def test_agents_list_additional_filter_old_version(self):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'', use_admin_context=True,
|
||||
query_string='additional_filter=abc',
|
||||
version='2.74')
|
||||
self.controller.index(req)
|
||||
|
||||
def test_agents_list_with_unknown_filter(self):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'', use_admin_context=True,
|
||||
query_string='unknown_filter=abc',
|
||||
version=self.microversion)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.controller.index, req)
|
||||
|
||||
def test_agents_list_with_hypervisor_and_additional_filter(self):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'', use_admin_context=True,
|
||||
query_string='hypervisor=kvm&additional_filter=abc',
|
||||
version=self.microversion)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.controller.index, req)
|
||||
|
||||
|
||||
class AgentsPolicyEnforcementV21(test.NoDBTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
|
|
@ -44,6 +44,20 @@ def fake_create(newflavor):
|
|||
newflavor["disabled"] = False
|
||||
|
||||
|
||||
def fake_create_without_swap(newflavor):
|
||||
newflavor['flavorid'] = 1234
|
||||
newflavor["name"] = 'test'
|
||||
newflavor["memory_mb"] = 512
|
||||
newflavor["vcpus"] = 2
|
||||
newflavor["root_gb"] = 1
|
||||
newflavor["ephemeral_gb"] = 1
|
||||
newflavor["swap"] = 0
|
||||
newflavor["rxtx_factor"] = 1.0
|
||||
newflavor["is_public"] = True
|
||||
newflavor["disabled"] = False
|
||||
newflavor["extra_specs"] = {"key1": "value1"}
|
||||
|
||||
|
||||
class FlavorManageTestV21(test.NoDBTestCase):
|
||||
controller = flavormanage_v21.FlavorManageController()
|
||||
validation_error = exception.ValidationError
|
||||
|
@ -128,10 +142,11 @@ class FlavorManageTestV21(test.NoDBTestCase):
|
|||
def test_create_missing_disk(self):
|
||||
self._test_create_missing_parameter('disk')
|
||||
|
||||
def _create_flavor_success_case(self, body, req=None):
|
||||
def _create_flavor_success_case(self, body, req=None, version=None):
|
||||
req = req if req else self._get_http_request(url=self.base_url)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.headers['X-OpenStack-Nova-API-Version'] = self.microversion
|
||||
req.headers['X-OpenStack-Nova-API-Version'] = (
|
||||
version or self.microversion)
|
||||
req.method = 'POST'
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
res = req.get_response(self.app)
|
||||
|
@ -466,6 +481,71 @@ class FlavorManageTestV2_61(FlavorManageTestV2_55):
|
|||
self.assertEqual({"key1": "value1"}, flavor['extra_specs'])
|
||||
|
||||
|
||||
class FlavorManageTestV2_75(FlavorManageTestV2_61):
|
||||
microversion = '2.75'
|
||||
|
||||
FLAVOR_WITH_NO_SWAP = objects.Flavor(
|
||||
name='test',
|
||||
memory_mb=512,
|
||||
vcpus=2,
|
||||
root_gb=1,
|
||||
ephemeral_gb=1,
|
||||
flavorid=1234,
|
||||
rxtx_factor=1.0,
|
||||
disabled=False,
|
||||
is_public=True,
|
||||
swap=0,
|
||||
extra_specs={"key1": "value1"}
|
||||
)
|
||||
|
||||
def test_create_flavor_default_swap_value_old_version(self):
|
||||
self.stub_out("nova.objects.Flavor.create", fake_create_without_swap)
|
||||
del self.request_body['flavor']['swap']
|
||||
resp = self._create_flavor_success_case(self.request_body,
|
||||
version='2.74')
|
||||
self.assertEqual(resp['flavor']['swap'], "")
|
||||
|
||||
@mock.patch('nova.objects.Flavor.get_by_flavor_id')
|
||||
@mock.patch('nova.objects.Flavor.save')
|
||||
def test_update_flavor_default_swap_value_old_version(self, mock_save,
|
||||
mock_get):
|
||||
self.stub_out("nova.objects.Flavor.create", fake_create_without_swap)
|
||||
del self.request_body['flavor']['swap']
|
||||
flavor = self._create_flavor_success_case(self.request_body,
|
||||
version='2.74')['flavor']
|
||||
mock_get.return_value = self.FLAVOR_WITH_NO_SWAP
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/fake/flavors',
|
||||
version='2.74')
|
||||
req.method = 'PUT'
|
||||
response = self.controller._update(
|
||||
req, flavor['id'],
|
||||
body={'flavor': {'description': None}})['flavor']
|
||||
self.assertEqual(response['swap'], '')
|
||||
|
||||
@mock.patch('nova.objects.FlavorList.get_all')
|
||||
def test_create_flavor_default_swap_value(self, mock_get):
|
||||
self.stub_out("nova.objects.Flavor.create", fake_create_without_swap)
|
||||
del self.request_body['flavor']['swap']
|
||||
resp = self._create_flavor_success_case(self.request_body)
|
||||
self.assertEqual(resp['flavor']['swap'], 0)
|
||||
|
||||
@mock.patch('nova.objects.Flavor.get_by_flavor_id')
|
||||
@mock.patch('nova.objects.Flavor.save')
|
||||
def test_update_flavor_default_swap_value(self, mock_save, mock_get):
|
||||
self.stub_out("nova.objects.Flavor.create", fake_create_without_swap)
|
||||
del self.request_body['flavor']['swap']
|
||||
mock_get.return_value = self.FLAVOR_WITH_NO_SWAP
|
||||
flavor = self._create_flavor_success_case(self.request_body)['flavor']
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/fake/flavors',
|
||||
version=self.microversion)
|
||||
response = self.controller._update(
|
||||
req, flavor['id'],
|
||||
body={'flavor': {'description': None}})['flavor']
|
||||
self.assertEqual(response['swap'], 0)
|
||||
|
||||
|
||||
class PrivateFlavorManageTestV21(test.TestCase):
|
||||
controller = flavormanage_v21.FlavorManageController()
|
||||
base_url = '/v2/fake/flavors'
|
||||
|
|
|
@ -619,7 +619,7 @@ class FlavorsTestV21(test.TestCase):
|
|||
'/flavors/detail', expected)
|
||||
|
||||
def _test_list_flavors_with_allowed_filter(
|
||||
self, url, expected=None):
|
||||
self, url, expected=None, req=None):
|
||||
controller_list = self.controller.index
|
||||
if 'detail' in url:
|
||||
controller_list = self.controller.detail
|
||||
|
@ -647,7 +647,7 @@ class FlavorsTestV21(test.TestCase):
|
|||
if 'detail' in url and self.expect_extra_specs:
|
||||
expected_resp[0]['extra_specs'] = (
|
||||
fakes.FLAVORS['2'].extra_specs)
|
||||
req = self._build_request(url + '&limit=1&marker=1')
|
||||
req = req or self._build_request(url + '&limit=1&marker=1')
|
||||
result = controller_list(req)
|
||||
self.assertEqual(expected_resp, result['flavors'])
|
||||
|
||||
|
@ -791,6 +791,110 @@ class FlavorsTestV2_61(FlavorsTestV2_55):
|
|||
expect_extra_specs = True
|
||||
|
||||
|
||||
class FlavorsTestV2_75(FlavorsTestV2_61):
|
||||
microversion = '2.75'
|
||||
|
||||
FLAVOR_WITH_NO_SWAP = objects.Flavor(
|
||||
id=1,
|
||||
name='flavor 1',
|
||||
memory_mb=256,
|
||||
vcpus=1,
|
||||
root_gb=10,
|
||||
ephemeral_gb=20,
|
||||
flavorid='1',
|
||||
rxtx_factor=1.0,
|
||||
vcpu_weight=None,
|
||||
disabled=False,
|
||||
is_public=True,
|
||||
swap=0,
|
||||
description=None,
|
||||
extra_specs={"key1": "value1", "key2": "value2"}
|
||||
)
|
||||
|
||||
def test_list_flavors_with_additional_filter_old_version(self):
|
||||
req = self.fake_request.blank(
|
||||
'/fake/flavors?limit=1&marker=1&additional=something',
|
||||
version='2.74')
|
||||
self._test_list_flavors_with_allowed_filter(
|
||||
'/fake/flavors?limit=1&marker=1&additional=something', req=req)
|
||||
|
||||
def test_list_detail_flavors_with_additional_filter_old_version(self):
|
||||
expected = {
|
||||
"ram": fakes.FLAVORS['2'].memory_mb,
|
||||
"disk": fakes.FLAVORS['2'].root_gb,
|
||||
"vcpus": fakes.FLAVORS['2'].vcpus,
|
||||
"os-flavor-access:is_public": True,
|
||||
"rxtx_factor": '',
|
||||
"OS-FLV-EXT-DATA:ephemeral": fakes.FLAVORS['2'].ephemeral_gb,
|
||||
"OS-FLV-DISABLED:disabled": fakes.FLAVORS['2'].disabled,
|
||||
"swap": fakes.FLAVORS['2'].swap
|
||||
}
|
||||
req = self.fake_request.blank(
|
||||
'/fake/flavors?limit=1&marker=1&additional=something',
|
||||
version='2.74')
|
||||
self._test_list_flavors_with_allowed_filter(
|
||||
'/fake/flavors/detail?limit=1&marker=1&additional=something',
|
||||
expected, req=req)
|
||||
|
||||
def _test_list_flavors_with_additional_filter(self, url):
|
||||
controller_list = self.controller.index
|
||||
if 'detail' in url:
|
||||
controller_list = self.controller.detail
|
||||
req = self._build_request(url)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
controller_list, req)
|
||||
|
||||
def test_list_flavors_with_additional_filter(self):
|
||||
self._test_list_flavors_with_additional_filter(
|
||||
'/flavors?limit=1&marker=1&additional=something')
|
||||
|
||||
def test_list_detail_flavors_with_additional_filter(self):
|
||||
self._test_list_flavors_with_additional_filter(
|
||||
'/flavors/detail?limit=1&marker=1&additional=something')
|
||||
|
||||
@mock.patch('nova.objects.FlavorList.get_all')
|
||||
def test_list_flavor_detail_default_swap_value_old_version(self, mock_get):
|
||||
mock_get.return_value = objects.FlavorList(
|
||||
objects=[self.FLAVOR_WITH_NO_SWAP])
|
||||
req = self.fake_request.blank(
|
||||
'/fake/flavors/detail?limit=1',
|
||||
version='2.74')
|
||||
response = self.controller.detail(req)
|
||||
response_list = response["flavors"]
|
||||
self.assertEqual(response_list[0]['swap'], "")
|
||||
|
||||
@mock.patch('nova.objects.Flavor.get_by_flavor_id')
|
||||
def test_show_flavor_default_swap_value_old_version(self, mock_get):
|
||||
mock_get.return_value = self.FLAVOR_WITH_NO_SWAP
|
||||
req = self.fake_request.blank(
|
||||
'/fake/flavors/detail?limit=1',
|
||||
version='2.74')
|
||||
response = self.controller.show(req, 1)
|
||||
response_list = response["flavor"]
|
||||
self.assertEqual(response_list['swap'], "")
|
||||
|
||||
@mock.patch('nova.objects.FlavorList.get_all')
|
||||
def test_list_flavor_detail_default_swap_value(self, mock_get):
|
||||
mock_get.return_value = objects.FlavorList(
|
||||
objects=[self.FLAVOR_WITH_NO_SWAP])
|
||||
req = self.fake_request.blank(
|
||||
'/fake/flavors/detail?limit=1',
|
||||
version=self.microversion)
|
||||
response = self.controller.detail(req)
|
||||
response_list = response["flavors"]
|
||||
self.assertEqual(response_list[0]['swap'], 0)
|
||||
|
||||
@mock.patch('nova.objects.Flavor.get_by_flavor_id')
|
||||
def test_show_flavor_default_swap_value(self, mock_get):
|
||||
mock_get.return_value = self.FLAVOR_WITH_NO_SWAP
|
||||
req = self.fake_request.blank(
|
||||
'/fake/flavors/detail?limit=1',
|
||||
version=self.microversion)
|
||||
response = self.controller.show(req, 1)
|
||||
response_list = response["flavor"]
|
||||
self.assertEqual(response_list['swap'], 0)
|
||||
|
||||
|
||||
class DisabledFlavorsWithRealDBTestV21(test.TestCase):
|
||||
"""Tests that disabled flavors should not be shown nor listed."""
|
||||
Controller = flavors_v21.FlavorsController
|
||||
|
|
|
@ -1387,3 +1387,53 @@ class HypervisorsTestV253(HypervisorsTestV252):
|
|||
uuids.hyper1)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.controller.show, req, uuids.hyper1)
|
||||
|
||||
|
||||
class HypervisorsTestV275(HypervisorsTestV253):
|
||||
api_version = '2.75'
|
||||
|
||||
def _test_servers_with_no_server(self, func, version=None, **kwargs):
|
||||
"""Tests GET APIs return 'servers' field in response even
|
||||
no servers on hypervisors.
|
||||
"""
|
||||
with mock.patch.object(self.controller.host_api,
|
||||
'instance_get_all_by_host',
|
||||
return_value=[]):
|
||||
req = fakes.HTTPRequest.blank('/os-hypervisors?with_servers=1',
|
||||
use_admin_context=True,
|
||||
version=version or self.api_version)
|
||||
result = func(req, **kwargs)
|
||||
return result
|
||||
|
||||
def test_list_servers_with_no_server_old_version(self):
|
||||
result = self._test_servers_with_no_server(self.controller.index,
|
||||
version='2.74')
|
||||
for hyper in result['hypervisors']:
|
||||
self.assertNotIn('servers', hyper)
|
||||
|
||||
def test_list_detail_servers_with_no_server_old_version(self):
|
||||
result = self._test_servers_with_no_server(self.controller.detail,
|
||||
version='2.74')
|
||||
for hyper in result['hypervisors']:
|
||||
self.assertNotIn('servers', hyper)
|
||||
|
||||
def test_show_servers_with_no_server_old_version(self):
|
||||
result = self._test_servers_with_no_server(self.controller.show,
|
||||
version='2.74',
|
||||
id=uuids.hyper1)
|
||||
self.assertNotIn('servers', result['hypervisor'])
|
||||
|
||||
def test_servers_with_no_server(self):
|
||||
result = self._test_servers_with_no_server(self.controller.index)
|
||||
for hyper in result['hypervisors']:
|
||||
self.assertEqual(0, len(hyper['servers']))
|
||||
|
||||
def test_list_detail_servers_with_empty_server_list(self):
|
||||
result = self._test_servers_with_no_server(self.controller.detail)
|
||||
for hyper in result['hypervisors']:
|
||||
self.assertEqual(0, len(hyper['servers']))
|
||||
|
||||
def test_show_servers_with_empty_server_list(self):
|
||||
result = self._test_servers_with_no_server(self.controller.show,
|
||||
id=uuids.hyper1)
|
||||
self.assertEqual(0, len(result['hypervisor']['servers']))
|
||||
|
|
|
@ -605,3 +605,43 @@ class KeypairsTestV235(test.TestCase):
|
|||
mock_kp_get.assert_called_once_with(
|
||||
req.environ['nova.context'], 'fake_user',
|
||||
limit=None, marker=None)
|
||||
|
||||
|
||||
class KeypairsTestV275(test.TestCase):
|
||||
def setUp(self):
|
||||
super(KeypairsTestV275, self).setUp()
|
||||
self.controller = keypairs_v21.KeypairController()
|
||||
|
||||
@mock.patch("nova.db.api.key_pair_get_all_by_user")
|
||||
@mock.patch('nova.objects.KeyPair.get_by_name')
|
||||
def test_keypair_list_additional_param_old_version(self, mock_get_by_name,
|
||||
mock_kp_get):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/os-keypairs?unknown=3',
|
||||
version='2.74', use_admin_context=True)
|
||||
self.controller.index(req)
|
||||
self.controller.show(req, 1)
|
||||
with mock.patch.object(self.controller.api,
|
||||
'delete_key_pair'):
|
||||
self.controller.delete(req, 1)
|
||||
|
||||
def test_keypair_list_additional_param(self):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/os-keypairs?unknown=3',
|
||||
version='2.75', use_admin_context=True)
|
||||
self.assertRaises(exception.ValidationError, self.controller.index,
|
||||
req)
|
||||
|
||||
def test_keypair_show_additional_param(self):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/os-keypairs?unknown=3',
|
||||
version='2.75', use_admin_context=True)
|
||||
self.assertRaises(exception.ValidationError, self.controller.show,
|
||||
req, 1)
|
||||
|
||||
def test_keypair_delete_additional_param(self):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/os-keypairs?unknown=3',
|
||||
version='2.75', use_admin_context=True)
|
||||
self.assertRaises(exception.ValidationError, self.controller.delete,
|
||||
req, 1)
|
||||
|
|
|
@ -492,3 +492,32 @@ class LimitsControllerTestV239(BaseLimitTestSuite):
|
|||
},
|
||||
}
|
||||
self.assertEqual(expected_response, response)
|
||||
|
||||
|
||||
class LimitsControllerTestV275(BaseLimitTestSuite):
|
||||
def setUp(self):
|
||||
super(LimitsControllerTestV275, self).setUp()
|
||||
self.controller = limits_v21.LimitsController()
|
||||
|
||||
def test_index_additional_query_param_old_version(self):
|
||||
absolute_limits = {
|
||||
"metadata_items": 1,
|
||||
}
|
||||
req = fakes.HTTPRequest.blank("/?unkown=fake",
|
||||
version='2.74')
|
||||
|
||||
def _get_project_quotas(context, project_id, usages=True):
|
||||
return {k: dict(limit=v, in_use=v // 2)
|
||||
for k, v in absolute_limits.items()}
|
||||
|
||||
with mock.patch('nova.quota.QUOTAS.get_project_quotas') as \
|
||||
get_project_quotas:
|
||||
get_project_quotas.side_effect = _get_project_quotas
|
||||
self.controller.index(req)
|
||||
|
||||
def test_index_additional_query_param(self):
|
||||
req = fakes.HTTPRequest.blank("/?unkown=fake",
|
||||
version='2.75')
|
||||
self.assertRaises(
|
||||
exception.ValidationError,
|
||||
self.controller.index, req=req)
|
||||
|
|
|
@ -675,3 +675,53 @@ class QuotaSetsTestV257(QuotaSetsTestV236):
|
|||
def setUp(self):
|
||||
super(QuotaSetsTestV257, self).setUp()
|
||||
self.filtered_quotas.extend(quotas_v21.FILTERED_QUOTAS_2_57)
|
||||
|
||||
|
||||
class QuotaSetsTestV275(QuotaSetsTestV257):
|
||||
microversion = '2.75'
|
||||
|
||||
@mock.patch('nova.objects.Quotas.destroy_all_by_project')
|
||||
@mock.patch('nova.objects.Quotas.create_limit')
|
||||
@mock.patch('nova.quota.QUOTAS.get_settable_quotas')
|
||||
@mock.patch('nova.quota.QUOTAS.get_project_quotas')
|
||||
def test_quota_additional_filter_older_version(self, mock_quotas,
|
||||
mock_settable,
|
||||
mock_create_limit,
|
||||
mock_destroy):
|
||||
mock_quotas.return_value = self.quotas
|
||||
mock_settable.return_value = {'cores': {'maximum': -1, 'minimum': 0}}
|
||||
query_string = 'additional_filter=2'
|
||||
req = fakes.HTTPRequest.blank('', version='2.74',
|
||||
query_string=query_string)
|
||||
self.controller.show(req, 1234)
|
||||
self.controller.update(req, 1234, body={'quota_set': {}})
|
||||
self.controller.detail(req, 1234)
|
||||
self.controller.delete(req, 1234)
|
||||
|
||||
def test_quota_update_additional_filter(self):
|
||||
query_string = 'user_id=1&additional_filter=2'
|
||||
req = fakes.HTTPRequest.blank('', version=self.microversion,
|
||||
query_string=query_string)
|
||||
self.assertRaises(exception.ValidationError, self.controller.update,
|
||||
req, 'update_me', body={'quota_set': {}})
|
||||
|
||||
def test_quota_show_additional_filter(self):
|
||||
query_string = 'user_id=1&additional_filter=2'
|
||||
req = fakes.HTTPRequest.blank('', version=self.microversion,
|
||||
query_string=query_string)
|
||||
self.assertRaises(exception.ValidationError, self.controller.show,
|
||||
req, 1234)
|
||||
|
||||
def test_quota_detail_additional_filter(self):
|
||||
query_string = 'user_id=1&additional_filter=2'
|
||||
req = fakes.HTTPRequest.blank('', version=self.microversion,
|
||||
query_string=query_string)
|
||||
self.assertRaises(exception.ValidationError, self.controller.detail,
|
||||
req, 1234)
|
||||
|
||||
def test_quota_delete_additional_filter(self):
|
||||
query_string = 'user_id=1&additional_filter=2'
|
||||
req = fakes.HTTPRequest.blank('', version=self.microversion,
|
||||
query_string=query_string)
|
||||
self.assertRaises(exception.ValidationError, self.controller.delete,
|
||||
req, 1234)
|
||||
|
|
|
@ -84,6 +84,7 @@ def server_group_db(sg):
|
|||
class ServerGroupTestV21(test.NoDBTestCase):
|
||||
USES_DB_SELF = True
|
||||
validation_error = exception.ValidationError
|
||||
wsgi_api_version = '2.1'
|
||||
|
||||
def setUp(self):
|
||||
super(ServerGroupTestV21, self).setUp()
|
||||
|
@ -306,7 +307,7 @@ class ServerGroupTestV21(test.NoDBTestCase):
|
|||
|
||||
mock_get_by_project.return_value = return_tenant_server_groups()
|
||||
|
||||
path = '/os-server-groups?all_projects=True'
|
||||
path = path or '/os-server-groups?all_projects=True'
|
||||
if limited:
|
||||
path += limited
|
||||
req = fakes.HTTPRequest.blank(path, version=api_version)
|
||||
|
@ -548,16 +549,19 @@ class ServerGroupTestV21(test.NoDBTestCase):
|
|||
self.controller.create, self.req, body=body)
|
||||
|
||||
def test_list_server_group_by_tenant(self):
|
||||
self._test_list_server_group_by_tenant(api_version='2.1')
|
||||
self._test_list_server_group_by_tenant(
|
||||
api_version=self.wsgi_api_version)
|
||||
|
||||
def test_list_server_group_all_v20(self):
|
||||
self._test_list_server_group_all(api_version='2.0')
|
||||
|
||||
def test_list_server_group_all(self):
|
||||
self._test_list_server_group_all(api_version='2.1')
|
||||
self._test_list_server_group_all(
|
||||
api_version=self.wsgi_api_version)
|
||||
|
||||
def test_list_server_group_offset_and_limit(self):
|
||||
self._test_list_server_group_offset_and_limit(api_version='2.1')
|
||||
self._test_list_server_group_offset_and_limit(
|
||||
api_version=self.wsgi_api_version)
|
||||
|
||||
def test_list_server_groups_rbac_default(self):
|
||||
# test as admin
|
||||
|
@ -567,59 +571,59 @@ class ServerGroupTestV21(test.NoDBTestCase):
|
|||
self.controller.index(self.req)
|
||||
|
||||
def test_list_server_group_multiple_param(self):
|
||||
self._test_list_server_group(api_version='2.1',
|
||||
self._test_list_server_group(api_version=self.wsgi_api_version,
|
||||
limited='&offset=2&limit=2&limit=1&offset=1',
|
||||
path='/os-server-groups?all_projects=False&all_projects=True')
|
||||
|
||||
def test_list_server_group_additional_param(self):
|
||||
self._test_list_server_group(api_version='2.1',
|
||||
self._test_list_server_group(api_version=self.wsgi_api_version,
|
||||
limited='&offset=1&limit=1',
|
||||
path='/os-server-groups?dummy=False&all_projects=True')
|
||||
|
||||
def test_list_server_group_param_as_int(self):
|
||||
self._test_list_server_group(api_version='2.1',
|
||||
self._test_list_server_group(api_version=self.wsgi_api_version,
|
||||
limited='&offset=1&limit=1',
|
||||
path='/os-server-groups?all_projects=1')
|
||||
|
||||
def test_list_server_group_negative_int_as_offset(self):
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self._test_list_server_group,
|
||||
api_version='2.1',
|
||||
api_version=self.wsgi_api_version,
|
||||
limited='&offset=-1',
|
||||
path='/os-server-groups?all_projects=1')
|
||||
|
||||
def test_list_server_group_string_int_as_offset(self):
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self._test_list_server_group,
|
||||
api_version='2.1',
|
||||
api_version=self.wsgi_api_version,
|
||||
limited='&offset=dummy',
|
||||
path='/os-server-groups?all_projects=1')
|
||||
|
||||
def test_list_server_group_multiparam_string_as_offset(self):
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self._test_list_server_group,
|
||||
api_version='2.1',
|
||||
api_version=self.wsgi_api_version,
|
||||
limited='&offset=dummy&offset=1',
|
||||
path='/os-server-groups?all_projects=1')
|
||||
|
||||
def test_list_server_group_negative_int_as_limit(self):
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self._test_list_server_group,
|
||||
api_version='2.1',
|
||||
api_version=self.wsgi_api_version,
|
||||
limited='&limit=-1',
|
||||
path='/os-server-groups?all_projects=1')
|
||||
|
||||
def test_list_server_group_string_int_as_limit(self):
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self._test_list_server_group,
|
||||
api_version='2.1',
|
||||
api_version=self.wsgi_api_version,
|
||||
limited='&limit=dummy',
|
||||
path='/os-server-groups?all_projects=1')
|
||||
|
||||
def test_list_server_group_multiparam_string_as_limit(self):
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self._test_list_server_group,
|
||||
api_version='2.1',
|
||||
api_version=self.wsgi_api_version,
|
||||
limited='&limit=dummy&limit=1',
|
||||
path='/os-server-groups?all_projects=1')
|
||||
|
||||
|
@ -848,3 +852,18 @@ class ServerGroupTestV264(ServerGroupTestV213):
|
|||
sgroup = server_group_template(unknown='unknown')
|
||||
self.assertRaises(self.validation_error, self.controller.create,
|
||||
req, body={'server_group': sgroup})
|
||||
|
||||
|
||||
class ServerGroupTestV275(ServerGroupTestV264):
|
||||
wsgi_api_version = '2.75'
|
||||
|
||||
def test_list_server_group_additional_param_old_version(self):
|
||||
self._test_list_server_group(api_version='2.74',
|
||||
limited='&offset=1&limit=1',
|
||||
path='/os-server-groups?dummy=False&all_projects=True')
|
||||
|
||||
def test_list_server_group_additional_param(self):
|
||||
req = fakes.HTTPRequest.blank('/os-server-groups?dummy=False',
|
||||
version=self.wsgi_api_version)
|
||||
self.assertRaises(self.validation_error, self.controller.index,
|
||||
req)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# under the License.
|
||||
|
||||
import collections
|
||||
import copy
|
||||
import datetime
|
||||
import ddt
|
||||
|
||||
|
@ -39,6 +40,7 @@ from nova.api.openstack import api_version_request
|
|||
from nova.api.openstack import common
|
||||
from nova.api.openstack import compute
|
||||
from nova.api.openstack.compute import ips
|
||||
from nova.api.openstack.compute.schemas import servers as servers_schema
|
||||
from nova.api.openstack.compute import servers
|
||||
from nova.api.openstack.compute import views
|
||||
from nova.api.openstack import wsgi as os_wsgi
|
||||
|
@ -83,6 +85,23 @@ UUID2 = '00000000-0000-0000-0000-000000000002'
|
|||
INSTANCE_IDS = {FAKE_UUID: 1}
|
||||
FIELDS = instance_obj.INSTANCE_DEFAULT_FIELDS
|
||||
|
||||
GET_ONLY_FIELDS = ['OS-EXT-AZ:availability_zone', 'config_drive',
|
||||
'OS-EXT-SRV-ATTR:host',
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname',
|
||||
'OS-EXT-SRV-ATTR:instance_name',
|
||||
'OS-EXT-SRV-ATTR:hostname',
|
||||
'OS-EXT-SRV-ATTR:kernel_id',
|
||||
'OS-EXT-SRV-ATTR:launch_index',
|
||||
'OS-EXT-SRV-ATTR:ramdisk_id',
|
||||
'OS-EXT-SRV-ATTR:reservation_id',
|
||||
'OS-EXT-SRV-ATTR:root_device_name',
|
||||
'OS-EXT-SRV-ATTR:user_data', 'host_status',
|
||||
'key_name', 'OS-SRV-USG:launched_at',
|
||||
'OS-SRV-USG:terminated_at',
|
||||
'OS-EXT-STS:task_state', 'OS-EXT-STS:vm_state',
|
||||
'OS-EXT-STS:power_state', 'security_groups',
|
||||
'os-extended-volumes:volumes_attached']
|
||||
|
||||
|
||||
def instance_update_and_get_original(context, instance_uuid, values,
|
||||
columns_to_join=None,
|
||||
|
@ -2655,6 +2674,128 @@ class ServersControllerTestV273(ControllerTest):
|
|||
cell_down_support=False, all_tenants=False)
|
||||
|
||||
|
||||
class ServersControllerTestV275(ControllerTest):
|
||||
wsgi_api_version = '2.75'
|
||||
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
|
||||
|
||||
@mock.patch('nova.compute.api.API.get_all')
|
||||
def test_get_servers_additional_query_param_old_version(self, mock_get):
|
||||
req = fakes.HTTPRequest.blank('/fake/servers?unknown=1',
|
||||
use_admin_context=True,
|
||||
version='2.74')
|
||||
self.controller.index(req)
|
||||
|
||||
@mock.patch('nova.compute.api.API.get_all')
|
||||
def test_get_servers_ignore_sort_key_old_version(self, mock_get):
|
||||
req = fakes.HTTPRequest.blank('/fake/servers?sort_key=deleted',
|
||||
use_admin_context=True,
|
||||
version='2.74')
|
||||
self.controller.index(req)
|
||||
|
||||
def test_get_servers_additional_query_param(self):
|
||||
req = fakes.HTTPRequest.blank('/fake/servers?unknown=1',
|
||||
use_admin_context=True,
|
||||
version=self.wsgi_api_version)
|
||||
self.assertRaises(exception.ValidationError, self.controller.index,
|
||||
req)
|
||||
|
||||
def test_get_servers_previously_ignored_sort_key(self):
|
||||
for s_ignore in servers_schema.SERVER_LIST_IGNORE_SORT_KEY_V273:
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/fake/servers?sort_key=%s' % s_ignore,
|
||||
use_admin_context=True,
|
||||
version=self.wsgi_api_version)
|
||||
self.assertRaises(exception.ValidationError, self.controller.index,
|
||||
req)
|
||||
|
||||
def test_get_servers_additional_sort_key(self):
|
||||
req = fakes.HTTPRequest.blank('/fake/servers?sort_key=unknown',
|
||||
use_admin_context=True,
|
||||
version=self.wsgi_api_version)
|
||||
self.assertRaises(exception.ValidationError, self.controller.index,
|
||||
req)
|
||||
|
||||
def test_update_response_no_show_server_only_attributes_old_version(self):
|
||||
# There are some old server attributes which were added only for
|
||||
# GET server APIs not for PUT. GET server and PUT server share the
|
||||
# same view builder method SHOW() to build the response, So make sure
|
||||
# attributes which are not supposed to be included for PUT
|
||||
# response are not present.
|
||||
body = {'server': {'name': 'server_test'}}
|
||||
req = fakes.HTTPRequest.blank('/fake/servers?unknown=1',
|
||||
use_admin_context=True,
|
||||
version='2.74')
|
||||
res_dict = self.controller.update(req, FAKE_UUID, body=body)
|
||||
for field in GET_ONLY_FIELDS:
|
||||
self.assertNotIn(field, res_dict['server'])
|
||||
for items in res_dict['server']['addresses'].values():
|
||||
for item in items:
|
||||
self.assertNotIn('OS-EXT-IPS:type', item)
|
||||
self.assertNotIn('OS-EXT-IPS-MAC:mac_addr', item)
|
||||
|
||||
def test_update_response_has_show_server_all_attributes(self):
|
||||
body = {'server': {'name': 'server_test'}}
|
||||
req = fakes.HTTPRequest.blank('/fake/servers?unknown=1',
|
||||
use_admin_context=True,
|
||||
version=self.wsgi_api_version)
|
||||
res_dict = self.controller.update(req, FAKE_UUID, body=body)
|
||||
for field in GET_ONLY_FIELDS:
|
||||
self.assertIn(field, res_dict['server'])
|
||||
for items in res_dict['server']['addresses'].values():
|
||||
for item in items:
|
||||
self.assertIn('OS-EXT-IPS:type', item)
|
||||
self.assertIn('OS-EXT-IPS-MAC:mac_addr', item)
|
||||
|
||||
def test_rebuild_response_no_show_server_only_attributes_old_version(self):
|
||||
# There are some old server attributes which were added only for
|
||||
# GET server APIs not for Rebuild. GET server and Rebuild server share
|
||||
# same view builder method SHOW() to build the response, So make sure
|
||||
# the attributes which are not supposed to be included for Rebuild
|
||||
# response are not present.
|
||||
body = {'rebuild': {"imageRef": self.image_uuid}}
|
||||
req = fakes.HTTPRequest.blank('/fake/servers?unknown=1',
|
||||
use_admin_context=True,
|
||||
version='2.74')
|
||||
fake_get = fakes.fake_compute_get(
|
||||
vm_state=vm_states.ACTIVE,
|
||||
project_id=req.environ['nova.context'].project_id,
|
||||
user_id=req.environ['nova.context'].user_id)
|
||||
self.mock_get.side_effect = fake_get
|
||||
|
||||
res_dict = self.controller._action_rebuild(req, FAKE_UUID,
|
||||
body=body).obj
|
||||
get_only_fields_Rebuild = copy.deepcopy(GET_ONLY_FIELDS)
|
||||
get_only_fields_Rebuild.remove('key_name')
|
||||
for field in get_only_fields_Rebuild:
|
||||
self.assertNotIn(field, res_dict['server'])
|
||||
for items in res_dict['server']['addresses'].values():
|
||||
for item in items:
|
||||
self.assertNotIn('OS-EXT-IPS:type', item)
|
||||
self.assertNotIn('OS-EXT-IPS-MAC:mac_addr', item)
|
||||
|
||||
def test_rebuild_response_has_show_server_all_attributes(self):
|
||||
body = {'rebuild': {"imageRef": self.image_uuid}}
|
||||
req = fakes.HTTPRequest.blank('/fake/servers?unknown=1',
|
||||
use_admin_context=True,
|
||||
version=self.wsgi_api_version)
|
||||
fake_get = fakes.fake_compute_get(
|
||||
vm_state=vm_states.ACTIVE,
|
||||
project_id=req.environ['nova.context'].project_id,
|
||||
user_id=req.environ['nova.context'].user_id)
|
||||
self.mock_get.side_effect = fake_get
|
||||
res_dict = self.controller._action_rebuild(req, FAKE_UUID,
|
||||
body=body).obj
|
||||
for field in GET_ONLY_FIELDS:
|
||||
if field == 'OS-EXT-SRV-ATTR:user_data':
|
||||
self.assertNotIn(field, res_dict['server'])
|
||||
field = 'user_data'
|
||||
self.assertIn(field, res_dict['server'])
|
||||
for items in res_dict['server']['addresses'].values():
|
||||
for item in items:
|
||||
self.assertIn('OS-EXT-IPS:type', item)
|
||||
self.assertIn('OS-EXT-IPS-MAC:mac_addr', item)
|
||||
|
||||
|
||||
class ServersControllerDeleteTest(ControllerTest):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -3007,22 +3148,9 @@ class ServersControllerRebuildInstanceTest(ControllerTest):
|
|||
|
||||
body = self.controller._action_rebuild(self.req, FAKE_UUID,
|
||||
body=body).obj
|
||||
|
||||
get_only_fields = ['OS-EXT-AZ:availability_zone', 'config_drive',
|
||||
'OS-EXT-SRV-ATTR:host',
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname',
|
||||
'OS-EXT-SRV-ATTR:instance_name',
|
||||
'OS-EXT-SRV-ATTR:hostname'
|
||||
'OS-EXT-SRV-ATTR:kernel_id',
|
||||
'OS-EXT-SRV-ATTR:launch_index',
|
||||
'OS-EXT-SRV-ATTR:ramdisk_id',
|
||||
'OS-EXT-SRV-ATTR:reservation_id',
|
||||
'OS-EXT-SRV-ATTR:root_device_name',
|
||||
'OS-EXT-SRV-ATTR:user_data', 'host_status',
|
||||
'OS-SRV-USG:launched_at',
|
||||
'OS-SRV-USG:terminated_at']
|
||||
if not self.expected_key_name:
|
||||
get_only_fields.append('key_name')
|
||||
get_only_fields = copy.deepcopy(GET_ONLY_FIELDS)
|
||||
if self.expected_key_name:
|
||||
get_only_fields.remove('key_name')
|
||||
for field in get_only_fields:
|
||||
self.assertNotIn(field, body['server'])
|
||||
|
||||
|
@ -3637,20 +3765,7 @@ class ServersControllerUpdateTest(ControllerTest):
|
|||
body = {'server': {'name': 'server_test'}}
|
||||
req = self._get_request(body)
|
||||
res_dict = self.controller.update(req, FAKE_UUID, body=body)
|
||||
get_only_fields = ['OS-EXT-AZ:availability_zone', 'config_drive',
|
||||
'OS-EXT-SRV-ATTR:host',
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname',
|
||||
'OS-EXT-SRV-ATTR:instance_name',
|
||||
'OS-EXT-SRV-ATTR:hostname'
|
||||
'OS-EXT-SRV-ATTR:kernel_id',
|
||||
'OS-EXT-SRV-ATTR:launch_index',
|
||||
'OS-EXT-SRV-ATTR:ramdisk_id',
|
||||
'OS-EXT-SRV-ATTR:reservation_id',
|
||||
'OS-EXT-SRV-ATTR:root_device_name',
|
||||
'OS-EXT-SRV-ATTR:user_data', 'host_status',
|
||||
'key_name', 'OS-SRV-USG:launched_at',
|
||||
'OS-SRV-USG:terminated_at']
|
||||
for field in get_only_fields:
|
||||
for field in GET_ONLY_FIELDS:
|
||||
self.assertNotIn(field, res_dict['server'])
|
||||
|
||||
def test_update_server_name_too_long(self):
|
||||
|
|
|
@ -1323,6 +1323,27 @@ class ServicesTestV253(test.TestCase):
|
|||
six.text_type(ex))
|
||||
|
||||
|
||||
class ServicesTestV275(test.TestCase):
|
||||
wsgi_api_version = '2.75'
|
||||
|
||||
def setUp(self):
|
||||
super(ServicesTestV275, self).setUp()
|
||||
self.controller = services_v21.ServiceController()
|
||||
|
||||
def test_services_list_with_additional_filter_old_version(self):
|
||||
url = '/fake/services?host=host1&binary=nova-compute&unknown=abc'
|
||||
req = fakes.HTTPRequest.blank(url, use_admin_context=True,
|
||||
version='2.74')
|
||||
self.controller.index(req)
|
||||
|
||||
def test_services_list_with_additional_filter(self):
|
||||
url = '/fake/services?host=host1&binary=nova-compute&unknown=abc'
|
||||
req = fakes.HTTPRequest.blank(url, use_admin_context=True,
|
||||
version=self.wsgi_api_version)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.controller.index, req)
|
||||
|
||||
|
||||
class ServicesPolicyEnforcementV21(test.NoDBTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
|
|
@ -454,6 +454,38 @@ class SimpleTenantUsageTestV40(SimpleTenantUsageTestV21):
|
|||
self._test_show_duplicate_query_parameters_validation(params)
|
||||
|
||||
|
||||
class SimpleTenantUsageTestV2_75(SimpleTenantUsageTestV40):
|
||||
version = '2.75'
|
||||
|
||||
def test_index_additional_query_param_old_version(self):
|
||||
req = fakes.HTTPRequest.blank('?start=%s&end=%s&additional=1' %
|
||||
(START.isoformat(), STOP.isoformat()),
|
||||
version='2.74')
|
||||
res = self.controller.index(req)
|
||||
self.assertIn('tenant_usages', res)
|
||||
|
||||
def test_index_additional_query_parameters(self):
|
||||
req = fakes.HTTPRequest.blank('?start=%s&end=%s&additional=1' %
|
||||
(START.isoformat(), STOP.isoformat()),
|
||||
version=self.version)
|
||||
self.assertRaises(exception.ValidationError, self.controller.index,
|
||||
req)
|
||||
|
||||
def test_show_additional_query_param_old_version(self):
|
||||
req = fakes.HTTPRequest.blank('?start=%s&end=%s&additional=1' %
|
||||
(START.isoformat(), STOP.isoformat()),
|
||||
version='2.74')
|
||||
res = self.controller.show(req, 1)
|
||||
self.assertIn('tenant_usage', res)
|
||||
|
||||
def test_show_additional_query_parameters(self):
|
||||
req = fakes.HTTPRequest.blank('?start=%s&end=%s&additional=1' %
|
||||
(START.isoformat(), STOP.isoformat()),
|
||||
version=self.version)
|
||||
self.assertRaises(exception.ValidationError, self.controller.show,
|
||||
req, 1)
|
||||
|
||||
|
||||
class SimpleTenantUsageLimitsTestV21(test.TestCase):
|
||||
version = '2.1'
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ from six.moves import urllib
|
|||
import webob
|
||||
from webob import exc
|
||||
|
||||
from nova.api.openstack import api_version_request
|
||||
from nova.api.openstack import common
|
||||
from nova.api.openstack.compute import assisted_volume_snapshots \
|
||||
as assisted_snaps_v21
|
||||
|
@ -419,6 +420,8 @@ class VolumeApiTestV21(test.NoDBTestCase):
|
|||
|
||||
class VolumeAttachTestsV21(test.NoDBTestCase):
|
||||
validation_error = exception.ValidationError
|
||||
microversion = '2.1'
|
||||
_prefix = '/servers/id/os-volume_attachments'
|
||||
|
||||
def setUp(self):
|
||||
super(VolumeAttachTestsV21, self).setUp()
|
||||
|
@ -436,12 +439,15 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
|
|||
}}
|
||||
self.attachments = volumes_v21.VolumeAttachmentController()
|
||||
|
||||
self.req = fakes.HTTPRequest.blank(
|
||||
'/v2/servers/id/os-volume_attachments/uuid')
|
||||
self.req = self._build_request('/uuid')
|
||||
self.req.body = jsonutils.dump_as_bytes({})
|
||||
self.req.headers['content-type'] = 'application/json'
|
||||
self.req.environ['nova.context'] = self.context
|
||||
|
||||
def _build_request(self, url=''):
|
||||
return fakes.HTTPRequest.blank(
|
||||
self._prefix + url, version=self.microversion)
|
||||
|
||||
def test_show(self):
|
||||
result = self.attachments.show(self.req, FAKE_UUID, FAKE_UUID_A)
|
||||
self.assertEqual(self.expected_show, result)
|
||||
|
@ -638,10 +644,12 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
|
|||
'device': '/dev/fake'}}
|
||||
self.assertRaises(webob.exc.HTTPConflict, self.attachments.create,
|
||||
self.req, FAKE_UUID, body=body)
|
||||
supports_multiattach = api_version_request.is_supported(
|
||||
self.req, '2.60')
|
||||
mock_attach_volume.assert_called_once_with(
|
||||
self.req.environ['nova.context'],
|
||||
test.MatchType(objects.Instance), FAKE_UUID_A, '/dev/fake',
|
||||
supports_multiattach=False, tag=None)
|
||||
supports_multiattach=supports_multiattach, tag=None)
|
||||
|
||||
def test_attach_volume_bad_id(self):
|
||||
self.stub_out('nova.compute.api.API.attach_volume',
|
||||
|
@ -701,7 +709,7 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
|
|||
body = {'volumeAttachment': {'volumeId': FAKE_UUID_A,
|
||||
'device': '/dev/fake'}}
|
||||
|
||||
req = fakes.HTTPRequest.blank('/v2/servers/id/os-volume_attachments')
|
||||
req = self._build_request()
|
||||
req.method = 'POST'
|
||||
req.body = jsonutils.dump_as_bytes({})
|
||||
req.headers['content-type'] = 'application/json'
|
||||
|
@ -796,8 +804,7 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
|
|||
'id': FAKE_UUID_B})
|
||||
|
||||
def _test_list_with_invalid_filter(self, url):
|
||||
prefix = '/servers/id/os-volume_attachments'
|
||||
req = fakes.HTTPRequest.blank(prefix + url)
|
||||
req = self._build_request(url)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.attachments.index,
|
||||
req,
|
||||
|
@ -833,8 +840,7 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
|
|||
'offset': 1
|
||||
}
|
||||
for param, value in params.items():
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/servers/id/os-volume_attachments' + '?%s=%s&%s=%s' %
|
||||
req = self._build_request('?%s=%s&%s=%s' %
|
||||
(param, value, param, value))
|
||||
self.attachments.index(req, FAKE_UUID)
|
||||
|
||||
|
@ -843,8 +849,8 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
|
|||
def test_list_with_additional_filter(self, mock_get):
|
||||
fake_bdms = objects.BlockDeviceMappingList()
|
||||
mock_get.return_value = fake_bdms
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/servers/id/os-volume_attachments?limit=1&additional=something')
|
||||
req = self._build_request(
|
||||
'?limit=1&additional=something')
|
||||
self.attachments.index(req, FAKE_UUID)
|
||||
|
||||
|
||||
|
@ -957,6 +963,36 @@ class VolumeAttachTestsV260(test.NoDBTestCase):
|
|||
'shelved-offloaded instances.', six.text_type(ex))
|
||||
|
||||
|
||||
class VolumeAttachTestsV2_75(VolumeAttachTestsV21):
|
||||
microversion = '2.75'
|
||||
|
||||
def setUp(self):
|
||||
super(VolumeAttachTestsV2_75, self).setUp()
|
||||
self.expected_show = {'volumeAttachment':
|
||||
{'device': '/dev/fake0',
|
||||
'serverId': FAKE_UUID,
|
||||
'id': FAKE_UUID_A,
|
||||
'volumeId': FAKE_UUID_A,
|
||||
'tag': None,
|
||||
}}
|
||||
|
||||
@mock.patch.object(objects.BlockDeviceMappingList,
|
||||
'get_by_instance_uuid')
|
||||
def test_list_with_additional_filter_old_version(self, mock_get):
|
||||
fake_bdms = objects.BlockDeviceMappingList()
|
||||
mock_get.return_value = fake_bdms
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/os-volumes?limit=1&offset=1&additional=something',
|
||||
version='2.74')
|
||||
self.attachments.index(req, FAKE_UUID)
|
||||
|
||||
def test_list_with_additional_filter(self):
|
||||
req = self._build_request(
|
||||
'?limit=1&additional=something')
|
||||
self.assertRaises(self.validation_error, self.attachments.index,
|
||||
req, FAKE_UUID)
|
||||
|
||||
|
||||
class SwapVolumeMultiattachTestCase(test.NoDBTestCase):
|
||||
|
||||
@mock.patch('nova.api.openstack.common.get_instance')
|
||||
|
@ -1185,6 +1221,7 @@ class AssistedSnapshotCreateTestCaseV21(test.NoDBTestCase):
|
|||
|
||||
class AssistedSnapshotDeleteTestCaseV21(test.NoDBTestCase):
|
||||
assisted_snaps = assisted_snaps_v21
|
||||
microversion = '2.1'
|
||||
|
||||
def _check_status(self, expected_status, res, controller_method):
|
||||
self.assertEqual(expected_status, controller_method.wsgi_code)
|
||||
|
@ -1204,13 +1241,15 @@ class AssistedSnapshotDeleteTestCaseV21(test.NoDBTestCase):
|
|||
}
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/v2/fake/os-assisted-volume-snapshots?%s' %
|
||||
urllib.parse.urlencode(params))
|
||||
urllib.parse.urlencode(params),
|
||||
version=self.microversion)
|
||||
req.method = 'DELETE'
|
||||
result = self.controller.delete(req, '5')
|
||||
self._check_status(204, result, self.controller.delete)
|
||||
|
||||
def test_assisted_delete_missing_delete_info(self):
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/os-assisted-volume-snapshots')
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/os-assisted-volume-snapshots',
|
||||
version=self.microversion)
|
||||
req.method = 'DELETE'
|
||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete,
|
||||
req, '5')
|
||||
|
@ -1223,7 +1262,8 @@ class AssistedSnapshotDeleteTestCaseV21(test.NoDBTestCase):
|
|||
}
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/v2/fake/os-assisted-volume-snapshots?%s' %
|
||||
urllib.parse.urlencode(params))
|
||||
urllib.parse.urlencode(params),
|
||||
version=self.microversion)
|
||||
req.method = 'DELETE'
|
||||
with mock.patch.object(compute_api.API, 'volume_snapshot_delete',
|
||||
side_effect=api_error):
|
||||
|
@ -1248,7 +1288,8 @@ class AssistedSnapshotDeleteTestCaseV21(test.NoDBTestCase):
|
|||
}
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/v2/fake/os-assisted-volume-snapshots?%s' %
|
||||
urllib.parse.urlencode(params))
|
||||
urllib.parse.urlencode(params),
|
||||
version=self.microversion)
|
||||
req.method = 'DELETE'
|
||||
self.controller.delete(req, '5')
|
||||
|
||||
|
@ -1259,7 +1300,8 @@ class AssistedSnapshotDeleteTestCaseV21(test.NoDBTestCase):
|
|||
}
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/v2/fake/os-assisted-volume-snapshots?%s' %
|
||||
urllib.parse.urlencode(params))
|
||||
urllib.parse.urlencode(params),
|
||||
version=self.microversion)
|
||||
req.method = 'DELETE'
|
||||
self.controller.delete(req, '5')
|
||||
|
||||
|
@ -1269,7 +1311,8 @@ class AssistedSnapshotDeleteTestCaseV21(test.NoDBTestCase):
|
|||
}
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/v2/fake/os-assisted-volume-snapshots?%s' %
|
||||
urllib.parse.urlencode(params))
|
||||
urllib.parse.urlencode(params),
|
||||
version=self.microversion)
|
||||
|
||||
req.method = 'DELETE'
|
||||
ex = self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
|
@ -1279,6 +1322,29 @@ class AssistedSnapshotDeleteTestCaseV21(test.NoDBTestCase):
|
|||
self.assertIn('volume_id', six.text_type(ex))
|
||||
|
||||
|
||||
class AssistedSnapshotDeleteTestCaseV275(AssistedSnapshotDeleteTestCaseV21):
|
||||
assisted_snaps = assisted_snaps_v21
|
||||
microversion = '2.75'
|
||||
|
||||
def test_delete_additional_query_parameters_old_version(self):
|
||||
params = {
|
||||
'delete_info': jsonutils.dumps({'volume_id': '1'}),
|
||||
'additional': 123
|
||||
}
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/v2/fake/os-assisted-volume-snapshots?%s' %
|
||||
urllib.parse.urlencode(params),
|
||||
version='2.74')
|
||||
self.controller.delete(req, 1)
|
||||
|
||||
def test_delete_additional_query_parameters(self):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/v2/fake/os-assisted-volume-snapshots?unknown=1',
|
||||
version=self.microversion)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.controller.delete, req, 1)
|
||||
|
||||
|
||||
class TestAssistedVolumeSnapshotsPolicyEnforcementV21(test.NoDBTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Multiple API cleanups is done in API microversion 2.75:
|
||||
|
||||
* 400 for unknown param for query param and for request body.
|
||||
|
||||
* Making server representation always consistent among GET, PUT
|
||||
and Rebuild serevr APIs response. ``PUT /servers/{server_id}``
|
||||
and ``POST /servers/{server_id}/action {rebuild}`` API response
|
||||
is modified to add all the missing fields which are return
|
||||
by ``GET /servers/{server_id}``.
|
||||
* Change the default return value of swap field from the empty
|
||||
string to 0 (integer) in flavor APIs.
|
||||
|
||||
* Return ``servers`` field always in the response of GET
|
||||
hypervisors API even there are no servers on hypervisor.
|
Loading…
Reference in New Issue