sma: support bdev-based QoS for vhost_blk devices
test/sma verifies that bdev-based QoS settings are correctly applied on vhost devices. Signed-off-by: Sebastian Brzezinka <sebastian.brzezinka@intel.com> Change-Id: I1b66275dcf457295e6ae58814f1d08ed319fb52a Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14338 Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
2a6f3d9753
commit
4291ed5130
@ -1,9 +1,11 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import uuid
|
||||||
from socket import AddressFamily
|
from socket import AddressFamily
|
||||||
|
|
||||||
import grpc
|
import grpc
|
||||||
from spdk.rpc.client import JSONRPCException
|
from spdk.rpc.client import JSONRPCException
|
||||||
|
from spdk.sma import qos
|
||||||
|
|
||||||
from ..common import format_volume_id, volume_id_to_nguid
|
from ..common import format_volume_id, volume_id_to_nguid
|
||||||
from ..proto import sma_pb2, virtio_blk_pb2
|
from ..proto import sma_pb2, virtio_blk_pb2
|
||||||
@ -188,3 +190,33 @@ class VhostBlkDeviceManager(DeviceManager):
|
|||||||
if not self._delete_controller(client, ctrlr):
|
if not self._delete_controller(client, ctrlr):
|
||||||
raise DeviceException(grpc.StatusCode.INTERNAL,
|
raise DeviceException(grpc.StatusCode.INTERNAL,
|
||||||
'Failed to delete vhost device')
|
'Failed to delete vhost device')
|
||||||
|
|
||||||
|
def set_qos(self, request):
|
||||||
|
ctrlr = request.device_handle[len(f'{self._prefix}:'):]
|
||||||
|
volume = format_volume_id(request.volume_id)
|
||||||
|
try:
|
||||||
|
with self._client() as client:
|
||||||
|
nctrlr = self._find_controller(client, ctrlr)
|
||||||
|
if nctrlr is None:
|
||||||
|
raise DeviceException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||||
|
'No device associated with device_handle could be found')
|
||||||
|
nbdev = nctrlr['backend_specific']['block']['bdev']
|
||||||
|
if len(request.volume_id) == 0:
|
||||||
|
id = self._find_bdev(client, nbdev)['uuid']
|
||||||
|
request.volume_id = uuid.UUID(id).bytes
|
||||||
|
elif volume is not None:
|
||||||
|
if not self._bdev_cmp(client, nbdev, volume):
|
||||||
|
raise DeviceException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||||
|
'Specified volume is not attached to the device')
|
||||||
|
else:
|
||||||
|
raise DeviceException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||||
|
'Invalid volume uuid')
|
||||||
|
qos.set_volume_bdev_qos(client, request)
|
||||||
|
except qos.QosException as ex:
|
||||||
|
raise DeviceException(ex.code, ex.message)
|
||||||
|
except JSONRPCException:
|
||||||
|
raise DeviceException(grpc.StatusCode.INTERNAL,
|
||||||
|
'Failed to set QoS')
|
||||||
|
|
||||||
|
def get_qos_capabilities(self, request):
|
||||||
|
return qos.get_bdev_qos_capabilities()
|
||||||
|
@ -195,5 +195,136 @@ crypto_bdev=$(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "cry
|
|||||||
delete_device $devid0
|
delete_device $devid0
|
||||||
[[ $(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")' | jq -r length) -eq 0 ]]
|
[[ $(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")' | jq -r length) -eq 0 ]]
|
||||||
|
|
||||||
|
# Test qos
|
||||||
|
device_vhost=2
|
||||||
|
device=$(create_device 0 $uuid | jq -r '.handle')
|
||||||
|
|
||||||
|
# First check the capabilities
|
||||||
|
diff <(get_qos_caps $device_vhost | jq --sort-keys) <(
|
||||||
|
jq --sort-keys <<- CAPS
|
||||||
|
{
|
||||||
|
"max_volume_caps": {
|
||||||
|
"rw_iops": true,
|
||||||
|
"rd_bandwidth": true,
|
||||||
|
"wr_bandwidth": true,
|
||||||
|
"rw_bandwidth": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CAPS
|
||||||
|
)
|
||||||
|
|
||||||
|
"$rootdir/scripts/sma-client.py" <<- EOF
|
||||||
|
{
|
||||||
|
"method": "SetQos",
|
||||||
|
"params": {
|
||||||
|
"device_handle": "$device",
|
||||||
|
"volume_id": "$(uuid2base64 $uuid)",
|
||||||
|
"maximum": {
|
||||||
|
"rd_iops": 0,
|
||||||
|
"wr_iops": 0,
|
||||||
|
"rw_iops": 3,
|
||||||
|
"rd_bandwidth": 4,
|
||||||
|
"wr_bandwidth": 5,
|
||||||
|
"rw_bandwidth": 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Make sure that limits were changed
|
||||||
|
diff <(rpc_cmd bdev_get_bdevs -b null63 | jq --sort-keys '.[].assigned_rate_limits') <(
|
||||||
|
jq --sort-keys <<- EOF
|
||||||
|
{
|
||||||
|
"rw_ios_per_sec": 3000,
|
||||||
|
"rw_mbytes_per_sec": 6,
|
||||||
|
"r_mbytes_per_sec": 4,
|
||||||
|
"w_mbytes_per_sec": 5
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
# Try to set capabilities with empty volume id
|
||||||
|
"$rootdir/scripts/sma-client.py" <<- EOF
|
||||||
|
{
|
||||||
|
"method": "SetQos",
|
||||||
|
"params": {
|
||||||
|
"device_handle": "$device",
|
||||||
|
"volume_id": "",
|
||||||
|
"maximum": {
|
||||||
|
"rd_iops": 0,
|
||||||
|
"wr_iops": 0,
|
||||||
|
"rw_iops": 4,
|
||||||
|
"rd_bandwidth": 5,
|
||||||
|
"wr_bandwidth": 6,
|
||||||
|
"rw_bandwidth": 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Make sure that limits were changed even if volume id is not set
|
||||||
|
diff <(rpc_cmd bdev_get_bdevs -b null63 | jq --sort-keys '.[].assigned_rate_limits') <(
|
||||||
|
jq --sort-keys <<- EOF
|
||||||
|
{
|
||||||
|
"rw_ios_per_sec": 4000,
|
||||||
|
"rw_mbytes_per_sec": 7,
|
||||||
|
"r_mbytes_per_sec": 5,
|
||||||
|
"w_mbytes_per_sec": 6
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
# Try none-existing volume uuid
|
||||||
|
NOT "$rootdir/scripts/sma-client.py" <<- EOF
|
||||||
|
{
|
||||||
|
"method": "SetQos",
|
||||||
|
"params": {
|
||||||
|
"device_handle": "$device",
|
||||||
|
"volume_id": "$(uuid2base64 $(uuidgen))",
|
||||||
|
"maximum": {
|
||||||
|
"rd_iops": 0,
|
||||||
|
"wr_iops": 0,
|
||||||
|
"rw_iops": 5,
|
||||||
|
"rd_bandwidth": 6,
|
||||||
|
"wr_bandwidth": 7,
|
||||||
|
"rw_bandwidth": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Try invalid (too short) volume uuid
|
||||||
|
NOT "$rootdir/scripts/sma-client.py" <<- EOF
|
||||||
|
{
|
||||||
|
"method": "SetQos",
|
||||||
|
"params": {
|
||||||
|
"device_handle": "$device",
|
||||||
|
"volume_id": "$(base64 <<<'invalid'))",
|
||||||
|
"maximum": {
|
||||||
|
"rd_iops": 0,
|
||||||
|
"wr_iops": 0,
|
||||||
|
"rw_iops": 5,
|
||||||
|
"rd_bandwidth": 6,
|
||||||
|
"wr_bandwidth": 7,
|
||||||
|
"rw_bandwidth": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Values remain unchanged
|
||||||
|
diff <(rpc_cmd bdev_get_bdevs -b null63 | jq --sort-keys '.[].assigned_rate_limits') <(
|
||||||
|
jq --sort-keys <<- EOF
|
||||||
|
{
|
||||||
|
"rw_ios_per_sec": 4000,
|
||||||
|
"rw_mbytes_per_sec": 7,
|
||||||
|
"r_mbytes_per_sec": 5,
|
||||||
|
"w_mbytes_per_sec": 6
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
delete_device "$device"
|
||||||
|
|
||||||
cleanup
|
cleanup
|
||||||
trap - SIGINT SIGTERM EXIT
|
trap - SIGINT SIGTERM EXIT
|
||||||
|
Loading…
Reference in New Issue
Block a user