Fix project assignment in VolumeType OVO

We have a problem with the assignment of the "project" field on the
VolumeType OVO class, because the DB queries return in some cases a list
of strings -for example in "volume_type_get" method- while on others
they return a VolumeTypeProjects SQLAlchemy model class.

The source of all this confussion is that some DB methods do not return
ORM instances but dictionaries with transformed data, which is something
that should never have been done in the first place.

This patch does not try to fix the underlying issue, just the incorrect
attribute assignment in the least intrussive way possible.

Change-Id: I0dd6b8ab2e726f69ceaaae886058e7a6181dded1
Closes-Bug: #1626704
This commit is contained in:
Gorka Eguileor 2016-09-22 21:37:20 +02:00
parent 4e2e29d1e5
commit d3ded36f7f
3 changed files with 30 additions and 2 deletions

View File

@ -14,6 +14,7 @@
from oslo_utils import versionutils
from oslo_versionedobjects import fields
import six
from cinder import db
from cinder import exception
@ -84,7 +85,13 @@ class VolumeType(base.CinderPersistentObject, base.CinderObject,
elif specs and isinstance(specs, dict):
type.extra_specs = specs
if 'projects' in expected_attrs:
type.projects = db_type.get('projects', [])
# NOTE(geguileo): Until projects stops being a polymorphic value we
# have to do a conversion here for VolumeTypeProjects ORM instance
# lists.
projects = db_type.get('projects', [])
if projects and not isinstance(projects[0], six.string_types):
projects = [p.project_id for p in projects]
type.projects = projects
if 'qos_specs' in expected_attrs:
qos_specs = objects.QualityOfServiceSpecs(context)
qos_specs._from_db_object(context, qos_specs, db_type['qos_specs'])

View File

@ -17,6 +17,7 @@ from oslo_utils import timeutils
import pytz
import six
from cinder.db.sqlalchemy import models
from cinder import objects
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_volume
@ -33,6 +34,26 @@ class TestVolumeType(test_objects.BaseObjectsTestCase):
fake.VOLUME_TYPE_ID)
self._compare(self, db_volume_type, volume_type)
@mock.patch('cinder.db.sqlalchemy.api._volume_type_get_full')
def test_get_by_id_with_projects(self, volume_type_get):
projects = [models.VolumeTypeProjects(project_id=fake.PROJECT_ID),
models.VolumeTypeProjects(project_id=fake.PROJECT2_ID)]
db_volume_type = fake_volume.fake_db_volume_type(projects=projects)
volume_type_get.return_value = db_volume_type
volume_type = objects.VolumeType.get_by_id(self.context,
fake.VOLUME_TYPE_ID)
db_volume_type['projects'] = [p.project_id for p in projects]
self._compare(self, db_volume_type, volume_type)
@mock.patch('cinder.db.sqlalchemy.api._volume_type_get_full')
def test_get_by_id_with_string_projects(self, volume_type_get):
projects = [fake.PROJECT_ID, fake.PROJECT2_ID]
db_volume_type = fake_volume.fake_db_volume_type(projects=projects)
volume_type_get.return_value = db_volume_type
volume_type = objects.VolumeType.get_by_id(self.context,
fake.VOLUME_TYPE_ID)
self._compare(self, db_volume_type, volume_type)
@mock.patch('cinder.db.sqlalchemy.api._volume_type_get_full')
def test_get_by_id_null_spec(self, volume_type_get):
db_volume_type = fake_volume.fake_db_volume_type(

View File

@ -51,7 +51,7 @@ def fake_db_get_vol_type(vol_type_number=1):
'description': 'desc',
'deleted': False,
'is_public': True,
'projects': None,
'projects': [],
'extra_specs': None}