Introduction

This document explains what conventions and coding guidelines to follow when writing new API(s) for CloudStack or updating the existing ones.

References

Instructions

When you need to introduce a new API command to CS, you will need to create a Request Class and a Response class (or re-use an existing API Response class, if you are extending CS API functionality for which the API response is already defined)

Writing a CS API Request class

1. Pick up the *Cmd abstract class to be extended by the request. 

CUD (create/update/delete commands):

 

R (read-list) commands:

IMPORTANT - starting 2.x, new CUD API commands can no longer extend BaseCmd class; they should come as Async commands and extend either BaseAsyncCmd, or BaseAsyncCreateCmd.

When to extend BaseAsyncCmd vs BaseAsyncCreateCmd? Use BaseAsyncCreate for commands creating a new CS entry. For UD commands extend BaseAsyncCmd.

2. The command class you add should end with *Cmd and be annotated with @ApiCommand. Read more about @ parameters in Annotations use in the API ref.

3. Define all request parameters. Annotate them all with @Parameter.

4. Implement execute() for RUD commands and execute()/create() for C commands.

5. Add s_name - the response name. Should be specified in lower case.

6. When thinking about the command name, prepend it with create/delete/update/list depending on the context. Only if none of those prependers fit your logic, use your own (assign for example).

 

Writing a CS API Response class

  1. Make your class extend BaseResponse.
  2. Annotate the class with @EntityReference set with the CloudStack interface representing the object you are returning to the API user. For example, VolumeResponse has @EntityReference set with Volume.
  3. Annotate each parameter with @SerializedName and @Param annotations. See more details on these annotations in Annotations use in the API .
  4. Parameter names should be lower case.
  5. Make sure that you don't expose actual DB ids by setting them to your Ids fields. Use UUID value instead.

API placement and registration

The command placement depends on whether the command is coming as a part of a plugin that can be enabled/disabled, or the CloudStack core base.

When the command comes as a part of the CS core base
  • Location: The request/response code should be placed in cloud-api/cloud-engine-api packages.
  • Access permissions: The command's access control permissions (who is eligible to call it) should be registered in commands.properties.in file.
  • Command registration: The command should be added to the list of all APIs CS supports, returned by ManagementServerImpl. getCommands().

Note that the calls done from the command, should reference only interfaces from cloud-api or cloud-util packages.



When the command comes as a part of a plugin/service
  • Location: Define the command (request/response) in the plugin package.
  • Access Permissions: Define the permissions in the Cmd file, @APICommand annotation, "authorized" field. Example: authorized = {RoleType.Admin}) 
  • Command Registration: Make your plugin manager extend PluggableService interface. Add the new API command to the list of commands returned by getCommands().

The commands defined in the plugin should reference only interfaces located in cloud-api/cloud-utils/<your plugin> packages.

 

 

Rules when modifying existing APIs

The main rule is - all APIs should remain backwards compatible. It means that:

  1. In the Request: Don't change the parameter from optional to required.
  2. In the Request: Don't add a new parameter to an existing command with required=true option.
  3. In the Request: Don't reduce the command permission from being available to normal user to becoming available to Admin only.
  4. In the Request/Response: Don't rename existing parameters.
  5. In the Request/Response: Don't change the parameter type (from String to Map for example).
  6. In the Response: Don't remove the parameter from the response as the third party software can rely on its presence. 

Other rules:

  1. When a new parameter is added, it should be set with "since=release #" field in @Parameter annotation. 
  2. If you think that some parameter should be removed in the future, mark it with @Deprecated and make sure it's documented for the n release. Once it's released, the customers will get a chance to review/change their code to get rid of this parameter, so it can be removed in the n+1 release.

 

  • No labels