217 lines
6.1 KiB
Python
217 lines
6.1 KiB
Python
"""
|
|
Utils for SPDK driver.
|
|
"""
|
|
|
|
import glob
|
|
import os
|
|
import re
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
|
|
from cyborg.accelerator import configuration
|
|
from cyborg.accelerator.common import exception
|
|
from cyborg.accelerator.drivers.spdk.util.pyspdk.py_spdk import PySPDK
|
|
from cyborg.common.i18n import _
|
|
from pyspdk.nvmf_client import NvmfTgt
|
|
from pyspdk.vhost_client import VhostTgt
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
accelerator_opts = [
|
|
cfg.StrOpt('spdk_conf_file',
|
|
default='/etc/cyborg/spdk.conf',
|
|
help=_('SPDK conf file to be used for the SPDK driver')),
|
|
|
|
cfg.StrOpt('accelerator_servers',
|
|
default=['vhost', 'nvmf', 'iscsi'],
|
|
help=_('A list of accelerator servers to enable by default')),
|
|
|
|
cfg.StrOpt('spdk_dir',
|
|
default='/home/wewe/spdk',
|
|
help=_('The SPDK directory is /home/{user_name}/spdk')),
|
|
|
|
cfg.StrOpt('device_type',
|
|
default='NVMe',
|
|
help=_('Backend device type is NVMe by default')),
|
|
|
|
cfg.BoolOpt('remoteable',
|
|
default=False,
|
|
help=_('Remoteable is false by default'))
|
|
]
|
|
|
|
CONF = cfg.CONF
|
|
CONF.register_opts(accelerator_opts, group=configuration.SHARED_CONF_GROUP)
|
|
|
|
config = configuration.Configuration(accelerator_opts)
|
|
config.append_config_values(accelerator_opts)
|
|
SERVERS = config.safe_get('accelerator_servers')
|
|
SERVERS_PATTERN = re.compile("|".join(["(%s)" % s for s in SERVERS]))
|
|
SPDK_SERVER_APP_DIR = os.path.join(config.safe_get('spdk_dir'), 'app/')
|
|
|
|
|
|
def discover_servers():
|
|
"""Discover backend servers according to the CONF
|
|
|
|
:returns: server list.
|
|
"""
|
|
servers = set()
|
|
for p in glob.glob1(SPDK_SERVER_APP_DIR, "*"):
|
|
m = SERVERS_PATTERN.match(p)
|
|
if m:
|
|
servers.add(m.group())
|
|
return list(servers)
|
|
|
|
|
|
def delete_bdev(py, accelerator, name):
|
|
"""Delete a blockdev
|
|
|
|
:param py: py_client.
|
|
:param accelerator: accelerator.
|
|
:param name: Blockdev name to be deleted.
|
|
"""
|
|
acc_client = get_accelerator_client(py, accelerator)
|
|
acc_client.delete_bdev(name)
|
|
|
|
|
|
def kill_instance(py, accelerator, sig_name):
|
|
"""Send signal to instance
|
|
|
|
:param py: py_client.
|
|
:param accelerator: accelerator.
|
|
:param sig_name: signal will be sent to server.
|
|
"""
|
|
acc_client = get_accelerator_client(py, accelerator)
|
|
acc_client.kill_instance(sig_name)
|
|
|
|
|
|
def construct_aio_bdev(py, accelerator, filename, name, block_size):
|
|
"""Add a bdev with aio backend
|
|
|
|
:param py: py_client.
|
|
:param accelerator: accelerator.
|
|
:param filename: Path to device or file (ex: /dev/sda).
|
|
:param name: Block device name.
|
|
:param block_size: Block size for this bdev.
|
|
:return: name.
|
|
"""
|
|
acc_client = get_accelerator_client(py, accelerator)
|
|
acc_client.construct_aio_bdev(filename, name, block_size)
|
|
return name
|
|
|
|
|
|
def construct_error_bdev(py, accelerator, basename):
|
|
"""Add a bdev with error backend
|
|
|
|
:param py: py_client.
|
|
:param accelerator: accelerator.
|
|
:param basename: Path to device or file (ex: /dev/sda).
|
|
"""
|
|
acc_client = get_accelerator_client(py, accelerator)
|
|
acc_client.construct_error_bdev(basename)
|
|
|
|
|
|
def construct_nvme_bdev(py,
|
|
accelerator,
|
|
name,
|
|
trtype,
|
|
traddr,
|
|
adrfam,
|
|
trsvcid,
|
|
subnqn
|
|
):
|
|
"""Add a bdev with nvme backend
|
|
|
|
:param py: py_client.
|
|
:param accelerator: accelerator.
|
|
:param name: Name of the bdev.
|
|
:param trtype: NVMe-oF target trtype: e.g., rdma, pcie.
|
|
:param traddr: NVMe-oF target address: e.g., an ip address
|
|
or BDF.
|
|
:param adrfam: NVMe-oF target adrfam: e.g., ipv4, ipv6, ib,
|
|
fc, intra_host.
|
|
:param trsvcid: NVMe-oF target trsvcid: e.g., a port number.
|
|
:param subnqn: NVMe-oF target subnqn.
|
|
:return: name.
|
|
"""
|
|
acc_client = get_accelerator_client(py, accelerator)
|
|
acc_client.construct_nvme_bdev(name,
|
|
trtype,
|
|
traddr,
|
|
adrfam,
|
|
trsvcid,
|
|
subnqn
|
|
)
|
|
return name
|
|
|
|
|
|
def construct_null_bdev(py,
|
|
accelerator,
|
|
name,
|
|
total_size,
|
|
block_size
|
|
):
|
|
"""Add a bdev with null backend
|
|
|
|
:param py: py_client.
|
|
:param accelerator: accelerator.
|
|
:param name: Block device name.
|
|
:param total_size: Size of null bdev in MB (int > 0).
|
|
:param block_size: Block size for this bdev.
|
|
:return: name.
|
|
"""
|
|
acc_client = get_accelerator_client(py, accelerator)
|
|
acc_client.construct_null_bdev(name, total_size, block_size)
|
|
return name
|
|
|
|
|
|
def get_py_client(server):
|
|
"""Get the py_client instance
|
|
|
|
:param server: server.
|
|
:return: Boolean.
|
|
:raise: InvalidAccelerator.
|
|
"""
|
|
if server in SERVERS:
|
|
py = PySPDK(server)
|
|
return py
|
|
else:
|
|
msg = (_("Could not find %s accelerator") % server)
|
|
raise exception.InvalidAccelerator(msg)
|
|
|
|
|
|
def check_for_setup_error(py, server):
|
|
"""Check server's status
|
|
|
|
:param py: py_client.
|
|
:param server: server.
|
|
:return: Boolean.
|
|
:raise: AcceleratorException.
|
|
"""
|
|
if py.is_alive():
|
|
return True
|
|
else:
|
|
msg = (_("%s accelerator is down") % server)
|
|
raise exception.AcceleratorException(msg)
|
|
|
|
|
|
def get_accelerator_client(py, accelerator):
|
|
"""Get the specific client that communicates with server
|
|
|
|
:param py: py_client.
|
|
:param accelerator: accelerator.
|
|
:return: acc_client.
|
|
:raise: InvalidAccelerator.
|
|
"""
|
|
acc_client = None
|
|
if accelerator == 'vhost':
|
|
acc_client = VhostTgt(py)
|
|
return acc_client
|
|
elif accelerator == 'nvmf':
|
|
acc_client = NvmfTgt(py)
|
|
return acc_client
|
|
else:
|
|
exc_msg = (_("accelerator_client %(acc_client) is missing")
|
|
% acc_client)
|
|
raise exception.InvalidAccelerator(exc_msg)
|