Support cinder api v3 and make it as the default version

Cinder already support api version 3, but rally is still not use v3 to
test, this patch is to make rally can test with v3 for cinder

Co-Authored-By: chenhb <chen.haibing1@zte.com.cn>

Change-Id: Ifcf9f3a33fe956cff6953aa5e2bdd43c0e18f027
This commit is contained in:
liangcui 2017-12-05 17:19:23 +08:00 committed by chenhb
parent 0a73f8ae80
commit 408391bcc6
13 changed files with 823 additions and 11 deletions

View File

@ -54,6 +54,7 @@
- rally-task-basic-with-existing-users:
# use_existing_users key did not trigger proper ansible tasks
voting: false
- rally-task-cinder
# NOTE(andreykurilin): this requires more thing to configure before
# launching.
#- rally-task-designate
@ -103,6 +104,7 @@
- rally-dsvm-tox-functional
- rally-docker-check
- rally-task-simple-job
- rally-task-cinder
#- rally-task-heat
- rally-task-ironic
- rally-task-keystone-glance-swift

View File

@ -28,6 +28,9 @@ Added
key files. Also the support for appropriate system environment variables (
``OS_CERT``, ``OS_KEY``) is added.
* Support client api option while deploying platform.
* Added Cinder V3 support and make it as the default version. You could use
api_versions context or api_info option of the spec to choose the proper
version.
Changed
~~~~~~~

View File

@ -92,6 +92,8 @@ class _Service(utils.ImmutableMixin, utils.EnumMixin):
NOVA = "nova"
NOVA_NET = "nova-network"
CINDER = "cinder"
CINDERV2 = "cinderv2"
CINDERV3 = "cinderv3"
MANILA = "manila"
EC2 = "ec2"
GLANCE = "glance"
@ -119,6 +121,8 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
"""OpenStack services types, mapped to service names."""
VOLUME = "volume"
VOLUMEV2 = "volumev2"
VOLUMEV3 = "volumev3"
SHARE = "share"
EC2 = "ec2"
IMAGE = "image"
@ -148,6 +152,8 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
self.CLUSTERING: _Service.SENLIN,
self.COMPUTE: _Service.NOVA,
self.VOLUME: _Service.CINDER,
self.VOLUMEV2: _Service.CINDERV2,
self.VOLUMEV3: _Service.CINDERV3,
self.SHARE: _Service.MANILA,
self.EC2: _Service.EC2,
self.IMAGE: _Service.GLANCE,

View File

@ -500,12 +500,13 @@ class Heat(OSClient):
return client
@configure("cinder", default_version="2", default_service_type="volumev2",
supported_versions=["1", "2"])
@configure("cinder", default_version="3", default_service_type="volumev3",
supported_versions=["1", "2", "3"])
class Cinder(OSClient):
"""Wrapper for CinderClient which returns an authenticated native client.
"""
def create_client(self, version=None, service_type=None):
"""Return cinder client."""
from cinderclient import client as cinder

View File

@ -66,7 +66,8 @@ class CreateAndGetVolumeType(cinder_utils.CinderBasic):
@validation.add("required_services", services=[consts.Service.CINDER])
@validation.add("required_api_versions", component="cinder", versions=["2"])
@validation.add("required_api_versions", component="cinder",
versions=["2", "3"])
@validation.add("required_platform", platform="openstack", admin=True)
@scenario.configure(context={"admin_cleanup@openstack": ["cinder"]},
name="CinderVolumeTypes.create_and_update_volume_type",
@ -380,7 +381,8 @@ class CreateAndUpdateEncryptionType(cinder_utils.CinderBasic):
@validation.add("required_platform", platform="openstack", admin=True)
@validation.add("required_api_versions", component="cinder", versions=["2"])
@validation.add("required_api_versions", component="cinder",
versions=["2", "3"])
@validation.add("required_services", services=consts.Service.CINDER)
@scenario.configure(
context={"admin_cleanup@openstack": ["cinder"]},

View File

@ -635,7 +635,8 @@ class CreateAndUploadVolumeToImage(cinder_utils.CinderBasic,
volume = self.cinder.create_volume(size, **kwargs)
image = self.cinder.upload_volume_to_image(
volume, force=force, container_format=container_format,
disk_format=disk_format)
disk_format=disk_format
)
if do_delete:
self.cinder.delete_volume(volume)

View File

@ -44,7 +44,7 @@ class BlockStorage(service.UnifiedService):
volume_type=None, user_id=None,
project_id=None, availability_zone=None,
metadata=None, imageRef=None, scheduler_hints=None,
source_replica=None, multiattach=False):
source_replica=None, multiattach=False, backup_id=None):
"""Creates a volume.
:param size: Size of volume in GB
@ -65,6 +65,7 @@ class BlockStorage(service.UnifiedService):
specified by the client to help boot an instance
:param multiattach: Allow the volume to be attached to more than
one instance
:param backup_id: ID of the backup
:returns: Return a new volume.
"""
@ -78,7 +79,7 @@ class BlockStorage(service.UnifiedService):
user_id=user_id, project_id=project_id,
availability_zone=availability_zone, metadata=metadata,
imageRef=imageRef, scheduler_hints=scheduler_hints,
multiattach=multiattach)
multiattach=multiattach, backup_id=backup_id)
@service.should_be_overridden
def list_volumes(self, detailed=True):

View File

@ -177,7 +177,7 @@ class UnifiedCinderV1Service(cinder_common.UnifiedCinderMixin,
volume_type=None, user_id=None,
project_id=None, availability_zone=None,
metadata=None, imageRef=None, scheduler_hints=None,
multiattach=False):
multiattach=False, backup_id=None):
"""Creates a volume.
:param size: Size of volume in GB
@ -197,6 +197,7 @@ class UnifiedCinderV1Service(cinder_common.UnifiedCinderMixin,
specified by the client to help boot an instance
:param multiattach: Allow the volume to be attached to more than
one instance
:param backup_id: ID of the backup(IGNORED)
:returns: Return a new volume.
"""

View File

@ -234,7 +234,7 @@ class UnifiedCinderV2Service(cinder_common.UnifiedCinderMixin,
volume_type=None, user_id=None,
project_id=None, availability_zone=None,
metadata=None, imageRef=None, scheduler_hints=None,
multiattach=False):
multiattach=False, backup_id=None):
"""Creates a volume.
:param size: Size of volume in GB
@ -254,6 +254,7 @@ class UnifiedCinderV2Service(cinder_common.UnifiedCinderMixin,
specified by the client to help boot an instance
:param multiattach: Allow the volume to be attached to more than
one instance
:param backup_id: ID of the backup(IGNORED)
:returns: Return a new volume.
"""

View File

@ -0,0 +1,380 @@
# All Rights Reserved.
#
# 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 random
from rally.common import utils as rutils
from rally.task import atomic
from rally_openstack import service
from rally_openstack.services.storage import block
from rally_openstack.services.storage import cinder_common
CONF = block.CONF
@service.service("cinder", service_type="block-storage", version="3")
class CinderV3Service(service.Service, cinder_common.CinderMixin):
@atomic.action_timer("cinder_v3.create_volume")
def create_volume(self, size, consistencygroup_id=None,
snapshot_id=None, source_volid=None, name=None,
description=None, volume_type=None,
availability_zone=None, metadata=None, imageRef=None,
scheduler_hints=None, multiattach=False, backup_id=None):
"""Creates a volume.
:param size: Size of volume in GB
:param consistencygroup_id: ID of the consistencygroup
:param snapshot_id: ID of the snapshot
:param name: Name of the volume
:param description: Description of the volume
:param volume_type: Type of volume
:param availability_zone: Availability Zone to use
:param metadata: Optional metadata to set on volume creation
:param imageRef: reference to an image stored in glance
:param source_volid: ID of source volume to clone from
:param scheduler_hints: (optional extension) arbitrary key-value pairs
specified by the client to help boot an instance
:param multiattach: Allow the volume to be attached to more than
one instance
:param backup_id: ID of the backup
:returns: Return a new volume.
"""
kwargs = {"name": name or self.generate_random_name(),
"description": description,
"consistencygroup_id": consistencygroup_id,
"snapshot_id": snapshot_id,
"source_volid": source_volid,
"volume_type": volume_type,
"availability_zone": availability_zone,
"metadata": metadata,
"imageRef": imageRef,
"scheduler_hints": scheduler_hints,
"multiattach": multiattach,
"backup_id": backup_id}
if isinstance(size, dict):
size = random.randint(size["min"], size["max"])
volume = (self._get_client()
.volumes.create(size, **kwargs))
# NOTE(msdubov): It is reasonable to wait 5 secs before starting to
# check whether the volume is ready => less API calls.
rutils.interruptable_sleep(
CONF.openstack.cinder_volume_create_prepoll_delay)
return self._wait_available_volume(volume)
@atomic.action_timer("cinder_v3.update_volume")
def update_volume(self, volume_id, name=None, description=None):
"""Update the name or description for a volume.
:param volume_id: The updated volume id.
:param name: The volume name.
:param description: The volume description.
:returns: The updated volume.
"""
kwargs = {}
if name is not None:
kwargs["name"] = name
if description is not None:
kwargs["description"] = description
updated_volume = self._get_client().volumes.update(
volume_id, **kwargs)
return updated_volume["volume"]
@atomic.action_timer("cinder_v3.list_types")
def list_types(self, search_opts=None, is_public=None):
"""Lists all volume types."""
return (self._get_client()
.volume_types.list(search_opts=search_opts,
is_public=is_public))
@atomic.action_timer("cinder_v3.create_snapshot")
def create_snapshot(self, volume_id, force=False,
name=None, description=None, metadata=None):
"""Create one snapshot.
Returns when the snapshot is actually created and is in the "Available"
state.
:param volume_id: volume uuid for creating snapshot
:param force: flag to indicate whether to snapshot a volume even if
it's attached to an instance
:param name: Name of the snapshot
:param description: Description of the snapshot
:returns: Created snapshot object
"""
kwargs = {"force": force,
"name": name or self.generate_random_name(),
"description": description,
"metadata": metadata}
snapshot = self._get_client().volume_snapshots.create(volume_id,
**kwargs)
rutils.interruptable_sleep(
CONF.openstack.cinder_volume_create_prepoll_delay)
snapshot = self._wait_available_volume(snapshot)
return snapshot
@atomic.action_timer("cinder_v3.create_backup")
def create_backup(self, volume_id, container=None,
name=None, description=None,
incremental=False, force=False,
snapshot_id=None):
"""Create a volume backup of the given volume.
:param volume_id: The ID of the volume to backup.
:param container: The name of the backup service container.
:param name: The name of the backup.
:param description: The description of the backup.
:param incremental: Incremental backup.
:param force: If True, allows an in-use volume to be backed up.
:param snapshot_id: The ID of the snapshot to backup.
"""
kwargs = {"force": force,
"name": name or self.generate_random_name(),
"description": description,
"container": container,
"incremental": incremental,
"force": force,
"snapshot_id": snapshot_id}
backup = self._get_client().backups.create(volume_id, **kwargs)
return self._wait_available_volume(backup)
@atomic.action_timer("cinder_v3.create_volume_type")
def create_volume_type(self, name=None, description=None, is_public=True):
"""create volume type.
:param name: Descriptive name of the volume type
:param description: Description of the volume type
:param is_public: Volume type visibility
:returns: Return the created volume type.
:returns: VolumeType object
"""
kwargs = {"name": name or self.generate_random_name(),
"description": description,
"is_public": is_public}
return self._get_client().volume_types.create(**kwargs)
@atomic.action_timer("cinder_v3.update_volume_type")
def update_volume_type(self, volume_type, update_name=False,
description=None, is_public=None):
"""Update the name and/or description for a volume type.
:param volume_type: The ID or a instance of the :class:`VolumeType`
to update.
:param update_name: if True, can update name by generating random name.
if False, don't update name.
:param description: Description of the the volume type.
:rtype: :class:`VolumeType`
"""
name = None
if update_name:
name = self.generate_random_name()
return self._get_client().volume_types.update(
volume_type=volume_type, name=name, description=description,
is_public=is_public)
@atomic.action_timer("cinder_v3.add_type_access")
def add_type_access(self, volume_type, project):
"""Add a project to the given volume type access list.
:param volume_type: Volume type name or ID to add access for the given
project
:project: Project ID to add volume type access for
:return: An instance of cinderclient.apiclient.base.TupleWithMeta
"""
return self._get_client().volume_type_access.add_project_access(
volume_type=volume_type, project=project)
@atomic.action_timer("cinder_v3.list_type_access")
def list_type_access(self, volume_type):
"""Print access information about the given volume type
:param volume_type: Filter results by volume type name or ID
:return: VolumeTypeAcces of specific project
"""
return self._get_client().volume_type_access.list(volume_type)
@service.compat_layer(CinderV3Service)
class UnifiedCinderV3Service(cinder_common.UnifiedCinderMixin,
block.BlockStorage):
@staticmethod
def _unify_volume(volume):
if isinstance(volume, dict):
return block.Volume(id=volume["id"], name=volume["name"],
size=volume["size"], status=volume["status"])
else:
return block.Volume(id=volume.id, name=volume.name,
size=volume.size, status=volume.status)
@staticmethod
def _unify_snapshot(snapshot):
return block.VolumeSnapshot(id=snapshot.id, name=snapshot.name,
volume_id=snapshot.volume_id,
status=snapshot.status)
def create_volume(self, size, consistencygroup_id=None,
group_id=None, snapshot_id=None, source_volid=None,
name=None, description=None,
volume_type=None, user_id=None,
project_id=None, availability_zone=None,
metadata=None, imageRef=None, scheduler_hints=None,
source_replica=None, multiattach=False, backup_id=None):
"""Creates a volume.
:param size: Size of volume in GB
:param consistencygroup_id: ID of the consistencygroup
:param group_id: ID of the group
:param snapshot_id: ID of the snapshot
:param name: Name of the volume
:param description: Description of the volume
:param volume_type: Type of volume
:param user_id: User id derived from context(IGNORED)
:param project_id: Project id derived from context(IGNORED)
:param availability_zone: Availability Zone to use
:param metadata: Optional metadata to set on volume creation
:param imageRef: reference to an image stored in glance
:param source_volid: ID of source volume to clone from
:param scheduler_hints: (optional extension) arbitrary key-value pairs
specified by the client to help boot an instance
:param multiattach: Allow the volume to be attached to more than
one instance
:param backup_id: ID of the backup
:returns: Return a new volume.
"""
return self._unify_volume(self._impl.create_volume(
size, consistencygroup_id=consistencygroup_id,
snapshot_id=snapshot_id,
source_volid=source_volid, name=name,
description=description, volume_type=volume_type,
availability_zone=availability_zone, metadata=metadata,
imageRef=imageRef, scheduler_hints=scheduler_hints,
multiattach=multiattach, backup_id=backup_id))
def list_volumes(self, detailed=True):
"""Lists all volumes.
:param detailed: Whether to return detailed volume info.
:returns: Return volumes list.
"""
return [self._unify_volume(volume)
for volume in self._impl.list_volumes(detailed=detailed)]
def get_volume(self, volume_id):
"""Get a volume.
:param volume_id: The ID of the volume to get.
:returns: Return the volume.
"""
return self._unify_volume(self._impl.get_volume(volume_id))
def extend_volume(self, volume, new_size):
"""Extend the size of the specified volume."""
return self._unify_volume(
self._impl.extend_volume(volume, new_size=new_size))
def update_volume(self, volume_id,
name=None, description=None):
"""Update the name or description for a volume.
:param volume_id: The updated volume id.
:param name: The volume name.
:param description: The volume description.
:returns: The updated volume.
"""
return self._unify_volume(self._impl.update_volume(
volume_id, name=name, description=description))
def list_types(self, search_opts=None, is_public=None):
"""Lists all volume types."""
return self._impl.list_types(search_opts=search_opts,
is_public=is_public)
def create_snapshot(self, volume_id, force=False,
name=None, description=None, metadata=None):
"""Create one snapshot.
Returns when the snapshot is actually created and is in the "Available"
state.
:param volume_id: volume uuid for creating snapshot
:param force: If force is True, create a snapshot even if the volume is
attached to an instance. Default is False.
:param name: Name of the snapshot
:param description: Description of the snapshot
:param metadata: Metadata of the snapshot
:returns: Created snapshot object
"""
return self._unify_snapshot(self._impl.create_snapshot(
volume_id, force=force, name=name,
description=description, metadata=metadata))
def list_snapshots(self, detailed=True):
"""Get a list of all snapshots."""
return [self._unify_snapshot(snapshot)
for snapshot in self._impl.list_snapshots(detailed=detailed)]
def create_backup(self, volume_id, container=None,
name=None, description=None,
incremental=False, force=False,
snapshot_id=None):
"""Creates a volume backup.
:param volume_id: The ID of the volume to backup.
:param container: The name of the backup service container.
:param name: The name of the backup.
:param description: The description of the backup.
:param incremental: Incremental backup.
:param force: If True, allows an in-use volume to be backed up.
:param snapshot_id: The ID of the snapshot to backup.
:returns: The created backup object.
"""
return self._unify_backup(self._impl.create_backup(
volume_id, container=container, name=name, description=description,
incremental=incremental, force=force, snapshot_id=snapshot_id))
def create_volume_type(self, name=None, description=None, is_public=True):
"""Creates a volume type.
:param name: Descriptive name of the volume type
:param description: Description of the volume type
:param is_public: Volume type visibility
:returns: Return the created volume type.
"""
return self._impl.create_volume_type(name=name,
description=description,
is_public=is_public)
def restore_backup(self, backup_id, volume_id=None):
"""Restore the given backup.
:param backup_id: The ID of the backup to restore.
:param volume_id: The ID of the volume to restore the backup to.
:returns: Return the restored backup.
"""
return self._unify_volume(self._impl.restore_backup(
backup_id, volume_id=volume_id))

View File

@ -40,7 +40,7 @@ class BlockTestCase(test.TestCase):
description=None, group_id=None, imageRef=None, metadata=None,
multiattach=False, name=None, project_id=None,
scheduler_hints=None, snapshot_id=None,
source_volid=None, user_id=None, volume_type=None)
source_volid=None, user_id=None, volume_type=None, backup_id=None)
def test_list_volumes(self):
self.assertEqual(self.service._impl.list_volumes.return_value,

View File

@ -0,0 +1,414 @@
# All Rights Reserved.
#
# 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 ddt
import mock
from rally.common import cfg
from rally_openstack.services.storage import cinder_v3
from tests.unit import fakes
from tests.unit import test
BASE_PATH = "rally_openstack.services.storage"
CONF = cfg.CONF
@ddt.ddt
class CinderV3ServiceTestCase(test.ScenarioTestCase):
def setUp(self):
super(CinderV3ServiceTestCase, self).setUp()
self.clients = mock.MagicMock()
self.cinder = self.clients.cinder.return_value
self.name_generator = mock.MagicMock()
self.service = cinder_v3.CinderV3Service(
self.clients, name_generator=self.name_generator)
def atomic_actions(self):
return self.service._atomic_actions
def test_create_volume(self):
self.service.generate_random_name = mock.MagicMock(
return_value="volume")
self.service._wait_available_volume = mock.MagicMock()
self.service._wait_available_volume.return_value = fakes.FakeVolume()
return_volume = self.service.create_volume(1)
kwargs = {"name": "volume",
"description": None,
"consistencygroup_id": None,
"snapshot_id": None,
"source_volid": None,
"volume_type": None,
"availability_zone": None,
"metadata": None,
"imageRef": None,
"scheduler_hints": None,
"multiattach": False,
"backup_id": None}
self.cinder.volumes.create.assert_called_once_with(1, **kwargs)
self.service._wait_available_volume.assert_called_once_with(
self.cinder.volumes.create.return_value)
self.assertEqual(self.service._wait_available_volume.return_value,
return_volume)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.create_volume")
@mock.patch("%s.cinder_v3.random" % BASE_PATH)
def test_create_volume_with_size_range(self, mock_random):
mock_random.randint.return_value = 3
self.service._wait_available_volume = mock.MagicMock()
self.service._wait_available_volume.return_value = fakes.FakeVolume()
return_volume = self.service.create_volume(
size={"min": 1, "max": 5}, name="volume")
kwargs = {"name": "volume",
"description": None,
"consistencygroup_id": None,
"snapshot_id": None,
"source_volid": None,
"volume_type": None,
"availability_zone": None,
"metadata": None,
"imageRef": None,
"scheduler_hints": None,
"multiattach": False,
"backup_id": None}
self.cinder.volumes.create.assert_called_once_with(
3, **kwargs)
self.service._wait_available_volume.assert_called_once_with(
self.cinder.volumes.create.return_value)
self.assertEqual(self.service._wait_available_volume.return_value,
return_volume)
def test_update_volume(self):
return_value = {"volume": fakes.FakeVolume()}
self.cinder.volumes.update.return_value = return_value
self.assertEqual(return_value["volume"],
self.service.update_volume(1))
self.cinder.volumes.update.assert_called_once_with(1)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.update_volume")
def test_update_volume_with_name_description(self):
return_value = {"volume": fakes.FakeVolume()}
self.cinder.volumes.update.return_value = return_value
return_volume = self.service.update_volume(
1, name="volume", description="fake")
self.cinder.volumes.update.assert_called_once_with(
1, name="volume", description="fake")
self.assertEqual(return_value["volume"], return_volume)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.update_volume")
def test_list_types(self):
self.assertEqual(self.cinder.volume_types.list.return_value,
self.service.list_types(search_opts=None,
is_public=None))
self.cinder.volume_types.list.assert_called_once_with(
search_opts=None, is_public=None)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.list_types")
def test_create_snapshot(self):
self.service._wait_available_volume = mock.MagicMock()
self.service._wait_available_volume.return_value = fakes.FakeVolume()
self.service.generate_random_name = mock.MagicMock(
return_value="snapshot")
return_snapshot = self.service.create_snapshot(1)
self.cinder.volume_snapshots.create.assert_called_once_with(
1, name="snapshot", description=None, force=False,
metadata=None)
self.service._wait_available_volume.assert_called_once_with(
self.cinder.volume_snapshots.create.return_value)
self.assertEqual(self.service._wait_available_volume.return_value,
return_snapshot)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.create_snapshot")
def test_create_snapshot_with_name(self):
self.service._wait_available_volume = mock.MagicMock()
self.service._wait_available_volume.return_value = fakes.FakeVolume()
return_snapshot = self.service.create_snapshot(1, name="snapshot")
self.cinder.volume_snapshots.create.assert_called_once_with(
1, name="snapshot", description=None, force=False,
metadata=None)
self.service._wait_available_volume.assert_called_once_with(
self.cinder.volume_snapshots.create.return_value)
self.assertEqual(self.service._wait_available_volume.return_value,
return_snapshot)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.create_snapshot")
def test_create_backup(self):
self.service._wait_available_volume = mock.MagicMock()
self.service._wait_available_volume.return_value = fakes.FakeVolume()
self.service.generate_random_name = mock.MagicMock(
return_value="backup")
return_backup = self.service.create_backup(1)
self.cinder.backups.create.assert_called_once_with(
1, name="backup", description=None, container=None,
incremental=False, force=False, snapshot_id=None)
self.service._wait_available_volume.assert_called_once_with(
self.cinder.backups.create.return_value)
self.assertEqual(self.service._wait_available_volume.return_value,
return_backup)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.create_backup")
def test_create_backup_with_name(self):
self.service._wait_available_volume = mock.MagicMock()
self.service._wait_available_volume.return_value = fakes.FakeVolume()
return_backup = self.service.create_backup(1, name="backup")
self.cinder.backups.create.assert_called_once_with(
1, name="backup", description=None, container=None,
incremental=False, force=False, snapshot_id=None)
self.service._wait_available_volume.assert_called_once_with(
self.cinder.backups.create.return_value)
self.assertEqual(self.service._wait_available_volume.return_value,
return_backup)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.create_backup")
def test_create_volume_type(self):
self.service.generate_random_name = mock.MagicMock(
return_value="volume_type")
return_type = self.service.create_volume_type(name=None,
description=None,
is_public=True)
self.cinder.volume_types.create.assert_called_once_with(
name="volume_type", description=None, is_public=True)
self.assertEqual(self.cinder.volume_types.create.return_value,
return_type)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.create_volume_type")
def test_create_volume_type_with_name_(self):
return_type = self.service.create_volume_type(name="type",
description=None,
is_public=True)
self.cinder.volume_types.create.assert_called_once_with(
name="type", description=None, is_public=True)
self.assertEqual(self.cinder.volume_types.create.return_value,
return_type)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.create_volume_type")
def test_update_volume_type(self):
volume_type = mock.Mock()
name = "random_name"
self.service.generate_random_name = mock.MagicMock(
return_value=name)
description = "test update"
result = self.service.update_volume_type(volume_type,
description=description,
update_name=True,
is_public=None)
self.assertEqual(
self.cinder.volume_types.update.return_value,
result)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.update_volume_type")
def test_add_type_access(self):
volume_type = mock.Mock()
project = mock.Mock()
type_access = self.service.add_type_access(volume_type,
project=project)
add_project_access = self.cinder.volume_type_access.add_project_access
add_project_access.assert_called_once_with(
volume_type=volume_type, project=project)
self.assertEqual(add_project_access.return_value,
type_access)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.add_type_access")
def test_list_type_access(self):
volume_type = mock.Mock()
type_access = self.service.list_type_access(volume_type)
self.cinder.volume_type_access.list.assert_called_once_with(
volume_type)
self.assertEqual(self.cinder.volume_type_access.list.return_value,
type_access)
self._test_atomic_action_timer(self.atomic_actions(),
"cinder_v3.list_type_access")
class UnifiedCinderV3ServiceTestCase(test.TestCase):
def setUp(self):
super(UnifiedCinderV3ServiceTestCase, self).setUp()
self.clients = mock.MagicMock()
self.service = cinder_v3.UnifiedCinderV3Service(self.clients)
self.service._impl = mock.MagicMock()
def test__unify_volume(self):
class SomeVolume(object):
id = 1
name = "volume"
size = 1
status = "st"
volume = self.service._unify_volume(SomeVolume())
self.assertEqual(1, volume.id)
self.assertEqual("volume", volume.name)
self.assertEqual(1, volume.size)
self.assertEqual("st", volume.status)
def test__unify_volume_with_dict(self):
some_volume = {"name": "volume", "id": 1, "size": 1, "status": "st"}
volume = self.service._unify_volume(some_volume)
self.assertEqual(1, volume.id)
self.assertEqual("volume", volume.name)
self.assertEqual(1, volume.size)
self.assertEqual("st", volume.status)
def test__unify_snapshot(self):
class SomeSnapshot(object):
id = 1
name = "snapshot"
volume_id = "volume"
status = "st"
snapshot = self.service._unify_snapshot(SomeSnapshot())
self.assertEqual(1, snapshot.id)
self.assertEqual("snapshot", snapshot.name)
self.assertEqual("volume", snapshot.volume_id)
self.assertEqual("st", snapshot.status)
def test_create_volume(self):
self.service._unify_volume = mock.MagicMock()
self.assertEqual(self.service._unify_volume.return_value,
self.service.create_volume(1))
self.service._impl.create_volume.assert_called_once_with(
1, availability_zone=None, consistencygroup_id=None,
description=None, imageRef=None,
metadata=None, multiattach=False, name=None,
scheduler_hints=None, snapshot_id=None,
source_volid=None, volume_type=None, backup_id=None)
self.service._unify_volume.assert_called_once_with(
self.service._impl.create_volume.return_value)
def test_list_volumes(self):
self.service._unify_volume = mock.MagicMock()
self.service._impl.list_volumes.return_value = ["vol"]
self.assertEqual([self.service._unify_volume.return_value],
self.service.list_volumes(detailed=True))
self.service._impl.list_volumes.assert_called_once_with(detailed=True)
self.service._unify_volume.assert_called_once_with("vol")
def test_get_volume(self):
self.service._unify_volume = mock.MagicMock()
self.assertEqual(self.service._unify_volume.return_value,
self.service.get_volume(1))
self.service._impl.get_volume.assert_called_once_with(1)
self.service._unify_volume.assert_called_once_with(
self.service._impl.get_volume.return_value)
def test_extend_volume(self):
self.service._unify_volume = mock.MagicMock()
self.assertEqual(self.service._unify_volume.return_value,
self.service.extend_volume("volume", new_size=1))
self.service._impl.extend_volume.assert_called_once_with("volume",
new_size=1)
self.service._unify_volume.assert_called_once_with(
self.service._impl.extend_volume.return_value)
def test_update_volume(self):
self.service._unify_volume = mock.MagicMock()
self.assertEqual(
self.service._unify_volume.return_value,
self.service.update_volume(1, name="volume",
description="fake"))
self.service._impl.update_volume.assert_called_once_with(
1, description="fake", name="volume")
self.service._unify_volume.assert_called_once_with(
self.service._impl.update_volume.return_value)
def test_list_types(self):
self.assertEqual(
self.service._impl.list_types.return_value,
self.service.list_types(search_opts=None, is_public=True))
self.service._impl.list_types.assert_called_once_with(
search_opts=None, is_public=True)
def test_create_snapshot(self):
self.service._unify_snapshot = mock.MagicMock()
self.assertEqual(
self.service._unify_snapshot.return_value,
self.service.create_snapshot(1, force=False,
name=None,
description=None,
metadata=None))
self.service._impl.create_snapshot.assert_called_once_with(
1, force=False, name=None, description=None, metadata=None)
self.service._unify_snapshot.assert_called_once_with(
self.service._impl.create_snapshot.return_value)
def test_list_snapshots(self):
self.service._unify_snapshot = mock.MagicMock()
self.service._impl.list_snapshots.return_value = ["snapshot"]
self.assertEqual([self.service._unify_snapshot.return_value],
self.service.list_snapshots(detailed=True))
self.service._impl.list_snapshots.assert_called_once_with(
detailed=True)
self.service._unify_snapshot.assert_called_once_with(
"snapshot")
def test_create_backup(self):
self.service._unify_backup = mock.MagicMock()
self.assertEqual(
self.service._unify_backup.return_value,
self.service.create_backup(1, container=None,
name=None,
description=None,
incremental=False,
force=False,
snapshot_id=None))
self.service._impl.create_backup.assert_called_once_with(
1, container=None, name=None, description=None,
incremental=False, force=False, snapshot_id=None)
self.service._unify_backup(
self.service._impl.create_backup.return_value)
def test_create_volume_type(self):
self.assertEqual(
self.service._impl.create_volume_type.return_value,
self.service.create_volume_type(name="type",
description="desp",
is_public=True))
self.service._impl.create_volume_type.assert_called_once_with(
name="type", description="desp", is_public=True)
def test_restore_backup(self):
self.service._unify_volume = mock.MagicMock()
self.assertEqual(self.service._unify_volume.return_value,
self.service.restore_backup(1, volume_id=1))
self.service._impl.restore_backup.assert_called_once_with(
1, volume_id=1)
self.service._unify_volume.assert_called_once_with(
self.service._impl.restore_backup.return_value)

View File

@ -644,7 +644,7 @@ class OSClientsTestCase(test.TestCase):
"session": mock_keystoneauth1.session.Session(),
"endpoint_override": mock_cinder__get_endpoint.return_value}
mock_cinder.client.Client.assert_called_once_with(
"2", **kw)
"3", **kw)
self.assertEqual(fake_cinder, self.clients.cache["cinder"])
@mock.patch("%s.Manila._get_endpoint" % PATH)