Skip to content

Instantly share code, notes, and snippets.

@patrick-east
Created May 5, 2016 23:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save patrick-east/afed6c0e68da1a11f1ab85f19a46cb34 to your computer and use it in GitHub Desktop.
Save patrick-east/afed6c0e68da1a11f1ab85f19a46cb34 to your computer and use it in GitHub Desktop.
diff --git a/cinder/volume/driver.py b/cinder/volume/driver.py
index 0da9e26..6e1f7a5 100644
--- a/cinder/volume/driver.py
+++ b/cinder/volume/driver.py
@@ -30,6 +30,7 @@ from cinder.i18n import _, _LE, _LW
from cinder.image import image_utils
from cinder import objects
from cinder import utils
+from cinder.volume import driver_utils
from cinder.volume import rpcapi as volume_rpcapi
from cinder.volume import throttling
@@ -316,6 +317,9 @@ class BaseVD(object):
self.configuration.append_config_values(iser_opts)
utils.setup_tracing(self.configuration.safe_get('trace_flags'))
+ self.driver_utils = driver_utils.VolumeDriverUtils(
+ self._driver_data_namespace(), self.db)
+
self._execute = execute
self._stats = {}
self._throttle = None
@@ -337,6 +341,11 @@ class BaseVD(object):
# set True by manager after successful check_for_setup
self._initialized = False
+ def _driver_data_namespace(self):
+ return (self.configuration.safe_get('driver_data_namespace') or
+ self.configuration.safe_get('volume_backend_name') or
+ self.__class__.__name__)
+
def _is_non_recoverable(self, err, non_recoverable_list):
for item in non_recoverable_list:
if item in err:
@@ -1486,26 +1495,13 @@ class BaseVD(object):
return
@abc.abstractmethod
- def initialize_connection(self, volume, connector, initiator_data=None):
+ def initialize_connection(self, volume, connector):
"""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 conn_info: 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.
+ :returns conn_info: A dictionary of connection information.
"""
return
diff --git a/cinder/volume/driver_utils.py b/cinder/volume/driver_utils.py
new file mode 100644
index 0000000..3cc634a
--- /dev/null
+++ b/cinder/volume/driver_utils.py
@@ -0,0 +1,65 @@
+# Copyright (c) 2014 Pure Storage, 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 six
+
+from oslo_log import log as logging
+
+from cinder import context
+from cinder import exception
+from cinder.i18n import _, _LE
+
+LOG = logging.getLogger(__name__)
+
+
+class VolumeDriverUtils(object):
+ def __init__(self, namespace, db):
+ self._data_namespace = namespace
+ self._db = db
+
+ @staticmethod
+ def _get_context(ctxt):
+ if not ctxt:
+ return context.get_admin_context()
+ return ctxt
+
+ def get_driver_initiator_data(self,initiator, ctxt=None):
+ try:
+ return self._db.driver_initiator_data_get(
+ self._get_context(ctxt),
+ initiator,
+ self._data_namespace
+ )
+ except exception.CinderException:
+ LOG.exception(_LE("Failed to get driver initiator data for"
+ " initiator %(initiator)s and namespace"
+ " %(namespace)s"),
+ {'initiator': initiator,
+ 'namespace': self._data_namespace})
+ raise
+
+ def save_driver_initiator_data(self, initiator, model_update, ctxt=None):
+ try:
+ self._db.driver_initiator_data_update(ctxt,
+ initiator,
+ self._data_namespace,
+ model_update)
+ except exception.CinderException:
+ LOG.exception(_LE("Failed to update initiator data for"
+ " initiator %(initiator)s and backend"
+ " %(backend)s"),
+ {'initiator': initiator,
+ 'backend': self._data_namespace})
+ raise
diff --git a/cinder/volume/drivers/pure.py b/cinder/volume/drivers/pure.py
index d6bbed9..a4496cb 100644
--- a/cinder/volume/drivers/pure.py
+++ b/cinder/volume/drivers/pure.py
@@ -408,7 +408,7 @@ class PureBaseVolumeDriver(san.SanDriver):
def create_export(self, context, volume, connector):
pass
- def initialize_connection(self, volume, connector, initiator_data=None):
+ def initialize_connection(self, volume, connector):
"""Connect the volume to the specified initiator in Purity.
This implementation is specific to the host type (iSCSI, FC, etc).
@@ -1493,9 +1493,9 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver):
return None
@pure_driver_debug_trace
- def initialize_connection(self, volume, connector, initiator_data=None):
+ def initialize_connection(self, volume, connector):
"""Allow connection to connector and return connection info."""
- connection = self._connect(volume, connector, initiator_data)
+ connection = self._connect(volume, connector)
target_ports = self._get_target_iscsi_ports()
multipath = connector.get("multipath", False)
@@ -1557,8 +1557,8 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver):
def _generate_chap_secret():
return volume_utils.generate_password()
- @classmethod
- def _get_chap_credentials(cls, host, data):
+ def _get_chap_credentials(self, host):
+ data = self.driver_utils.get_driver_initator_data(host)
initiator_updates = None
username = host
password = None
@@ -1568,22 +1568,25 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver):
password = d["value"]
break
if not password:
- password = cls._generate_chap_secret()
+ password = self._generate_chap_secret()
initiator_updates = {
"set_values": {
CHAP_SECRET_KEY: password
}
}
- return username, password, initiator_updates
+ if initiator_updates:
+ self.driver_utils.save_driver_initiator_data(host,
+ initiator_updates)
+ return username, password
@utils.synchronized(CONNECT_LOCK_NAME, external=True)
- def _connect(self, volume, connector, initiator_data):
+ def _connect(self, volume, connector):
"""Connect the host and volume; return dict describing connection."""
iqn = connector["initiator"]
if self.configuration.use_chap_auth:
- (chap_username, chap_password, initiator_update) = \
- self._get_chap_credentials(connector['host'], initiator_data)
+ (chap_username, chap_password) = \
+ self._get_chap_credentials(connector['host'])
current_array = self._get_current_array()
vol_name = self._get_vol_name(volume)
@@ -1663,7 +1666,7 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver):
@fczm_utils.AddFCZone
@pure_driver_debug_trace
- def initialize_connection(self, volume, connector, initiator_data=None):
+ def initialize_connection(self, volume, connector):
"""Allow connection to connector and return connection info."""
current_array = self._get_current_array()
connection = self._connect(volume, connector)
diff --git a/cinder/volume/drivers/solidfire.py b/cinder/volume/drivers/solidfire.py
index 4c93661..da771e4 100644
--- a/cinder/volume/drivers/solidfire.py
+++ b/cinder/volume/drivers/solidfire.py
@@ -1650,14 +1650,12 @@ class SolidFireDriver(san.SanISCSIDriver):
results['thinProvisioningPercent'])
self.cluster_stats = data
- def initialize_connection(self, volume, connector, initiator_data=None):
+ def initialize_connection(self, volume, connector):
"""Initialize the connection and return connection info.
Optionally checks and utilizes volume access groups.
"""
- properties = self._sf_initialize_connection(volume,
- connector,
- initiator_data)
+ properties = self._sf_initialize_connection(volume, connector)
properties['data']['discard'] = True
return properties
@@ -1979,8 +1977,7 @@ class SolidFireISCSI(iscsi_driver.SanISCSITarget):
def terminate_connection(self, volume, connector, **kwargs):
pass
- def _sf_initialize_connection(self, volume, connector,
- initiator_data=None):
+ def _sf_initialize_connection(self, volume, connector):
"""Initialize the connection and return connection info.
Optionally checks and utilizes volume access groups.
diff --git a/cinder/volume/manager.py b/cinder/volume/manager.py
index aaf9ef9..03844b1 100644
--- a/cinder/volume/manager.py
+++ b/cinder/volume/manager.py
@@ -1353,50 +1353,6 @@ class VolumeManager(manager.SchedulerDependentManager):
exc_info=True, resource={'type': 'image',
'id': image_id})
- def _driver_data_namespace(self):
- return self.driver.configuration.safe_get('driver_data_namespace') \
- or self.driver.configuration.safe_get('volume_backend_name') \
- or self.driver.__class__.__name__
-
- def _get_driver_initiator_data(self, context, connector):
- data = None
- initiator = connector.get('initiator', False)
- if initiator:
- if not isinstance(initiator, six.string_types):
- msg = _('Invalid initiator value received')
- raise exception.InvalidInput(reason=msg)
- namespace = self._driver_data_namespace()
- try:
- data = self.db.driver_initiator_data_get(
- context,
- initiator,
- namespace
- )
- except exception.CinderException:
- LOG.exception(_LE("Failed to get driver initiator data for"
- " initiator %(initiator)s and namespace"
- " %(namespace)s"),
- {'initiator': initiator,
- 'namespace': namespace})
- raise
- return data
-
- def _save_driver_initiator_data(self, context, connector, model_update):
- if connector.get('initiator', False) and model_update:
- namespace = self._driver_data_namespace()
- try:
- self.db.driver_initiator_data_update(context,
- connector['initiator'],
- namespace,
- model_update)
- except exception.CinderException:
- LOG.exception(_LE("Failed to update initiator data for"
- " initiator %(initiator)s and backend"
- " %(backend)s"),
- {'initiator': connector['initiator'],
- 'backend': namespace})
- raise
-
def initialize_connection(self, context, volume_id, connector):
"""Prepare volume for connection from host represented by connector.
@@ -1467,15 +1423,8 @@ class VolumeManager(manager.SchedulerDependentManager):
LOG.exception(_LE("Model update failed."), resource=volume)
raise exception.ExportFailure(reason=six.text_type(ex))
- initiator_data = self._get_driver_initiator_data(context, connector)
try:
- if initiator_data:
- conn_info = self.driver.initialize_connection(volume,
- connector,
- initiator_data)
- else:
- conn_info = self.driver.initialize_connection(volume,
- connector)
+ conn_info = self.driver.initialize_connection(volume, connector)
except Exception as err:
err_msg = (_("Driver initialize connection failed "
"(error: %(err)s).") % {'err': six.text_type(err)})
@@ -1485,12 +1434,6 @@ class VolumeManager(manager.SchedulerDependentManager):
raise exception.VolumeBackendAPIException(data=err_msg)
- initiator_update = conn_info.get('initiator_update', None)
- if initiator_update:
- self._save_driver_initiator_data(context, connector,
- initiator_update)
- del conn_info['initiator_update']
-
# Add qos_specs to connection info
typeid = volume['volume_type_id']
specs = None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment