Implement create_and_upload_volume_to_image scenario for Cinder
The `create_and_upload_volume_to_image' sceanario can not be run on the DSVM gate with the default settings because it uses 1GB Swift backend for Glance image store. Change-Id: I41e1b391c560c7b9156e68c640531942cc8bf34c
This commit is contained in:
parent
f41531e60c
commit
8afb31c2dc
@ -258,3 +258,19 @@
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
CinderVolumes.create_and_upload_volume_to_image:
|
||||
-
|
||||
args:
|
||||
size: 1
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 1
|
||||
concurrency: 1
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
@ -125,6 +125,46 @@ class CinderScenario(base.Scenario):
|
||||
check_interval=CONF.benchmark.cinder_volume_create_poll_interval
|
||||
)
|
||||
|
||||
@base.atomic_action_timer("cinder.upload_volume_to_image")
|
||||
def _upload_volume_to_image(self, volume, force=False,
|
||||
container_format="bare", disk_format="raw"):
|
||||
"""Upload the given volume to image.
|
||||
|
||||
Returns created image.
|
||||
|
||||
:param volume: volume object
|
||||
:param force: flag to indicate whether to snapshot a volume even if
|
||||
it's attached to an instance
|
||||
:param container_format: container format of image. Acceptable
|
||||
formats: ami, ari, aki, bare, and ovf
|
||||
:param: disk_format: disk format of image. Acceptable formats:
|
||||
ami, ari, aki, vhd, vmdk, raw, qcow2, vdi
|
||||
and iso
|
||||
:returns: Returns created image object
|
||||
"""
|
||||
resp, img = volume.upload_to_image(force, self._generate_random_name(),
|
||||
container_format, disk_format)
|
||||
# NOTE (e0ne): upload_to_image changes volume status to uploading so
|
||||
# we need to wait until it will be available.
|
||||
volume = bench_utils.wait_for(
|
||||
volume,
|
||||
is_ready=bench_utils.resource_is("available"),
|
||||
update_resource=bench_utils.get_from_manager(),
|
||||
timeout=CONF.benchmark.cinder_volume_create_timeout,
|
||||
check_interval=CONF.benchmark.cinder_volume_create_poll_interval
|
||||
)
|
||||
image_id = img["os-volume_upload_image"]["image_id"]
|
||||
image = self.clients("glance").images.get(image_id)
|
||||
image = bench_utils.wait_for(
|
||||
image,
|
||||
is_ready=bench_utils.resource_is("active"),
|
||||
update_resource=bench_utils.get_from_manager(),
|
||||
timeout=CONF.benchmark.glance_image_create_prepoll_delay,
|
||||
check_interval=CONF.benchmark.glance_image_create_poll_interval
|
||||
)
|
||||
|
||||
return image
|
||||
|
||||
@base.atomic_action_timer("cinder.create_snapshot")
|
||||
def _create_snapshot(self, volume_id, force=False, **kwargs):
|
||||
"""Create one snapshot.
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
from rally.benchmark.scenarios import base
|
||||
from rally.benchmark.scenarios.cinder import utils
|
||||
from rally.benchmark.scenarios.glance import utils as glance_utils
|
||||
from rally.benchmark.scenarios.nova import utils as nova_utils
|
||||
from rally.benchmark import types as types
|
||||
from rally.benchmark import validation
|
||||
@ -27,7 +28,8 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CinderVolumes(utils.CinderScenario,
|
||||
nova_utils.NovaScenario):
|
||||
nova_utils.NovaScenario,
|
||||
glance_utils.GlanceScenario):
|
||||
"""Benchmark scenarios for Cinder Volumes."""
|
||||
|
||||
@types.set(image=types.ImageResourceType)
|
||||
@ -359,3 +361,30 @@ class CinderVolumes(utils.CinderScenario,
|
||||
volume = random.choice(self.context["tenant"]["volumes"])
|
||||
self._create_snapshot(volume["id"], force=force, **kwargs)
|
||||
self._list_snapshots(detailed)
|
||||
|
||||
@validation.required_services(consts.Service.CINDER, consts.Service.GLANCE)
|
||||
@validation.required_openstack(users=True)
|
||||
@validation.required_parameters("size")
|
||||
@base.scenario(context={"cleanup": ["cinder", "glance"]})
|
||||
def create_and_upload_volume_to_image(self, size, force=False,
|
||||
container_format="bare",
|
||||
disk_format="raw",
|
||||
do_delete=True,
|
||||
**kwargs):
|
||||
"""Create and upload a volume to image.
|
||||
|
||||
:param size: volume size (integers, in GB)
|
||||
:param force: when set to True volume that is attached to an instance
|
||||
could be uploaded to image
|
||||
:param container_format: image container format
|
||||
:param disk_format: disk format for image
|
||||
:param do_delete: deletes image and volume after uploading if True
|
||||
:param kwargs: optional args to create a volume
|
||||
"""
|
||||
volume = self._create_volume(size, **kwargs)
|
||||
image = self._upload_volume_to_image(volume, force, container_format,
|
||||
disk_format)
|
||||
|
||||
if do_delete:
|
||||
self._delete_volume(volume)
|
||||
self._delete_image(image)
|
||||
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"CinderVolumes.create_and_upload_volume_to_image": [
|
||||
{
|
||||
"args": {
|
||||
"size": 1,
|
||||
"force": false,
|
||||
"container_format": "bare",
|
||||
"disk_format": "raw",
|
||||
"do_delete": true
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 3,
|
||||
"concurrency": 2
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 2,
|
||||
"users_per_tenant": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
---
|
||||
CinderVolumes.create_and_upload_volume_to_image:
|
||||
-
|
||||
args:
|
||||
size: 1
|
||||
force: false
|
||||
container_format: "bare"
|
||||
disk_format: "raw"
|
||||
do_delete: true
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 3
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
@ -107,6 +107,23 @@ class CinderScenarioTestCase(test.TestCase):
|
||||
self._test_atomic_action_timer(self.scenario.atomic_actions(),
|
||||
"cinder.extend_volume")
|
||||
|
||||
@mock.patch(CINDER_UTILS + ".CinderScenario.clients")
|
||||
def test__upload_volume_to_image(self, mock_clients):
|
||||
volume = mock.Mock()
|
||||
image = {"os-volume_upload_image": {"image_id": 1}}
|
||||
volume.upload_to_image.return_value = (None, image)
|
||||
mock_clients("cinder").images.get.return_value = image
|
||||
|
||||
self.scenario._generate_random_name = mock.Mock(
|
||||
return_value="test_vol")
|
||||
self.scenario._upload_volume_to_image(volume, False,
|
||||
"container", "disk")
|
||||
|
||||
volume.upload_to_image.assert_called_once_with(False, "test_vol",
|
||||
"container", "disk")
|
||||
self.assertTrue(self.wait_for.mock.called)
|
||||
self.assertEqual(2, self.wait_for.mock.call_count)
|
||||
|
||||
@mock.patch(CINDER_UTILS + ".CinderScenario.clients")
|
||||
def test__create_snapshot(self, mock_clients):
|
||||
snapshot = mock.Mock()
|
||||
|
@ -180,6 +180,40 @@ class CinderServersTestCase(test.TestCase):
|
||||
scenario._delete_volume.assert_called_once_with(fake_volume)
|
||||
scenario._delete_server.assert_called_once_with(fake_server)
|
||||
|
||||
def test_create_and_upload_volume_to_image(self):
|
||||
fake_volume = mock.Mock()
|
||||
fake_image = mock.Mock()
|
||||
scenario = volumes.CinderVolumes()
|
||||
|
||||
scenario._create_volume = mock.MagicMock(return_value=fake_volume)
|
||||
scenario._upload_volume_to_image = mock.MagicMock(
|
||||
return_value=fake_image)
|
||||
scenario._delete_volume = mock.MagicMock()
|
||||
scenario._delete_image = mock.MagicMock()
|
||||
|
||||
scenario.create_and_upload_volume_to_image(2,
|
||||
container_format="fake",
|
||||
disk_format="disk",
|
||||
do_delete=False)
|
||||
|
||||
scenario._create_volume.assert_called_once_with(2)
|
||||
scenario._upload_volume_to_image.assert_called_once_with(fake_volume,
|
||||
False,
|
||||
"fake",
|
||||
"disk")
|
||||
scenario._create_volume.reset_mock()
|
||||
scenario._upload_volume_to_image.reset_mock()
|
||||
|
||||
scenario.create_and_upload_volume_to_image(1, do_delete=True)
|
||||
|
||||
scenario._create_volume.assert_called_once_with(1)
|
||||
scenario._upload_volume_to_image.assert_called_once_with(fake_volume,
|
||||
False,
|
||||
"bare",
|
||||
"raw")
|
||||
scenario._delete_volume.assert_called_once_with(fake_volume)
|
||||
scenario._delete_image.assert_called_once_with(fake_image)
|
||||
|
||||
def test_create_snapshot_and_attach_volume(self):
|
||||
fake_volume = mock.MagicMock()
|
||||
fake_snapshot = mock.MagicMock()
|
||||
|
Loading…
Reference in New Issue
Block a user