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:
|
sla:
|
||||||
failure_rate:
|
failure_rate:
|
||||||
max: 0
|
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
|
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")
|
@base.atomic_action_timer("cinder.create_snapshot")
|
||||||
def _create_snapshot(self, volume_id, force=False, **kwargs):
|
def _create_snapshot(self, volume_id, force=False, **kwargs):
|
||||||
"""Create one snapshot.
|
"""Create one snapshot.
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
from rally.benchmark.scenarios import base
|
from rally.benchmark.scenarios import base
|
||||||
from rally.benchmark.scenarios.cinder import utils
|
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.scenarios.nova import utils as nova_utils
|
||||||
from rally.benchmark import types as types
|
from rally.benchmark import types as types
|
||||||
from rally.benchmark import validation
|
from rally.benchmark import validation
|
||||||
@ -27,7 +28,8 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class CinderVolumes(utils.CinderScenario,
|
class CinderVolumes(utils.CinderScenario,
|
||||||
nova_utils.NovaScenario):
|
nova_utils.NovaScenario,
|
||||||
|
glance_utils.GlanceScenario):
|
||||||
"""Benchmark scenarios for Cinder Volumes."""
|
"""Benchmark scenarios for Cinder Volumes."""
|
||||||
|
|
||||||
@types.set(image=types.ImageResourceType)
|
@types.set(image=types.ImageResourceType)
|
||||||
@ -359,3 +361,30 @@ class CinderVolumes(utils.CinderScenario,
|
|||||||
volume = random.choice(self.context["tenant"]["volumes"])
|
volume = random.choice(self.context["tenant"]["volumes"])
|
||||||
self._create_snapshot(volume["id"], force=force, **kwargs)
|
self._create_snapshot(volume["id"], force=force, **kwargs)
|
||||||
self._list_snapshots(detailed)
|
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(),
|
self._test_atomic_action_timer(self.scenario.atomic_actions(),
|
||||||
"cinder.extend_volume")
|
"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")
|
@mock.patch(CINDER_UTILS + ".CinderScenario.clients")
|
||||||
def test__create_snapshot(self, mock_clients):
|
def test__create_snapshot(self, mock_clients):
|
||||||
snapshot = mock.Mock()
|
snapshot = mock.Mock()
|
||||||
|
@ -180,6 +180,40 @@ class CinderServersTestCase(test.TestCase):
|
|||||||
scenario._delete_volume.assert_called_once_with(fake_volume)
|
scenario._delete_volume.assert_called_once_with(fake_volume)
|
||||||
scenario._delete_server.assert_called_once_with(fake_server)
|
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):
|
def test_create_snapshot_and_attach_volume(self):
|
||||||
fake_volume = mock.MagicMock()
|
fake_volume = mock.MagicMock()
|
||||||
fake_snapshot = mock.MagicMock()
|
fake_snapshot = mock.MagicMock()
|
||||||
|
Loading…
Reference in New Issue
Block a user