1# SPDX-License-Identifier: BSD-3-Clause 2# Copyright (C) 2022 Intel Corporation. 3# All rights reserved. 4 5import grpc 6 7from spdk.rpc.client import JSONRPCException 8from .common import format_volume_id 9from .proto import sma_pb2 10 11 12LIMIT_UNDEFINED = (1 << 64) - 1 13 14 15class QosException(Exception): 16 def __init__(self, code, message): 17 self.code = code 18 self.message = message 19 20 21def set_volume_bdev_qos(client, params): 22 class BdevLimit: 23 def __init__(self, name, transform=lambda v: v): 24 self.name = name 25 self._transform = transform 26 27 def get_value(self, value): 28 return self._transform(value) 29 30 supported_limits = { 31 'rw_iops': BdevLimit('rw_ios_per_sec', lambda v: v * 1000), 32 'rd_bandwidth': BdevLimit('r_mbytes_per_sec'), 33 'wr_bandwidth': BdevLimit('w_mbytes_per_sec'), 34 'rw_bandwidth': BdevLimit('rw_mbytes_per_sec') 35 } 36 # Check that none of the unsupported fields aren't set either 37 if params.HasField('maximum'): 38 for field, value in params.maximum.ListFields(): 39 if field.name in supported_limits.keys(): 40 continue 41 if value != 0 and value != LIMIT_UNDEFINED: 42 raise QosException(grpc.StatusCode.INVALID_ARGUMENT, 43 f'Unsupported QoS limit: maximum.{field.name}') 44 try: 45 rpc_params = {'name': format_volume_id(params.volume_id)} 46 for name, limit in supported_limits.items(): 47 value = getattr(params.maximum, name) 48 if value != LIMIT_UNDEFINED: 49 rpc_params[limit.name] = limit.get_value(value) 50 client.call('bdev_set_qos_limit', rpc_params) 51 except JSONRPCException: 52 raise QosException(grpc.StatusCode.INTERNAL, 'Failed to set QoS') 53 54 55def get_bdev_qos_capabilities(): 56 return sma_pb2.GetQosCapabilitiesResponse( 57 max_volume_caps=sma_pb2.GetQosCapabilitiesResponse.QosCapabilities( 58 rw_iops=True, 59 rw_bandwidth=True, 60 rd_bandwidth=True, 61 wr_bandwidth=True 62 ), 63 ) 64