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:
parent
0a73f8ae80
commit
408391bcc6
@ -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
|
||||
|
@ -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
|
||||
~~~~~~~
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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"]},
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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.
|
||||
"""
|
||||
|
@ -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.
|
||||
"""
|
||||
|
380
rally_openstack/services/storage/cinder_v3.py
Normal file
380
rally_openstack/services/storage/cinder_v3.py
Normal 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))
|
@ -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,
|
||||
|
414
tests/unit/services/storage/test_cinder_v3.py
Normal file
414
tests/unit/services/storage/test_cinder_v3.py
Normal 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)
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user