sma: add bdev QoS helper functions

These helper functions can be used by any device manager that wants to
provide volume-level QoS support using bdev-based QoS mechanism.  A
device manager is responsible for making sure that a volume exists and
is attached to a given device, but the validity of the QoS parameters is
checked within the helper functions.

Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I4d0efcf190a64b289b4cfbdf872f77e40a013d1f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14268
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Konrad Sztyber 2022-08-30 05:49:54 +02:00 committed by Tomasz Zawadzki
parent 784815ea3a
commit aed37fb98f

59
python/spdk/sma/qos.py Normal file
View File

@ -0,0 +1,59 @@
import grpc
from spdk.rpc.client import JSONRPCException
from .common import format_volume_id
from .proto import sma_pb2
LIMIT_UNDEFINED = (1 << 64) - 1
class QosException(Exception):
def __init__(self, code, message):
self.code = code
self.message = message
def set_volume_bdev_qos(client, params):
class BdevLimit:
def __init__(self, name, transform=lambda v: v):
self.name = name
self._transform = transform
def get_value(self, value):
return self._transform(value)
supported_limits = {
'rw_iops': BdevLimit('rw_ios_per_sec', lambda v: v * 1000),
'rd_bandwidth': BdevLimit('r_mbytes_per_sec'),
'wr_bandwidth': BdevLimit('w_mbytes_per_sec'),
'rw_bandwidth': BdevLimit('rw_mbytes_per_sec')
}
# Check that none of the unsupported fields aren't set either
if params.HasField('maximum'):
for field, value in params.maximum.ListFields():
if field.name in supported_limits.keys():
continue
if value != 0 and value != LIMIT_UNDEFINED:
raise QosException(grpc.StatusCode.INVALID_ARGUMENT,
f'Unsupported QoS limit: maximum.{field.name}')
try:
rpc_params = {'name': format_volume_id(params.volume_id)}
for name, limit in supported_limits.items():
value = getattr(params.maximum, name)
if value != LIMIT_UNDEFINED:
rpc_params[limit.name] = limit.get_value(value)
client.call('bdev_set_qos_limit', rpc_params)
except JSONRPCException:
raise QosException(grpc.StatusCode.INTERNAL, 'Failed to set QoS')
def get_bdev_qos_capabilities():
return sma_pb2.GetQosCapabilitiesResponse(
max_volume_caps=sma_pb2.GetQosCapabilitiesResponse.QosCapabilities(
rw_iops=True,
rw_bandwidth=True,
rd_bandwidth=True,
wr_bandwidth=True
),
)