Add driver interface checks

This is the start of an effort to both validate that drivers fully
implement the expected minimum requirements as well as to create a clear
place for driver developers to learn what needs to be implemented and get
documentation explaining what is expected for each method.

This also enables us to create tooling for documenting the available
drivers and their capabilities, to some degree. A follow up patch will
show some of what I'm thinking there, but it will make it possible to write
scripts for different needs.

This is somewhat a cleanup attempt to the ABC work that was started a
while back. This does not aim to replace that effort, but give a
mechanism for some of the things expected out of that effort that ended
up not being possible with how it evolved.

In most cases we do not really care if a driver is inherited from a
certain base class, just that it conforms to the given interface.

The interface/inheritance work really centers around two separate
things:

 * Ensuring drivers conform to an expected interface
 * Allowing code reuse and common implementation

This is really for the first item. Additional work is needed to complete
the ABC work we've done, but that really focuses on the second item, and
is out of scope for the intent of this patch.

Change-Id: I4168225126fe88c31712d94f0a130e9e7ede3446
This commit is contained in:
Sean McGinnis 2016-03-23 16:39:07 -05:00
parent 0f72ff555d
commit e7b40242f8
106 changed files with 1597 additions and 102 deletions

View File

@ -58,6 +58,7 @@ from six.moves import range
from cinder.backup import driver
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder import utils
import cinder.volume.drivers.rbd as rbd_driver
@ -152,6 +153,7 @@ class VolumeMetadataBackup(object):
self.name)
@interface.backupdriver
class CephBackupDriver(driver.BackupDriver):
"""Backup Cinder volumes to Ceph Object Store.

View File

@ -24,6 +24,7 @@ from oslo_config import cfg
from cinder.backup.drivers import posix
from cinder import exception
from cinder import interface
from cinder import utils
@ -41,6 +42,7 @@ CONF = cfg.CONF
CONF.register_opts(glusterfsbackup_service_opts)
@interface.backupdriver
class GlusterfsBackupDriver(posix.PosixBackupDriver):
"""Provides backup, restore and delete using GlusterFS repository."""

View File

@ -42,6 +42,7 @@ import six
from cinder.backup import chunkeddriver
from cinder import exception
from cinder.i18n import _
from cinder import interface
LOG = logging.getLogger(__name__)
@ -110,6 +111,7 @@ def gcs_logger(func):
return func_wrapper
@interface.backupdriver
class GoogleBackupDriver(chunkeddriver.ChunkedBackupDriver):
"""Provides backup, restore and delete of backup objects within GCS."""

View File

@ -23,6 +23,7 @@ from oslo_log import log as logging
from cinder.backup.drivers import posix
from cinder import exception
from cinder.i18n import _
from cinder import interface
from cinder import utils
LOG = logging.getLogger(__name__)
@ -44,6 +45,7 @@ CONF = cfg.CONF
CONF.register_opts(nfsbackup_service_opts)
@interface.backupdriver
class NFSBackupDriver(posix.PosixBackupDriver):
"""Provides backup, restore and delete using NFS supplied repository."""

View File

@ -26,6 +26,7 @@ from oslo_log import log as logging
from cinder.backup import chunkeddriver
from cinder import exception
from cinder import interface
LOG = logging.getLogger(__name__)
@ -63,6 +64,7 @@ CONF = cfg.CONF
CONF.register_opts(posixbackup_service_opts)
@interface.backupdriver
class PosixBackupDriver(chunkeddriver.ChunkedBackupDriver):
"""Provides backup, restore and delete using a Posix file system."""

View File

@ -56,6 +56,7 @@ from cinder.backup import chunkeddriver
from cinder import exception
from cinder.i18n import _
from cinder.i18n import _LE
from cinder import interface
LOG = logging.getLogger(__name__)
@ -138,6 +139,7 @@ CONF = cfg.CONF
CONF.register_opts(swiftbackup_service_opts)
@interface.backupdriver
class SwiftBackupDriver(chunkeddriver.ChunkedBackupDriver):
"""Provides backup, restore and delete of backup objects within Swift."""

View File

@ -36,6 +36,7 @@ from oslo_log import log as logging
from cinder.backup import driver
from cinder import exception
from cinder.i18n import _LE, _
from cinder import interface
from cinder import utils
LOG = logging.getLogger(__name__)
@ -259,6 +260,7 @@ def _cleanup_device_hardlink(hardlink_path, volume_path, volume_id):
'err': exc.stderr})
@interface.backupdriver
class TSMBackupDriver(driver.BackupDriver):
"""Provides backup, restore and delete of volumes backup for TSM."""

View File

@ -0,0 +1,37 @@
# Copyright 2016 Dell Inc.
# 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.
#
_volume_register = []
_backup_register = []
_fczm_register = []
def volumedriver(cls):
"""Decorator for concrete volume driver implementations."""
_volume_register.append(cls)
return cls
def backupdriver(cls):
"""Decorator for concrete backup driver implementations."""
_backup_register.append(cls)
return cls
def fczmdriver(cls):
"""Decorator for concrete fibre channel zone manager drivers."""
_fczm_register.append(cls)
return cls

View File

@ -0,0 +1,79 @@
# Copyright 2016 Dell Inc.
# 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.
#
"""
Backup driver with 'chunked' backup operations.
"""
from cinder.interface import backup_driver
class BackupDriverWithVerify(backup_driver.BackupDriver):
"""Backup driver that supports 'chunked' backups."""
def put_container(self, container):
"""Create the container if needed. No failure if it pre-exists.
:param container: The container to write into.
"""
def get_container_entries(self, container, prefix):
"""Get container entry names.
:param container: The container from which to get entries.
:param prefix: The prefix used to match entries.
"""
def get_object_writer(self, container, object_name, extra_metadata=None):
"""Returns a writer which stores the chunk data in backup repository.
:param container: The container to write to.
:param object_name: The object name to write.
:param extra_metadata: Extra metadata to be included.
:returns: A context handler that can be used in a "with" context.
"""
def get_object_reader(self, container, object_name, extra_metadata=None):
"""Returns a reader object for the backed up chunk.
:param container: The container to read from.
:param object_name: The object name to read.
:param extra_metadata: Extra metadata to be included.
"""
def delete_object(self, container, object_name):
"""Delete object from container.
:param container: The container to modify.
:param object_name: The object name delete.
"""
def update_container_name(self, backup, container):
"""Allows sub-classes to override container name.
This method exists so that sub-classes can override the container name
as it comes in to the driver in the backup object. Implementations
should return None if no change to the container name is desired.
"""
def get_extra_metadata(self, backup, volume):
"""Return extra metadata to use in prepare_backup.
This method allows for collection of extra metadata in prepare_backup()
which will be passed to get_object_reader() and get_object_writer().
Subclass extensions can use this extra information to optimize
data transfers. Return a json serializable object.
"""

View File

@ -0,0 +1,111 @@
# Copyright 2016 Dell Inc.
# 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.
#
"""
Core backup driver interface.
All backup drivers should support this interface as a bare minimum.
"""
from cinder.interface import base
class BackupDriver(base.CinderInterface):
"""Backup driver required interface."""
def get_metadata(self, volume_id):
"""Get volume metadata.
Returns a json-encoded dict containing all metadata and the restore
version i.e. the version used to decide what actually gets restored
from this container when doing a backup restore.
Typically best to use py:class:`BackupMetadataAPI` for this.
:param volume_id: The ID of the volume.
:returns: json-encoded dict of metadata.
"""
def put_metadata(self, volume_id, json_metadata):
"""Set volume metadata.
Typically best to use py:class:`BackupMetadataAPI` for this.
:param volume_id: The ID of the volume.
:param json_metadata: The json-encoded dict of metadata.
"""
def backup(self, backup, volume_file, backup_metadata=False):
"""Start a backup of a specified volume.
If backup['parent_id'] is given, then an incremental backup
should be performed is supported.
If the parent backup is a different size, a full backup should be
performed to ensure all data is included.
TODO(smcginnis) Document backup variable structure.
:param backup: The backup information.
:param volume_file: The volume or file to write the backup to.
:param backup_metadata: Whether to include volume metadata in the
backup.
"""
def restore(self, backup, volume_id, volume_file):
"""Restore data from a backup.
:param backup: The backup information.
:param volume_id: The volume to be restored.
:param volume_file: The volume or file to read the data from.
"""
def delete(self, backup):
"""Delete a backup from the backup store.
:param backup: The backup to be deleted.
"""
def export_record(self, backup):
"""Export driver specific backup record information.
If backup backend needs additional driver specific information to
import backup record back into the system it must overwrite this method
and return it here as a dictionary so it can be serialized into a
string.
Default backup driver implementation has no extra information.
:param backup: backup object to export
:returns: driver_info - dictionary with extra information
"""
def import_record(self, backup, driver_info):
"""Import driver specific backup record information.
If backup backend needs additional driver specific information to
import backup record back into the system it must overwrite this method
since it will be called with the extra information that was provided by
export_record when exporting the backup.
Default backup driver implementation does nothing since it didn't
export any specific data in export_record.
:param backup: backup object to export
:param driver_info: dictionary with driver specific backup record
information
:returns: nothing
"""

View File

@ -0,0 +1,38 @@
# Copyright 2016 Dell Inc.
# 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.
#
"""
Backup driver with verification interface.
Used for backup drivers that support the option to verify the backup after
completion.
"""
from cinder.interface import backup_driver
class BackupDriverWithVerify(backup_driver.BackupDriver):
"""Backup driver that supports the optional verification."""
def verify(self, backup):
"""Verify that the backup exists on the backend.
Verify that the backup is OK, possibly following an import record
operation.
:param backup: Backup id of the backup to verify.
:raises: InvalidBackup, NotImplementedError
"""

105
cinder/interface/base.py Normal file
View File

@ -0,0 +1,105 @@
# Copyright 2016 Dell Inc.
# 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.
#
import abc
import inspect
import six
def _get_arg_count(method):
"""Get the number of args for a method.
:param method: The method to check.
:returns: The number of args for the method.
"""
if not method:
return 0
arg_spec = inspect.getargspec(method)
return len(arg_spec[0])
def _get_method_info(cls):
"""Get all methods defined in a class.
Note: This will only return public methods and their associated arg count.
:param cls: The class to inspect.
:returns: `Dict` of method names with a tuple of the method and their arg
counts.
"""
result = {}
methods = inspect.getmembers(cls, inspect.ismethod)
for (name, method) in methods:
if name.startswith('_'):
# Skip non-public methods
continue
result[name] = (method, _get_arg_count(method))
return result
@six.add_metaclass(abc.ABCMeta)
class CinderInterface(object):
"""Interface base class for Cinder.
Cinder interfaces should inherit from this class to support indirect
inheritance evaluation.
This can be used to validate compliance to an interface without requiring
that the class actually be inherited from the same base class.
"""
_method_cache = None
@classmethod
def _get_methods(cls):
if not cls._method_cache:
cls._method_cache = _get_method_info(cls)
return cls._method_cache
@classmethod
def __subclasshook__(cls, other_cls):
"""Custom class inheritance evaluation.
:param cls: The CinderInterface to check against.
:param other_cls: The class to be checked if it implements
our interface.
"""
interface_methods = cls._get_methods()
driver_methods = _get_method_info(other_cls)
interface_keys = interface_methods.keys()
driver_keys = driver_methods.keys()
matching_count = len(set(interface_keys) & set(driver_keys))
if matching_count != len(interface_keys):
# Missing some methods, does not implement this interface or is
# missing something.
return NotImplemented
# TODO(smcginnis) Add method signature checking.
# We know all methods are there, now make sure they look right.
# Unfortunately the methods can be obfuscated by certain decorators,
# so we need to find a better way to pull out the real method
# signatures.
# driver_methods[method_name][0].func_closure.cell_contents works
# for most cases but not all.
# AST might work instead of using introspect.
return True

View File

@ -0,0 +1,78 @@
# Copyright 2016 Dell Inc.
# 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.
#
"""
Core fibre channel zone manager driver interface.
All fczm drivers should support this interface as a bare minimum.
"""
from cinder.interface import base
class FibreChannelZoneManagerDriver(base.CinderInterface):
"""FCZM driver required interface."""
def add_connection(self, fabric, initiator_target_map, host_name=None,
storage_system=None):
"""Add a new initiator<>target connection.
All implementing drivers should provide concrete implementation
for this API.
:param fabric: Fabric name from cinder.conf file
:param initiator_target_map: Mapping of initiator to list of targets
.. code-block:: python
Example initiator_target_map:
{
'10008c7cff523b01': ['20240002ac000a50', '20240002ac000a40']
}
Note that WWPN can be in lower or upper case and can be ':'
separated strings.
"""
def delete_connection(self, fabric, initiator_target_map, host_name=None,
storage_system=None):
"""Delete an initiator<>target connection.
:param fabric: Fabric name from cinder.conf file
:param initiator_target_map: Mapping of initiator to list of targets
.. code-block:: python
Example initiator_target_map:
{
'10008c7cff523b01': ['20240002ac000a50', '20240002ac000a40']
}
Note that WWPN can be in lower or upper case and can be ':'
separated strings.
"""
def get_san_context(self, target_wwn_list):
"""Get SAN context for end devices.
:param target_wwn_list: Mapping of initiator to list of targets
Example initiator_target_map: ['20240002ac000a50', '20240002ac000a40']
Note that WWPN can be in lower or upper case and can be
':' separated strings.
"""

78
cinder/interface/util.py Normal file
View File

@ -0,0 +1,78 @@
# Copyright 2016 Dell Inc.
# 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.
#
import fnmatch
import inspect
import os
from cinder import interface
def _ensure_loaded(start_path):
"""Loads everything in a given path.
This will make sure all classes have been loaded and therefore all
decorators have registered class.
:param start_path: The starting path to load.
"""
for root, folder, files in os.walk(start_path):
for phile in fnmatch.filter(files, '*.py'):
path = os.path.join(root, phile)
try:
__import__(
path.replace('/', '.')[:-3], globals(), locals())
except Exception:
# Really don't care here
pass
def get_volume_drivers():
"""Get a list of all volume drivers."""
_ensure_loaded('cinder/volume/drivers')
return [DriverInfo(x) for x in interface._volume_register]
def get_backup_drivers():
"""Get a list of all backup drivers."""
_ensure_loaded('cinder/backup/drivers')
return [DriverInfo(x) for x in interface._backup_register]
def get_fczm_drivers():
"""Get a list of all fczm drivers."""
_ensure_loaded('cinder/zonemanager/drivers')
return [DriverInfo(x) for x in interface._fczm_register]
class DriverInfo(object):
"""Information about driver implementations."""
def __init__(self, cls):
self.cls = cls
self.desc = cls.__doc__
self.class_name = cls.__name__
self.class_fqn = '{}.{}'.format(inspect.getmodule(cls).__name__,
self.class_name)
self.version = getattr(cls, 'VERSION', None)
def __str__(self):
return self.class_name
def __repr__(self):
return self.class_fqn
def __hash__(self):
return hash(self.class_fqn)

View File

@ -0,0 +1,231 @@
# Copyright 2016 Dell Inc.
# 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.
#
"""
Consistency group volume driver interface.
"""
from cinder.interface import base
class VolumeConsistencyGroupDriver(base.CinderInterface):
"""Interface for drivers that support consistency groups."""
def create_consistencygroup(self, context, group):
"""Creates a consistencygroup.
:param context: the context of the caller.
:param group: the dictionary of the consistency group to be created.
:returns: model_update
model_update will be in this format: {'status': xxx, ......}.
If the status in model_update is 'error', the manager will throw
an exception and it will be caught in the try-except block in the
manager. If the driver throws an exception, the manager will also
catch it in the try-except block. The group status in the db will
be changed to 'error'.
For a successful operation, the driver can either build the
model_update and return it or return None. The group status will
be set to 'available'.
"""
def create_consistencygroup_from_src(self, context, group, volumes,
cgsnapshot=None, snapshots=None,
source_cg=None, source_vols=None):
"""Creates a consistencygroup from source.
:param context: the context of the caller.
:param group: the dictionary of the consistency group to be created.
:param volumes: a list of volume dictionaries in the group.
:param cgsnapshot: the dictionary of the cgsnapshot as source.
:param snapshots: a list of snapshot dictionaries in the cgsnapshot.
:param source_cg: the dictionary of a consistency group as source.
:param source_vols: a list of volume dictionaries in the source_cg.
:returns: model_update, volumes_model_update
The source can be cgsnapshot or a source cg.
param volumes is retrieved directly from the db. It is a list of
cinder.db.sqlalchemy.models.Volume to be precise. It cannot be
assigned to volumes_model_update. volumes_model_update is a list of
dictionaries. It has to be built by the driver. An entry will be
in this format: {'id': xxx, 'status': xxx, ......}. model_update
will be in this format: {'status': xxx, ......}.
To be consistent with other volume operations, the manager will
assume the operation is successful if no exception is thrown by
the driver. For a successful operation, the driver can either build
the model_update and volumes_model_update and return them or
return None, None.
"""
def delete_consistencygroup(self, context, group, volumes):
"""Deletes a consistency group.
:param context: the context of the caller.
:param group: the dictionary of the consistency group to be deleted.
:param volumes: a list of volume dictionaries in the group.
:returns: model_update, volumes_model_update
param volumes is retrieved directly from the db. It is a list of
cinder.db.sqlalchemy.models.Volume to be precise. It cannot be
assigned to volumes_model_update. volumes_model_update is a list of
dictionaries. It has to be built by the driver. An entry will be
in this format: {'id': xxx, 'status': xxx, ......}. model_update
will be in this format: {'status': xxx, ......}.
The driver should populate volumes_model_update and model_update
and return them.
The manager will check volumes_model_update and update db accordingly
for each volume. If the driver successfully deleted some volumes
but failed to delete others, it should set statuses of the volumes
accordingly so that the manager can update db correctly.
If the status in any entry of volumes_model_update is 'error_deleting'
or 'error', the status in model_update will be set to the same if it
is not already 'error_deleting' or 'error'.
If the status in model_update is 'error_deleting' or 'error', the
manager will raise an exception and the status of the group will be
set to 'error' in the db. If volumes_model_update is not returned by
the driver, the manager will set the status of every volume in the
group to 'error' in the except block.
If the driver raises an exception during the operation, it will be
caught by the try-except block in the manager. The statuses of the
group and all volumes in it will be set to 'error'.
For a successful operation, the driver can either build the
model_update and volumes_model_update and return them or
return None, None. The statuses of the group and all volumes
will be set to 'deleted' after the manager deletes them from db.
"""
def update_consistencygroup(self, context, group,
add_volumes=None, remove_volumes=None):
"""Updates a consistency group.
:param context: the context of the caller.
:param group: the dictionary of the consistency group to be updated.
:param add_volumes: a list of volume dictionaries to be added.
:param remove_volumes: a list of volume dictionaries to be removed.
:returns: model_update, add_volumes_update, remove_volumes_update
model_update is a dictionary that the driver wants the manager
to update upon a successful return. If None is returned, the manager
will set the status to 'available'.
add_volumes_update and remove_volumes_update are lists of dictionaries
that the driver wants the manager to update upon a successful return.
Note that each entry requires a {'id': xxx} so that the correct
volume entry can be updated. If None is returned, the volume will
remain its original status. Also note that you cannot directly
assign add_volumes to add_volumes_update as add_volumes is a list of
cinder.db.sqlalchemy.models.Volume objects and cannot be used for
db update directly. Same with remove_volumes.
If the driver throws an exception, the status of the group as well as
those of the volumes to be added/removed will be set to 'error'.
"""
def create_cgsnapshot(self, context, cgsnapshot, snapshots):
"""Creates a cgsnapshot.
:param context: the context of the caller.
:param cgsnapshot: the dictionary of the cgsnapshot to be created.
:param snapshots: a list of snapshot dictionaries in the cgsnapshot.
:returns: model_update, snapshots_model_update
param snapshots is retrieved directly from the db. It is a list of
cinder.db.sqlalchemy.models.Snapshot to be precise. It cannot be
assigned to snapshots_model_update. snapshots_model_update is a list
of dictionaries. It has to be built by the driver. An entry will be
in this format: {'id': xxx, 'status': xxx, ......}. model_update
will be in this format: {'status': xxx, ......}.
The driver should populate snapshots_model_update and model_update
and return them.
The manager will check snapshots_model_update and update db accordingly
for each snapshot. If the driver successfully deleted some snapshots
but failed to delete others, it should set statuses of the snapshots
accordingly so that the manager can update db correctly.
If the status in any entry of snapshots_model_update is 'error', the
status in model_update will be set to the same if it is not already
'error'.
If the status in model_update is 'error', the manager will raise an
exception and the status of cgsnapshot will be set to 'error' in the
db. If snapshots_model_update is not returned by the driver, the
manager will set the status of every snapshot to 'error' in the except
block.
If the driver raises an exception during the operation, it will be
caught by the try-except block in the manager and the statuses of
cgsnapshot and all snapshots will be set to 'error'.
For a successful operation, the driver can either build the
model_update and snapshots_model_update and return them or
return None, None. The statuses of cgsnapshot and all snapshots
will be set to 'available' at the end of the manager function.
"""
def delete_cgsnapshot(self, context, cgsnapshot, snapshots):
"""Deletes a cgsnapshot.
:param context: the context of the caller.
:param cgsnapshot: the dictionary of the cgsnapshot to be deleted.
:param snapshots: a list of snapshot dictionaries in the cgsnapshot.
:returns: model_update, snapshots_model_update
param snapshots is retrieved directly from the db. It is a list of
cinder.db.sqlalchemy.models.Snapshot to be precise. It cannot be
assigned to snapshots_model_update. snapshots_model_update is a list
of dictionaries. It has to be built by the driver. An entry will be
in this format: {'id': xxx, 'status': xxx, ......}. model_update
will be in this format: {'status': xxx, ......}.
The driver should populate snapshots_model_update and model_update
and return them.
The manager will check snapshots_model_update and update db accordingly
for each snapshot. If the driver successfully deleted some snapshots
but failed to delete others, it should set statuses of the snapshots
accordingly so that the manager can update db correctly.
If the status in any entry of snapshots_model_update is
'error_deleting' or 'error', the status in model_update will be set to
the same if it is not already 'error_deleting' or 'error'.
If the status in model_update is 'error_deleting' or 'error', the
manager will raise an exception and the status of cgsnapshot will be
set to 'error' in the db. If snapshots_model_update is not returned by
the driver, the manager will set the status of every snapshot to
'error' in the except block.
If the driver raises an exception during the operation, it will be
caught by the try-except block in the manager and the statuses of
cgsnapshot and all snapshots will be set to 'error'.
For a successful operation, the driver can either build the
model_update and snapshots_model_update and return them or
return None, None. The statuses of cgsnapshot and all snapshots
will be set to 'deleted' after the manager deletes them from db.
"""

View File

@ -0,0 +1,247 @@
# Copyright 2016 Dell Inc.
# 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.
#
"""
Core backend volume driver interface.
All backend drivers should support this interface as a bare minimum.
"""
from cinder.interface import base
class VolumeDriverCore(base.CinderInterface):
"""Core backend driver required interface."""
def do_setup(self, context):
"""Any initialization the volume driver needs to do while starting.
Called once by the manager after the driver is loaded.
Can be used to set up clients, check licenses, set up protocol
specific helpers, etc.
:param context: The admin context.
"""
def check_for_setup_error(self):
"""Validate there are no issues with the driver configuration.
Called after do_setup(). Driver initialization can occur there or in
this call, but must be complete by the time this returns.
If this method raises an exception, the driver will be left in an
"uninitialized" state by the volume manager, which means that it will
not be sent requests for volume operations.
This method typically checks things like whether the configured
credentials can be used to log in the storage backend, and whether any
external dependencies are present and working.
:raises: VolumeBackendAPIException in case of setup error.
"""
def get_volume_stats(self, refresh=False):
"""Collects volume backend stats.
The get_volume_stats method is used by the volume manager to collect
information from the driver instance related to information about the
driver, available and used space, and driver/backend capabilities.
It returns a dict with the following required fields:
* volume_backend_name
This is an identifier for the backend taken from cinder.conf.
Useful when using multi-backend.
* vendor_name
Vendor/author of the driver who serves as the contact for the
driver's development and support.
* driver_version
The driver version is logged at cinder-volume startup and is useful
for tying volume service logs to a specific release of the code.
There are currently no rules for how or when this is updated, but
it tends to follow typical major.minor.revision ideas.
* storage_protocol
The protocol used to connect to the storage, this should be a short
string such as: "iSCSI", "FC", "nfs", "ceph", etc.
* total_capacity_gb
The total capacity in gigabytes (GiB) of the storage backend being
used to store Cinder volumes.
* free_capacity_gb
The free capacity in gigabytes (GiB).
And the following optional fields:
* reserved_percentage (integer)
Percentage of backend capacity which is not used by the scheduler.
* location_info (string)
Driver-specific information used by the driver and storage backend
to correlate Cinder volumes and backend LUNs/files.
* QoS_support (Boolean)
Whether the backend supports quality of service.
* provisioned_capacity_gb
The total provisioned capacity on the storage backend, in gigabytes
(GiB), including space consumed by any user other than Cinder
itself.
* max_over_subscription_ratio
The maximum amount a backend can be over subscribed.
* thin_provisioning_support (Boolean)
Whether the backend is capable of allocating thinly provisioned
volumes.
* thick_provisioning_support (Boolean)
Whether the backend is capable of allocating thick provisioned
volumes. (Typically True.)
* total_volumes (integer)
Total number of volumes on the storage backend. This can be used in
custom driver filter functions.
* filter_function (string)
A custom function used by the scheduler to determine whether a
volume should be allocated to this backend or not. Example:
capabilities.total_volumes < 10
* goodness_function (string)
Similar to filter_function, but used to weigh multiple volume
backends. Example:
capabilities.capacity_utilization < 0.6 ? 100 : 25
* multiattach (Boolean)
Whether the backend supports multiattach or not. Defaults to False.
* sparse_copy_volume (Boolean)
Whether copies performed by the volume manager for operations such
as migration should attempt to preserve sparseness.
The returned dict may also contain a list, "pools", which has a similar
dict for each pool being used with the backend.
:param refresh: Whether to discard any cached values and force a full
refresh of stats.
:returns: dict of appropriate values (see above).
"""
def create_volume(self, volume):
"""Create a new volume on the backend.
This method is responsible only for storage allocation on the backend.
It should not export a LUN or actually make this storage available for
use, this is done in a later call.
# TODO(smcginnis) - Add example data structure of volume object.
:param volume: Volume object containing specifics to create.
:returns: (Optional) dict of database updates for the new volume.
:raises: VolumeBackendAPIException if creation failed.
"""
def delete_volume(self, volume):
"""Delete a volume from the backend.
If the driver can talk to the backend and detects that the volume is no
longer present, this call should succeed and allow Cinder to complete
the process of deleting the volume.
:param volume: The volume to delete.
:raises: VolumeIsBusy if the volume is still attached or has snapshots.
VolumeBackendAPIException on error.
"""
def initialize_connection(self, volume, connector, initiator_data=None):
"""Allow connection to connector and return connection info.
:param volume: The volume to be attached.
:param connector: Dictionary containing information about what is being
connected to.
:param initiator_data: (Optional) A dictionary of driver_initiator_data
objects with key-value pairs that have been
saved for this initiator by a driver in previous
initialize_connection calls.
:returns: A dictionary of connection information. This can optionally
include a "initiator_updates" field.
The "initiator_updates" field must be a dictionary containing a
"set_values" and/or "remove_values" field. The "set_values" field must
be a dictionary of key-value pairs to be set/updated in the db. The
"remove_values" field must be a list of keys, previously set with
"set_values", that will be deleted from the db.
May be called multiple times to get connection information after a
volume has already been attached.
"""
def attach_volume(self, context, volume, instance_uuid, host_name,
mountpoint):
"""Lets the driver know Nova has attached the volume to an instance.
:param context: Security/policy info for the request.
:param volume: Volume being attached.
:param instance_uuid: ID of the instance being attached to.
:param host_name: The host name.
:param mountpoint: Device mount point on the instance.
"""
def terminate_connection(self, volume, connector):
"""Remove access to a volume.
:param volume: The volume to remove.
:param connector: The Dictionary containing information about the
connection.
"""
def detach_volume(self, context, volume, attachment=None):
"""Detach volume from an instance.
:param context: Security/policy info for the request.
:param volume: Volume being detached.
:param attachment: (Optional) Attachment information.
"""
def clone_image(self, volume, image_location, image_id, image_metadata,
image_service):
"""Clone an image to a volume.
:param volume: The volume to create.
:param image_location: Where to pull the image from.
:param image_id: The image identifier.
:param image_metadata: Information about the image.
:param image_service: The image service to use.
:returns: Model updates.
"""
def copy_image_to_volume(self, context, volume, image_service, image_id):
"""Fetch the image from image_service and write it to the volume.
:param context: Security/policy info for the request.
:param volume: The volume to create.
:param image_service: The image service to use.
:param image_id: The image identifier.
:returns: Model updates.
"""
def copy_volume_to_image(self, context, volume, image_service, image_meta):
"""Copy the volume to the specified image.
:param context: Security/policy info for the request.
:param volume: The volume to copy.
:param image_service: The image service to use.
:param image_meta: Information about the image.
:returns: Model updates.
"""
def extend_volume(self, volume, new_size):
"""Extend the size of a volume.
:param volume: The volume to extend.
:param new_size: The new desired size of the volume.
"""

View File

@ -0,0 +1,81 @@
# Copyright 2016 Dell Inc.
# 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.
#
"""
Manage/unmanage existing volume driver interface.
"""
from cinder.interface import base
class VolumeManagementDriver(base.CinderInterface):
"""Interface for drivers that support managing existing volumes."""
def manage_existing(self, volume, existing_ref):
"""Brings an existing backend storage object under Cinder management.
existing_ref is passed straight through from the API request's
manage_existing_ref value, and it is up to the driver how this should
be interpreted. It should be sufficient to identify a storage object
that the driver should somehow associate with the newly-created cinder
volume structure.
There are two ways to do this:
1. Rename the backend storage object so that it matches the,
volume['name'] which is how drivers traditionally map between a
cinder volume and the associated backend storage object.
2. Place some metadata on the volume, or somewhere in the backend, that
allows other driver requests (e.g. delete, clone, attach, detach...)
to locate the backend storage object when required.
If the existing_ref doesn't make sense, or doesn't refer to an existing
backend storage object, raise a ManageExistingInvalidReference
exception.
The volume may have a volume_type, and the driver can inspect that and
compare against the properties of the referenced backend storage
object. If they are incompatible, raise a
ManageExistingVolumeTypeMismatch, specifying a reason for the failure.
:param volume: Cinder volume to manage
:param existing_ref: Driver-specific information used to identify a
volume
"""
def manage_existing_get_size(self, volume, existing_ref):
"""Return size of volume to be managed by manage_existing.
When calculating the size, round up to the next GB.
:param volume: Cinder volume to manage
:param existing_ref: Driver-specific information used to identify a
volume
"""
def unmanage(self, volume):
"""Removes the specified volume from Cinder management.
Does not delete the underlying backend storage object.
For most drivers, this will not need to do anything. However, some
drivers might use this call as an opportunity to clean up any
Cinder-specific configuration that they have associated with the
backend storage object.
:param volume: Cinder volume to unmanage
"""

View File

@ -0,0 +1,57 @@
# Copyright 2016 Dell Inc.
# 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.
#
"""
Snapshot capable volume driver interface.
"""
from cinder.interface import base
class VolumeSnapshotDriver(base.CinderInterface):
"""Interface for drivers that support snapshots.
TODO(smcginnis) Merge into VolumeDriverBase once NFS driver supports
snapshots.
"""
def create_snapshot(self, snapshot):
"""Creates a snapshot.
:param snapshot: Information for the snapshot to be created.
"""
def delete_snapshot(self, snapshot):
"""Deletes a snapshot.
:param snapshot: The snapshot to delete.
"""
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot.
If volume_type extra specs includes 'replication: <is> True'
the driver needs to create a volume replica (secondary),
and setup replication between the newly created volume and
the secondary volume.
An optional larger size for the new snapshot can be specified. Drivers
should check this value and create or expand the new volume to match.
:param volume: The volume to be created.
:param snapshot: The snapshot from which to create the volume.
:returns: A dict of database updates for the new volume.
"""

View File

@ -0,0 +1,73 @@
# Copyright 2016 Dell Inc.
# 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.
#
"""
Manage/unmanage existing volume snapshots driver interface.
"""
from cinder.interface import base
class VolumeSnapshotManagementDriver(base.CinderInterface):
"""Interface for drivers that support managing existing snapshots."""
def manage_existing_snapshot(self, snapshot, existing_ref):
"""Brings an existing backend storage object under Cinder management.
existing_ref is passed straight through from the API request's
manage_existing_ref value, and it is up to the driver how this should
be interpreted. It should be sufficient to identify a storage object
that the driver should somehow associate with the newly-created cinder
snapshot structure.
There are two ways to do this:
1. Rename the backend storage object so that it matches the
snapshot['name'] which is how drivers traditionally map between a
cinder snapshot and the associated backend storage object.
2. Place some metadata on the snapshot, or somewhere in the backend,
that allows other driver requests (e.g. delete) to locate the
backend storage object when required.
:param snapshot: The snapshot to manage.
:param existing_ref: A reference to the existing snap.
:raises: ManageExistingInvalidReference If the existing_ref doesn't
make sense, or doesn't refer to an existing backend storage
object.
"""
def manage_existing_snapshot_get_size(self, snapshot, existing_ref):
"""Return size of snapshot to be managed by manage_existing.
When calculating the size, round up to the next GB.
:param snapshot: The snapshot.
:param existing_ref: A reference to the existing snap.
"""
def unmanage_snapshot(self, snapshot):
"""Removes the specified snapshot from Cinder management.
Does not delete the underlying backend storage object.
For most drivers, this will not need to do anything. However, some
drivers might use this call as an opportunity to clean up any
Cinder-specific configuration that they have associated with the
backend storage object.
:param snapshot: The snapshot to unmanage.
"""

View File

View File

@ -0,0 +1,45 @@
# Copyright 2016 Dell Inc.
# 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.
#
import ddt
from cinder.interface import backup_driver
from cinder.interface import util
from cinder import test
BACKUP_DRIVERS = util.get_backup_drivers()
@ddt.ddt
class TestBackupDrivers(test.TestCase):
def test_backup_driver_decorator(self):
"""Sanity check on the decorator.
The interface code is somewhat implicitly tested. We don't need unit
tests for all of that code, but as a minimum we should make sure it
returns at least one registered driver, else the compliance test will
never even run.
"""
self.assertTrue(len(BACKUP_DRIVERS) > 0)
@ddt.data(*BACKUP_DRIVERS)
def test_backup_driver_compliance(self, driver):
"""Makes sure all backup drivers support the minimum requirements."""
self.assertTrue(
issubclass(driver.cls, backup_driver.BackupDriver),
"Driver {} does not conform to minimum backup driver "
"requirements!".format(driver.class_fqn))

View File

@ -0,0 +1,45 @@
# Copyright 2016 Dell Inc.
# 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.
#
import ddt
from cinder.interface import fczm_driver
from cinder.interface import util
from cinder import test
FCZM_DRIVERS = util.get_fczm_drivers()
@ddt.ddt
class TestFibreChannelZoneManagerDrivers(test.TestCase):
def test_fczm_driver_decorator(self):
"""Sanity check on the decorator.
The interface code is somewhat implicitly tested. We don't need unit
tests for all of that code, but as a minimum we should make sure it
returns at least one registered driver, else the compliance test will
never even run.
"""
self.assertTrue(len(FCZM_DRIVERS) > 0)
@ddt.data(*FCZM_DRIVERS)
def test_fczm_driver_compliance(self, driver):
"""Makes sure all fczm drivers support the minimum requirements."""
self.assertTrue(
issubclass(driver.cls, fczm_driver.FibreChannelZoneManagerDriver),
"Driver {} does not conform to minimum fczm driver "
"requirements!".format(driver.class_fqn))

View File

@ -0,0 +1,44 @@
# Copyright 2016 Dell Inc.
# 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.
#
import ddt
from cinder.interface import util
from cinder.interface import volume_driver
from cinder import test
VOLUME_DRIVERS = util.get_volume_drivers()
@ddt.ddt
class TestVolumeDrivers(test.TestCase):
def test_volume_driver_decorator(self):
"""Sanity check on the decorator.
The interface code is somewhat implicitly tested. We don't need unit
tests for all of that code, but as a minimum we should make sure it
returns at least one registered driver, else the compliance test will
never even run.
"""
self.assertTrue(len(VOLUME_DRIVERS) > 0)
@ddt.data(*VOLUME_DRIVERS)
def test_volume_driver_compliance(self, driver):
self.assertTrue(
issubclass(driver.cls, volume_driver.VolumeDriverCore),
"Driver {} does not conform to minimum volume driver "
"requirements!".format(driver.class_fqn))

View File

@ -24,6 +24,7 @@ from cinder import context
from cinder import exception
from cinder.i18n import _, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder import objects
from cinder import utils
from cinder.volume import driver
@ -42,6 +43,7 @@ CONF = cfg.CONF
CONF.register_opts(volume_opts)
@interface.volumedriver
class BlockDeviceDriver(driver.BaseVD, driver.LocalVD,
driver.CloneableImageVD, driver.TransferVD):
VERSION = '2.2.0'

View File

@ -29,6 +29,7 @@ from six.moves import urllib
from cinder import context
from cinder import exception
from cinder.i18n import _
from cinder import interface
from cinder.volume import driver
from cinder.volume import utils as volume_utils
@ -168,6 +169,7 @@ class BlockbridgeAPIClient(object):
return rsp_data
@interface.volumedriver
class BlockbridgeISCSIDriver(driver.ISCSIDriver):
"""Manages volumes hosted on Blockbridge EPS."""

View File

@ -26,6 +26,7 @@ from six.moves import urllib
from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI
from cinder import interface
from cinder.volume.drivers.cloudbyte import options
from cinder.volume.drivers.san import san
from cinder.volume import qos_specs
@ -34,6 +35,7 @@ from cinder.volume import volume_types
LOG = logging.getLogger(__name__)
@interface.volumedriver
class CloudByteISCSIDriver(san.SanISCSIDriver):
"""CloudByte ISCSI Driver.

View File

@ -25,6 +25,7 @@ from random import randint
from cinder import exception
from cinder.i18n import _
from cinder import interface
from cinder import utils
from cinder.volume.drivers import nfs
@ -292,6 +293,7 @@ CONF = cfg.CONF
CONF.register_opts(coho_opts)
@interface.volumedriver
class CohoDriver(nfs.NfsDriver):
"""Coho Data NFS based cinder driver.

View File

@ -29,6 +29,7 @@ import six
from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI
from cinder import interface
from cinder import utils
from cinder.volume.drivers.san import san
from cinder.volume import qos_specs
@ -111,6 +112,7 @@ def _authenticated(func):
return func_wrapper
@interface.volumedriver
@six.add_metaclass(utils.TraceWrapperWithABCMetaclass)
class DateraDriver(san.SanISCSIDriver):

View File

@ -19,6 +19,7 @@ from oslo_utils import excutils
from cinder import exception
from cinder.i18n import _, _LE
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.dell import dell_storagecenter_common
from cinder.zonemanager import utils as fczm_utils
@ -26,6 +27,7 @@ from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
@interface.volumedriver
class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver,
driver.FibreChannelDriver):

View File

@ -19,11 +19,13 @@ from oslo_utils import excutils
from cinder import exception
from cinder.i18n import _, _LE, _LI
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.dell import dell_storagecenter_common
LOG = logging.getLogger(__name__)
@interface.volumedriver
class DellStorageCenterISCSIDriver(dell_storagecenter_common.DellCommonDriver,
driver.ISCSIDriver):

View File

@ -31,6 +31,7 @@ from cinder.db.sqlalchemy import api
from cinder import exception
from cinder.i18n import _
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume import driver
@ -82,6 +83,7 @@ CONF.register_opts(disco_opts)
# Driver to communicate with DISCO storage solution
@interface.volumedriver
class DiscoDriver(driver.VolumeDriver):
"""Execute commands related to DISCO Volumes."""

View File

@ -14,12 +14,14 @@
# under the License.
#
from cinder import interface
import cinder.volume.driver
from cinder.volume.drivers.dothill import dothill_common
from cinder.volume.drivers.san import san
from cinder.zonemanager import utils as fczm_utils
@interface.volumedriver
class DotHillFCDriver(cinder.volume.driver.FibreChannelDriver):
"""OpenStack Fibre Channel cinder drivers for DotHill Arrays.

View File

@ -18,6 +18,7 @@ from oslo_log import log as logging
from cinder import exception
from cinder.i18n import _
from cinder import interface
import cinder.volume.driver
from cinder.volume.drivers.dothill import dothill_common as dothillcommon
from cinder.volume.drivers.san import san
@ -27,6 +28,7 @@ DEFAULT_ISCSI_PORT = "3260"
LOG = logging.getLogger(__name__)
@interface.volumedriver
class DotHillISCSIDriver(cinder.volume.driver.ISCSIDriver):
"""OpenStack iSCSI cinder drivers for DotHill Arrays.

View File

@ -38,6 +38,7 @@ from oslo_utils import units
from cinder import exception
from cinder.i18n import _, _LW, _LI, _LE
from cinder import interface
from cinder.volume import driver
try:
@ -758,7 +759,7 @@ class DrbdManageBaseDriver(driver.VolumeDriver):
# Class with iSCSI interface methods
@interface.volumedriver
class DrbdManageIscsiDriver(DrbdManageBaseDriver):
"""Cinder driver that uses the iSCSI protocol. """
@ -820,6 +821,7 @@ DrbdManageDriver = DrbdManageIscsiDriver
# Class with DRBD transport mode
@interface.volumedriver
class DrbdManageDrbdDriver(DrbdManageBaseDriver):
"""Cinder driver that uses the DRBD protocol. """

View File

@ -16,6 +16,7 @@
from oslo_log import log as logging
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.emc import emc_vnx_cli
from cinder.zonemanager import utils as zm_utils
@ -24,6 +25,7 @@ from cinder.zonemanager import utils as zm_utils
LOG = logging.getLogger(__name__)
@interface.volumedriver
class EMCCLIFCDriver(driver.FibreChannelDriver):
"""EMC FC Driver for VNX using CLI.

View File

@ -16,12 +16,14 @@
from oslo_log import log as logging
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.emc import emc_vnx_cli
LOG = logging.getLogger(__name__)
@interface.volumedriver
class EMCCLIISCSIDriver(driver.ISCSIDriver):
"""EMC ISCSI Drivers for VNX using CLI.

View File

@ -20,6 +20,7 @@ import six
from cinder import context
from cinder.i18n import _LW
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.emc import emc_vmax_common
from cinder.zonemanager import utils as fczm_utils
@ -27,6 +28,7 @@ from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
@interface.volumedriver
class EMCVMAXFCDriver(driver.FibreChannelDriver):
"""EMC FC Drivers for VMAX using SMI-S.

View File

@ -24,6 +24,7 @@ import six
from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.emc import emc_vmax_common
@ -33,6 +34,7 @@ LOG = logging.getLogger(__name__)
CINDER_CONF = '/etc/cinder/cinder.conf'
@interface.volumedriver
class EMCVMAXISCSIDriver(driver.ISCSIDriver):
"""EMC ISCSI Drivers for VMAX using SMI-S.

View File

@ -32,6 +32,7 @@ from cinder import context
from cinder import exception
from cinder.i18n import _, _LI, _LW, _LE
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume import driver
from cinder.volume.drivers.san import san
@ -88,6 +89,7 @@ VOLUME_NOT_MAPPED_ERROR = 84
VOLUME_ALREADY_MAPPED_ERROR = 81
@interface.volumedriver
class ScaleIODriver(driver.VolumeDriver):
"""EMC ScaleIO Driver."""

View File

@ -44,6 +44,7 @@ import six
from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder import objects
from cinder.objects import fields
from cinder import utils
@ -774,6 +775,7 @@ class XtremIOVolumeDriver(san.SanDriver):
(data=_("Failed to create IG, %s") % name))
@interface.volumedriver
class XtremIOISCSIDriver(XtremIOVolumeDriver, driver.ISCSIDriver):
"""Executes commands relating to ISCSI volumes.
@ -918,6 +920,7 @@ class XtremIOISCSIDriver(XtremIOVolumeDriver, driver.ISCSIDriver):
return connector['initiator']
@interface.volumedriver
class XtremIOFibreChannelDriver(XtremIOVolumeDriver,
driver.FibreChannelDriver):

View File

@ -30,6 +30,7 @@ from six.moves import range
from cinder import exception
from cinder.i18n import _, _LE, _LW, _LI
from cinder import interface
from cinder import ssh_utils
from cinder import utils
from cinder.volume.drivers import san
@ -102,6 +103,7 @@ def with_timeout(f):
return __inner
@interface.volumedriver
class DellEQLSanISCSIDriver(san.SanISCSIDriver):
"""Implements commands for Dell EqualLogic SAN ISCSI management.

View File

@ -22,6 +22,7 @@ FibreChannel Cinder Volume driver for Fujitsu ETERNUS DX S3 series.
from oslo_log import log as logging
import six
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.fujitsu import eternus_dx_common
from cinder.zonemanager import utils as fczm_utils
@ -29,6 +30,7 @@ from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
@interface.volumedriver
class FJDXFCDriver(driver.FibreChannelDriver):
"""FC Cinder Volume Driver for Fujitsu ETERNUS DX S3 series."""

View File

@ -22,6 +22,7 @@ iSCSI Cinder Volume driver for Fujitsu ETERNUS DX S3 series.
import six
from cinder.i18n import _LI
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.fujitsu import eternus_dx_common
from oslo_log import log as logging
@ -29,6 +30,7 @@ from oslo_log import log as logging
LOG = logging.getLogger(__name__)
@interface.volumedriver
class FJDXISCSIDriver(driver.ISCSIDriver):
"""iSCSI Cinder Volume Driver for Fujitsu ETERNUS DX S3 series."""

View File

@ -27,6 +27,7 @@ from oslo_utils import units
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume import driver
from cinder.volume.drivers import remotefs as remotefs_drv
@ -47,6 +48,7 @@ CONF = cfg.CONF
CONF.register_opts(volume_opts)
@interface.volumedriver
class GlusterfsDriver(remotefs_drv.RemoteFSSnapDriver,
driver.ExtendVD):
"""Gluster based cinder driver.

View File

@ -38,6 +38,7 @@ from cinder.i18n import _
from cinder.i18n import _LE
from cinder.i18n import _LW
from cinder.image import image_utils
from cinder import interface
from cinder.volume import driver
from cinder.volume import utils as volutils
@ -70,6 +71,7 @@ CONF = cfg.CONF
CONF.register_opts(hgst_opts)
@interface.volumedriver
class HGSTDriver(driver.VolumeDriver):
"""This is the Class to set in cinder.conf (volume_driver).

View File

@ -26,6 +26,7 @@ import six
from cinder import exception
from cinder.i18n import _LI, _LW
from cinder import interface
from cinder import utils
import cinder.volume.driver
from cinder.volume.drivers.hitachi import hbsd_basiclib as basic_lib
@ -44,6 +45,7 @@ CONF = cfg.CONF
CONF.register_opts(volume_opts)
@interface.volumedriver
class HBSDFCDriver(cinder.volume.driver.FibreChannelDriver):
VERSION = common.VERSION

View File

@ -25,6 +25,7 @@ import six
from cinder import exception
from cinder.i18n import _LE, _LI
from cinder import interface
from cinder import utils
import cinder.volume.driver
from cinder.volume.drivers.hitachi import hbsd_basiclib as basic_lib
@ -52,6 +53,7 @@ CONF = cfg.CONF
CONF.register_opts(volume_opts)
@interface.volumedriver
class HBSDISCSIDriver(cinder.volume.driver.ISCSIDriver):
VERSION = common.VERSION

View File

@ -30,6 +30,7 @@ from oslo_utils import units
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder import utils as cinder_utils
from cinder.volume import driver
from cinder.volume.drivers.hitachi import hnas_backend
@ -164,6 +165,7 @@ def _read_config(xml_config_file):
return config
@interface.volumedriver
class HDSISCSIDriver(driver.ISCSIDriver):
"""HDS HNAS volume driver.

View File

@ -33,6 +33,7 @@ from oslo_utils import units
from cinder import exception
from cinder.i18n import _, _LE, _LI
from cinder.image import image_utils
from cinder import interface
from cinder import utils as cutils
from cinder.volume.drivers.hitachi import hnas_backend
from cinder.volume.drivers import nfs
@ -150,6 +151,7 @@ def factory_bend(drv_config):
return hnas_backend.HnasBackend(drv_config)
@interface.volumedriver
class HDSNFSDriver(nfs.NfsDriver):
"""Base class for Hitachi NFS driver.

View File

@ -38,6 +38,7 @@ from oslo_log import log as logging
from cinder import exception
from cinder.i18n import _, _LI, _LW
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.hpe import hpe_3par_common as hpecommon
from cinder.volume.drivers.san import san
@ -46,6 +47,7 @@ from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
@interface.volumedriver
class HPE3PARFCDriver(driver.TransferVD,
driver.ManageableVD,
driver.ExtendVD,

View File

@ -40,6 +40,7 @@ import six
from cinder import exception
from cinder.i18n import _, _LE, _LW
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.hpe import hpe_3par_common as hpecommon
from cinder.volume.drivers.san import san
@ -51,6 +52,7 @@ CHAP_USER_KEY = "HPQ-cinder-CHAP-name"
CHAP_PASS_KEY = "HPQ-cinder-CHAP-secret"
@interface.volumedriver
class HPE3PARISCSIDriver(driver.TransferVD,
driver.ManageableVD,
driver.ExtendVD,

View File

@ -44,6 +44,7 @@ from oslo_utils import units
from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder.objects import fields
from cinder.volume import driver
from cinder.volume.drivers.san import san
@ -120,6 +121,7 @@ extra_specs_value_map = {
}
@interface.volumedriver
class HPELeftHandISCSIDriver(driver.ISCSIDriver):
"""Executes REST commands relating to HPE/LeftHand SAN ISCSI volumes.

View File

@ -18,6 +18,7 @@ Fibre channel Cinder volume driver for Hewlett Packard Enterprise storage.
from oslo_utils import importutils
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.hpe import hpe_xp_opts as opts
from cinder.zonemanager import utils as fczm_utils
@ -26,6 +27,7 @@ _DRIVER_DIR = 'cinder.volume.drivers.hpe'
_DRIVER_CLASS = 'hpe_xp_horcm_fc.HPEXPHORCMFC'
@interface.volumedriver
class HPEXPFCDriver(driver.FibreChannelDriver):
"""OpenStack Fibre Channel driver to enable HPE XP storage."""

View File

@ -26,6 +26,7 @@ from oslo_utils import units
from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder import utils
from cinder.volume import driver
from cinder.volume.drivers.huawei import constants
@ -1586,6 +1587,7 @@ class HuaweiBaseDriver(driver.VolumeDriver):
return secondary_id, volumes_update
@interface.volumedriver
class HuaweiISCSIDriver(HuaweiBaseDriver, driver.ISCSIDriver):
"""ISCSI driver for Huawei storage arrays.
@ -1777,6 +1779,7 @@ class HuaweiISCSIDriver(HuaweiBaseDriver, driver.ISCSIDriver):
self.client.delete_mapping_view(view_id)
@interface.volumedriver
class HuaweiFCDriver(HuaweiBaseDriver, driver.FibreChannelDriver):
"""FC driver for Huawei OceanStor storage arrays.

View File

@ -33,6 +33,7 @@ import six
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder import utils
import cinder.volume.driver
from cinder.volume.drivers.ibm import flashsystem_common as fscommon
@ -53,6 +54,7 @@ CONF = cfg.CONF
CONF.register_opts(flashsystem_fc_opts)
@interface.volumedriver
class FlashSystemFCDriver(fscommon.FlashSystemDriver,
cinder.volume.driver.FibreChannelDriver):
"""IBM FlashSystem FC volume driver.

View File

@ -33,6 +33,7 @@ import six
from cinder import exception
from cinder.i18n import _, _LE, _LW
from cinder import interface
from cinder import utils
import cinder.volume.driver
from cinder.volume.drivers.ibm import flashsystem_common as fscommon
@ -51,6 +52,7 @@ CONF = cfg.CONF
CONF.register_opts(flashsystem_iscsi_opts)
@interface.volumedriver
class FlashSystemISCSIDriver(fscommon.FlashSystemDriver,
cinder.volume.driver.ISCSIDriver):
"""IBM FlashSystem iSCSI volume driver.

View File

@ -31,6 +31,7 @@ from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI
from cinder.image import image_utils
from cinder import interface
from cinder.objects import fields
from cinder import utils
from cinder.volume import driver
@ -105,6 +106,7 @@ def _sizestr(size_in_g):
return '%sG' % size_in_g
@interface.volumedriver
class GPFSDriver(driver.ConsistencyGroupVD, driver.ExtendVD,
driver.LocalVD, driver.TransferVD,
driver.CloneableImageVD, driver.SnapshotVD,
@ -1240,6 +1242,7 @@ class GPFSDriver(driver.ConsistencyGroupVD, driver.ExtendVD,
return model_update, snapshots_model_update
@interface.volumedriver
class GPFSNFSDriver(GPFSDriver, nfs.NfsDriver, san.SanDriver):
"""GPFS cinder driver extension.

View File

@ -40,6 +40,7 @@ from oslo_utils import excutils
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder import utils
from cinder.volume.drivers.ibm.storwize_svc import (
storwize_svc_common as storwize_common)
@ -58,6 +59,7 @@ CONF = cfg.CONF
CONF.register_opts(storwize_svc_fc_opts)
@interface.volumedriver
class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
"""IBM Storwize V7000 and SVC FC volume driver.

View File

@ -40,6 +40,7 @@ from oslo_utils import excutils
from cinder import exception
from cinder.i18n import _, _LE, _LW
from cinder import interface
from cinder import utils
from cinder.volume.drivers.ibm.storwize_svc import (
@ -58,6 +59,7 @@ CONF = cfg.CONF
CONF.register_opts(storwize_svc_iscsi_opts)
@interface.volumedriver
class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
"""IBM Storwize V7000 and SVC iSCSI volume driver.

View File

@ -27,6 +27,7 @@ from oslo_log import log as logging
from oslo_utils import importutils
from cinder import exception
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.san import san
@ -58,6 +59,7 @@ CONF.register_opts(xiv_ds8k_opts)
LOG = logging.getLogger(__name__)
@interface.volumedriver
class XIVDS8KDriver(san.SanDriver,
driver.ManageableVD,
driver.ExtendVD,

View File

@ -19,6 +19,7 @@ Fibre Channel Driver for Infortrend Eonstor based on CLI.
from oslo_log import log as logging
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.infortrend.eonstor_ds_cli import common_cli
from cinder.zonemanager import utils as fczm_utils
@ -26,6 +27,7 @@ from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
@interface.volumedriver
class InfortrendCLIFCDriver(driver.FibreChannelDriver):
"""Infortrend Fibre Channel Driver for Eonstor DS using CLI.

View File

@ -18,12 +18,14 @@ iSCSI Driver for Infortrend Eonstor based on CLI.
from oslo_log import log as logging
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.infortrend.eonstor_ds_cli import common_cli
LOG = logging.getLogger(__name__)
@interface.volumedriver
class InfortrendCLIISCSIDriver(driver.ISCSIDriver):
"""Infortrend iSCSI Driver for Eonstor DS using CLI.

View File

@ -14,10 +14,12 @@
# under the License.
#
from cinder import interface
from cinder.volume.drivers.dothill import dothill_fc
from cinder.volume.drivers.lenovo import lenovo_common
@interface.volumedriver
class LenovoFCDriver(dothill_fc.DotHillFCDriver):
"""OpenStack Fibre Channel cinder drivers for Lenovo Storage arrays.

View File

@ -14,10 +14,12 @@
# under the License.
#
from cinder import interface
from cinder.volume.drivers.dothill import dothill_iscsi
from cinder.volume.drivers.lenovo import lenovo_common
@interface.volumedriver
class LenovoISCSIDriver(dothill_iscsi.DotHillISCSIDriver):
"""OpenStack iSCSI cinder drivers for Lenovo Storage arrays.

View File

@ -31,6 +31,7 @@ from cinder.brick.local_dev import lvm as lvm
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder import objects
from cinder import utils
from cinder.volume import driver
@ -75,6 +76,7 @@ CONF = cfg.CONF
CONF.register_opts(volume_opts)
@interface.volumedriver
class LVMVolumeDriver(driver.VolumeDriver):
"""Executes commands relating to Volumes."""

View File

@ -16,11 +16,13 @@
Volume driver for NetApp Data ONTAP (7-mode) FibreChannel storage systems.
"""
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.netapp.dataontap import block_7mode
from cinder.zonemanager import utils as fczm_utils
@interface.volumedriver
class NetApp7modeFibreChannelDriver(driver.BaseVD,
driver.ConsistencyGroupVD,
driver.ManageableVD,

View File

@ -16,11 +16,13 @@
Volume driver for NetApp Data ONTAP (C-mode) FibreChannel storage systems.
"""
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.netapp.dataontap import block_cmode
from cinder.zonemanager import utils as fczm_utils
@interface.volumedriver
class NetAppCmodeFibreChannelDriver(driver.BaseVD,
driver.ConsistencyGroupVD,
driver.ManageableVD,

View File

@ -16,10 +16,12 @@
Volume driver for NetApp Data ONTAP (7-mode) iSCSI storage systems.
"""
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.netapp.dataontap import block_7mode
@interface.volumedriver
class NetApp7modeISCSIDriver(driver.BaseVD,
driver.ConsistencyGroupVD,
driver.ManageableVD,

View File

@ -16,10 +16,12 @@
Volume driver for NetApp Data ONTAP (C-mode) iSCSI storage systems.
"""
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.netapp.dataontap import block_cmode
@interface.volumedriver
class NetAppCmodeISCSIDriver(driver.BaseVD,
driver.ConsistencyGroupVD,
driver.ManageableVD,

View File

@ -28,6 +28,7 @@ import six
from cinder import exception
from cinder.i18n import _
from cinder import interface
from cinder import utils
from cinder.volume.drivers.netapp.dataontap.client import client_7mode
from cinder.volume.drivers.netapp.dataontap import nfs_base
@ -40,6 +41,7 @@ LOG = logging.getLogger(__name__)
@six.add_metaclass(utils.TraceWrapperWithABCMetaclass)
@interface.volumedriver
class NetApp7modeNfsDriver(nfs_base.NetAppNfsDriver):
"""NetApp NFS driver for Data ONTAP (7-mode)."""

View File

@ -32,6 +32,7 @@ import six
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume.drivers.netapp.dataontap.client import client_cmode
from cinder.volume.drivers.netapp.dataontap import nfs_base
@ -47,6 +48,7 @@ LOG = logging.getLogger(__name__)
QOS_CLEANUP_INTERVAL_SECONDS = 60
@interface.volumedriver
@six.add_metaclass(utils.TraceWrapperWithABCMetaclass)
class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver):
"""NetApp NFS driver for Data ONTAP (Cluster-mode)."""

View File

@ -16,12 +16,14 @@
Volume driver for NetApp E-Series FibreChannel storage systems.
"""
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.netapp.eseries import library
from cinder.volume.drivers.netapp import utils as na_utils
from cinder.zonemanager import utils as fczm_utils
@interface.volumedriver
class NetAppEseriesFibreChannelDriver(driver.BaseVD,
driver.ManageableVD,
driver.ExtendVD,

View File

@ -18,11 +18,13 @@
Volume driver for NetApp E-Series iSCSI storage systems.
"""
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.netapp.eseries import library
from cinder.volume.drivers.netapp import utils as na_utils
@interface.volumedriver
class NetAppEseriesISCSIDriver(driver.BaseVD,
driver.ManageableVD,
driver.ExtendVD,

View File

@ -20,6 +20,7 @@ from oslo_utils import excutils
from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.nexenta import jsonrpc
from cinder.volume.drivers.nexenta import options
@ -29,6 +30,7 @@ VERSION = '1.3.0.1'
LOG = logging.getLogger(__name__)
@interface.volumedriver
class NexentaISCSIDriver(driver.ISCSIDriver):
"""Executes volume driver commands on Nexenta Appliance.

View File

@ -21,6 +21,7 @@ from oslo_utils import units
from cinder import exception
from cinder.i18n import _, _LE, _LI
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.nexenta.nexentaedge import jsonrpc
from cinder.volume.drivers.nexenta import options
@ -29,6 +30,7 @@ from cinder.volume.drivers.nexenta import options
LOG = logging.getLogger(__name__)
@interface.volumedriver
class NexentaEdgeISCSIDriver(driver.ISCSIDriver):
"""Executes volume driver commands on NexentaEdge cluster.

View File

@ -26,6 +26,7 @@ from cinder import context
from cinder import db
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder.volume.drivers.nexenta import jsonrpc
from cinder.volume.drivers.nexenta import options
from cinder.volume.drivers.nexenta import utils
@ -35,6 +36,7 @@ VERSION = '1.3.0'
LOG = logging.getLogger(__name__)
@interface.volumedriver
class NexentaNfsDriver(nfs.NfsDriver): # pylint: disable=R0921
"""Executes volume driver commands on Nexenta Appliance.

View File

@ -20,6 +20,7 @@ from cinder import context
from cinder import db
from cinder import exception
from cinder.i18n import _, _LI, _LE, _LW
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.nexenta.ns5 import jsonrpc
from cinder.volume.drivers.nexenta import options
@ -29,6 +30,7 @@ VERSION = '1.0.0'
LOG = logging.getLogger(__name__)
@interface.volumedriver
class NexentaISCSIDriver(driver.ISCSIDriver): # pylint: disable=R0921
"""Executes volume driver commands on Nexenta Appliance.

View File

@ -22,6 +22,7 @@ from cinder import context
from cinder import db
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder.volume.drivers.nexenta.ns5 import jsonrpc
from cinder.volume.drivers.nexenta import options
from cinder.volume.drivers.nexenta import utils
@ -31,6 +32,7 @@ VERSION = '1.0.0'
LOG = logging.getLogger(__name__)
@interface.volumedriver
class NexentaNfsDriver(nfs.NfsDriver): # pylint: disable=R0921
"""Executes volume driver commands on Nexenta Appliance.

View File

@ -27,6 +27,7 @@ import six
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume import driver
from cinder.volume.drivers import remotefs
@ -63,6 +64,7 @@ CONF = cfg.CONF
CONF.register_opts(nfs_opts)
@interface.volumedriver
class NfsDriver(driver.ExtendVD, remotefs.RemoteFSDriver):
"""NFS based cinder driver.

View File

@ -33,6 +33,7 @@ from suds import client
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder.objects import volume
from cinder.volume.drivers.san import san
from cinder.volume import volume_types
@ -84,6 +85,7 @@ class NimbleAPIException(exception.VolumeBackendAPIException):
message = _("Unexpected response from Nimble API")
@interface.volumedriver
class NimbleISCSIDriver(san.SanISCSIDriver):
"""OpenStack driver to enable Nimble Controller.

View File

@ -19,6 +19,7 @@ from oslo_log import log as logging
from cinder import exception
from cinder.i18n import _, _LE, _LI
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.prophetstor import dplcommon
from cinder.zonemanager import utils as fczm_utils
@ -26,6 +27,7 @@ from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
@interface.volumedriver
class DPLFCDriver(dplcommon.DPLCOMMONDriver,
driver.FibreChannelDriver):
def __init__(self, *args, **kwargs):

View File

@ -19,12 +19,14 @@ from oslo_log import log as logging
from cinder import exception
from cinder.i18n import _, _LI, _LW
from cinder import interface
import cinder.volume.driver
from cinder.volume.drivers.prophetstor import dplcommon
LOG = logging.getLogger(__name__)
@interface.volumedriver
class DPLISCSIDriver(dplcommon.DPLCOMMONDriver,
cinder.volume.driver.ISCSIDriver):
def __init__(self, *args, **kwargs):

View File

@ -18,6 +18,7 @@ Volume driver for Pure Storage FlashArray storage system.
This driver requires Purity version 4.0.0 or later.
"""
import functools
import math
import platform
import re
@ -32,6 +33,7 @@ import six
from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder.objects import fields
from cinder import utils
from cinder.volume import driver
@ -119,6 +121,7 @@ def pure_driver_debug_trace(f):
This should only be used on VolumeDriver class methods. It depends on
having a 'self' argument that is a PureBaseVolumeDriver.
"""
@functools.wraps(f)
def wrapper(*args, **kwargs):
driver = args[0] # self
cls_name = driver.__class__.__name__
@ -1470,6 +1473,7 @@ class PureBaseVolumeDriver(san.SanDriver):
self._array = array
@interface.volumedriver
class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver):
VERSION = "4.0.0"
@ -1632,6 +1636,7 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver):
return connection
@interface.volumedriver
class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver):
VERSION = "2.0.0"

View File

@ -26,6 +26,7 @@ from cinder import compute
from cinder import exception
from cinder.i18n import _, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume.drivers import remotefs as remotefs_drv
@ -57,6 +58,7 @@ CONF = cfg.CONF
CONF.register_opts(volume_opts)
@interface.volumedriver
class QuobyteDriver(remotefs_drv.RemoteFSSnapDriver):
"""Cinder driver for Quobyte USP.

View File

@ -30,6 +30,7 @@ from six.moves import urllib
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume import driver
@ -261,6 +262,7 @@ class RADOSClient(object):
return int(features)
@interface.volumedriver
class RBDDriver(driver.TransferVD, driver.ExtendVD,
driver.CloneableImageVD, driver.SnapshotVD,
driver.MigrateVD, driver.ManageableVD, driver.BaseVD):

View File

@ -14,10 +14,12 @@
# under the License.
#
from cinder import interface
from cinder.volume.drivers.dothill import dothill_fc
from cinder.volume.drivers.san.hp import hpmsa_common
@interface.volumedriver
class HPMSAFCDriver(dothill_fc.DotHillFCDriver):
"""OpenStack Fibre Channel cinder drivers for HPMSA arrays.

View File

@ -14,10 +14,12 @@
# under the License.
#
from cinder import interface
from cinder.volume.drivers.dothill import dothill_iscsi
from cinder.volume.drivers.san.hp import hpmsa_common
@interface.volumedriver
class HPMSAISCSIDriver(dothill_iscsi.DotHillISCSIDriver):
"""OpenStack iSCSI cinder drivers for HPMSA arrays.

View File

@ -31,6 +31,7 @@ from six.moves import urllib
from cinder import exception
from cinder.i18n import _, _LI
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume.drivers import remotefs as remotefs_drv
from cinder.volume import utils as volume_utils
@ -53,6 +54,7 @@ CONF = cfg.CONF
CONF.register_opts(volume_opts)
@interface.volumedriver
class ScalityDriver(remotefs_drv.RemoteFSSnapDriver):
"""Scality SOFS cinder driver.

View File

@ -34,6 +34,7 @@ from oslo_utils import units
from cinder import exception
from cinder.i18n import _, _LE, _LW
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume import driver
@ -423,6 +424,7 @@ class SheepdogIOWrapper(io.RawIOBase):
raise IOError(_("fileno is not supported by SheepdogIOWrapper"))
@interface.volumedriver
class SheepdogDriver(driver.VolumeDriver):
"""Executes commands relating to Sheepdog Volumes."""

View File

@ -29,6 +29,7 @@ from oslo_utils import units
from cinder import exception
from cinder.i18n import _, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume.drivers import remotefs as remotefs_drv
@ -97,6 +98,7 @@ def update_allocation_data(delete=False):
return wrapper
@interface.volumedriver
class SmbfsDriver(remotefs_drv.RemoteFSSnapDriver):
"""SMBFS based cinder volume driver."""

View File

@ -35,6 +35,7 @@ from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LW
from cinder.image import image_utils
from cinder import interface
from cinder.objects import fields
from cinder.volume.drivers.san import san
from cinder.volume import qos_specs
@ -133,6 +134,7 @@ def retry(exc_tuple, tries=5, delay=1, backoff=2):
return retry_dec
@interface.volumedriver
class SolidFireDriver(san.SanISCSIDriver):
"""OpenStack driver to enable SolidFire cluster.

View File

@ -28,6 +28,7 @@ import six
from cinder import exception
from cinder import utils
from cinder.i18n import _, _LI, _LW
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.san import san
from cinder.volume import utils as volume_utils
@ -472,6 +473,7 @@ class TegileIntelliFlashVolumeDriver(san.SanDriver):
'set.') % {'attr': attr})
@interface.volumedriver
class TegileISCSIDriver(TegileIntelliFlashVolumeDriver, san.SanISCSIDriver):
"""Tegile ISCSI Driver."""
@ -584,6 +586,7 @@ class TegileISCSIDriver(TegileIntelliFlashVolumeDriver, san.SanISCSIDriver):
'provider_auth': provider_auth})
@interface.volumedriver
class TegileFCDriver(TegileIntelliFlashVolumeDriver,
driver.FibreChannelDriver):
"""Tegile FC driver."""

View File

@ -34,6 +34,7 @@ from cinder import exception
from cinder import utils
from cinder.i18n import _, _LE, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers import nfs
@ -65,6 +66,7 @@ CONF = cfg.CONF
CONF.register_opts(tintri_opts)
@interface.volumedriver
class TintriDriver(driver.ManageableVD,
driver.CloneableImageVD,
driver.SnapshotVD,

View File

@ -39,6 +39,7 @@ from oslo_log import log as logging
from cinder import exception
from cinder.i18n import _, _LE, _LI
from cinder import interface
from cinder import utils
from cinder.volume import driver
from cinder.volume.drivers.san import san
@ -50,6 +51,7 @@ import socket
LOG = logging.getLogger(__name__)
@interface.volumedriver
class V7000FCPDriver(driver.FibreChannelDriver):
"""Executes commands relating to fibre channel based Violin Memory arrays.

View File

@ -43,6 +43,7 @@ import six
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.vmware import datastore as hub
from cinder.volume.drivers.vmware import exceptions as vmdk_exceptions
@ -207,6 +208,7 @@ class ImageDiskType(object):
extra_spec_disk_type)
@interface.volumedriver
class VMwareVcVmdkDriver(driver.VolumeDriver):
"""Manage volumes on VMware vCenter server."""

View File

@ -27,6 +27,7 @@ from oslo_utils import units
from cinder import exception
from cinder.i18n import _, _LI
from cinder.image import image_utils
from cinder import interface
from cinder import utils
from cinder.volume.drivers import remotefs as remotefs_drv
@ -62,6 +63,7 @@ CONF = cfg.CONF
CONF.register_opts(vzstorage_opts)
@interface.volumedriver
class VZStorageDriver(remotefs_drv.RemoteFSSnapDriver):
"""Cinder driver for Virtuozzo Storage.

View File

@ -26,6 +26,7 @@ from oslo_utils import units
from cinder import exception
from cinder.i18n import _, _LI
from cinder.image import image_utils
from cinder import interface
from cinder.volume.drivers import remotefs as remotefs_drv
from cinder.volume.drivers import smbfs
from cinder.volume.drivers.windows import remotefs
@ -42,6 +43,7 @@ CONF.set_default('smbfs_mount_point_base', r'C:\OpenStack\_mnt')
CONF.set_default('smbfs_default_volume_format', 'vhd')
@interface.volumedriver
class WindowsSmbfsDriver(smbfs.SmbfsDriver):
VERSION = VERSION
_MINIMUM_QEMU_IMG_VERSION = '1.6'

View File

@ -23,6 +23,7 @@ from six.moves import urllib
from cinder import context
from cinder import exception
from cinder.i18n import _LE, _LI, _LW
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.san import san
from cinder.volume import qos_specs
@ -1380,6 +1381,7 @@ class XIOISEDriver(object):
# Protocol specific classes for entry. They are wrappers around base class
# above and every external API resuslts in a call to common function in base
# class.
@interface.volumedriver
class XIOISEISCSIDriver(driver.ISCSIDriver):
"""Requires ISE Running FW version 3.1.0 or higher"""
@ -1506,6 +1508,7 @@ class XIOISEISCSIDriver(driver.ISCSIDriver):
return self.driver.remove_export(context, volume)
@interface.volumedriver
class XIOISEFCDriver(driver.FibreChannelDriver):
"""Requires ISE Running FW version 2.8.0 or higher"""

View File

@ -28,6 +28,7 @@ from cinder import exception
from cinder import utils
from cinder.i18n import _, _LE, _LI, _LW
from cinder.image import image_utils
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.san import san
from cinder.volume.drivers.zfssa import zfssarest
@ -105,6 +106,7 @@ def factory_zfssa():
return zfssarest.ZFSSAApi()
@interface.volumedriver
class ZFSSAISCSIDriver(driver.ISCSIDriver):
"""ZFSSA Cinder iSCSI volume driver.
@ -224,10 +226,10 @@ class ZFSSAISCSIDriver(driver.ISCSIDriver):
# Parse interfaces
interfaces = []
for interface in lcfg.zfssa_target_interfaces.split(','):
if interface == '':
for intrface in lcfg.zfssa_target_interfaces.split(','):
if intrface == '':
continue
interfaces.append(interface)
interfaces.append(intrface)
# Setup target and target group
iqn = self.zfssa.create_target(

View File

@ -30,6 +30,7 @@ from cinder import exception
from cinder import utils
from cinder.i18n import _, _LE, _LI
from cinder.image import image_utils
from cinder import interface
from cinder.volume.drivers import nfs
from cinder.volume.drivers.san import san
from cinder.volume.drivers.zfssa import zfssarest
@ -76,6 +77,7 @@ def factory_zfssa():
return zfssarest.ZFSSANfsApi()
@interface.volumedriver
class ZFSSANFSDriver(nfs.NfsDriver):
"""ZFSSA Cinder NFS volume driver.

Some files were not shown because too many files have changed in this diff Show More