Add microversion to support extra_specs in flavor API.
Exposes flavor extra_specs in the flavor representation since microversion 2.61. Now users can see the flavor extra-specs in flavor APIs response only and do not need to call ``GET /flavors/{flavor_id}/extra_specs`` API. Flavor extra_specs will be included in Response body of the following APIs: * ``GET /flavors/detail`` * ``GET /flavors/{flavor_id}`` * ``POST /flavors`` * ``PUT /flavors/{flavor_id}`` Part of blueprint add-extra-specs-to-flavor-list Change-Id: I048747633babf690a63c6de9773bff5547872053
This commit is contained in:
parent
1e6564b7d4
commit
0baba40b1b
@ -105,11 +105,12 @@ Response
|
|||||||
- swap: flavor_swap
|
- swap: flavor_swap
|
||||||
- rxtx_factor: flavor_rxtx_factor
|
- rxtx_factor: flavor_rxtx_factor
|
||||||
- os-flavor-access:is_public: flavor_is_public
|
- os-flavor-access:is_public: flavor_is_public
|
||||||
|
- extra_specs: extra_specs_2_61
|
||||||
|
|
||||||
|
|
||||||
**Example Create Flavor (v2.55)**
|
**Example Create Flavor (v2.61)**
|
||||||
|
|
||||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.55/flavor-create-post-resp.json
|
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.61/flavor-create-post-resp.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
List Flavors With Details
|
List Flavors With Details
|
||||||
@ -155,10 +156,11 @@ Response
|
|||||||
- swap: flavor_swap
|
- swap: flavor_swap
|
||||||
- rxtx_factor: flavor_rxtx_factor
|
- rxtx_factor: flavor_rxtx_factor
|
||||||
- os-flavor-access:is_public: flavor_is_public
|
- os-flavor-access:is_public: flavor_is_public
|
||||||
|
- extra_specs: extra_specs_2_61
|
||||||
|
|
||||||
**Example List Flavors With Details (v2.55)**
|
**Example List Flavors With Details (v2.61)**
|
||||||
|
|
||||||
.. literalinclude:: ../../doc/api_samples/flavors/v2.55/flavors-detail-resp.json
|
.. literalinclude:: ../../doc/api_samples/flavors/v2.61/flavors-detail-resp.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
Show Flavor Details
|
Show Flavor Details
|
||||||
@ -197,10 +199,11 @@ Response
|
|||||||
- swap: flavor_swap
|
- swap: flavor_swap
|
||||||
- rxtx_factor: flavor_rxtx_factor
|
- rxtx_factor: flavor_rxtx_factor
|
||||||
- os-flavor-access:is_public: flavor_is_public
|
- os-flavor-access:is_public: flavor_is_public
|
||||||
|
- extra_specs: extra_specs_2_61
|
||||||
|
|
||||||
**Example Show Flavor Details (v2.55)**
|
**Example Show Flavor Details (v2.61)**
|
||||||
|
|
||||||
.. literalinclude:: ../../doc/api_samples/flavors/v2.55/flavor-get-resp.json
|
.. literalinclude:: ../../doc/api_samples/flavors/v2.61/flavor-get-resp.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
Update Flavor Description
|
Update Flavor Description
|
||||||
@ -252,11 +255,12 @@ Response
|
|||||||
- swap: flavor_swap
|
- swap: flavor_swap
|
||||||
- rxtx_factor: flavor_rxtx_factor
|
- rxtx_factor: flavor_rxtx_factor
|
||||||
- os-flavor-access:is_public: flavor_is_public
|
- os-flavor-access:is_public: flavor_is_public
|
||||||
|
- extra_specs: extra_specs_2_61
|
||||||
|
|
||||||
|
|
||||||
**Example Update Flavor Description (v2.55)**
|
**Example Update Flavor Description (v2.61)**
|
||||||
|
|
||||||
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.55/flavor-update-resp.json
|
.. literalinclude:: ../../doc/api_samples/flavor-manage/v2.61/flavor-update-resp.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
Delete Flavor
|
Delete Flavor
|
||||||
|
@ -2332,6 +2332,15 @@ extra_specs_2_47:
|
|||||||
in: body
|
in: body
|
||||||
required: false
|
required: false
|
||||||
type: object
|
type: object
|
||||||
|
extra_specs_2_61:
|
||||||
|
min_version: 2.61
|
||||||
|
description: |
|
||||||
|
A dictionary of the flavor's extra-specs key-and-value pairs. This will
|
||||||
|
only be included if the user is allowed by policy to index flavor
|
||||||
|
extra_specs.
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
type: object
|
||||||
fault:
|
fault:
|
||||||
description: |
|
description: |
|
||||||
A fault object. Only displayed in the failed response.
|
A fault object. Only displayed in the failed response.
|
||||||
|
@ -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": "",
|
||||||
|
"rxtx_factor": 2.0,
|
||||||
|
"vcpus": 2,
|
||||||
|
"description": "test description",
|
||||||
|
"extra_specs": {}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"flavor": {
|
||||||
|
"description": "updated description"
|
||||||
|
}
|
||||||
|
}
|
26
doc/api_samples/flavor-manage/v2.61/flavor-update-resp.json
Normal file
26
doc/api_samples/flavor-manage/v2.61/flavor-update-resp.json
Normal file
@ -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": "",
|
||||||
|
"vcpus": 1,
|
||||||
|
"rxtx_factor": 1.0,
|
||||||
|
"description": "updated description",
|
||||||
|
"extra_specs": {}
|
||||||
|
}
|
||||||
|
}
|
29
doc/api_samples/flavors/v2.61/flavor-get-resp.json
Normal file
29
doc/api_samples/flavors/v2.61/flavor-get-resp.json
Normal file
@ -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": "",
|
||||||
|
"vcpus": 1,
|
||||||
|
"rxtx_factor": 1.0,
|
||||||
|
"description": "test description",
|
||||||
|
"extra_specs": {
|
||||||
|
"key1": "value1",
|
||||||
|
"key2": "value2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
179
doc/api_samples/flavors/v2.61/flavors-detail-resp.json
Normal file
179
doc/api_samples/flavors/v2.61/flavors-detail-resp.json
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
{
|
||||||
|
"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,
|
||||||
|
"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": "",
|
||||||
|
"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": "",
|
||||||
|
"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": "",
|
||||||
|
"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": "",
|
||||||
|
"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": "",
|
||||||
|
"vcpus": 1,
|
||||||
|
"rxtx_factor": 1.0,
|
||||||
|
"description": null,
|
||||||
|
"extra_specs": {
|
||||||
|
"hw:cpu_model": "SandyBridge",
|
||||||
|
"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": "",
|
||||||
|
"vcpus": 1,
|
||||||
|
"rxtx_factor": 1.0,
|
||||||
|
"description": "test description",
|
||||||
|
"extra_specs": {
|
||||||
|
"key1": "value1",
|
||||||
|
"key2": "value2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
109
doc/api_samples/flavors/v2.61/flavors-list-resp.json
Normal file
109
doc/api_samples/flavors/v2.61/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",
|
"status": "CURRENT",
|
||||||
"version": "2.60",
|
"version": "2.61",
|
||||||
"min_version": "2.1",
|
"min_version": "2.1",
|
||||||
"updated": "2013-07-23T11:33:21Z"
|
"updated": "2013-07-23T11:33:21Z"
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"status": "CURRENT",
|
"status": "CURRENT",
|
||||||
"version": "2.60",
|
"version": "2.61",
|
||||||
"min_version": "2.1",
|
"min_version": "2.1",
|
||||||
"updated": "2013-07-23T11:33:21Z"
|
"updated": "2013-07-23T11:33:21Z"
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,9 @@ REST_API_VERSION_HISTORY = """REST API Version History:
|
|||||||
API. And the os-migrations API now returns both the id and the
|
API. And the os-migrations API now returns both the id and the
|
||||||
uuid in response.
|
uuid in response.
|
||||||
* 2.60 - Add support for attaching a single volume to multiple instances.
|
* 2.60 - Add support for attaching a single volume to multiple instances.
|
||||||
|
* 2.61 - Exposes flavor extra_specs in the flavor representation. Flavor
|
||||||
|
extra_specs will be included in Response body of GET, POST, PUT
|
||||||
|
/flavors APIs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# The minimum and maximum versions of the API supported
|
# The minimum and maximum versions of the API supported
|
||||||
@ -151,7 +154,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
|
|||||||
# Note(cyeoh): This only applies for the v2.1 API once microversions
|
# Note(cyeoh): This only applies for the v2.1 API once microversions
|
||||||
# support is fully merged. It does not affect the V2 API.
|
# support is fully merged. It does not affect the V2 API.
|
||||||
_MIN_API_VERSION = "2.1"
|
_MIN_API_VERSION = "2.1"
|
||||||
_MAX_API_VERSION = "2.60"
|
_MAX_API_VERSION = "2.61"
|
||||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||||
|
|
||||||
# Almost all proxy APIs which are related to network, images and baremetal
|
# Almost all proxy APIs which are related to network, images and baremetal
|
||||||
|
@ -21,6 +21,7 @@ from nova.compute import flavors
|
|||||||
from nova import exception
|
from nova import exception
|
||||||
from nova import objects
|
from nova import objects
|
||||||
from nova.policies import base
|
from nova.policies import base
|
||||||
|
from nova.policies import flavor_extra_specs as fes_policies
|
||||||
from nova.policies import flavor_manage as fm_policies
|
from nova.policies import flavor_manage as fm_policies
|
||||||
from nova import policy
|
from nova import policy
|
||||||
|
|
||||||
@ -110,7 +111,17 @@ class FlavorManageController(wsgi.Controller):
|
|||||||
exception.FlavorIdExists) as err:
|
exception.FlavorIdExists) as err:
|
||||||
raise webob.exc.HTTPConflict(explanation=err.format_message())
|
raise webob.exc.HTTPConflict(explanation=err.format_message())
|
||||||
|
|
||||||
return self._view_builder.show(req, flavor, include_description)
|
include_extra_specs = False
|
||||||
|
if api_version_request.is_supported(
|
||||||
|
req, flavors_view.FLAVOR_EXTRA_SPECS_MICROVERSION):
|
||||||
|
include_extra_specs = context.can(
|
||||||
|
fes_policies.POLICY_ROOT % 'index', fatal=False)
|
||||||
|
# NOTE(yikun): This empty extra_spec only for keeping consistent
|
||||||
|
# with other related flavor api.
|
||||||
|
flavor.extra_specs = {}
|
||||||
|
|
||||||
|
return self._view_builder.show(req, flavor, include_description,
|
||||||
|
include_extra_specs=include_extra_specs)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(flavors_view.FLAVOR_DESCRIPTION_MICROVERSION)
|
@wsgi.Controller.api_version(flavors_view.FLAVOR_DESCRIPTION_MICROVERSION)
|
||||||
@wsgi.action('update')
|
@wsgi.action('update')
|
||||||
@ -133,4 +144,10 @@ class FlavorManageController(wsgi.Controller):
|
|||||||
# Cache the flavor so the flavor_access and flavor_rxtx extensions
|
# Cache the flavor so the flavor_access and flavor_rxtx extensions
|
||||||
# can add stuff to the response.
|
# can add stuff to the response.
|
||||||
req.cache_db_flavor(flavor)
|
req.cache_db_flavor(flavor)
|
||||||
return self._view_builder.show(req, flavor, include_description=True)
|
include_extra_specs = False
|
||||||
|
if api_version_request.is_supported(
|
||||||
|
req, flavors_view.FLAVOR_EXTRA_SPECS_MICROVERSION):
|
||||||
|
include_extra_specs = context.can(
|
||||||
|
fes_policies.POLICY_ROOT % 'index', fatal=False)
|
||||||
|
return self._view_builder.show(req, flavor, include_description=True,
|
||||||
|
include_extra_specs=include_extra_specs)
|
||||||
|
@ -26,6 +26,7 @@ from nova.compute import flavors
|
|||||||
from nova import exception
|
from nova import exception
|
||||||
from nova.i18n import _
|
from nova.i18n import _
|
||||||
from nova import objects
|
from nova import objects
|
||||||
|
from nova.policies import flavor_extra_specs as fes_policies
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
ALIAS = 'flavors'
|
ALIAS = 'flavors'
|
||||||
@ -47,9 +48,16 @@ class FlavorsController(wsgi.Controller):
|
|||||||
@wsgi.expected_errors(400)
|
@wsgi.expected_errors(400)
|
||||||
def detail(self, req):
|
def detail(self, req):
|
||||||
"""Return all flavors in detail."""
|
"""Return all flavors in detail."""
|
||||||
|
context = req.environ['nova.context']
|
||||||
limited_flavors = self._get_flavors(req)
|
limited_flavors = self._get_flavors(req)
|
||||||
req.cache_db_flavors(limited_flavors)
|
req.cache_db_flavors(limited_flavors)
|
||||||
return self._view_builder.detail(req, limited_flavors)
|
include_extra_specs = False
|
||||||
|
if api_version_request.is_supported(
|
||||||
|
req, flavors_view.FLAVOR_EXTRA_SPECS_MICROVERSION):
|
||||||
|
include_extra_specs = context.can(
|
||||||
|
fes_policies.POLICY_ROOT % 'index', fatal=False)
|
||||||
|
return self._view_builder.detail(
|
||||||
|
req, limited_flavors, include_extra_specs=include_extra_specs)
|
||||||
|
|
||||||
@wsgi.expected_errors(404)
|
@wsgi.expected_errors(404)
|
||||||
def show(self, req, id):
|
def show(self, req, id):
|
||||||
@ -61,9 +69,16 @@ class FlavorsController(wsgi.Controller):
|
|||||||
except exception.FlavorNotFound as e:
|
except exception.FlavorNotFound as e:
|
||||||
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
||||||
|
|
||||||
|
include_extra_specs = False
|
||||||
|
if api_version_request.is_supported(
|
||||||
|
req, flavors_view.FLAVOR_EXTRA_SPECS_MICROVERSION):
|
||||||
|
include_extra_specs = context.can(
|
||||||
|
fes_policies.POLICY_ROOT % 'index', fatal=False)
|
||||||
include_description = api_version_request.is_supported(
|
include_description = api_version_request.is_supported(
|
||||||
req, flavors_view.FLAVOR_DESCRIPTION_MICROVERSION)
|
req, flavors_view.FLAVOR_DESCRIPTION_MICROVERSION)
|
||||||
return self._view_builder.show(req, flavor, include_description)
|
return self._view_builder.show(
|
||||||
|
req, flavor, include_description=include_description,
|
||||||
|
include_extra_specs=include_extra_specs)
|
||||||
|
|
||||||
def _parse_is_public(self, is_public):
|
def _parse_is_public(self, is_public):
|
||||||
"""Parse is_public into something usable."""
|
"""Parse is_public into something usable."""
|
||||||
|
@ -765,3 +765,18 @@ From this version of the API users can attach a ``multiattach`` capable volume
|
|||||||
to multiple instances. The API request for creating the additional attachments
|
to multiple instances. The API request for creating the additional attachments
|
||||||
is the same. The chosen virt driver and the volume back end has to support the
|
is the same. The chosen virt driver and the volume back end has to support the
|
||||||
functionality as well.
|
functionality as well.
|
||||||
|
|
||||||
|
2.61
|
||||||
|
----
|
||||||
|
|
||||||
|
Exposes flavor extra_specs in the flavor representation. Now users can see the
|
||||||
|
flavor extra-specs in flavor APIs response and do not need to call
|
||||||
|
``GET /flavors/{flavor_id}/os-extra_specs`` API. If the user is prevented by
|
||||||
|
policy from indexing extra-specs, then the ``extra_specs`` field will not be
|
||||||
|
included in the flavor information. Flavor extra_specs will be included in
|
||||||
|
Response body of the following APIs:
|
||||||
|
|
||||||
|
* ``GET /flavors/detail``
|
||||||
|
* ``GET /flavors/{flavor_id}``
|
||||||
|
* ``POST /flavors``
|
||||||
|
* ``PUT /flavors/{flavor_id}``
|
||||||
|
@ -19,6 +19,7 @@ from nova.policies import flavor_access as fa_policies
|
|||||||
from nova.policies import flavor_rxtx as fr_policies
|
from nova.policies import flavor_rxtx as fr_policies
|
||||||
|
|
||||||
FLAVOR_DESCRIPTION_MICROVERSION = '2.55'
|
FLAVOR_DESCRIPTION_MICROVERSION = '2.55'
|
||||||
|
FLAVOR_EXTRA_SPECS_MICROVERSION = '2.61'
|
||||||
|
|
||||||
|
|
||||||
class ViewBuilder(common.ViewBuilder):
|
class ViewBuilder(common.ViewBuilder):
|
||||||
@ -26,10 +27,12 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
_collection_name = "flavors"
|
_collection_name = "flavors"
|
||||||
|
|
||||||
def basic(self, request, flavor, include_description=False,
|
def basic(self, request, flavor, include_description=False,
|
||||||
update_is_public=None, update_rxtx_factor=None):
|
update_is_public=None, update_rxtx_factor=None,
|
||||||
# update_is_public & update_rxtx_factor are placeholder param
|
include_extra_specs=False):
|
||||||
# which are not used in this method as basic() method is used by
|
# include_extra_specs & update_is_public & update_rxtx_factor are
|
||||||
# index() (GET /flavors) which does not return those keys in response.
|
# placeholder param which are not used in this method as basic() method
|
||||||
|
# is used by index() (GET /flavors) which does not return those keys in
|
||||||
|
# response.
|
||||||
flavor_dict = {
|
flavor_dict = {
|
||||||
"flavor": {
|
"flavor": {
|
||||||
"id": flavor["flavorid"],
|
"id": flavor["flavorid"],
|
||||||
@ -46,7 +49,8 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
return flavor_dict
|
return flavor_dict
|
||||||
|
|
||||||
def show(self, request, flavor, include_description=False,
|
def show(self, request, flavor, include_description=False,
|
||||||
update_is_public=None, update_rxtx_factor=None):
|
update_is_public=None, update_rxtx_factor=None,
|
||||||
|
include_extra_specs=False):
|
||||||
flavor_dict = {
|
flavor_dict = {
|
||||||
"flavor": {
|
"flavor": {
|
||||||
"id": flavor["flavorid"],
|
"id": flavor["flavorid"],
|
||||||
@ -66,6 +70,9 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
if include_description:
|
if include_description:
|
||||||
flavor_dict['flavor']['description'] = flavor.description
|
flavor_dict['flavor']['description'] = flavor.description
|
||||||
|
|
||||||
|
if include_extra_specs:
|
||||||
|
flavor_dict['flavor']['extra_specs'] = flavor.extra_specs
|
||||||
|
|
||||||
# TODO(gmann): 'update_is_public' & 'update_rxtx_factor' are policies
|
# TODO(gmann): 'update_is_public' & 'update_rxtx_factor' are policies
|
||||||
# checks. Once os-flavor-access & os-flavor-rxtx policies are
|
# checks. Once os-flavor-access & os-flavor-rxtx policies are
|
||||||
# removed, 'os-flavor-access:is_public' and 'rxtx_factor' need to be
|
# removed, 'os-flavor-access:is_public' and 'rxtx_factor' need to be
|
||||||
@ -96,7 +103,7 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
return self._list_view(self.basic, request, flavors, coll_name,
|
return self._list_view(self.basic, request, flavors, coll_name,
|
||||||
include_description=include_description)
|
include_description=include_description)
|
||||||
|
|
||||||
def detail(self, request, flavors):
|
def detail(self, request, flavors, include_extra_specs=False):
|
||||||
"""Return the 'detail' view of flavors."""
|
"""Return the 'detail' view of flavors."""
|
||||||
coll_name = self._collection_name + '/detail'
|
coll_name = self._collection_name + '/detail'
|
||||||
include_description = api_version_request.is_supported(
|
include_description = api_version_request.is_supported(
|
||||||
@ -109,11 +116,12 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
return self._list_view(self.show, request, flavors, coll_name,
|
return self._list_view(self.show, request, flavors, coll_name,
|
||||||
include_description=include_description,
|
include_description=include_description,
|
||||||
update_is_public=update_is_public,
|
update_is_public=update_is_public,
|
||||||
update_rxtx_factor=update_rxtx_factor)
|
update_rxtx_factor=update_rxtx_factor,
|
||||||
|
include_extra_specs=include_extra_specs)
|
||||||
|
|
||||||
def _list_view(self, func, request, flavors, coll_name,
|
def _list_view(self, func, request, flavors, coll_name,
|
||||||
include_description=False, update_is_public=None,
|
include_description=False, update_is_public=None,
|
||||||
update_rxtx_factor=None):
|
update_rxtx_factor=None, include_extra_specs=False):
|
||||||
"""Provide a view for a list of flavors.
|
"""Provide a view for a list of flavors.
|
||||||
|
|
||||||
:param func: Function used to format the flavor data
|
:param func: Function used to format the flavor data
|
||||||
@ -127,11 +135,14 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
included in the response dict.
|
included in the response dict.
|
||||||
:param update_rxtx_factor: If the flavor.rxtx_factor field should be
|
:param update_rxtx_factor: If the flavor.rxtx_factor field should be
|
||||||
included in the response dict.
|
included in the response dict.
|
||||||
|
:param include_extra_specs: If the flavor.extra_specs should be
|
||||||
|
included in the response dict.
|
||||||
|
|
||||||
:returns: Flavor reply data in dictionary format
|
:returns: Flavor reply data in dictionary format
|
||||||
"""
|
"""
|
||||||
flavor_list = [func(request, flavor, include_description,
|
flavor_list = [func(request, flavor, include_description,
|
||||||
update_is_public, update_rxtx_factor)["flavor"]
|
update_is_public, update_rxtx_factor,
|
||||||
|
include_extra_specs)["flavor"]
|
||||||
for flavor in flavors]
|
for flavor in flavors]
|
||||||
flavors_links = self._get_collection_links(request,
|
flavors_links = self._get_collection_links(request,
|
||||||
flavors,
|
flavors,
|
||||||
|
@ -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": "",
|
||||||
|
"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": "",
|
||||||
|
"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": "",
|
||||||
|
"vcpus": 1,
|
||||||
|
"rxtx_factor": 1.0,
|
||||||
|
"description": "test description",
|
||||||
|
"extra_specs": {
|
||||||
|
"key1": "value1",
|
||||||
|
"key2": "value2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,179 @@
|
|||||||
|
{
|
||||||
|
"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,
|
||||||
|
"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": "",
|
||||||
|
"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": "",
|
||||||
|
"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": "",
|
||||||
|
"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": "",
|
||||||
|
"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": "",
|
||||||
|
"vcpus": 1,
|
||||||
|
"rxtx_factor": 1.0,
|
||||||
|
"description": null,
|
||||||
|
"extra_specs": {
|
||||||
|
"hw:cpu_model": "SandyBridge",
|
||||||
|
"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": "",
|
||||||
|
"vcpus": 1,
|
||||||
|
"rxtx_factor": 1.0,
|
||||||
|
"description": "test description",
|
||||||
|
"extra_specs": {
|
||||||
|
"key1": "value1",
|
||||||
|
"key2": "value2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -57,3 +57,26 @@ class FlavorsSampleJsonTest2_55(FlavorsSampleJsonTest):
|
|||||||
new_flavor.create()
|
new_flavor.create()
|
||||||
self.flavor_show_id = new_flavor_id
|
self.flavor_show_id = new_flavor_id
|
||||||
self.subs = {'flavorid': new_flavor_id}
|
self.subs = {'flavorid': new_flavor_id}
|
||||||
|
|
||||||
|
|
||||||
|
class FlavorsSampleJsonTest2_61(FlavorsSampleJsonTest):
|
||||||
|
microversion = '2.61'
|
||||||
|
scenarios = [('v2_61', {'api_major_version': 'v2.1'})]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(FlavorsSampleJsonTest2_61, self).setUp()
|
||||||
|
# Get the existing flavors created by DefaultFlavorsFixture.
|
||||||
|
ctxt = nova_context.get_admin_context()
|
||||||
|
flavors = objects.FlavorList.get_all(ctxt)
|
||||||
|
# Flavors are sorted by flavorid in ascending order by default, so
|
||||||
|
# get the last flavor in the list and create a new flavor with an
|
||||||
|
# incremental flavorid so we have a predictable sort order for the
|
||||||
|
# sample response.
|
||||||
|
new_flavor_id = int(flavors[-1].flavorid) + 1
|
||||||
|
new_flavor = objects.Flavor(
|
||||||
|
ctxt, memory_mb=2048, vcpus=1, root_gb=20, flavorid=new_flavor_id,
|
||||||
|
name='m1.small.description', description='test description',
|
||||||
|
extra_specs={"key1": "value1", "key2": "value2"})
|
||||||
|
new_flavor.create()
|
||||||
|
self.flavor_show_id = new_flavor_id
|
||||||
|
self.subs = {'flavorid': new_flavor_id}
|
||||||
|
@ -52,6 +52,8 @@ class FlavorsTestV21(test.TestCase):
|
|||||||
microversion = '2.1'
|
microversion = '2.1'
|
||||||
# Flag to tell the test if a description should be expected in a response.
|
# Flag to tell the test if a description should be expected in a response.
|
||||||
expect_description = False
|
expect_description = False
|
||||||
|
# Flag to tell the test if a extra_specs should be expected in a response.
|
||||||
|
expect_extra_specs = False
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(FlavorsTestV21, self).setUp()
|
super(FlavorsTestV21, self).setUp()
|
||||||
@ -73,6 +75,8 @@ class FlavorsTestV21(test.TestCase):
|
|||||||
expected['swap'] = flavor.swap
|
expected['swap'] = flavor.swap
|
||||||
if self.expect_description:
|
if self.expect_description:
|
||||||
expected['description'] = flavor.description
|
expected['description'] = flavor.description
|
||||||
|
if self.expect_extra_specs:
|
||||||
|
expected['extra_specs'] = flavor.extra_specs
|
||||||
|
|
||||||
@mock.patch('nova.objects.Flavor.get_by_flavor_id',
|
@mock.patch('nova.objects.Flavor.get_by_flavor_id',
|
||||||
side_effect=return_flavor_not_found)
|
side_effect=return_flavor_not_found)
|
||||||
@ -769,6 +773,12 @@ class FlavorsTestV2_55(FlavorsTestV21):
|
|||||||
expect_description = True
|
expect_description = True
|
||||||
|
|
||||||
|
|
||||||
|
class FlavorsTestV2_61(FlavorsTestV2_55):
|
||||||
|
"""Run the same tests as we would for v2.55 but with a extra_specs."""
|
||||||
|
microversion = '2.61'
|
||||||
|
expect_extra_specs = True
|
||||||
|
|
||||||
|
|
||||||
class FlavorsPolicyEnforcementV21(test.NoDBTestCase):
|
class FlavorsPolicyEnforcementV21(test.NoDBTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -705,7 +705,8 @@ FLAVORS = {
|
|||||||
vcpu_weight=None,
|
vcpu_weight=None,
|
||||||
disabled=False,
|
disabled=False,
|
||||||
is_public=True,
|
is_public=True,
|
||||||
description=None
|
description=None,
|
||||||
|
extra_specs={"key1": "value1", "key2": "value2"}
|
||||||
),
|
),
|
||||||
'2': objects.Flavor(
|
'2': objects.Flavor(
|
||||||
id=2,
|
id=2,
|
||||||
@ -720,7 +721,8 @@ FLAVORS = {
|
|||||||
vcpu_weight=None,
|
vcpu_weight=None,
|
||||||
disabled=True,
|
disabled=True,
|
||||||
is_public=True,
|
is_public=True,
|
||||||
description='flavor 2 description'
|
description='flavor 2 description',
|
||||||
|
extra_specs={}
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Exposes flavor extra_specs in the flavor representation since microversion
|
||||||
|
2.61. Flavor extra_specs will be included in Response body of the
|
||||||
|
following APIs:
|
||||||
|
|
||||||
|
* ``GET /flavors/detail``
|
||||||
|
* ``GET /flavors/{flavor_id}``
|
||||||
|
* ``POST /flavors``
|
||||||
|
* ``PUT /flavors/{flavor_id}``
|
||||||
|
|
||||||
|
Now users can see the flavor extra-specs in flavor APIs response and do
|
||||||
|
not need to call ``GET /flavors/{flavor_id}/os-extra_specs`` API. The
|
||||||
|
visibility of the flavor extra_specs within the flavor resource will be
|
||||||
|
controlled by the same policy rules as are used for showing the flavor
|
||||||
|
extra_specs. If the user has no access to query extra_specs, the
|
||||||
|
``flavor.extra_specs`` will not be included.
|
Loading…
x
Reference in New Issue
Block a user