Create driver directories and prototype generic driver

Change-Id: I595d6b969acd53ecae3d28cec22fe152ca5d5ff7
This commit is contained in:
Rushil Chugh 2017-06-11 23:03:38 -04:00
parent 8584b50f60
commit df8671c65a
7 changed files with 311 additions and 0 deletions

View File

View File

@ -0,0 +1,118 @@
# 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
from oslo_log import log as logging
from oslo_serialization import jsonutils
import six
from six.moves import http_client
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 = [(jsonutils.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"

View File

View File

@ -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

View File

@ -0,0 +1,33 @@
# 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
class GenericDriver(object):
"""Abstract base class representing the generic driver for Cyborg.
This class provides a reference implementation for a Cyborg driver.
"""
def __init__(self):
self.discover = generic.discover()
self.list = generic.list()
self.update = generic.update
self.attach = generic.attach()
self.detach = generic.detach()

View File

@ -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__)
# TODO(crushil): REQUIRED_PROPERTIES needs to be filled out.
REQUIRED_PROPERTIES = {}
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):
def install(self):
pass
def detach(self):
def uninstall(self):
pass
def delete(self):
pass
def discover(self):
pass
def list(self):
pass
def update(self):
pass