From a550ade303c839abc285d6926dc02a15b5c73ff0 Mon Sep 17 00:00:00 2001 From: whoami-rajat Date: Tue, 26 Feb 2019 00:33:34 +0530 Subject: [PATCH] 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 --- .../volume-types-list-response.json | 25 +- .../volumes/volume-create-response.json | 2 +- .../samples/volumes/volume-show-response.json | 2 +- .../volumes/volume-update-response.json | 2 +- .../volumes-list-detailed-response.json | 2 +- cinder/api/contrib/types_manage.py | 5 + cinder/api/v2/volumes.py | 6 + cinder/api/v3/volumes.py | 6 + cinder/cmd/manage.py | 6 +- cinder/db/api.py | 7 + cinder/db/sqlalchemy/api.py | 47 ++ .../132_create_default_volume_type.py | 45 ++ cinder/exception.py | 5 + cinder/objects/snapshot.py | 5 + cinder/objects/volume.py | 5 + cinder/test.py | 6 + .../volume-types-list-response.json.tpl | 21 +- .../volumes/volume-create-response.json.tpl | 2 +- .../volumes/volume-show-response.json.tpl | 2 +- .../volumes/volume-update-response.json.tpl | 2 +- .../volumes-list-detailed-response.json.tpl | 2 +- .../unit/api/contrib/test_admin_actions.py | 85 ++- .../api/contrib/test_consistencygroups.py | 15 +- .../unit/api/contrib/test_scheduler_hints.py | 8 +- .../unit/api/contrib/test_volume_actions.py | 7 +- .../test_volume_encryption_metadata.py | 1 + .../api/contrib/test_volume_image_metadata.py | 9 +- .../unit/api/contrib/test_volume_transfer.py | 8 +- cinder/tests/unit/api/v2/fakes.py | 19 +- .../unit/api/v2/test_snapshot_metadata.py | 6 +- cinder/tests/unit/api/v2/test_snapshots.py | 17 +- cinder/tests/unit/api/v2/test_types.py | 27 +- .../tests/unit/api/v2/test_volume_metadata.py | 3 +- cinder/tests/unit/api/v2/test_volumes.py | 69 +- cinder/tests/unit/api/v3/test_snapshots.py | 8 +- cinder/tests/unit/api/v3/test_types.py | 4 +- .../tests/unit/api/v3/test_volume_transfer.py | 8 +- cinder/tests/unit/api/v3/test_volumes.py | 61 +- .../unit/attachments/test_attachments_api.py | 3 + .../attachments/test_attachments_manager.py | 6 +- .../unit/backup/drivers/test_backup_ceph.py | 3 +- .../backup/drivers/test_backup_driver_base.py | 44 +- .../unit/backup/drivers/test_backup_google.py | 3 +- .../unit/backup/drivers/test_backup_nfs.py | 3 +- .../unit/backup/drivers/test_backup_swift.py | 3 +- .../unit/backup/drivers/test_backup_tsm.py | 3 +- cinder/tests/unit/backup/test_backup.py | 3 + cinder/tests/unit/conf_fixture.py | 2 +- cinder/tests/unit/db/test_migrations.py | 9 + cinder/tests/unit/db/test_purge.py | 15 +- cinder/tests/unit/fake_constants.py | 1 + .../tests/unit/group/test_groups_manager.py | 9 +- cinder/tests/unit/objects/test_volume_type.py | 4 + cinder/tests/unit/test_cmd.py | 3 +- cinder/tests/unit/test_db_api.py | 590 ++++++++++++------ cinder/tests/unit/test_quota.py | 34 +- .../tests/unit/test_volume_glance_metadata.py | 36 +- cinder/tests/unit/test_volume_transfer.py | 9 +- cinder/tests/unit/test_volume_types.py | 20 +- cinder/tests/unit/utils.py | 2 + .../volume/drivers/ibm/test_ds8k_proxy.py | 3 +- .../volume/drivers/ibm/test_storwize_svc.py | 32 +- .../unit/volume/drivers/ibm/test_xiv_proxy.py | 86 ++- .../drivers/inspur/instorage/test_common.py | 18 +- .../inspur/instorage/test_fc_driver.py | 3 +- .../inspur/instorage/test_iscsi_driver.py | 3 +- .../volume/drivers/nexenta/test_nexenta.py | 6 +- cinder/tests/unit/volume/test_connection.py | 22 +- cinder/tests/unit/volume/test_driver.py | 3 +- cinder/tests/unit/volume/test_image.py | 25 +- cinder/tests/unit/volume/test_rpcapi.py | 1 + cinder/tests/unit/volume/test_snapshot.py | 10 + cinder/tests/unit/volume/test_volume.py | 63 +- .../unit/volume/test_volume_usage_audit.py | 20 +- cinder/volume/volume_types.py | 14 +- ...yped_to_default_type-0068e6bc8000986c.yaml | 10 + 76 files changed, 1188 insertions(+), 496 deletions(-) create mode 100644 cinder/db/sqlalchemy/migrate_repo/versions/132_create_default_volume_type.py create mode 100644 releasenotes/notes/untyped_to_default_type-0068e6bc8000986c.yaml diff --git a/api-ref/source/v3/samples/volume_type/volume-types-list-response.json b/api-ref/source/v3/samples/volume_type/volume-types-list-response.json index 06f71707b4c..1a33fbd05ed 100644 --- a/api-ref/source/v3/samples/volume_type/volume-types-list-response.json +++ b/api-ref/source/v3/samples/volume_type/volume-types-list-response.json @@ -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 } ] -} +} \ No newline at end of file diff --git a/api-ref/source/v3/samples/volumes/volume-create-response.json b/api-ref/source/v3/samples/volumes/volume-create-response.json index 8a6f47665eb..30feb2ac669 100644 --- a/api-ref/source/v3/samples/volumes/volume-create-response.json +++ b/api-ref/source/v3/samples/volumes/volume-create-response.json @@ -29,6 +29,6 @@ "status": "creating", "updated_at": null, "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e", - "volume_type": null + "volume_type": "__DEFAULT__" } } \ No newline at end of file diff --git a/api-ref/source/v3/samples/volumes/volume-show-response.json b/api-ref/source/v3/samples/volumes/volume-show-response.json index 269130f731a..186411e9012 100644 --- a/api-ref/source/v3/samples/volumes/volume-show-response.json +++ b/api-ref/source/v3/samples/volumes/volume-show-response.json @@ -33,6 +33,6 @@ "status": "creating", "updated_at": null, "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e", - "volume_type": null + "volume_type": "__DEFAULT__" } } \ No newline at end of file diff --git a/api-ref/source/v3/samples/volumes/volume-update-response.json b/api-ref/source/v3/samples/volumes/volume-update-response.json index 56c544ee4e8..4a587f679d9 100644 --- a/api-ref/source/v3/samples/volumes/volume-update-response.json +++ b/api-ref/source/v3/samples/volumes/volume-update-response.json @@ -31,6 +31,6 @@ "status": "creating", "updated_at": null, "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e", - "volume_type": null + "volume_type": "__DEFAULT__" } } \ No newline at end of file diff --git a/api-ref/source/v3/samples/volumes/volumes-list-detailed-response.json b/api-ref/source/v3/samples/volumes/volumes-list-detailed-response.json index 4204a9a06d7..1a012ad81ac 100644 --- a/api-ref/source/v3/samples/volumes/volumes-list-detailed-response.json +++ b/api-ref/source/v3/samples/volumes/volumes-list-detailed-response.json @@ -34,7 +34,7 @@ "status": "creating", "updated_at": null, "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e", - "volume_type": null + "volume_type": "__DEFAULT__" } ] } \ No newline at end of file diff --git a/cinder/api/contrib/types_manage.py b/cinder/api/contrib/types_manage.py index d302ff9217f..34104095852 100644 --- a/cinder/api/contrib/types_manage.py +++ b/cinder/api/contrib/types_manage.py @@ -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) diff --git a/cinder/api/v2/volumes.py b/cinder/api/v2/volumes.py index 86d2b082e5a..d2b7a6bc616 100644 --- a/cinder/api/v2/volumes.py +++ b/cinder/api/v2/volumes.py @@ -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) diff --git a/cinder/api/v3/volumes.py b/cinder/api/v3/volumes.py index a9704292a5e..e951817e450 100644 --- a/cinder/api/v3/volumes.py +++ b/cinder/api/v3/volumes.py @@ -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) diff --git a/cinder/cmd/manage.py b/cinder/cmd/manage.py index 85d5c03e110..ded40613ca6 100644 --- a/cinder/cmd/manage.py +++ b/cinder/cmd/manage.py @@ -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): diff --git a/cinder/db/api.py b/cinder/db/api.py index 0d31ebf4505..aca031af0ad 100644 --- a/cinder/db/api.py +++ b/cinder/db/api.py @@ -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) + #################### diff --git a/cinder/db/sqlalchemy/api.py b/cinder/db/sqlalchemy/api.py index b1e6d23ea8d..9cd2f809bf8 100644 --- a/cinder/db/sqlalchemy/api.py +++ b/cinder/db/sqlalchemy/api.py @@ -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 + ################### diff --git a/cinder/db/sqlalchemy/migrate_repo/versions/132_create_default_volume_type.py b/cinder/db/sqlalchemy/migrate_repo/versions/132_create_default_volume_type.py new file mode 100644 index 00000000000..8f0f23a73aa --- /dev/null +++ b/cinder/db/sqlalchemy/migrate_repo/versions/132_create_default_volume_type.py @@ -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) diff --git a/cinder/exception.py b/cinder/exception.py index c71ecaf4e6d..2eb7f9c6a89 100644 --- a/cinder/exception.py +++ b/cinder/exception.py @@ -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.") diff --git a/cinder/objects/snapshot.py b/cinder/objects/snapshot.py index 934c0f774c4..844c51ca5ca 100644 --- a/cinder/objects/snapshot.py +++ b/cinder/objects/snapshot.py @@ -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) diff --git a/cinder/objects/volume.py b/cinder/objects/volume.py index 7999be36683..1fe15bbac70 100644 --- a/cinder/objects/volume.py +++ b/cinder/objects/volume.py @@ -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) diff --git a/cinder/test.py b/cinder/test.py index 630ca552f7c..cbdeff5b10e 100644 --- a/cinder/test.py +++ b/cinder/test.py @@ -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 diff --git a/cinder/tests/functional/api_sample_tests/samples/volume_type/volume-types-list-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/volume_type/volume-types-list-response.json.tpl index d5e80463b64..2ef7c3ddd1f 100644 --- a/cinder/tests/functional/api_sample_tests/samples/volume_type/volume-types-list-response.json.tpl +++ b/cinder/tests/functional/api_sample_tests/samples/volume_type/volume-types-list-response.json.tpl @@ -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 } ] -} +} \ No newline at end of file diff --git a/cinder/tests/functional/api_sample_tests/samples/volumes/volume-create-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/volumes/volume-create-response.json.tpl index c94c0dfd840..df2f20ea2d8 100644 --- a/cinder/tests/functional/api_sample_tests/samples/volumes/volume-create-response.json.tpl +++ b/cinder/tests/functional/api_sample_tests/samples/volumes/volume-create-response.json.tpl @@ -29,6 +29,6 @@ "status": "creating", "updated_at": null, "user_id": "%(uuid)s", - "volume_type": null + "volume_type": "__DEFAULT__" } } \ No newline at end of file diff --git a/cinder/tests/functional/api_sample_tests/samples/volumes/volume-show-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/volumes/volume-show-response.json.tpl index 7daac81db48..1a01d8278ae 100644 --- a/cinder/tests/functional/api_sample_tests/samples/volumes/volume-show-response.json.tpl +++ b/cinder/tests/functional/api_sample_tests/samples/volumes/volume-show-response.json.tpl @@ -33,6 +33,6 @@ "status": "creating", "updated_at": null, "user_id": "%(uuid)s", - "volume_type": null + "volume_type": "__DEFAULT__" } } \ No newline at end of file diff --git a/cinder/tests/functional/api_sample_tests/samples/volumes/volume-update-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/volumes/volume-update-response.json.tpl index c6ce7a552d1..3ce105f265f 100644 --- a/cinder/tests/functional/api_sample_tests/samples/volumes/volume-update-response.json.tpl +++ b/cinder/tests/functional/api_sample_tests/samples/volumes/volume-update-response.json.tpl @@ -31,6 +31,6 @@ "status": "creating", "updated_at": null, "user_id": "%(uuid)s", - "volume_type": null + "volume_type": "__DEFAULT__" } } \ No newline at end of file diff --git a/cinder/tests/functional/api_sample_tests/samples/volumes/volumes-list-detailed-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/volumes/volumes-list-detailed-response.json.tpl index 9157e537e67..071d4b6086a 100644 --- a/cinder/tests/functional/api_sample_tests/samples/volumes/volumes-list-detailed-response.json.tpl +++ b/cinder/tests/functional/api_sample_tests/samples/volumes/volumes-list-detailed-response.json.tpl @@ -34,7 +34,7 @@ "status": "creating", "updated_at": null, "user_id": "%(uuid)s", - "volume_type": null + "volume_type": "__DEFAULT__" } ] } \ No newline at end of file diff --git a/cinder/tests/unit/api/contrib/test_admin_actions.py b/cinder/tests/unit/api/contrib/test_admin_actions.py index c87428cbfe9..e692ee1d032 100644 --- a/cinder/tests/unit/api/contrib/test_admin_actions.py +++ b/cinder/tests/unit/api/contrib/test_admin_actions.py @@ -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' diff --git a/cinder/tests/unit/api/contrib/test_consistencygroups.py b/cinder/tests/unit/api/contrib/test_consistencygroups.py index 1b5de5bc1dc..1e40b915a11 100644 --- a/cinder/tests/unit/api/contrib/test_consistencygroups.py +++ b/cinder/tests/unit/api/contrib/test_consistencygroups.py @@ -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' diff --git a/cinder/tests/unit/api/contrib/test_scheduler_hints.py b/cinder/tests/unit/api/contrib/test_scheduler_hints.py index d16721bcc19..ed9ecf97165 100644 --- a/cinder/tests/unit/api/contrib/test_scheduler_hints.py +++ b/cinder/tests/unit/api/contrib/test_scheduler_hints.py @@ -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) diff --git a/cinder/tests/unit/api/contrib/test_volume_actions.py b/cinder/tests/unit/api/contrib/test_volume_actions.py index 2aaf9635875..627c622827b 100644 --- a/cinder/tests/unit/api/contrib/test_volume_actions.py +++ b/cinder/tests/unit/api/contrib/test_volume_actions.py @@ -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}} diff --git a/cinder/tests/unit/api/contrib/test_volume_encryption_metadata.py b/cinder/tests/unit/api/contrib/test_volume_encryption_metadata.py index c18769bf1d3..4b268fe4259 100644 --- a/cinder/tests/unit/api/contrib/test_volume_encryption_metadata.py +++ b/cinder/tests/unit/api/contrib/test_volume_encryption_metadata.py @@ -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'] diff --git a/cinder/tests/unit/api/contrib/test_volume_image_metadata.py b/cinder/tests/unit/api/contrib/test_volume_image_metadata.py index c3c5f509ecc..674ee4d9f05 100644 --- a/cinder/tests/unit/api/contrib/test_volume_image_metadata.py +++ b/cinder/tests/unit/api/contrib/test_volume_image_metadata.py @@ -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, diff --git a/cinder/tests/unit/api/contrib/test_volume_transfer.py b/cinder/tests/unit/api/contrib/test_volume_transfer.py index 92018422ad6..137fbdd0672 100644 --- a/cinder/tests/unit/api/contrib/test_volume_transfer.py +++ b/cinder/tests/unit/api/contrib/test_volume_transfer.py @@ -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) diff --git a/cinder/tests/unit/api/v2/fakes.py b/cinder/tests/unit/api/v2/fakes.py index 501d4138e8d..132516dc0c5 100644 --- a/cinder/tests/unit/api/v2/fakes.py +++ b/cinder/tests/unit/api/v2/fakes.py @@ -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: diff --git a/cinder/tests/unit/api/v2/test_snapshot_metadata.py b/cinder/tests/unit/api/v2/test_snapshot_metadata.py index efaacdaf145..acc01c25283 100644 --- a/cinder/tests/unit/api/v2/test_snapshot_metadata.py +++ b/cinder/tests/unit/api/v2/test_snapshot_metadata.py @@ -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 = {} diff --git a/cinder/tests/unit/api/v2/test_snapshots.py b/cinder/tests/unit/api/v2/test_snapshots.py index d9e1554267c..1abbbce1895 100644 --- a/cinder/tests/unit/api/v2/test_snapshots.py +++ b/cinder/tests/unit/api/v2/test_snapshots.py @@ -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)) diff --git a/cinder/tests/unit/api/v2/test_types.py b/cinder/tests/unit/api/v2/test_types.py index 96d740f55a7..63b2383043b 100644 --- a/cinder/tests/unit/api/v2/test_types.py +++ b/cinder/tests/unit/api/v2/test_types.py @@ -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', diff --git a/cinder/tests/unit/api/v2/test_volume_metadata.py b/cinder/tests/unit/api/v2/test_volume_metadata.py index 5d32f73b943..cc38f973f26 100644 --- a/cinder/tests/unit/api/v2/test_volume_metadata.py +++ b/cinder/tests/unit/api/v2/test_volume_metadata.py @@ -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) diff --git a/cinder/tests/unit/api/v2/test_volumes.py b/cinder/tests/unit/api/v2/test_volumes.py index 07c560efc65..b6c001a7672 100644 --- a/cinder/tests/unit/api/v2/test_volumes.py +++ b/cinder/tests/unit/api/v2/test_volumes.py @@ -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, diff --git a/cinder/tests/unit/api/v3/test_snapshots.py b/cinder/tests/unit/api/v3/test_snapshots.py index 7c799bc0ae3..e6cd4240663 100644 --- a/cinder/tests/unit/api/v3/test_snapshots.py +++ b/cinder/tests/unit/api/v3/test_snapshots.py @@ -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) diff --git a/cinder/tests/unit/api/v3/test_types.py b/cinder/tests/unit/api/v3/test_types.py index 14f33f3cedd..75347433591 100644 --- a/cinder/tests/unit/api/v3/test_types.py +++ b/cinder/tests/unit/api/v3/test_types.py @@ -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( diff --git a/cinder/tests/unit/api/v3/test_volume_transfer.py b/cinder/tests/unit/api/v3/test_volume_transfer.py index 6f6eb985e22..d521f5f8d92 100644 --- a/cinder/tests/unit/api/v3/test_volume_transfer.py +++ b/cinder/tests/unit/api/v3/test_volume_transfer.py @@ -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') diff --git a/cinder/tests/unit/api/v3/test_volumes.py b/cinder/tests/unit/api/v3/test_volumes.py index dc2c52b9558..26e5a606fca 100644 --- a/cinder/tests/unit/api/v3/test_volumes.py +++ b/cinder/tests/unit/api/v3/test_volumes.py @@ -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) diff --git a/cinder/tests/unit/attachments/test_attachments_api.py b/cinder/tests/unit/attachments/test_attachments_api.py index 30d06aa7e1d..8b50b072a37 100644 --- a/cinder/tests/unit/attachments/test_attachments_api.py +++ b/cinder/tests/unit/attachments/test_attachments_api.py @@ -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'} diff --git a/cinder/tests/unit/attachments/test_attachments_manager.py b/cinder/tests/unit/attachments/test_attachments_manager.py index a50f9d4edd5..3b62d3d0854 100644 --- a/cinder/tests/unit/attachments/test_attachments_manager.py +++ b/cinder/tests/unit/attachments/test_attachments_manager.py @@ -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 = { diff --git a/cinder/tests/unit/backup/drivers/test_backup_ceph.py b/cinder/tests/unit/backup/drivers/test_backup_ceph.py index 048ea4d4edb..19d90eb9266 100644 --- a/cinder/tests/unit/backup/drivers/test_backup_ceph.py +++ b/cinder/tests/unit/backup/drivers/test_backup_ceph.py @@ -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, diff --git a/cinder/tests/unit/backup/drivers/test_backup_driver_base.py b/cinder/tests/unit/backup/drivers/test_backup_driver_base.py index cc955b3cd83..5caa5bfa7f1 100644 --- a/cinder/tests/unit/backup/drivers/test_backup_driver_base.py +++ b/cinder/tests/unit/backup/drivers/test_backup_driver_base.py @@ -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, [])) diff --git a/cinder/tests/unit/backup/drivers/test_backup_google.py b/cinder/tests/unit/backup/drivers/test_backup_google.py index f88e32f467e..b0af9381863 100644 --- a/cinder/tests/unit/backup/drivers/test_backup_google.py +++ b/cinder/tests/unit/backup/drivers/test_backup_google.py @@ -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, diff --git a/cinder/tests/unit/backup/drivers/test_backup_nfs.py b/cinder/tests/unit/backup/drivers/test_backup_nfs.py index f5ba3b128ad..6c03e877f88 100644 --- a/cinder/tests/unit/backup/drivers/test_backup_nfs.py +++ b/cinder/tests/unit/backup/drivers/test_backup_nfs.py @@ -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, diff --git a/cinder/tests/unit/backup/drivers/test_backup_swift.py b/cinder/tests/unit/backup/drivers/test_backup_swift.py index adae7031352..9c6963aaf12 100644 --- a/cinder/tests/unit/backup/drivers/test_backup_swift.py +++ b/cinder/tests/unit/backup/drivers/test_backup_swift.py @@ -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, diff --git a/cinder/tests/unit/backup/drivers/test_backup_tsm.py b/cinder/tests/unit/backup/drivers/test_backup_tsm.py index 777308102df..953506f9c7c 100644 --- a/cinder/tests/unit/backup/drivers/test_backup_tsm.py +++ b/cinder/tests/unit/backup/drivers/test_backup_tsm.py @@ -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): diff --git a/cinder/tests/unit/backup/test_backup.py b/cinder/tests/unit/backup/test_backup.py index 71967648116..abe3308fa45 100644 --- a/cinder/tests/unit/backup/test_backup.py +++ b/cinder/tests/unit/backup/test_backup.py @@ -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): diff --git a/cinder/tests/unit/conf_fixture.py b/cinder/tests/unit/conf_fixture.py index fd1e0a7e27b..17a95782c0e 100644 --- a/cinder/tests/unit/conf_fixture.py +++ b/cinder/tests/unit/conf_fixture.py @@ -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): diff --git a/cinder/tests/unit/db/test_migrations.py b/cinder/tests/unit/db/test_migrations.py index fbbae7d9f88..498871e6dd3 100644 --- a/cinder/tests/unit/db/test_migrations.py +++ b/cinder/tests/unit/db/test_migrations.py @@ -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. diff --git a/cinder/tests/unit/db/test_purge.py b/cinder/tests/unit/db/test_purge.py index 9fc048f9143..7d3f005fbb8 100644 --- a/cinder/tests/unit/db/test_purge.py +++ b/cinder/tests/unit/db/test_purge.py @@ -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) diff --git a/cinder/tests/unit/fake_constants.py b/cinder/tests/unit/fake_constants.py index c1436711628..b8b69dc79d8 100644 --- a/cinder/tests/unit/fake_constants.py +++ b/cinder/tests/unit/fake_constants.py @@ -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' diff --git a/cinder/tests/unit/group/test_groups_manager.py b/cinder/tests/unit/group/test_groups_manager.py index 3c9939b062e..f68f976a2c7 100644 --- a/cinder/tests/unit/group/test_groups_manager.py +++ b/cinder/tests/unit/group/test_groups_manager.py @@ -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, diff --git a/cinder/tests/unit/objects/test_volume_type.py b/cinder/tests/unit/objects/test_volume_type.py index 0b3fbf9fa9b..6267ac1bd54 100644 --- a/cinder/tests/unit/objects/test_volume_type.py +++ b/cinder/tests/unit/objects/test_volume_type.py @@ -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, diff --git a/cinder/tests/unit/test_cmd.py b/cinder/tests/unit/test_cmd.py index bd4fccdf240..cb75c0b7a9e 100644 --- a/cinder/tests/unit/test_cmd.py +++ b/cinder/tests/unit/test_cmd.py @@ -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', diff --git a/cinder/tests/unit/test_db_api.py b/cinder/tests/unit/test_db_api.py index e63d0c3a9aa..ed98bc63240 100644 --- a/cinder/tests/unit/test_db_api.py +++ b/cinder/tests/unit/test_db_api.py @@ -86,8 +86,10 @@ class DBCommonFilterTestCase(BaseTest): def setUp(self): super(DBCommonFilterTestCase, self).setUp() - self.fake_volume = db.volume_create(self.ctxt, - {'display_name': 'fake_name'}) + self.fake_volume = db.volume_create( + self.ctxt, + {'display_name': 'fake_name', + 'volume_type_id': fake.VOLUME_TYPE_ID}) self.fake_group = utils.create_group( self.ctxt, group_type_id=fake.GROUP_TYPE_ID, @@ -135,6 +137,8 @@ class DBCommonFilterTestCase(BaseTest): def test_resource_get_all_like_filter(self, handler, column, resource): for index in ['001', '002']: option = {column: "fake_%s_%s" % (column, index)} + if resource in ['volume', 'snapshot']: + option['volume_type_id'] = fake.VOLUME_TYPE_ID if resource in ['snapshot', 'backup']: option['volume_id'] = self.fake_volume.id if resource in ['message']: @@ -394,7 +398,9 @@ class DBAPIVolumeTestCase(BaseTest): """Unit tests for cinder.db.api.volume_*.""" def test_volume_create(self): - volume = db.volume_create(self.ctxt, {'host': 'host1'}) + volume = db.volume_create( + self.ctxt, {'host': 'host1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) self.assertTrue(uuidutils.is_uuid_like(volume['id'])) self.assertEqual('host1', volume.host) @@ -403,7 +409,9 @@ class DBAPIVolumeTestCase(BaseTest): 42, 'invalid-uuid', None, '/tmp') def test_volume_attached_to_instance(self): - volume = db.volume_create(self.ctxt, {'host': 'host1'}) + volume = db.volume_create( + self.ctxt, {'host': 'host1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) instance_uuid = fake.INSTANCE_ID values = {'volume_id': volume['id'], 'instance_uuid': instance_uuid, @@ -437,7 +445,9 @@ class DBAPIVolumeTestCase(BaseTest): self.assertEqual(volume.project_id, attachment['volume']['project_id']) def test_volume_attached_to_host(self): - volume = db.volume_create(self.ctxt, {'host': 'host1'}) + volume = db.volume_create( + self.ctxt, {'host': 'host1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) host_name = 'fake_host' values = {'volume_id': volume['id'], 'attached_host': host_name, @@ -471,8 +481,10 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_data_get_for_host(self): for i in range(THREE): for j in range(THREE): - db.volume_create(self.ctxt, {'host': 'h%d' % i, - 'size': ONE_HUNDREDS}) + db.volume_create( + self.ctxt, {'host': 'h%d' % i, + 'size': ONE_HUNDREDS, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for i in range(THREE): self.assertEqual((THREE, THREE_HUNDREDS), db.volume_data_get_for_host( @@ -481,9 +493,10 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_data_get_for_host_for_multi_backend(self): for i in range(THREE): for j in range(THREE): - db.volume_create(self.ctxt, {'host': - 'h%d@lvmdriver-1#lvmdriver-1' % i, - 'size': ONE_HUNDREDS}) + db.volume_create( + self.ctxt, {'host': 'h%d@lvmdriver-1#lvmdriver-1' % i, + 'size': ONE_HUNDREDS, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for i in range(THREE): self.assertEqual((THREE, THREE_HUNDREDS), db.volume_data_get_for_host( @@ -492,10 +505,11 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_data_get_for_project(self): for i in range(THREE): for j in range(THREE): - db.volume_create(self.ctxt, {'project_id': 'p%d' % i, - 'size': ONE_HUNDREDS, - 'host': 'h-%d-%d' % (i, j), - }) + db.volume_create( + self.ctxt, {'project_id': 'p%d' % i, + 'size': ONE_HUNDREDS, + 'host': 'h-%d-%d' % (i, j), + 'volume_type_id': fake.VOLUME_TYPE_ID}) for i in range(THREE): self.assertEqual((THREE, THREE_HUNDREDS), db.volume_data_get_for_project( @@ -505,20 +519,24 @@ class DBAPIVolumeTestCase(BaseTest): db.volume_create(self.ctxt, {'project_id': fake.PROJECT_ID, 'size': 100, - 'host': 'host1'}) + 'host': 'host1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_create(self.ctxt, {'project_id': fake.PROJECT2_ID, 'size': 200, - 'host': 'host1'}) + 'host': 'host1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_create(self.ctxt, {'project_id': fake.PROJECT2_ID, 'size': 300, - 'host': 'host2'}) + 'host': 'host2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) resp = db.volume_data_get_for_project(self.ctxt, fake.PROJECT2_ID, host='host2') self.assertEqual((1, 300), resp) def test_volume_detached_from_instance(self): - volume = db.volume_create(self.ctxt, {}) + volume = db.volume_create(self.ctxt, + {'volume_type_id': fake.VOLUME_TYPE_ID}) instance_uuid = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' values = {'volume_id': volume['id'], 'instance_uuid': instance_uuid, @@ -547,7 +565,8 @@ class DBAPIVolumeTestCase(BaseTest): self.assertEqual('available', volume.status) def test_volume_detached_two_attachments(self): - volume = db.volume_create(self.ctxt, {}) + volume = db.volume_create(self.ctxt, + {'volume_type_id': fake.VOLUME_TYPE_ID}) instance_uuid = fake.INSTANCE_ID values = {'volume_id': volume.id, 'instance_uuid': instance_uuid, @@ -580,7 +599,8 @@ class DBAPIVolumeTestCase(BaseTest): self.assertEqual('in-use', volume.status) def test_volume_detached_invalid_attachment(self): - volume = db.volume_create(self.ctxt, {}) + volume = db.volume_create(self.ctxt, + {'volume_type_id': fake.VOLUME_TYPE_ID}) # detach it again volume_updates, attachment_updates = ( db.volume_detached(self.ctxt, volume.id, fake.ATTACHMENT_ID)) @@ -593,7 +613,8 @@ class DBAPIVolumeTestCase(BaseTest): self.assertEqual('available', volume.status) def test_volume_detached_from_host(self): - volume = db.volume_create(self.ctxt, {}) + volume = db.volume_create(self.ctxt, + {'volume_type_id': fake.VOLUME_TYPE_ID}) host_name = 'fake_host' values = {'volume_id': volume.id, 'attach_host': host_name, @@ -621,13 +642,15 @@ class DBAPIVolumeTestCase(BaseTest): self.assertEqual('available', volume.status) def test_volume_get(self): - volume = db.volume_create(self.ctxt, {}) + volume = db.volume_create(self.ctxt, + {'volume_type_id': fake.VOLUME_TYPE_ID}) self._assertEqualObjects(volume, db.volume_get(self.ctxt, volume['id'])) @mock.patch('oslo_utils.timeutils.utcnow', return_value=UTC_NOW) def test_volume_destroy(self, utcnow_mock): - volume = db.volume_create(self.ctxt, {}) + volume = db.volume_create(self.ctxt, + {'volume_type_id': fake.VOLUME_TYPE_ID}) self.assertDictEqual( {'status': 'deleted', 'deleted': True, 'deleted_at': UTC_NOW, 'migration_status': None}, @@ -637,7 +660,8 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_get_all(self): volumes = [db.volume_create(self.ctxt, - {'host': 'h%d' % i, 'size': i}) + {'host': 'h%d' % i, 'size': i, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for i in range(3)] self._assertEqualListsOfObjects(volumes, db.volume_get_all( self.ctxt, None, None, ['host'], None)) @@ -659,10 +683,18 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_get_all_marker_passed(self): volumes = [ - db.volume_create(self.ctxt, {'id': 1}), - db.volume_create(self.ctxt, {'id': 2}), - db.volume_create(self.ctxt, {'id': 3}), - db.volume_create(self.ctxt, {'id': 4}), + db.volume_create( + self.ctxt, {'id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}), + db.volume_create( + self.ctxt, {'id': 2, + 'volume_type_id': fake.VOLUME_TYPE_ID}), + db.volume_create( + self.ctxt, {'id': 3, + 'volume_type_id': fake.VOLUME_TYPE_ID}), + db.volume_create( + self.ctxt, {'id': 4, + 'volume_type_id': fake.VOLUME_TYPE_ID}), ] self._assertEqualListsOfObjects(volumes[2:], db.volume_get_all( @@ -671,7 +703,9 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_get_all_by_host(self): volumes = [] for i in range(3): - volumes.append([db.volume_create(self.ctxt, {'host': 'h%d' % i}) + volumes.append([db.volume_create( + self.ctxt, {'host': 'h%d' % i, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for j in range(3)]) for i in range(3): self._assertEqualListsOfObjects(volumes[i], @@ -680,26 +714,39 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_get_all_by_host_with_pools(self): volumes = [] - vol_on_host_wo_pool = [db.volume_create(self.ctxt, {'host': 'foo'}) - for j in range(3)] + vol_on_host_wo_pool = [db.volume_create( + self.ctxt, + {'host': 'foo', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + for j in range(3)] vol_on_host_w_pool = [db.volume_create( - self.ctxt, {'host': 'foo#pool0'})] + self.ctxt, {'host': 'foo#pool0', + 'volume_type_id': fake.VOLUME_TYPE_ID})] volumes.append((vol_on_host_wo_pool + vol_on_host_w_pool)) # insert an additional record that doesn't belongs to the same # host as 'foo' and test if it is included in the result - db.volume_create(self.ctxt, {'host': 'foobar'}) + db.volume_create(self.ctxt, {'host': 'foobar', + 'volume_type_id': fake.VOLUME_TYPE_ID}) self._assertEqualListsOfObjects(volumes[0], db.volume_get_all_by_host( self.ctxt, 'foo')) def test_volume_get_all_by_host_with_filters(self): - v1 = db.volume_create(self.ctxt, {'host': 'h1', 'display_name': 'v1', - 'status': 'available'}) - v2 = db.volume_create(self.ctxt, {'host': 'h1', 'display_name': 'v2', - 'status': 'available'}) - v3 = db.volume_create(self.ctxt, {'host': 'h2', 'display_name': 'v1', - 'status': 'available'}) + v1 = db.volume_create( + self.ctxt, {'host': 'h1', 'display_name': 'v1', + 'status': 'available', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + v2 = db.volume_create( + self.ctxt, + {'host': 'h1', 'display_name': 'v2', + 'status': 'available', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + v3 = db.volume_create( + self.ctxt, + {'host': 'h2', 'display_name': 'v1', + 'status': 'available', + 'volume_type_id': fake.VOLUME_TYPE_ID}) self._assertEqualListsOfObjects( [v1], db.volume_get_all_by_host(self.ctxt, 'h1', @@ -730,19 +777,26 @@ class DBAPIVolumeTestCase(BaseTest): volumes = [] for i in range(3): volumes.append([db.volume_create(self.ctxt, { - 'consistencygroup_id': 'g%d' % i}) for j in range(3)]) + 'consistencygroup_id': 'g%d' % i, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for j in range(3)]) for i in range(3): self._assertEqualListsOfObjects(volumes[i], db.volume_get_all_by_group( self.ctxt, 'g%d' % i)) def test_volume_get_all_by_group_with_filters(self): - v1 = db.volume_create(self.ctxt, {'consistencygroup_id': 'g1', - 'display_name': 'v1'}) - v2 = db.volume_create(self.ctxt, {'consistencygroup_id': 'g1', - 'display_name': 'v2'}) - v3 = db.volume_create(self.ctxt, {'consistencygroup_id': 'g2', - 'display_name': 'v1'}) + v1 = db.volume_create(self.ctxt, + {'consistencygroup_id': 'g1', + 'display_name': 'v1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + v2 = db.volume_create(self.ctxt, + {'consistencygroup_id': 'g1', + 'display_name': 'v2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + v3 = db.volume_create(self.ctxt, + {'consistencygroup_id': 'g2', + 'display_name': 'v1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) self._assertEqualListsOfObjects( [v1], db.volume_get_all_by_group(self.ctxt, 'g1', @@ -768,7 +822,8 @@ class DBAPIVolumeTestCase(BaseTest): volumes = [] for i in range(3): volumes.append([db.volume_create(self.ctxt, { - 'project_id': 'p%d' % i}) for j in range(3)]) + 'project_id': 'p%d' % i, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for j in range(3)]) for i in range(3): self._assertEqualListsOfObjects(volumes[i], db.volume_get_all_by_project( @@ -776,9 +831,15 @@ class DBAPIVolumeTestCase(BaseTest): None, ['host'], None)) def test_volume_get_by_name(self): - db.volume_create(self.ctxt, {'display_name': 'vol1'}) - db.volume_create(self.ctxt, {'display_name': 'vol2'}) - db.volume_create(self.ctxt, {'display_name': 'vol3'}) + db.volume_create(self.ctxt, + {'display_name': 'vol1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + db.volume_create(self.ctxt, + {'display_name': 'vol2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + db.volume_create(self.ctxt, + {'display_name': 'vol3', + 'volume_type_id': fake.VOLUME_TYPE_ID}) # no name filter volumes = db.volume_get_all(self.ctxt, None, None, ['created_at'], @@ -796,11 +857,14 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_list_by_status(self): db.volume_create(self.ctxt, {'display_name': 'vol1', - 'status': 'available'}) + 'status': 'available', + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_create(self.ctxt, {'display_name': 'vol2', - 'status': 'available'}) + 'status': 'available', + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_create(self.ctxt, {'display_name': 'vol3', - 'status': 'in-use'}) + 'status': 'in-use', + 'volume_type_id': fake.VOLUME_TYPE_ID}) # no status filter volumes = db.volume_get_all(self.ctxt, None, None, ['created_at'], @@ -870,21 +934,25 @@ class DBAPIVolumeTestCase(BaseTest): vols.extend([db.volume_create(self.ctxt, {'project_id': 'g1', 'display_name': 'name_%d' % i, - 'size': 1}) + 'size': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for i in range(2)]) vols.extend([db.volume_create(self.ctxt, {'project_id': 'g1', 'display_name': 'name_%d' % i, - 'size': 2}) + 'size': 2, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for i in range(2)]) vols.extend([db.volume_create(self.ctxt, {'project_id': 'g1', - 'display_name': 'name_%d' % i}) + 'display_name': 'name_%d' % i, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for i in range(2)]) vols.extend([db.volume_create(self.ctxt, {'project_id': 'g2', 'display_name': 'name_%d' % i, - 'size': 1}) + 'size': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for i in range(2)]) # By project, filter on size and name @@ -930,17 +998,25 @@ class DBAPIVolumeTestCase(BaseTest): self._assertEqualsVolumeOrderResult([], filters=filters) def test_volume_get_all_filters_limit(self): - vol1 = db.volume_create(self.ctxt, {'display_name': 'test1'}) - vol2 = db.volume_create(self.ctxt, {'display_name': 'test2'}) - vol3 = db.volume_create(self.ctxt, {'display_name': 'test2', - 'metadata': {'key1': 'val1'}}) - vol4 = db.volume_create(self.ctxt, {'display_name': 'test3', - 'metadata': {'key1': 'val1', - 'key2': 'val2'}}) - vol5 = db.volume_create(self.ctxt, {'display_name': 'test3', - 'metadata': {'key2': 'val2', - 'key3': 'val3'}, - 'host': 'host5'}) + vol1 = db.volume_create(self.ctxt, + {'display_name': 'test1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + vol2 = db.volume_create(self.ctxt, + {'display_name': 'test2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + vol3 = db.volume_create(self.ctxt, + {'display_name': 'test2', + 'metadata': {'key1': 'val1'}, + 'volume_type_id': fake.VOLUME_TYPE_ID}) + vol4 = db.volume_create(self.ctxt, + {'display_name': 'test3', + 'metadata': {'key1': 'val1', 'key2': 'val2'}, + 'volume_type_id': fake.VOLUME_TYPE_ID}) + vol5 = db.volume_create(self.ctxt, + {'display_name': 'test3', + 'metadata': {'key2': 'val2', 'key3': 'val3'}, + 'host': 'host5', + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_admin_metadata_update(self.ctxt, vol5.id, {"readonly": "True"}, False) @@ -1014,13 +1090,21 @@ class DBAPIVolumeTestCase(BaseTest): This filter returns volumes with either a NULL 'migration_status' or a non-NULL value that does not start with 'target:'. """ - vol1 = db.volume_create(self.ctxt, {'display_name': 'test1'}) - vol2 = db.volume_create(self.ctxt, {'display_name': 'test2', - 'migration_status': 'bogus'}) - vol3 = db.volume_create(self.ctxt, {'display_name': 'test3', - 'migration_status': 'btarget:'}) - vol4 = db.volume_create(self.ctxt, {'display_name': 'test4', - 'migration_status': 'target:'}) + vol1 = db.volume_create(self.ctxt, + {'display_name': 'test1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + vol2 = db.volume_create(self.ctxt, + {'display_name': 'test2', + 'migration_status': 'bogus', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + vol3 = db.volume_create(self.ctxt, + {'display_name': 'test3', + 'migration_status': 'btarget:', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + vol4 = db.volume_create(self.ctxt, + {'display_name': 'test4', + 'migration_status': 'target:', + 'volume_type_id': fake.VOLUME_TYPE_ID}) # Ensure we have 4 total instances, default sort of created_at (desc) self._assertEqualsVolumeOrderResult([vol4, vol3, vol2, vol1]) @@ -1038,31 +1122,47 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_get_all_by_filters_sort_keys(self): # Volumes that will reply to the query - test_h1_avail = db.volume_create(self.ctxt, {'display_name': 'test', - 'status': 'available', - 'host': 'h1'}) - test_h1_error = db.volume_create(self.ctxt, {'display_name': 'test', - 'status': 'error', - 'host': 'h1'}) - test_h1_error2 = db.volume_create(self.ctxt, {'display_name': 'test', - 'status': 'error', - 'host': 'h1'}) - test_h2_avail = db.volume_create(self.ctxt, {'display_name': 'test', - 'status': 'available', - 'host': 'h2'}) - test_h2_error = db.volume_create(self.ctxt, {'display_name': 'test', - 'status': 'error', - 'host': 'h2'}) - test_h2_error2 = db.volume_create(self.ctxt, {'display_name': 'test', - 'status': 'error', - 'host': 'h2'}) + test_h1_avail = db.volume_create( + self.ctxt, {'display_name': 'test', + 'status': 'available', + 'host': 'h1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test_h1_error = db.volume_create( + self.ctxt, {'display_name': 'test', + 'status': 'error', + 'host': 'h1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test_h1_error2 = db.volume_create( + self.ctxt, {'display_name': 'test', + 'status': 'error', + 'host': 'h1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test_h2_avail = db.volume_create( + self.ctxt, {'display_name': 'test', + 'status': 'available', + 'host': 'h2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test_h2_error = db.volume_create( + self.ctxt, {'display_name': 'test', + 'status': 'error', + 'host': 'h2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test_h2_error2 = db.volume_create( + self.ctxt, {'display_name': 'test', + 'status': 'error', + 'host': 'h2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) # Other volumes in the DB, will not match name filter - other_error = db.volume_create(self.ctxt, {'display_name': 'other', - 'status': 'error', - 'host': 'a'}) - other_active = db.volume_create(self.ctxt, {'display_name': 'other', - 'status': 'available', - 'host': 'a'}) + other_error = db.volume_create( + self.ctxt, {'display_name': 'other', + 'status': 'error', + 'host': 'a', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + other_active = db.volume_create( + self.ctxt, {'display_name': 'other', + 'status': 'available', + 'host': 'a', + 'volume_type_id': fake.VOLUME_TYPE_ID}) filters = {'display_name': 'test'} # Verify different sort key/direction combinations @@ -1120,28 +1220,44 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_get_all_by_filters_sort_keys_paginate(self): """Verifies sort order with pagination.""" # Volumes that will reply to the query - test1_avail = db.volume_create(self.ctxt, {'display_name': 'test', - 'size': 1, - 'status': 'available'}) - test1_error = db.volume_create(self.ctxt, {'display_name': 'test', - 'size': 1, - 'status': 'error'}) - test1_error2 = db.volume_create(self.ctxt, {'display_name': 'test', - 'size': 1, - 'status': 'error'}) - test2_avail = db.volume_create(self.ctxt, {'display_name': 'test', - 'size': 2, - 'status': 'available'}) - test2_error = db.volume_create(self.ctxt, {'display_name': 'test', - 'size': 2, - 'status': 'error'}) - test2_error2 = db.volume_create(self.ctxt, {'display_name': 'test', - 'size': 2, - 'status': 'error'}) + test1_avail = db.volume_create( + self.ctxt, {'display_name': 'test', + 'size': 1, + 'status': 'available', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test1_error = db.volume_create( + self.ctxt, {'display_name': 'test', + 'size': 1, + 'status': 'error', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test1_error2 = db.volume_create( + self.ctxt, {'display_name': 'test', + 'size': 1, + 'status': 'error', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test2_avail = db.volume_create( + self.ctxt, {'display_name': 'test', + 'size': 2, + 'status': 'available', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test2_error = db.volume_create( + self.ctxt, {'display_name': 'test', + 'size': 2, + 'status': 'error', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + test2_error2 = db.volume_create( + self.ctxt, {'display_name': 'test', + 'size': 2, + 'status': 'error', + 'volume_type_id': fake.VOLUME_TYPE_ID}) # Other volumes in the DB, will not match name filter - db.volume_create(self.ctxt, {'display_name': 'other'}) - db.volume_create(self.ctxt, {'display_name': 'other'}) + db.volume_create(self.ctxt, + {'display_name': 'other', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + db.volume_create(self.ctxt, + {'display_name': 'other', + 'volume_type_id': fake.VOLUME_TYPE_ID}) filters = {'display_name': 'test'} # Common sort information for every query sort_keys = ['size', 'status', 'created_at'] @@ -1176,7 +1292,9 @@ class DBAPIVolumeTestCase(BaseTest): self.ctxt, None, None, sort_keys=keys) def test_volume_update(self): - volume = db.volume_create(self.ctxt, {'host': 'h1'}) + volume = db.volume_create(self.ctxt, + {'host': 'h1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_update(self.ctxt, volume.id, {'host': 'h2', 'metadata': {'m1': 'v1'}}) @@ -1193,7 +1311,8 @@ class DBAPIVolumeTestCase(BaseTest): def test_volume_metadata_get(self): metadata = {'a': 'b', 'c': 'd'} - db.volume_create(self.ctxt, {'id': 1, 'metadata': metadata}) + db.volume_create(self.ctxt, {'id': 1, 'metadata': metadata, + 'volume_type_id': fake.VOLUME_TYPE_ID}) self.assertEqual(metadata, db.volume_metadata_get(self.ctxt, 1)) @@ -1202,7 +1321,8 @@ class DBAPIVolumeTestCase(BaseTest): metadata2 = {'a': '3', 'd': '5'} should_be = {'a': '3', 'c': '2', 'd': '5'} - db.volume_create(self.ctxt, {'id': 1, 'metadata': metadata1}) + db.volume_create(self.ctxt, {'id': 1, 'metadata': metadata1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db_meta = db.volume_metadata_update(self.ctxt, 1, metadata2, False) self.assertEqual(should_be, db_meta) @@ -1216,7 +1336,8 @@ class DBAPIVolumeTestCase(BaseTest): # create volume with metadata. db.volume_create(self.ctxt, {'id': 1, - 'metadata': image_metadata}) + 'metadata': image_metadata, + 'volume_type_id': fake.VOLUME_TYPE_ID}) # delete metadata associated with the volume. db.volume_metadata_delete(self.ctxt, @@ -1233,7 +1354,8 @@ class DBAPIVolumeTestCase(BaseTest): # create volume with metadata. db.volume_create(self.ctxt, {'id': 1, - 'metadata': user_metadata}) + 'metadata': user_metadata, + 'volume_type_id': fake.VOLUME_TYPE_ID}) # delete user metadata associated with the volume. db.volume_metadata_delete(self.ctxt, 1, 'c', @@ -1276,7 +1398,8 @@ class DBAPIVolumeTestCase(BaseTest): expected2 = {'e': '3', 'f': '2', 'g': '5'} FAKE_METADATA_TYPE = enum.Enum('METADATA_TYPES', 'fake_type') - db.volume_create(self.ctxt, {'id': 1, 'metadata': user_metadata1}) + db.volume_create(self.ctxt, {'id': 1, 'metadata': user_metadata1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) # update user metatdata associated with volume. db_meta = db.volume_metadata_update( @@ -1340,14 +1463,16 @@ class DBAPIVolumeTestCase(BaseTest): metadata2 = {'a': '3', 'd': '4'} should_be = metadata2 - db.volume_create(self.ctxt, {'id': 1, 'metadata': metadata1}) + db.volume_create(self.ctxt, {'id': 1, 'metadata': metadata1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db_meta = db.volume_metadata_update(self.ctxt, 1, metadata2, True) self.assertEqual(should_be, db_meta) def test_volume_metadata_delete(self): metadata = {'a': 'b', 'c': 'd'} - db.volume_create(self.ctxt, {'id': 1, 'metadata': metadata}) + db.volume_create(self.ctxt, {'id': 1, 'metadata': metadata, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_metadata_delete(self.ctxt, 1, 'c') metadata.pop('c') self.assertEqual(metadata, db.volume_metadata_get(self.ctxt, 1)) @@ -1358,7 +1483,8 @@ class DBAPIVolumeTestCase(BaseTest): FAKE_METADATA_TYPE = enum.Enum('METADATA_TYPES', 'fake_type') # test that user metadata deleted with meta_type specified. - db.volume_create(self.ctxt, {'id': 1, 'metadata': user_metadata}) + db.volume_create(self.ctxt, {'id': 1, 'metadata': user_metadata, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_metadata_delete(self.ctxt, 1, 'c', meta_type=common.METADATA_TYPES.user) user_metadata.pop('c') @@ -1393,7 +1519,9 @@ class DBAPIVolumeTestCase(BaseTest): FAKE_METADATA_TYPE.fake_type) def test_volume_glance_metadata_create(self): - volume = db.volume_create(self.ctxt, {'host': 'h1'}) + volume = db.volume_create(self.ctxt, + {'host': 'h1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_glance_metadata_create(self.ctxt, volume['id'], 'image_name', u'\xe4\xbd\xa0\xe5\xa5\xbd') @@ -1407,13 +1535,15 @@ class DBAPIVolumeTestCase(BaseTest): """Test volume_glance_metadata_list_get in DB API.""" db.volume_create(self.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(self.ctxt, 'fake1', 'key1', 'value1') db.volume_glance_metadata_create(self.ctxt, 'fake1', 'key2', 'value2') db.volume_create(self.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(self.ctxt, 'fake2', 'key3', 'value3') db.volume_glance_metadata_create(self.ctxt, 'fake2', 'key4', 'value4') @@ -1435,12 +1565,16 @@ class DBAPIVolumeTestCase(BaseTest): 'updated_at']) def _create_volume_with_image_metadata(self): - vol1 = db.volume_create(self.ctxt, {'display_name': 'test1'}) + vol1 = db.volume_create(self.ctxt, + {'display_name': 'test1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_glance_metadata_create(self.ctxt, vol1.id, 'image_name', 'imageTestOne') db.volume_glance_metadata_create(self.ctxt, vol1.id, 'test_image_key', 'test_image_value') - vol2 = db.volume_create(self.ctxt, {'display_name': 'test2'}) + vol2 = db.volume_create(self.ctxt, + {'display_name': 'test2', + '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', @@ -1477,13 +1611,16 @@ class DBAPIVolumeTestCase(BaseTest): return [ db.volume_create(self.ctxt, {'host': 'host1@backend1#pool1', - 'cluster_name': 'cluster1@backend1#pool1'}), + 'cluster_name': 'cluster1@backend1#pool1', + 'volume_type_id': fake.VOLUME_TYPE_ID}), db.volume_create(self.ctxt, {'host': 'host1@backend2#pool2', - 'cluster_name': 'cluster1@backend2#pool2'}), + 'cluster_name': 'cluster1@backend2#pool2', + 'volume_type_id': fake.VOLUME_TYPE_ID}), db.volume_create(self.ctxt, {'host': 'host2@backend#poo1', - 'cluster_name': 'cluster2@backend#pool'}), + 'cluster_name': 'cluster2@backend#pool', + 'volume_type_id': fake.VOLUME_TYPE_ID}), ] @ddt.data('host1@backend1#pool1', 'host1@backend1') @@ -1556,10 +1693,12 @@ class DBAPISnapshotTestCase(BaseTest): self.assertEqual((0, 0), actual) db.volume_create(self.ctxt, {'id': 1, 'project_id': 'project1', - 'size': 42}) + 'size': 42, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, {'id': 1, 'volume_id': 1, 'project_id': 'project1', - 'volume_size': 42}) + 'volume_size': 42, + 'volume_type_id': fake.VOLUME_TYPE_ID}) actual = db.snapshot_data_get_for_project(self.ctxt, 'project1') self.assertEqual((1, 42), actual) @@ -1574,13 +1713,15 @@ class DBAPISnapshotTestCase(BaseTest): def hours_ago(hour): return timeutils.utcnow() - datetime.timedelta( hours=hour) - db.volume_create(self.ctxt, {'id': 1}) + db.volume_create(self.ctxt, {'id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for snapshot in time_collection: db.snapshot_create(self.ctxt, {'id': snapshot, 'volume_id': 1, 'display_name': 'one', 'created_at': hours_ago(snapshot), - 'status': fields.SnapshotStatus.AVAILABLE}) + 'status': fields.SnapshotStatus.AVAILABLE, + 'volume_type_id': fake.VOLUME_TYPE_ID}) snapshot = db.snapshot_get_latest_for_volume(self.ctxt, 1) @@ -1588,34 +1729,44 @@ class DBAPISnapshotTestCase(BaseTest): def test_snapshot_get_latest_for_volume_not_found(self): - db.volume_create(self.ctxt, {'id': 1}) + db.volume_create(self.ctxt, {'id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) for t_id in [2, 3]: db.snapshot_create(self.ctxt, {'id': t_id, 'volume_id': t_id, 'display_name': 'one', - 'status': fields.SnapshotStatus.AVAILABLE}) + 'status': fields.SnapshotStatus.AVAILABLE, + 'volume_type_id': fake.VOLUME_TYPE_ID}) self.assertRaises(exception.VolumeSnapshotNotFound, db.snapshot_get_latest_for_volume, self.ctxt, 1) def test_snapshot_get_all_by_filter(self): - db.volume_create(self.ctxt, {'id': 1}) - db.volume_create(self.ctxt, {'id': 2}) + db.volume_create(self.ctxt, {'id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) + db.volume_create(self.ctxt, {'id': 2, + 'volume_type_id': fake.VOLUME_TYPE_ID}) snapshot1 = db.snapshot_create(self.ctxt, {'id': 1, 'volume_id': 1, 'display_name': 'one', 'status': - fields.SnapshotStatus.AVAILABLE}) + fields.SnapshotStatus.AVAILABLE, + 'volume_type_id': fake.VOLUME_TYPE_ID} + ) snapshot2 = db.snapshot_create(self.ctxt, {'id': 2, 'volume_id': 1, 'display_name': 'two', 'status': - fields.SnapshotStatus.CREATING}) + fields.SnapshotStatus.CREATING, + 'volume_type_id': fake.VOLUME_TYPE_ID} + ) snapshot3 = db.snapshot_create(self.ctxt, {'id': 3, 'volume_id': 2, 'display_name': 'three', 'status': - fields.SnapshotStatus.AVAILABLE}) + fields.SnapshotStatus.AVAILABLE, + 'volume_type_id': fake.VOLUME_TYPE_ID} + ) # no filter filters = {} snapshots = db.snapshot_get_all(self.ctxt, filters=filters) @@ -1691,14 +1842,21 @@ class DBAPISnapshotTestCase(BaseTest): {s.id for s in result}) def test_snapshot_get_all_by_host(self): - db.volume_create(self.ctxt, {'id': 1, 'host': 'host1'}) - db.volume_create(self.ctxt, {'id': 2, 'host': 'host2'}) - snapshot1 = db.snapshot_create(self.ctxt, {'id': 1, 'volume_id': 1}) + db.volume_create(self.ctxt, {'id': 1, 'host': 'host1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + db.volume_create(self.ctxt, {'id': 2, 'host': 'host2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + snapshot1 = db.snapshot_create(self.ctxt, + {'id': 1, 'volume_id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID} + ) snapshot2 = db.snapshot_create(self.ctxt, {'id': 2, 'volume_id': 2, 'status': - fields.SnapshotStatus.ERROR}) + fields.SnapshotStatus.ERROR, + 'volume_type_id': fake.VOLUME_TYPE_ID} + ) self._assertEqualListsOfObjects([snapshot1], db.snapshot_get_all_by_host( @@ -1728,11 +1886,19 @@ class DBAPISnapshotTestCase(BaseTest): self.assertEqual([], db.snapshot_get_all_by_host(self.ctxt, '')) def test_snapshot_get_all_by_host_with_pools(self): - db.volume_create(self.ctxt, {'id': 1, 'host': 'host1#pool1'}) - db.volume_create(self.ctxt, {'id': 2, 'host': 'host1#pool2'}) + db.volume_create(self.ctxt, {'id': 1, 'host': 'host1#pool1', + 'volume_type_id': fake.VOLUME_TYPE_ID}) + db.volume_create(self.ctxt, {'id': 2, 'host': 'host1#pool2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) - snapshot1 = db.snapshot_create(self.ctxt, {'id': 1, 'volume_id': 1}) - snapshot2 = db.snapshot_create(self.ctxt, {'id': 2, 'volume_id': 2}) + snapshot1 = db.snapshot_create(self.ctxt, + {'id': 1, 'volume_id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID} + ) + snapshot2 = db.snapshot_create(self.ctxt, + {'id': 2, 'volume_id': 2, + 'volume_type_id': fake.VOLUME_TYPE_ID} + ) self._assertEqualListsOfObjects([snapshot1, snapshot2], db.snapshot_get_all_by_host( @@ -1752,13 +1918,19 @@ class DBAPISnapshotTestCase(BaseTest): ignored_keys='volume') def test_snapshot_get_all_by_project(self): - db.volume_create(self.ctxt, {'id': 1}) - db.volume_create(self.ctxt, {'id': 2}) - snapshot1 = db.snapshot_create(self.ctxt, {'id': 1, 'volume_id': 1, - 'project_id': 'project1'}) + db.volume_create(self.ctxt, {'id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) + db.volume_create(self.ctxt, {'id': 2, + 'volume_type_id': fake.VOLUME_TYPE_ID}) + snapshot1 = db.snapshot_create(self.ctxt, + {'id': 1, 'volume_id': 1, + 'project_id': 'project1', + 'volume_type_id': fake.VOLUME_TYPE_ID} + ) snapshot2 = db.snapshot_create( self.ctxt, {'id': 2, 'volume_id': 2, 'status': - fields.SnapshotStatus.ERROR, 'project_id': 'project2'}) + fields.SnapshotStatus.ERROR, 'project_id': 'project2', + 'volume_type_id': fake.VOLUME_TYPE_ID}) self._assertEqualListsOfObjects([snapshot1], db.snapshot_get_all_by_project( @@ -1790,20 +1962,26 @@ class DBAPISnapshotTestCase(BaseTest): def test_snapshot_get_all_by_project_with_host(self): db.volume_create(self.ctxt, {'id': 1, 'host': 'host1', 'size': 1, - 'project_id': fake.PROJECT_ID}) + 'project_id': fake.PROJECT_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_create(self.ctxt, {'id': 2, 'host': 'host1', 'size': 2, - 'project_id': fake.PROJECT2_ID}) + 'project_id': fake.PROJECT2_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.volume_create(self.ctxt, {'id': 3, 'host': 'host2', 'size': 3, - 'project_id': fake.PROJECT2_ID}) + 'project_id': fake.PROJECT2_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, {'id': 1, 'volume_id': 1, 'project_id': fake.PROJECT_ID, - 'volume_size': 1}) + 'volume_size': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, {'id': 2, 'volume_id': 2, 'project_id': fake.PROJECT2_ID, - 'volume_size': 2}) + 'volume_size': 2, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, {'id': 3, 'volume_id': 3, 'project_id': fake.PROJECT2_ID, - 'volume_size': 3}) + 'volume_size': 3, + 'volume_type_id': fake.VOLUME_TYPE_ID}) resp = db.snapshot_data_get_for_project(self.ctxt, fake.PROJECT2_ID, host='host2') @@ -1811,9 +1989,11 @@ class DBAPISnapshotTestCase(BaseTest): def test_snapshot_metadata_get(self): metadata = {'a': 'b', 'c': 'd'} - db.volume_create(self.ctxt, {'id': 1}) + db.volume_create(self.ctxt, {'id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, - {'id': 1, 'volume_id': 1, 'metadata': metadata}) + {'id': 1, 'volume_id': 1, 'metadata': metadata, + 'volume_type_id': fake.VOLUME_TYPE_ID}) self.assertEqual(metadata, db.snapshot_metadata_get(self.ctxt, 1)) @@ -1822,9 +2002,11 @@ class DBAPISnapshotTestCase(BaseTest): metadata2 = {'a': '3', 'd': '5'} should_be = {'a': '3', 'c': '2', 'd': '5'} - db.volume_create(self.ctxt, {'id': 1}) + db.volume_create(self.ctxt, {'id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, - {'id': 1, 'volume_id': 1, 'metadata': metadata1}) + {'id': 1, 'volume_id': 1, 'metadata': metadata1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db_meta = db.snapshot_metadata_update(self.ctxt, 1, metadata2, False) self.assertEqual(should_be, db_meta) @@ -1834,9 +2016,11 @@ class DBAPISnapshotTestCase(BaseTest): metadata2 = {'a': '3', 'd': '5'} should_be = metadata2 - db.volume_create(self.ctxt, {'id': 1}) + db.volume_create(self.ctxt, {'id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, - {'id': 1, 'volume_id': 1, 'metadata': metadata1}) + {'id': 1, 'volume_id': 1, 'metadata': metadata1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db_meta = db.snapshot_metadata_update(self.ctxt, 1, metadata2, True) self.assertEqual(should_be, db_meta) @@ -1865,9 +2049,11 @@ class DBAPISnapshotTestCase(BaseTest): metadata = {'a': '1', 'c': '2'} should_be = {'a': '1'} - db.volume_create(self.ctxt, {'id': 1}) + db.volume_create(self.ctxt, {'id': 1, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, - {'id': 1, 'volume_id': 1, 'metadata': metadata}) + {'id': 1, 'volume_id': 1, 'metadata': metadata, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_metadata_delete(self.ctxt, 1, 'c') self.assertEqual(should_be, db.snapshot_metadata_get(self.ctxt, 1)) @@ -2050,18 +2236,13 @@ class DBAPIVolumeTypeTestCase(BaseTest): super(DBAPIVolumeTypeTestCase, self).setUp() def test_volume_type_create_exists(self): - vt = db.volume_type_create(self.ctxt, {'name': 'n1'}) self.assertRaises(exception.VolumeTypeExists, db.volume_type_create, self.ctxt, - {'name': 'n1'}) - self.assertRaises(exception.VolumeTypeExists, - db.volume_type_create, - self.ctxt, - {'name': 'n2', 'id': vt['id']}) + {'name': 'n2', 'id': self.vt['id']}) def test_volume_type_access_remove(self): - vt = db.volume_type_create(self.ctxt, {'name': 'n1'}) + vt = db.volume_type_create(self.ctxt, {'name': 'n2'}) db.volume_type_access_add(self.ctxt, vt['id'], 'fake_project') vtas = db.volume_type_access_get_all(self.ctxt, vt['id']) self.assertEqual(1, len(vtas)) @@ -2070,7 +2251,7 @@ class DBAPIVolumeTypeTestCase(BaseTest): self.assertEqual(0, len(vtas)) def test_volume_type_access_remove_high_id(self): - vt = db.volume_type_create(self.ctxt, {'name': 'n1'}) + vt = db.volume_type_create(self.ctxt, {'name': 'n2'}) vta = db.volume_type_access_add(self.ctxt, vt['id'], 'fake_project') vtas = db.volume_type_access_get_all(self.ctxt, vt['id']) self.assertEqual(1, len(vtas)) @@ -2093,7 +2274,7 @@ class DBAPIVolumeTypeTestCase(BaseTest): # the DB session is closed. vt_extra_specs = {'mock_key': 'mock_value'} vt = db.volume_type_create(self.ctxt, - {'name': 'n1', + {'name': 'n2', 'extra_specs': vt_extra_specs}) volume_ref = db.volume_create(self.ctxt, {'volume_type_id': vt.id}) @@ -2215,7 +2396,8 @@ class DBAPIEncryptionTestCase(BaseTest): def test_volume_encryption_get(self): # normal volume -- metadata should be None - volume = db.volume_create(self.ctxt, {}) + volume = db.volume_create(self.ctxt, { + 'volume_type_id': fake.VOLUME_TYPE_ID}) values = db.volume_encryption_metadata_get(self.ctxt, volume.id) self.assertEqual({'encryption_key_id': None}, values) @@ -3055,34 +3237,45 @@ class DBAPIGenericTestCase(BaseTest): # sql.exists().where(and_(*conditions))) # Instead of what we do: # query = get_session().query(sql.exists().where(and_(*conditions))) - db.volume_create(self.ctxt, {'id': fake.VOLUME_ID}) - db.volume_create(self.ctxt, {'id': fake.VOLUME2_ID}) + db.volume_create(self.ctxt, {'id': fake.VOLUME_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) + db.volume_create(self.ctxt, {'id': fake.VOLUME2_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) model = db.get_model_for_versioned_object(objects.Volume) res = sqlalchemy_api.resource_exists(self.ctxt, model, fake.VOLUME_ID) self.assertTrue(res, msg="Couldn't find existing Volume") def test_resource_exists_volume_fails(self): - db.volume_create(self.ctxt, {'id': fake.VOLUME_ID}) + db.volume_create(self.ctxt, {'id': fake.VOLUME_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) model = db.get_model_for_versioned_object(objects.Volume) res = sqlalchemy_api.resource_exists(self.ctxt, model, fake.VOLUME2_ID) self.assertFalse(res, msg='Found nonexistent Volume') def test_resource_exists_snapshot(self): # Read NOTE in test_resource_exists_volume on why we create 2 snapshots - vol = db.volume_create(self.ctxt, {'id': fake.VOLUME_ID}) + vol = db.volume_create(self.ctxt, + {'id': fake.VOLUME_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, {'id': fake.SNAPSHOT_ID, - 'volume_id': vol.id}) + 'volume_id': vol.id, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, {'id': fake.SNAPSHOT2_ID, - 'volume_id': vol.id}) + 'volume_id': vol.id, + 'volume_type_id': fake.VOLUME_TYPE_ID}) model = db.get_model_for_versioned_object(objects.Snapshot) res = sqlalchemy_api.resource_exists(self.ctxt, model, fake.SNAPSHOT_ID) self.assertTrue(res, msg="Couldn't find existing Snapshot") def test_resource_exists_snapshot_fails(self): - vol = db.volume_create(self.ctxt, {'id': fake.VOLUME_ID}) + vol = db.volume_create(self.ctxt, + {'id': fake.VOLUME_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) db.snapshot_create(self.ctxt, {'id': fake.SNAPSHOT_ID, - 'volume_id': vol.id}) + 'volume_id': vol.id, + 'volume_type_id': + fake.VOLUME_TYPE_ID}) model = db.get_model_for_versioned_object(objects.Snapshot) res = sqlalchemy_api.resource_exists(self.ctxt, model, fake.SNAPSHOT2_ID) @@ -3094,7 +3287,8 @@ class DBAPIGenericTestCase(BaseTest): user2_context = context.RequestContext(fake.USER2_ID, fake.PROJECT2_ID, is_admin=False) volume = db.volume_create(user_context, - {'project_id': fake.PROJECT_ID}) + {'project_id': fake.PROJECT_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) model = db.get_model_for_versioned_object(objects.Volume) # Owner can find it @@ -3115,9 +3309,13 @@ class DBAPIGenericTestCase(BaseTest): is_admin=False) user2_context = context.RequestContext(fake.USER2_ID, fake.PROJECT2_ID, is_admin=False) - vol = db.volume_create(user_context, {'project_id': fake.PROJECT_ID}) - snap = db.snapshot_create(self.ctxt, {'project_id': fake.PROJECT_ID, - 'volume_id': vol.id}) + vol = db.volume_create(user_context, + {'project_id': fake.PROJECT_ID, + 'volume_type_id': fake.VOLUME_TYPE_ID}) + snap = db.snapshot_create(self.ctxt, + {'project_id': fake.PROJECT_ID, + 'volume_id': vol.id, + 'volume_type_id': fake.VOLUME_TYPE_ID}) model = db.get_model_for_versioned_object(objects.Snapshot) # Owner can find it diff --git a/cinder/tests/unit/test_quota.py b/cinder/tests/unit/test_quota.py index 90a55370441..c240776121e 100644 --- a/cinder/tests/unit/test_quota.py +++ b/cinder/tests/unit/test_quota.py @@ -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') diff --git a/cinder/tests/unit/test_volume_glance_metadata.py b/cinder/tests/unit/test_volume_glance_metadata.py index ec2145a9f4c..fc09cf82960 100644 --- a/cinder/tests/unit/test_volume_glance_metadata.py +++ b/cinder/tests/unit/test_volume_glance_metadata.py @@ -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, diff --git a/cinder/tests/unit/test_volume_transfer.py b/cinder/tests/unit/test_volume_transfer.py index 5b5428f085e..1a75c12aee8 100644 --- a/cinder/tests/unit/test_volume_transfer.py +++ b/cinder/tests/unit/test_volume_transfer.py @@ -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() diff --git a/cinder/tests/unit/test_volume_types.py b/cinder/tests/unit/test_volume_types.py index f7858aabf79..a4e56e31944 100644 --- a/cinder/tests/unit/test_volume_types.py +++ b/cinder/tests/unit/test_volume_types.py @@ -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.""" diff --git a/cinder/tests/unit/utils.py b/cinder/tests/unit/utils.py index 6949e968ea2..a31b90d339b 100644 --- a/cinder/tests/unit/utils.py +++ b/cinder/tests/unit/utils.py @@ -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: diff --git a/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py b/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py index f14ab72eda5..de55377404d 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py @@ -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: diff --git a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py index 6cfd1938a5a..824ad1e4bb0 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py @@ -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 diff --git a/cinder/tests/unit/volume/drivers/ibm/test_xiv_proxy.py b/cinder/tests/unit/volume/drivers/ibm/test_xiv_proxy.py index 3840f01b5a7..3ed2acb3822 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_xiv_proxy.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_xiv_proxy.py @@ -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) diff --git a/cinder/tests/unit/volume/drivers/inspur/instorage/test_common.py b/cinder/tests/unit/volume/drivers/inspur/instorage/test_common.py index a61db20076e..2d921866493 100644 --- a/cinder/tests/unit/volume/drivers/inspur/instorage/test_common.py +++ b/cinder/tests/unit/volume/drivers/inspur/instorage/test_common.py @@ -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 diff --git a/cinder/tests/unit/volume/drivers/inspur/instorage/test_fc_driver.py b/cinder/tests/unit/volume/drivers/inspur/instorage/test_fc_driver.py index 20f92d551af..05e652f9c8f 100644 --- a/cinder/tests/unit/volume/drivers/inspur/instorage/test_fc_driver.py +++ b/cinder/tests/unit/volume/drivers/inspur/instorage/test_fc_driver.py @@ -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] diff --git a/cinder/tests/unit/volume/drivers/inspur/instorage/test_iscsi_driver.py b/cinder/tests/unit/volume/drivers/inspur/instorage/test_iscsi_driver.py index a38b5cc41e4..f672d217817 100644 --- a/cinder/tests/unit/volume/drivers/inspur/instorage/test_iscsi_driver.py +++ b/cinder/tests/unit/volume/drivers/inspur/instorage/test_iscsi_driver.py @@ -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] diff --git a/cinder/tests/unit/volume/drivers/nexenta/test_nexenta.py b/cinder/tests/unit/volume/drivers/nexenta/test_nexenta.py index b4be1419ad5..0033126aaf7 100644 --- a/cinder/tests/unit/volume/drivers/nexenta/test_nexenta.py +++ b/cinder/tests/unit/volume/drivers/nexenta/test_nexenta.py @@ -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'] diff --git a/cinder/tests/unit/volume/test_connection.py b/cinder/tests/unit/volume/test_connection.py index 5577c94a866..ac7b70398fa 100644 --- a/cinder/tests/unit/volume/test_connection.py +++ b/cinder/tests/unit/volume/test_connection.py @@ -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): diff --git a/cinder/tests/unit/volume/test_driver.py b/cinder/tests/unit/volume/test_driver.py index d7213bb7be3..be68f4191e6 100644 --- a/cinder/tests/unit/volume/test_driver.py +++ b/cinder/tests/unit/volume/test_driver.py @@ -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) diff --git a/cinder/tests/unit/volume/test_image.py b/cinder/tests/unit/volume/test_image.py index d2231954597..812d58bf87c 100644 --- a/cinder/tests/unit/volume/test_image.py +++ b/cinder/tests/unit/volume/test_image.py @@ -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']) diff --git a/cinder/tests/unit/volume/test_rpcapi.py b/cinder/tests/unit/volume/test_rpcapi.py index 1f12d9b259f..7075e3eaeed 100644 --- a/cinder/tests/unit/volume/test_rpcapi.py +++ b/cinder/tests/unit/volume/test_rpcapi.py @@ -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 = { diff --git a/cinder/tests/unit/volume/test_snapshot.py b/cinder/tests/unit/volume/test_snapshot.py index bd942a42e52..74dcf3b16e9 100644 --- a/cinder/tests/unit/volume/test_snapshot.py +++ b/cinder/tests/unit/volume/test_snapshot.py @@ -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) diff --git a/cinder/tests/unit/volume/test_volume.py b/cinder/tests/unit/volume/test_volume.py index 5570dc4cd69..ba6e9d807d5 100644 --- a/cinder/tests/unit/volume/test_volume.py +++ b/cinder/tests/unit/volume/test_volume.py @@ -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, diff --git a/cinder/tests/unit/volume/test_volume_usage_audit.py b/cinder/tests/unit/volume/test_volume_usage_audit.py index a20c21ac19f..bb9270d7000 100644 --- a/cinder/tests/unit/volume/test_volume_usage_audit.py +++ b/cinder/tests/unit/volume/test_volume_usage_audit.py @@ -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 diff --git a/cinder/volume/volume_types.py b/cinder/volume/volume_types.py index 65f94d7958b..5249a044183 100644 --- a/cinder/volume/volume_types.py +++ b/cinder/volume/volume_types.py @@ -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 diff --git a/releasenotes/notes/untyped_to_default_type-0068e6bc8000986c.yaml b/releasenotes/notes/untyped_to_default_type-0068e6bc8000986c.yaml new file mode 100644 index 00000000000..bd23bbd38d2 --- /dev/null +++ b/releasenotes/notes/untyped_to_default_type-0068e6bc8000986c.yaml @@ -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.