summaryrefslogtreecommitdiffstats
path: root/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator
diff options
context:
space:
mode:
Diffstat (limited to 'cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator')
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/__init__.py19
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/accelerator.py36
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/common/__init__.py0
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/common/exception.py123
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/configuration.py157
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/__init__.py0
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/base.py79
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/__init__.py41
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/base.py51
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/__init__.py0
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/driver.py56
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/sysinfo.py162
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/utils.py36
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/generic_driver.py80
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/__init__.py28
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/base.py56
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/__init__.py1
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/driver.py41
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/sysinfo.py30
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/utils.py67
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/__init__.py0
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/generic.py81
-rwxr-xr-xcyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/netronome.py73
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/spdk.py147
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/__init__.py0
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/nvmf/__init__.py0
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/nvmf/nvmf.py113
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/spdk.py75
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/__init__.py0
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/common_fun.py206
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/__init__.py0
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/nvmf_client.py119
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/py_spdk.py82
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/vhost_client.py121
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/vhost/__init__.py0
-rw-r--r--cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/vhost/vhost.py92
36 files changed, 2172 insertions, 0 deletions
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/__init__.py
new file mode 100644
index 0000000..d0f34f0
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/__init__.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import pbr.version
+
+
+__version__ = pbr.version.VersionInfo(
+ 'cyborg').version_string()
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/accelerator.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/accelerator.py
new file mode 100644
index 0000000..18cc4e9
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/accelerator.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2016-2017 OpenStack Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from sqlalchemy import Column, Integer, String
+from sqlalchemy.ext.declarative import declarative_base
+Base = declarative_base()
+
+
+# A common internal acclerator object for internal use.
+class Accelerator(Base):
+ __tablename__ = 'accelerators'
+ accelerator_id = Column(String, primary_key=True)
+ device_type = Column(String)
+ remoteable = Column(Integer)
+ vender_id = Column(String)
+ product_id = Column(String)
+
+ def __init__(self, **kwargs):
+ self.accelerator_id = kwargs['accelerator_id']
+ self.device_type = kwargs['device_type']
+ self.remoteable = kwargs['remoteable']
+ self.vendor_id = kwargs['vendor_id']
+ self.product_id = kwargs['product_id']
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/common/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/common/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/common/__init__.py
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/common/exception.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/common/exception.py
new file mode 100644
index 0000000..5999e02
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/common/exception.py
@@ -0,0 +1,123 @@
+# Copyright 2017 Lenovo, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Accelerator base exception handling. """
+
+import collections
+import json
+from oslo_log import log as logging
+import six
+from six.moves import http_client
+from cyborg.common.i18n import _
+
+
+LOG = logging.getLogger(__name__)
+
+
+def _ensure_exception_kwargs_serializable(exc_class_name, kwargs):
+ """Ensure that kwargs are serializable
+
+ Ensure that all kwargs passed to exception constructor can be passed over
+ RPC, by trying to convert them to JSON, or, as a last resort, to string.
+ If it is not possible, unserializable kwargs will be removed, letting the
+ receiver to handle the exception string as it is configured to.
+
+ :param exc_class_name: an AcceleratorException class name.
+ :param kwargs: a dictionary of keyword arguments passed to the exception
+ constructor.
+ :returns: a dictionary of serializable keyword arguments.
+ """
+ serializers = [(json.dumps, _('when converting to JSON')),
+ (six.text_type, _('when converting to string'))]
+ exceptions = collections.defaultdict(list)
+ serializable_kwargs = {}
+ for k, v in kwargs.items():
+ for serializer, msg in serializers:
+ try:
+ serializable_kwargs[k] = serializer(v)
+ exceptions.pop(k, None)
+ break
+ except Exception as e:
+ exceptions[k].append(
+ '(%(serializer_type)s) %(e_type)s: %(e_contents)s' %
+ {'serializer_type': msg, 'e_contents': e,
+ 'e_type': e.__class__.__name__})
+ if exceptions:
+ LOG.error("One or more arguments passed to the %(exc_class)s "
+ "constructor as kwargs can not be serialized. The "
+ "serialized arguments: %(serialized)s. These "
+ "unserialized kwargs were dropped because of the "
+ "exceptions encountered during their "
+ "serialization:\n%(errors)s",
+ dict(errors=';\n'.join("%s: %s" % (k, '; '.join(v))
+ for k, v in exceptions.items()),
+ exc_class=exc_class_name,
+ serialized=serializable_kwargs))
+ # We might be able to actually put the following keys' values into
+ # format string, but there is no guarantee, drop it just in case.
+ for k in exceptions:
+ del kwargs[k]
+ return serializable_kwargs
+
+
+class AcceleratorException(Exception):
+ """Base Accelerator Exception
+
+ To correctly use this class, inherit from it and define
+ a '_msg_fmt' property. That message will get printf'd
+ with the keyword arguments provided to the constructor.
+
+ If you need to access the message from an exception you should use
+ six.text_type(exc)
+
+ """
+ _msg_fmt = _("An unknown exception occurred.")
+ code = http_client.INTERNAL_SERVER_ERROR
+ headers = {}
+ safe = False
+
+ def __init__(self, message=None, **kwargs):
+
+ self.kwargs = _ensure_exception_kwargs_serializable(
+ self.__class__.__name__, kwargs)
+
+ if 'code' not in self.kwargs:
+ try:
+ self.kwargs['code'] = self.code
+ except AttributeError:
+ pass
+
+ if not message:
+ if kwargs:
+ message = self._msg_fmt % kwargs
+ else:
+ message = self._msg_fmt
+
+ super(AcceleratorException, self).__init__(message)
+
+
+class Invalid(AcceleratorException):
+ _msg_fmt = _("Unacceptable parameters.")
+
+
+class InvalidParameterValue(Invalid):
+ _msg_fmt = "%(err)s"
+
+
+class MissingParameterValue(InvalidParameterValue):
+ _msg_fmt = "%(err)s"
+
+
+class InvalidAccelerator(InvalidParameterValue):
+ _msg_fmt = '%(err)s' \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/configuration.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/configuration.py
new file mode 100644
index 0000000..b1c172a
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/configuration.py
@@ -0,0 +1,157 @@
+# Copyright (c) 2012 Rackspace Hosting
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Configuration support for all drivers. from openstack/cyborg"""
+
+from oslo_config import cfg
+
+CONF = cfg.CONF
+SHARED_CONF_GROUP = 'backend_defaults'
+
+
+class DefaultGroupConfiguration(object):
+ """Get config options from only DEFAULT."""
+
+ def __init__(self):
+ # set the local conf so that __call__'s know what to use
+ self.local_conf = CONF
+
+ def _ensure_config_values(self, accelerator_opts):
+ CONF.register_opts(accelerator_opts, group=None)
+
+ def append_config_values(self, accelerator_opts):
+ self._ensure_config_values(accelerator_opts)
+
+ def safe_get(self, value):
+ """get default group value from CONF
+ :param value: value.
+ :return: get default group value from CONF.
+ """
+ try:
+ return self.__getattr__(value)
+ except cfg.NoSuchOptError:
+ return None
+
+ def __getattr__(self, value):
+ """Don't use self.local_conf to avoid reentrant call to __getattr__()
+ :param value: value.
+ :return: getattr(local_conf, value).
+ """
+ local_conf = object.__getattribute__(self, 'local_conf')
+ return getattr(local_conf, value)
+
+
+class BackendGroupConfiguration(object):
+ def __init__(self, accelerator_opts, config_group=None):
+ """Initialize configuration.
+ This takes care of grafting the implementation's config
+ values into the config group and shared defaults. We will try to
+ pull values from the specified 'config_group', but fall back to
+ defaults from the SHARED_CONF_GROUP.
+ """
+ self.config_group = config_group
+
+ # set the local conf so that __call__'s know what to use
+ self._ensure_config_values(accelerator_opts)
+ self.backend_conf = CONF._get(self.config_group)
+ self.shared_backend_conf = CONF._get(SHARED_CONF_GROUP)
+
+ def _safe_register(self, opt, group):
+ try:
+ CONF.register_opt(opt, group=group)
+ except cfg.DuplicateOptError:
+ pass # If it's already registered ignore it
+
+ def _ensure_config_values(self, accelerator_opts):
+ """Register the options in the shared group.
+ When we go to get a config option we will try the backend specific
+ group first and fall back to the shared group. We override the default
+ from all the config options for the backend group so we can know if it
+ was set or not.
+ """
+ for opt in accelerator_opts:
+ self._safe_register(opt, SHARED_CONF_GROUP)
+ # Assuming they aren't the same groups, graft on the options into
+ # the backend group and override its default value.
+ if self.config_group != SHARED_CONF_GROUP:
+ self._safe_register(opt, self.config_group)
+ CONF.set_default(opt.name, None, group=self.config_group)
+
+ def append_config_values(self, accelerator_opts):
+ self._ensure_config_values(accelerator_opts)
+
+ def set_default(self, opt_name, default):
+ CONF.set_default(opt_name, default, group=SHARED_CONF_GROUP)
+
+ def get(self, key, default=None):
+ return getattr(self, key, default)
+
+ def safe_get(self, value):
+ """get config_group value from CONF
+ :param value: value.
+ :return: get config_group value from CONF.
+ """
+
+ try:
+ return self.__getattr__(value)
+ except cfg.NoSuchOptError:
+ return None
+
+ def __getattr__(self, opt_name):
+ """Don't use self.X to avoid reentrant call to __getattr__()
+ :param opt_name: opt_name.
+ :return: opt_value.
+ """
+ backend_conf = object.__getattribute__(self, 'backend_conf')
+ opt_value = getattr(backend_conf, opt_name)
+ if opt_value is None:
+ shared_conf = object.__getattribute__(self, 'shared_backend_conf')
+ opt_value = getattr(shared_conf, opt_name)
+ return opt_value
+
+
+class Configuration(object):
+ def __init__(self, accelerator_opts, config_group=None):
+ """Initialize configuration.
+ This shim will allow for compatibility with the DEFAULT
+ style of backend configuration which is used by some of the users
+ of this configuration helper, or by the volume drivers that have
+ all been forced over to the config_group style.
+ """
+ self.config_group = config_group
+ if config_group:
+ self.conf = BackendGroupConfiguration(accelerator_opts,
+ config_group)
+ else:
+ self.conf = DefaultGroupConfiguration()
+
+ def append_config_values(self, accelerator_opts):
+ self.conf.append_config_values(accelerator_opts)
+
+ def safe_get(self, value):
+ """get value from CONF
+ :param value: value.
+ :return: get value from CONF.
+ """
+
+ return self.conf.safe_get(value)
+
+ def __getattr__(self, value):
+ """Don't use self.conf to avoid reentrant call to __getattr__()
+ :param value: value.
+ :return: getattr(conf, value).
+ """
+ conf = object.__getattribute__(self, 'conf')
+ return getattr(conf, value) \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/__init__.py
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/base.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/base.py
new file mode 100644
index 0000000..2706022
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/base.py
@@ -0,0 +1,79 @@
+# Copyright 2017 Lenovo, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+"""
+Abstract base classes for drivers.
+"""
+
+import abc
+import six
+
+
+@six.add_metaclass(abc.ABCMeta)
+class BaseDriver(object):
+ """Base class for all drivers.
+
+ Defines the abstract base class for generic and vendor drivers.
+ """
+
+ standard_interfaces = ('discover', 'list', 'update', 'attach', 'detach')
+
+ discover = None
+ """`Standard` attribute for discovering drivers.
+
+ A reference to an instance of :class:DiscoverInterface.
+ """
+
+ list = None
+ """`Core` attribute for listing drivers.
+
+ A reference to an instance of :class:ListInterface.
+ """
+
+ update = None
+ """`Standard` attribute to update drivers.
+
+ A reference to an instance of :class:UpdateInterface.
+ """
+
+ attach = None
+ """`Standard` attribute to attach accelerator to an instance.
+
+ A reference to an instance of :class:AttachInterface.
+ """
+
+ detach = None
+ """`Standard` attribute to detach accelerator to an instance.
+
+ A reference to an instance of :class:AttachInterface.
+ """
+
+ def __init__(self):
+ pass
+
+ @property
+ def all_interfaces(self):
+ return (list(self.standard_interfaces))
+
+ def get_properties(self):
+ """Gets the properties of the driver.
+
+ :returns: dictionary of <property name>:<property description> entries.
+ """
+
+ properties = {}
+ for iface_name in self.all_interfaces:
+ iface = getattr(self, iface_name, None)
+ if iface:
+ properties.update(iface.get_properties())
+ return properties
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/__init__.py
new file mode 100644
index 0000000..d6eaff6
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/__init__.py
@@ -0,0 +1,41 @@
+# Copyright 2018 Intel, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import os
+import glob
+
+from oslo_log import log as logging
+
+
+__import__('pkg_resources').declare_namespace(__name__)
+__import__(".".join([__package__, 'base']))
+
+
+LOG = logging.getLogger(__name__)
+
+
+def load_fpga_vendor_driver():
+ files = glob.glob(os.path.join(os.path.dirname(__file__), "*/driver*"))
+ modules = set(map(lambda s: ".".join(s.rsplit(".")[0].rsplit("/", 2)[-2:]),
+ files))
+ for m in modules:
+ try:
+ __import__(".".join([__package__, m]))
+ LOG.debug("Successfully loaded FPGA vendor driver: %s." % m)
+ except ImportError as e:
+ LOG.error("Failed to load FPGA vendor driver: %s. Details: %s"
+ % (m, e))
+
+
+load_fpga_vendor_driver() \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/base.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/base.py
new file mode 100644
index 0000000..4da1d9d
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/base.py
@@ -0,0 +1,51 @@
+# Copyright 2018 Intel, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Cyborg FPGA driver implementation.
+"""
+
+from cyborg.accelerator.drivers.fpga import utils
+
+
+VENDOR_MAPS = {"0x8086": "intel"}
+
+
+class FPGADriver(object):
+ """Base class for FPGA drivers.
+ This is just a virtual FPGA drivers interface.
+ Vendors should implement their specific drivers.
+ """
+
+ @classmethod
+ def create(cls, vendor, *args, **kwargs):
+ for sclass in cls.__subclasses__():
+ vendor = VENDOR_MAPS.get(vendor, vendor)
+ if vendor == sclass.VENDOR:
+ return sclass(*args, **kwargs)
+ raise LookupError("Not find the FPGA driver for vendor %s" % vendor)
+
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def discover(self):
+ raise NotImplementedError()
+
+ def program(self, device_path, image):
+ raise NotImplementedError()
+
+ @classmethod
+ def discover_vendors(cls):
+ return utils.discover_vendors() \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/__init__.py
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/driver.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/driver.py
new file mode 100644
index 0000000..d04f7d9
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/driver.py
@@ -0,0 +1,56 @@
+
+# Copyright 2018 Intel, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Cyborg Intel FPGA driver implementation.
+"""
+
+import subprocess
+
+from cyborg.accelerator.drivers.fpga.base import FPGADriver
+from cyborg.accelerator.drivers.fpga.intel import sysinfo
+
+
+class IntelFPGADriver(FPGADriver):
+ """Base class for FPGA drivers.
+ This is just a virtual FPGA drivers interface.
+ Vedor should implement their specific drivers.
+ """
+ VENDOR = "intel"
+
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def discover(self):
+ return sysinfo.fpga_tree()
+
+ def program(self, device_path, image):
+ bdf = ""
+ path = sysinfo.find_pf_by_vf(device_path) if sysinfo.is_vf(
+ device_path) else device_path
+ if sysinfo.is_bdf(device_path):
+ bdf = sysinfo.get_pf_bdf(device_path)
+ else:
+ bdf = sysinfo.get_bdf_by_path(path)
+ bdfs = sysinfo.split_bdf(bdf)
+ cmd = ["sudo", "fpgaconf"]
+ for i in zip(["-b", "-d", "-f"], bdfs):
+ cmd.extend(i)
+ cmd.append(image)
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ # FIXME Should log p.communicate(), p.stderr
+ p.wait()
+ return p.returncode \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/sysinfo.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/sysinfo.py
new file mode 100644
index 0000000..64cfc13
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/intel/sysinfo.py
@@ -0,0 +1,162 @@
+# Copyright 2018 Intel, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Cyborg Intel FPGA driver implementation.
+"""
+
+# from cyborg.accelerator.drivers.fpga.base import FPGADriver
+
+import glob
+import os
+import re
+
+
+SYS_FPGA = "/sys/class/fpga"
+DEVICE = "device"
+PF = "physfn"
+VF = "virtfn*"
+BDF_PATTERN = re.compile(
+ "^[a-fA-F\d]{4}:[a-fA-F\d]{2}:[a-fA-F\d]{2}\.[a-fA-F\d]$")
+
+
+DEVICE_FILE_MAP = {"vendor": "vendor_id",
+ "device": "product_id",
+ "sriov_numvfs": "pr_num"}
+DEVICE_FILE_HANDLER = {}
+DEVICE_EXPOSED = ["vendor", "device", "sriov_numvfs"]
+
+
+def all_fpgas():
+ # glob.glob1("/sys/class/fpga", "*")
+ return glob.glob(os.path.join(SYS_FPGA, "*"))
+
+
+def all_vf_fpgas():
+ return [dev.rsplit("/", 2)[0] for dev in
+ glob.glob(os.path.join(SYS_FPGA, "*/device/physfn"))]
+
+
+def all_pure_pf_fpgas():
+ return [dev.rsplit("/", 2)[0] for dev in
+ glob.glob(os.path.join(SYS_FPGA, "*/device/virtfn0"))]
+
+
+def target_symbolic_map():
+ maps = {}
+ for f in glob.glob(os.path.join(SYS_FPGA, "*/device")):
+ maps[os.path.realpath(f)] = os.path.dirname(f)
+ return maps
+
+
+def bdf_path_map():
+ maps = {}
+ for f in glob.glob(os.path.join(SYS_FPGA, "*/device")):
+ maps[os.path.basename(os.path.realpath(f))] = os.path.dirname(f)
+ return maps
+
+
+def all_vfs_in_pf_fpgas(pf_path):
+ maps = target_symbolic_map()
+ vfs = glob.glob(os.path.join(pf_path, "device/virtfn*"))
+ return [maps[os.path.realpath(vf)] for vf in vfs]
+
+
+def all_pf_fpgas():
+ return [dev.rsplit("/", 2)[0] for dev in
+ glob.glob(os.path.join(SYS_FPGA, "*/device/sriov_totalvfs"))]
+
+
+def is_vf(path):
+ return True if glob.glob(os.path.join(path, "device/physfn")) else False
+
+
+def find_pf_by_vf(path):
+ maps = target_symbolic_map()
+ p = os.path.realpath(os.path.join(path, "device/physfn"))
+ return maps[p]
+
+
+def is_bdf(bdf):
+ return True if BDF_PATTERN.match(bdf) else False
+
+
+def get_bdf_by_path(path):
+ return os.path.basename(os.readlink(os.path.join(path, "device")))
+
+
+def split_bdf(bdf):
+ return ["0x" + v for v in bdf.replace(".", ":").rsplit(":")[1:]]
+
+
+def get_pf_bdf(bdf):
+ path = bdf_path_map().get(bdf)
+ if path:
+ path = find_pf_by_vf(path) if is_vf(path) else path
+ return get_bdf_by_path(path)
+ return bdf
+
+
+def fpga_device(path):
+ infos = {}
+
+ def read_line(filename):
+ with open(filename) as f:
+ return f.readline().strip()
+
+ # NOTE "In 3.x, os.path.walk is removed in favor of os.walk."
+ for (dirpath, dirnames, filenames) in os.walk(path):
+ for filename in filenames:
+ if filename in DEVICE_EXPOSED:
+ key = DEVICE_FILE_MAP.get(filename) or filename
+ if key in DEVICE_FILE_HANDLER and callable(
+ DEVICE_FILE_HANDLER(key)):
+ infos[key] = DEVICE_FILE_HANDLER(key)(
+ os.path.join(dirpath, filename))
+ else:
+ infos[key] = read_line(os.path.join(dirpath, filename))
+ return infos
+
+
+def fpga_tree():
+
+ def gen_fpga_infos(path, vf=True):
+ name = os.path.basename(path)
+ dpath = os.path.realpath(os.path.join(path, DEVICE))
+ bdf = os.path.basename(dpath)
+ func = "vf" if vf else "pf"
+ pf_bdf = os.path.basename(
+ os.path.realpath(os.path.join(dpath, PF))) if vf else ""
+ fpga = {"path": path, "function": func,
+ "devices": bdf, "assignable": True,
+ "parent_devices": pf_bdf,
+ "name": name}
+ d_info = fpga_device(dpath)
+ fpga.update(d_info)
+ return fpga
+
+ devs = []
+ pure_pfs = all_pure_pf_fpgas()
+ for pf in all_pf_fpgas():
+ fpga = gen_fpga_infos(pf, False)
+ if pf in pure_pfs:
+ fpga["assignable"] = False
+ fpga["regions"] = []
+ vfs = all_vfs_in_pf_fpgas(pf)
+ for vf in vfs:
+ vf_fpga = gen_fpga_infos(vf, True)
+ fpga["regions"].append(vf_fpga)
+ devs.append(fpga)
+ return devs \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/utils.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/utils.py
new file mode 100644
index 0000000..b090659
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/fpga/utils.py
@@ -0,0 +1,36 @@
+# Copyright 2018 Intel, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Utils for FPGA driver.
+"""
+
+import glob
+import re
+
+
+VENDORS = ["intel"] # can extend, such as ["intel", "xilinx"]
+
+SYS_FPGA_PATH = "/sys/class/fpga"
+VENDORS_PATTERN = re.compile("|".join(["(%s)" % v for v in VENDORS]))
+
+
+def discover_vendors():
+ vendors = set()
+ for p in glob.glob1(SYS_FPGA_PATH, "*"):
+ m = VENDORS_PATTERN.match(p)
+ if m:
+ vendors.add(m.group())
+ return list(vendors) \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/generic_driver.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/generic_driver.py
new file mode 100644
index 0000000..2e13ecc
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/generic_driver.py
@@ -0,0 +1,80 @@
+# Copyright 2017 Lenovo, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Cyborg Generic driver implementation.
+"""
+
+from modules import generic
+from oslo_config import cfg
+from oslo_log import log
+
+from cyborg.accelerator import accelerator
+from cyborg.conductor.rpcapi import ConductorAPI as conductor_api
+
+LOG = log.getLogger(__name__)
+
+
+CONF = cfg.CONF
+
+
+class GenericDriver(generic.GENERICDRIVER):
+ """Executes commands relating to Shares."""
+
+ def __init__(self, *args, **kwargs):
+ """Do initialization."""
+ super(GenericDriver, self).__init__()
+ self.configuration.append_config_values()
+ self._helpers = {}
+ self.backend_name = self.configuration.safe_get(
+ 'accelerator_backend_name')
+
+ def do_setup(self, context):
+ """Any initialization the generic driver does while starting."""
+ super(GenericDriver, self).do_setup(context)
+ self.acc = accelerator.Accelerator()
+
+ def create_accelerator(self, context):
+ """Creates accelerator."""
+ self.acc = conductor_api.accelerator_create(
+ context=context, obj_acc=self.accelerator)
+ LOG.debug("Created a new accelerator with the UUID %s ",
+ self.accelerator.accelerator_id)
+
+ def get_accelerator(self, context):
+ """Gets accelerator by UUID."""
+ self.acc = conductor_api.accelerator_list_one(
+ context=context, obj_acc=self.accelerator)
+ return self.acc
+
+ def list_accelerators(self, context):
+ """Lists all accelerators."""
+ self.acc = conductor_api.accelerator_list_all(
+ context=context, obj_acc=self.accelerator)
+ return self.acc
+
+ def update_accelerator(self, context):
+ """Updates accelerator with a patch update."""
+
+ self.acc = conductor_api.accelerator_update(
+ context=context, obj_acc=self.accelerator)
+ LOG.debug("Updated accelerator %s ",
+ self.accelerator.accelerator_id)
+
+ def delete_accelerator(self, context):
+ """Deletes a specific accelerator."""
+ LOG.debug("Deleting accelerator %s ", self.accelerator.accelerator_id)
+ conductor_api.accelerator_delete(context=context,
+ obj_acc=self.accelerator)
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/__init__.py
new file mode 100644
index 0000000..a226d3f
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/__init__.py
@@ -0,0 +1,28 @@
+from cyborg.accelerator.drivers.gpu.nvidia.driver import NVIDIAGPUDriver
+import os
+import glob
+
+from oslo_log import log as logging
+
+
+__import__('pkg_resources').declare_namespace(__name__)
+__import__(".".join([__package__, 'base']))
+
+
+LOG = logging.getLogger(__name__)
+
+
+def load_gpu_vendor_driver():
+ files = glob.glob(os.path.join(os.path.dirname(__file__), "*/driver*"))
+ modules = set(map(lambda s: ".".join(s.rsplit(".")[0].rsplit("/", 2)[-2:]),
+ files))
+ for m in modules:
+ try:
+ __import__(".".join([__package__, m]))
+ LOG.debug("Successfully loaded GPU vendor driver: %s." % m)
+ except ImportError as e:
+ LOG.error("Failed to load GPU vendor driver: %s. Details: %s"
+ % (m, e))
+
+
+load_gpu_vendor_driver()
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/base.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/base.py
new file mode 100644
index 0000000..80f31fc
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/base.py
@@ -0,0 +1,56 @@
+# Copyright 2018 Lenovo, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Cyborg GPU driver implementation.
+"""
+from oslo_log import log as logging
+
+from cyborg.accelerator.drivers.gpu import utils
+
+
+LOG = logging.getLogger(__name__)
+
+VENDOR_MAPS = {"10de": "nvidia", "102b": "matrox"}
+
+
+class GPUDriver(object):
+ """Base class for GPU drivers.
+
+ This is just a virtual GPU drivers interface.
+ Vedor should implement their specific drivers.
+ """
+
+ @classmethod
+ def create(cls, vendor, *args, **kwargs):
+ for sclass in cls.__subclasses__():
+ vendor_name = VENDOR_MAPS.get(vendor)
+ if vendor_name == sclass.VENDOR:
+ return sclass(*args, **kwargs)
+ # raise LookupError("Not find the GPU driver for vendor_id %s" % vendor)
+ LOG.warn("Not find the GPU driver for vendor_id %s" % vendor)
+
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def discover(self):
+ raise NotImplementedError()
+
+ def program(self, device_path, image):
+ raise NotImplementedError()
+
+ @classmethod
+ def discover_vendors(cls):
+ return utils.discover_vendors()
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/__init__.py
new file mode 100644
index 0000000..4e5d499
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/__init__.py
@@ -0,0 +1 @@
+__author__ = 'wangzh21'
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/driver.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/driver.py
new file mode 100644
index 0000000..c225555
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/driver.py
@@ -0,0 +1,41 @@
+# Copyright 2018 Lenovo, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Cyborg Intel GPU driver implementation.
+"""
+
+import subprocess
+
+from cyborg.accelerator.drivers.gpu.base import GPUDriver
+from cyborg.accelerator.drivers.gpu.nvidia import sysinfo
+
+
+class NVIDIAGPUDriver(GPUDriver):
+ """Base class for GPU drivers.
+
+ This is just a virtual GPU drivers interface.
+ Vedor should implement their specific drivers.
+ """
+ VENDOR = "nvidia"
+
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def discover(self):
+ return sysinfo.gpu_tree()
+
+ def program(self, device_path, image):
+ pass
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/sysinfo.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/sysinfo.py
new file mode 100644
index 0000000..cab4c32
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/nvidia/sysinfo.py
@@ -0,0 +1,30 @@
+# Copyright 2018 Lenovo, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Cyborg Intel GPU driver implementation.
+"""
+
+from cyborg.accelerator.drivers.gpu import utils
+VENDER_ID = "10de"
+
+
+def all_gpus():
+ pass
+
+
+def gpu_tree():
+ devs = utils.discover_gpus(VENDER_ID)
+ return devs
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/utils.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/utils.py
new file mode 100644
index 0000000..97c7909
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/gpu/utils.py
@@ -0,0 +1,67 @@
+# Copyright 2018 Lenovo, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Utils for GPU driver.
+"""
+
+import re
+import subprocess
+
+
+GPU_FLAGS = ["VGA compatible controller", "3D controller"]
+GPU_INFO_PATTERN = re.compile("(?P<devices>[0-9]{2}:[0-9]{2}\.[0-9]) (?P"
+ "<name>.*) \[.* [\[](?P<vendor_id>[0-9a-fA-F]{4})"
+ ":(?P<product_id>[0-9a-fA-F]{4})] .*")
+
+
+def discover_vendors():
+ cmd = "sudo lspci -nnn | grep -E '%s'"
+ cmd = cmd % "|".join(GPU_FLAGS)
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
+ p.wait()
+ gpus = p.stdout.readlines()
+ vendors = set()
+ for gpu in gpus:
+ m = GPU_INFO_PATTERN.match(gpu)
+ if m:
+ vendor_id = m.groupdict().get("vendor_id")
+ vendors.add(vendor_id)
+ return vendors
+
+
+def discover_gpus(vender_id=None):
+ cmd = "sudo lspci -nnn | grep -E '%s'"
+ cmd = cmd % "|".join(GPU_FLAGS)
+ if vender_id:
+ cmd = cmd + "| grep " + vender_id
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
+ p.wait()
+ gpus = p.stdout.readlines()
+ gpu_list = []
+ for gpu in gpus:
+ m = GPU_INFO_PATTERN.match(gpu)
+ if m:
+ gpu_dict = m.groupdict()
+ gpu_dict["function"] = "GPU"
+ gpu_dict["devices"] = _match_nova_addr(gpu_dict["devices"])
+ gpu_dict["assignable"] = True
+ gpu_list.append(gpu_dict)
+ return gpu_list
+
+
+def _match_nova_addr(devices):
+ addr = '0000:'+devices.replace(".", ":")
+ return addr
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/__init__.py
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/generic.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/generic.py
new file mode 100644
index 0000000..cc284a7
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/generic.py
@@ -0,0 +1,81 @@
+# Copyright 2017 Lenovo, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+"""
+Cyborg Generic driver modules implementation.
+"""
+
+from cyborg.accelerator.common import exception
+from cyborg.accelerator.drivers import base
+from oslo_log import log as logging
+
+LOG = logging.getLogger(__name__)
+
+# NOTE (crushil): REQUIRED_PROPERTIES needs to be filled out.
+REQUIRED_PROPERTIES = {'create', 'get', 'list', 'update', 'delete'}
+COMMON_PROPERTIES = REQUIRED_PROPERTIES
+
+
+def _check_for_missing_params(info_dict, error_msg, param_prefix=''):
+ missing_info = []
+ for label, value in info_dict.items():
+ if not value:
+ missing_info.append(param_prefix + label)
+
+ if missing_info:
+ exc_msg = _("%(error_msg)s. Missing are: %(missing_info)s")
+ raise exception.MissingParameterValue(
+ exc_msg % {'error_msg': error_msg, 'missing_info': missing_info})
+
+
+def _parse_driver_info(driver):
+ info = driver.driver_info
+ d_info = {k: info.get(k) for k in COMMON_PROPERTIES}
+ error_msg = _("Cannot validate Generic Driver. Some parameters were"
+ " missing in the configuration file.")
+ _check_for_missing_params(d_info, error_msg)
+ return d_info
+
+
+class GENERICDRIVER(base.BaseDriver):
+
+ def get_properties(self):
+ """Return the properties of the generic driver.
+
+ :returns: dictionary of <property name>:<property description> entries.
+ """
+ return COMMON_PROPERTIES
+
+ def attach(self, accelerator, instance):
+
+ def install(self, accelerator):
+ pass
+
+ def detach(self, accelerator, instance):
+
+ def uninstall(self, accelerator):
+ pass
+
+ def delete(self):
+ pass
+
+ def discover(self):
+ pass
+
+ def list(self):
+ pass
+
+ def update(self, accelerator, **kwargs):
+ pass
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/netronome.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/netronome.py
new file mode 100755
index 0000000..6b15d34
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/netronome.py
@@ -0,0 +1,73 @@
+"""
+Cyborg Netronome driver modules implementation.
+"""
+import os
+import json
+import socket
+
+
+
+from cyborg.accelerator.drivers.modules import generic
+
+from oslo_log import log as logging
+
+LOG = logging.getLogger(__name__)
+
+class NETRONOMEDRIVER(generic.GENERICDRIVER):
+ def __init__(self, *args, **kwargs):
+ super(NETRONOMEDRIVER, self).__init__(*args, **kwargs)
+
+ self.port_name_prefix = 'sdn_v0.'
+ self.port_index_max = 59
+
+ def get_available_resource(self):
+ port_resource = self._read_config()
+ if port_resource:
+ for port in port_resource:
+ port["computer_node"] = socket.gethostname()
+ LOG.info('Discover netronome port %s '% (port_resource))
+ return port_resource
+
+ def _ovs_port_check(self, port_name):
+ for port in self.bridge_port_list:
+ if port_name == port.strip():
+ return True
+
+ return False
+
+
+ def _read_config(self):
+ '''read tag_config_path tags config file
+ and return direction format variables'''
+ self.tag_config_path = '/etc/cyborg/netronome_ports.json'
+ if os.path.exists(self.tag_config_path):
+ config_file = open(self.tag_config_path, 'r')
+ else:
+ output = 'There is no %s' % (self.tag_config_path)
+ LOG.error('There is no %s' % (self.tag_config_path))
+ return
+
+ try:
+ buf = config_file.read()
+ netronome = json.loads(buf)
+ except Exception:
+ LOG.error('Failed to read %s' % (self.tag_config_path))
+
+ return netronome['netronome_ports']
+
+ def discover_ports(self):
+ port_list = []
+ for i in range(0, port_index_max + 1):
+ port_name = port_name_prefix + str(i)
+ port = dict()
+ port["bind_instance"] = None
+ port["bind_port"] = None
+ port["is_used"] = False
+ port["pci_slot"] = os.popen("ethtool -i %s | grep bus-info | cut -d ' ' -f 5" % port_name).read().strip()
+ port["port_id"] = i
+ port["port_name"] = port_name
+ port["product_id"] = "6003"
+ port["vender_id"] = "19ee"
+
+ port_list.append(port)
+
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/spdk.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/spdk.py
new file mode 100644
index 0000000..276b9bb
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/modules/spdk.py
@@ -0,0 +1,147 @@
+"""
+Cyborg SPDK driver modules implementation.
+"""
+
+import socket
+from cyborg.accelerator.common import exception
+from cyborg.accelerator.drivers.modules import generic
+from oslo_log import log as logging
+from oslo_config import cfg
+from oslo_concurrency import processutils as putils
+from cyborg.common.i18n import _
+from cyborg.accelerator import configuration
+from cyborg.db.sqlalchemy import api
+
+LOG = logging.getLogger(__name__)
+
+accelerator_opts = [
+ cfg.StrOpt('spdk_conf_file',
+ default='/etc/cyborg/spdk.conf',
+ help=_('SPDK conf file to use for the SPDK driver in Cyborg;')),
+
+ cfg.StrOpt('device_type',
+ default='NVMe',
+ help=_('Default backend device type: NVMe')),
+
+ cfg.IntOpt('queue',
+ default=8,
+ help=_('Default number of queues')),
+
+ cfg.IntOpt('iops',
+ default=1000,
+ help=_('Default number of iops')),
+
+ cfg.IntOpt('bandwidth:',
+ default=800,
+ help=_('Default bandwidth')),
+
+ cfg.BoolOpt('remoteable:',
+ default=False,
+ help=_('remoteable is false by default'))
+
+]
+
+CONF = cfg.CONF
+CONF.register_opts(accelerator_opts, group=configuration.SHARED_CONF_GROUP)
+
+try:
+ import py_spdk
+except ImportError:
+ py_spdk = None
+
+
+class SPDKDRIVER(generic.GENERICDRIVER):
+ def __init__(self, execute=putils.execute, *args, **kwargs):
+ super(SPDKDRIVER, self).__init__(execute, *args, **kwargs)
+ self.configuration.append_config_values(accelerator_opts)
+ self.hostname = socket.gethostname()
+ self.driver_type = self.configuration\
+ .safe_get('accelerator_backend_name') or 'SPDK'
+ self.device_type = self.configuration.safe_get('device_type')
+ self.dbconn = api.get_backend()
+
+ def initialize_connection(self, accelerator, connector):
+ return py_spdk.initialize_connection(accelerator, connector)
+
+ def validate_connection(self, connector):
+ return py_spdk.initialize_connection(connector)
+
+ def destory_db(self):
+ if self.dbconn is not None:
+ self.dbconn.close()
+
+ def discover_driver(self, driver_type):
+ HAVE_SPDK = None
+ if HAVE_SPDK:
+ values = {'acc_type': self.driver_type}
+ self.dbconn.accelerator_create(None, values)
+
+ def install_driver(self, driver_id, driver_type):
+ accelerator = self.dbconn.accelerator_query(None, driver_id)
+ if accelerator:
+ self.initialize_connection(accelerator, None)
+ self.do_setup()
+ ctrlr = self.get_controller()
+ nsid = self.get_allocated_nsid(ctrlr)
+ self.attach_instance(nsid)
+ else:
+ msg = (_("Could not find %s accelerator") % driver_type)
+ raise exception.InvalidAccelerator(msg)
+
+ def uninstall_driver(self, driver_id, driver_type):
+ ctrlr = self.get_controller()
+ nsid = self.get_allocated_nsid(ctrlr)
+ self.detach_instance(nsid)
+ pass
+
+ def driver_list(self, driver_type):
+ return self.dbconn.accelerator_query(None, driver_type)
+
+ def update(self, driver_type):
+ pass
+
+ def attach_instance(self, instance_id):
+ self.add_ns()
+ self.attach_and_detach_ns()
+ pass
+
+ def detach_instance(self, instance_id):
+ self.delete_ns()
+ self.detach_and_detach_ns()
+ pass
+
+ def get_controller(self):
+ return self.ctrlr
+
+ '''list controllers'''
+
+ def display_controller_list(self):
+ pass
+
+ '''create namespace'''
+
+ def add_ns(self):
+ pass
+
+ '''delete namespace'''
+
+ def delete_ns(self):
+ pass
+
+ '''attach namespace to controller'''
+
+ def attach_and_detach_ns(self):
+ pass
+
+ '''detach namespace from controller'''
+
+ def detach_and_detach_ns(self):
+ pass
+
+ ''' format namespace or controller'''
+
+ def format_nvm(self):
+ pass
+
+ def get_allocated_nsid(self, ctrl):
+ return self.nsid
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/__init__.py
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/nvmf/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/nvmf/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/nvmf/__init__.py
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/nvmf/nvmf.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/nvmf/nvmf.py
new file mode 100644
index 0000000..6e482a1
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/nvmf/nvmf.py
@@ -0,0 +1,113 @@
+"""
+SPDK NVMFDRIVER module implementation.
+"""
+
+from cyborg.accelerator.drivers.spdk.util.pyspdk.nvmf_client import NvmfTgt
+from oslo_log import log as logging
+from cyborg.accelerator.common import exception
+from cyborg.accelerator.drivers.spdk.util import common_fun
+from cyborg.accelerator.drivers.spdk.spdk import SPDKDRIVER
+from cyborg.accelerator.drivers.spdk.util.pyspdk.py_spdk import PySPDK
+
+LOG = logging.getLogger(__name__)
+
+
+class NVMFDRIVER(SPDKDRIVER):
+ """NVMFDRIVER class.
+ nvmf_tgt server app should be able to implement this driver.
+ """
+
+ SERVER = 'nvmf'
+
+ def __init__(self, *args, **kwargs):
+ super(NVMFDRIVER, self).__init__(*args, **kwargs)
+ self.servers = common_fun.discover_servers()
+ self.py = common_fun.get_py_client(self.SERVER)
+
+ def discover_accelerator(self):
+ if common_fun.check_for_setup_error(self.py, self.SERVER):
+ return self.get_one_accelerator()
+
+ def get_one_accelerator(self):
+ acc_client = NvmfTgt(self.py)
+ bdevs = acc_client.get_bdevs()
+ # Display current blockdev list
+ subsystems = acc_client.get_nvmf_subsystems()
+ # Display nvmf subsystems
+ accelerator_obj = {
+ 'server': self.SERVER,
+ 'bdevs': bdevs,
+ 'subsystems': subsystems
+ }
+ return accelerator_obj
+
+ def install_accelerator(self, driver_id, driver_type):
+ pass
+
+ def uninstall_accelerator(self, driver_id, driver_type):
+ pass
+
+ def accelerator_list(self):
+ return self.get_all_accelerators()
+
+ def get_all_accelerators(self):
+ accelerators = []
+ for accelerator_i in range(len(self.servers)):
+ accelerator = self.servers[accelerator_i]
+ py_tmp = PySPDK(accelerator)
+ if py_tmp.is_alive():
+ accelerators.append(self.get_one_accelerator())
+ return accelerators
+
+ def update(self, driver_type, **kwargs):
+ pass
+
+ def attach_instance(self, instance_id):
+ pass
+
+ def detach_instance(self, instance_id):
+ pass
+
+ def delete_subsystem(self, nqn):
+ """Delete a nvmf subsystem
+ :param nqn: Target nqn(ASCII).
+ :raise exception: Invaid
+ """
+ if nqn == "":
+ acc_client = NvmfTgt(self.py)
+ acc_client.delete_nvmf_subsystem(nqn)
+ else:
+ raise exception.Invalid('Delete nvmf subsystem failed.')
+
+ def construct_subsystem(self,
+ nqn,
+ listen,
+ hosts,
+ serial_number,
+ namespaces
+ ):
+ """Add a nvmf subsystem
+ :param nqn: Target nqn(ASCII).
+ :param listen: comma-separated list of Listen
+ <trtype:transport_name traddr:address trsvcid:port_id>
+ pairs enclosed in quotes. Format:'trtype:transport0
+ traddr:traddr0 trsvcid:trsvcid0,trtype:transport1
+ traddr:traddr1 trsvcid:trsvcid1' etc.
+ Example: 'trtype:RDMA traddr:192.168.100.8 trsvcid:4420,
+ trtype:RDMA traddr:192.168.100.9 trsvcid:4420.'
+ :param hosts: Whitespace-separated list of host nqn list.
+ :param serial_number: Example: 'SPDK00000000000001.
+ :param namespaces: Whitespace-separated list of namespaces.
+ :raise exception: Invaid
+ """
+ if ((namespaces != '' and listen != '') and
+ (hosts != '' and serial_number != '')) and nqn != '':
+ acc_client = NvmfTgt(self.py)
+ acc_client.construct_nvmf_subsystem(nqn,
+ listen,
+ hosts,
+ serial_number,
+ namespaces
+ )
+ else:
+ raise exception.Invalid('Construct nvmf subsystem failed.') \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/spdk.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/spdk.py
new file mode 100644
index 0000000..c42522f
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/spdk.py
@@ -0,0 +1,75 @@
+"""
+Cyborg SPDK driver modules implementation.
+"""
+
+from oslo_log import log as logging
+LOG = logging.getLogger(__name__)
+
+
+class SPDKDRIVER(object):
+ """SPDKDRIVER
+ This is just a virtual SPDK drivers interface.
+ SPDK-based app server should implement their specific drivers.
+ """
+ @classmethod
+ def create(cls, server, *args, **kwargs):
+ for subclass in cls.__subclasses__():
+ if server == subclass.SERVER:
+ return subclass(*args, **kwargs)
+ raise LookupError("Could not find the driver for server %s" % server)
+
+ def __init__(self, *args, **kwargs):
+ super(SPDKDRIVER, self).__init__()
+
+ def discover_accelerator(self):
+ """Discover a backend accelerator
+ :return: accelerator list.
+ """
+ raise NotImplementedError('Subclasses must implement this method.')
+
+ def install_accelerator(self, driver_id, driver_type):
+ """install a backend accelerator
+ :param driver_id: driver id.
+ :param driver_type: driver type.
+ :raise: NotImplementedError.
+ """
+ raise NotImplementedError('Subclasses must implement this method.')
+
+ def uninstall_accelerator(self, driver_id, driver_type):
+ """uninstall a backend accelerator
+ :param driver_id: driver id.
+ :param driver_type: driver type.
+ :raise: NotImplementedError.
+ """
+ raise NotImplementedError('Subclasses must implement this method.')
+
+ def accelerator_list(self):
+ """Discover a backend accelerator list
+ :return: accelerator list.
+ :raise: NotImplementedError.
+ """
+ raise NotImplementedError('Subclasses must implement this method.')
+
+ def update(self, driver_type, **kwargs):
+ """update
+ :param driver_type: driver type.
+ :param kwargs: kwargs.
+ :raise: NotImplementedError.
+ """
+ raise NotImplementedError('Subclasses must implement this method.')
+
+ def attach_instance(self, instance_id):
+ """attach a backend instance
+ :param instance_id: instance id.
+ :return: instance.
+ :raise: NotImplementedError.
+ """
+ raise NotImplementedError('Subclasses must implement this method.')
+
+ def detach_instance(self, instance_id):
+ """detach a backend instance
+ :param instance_id: instance id.
+ :return: instance.
+ :raise: NotImplementedError.
+ """
+ raise NotImplementedError('Subclasses must implement this method.') \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/__init__.py
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/common_fun.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/common_fun.py
new file mode 100644
index 0000000..34f3e87
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/common_fun.py
@@ -0,0 +1,206 @@
+"""
+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) \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/__init__.py
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/nvmf_client.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/nvmf_client.py
new file mode 100644
index 0000000..840087f
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/nvmf_client.py
@@ -0,0 +1,119 @@
+import json
+
+
+class NvmfTgt(object):
+
+ def __init__(self, py):
+ super(NvmfTgt, self).__init__()
+ self.py = py
+
+ def get_rpc_methods(self):
+ rpc_methods = self._get_json_objs(
+ 'get_rpc_methods', '10.0.2.15')
+ return rpc_methods
+
+ def get_bdevs(self):
+ block_devices = self._get_json_objs(
+ 'get_bdevs', '10.0.2.15')
+ return block_devices
+
+ def delete_bdev(self, name):
+ sub_args = [name]
+ res = self.py.exec_rpc('delete_bdev', '10.0.2.15', sub_args=sub_args)
+ print res
+
+ def kill_instance(self, sig_name):
+ sub_args = [sig_name]
+ res = self.py.exec_rpc('kill_instance', '10.0.2.15', sub_args=sub_args)
+ print res
+
+ def construct_aio_bdev(self, filename, name, block_size):
+ sub_args = [filename, name, str(block_size)]
+ res = self.py.exec_rpc(
+ 'construct_aio_bdev',
+ '10.0.2.15',
+ sub_args=sub_args)
+ print res
+
+ def construct_error_bdev(self, basename):
+ sub_args = [basename]
+ res = self.py.exec_rpc(
+ 'construct_error_bdev',
+ '10.0.2.15',
+ sub_args=sub_args)
+ print res
+
+ def construct_nvme_bdev(
+ self,
+ name,
+ trtype,
+ traddr,
+ adrfam=None,
+ trsvcid=None,
+ subnqn=None):
+ sub_args = ["-b", "-t", "-a"]
+ sub_args.insert(1, name)
+ sub_args.insert(2, trtype)
+ sub_args.insert(3, traddr)
+ if adrfam is not None:
+ sub_args.append("-f")
+ sub_args.append(adrfam)
+ if trsvcid is not None:
+ sub_args.append("-s")
+ sub_args.append(trsvcid)
+ if subnqn is not None:
+ sub_args.append("-n")
+ sub_args.append(subnqn)
+ res = self.py.exec_rpc(
+ 'construct_nvme_bdev',
+ '10.0.2.15',
+ sub_args=sub_args)
+ return res
+
+ def construct_null_bdev(self, name, total_size, block_size):
+ sub_args = [name, str(total_size), str(block_size)]
+ res = self.py.exec_rpc(
+ 'construct_null_bdev',
+ '10.0.2.15',
+ sub_args=sub_args)
+ return res
+
+ def construct_malloc_bdev(self, total_size, block_size):
+ sub_args = [str(total_size), str(block_size)]
+ res = self.py.exec_rpc(
+ 'construct_malloc_bdev',
+ '10.0.2.15',
+ sub_args=sub_args)
+ print res
+
+ def delete_nvmf_subsystem(self, nqn):
+ sub_args = [nqn]
+ res = self.py.exec_rpc(
+ 'delete_nvmf_subsystem',
+ '10.0.2.15',
+ sub_args=sub_args)
+ print res
+
+ def construct_nvmf_subsystem(
+ self,
+ nqn,
+ listen,
+ hosts,
+ serial_number,
+ namespaces):
+ sub_args = [nqn, listen, hosts, serial_number, namespaces]
+ res = self.py.exec_rpc(
+ 'construct_nvmf_subsystem',
+ '10.0.2.15',
+ sub_args=sub_args)
+ print res
+
+ def get_nvmf_subsystems(self):
+ subsystems = self._get_json_objs(
+ 'get_nvmf_subsystems', '10.0.2.15')
+ return subsystems
+
+ def _get_json_objs(self, method, server_ip):
+ res = self.py.exec_rpc(method, server_ip)
+ json_obj = json.loads(res)
+ return json_obj \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/py_spdk.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/py_spdk.py
new file mode 100644
index 0000000..a298c18
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/py_spdk.py
@@ -0,0 +1,82 @@
+import psutil
+import re
+import os
+import subprocess
+
+
+class PySPDK(object):
+
+ def __init__(self, pname):
+ super(PySPDK, self).__init__()
+ self.pid = None
+ self.pname = pname
+
+ def start_server(self, spdk_dir, server_name):
+ if not self.is_alive():
+ self.init_hugepages(spdk_dir)
+ server_dir = os.path.join(spdk_dir, 'app/')
+ file_dir = self._search_file(server_dir, server_name)
+ print file_dir
+ os.chdir(file_dir)
+ p = subprocess.Popen(
+ 'sudo ./%s' % server_name,
+ shell=True, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ return out
+
+ def init_hugepages(self, spdk_dir):
+ huge_dir = os.path.join(spdk_dir, 'scripts/')
+ file_dir = self._search_file(huge_dir, 'setup.sh')
+ print file_dir
+ os.chdir(file_dir)
+ p = subprocess.Popen(
+ 'sudo ./setup.sh',
+ shell=True, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ return out
+
+ @staticmethod
+ def _search_file(spdk_dir, file_name):
+ for dirpath, dirnames, filenames in os.walk(spdk_dir):
+ for filename in filenames:
+ if filename == file_name:
+ return dirpath
+
+ def _get_process_id(self):
+ for proc in psutil.process_iter():
+ try:
+ pinfo = proc.as_dict(attrs=['pid', 'cmdline'])
+ if re.search(self.pname, str(pinfo.get('cmdline'))):
+ self.pid = pinfo.get('pid')
+ return self.pid
+ except psutil.NoSuchProcess:
+ print "NoSuchProcess:%s" % self.pname
+ print "NoSuchProcess:%s" % self.pname
+ return self.pid
+
+ def is_alive(self):
+ self.pid = self._get_process_id()
+ if self.pid:
+ p = psutil.Process(self.pid)
+ if p.is_running():
+ return True
+ return False
+
+ @staticmethod
+ def exec_rpc(method, server='127.0.0.1', port=5260, sub_args=None):
+ exec_cmd = ["./rpc.py", "-s", "-p"]
+ exec_cmd.insert(2, server)
+ exec_cmd.insert(4, str(port))
+ exec_cmd.insert(5, method)
+ if sub_args is None:
+ sub_args = []
+ exec_cmd.extend(sub_args)
+ p = subprocess.Popen(
+ exec_cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE
+ )
+ out, err = p.communicate()
+ return out \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/vhost_client.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/vhost_client.py
new file mode 100644
index 0000000..63bce70
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/util/pyspdk/vhost_client.py
@@ -0,0 +1,121 @@
+import json
+
+
+class VhostTgt(object):
+
+ def __init__(self, py):
+ super(VhostTgt, self).__init__()
+ self.py = py
+
+ def get_rpc_methods(self):
+ rpc_methods = self._get_json_objs('get_rpc_methods', '127.0.0.1')
+ return rpc_methods
+
+ def get_scsi_devices(self):
+ scsi_devices = self._get_json_objs(
+ 'get_scsi_devices', '127.0.0.1')
+ return scsi_devices
+
+ def get_luns(self):
+ luns = self._get_json_objs('get_luns', '127.0.0.1')
+ return luns
+
+ def get_interfaces(self):
+ interfaces = self._get_json_objs(
+ 'get_interfaces', '127.0.0.1')
+ return interfaces
+
+ def add_ip_address(self, ifc_index, ip_addr):
+ sub_args = [ifc_index, ip_addr]
+ res = self.py.exec_rpc(
+ 'add_ip_address',
+ '127.0.0.1',
+ sub_args=sub_args)
+ return res
+
+ def delete_ip_address(self, ifc_index, ip_addr):
+ sub_args = [ifc_index, ip_addr]
+ res = self.py.exec_rpc(
+ 'delete_ip_address',
+ '127.0.0.1',
+ sub_args=sub_args)
+ return res
+
+ def get_bdevs(self):
+ block_devices = self._get_json_objs(
+ 'get_bdevs', '127.0.0.1')
+ return block_devices
+
+ def delete_bdev(self, name):
+ sub_args = [name]
+ res = self.py.exec_rpc('delete_bdev', '127.0.0.1', sub_args=sub_args)
+ print res
+
+ def kill_instance(self, sig_name):
+ sub_args = [sig_name]
+ res = self.py.exec_rpc('kill_instance', '127.0.0.1', sub_args=sub_args)
+ print res
+
+ def construct_aio_bdev(self, filename, name, block_size):
+ sub_args = [filename, name, str(block_size)]
+ res = self.py.exec_rpc(
+ 'construct_aio_bdev',
+ '127.0.0.1',
+ sub_args=sub_args)
+ print res
+
+ def construct_error_bdev(self, basename):
+ sub_args = [basename]
+ res = self.py.exec_rpc(
+ 'construct_error_bdev',
+ '127.0.0.1',
+ sub_args=sub_args)
+ print res
+
+ def construct_nvme_bdev(
+ self,
+ name,
+ trtype,
+ traddr,
+ adrfam=None,
+ trsvcid=None,
+ subnqn=None):
+ sub_args = ["-b", "-t", "-a"]
+ sub_args.insert(1, name)
+ sub_args.insert(2, trtype)
+ sub_args.insert(3, traddr)
+ if adrfam is not None:
+ sub_args.append("-f")
+ sub_args.append(adrfam)
+ if trsvcid is not None:
+ sub_args.append("-s")
+ sub_args.append(trsvcid)
+ if subnqn is not None:
+ sub_args.append("-n")
+ sub_args.append(subnqn)
+ res = self.py.exec_rpc(
+ 'construct_nvme_bdev',
+ '127.0.0.1',
+ sub_args=sub_args)
+ return res
+
+ def construct_null_bdev(self, name, total_size, block_size):
+ sub_args = [name, str(total_size), str(block_size)]
+ res = self.py.exec_rpc(
+ 'construct_null_bdev',
+ '127.0.0.1',
+ sub_args=sub_args)
+ return res
+
+ def construct_malloc_bdev(self, total_size, block_size):
+ sub_args = [str(total_size), str(block_size)]
+ res = self.py.exec_rpc(
+ 'construct_malloc_bdev',
+ '10.0.2.15',
+ sub_args=sub_args)
+ print res
+
+ def _get_json_objs(self, method, server_ip):
+ res = self.py.exec_rpc(method, server_ip)
+ json_obj = json.loads(res)
+ return json_obj \ No newline at end of file
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/vhost/__init__.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/vhost/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/vhost/__init__.py
diff --git a/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/vhost/vhost.py b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/vhost/vhost.py
new file mode 100644
index 0000000..b7aef33
--- /dev/null
+++ b/cyborg_enhancement/mitaka_version/cyborg/cyborg/accelerator/drivers/spdk/vhost/vhost.py
@@ -0,0 +1,92 @@
+"""
+SPDK VHOSTDRIVER module implementation.
+"""
+
+from cyborg.accelerator.drivers.spdk.util.pyspdk.vhost_client import VhostTgt
+from oslo_log import log as logging
+from cyborg.accelerator.drivers.spdk.util import common_fun
+from cyborg.accelerator.drivers.spdk.spdk import SPDKDRIVER
+from cyborg.accelerator.drivers.spdk.util.pyspdk.py_spdk import PySPDK
+
+LOG = logging.getLogger(__name__)
+
+
+class VHOSTDRIVER(SPDKDRIVER):
+ """VHOSTDRIVER class.
+ vhost server app should be able to implement this driver.
+ """
+
+ SERVER = 'vhost'
+
+ def __init__(self, *args, **kwargs):
+ super(VHOSTDRIVER, self).__init__(*args, **kwargs)
+ self.servers = common_fun.discover_servers()
+ self.py = common_fun.get_py_client(self.SERVER)
+
+ def discover_accelerator(self):
+ if common_fun.check_for_setup_error(self.py, self.SERVER):
+ return self.get_one_accelerator()
+
+ def get_one_accelerator(self):
+ acc_client = VhostTgt(self.py)
+ bdevs = acc_client.get_bdevs()
+ # Display current blockdev list
+ scsi_devices = acc_client.get_scsi_devices()
+ # Display SCSI devices
+ luns = acc_client.get_luns()
+ # Display active LUNs
+ interfaces = acc_client.get_interfaces()
+ # Display current interface list
+ accelerator_obj = {
+ 'server': self.SERVER,
+ 'bdevs': bdevs,
+ 'scsi_devices': scsi_devices,
+ 'luns': luns,
+ 'interfaces': interfaces
+ }
+ return accelerator_obj
+
+ def install_accelerator(self, driver_id, driver_type):
+ pass
+
+ def uninstall_accelerator(self, driver_id, driver_type):
+ pass
+
+ def accelerator_list(self):
+ return self.get_all_accelerators()
+
+ def get_all_accelerators(self):
+ accelerators = []
+ for accelerator_i in range(len(self.servers)):
+ accelerator = self.servers[accelerator_i]
+ py_tmp = PySPDK(accelerator)
+ if py_tmp.is_alive():
+ accelerators.append(self.get_one_accelerator())
+ return accelerators
+
+ def update(self, driver_type, **kwargs):
+ pass
+
+ def attach_instance(self, instance_id):
+ pass
+
+ def detach_instance(self, instance_id):
+ pass
+
+ def add_ip_address(self, ifc_index, ip_addr):
+ """Add IP address
+ :param ifc_index: ifc index of the nic device.
+ :param ip_addr: ip address will be added.
+ :return: ip_address
+ """
+ acc_client = VhostTgt(self.py)
+ return acc_client.add_ip_address(ifc_index, ip_addr)
+
+ def delete_ip_address(self, ifc_index, ip_addr):
+ """Delete IP address
+ :param ifc_index: ifc index of the nic device.
+ :param ip_addr: ip address will be added.
+ :return: ip_address
+ """
+ acc_client = VhostTgt(self.py)
+ return acc_client.delete_ip_address(ifc_index, ip_addr) \ No newline at end of file