diff --git a/doc/samples/tasks/cinder/create-and-delete-volume.json b/doc/samples/tasks/cinder/create-and-delete-volume.json new file mode 100644 index 0000000000..5c02b264a6 --- /dev/null +++ b/doc/samples/tasks/cinder/create-and-delete-volume.json @@ -0,0 +1,10 @@ +{ + "CinderVolumes.create_and_delete_volume": [ + { + "args": {"size": 1}, + "execution": "continuous", + "config": {"times": 3, "active_users": 2, + "tenants": 2, "users_per_tenant": 2} + } + ] +} \ No newline at end of file diff --git a/rally/benchmark/scenarios/cinder/__init__.py b/rally/benchmark/scenarios/cinder/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/rally/benchmark/scenarios/cinder/utils.py b/rally/benchmark/scenarios/cinder/utils.py new file mode 100644 index 0000000000..d9a0813876 --- /dev/null +++ b/rally/benchmark/scenarios/cinder/utils.py @@ -0,0 +1,75 @@ +# Copyright 2013 Huawei Technologies Co.,LTD. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import random +import string +import time + +from rally.benchmark import base +from rally.benchmark import utils as bench_utils +from rally import utils + +# TODO(boris-42): Bind name to the uuid of benchmark. +TEMP_TEMPLATE = "rally_c_" + + +def is_temporary(resource): + return resource.name.startswith(TEMP_TEMPLATE) + + +def generate_volume_name(length=10): + """Generate random name for volume.""" + rand_part = ''.join(random.choice(string.lowercase) for i in range(length)) + return TEMP_TEMPLATE + rand_part + + +class CinderScenario(base.Scenario): + + @classmethod + def _create_volume(cls, size, **kwargs): + """create one volume. + + Returns when the volume is actually created and is in the "Available" + state. + + :param size: int be size of volume in GB + :param **kwargs: Other optional parameters to initialize the volume + + :returns: Created volume object + """ + volumename = kwargs.get('display_name', generate_volume_name(10)) + kwargs['display_name'] = volumename + volume = cls.clients("cinder").volumes.create(size, **kwargs) + # NOTE(msdubov): It is reasonable to wait 5 secs before starting to + # check whether the volume is ready => less API calls. + time.sleep(3) + volume = utils.wait_for(volume, + is_ready=bench_utils.resource_is("available"), + update_resource=bench_utils.get_from_manager(), + timeout=600, check_interval=3) + return volume + + @classmethod + def _delete_volume(cls, volume): + """Delete the given volume. + + Returns when the volume is actually deleted. + + :param volume: volume object + """ + volume.delete() + utils.wait_for(volume, is_ready=bench_utils.is_none, + update_resource=bench_utils.get_from_manager(), + timeout=600, check_interval=2) diff --git a/rally/benchmark/scenarios/cinder/volumes.py b/rally/benchmark/scenarios/cinder/volumes.py new file mode 100644 index 0000000000..dc717058cd --- /dev/null +++ b/rally/benchmark/scenarios/cinder/volumes.py @@ -0,0 +1,32 @@ +# Copyright 2013 Huawei Technologies Co.,LTD. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from rally.benchmark.scenarios.cinder import utils + + +class CinderVolumes(utils.CinderScenario): + + @classmethod + def create_and_delete_volume(cls, size, + min_sleep=0, max_sleep=0, **kwargs): + """Tests creating and then deleting a volume.""" + + volume = cls._create_volume(size, **kwargs) + cls.sleep_between(min_sleep, max_sleep) + cls._delete_volume(volume) + + @classmethod + def create_volume(cls, size, **kwargs): + cls._create_volume(size, **kwargs) diff --git a/tests/benchmark/scenarios/cinder/__init__.py b/tests/benchmark/scenarios/cinder/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/benchmark/scenarios/cinder/test_volumes.py b/tests/benchmark/scenarios/cinder/test_volumes.py new file mode 100644 index 0000000000..676c5f4137 --- /dev/null +++ b/tests/benchmark/scenarios/cinder/test_volumes.py @@ -0,0 +1,42 @@ +# Copyright 2013 Huawei Technologies Co.,LTD. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import mock + +from rally.benchmark.scenarios.cinder import volumes +from rally import test + + +CINDER_VOLUMES = "rally.benchmark.scenarios.cinder.volumes.CinderVolumes" + + +class CinderServersTestCase(test.TestCase): + + @mock.patch(CINDER_VOLUMES + ".sleep_between") + @mock.patch(CINDER_VOLUMES + "._delete_volume") + @mock.patch(CINDER_VOLUMES + "._create_volume") + def _verify_create_and_delete_volume(self, mock_create, mock_delete, + mock_sleep): + fake_volume = object() + mock_create.return_value = fake_volume + volumes.CinderVolumes.create_and_delete_volume(1, 10, 20, + fakearg="f") + + mock_create.assert_called_once_with(1, fakearg="f") + mock_sleep.assert_called_once_with(10, 20) + mock_delete.assert_called_once_with(fake_volume) + + def test_create_and_delete_volume(self): + self._verify_create_and_delete_volume()