Add microversion to allow setting flavor description
This adds the new microversion to allow providing a description when creating a flavor, returning a flavor description when showing flavor details, and updating the description on an existing flavor. Implements blueprint flavor-description Change-Id: Ib16b0de82f9f9492f5cacf646dc3165a0849d75e
This commit is contained in:
parent
f93f10e7b6
commit
034d7f3795
@ -42,14 +42,12 @@ Response
|
||||
- flavors: flavors
|
||||
- id: flavor_id_body
|
||||
- name: flavor_name
|
||||
- description: flavor_description_resp
|
||||
- links: links
|
||||
|
||||
**Example List Flavors**
|
||||
**Example List Flavors (v2.55)**
|
||||
|
||||
Showing all the default flavors of a Liberty era Nova installation
|
||||
that was not customized by the site operators.
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/flavors-list-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/v2.55/flavors-list-resp.json
|
||||
:language: javascript
|
||||
|
||||
Create Flavor
|
||||
@ -74,6 +72,7 @@ Request
|
||||
|
||||
- flavor: flavor
|
||||
- name: flavor_name
|
||||
- description: flavor_description
|
||||
- id: flavor_id_body_create
|
||||
- ram: flavor_ram
|
||||
- disk: flavor_disk
|
||||
@ -83,9 +82,9 @@ Request
|
||||
- rxtx_factor: flavor_rxtx_factor_in
|
||||
- os-flavor-access:is_public: flavor_is_public_in
|
||||
|
||||
**Example Create Flavor**
|
||||
**Example Create Flavor (v2.55)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/flavor-create-post-req.json
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.55/flavor-create-post-req.json
|
||||
:language: javascript
|
||||
|
||||
Response
|
||||
@ -95,6 +94,7 @@ Response
|
||||
|
||||
- flavor: flavor
|
||||
- name: flavor_name
|
||||
- description: flavor_description_resp
|
||||
- id: flavor_id_body
|
||||
- ram: flavor_ram
|
||||
- disk: flavor_disk
|
||||
@ -107,9 +107,9 @@ Response
|
||||
- os-flavor-access:is_public: flavor_is_public
|
||||
|
||||
|
||||
**Example Create Flavor**
|
||||
**Example Create Flavor (v2.55)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/flavor-create-post-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.55/flavor-create-post-resp.json
|
||||
:language: javascript
|
||||
|
||||
List Flavors With Details
|
||||
@ -144,6 +144,7 @@ Response
|
||||
|
||||
- flavors: flavors
|
||||
- name: flavor_name
|
||||
- description: flavor_description_resp
|
||||
- id: flavor_id_body
|
||||
- ram: flavor_ram
|
||||
- disk: flavor_disk
|
||||
@ -155,9 +156,9 @@ Response
|
||||
- rxtx_factor: flavor_rxtx_factor
|
||||
- os-flavor-access:is_public: flavor_is_public
|
||||
|
||||
**Example List Flavors With Details**
|
||||
**Example List Flavors With Details (v2.55)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/flavors-detail-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/v2.55/flavors-detail-resp.json
|
||||
:language: javascript
|
||||
|
||||
Show Flavor Details
|
||||
@ -185,6 +186,7 @@ Response
|
||||
|
||||
- flavor: flavor
|
||||
- name: flavor_name
|
||||
- description: flavor_description_resp
|
||||
- id: flavor_id_body
|
||||
- ram: flavor_ram
|
||||
- disk: flavor_disk
|
||||
@ -196,9 +198,65 @@ Response
|
||||
- rxtx_factor: flavor_rxtx_factor
|
||||
- os-flavor-access:is_public: flavor_is_public
|
||||
|
||||
**Example Show Flavor Details**
|
||||
**Example Show Flavor Details (v2.55)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/flavor-get-resp.json
|
||||
.. literalinclude:: ../../doc/api_samples/flavors/v2.55/flavor-get-resp.json
|
||||
:language: javascript
|
||||
|
||||
Update Flavor Description
|
||||
=========================
|
||||
|
||||
.. rest_method:: PUT /flavors/{flavor_id}
|
||||
|
||||
Updates a flavor description.
|
||||
|
||||
This API is available starting with microversion 2.55.
|
||||
|
||||
Policy defaults enable only users with the administrative role to
|
||||
perform this operation. Cloud providers can change these permissions
|
||||
through the ``policy.json`` file.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: badRequest(400), unauthorized(401), forbidden(403), itemNotFound(404)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- flavor_id: flavor_id
|
||||
- flavor: flavor
|
||||
- description: flavor_description_required
|
||||
|
||||
**Example Update Flavor Description (v2.55)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.55/flavor-update-req.json
|
||||
:language: javascript
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- flavor: flavor
|
||||
- name: flavor_name
|
||||
- description: flavor_description_resp
|
||||
- id: flavor_id_body
|
||||
- ram: flavor_ram
|
||||
- disk: flavor_disk
|
||||
- vcpus: flavor_cpus
|
||||
- links: links
|
||||
- OS-FLV-EXT-DATA:ephemeral: flavor_ephem_disk
|
||||
- OS-FLV-DISABLED:disabled: flavor_disabled
|
||||
- swap: flavor_swap
|
||||
- rxtx_factor: flavor_rxtx_factor
|
||||
- os-flavor-access:is_public: flavor_is_public
|
||||
|
||||
|
||||
**Example Update Flavor Description (v2.55)**
|
||||
|
||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.55/flavor-update-resp.json
|
||||
:language: javascript
|
||||
|
||||
Delete Flavor
|
||||
|
@ -2365,6 +2365,29 @@ flavor_cpus_2_47:
|
||||
type: integer
|
||||
description: |
|
||||
The number of virtual CPUs that were allocated to the server.
|
||||
flavor_description:
|
||||
type: string
|
||||
in: body
|
||||
required: false
|
||||
min_version: 2.55
|
||||
description: |
|
||||
A free form description of the flavor. Limited to 65535 characters
|
||||
in length. Only printable characters are allowed.
|
||||
flavor_description_required:
|
||||
type: string
|
||||
in: body
|
||||
required: true
|
||||
min_version: 2.55
|
||||
description: |
|
||||
A free form description of the flavor. Limited to 65535 characters
|
||||
in length. Only printable characters are allowed.
|
||||
flavor_description_resp:
|
||||
description: |
|
||||
The description of the flavor.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.55
|
||||
flavor_disabled:
|
||||
in: body
|
||||
required: false
|
||||
|
@ -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,25 @@
|
||||
{
|
||||
"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": "",
|
||||
"rxtx_factor": 2.0,
|
||||
"vcpus": 2,
|
||||
"description": "test description"
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"flavor": {
|
||||
"description": "updated description"
|
||||
}
|
||||
}
|
25
doc/api_samples/flavor-manage/v2.55/flavor-update-resp.json
Normal file
25
doc/api_samples/flavor-manage/v2.55/flavor-update-resp.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "updated description"
|
||||
}
|
||||
}
|
25
doc/api_samples/flavors/v2.55/flavor-get-resp.json
Normal file
25
doc/api_samples/flavors/v2.55/flavor-get-resp.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "test description"
|
||||
}
|
||||
}
|
165
doc/api_samples/flavors/v2.55/flavors-detail-resp.json
Normal file
165
doc/api_samples/flavors/v2.55/flavors-detail-resp.json
Normal file
@ -0,0 +1,165 @@
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 2,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 4,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 8,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "test description"
|
||||
}
|
||||
]
|
||||
}
|
109
doc/api_samples/flavors/v2.55/flavors-list-resp.json
Normal file
109
doc/api_samples/flavors/v2.55/flavors-list-resp.json
Normal file
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"status": "CURRENT",
|
||||
"version": "2.54",
|
||||
"version": "2.55",
|
||||
"min_version": "2.1",
|
||||
"updated": "2013-07-23T11:33:21Z"
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
}
|
||||
],
|
||||
"status": "CURRENT",
|
||||
"version": "2.54",
|
||||
"version": "2.55",
|
||||
"min_version": "2.1",
|
||||
"updated": "2013-07-23T11:33:21Z"
|
||||
}
|
||||
|
@ -129,6 +129,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
|
||||
id field, and takes a uuid in requests. PUT and GET requests
|
||||
and responses are also changed.
|
||||
* 2.54 - Enable reset key pair while rebuilding instance.
|
||||
* 2.55 - Added flavor.description to GET/POST/PUT flavors APIs.
|
||||
"""
|
||||
|
||||
# The minimum and maximum versions of the API supported
|
||||
@ -137,7 +138,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.54"
|
||||
_MAX_API_VERSION = "2.55"
|
||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||
|
||||
# Almost all proxy APIs which are related to network, images and baremetal
|
||||
|
@ -87,6 +87,13 @@ class FlavorActionController(wsgi.Controller):
|
||||
|
||||
self._extend_flavor(resp_obj.obj['flavor'], db_flavor)
|
||||
|
||||
@wsgi.extends(action='update')
|
||||
def update(self, req, id, body, resp_obj):
|
||||
context = req.environ['nova.context']
|
||||
if context.can(fa_policies.BASE_POLICY_NAME, fatal=False):
|
||||
db_flavor = req.get_db_flavor(resp_obj.obj['flavor']['id'])
|
||||
self._extend_flavor(resp_obj.obj['flavor'], db_flavor)
|
||||
|
||||
@extensions.expected_errors((400, 403, 404, 409))
|
||||
@wsgi.action("addTenantAccess")
|
||||
@validation.schema(flavor_access.add_tenant_access)
|
||||
|
@ -14,6 +14,7 @@ import webob
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from nova.api.openstack import api_version_request
|
||||
from nova.api.openstack.compute.schemas import flavor_manage
|
||||
from nova.api.openstack.compute.views import flavors as flavors_view
|
||||
from nova.api.openstack import extensions
|
||||
@ -67,7 +68,9 @@ class FlavorManageController(wsgi.Controller):
|
||||
@wsgi.action("create")
|
||||
@extensions.expected_errors((400, 409))
|
||||
@validation.schema(flavor_manage.create_v20, '2.0', '2.0')
|
||||
@validation.schema(flavor_manage.create, '2.1')
|
||||
@validation.schema(flavor_manage.create, '2.1', '2.54')
|
||||
@validation.schema(flavor_manage.create_v2_55,
|
||||
flavors_view.FLAVOR_DESCRIPTION_MICROVERSION)
|
||||
def _create(self, req, body):
|
||||
context = req.environ['nova.context']
|
||||
# TODO(rb560u): remove this check in future release
|
||||
@ -92,12 +95,18 @@ class FlavorManageController(wsgi.Controller):
|
||||
rxtx_factor = vals.get('rxtx_factor', 1.0)
|
||||
is_public = vals.get('os-flavor-access:is_public', True)
|
||||
|
||||
# The user can specify a description starting with microversion 2.55.
|
||||
include_description = api_version_request.is_supported(
|
||||
req, flavors_view.FLAVOR_DESCRIPTION_MICROVERSION)
|
||||
description = vals.get('description') if include_description else None
|
||||
|
||||
try:
|
||||
flavor = flavors.create(name, memory, vcpus, root_gb,
|
||||
ephemeral_gb=ephemeral_gb,
|
||||
flavorid=flavorid, swap=swap,
|
||||
rxtx_factor=rxtx_factor,
|
||||
is_public=is_public)
|
||||
is_public=is_public,
|
||||
description=description)
|
||||
# NOTE(gmann): For backward compatibility, non public flavor
|
||||
# access is not being added for created tenant. Ref -bug/1209101
|
||||
req.cache_db_flavor(flavor)
|
||||
@ -105,4 +114,27 @@ class FlavorManageController(wsgi.Controller):
|
||||
exception.FlavorIdExists) as err:
|
||||
raise webob.exc.HTTPConflict(explanation=err.format_message())
|
||||
|
||||
return self._view_builder.show(req, flavor)
|
||||
return self._view_builder.show(req, flavor, include_description)
|
||||
|
||||
@wsgi.Controller.api_version(flavors_view.FLAVOR_DESCRIPTION_MICROVERSION)
|
||||
@wsgi.action('update')
|
||||
@extensions.expected_errors((400, 404))
|
||||
@validation.schema(flavor_manage.update_v2_55,
|
||||
flavors_view.FLAVOR_DESCRIPTION_MICROVERSION)
|
||||
def _update(self, req, id, body):
|
||||
# Validate the policy.
|
||||
context = req.environ['nova.context']
|
||||
context.can(fm_policies.POLICY_ROOT % 'update')
|
||||
|
||||
# Get the flavor and update the description.
|
||||
try:
|
||||
flavor = objects.Flavor.get_by_flavor_id(context, id)
|
||||
flavor.description = body['flavor']['description']
|
||||
flavor.save()
|
||||
except exception.FlavorNotFound as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
||||
|
||||
# Cache the flavor so the flavor_access and flavor_rxtx extensions
|
||||
# can add stuff to the response.
|
||||
req.cache_db_flavor(flavor)
|
||||
return self._view_builder.show(req, flavor, include_description=True)
|
||||
|
@ -42,6 +42,10 @@ class FlavorRxtxController(wsgi.Controller):
|
||||
def create(self, req, resp_obj, body):
|
||||
return self._show(req, resp_obj)
|
||||
|
||||
@wsgi.extends(action='update')
|
||||
def update(self, req, id, body, resp_obj):
|
||||
return self._show(req, resp_obj)
|
||||
|
||||
@wsgi.extends
|
||||
def detail(self, req, resp_obj):
|
||||
context = req.environ['nova.context']
|
||||
|
@ -16,6 +16,7 @@
|
||||
from oslo_utils import strutils
|
||||
import webob
|
||||
|
||||
from nova.api.openstack import api_version_request
|
||||
from nova.api.openstack import common
|
||||
from nova.api.openstack.compute.views import flavors as flavors_view
|
||||
from nova.api.openstack import extensions
|
||||
@ -57,7 +58,9 @@ class FlavorsController(wsgi.Controller):
|
||||
except exception.FlavorNotFound as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
||||
|
||||
return self._view_builder.show(req, flavor)
|
||||
include_description = api_version_request.is_supported(
|
||||
req, flavors_view.FLAVOR_DESCRIPTION_MICROVERSION)
|
||||
return self._view_builder.show(req, flavor, include_description)
|
||||
|
||||
def _parse_is_public(self, is_public):
|
||||
"""Parse is_public into something usable."""
|
||||
|
@ -688,3 +688,16 @@ uniqueness across cells. This microversion brings the following changes:
|
||||
----
|
||||
|
||||
Allow the user to set the server key pair while rebuilding.
|
||||
|
||||
2.55
|
||||
----
|
||||
|
||||
Adds a ``description`` field to the flavor resource in the following APIs:
|
||||
|
||||
* ``GET /flavors``
|
||||
* ``GET /flavors/detail``
|
||||
* ``GET /flavors/{flavor_id}``
|
||||
* ``POST /flavors``
|
||||
* ``PUT /flavors/{flavor_id}``
|
||||
|
||||
The embedded flavor description will not be included in server representations.
|
||||
|
@ -429,6 +429,7 @@ ROUTE_LIST = (
|
||||
}),
|
||||
('/flavors/{id}', {
|
||||
'GET': [flavor_controller, 'show'],
|
||||
'PUT': [flavor_controller, 'update'],
|
||||
'DELETE': [flavor_controller, 'delete']
|
||||
}),
|
||||
('/flavors/{id}/action', {
|
||||
|
@ -65,3 +65,37 @@ create = {
|
||||
create_v20 = copy.deepcopy(create)
|
||||
create_v20['properties']['flavor']['properties']['name'] = (parameter_types.
|
||||
name_with_leading_trailing_spaces)
|
||||
|
||||
|
||||
# 2.55 adds an optional description field with a max length of 65535 since the
|
||||
# backing database column is a TEXT column which is 64KiB.
|
||||
flavor_description = {
|
||||
'type': ['string', 'null'], 'minLength': 0, 'maxLength': 65535,
|
||||
'pattern': parameter_types.valid_description_regex,
|
||||
}
|
||||
|
||||
|
||||
create_v2_55 = copy.deepcopy(create)
|
||||
create_v2_55['properties']['flavor']['properties']['description'] = (
|
||||
flavor_description)
|
||||
|
||||
|
||||
update_v2_55 = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'flavor': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'description': flavor_description
|
||||
},
|
||||
# Since the only property that can be specified on update is the
|
||||
# description field, it is required. If we allow updating other
|
||||
# flavor attributes in a later microversion, we should reconsider
|
||||
# what is required.
|
||||
'required': ['description'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['flavor'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
@ -13,15 +13,18 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from nova.api.openstack import api_version_request
|
||||
from nova.api.openstack import common
|
||||
|
||||
FLAVOR_DESCRIPTION_MICROVERSION = '2.55'
|
||||
|
||||
|
||||
class ViewBuilder(common.ViewBuilder):
|
||||
|
||||
_collection_name = "flavors"
|
||||
|
||||
def basic(self, request, flavor):
|
||||
return {
|
||||
def basic(self, request, flavor, include_description=False):
|
||||
flavor_dict = {
|
||||
"flavor": {
|
||||
"id": flavor["flavorid"],
|
||||
"name": flavor["name"],
|
||||
@ -31,7 +34,12 @@ class ViewBuilder(common.ViewBuilder):
|
||||
},
|
||||
}
|
||||
|
||||
def show(self, request, flavor):
|
||||
if include_description:
|
||||
flavor_dict['flavor']['description'] = flavor.description
|
||||
|
||||
return flavor_dict
|
||||
|
||||
def show(self, request, flavor, include_description=False):
|
||||
flavor_dict = {
|
||||
"flavor": {
|
||||
"id": flavor["flavorid"],
|
||||
@ -48,19 +56,29 @@ class ViewBuilder(common.ViewBuilder):
|
||||
},
|
||||
}
|
||||
|
||||
if include_description:
|
||||
flavor_dict['flavor']['description'] = flavor.description
|
||||
|
||||
return flavor_dict
|
||||
|
||||
def index(self, request, flavors):
|
||||
"""Return the 'index' view of flavors."""
|
||||
coll_name = self._collection_name
|
||||
return self._list_view(self.basic, request, flavors, coll_name)
|
||||
include_description = api_version_request.is_supported(
|
||||
request, FLAVOR_DESCRIPTION_MICROVERSION)
|
||||
return self._list_view(self.basic, request, flavors, coll_name,
|
||||
include_description=include_description)
|
||||
|
||||
def detail(self, request, flavors):
|
||||
"""Return the 'detail' view of flavors."""
|
||||
coll_name = self._collection_name + '/detail'
|
||||
return self._list_view(self.show, request, flavors, coll_name)
|
||||
include_description = api_version_request.is_supported(
|
||||
request, FLAVOR_DESCRIPTION_MICROVERSION)
|
||||
return self._list_view(self.show, request, flavors, coll_name,
|
||||
include_description=include_description)
|
||||
|
||||
def _list_view(self, func, request, flavors, coll_name):
|
||||
def _list_view(self, func, request, flavors, coll_name,
|
||||
include_description=False):
|
||||
"""Provide a view for a list of flavors.
|
||||
|
||||
:param func: Function used to format the flavor data
|
||||
@ -68,10 +86,13 @@ class ViewBuilder(common.ViewBuilder):
|
||||
:param flavors: List of flavors in dictionary format
|
||||
:param coll_name: Name of collection, used to generate the next link
|
||||
for a pagination query
|
||||
:param include_description: If the flavor.description should be
|
||||
included in the response dict.
|
||||
|
||||
:returns: Flavor reply data in dictionary format
|
||||
"""
|
||||
flavor_list = [func(request, flavor)["flavor"] for flavor in flavors]
|
||||
flavor_list = [func(request, flavor, include_description)["flavor"]
|
||||
for flavor in flavors]
|
||||
flavors_links = self._get_collection_links(request,
|
||||
flavors,
|
||||
coll_name,
|
||||
|
@ -69,7 +69,7 @@ system_metadata_flavor_extra_props = [
|
||||
|
||||
|
||||
def create(name, memory, vcpus, root_gb, ephemeral_gb=0, flavorid=None,
|
||||
swap=0, rxtx_factor=1.0, is_public=True):
|
||||
swap=0, rxtx_factor=1.0, is_public=True, description=None):
|
||||
"""Creates flavors."""
|
||||
if not flavorid:
|
||||
flavorid = uuidutils.generate_uuid()
|
||||
@ -81,6 +81,7 @@ def create(name, memory, vcpus, root_gb, ephemeral_gb=0, flavorid=None,
|
||||
'ephemeral_gb': ephemeral_gb,
|
||||
'swap': swap,
|
||||
'rxtx_factor': rxtx_factor,
|
||||
'description': description
|
||||
}
|
||||
|
||||
if isinstance(name, six.string_types):
|
||||
|
@ -71,6 +71,10 @@ to a flavor via an os-flavor-access API.
|
||||
'method': 'POST',
|
||||
'path': '/flavors'
|
||||
},
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/flavors/{flavor_id}'
|
||||
},
|
||||
]),
|
||||
]
|
||||
|
||||
|
@ -52,6 +52,16 @@ flavor_manage_policies = [
|
||||
'path': '/flavors'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
POLICY_ROOT % 'update',
|
||||
base.RULE_ADMIN_API,
|
||||
"Update a flavor",
|
||||
[
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/flavors/{flavor_id}'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
POLICY_ROOT % 'delete',
|
||||
BASE_POLICY_RULE,
|
||||
|
@ -40,6 +40,10 @@ flavor_rxtx_policies = [
|
||||
'method': 'POST',
|
||||
'path': '/flavors'
|
||||
},
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/flavors/{flavor_id}'
|
||||
},
|
||||
]),
|
||||
]
|
||||
|
||||
|
@ -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,25 @@
|
||||
{
|
||||
"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": "",
|
||||
"rxtx_factor": 2.0,
|
||||
"description": "test description"
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"flavor": {
|
||||
"description": "updated description"
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "updated description"
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "test description"
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 2,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 4,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 8,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"vcpus": 1,
|
||||
"rxtx_factor": 1.0,
|
||||
"description": "test description"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
{
|
||||
"flavors": [
|
||||
{
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/1",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/2",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/2",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.small",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/3",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/3",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.medium",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/4",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/4",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.large",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/5",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/5",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.xlarge",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(versioned_compute_endpoint)s/flavors/6",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(compute_endpoint)s/flavors/6",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny.specs",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"description": "test description"
|
||||
}
|
||||
]
|
||||
}
|
@ -37,3 +37,12 @@ class FlavorManageSampleJsonTests(api_sample_base.ApiSampleTestBaseV21):
|
||||
response = self._do_delete("flavors/10")
|
||||
self.assertEqual(202, response.status_code)
|
||||
self.assertEqual('', response.text)
|
||||
|
||||
|
||||
class FlavorManageSampleJsonTests2_55(FlavorManageSampleJsonTests):
|
||||
microversion = '2.55'
|
||||
scenarios = [('v2_55', {'api_major_version': 'v2.1'})]
|
||||
|
||||
def test_update_flavor_description(self):
|
||||
response = self._do_put("flavors/1", "flavor-update-req", {})
|
||||
self._verify_response("flavor-update-resp", {}, response, 200)
|
||||
|
@ -13,20 +13,47 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from nova import context as nova_context
|
||||
from nova import objects
|
||||
from nova.tests.functional.api_sample_tests import api_sample_base
|
||||
|
||||
|
||||
class FlavorsSampleJsonTest(api_sample_base.ApiSampleTestBaseV21):
|
||||
sample_dir = 'flavors'
|
||||
flavor_show_id = '1'
|
||||
subs = {}
|
||||
|
||||
def test_flavors_get(self):
|
||||
response = self._do_get('flavors/1')
|
||||
self._verify_response('flavor-get-resp', {}, response, 200)
|
||||
response = self._do_get('flavors/%s' % self.flavor_show_id)
|
||||
self._verify_response('flavor-get-resp', self.subs, response, 200)
|
||||
|
||||
def test_flavors_list(self):
|
||||
response = self._do_get('flavors')
|
||||