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:
parent
784815ea3a
commit
aed37fb98f
59
python/spdk/sma/qos.py
Normal file
59
python/spdk/sma/qos.py
Normal 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
|
||||||
|
),
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user