Use ovo instead of dict

Currently when Cinder calls volume.api.create(), it transfers
dict of volume type to the interface.

This patch is to get volume type object, and transfer it to
volume.api.create() interface. So that it uses object fields
instead of dict.

Change-Id: I981b5060abaff280aa34a9570c65300f467045d6
This commit is contained in:
lisali 2016-12-05 08:01:16 +00:00
parent a491f3e60f
commit 1794131293
9 changed files with 206 additions and 192 deletions

View File

@ -25,11 +25,11 @@ from webob import exc
from cinder.api import common from cinder.api import common
from cinder.api.openstack import wsgi from cinder.api.openstack import wsgi
from cinder.i18n import _, _LI from cinder.i18n import _, _LI
from cinder import objects
from cinder.objects import fields from cinder.objects import fields
from cinder import utils from cinder import utils
from cinder import volume as cinder_volume from cinder import volume as cinder_volume
from cinder.volume import utils as volume_utils from cinder.volume import utils as volume_utils
from cinder.volume import volume_types
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -229,7 +229,7 @@ class VolumeController(wsgi.Controller):
if req_volume_type: if req_volume_type:
# Not found exception will be handled at the wsgi level # Not found exception will be handled at the wsgi level
kwargs['volume_type'] = ( kwargs['volume_type'] = (
volume_types.get_by_name_or_id(context, req_volume_type)) objects.VolumeType.get_by_name_or_id(context, req_volume_type))
kwargs['metadata'] = volume.get('metadata', None) kwargs['metadata'] = volume.get('metadata', None)

View File

@ -30,10 +30,10 @@ from cinder import exception
from cinder import group as group_api from cinder import group as group_api
from cinder.i18n import _, _LI from cinder.i18n import _, _LI
from cinder.image import glance from cinder.image import glance
from cinder import objects
from cinder import utils from cinder import utils
from cinder import volume as cinder_volume from cinder import volume as cinder_volume
from cinder.volume import utils as volume_utils from cinder.volume import utils as volume_utils
from cinder.volume import volume_types
CONF = cfg.CONF CONF = cfg.CONF
@ -199,7 +199,7 @@ class VolumeController(wsgi.Controller):
if req_volume_type: if req_volume_type:
# Not found exception will be handled at the wsgi level # Not found exception will be handled at the wsgi level
kwargs['volume_type'] = ( kwargs['volume_type'] = (
volume_types.get_by_name_or_id(context, req_volume_type)) objects.VolumeType.get_by_name_or_id(context, req_volume_type))
kwargs['metadata'] = volume.get('metadata', None) kwargs['metadata'] = volume.get('metadata', None)

View File

@ -24,10 +24,10 @@ from cinder.api.v2 import volumes as volumes_v2
from cinder.api.v3.views import volumes as volume_views_v3 from cinder.api.v3.views import volumes as volume_views_v3
from cinder import exception from cinder import exception
from cinder import group as group_api from cinder import group as group_api
from cinder import objects
from cinder.i18n import _, _LI from cinder.i18n import _, _LI
import cinder.policy import cinder.policy
from cinder import utils from cinder import utils
from cinder.volume import volume_types
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -197,7 +197,7 @@ class VolumeController(volumes_v2.VolumeController):
if req_volume_type: if req_volume_type:
# Not found exception will be handled at the wsgi level # Not found exception will be handled at the wsgi level
kwargs['volume_type'] = ( kwargs['volume_type'] = (
volume_types.get_by_name_or_id(context, req_volume_type)) objects.VolumeType.get_by_name_or_id(context, req_volume_type))
kwargs['metadata'] = volume.get('metadata', None) kwargs['metadata'] = volume.get('metadata', None)

View File

@ -154,6 +154,13 @@ class VolumeType(base.CinderPersistentObject, base.CinderObject,
self.obj_reset_changes(fields=[attrname]) self.obj_reset_changes(fields=[attrname])
@classmethod
def get_by_name_or_id(cls, context, identity):
orm_obj = volume_types.get_by_name_or_id(context, identity)
expected_attrs = cls._get_expected_attrs(context)
return cls._from_db_object(context, cls(context),
orm_obj, expected_attrs=expected_attrs)
@base.CinderObjectRegistry.register @base.CinderObjectRegistry.register
class VolumeTypeList(base.ObjectListBase, base.CinderObject): class VolumeTypeList(base.ObjectListBase, base.CinderObject):

View File

@ -24,6 +24,7 @@ from cinder import quota
from cinder.tests.unit import conf_fixture from cinder.tests.unit import conf_fixture
from cinder.tests.unit import fake_constants as fake from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_snapshot from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
from cinder.tests.unit import utils as tests_utils from cinder.tests.unit import utils as tests_utils
from cinder.tests.unit import volume as base from cinder.tests.unit import volume as base
import cinder.volume import cinder.volume
@ -716,17 +717,16 @@ class ConsistencyGroupTestCase(base.BaseVolumeTestCase):
context.get_admin_context(), context.get_admin_context(),
dict(name=conf_fixture.def_vol_type, extra_specs={}) dict(name=conf_fixture.def_vol_type, extra_specs={})
) )
db_vol_type = db.volume_type_get(context.get_admin_context(), vol_type = objects.VolumeType.get_by_id(self.context,
vol_type.id) vol_type.id)
cg = { cg = objects.ConsistencyGroup(self.context,
'id': '1', id=fake.CONSISTENCY_GROUP_ID,
'name': 'cg1', name='cg1',
'volume_type_id': db_vol_type['id'], volume_type_id=vol_type.id)
} fake_type = fake_volume.fake_volume_type_obj(
fake_type = { self.context,
'id': '9999', id=fake.VOLUME_TYPE_ID,
'name': 'fake', name='fake')
}
vol_api = cinder.volume.api.API() vol_api = cinder.volume.api.API()
# Volume type must be provided when creating a volume in a # Volume type must be provided when creating a volume in a

View File

@ -28,6 +28,7 @@ from cinder import test
from cinder.tests.unit import conf_fixture from cinder.tests.unit import conf_fixture
from cinder.tests.unit import fake_constants as fake from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_snapshot from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
from cinder.tests.unit import utils as tests_utils from cinder.tests.unit import utils as tests_utils
from cinder.volume import api as volume_api from cinder.volume import api as volume_api
from cinder.volume import configuration as conf from cinder.volume import configuration as conf
@ -723,10 +724,10 @@ class GroupManagerTestCase(test.TestCase):
group_type_id=fake.GROUP_TYPE_ID, group_type_id=fake.GROUP_TYPE_ID,
host=CONF.host) host=CONF.host)
fake_type = { fake_type = fake_volume.fake_volume_type_obj(
'id': '9999', self.context,
'name': 'fake', id=fake.VOLUME_TYPE_ID,
} name='fake')
# Volume type must be provided when creating a volume in a # Volume type must be provided when creating a volume in a
# group. # group.

View File

@ -65,6 +65,14 @@ class TestVolumeType(test_objects.BaseObjectsTestCase):
fake.VOLUME_TYPE_ID) fake.VOLUME_TYPE_ID)
self._compare(self, db_volume_type, volume_type) self._compare(self, db_volume_type, volume_type)
@mock.patch('cinder.volume.volume_types.get_by_name_or_id')
def test_get_by_name_or_id(self, volume_type_get):
db_volume_type = fake_volume.fake_db_volume_type()
volume_type_get.return_value = db_volume_type
volume_type = objects.VolumeType.get_by_name_or_id(
self.context, fake.VOLUME_TYPE_ID)
self._compare(self, db_volume_type, volume_type)
@ddt.data('1.0', '1.1') @ddt.data('1.0', '1.1')
def test_obj_make_compatible(self, version): def test_obj_make_compatible(self, version):
volume_type = objects.VolumeType(context=self.context) volume_type = objects.VolumeType(context=self.context)

View File

@ -847,26 +847,31 @@ class VolumeTestCase(base.BaseVolumeTestCase):
"""Test volume create from snapshot with types including mistmatch.""" """Test volume create from snapshot with types including mistmatch."""
volume_api = cinder.volume.api.API() volume_api = cinder.volume.api.API()
db.volume_type_create( foo_type = fake_volume.fake_volume_type_obj(
context.get_admin_context(), self.context,
{'name': 'foo', id=fake.VOLUME_TYPE_ID,
'extra_specs': {'volume_backend_name': 'dev_1'}}) name='foo',
extra_specs={'volume_backend_name': 'dev_1'})
db.volume_type_create( biz_type = fake_volume.fake_volume_type_obj(
context.get_admin_context(), self.context,
{'name': 'biz', 'extra_specs': {'volume_backend_name': 'dev_2'}}) id=fake.VOLUME_TYPE2_ID,
name='foo',
foo_type = db.volume_type_get_by_name(context.get_admin_context(), extra_specs={'volume_backend_name': 'dev_2'})
'foo')
biz_type = db.volume_type_get_by_name(context.get_admin_context(),
'biz')
source_vol = fake_volume.fake_volume_obj(
self.context,
id=fake.VOLUME_ID,
status='available',
volume_size=10,
volume_type_id=biz_type.id)
source_vol.volume_type = biz_type
snapshot = {'id': fake.SNAPSHOT_ID, snapshot = {'id': fake.SNAPSHOT_ID,
'status': fields.SnapshotStatus.AVAILABLE, 'status': fields.SnapshotStatus.AVAILABLE,
'volume_size': 10, 'volume_size': 10,
'volume_type_id': biz_type['id']} 'volume_type_id': biz_type.id}
snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context, snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context,
**snapshot) **snapshot)
snapshot_obj.volume = source_vol
# Make sure the case of specifying a type that # Make sure the case of specifying a type that
# doesn't match the snapshots type fails # doesn't match the snapshots type fails
self.assertRaises(exception.InvalidInput, self.assertRaises(exception.InvalidInput,
@ -881,7 +886,9 @@ class VolumeTestCase(base.BaseVolumeTestCase):
# Make sure that trying to specify a type # Make sure that trying to specify a type
# when the snapshots type is None fails # when the snapshots type is None fails
snapshot_obj.volume_type_id = None snapshot_obj.volume_type_id = None
self.assertRaises(exception.InvalidVolumeType, snapshot_obj.volume.volume_type_id = None
snapshot_obj.volume.volume_type = None
self.assertRaises(exception.InvalidInput,
volume_api.create, volume_api.create,
self.context, self.context,
size=1, size=1,
@ -890,43 +897,36 @@ class VolumeTestCase(base.BaseVolumeTestCase):
volume_type=foo_type, volume_type=foo_type,
snapshot=snapshot_obj) snapshot=snapshot_obj)
with mock.patch.object(cinder.volume.volume_types, snapshot_obj.volume_type_id = foo_type.id
'get_volume_type') as mock_get_type: snapshot_obj.volume.volume_type_id = foo_type.id
mock_get_type.return_value = biz_type snapshot_obj.volume.volume_type = foo_type
snapshot_obj.volume_type_id = foo_type['id'] volume_api.create(self.context, size=1, name='fake_name',
volume_api.create(self.context, size=1, name='fake_name', description='fake_desc', volume_type=foo_type,
description='fake_desc', volume_type=foo_type, snapshot=snapshot_obj)
snapshot=snapshot_obj)
db.volume_type_destroy(context.get_admin_context(),
foo_type['id'])
db.volume_type_destroy(context.get_admin_context(),
biz_type['id'])
@mock.patch('cinder.volume.flows.api.create_volume.get_flow') @mock.patch('cinder.volume.flows.api.create_volume.get_flow')
def test_create_volume_from_source_with_types(self, _get_flow): def test_create_volume_from_source_with_types(self, _get_flow):
"""Test volume create from source with types including mistmatch.""" """Test volume create from source with types including mistmatch."""
volume_api = cinder.volume.api.API() volume_api = cinder.volume.api.API()
foo_type = fake_volume.fake_volume_type_obj(
self.context,
id=fake.VOLUME_TYPE_ID,
name='foo',
extra_specs={'volume_backend_name': 'dev_1'})
db.volume_type_create( biz_type = fake_volume.fake_volume_type_obj(
context.get_admin_context(), self.context,
{'name': 'foo', id=fake.VOLUME_TYPE2_ID,
'extra_specs': {'volume_backend_name': 'dev_1'}}) name='biz',
extra_specs={'volume_backend_name': 'dev_2'})
db.volume_type_create( source_vol = fake_volume.fake_volume_obj(
context.get_admin_context(), self.context,
{'name': 'biz', 'extra_specs': {'volume_backend_name': 'dev_2'}}) id=fake.VOLUME_ID,
status='available',
foo_type = db.volume_type_get_by_name(context.get_admin_context(), volume_size=0,
'foo') volume_type_id=biz_type.id)
biz_type = db.volume_type_get_by_name(context.get_admin_context(), source_vol.volume_type = biz_type
'biz')
source_vol = {'id': fake.VOLUME_ID,
'status': 'available',
'volume_size': 10,
'volume_type': biz_type,
'volume_type_id': biz_type['id']}
self.assertRaises(exception.InvalidInput, self.assertRaises(exception.InvalidInput,
volume_api.create, volume_api.create,
@ -939,9 +939,9 @@ class VolumeTestCase(base.BaseVolumeTestCase):
# Make sure that trying to specify a type # Make sure that trying to specify a type
# when the source type is None fails # when the source type is None fails
source_vol['volume_type_id'] = None source_vol.volume_type_id = None
source_vol['volume_type'] = None source_vol.volume_type = None
self.assertRaises(exception.InvalidVolumeType, self.assertRaises(exception.InvalidInput,
volume_api.create, volume_api.create,
self.context, self.context,
size=1, size=1,
@ -950,99 +950,95 @@ class VolumeTestCase(base.BaseVolumeTestCase):
volume_type=foo_type, volume_type=foo_type,
source_volume=source_vol) source_volume=source_vol)
with mock.patch.object(cinder.volume.volume_types, source_vol.volume_type_id = biz_type.id
'get_volume_type') as mock_get_type: source_vol.volume_type = biz_type
mock_get_type.return_value = biz_type volume_api.create(self.context, size=1, name='fake_name',
source_vol['volume_type_id'] = biz_type['id'] description='fake_desc', volume_type=biz_type,
source_vol['volume_type'] = biz_type source_volume=source_vol)
volume_api.create(self.context, size=1, name='fake_name',
description='fake_desc', volume_type=biz_type,
source_volume=source_vol)
db.volume_type_destroy(context.get_admin_context(),
foo_type['id'])
db.volume_type_destroy(context.get_admin_context(),
biz_type['id'])
@mock.patch('cinder.volume.flows.api.create_volume.get_flow') @mock.patch('cinder.volume.flows.api.create_volume.get_flow')
def test_create_volume_from_source_with_same_backend(self, _get_flow): def test_create_volume_from_source_with_same_backend(self, _get_flow):
"""Test volume create from source with type mismatch same backend.""" """Test volume create from source with type mismatch same backend."""
volume_api = cinder.volume.api.API() volume_api = cinder.volume.api.API()
foo_type = { foo_type = fake_volume.fake_volume_type_obj(
'name': 'foo', self.context,
'qos_specs_id': None, id=fake.VOLUME_TYPE_ID,
'deleted': False, name='foo',
'created_at': datetime.datetime(2015, 5, 8, 0, 40, 5, 408232), qos_specs_id=None,
'updated_at': None, deleted=False,
'extra_specs': {'volume_backend_name': 'dev_1'}, created_at=datetime.datetime(2015, 5, 8, 0, 40, 5, 408232),
'is_public': True, updated_at=None,
'deleted_at': None, extra_specs={'volume_backend_name': 'dev_1'},
'id': '29e43b50-2cd7-4d0c-8ddd-2119daab3a38', is_public=True,
'description': None} deleted_at=None,
description=None)
biz_type = { biz_type = fake_volume.fake_volume_type_obj(
'name': 'biz', self.context,
'qos_specs_id': None, id=fake.VOLUME_TYPE2_ID,
'deleted': False, name='biz',
'created_at': datetime.datetime(2015, 5, 8, 0, 20, 5, 408232), qos_specs_id=None,
'updated_at': None, deleted=False,
'extra_specs': {'volume_backend_name': 'dev_1'}, created_at=datetime.datetime(2015, 5, 8, 0, 20, 5, 408232),
'is_public': True, updated_at=None,
'deleted_at': None, extra_specs={'volume_backend_name': 'dev_1'},
'id': '34e54c31-3bc8-5c1d-9fff-2225bcce4b59', is_public=True,
'description': None} deleted_at=None,
description=None)
source_vol = {'id': fake.VOLUME_ID, source_vol = fake_volume.fake_volume_obj(
'status': 'available', self.context,
'volume_size': 10, id=fake.VOLUME_ID,
'volume_type': biz_type, status='available',
'volume_type_id': biz_type['id']} volume_size=10,
volume_type_id=biz_type.id)
with mock.patch.object(cinder.volume.volume_types, source_vol.volume_type = biz_type
'get_volume_type') as mock_get_type: volume_api.create(self.context,
mock_get_type.return_value = biz_type size=1,
volume_api.create(self.context, name='fake_name',
size=1, description='fake_desc',
name='fake_name', volume_type=foo_type,
description='fake_desc', source_volume=source_vol)
volume_type=foo_type,
source_volume=source_vol)
@mock.patch('cinder.volume.flows.api.create_volume.get_flow') @mock.patch('cinder.volume.flows.api.create_volume.get_flow')
def test_create_from_source_and_snap_only_one_backend(self, _get_flow): def test_create_from_source_and_snap_only_one_backend(self, _get_flow):
"""Test create from source and snap with type mismatch one backend.""" """Test create from source and snap with type mismatch one backend."""
volume_api = cinder.volume.api.API() volume_api = cinder.volume.api.API()
foo_type = { foo_type = fake_volume.fake_volume_type_obj(
'name': 'foo', self.context,
'qos_specs_id': None, id=fake.VOLUME_TYPE_ID,
'deleted': False, name='foo',
'created_at': datetime.datetime(2015, 5, 8, 0, 40, 5, 408232), qos_specs_id=None,
'updated_at': None, deleted=False,
'extra_specs': {'some_key': 3}, created_at=datetime.datetime(2015, 5, 8, 0, 40, 5, 408232),
'is_public': True, updated_at=None,
'deleted_at': None, extra_specs={'some_key': 3},
'id': '29e43b50-2cd7-4d0c-8ddd-2119daab3a38', is_public=True,
'description': None} deleted_at=None,
description=None)
biz_type = { biz_type = fake_volume.fake_volume_type_obj(
'name': 'biz', self.context,
'qos_specs_id': None, id=fake.VOLUME_TYPE2_ID,
'deleted': False, name='biz',
'created_at': datetime.datetime(2015, 5, 8, 0, 20, 5, 408232), qos_specs_id=None,
'updated_at': None, deleted=False,
'extra_specs': {'some_other_key': 4}, created_at=datetime.datetime(2015, 5, 8, 0, 20, 5, 408232),
'is_public': True, updated_at=None,
'deleted_at': None, extra_specs={'some_other_key': 4},
'id': '34e54c31-3bc8-5c1d-9fff-2225bcce4b59', is_public=True,
'description': None} deleted_at=None,
description=None)
source_vol = {'id': fake.VOLUME_ID, source_vol = fake_volume.fake_volume_obj(
'status': 'available', self.context,
'volume_size': 10, id=fake.VOLUME_ID,
'volume_type': biz_type, status='available',
'volume_type_id': biz_type['id']} volume_size=10,
volume_type_id=biz_type.id)
source_vol.volume_type = biz_type
snapshot = {'id': fake.SNAPSHOT_ID, snapshot = {'id': fake.SNAPSHOT_ID,
'status': fields.SnapshotStatus.AVAILABLE, 'status': fields.SnapshotStatus.AVAILABLE,
@ -1050,6 +1046,7 @@ class VolumeTestCase(base.BaseVolumeTestCase):
'volume_type_id': biz_type['id']} 'volume_type_id': biz_type['id']}
snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context, snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context,
**snapshot) **snapshot)
snapshot_obj.volume = source_vol
with mock.patch('cinder.db.service_get_all') as mock_get_service, \ with mock.patch('cinder.db.service_get_all') as mock_get_service, \
mock.patch.object(volume_api, mock.patch.object(volume_api,
@ -1073,22 +1070,24 @@ class VolumeTestCase(base.BaseVolumeTestCase):
def _test_create_from_source_snapshot_encryptions( def _test_create_from_source_snapshot_encryptions(
self, is_snapshot=False): self, is_snapshot=False):
volume_api = cinder.volume.api.API() volume_api = cinder.volume.api.API()
foo_type = { foo_type = fake_volume.fake_volume_type_obj(
'name': 'foo', self.context,
'extra_specs': {'volume_backend_name': 'dev_1'}, id=fake.VOLUME_TYPE_ID,
'id': fake.VOLUME_TYPE_ID, name='foo',
'description': None} extra_specs={'volume_backend_name': 'dev_1'})
biz_type = fake_volume.fake_volume_type_obj(
self.context,
id=fake.VOLUME_TYPE2_ID,
name='biz',
extra_specs={'volume_backend_name': 'dev_1'})
biz_type = { source_vol = fake_volume.fake_volume_obj(
'name': 'foo', self.context,
'extra_specs': {'volume_backend_name': 'dev_1'}, id=fake.VOLUME_ID,
'id': fake.VOLUME_TYPE2_ID, status='available',
'description': None} volume_size=1,
source_vol = {'id': fake.VOLUME_ID, volume_type_id=biz_type.id)
'status': 'available', source_vol.volume_type = biz_type
'volume_size': 1,
'volume_type': biz_type,
'volume_type_id': biz_type['id']}
snapshot = {'id': fake.SNAPSHOT_ID, snapshot = {'id': fake.SNAPSHOT_ID,
'status': fields.SnapshotStatus.AVAILABLE, 'status': fields.SnapshotStatus.AVAILABLE,
@ -1096,6 +1095,7 @@ class VolumeTestCase(base.BaseVolumeTestCase):
'volume_type_id': biz_type['id']} 'volume_type_id': biz_type['id']}
snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context, snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context,
**snapshot) **snapshot)
snapshot_obj.volume = source_vol
with mock.patch.object( with mock.patch.object(
cinder.volume.volume_types, cinder.volume.volume_types,

View File

@ -174,31 +174,34 @@ class API(base.Base):
return tuple(azs) return tuple(azs)
def _retype_is_possible(self, context, def _retype_is_possible(self, context,
source_type_id, target_type_id): source_type, target_type):
safe = False
elevated = context.elevated() elevated = context.elevated()
# If encryptions are different, it is not allowed # If encryptions are different, it is not allowed
# to create volume from source volume or snapshot. # to create volume from source volume or snapshot.
if volume_types.volume_types_encryption_changed( if volume_types.volume_types_encryption_changed(
elevated, source_type_id, target_type_id): elevated,
source_type.id if source_type else None,
target_type.id if target_type else None):
return False return False
services = objects.ServiceList.get_all_by_topic( services = objects.ServiceList.get_all_by_topic(
elevated, elevated,
constants.VOLUME_TOPIC, constants.VOLUME_TOPIC,
disabled=True) disabled=True)
if len(services.objects) == 1: if len(services.objects) == 1:
safe = True return True
else:
source_type = volume_types.get_volume_type( source_extra_specs = {}
elevated, if source_type:
source_type_id) with source_type.obj_as_admin():
target_type = volume_types.get_volume_type( source_extra_specs = source_type.extra_specs
elevated, target_extra_specs = {}
target_type_id) if target_type:
if (volume_utils.matching_backend_name( with target_type.obj_as_admin():
source_type['extra_specs'], target_type['extra_specs'])): target_extra_specs = target_type.extra_specs
safe = True if (volume_utils.matching_backend_name(
return safe source_extra_specs, target_extra_specs)):
return True
return False
def _is_volume_migrating(self, volume): def _is_volume_migrating(self, volume):
# The migration status 'none' means no migration has ever been done # The migration status 'none' means no migration has ever been done
@ -242,8 +245,8 @@ class API(base.Base):
msg = _("volume_type must be provided when creating " msg = _("volume_type must be provided when creating "
"a volume in a consistency group.") "a volume in a consistency group.")
raise exception.InvalidInput(reason=msg) raise exception.InvalidInput(reason=msg)
cg_voltypeids = consistencygroup.get('volume_type_id') cg_voltypeids = consistencygroup.volume_type_id
if volume_type.get('id') not in cg_voltypeids: if volume_type.id not in cg_voltypeids:
msg = _("Invalid volume_type provided: %s (requested " msg = _("Invalid volume_type provided: %s (requested "
"type must be supported by this consistency " "type must be supported by this consistency "
"group).") % volume_type "group).") % volume_type
@ -255,26 +258,21 @@ class API(base.Base):
"a volume in a group.") "a volume in a group.")
raise exception.InvalidInput(reason=msg) raise exception.InvalidInput(reason=msg)
vol_type_ids = [v_type.id for v_type in group.volume_types] vol_type_ids = [v_type.id for v_type in group.volume_types]
if volume_type.get('id') not in vol_type_ids: if volume_type.id not in vol_type_ids:
msg = _("Invalid volume_type provided: %s (requested " msg = _("Invalid volume_type provided: %s (requested "
"type must be supported by this " "type must be supported by this "
"group).") % volume_type "group).") % volume_type
raise exception.InvalidInput(reason=msg) raise exception.InvalidInput(reason=msg)
if volume_type and 'extra_specs' not in volume_type:
extra_specs = volume_types.get_volume_type_extra_specs(
volume_type['id'])
volume_type['extra_specs'] = extra_specs
if source_volume and volume_type: if source_volume and volume_type:
if volume_type['id'] != source_volume['volume_type_id']: if volume_type.id != source_volume.volume_type_id:
if not self._retype_is_possible( if not self._retype_is_possible(
context, context,
source_volume['volume_type_id'], source_volume.volume_type,
volume_type['id']): volume_type):
msg = _("Invalid volume_type provided: %s (requested type " msg = _("Invalid volume_type provided: %s (requested type "
"is not compatible; either match source volume, " "is not compatible; either match source volume, "
"or omit type argument).") % volume_type['id'] "or omit type argument).") % volume_type.id
raise exception.InvalidInput(reason=msg) raise exception.InvalidInput(reason=msg)
# When cloning replica (for testing), volume type must be omitted # When cloning replica (for testing), volume type must be omitted
@ -284,13 +282,13 @@ class API(base.Base):
raise exception.InvalidInput(reason=msg) raise exception.InvalidInput(reason=msg)
if snapshot and volume_type: if snapshot and volume_type:
if volume_type['id'] != snapshot.volume_type_id: if volume_type.id != snapshot.volume_type_id:
if not self._retype_is_possible(context, if not self._retype_is_possible(context,
snapshot.volume_type_id, snapshot.volume.volume_type,
volume_type['id']): volume_type):
msg = _("Invalid volume_type provided: %s (requested " msg = _("Invalid volume_type provided: %s (requested "
"type is not compatible; recommend omitting " "type is not compatible; recommend omitting "
"the type argument).") % volume_type['id'] "the type argument).") % volume_type.id
raise exception.InvalidInput(reason=msg) raise exception.InvalidInput(reason=msg)
# Determine the valid availability zones that the volume could be # Determine the valid availability zones that the volume could be