diff options
Diffstat (limited to 'docs/testing')
-rw-r--r-- | docs/testing/developer/devguide/api.rst | 239 | ||||
-rw-r--r-- | docs/testing/user/userguide/api.rst | 91 | ||||
-rw-r--r-- | docs/testing/user/userguide/index.rst | 1 |
3 files changed, 329 insertions, 2 deletions
diff --git a/docs/testing/developer/devguide/api.rst b/docs/testing/developer/devguide/api.rst index eb2b0d67..48ae3ae4 100644 --- a/docs/testing/developer/devguide/api.rst +++ b/docs/testing/developer/devguide/api.rst @@ -1,2 +1,237 @@ -- Which framework has been used and why -- How to extend to more api +********************************************** +QTIP RESTful Application Programming Interface +********************************************** + +Abstract +######## + +QTIP consists of different tools(metrics) to benchmark the NFVI. These metrics +fall under different NFVI subsystems(QPI's) such as compute, storage and network. +A plan consists of one or more QPI's, depending upon how the end-user would want +to measure performance. API is designed to expose a RESTful interface to the user +for executing benchmarks and viewing respective scores. + +Framework +========= + +QTIP API has been created using the Python package `Connexion`_. It has been chosen +for a number of reasons. It follows API First approach to create micro-services. +Hence, firstly the API specifications are defined from the client side perspective, +followed by the implementation of the micro-service. It decouples the business logic +from routing and resource mapping making design and implementation cleaner. + +It has two major components: + +API Specifications + + The API specification is defined in a yaml or json file. Connexion follows + `Open API specification`_ to determine the design and maps the endpoints to methods in python. + +Micro-service Implementation + Connexion maps the ``operationId`` corresponding to every operation in API + Specification to methods in python which handles request and responses. + +As explained, QTIP consists of metrics, QPI's and plans. The API is designed to provide +a RESTful interface to all these components. It is responsible to provide listing and details of +each individual element making up these components. + +Design +====== + +Specification +------------- + +API's entry point (``main``) runs connexion ``App`` class object after adding API Specification +using ``App.add_api`` method. It loads specification from ``swagger.yaml`` file by specifying +``specification_dir``. + +Connexion reads API's endpoints(paths), operations, their request and response parameter +details and response definitions from the API specification i.e. ``swagger.yaml`` in this case. + +Following example demonstrates specification for the resource ``plans``. + +:: + + paths: + /plans/{name}: + get: + summary: Get a plan by plan name + operationId: qtip.api.controllers.plan.get_plan + tags: + - Plan + - Standalone + parameters: + - name: name + in: path + description: Plan name + required: true + type: string + responses: + 200: + description: Plan information + schema: + $ref: '#/definitions/Plan' + 404: + description: Plan not found + schema: + $ref: '#/definitions/Error' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + definitions: + Plan: + type: object + required: + - name + properties: + name: + type: string + description: + type: string + info: + type: object + config: + type: object + +Every ``operationId`` in above operations corresponds to a method in controllers. +QTIP has three controller modules each for plan, QPI and metric. Connexion will +read these mappings and automatically route endpoints to business logic. + +`Swagger Editor`_ can be explored to play with more such examples and to validate +the specification. + +Controllers +----------- + +The request is handled through these methods and response is sent back to the client. +Connexion takes care of data validation. + +.. code-block:: python + + @common.check_endpoint_for_error(resource='Plan') + def get_plan(name): + plan_spec = plan.Plan(name) + return plan_spec.content + +In above code ``get_plan`` takes a plan name and return its content. + +The decorator ``check_endpoint_for_error`` defined in ``common`` is used to handle error +and return a suitable error response. + + +During Development the server can be run by passing specification file(``swagger.yaml`` +in this case) to connexion cli - + +:: + + connexion run <path_to_specification_file> -v + + +Extending the Framework +======================= + +Modifying Existing API: +----------------------- + API can be modified by adding entries in ``swagger.yaml`` and adding the corresponding + controller mapped from ``operationID``. + + Adding endpoints: + + New endpoints can be defined in ``paths`` section in ``swagger.yaml``. To add a new resource *dummy* - + + :: + + paths: + /dummies: + get: + summary: Get all dummies + operationId: qtip.api.controllers.dummy.get_dummies + tags: + - dummy + responses: + 200: + description: Foo information + schema: + $ref: '#/definitions/Dummy + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + + + And then model of the resource can be defined in the ``definitions`` section. + + :: + + definitions: + Dummy: + type: object + required: + - name + properties: + name: + type: string + description: + type: string + id: + type: string + + + Adding controller methods: + Methods for handling requests and responses for every operation for the endpoint added can be + implemented in ``controller``. + + In ``controllers.dummy`` + + .. code-block:: python + + def get_dummies(): + all_dummies = [<code to get all dummies>] + return all_dummies, httplib.OK + + Adding error responses + Decorators for handling errors are defined in ``common.py`` in ``api``. + + .. code-block:: python + + from qtip.api import common + + @common.check_endpoint_for_error(resource='dummy',operation='get') + def get_dummies() + all_dummies = [<code to get all dummies>] + return all_dummies + +Adding new API: +--------------- + + API can easily be extended by adding more APIs to ``Connexion.App`` class object using + ``add_api`` class method. + + In ``__main__`` + + .. code-block:: python + + def get_app(): + app = connexion.App(__name__, specification_dir=swagger_dir) + app.add_api('swagger.yaml', base_path='/v1.0', strict_validation=True) + return app + + + Extending it to add new APIs. The new API should have all endpoints mapped using ``operationId``. + + .. code-block:: python + + from qtip.api import __main__ + my_app = __main__.get_app() + my_app.add_api('new_api.yaml',base_path'api2',strict_validation=True) + my_app.run(host="0.0.0.0", port=5000) + + +.. _Connexion: https://connexion.readthedocs.io/en/latest/ +.. _Open API specification: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md +.. _Swagger Editor: http://editor.swagger.io/ diff --git a/docs/testing/user/userguide/api.rst b/docs/testing/user/userguide/api.rst new file mode 100644 index 00000000..080fef5f --- /dev/null +++ b/docs/testing/user/userguide/api.rst @@ -0,0 +1,91 @@ +************** +QTIP API Usage +************** + +QTIP consists of a number of benchmarking tools or metrics, grouped under QPI's. QPI's map to the different +components of an NFVI ecosystem, such as compute, network and storage. Depending on the type of application, +a user may group them under plans. + +QTIP API provides a RESTful interface to all of the above components. User can retrieve list of plans, QPIs +and metrics and their individual information. + + +Running +======= + +After installing QTIP. API server can be run using command ``qtip-api`` on the local machine. + +All the resources and their corresponding operation details can be seen at ``/v1.0/ui``, +on hosting server(``0.0.0.0:5000`` for the local machine). + +The whole API specification in json format can be seen at ``/v1.0/swagger.json``. + +The data models are given below: + + * Plan + * Metric + * QPI + +Plan:: + + { + "name": <plan name>, + "description": <plan profile>, + "info": <{plan info}>, + "config": <{plan configuration}>, + "QPIs": <[list of qpis]>, + }, + +Metric:: + + { + "name": <metric name>, + "description": <metric description>, + "links": <[links with metric information]>, + "workloads": <[cpu workloads(single_cpu, multi_cpu]>, + }, + +QPI:: + + { + "name": <qpi name>, + "description": <qpi description>, + "formula": <formula>, + "sections": <[list of sections with different metrics and formulaes]>, + } + +The API can be described as follows + +Plans: + + +--------+----------------------------+-----------------------------------------+ + | Method | Path | Description | + +========+============================+=========================================+ + | GET | /v1.0/plans | Get the list of of all plans | + +--------+----------------------------+-----------------------------------------+ + | GET | /v1.0/plans/{name} | Get details of the specified plan | + +--------+----------------------------+-----------------------------------------+ + +Metrics: + + +--------+----------------------------+-----------------------------------------+ + | Method | Path | Description | + +========+============================+=========================================+ + | GET | /v1.0/metrics | Get the list of all metrics | + +--------+----------------------------+-----------------------------------------+ + | GET | /v1.0/metrics/{name} | Get details of specified metric | + +--------+----------------------------+-----------------------------------------+ + +QPIs: + + +--------+----------------------------+-----------------------------------------+ + | Method | Path | Description | + +========+============================+=========================================+ + | GET | /v1.0/qpis | Get the list of all QPIs | + +--------+----------------------------+-----------------------------------------+ + | GET | /v1.0/qpis/{name} | Get details of specified QPI | + +--------+----------------------------+-----------------------------------------+ + + +*Note:* + *running API with connexion cli does not require base path (/v1.0/) in url* diff --git a/docs/testing/user/userguide/index.rst b/docs/testing/user/userguide/index.rst index 78c5d117..576a988d 100644 --- a/docs/testing/user/userguide/index.rst +++ b/docs/testing/user/userguide/index.rst @@ -12,4 +12,5 @@ QTIP User Guide :maxdepth: 2 cli.rst + api.rst qpi-compute.rst |