From 19f6b7703663e12836fd6805e8c20b5507ede098 Mon Sep 17 00:00:00 2001 From: Lucian Petrut Date: Wed, 25 Mar 2015 18:01:02 +0200 Subject: [PATCH] Eager load volume extra specs The Linux SMBFS driver uses volume extra specs in order to determine the according image format when creating new volumes. Accessing the extra_specs attribute can raise DetachedInstanceError as this attribute is lazy loaded and the session might close by the time this attribute is accessed. This can be avoided by simply eager loading the volume extra specs. Change-Id: Iffdb160a4a968067261aa90638832782caed5ed0 Closes-Bug: #1436418 --- cinder/db/sqlalchemy/api.py | 2 ++ cinder/tests/test_db_api.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/cinder/db/sqlalchemy/api.py b/cinder/db/sqlalchemy/api.py index 5a88fccad..432f59c02 100644 --- a/cinder/db/sqlalchemy/api.py +++ b/cinder/db/sqlalchemy/api.py @@ -1232,6 +1232,7 @@ def _volume_get_query(context, session=None, project_only=False): options(joinedload('volume_metadata')).\ options(joinedload('volume_admin_metadata')).\ options(joinedload('volume_type')).\ + options(joinedload('volume_type.extra_specs')).\ options(joinedload('volume_attachment')).\ options(joinedload('consistencygroup')) else: @@ -1239,6 +1240,7 @@ def _volume_get_query(context, session=None, project_only=False): project_only=project_only).\ options(joinedload('volume_metadata')).\ options(joinedload('volume_type')).\ + options(joinedload('volume_type.extra_specs')).\ options(joinedload('volume_attachment')).\ options(joinedload('consistencygroup')) diff --git a/cinder/tests/test_db_api.py b/cinder/tests/test_db_api.py index eb3e2adc7..643721ecf 100644 --- a/cinder/tests/test_db_api.py +++ b/cinder/tests/test_db_api.py @@ -997,6 +997,25 @@ class DBAPIVolumeTypeTestCase(BaseTest): self.ctxt, {'name': 'n2', 'id': vt['id']}) + def test_get_volume_type_extra_specs(self): + # Ensure that volume type extra specs can be accessed after + # the DB session is closed. + vt_extra_specs = {'mock_key': 'mock_value'} + vt = db.volume_type_create(self.ctxt, + {'name': 'n1', + 'extra_specs': vt_extra_specs}) + volume_ref = db.volume_create(self.ctxt, {'volume_type_id': vt.id}) + + session = sqlalchemy_api.get_session() + volume = sqlalchemy_api._volume_get(self.ctxt, volume_ref.id, + session=session) + session.close() + + actual_specs = {} + for spec in volume.volume_type.extra_specs: + actual_specs[spec.key] = spec.value + self.assertEqual(vt_extra_specs, actual_specs) + class DBAPIEncryptionTestCase(BaseTest): -- 2.45.2