Merge "Add nova.BootServerAttachVolumeAndListAttachemnt"
This commit is contained in:
commit
03b4700660
@ -1351,3 +1351,26 @@
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
NovaServers.boot_server_attach_volume_and_list_attachments:
|
||||
-
|
||||
args:
|
||||
flavor:
|
||||
name: {{flavor_name}}
|
||||
image:
|
||||
name: {{image_name}}
|
||||
volume_size: 1
|
||||
volume_num: 2
|
||||
boot_server_kwargs: {}
|
||||
create_volume_kwargs: {}
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 2
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
@ -482,6 +482,55 @@ class BootServerAttachCreatedVolumeAndResize(utils.NovaScenario,
|
||||
self._delete_server(server, force=force_delete)
|
||||
|
||||
|
||||
@validation.add("number", param_name="volume_num", minval=1,
|
||||
integer_only=True)
|
||||
@validation.add("number", param_name="volume_size", minval=1,
|
||||
integer_only=True)
|
||||
@types.convert(image={"type": "glance_image"},
|
||||
flavor={"type": "nova_flavor"})
|
||||
@validation.add("image_valid_on_flavor", flavor_param="flavor",
|
||||
image_param="image", validate_disk=False)
|
||||
@validation.add("required_services", services=[consts.Service.NOVA,
|
||||
consts.Service.CINDER])
|
||||
@validation.add("required_platform", platform="openstack", users=True)
|
||||
@scenario.configure(context={"cleanup": ["cinder", "nova"]},
|
||||
name=("NovaServers.boot_server"
|
||||
"_attach_volume_and_list_attachments"))
|
||||
class BootServerAttachVolumeAndListAttachments(utils.NovaScenario,
|
||||
cinder_utils.CinderBasic):
|
||||
|
||||
def run(self, image, flavor, volume_size=1, volume_num=2,
|
||||
boot_server_kwargs=None, create_volume_kwargs=None):
|
||||
"""Create a VM, attach N volume to it and list server's attachemnt.
|
||||
|
||||
Measure the "nova volume-attachments" command performance.
|
||||
|
||||
:param image: Glance image name to use for the VM
|
||||
:param flavor: VM flavor name
|
||||
:param volume_size: volume size (in GB), default 1G
|
||||
:param volume_num: the num of attached volume
|
||||
: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)
|
||||
attachments = []
|
||||
for i in range(volume_num):
|
||||
volume = self.cinder.create_volume(volume_size,
|
||||
**create_volume_kwargs)
|
||||
attachments.append(self._attach_volume(server, volume))
|
||||
|
||||
list_attachments = self._list_attachments(server.id)
|
||||
|
||||
for attachment in attachments:
|
||||
msg = ("attachment not included into list of available"
|
||||
"attachments\n attachment: {}\n"
|
||||
"list attachments: {}").format(attachment, list_attachments)
|
||||
self.assertIn(attachment, list_attachments, err_msg=msg)
|
||||
|
||||
|
||||
@types.convert(image={"type": "glance_image"},
|
||||
flavor={"type": "nova_flavor"},
|
||||
to_flavor={"type": "nova_flavor"})
|
||||
|
@ -691,6 +691,15 @@ class NovaScenario(scenario.OpenStackScenario):
|
||||
)
|
||||
return attachment
|
||||
|
||||
@atomic.action_timer("nova.list_attachments")
|
||||
def _list_attachments(self, server_id):
|
||||
"""Get a list of all the attached volumes for the given server ID.
|
||||
|
||||
:param server_id: The ID of the server
|
||||
:rtype: list of :class:`Volume`
|
||||
"""
|
||||
return self.clients("nova").volumes.get_server_volumes(server_id)
|
||||
|
||||
@atomic.action_timer("nova.detach_volume")
|
||||
def _detach_volume(self, server, volume, attachment=None):
|
||||
server_id = server.id
|
||||
|
@ -0,0 +1,36 @@
|
||||
{% set flavor_name = flavor_name or "m1.tiny" %}
|
||||
{% set image_name = "^(cirros.*-disk|TestVM)$" %}
|
||||
{
|
||||
"NovaServers.boot_server_attach_volume_and_list_attachments": [
|
||||
{
|
||||
"args": {
|
||||
"flavor": {
|
||||
"name": "{{flavor_name}}"
|
||||
},
|
||||
"image": {
|
||||
"name": "{{image_name}}"
|
||||
},
|
||||
"volume_size": 1,
|
||||
"volume_num": 2,
|
||||
"boot_server_kwargs": {},
|
||||
"create_volume_kwargs": {}
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 5,
|
||||
"concurrency": 2
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 2,
|
||||
"users_per_tenant": 2
|
||||
}
|
||||
},
|
||||
"sla": {
|
||||
"failure_rate": {
|
||||
"max": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
{% set flavor_name = flavor_name or "m1.tiny" %}
|
||||
{% set image_name = "^(cirros.*-disk|TestVM)$" %}
|
||||
---
|
||||
NovaServers.boot_server_attach_volume_and_list_attachments:
|
||||
-
|
||||
args:
|
||||
flavor:
|
||||
name: "{{flavor_name}}"
|
||||
image:
|
||||
name: "{{image_name}}"
|
||||
volume_size: 1
|
||||
volume_num: 2
|
||||
boot_server_kwargs: {}
|
||||
create_volume_kwargs: {}
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 5
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
@ -568,6 +568,94 @@ class NovaServersTestCase(test.ScenarioTestCase):
|
||||
scenario._delete_server.assert_called_once_with(fake_server,
|
||||
force=False)
|
||||
|
||||
@mock.patch("rally.plugins.openstack.services.storage.block.BlockStorage")
|
||||
def test_list_attachments(self, mock_block_storage):
|
||||
mock_volume_service = mock_block_storage.return_value
|
||||
fake_volume = mock.MagicMock()
|
||||
fake_server = mock.MagicMock()
|
||||
flavor = mock.MagicMock()
|
||||
fake_attachment = mock.MagicMock()
|
||||
list_attachments = [mock.MagicMock(),
|
||||
fake_attachment,
|
||||
mock.MagicMock()]
|
||||
context = self.context
|
||||
context.update({
|
||||
"admin": {
|
||||
"id": "fake_user_id",
|
||||
"credential": mock.MagicMock()
|
||||
},
|
||||
"user": {"id": "fake_user_id",
|
||||
"credential": mock.MagicMock()},
|
||||
"tenant": {"id": "fake", "name": "fake",
|
||||
"volumes": [{"id": "uuid", "size": 1}],
|
||||
"servers": [1]}})
|
||||
scenario = servers.BootServerAttachVolumeAndListAttachments(
|
||||
context)
|
||||
scenario._boot_server = mock.MagicMock(return_value=fake_server)
|
||||
scenario._attach_volume = mock.MagicMock()
|
||||
scenario._list_attachments = mock.MagicMock()
|
||||
mock_volume_service.create_volume.return_value = fake_volume
|
||||
scenario._list_attachments.return_value = list_attachments
|
||||
|
||||
img_name = "img"
|
||||
volume_size = 10
|
||||
volume_num = 1
|
||||
|
||||
scenario._attach_volume.return_value = fake_attachment
|
||||
scenario.run(img_name, flavor, volume_size, volume_num)
|
||||
|
||||
scenario._boot_server.assert_called_once_with(img_name, flavor)
|
||||
mock_volume_service.create_volume.assert_called_once_with(volume_size)
|
||||
scenario._attach_volume.assert_called_once_with(fake_server,
|
||||
fake_volume)
|
||||
scenario._list_attachments.assert_called_once_with(fake_server.id)
|
||||
|
||||
@mock.patch("rally.plugins.openstack.services.storage.block.BlockStorage")
|
||||
def test_list_attachments_fails(self, mock_block_storage):
|
||||
mock_volume_service = mock_block_storage.return_value
|
||||
fake_volume = mock.MagicMock()
|
||||
fake_server = mock.MagicMock()
|
||||
flavor = mock.MagicMock()
|
||||
fake_attachment = mock.MagicMock()
|
||||
list_attachments = [mock.MagicMock(),
|
||||
mock.MagicMock(),
|
||||
mock.MagicMock()]
|
||||
|
||||
context = self.context
|
||||
context.update({
|
||||
"admin": {
|
||||
"id": "fake_user_id",
|
||||
"credential": mock.MagicMock()
|
||||
},
|
||||
"user": {"id": "fake_user_id",
|
||||
"credential": mock.MagicMock()},
|
||||
"tenant": {"id": "fake", "name": "fake",
|
||||
"volumes": [{"id": "uuid", "size": 1}],
|
||||
"servers": [1]}})
|
||||
scenario = servers.BootServerAttachVolumeAndListAttachments(
|
||||
context)
|
||||
scenario._boot_server = mock.MagicMock(return_value=fake_server)
|
||||
mock_volume_service.create_volume.return_value = fake_volume
|
||||
scenario._attach_volume = mock.MagicMock()
|
||||
scenario._list_attachments = mock.MagicMock()
|
||||
scenario._attach_volume.return_value = fake_attachment
|
||||
scenario._list_attachments.return_value = list_attachments
|
||||
|
||||
img_name = "img"
|
||||
volume_size = 10
|
||||
|
||||
# Negative case: attachment not included into list of
|
||||
# available attachments
|
||||
self.assertRaises(rally_exceptions.RallyAssertionError,
|
||||
scenario.run,
|
||||
img_name, flavor, volume_size)
|
||||
|
||||
scenario._boot_server.assert_called_with(img_name, flavor)
|
||||
mock_volume_service.create_volume.assert_called_with(volume_size)
|
||||
scenario._attach_volume.assert_called_with(fake_server,
|
||||
fake_volume)
|
||||
scenario._list_attachments.assert_called_with(fake_server.id)
|
||||
|
||||
@ddt.data({"confirm": True, "do_delete": True},
|
||||
{"confirm": False, "do_delete": True})
|
||||
@ddt.unpack
|
||||
|
@ -617,6 +617,18 @@ class NovaScenarioTestCase(test.ScenarioTestCase):
|
||||
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||
"nova.attach_volume")
|
||||
|
||||
def test__list_attachments(self):
|
||||
expect_attachments = [mock.MagicMock()]
|
||||
(self.clients("nova").volumes.get_server_volumes
|
||||
.return_value) = expect_attachments
|
||||
nova_scenario = utils.NovaScenario(context=self.context)
|
||||
list_attachments = nova_scenario._list_attachments(self.server.id)
|
||||
self.assertEqual(expect_attachments, list_attachments)
|
||||
(self.clients("nova").volumes.get_server_volumes
|
||||
.assert_called_once_with(self.server.id))
|
||||
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||
"nova.list_attachments")
|
||||
|
||||
def test__detach_volume(self):
|
||||
attach = mock.MagicMock(id="attach_id")
|
||||
self.clients("nova").volumes.delete_server_volume.return_value = None
|
||||
|
Loading…
Reference in New Issue
Block a user