Created
June 1, 2016 15:32
-
-
Save patrick-east/52c8b3782ea4a578e3cac3c45d5d7182 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/cinder/db/api.py b/cinder/db/api.py | |
index 73a48cf..5fc5566 100644 | |
--- a/cinder/db/api.py | |
+++ b/cinder/db/api.py | |
@@ -1071,14 +1071,25 @@ def get_booleans_for_table(table_name): | |
################### | |
-def driver_initiator_data_update(context, initiator, namespace, updates): | |
- """Create DriverPrivateData from the values dictionary.""" | |
- return IMPL.driver_initiator_data_update(context, initiator, | |
- namespace, updates) | |
+def driver_initiator_data_set_by_key(context, initiator, namespace, key, | |
+ value, expected): | |
+ """Updates DriverInitiatorData entry. | |
+ | |
+ Sets the value for the specified key within the namespace. | |
+ | |
+ If expected values are provided a conditional update is done, if it fails | |
+ this will return false. | |
+ """ | |
+ return IMPL.driver_initiator_data_set_by_key(context, | |
+ initiator, | |
+ namespace, | |
+ key, | |
+ value, | |
+ expected) | |
def driver_initiator_data_get(context, initiator, namespace): | |
- """Query for an DriverPrivateData that has the specified key""" | |
+ """Query for an DriverInitiatorData that has the specified key""" | |
return IMPL.driver_initiator_data_get(context, initiator, namespace) | |
diff --git a/cinder/db/sqlalchemy/api.py b/cinder/db/sqlalchemy/api.py | |
index b1566ec..66d313b 100644 | |
--- a/cinder/db/sqlalchemy/api.py | |
+++ b/cinder/db/sqlalchemy/api.py | |
@@ -4346,35 +4346,33 @@ def message_destroy(context, message): | |
@require_context | |
-def driver_initiator_data_update(context, initiator, namespace, updates): | |
- session = get_session() | |
- with session.begin(): | |
- set_values = updates.get('set_values', {}) | |
- for key, value in set_values.items(): | |
- data = session.query(models.DriverInitiatorData).\ | |
- filter_by(initiator=initiator).\ | |
- filter_by(namespace=namespace).\ | |
- filter_by(key=key).\ | |
- first() | |
+def driver_initiator_data_set_by_key(context, initiator, namespace, | |
+ key, value, expected): | |
+ if expected is None: | |
+ expected_values = {} | |
+ else: | |
+ expected_values = expected.copy() | |
+ | |
+ expected_values.update({ | |
+ 'initiator': initiator, | |
+ 'namespace': namespace, | |
+ 'key': key, | |
+ }) | |
+ | |
+ result = _conditional_update(context, models.DriverInitiatorData, | |
+ {'value': value}, expected_values) | |
+ | |
+ # Didn't update anything, so add the new key | |
+ if 0 == result: | |
+ data = models.DriverInitiatorData() | |
+ data.initiator = initiator | |
+ data.namespace = namespace | |
+ data.key = key | |
+ data.value = value | |
+ session = get_session() | |
+ with session.begin(): | |
+ session.add(data) | |
- if data: | |
- data.update({'value': value}) | |
- data.save(session=session) | |
- else: | |
- data = models.DriverInitiatorData() | |
- data.initiator = initiator | |
- data.namespace = namespace | |
- data.key = key | |
- data.value = value | |
- session.add(data) | |
- | |
- remove_values = updates.get('remove_values', []) | |
- for key in remove_values: | |
- session.query(models.DriverInitiatorData).\ | |
- filter_by(initiator=initiator).\ | |
- filter_by(namespace=namespace).\ | |
- filter_by(key=key).\ | |
- delete() | |
@require_context | |
@@ -4590,9 +4588,17 @@ def _check_is_not_multitable(values, model): | |
@require_context | |
-@_retry_on_deadlock | |
def conditional_update(context, model, values, expected_values, filters=(), | |
include_deleted='no', project_only=False, order=None): | |
+ result = _conditional_update(context, model, values, expected_values, | |
+ filters, include_deleted, project_only, order) | |
+ # Return True if we were able to change any DB entry, False otherwise | |
+ return 0 != result | |
+ | |
+ | |
+@_retry_on_deadlock | |
+def _conditional_update(context, model, values, expected_values, filters=(), | |
+ include_deleted='no', project_only=False, order=None): | |
"""Compare-and-swap conditional update SQLAlchemy implementation.""" | |
_check_is_not_multitable(values, model) | |
@@ -4659,6 +4665,4 @@ def conditional_update(context, model, values, expected_values, filters=(), | |
# And we have to tell SQLAlchemy that we want to preserve the order | |
update_args['update_args'] = {'preserve_parameter_order': True} | |
- # Return True if we were able to change any DB entry, False otherwise | |
- result = query.update(values, **update_args) | |
- return 0 != result | |
+ return query.update(values, **update_args) | |
diff --git a/cinder/volume/driver_utils.py b/cinder/volume/driver_utils.py | |
index cc408f4..c851eb4 100644 | |
--- a/cinder/volume/driver_utils.py | |
+++ b/cinder/volume/driver_utils.py | |
@@ -48,12 +48,26 @@ class VolumeDriverUtils(object): | |
'namespace': self._data_namespace}) | |
raise | |
- def save_driver_initiator_data(self, initiator, model_update, ctxt=None): | |
+ def save_driver_initiator_data(self, initiator, key, value, | |
+ expected=None, ctxt=None): | |
+ """ Update the initiator data at key with value. | |
+ | |
+ If expected has been provided we will do a conditional update. If it | |
+ fails then this will return False. Otherwise return True. | |
+ | |
+ Expected should be a dictionary in the form of | |
+ {'value': expected_value}. This allows for an expected value of None | |
+ to be specified. Any fields other than 'value' are ignored. | |
+ """ | |
try: | |
- self._db.driver_initiator_data_update(self._get_context(ctxt), | |
- initiator, | |
- self._data_namespace, | |
- model_update) | |
+ return self._db.driver_initiator_data_set_by_key( | |
+ self._get_context(ctxt), | |
+ initiator, | |
+ self._data_namespace, | |
+ key, | |
+ value, | |
+ expected | |
+ ) | |
except exception.CinderException: | |
LOG.exception(_LE("Failed to update initiator data for" | |
" initiator %(initiator)s and backend" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment