xref: /spdk/doc/sma.md (revision 8de3c57f8d11430c8046bbf7b9a56c144e10cd0d)
179a3ac88SKonrad Sztyber# Storage Management Agent {#sma}
279a3ac88SKonrad Sztyber
379a3ac88SKonrad SztyberStorage Management Agent (SMA) is a service providing a gRPC interface for
479a3ac88SKonrad Sztyberorchestrating SPDK applications.  It's a standalone application that allows
579a3ac88SKonrad Sztyberusers to create and manage various types of devices (e.g. NVMe, virtio-blk,
679a3ac88SKonrad Sztyberetc.).  The major difference between SMA's API and the existing SPDK-RPC
779a3ac88SKonrad Sztyberinterface is that it's designed to abstract the low level details exposed by
879a3ac88SKonrad SztyberSPDK-RPCs, which enables it to be more easily consumed by orchestration
979a3ac88SKonrad Sztyberframeworks, such as k8s or OpenStack.  This is especially important for
1079a3ac88SKonrad Sztyberdeployments on IPUs (Infrastructure Processing Unit), which usually require a
1179a3ac88SKonrad Sztyberlot of hardware-specific options.
1279a3ac88SKonrad Sztyber
1379a3ac88SKonrad Sztyber## Interface
1479a3ac88SKonrad Sztyber
1557cf8961SJohn KariukiThe interface is defined in a protobuf files located in `proto`
1679a3ac88SKonrad Sztyberdirectory.  The generic interface common to all types of devices is defined in
1779a3ac88SKonrad Sztyber`sma.proto` file, while device-specific options are defined in their separate
1879a3ac88SKonrad Sztyberfiles (e.g. `nvme.proto` for NVMe).
1979a3ac88SKonrad Sztyber
2079a3ac88SKonrad SztyberCurrently, the interface consists of four methods.  Additionally, it defines two
2179a3ac88SKonrad Sztybermain types of objects: volumes and devices.  A volume is a representation of
2279a3ac88SKonrad Sztybersome storage media.  It is equivalent to a SPDK bdev and/or an NVMe namespace
2379a3ac88SKonrad Sztyberand can exist even if it's not presented to the host system.  A device is
2479a3ac88SKonrad Sztyberusually a virtual/physical PCIe function that is exposed to a host.  It is
2579a3ac88SKonrad Sztybercapable of presenting one or more volumes (depending on the type of the device)
2679a3ac88SKonrad Sztyberto a host.
2779a3ac88SKonrad Sztyber
2879a3ac88SKonrad SztyberThe following sections provide a high-level description of each method.  For
2979a3ac88SKonrad Sztybermore details, consult the protobuf definitions.
3079a3ac88SKonrad Sztyber
3179a3ac88SKonrad Sztyber### CreateDevice
3279a3ac88SKonrad Sztyber
3379a3ac88SKonrad SztyberThis method creates a device.  If a device with given parameters already exists,
3479a3ac88SKonrad Sztyberit becomes a no-op and returns a handle to that device.
3579a3ac88SKonrad Sztyber
3679a3ac88SKonrad SztyberInput:
3779a3ac88SKonrad Sztyber
3879a3ac88SKonrad Sztyber- `volume`: Volume parameters describing a volume to immediately attach to the
3979a3ac88SKonrad Sztyber  created device.  This field may be optional for some device types (e.g. NVMe),
40*8de3c57fSMichal Rozegnal  while it may be required for others (e.g. virtio-blk). Extending parameters with
41*8de3c57fSMichal Rozegnal  crypto attributes like encryption type, keys, tweak mode allows the user to configure
42*8de3c57fSMichal Rozegnal  crypto when attaching a volume to a device. Users must specify the crypto engine
43*8de3c57fSMichal Rozegnal  to use under `crypto` section in config. It is also possible to register out-of-tree
44*8de3c57fSMichal Rozegnal  crypto engines by inheriting from the `CryptoEngine` class.
4579a3ac88SKonrad Sztyber- `params`: Device-specific parameters.  The type of this structure determines
4679a3ac88SKonrad Sztyber  the type of device to create.
4779a3ac88SKonrad Sztyber
4879a3ac88SKonrad SztyberOutput:
4979a3ac88SKonrad Sztyber
5079a3ac88SKonrad Sztyber- `handle`: Opaque handle identifying the device.
5179a3ac88SKonrad Sztyber
5279a3ac88SKonrad Sztyber### DeleteDevice
5379a3ac88SKonrad Sztyber
5479a3ac88SKonrad SztyberThis method deletes a device.  Volumes that are still attached to a device being
5579a3ac88SKonrad Sztyberdeleted will be automatically detached.
5679a3ac88SKonrad Sztyber
5779a3ac88SKonrad SztyberInput:
5879a3ac88SKonrad Sztyber
5979a3ac88SKonrad Sztyber- `handle`: Device handle obtained from `CreateDevice`.
6079a3ac88SKonrad Sztyber
6179a3ac88SKonrad Sztyber### AttachVolume
6279a3ac88SKonrad Sztyber
6379a3ac88SKonrad SztyberThis method creates a volume and attaches it to a device exposing it to the
6479a3ac88SKonrad Sztyberhost.  It might lead to establishing a connection to remote storage target.
6579a3ac88SKonrad SztyberHowever, this is not always the case, even if the volume is remote.  For
6679a3ac88SKonrad Sztyberinstance, if a volume describes an NVMe namespace, it might already be connected
6779a3ac88SKonrad Sztyberif another volume on the same subsystem was created previously.  It may be
6879a3ac88SKonrad Sztyberunsupported by some types of devices (e.g. virtio-blk).
6979a3ac88SKonrad Sztyber
7079a3ac88SKonrad SztyberInput:
7179a3ac88SKonrad Sztyber
7279a3ac88SKonrad Sztyber- `volume`: Parameters describing the volume to attach.  The type of this
7379a3ac88SKonrad Sztyber  structure determines the method to create it (e.g. direct NVMe-oF connection,
74*8de3c57fSMichal Rozegnal  NVMe-oF through discovery service, iSCSI, etc.). Extending parameters with
75*8de3c57fSMichal Rozegnal  crypto attributes like type, keys, tweak mode allowing the user to configure crypto
76*8de3c57fSMichal Rozegnal  when attaching a volume to a device. Users must specify the crypto engine to use under
77*8de3c57fSMichal Rozegnal  `crypto` section in config. It is also possible to register out-of-tree crypto engines
78*8de3c57fSMichal Rozegnal  by inheriting from the `CryptoEngine` class.
7979a3ac88SKonrad Sztyber- `device_handle`: Device handle obtained from `CreateDevice`.
8079a3ac88SKonrad Sztyber
8179a3ac88SKonrad Sztyber### DetachVolume
8279a3ac88SKonrad Sztyber
8379a3ac88SKonrad SztyberThis method detaches a volume from a device making it unavailable to the host.
8479a3ac88SKonrad SztyberIt may be unsupported by some types of devices (e.g. virtio-blk).
8579a3ac88SKonrad Sztyber
8679a3ac88SKonrad SztyberInput:
8779a3ac88SKonrad Sztyber
8879a3ac88SKonrad Sztyber- `volume_id`: Volume UUID/GUID.
8979a3ac88SKonrad Sztyber- `device_handle`: Device handle obtained from `CreateDevice`.
9079a3ac88SKonrad Sztyber
91*8de3c57fSMichal Rozegnal### SetQos
92*8de3c57fSMichal Rozegnal
93*8de3c57fSMichal RozegnalThis method configures QoS on a per-device or per-volume level.
94*8de3c57fSMichal RozegnalNot all QoS settings have to be supported by each device, so users
95*8de3c57fSMichal Rozegnalcan use `GetQosCapabilities` to get capabilities.
96*8de3c57fSMichal Rozegnal
97*8de3c57fSMichal RozegnalInput:
98*8de3c57fSMichal Rozegnal
99*8de3c57fSMichal Rozegnal- `handle`: Device handle obtained from `CreateDevice`.
100*8de3c57fSMichal Rozegnal- `volume_id`: Volume UUID/GUID. If this parameter is omitted, the QoS will be set up
101*8de3c57fSMichal Rozegnal  on the whole device (all volumes attached to that device will share QoS settings).
102*8de3c57fSMichal Rozegnal  Some device types might only support configuring QoS on per-device
103*8de3c57fSMichal Rozegnal  (volume_id must be empty) or per-volume level (volume_id cannot be empty).
104*8de3c57fSMichal Rozegnal  This information can be obtained by sending a GetQosCapabilities request.
105*8de3c57fSMichal Rozegnal- `maximum`: Maximum allowed IOPS/bandwidth values.
106*8de3c57fSMichal Rozegnal
107*8de3c57fSMichal Rozegnal### GetQosCapabilities
108*8de3c57fSMichal Rozegnal
109*8de3c57fSMichal RozegnalThis method queries supported QoS settings.
110*8de3c57fSMichal Rozegnal
111*8de3c57fSMichal RozegnalInput:
112*8de3c57fSMichal Rozegnal
113*8de3c57fSMichal Rozegnal- `device_type`: Type of a device to query for QoS capabilities.
114*8de3c57fSMichal Rozegnal
115*8de3c57fSMichal RozegnalOutput:
116*8de3c57fSMichal Rozegnal
117*8de3c57fSMichal Rozegnal- `capabilities`: QoS capabilities response including device/volume
118*8de3c57fSMichal Rozegnal   QoS limits like read IOPS, write IOPS, read/write IOPS, read bandwidth,
119*8de3c57fSMichal Rozegnal   write bandwidth, read/write bandwidth.
120*8de3c57fSMichal Rozegnal
12179a3ac88SKonrad Sztyber## Running and Configuration
12279a3ac88SKonrad Sztyber
12379a3ac88SKonrad SztyberIn order to run SMA, SPDK needs to be configured with the `--with-sma` flag.
12479a3ac88SKonrad SztyberThen, SMA can be started using a script located in `scripts/sma.py`.  It
12579a3ac88SKonrad Sztyberrequires a YAML configuration file that specifies which types of devices to
12679a3ac88SKonrad Sztyberservice, as well as several other options (e.g. listen address, SPDK-RPC socket,
12779a3ac88SKonrad Sztyberetc.).  Device types not listed in the configuration will be disabled and it
12879a3ac88SKonrad Sztyberwon't be possible to manage them.  Below is an example configuration enabling
12979a3ac88SKonrad Sztybertwo device types (NVMe/vfiouser and vhost-blk):
13079a3ac88SKonrad Sztyber
13179a3ac88SKonrad Sztyber```yaml
13279a3ac88SKonrad Sztyberaddress: 'localhost'
13379a3ac88SKonrad Sztybersocket: '/var/tmp/spdk.sock'
13479a3ac88SKonrad Sztyberport: 8080
13579a3ac88SKonrad Sztyberdevices:
13679a3ac88SKonrad Sztyber  - name: 'vfiouser'
13779a3ac88SKonrad Sztyber    params:
13879a3ac88SKonrad Sztyber      root_path: '/var/tmp/vfiouser'
13979a3ac88SKonrad Sztyber      bus: 'bus0'
14079a3ac88SKonrad Sztyber      address: '127.0.0.1'
14179a3ac88SKonrad Sztyber      port: 4444
14279a3ac88SKonrad Sztyber  - name: 'vhost-blk'
14379a3ac88SKonrad Sztyber```
14479a3ac88SKonrad Sztyber
14579a3ac88SKonrad Sztyber## Plugins
14679a3ac88SKonrad Sztyber
14779a3ac88SKonrad SztyberSMA provides a way to load external plugins implementing support for specific
14879a3ac88SKonrad Sztyberdevice types.  A plugin will be loaded if it's specified in the `SMA_PLUGINS`
14979a3ac88SKonrad Sztyberenvironment variable (multiple plugins are separated with a colon) or if it's
15079a3ac88SKonrad Sztyberspecified in the `plugins` section of the config file.  For example, the
15179a3ac88SKonrad Sztyberfollowing two methods are equivalent:
15279a3ac88SKonrad Sztyber
15379a3ac88SKonrad Sztyber```sh
15479a3ac88SKonrad Sztyber$ SMA_PLUGINS=plugin1:plugin2 scripts/sma.py
15579a3ac88SKonrad Sztyber
15679a3ac88SKonrad Sztyber$ cat sma.yaml
15779a3ac88SKonrad Sztyberaddress: 'localhost'
15879a3ac88SKonrad Sztyberport: 8080
15979a3ac88SKonrad Sztyberplugins:
16079a3ac88SKonrad Sztyber  - 'plugin1'
16179a3ac88SKonrad Sztyber  - 'plugin2'
16279a3ac88SKonrad Sztyberdevices:
16379a3ac88SKonrad Sztyber  - name: 'device-from-plugin1'
16479a3ac88SKonrad Sztyber  - name: 'device-from-plugin2'
16579a3ac88SKonrad Sztyber$ scripts/sma.py -c sma.yaml
16679a3ac88SKonrad Sztyber```
16779a3ac88SKonrad Sztyber
16879a3ac88SKonrad SztyberEach plugin needs to be in the python search path (either in one of the default
16979a3ac88SKonrad Sztyberdirectories or added to `PYTHONPATH`).
17079a3ac88SKonrad Sztyber
17179a3ac88SKonrad SztyberA plugin is required to define a global variable called `devices` storing a list
17279a3ac88SKonrad Sztyberof classes deriving from `spdk.sma.DeviceManager`.  This base class define the
17379a3ac88SKonrad Sztyberinterface each device needs to implement.  Additionally, each DeviceManager
17479a3ac88SKonrad Sztyberneeds to define a unique name that will be used to identify it in config file as
17579a3ac88SKonrad Sztyberwell as the name of the protocol it supports.  There can be many DeviceManagers
17679a3ac88SKonrad Sztybersupporting the same protocol, but only one can be active at a time.  The name of
17779a3ac88SKonrad Sztyberthe protocol shall match the type specified in `CreateDeviceRequest.params`
17879a3ac88SKonrad Sztyber(e.g. "nvme", "virtio_blk", etc.), as it'll be used to select the DeviceManager
17979a3ac88SKonrad Sztyberto handle a gRPC request.  Finally, a DeviceManager needs to implement the
18079a3ac88SKonrad Sztyber`own_device()` method returning a boolean value indicating whether a given
18179a3ac88SKonrad Sztyberdevice handle is owned by that DeviceManager.
182