From e08aff21aed12ed1e611f43a09b6a17ad671217b Mon Sep 17 00:00:00 2001 From: maxinjian Date: Tue, 18 Oct 2016 23:16:17 -0400 Subject: [PATCH] Add CinderVolumes.create_and_accept_transfer Create a volume transfer, then accept it Measure the "cinder transfer-create" and "cinder transfer-accept" command performace. Change-Id: I4eba595e8798d7787c3d056e7ec22d58280541c9 --- rally-jobs/cinder.yaml | 32 +++++++++++++++++++ .../openstack/scenarios/cinder/utils.py | 20 ++++++++++++ .../openstack/scenarios/cinder/volumes.py | 25 +++++++++++++++ .../cinder/create-and-accept-transfer.json | 25 +++++++++++++++ .../cinder/create-and-accept-transfer.yaml | 16 ++++++++++ tests/ci/osresources.py | 3 ++ .../openstack/scenarios/cinder/test_utils.py | 25 +++++++++++++++ .../scenarios/cinder/test_volumes.py | 18 +++++++++++ 8 files changed, 164 insertions(+) create mode 100644 samples/tasks/scenarios/cinder/create-and-accept-transfer.json create mode 100644 samples/tasks/scenarios/cinder/create-and-accept-transfer.yaml diff --git a/rally-jobs/cinder.yaml b/rally-jobs/cinder.yaml index 33bef6a1..5487ed9f 100755 --- a/rally-jobs/cinder.yaml +++ b/rally-jobs/cinder.yaml @@ -336,6 +336,38 @@ failure_rate: max: 0 + CinderVolumes.create_and_accept_transfer: + - + args: + size: 1 + runner: + type: "constant" + times: 3 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 + - + args: + size: 1 + image: + name: {{image_name}} + runner: + type: "constant" + times: 3 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 + CinderVolumes.create_and_extend_volume: - args: diff --git a/rally/plugins/openstack/scenarios/cinder/utils.py b/rally/plugins/openstack/scenarios/cinder/utils.py index 1290d184..791f4e1b 100644 --- a/rally/plugins/openstack/scenarios/cinder/utils.py +++ b/rally/plugins/openstack/scenarios/cinder/utils.py @@ -413,3 +413,23 @@ class CinderScenario(scenario.OpenStackScenario): tuple_res = self.admin_clients("cinder").volume_types.delete( volume_type) return (tuple_res[0].status_code == 202) + + @atomic.action_timer("cinder.transfer_create") + def _transfer_create(self, volume_id): + """Create a volume transfer. + + :param volume_id: The ID of the volume to transfer + :rtype: VolumeTransfer + """ + name = self.generate_random_name() + return self.clients("cinder").transfers.create(volume_id, name) + + @atomic.action_timer("cinder.transfer_accept") + def _transfer_accept(self, transfer_id, auth_key): + """Accept a volume transfer. + + :param transfer_id: The ID of the transfer to accept. + :param auth_key: The auth_key of the transfer. + :rtype: VolumeTransfer + """ + return self.clients("cinder").transfers.accept(transfer_id, auth_key) diff --git a/rally/plugins/openstack/scenarios/cinder/volumes.py b/rally/plugins/openstack/scenarios/cinder/volumes.py index 57467eea..2384f283 100755 --- a/rally/plugins/openstack/scenarios/cinder/volumes.py +++ b/rally/plugins/openstack/scenarios/cinder/volumes.py @@ -763,3 +763,28 @@ class CreateVolumeAndUpdateReadonlyFlag(cinder_utils.CinderScenario, kwargs["imageRef"] = image volume = self._create_volume(size, **kwargs) self._update_readonly_flag(volume.id, read_only) + + +@types.convert(image={"type": "glance_image"}) +@validation.image_exists("image", nullable=True) +@validation.required_services(consts.Service.CINDER) +@validation.required_openstack(users=True) +@scenario.configure(context={"cleanup": ["cinder"]}, + name="CinderVolumes.create_and_accept_transfer") +class CreateAndAcceptTransfer(cinder_utils.CinderScenario, + glance_utils.GlanceScenario): + + def run(self, size, image=None, **kwargs): + """Create a volume transfer, then accept it + + Measure the "cinder transfer-create" and "cinder transfer-accept" + command performace. + :param size: volume size (integer, in GB) + :param image: image to be used to create initial volume + :param kwargs: optional args to create a volume + """ + if image: + kwargs["imageRef"] = image + volume = self._create_volume(size, **kwargs) + transfer = self._transfer_create(volume.id) + self._transfer_accept(transfer.id, transfer.auth_key) diff --git a/samples/tasks/scenarios/cinder/create-and-accept-transfer.json b/samples/tasks/scenarios/cinder/create-and-accept-transfer.json new file mode 100644 index 00000000..339fcf3b --- /dev/null +++ b/samples/tasks/scenarios/cinder/create-and-accept-transfer.json @@ -0,0 +1,25 @@ +{ + "CinderVolumes.create_and_accept_transfer": [ + { + "args": { + "size": 1 + }, + "runner": { + "type": "constant", + "times": 3, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/cinder/create-and-accept-transfer.yaml b/samples/tasks/scenarios/cinder/create-and-accept-transfer.yaml new file mode 100644 index 00000000..32a15eaf --- /dev/null +++ b/samples/tasks/scenarios/cinder/create-and-accept-transfer.yaml @@ -0,0 +1,16 @@ +--- + CinderVolumes.create_and_accept_transfer: + - + args: + size: 1 + runner: + type: "constant" + times: 3 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 diff --git a/tests/ci/osresources.py b/tests/ci/osresources.py index 45e76881..f3ab69d9 100755 --- a/tests/ci/osresources.py +++ b/tests/ci/osresources.py @@ -259,6 +259,9 @@ class Cinder(ResourceManager): def list_volume_types(self): return self.client.volume_types.list() + def list_transfers(self): + return self.client.transfers.list() + def list_volumes(self): return self.client.volumes.list( search_opts={"all_tenants": True}) diff --git a/tests/unit/plugins/openstack/scenarios/cinder/test_utils.py b/tests/unit/plugins/openstack/scenarios/cinder/test_utils.py index fdbaa5b8..76d8bd6d 100644 --- a/tests/unit/plugins/openstack/scenarios/cinder/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/cinder/test_utils.py @@ -382,3 +382,28 @@ class CinderScenarioTestCase(test.ScenarioTestCase): volume_type) self._test_atomic_action_timer(self.scenario.atomic_actions(), "cinder.delete_volume_type") + + def test__transfer_create(self): + fake_volume = mock.MagicMock() + random_name = "random_name" + self.scenario.generate_random_name = mock.MagicMock( + return_value=random_name) + result = self.scenario._transfer_create(fake_volume.id) + self.assertEqual( + self.clients("cinder").transfers.create.return_value, + result) + self.clients("cinder").transfers.create.assert_called_once_with( + fake_volume.id, random_name) + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "cinder.transfer_create") + + def test__transfer_accept(self): + fake_transfer = mock.MagicMock() + result = self.scenario._transfer_accept(fake_transfer.id, "fake_key") + self.assertEqual( + self.clients("cinder").transfers.accept.return_value, + result) + self.clients("cinder").transfers.accept.assert_called_once_with( + fake_transfer.id, "fake_key") + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "cinder.transfer_accept") diff --git a/tests/unit/plugins/openstack/scenarios/cinder/test_volumes.py b/tests/unit/plugins/openstack/scenarios/cinder/test_volumes.py index 92accb32..5784d7de 100755 --- a/tests/unit/plugins/openstack/scenarios/cinder/test_volumes.py +++ b/tests/unit/plugins/openstack/scenarios/cinder/test_volumes.py @@ -655,3 +655,21 @@ class CinderServersTestCase(test.ScenarioTestCase): 1, snapshot_id=fake_snapshot.id, fakearg="f") self.assertFalse(scenario._delete_snapshot.called) self.assertFalse(scenario._delete_volume.called) + + @ddt.data({}, + {"image": "img"}) + @ddt.unpack + def test_create_and_accept_transfer(self, image=None): + fake_volume = mock.MagicMock() + fake_transfer = mock.MagicMock() + scenario = volumes.CreateAndAcceptTransfer(self._get_context()) + scenario._create_volume = mock.MagicMock(return_value=fake_volume) + scenario._transfer_create = mock.MagicMock(return_value=fake_transfer) + scenario._transfer_accept = mock.MagicMock() + scenario.run(1, image=image, fakearg="fake") + expected = [mock.call(1, imageRef=image, fakearg="fake") + if image else mock.call(1, fakearg="fake")] + scenario._create_volume.assert_has_calls(expected) + scenario._transfer_create.assert_called_once_with(fake_volume.id) + scenario._transfer_accept.assert_called_once_with( + fake_transfer.id, fake_transfer.auth_key)