Change to use /flavors in URI
Change-Id: I6a6a571e5485b9e64c34b1a551256c0bd3675ea5 Depends-On: I50358a289c58b827283c9c4c6e068eee17063bfd
This commit is contained in:
parent
c1d2fa7172
commit
24ef8d2793
303
api-ref/source/v1/flavors.inc
Normal file
303
api-ref/source/v1/flavors.inc
Normal file
@ -0,0 +1,303 @@
|
||||
.. -*- rst -*-
|
||||
|
||||
=========
|
||||
Flavors
|
||||
=========
|
||||
|
||||
Show and manage server flavors.
|
||||
|
||||
Flavors are a way to describe the basic dimensions of a instance to be
|
||||
created including how much ``cpu``, ``ram``, and ``disk space`` are
|
||||
allocated to an instance built with this flavor.
|
||||
|
||||
List Flavors
|
||||
============
|
||||
|
||||
.. rest_method:: GET /flavors
|
||||
|
||||
Lists all flavors accessible to your project.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- flavors: flavors
|
||||
- name: flavor_name
|
||||
- links: links
|
||||
- description: flavor_description
|
||||
- uuid: flavor_uuid
|
||||
- created_at: created_at
|
||||
- updated_at: updated_at
|
||||
- is_public: flavor_is_public
|
||||
- extra_specs: flavor_extra_specs
|
||||
|
||||
**Example List flavors**
|
||||
|
||||
.. literalinclude:: samples/flavors/flavors-list-resp.json
|
||||
:language: javascript
|
||||
|
||||
Create Flavor
|
||||
=============
|
||||
|
||||
.. rest_method:: POST /flavors
|
||||
|
||||
Creates a flavor.
|
||||
|
||||
Creating a flavor is typically only available to administrators of a
|
||||
cloud because this has implications for scheduling efficiently in the cloud.
|
||||
|
||||
Normal response codes: 201
|
||||
|
||||
Error response codes: badRequest(400), unauthorized(401), forbidden(403),
|
||||
conflict(409)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- name: flavor_name
|
||||
- description: flavor_description
|
||||
- is_public: flavor_is_public_not_required
|
||||
- uuid: flavor_uuid_not_required
|
||||
|
||||
**Example Create Flavor**
|
||||
|
||||
.. literalinclude:: samples/flavors/flavor-create-post-req.json
|
||||
:language: javascript
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- name: flavor_name
|
||||
- links: links
|
||||
- description: flavor_description
|
||||
- uuid: flavor_uuid
|
||||
- created_at: created_at
|
||||
- updated_at: updated_at
|
||||
- is_public: flavor_is_public
|
||||
- extra_specs: flavor_extra_specs
|
||||
|
||||
**Example Create flavor**
|
||||
|
||||
.. literalinclude:: samples/flavors/flavor-create-post-resp.json
|
||||
:language: javascript
|
||||
|
||||
Update Flavor
|
||||
=============
|
||||
|
||||
.. rest_method:: PUT /flavors/{flavor_uuid}
|
||||
|
||||
Updates a flavor.
|
||||
|
||||
Updating a flavor is typically only available to administrators of a
|
||||
cloud because this has implications for scheduling efficiently in the cloud.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: badRequest(400), unauthorized(401), forbidden(403),
|
||||
conflict(409)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- flavor_uuid: flavor_uuid_path
|
||||
- name: flavor_name
|
||||
- description: flavor_description
|
||||
- is_public: flavor_is_public_not_required
|
||||
|
||||
**Example Update Flavor**
|
||||
|
||||
.. literalinclude:: samples/flavors/flavor-update-put-req.json
|
||||
:language: javascript
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- name: flavor_name
|
||||
- links: links
|
||||
- description: flavor_description
|
||||
- uuid: flavor_uuid
|
||||
- created_at: created_at
|
||||
- updated_at: updated_at
|
||||
- is_public: flavor_is_public
|
||||
- extra_specs: flavor_extra_specs
|
||||
|
||||
**Example Update flavor**
|
||||
|
||||
.. literalinclude:: samples/flavors/flavor-update-put-resp.json
|
||||
:language: javascript
|
||||
|
||||
Show Server Flavor Details
|
||||
==========================
|
||||
|
||||
.. rest_method:: GET /flavors/{flavor_uuid}
|
||||
|
||||
Shows details for a flavor.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403), itemNotFound(404)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- flavor_uuid: flavor_uuid_path
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- name: flavor_name
|
||||
- links: links
|
||||
- description: flavor_description
|
||||
- uuid: flavor_uuid
|
||||
- created_at: created_at
|
||||
- updated_at: updated_at
|
||||
- is_public: flavor_is_public
|
||||
- extra_specs: flavor_extra_specs
|
||||
|
||||
**Example Show Flavor Details**
|
||||
|
||||
.. literalinclude:: samples/flavors/flavor-get-resp.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Delete Flavor
|
||||
=============
|
||||
|
||||
.. rest_method:: DELETE /flavors/{flavor_uuid}
|
||||
|
||||
Deletes a flavor.
|
||||
|
||||
This is typically an admin only action. Deleting a flavor that is in use by
|
||||
existing instances is not recommended as it can cause incorrect data to
|
||||
be returned to the user under some operations.
|
||||
|
||||
Normal response codes: 204
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403), itemNotFound(404)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- flavor_uuid: flavor_uuid_path
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
No body content is returned on a successful DELETE.
|
||||
|
||||
|
||||
List Extra Specs
|
||||
================
|
||||
|
||||
.. rest_method:: GET /flavors/{flavor_uuid}/extraspecs
|
||||
|
||||
Lists all extra specs related to the given flavor.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- flavor_uuid: flavor_uuid_path
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- extra_specs: flavor_extra_specs
|
||||
|
||||
**Example List Extra Specs**
|
||||
|
||||
.. literalinclude:: samples/flavors/flavor-extra-specs-list-resp.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Create/Update Extra Spec
|
||||
========================
|
||||
|
||||
.. rest_method:: PATCH /flavors/{flavor_uuid}/extraspecs
|
||||
|
||||
Create/update extra specs to the given flavor.
|
||||
|
||||
Normal response codes: 201
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- flavor_uuid: flavor_uuid_path
|
||||
- extra_specs: flavor_extra_specs
|
||||
|
||||
**Example Create Extra Specs**
|
||||
|
||||
.. literalinclude:: samples/flavors/flavor-extra-specs-patch-req.json
|
||||
:language: javascript
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- extra_specs: flavor_extra_specs
|
||||
|
||||
**Example Create Extra Specs**
|
||||
|
||||
.. literalinclude:: samples/flavors/flavor-extra-specs-patch-resp.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Delete Extra Spec
|
||||
=================
|
||||
|
||||
.. rest_method:: DELETE /flavors/{flavor_uuid}/extraspecs/key
|
||||
|
||||
Deletes an extra spec related to the specific flavor.
|
||||
|
||||
Normal response codes: 204
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403), itemNotFound(404)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- flavor_uuid: flavor_uuid_path
|
||||
- key: spec_key_path
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
No body content is returned on a successful DELETE.
|
||||
|
@ -10,5 +10,5 @@ Baremetal Compute API V1 (CURRENT)
|
||||
.. include:: instances.inc
|
||||
.. include:: instance_states.inc
|
||||
.. include:: instance_networks.inc
|
||||
.. include:: instance_types.inc
|
||||
.. include:: flavors.inc
|
||||
.. include:: availability_zones.inc
|
||||
|
@ -1,303 +0,0 @@
|
||||
.. -*- rst -*-
|
||||
|
||||
===============
|
||||
Instance Type
|
||||
===============
|
||||
|
||||
Show and manage Instance Types.
|
||||
|
||||
Types are a way to describe the basic dimensions of a instance to be
|
||||
created including how much ``cpu``, ``ram``, and ``disk space`` are
|
||||
allocated to an instance built with this type.
|
||||
|
||||
List Types
|
||||
==========
|
||||
|
||||
.. rest_method:: GET /types
|
||||
|
||||
Lists all types accessible to your project.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- types: types
|
||||
- name: type_name
|
||||
- links: links
|
||||
- description: type_description
|
||||
- uuid: type_uuid
|
||||
- created_at: created_at
|
||||
- updated_at: updated_at
|
||||
- is_public: type_is_public
|
||||
- extra_specs: type_extra_specs
|
||||
|
||||
**Example List types**
|
||||
|
||||
.. literalinclude:: samples/instance_types/types-list-resp.json
|
||||
:language: javascript
|
||||
|
||||
Create Instance Type
|
||||
====================
|
||||
|
||||
.. rest_method:: POST /types
|
||||
|
||||
Creates a type.
|
||||
|
||||
Creating a type is typically only available to administrators of a
|
||||
cloud because this has implications for scheduling efficiently in the cloud.
|
||||
|
||||
Normal response codes: 201
|
||||
|
||||
Error response codes: badRequest(400), unauthorized(401), forbidden(403),
|
||||
conflict(409)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- name: type_name
|
||||
- description: type_description
|
||||
- is_public: type_is_public_not_required
|
||||
- uuid: type_uuid_not_required
|
||||
|
||||
**Example Create Type**
|
||||
|
||||
.. literalinclude:: samples/instance_types/type-create-post-req.json
|
||||
:language: javascript
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- name: type_name
|
||||
- links: links
|
||||
- description: type_description
|
||||
- uuid: type_uuid
|
||||
- created_at: created_at
|
||||
- updated_at: updated_at
|
||||
- is_public: type_is_public
|
||||
- extra_specs: type_extra_specs
|
||||
|
||||
**Example Create type**
|
||||
|
||||
.. literalinclude:: samples/instance_types/type-create-post-resp.json
|
||||
:language: javascript
|
||||
|
||||
Update Instance Type
|
||||
====================
|
||||
|
||||
.. rest_method:: PUT /types/{type_uuid}
|
||||
|
||||
Updates a type.
|
||||
|
||||
Updating a type is typically only available to administrators of a
|
||||
cloud because this has implications for scheduling efficiently in the cloud.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: badRequest(400), unauthorized(401), forbidden(403),
|
||||
conflict(409)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- type_uuid: type_uuid_path
|
||||
- name: type_name
|
||||
- description: type_description
|
||||
- is_public: type_is_public_not_required
|
||||
|
||||
**Example Update Type**
|
||||
|
||||
.. literalinclude:: samples/instance_types/type-update-put-req.json
|
||||
:language: javascript
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- name: type_name
|
||||
- links: links
|
||||
- description: type_description
|
||||
- uuid: type_uuid
|
||||
- created_at: created_at
|
||||
- updated_at: updated_at
|
||||
- is_public: type_is_public
|
||||
- extra_specs: type_extra_specs
|
||||
|
||||
**Example Update type**
|
||||
|
||||
.. literalinclude:: samples/instance_types/type-update-put-resp.json
|
||||
:language: javascript
|
||||
|
||||
Show Instance Type Details
|
||||
==========================
|
||||
|
||||
.. rest_method:: GET /types/{type_uuid}
|
||||
|
||||
Shows details for a type.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403), itemNotFound(404)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- type_uuid: type_uuid_path
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- name: type_name
|
||||
- links: links
|
||||
- description: type_description
|
||||
- uuid: type_uuid
|
||||
- created_at: created_at
|
||||
- updated_at: updated_at
|
||||
- is_public: type_is_public
|
||||
- extra_specs: type_extra_specs
|
||||
|
||||
**Example Show type Details**
|
||||
|
||||
.. literalinclude:: samples/instance_types/type-get-resp.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Delete Instance Type
|
||||
====================
|
||||
|
||||
.. rest_method:: DELETE /types/{type_uuid}
|
||||
|
||||
Deletes a type.
|
||||
|
||||
This is typically an admin only action. Deleting a type that is in use by
|
||||
existing instances is not recommended as it can cause incorrect data to
|
||||
be returned to the user under some operations.
|
||||
|
||||
Normal response codes: 204
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403), itemNotFound(404)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- type_uuid: type_uuid_path
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
No body content is returned on a successful DELETE.
|
||||
|
||||
|
||||
List Extra Specs
|
||||
================
|
||||
|
||||
.. rest_method:: GET /types/{type_uuid}/extraspecs
|
||||
|
||||
Lists all extra specs related to the given type.
|
||||
|
||||
Normal response codes: 200
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- type_uuid: type_uuid_path
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- extra_specs: type_extra_specs
|
||||
|
||||
**Example List Extra Specs**
|
||||
|
||||
.. literalinclude:: samples/instance_types/type-extra-specs-list-resp.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Create/Update Extra Spec
|
||||
========================
|
||||
|
||||
.. rest_method:: PATCH /types/{type_uuid}/extraspecs
|
||||
|
||||
Create/update extra specs to the given type.
|
||||
|
||||
Normal response codes: 201
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- type_uuid: type_uuid_path
|
||||
- extra_specs: type_extra_specs
|
||||
|
||||
**Example Create Extra Specs**
|
||||
|
||||
.. literalinclude:: samples/instance_types/type-extra-specs-patch-req.json
|
||||
:language: javascript
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- extra_specs: type_extra_specs
|
||||
|
||||
**Example Create Extra Specs**
|
||||
|
||||
.. literalinclude:: samples/instance_types/type-extra-specs-patch-resp.json
|
||||
:language: javascript
|
||||
|
||||
|
||||
Delete Extra Spec
|
||||
=================
|
||||
|
||||
.. rest_method:: DELETE /types/{type_uuid}/extraspecs/key
|
||||
|
||||
Deletes an extra spec related to the specific type.
|
||||
|
||||
Normal response codes: 204
|
||||
|
||||
Error response codes: unauthorized(401), forbidden(403), itemNotFound(404)
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- type_uuid: type_uuid_path
|
||||
- key: spec_key_path
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
No body content is returned on a successful DELETE.
|
||||
|
@ -32,7 +32,7 @@ Request
|
||||
|
||||
- name: instance_name
|
||||
- description: instance_description
|
||||
- instance_type_uuid: typeRef
|
||||
- instance_type_uuid: flavorRef
|
||||
- image_uuid: imageRef
|
||||
- availability_zone: availability_zone
|
||||
- networks: networks
|
||||
@ -53,7 +53,7 @@ Response
|
||||
|
||||
- name: instance_name
|
||||
- description: instance_description
|
||||
- instance_type_uuid: typeRef
|
||||
- instance_type_uuid: flavorRef
|
||||
- image_uuid: imageRef
|
||||
- availability_zone: availability_zone
|
||||
- network_info: network_info
|
||||
@ -186,7 +186,7 @@ Response
|
||||
|
||||
- name: instance_name
|
||||
- description: instance_description
|
||||
- instance_type_uuid: typeRef
|
||||
- instance_type_uuid: flavorRef
|
||||
- image_uuid: imageRef
|
||||
- availability_zone: availability_zone
|
||||
- network_info: network_info
|
||||
@ -236,7 +236,7 @@ Response
|
||||
|
||||
- name: instance_name
|
||||
- description: instance_description
|
||||
- instance_type_uuid: typeRef
|
||||
- instance_type_uuid: flavorRef
|
||||
- image_uuid: imageRef
|
||||
- availability_zone: availability_zone
|
||||
- network_info: network_info
|
||||
@ -291,7 +291,7 @@ Response
|
||||
|
||||
- name: instance_name
|
||||
- description: instance_description
|
||||
- instance_type_uuid: typeRef
|
||||
- instance_type_uuid: flavorRef
|
||||
- image_uuid: imageRef
|
||||
- availability_zone: availability_zone
|
||||
- network_info: network_info
|
||||
|
@ -21,6 +21,12 @@ api_version:
|
||||
type: string
|
||||
description: >
|
||||
The API version as returned in the links from the ``GET /`` call.
|
||||
flavor_uuid_path:
|
||||
description: |
|
||||
The UUID of the flavor.
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
instance_ident:
|
||||
description: |
|
||||
The UUID of the instance.
|
||||
@ -33,12 +39,6 @@ spec_key_path:
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
type_uuid_path:
|
||||
description: |
|
||||
The UUID of the type.
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
|
||||
# variables in query
|
||||
all_tenants:
|
||||
@ -125,6 +125,62 @@ fixed_address:
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
flavor_description:
|
||||
description: |
|
||||
The description of the flavor.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
flavor_extra_specs:
|
||||
description: |
|
||||
Extra spec key and value pairs associate with the flavor.
|
||||
in: body
|
||||
required: true
|
||||
type: object
|
||||
flavor_is_public:
|
||||
description: |
|
||||
Whether the flavor is public (available to all projects) or scoped
|
||||
to a set of projects. Default is True if not specified.
|
||||
in: body
|
||||
required: true
|
||||
type: boolean
|
||||
flavor_is_public_not_required:
|
||||
description: |
|
||||
Whether the flavor is public (available to all projects) or scoped
|
||||
to a set of projects. Default is True if not specified.
|
||||
in: body
|
||||
required: true
|
||||
type: boolean
|
||||
flavor_name:
|
||||
description: |
|
||||
The name of the flavor.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
flavor_uuid:
|
||||
description: |
|
||||
The UUID of the flavor.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
flavor_uuid_not_required:
|
||||
description: |
|
||||
The UUID of the flavor.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
flavorRef:
|
||||
description: |
|
||||
The flavor reference, as a UUID for the flavor for your server instance.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
flavors:
|
||||
description: |
|
||||
An array of flavor objects.
|
||||
in: body
|
||||
required: true
|
||||
type: array
|
||||
imageRef:
|
||||
description: |
|
||||
The UUID of the image to use for your instance.
|
||||
@ -275,62 +331,6 @@ provision_state:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
type_description:
|
||||
description: |
|
||||
The description of the type.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
type_extra_specs:
|
||||
description: |
|
||||
Extra spec key and value pairs associate with the type.
|
||||
in: body
|
||||
required: true
|
||||
type: object
|
||||
type_is_public:
|
||||
description: |
|
||||
Whether the type is public (available to all projects) or scoped
|
||||
to a set of projects. Default is True if not specified.
|
||||
in: body
|
||||
required: true
|
||||
type: boolean
|
||||
type_is_public_not_required:
|
||||
description: |
|
||||
Whether the type is public (available to all projects) or scoped
|
||||
to a set of projects. Default is True if not specified.
|
||||
in: body
|
||||
required: true
|
||||
type: boolean
|
||||
type_name:
|
||||
description: |
|
||||
The name of the type.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
type_uuid:
|
||||
description: |
|
||||
The UUID of the type.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
type_uuid_not_required:
|
||||
description: |
|
||||
The UUID of the type.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
typeRef:
|
||||
description: |
|
||||
The type reference, as a UUID or full URL, for the type for your server instance.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
types:
|
||||
description: |
|
||||
An array of type objects.
|
||||
in: body
|
||||
required: true
|
||||
type: array
|
||||
updated_at:
|
||||
description: |
|
||||
The date and time when the resource was updated. The date and time
|
||||
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "test_flavor",
|
||||
"description": "this is a test flavor",
|
||||
"is_public": true
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"description": "this is a test type",
|
||||
"description": "this is a test flavor",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/v1/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"href": "http://10.3.150.17:6688/v1/flavors/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"href": "http://10.3.150.17:6688/flavors/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
@ -15,5 +15,5 @@
|
||||
"updated_at": null,
|
||||
"extra_specs": {},
|
||||
"is_public": true,
|
||||
"name": "test_type"
|
||||
"name": "test_flavor"
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"description": "this is a test type",
|
||||
"description": "this is a test flavor",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/v1/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"href": "http://10.3.150.17:6688/v1/flavors/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"href": "http://10.3.150.17:6688/flavors/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
@ -15,5 +15,5 @@
|
||||
"updated_at": null,
|
||||
"extra_specs": {},
|
||||
"is_public": true,
|
||||
"name": "test_type"
|
||||
"name": "test_flavor"
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "updated_flavor",
|
||||
"description": "this is a flavor to be updated",
|
||||
"is_public": false
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"description": "this is a type to be updated",
|
||||
"description": "this is a flavor to be updated",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/v1/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"href": "http://10.3.150.17:6688/v1/flavors/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"href": "http://10.3.150.17:6688/flavors/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
@ -15,5 +15,5 @@
|
||||
"updated_at": null,
|
||||
"extra_specs": {},
|
||||
"is_public": false,
|
||||
"name": "updated_type"
|
||||
"name": "updated_flavor"
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
{
|
||||
"types": [
|
||||
"flavors": [
|
||||
{
|
||||
"description": "this is a test type1",
|
||||
"description": "this is a test flavor1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/v1/types/2ce3df6b-f571-42e8-b6a8-8f7fa1c019ce",
|
||||
"href": "http://10.3.150.17:6688/v1/flavors/2ce3df6b-f571-42e8-b6a8-8f7fa1c019ce",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/types/2ce3df6b-f571-42e8-b6a8-8f7fa1c019ce",
|
||||
"href": "http://10.3.150.17:6688/flavors/2ce3df6b-f571-42e8-b6a8-8f7fa1c019ce",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
@ -22,14 +22,14 @@
|
||||
"name": "new_test1"
|
||||
},
|
||||
{
|
||||
"description": "this is a test type2",
|
||||
"description": "this is a test flavor2",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/v1/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"href": "http://10.3.150.17:6688/v1/flavors/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://10.3.150.17:6688/types/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"href": "http://10.3.150.17:6688/flavors/7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "test_type",
|
||||
"description": "this is a test type",
|
||||
"is_public": true
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "updated_type",
|
||||
"description": "this is a type to be updated",
|
||||
"is_public": false
|
||||
}
|
@ -181,15 +181,15 @@ function _mogan_cleanup_mogan_dashboard {
|
||||
}
|
||||
|
||||
|
||||
function create_instance_type {
|
||||
openstack baremetal flavor create ${MOGAN_DEFAULT_INSTANCE_TYPE} --description 'Mogan default instance type'
|
||||
function create_flavor {
|
||||
openstack baremetal flavor create ${MOGAN_DEFAULT_FLAVOR} --description 'Mogan default flavor'
|
||||
}
|
||||
|
||||
|
||||
function update_ironic_node_type {
|
||||
ironic_nodes=$(openstack baremetal node list -c UUID -f value)
|
||||
for node in ${ironic_nodes};do
|
||||
openstack baremetal node set --property node_type=${MOGAN_DEFAULT_INSTANCE_TYPE} ${node}
|
||||
openstack baremetal node set --property node_type=${MOGAN_DEFAULT_FLAVOR} ${node}
|
||||
done
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ if is_service_enabled mogan; then
|
||||
init_mogan
|
||||
start_mogan
|
||||
echo_summary "Creating instance type"
|
||||
create_instance_type
|
||||
create_flavor
|
||||
echo_summary "Updating ironic node properties"
|
||||
update_ironic_node_type
|
||||
fi
|
||||
|
@ -27,4 +27,4 @@ MOGAN_SERVICE_PORT=${MOGAN_SERVICE_PORT:-6688}
|
||||
MOGAN_SERVICE_PROTOCOL=${MOGAN_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
|
||||
|
||||
MOGAN_ADMIN_USER=${MOGAN_ADMIN_USER:-mogan}
|
||||
MOGAN_DEFAULT_INSTANCE_TYPE=${MOGAN_DEFAULT_INSTANCE_TYPE:-small}
|
||||
MOGAN_DEFAULT_FLAVOR=${MOGAN_DEFAULT_FLAVOR:-small}
|
||||
|
@ -26,7 +26,7 @@ from wsme import types as wtypes
|
||||
from mogan.api.controllers import base
|
||||
from mogan.api.controllers import link
|
||||
from mogan.api.controllers.v1 import availability_zone
|
||||
from mogan.api.controllers.v1 import instance_types
|
||||
from mogan.api.controllers.v1 import flavors
|
||||
from mogan.api.controllers.v1 import instances
|
||||
from mogan.api import expose
|
||||
|
||||
@ -40,7 +40,7 @@ class V1(base.APIBase):
|
||||
instances = [link.Link]
|
||||
"""Links to the instances resource"""
|
||||
|
||||
types = [link.Link]
|
||||
flavors = [link.Link]
|
||||
"""Links to the instance types resource"""
|
||||
|
||||
availability_zones = [link.Link]
|
||||
@ -57,11 +57,11 @@ class V1(base.APIBase):
|
||||
'instances', '',
|
||||
bookmark=True)
|
||||
]
|
||||
v1.types = [link.Link.make_link('self', pecan.request.public_url,
|
||||
'types', ''),
|
||||
v1.flavors = [link.Link.make_link('self', pecan.request.public_url,
|
||||
'flavors', ''),
|
||||
link.Link.make_link('bookmark',
|
||||
pecan.request.public_url,
|
||||
'types', '',
|
||||
'flavors', '',
|
||||
bookmark=True)
|
||||
]
|
||||
v1.availability_zones = [link.Link.make_link('self',
|
||||
@ -78,7 +78,7 @@ class V1(base.APIBase):
|
||||
class Controller(rest.RestController):
|
||||
"""Version 1 API controller root."""
|
||||
|
||||
types = instance_types.InstanceTypeController()
|
||||
flavors = flavors.FlavorsController()
|
||||
instances = instances.InstanceController()
|
||||
availability_zones = availability_zone.AvailabilityZoneController()
|
||||
|
||||
|
201
mogan/api/controllers/v1/flavors.py
Normal file
201
mogan/api/controllers/v1/flavors.py
Normal file
@ -0,0 +1,201 @@
|
||||
# Copyright 2016 Huawei Technologies Co.,LTD.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
from six.moves import http_client
|
||||
import wsme
|
||||
from wsme import types as wtypes
|
||||
|
||||
from mogan.api.controllers import base
|
||||
from mogan.api.controllers import link
|
||||
from mogan.api.controllers.v1 import types
|
||||
from mogan.api import expose
|
||||
from mogan.common import exception
|
||||
from mogan.common.i18n import _
|
||||
from mogan import objects
|
||||
|
||||
|
||||
class Flavor(base.APIBase):
|
||||
"""API representation of a flavor.
|
||||
|
||||
This class enforces type checking and value constraints, and converts
|
||||
between the internal object model and the API representation of
|
||||
a flavor.
|
||||
"""
|
||||
uuid = types.uuid
|
||||
"""The UUID of the flavor"""
|
||||
|
||||
name = wtypes.text
|
||||
"""The name of the flavor"""
|
||||
|
||||
description = wtypes.text
|
||||
"""The description of the flavor"""
|
||||
|
||||
is_public = types.boolean
|
||||
"""Indicates whether the flavor is public."""
|
||||
|
||||
extra_specs = {wtypes.text: types.jsontype}
|
||||
"""The extra specs of the flavor"""
|
||||
|
||||
links = wsme.wsattr([link.Link], readonly=True)
|
||||
"""A list containing a self link"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fields = []
|
||||
for field in objects.InstanceType.fields:
|
||||
# Skip fields we do not expose.
|
||||
if not hasattr(self, field):
|
||||
continue
|
||||
self.fields.append(field)
|
||||
setattr(self, field, kwargs.get(field, wtypes.Unset))
|
||||
|
||||
@classmethod
|
||||
def convert_with_links(cls, rpc_flavor):
|
||||
flavor = Flavor(**rpc_flavor.as_dict())
|
||||
url = pecan.request.public_url
|
||||
flavor.links = [link.Link.make_link('self', url,
|
||||
'flavors',
|
||||
flavor.uuid),
|
||||
link.Link.make_link('bookmark', url,
|
||||
'flavors',
|
||||
flavor.uuid,
|
||||
bookmark=True)
|
||||
]
|
||||
|
||||
return flavor
|
||||
|
||||
|
||||
class FlavorCollection(base.APIBase):
|
||||
"""API representation of a collection of flavor."""
|
||||
|
||||
flavors = [Flavor]
|
||||
"""A list containing Flavor objects"""
|
||||
|
||||
@staticmethod
|
||||
def convert_with_links(flavors, url=None, **kwargs):
|
||||
collection = FlavorCollection()
|
||||
collection.flavors = [Flavor.convert_with_links(flavor)
|
||||
for flavor in flavors]
|
||||
return collection
|
||||
|
||||
|
||||
class FlavorExtraSpecsController(rest.RestController):
|
||||
"""REST controller for flavor extra specs."""
|
||||
|
||||
@expose.expose(wtypes.text, types.uuid)
|
||||
def get_all(self, flavor_uuid):
|
||||
"""Retrieve a list of extra specs of the queried flavor."""
|
||||
|
||||
flavor = objects.InstanceType.get(pecan.request.context,
|
||||
flavor_uuid)
|
||||
return dict(extra_specs=flavor.extra_specs)
|
||||
|
||||
@expose.expose(types.jsontype, types.uuid, body=types.jsontype,
|
||||
status_code=http_client.ACCEPTED)
|
||||
def patch(self, flavor_uuid, extra_spec):
|
||||
"""Create/update extra specs for the given flavor."""
|
||||
|
||||
flavor = objects.InstanceType.get(pecan.request.context,
|
||||
flavor_uuid)
|
||||
flavor.extra_specs = dict(flavor.extra_specs, **extra_spec)
|
||||
flavor.save()
|
||||
return dict(extra_specs=flavor.extra_specs)
|
||||
|
||||
@expose.expose(None, types.uuid, wtypes.text,
|
||||
status_code=http_client.NO_CONTENT)
|
||||
def delete(self, flavor_uuid, spec_name):
|
||||
"""Delete an extra specs for the given flavor."""
|
||||
|
||||
flavor = objects.InstanceType.get(pecan.request.context,
|
||||
flavor_uuid)
|
||||
del flavor.extra_specs[spec_name]
|
||||
flavor.save()
|
||||
|
||||
|
||||
class FlavorsController(rest.RestController):
|
||||
"""REST controller for Flavors."""
|
||||
|
||||
extraspecs = FlavorExtraSpecsController()
|
||||
|
||||
@expose.expose(FlavorCollection)
|
||||
def get_all(self):
|
||||
"""Retrieve a list of flavor."""
|
||||
|
||||
flavors = objects.InstanceType.list(pecan.request.context)
|
||||
return FlavorCollection.convert_with_links(flavors)
|
||||
|
||||
@expose.expose(Flavor, types.uuid)
|
||||
def get_one(self, flavor_uuid):
|
||||
"""Retrieve information about the given flavor.
|
||||
|
||||
:param flavor_uuid: UUID of a flavor.
|
||||
"""
|
||||
rpc_flavor = objects.InstanceType.get(pecan.request.context,
|
||||
flavor_uuid)
|
||||
return Flavor.convert_with_links(rpc_flavor)
|
||||
|
||||
@expose.expose(Flavor, body=Flavor,
|
||||
status_code=http_client.CREATED)
|
||||
def post(self, flavor):
|
||||
"""Create an new flavor.
|
||||
|
||||
:param flavor: a flavor within the request body.
|
||||
"""
|
||||
new_flavor = objects.InstanceType(pecan.request.context,
|
||||
**flavor.as_dict())
|
||||
new_flavor.create()
|
||||
# Set the HTTP Location Header
|
||||
pecan.response.location = link.build_url('flavors',
|
||||
new_flavor.uuid)
|
||||
return Flavor.convert_with_links(new_flavor)
|
||||
|
||||
@expose.expose(Flavor, types.uuid, body=Flavor)
|
||||
def put(self, flavor_uuid, flavor):
|
||||
"""Update a flavor.
|
||||
|
||||
:param flavor_uuid: the uuid of the flavor to be updated.
|
||||
:param flavor: a flavor within the request body.
|
||||
"""
|
||||
try:
|
||||
flavor_in_db = objects.InstanceType.get(
|
||||
pecan.request.context, flavor_uuid)
|
||||
except exception.InstanceTypeNotFound:
|
||||
msg = (_("InstanceType %s could not be found") %
|
||||
flavor_uuid)
|
||||
raise wsme.exc.ClientSideError(
|
||||
msg, status_code=http_client.BAD_REQUEST)
|
||||
need_to_update = False
|
||||
for attr in ('name', 'description', 'is_public'):
|
||||
if getattr(flavor, attr) != wtypes.Unset:
|
||||
need_to_update = True
|
||||
setattr(flavor_in_db, attr, getattr(flavor, attr))
|
||||
# don't need to call db_api if no update
|
||||
if need_to_update:
|
||||
flavor_in_db.save()
|
||||
# Set the HTTP Location Header
|
||||
pecan.response.location = link.build_url('flavor',
|
||||
flavor_in_db.uuid)
|
||||
return Flavor.convert_with_links(flavor_in_db)
|
||||
|
||||
@expose.expose(None, types.uuid, status_code=http_client.NO_CONTENT)
|
||||
def delete(self, flavor_uuid):
|
||||
"""Delete a flavor.
|
||||
|
||||
:param flavor_uuid: UUID of a flavor.
|
||||
"""
|
||||
rpc_flavor = objects.InstanceType.get(pecan.request.context,
|
||||
flavor_uuid)
|
||||
rpc_flavor.destroy()
|
@ -1,202 +0,0 @@
|
||||
# Copyright 2016 Huawei Technologies Co.,LTD.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
from six.moves import http_client
|
||||
import wsme
|
||||
from wsme import types as wtypes
|
||||
|
||||
from mogan.api.controllers import base
|
||||
from mogan.api.controllers import link
|
||||
from mogan.api.controllers.v1 import types
|
||||
from mogan.api import expose
|
||||
from mogan.common import exception
|
||||
from mogan.common.i18n import _
|
||||
from mogan import objects
|
||||
|
||||
|
||||
class InstanceType(base.APIBase):
|
||||
"""API representation of an instance type.
|
||||
|
||||
This class enforces type checking and value constraints, and converts
|
||||
between the internal object model and the API representation of
|
||||
an instance type.
|
||||
"""
|
||||
uuid = types.uuid
|
||||
"""The UUID of the instance type"""
|
||||
|
||||
name = wtypes.text
|
||||
"""The name of the instance type"""
|
||||
|
||||
description = wtypes.text
|
||||
"""The description of the instance type"""
|
||||
|
||||
is_public = types.boolean
|
||||
"""Indicates whether the instance type is public."""
|
||||
|
||||
extra_specs = {wtypes.text: types.jsontype}
|
||||
"""The extra specs of the instance type"""
|
||||
|
||||
links = wsme.wsattr([link.Link], readonly=True)
|
||||
"""A list containing a self link"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fields = []
|
||||
for field in objects.InstanceType.fields:
|
||||
# Skip fields we do not expose.
|
||||
if not hasattr(self, field):
|
||||
continue
|
||||
self.fields.append(field)
|
||||
setattr(self, field, kwargs.get(field, wtypes.Unset))
|
||||
|
||||
@classmethod
|
||||
def convert_with_links(cls, rpc_instance_type):
|
||||
instance_type = InstanceType(**rpc_instance_type.as_dict())
|
||||
url = pecan.request.public_url
|
||||
instance_type.links = [link.Link.make_link('self', url,
|
||||
'types',
|
||||
instance_type.uuid),
|
||||
link.Link.make_link('bookmark', url,
|
||||
'types',
|
||||
instance_type.uuid,
|
||||
bookmark=True)
|
||||
]
|
||||
|
||||
return instance_type
|
||||
|
||||
|
||||
class InstanceTypeCollection(base.APIBase):
|
||||
"""API representation of a collection of instance type."""
|
||||
|
||||
types = [InstanceType]
|
||||
"""A list containing Instance Type objects"""
|
||||
|
||||
@staticmethod
|
||||
def convert_with_links(instance_types, url=None, **kwargs):
|
||||
collection = InstanceTypeCollection()
|
||||
collection.types = [InstanceType.convert_with_links(type1)
|
||||
for type1 in instance_types]
|
||||
return collection
|
||||
|
||||
|
||||
class TypeExtraSpecController(rest.RestController):
|
||||
"""REST controller for Instance Type extra spec."""
|
||||
|
||||
@expose.expose(wtypes.text, types.uuid)
|
||||
def get_all(self, instance_type_uuid):
|
||||
"""Retrieve a list of extra specs of the queried instance type."""
|
||||
|
||||
instance_type = objects.InstanceType.get(pecan.request.context,
|
||||
instance_type_uuid)
|
||||
return dict(extra_specs=instance_type.extra_specs)
|
||||
|
||||
@expose.expose(types.jsontype, types.uuid, body=types.jsontype,
|
||||
status_code=http_client.ACCEPTED)
|
||||
def patch(self, instance_type_uuid, extra_spec):
|
||||
"""Create/update extra specs for the given instance type."""
|
||||
|
||||
instance_type = objects.InstanceType.get(pecan.request.context,
|
||||
instance_type_uuid)
|
||||
instance_type.extra_specs = dict(instance_type.extra_specs,
|
||||
**extra_spec)
|
||||
instance_type.save()
|
||||
return dict(extra_specs=instance_type.extra_specs)
|
||||
|
||||
@expose.expose(None, types.uuid, wtypes.text,
|
||||
status_code=http_client.NO_CONTENT)
|
||||
def delete(self, instance_type_uuid, spec_name):
|
||||
"""Delete an extra specs for the given instance type."""
|
||||
|
||||
instance_type = objects.InstanceType.get(pecan.request.context,
|
||||
instance_type_uuid)
|
||||
del instance_type.extra_specs[spec_name]
|
||||
instance_type.save()
|
||||
|
||||
|
||||
class InstanceTypeController(rest.RestController):
|
||||
"""REST controller for Instance Type."""
|
||||
|
||||
extraspecs = TypeExtraSpecController()
|
||||
|
||||
@expose.expose(InstanceTypeCollection)
|
||||
def get_all(self):
|
||||
"""Retrieve a list of instance type."""
|
||||
|
||||
instance_types = objects.InstanceType.list(pecan.request.context)
|
||||
return InstanceTypeCollection.convert_with_links(instance_types)
|
||||
|
||||
@expose.expose(InstanceType, types.uuid)
|
||||
def get_one(self, instance_type_uuid):
|
||||
"""Retrieve information about the given instance type.
|
||||
|
||||
:param instance_type_uuid: UUID of a instance type.
|
||||
"""
|
||||
rpc_instance_type = objects.InstanceType.get(pecan.request.context,
|
||||
instance_type_uuid)
|
||||
return InstanceType.convert_with_links(rpc_instance_type)
|
||||
|
||||
@expose.expose(InstanceType, body=InstanceType,
|
||||
status_code=http_client.CREATED)
|
||||
def post(self, instance_type):
|
||||
"""Create an new instance type.
|
||||
|
||||
:param instance_type: a instance type within the request body.
|
||||
"""
|
||||
new_instance_type = objects.InstanceType(pecan.request.context,
|
||||
**instance_type.as_dict())
|
||||
new_instance_type.create()
|
||||
# Set the HTTP Location Header
|
||||
pecan.response.location = link.build_url('types',
|
||||
new_instance_type.uuid)
|
||||
return InstanceType.convert_with_links(new_instance_type)
|
||||
|
||||
@expose.expose(InstanceType, types.uuid, body=InstanceType)
|
||||
def put(self, instance_type_uuid, instance_type):
|
||||
"""Update an instance type.
|
||||
|
||||
:param instance_type_uuid: the uuid of instance_type to be updated.
|
||||
:param instance_type: a instance type within the request body.
|
||||
"""
|
||||
try:
|
||||
inst_type_in_db = objects.InstanceType.get(
|
||||
pecan.request.context, instance_type_uuid)
|
||||
except exception.InstanceTypeNotFound:
|
||||
msg = (_("InstanceType %s could not be found") %
|
||||
instance_type_uuid)
|
||||
raise wsme.exc.ClientSideError(
|
||||
msg, status_code=http_client.BAD_REQUEST)
|
||||
need_to_update = False
|
||||
for attr in ('name', 'description', 'is_public'):
|
||||
if getattr(instance_type, attr) != wtypes.Unset:
|
||||
need_to_update = True
|
||||
setattr(inst_type_in_db, attr, getattr(instance_type, attr))
|
||||
# don't need to call db_api if no update
|
||||
if need_to_update:
|
||||
inst_type_in_db.save()
|
||||
# Set the HTTP Location Header
|
||||
pecan.response.location = link.build_url('instance_type',
|
||||
inst_type_in_db.uuid)
|
||||
return InstanceType.convert_with_links(inst_type_in_db)
|
||||
|
||||
@expose.expose(None, types.uuid, status_code=http_client.NO_CONTENT)
|
||||
def delete(self, instance_type_uuid):
|
||||
"""Delete an instance type.
|
||||
|
||||
:param instance_type_uuid: UUID of an instance type.
|
||||
"""
|
||||
rpc_instance_type = objects.InstanceType.get(pecan.request.context,
|
||||
instance_type_uuid)
|
||||
rpc_instance_type.destroy()
|
@ -1,4 +1,3 @@
|
||||
#
|
||||
# Copyright 2016 Huawei Technologies Co., Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
@ -21,27 +20,27 @@ from oslo_serialization import jsonutils
|
||||
from mogan.tests.functional.api import v1 as v1_test
|
||||
|
||||
|
||||
class TestInstanceType(v1_test.APITestV1):
|
||||
class TestFlavor(v1_test.APITestV1):
|
||||
|
||||
TYPE_UUIDS = ['ff28b5a2-73e5-431c-b4b7-1b96b74bca7b',
|
||||
FLAVOR_UUIDS = ['ff28b5a2-73e5-431c-b4b7-1b96b74bca7b',
|
||||
'94baf80e-2bae-4c3e-8dab-38b5441e7097',
|
||||
'4bcfff85-c55a-493b-b544-b6c90b8fb397',
|
||||
'e50fb289-4ee1-47dd-b371-6ca39af12888']
|
||||
|
||||
def setUp(self):
|
||||
super(TestInstanceType, self).setUp()
|
||||
super(TestFlavor, self).setUp()
|
||||
|
||||
@mock.patch('oslo_utils.uuidutils.generate_uuid')
|
||||
def _prepare_instance_types(self, mocked):
|
||||
mocked.side_effect = self.TYPE_UUIDS
|
||||
def _prepare_flavors(self, mocked):
|
||||
mocked.side_effect = self.FLAVOR_UUIDS
|
||||
for i in six.moves.xrange(4):
|
||||
body = {"name": "test" + str(i),
|
||||
"description": "just test" + str(i)}
|
||||
self.post_json('/types', body, status=201)
|
||||
self.post_json('/flavors', body, status=201)
|
||||
|
||||
def test_instance_type_post(self):
|
||||
def test_flavor_post(self):
|
||||
body = {"name": "test", "description": "just test"}
|
||||
resp = self.post_json('/types', body, status=201)
|
||||
resp = self.post_json('/flavors', body, status=201)
|
||||
resp = resp.json
|
||||
self.assertEqual('test', resp['name'])
|
||||
self.assertEqual('just test', resp['description'])
|
||||
@ -50,76 +49,76 @@ class TestInstanceType(v1_test.APITestV1):
|
||||
self.assertIn('extra_specs', resp)
|
||||
self.assertIn('links', resp)
|
||||
|
||||
def test_instance_type_get_all(self):
|
||||
self._prepare_instance_types()
|
||||
resp = self.get_json('/types')
|
||||
self.assertEqual(4, len(resp['types']))
|
||||
def test_flavor_get_all(self):
|
||||
self._prepare_flavors()
|
||||
resp = self.get_json('/flavors')
|
||||
self.assertEqual(4, len(resp['flavors']))
|
||||
|
||||
def test_instance_type_get_one(self):
|
||||
self._prepare_instance_types()
|
||||
resp = self.get_json('/types/' + self.TYPE_UUIDS[0])
|
||||
def test_flavor_get_one(self):
|
||||
self._prepare_flavors()
|
||||
resp = self.get_json('/flavors/' + self.FLAVOR_UUIDS[0])
|
||||
self.assertEqual('test0', resp['name'])
|
||||
self.assertEqual('just test0', resp['description'])
|
||||
|
||||
def test_instance_type_delete(self):
|
||||
self._prepare_instance_types()
|
||||
resp = self.get_json('/types')
|
||||
self.assertEqual(4, len(resp['types']))
|
||||
self.delete('/types/' + self.TYPE_UUIDS[0], status=204)
|
||||
resp = self.get_json('/types')
|
||||
self.assertEqual(3, len(resp['types']))
|
||||
def test_flavor_delete(self):
|
||||
self._prepare_flavors()
|
||||
resp = self.get_json('/flavors')
|
||||
self.assertEqual(4, len(resp['flavors']))
|
||||
self.delete('/flavors/' + self.FLAVOR_UUIDS[0], status=204)
|
||||
resp = self.get_json('/flavors')
|
||||
self.assertEqual(3, len(resp['flavors']))
|
||||
|
||||
def test_instance_type_update(self):
|
||||
self._prepare_instance_types()
|
||||
resp = self.get_json('/types/' + self.TYPE_UUIDS[0])
|
||||
def test_flavor_update(self):
|
||||
self._prepare_flavors()
|
||||
resp = self.get_json('/flavors/' + self.FLAVOR_UUIDS[0])
|
||||
self.assertEqual('test0', resp['name'])
|
||||
self.assertEqual('just test0', resp['description'])
|
||||
values = {"name": "update_name", "description": "updated_description",
|
||||
"is_public": False}
|
||||
self.put_json('/types/' + self.TYPE_UUIDS[0], values, status=200)
|
||||
resp = self.get_json('/types/' + self.TYPE_UUIDS[0])
|
||||
self.put_json('/flavors/' + self.FLAVOR_UUIDS[0], values, status=200)
|
||||
resp = self.get_json('/flavors/' + self.FLAVOR_UUIDS[0])
|
||||
self.assertEqual('update_name', resp['name'])
|
||||
self.assertEqual('updated_description', resp['description'])
|
||||
self.assertEqual(False, resp['is_public'])
|
||||
|
||||
|
||||
class TestInstanceTypeExtra(v1_test.APITestV1):
|
||||
TYPE_UUID = 'ff28b5a2-73e5-431c-b4b7-1b96b74bca7b'
|
||||
class TestFlavorExtra(v1_test.APITestV1):
|
||||
FLAVOR_UUID = 'ff28b5a2-73e5-431c-b4b7-1b96b74bca7b'
|
||||
|
||||
def setUp(self):
|
||||
super(TestInstanceTypeExtra, self).setUp()
|
||||
self._prepare_instance_type()
|
||||
super(TestFlavorExtra, self).setUp()
|
||||
self._prepare_flavor()
|
||||
|
||||
@mock.patch('oslo_utils.uuidutils.generate_uuid')
|
||||
def _prepare_instance_type(self, mocked):
|
||||
mocked.return_value = self.TYPE_UUID
|
||||
body = {"name": "test_type_extra",
|
||||
"description": "just test type extra"}
|
||||
self.post_json('/types', body, status=201)
|
||||
def _prepare_flavor(self, mocked):
|
||||
mocked.return_value = self.FLAVOR_UUID
|
||||
body = {"name": "test_flavor_extra",
|
||||
"description": "just test flavor extra"}
|
||||
self.post_json('/flavors', body, status=201)
|
||||
|
||||
def test_list_extra_empty(self):
|
||||
resp = self.get_json('/types/%s/extraspecs' % self.TYPE_UUID)
|
||||
resp = self.get_json('/flavors/%s/extraspecs' % self.FLAVOR_UUID)
|
||||
self.assertEqual({}, resp['extra_specs'])
|
||||
|
||||
def test_add_extra(self):
|
||||
resp = self.patch_json('/types/%s/extraspecs' % self.TYPE_UUID,
|
||||
resp = self.patch_json('/flavors/%s/extraspecs' % self.FLAVOR_UUID,
|
||||
{'test_key': 'test_value'})
|
||||
resp = resp.json
|
||||
self.assertEqual({'extra_specs': {'test_key': 'test_value'}}, resp)
|
||||
|
||||
def test_update_extra(self):
|
||||
resp = self.patch_json('/types/%s/extraspecs' % self.TYPE_UUID,
|
||||
resp = self.patch_json('/flavors/%s/extraspecs' % self.FLAVOR_UUID,
|
||||
{'test_key': 'test_value1'})
|
||||
resp = resp.json
|
||||
self.assertEqual({'extra_specs': {'test_key': 'test_value1'}}, resp)
|
||||
|
||||
resp = self.patch_json('/types/%s/extraspecs' % self.TYPE_UUID,
|
||||
resp = self.patch_json('/flavors/%s/extraspecs' % self.FLAVOR_UUID,
|
||||
{'test_key': 'test_value2'})
|
||||
resp = resp.json
|
||||
self.assertEqual({'extra_specs': {'test_key': 'test_value2'}}, resp)
|
||||
|
||||
def test_list_extra(self):
|
||||
resp = self.patch_json('/types/%s/extraspecs' % self.TYPE_UUID,
|
||||
resp = self.patch_json('/flavors/%s/extraspecs' % self.FLAVOR_UUID,
|
||||
{'test_key1': 'test_value1',
|
||||
'test_key2': 'test_value2'})
|
||||
resp = resp.json
|
||||
@ -127,16 +126,16 @@ class TestInstanceTypeExtra(v1_test.APITestV1):
|
||||
'{"test_key1": "test_value1", "test_key2": "test_value2"}',
|
||||
jsonutils.dumps(resp['extra_specs'], sort_keys=True))
|
||||
|
||||
self.patch_json('/types/%s/extraspecs' % self.TYPE_UUID,
|
||||
self.patch_json('/flavors/%s/extraspecs' % self.FLAVOR_UUID,
|
||||
{'test_key3': 'test_value3'})
|
||||
resp = self.get_json('/types/%s/extraspecs' % self.TYPE_UUID)
|
||||
resp = self.get_json('/flavors/%s/extraspecs' % self.FLAVOR_UUID)
|
||||
self.assertEqual(
|
||||
'{"test_key1": "test_value1", "test_key2": "test_value2", '
|
||||
'"test_key3": "test_value3"}',
|
||||
jsonutils.dumps(resp['extra_specs'], sort_keys=True))
|
||||
|
||||
def test_delete_extra(self):
|
||||
resp = self.patch_json('/types/%s/extraspecs' % self.TYPE_UUID,
|
||||
resp = self.patch_json('/flavors/%s/extraspecs' % self.FLAVOR_UUID,
|
||||
{'test_key1': 'test_value1',
|
||||
'test_key2': 'test_value2'})
|
||||
resp = resp.json
|
||||
@ -144,6 +143,6 @@ class TestInstanceTypeExtra(v1_test.APITestV1):
|
||||
'{"test_key1": "test_value1", "test_key2": "test_value2"}',
|
||||
jsonutils.dumps(resp['extra_specs'], sort_keys=True))
|
||||
|
||||
self.delete('/types/%s/extraspecs/test_key1' % self.TYPE_UUID)
|
||||
resp = self.get_json('/types/%s/extraspecs' % self.TYPE_UUID)
|
||||
self.delete('/flavors/%s/extraspecs/test_key1' % self.FLAVOR_UUID)
|
||||
resp = self.get_json('/flavors/%s/extraspecs' % self.FLAVOR_UUID)
|
||||
self.assertEqual({'test_key2': 'test_value2'}, resp['extra_specs'])
|
@ -101,7 +101,7 @@ class TestInstances(v1_test.APITestV1):
|
||||
expect_errors=True)
|
||||
|
||||
def _clean_type(self):
|
||||
self.delete('/types/' + self.INSTANCE_TYPE_UUID, status=204)
|
||||
self.delete('/flavors/' + self.INSTANCE_TYPE_UUID, status=204)
|
||||
|
||||
def _make_app(self):
|
||||
return super(TestInstances, self)._make_app()
|
||||
@ -111,7 +111,7 @@ class TestInstances(v1_test.APITestV1):
|
||||
mocked.side_effect = [self.INSTANCE_TYPE_UUID]
|
||||
body = {"name": "type_for_instance_testing",
|
||||
"description": "type for instance testing"}
|
||||
self.post_json('/types', body, status=201)
|
||||
self.post_json('/flavors', body, status=201)
|
||||
|
||||
@mock.patch('oslo_utils.uuidutils.generate_uuid')
|
||||
def _prepare_instance(self, amount, mocked):
|
||||
|
@ -50,10 +50,10 @@ class BaseBaremetalComputeTest(tempest.test.BaseTestCase):
|
||||
|
||||
@classmethod
|
||||
def _get_small_flavor(cls):
|
||||
types = cls.baremetal_compute_client.list_instance_types()
|
||||
for t in types:
|
||||
if t['name'] == 'small':
|
||||
return t['uuid']
|
||||
flavors = cls.baremetal_compute_client.list_flavors()
|
||||
for f in flavors:
|
||||
if f['name'] == 'small':
|
||||
return f['uuid']
|
||||
else:
|
||||
# TODO(liusheng) we shouldn't depend on the default
|
||||
# type created by devstack
|
||||
@ -70,7 +70,7 @@ class BaseBaremetalComputeTest(tempest.test.BaseTestCase):
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(BaseBaremetalComputeTest, cls).resource_setup()
|
||||
cls.type_ids = []
|
||||
cls.flavor_ids = []
|
||||
cls.instance_ids = []
|
||||
cls.small_flavor = cls._get_small_flavor()
|
||||
cls.image_id = CONF.compute.image_ref
|
||||
@ -129,7 +129,7 @@ class BaseBaremetalComputeTest(tempest.test.BaseTestCase):
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.cleanup_resources(
|
||||
cls.baremetal_compute_client.delete_instance_type, cls.type_ids)
|
||||
cls.baremetal_compute_client.delete_flavor, cls.flavor_ids)
|
||||
cls.cleanup_resources(cls.baremetal_compute_client.delete_instance,
|
||||
cls.instance_ids)
|
||||
super(BaseBaremetalComputeTest, cls).resource_cleanup()
|
||||
|
@ -1,4 +1,3 @@
|
||||
#
|
||||
# Copyright 2016 Huawei Technologies Co., Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
@ -28,48 +27,48 @@ class BaremetalComputeAPITest(base.BaseBaremetalComputeTest):
|
||||
def resource_setup(cls):
|
||||
super(BaremetalComputeAPITest, cls).resource_setup()
|
||||
for i in six.moves.xrange(3):
|
||||
body = {"name": data_utils.rand_name('mogan_instance_type'),
|
||||
"description": "mogan instance type description",
|
||||
body = {"name": data_utils.rand_name('mogan_flavor'),
|
||||
"description": "mogan flavor description",
|
||||
'is_public': bool(data_utils.rand_int_id(0, 1))}
|
||||
resp = cls.baremetal_compute_client.create_instance_type(**body)
|
||||
cls.type_ids.append(resp['uuid'])
|
||||
resp = cls.baremetal_compute_client.create_flavor(**body)
|
||||
cls.flavor_ids.append(resp['uuid'])
|
||||
|
||||
@decorators.idempotent_id('4b256d35-47a9-4195-8f7e-56ceb4ce4737')
|
||||
def test_type_list(self):
|
||||
def test_flavor_list(self):
|
||||
# List instance types
|
||||
type_list = self.baremetal_compute_client.list_instance_types()
|
||||
flavor_list = self.baremetal_compute_client.list_flavors()
|
||||
|
||||
# Verify created instance type in the list
|
||||
fetched_ids = [t['uuid'] for t in type_list]
|
||||
missing_types = [a for a in self.type_ids if a not in fetched_ids]
|
||||
self.assertEqual(0, len(missing_types),
|
||||
fetched_ids = [f['uuid'] for f in flavor_list]
|
||||
missing_flavors = [a for a in self.flavor_ids if a not in fetched_ids]
|
||||
self.assertEqual(0, len(missing_flavors),
|
||||
"Failed to find the following created"
|
||||
" instance_type(s) in a fetched list: %s" %
|
||||
', '.join(str(t) for t in missing_types))
|
||||
" flavor(s) in a fetched list: %s" %
|
||||
', '.join(str(t) for t in missing_flavors))
|
||||
|
||||
@decorators.idempotent_id('f6ad64af-abc9-456c-9109-bc27cd9af635')
|
||||
def test_type_create_show_delete(self):
|
||||
# Create an instance type
|
||||
body = {"name": 'mogan_type_create',
|
||||
"description": "mogan instance type description",
|
||||
def test_flavor_create_show_delete(self):
|
||||
# Create a flavor
|
||||
body = {"name": 'mogan_flavor_create',
|
||||
"description": "mogan flavor description",
|
||||
'is_public': True}
|
||||
resp = self.baremetal_compute_client.create_instance_type(**body)
|
||||
self.assertEqual('mogan_type_create', resp['name'])
|
||||
self.assertEqual('mogan instance type description',
|
||||
resp = self.baremetal_compute_client.create_flavor(**body)
|
||||
self.assertEqual('mogan_flavor_create', resp['name'])
|
||||
self.assertEqual('mogan flavor description',
|
||||
resp['description'])
|
||||
self.assertEqual(True, resp['is_public'])
|
||||
self.assertIn('uuid', resp)
|
||||
self.assertIn('extra_specs', resp)
|
||||
self.assertIn('links', resp)
|
||||
resp = self.baremetal_compute_client.show_instance_type(resp['uuid'])
|
||||
self.assertEqual('mogan_type_create', resp['name'])
|
||||
self.assertEqual('mogan instance type description',
|
||||
resp = self.baremetal_compute_client.show_flavor(resp['uuid'])
|
||||
self.assertEqual('mogan_flavor_create', resp['name'])
|
||||
self.assertEqual('mogan flavor description',
|
||||
resp['description'])
|
||||
self.assertEqual(True, resp['is_public'])
|
||||
self.assertIn('uuid', resp)
|
||||
self.assertIn('extra_specs', resp)
|
||||
self.assertIn('links', resp)
|
||||
self.baremetal_compute_client.delete_instance_type(resp['uuid'])
|
||||
self.baremetal_compute_client.delete_flavor(resp['uuid'])
|
||||
self.assertRaises(lib_exc.NotFound,
|
||||
self.baremetal_compute_client.show_instance_type,
|
||||
self.baremetal_compute_client.show_flavor,
|
||||
resp['uuid'])
|
@ -36,30 +36,30 @@ class BaremetalComputeClient(rest_client.RestClient):
|
||||
def serialize(self, body):
|
||||
return json.dumps(body)
|
||||
|
||||
def list_instance_types(self):
|
||||
uri = '%s/types' % self.uri_prefix
|
||||
def list_flavors(self):
|
||||
uri = '%s/flavors' % self.uri_prefix
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)['types']
|
||||
body = self.deserialize(body)['flavors']
|
||||
return rest_client.ResponseBodyList(resp, body)
|
||||
|
||||
def show_instance_type(self, type_id):
|
||||
uri = '%s/types/%s' % (self.uri_prefix, type_id)
|
||||
def show_flavor(self, flavor_uuid):
|
||||
uri = '%s/flavors/%s' % (self.uri_prefix, flavor_uuid)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_instance_type(self, type_id):
|
||||
uri = "%s/types/%s" % (self.uri_prefix, type_id)
|
||||
def delete_flavor(self, flavor_uuid):
|
||||
uri = "%s/flavors/%s" % (self.uri_prefix, flavor_uuid)
|
||||
resp, body = self.delete(uri)
|
||||
self.expected_success(204, resp.status)
|
||||
if body:
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def create_instance_type(self, **kwargs):
|
||||
uri = "%s/types" % self.uri_prefix
|
||||
def create_flavor(self, **kwargs):
|
||||
uri = "%s/flavors" % self.uri_prefix
|
||||
body = self.serialize(kwargs)
|
||||
resp, body = self.post(uri, body)
|
||||
self.expected_success(201, resp.status)
|
||||
|
Loading…
Reference in New Issue
Block a user