High level goals of API refactoring

To make the system more modular and dynamic, API refactoring is part of the 4.1 new architecture efforts. Another goal is to allow developers and partners to quickly add plugins and new service modules and access control, making cloudstack more adaptive.

The solution is not the final perfect solution, for sure, feedback and suggestion is always welcome to make it a much better and adaptive product.

Current problem:

1. Security and access check is lying around in different layers. For example, in apiSevlet we check the web access username/password credentials, apiServer checks the command existence, and several other checks, then the DB access check mainly is done at the service layer. So it is hard for developers and system admin to follow all the access and validations, to make sure all the checks are done correctly. To do it, developers need to be familiar with the various parts of the CS code.

2. Static: Majority of the DB access check and security validation is tightly coupled with the lower layer service class. This not only made the code hard to follow, also inherently made the policy static. This makes it impossible for system admin to apply a different security policy adaptively. If one wants to adopt a different policy, not only he needs to understand code scattered around, he also needs to rebuild the CS after any changes. Any security role modification is not dynamic.

3. Performance implication: Access check done at the lower service layer makes the error code path long.

4. Docs generated, CLI and APIs are loosely coupled.

5. Over the wire(OTW) entity is not well defined. For example, to listVMsCmd, it involves multiple DB access, with the large amount of data showing NICs, Vols, Secondary storage etc, the command can take quite a while.
6. Admin and user have basically the same end-point access.

The goal of the API refactoring is aiming to tackle these problems:

1. We would pull security checks, DB access checks, any related checks up from service layer/orchestration engine to the API layer as much as possible. This makes the necessary checking done more centralized and easy to follow. Conceptually the cloud orchestration engine layer handles the orchestration, the security check and the access check should have done before reaching this layer. This has performance benefits, since checks are done earlier instead of reaching deep in the code path; this also has the benefits of a clear architecture. The API layer does the necessary access check and role based authentication, makes it easier and dynamic for future policy change. New policy can be added easily and dynamically as a plugin to the system.

2. The ACL and security checks also are written as adapter plugins, hence make them dynamic. Users and developers and easily adapt new policy if needed. This made the code more modular and more adaptive.

3. Help improves performance: Instead of finding access error layer into the service layer, by doing 1, we would do possible checks early in the code path, which helps stop the wrong access earlier in the code path.

4. API layer is more tightly coupled with Doc generation, and CLI. Related commands are grouped together, and the new @Doc annotation will help show the related commands in document.

5. We define new view objects as response objects, avoiding big DB joins at run time.

6. Separate the admin and user APIs. This is for developers to understand the code, which should be accessible by users, which should only be handled by Admin. Hence developers will have better grasp of the role and pay attention to the new code added. It also helps the document generated.

Notes:

1. For end users, the new APIs after refactoring looks pretty much the same. One big change is the ID, we will always use UUID in the over the wire APIs. The UUID can be created by Cloudstack, or can be provided by users (we call it Xid – external ID). Every UUID should be unique in the cloudstack system.

2. The API layer provides a translation from the UUID to the internal DB_ID to the DB entity, but this translation is done internally. Outside users will never see DB_ID. Before the response is sending back by CS, API layer replaces the internal DB_ID with the UUID.

3. In original FS document, the annotation of entityType in @Parameter points to a resource class, this is replaced by a response class. So entityType points to a response object, and the response class has a one-to-one mapping from the response to the physical entity itself. This translation work is done by the API layer and the entityManagerImpl.

4. The packages for the new API commands are all moved from the current com.cloud.api.commands to new location: org.apache.cloudstack.api.commands.user.[group name]
org.apache.cloudstack.api.commands.admin.[group_name]

The responses are also moved to new location at
org.apache.cloudstack.api.response

More implementation details can refer to the FS document. We will also update the document along the way. The code is branch from master at api_refactoring. Since the change is not minimum, we would like the community to know and give feedback.

Summary

This is a proposal to refactor current API commands in CloudStack to:

- facilitate better document generation

- parameter validation

- command packaging

- ACL code cleanup and doing existing access checks at API layer

- UUID annotation in all commands

- ID to UUID conversion in all response objects

- List API optimization using DB views

Please check out the proposal here.

Interface change list

Our goal is that current clients do not need to change their existing API to access Cloudstack.
(I used an example to show the difference for each item in the list. )

1. For each API command, the original @Implementation is replaced by @APICommand, New field "name" is added for the APICommand:

Existing one in 4.0 master:
@Implementation(description = "Adds Swift.", responseObject = HostResponse.class, since="3.0.0")
New 4.1 with API refactoring:
@APICommand(name = “ addSwift”, description =”Adds swift”, responseObject = HostResponse.class, since = “3.0.0”)

2. @IdentityMapper is removed, @IdentityMapper is used to point to the DB table directly. e.g.,
Existing in 4.0 master:
@IdentityMapper(entityTableName="data_center")

A New entityType is added to the @Parameter annotation. This new entityType replaces the previous @IdentityMapper.
Instead of accessing the DB table directly, it uses the new DB views from the response class.
This new DB views optimize the list commands.

New 4.1 with API refactoring:
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class, ….)

3. In the @Parameter annotation, some type fields have changed from long to UUID (because we will use UUID instead of Internal ID).
Existing in 4.0 master:
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.long,
required=true, description="availability zone for the virtual machine")

New 4.1 with refactoring:
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
required=true, description="availability zone for the virtual machine")

4. Regoup of the commands. In existing master, all api commands are flat in one directory. Now they are grouped according to their functionality into several groups under: org.apache.cloudstack.api.command

5. Add the new @ACL annotation for the access control check.

Project progress for access check and validation

For milestone 1, the main goal is to make the access control and the validation flow into the API layer.

There are three files handling the API layer checks and validation: apiServet, apiServer and apiDispatcher.
apiSevlet checks the web access is valid;
If it passes, it goes to the apiServer;
apiServer parses the command annotation, and checks access to the adapter and check if cmd exists;
apiDispatcher has the logic to check the ACL access, the parameter valication, the DB access validation.

  • We have separated all the API commands into separate groups according to their functionality. All API commands also moved from the previous com.cloud.api.commands packages to org.apache.cloudstack.api[command.admin|user].{groupname}
    - The separation of user and admin commands is for the developers to get better understanding of the commands and the options for commands;
    - The separation is alos for document generation purpose.
  • ACL as a plugin adapter is integrated into API server;
  • Add entityType to @parameter annotation, it points to the DB View response object;
  • Add the mapping for DB view in response class to the DB entity object;
  • Next we need to add the ACL and validation logic in the command execution context to the apiDispatcher.

Project progress for list api performance optimization

  • Removed IdentityProxy fields in all Response classes to avoid internal DB Id to UUID conversion (extra db lookup) in list result serialization phase.
  • Created DB views to further speed up the following costly list APIs:
    1. listAccounts
    2. listAsyncJobs
    3. listDomainRouters
    4. listEvents
    5. listHosts
    6. listVmGroups
    7. listProjects
    8. listProjectAccounts
    9. listProjectInvitations
    10. listResourceTags
    11. listSecurityGroups
    12. listUsers
    13. listVirtualMachines
    14. listVolumes
    15. listStoragePools
    16. listZones
    17. listDiskOfferings
    18. listServiceOfferings
  • Added a new create-schema-view.sql to create these new DB views during database setup phase.
  • Also handled upgrade script for these new DB views in schema-40to410.sql.
  • No labels