create a new server in each iteration when making snapshots from a server

1. maxinum number of volumes per VM is 26 because of hard-coded limit
2. detaching will be blocked when large concurency

Closes-Bug: #1708160
Change-Id: Ice2126209abd1812d1d133f597660be9e6dd3e6c
This commit is contained in:
cxhuawei 2017-09-20 19:14:15 -07:00 committed by Andrey Kurilin
parent 7d8df9c3a8
commit a48810e082
8 changed files with 102 additions and 110 deletions

View File

@ -471,6 +471,10 @@
CinderVolumes.create_snapshot_and_attach_volume:
volume_type: "lvmdriver-1"
size: 1
image:
name: {{image_name}}
flavor:
name: {{flavor_name}}
runner:
constant:
times: 2
@ -479,18 +483,16 @@
users:
tenants: 2
users_per_tenant: 2
servers:
image:
name: {{image_name}}
flavor:
name: {{flavor_name}}
servers_per_tenant: 1
-
description: "Create a volume using volume type created in context."
scenario:
CinderVolumes.create_snapshot_and_attach_volume:
volume_type: "test"
size: 1
image:
name: {{image_name}}
flavor:
name: {{flavor_name}}
runner:
constant:
times: 2
@ -499,12 +501,6 @@
users:
tenants: 2
users_per_tenant: 2
servers:
image:
name: {{image_name}}
flavor:
name: {{flavor_name}}
servers_per_tenant: 1
volume_types:
- "test"
-
@ -691,6 +687,10 @@
min: 1
max: 1
nested_level: 2
image:
name: {{image_name}}
flavor:
name: {{flavor_name}}
runner:
constant:
times: 2
@ -699,12 +699,6 @@
users:
tenants: 2
users_per_tenant: 1
servers:
image:
name: {{image_name}}
flavor:
name: {{flavor_name}}
servers_per_tenant: 2
-
title: CinderVolumes.create_volume_and_clone tests

View File

@ -43,17 +43,14 @@
size:
min: 1
max: 1
runner:
constant:
times: 2
concurrency: 2
contexts:
servers:
image:
name: {{image_name}}
flavor:
name: {{flavor_name}}
servers_per_tenant: 1
runner:
constant:
times: 2
concurrency: 2
sla:
failure_rate:
max: 0

View File

@ -449,6 +449,12 @@ class CreateAndAttachVolume(cinder_utils.CinderBasic,
self._delete_server(server)
@types.convert(image={"type": "glance_image"},
flavor={"type": "nova_flavor"})
@validation.add("image_valid_on_flavor", flavor_param="flavor",
image_param="image")
@validation.add("restricted_parameters", param_names=["name", "display_name"],
subdict="create_vm_params")
@validation.add("restricted_parameters", param_names=["name", "display_name"])
@validation.add("required_services", services=[consts.Service.NOVA,
consts.Service.CINDER])
@ -460,14 +466,18 @@ class CreateAndAttachVolume(cinder_utils.CinderBasic,
class CreateSnapshotAndAttachVolume(cinder_utils.CinderBasic,
nova_utils.NovaScenario):
def run(self, volume_type=None, size=None, **kwargs):
"""Create volume, snapshot and attach/detach volume.
def run(self, image, flavor, volume_type=None, size=None,
create_vm_params=None, **kwargs):
"""Create vm, volume, snapshot and attach/detach volume.
:param image: Glance image name to use for the VM
:param flavor: VM flavor name
:param volume_type: Name of volume type to use
:param size: Volume size - dictionary, contains two values:
min - minimum size volumes will be created as;
max - maximum size volumes will be created as.
default values: {"min": 1, "max": 5}
:param create_vm_params: optional arguments for VM creation
:param kwargs: Optional parameters used during volume
snapshot creation.
"""
@ -477,22 +487,30 @@ class CreateSnapshotAndAttachVolume(cinder_utils.CinderBasic,
volume = self.cinder.create_volume(size, volume_type=volume_type)
snapshot = self.cinder.create_snapshot(volume.id, force=False,
**kwargs)
create_vm_params = create_vm_params or {}
server = self.get_random_server()
server = self._boot_server(image, flavor, **create_vm_params)
self._attach_volume(server, volume)
self._detach_volume(server, volume)
self.cinder.delete_snapshot(snapshot)
self.cinder.delete_volume(volume)
self._delete_server(server)
@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("restricted_parameters", param_names=["name", "display_name"],
subdict="create_volume_kwargs")
@validation.add("restricted_parameters", param_names=["name", "display_name"],
subdict="create_snapshot_kwargs")
@validation.add("restricted_parameters", param_names=["name", "display_name"],
subdict="create_vm_params")
@validation.add("required_platform", platform="openstack", users=True)
@scenario.configure(context={"cleanup": ["cinder", "nova"]},
name="CinderVolumes.create_nested_snapshots"
@ -501,18 +519,18 @@ class CreateSnapshotAndAttachVolume(cinder_utils.CinderBasic,
class CreateNestedSnapshotsAndAttachVolume(cinder_utils.CinderBasic,
nova_utils.NovaScenario):
@logging.log_deprecated_args(
"Use 'create_snapshot_kwargs' for additional snapshot kwargs.",
"0.4.1", ["kwargs"], once=True)
def run(self, size=None, nested_level=1, create_volume_kwargs=None,
create_snapshot_kwargs=None, **kwargs):
def run(self, image, flavor, size=None, nested_level=1,
create_volume_kwargs=None, create_snapshot_kwargs=None,
create_vm_params=None):
"""Create a volume from snapshot and attach/detach the volume
This scenario create volume, create it's snapshot, attach volume,
This scenario create vm, volume, create it's snapshot, attach volume,
then create new volume from existing snapshot and so on,
with defined nested level, after all detach and delete them.
volume->snapshot->volume->snapshot->volume ...
:param image: Glance image name to use for the VM
:param flavor: VM flavor name
:param size: Volume size - dictionary, contains two values:
min - minimum size volumes will be created as;
max - maximum size volumes will be created as.
@ -520,8 +538,7 @@ class CreateNestedSnapshotsAndAttachVolume(cinder_utils.CinderBasic,
:param nested_level: amount of nested levels
:param create_volume_kwargs: optional args to create a volume
:param create_snapshot_kwargs: optional args to create a snapshot
:param kwargs: Optional parameters used during volume
snapshot creation.
:param create_vm_params: optional arguments for VM creation
"""
if size is None:
size = {"min": 1, "max": 5}
@ -533,29 +550,31 @@ class CreateNestedSnapshotsAndAttachVolume(cinder_utils.CinderBasic,
size = random.randint(size["min"], size["max"])
create_volume_kwargs = create_volume_kwargs or {}
create_snapshot_kwargs = create_snapshot_kwargs or kwargs or {}
server = self.get_random_server()
create_snapshot_kwargs = create_snapshot_kwargs or {}
create_vm_params = create_vm_params or {}
server = self._boot_server(image, flavor, **create_vm_params)
source_vol = self.cinder.create_volume(size, **create_volume_kwargs)
snapshot = self.cinder.create_snapshot(source_vol.id, force=False,
**create_snapshot_kwargs)
attachment = self._attach_volume(server, source_vol)
self._attach_volume(server, source_vol)
nes_objs = [(server, source_vol, snapshot, attachment)]
nes_objs = [(server, source_vol, snapshot)]
for i in range(nested_level - 1):
volume = self.cinder.create_volume(size, snapshot_id=snapshot.id)
snapshot = self.cinder.create_snapshot(volume.id, force=False,
**create_snapshot_kwargs)
server = self.get_random_server()
attachment = self._attach_volume(server, volume)
self._attach_volume(server, volume)
nes_objs.append((server, volume, snapshot, attachment))
nes_objs.append((server, volume, snapshot))
nes_objs.reverse()
for server, volume, snapshot, attachment in nes_objs:
for server, volume, snapshot in nes_objs:
self._detach_volume(server, volume)
self.cinder.delete_snapshot(snapshot)
self.cinder.delete_volume(volume)
self._delete_server(server)
@validation.add("required_services", services=[consts.Service.CINDER])

View File

@ -7,7 +7,13 @@
"min": 1,
"max": 5
},
"nested_level": 5
"nested_level": 5,
"image": {
"name": "^cirros.*-disk$"
},
"flavor": {
"name": "{{flavor_name}}"
}
},
"runner": {
"type": "constant",
@ -18,15 +24,6 @@
"users": {
"tenants": 2,
"users_per_tenant": 1
},
"servers": {
"image": {
"name": "^cirros.*-disk$"
},
"flavor": {
"name": "{{flavor_name}}"
},
"servers_per_tenant": 2
}
},
"sla": {

View File

@ -7,6 +7,10 @@
min: 1
max: 5
nested_level: 5
image:
name: "^cirros.*-disk$"
flavor:
name: "{{flavor_name}}"
runner:
type: "constant"
times: 1
@ -15,12 +19,6 @@
users:
tenants: 2
users_per_tenant: 1
servers:
image:
name: "^cirros.*-disk$"
flavor:
name: "{{flavor_name}}"
servers_per_tenant: 2
sla:
failure_rate:
max: 0

View File

@ -7,6 +7,12 @@
"size": {
"min": 1,
"max": 5
},
"image": {
"name": "^cirros.*-disk$"
},
"flavor": {
"name": "{{flavor_name}}"
}
},
"runner": {
@ -18,15 +24,6 @@
"users": {
"tenants": 2,
"users_per_tenant": 1
},
"servers": {
"image": {
"name": "^cirros.*-disk$"
},
"flavor": {
"name": "{{flavor_name}}"
},
"servers_per_tenant": 2
}
},
"sla": {
@ -41,6 +38,12 @@
"size": {
"min": 1,
"max": 5
},
"image": {
"name": "^cirros.*-disk$"
},
"flavor": {
"name": "{{flavor_name}}"
}
},
"runner": {
@ -53,15 +56,6 @@
"tenants": 2,
"users_per_tenant": 1
},
"servers": {
"image": {
"name": "^cirros.*-disk$"
},
"flavor": {
"name": "{{flavor_name}}"
},
"servers_per_tenant": 2
},
"volume_types": ["test"]
},
"sla": {

View File

@ -7,6 +7,10 @@
size:
min: 1
max: 5
image:
name: "^cirros.*-disk$"
flavor:
name: "{{flavor_name}}"
runner:
type: "constant"
times: 4
@ -15,12 +19,6 @@
users:
tenants: 2
users_per_tenant: 1
servers:
image:
name: "^cirros.*-disk$"
flavor:
name: "{{flavor_name}}"
servers_per_tenant: 2
sla:
failure_rate:
max: 0
@ -30,6 +28,10 @@
size:
min: 1
max: 5
image:
name: "^cirros.*-disk$"
flavor:
name: "{{flavor_name}}"
runner:
type: "constant"
times: 4
@ -38,12 +40,6 @@
users:
tenants: 2
users_per_tenant: 1
servers:
image:
name: "^cirros.*-disk$"
flavor:
name: "{{flavor_name}}"
servers_per_tenant: 2
volume_types:
- "test"
sla:

View File

@ -268,10 +268,10 @@ class CinderServersTestCase(test.ScenarioTestCase):
def test_create_snapshot_and_attach_volume(self):
mock_service = self.mock_cinder.return_value
scenario = volumes.CreateSnapshotAndAttachVolume(self._get_context())
scenario.get_random_server = mock.MagicMock()
scenario._boot_server = mock.MagicMock()
scenario._attach_volume = mock.MagicMock()
scenario._detach_volume = mock.MagicMock()
scenario.run()
scenario.run("img", "flavor")
self.assertTrue(mock_service.create_volume.called)
volume = mock_service.create_volume.return_value
@ -280,9 +280,9 @@ class CinderServersTestCase(test.ScenarioTestCase):
force=False)
mock_service.delete_snapshot.assert_called_once_with(snapshot)
scenario._attach_volume.assert_called_once_with(
scenario.get_random_server.return_value, volume)
scenario._boot_server.return_value, volume)
scenario._detach_volume.assert_called_once_with(
scenario.get_random_server.return_value, volume)
scenario._boot_server.return_value, volume)
mock_service.delete_volume.assert_called_once_with(volume)
@mock.patch("random.choice")
@ -291,13 +291,13 @@ class CinderServersTestCase(test.ScenarioTestCase):
mock_service = self.mock_cinder.return_value
scenario = volumes.CreateSnapshotAndAttachVolume(self._get_context())
scenario.get_random_server = mock.MagicMock()
scenario._boot_server = mock.MagicMock()
scenario._attach_volume = mock.MagicMock()
scenario._detach_volume = mock.MagicMock()
scenario.run(volume_type="type")
scenario.run("img", "flavor", volume_type="type")
fake_volume = mock_service.create_volume.return_value
fake_server = scenario.get_random_server.return_value
fake_server = scenario._boot_server.return_value
fake_snapshot = mock_service.create_snapshot.return_value
mock_service.create_volume.assert_called_once_with(
@ -320,10 +320,10 @@ class CinderServersTestCase(test.ScenarioTestCase):
scenario = volumes.CreateNestedSnapshotsAndAttachVolume(
context=self._get_context())
scenario.get_random_server = mock.MagicMock()
scenario._boot_server = mock.MagicMock()
scenario._attach_volume = mock.MagicMock()
scenario._detach_volume = mock.MagicMock()
scenario.run(create_volume_kwargs=volume_kwargs,
scenario.run("img", "flavor", create_volume_kwargs=volume_kwargs,
create_snapshot_kwargs=snapshot_kwargs)
mock_service.create_volume.assert_called_once_with(
@ -331,14 +331,14 @@ class CinderServersTestCase(test.ScenarioTestCase):
mock_service.create_snapshot.assert_called_once_with(
mock_service.create_volume.return_value.id, force=False,
**snapshot_kwargs)
scenario._attach_volume(scenario.get_random_server.return_value,
scenario._attach_volume(scenario._boot_server.return_value,
mock_service.create_volume.return_value)
mock_service.delete_volume.assert_called_once_with(
mock_service.create_volume.return_value)
mock_service.delete_snapshot.assert_called_once_with(
mock_service.create_snapshot.return_value)
scenario._detach_volume.assert_called_once_with(
scenario.get_random_server.return_value,
scenario._boot_server.return_value,
mock_service.create_volume.return_value)
@mock.patch("random.randint")
@ -351,21 +351,19 @@ class CinderServersTestCase(test.ScenarioTestCase):
for i in range(nested_level)]
fake_snapshots = [mock.Mock()
for i in range(nested_level)]
fake_attachs = [mock.Mock(size=volume_size)
for i in range(nested_level)]
mock_service.create_volume.side_effect = fake_volumes
mock_service.create_snapshot.side_effect = fake_snapshots
scenario = volumes.CreateNestedSnapshotsAndAttachVolume(
context=self._get_context())
scenario.get_random_server = mock.MagicMock()
scenario._attach_volume = mock.MagicMock(side_effect=fake_attachs)
scenario._boot_server = mock.MagicMock()
scenario._attach_volume = mock.MagicMock()
scenario._detach_volume = mock.MagicMock()
scenario.run(nested_level=nested_level)
scenario.run("img", "flavor", nested_level=nested_level)
expected_volumes = [mock.call(volume_size)]
expected_snapshots = [mock.call(fake_volumes[0].id, force=False)]
expected_attachs = [mock.call(scenario.get_random_server.return_value,
expected_attachs = [mock.call(scenario._boot_server.return_value,
fake_volumes[0])]
for i in range(nested_level - 1):
expected_volumes.append(
@ -373,7 +371,7 @@ class CinderServersTestCase(test.ScenarioTestCase):
expected_snapshots.append(
mock.call(fake_volumes[i + 1].id, force=False))
expected_attachs.append(
mock.call(scenario.get_random_server.return_value,
mock.call(scenario._boot_server.return_value,
fake_volumes[i + 1]))
mock_service.create_volume.assert_has_calls(expected_volumes)
@ -381,13 +379,12 @@ class CinderServersTestCase(test.ScenarioTestCase):
scenario._attach_volume.assert_has_calls(expected_attachs)
fake_volumes.reverse()
fake_snapshots.reverse()
fake_attachs.reverse()
mock_service.delete_volume.assert_has_calls(
[mock.call(volume) for volume in fake_volumes])
mock_service.delete_snapshot.assert_has_calls(
[mock.call(snapshot) for snapshot in fake_snapshots])
scenario._detach_volume.assert_has_calls(
[mock.call(scenario.get_random_server.return_value,
[mock.call(scenario._boot_server.return_value,
fake_volumes[i])
for i in range(len(fake_volumes))])