ServerInstanceCountForFlavors

= Server Instance Count for Nova Flavors =


 * Launchpad Entry: Server Instance Count for Flavors
 * Created: 3 October 2012
 * Contributors: Yehia Beyh, Gustavo Knuppe

Summary
Currently Nova Flavors (Instance Types) API does not provide information regarding instance count used by flavors. Adding the instance count to the current list of flavors and flavors details APIs would facilitate Cloud Administrators/Users to make intelligent decision before modifying or deleting a given flavor. It can also be used for metrics data to evaluate system resources usage. Adding support to prevent cloud users from deleting flavors referenced by servers and enhance error handling would help Cloud administrators manage flavors and root cause issues quickly.

Release Note
This feature will be provided as an API extension based on OpenStack extension model. Hence, existing users should not be impacted. Advanced users and cloud providers can take advantage of the instance count for analysis and planning.

User stories

 * As a Cloud Administrator, I want to plan updates of my cloud resources based server usage of flavors.
 * As a Cloud Administrator, I want to be able to easily delete or modify flavors without guessing if a flavor is in use by servers
 * As a Cloud Administrator, I want to see a graph of my flavor's utilization by servers
 * As a Cloud Administrator, I want to prevent the deletion of a flavors while it is referenced by servers
 * As a Cloud Administrator, I want to be able to see better error handling to help me root cause issues quickly

Assumptions
TBD

Design
The initial implementation of server instance count feature is added as a nova extension. In addition, notification and a "sub-code:" has been added in the returned header to help clients easily identify issues and root cause failures during flavor delete operation.

Modules

 * nova/api/openstack/compute/contrib/isc_flavor.py
 * nova/db/sqlalchemy/isc_flavor_sql_api.py
 * nova/db/isc_flavor_api.py

Nova cli Changes

 * REST APIs for programmatic access
 * Support for the nova cli to leverage the list of the instance count

SAMPLE of NOVA CLI OUTPUT

++--+---+--+---+--+---+-+--+ ++--+---+--+---+--+---+-+--+ ++--+---+--+---+--+---+-+--+
 * 1) nova flavor-list
 * ID |      Name       | Memory_MB | Disk | Ephemeral | Swap | VCPUs | RXTX_Factor | Server Count |
 * 1 | standard.xsmall  | 1024      | 30   | 0         |      | 1     | 1.0         | 10           |
 * 2 | standard.small   | 2048      | 60   | 0         |      | 2     | 1.0         | 0            |
 * 3 | standard.medium  | 4096      | 120  | 0         |      | 2     | 1.0         | 99           |
 * 4 | standard.large   | 8192      | 240  | 0         |      | 4     | 1.0         | 15           |
 * 5 | standard.xlarge  | 16384     | 480  | 0         |      | 4     | 1.0         | 0            |
 * 6 | standard.2xlarge | 32768     | 960  | 0         |      | 8     | 1.0         | 5            |

Implementation of Sub-code
class FlavorHasInvalidCpuCount(IscBadRequest): SUBCODE = '502001' explanation = _("Flavor '%(flavorname)s' cannot be created. The number of " "cpus inserted is '%(count)i' but it must be between " "'%(min)i' and '%(max)i'.")

class FlavorHasInvalidMemorySize(IscBadRequest): SUBCODE = '502002' explanation = _("Flavor '%(flavorname)s' cannot be created. The memory " "size in MB inserted is '%(count)i' but it must be between " "'%(min)i' and '%(max)i'.")

class FlavorHasInvalidDiskSize(IscBadRequest): SUBCODE = '502003' explanation = _("Flavor '%(flavorname)s' cannot be created. The disk size " "in GB inserted is '%(count)i' but it must be between " "'%(min)i' and '%(max)i'.")

class FlavorHasInvalidAdditionalDiskSize(IscBadRequest): SUBCODE = '502004' explanation = _("Flavor '%(flavorname)s' cannot be created. The " "additional disk size in GB inserted is '%(count)i' but it " "must be between '%(min)i' and '%(max)i'.")

class FlavorNameHasInvalidSize(IscBadRequest): SUBCODE = '502005' explanation = _("Flavor '%(flavorname)s' cannot be created. The length of " "the flavor name is '%(count)i' but it must be between " "'%(min)i' and '%(max)i'.")

class FlavorNameHasTrailingWhitespaces(IscBadRequest): SUBCODE = '502006' explanation = _("Flavor '%(flavorname)s' cannot be created. It contains " "whitespaces either at its beginning or at its end. Please " "remove them and repeat the operation.")

List Server Instance Count

 * REST API for INDEXING
 * HTTP GET METHOD: http:///rest/compute/v2//flavors?instance_count=yes
 * REST API for DETAILING
 * HTTP GET METHOD: http:///rest/compute/v2//flavors/detail?instance_count=yes

Expected JSON output
EXAMPLES:

http://16.125.106.178:8774/v2/26180ca86661451d91f7d812d80c18b7/flavors/?instance_count=yes

{   "flavors": [{ "instance_count": 10, "id": "1", "links": [{ "href": "http://16.125.106.178:8774/v2/26180ca86661451d91f7d812d80c18b7/flavors/1", "rel": "self" }, {           "href": "http://16.125.106.178:8774/26180ca86661451d91f7d812d80c18b7/flavors/1", "rel": "bookmark" }],       "name": "standard.xsmall" }, {       "instance_count": 0, "id": "2", "links": [{ "href": "http://16.125.106.178:8774/v2/26180ca86661451d91f7d812d80c18b7/flavors/2", "rel": "self" }, {           "href": "http://16.125.106.178:8774/26180ca86661451d91f7d812d80c18b7/flavors/2", "rel": "bookmark" }],       "name": "standard.small" }, {       "instance_count": 99, "id": "3", "links": [{ "href": "http://16.125.106.178:8774/v2/26180ca86661451d91f7d812d80c18b7/flavors/3", "rel": "self" }, {           "href": "http://16.125.106.178:8774/26180ca86661451d91f7d812d80c18b7/flavors/3", "rel": "bookmark" }],       "name": "standard.medium" }, {       "instance_count": 15, "id": "4", "links": [{ "href": "http://16.125.106.178:8774/v2/26180ca86661451d91f7d812d80c18b7/flavors/4", "rel": "self" }, {           "href": "http://16.125.106.178:8774/26180ca86661451d91f7d812d80c18b7/flavors/4", "rel": "bookmark" }],       "name": "standard.large" }, {       "instance_count": 0, "id": "5", "links": [{ "href": "http://16.125.106.178:8774/v2/26180ca86661451d91f7d812d80c18b7/flavors/5", "rel": "self" }, {           "href": "http://16.125.106.178:8774/26180ca86661451d91f7d812d80c18b7/flavors/5", "rel": "bookmark" }],       "name": "standard.xlarge" }, {       "instance_count": 5, "id": "6", "links": [{ "href": "http://16.125.106.178:8774/v2/26180ca86661451d91f7d812d80c18b7/flavors/6", "rel": "self" }, {           "href": "http://16.125.106.178:8774/26180ca86661451d91f7d812d80c18b7/flavors/6", "rel": "bookmark" }],       "name": "standard.2xlarge" }] }

http://16.125.106.178:8774/v2/26180ca86661451d91f7d812d80c18b7/flavors/1?instance_count=yes

{   "flavor": { "vcpus": 1, "disk": 0, "OS-FLV-EXT-DATA:ephemeral": 10, "name": "m1.tiny", "links": [{ "href": "http://16.125.106.178:8774/v2/26180ca86661451d91f7d812d80c18b7/flavors/1", "rel": "self" }, {           "href": "http://16.125.106.178:8774/26180ca86661451d91f7d812d80c18b7/flavors/1", "rel": "bookmark" }],       "rxtx_factor": 1.0, "instance_count": 0, "ram": 512, "id": "1", "swap": "" } }

Error Code

 * Normal Response Code(s): 200, 203
 * Error Response Code(s): computeFault (400), serviceUnavailable (503), unauthorized (401), forbidden (403), badRequest (400), badMethod (405), overLimit (413)

Test/Demo Plan
The tests for this property has been added.

Unresolved issues
none

BoF agenda and discussion
Use this section to take notes during the BoF; if you keep it in the approved spec, use it for summarizing what was discussed and note any options that were rejected.

TBD