Skip to content

Commit

Permalink
Merge "Implement create_and_upload_volume_to_image scenario for Cinder"
Browse files Browse the repository at this point in the history
  • Loading branch information
Jenkins authored and openstack-gerrit committed Mar 9, 2015
2 parents 52b7252 + 8afb31c commit dfa302f
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 1 deletion.
16 changes: 16 additions & 0 deletions rally-jobs/rally-mos_neutron_v3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
40 changes: 40 additions & 0 deletions rally/benchmark/scenarios/cinder/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,46 @@ def _extend_volume(self, volume, new_size):
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.
Expand Down
31 changes: 30 additions & 1 deletion rally/benchmark/scenarios/cinder/volumes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -27,7 +28,8 @@


class CinderVolumes(utils.CinderScenario,
nova_utils.NovaScenario):
nova_utils.NovaScenario,
glance_utils.GlanceScenario):
"""Benchmark scenarios for Cinder Volumes."""

@types.set(image=types.ImageResourceType)
Expand Down Expand Up @@ -359,3 +361,30 @@ def create_and_list_snapshots(self, force=False, detailed=True, **kwargs):
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)
Original file line number Diff line number Diff line change
@@ -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
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions tests/unit/benchmark/scenarios/cinder/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,23 @@ def test__extend_volume(self, mock_clients):
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()
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/benchmark/scenarios/cinder/test_volumes.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,40 @@ def test_create_and_attach_volume(self):
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()
Expand Down

0 comments on commit dfa302f

Please sign in to comment.