db: Migrate "volume metadata" APIs to enginefacade

Migrate volume metadata-related APIs from the legacy enginefacade to the
modern context-based enginefacade.

Change-Id: I9ba5e935ff455da673312cd88cfc778e4cf6160b
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2022-02-15 10:51:20 +00:00
parent 4ffe3139cf
commit 0a4a235141

View File

@ -3376,14 +3376,14 @@ def volume_has_other_project_snp_filter():
#################### ####################
def _volume_x_metadata_get_query(context, volume_id, model, session=None): def _volume_x_metadata_get_query(context, volume_id, model):
return model_query(context, model, session=session, read_deleted="no").\ return model_query(context, model, read_deleted="no").filter_by(
filter_by(volume_id=volume_id) volume_id=volume_id
)
def _volume_x_metadata_get(context, volume_id, model, session=None): def _volume_x_metadata_get(context, volume_id, model):
rows = _volume_x_metadata_get_query(context, volume_id, model, rows = _volume_x_metadata_get_query(context, volume_id, model).all()
session=session).all()
result = {} result = {}
for row in rows: for row in rows:
result[row['key']] = row['value'] result[row['key']] = row['value']
@ -3391,12 +3391,12 @@ def _volume_x_metadata_get(context, volume_id, model, session=None):
return result return result
def _volume_x_metadata_get_item(context, volume_id, key, model, notfound_exec, def _volume_x_metadata_get_item(context, volume_id, key, model, notfound_exec):
session=None): result = (
result = _volume_x_metadata_get_query(context, volume_id, _volume_x_metadata_get_query(context, volume_id, model)
model, session=session).\ .filter_by(key=key)
filter_by(key=key).\ .first()
first() )
if not result: if not result:
if model is models.VolumeGlanceMetadata: if model is models.VolumeGlanceMetadata:
@ -3406,109 +3406,117 @@ def _volume_x_metadata_get_item(context, volume_id, key, model, notfound_exec,
return result return result
def _volume_x_metadata_update(context, volume_id, metadata, delete, model, # TODO: We dropped 'subtransactions=True' here. Is that an issue?
session=None, add=True, update=True): def _volume_x_metadata_update(
session = session or get_session() context, volume_id, metadata, delete, model, add=True, update=True
):
metadata = metadata.copy() metadata = metadata.copy()
with session.begin(subtransactions=True): # Set existing metadata to deleted if delete argument is True. This is
# Set existing metadata to deleted if delete argument is True. This is # committed immediately to the DB
# committed immediately to the DB if delete:
if delete: expected_values = {'volume_id': volume_id}
expected_values = {'volume_id': volume_id} # We don't want to delete keys we are going to update
# We don't want to delete keys we are going to update if metadata:
if metadata: expected_values['key'] = db.Not(metadata.keys())
expected_values['key'] = db.Not(metadata.keys()) conditional_update(
conditional_update(context, model, context,
{'deleted': True, model,
'deleted_at': timeutils.utcnow()}, {'deleted': True, 'deleted_at': timeutils.utcnow()},
expected_values) expected_values,
)
# Get existing metadata # Get existing metadata
db_meta = _volume_x_metadata_get_query(context, volume_id, model).all() db_meta = _volume_x_metadata_get_query(context, volume_id, model).all()
save = [] save = []
skip = [] skip = []
# We only want to send changed metadata. # We only want to send changed metadata.
for row in db_meta: for row in db_meta:
if row.key in metadata: if row.key in metadata:
value = metadata.pop(row.key) value = metadata.pop(row.key)
if row.value != value and update: if row.value != value and update:
# ORM objects will not be saved until we do the bulk save # ORM objects will not be saved until we do the bulk save
row.value = value row.value = value
save.append(row) save.append(row)
continue continue
skip.append(row) skip.append(row)
# We also want to save non-existent metadata # We also want to save non-existent metadata
if add: if add:
save.extend(model(key=key, value=value, volume_id=volume_id) save.extend(
for key, value in metadata.items()) model(key=key, value=value, volume_id=volume_id)
# Do a bulk save for key, value in metadata.items()
if save: )
session.bulk_save_objects(save, update_changed_only=True) # Do a bulk save
if save:
context.session.bulk_save_objects(save, update_changed_only=True)
# Construct result dictionary with current metadata # Construct result dictionary with current metadata
save.extend(skip) save.extend(skip)
result = {row['key']: row['value'] for row in save} result = {row['key']: row['value'] for row in save}
return result return result
def _volume_user_metadata_get_query(context, volume_id, session=None): def _volume_user_metadata_get_query(context, volume_id):
return _volume_x_metadata_get_query(context, volume_id, return _volume_x_metadata_get_query(
models.VolumeMetadata, session=session) context, volume_id, models.VolumeMetadata
)
def _volume_image_metadata_get_query(context, volume_id, session=None): def _volume_image_metadata_get_query(context, volume_id):
return _volume_x_metadata_get_query(context, volume_id, return _volume_x_metadata_get_query(
models.VolumeGlanceMetadata, context, volume_id, models.VolumeGlanceMetadata
session=session) )
@require_context @require_context
def _volume_user_metadata_get(context, volume_id, session=None): def _volume_user_metadata_get(context, volume_id):
return _volume_x_metadata_get(context, volume_id, return _volume_x_metadata_get(context, volume_id, models.VolumeMetadata)
models.VolumeMetadata, session=session)
@require_context @require_context
def _volume_user_metadata_get_item(context, volume_id, key, session=None): def _volume_user_metadata_get_item(context, volume_id, key):
return _volume_x_metadata_get_item(context, volume_id, key, return _volume_x_metadata_get_item(
models.VolumeMetadata, context,
exception.VolumeMetadataNotFound, volume_id,
session=session) key,
models.VolumeMetadata,
exception.VolumeMetadataNotFound,
)
@require_context @require_context
@require_volume_exists @require_volume_exists
def _volume_user_metadata_update(context, volume_id, metadata, delete, def _volume_user_metadata_update(context, volume_id, metadata, delete):
session=None): return _volume_x_metadata_update(
return _volume_x_metadata_update(context, volume_id, metadata, delete, context, volume_id, metadata, delete, models.VolumeMetadata
models.VolumeMetadata, )
session=session)
@require_context @require_context
@require_volume_exists @require_volume_exists
def _volume_image_metadata_update(context, volume_id, metadata, delete, def _volume_image_metadata_update(context, volume_id, metadata, delete):
session=None): return _volume_x_metadata_update(
return _volume_x_metadata_update(context, volume_id, metadata, delete, context, volume_id, metadata, delete, models.VolumeGlanceMetadata
models.VolumeGlanceMetadata, )
session=session)
@require_context @require_context
def _volume_glance_metadata_key_to_id(context, volume_id, key): def _volume_glance_metadata_key_to_id(context, volume_id, key):
db_data = volume_glance_metadata_get(context, volume_id) db_data = volume_glance_metadata_get(context, volume_id)
metadata = {meta_entry.key: meta_entry.id metadata = {
for meta_entry in db_data meta_entry.key: meta_entry.id
if meta_entry.key == key} for meta_entry in db_data
if meta_entry.key == key
}
metadata_id = metadata[key] metadata_id = metadata[key]
return metadata_id return metadata_id
@require_context @require_context
@require_volume_exists @require_volume_exists
@main_context_manager.reader
def volume_metadata_get(context, volume_id): def volume_metadata_get(context, volume_id):
return _volume_user_metadata_get(context, volume_id) return _volume_user_metadata_get(context, volume_id)
@ -3516,73 +3524,95 @@ def volume_metadata_get(context, volume_id):
@require_context @require_context
@require_volume_exists @require_volume_exists
@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True) @oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
@main_context_manager.writer
def volume_metadata_delete(context, volume_id, key, meta_type): def volume_metadata_delete(context, volume_id, key, meta_type):
if meta_type == common.METADATA_TYPES.user: if meta_type == common.METADATA_TYPES.user:
query = _volume_user_metadata_get_query(context, volume_id).\ query = _volume_user_metadata_get_query(context, volume_id).filter_by(
filter_by(key=key) key=key
)
entity = query.column_descriptions[0]['entity'] entity = query.column_descriptions[0]['entity']
query.update({'deleted': True, query.update(
'deleted_at': timeutils.utcnow(), {
'updated_at': entity.updated_at}) 'deleted': True,
'deleted_at': timeutils.utcnow(),
'updated_at': entity.updated_at,
}
)
elif meta_type == common.METADATA_TYPES.image: elif meta_type == common.METADATA_TYPES.image:
metadata_id = _volume_glance_metadata_key_to_id(context, metadata_id = _volume_glance_metadata_key_to_id(
volume_id, key) context, volume_id, key
query = _volume_image_metadata_get_query(context, volume_id).\ )
filter_by(id=metadata_id) query = _volume_image_metadata_get_query(context, volume_id).filter_by(
id=metadata_id
)
entity = query.column_descriptions[0]['entity'] entity = query.column_descriptions[0]['entity']
query.update({'deleted': True, query.update(
'deleted_at': timeutils.utcnow(), {
'updated_at': entity.updated_at}) 'deleted': True,
'deleted_at': timeutils.utcnow(),
'updated_at': entity.updated_at,
}
)
else: else:
raise exception.InvalidMetadataType(metadata_type=meta_type, raise exception.InvalidMetadataType(
id=volume_id) metadata_type=meta_type, id=volume_id
)
@require_context @require_context
@handle_db_data_error @handle_db_data_error
@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True) @oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
@main_context_manager.writer
def volume_metadata_update(context, volume_id, metadata, delete, meta_type): def volume_metadata_update(context, volume_id, metadata, delete, meta_type):
if meta_type == common.METADATA_TYPES.user: if meta_type == common.METADATA_TYPES.user:
return _volume_user_metadata_update(context, return _volume_user_metadata_update(
volume_id, context, volume_id, metadata, delete
metadata, )
delete)
elif meta_type == common.METADATA_TYPES.image: elif meta_type == common.METADATA_TYPES.image:
return _volume_image_metadata_update(context, return _volume_image_metadata_update(
volume_id, context, volume_id, metadata, delete
metadata, )
delete)
else: else:
raise exception.InvalidMetadataType(metadata_type=meta_type, raise exception.InvalidMetadataType(
id=volume_id) metadata_type=meta_type, id=volume_id
)
################### ###################
def _volume_admin_metadata_get_query(context, volume_id, session=None): def _volume_admin_metadata_get_query(context, volume_id):
return _volume_x_metadata_get_query(context, volume_id, return _volume_x_metadata_get_query(
models.VolumeAdminMetadata, context, volume_id, models.VolumeAdminMetadata
session=session) )
@require_admin_context @require_admin_context
@require_volume_exists @require_volume_exists
def _volume_admin_metadata_get(context, volume_id, session=None): def _volume_admin_metadata_get(context, volume_id):
return _volume_x_metadata_get(context, volume_id, return _volume_x_metadata_get(
models.VolumeAdminMetadata, session=session) context, volume_id, models.VolumeAdminMetadata
)
@require_admin_context @require_admin_context
@require_volume_exists @require_volume_exists
def _volume_admin_metadata_update(context, volume_id, metadata, delete, def _volume_admin_metadata_update(
session=None, add=True, update=True): context, volume_id, metadata, delete, add=True, update=True
return _volume_x_metadata_update(context, volume_id, metadata, delete, ):
models.VolumeAdminMetadata, return _volume_x_metadata_update(
session=session, add=add, update=update) context,
volume_id,
metadata,
delete,
models.VolumeAdminMetadata,
add=add,
update=update,
)
@require_admin_context @require_admin_context
@main_context_manager.reader
def volume_admin_metadata_get(context, volume_id): def volume_admin_metadata_get(context, volume_id):
return _volume_admin_metadata_get(context, volume_id) return _volume_admin_metadata_get(context, volume_id)
@ -3590,21 +3620,30 @@ def volume_admin_metadata_get(context, volume_id):
@require_admin_context @require_admin_context
@require_volume_exists @require_volume_exists
@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True) @oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
@main_context_manager.writer
def volume_admin_metadata_delete(context, volume_id, key): def volume_admin_metadata_delete(context, volume_id, key):
query = _volume_admin_metadata_get_query(context, volume_id).\ query = _volume_admin_metadata_get_query(context, volume_id).filter_by(
filter_by(key=key) key=key
)
entity = query.column_descriptions[0]['entity'] entity = query.column_descriptions[0]['entity']
query.update({'deleted': True, query.update(
'deleted_at': timeutils.utcnow(), {
'updated_at': entity.updated_at}) 'deleted': True,
'deleted_at': timeutils.utcnow(),
'updated_at': entity.updated_at,
}
)
@require_admin_context @require_admin_context
@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True) @oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
def volume_admin_metadata_update(context, volume_id, metadata, delete, @main_context_manager.writer
add=True, update=True): def volume_admin_metadata_update(
return _volume_admin_metadata_update(context, volume_id, metadata, delete, context, volume_id, metadata, delete, add=True, update=True
add=add, update=update) ):
return _volume_admin_metadata_update(
context, volume_id, metadata, delete, add=add, update=update
)
################### ###################