Untyped to Default Volume Type

The patch adds the following functionality:
* A default volume type (``__DEFAULT__``) will be
  created during cinder DB migration.
* Admins can override the default type in cinder.conf
* Creating a new volume without any type (and
  `default_volume_type` option is unset in cinder.conf)
  will be assigned the ``__DEFAULT__`` type.
* The default volume type cannot be deleted
* All untyped volumes and snapshots will be migrated to the
  ``__DEFAULT__`` type.

Change-Id: I4da0c13b5b3f8174a30b8557f968d6b9e641b091
Implements: blueprint untyped-volumes-default-volume-type
This commit is contained in:
whoami-rajat 2019-02-26 00:33:34 +05:30 committed by Rajat Dhasmana
parent b1de0652ca
commit a550ade303
76 changed files with 1188 additions and 496 deletions

View File

@ -1,26 +1,35 @@
{
"volume_types": [
{
"description": "volume type 0002",
"extra_specs": {
"capabilities": "gpu"
},
"id": "ef512777-6552-4013-82f0-57a96e5804b7",
"is_public": true,
"name": "vol-type-002",
"os-volume-type-access:is_public": true,
"qos_specs_id": null
},
{
"description": "volume type 0001",
"extra_specs": {
"capabilities": "gpu"
},
"id": "6685584b-1eac-4da6-b5c3-555430cf68ff",
"id": "18947ff2-ad57-42b2-9350-34262e530203",
"is_public": true,
"name": "vol-type-001",
"os-volume-type-access:is_public": true,
"qos_specs_id": null
},
{
"description": "volume type 0002",
"extra_specs": {
"capabilities": "gpu"
},
"id": "6685584b-1eac-4da6-b5c3-555430cf68ff",
"description": "Default Volume Type",
"extra_specs": {},
"id": "7a56b996-b73f-4233-9f00-dd6a68b49b27",
"is_public": true,
"name": "vol-type-002",
"name": "__DEFAULT__",
"os-volume-type-access:is_public": true,
"qos_specs_id": null
}
]
}
}

View File

@ -29,6 +29,6 @@
"status": "creating",
"updated_at": null,
"user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
"volume_type": null
"volume_type": "__DEFAULT__"
}
}

View File

@ -33,6 +33,6 @@
"status": "creating",
"updated_at": null,
"user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
"volume_type": null
"volume_type": "__DEFAULT__"
}
}

View File

@ -31,6 +31,6 @@
"status": "creating",
"updated_at": null,
"user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
"volume_type": null
"volume_type": "__DEFAULT__"
}
}

View File

@ -34,7 +34,7 @@
"status": "creating",
"updated_at": null,
"user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
"volume_type": null
"volume_type": "__DEFAULT__"
}
]
}

View File

@ -158,6 +158,11 @@ class VolumeTypesManageController(wsgi.Controller):
context, 'volume_type.delete', err, id=id)
# Not found exception will be handled at the wsgi level
raise
except exception.VolumeTypeDefault as err:
self._notify_volume_type_error(
context, 'volume_type.delete', err, volume_type=vol_type)
msg = _('Target volume type is default and cannot be deleted.')
raise webob.exc.HTTPBadRequest(explanation=msg)
return webob.Response(status_int=http_client.ACCEPTED)

View File

@ -39,6 +39,7 @@ from cinder.image import glance
from cinder import objects
from cinder import utils
from cinder import volume as cinder_volume
from cinder.volume import volume_types
from cinder.volume import volume_utils
CONF = cfg.CONF
@ -213,6 +214,11 @@ class VolumeController(wsgi.Controller):
# Not found exception will be handled at the wsgi level
kwargs['volume_type'] = (
objects.VolumeType.get_by_name_or_id(context, req_volume_type))
else:
kwargs['volume_type'] = (
objects.VolumeType.get_by_name_or_id(
context,
volume_types.get_default_volume_type()['id']))
kwargs['metadata'] = volume.get('metadata', None)

View File

@ -37,6 +37,7 @@ from cinder.image import glance
from cinder import objects
from cinder.policies import volumes as policy
from cinder import utils
from cinder.volume import volume_types
LOG = logging.getLogger(__name__)
@ -285,6 +286,11 @@ class VolumeController(volumes_v2.VolumeController):
# Not found exception will be handled at the wsgi level
kwargs['volume_type'] = (
objects.VolumeType.get_by_name_or_id(context, req_volume_type))
else:
kwargs['volume_type'] = (
objects.VolumeType.get_by_name_or_id(
context,
volume_types.get_default_volume_type()['id']))
kwargs['metadata'] = volume.get('metadata', None)

View File

@ -250,7 +250,11 @@ class DbCommands(object):
# preceed any element of the "online_migrations" tuple, like this:
# # Added in Queens remove in Rocky
# db.service_uuids_online_data_migration,
online_migrations = tuple(
online_migrations = (
# Added in Train
db.untyped_volumes_online_data_migration,
# Added in Train
db.untyped_snapshots_online_data_migration
)
def __init__(self):

View File

@ -429,6 +429,13 @@ def volume_has_other_project_snp_filter():
return IMPL.volume_has_other_project_snp_filter()
def untyped_volumes_online_data_migration(context, max_count):
return IMPL.untyped_volumes_online_data_migration(context, max_count)
def untyped_snapshots_online_data_migration(context, max_count):
return IMPL.untyped_snapshots_online_data_migration(context, max_count)
####################

View File

@ -569,6 +569,53 @@ def service_update(context, service_id, values):
raise exception.ServiceNotFound(service_id=service_id)
@enginefacade.writer
def untyped_volumes_online_data_migration(context, max_count):
from cinder.volume import volume_types
default_type = volume_types.get_default_volume_type()
# get all volumes having volume_type=None
total = 0
updated = 0
session = get_session()
with session.begin():
total = model_query(context,
models.Volume,
session=session).filter_by(
volume_type_id=None).limit(max_count).count()
volumes = model_query(context,
models.Volume,
session=session).filter_by(
volume_type_id=None).limit(max_count).all()
for volume in volumes:
volume.volume_type_id = default_type.get('id')
updated += 1
return total, updated
@enginefacade.writer
def untyped_snapshots_online_data_migration(context, max_count):
from cinder.volume import volume_types
default_type = volume_types.get_default_volume_type()
# get all snapshots having volume_type=None
total = 0
updated = 0
session = get_session()
with session.begin():
total = model_query(context,
models.Snapshot,
session=session).filter_by(
volume_type_id=None).limit(max_count).count()
snapshots = model_query(context,
models.Snapshot,
session=session).filter_by(
volume_type_id=None).limit(max_count).all()
for snapshot in snapshots:
snapshot.volume_type_id = default_type.get('id')
updated += 1
return total, updated
###################

View File

@ -0,0 +1,45 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import uuid
from oslo_utils import timeutils
import six
from sqlalchemy import MetaData, Table
from cinder.volume import volume_types
def upgrade(migrate_engine):
"""Create default volume type"""
meta = MetaData(bind=migrate_engine)
now = timeutils.utcnow()
# create a default volume type during cinder DB migration
vtypes = Table("volume_types", meta, autoload=True)
results = list(vtypes.select().where(
vtypes.c.name == volume_types.DEFAULT_VOLUME_TYPE and
vtypes.c.deleted is False).execute())
if not results:
vtype_id = six.text_type(uuid.uuid4())
volume_type_dict = {
'id': vtype_id,
'name': volume_types.DEFAULT_VOLUME_TYPE,
'description': 'Default Volume Type',
'created_at': now,
'updated_at': now,
'deleted': False,
'is_public': True,
}
vtype = vtypes.insert()
vtype.execute(volume_type_dict)

View File

@ -391,6 +391,11 @@ class VolumeTypeInUse(CinderException):
"volumes present with the type.")
class VolumeTypeDefault(CinderException):
message = _("The volume type %(volume_type_name)s "
"is the default volume type and cannot be deleted.")
class GroupTypeNotFound(NotFound):
message = _("Group type %(group_type_id)s could not be found.")

View File

@ -23,6 +23,7 @@ from cinder import objects
from cinder.objects import base
from cinder.objects import cleanable
from cinder.objects import fields as c_fields
from cinder.volume import volume_types
CONF = cfg.CONF
@ -191,6 +192,10 @@ class Snapshot(cleanable.CinderCleanableObject, base.CinderObject,
raise exception.ObjectActionError(
action='create',
reason=_('group_snapshot assigned'))
if ('volume_type_id' not in updates or
updates['volume_type_id'] is None):
updates['volume_type_id'] = (
volume_types.get_default_volume_type()['id'])
db_snapshot = db.snapshot_create(self._context, updates)
self._from_db_object(self._context, self, db_snapshot)

View File

@ -23,6 +23,7 @@ from cinder import objects
from cinder.objects import base
from cinder.objects import cleanable
from cinder.objects import fields as c_fields
from cinder.volume import volume_types
CONF = cfg.CONF
@ -340,6 +341,10 @@ class Volume(cleanable.CinderCleanableObject, base.CinderObject,
if 'group' in updates:
raise exception.ObjectActionError(
action='create', reason=_('group assigned'))
if ('volume_type_id' not in updates or
updates['volume_type_id'] is None):
updates['volume_type_id'] = (
volume_types.get_default_volume_type()['id'])
db_volume = db.volume_create(self._context, updates)
self._from_db_object(self._context, self, db_volume)

View File

@ -55,6 +55,7 @@ from cinder import service
from cinder.tests import fixtures as cinder_fixtures
from cinder.tests.unit import conf_fixture
from cinder.tests.unit import fake_notifier
from cinder.volume import volume_types
from cinder.volume import volume_utils
@ -324,6 +325,11 @@ class TestCase(testtools.TestCase):
# NOTE(mikal): make sure we don't load a privsep helper accidentally
self.useFixture(cinder_fixtures.PrivsepNoHelperFixture())
# NOTE: This volume type is created to avoid failure at database since
# volume_type_id is non-nullable for volumes and snapshots
self.vt = volume_types.get_default_volume_type()
def _restore_obj_registry(self):
objects_base.CinderObjectRegistry._registry._obj_classes = \
self._base_test_obj_backup

View File

@ -1,5 +1,16 @@
{
"volume_types": [
{
"description": "volume type 0002",
"extra_specs": {
"capabilities": "gpu"
},
"id": "%(uuid)s",
"is_public": true,
"name": "vol-type-002",
"os-volume-type-access:is_public": true,
"qos_specs_id": null
},
{
"description": "volume type 0001",
"extra_specs": {
@ -12,15 +23,13 @@
"qos_specs_id": null
},
{
"description": "volume type 0002",
"extra_specs": {
"capabilities": "gpu"
},
"description": "Default Volume Type",
"extra_specs": {},
"id": "%(uuid)s",
"is_public": true,
"name": "vol-type-002",
"name": "__DEFAULT__",
"os-volume-type-access:is_public": true,
"qos_specs_id": null
}
]
}
}

View File

@ -29,6 +29,6 @@
"status": "creating",
"updated_at": null,
"user_id": "%(uuid)s",
"volume_type": null
"volume_type": "__DEFAULT__"
}
}

View File

@ -33,6 +33,6 @@
"status": "creating",
"updated_at": null,
"user_id": "%(uuid)s",
"volume_type": null
"volume_type": "__DEFAULT__"
}
}

View File

@ -31,6 +31,6 @@
"status": "creating",
"updated_at": null,
"user_id": "%(uuid)s",
"volume_type": null
"volume_type": "__DEFAULT__"
}
}

View File

@ -34,7 +34,7 @@
"status": "creating",
"updated_at": null,
"user_id": "%(uuid)s",
"volume_type": null
"volume_type": "__DEFAULT__"
}
]
}

View File

@ -42,6 +42,7 @@ from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import utils as test_utils
from cinder.volume import api as volume_api
from cinder.volume import rpcapi
from cinder.volume import volume_types
def app():
@ -71,7 +72,9 @@ class BaseAdminTest(test.TestCase):
'host': 'test',
'binary': constants.VOLUME_BINARY,
'availability_zone': 'fake_zone',
'attach_status': fields.VolumeAttachStatus.DETACHED}
'attach_status': fields.VolumeAttachStatus.DETACHED,
'volume_type_id':
volume_types.get_default_volume_type()['id']}
if updates:
db_volume.update(updates)
@ -192,7 +195,8 @@ class AdminActionsTest(BaseAdminTest):
def test_reset_attach_status(self):
volume = db.volume_create(self.ctx,
{'attach_status':
fields.VolumeAttachStatus.DETACHED})
fields.VolumeAttachStatus.DETACHED,
'volume_type_id': fake.VOLUME_TYPE_ID})
resp = self._issue_volume_reset(self.ctx,
volume,
@ -207,7 +211,8 @@ class AdminActionsTest(BaseAdminTest):
def test_reset_attach_invalid_status(self):
volume = db.volume_create(self.ctx,
{'attach_status':
fields.VolumeAttachStatus.DETACHED})
fields.VolumeAttachStatus.DETACHED,
'volume_type_id': fake.VOLUME_TYPE_ID})
resp = self._issue_volume_reset(self.ctx,
volume,
@ -219,7 +224,9 @@ class AdminActionsTest(BaseAdminTest):
volume['attach_status'])
def test_reset_migration_invalid_status(self):
volume = db.volume_create(self.ctx, {'migration_status': None})
volume = db.volume_create(self.ctx, {'migration_status': None,
'volume_type_id':
fake.VOLUME_TYPE_ID})
resp = self._issue_volume_reset(self.ctx,
volume,
@ -230,7 +237,9 @@ class AdminActionsTest(BaseAdminTest):
self.assertIsNone(volume['migration_status'])
def test_reset_migration_status(self):
volume = db.volume_create(self.ctx, {'migration_status': None})
volume = db.volume_create(self.ctx, {'migration_status': None,
'volume_type_id':
fake.VOLUME_TYPE_ID})
resp = self._issue_volume_reset(self.ctx,
volume,
@ -241,7 +250,9 @@ class AdminActionsTest(BaseAdminTest):
self.assertEqual('migrating', volume['migration_status'])
def test_reset_status_as_admin(self):
volume = db.volume_create(self.ctx, {'status': 'available'})
volume = db.volume_create(self.ctx, {'status': 'available',
'volume_type_id':
fake.VOLUME_TYPE_ID})
resp = self._issue_volume_reset(self.ctx,
volume,
@ -255,7 +266,8 @@ class AdminActionsTest(BaseAdminTest):
def test_reset_status_as_non_admin(self, fake_get):
ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID)
volume = db.volume_create(self.ctx,
{'status': 'error', 'size': 1})
{'status': 'error', 'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
fake_get.return_value = volume
resp = self._issue_volume_reset(ctx,
volume,
@ -270,7 +282,9 @@ class AdminActionsTest(BaseAdminTest):
def test_backup_reset_status_as_admin(self):
volume = db.volume_create(self.ctx, {'status': 'available',
'user_id': fake.USER_ID,
'project_id': fake.PROJECT_ID})
'project_id': fake.PROJECT_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
backup = db.backup_create(self.ctx,
{'status': fields.BackupStatus.AVAILABLE,
'size': 1,
@ -297,7 +311,8 @@ class AdminActionsTest(BaseAdminTest):
def test_backup_reset_status(self):
volume = db.volume_create(self.ctx,
{'status': 'available', 'host': 'test',
'provider_location': '', 'size': 1})
'provider_location': '', 'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
backup = db.backup_create(self.ctx,
{'status': fields.BackupStatus.AVAILABLE,
'volume_id': volume['id'],
@ -315,7 +330,8 @@ class AdminActionsTest(BaseAdminTest):
def test_invalid_status_for_backup(self, status):
volume = db.volume_create(self.ctx,
{'status': 'available', 'host': 'test',
'provider_location': '', 'size': 1})
'provider_location': '', 'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
backup = db.backup_create(self.ctx, {'status': 'available',
'volume_id': volume['id']})
resp = self._issue_backup_reset(self.ctx,
@ -325,7 +341,8 @@ class AdminActionsTest(BaseAdminTest):
def test_backup_reset_status_with_invalid_backup(self):
volume = db.volume_create(self.ctx,
{'status': 'available', 'host': 'test',
'provider_location': '', 'size': 1})
'provider_location': '', 'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
backup = db.backup_create(self.ctx,
{'status': fields.BackupStatus.AVAILABLE,
'volume_id': volume['id'],
@ -344,7 +361,8 @@ class AdminActionsTest(BaseAdminTest):
def test_backup_reset_status_with_invalid_body(self, body):
volume = db.volume_create(self.ctx,
{'status': 'available', 'host': 'test',
'provider_location': '', 'size': 1})
'provider_location': '', 'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
backup = db.backup_create(self.ctx,
{'status': fields.BackupStatus.AVAILABLE,
'volume_id': volume['id'],
@ -361,7 +379,9 @@ class AdminActionsTest(BaseAdminTest):
self.assertEqual(http_client.BAD_REQUEST, resp.status_int)
def test_malformed_reset_status_body(self):
volume = db.volume_create(self.ctx, {'status': 'available', 'size': 1})
volume = db.volume_create(self.ctx, {'status': 'available', 'size': 1,
'volume_type_id':
fake.VOLUME_TYPE_ID})
resp = self._issue_volume_reset(self.ctx,
volume,
@ -372,7 +392,9 @@ class AdminActionsTest(BaseAdminTest):
self.assertEqual('available', volume['status'])
def test_invalid_status_for_volume(self):
volume = db.volume_create(self.ctx, {'status': 'available', 'size': 1})
volume = db.volume_create(self.ctx, {'status': 'available', 'size': 1,
'volume_type_id':
fake.VOLUME_TYPE_ID})
resp = self._issue_volume_reset(self.ctx,
volume,
{'status': 'invalid'})
@ -445,7 +467,8 @@ class AdminActionsTest(BaseAdminTest):
{'status': 'available', 'host': 'test',
'provider_location': '', 'size': 1,
'attach_status':
fields.VolumeAttachStatus.DETACHED})
fields.VolumeAttachStatus.DETACHED,
'volume_type_id': fake.VOLUME_TYPE_ID})
resp = self._issue_volume_reset(
self.ctx,
volume,
@ -463,7 +486,8 @@ class AdminActionsTest(BaseAdminTest):
'provider_location': '', 'size': 1,
'availability_zone': 'test',
'attach_status':
fields.VolumeAttachStatus.DETACHED})
fields.VolumeAttachStatus.DETACHED,
'volume_type_id': fake.VOLUME_TYPE_ID})
kwargs = {
'volume_id': volume['id'],
'cgsnapshot_id': None,
@ -490,7 +514,8 @@ class AdminActionsTest(BaseAdminTest):
def test_invalid_status_for_snapshot(self, updated_status):
volume = db.volume_create(self.ctx,
{'status': 'available', 'host': 'test',
'provider_location': '', 'size': 1})
'provider_location': '', 'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
snapshot = objects.Snapshot(self.ctx,
status=fields.SnapshotStatus.AVAILABLE,
volume_id=volume['id'])
@ -506,10 +531,12 @@ class AdminActionsTest(BaseAdminTest):
def test_snapshot_reset_status_with_invalid_body(self, body):
volume = db.volume_create(self.ctx,
{'status': 'available', 'host': 'test',
'provider_location': '', 'size': 1})
'provider_location': '', 'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
snapshot = objects.Snapshot(self.ctx,
status=fields.SnapshotStatus.AVAILABLE,
volume_id=volume['id'])
volume_id=volume['id'],
volume_tpe_id=volume['volume_type_id'])
snapshot.create()
self.addCleanup(snapshot.destroy)
@ -798,8 +825,12 @@ class AdminActionsTest(BaseAdminTest):
@mock.patch("cinder.volume.api.API.get")
def test_migrate_volume_comp_as_non_admin(self, fake_get):
volume = db.volume_create(self.ctx, {'id': fake.VOLUME_ID})
new_volume = db.volume_create(self.ctx, {'id': fake.VOLUME2_ID})
volume = db.volume_create(self.ctx, {'id': fake.VOLUME_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
new_volume = db.volume_create(self.ctx, {'id': fake.VOLUME2_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
expected_status = http_client.FORBIDDEN
expected_id = None
fake_get.return_value = volume
@ -829,8 +860,12 @@ class AdminActionsTest(BaseAdminTest):
expected_status, expected_id)
def test_migrate_volume_comp_no_action(self):
volume = db.volume_create(self.ctx, {'id': fake.VOLUME_ID})
new_volume = db.volume_create(self.ctx, {'id': fake.VOLUME2_ID})
volume = db.volume_create(self.ctx, {'id': fake.VOLUME_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
new_volume = db.volume_create(self.ctx, {'id': fake.VOLUME2_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
expected_status = http_client.BAD_REQUEST
expected_id = None
ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID)
@ -854,7 +889,9 @@ class AdminActionsTest(BaseAdminTest):
expected_status, expected_id)
def test_migrate_volume_comp_no_new_volume(self):
volume = db.volume_create(self.ctx, {'id': fake.VOLUME_ID})
volume = db.volume_create(self.ctx, {'id': fake.VOLUME_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
req = webob.Request.blank('/v2/%s/volumes/%s/action' % (
fake.PROJECT_ID, volume['id']))
req.method = 'POST'

View File

@ -50,6 +50,12 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
is_admin=True)
self.user_ctxt = context.RequestContext(
fake.USER_ID, fake.PROJECT_ID, auth_token=True)
self.admin_ctxt = context.get_admin_context()
db.volume_type_create(self.admin_ctxt,
v2_fakes.fake_default_type_get(
fake.VOLUME_TYPE2_ID))
self.vol_type = db.volume_type_get_by_name(self.admin_ctxt,
'vol_type_name')
def _create_consistencygroup(
self,
@ -1195,11 +1201,12 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
@mock.patch('cinder.scheduler.rpcapi.SchedulerAPI.validate_host_capacity')
def test_create_consistencygroup_from_src_cg(self, mock_validate):
self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_create)
source_cg = utils.create_group(
self.ctxt, group_type_id=fake.GROUP_TYPE_ID,
volume_type_ids=[fake.VOLUME_TYPE_ID],)
volume_type_ids=[self.vol_type['id']],)
volume_id = utils.create_volume(
self.ctxt,
@ -1531,14 +1538,16 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
side_effect=exception.CinderException(
'Create volume failed.'))
@mock.patch('cinder.scheduler.rpcapi.SchedulerAPI.validate_host_capacity')
@mock.patch('cinder.db.sqlalchemy.api.volume_type_get')
def test_create_consistencygroup_from_src_cg_create_volume_failed(
self, mock_validate, mock_create):
self, mock_validate, mock_create, mock_vol_type_get):
source_cg = utils.create_group(
self.ctxt, group_type_id=fake.GROUP_TYPE_ID,
volume_type_ids=[fake.VOLUME_TYPE_ID],)
volume_id = utils.create_volume(
self.ctxt,
group_id=source_cg.id)['id']
group_id=source_cg.id,
volume_type_id=fake.VOLUME_TYPE_ID)['id']
mock_validate.return_value = True
test_cg_name = 'test cg'

View File

@ -49,6 +49,12 @@ class SchedulerHintsTestCase(test.TestCase):
self.user_ctxt = context.RequestContext(
fake.USER_ID, fake.PROJECT_ID, auth_token=True)
self.app = fakes.wsgi_app(fake_auth_context=self.user_ctxt)
self.admin_ctxt = context.get_admin_context()
cinder.db.volume_type_create(self.admin_ctxt,
v2_fakes.fake_default_type_get(
fake.VOLUME_TYPE2_ID))
self.vol_type = cinder.db.volume_type_get_by_name(self.admin_ctxt,
'vol_type_name')
def test_create_server_without_hints(self):
@ -120,7 +126,7 @@ class SchedulerHintsTestCase(test.TestCase):
req = fakes.HTTPRequest.blank('/v2/%s/volumes' % fake.PROJECT_ID)
req.method = 'POST'
req.content_type = 'application/json'
body = {'volume': {'size': 1},
body = {'volume': {'size': 1, 'volume_type': self.vol_type['id']},
'OS-SCH-HNT:scheduler_hints': value}
req.body = jsonutils.dump_as_bytes(body)

View File

@ -711,7 +711,7 @@ class VolumeRetypeActionsTest(test.TestCase):
name='old',
qos_specs_id=qos_old).id
else:
vol_type_old = None
vol_type_old = v2_fakes.fake_default_type_get()
vol_type_new = utils.create_volume_type(admin_ctxt, self,
name='new',
@ -741,7 +741,7 @@ class VolumeRetypeActionsTest(test.TestCase):
if enc_orig:
utils.create_encryption(admin_ctxt, vol_type_old, self)
else:
vol_type_old = None
vol_type_old = v2_fakes.fake_default_type_get()
vol_type_new = utils.create_volume_type(admin_ctxt, self,
name='new').id
@ -1072,7 +1072,8 @@ class VolumeImageActionsTest(test.TestCase):
def test_extend_attached_volume(self, version, status):
vol = db.volume_create(self.context,
{'size': 1, 'project_id': fake.PROJECT_ID,
'status': status})
'status': status,
'volume_type_id': fake.VOLUME_TYPE_ID})
self.mock_object(volume_api.API, 'get', return_value=vol)
mock_extend = self.mock_object(volume_api.API, '_extend')
body = {"os-extend": {"new_size": 2}}

View File

@ -63,6 +63,7 @@ class VolumeEncryptionMetadataTest(test.TestCase):
'availability_zone': availability_zone,
'host': host,
'encryption_key_id': encryption_key_id,
'volume_type_id': fake.VOLUME_TYPE_ID
}
return db.volume_create(context, volume)['id']

View File

@ -144,7 +144,8 @@ class VolumeImageMetadataTest(test.TestCase):
# create a bootable volume
db.volume_create(ctxt, {'id': fake.VOLUME_ID, 'status': 'available',
'host': 'test', 'provider_location': '',
'size': 1})
'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID,
'image_id', fake.IMAGE_ID)
db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID,
@ -157,7 +158,8 @@ class VolumeImageMetadataTest(test.TestCase):
# create an unbootable volume
db.volume_create(ctxt, {'id': fake.VOLUME2_ID, 'status': 'available',
'host': 'test', 'provider_location': '',
'size': 1})
'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
def test_get_volume(self):
self._create_volume_and_glance_metadata()
@ -191,7 +193,8 @@ class VolumeImageMetadataTest(test.TestCase):
ctxt = context.get_admin_context()
db.volume_create(ctxt, {'id': fake.VOLUME_ID, 'status': 'available',
'host': 'test', 'provider_location': '',
'size': 1})
'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID,
'key1', 'value1')
db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID,

View File

@ -17,6 +17,7 @@
Tests for volume transfer code.
"""
import mock
from oslo_serialization import jsonutils
from six.moves import http_client
import webob
@ -26,8 +27,10 @@ from cinder import context
from cinder import db
from cinder import exception
from cinder.objects import fields
from cinder import quota
from cinder import test
from cinder.tests.unit.api import fakes
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
import cinder.transfer
@ -67,6 +70,7 @@ class VolumeTransferAPITestCase(test.TestCase):
vol['display_description'] = display_description
vol['attach_status'] = attach_status
vol['availability_zone'] = 'fake_zone'
vol['volume_type_id'] = fake.VOLUME_TYPE_ID
return db.volume_create(context.get_admin_context(), vol)['id']
def test_show_transfer(self):
@ -343,7 +347,9 @@ class VolumeTransferAPITestCase(test.TestCase):
fake.WILL_NOT_BE_FOUND_ID,
res_dict['itemNotFound']['message'])
def test_accept_transfer_volume_id_specified_json(self):
@mock.patch.object(quota.QUOTAS, 'reserve')
@mock.patch.object(db, 'volume_type_get', v2_fakes.fake_volume_type_get)
def test_accept_transfer_volume_id_specified_json(self, type_get):
volume_id = self._create_volume()
transfer = self._create_transfer(volume_id)

View File

@ -23,7 +23,6 @@ from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_volume
from cinder import utils
DEFAULT_VOL_NAME = "displayname"
DEFAULT_VOL_DESCRIPTION = "displaydesc"
DEFAULT_VOL_SIZE = 1
@ -284,6 +283,24 @@ def fake_volume_type_get(context, id, *args, **kwargs):
'deleted': False}
def fake_default_type_get(id=fake.VOLUME_TYPE_ID):
return {'id': id,
'name': 'vol_type_name',
'description': 'A fake volume type',
'is_public': True,
'projects': [],
'extra_specs': {},
'created_at': None,
'deleted_at': None,
'updated_at': None,
'qos_specs_id': fake.QOS_SPEC_ID,
'deleted': False}
def fake_volume_type_name_get(context, id, *args, **kwargs):
return fake_volume_type_get(context, id)['name'] or id
def fake_volume_admin_metadata_get(context, volume_id, **kwargs):
admin_meta = {'attached_mode': 'rw', 'readonly': 'False'}
if kwargs.get('attach_status') == fields.VolumeAttachStatus.DETACHED:

View File

@ -31,6 +31,7 @@ from cinder.objects import fields
from cinder.scheduler import rpcapi as scheduler_rpcapi
from cinder import test
from cinder.tests.unit.api import fakes
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
@ -95,7 +96,7 @@ def fake_get(self, context, *args, **kwargs):
'host': 'fake-host',
'status': 'available',
'encryption_key_id': None,
'volume_type_id': None,
'volume_type_id': fake.VOLUME_TYPE_ID,
'migration_status': None,
'availability_zone': 'fake-zone',
'attach_status': fields.VolumeAttachStatus.DETACHED,
@ -114,10 +115,13 @@ class SnapshotMetaDataTest(test.TestCase):
super(SnapshotMetaDataTest, self).setUp()
self.volume_api = cinder.volume.api.API()
self.mock_object(volume.api.API, 'get', fake_get)
self.mock_object(cinder.db.sqlalchemy.api, 'volume_type_get',
v2_fakes.fake_volume_type_get)
self.mock_object(scheduler_rpcapi.SchedulerAPI, 'create_snapshot')
self.mock_object(cinder.db, 'snapshot_get', return_snapshot)
self.mock_object(self.volume_api, 'update_snapshot_metadata')
self.patch('cinder.objects.volume.Volume.refresh')
self.patch('cinder.quota.QuotaEngine.reserve')
self.ext_mgr = extensions.ExtensionManager()
self.ext_mgr.extensions = {}

View File

@ -90,7 +90,7 @@ class SnapshotApiTest(test.TestCase):
self.ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True)
def test_snapshot_create(self):
volume = utils.create_volume(self.ctx)
volume = utils.create_volume(self.ctx, volume_type_id=None)
snapshot_name = 'Snapshot Test Name'
snapshot_description = 'Snapshot Test Desc'
snapshot = {
@ -113,7 +113,7 @@ class SnapshotApiTest(test.TestCase):
def test_snapshot_create_with_null_validate(self):
volume = utils.create_volume(self.ctx)
volume = utils.create_volume(self.ctx, volume_type_id=None)
snapshot = {
"volume_id": volume.id,
"force": False,
@ -132,7 +132,8 @@ class SnapshotApiTest(test.TestCase):
@ddt.data(True, 'y', 'true', 'yes', '1', 'on')
def test_snapshot_create_force(self, force_param):
volume = utils.create_volume(self.ctx, status='in-use')
volume = utils.create_volume(self.ctx, status='in-use',
volume_type_id=None)
snapshot_name = 'Snapshot Test Name'
snapshot_description = 'Snapshot Test Desc'
snapshot = {
@ -156,7 +157,8 @@ class SnapshotApiTest(test.TestCase):
@ddt.data(False, 'n', 'false', 'No', '0', 'off')
def test_snapshot_create_force_failure(self, force_param):
volume = utils.create_volume(self.ctx, status='in-use')
volume = utils.create_volume(self.ctx, status='in-use',
volume_type_id=None)
snapshot_name = 'Snapshot Test Name'
snapshot_description = 'Snapshot Test Desc'
snapshot = {
@ -177,7 +179,8 @@ class SnapshotApiTest(test.TestCase):
@ddt.data("**&&^^%%$$##@@", '-1', 2, '01', 'falSE', 0, 'trUE', 1,
"1 ")
def test_snapshot_create_invalid_force_param(self, force_param):
volume = utils.create_volume(self.ctx, status='available')
volume = utils.create_volume(self.ctx, status='available',
volume_type_id=None)
snapshot_name = 'Snapshot Test Name'
snapshot_description = 'Snapshot Test Desc'
@ -217,7 +220,7 @@ class SnapshotApiTest(test.TestCase):
{"snapshot": {"description": " sample description ",
"name": " test name "}})
def test_snapshot_create_with_leading_trailing_spaces(self, body):
volume = utils.create_volume(self.ctx)
volume = utils.create_volume(self.ctx, volume_type_id=None)
body['snapshot']['volume_id'] = volume.id
req = fakes.HTTPRequest.blank('/v2/snapshots')
resp_dict = self.controller.create(req, body=body)
@ -609,7 +612,7 @@ class SnapshotApiTest(test.TestCase):
self.assertNotIn('snapshots_links', res)
def _create_db_snapshots(self, num_snaps):
volume = utils.create_volume(self.ctx)
volume = utils.create_volume(self.ctx, volume_type_id=None)
snaps = [utils.create_snapshot(self.ctx,
volume.id,
display_name='snap' + str(i))

View File

@ -94,6 +94,8 @@ class VolumeTypesApiTest(test.TestCase):
is_admin=True)
self.mock_authorize = self.patch(
'cinder.context.RequestContext.authorize')
# since __DEFAULT__ type always exists, total number of volume types
# is total_types_created + 1. In this case it's 4
self.type_id1 = self._create_volume_type('volume_type1',
{'key1': 'value1'})
self.type_id2 = self._create_volume_type('volume_type2',
@ -101,6 +103,9 @@ class VolumeTypesApiTest(test.TestCase):
self.type_id3 = self._create_volume_type('volume_type3',
{'key3': 'value3'}, False,
[fake.PROJECT_ID])
self.default_type = volume_types.get_default_volume_type()['id']
self.vol_type = volume_types.get_by_name_or_id(
context.get_admin_context(), '__DEFAULT__')['id']
def test_volume_types_index(self):
self.mock_object(volume_types, 'get_all_types',
@ -147,7 +152,7 @@ class VolumeTypesApiTest(test.TestCase):
req.environ['cinder.context'] = self.ctxt
res = self.controller.index(req)
self.assertEqual(2, len(res['volume_types']))
self.assertEqual(3, len(res['volume_types']))
def test_volume_types_index_with_offset_out_of_range(self):
url = '/v2/%s/types?offset=424366766556787' % fake.PROJECT_ID
@ -182,7 +187,7 @@ class VolumeTypesApiTest(test.TestCase):
req.environ['cinder.context'] = self.ctxt
res = self.controller.index(req)
self.assertEqual(3, len(res['volume_types']))
self.assertEqual(4, len(res['volume_types']))
self.assertEqual(self.type_id3, res['volume_types'][0]['id'])
self.assertEqual(self.type_id2, res['volume_types'][1]['id'])
self.assertEqual(self.type_id1, res['volume_types'][2]['id'])
@ -194,26 +199,30 @@ class VolumeTypesApiTest(test.TestCase):
user_id=fake.USER_ID, project_id=fake.PROJECT_ID, is_admin=False)
res = self.controller.index(req)
self.assertEqual(3, len(res['volume_types']))
self.assertEqual(4, len(res['volume_types']))
def test_volume_types_index_with_sort_keys(self):
req = fakes.HTTPRequest.blank('/v2/%s/types?sort=id' % fake.PROJECT_ID)
req.environ['cinder.context'] = self.ctxt
res = self.controller.index(req)
expect_result = [self.type_id1, self.type_id2, self.type_id3]
expect_result = [self.default_type, self.type_id1,
self.type_id2, self.type_id3]
expect_result.sort(reverse=True)
self.assertEqual(3, len(res['volume_types']))
self.assertEqual(4, len(res['volume_types']))
self.assertEqual(expect_result[0], res['volume_types'][0]['id'])
self.assertEqual(expect_result[1], res['volume_types'][1]['id'])
self.assertEqual(expect_result[2], res['volume_types'][2]['id'])
self.assertEqual(expect_result[3], res['volume_types'][3]['id'])
def test_volume_types_index_with_sort_and_limit(self):
req = fakes.HTTPRequest.blank(
'/v2/%s/types?sort=id&limit=2' % fake.PROJECT_ID)
req.environ['cinder.context'] = self.ctxt
res = self.controller.index(req)
expect_result = [self.type_id1, self.type_id2, self.type_id3]
expect_result = [self.default_type, self.type_id1,
self.type_id2, self.type_id3]
expect_result.sort(reverse=True)
self.assertEqual(2, len(res['volume_types']))
@ -225,13 +234,15 @@ class VolumeTypesApiTest(test.TestCase):
'/v2/%s/types?sort=id:asc' % fake.PROJECT_ID)
req.environ['cinder.context'] = self.ctxt
res = self.controller.index(req)
expect_result = [self.type_id1, self.type_id2, self.type_id3]
expect_result = [self.default_type, self.type_id1,
self.type_id2, self.type_id3]
expect_result.sort()
self.assertEqual(3, len(res['volume_types']))
self.assertEqual(4, len(res['volume_types']))
self.assertEqual(expect_result[0], res['volume_types'][0]['id'])
self.assertEqual(expect_result[1], res['volume_types'][1]['id'])
self.assertEqual(expect_result[2], res['volume_types'][2]['id'])
self.assertEqual(expect_result[3], res['volume_types'][3]['id'])
def test_volume_types_show(self):
self.mock_object(volume_types, 'get_volume_type',

View File

@ -136,7 +136,8 @@ class VolumeMetaDataTest(test.TestCase):
"display_name": "Volume Test Name",
"display_description": "Volume Test Desc",
"availability_zone": "zone1:host1",
"metadata": {}}
"metadata": {},
"volume_type": self.vt['id']}
body = {"volume": vol}
req = fakes.HTTPRequest.blank('/v2/%s/volumes' % fake.PROJECT_ID)
self.volume_controller.create(req, body=body)

View File

@ -30,6 +30,7 @@ import webob
from cinder.api import common
from cinder.api import extensions
from cinder.api.v2.views import volumes as v_vol
from cinder.api.v2 import volumes
from cinder import context
from cinder import db
@ -45,6 +46,7 @@ from cinder.tests.unit import fake_volume
from cinder.tests.unit.image import fake as fake_image
from cinder.tests.unit import utils
from cinder.volume import api as volume_api
from cinder.volume import volume_types
CONF = cfg.CONF
@ -65,6 +67,23 @@ class VolumeApiTest(test.TestCase):
self.ctxt = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True)
# This will be cleaned up by the NestedTempfile fixture in base class
self.tmp_path = self.useFixture(fixtures.TempDir()).path
self.mock_object(objects.VolumeType, 'get_by_id',
self.fake_volume_type_get)
self.mock_object(v_vol.ViewBuilder, '_get_volume_type',
v2_fakes.fake_volume_type_name_get)
def fake_volume_type_get(self, context, id, *args, **kwargs):
return {'id': id,
'name': 'vol_type_name',
'description': 'A fake volume type',
'is_public': True,
'projects': [],
'extra_specs': {},
'created_at': None,
'deleted_at': None,
'updated_at': None,
'qos_specs_id': fake.QOS_SPEC_ID,
'deleted': False}
@mock.patch(
'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
@ -91,13 +110,8 @@ class VolumeApiTest(test.TestCase):
@mock.patch(
'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
def test_volume_create_with_type(self, mock_validate, mock_service_get):
vol_type = db.volume_type_create(
context.get_admin_context(),
dict(name=CONF.default_volume_type, extra_specs={})
)
db_vol_type = db.volume_type_get(context.get_admin_context(),
vol_type.id)
db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
'__DEFAULT__')
vol = self._vol_in_request_body(volume_type="FakeTypeName")
body = {"volume": vol}
@ -120,8 +134,9 @@ class VolumeApiTest(test.TestCase):
volume_id = res_dict['volume']['id']
self.assertEqual(1, len(res_dict))
vol_db = v2_fakes.create_fake_volume(volume_id,
volume_type={'name': vol_type})
vol_db = v2_fakes.create_fake_volume(
volume_id,
volume_type={'name': db_vol_type['name']})
vol_obj = fake_volume.fake_volume_obj(context.get_admin_context(),
**vol_db)
self.mock_object(volume_api.API, 'get_all',
@ -256,10 +271,15 @@ class VolumeApiTest(test.TestCase):
kwargs = self._expected_volume_api_create_kwargs(
v2_fakes.fake_snapshot(snapshot_id))
create.assert_called_once_with(self.controller.volume_api, context,
vol['size'], v2_fakes.DEFAULT_VOL_NAME,
v2_fakes.DEFAULT_VOL_DESCRIPTION,
**kwargs)
create.assert_called_once_with(
self.controller.volume_api, context,
vol['size'], v2_fakes.DEFAULT_VOL_NAME,
v2_fakes.DEFAULT_VOL_DESCRIPTION,
volume_type=
objects.VolumeType.get_by_name_or_id(
context,
volume_types.get_default_volume_type()['id']),
**kwargs)
@mock.patch.object(volume_api.API, 'get_snapshot', autospec=True)
def test_volume_creation_fails_with_invalid_snapshot(self, get_snapshot):
@ -316,10 +336,15 @@ class VolumeApiTest(test.TestCase):
vol_obj = fake_volume.fake_volume_obj(context, **db_vol)
kwargs = self._expected_volume_api_create_kwargs(
source_volume=vol_obj)
create.assert_called_once_with(self.controller.volume_api, context,
vol['size'], v2_fakes.DEFAULT_VOL_NAME,
v2_fakes.DEFAULT_VOL_DESCRIPTION,
**kwargs)
create.assert_called_once_with(
self.controller.volume_api, context,
vol['size'], v2_fakes.DEFAULT_VOL_NAME,
v2_fakes.DEFAULT_VOL_DESCRIPTION,
volume_type=
objects.VolumeType.get_by_name_or_id(
context,
volume_types.get_default_volume_type()['id']),
**kwargs)
@mock.patch.object(volume_api.API, 'get_volume', autospec=True)
def test_volume_creation_fails_with_invalid_source_volume(self,
@ -710,7 +735,6 @@ class VolumeApiTest(test.TestCase):
volume = v2_fakes.create_fake_volume(fake.VOLUME_ID)
del volume['name']
del volume['volume_type']
del volume['volume_type_id']
volume['metadata'] = {'key': 'value'}
db.volume_create(context.get_admin_context(), volume)
@ -736,7 +760,7 @@ class VolumeApiTest(test.TestCase):
req.environ['cinder.context'] = admin_ctx
res_dict = self.controller.update(req, fake.VOLUME_ID, body=body)
expected = self._expected_vol_from_controller(
availability_zone=v2_fakes.DEFAULT_AZ, volume_type=None,
availability_zone=v2_fakes.DEFAULT_AZ,
status='in-use', name='Updated Test Name',
attachments=[{'id': fake.VOLUME_ID,
'attachment_id': attachment['id'],
@ -747,6 +771,7 @@ class VolumeApiTest(test.TestCase):
'attached_at': attach_tmp['attach_time'].replace(
tzinfo=iso8601.UTC),
}],
volume_type=fake.VOLUME_TYPE_NAME,
metadata={'key': 'value', 'readonly': 'True'},
with_migration_status=True)
expected['volume']['updated_at'] = volume_tmp['updated_at'].replace(
@ -863,7 +888,6 @@ class VolumeApiTest(test.TestCase):
volume = v2_fakes.create_fake_volume(fake.VOLUME_ID)
del volume['name']
del volume['volume_type']
del volume['volume_type_id']
volume['metadata'] = {'key': 'value'}
db.volume_create(context.get_admin_context(), volume)
db.volume_admin_metadata_update(context.get_admin_context(),
@ -885,7 +909,7 @@ class VolumeApiTest(test.TestCase):
res_dict = self.controller.detail(req)
exp_vol = self._expected_vol_from_controller(
availability_zone=v2_fakes.DEFAULT_AZ,
status="in-use", volume_type=None,
status="in-use", volume_type=fake.VOLUME_TYPE_NAME,
attachments=[{'attachment_id': attachment['id'],
'device': '/',
'server_id': fake.INSTANCE_ID,
@ -1326,7 +1350,6 @@ class VolumeApiTest(test.TestCase):
volume = v2_fakes.create_fake_volume(fake.VOLUME_ID)
del volume['name']
del volume['volume_type']
del volume['volume_type_id']
volume['metadata'] = {'key': 'value'}
db.volume_create(context.get_admin_context(), volume)
db.volume_admin_metadata_update(context.get_admin_context(),
@ -1347,7 +1370,7 @@ class VolumeApiTest(test.TestCase):
res_dict = self.controller.show(req, fake.VOLUME_ID)
expected = self._expected_vol_from_controller(
availability_zone=v2_fakes.DEFAULT_AZ,
volume_type=None, status='in-use',
volume_type=fake.VOLUME_TYPE_NAME, status='in-use',
attachments=[{'id': fake.VOLUME_ID,
'attachment_id': attachment['id'],
'volume_id': v2_fakes.DEFAULT_VOL_ID,

View File

@ -20,11 +20,13 @@ from oslo_utils import strutils
from cinder.api import microversions as mv
from cinder.api.v3 import snapshots
from cinder import context
from cinder import db
from cinder import exception
from cinder.objects import fields
from cinder.scheduler import rpcapi as scheduler_rpcapi
from cinder import test
from cinder.tests.unit.api import fakes
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
@ -46,7 +48,8 @@ def fake_get(self, context, *args, **kwargs):
'migration_status': None,
'availability_zone': 'fake-zone',
'attach_status': 'detached',
'metadata': {}}
'metadata': {},
'volume_type_id': fake.VOLUME_TYPE_ID}
return fake_volume.fake_volume_obj(context, **vol)
@ -66,6 +69,9 @@ class SnapshotApiTest(test.TestCase):
def setUp(self):
super(SnapshotApiTest, self).setUp()
self.mock_object(volume.api.API, 'get', fake_get)
self.mock_object(db.sqlalchemy.api, 'volume_type_get',
v2_fakes.fake_volume_type_get)
self.patch('cinder.quota.QUOTAS.reserve')
self.mock_object(scheduler_rpcapi.SchedulerAPI, 'create_snapshot')
self.controller = snapshots.SnapshotsController()
self.ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True)

View File

@ -62,7 +62,9 @@ class VolumeTypesApiTest(test.TestCase):
mv.SUPPORT_VOLUME_TYPE_FILTER))
res_dict = self.controller.index(req)
self.assertEqual(3, len(res_dict['volume_types']))
# since __DEFAULT__ type always exists, total number of volume types
# is total_types_created + 1. In this case it's 4
self.assertEqual(4, len(res_dict['volume_types']))
# Test filter volume type with extra specs
req = fakes.HTTPRequest.blank(

View File

@ -18,6 +18,7 @@ Tests for volume transfer code.
"""
import ddt
import mock
from oslo_serialization import jsonutils
from six.moves import http_client
import webob
@ -28,8 +29,10 @@ from cinder.api.v3 import volume_transfer as volume_transfer_v3
from cinder import context
from cinder import db
from cinder.objects import fields
from cinder import quota
from cinder import test
from cinder.tests.unit.api import fakes
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
import cinder.transfer
@ -77,6 +80,7 @@ class VolumeTransferAPITestCase(test.TestCase):
vol['display_description'] = display_description
vol['attach_status'] = attach_status
vol['availability_zone'] = 'fake_zone'
vol['volume_type_id'] = fake.VOLUME_TYPE_ID
volume_id = db.volume_create(context.get_admin_context(), vol)['id']
self.addCleanup(db.volume_destroy, context.get_admin_context(),
volume_id)
@ -324,7 +328,9 @@ class VolumeTransferAPITestCase(test.TestCase):
self.assertEqual(db.volume_get(context.get_admin_context(),
volume_id)['status'], 'available')
def test_accept_transfer_volume_id_specified(self):
@mock.patch.object(quota.QUOTAS, 'reserve')
@mock.patch.object(db, 'volume_type_get', v2_fakes.fake_volume_type_get)
def test_accept_transfer_volume_id_specified(self, type_get):
volume_id = self._create_volume()
transfer = self.volume_transfer_api.create(context.get_admin_context(),
volume_id, 'test_transfer')

View File

@ -46,6 +46,7 @@ from cinder.tests.unit.image import fake as fake_image
from cinder.tests.unit import utils as test_utils
from cinder.volume import api as volume_api
from cinder.volume import api as vol_get
from cinder.volume import volume_types
DEFAULT_AZ = "zone1:host1"
@ -121,12 +122,16 @@ class VolumeApiTest(test.TestCase):
def _create_volume_with_glance_metadata(self):
vol1 = db.volume_create(self.ctxt, {'display_name': 'test1',
'project_id':
self.ctxt.project_id})
self.ctxt.project_id,
'volume_type_id':
fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(self.ctxt, vol1.id, 'image_name',
'imageTestOne')
vol2 = db.volume_create(self.ctxt, {'display_name': 'test2',
'project_id':
self.ctxt.project_id})
self.ctxt.project_id,
'volume_type_id':
fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(self.ctxt, vol2.id, 'image_name',
'imageTestTwo')
db.volume_glance_metadata_create(self.ctxt, vol2.id, 'disk_format',
@ -138,23 +143,30 @@ class VolumeApiTest(test.TestCase):
'project_id':
self.ctxt.project_id,
'group_id':
fake.GROUP_ID})
fake.GROUP_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
vol2 = db.volume_create(self.ctxt, {'display_name': 'test2',
'project_id':
self.ctxt.project_id,
'group_id':
fake.GROUP2_ID})
fake.GROUP2_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
return [vol1, vol2]
def _create_multiple_volumes_with_different_project(self):
# Create volumes in project 1
db.volume_create(self.ctxt, {'display_name': 'test1',
'project_id': fake.PROJECT_ID})
'project_id': fake.PROJECT_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_create(self.ctxt, {'display_name': 'test2',
'project_id': fake.PROJECT_ID})
'project_id': fake.PROJECT_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
# Create volume in project 2
db.volume_create(self.ctxt, {'display_name': 'test3',
'project_id': fake.PROJECT2_ID})
'project_id': fake.PROJECT2_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
def test_volume_index_filter_by_glance_metadata(self):
vols = self._create_volume_with_glance_metadata()
@ -224,6 +236,8 @@ class VolumeApiTest(test.TestCase):
def test_list_volume_with_count_param(self, method, display_param):
self._create_multiple_volumes_with_different_project()
self.mock_object(ViewBuilder, '_get_volume_type',
v2_fakes.fake_volume_type_name_get)
is_detail = True if 'detail' in method else False
show_count = strutils.bool_from_string(display_param, strict=True)
# Request with 'with_count' and 'limit'
@ -322,7 +336,11 @@ class VolumeApiTest(test.TestCase):
create.assert_called_once_with(
self.controller.volume_api, context,
vol['size'], v2_fakes.DEFAULT_VOL_NAME,
v2_fakes.DEFAULT_VOL_DESCRIPTION, **kwargs)
v2_fakes.DEFAULT_VOL_DESCRIPTION,
volume_type=objects.VolumeType.get_by_name_or_id(
context,
volume_types.get_default_volume_type()['id']),
**kwargs)
def test_volumes_summary_in_unsupport_version(self):
"""Function call to test summary volumes API in unsupported version"""
@ -620,6 +638,7 @@ class VolumeApiTest(test.TestCase):
create.side_effect = v2_fakes.fake_volume_api_create
get_snapshot.side_effect = v2_fakes.fake_snapshot_get
volume_type_get.side_effect = v2_fakes.fake_volume_type_get
fake_group = {
'id': fake.GROUP_ID,
'group_type_id': fake.GROUP_TYPE_ID,
@ -647,10 +666,14 @@ class VolumeApiTest(test.TestCase):
v2_fakes.fake_snapshot(snapshot_id),
test_group=fake_group,
req_version=req.api_version_request)
create.assert_called_once_with(self.controller.volume_api, context,
vol['size'], v2_fakes.DEFAULT_VOL_NAME,
v2_fakes.DEFAULT_VOL_DESCRIPTION,
**kwargs)
create.assert_called_once_with(
self.controller.volume_api, context,
vol['size'], v2_fakes.DEFAULT_VOL_NAME,
v2_fakes.DEFAULT_VOL_DESCRIPTION,
volume_type=objects.VolumeType.get_by_name_or_id(
context,
volume_types.get_default_volume_type()['id']),
**kwargs)
@ddt.data(mv.VOLUME_CREATE_FROM_BACKUP,
mv.get_prior_version(mv.VOLUME_CREATE_FROM_BACKUP))
@ -685,11 +708,15 @@ class VolumeApiTest(test.TestCase):
context, backup_id)
kwargs.update({'backup': v2_fakes.fake_backup_get(None, context,
backup_id)})
create.assert_called_once_with(self.controller.volume_api, context,
vol['size'],
v2_fakes.DEFAULT_VOL_NAME,
v2_fakes.DEFAULT_VOL_DESCRIPTION,
**kwargs)
create.assert_called_once_with(
self.controller.volume_api, context,
vol['size'],
v2_fakes.DEFAULT_VOL_NAME,
v2_fakes.DEFAULT_VOL_DESCRIPTION,
volume_type=objects.VolumeType.get_by_name_or_id(
context,
volume_types.get_default_volume_type()['id']),
**kwargs)
def test_volume_creation_with_scheduler_hints(self):
vol = self._vol_in_request_body(availability_zone=None)

View File

@ -22,6 +22,7 @@ from cinder.policies import attachments as attachment_policy
from cinder.policies import base as base_policy
from cinder import policy
from cinder import test
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import utils as tests_utils
from cinder.volume import api as volume_api
@ -321,6 +322,8 @@ class AttachmentManagerTestCase(test.TestCase):
return_value={})
@mock.patch('cinder.volume.rpcapi.VolumeAPI.attachment_update',
return_value={})
@mock.patch.object(db.sqlalchemy.api, '_volume_type_get',
v2_fakes.fake_volume_type_get)
def test_attachment_update_duplicate(self, mock_va_update, mock_db_upd):
volume_params = {'status': 'available'}

View File

@ -20,6 +20,7 @@ from cinder import exception
from cinder.objects import fields
from cinder.objects import volume_attachment
from cinder import test
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import utils as tests_utils
from cinder.volume import configuration as conf
@ -43,7 +44,10 @@ class AttachmentManagerTestCase(test.TestCase):
self.manager.stats = {'allocated_capacity_gb': 100,
'pools': {}}
def test_attachment_update(self):
@mock.patch.object(db.sqlalchemy.api, '_volume_type_get',
v2_fakes.fake_volume_type_get)
@mock.patch('cinder.db.sqlalchemy.api.volume_type_qos_specs_get')
def test_attachment_update(self, mock_type_get):
"""Test attachment_update."""
volume_params = {'status': 'available'}
connector = {

View File

@ -111,7 +111,8 @@ class BackupCephTestCase(test.TestCase):
"""Test case for ceph backup driver."""
def _create_volume_db_entry(self, id, size):
vol = {'id': id, 'size': size, 'status': 'available'}
vol = {'id': id, 'size': size, 'status': 'available',
'volume_type_id': self.vt['id']}
return db.volume_create(self.ctxt, vol)['id']
def _create_backup_db_entry(self, backupid, volid, size,

View File

@ -26,7 +26,6 @@ from cinder import exception
from cinder import objects
from cinder import test
from cinder.tests.unit.backup import fake_service
from cinder.volume import volume_types
_backup_db_fields = ['id', 'user_id', 'project_id',
'volume_id', 'host', 'availability_zone',
@ -39,7 +38,8 @@ _backup_db_fields = ['id', 'user_id', 'project_id',
class BackupBaseDriverTestCase(test.TestCase):
def _create_volume_db_entry(self, id, size):
vol = {'id': id, 'size': size, 'status': 'available'}
vol = {'id': id, 'size': size, 'status': 'available',
'volume_type_id': self.vt['id']}
return db.volume_create(self.ctxt, vol)['id']
def _create_backup_db_entry(self, backupid, volid, size,
@ -90,7 +90,8 @@ class BackupMetadataAPITestCase(test.TestCase):
display_description):
vol = {'id': id, 'size': size, 'status': 'available',
'display_name': display_name,
'display_description': display_description}
'display_description': display_description,
'volume_type_id': self.vt['id']}
return db.volume_create(self.ctxt, vol)['id']
def setUp(self):
@ -226,12 +227,9 @@ class BackupMetadataAPITestCase(test.TestCase):
self.assertEqual(set([]),
set(keys).symmetric_difference(set(fact.keys())))
volume_types.create(self.ctxt, 'faketype')
vol_type = volume_types.get_volume_type_by_name(self.ctxt, 'faketype')
meta_container = {self.bak_meta_api.TYPE_TAG_VOL_BASE_META:
{'encryption_key_id': '123',
'volume_type_id': vol_type.get('id'),
'volume_type_id': self.vt.get('id'),
'display_name': 'vol-2',
'display_description': 'description'},
self.bak_meta_api.TYPE_TAG_VOL_META: {},
@ -358,38 +356,6 @@ class BackupMetadataAPITestCase(test.TestCase):
container[self.bak_meta_api.TYPE_TAG_VOL_BASE_META], enc_vol2_id,
fields)
def test_restore_encrypted_vol_to_none_type_source_type_unavailable(self):
fields = ['encryption_key_id']
container = {}
enc_vol_id = self._create_encrypted_volume_db_entry(str(uuid.uuid4()),
'enc_vol_type',
True)
undef_vol_id = self._create_encrypted_volume_db_entry(
str(uuid.uuid4()), None, False)
self.bak_meta_api._save_vol_base_meta(container, enc_vol_id)
self.assertRaises(exception.EncryptedBackupOperationFailed,
self.bak_meta_api._restore_vol_base_meta,
container[self.bak_meta_api.TYPE_TAG_VOL_BASE_META],
undef_vol_id, fields)
def test_restore_encrypted_vol_to_none_type_source_type_available(self):
fields = ['encryption_key_id']
container = {}
db.volume_type_create(self.ctxt, {'id': 'enc_vol_type_id',
'name': 'enc_vol_type'})
enc_vol_id = self._create_encrypted_volume_db_entry(str(uuid.uuid4()),
'enc_vol_type_id',
True)
undef_vol_id = self._create_encrypted_volume_db_entry(
str(uuid.uuid4()), None, False)
self.bak_meta_api._save_vol_base_meta(container, enc_vol_id)
self.bak_meta_api._restore_vol_base_meta(
container[self.bak_meta_api.TYPE_TAG_VOL_BASE_META], undef_vol_id,
fields)
self.assertEqual(
db.volume_get(self.ctxt, undef_vol_id)['volume_type_id'],
db.volume_get(self.ctxt, enc_vol_id)['volume_type_id'])
def test_filter(self):
metadata = {'a': 1, 'b': 2, 'c': 3}
self.assertEqual(metadata, self.bak_meta_api._filter(metadata, []))

View File

@ -128,7 +128,8 @@ class GoogleBackupDriverTestCase(test.TestCase):
def _create_volume_db_entry(self, volume_id=_DEFAULT_VOLUME_ID):
vol = {'id': volume_id,
'size': 1,
'status': 'available'}
'status': 'available',
'volume_type_id': self.vt['id']}
return db.volume_create(self.ctxt, vol)['id']
def _create_backup_db_entry(self,

View File

@ -194,7 +194,8 @@ class BackupNFSTestCase(test.TestCase):
def _create_volume_db_entry(self, volume_id=_DEFAULT_VOLUME_ID):
vol = {'id': volume_id,
'size': 1,
'status': 'available'}
'status': 'available',
'volume_type_id': self.vt['id']}
return db.volume_create(self.ctxt, vol)['id']
def _create_backup_db_entry(self,

View File

@ -68,7 +68,8 @@ class BackupSwiftTestCase(test.TestCase):
def _create_volume_db_entry(self, volume_id=_DEFAULT_VOLUME_ID):
vol = {'id': volume_id,
'size': 1,
'status': 'available'}
'status': 'available',
'volume_type_id': self.vt['id']}
return db.volume_create(self.ctxt, vol)['id']
def _create_backup_db_entry(self,

View File

@ -244,7 +244,8 @@ class BackupTSMTestCase(test.TestCase):
def _create_volume_db_entry(self, volume_id):
vol = {'id': volume_id,
'size': 1,
'status': 'available'}
'status': 'available',
'volume_type_id': self.vt['id']}
return db.volume_create(self.ctxt, vol)['id']
def _create_backup_db_entry(self, backup_id, mode):

View File

@ -141,6 +141,7 @@ class BaseBackupTest(test.TestCase):
vol['availability_zone'] = '1'
vol['previous_status'] = previous_status
vol['encryption_key_id'] = encryption_key_id
vol['volume_type_id'] = fake.VOLUME_TYPE_ID
volume = objects.Volume(context=self.ctxt, **vol)
volume.create()
return volume.id
@ -222,6 +223,8 @@ class BackupTestCase(BaseBackupTest):
'do_setup')
@mock.patch.object(cinder.tests.fake_driver.FakeLoggingVolumeDriver,
'check_for_setup_error')
@mock.patch.object(cinder.db.sqlalchemy.api, '_volume_type_get_by_name',
v2_fakes.fake_volume_type_get)
@mock.patch('cinder.context.get_admin_context')
def test_init_host(self, mock_get_admin_context, mock_check, mock_setup,
mock_set_initialized):

View File

@ -29,7 +29,7 @@ CONF.import_opt('backup_driver', 'cinder.backup.manager')
CONF.import_opt('backend', 'cinder.keymgr', group='key_manager')
CONF.import_opt('scheduler_driver', 'cinder.scheduler.manager')
def_vol_type = 'fake_vol_type'
def_vol_type = '__DEFAULT__'
def set_defaults(conf):

View File

@ -35,6 +35,7 @@ from sqlalchemy.engine import reflection
from cinder.db import migration
import cinder.db.sqlalchemy.migrate_repo
from cinder.tests.unit import utils as test_utils
from cinder.volume import volume_types
class MigrationsMixin(test_migrations.WalkVersionsMixin):
@ -179,6 +180,14 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
self.assertIn('destination_project_id', volume_transfer.c)
self.assertIn('accepted', volume_transfer.c)
def _check_132(self, engine, data):
"""Test create default volume type."""
vol_types = db_utils.get_table(engine, 'volume_types')
vtype = (vol_types.select(vol_types.c.name ==
volume_types.DEFAULT_VOLUME_TYPE)
.execute().first())
self.assertIsNotNone(vtype)
# NOTE: this test becomes slower with each addition of new DB migration.
# 'pymysql' works much slower on slow nodes than 'psycopg2'. And such
# timeout mostly required for testing of 'mysql' backend.

View File

@ -68,7 +68,8 @@ class PurgeDeletedTest(test.TestCase):
self.uuidstrs.append(uuid.uuid4().hex)
# Add 6 rows to table
for uuidstr in self.uuidstrs:
ins_stmt = self.volumes.insert().values(id=uuidstr)
ins_stmt = self.volumes.insert().values(id=uuidstr,
volume_type_id=uuidstr)
self.conn.execute(ins_stmt)
ins_stmt = self.vm.insert().values(volume_id=uuidstr)
self.conn.execute(ins_stmt)
@ -83,7 +84,8 @@ class PurgeDeletedTest(test.TestCase):
self.conn.execute(ins_stmt)
ins_stmt = self.snapshots.insert().values(
id=uuidstr, volume_id=uuidstr)
id=uuidstr, volume_id=uuidstr,
volume_type_id=uuidstr)
self.conn.execute(ins_stmt)
ins_stmt = self.sm.insert().values(snapshot_id=uuidstr)
self.conn.execute(ins_stmt)
@ -281,7 +283,7 @@ class PurgeDeletedTest(test.TestCase):
# Verify that we only have 1 rows now
self.assertEqual(1, vol_rows)
self.assertEqual(1, vol_meta_rows)
self.assertEqual(2, vol_type_rows)
self.assertEqual(3, vol_type_rows)
self.assertEqual(1, vol_type_proj_rows)
self.assertEqual(1, snap_rows)
self.assertEqual(1, snap_meta_rows)
@ -314,7 +316,7 @@ class PurgeDeletedTest(test.TestCase):
# Verify that we only deleted 2
self.assertEqual(4, vol_rows)
self.assertEqual(4, vol_meta_rows)
self.assertEqual(8, vol_type_rows)
self.assertEqual(9, vol_type_rows)
self.assertEqual(4, vol_type_proj_rows)
self.assertEqual(4, snap_rows)
self.assertEqual(4, snap_meta_rows)
@ -347,7 +349,7 @@ class PurgeDeletedTest(test.TestCase):
# Verify that we only have 2 rows now
self.assertEqual(2, vol_rows)
self.assertEqual(2, vol_meta_rows)
self.assertEqual(4, vol_type_rows)
self.assertEqual(5, vol_type_rows)
self.assertEqual(2, vol_type_proj_rows)
self.assertEqual(2, snap_rows)
self.assertEqual(2, snap_meta_rows)
@ -379,7 +381,8 @@ class PurgeDeletedTest(test.TestCase):
# add new entry in volume and volume_admin_metadata for
# integrity check
uuid_str = uuid.uuid4().hex
ins_stmt = self.volumes.insert().values(id=uuid_str)
ins_stmt = self.volumes.insert().values(id=uuid_str,
volume_type_id=uuid_str)
self.conn.execute(ins_stmt)
ins_stmt = self.vm.insert().values(volume_id=uuid_str)
self.conn.execute(ins_stmt)

View File

@ -69,6 +69,7 @@ VOLUME6_ID = '84375761-46e0-4df2-a567-02f0113428d7'
VOLUME_NAME_ID = 'ee73d33c-52ed-4cb7-a8a9-2687c1205c22'
VOLUME2_NAME_ID = '63fbdd21-03bc-4309-b867-2893848f86af'
VOLUME_TYPE_ID = '4e9e6d23-eed0-426d-b90a-28f87a94b6fe'
VOLUME_TYPE_NAME = 'vol_type_name'
VOLUME_TYPE2_ID = 'c4daaf47-c530-4901-b28e-f5f0a359c4e6'
VOLUME_TYPE3_ID = 'a3d55d15-eeb1-4816-ada9-bf82decc09b3'
VOLUME_TYPE4_ID = '69943076-754d-4da8-8718-0b0117e9cab1'

View File

@ -25,7 +25,6 @@ from cinder import objects
from cinder.objects import fields
from cinder import quota
from cinder import test
from cinder.tests.unit import conf_fixture
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_group
from cinder.tests.unit import fake_group_snapshot
@ -892,12 +891,8 @@ class GroupManagerTestCase(test.TestCase):
def test_create_volume_with_group_invalid_type(self):
"""Test volume creation with group & invalid volume type."""
vol_type = db.volume_type_create(
context.get_admin_context(),
dict(name=conf_fixture.def_vol_type, extra_specs={})
)
db_vol_type = db.volume_type_get(context.get_admin_context(),
vol_type.id)
db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
'__DEFAULT__')
grp = tests_utils.create_group(
self.context,

View File

@ -18,8 +18,10 @@ from oslo_utils import timeutils
import pytz
import six
from cinder import db
from cinder.db.sqlalchemy import models
from cinder import objects
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_volume
from cinder.tests.unit import objects as test_objects
@ -118,6 +120,8 @@ class TestVolumeType(test_objects.BaseObjectsTestCase):
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
@mock.patch('cinder.db.sqlalchemy.api.volume_type_destroy')
@mock.patch.object(db.sqlalchemy.api, 'volume_type_get',
v2_fakes.fake_volume_type_get)
def test_destroy(self, volume_type_destroy, utcnow_mock):
volume_type_destroy.return_value = {
'deleted': True,

View File

@ -2239,7 +2239,8 @@ class TestVolumeSharedTargetsOnlineMigration(test.TestCase):
sqlalchemy_api.volume_create(
ctxt,
{'host': 'host1@lvm-driver1#lvm-driver1',
'service_uuid': 'f080f895-cff2-4eb3-9c61-050c060b59ad'})
'service_uuid': 'f080f895-cff2-4eb3-9c61-050c060b59ad',
'volume_type_id': fake.VOLUME_TYPE_ID})
values = {
'host': 'host1@lvm-driver1',

File diff suppressed because it is too large Load Diff

View File

@ -51,16 +51,9 @@ class QuotaIntegrationTestCase(test.TestCase):
objects.register_all()
super(QuotaIntegrationTestCase, self).setUp()
self.volume_type_name = CONF.default_volume_type
self.volume_type = objects.VolumeType(context.get_admin_context(),
name=self.volume_type_name,
description='',
is_public=False,
projects=[],
extra_specs={})
self.volume_type.create()
self.addCleanup(db.volume_type_destroy, context.get_admin_context(),
self.volume_type['id'])
self.volume_type = objects.VolumeType.get_by_name_or_id(
context.get_admin_context(),
identity=self.volume_type_name)
self.flags(quota_volumes=2,
quota_snapshots=2,
@ -164,12 +157,14 @@ class QuotaIntegrationTestCase(test.TestCase):
test_volume1 = tests_utils.create_volume(
self.context,
status='available',
host=CONF.host)
host=CONF.host,
volume_type_id=self.vt['id'])
test_volume2 = tests_utils.create_volume(
self.context,
status='available',
host=CONF.host)
volume_api = cinder.volume.api.API()
host=CONF.host,
volume_type_id=self.vt['id'])
volume_api = volume.api.API()
volume_api.create_snapshots_in_db(self.context,
[test_volume1, test_volume2],
'fake_name',
@ -1092,7 +1087,14 @@ class DbQuotaDriverTestCase(DbQuotaDriverBaseTestCase):
@mock.patch('cinder.quota.db.quota_class_get_defaults')
def test_get_project_quotas_lazy_load_defaults(
self, mock_defaults, mock_quotas):
mock_quotas.return_value = self._default_quotas_non_child
defaults = self._default_quotas_non_child
volume_types = volume.volume_types.get_all_types(
context.get_admin_context())
for vol_type in volume_types:
defaults['volumes_' + vol_type] = -1
defaults['snapshots_' + vol_type] = -1
defaults['gigabytes_' + vol_type] = -1
mock_quotas.return_value = defaults
self.driver.get_project_quotas(
FakeContext('test_project', None),
quota.QUOTAS.resources, 'test_project', usages=False)
@ -2186,9 +2188,9 @@ class QuotaVolumeTypeReservationTestCase(test.TestCase):
super(QuotaVolumeTypeReservationTestCase, self).setUp()
self.volume_type_name = CONF.default_volume_type
self.volume_type = db.volume_type_create(
self.volume_type = db.volume_type_get_by_name(
context.get_admin_context(),
dict(name=self.volume_type_name))
name=self.volume_type_name)
@mock.patch.object(quota.QUOTAS, 'reserve')
@mock.patch.object(quota.QUOTAS, 'add_volume_type_opts')

View File

@ -42,8 +42,10 @@ class VolumeGlanceMetadataTestCase(test.TestCase):
def test_vol_update_glance_metadata(self):
ctxt = context.get_admin_context()
db.volume_create(ctxt, {'id': fake.VOLUME_ID})
db.volume_create(ctxt, {'id': fake.VOLUME2_ID})
db.volume_create(ctxt, {'id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_create(ctxt, {'id': fake.VOLUME2_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID, 'key1',
'value1')
db.volume_glance_metadata_create(ctxt, fake.VOLUME2_ID, 'key1',
@ -88,9 +90,12 @@ class VolumeGlanceMetadataTestCase(test.TestCase):
def test_vols_get_glance_metadata(self):
ctxt = context.get_admin_context()
db.volume_create(ctxt, {'id': fake.VOLUME_ID})
db.volume_create(ctxt, {'id': fake.VOLUME2_ID})
db.volume_create(ctxt, {'id': '3'})
db.volume_create(ctxt, {'id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_create(ctxt, {'id': fake.VOLUME2_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_create(ctxt, {'id': '3',
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID, 'key1',
'value1')
db.volume_glance_metadata_create(ctxt, fake.VOLUME2_ID, 'key2',
@ -114,7 +119,8 @@ class VolumeGlanceMetadataTestCase(test.TestCase):
def test_vol_delete_glance_metadata(self):
ctxt = context.get_admin_context()
db.volume_create(ctxt, {'id': fake.VOLUME_ID})
db.volume_create(ctxt, {'id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_delete_by_volume(ctxt, fake.VOLUME_ID)
db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID, 'key1',
'value1')
@ -124,7 +130,8 @@ class VolumeGlanceMetadataTestCase(test.TestCase):
def test_vol_glance_metadata_copy_to_snapshot(self):
ctxt = context.get_admin_context()
db.volume_create(ctxt, {'id': fake.VOLUME_ID})
db.volume_create(ctxt, {'id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
snap = objects.Snapshot(ctxt, volume_id=fake.VOLUME_ID)
snap.create()
db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID, 'key1',
@ -143,9 +150,11 @@ class VolumeGlanceMetadataTestCase(test.TestCase):
def test_vol_glance_metadata_copy_from_volume_to_volume(self):
ctxt = context.get_admin_context()
db.volume_create(ctxt, {'id': fake.VOLUME_ID})
db.volume_create(ctxt, {'id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_create(ctxt, {'id': fake.VOLUME2_ID,
'source_volid': fake.VOLUME_ID})
'source_volid': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID, 'key1',
'value1')
db.volume_glance_metadata_copy_from_volume_to_volume(ctxt,
@ -160,8 +169,10 @@ class VolumeGlanceMetadataTestCase(test.TestCase):
self.assertEqual(value, meta[key])
def test_volume_glance_metadata_copy_to_volume(self):
vol1 = db.volume_create(self.ctxt, {})
vol2 = db.volume_create(self.ctxt, {})
vol1 = db.volume_create(self.ctxt,
{'volume_type_id': fake.VOLUME_TYPE_ID})
vol2 = db.volume_create(self.ctxt,
{'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(self.ctxt, vol1['id'], 'm1', 'v1')
snapshot = objects.Snapshot(self.ctxt, volume_id=vol1['id'])
snapshot.create()
@ -174,7 +185,8 @@ class VolumeGlanceMetadataTestCase(test.TestCase):
self.assertEqual({'m1': 'v1'}, metadata)
def test_volume_snapshot_glance_metadata_get_nonexistent(self):
vol = db.volume_create(self.ctxt, {})
vol = db.volume_create(self.ctxt,
{'volume_type_id': fake.VOLUME_TYPE_ID})
snapshot = objects.Snapshot(self.ctxt, volume_id=vol['id'])
snapshot.create()
self.assertRaises(exception.GlanceMetadataNotFound,

View File

@ -24,6 +24,7 @@ from cinder import exception
from cinder import objects
from cinder import quota
from cinder import test
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import utils
from cinder.transfer import api as transfer_api
@ -105,7 +106,8 @@ class VolumeTransferTestCase(test.TestCase):
svc = self.start_service('volume', host='test_host')
self.addCleanup(svc.stop)
tx_api = transfer_api.API()
volume = utils.create_volume(self.ctxt, updated_at=self.updated_at)
volume = utils.create_volume(self.ctxt, updated_at=self.updated_at,
volume_type_id=self.vt['id'])
transfer = tx_api.create(self.ctxt, volume.id, 'Description')
volume = objects.Volume.get_by_id(self.ctxt, volume.id)
self.assertEqual('awaiting-transfer', volume['status'],
@ -365,7 +367,10 @@ class VolumeTransferTestCase(test.TestCase):
tx_api.create, self.ctxt, volume.id, 'Description')
@mock.patch('cinder.volume.volume_utils.notify_about_volume_usage')
def test_transfer_accept_with_detail_records(self, mock_notify):
@mock.patch.object(db, 'volume_type_get', v2_fakes.fake_volume_type_get)
@mock.patch.object(quota.QUOTAS, 'reserve')
def test_transfer_accept_with_detail_records(self, mock_notify,
mock_type_get):
svc = self.start_service('volume', host='test_host')
self.addCleanup(svc.stop)
tx_api = transfer_api.API()

View File

@ -18,7 +18,6 @@ import datetime
import mock
import time
from oslo_config import cfg
from oslo_db import exception as db_exc
from oslo_utils import uuidutils
@ -224,7 +223,6 @@ class VolumeTypeTestCase(test.TestCase):
def test_get_default_volume_type(self):
"""Ensures default volume type can be retrieved."""
volume_types.create(self.ctxt, conf_fixture.def_vol_type, {})
default_vol_type = volume_types.get_default_volume_type()
self.assertEqual(conf_fixture.def_vol_type,
default_vol_type.get('name'))
@ -236,12 +234,18 @@ class VolumeTypeTestCase(test.TestCase):
is not in database.
"""
default_vol_type = volume_types.get_default_volume_type()
self.assertEqual({}, default_vol_type)
def test_get_default_volume_type_under_non_default(self):
cfg.CONF.set_default('default_volume_type', None)
self.assertEqual({}, volume_types.get_default_volume_type())
self.assertEqual(
{'created_at': default_vol_type['created_at'],
'deleted': False,
'deleted_at': None,
'description': u'Default Volume Type',
'extra_specs': {},
'id': default_vol_type['id'],
'is_public': True,
'name': u'__DEFAULT__',
'qos_specs_id': None,
'updated_at': default_vol_type['updated_at']},
default_vol_type)
def test_non_existent_vol_type_shouldnt_delete(self):
"""Ensures that volume type creation fails with invalid args."""

View File

@ -67,6 +67,7 @@ def create_volume(ctxt,
id=None,
metadata=None,
admin_metadata=None,
volume_type_id=fake.VOLUME_TYPE2_ID,
**kwargs):
"""Create a volume object in the DB."""
vol = {'size': size,
@ -78,6 +79,7 @@ def create_volume(ctxt,
'display_description': display_description,
'attach_status': fields.VolumeAttachStatus.DETACHED,
'availability_zone': availability_zone,
'volume_type_id': volume_type_id
}
if metadata:

View File

@ -1111,7 +1111,8 @@ class DS8KProxyTest(test.TestCase):
def _create_volume(self, **kwargs):
properties = {
'host': TEST_HOST_2,
'size': 1
'size': 1,
'volume_type_id': self.vt['id']
}
for p in properties.keys():
if p not in kwargs:

View File

@ -3103,7 +3103,8 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
def _create_volume(self, **kwargs):
pool = _get_test_pool()
prop = {'host': 'openstack@svc#%s' % pool,
'size': 1}
'size': 1,
'volume_type_id': self.vt['id']}
for p in prop.keys():
if p not in kwargs:
kwargs[p] = prop[p]
@ -3742,7 +3743,8 @@ class StorwizeSVCFcDriverTestCase(test.TestCase):
def _create_volume(self, **kwargs):
pool = _get_test_pool()
prop = {'host': 'openstack@svc#%s' % pool,
'size': 1}
'size': 1,
'volume_type_id': self.vt['id']}
for p in prop.keys():
if p not in kwargs:
kwargs[p] = prop[p]
@ -4798,9 +4800,13 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
pools = _get_test_pool(get_all=True)
for pool in pools:
host = 'openstack@svc#%s' % pool
vol1 = testutils.create_volume(self.ctxt, host=host)
vol1 = testutils.create_volume(
self.ctxt, host=host,
volume_type_id=self.vt['id'])
self.driver.create_volume(vol1)
vol2 = testutils.create_volume(self.ctxt, host=host)
vol2 = testutils.create_volume(
self.ctxt, host=host,
volume_type_id=self.vt['id'])
self.driver.create_volume(vol2)
for pool in pools:
pool_vols = self._get_pool_volumes(pool)
@ -4835,7 +4841,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
def _generate_vol_info(self, vol_type=None, size=10):
pool = _get_test_pool()
prop = {'size': size,
'host': 'openstack@svc#%s' % pool}
'host': 'openstack@svc#%s' % pool,
'volume_type_id': self.vt['id']}
if vol_type:
prop['volume_type_id'] = vol_type.id
vol = testutils.create_volume(self.ctxt, **prop)
@ -4859,7 +4866,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
def _create_volume(self, **kwargs):
pool = _get_test_pool()
prop = {'host': 'openstack@svc#%s' % pool,
'size': 1}
'size': 1,
'volume_type_id': self.vt['id']}
for p in prop.keys():
if p not in kwargs:
kwargs[p] = prop[p]
@ -5044,8 +5052,12 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
def test_storwize_svc_create_cloned_volume(self):
vol1 = self._create_volume()
vol2 = testutils.create_volume(self.ctxt)
vol3 = testutils.create_volume(self.ctxt)
vol2 = testutils.create_volume(
self.ctxt,
volume_type_id=self.vt['id'])
vol3 = testutils.create_volume(
self.ctxt,
volume_type_id=self.vt['id'])
# Try to clone where source size = target size
vol1['size'] = vol2['size']
@ -5097,7 +5109,9 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
new_type_ref['id'])
self.driver.create_volume(volume)
volume2 = testutils.create_volume(self.ctxt)
volume2 = testutils.create_volume(
self.ctxt,
volume_type_id=self.vt['id'])
self.driver.create_cloned_volume(volume2, volume)
if self.USESIM:
# Validate copyrate was set on the flash copy

View File

@ -393,7 +393,8 @@ class XIVProxyTest(test.TestCase):
p.ibm_storage_cli = mock.MagicMock()
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32')
self.ctxt, size=16, display_name='WTF32',
volume_type_id=self.vt['id'])
p.create_volume(volume)
p.ibm_storage_cli.cmd.vol_create.assert_called_once_with(
@ -414,7 +415,8 @@ class XIVProxyTest(test.TestCase):
p.ibm_storage_cli = mock.MagicMock()
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32')
self.ctxt, size=16, display_name='WTF32',
volume_type_id=self.vt['id'])
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
p.create_volume_from_snapshot(volume, snapshot)
@ -445,7 +447,7 @@ class XIVProxyTest(test.TestCase):
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32',
volume_type_id='b3fcacb5-fbd8-4394-8c00-06853bc13929')
volume_type_id=self.vt['id'])
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_volume, volume)
@ -478,7 +480,8 @@ class XIVProxyTest(test.TestCase):
p.targets = {'tgt1': 'info1'}
group = self._create_test_group('WTF')
vol = testutils.create_volume(self.ctxt)
vol = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
ret = p.enable_replication(self.ctxt, group, [vol])
self.assertEqual((
@ -519,7 +522,8 @@ class XIVProxyTest(test.TestCase):
p._call_remote_xiv_xcli.cmd.cg_create.side_effect = error
group = self._create_test_group('WTF')
vol = testutils.create_volume(self.ctxt)
vol = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
ret = p.enable_replication(self.ctxt, group, [vol])
self.assertEqual((
@ -581,7 +585,8 @@ class XIVProxyTest(test.TestCase):
driver)
group = self._create_test_group('WTF')
group.replication_status = fields.ReplicationStatus.FAILED_OVER
vol = testutils.create_volume(self.ctxt)
vol = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
group_update, vol_update = p.failover_replication(self.ctxt, group,
[vol], 'default')
updates = {'status': 'available'}
@ -615,7 +620,8 @@ class XIVProxyTest(test.TestCase):
group = self._create_test_group('WTF')
failed_over = fields.ReplicationStatus.FAILED_OVER
group.replication_status = failed_over
vol = testutils.create_volume(self.ctxt)
vol = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
group_update, vol_update = p.failover_replication(self.ctxt, group,
[vol],
'secondary_id')
@ -807,7 +813,7 @@ class XIVProxyTest(test.TestCase):
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32',
volume_type_id='b3fcacb5-fbd8-4394-8c00-06853bc13929')
volume_type_id=self.vt['id'])
volume.group = None
p.create_volume(volume)
@ -835,7 +841,7 @@ class XIVProxyTest(test.TestCase):
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32',
volume_type_id='b3fcacb5-fbd8-4394-8c00-06853bc13929')
volume_type_id=self.vt['id'])
grp = testutils.create_group(self.ctxt, name='bla', group_type_id='1')
volume.group = grp
ex = getattr(p, "_get_exception")()
@ -861,7 +867,7 @@ class XIVProxyTest(test.TestCase):
p.ibm_storage_cli = mock.MagicMock()
volume = testutils.create_volume(
self.ctxt, size=16, display_name='WTF32',
volume_type_id='b3fcacb5-fbd8-4394-8c00-06853bc13929')
volume_type_id=self.vt['id'])
volume.group = None
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_volume, volume)
@ -1879,7 +1885,8 @@ class XIVProxyTest(test.TestCase):
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
volume = testutils.create_volume(self.ctxt)
volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
model_update, vols_model_update = p.create_group_from_src(
@ -1908,8 +1915,10 @@ class XIVProxyTest(test.TestCase):
group_obj = self._create_test_group()
src_group_obj = self._create_test_group(g_name='src_group')
volume = testutils.create_volume(self.ctxt)
src_volume = testutils.create_volume(self.ctxt)
volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
src_volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
model_update, vols_model_update = p.create_group_from_src(
{}, group_obj, [volume],
@ -1939,7 +1948,8 @@ class XIVProxyTest(test.TestCase):
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
volume = testutils.create_volume(self.ctxt)
volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
ex = getattr(p, "_get_exception")()
@ -1965,8 +1975,10 @@ class XIVProxyTest(test.TestCase):
group_obj = self._create_test_group()
src_group_obj = self._create_test_group(g_name='src_group')
volume = testutils.create_volume(self.ctxt)
src_volume = testutils.create_volume(self.ctxt)
volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
src_volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_from_src, {},
@ -1992,7 +2004,8 @@ class XIVProxyTest(test.TestCase):
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
volume = testutils.create_volume(self.ctxt)
volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
ex = getattr(p, "_get_exception")()
@ -2018,8 +2031,10 @@ class XIVProxyTest(test.TestCase):
group_obj = self._create_test_group()
src_group_obj = self._create_test_group(g_name='src_group')
volume = testutils.create_volume(self.ctxt)
src_volume = testutils.create_volume(self.ctxt)
volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
src_volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_from_src, {},
@ -2045,7 +2060,8 @@ class XIVProxyTest(test.TestCase):
group_obj = self._create_test_group()
cgsnap_group_obj = self._create_test_cgsnapshot(group_obj.id)
volume = testutils.create_volume(self.ctxt)
volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
snapshot = testutils.create_snapshot(self.ctxt, volume.id)
ex = getattr(p, "_get_exception")()
@ -2071,8 +2087,10 @@ class XIVProxyTest(test.TestCase):
group_obj = self._create_test_group()
src_group_obj = self._create_test_group(g_name='src_group')
volume = testutils.create_volume(self.ctxt)
src_volume = testutils.create_volume(self.ctxt)
volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
src_volume = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.create_group_from_src, {},
@ -2244,8 +2262,10 @@ class XIVProxyTest(test.TestCase):
p.ibm_storage_cli = mock.MagicMock()
group_obj = self._create_test_group()
vol_add = testutils.create_volume(self.ctxt, display_name='WTF32')
vol_remove = testutils.create_volume(self.ctxt, display_name='WTF64')
vol_add = testutils.create_volume(self.ctxt, display_name='WTF32',
volume_type_id=self.vt['id'])
vol_remove = testutils.create_volume(self.ctxt, display_name='WTF64',
volume_type_id=self.vt['id'])
model_update, add_model_update, remove_model_update = (
p.update_group({}, group_obj, [vol_add], [vol_remove]))
@ -2272,7 +2292,8 @@ class XIVProxyTest(test.TestCase):
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
vol_add = testutils.create_volume(self.ctxt, display_name='WTF32')
vol_add = testutils.create_volume(self.ctxt, display_name='WTF32',
volume_type_id=self.vt['id'])
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.update_group, {}, group_obj, [vol_add], [])
@ -2293,7 +2314,8 @@ class XIVProxyTest(test.TestCase):
'bla', 'bla', ElementTree.Element('bla'))
group_obj = self._create_test_group()
vol_remove = testutils.create_volume(self.ctxt)
vol_remove = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
ex = getattr(p, "_get_exception")()
self.assertRaises(ex, p.update_group, {},
@ -2316,7 +2338,8 @@ class XIVProxyTest(test.TestCase):
'bla', 'bla', ElementTree.Element('bla')))
group_obj = self._create_test_group()
vol_remove = testutils.create_volume(self.ctxt)
vol_remove = testutils.create_volume(self.ctxt,
volume_type_id=self.vt['id'])
model_update, add_model_update, remove_model_update = (
p.update_group({}, group_obj, [], [vol_remove]))
@ -2548,9 +2571,11 @@ class XIVProxyTest(test.TestCase):
driver)
vol_src = testutils.create_volume(self.ctxt, display_name='bla',
size=17)
size=17,
volume_type_id=self.vt['id'])
vol_trg = testutils.create_volume(self.ctxt, display_name='bla',
size=17)
size=17,
volume_type_id=self.vt['id'])
p.ibm_storage_cli = mock.MagicMock()
p._cg_name_from_volume = mock.MagicMock(return_value="cg")
@ -2586,7 +2611,8 @@ class XIVProxyTest(test.TestCase):
xiv_replication.VolumeReplication = mock.MagicMock()
grp = testutils.create_group(self.ctxt, name='bla', group_type_id='1')
volume = testutils.create_volume(self.ctxt, display_name='bla')
volume = testutils.create_volume(self.ctxt, display_name='bla',
volume_type_id=self.vt['id'])
volume.group = grp
ret_val = p.handle_created_vol_properties({'enabled': True}, volume)

View File

@ -289,7 +289,8 @@ class InStorageMCSCommonDriverTestCase(test.TestCase):
def _generate_vol_info(self, vol_name, vol_id):
pool = fakes.get_test_pool()
prop = {'mdisk_grp_name': pool}
prop = {'mdisk_grp_name': pool,
'volume_type_id': self.vt['id']}
if vol_name:
prop.update(volume_name=vol_name,
volume_id=vol_id,
@ -309,7 +310,8 @@ class InStorageMCSCommonDriverTestCase(test.TestCase):
def _create_volume(self, **kwargs):
pool = fakes.get_test_pool()
prop = {'host': 'openstack@mcs#%s' % pool,
'size': 1}
'size': 1,
'volume_type_id': self.vt['id']}
for p in prop.keys():
if p not in kwargs:
kwargs[p] = prop[p]
@ -403,7 +405,9 @@ class InStorageMCSCommonDriverTestCase(test.TestCase):
'_get_vdisk_params')
def test_instorage_mcs_create_volume_with_qos(self, get_vdisk_params,
add_vdisk_qos):
vol = testutils.create_volume(self.ctxt)
vol = testutils.create_volume(
self.ctxt,
volume_type_id=self.vt['id'])
fake_opts = self._get_default_opts()
# If the qos is empty, chvdisk should not be called
# for create_volume.
@ -470,8 +474,12 @@ class InStorageMCSCommonDriverTestCase(test.TestCase):
def test_instorage_mcs_create_cloned_volume(self):
vol1 = self._create_volume()
vol2 = testutils.create_volume(self.ctxt)
vol3 = testutils.create_volume(self.ctxt)
vol2 = testutils.create_volume(
self.ctxt,
volume_type_id=self.vt['id'])
vol3 = testutils.create_volume(
self.ctxt,
volume_type_id=self.vt['id'])
# Try to clone where source size > target size
vol1['size'] = vol2['size'] + 1

View File

@ -78,7 +78,8 @@ class InStorageMCSFcDriverTestCase(test.TestCase):
def _create_volume(self, **kwargs):
pool = fakes.get_test_pool()
prop = {'host': 'openstack@mcs#%s' % pool,
'size': 1}
'size': 1,
'volume_type_id': self.vt['id']}
for p in prop.keys():
if p not in kwargs:
kwargs[p] = prop[p]

View File

@ -78,7 +78,8 @@ class InStorageMCSISCSIDriverTestCase(test.TestCase):
def _create_volume(self, **kwargs):
pool = fakes.get_test_pool()
prop = {'host': 'openstack@mcs#%s' % pool,
'size': 1}
'size': 1,
'volume_type_id': self.vt['id']}
for p in prop.keys():
if p not in kwargs:
kwargs[p] = prop[p]

View File

@ -307,7 +307,8 @@ class TestNexentaISCSIDriver(test.TestCase):
'id': '1',
'size': 1,
'status': 'available',
'provider_location': self.TEST_VOLUME_NAME
'provider_location': self.TEST_VOLUME_NAME,
'volume_type_id': self.vt['id']
}
return db.volume_create(self.ctxt, vol)['id']
@ -368,7 +369,8 @@ class TestNexentaNfsDriver(test.TestCase):
'id': '1',
'size': 1,
'status': 'available',
'provider_location': self.TEST_EXPORT1
'provider_location': self.TEST_EXPORT1,
'volume_type_id': self.vt['id']
}
self.drv.share2nms = {self.TEST_EXPORT1: self.nms_mock}
return db.volume_create(self.ctxt, vol)['id']

View File

@ -25,6 +25,7 @@ from cinder.message import message_field
from cinder import objects
from cinder.objects import fields
from cinder.tests import fake_driver
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_volume
from cinder.tests.unit import utils as tests_utils
@ -40,6 +41,11 @@ class DiscardFlagTestCase(base.BaseVolumeTestCase):
def setUp(self):
super(DiscardFlagTestCase, self).setUp()
self.volume.driver = mock.MagicMock()
db.volume_type_create(self.context,
v2_fakes.fake_default_type_get(
fake.VOLUME_TYPE2_ID))
self.vol_type = db.volume_type_get_by_name(self.context,
'vol_type_name')
@ddt.data(dict(config_discard_flag=True,
driver_discard_flag=None,
@ -102,6 +108,15 @@ class DiscardFlagTestCase(base.BaseVolumeTestCase):
class VolumeConnectionTestCase(base.BaseVolumeTestCase):
def setUp(self, *args, **kwargs):
super(VolumeConnectionTestCase, self).setUp()
db.volume_type_create(self.context,
v2_fakes.fake_default_type_get(
fake.VOLUME_TYPE2_ID))
self.vol_type = db.volume_type_get_by_name(self.context,
'vol_type_name')
@mock.patch.object(cinder.volume.targets.iscsi.ISCSITarget,
'_get_target_chap_auth')
@mock.patch.object(db, 'volume_admin_metadata_get')
@ -368,7 +383,7 @@ class VolumeConnectionTestCase(base.BaseVolumeTestCase):
"""Test exception path for create_export failure."""
volume = tests_utils.create_volume(
self.context, admin_metadata={'fake-key': 'fake-value'},
volume_type_id=fake.VOLUME_TYPE_ID, **self.volume_params)
**self.volume_params)
_mock_create_export.side_effect = exception.CinderException
connector = {'ip': 'IP', 'initiator': 'INITIATOR'}
@ -399,6 +414,11 @@ class VolumeAttachDetachTestCase(base.BaseVolumeTestCase):
self.patch('cinder.volume.volume_utils.clear_volume', autospec=True)
self.user_context = context.RequestContext(user_id=fake.USER_ID,
project_id=fake.PROJECT_ID)
db.volume_type_create(self.context,
v2_fakes.fake_default_type_get(
fake.VOLUME_TYPE2_ID))
self.vol_type = db.volume_type_get_by_name(self.context,
'vol_type_name')
@ddt.data(False, True)
def test_run_attach_detach_volume_for_instance(self, volume_object):

View File

@ -256,7 +256,8 @@ class GenericVolumeDriverTestCase(BaseDriverTestCase):
'host': 'fakehost',
'cluster_name': 'fakecluster',
'availability_zone': 'fakezone',
'size': 1}
'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID}
vol = fake_volume.fake_volume_obj(self.context, **volume_dict)
snapshot = fake_snapshot.fake_snapshot_obj(self.context)

View File

@ -30,6 +30,7 @@ from cinder import objects
from cinder.objects import fields
from cinder import quota
from cinder.tests import fake_driver
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit.image import fake as fake_image
from cinder.tests.unit import utils as tests_utils
@ -79,8 +80,11 @@ class CopyVolumeToImageTestCase(base.BaseVolumeTestCase):
'display_description': 'Test Desc',
'size': 20,
'status': 'uploading',
'host': 'dummy'
'host': 'dummy',
'volume_type_id': fake.VOLUME_TYPE_ID
}
self.mock_object(db.sqlalchemy.api, 'volume_type_get',
v2_fakes.fake_volume_type_get)
def test_copy_volume_to_image_status_available(self):
# creating volume testdata
@ -437,6 +441,14 @@ class ImageVolumeCacheTestCase(base.BaseVolumeTestCase):
class ImageVolumeTestCases(base.BaseVolumeTestCase):
def setUp(self):
super(ImageVolumeTestCases, self).setUp()
db.volume_type_create(self.context,
v2_fakes.fake_default_type_get(
fake.VOLUME_TYPE2_ID))
self.vol_type = db.volume_type_get_by_name(self.context,
'vol_type_name')
@mock.patch('cinder.volume.drivers.lvm.LVMVolumeDriver.'
'create_cloned_volume')
@mock.patch('cinder.quota.QUOTAS.rollback')
@ -453,7 +465,9 @@ class ImageVolumeTestCases(base.BaseVolumeTestCase):
self.assertNotEqual(False, result)
mock_reserve.assert_called_once_with(self.context, volumes=1,
gigabytes=vol.size)
volumes_vol_type_name=1,
gigabytes=vol.size,
gigabytes_vol_type_name=vol.size)
mock_commit.assert_called_once_with(self.context, ["RESERVATION"],
project_id=vol.project_id)
@ -468,7 +482,9 @@ class ImageVolumeTestCases(base.BaseVolumeTestCase):
self.context, vol, {'id': fake.VOLUME_ID}))
mock_reserve.assert_called_once_with(self.context, volumes=1,
gigabytes=vol.size)
volumes_vol_type_name=1,
gigabytes=vol.size,
gigabytes_vol_type_name=vol.size)
mock_rollback.assert_called_once_with(self.context, ["RESERVATION"])
@mock.patch('cinder.image.image_utils.qemu_img_info')
@ -669,7 +685,8 @@ class ImageVolumeTestCases(base.BaseVolumeTestCase):
volume_api = cinder.volume.api.API(
image_service=FakeImageService())
volume = volume_api.create(self.context, 2, 'name', 'description',
image_id=self.FAKE_UUID)
image_id=self.FAKE_UUID,
volume_type=self.vol_type)
volume_id = volume['id']
self.assertEqual('creating', volume['status'])

View File

@ -52,6 +52,7 @@ class VolumeRPCAPITestCase(test.RPCAPITestCase):
vol['attach_status'] = "detached"
vol['metadata'] = {"test_key": "test_val"}
vol['size'] = 1
vol['volume_type_id'] = fake.VOLUME_TYPE_ID
volume = db.volume_create(self.context, vol)
kwargs = {

View File

@ -30,6 +30,7 @@ from cinder import objects
from cinder.objects import fields
from cinder import quota
from cinder import test
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit.brick import fake_lvm
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import utils as tests_utils
@ -66,6 +67,15 @@ def create_snapshot(volume_id, size=1, metadata=None, ctxt=None,
@ddt.ddt
class SnapshotTestCase(base.BaseVolumeTestCase):
def setUp(self, *args, **kwargs):
super(SnapshotTestCase, self).setUp()
db.volume_type_create(self.context,
v2_fakes.fake_default_type_get(
fake.VOLUME_TYPE2_ID))
self.vol_type = db.volume_type_get_by_name(self.context,
'vol_type_name')
def test_delete_snapshot_frozen(self):
service = tests_utils.create_service(self.context, {'frozen': True})
volume = tests_utils.create_volume(self.context, host=service.host)

View File

@ -42,6 +42,7 @@ from cinder.objects import fields
from cinder.policies import volumes as vol_policy
from cinder import quota
from cinder.tests import fake_driver
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit import conf_fixture
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_snapshot
@ -97,6 +98,17 @@ class VolumeTestCase(base.BaseVolumeTestCase):
self.service_id = 1
self.user_context = context.RequestContext(user_id=fake.USER_ID,
project_id=fake.PROJECT_ID)
elevated = context.get_admin_context()
db.volume_type_create(elevated,
v2_fakes.fake_default_type_get(
id=fake.VOLUME_TYPE2_ID))
self.vol_type = db.volume_type_get_by_name(elevated, '__DEFAULT__')
def _create_volume(self, context, **kwargs):
return tests_utils.create_volume(
context,
volume_type_id=volume_types.get_default_volume_type()['id'],
**kwargs)
@mock.patch('cinder.objects.service.Service.get_minimum_rpc_version')
@mock.patch('cinder.objects.service.Service.get_minimum_obj_version')
@ -560,14 +572,16 @@ class VolumeTestCase(base.BaseVolumeTestCase):
volume = volume_api.create(self.context,
1,
'name',
'description')
'description',
volume_type=self.vol_type)
self.assertEqual('az2', volume['availability_zone'])
self.override_config('default_availability_zone', 'default-az')
volume = volume_api.create(self.context,
1,
'name',
'description')
'description',
volume_type=self.vol_type)
self.assertEqual('default-az', volume['availability_zone'])
@mock.patch('cinder.quota.QUOTAS.rollback', new=mock.MagicMock())
@ -582,15 +596,12 @@ class VolumeTestCase(base.BaseVolumeTestCase):
volume = volume_api.create(self.context,
1,
'name',
'description')
self.assertIsNone(volume['volume_type_id'])
'description',
volume_type=self.vol_type)
self.assertIsNone(volume['encryption_key_id'])
# Create default volume type
vol_type = conf_fixture.def_vol_type
db.volume_type_create(context.get_admin_context(),
{'name': vol_type, 'extra_specs': {}})
db_vol_type = db.volume_type_get_by_name(context.get_admin_context(),
vol_type)
@ -646,7 +657,8 @@ class VolumeTestCase(base.BaseVolumeTestCase):
"""
volume_api = cinder.volume.api.API()
volume = volume_api.create(
self.context, 1, 'name', 'description', multiattach=True)
self.context, 1, 'name', 'description', multiattach=True,
volume_type=self.vol_type)
self.assertTrue(volume.multiattach)
def _fail_multiattach_policy_authorize(self, policy):
@ -2167,7 +2179,8 @@ class VolumeTestCase(base.BaseVolumeTestCase):
volume = volume_api.create(self.context,
size,
'name',
'description')
'description',
volume_type=self.vol_type)
self.assertEqual(int(size), volume['size'])
def test_create_volume_int_size(self):
@ -2281,12 +2294,14 @@ class VolumeTestCase(base.BaseVolumeTestCase):
ctxt = context.get_admin_context()
db.volume_create(ctxt, {'id': 'fake1', 'status': 'available',
'host': 'test', 'provider_location': '',
'size': 1})
'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(ctxt, 'fake1', 'key1', 'value1')
db.volume_glance_metadata_create(ctxt, 'fake1', 'key2', 'value2')
db.volume_create(ctxt, {'id': 'fake2', 'status': 'available',
'host': 'test', 'provider_location': '',
'size': 1})
'size': 1,
'volume_type_id': fake.VOLUME_TYPE_ID})
db.volume_glance_metadata_create(ctxt, 'fake2', 'key3', 'value3')
db.volume_glance_metadata_create(ctxt, 'fake2', 'key4', 'value4')
volume_api = cinder.volume.api.API()
@ -2299,8 +2314,8 @@ class VolumeTestCase(base.BaseVolumeTestCase):
@mock.patch.object(QUOTAS, 'limit_check')
@mock.patch.object(QUOTAS, 'reserve')
def test_extend_attached_volume(self, reserve, limit_check):
volume = tests_utils.create_volume(self.context, size=2,
status='available', host=CONF.host)
volume = self._create_volume(self.context, size=2,
status='available', host=CONF.host)
volume_api = cinder.volume.api.API()
self.assertRaises(exception.InvalidVolume,
@ -2316,6 +2331,7 @@ class VolumeTestCase(base.BaseVolumeTestCase):
self.assertEqual('extending', volume.status)
self.assertEqual('in-use', volume.previous_status)
reserve.assert_called_once_with(self.context, gigabytes=1,
gigabytes___DEFAULT__=1,
project_id=volume.project_id)
limit_check.side_effect = None
reserve.side_effect = None
@ -2326,7 +2342,7 @@ class VolumeTestCase(base.BaseVolumeTestCase):
request_spec = {
'volume_properties': volume,
'volume_type': {},
'volume_type': self.vol_type,
'volume_id': volume.id
}
volume_api.scheduler_rpcapi.extend_volume.assert_called_once_with(
@ -2339,8 +2355,8 @@ class VolumeTestCase(base.BaseVolumeTestCase):
def test_extend_volume(self, reserve, limit_check):
"""Test volume can be extended at API level."""
# create a volume and assign to host
volume = tests_utils.create_volume(self.context, size=2,
status='in-use', host=CONF.host)
volume = self._create_volume(self.context, size=2,
status='in-use', host=CONF.host)
volume_api = cinder.volume.api.API()
# Extend fails when status != available
@ -2373,6 +2389,7 @@ class VolumeTestCase(base.BaseVolumeTestCase):
self.assertEqual('extending', volume.status)
self.assertEqual('available', volume.previous_status)
reserve.assert_called_once_with(self.context, gigabytes=1,
gigabytes___DEFAULT__=1,
project_id=volume.project_id)
# Test the quota exceeded
@ -2404,7 +2421,7 @@ class VolumeTestCase(base.BaseVolumeTestCase):
request_spec = {
'volume_properties': volume,
'volume_type': {},
'volume_type': self.vol_type,
'volume_id': volume.id
}
volume_api.scheduler_rpcapi.extend_volume.assert_called_once_with(
@ -2603,9 +2620,9 @@ class VolumeTestCase(base.BaseVolumeTestCase):
"""Test volume can't be cloned from an other volume in different az."""
volume_api = cinder.volume.api.API()
volume_src = tests_utils.create_volume(self.context,
availability_zone='az2',
**self.volume_params)
volume_src = self._create_volume(self.context,
availability_zone='az2',
**self.volume_params)
self.volume.create_volume(self.context, volume_src)
volume_src = db.volume_get(self.context, volume_src['id'])
@ -2614,7 +2631,11 @@ class VolumeTestCase(base.BaseVolumeTestCase):
size=1,
name='fake_name',
description='fake_desc',
source_volume=volume_src)
source_volume=volume_src,
volume_type=
objects.VolumeType.get_by_name_or_id(
self.context,
self.vol_type['id']))
self.assertEqual('az2', volume_dst['availability_zone'])
self.assertRaises(exception.InvalidInput,

View File

@ -37,6 +37,7 @@ class GetActiveByWindowTestCase(base.BaseVolumeTestCase):
'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
'deleted': True, 'status': 'deleted',
'deleted_at': datetime.datetime(1, 2, 1, 1, 1, 1),
'volume_type_id': fake.VOLUME_TYPE_ID,
},
{
'id': fake.VOLUME2_ID,
@ -45,6 +46,7 @@ class GetActiveByWindowTestCase(base.BaseVolumeTestCase):
'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
'deleted': True, 'status': 'deleted',
'deleted_at': datetime.datetime(1, 3, 10, 1, 1, 1),
'volume_type_id': fake.VOLUME_TYPE_ID,
},
{
'id': fake.VOLUME3_ID,
@ -53,18 +55,21 @@ class GetActiveByWindowTestCase(base.BaseVolumeTestCase):
'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
'deleted': True, 'status': 'deleted',
'deleted_at': datetime.datetime(1, 5, 1, 1, 1, 1),
'volume_type_id': fake.VOLUME_TYPE_ID,
},
{
'id': fake.VOLUME4_ID,
'host': 'devstack',
'project_id': fake.PROJECT_ID,
'created_at': datetime.datetime(1, 3, 10, 1, 1, 1),
'volume_type_id': fake.VOLUME_TYPE_ID,
},
{
'id': fake.VOLUME5_ID,
'host': 'devstack',
'project_id': fake.PROJECT_ID,
'created_at': datetime.datetime(1, 5, 1, 1, 1, 1),
'volume_type_id': fake.VOLUME_TYPE_ID,
}
]
@ -77,6 +82,7 @@ class GetActiveByWindowTestCase(base.BaseVolumeTestCase):
'status': fields.SnapshotStatus.DELETED,
'deleted_at': datetime.datetime(1, 2, 1, 1, 1, 1),
'volume_id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID,
},
{
@ -87,6 +93,7 @@ class GetActiveByWindowTestCase(base.BaseVolumeTestCase):
'status': fields.SnapshotStatus.DELETED,
'deleted_at': datetime.datetime(1, 3, 10, 1, 1, 1),
'volume_id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID,
},
{
'id': fake.SNAPSHOT3_ID,
@ -96,18 +103,21 @@ class GetActiveByWindowTestCase(base.BaseVolumeTestCase):
'status': fields.SnapshotStatus.DELETED,
'deleted_at': datetime.datetime(1, 5, 1, 1, 1, 1),
'volume_id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID,
},
{
'id': fake.SNAPSHOT_ID,
'project_id': 'p1',
'created_at': datetime.datetime(1, 3, 10, 1, 1, 1),
'volume_id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID,
},
{
'id': fake.SNAPSHOT2_ID,
'project_id': 'p1',
'created_at': datetime.datetime(1, 5, 1, 1, 1, 1),
'volume_id': fake.VOLUME_ID
'volume_id': fake.VOLUME_ID,
'volume_type_id': fake.VOLUME_TYPE_ID
}
]
@ -183,7 +193,9 @@ class GetActiveByWindowTestCase(base.BaseVolumeTestCase):
def test_snapshot_get_all_active_by_window(self):
# Find all all snapshots valid within a timeframe window.
db.volume_create(self.context, {'id': fake.VOLUME_ID})
db.volume_create(self.context, {'id': fake.VOLUME_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
for i in range(5):
self.db_vol_attrs[i]['volume_id'] = fake.VOLUME_ID
@ -226,7 +238,9 @@ class GetActiveByWindowTestCase(base.BaseVolumeTestCase):
def test_backup_get_all_active_by_window(self):
# Find all backups valid within a timeframe window.
db.volume_create(self.context, {'id': fake.VOLUME_ID})
db.volume_create(self.context, {'id': fake.VOLUME_ID,
'volume_type_id':
fake.VOLUME_TYPE_ID})
for i in range(5):
self.db_back_attrs[i]['volume_id'] = fake.VOLUME_ID

View File

@ -38,6 +38,7 @@ LOG = logging.getLogger(__name__)
QUOTAS = quota.QUOTAS
ENCRYPTION_IGNORED_FIELDS = ['volume_type_id', 'created_at', 'updated_at',
'deleted_at', 'encryption_id']
DEFAULT_VOLUME_TYPE = "__DEFAULT__"
def create(context,
@ -102,6 +103,9 @@ def destroy(context, id):
if id is None:
msg = _("id cannot be None")
raise exception.InvalidVolumeType(reason=msg)
vol_type = get_volume_type(context, id)
if vol_type['name'] == DEFAULT_VOLUME_TYPE:
raise exception.VolumeTypeDefault(vol_type['name'])
elevated = context if context.is_admin else context.elevated()
return db.volume_type_destroy(elevated, id)
@ -169,17 +173,19 @@ def get_default_volume_type():
"""Get the default volume type."""
name = CONF.default_volume_type
vol_type = {}
if name is not None:
ctxt = context.get_admin_context()
ctxt = context.get_admin_context()
if name:
try:
vol_type = get_volume_type_by_name(ctxt, name)
except exception.VolumeTypeNotFoundByName:
# Couldn't find volume type with the name in default_volume_type
# flag, record this issue and move on
# flag, record this issue and raise exception
# TODO(zhiteng) consider add notification to warn admin
LOG.exception('Default volume type is not found. '
'Please check default_volume_type config:')
raise exception.VolumeTypeNotFoundByName(volume_type_name=name)
else:
vol_type = get_volume_type_by_name(ctxt, DEFAULT_VOLUME_TYPE)
return vol_type

View File

@ -0,0 +1,10 @@
---
features:
- |
Added a new default volume type ``__DEFAULT__`` which
will be used when
- A new volume is created without any type
- The `default_volume_type` option is unset in cinder.conf
The volume will be assigned the ``__DEFAULT__`` type.
All existing volume, snapshots without a type will
be migrated to the ``__DEFAULT__`` type.