From ade1972fc37c2d6ba9a80c4a86749f4af4c05d48 Mon Sep 17 00:00:00 2001 From: Arthur Dayne Date: Thu, 3 Jun 2021 17:54:55 +0800 Subject: [PATCH] Doc Improvment:Add doc about cyborg-nova interaction Change-Id: I850a7e29880a9744b18523281756bab2de1d5492 Closes-Bug: #1930404 --- doc/source/admin/index.rst | 237 ++++++++++++++++++ .../cyborg-nova-interaction-workflow.svg | 83 ++++++ .../figures/cyborg-nova-interaction.png | Bin 0 -> 37829 bytes doc/source/index.rst | 9 + 4 files changed, 329 insertions(+) create mode 100644 doc/source/admin/index.rst create mode 100644 doc/source/figures/cyborg-nova-interaction-workflow.svg create mode 100644 doc/source/figures/cyborg-nova-interaction.png diff --git a/doc/source/admin/index.rst b/doc/source/admin/index.rst new file mode 100644 index 00000000..609060c3 --- /dev/null +++ b/doc/source/admin/index.rst @@ -0,0 +1,237 @@ +==================== +Acceleration Service +==================== + +The OpenStack Cyborg is running as an acceleration service that allows you to +manage the lifecycle of accelerating for an instance in cloud computing +platform. It gives you control over accelerators attached to instances easily. + +Overview +-------- + +A good understand on how Cyborg interacts with Nova and Placement help +operators manage the acceleration service more effectively. + +.. image:: ../figures/cyborg-nova-interaction.png + :width: 700 px + :scale: 99 % + :align: center + +Coexistence with PCI whitelists +------------------------------- + +The operator tells Nova which PCI devices to claim and to be used by +configuring the PCI Whitelists mechanism. In addition, the operator installs +Cyborg drivers in compute nodes and configures/enables them. Those drivers may +then discover and report some PCI devices. The operator must ensure that both +configurations are compatible. + +Ideally, there is a single way for the operator to identify which PCI +devices should be claimed by Nova and which by Cyborg. Until that is figured +out, the operator shall use Cyborg’s configuration file to specify which Cyborg +drivers are enabled. Since each driver claims specific PCI IDs, the operator +can and must ensure that none of these PCI IDs are included in Nova’s PCI +whitelist. + +Placement update +---------------- + +Cyborg conductor calls Placement API directly to represent devices and +accelerators. Some of the intended use cases for the API invocation are: + +* Create or delete child RPs under the compute node RP. + +* Create or delete custom RCs and custom traits. + +* Associate traits with RPs or remove such association. + +* Update RP inventory. + +Cyborg shall not modify the RPs created by any other component, such as Nova +virt drivers. + +User Requests +------------- + +The user request for accelerators is encapsulated in a device profile, +which is created and managed by the admin via the Cyborg API. + +The structure overview of a `device_profile` is like this: + +.. code:: json + + { + "device_profiles":[ + { + "name":"fpga-dp1", + "uuid":"5518a925-1c2c-49a2-a8bf-0927d9456f3e", + "description": "", + "groups":[ + { + "trait:CUSTOM_FPGA_TRAITS":"required", + "resources:FPGA":"1", + "accel:bitstream_id":"d5ca2f11-3108-4426-a11c-a959987565df" + } + ], + "created_at": "2020-03-10 03:52:15+00:00", + "updated_at": null, + "links":[ + { + "href":"http://192.168.32.217/accelerator/v2/device_profiles/5518a925-1c2c-49a2-a8bf-0927d9456f3e", + "rel":"self" + } + ] + } + ] + } + +The device profile is folded into the flavor as an extra spec by the operator, +as below: + +.. code:: bash + + openstack flavor set --property 'accel:device_profile=' flavor + +Thus the standard Nova API can be used to create an instance with only the +flavor (without device profiles), like this: + +.. code:: bash + + openstack server create --flavor f .... # instance creation + +In the future, device profile may be used by itself to specify accelerator +resources for the instance creation API. + +Updating the Request Spec +------------------------- + +When the user submits a request to create an instance, as described in Section +User Requests, Nova needs to call a Cyborg API, to get back the resource +request groups in the device profile and merge them into the request spec. + +This call, like all the others that Nova would make to Cyborg APIs, is done +through a Keystone-based adapter that would locate the Cyborg service, similar +to the way Nova calls Placement. A Cyborg client module added to Nova, will +encapsulate such calls. + +VM images in Glance may be associated with image properties (other than image +traits), such as bitstream/function IDs needed for that image. So, Nova should +pass the VM image UUID from the request spec to Cyborg. + +The groups in the device profile are numbered by Cyborg. The request groups +that are merged into the request spec are numbered by Nova. These numberings +would not be the same in general, i.e., the N-th device profile group may not +correspond to the N-th request group in the request spec. + +When the device profile request groups are added to other request groups in the +flavor, the group_policy of the flavor shall govern the overall semantics of +all request groups. + +Accelerator Requests +-------------------- + +An accelerator request (ARQ) is an object that represents the state of the +request for an accelerator to be assigned to an instance. The creation and +management of ARQs are handled by Cyborg, and ARQs are persisted in Cyborg +database. + +An ARQ represents a request for a single accelerator by definition. The +device profile in the user request may have N request groups, each asking for M +accelerators, then N * M ARQs will be created for that device profile. + +When an ARQ is initially created by Cyborg, it is not yet associated with a +specific host name or a device resource provider. So it is said to be in an +unbound state. Subsequently, Nova calls Cyborg to bind the ARQ to a host name, +a device RP UUID and an instance UUID. If the instance fails to spawn, Nova +would unbind the ARQ with deleting it. On instance termination, Nova would +delete the ARQs after unbinding them. + +Each ARQ needs to be matched to the specific RP in the allocation candidate +that Nova has chosen, before the ARQ is bound. The current Nova code maps +request groups to RPs, while the Cyborg client module in Nova +(cyborg-client-module) matches ARQs to request groups. The matching is done +using the request_id field in the RequestGroup object as below: + +* The order of request groups in a device profile is not significant, but it is + preserved by Cyborg. Thus, each device profile request group has a unique + index. + +* When the device profile request groups returned by Cyborg are added to the + request spec, the request_id field is set to ‘device_profile_’ for the + N-th device profile request group (starting from zero). The device profile + name need not be included here because there is only one device profile per + request spec. + +* When Cyborg creates an ARQ for a device profile, it embeds the device profile + request group index in the ARQ before returning it to Nova. + +* The matching is done in two steps: + + * Each ARQ is mapped to a specific request group in the request spec using + the request_id field. + + * Each request group is mapped to a specific RP using the same logic as the + Neutron bandwidth provider. + +Cyborg and Nova interaction workflow +------------------------------------ + +This flow is captured by the following sequence diagram, in which the Nova +conductor and scheduler are together represented as the Nova controller. + +.. image:: ../figures/cyborg-nova-interaction-workflow.svg + +A Cyborg client module is added to nova (cyborg-client-module). All Cyborg API +calls are routed through that. + +1. The Nova API server receives a `POST /servers` API request with a flavor + that includes a device profile name. + +2. The Nova API server calls the Cyborg API + `GET /v2/device_profiles?name=$device_profile_name` and gets back the device + profile. The request groups in that device profile are added to the request + spec. + +3. The Nova scheduler invokes Placement and gets a list of allocation + candidates. It selects one of those candidates and makes claim(s) in + Placement. The Nova conductor then sends a RPC message + build_and_run_instances to the Nova compute manager. + +4. Nova conductor manager calls the Cyborg API `POST /v2/accelerator_requests` + with the device profile name. Cyborg creates a set of unbound ARQs for that + device profile and returns them to Nova. + +5. The Cyborg client in Nova matches each ARQ to the resource provider picked + for that accelerator. + +6. The Nova compute manager calls the Cyborg API + `PATCH /v2/accelerator_requests` to bind the ARQ with the host name, + device’s RP UUID and instance UUID. This is an asynchronous call which + prepares or reconfigures the device in the background. + +7. Cyborg, on completion of the bindings (successfully or otherwise), + calls Nova’s `POST /os-server-external-events` API with: + +.. code:: + + { + "events": [ + { "name": "accelerator-request-bound", + "tag": $device_profile_name, + "server_uuid": $instance_uuid, + "status": "completed" # or "failed" + }, + ... + ] + } + +8. The Nova compute manager waits for the notification, subject to the timeout + mentioned in Section Other deployer impact. It then calls the Cyborg REST + API `GET /v2/accelerator_requests?instance=&bind_state=resolved`. + +9. The Nova virt driver uses the attach handles returned from the Cyborg call + to compose PCI passthrough devices into the VM’s definition. + +10. If there is any error after binding has been initiated, Nova must unbind + the relevant ARQs by calling Cyborg API. It may then retry on another host + or delete the (unbound) ARQs for the instance. diff --git a/doc/source/figures/cyborg-nova-interaction-workflow.svg b/doc/source/figures/cyborg-nova-interaction-workflow.svg new file mode 100644 index 00000000..6e668eeb --- /dev/null +++ b/doc/source/figures/cyborg-nova-interaction-workflow.svg @@ -0,0 +1,83 @@ + + + + + + + blockdiag + + + + + + + + + + + Nova Controller + + Placement + + Cyborg + + Nova Compute + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GET /v2/device_profiles?name=mydp + {"device_profiles": $device_profile} + Merge request grou + ps into request_sp + ec + Get /allocation_candidates + allocation candidates with nes + ted RPs + Select a candidate + build_and_run_instances() + POST /v2/accelerator_requests + {"arqs": [$arq, ...] + PATCH /v2/accelerator_requests + {"arqs": [$arq, ...] + POST /os-server-external-events + Wait for notific + ation from Cybor + g + GET /v2/accelerator_requests? + instance=$uuid&bind_state=reso + lved + {"arqs": [$arq, ....]} + \ No newline at end of file diff --git a/doc/source/figures/cyborg-nova-interaction.png b/doc/source/figures/cyborg-nova-interaction.png new file mode 100644 index 0000000000000000000000000000000000000000..5c0674b641b892a90e767a265c520d775fb19236 GIT binary patch literal 37829 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 HrhooFV{1d{ literal 0 HcmV?d00001 diff --git a/doc/source/index.rst b/doc/source/index.rst index ef7792cb..b842f143 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -29,6 +29,7 @@ Installation install/install-from-pip install/install-from-source admin/config-wsgi + admin/index Configuration Reference ~~~~~~~~~~~~~~~~~~~~~~~ @@ -39,6 +40,14 @@ Configuration Reference configuration/index reference/support-matrix +Maintenance +~~~~~~~~~~~ + +Once you are running cyborg, the following information is extremely useful. + +* :doc:`Admin Guide `: A collection of guides for administrating + cyborg. + For End Users -------------