Add new boot_server_attach_created_volume_and_extend test

This adds a new job to the nova scenarios that creates a server
and volume, attaches the volume and then extends the volume
while it's attached to the server as introduced in Pike [1].

[1] https://specs.openstack.org/openstack/nova-specs/specs/pike/implemented/nova-support-attached-volume-extend.html

Change-Id: Ia30f6fb65d3d60f02816125f47b545465f36f148
This commit is contained in:
Tobias Urdin 2022-08-24 08:58:24 +02:00
parent a73e803e7c
commit ba45f16ef1
5 changed files with 180 additions and 0 deletions

View File

@ -480,6 +480,28 @@
users: users:
tenants: 2 tenants: 2
users_per_tenant: 1 users_per_tenant: 1
-
title: NovaServers.boot_server_attach_created_volume_and_extend tests
scenario:
NovaServers.boot_server_attach_created_volume_and_extend:
flavor:
name: {{flavor_name}}
image:
name: {{image_name}}
volume_size: 1
new_volume_size: 2
force_delete: false
do_delete: true
boot_server_kwargs: {}
create_volume_kwargs: {}
runner:
constant:
times: 2
concurrency: 2
contexts:
users:
tenants: 2
users_per_tenant: 1
- -
title: NovaServers.boot_server_from_volume_and_resize tests title: NovaServers.boot_server_from_volume_and_resize tests
scenario: scenario:

View File

@ -491,6 +491,61 @@ class BootServerAttachCreatedVolumeAndResize(utils.NovaScenario,
self._delete_server(server, force=force_delete) self._delete_server(server, force=force_delete)
@types.convert(image={"type": "glance_image"},
flavor={"type": "nova_flavor"})
@validation.add("image_valid_on_flavor", flavor_param="flavor",
image_param="image")
@validation.add("required_services", services=[consts.Service.NOVA,
consts.Service.CINDER])
@validation.add("required_platform", platform="openstack", users=True)
@scenario.configure(
context={"cleanup@openstack": ["cinder", "nova"]},
name="NovaServers.boot_server_attach_created_volume_and_extend",
platform="openstack")
class BootServerAttachCreatedVolumeAndExtend(utils.NovaScenario,
cinder_utils.CinderBasic):
def run(self, image, flavor, volume_size, new_volume_size, min_sleep=0,
max_sleep=0, force_delete=False, do_delete=True,
boot_server_kwargs=None, create_volume_kwargs=None):
"""Create a VM from image, attach a volume then extend volume
Simple test to create a VM and attach a volume, then extend the
volume while its running, detach the volume then delete volume
and VM.
Optional 'min_sleep' and 'max_sleep' parameters allow the scenario
to simulate a pause between attaching a volume and running resize
(of random duration from range [min_sleep, max_sleep]).
:param image: Glance image name to use for the VM
:param flavor: VM flavor name
:param volume_size: volume size (in GB)
:param new_volume_size: new volume size (in GB)
:param min_sleep: Minimum sleep time in seconds (non-negative)
:param max_sleep: Maximum sleep time in seconds (non-negative)
:param force_delete: True if force_delete should be used
:param do_delete: True if resources needs to be deleted explicitly
else use rally cleanup to remove resources
:param boot_server_kwargs: optional arguments for VM creation
:param create_volume_kwargs: optional arguments for volume creation
"""
boot_server_kwargs = boot_server_kwargs or {}
create_volume_kwargs = create_volume_kwargs or {}
server = self._boot_server(image, flavor, **boot_server_kwargs)
volume = self.cinder.create_volume(volume_size, **create_volume_kwargs)
self._attach_volume(server, volume)
self.sleep_between(min_sleep, max_sleep)
self.cinder.extend_volume(volume, new_size=new_volume_size)
if do_delete:
self._detach_volume(server, volume)
self.cinder.delete_volume(volume)
self._delete_server(server, force=force_delete)
@validation.add("number", param_name="volume_num", minval=1, @validation.add("number", param_name="volume_num", minval=1,
integer_only=True) integer_only=True)
@validation.add("number", param_name="volume_size", minval=1, @validation.add("number", param_name="volume_size", minval=1,

View File

@ -0,0 +1,37 @@
{% set flavor_name = flavor_name or "m1.tiny" %}
{
"NovaServers.boot_server_attach_created_volume_and_extend": [
{
"args": {
"flavor": {
"name": "{{flavor_name}}"
},
"image": {
"name": "^cirros.*-disk$"
},
"volume_size": 1,
"new_volume_size": 2,
"force_delete": false,
"do_delete": true,
"boot_server_kwargs": {},
"create_volume_kwargs": {}
},
"runner": {
"type": "constant",
"times": 10,
"concurrency": 2
},
"context": {
"users": {
"tenants": 3,
"users_per_tenant": 2
}
},
"sla": {
"failure_rate": {
"max": 0
}
}
}
]
}

View File

@ -0,0 +1,26 @@
{% set flavor_name = flavor_name or "m1.tiny" %}
---
NovaServers.boot_server_attach_created_volume_and_extend:
-
args:
flavor:
name: "{{flavor_name}}"
image:
name: "^cirros.*-disk$"
volume_size: 1
new_volume_size: 2
force_delete: false
do_delete: true
boot_server_kwargs: {}
create_volume_kwargs: {}
runner:
type: "constant"
times: 10
concurrency: 2
context:
users:
tenants: 3
users_per_tenant: 2
sla:
failure_rate:
max: 0

View File

@ -567,6 +567,46 @@ class NovaServersTestCase(test.ScenarioTestCase):
scenario._delete_server.assert_called_once_with(fake_server, scenario._delete_server.assert_called_once_with(fake_server,
force=False) force=False)
@mock.patch("rally_openstack.common.services.storage.block.BlockStorage")
def test_boot_server_attach_created_volume_and_extend(
self, mock_block_storage, do_delete=False):
fake_volume = mock.MagicMock()
fake_server = mock.MagicMock()
flavor = mock.MagicMock()
fake_attachment = mock.MagicMock()
cinder = mock_block_storage.return_value
cinder.create_volume.return_value = fake_volume
scenario = servers.BootServerAttachCreatedVolumeAndExtend(
self.context, clients=mock.Mock())
scenario.generate_random_name = mock.MagicMock(return_value="name")
scenario._boot_server = mock.MagicMock(return_value=fake_server)
scenario._attach_volume = mock.MagicMock(return_value=fake_attachment)
scenario._detach_volume = mock.MagicMock()
scenario._delete_server = mock.MagicMock()
scenario.sleep_between = mock.MagicMock()
volume_size = 10
new_volume_size = 20
scenario.run("img", flavor, volume_size, new_volume_size,
min_sleep=10, max_sleep=20, do_delete=do_delete)
scenario._boot_server.assert_called_once_with("img", flavor)
cinder.create_volume.assert_called_once_with(volume_size)
scenario._attach_volume.assert_called_once_with(fake_server,
fake_volume)
scenario.sleep_between.assert_called_once_with(10, 20)
cinder.extend_volume.assert_called_once_with(
fake_volume, new_size=new_volume_size)
if do_delete:
scenario._detach_volume.assert_called_once_with(fake_server,
fake_volume)
cinder.delete_volume.assert_called_once_with(fake_volume)
scenario._delete_server.assert_called_once_with(fake_server,
force=False)
@mock.patch("rally_openstack.common.services.storage.block.BlockStorage") @mock.patch("rally_openstack.common.services.storage.block.BlockStorage")
def test_list_attachments(self, mock_block_storage): def test_list_attachments(self, mock_block_storage):
mock_volume_service = mock_block_storage.return_value mock_volume_service = mock_block_storage.return_value