From 8d651e9c25ba7d6ca97f97d27dca40264bb7efd3 Mon Sep 17 00:00:00 2001 From: Pradeep K Surisetty Date: Tue, 21 Apr 2015 13:02:59 +0530 Subject: [PATCH] Add Nova shelve and unshelve scenario This scenario covers "shelve" and "unshelve" commands Change-Id: I326f97cba1363956820fac75c75d191b9ba91d14 --- etc/rally/rally.conf.sample | 20 ++++++++++ rally-jobs/rally.yaml | 19 ++++++++++ rally/benchmark/scenarios/nova/servers.py | 20 ++++++++++ rally/benchmark/scenarios/nova/utils.py | 37 +++++++++++++++++++ .../scenarios/nova/shelve-and-unshelve.json | 26 +++++++++++++ .../scenarios/nova/shelve-and-unshelve.yaml | 17 +++++++++ .../benchmark/scenarios/nova/test_servers.py | 18 +++++++++ .../benchmark/scenarios/nova/test_utils.py | 24 ++++++++++++ 8 files changed, 181 insertions(+) create mode 100644 samples/tasks/scenarios/nova/shelve-and-unshelve.json create mode 100644 samples/tasks/scenarios/nova/shelve-and-unshelve.yaml diff --git a/etc/rally/rally.conf.sample b/etc/rally/rally.conf.sample index bd2df9666c..5f9e515064 100644 --- a/etc/rally/rally.conf.sample +++ b/etc/rally/rally.conf.sample @@ -320,6 +320,26 @@ # Server unpause poll interval (floating point value) #nova_server_unpause_poll_interval = 2.0 +# Time to sleep after shelve before polling for status (floating +# point value) +#nova_server_shelve_prepoll_delay = 2.0 + +# Server shelve timeout (floating point value) +#nova_server_shelve_timeout = 300.0 + +# Server shelve poll interval (floating point value) +#nova_server_shelve_poll_interval = 2.0 + +# Time to sleep after unshelve before polling for status (floating +# point value) +#nova_server_unshelve_prepoll_delay = 2.0 + +# Server unshelve timeout (floating point value) +#nova_server_unshelve_timeout = 300.0 + +# Server unshelve poll interval (floating point value) +#nova_server_unshelve_poll_interval = 2.0 + # Time to sleep after image_create before polling for status (floating # point value) #nova_server_image_create_prepoll_delay = 0.0 diff --git a/rally-jobs/rally.yaml b/rally-jobs/rally.yaml index a4b66cb592..48c7b485ae 100755 --- a/rally-jobs/rally.yaml +++ b/rally-jobs/rally.yaml @@ -1099,6 +1099,25 @@ failure_rate: max: 0 + NovaServers.shelve_and_unshelve_server: + - + args: + flavor: + name: "m1.tiny" + image: + name: {{image_name}} + runner: + type: "constant" + times: 3 + concurrency: 3 + context: + users: + tenants: 3 + users_per_tenant: 1 + sla: + failure_rate: + max: 0 + NovaServers.boot_and_rebuild_server: - args: diff --git a/rally/benchmark/scenarios/nova/servers.py b/rally/benchmark/scenarios/nova/servers.py index c1feeeaac4..75367344cd 100644 --- a/rally/benchmark/scenarios/nova/servers.py +++ b/rally/benchmark/scenarios/nova/servers.py @@ -351,6 +351,26 @@ class NovaServers(utils.NovaScenario, self._unpause_server(server) self._delete_server(server, force=force_delete) + @types.set(image=types.ImageResourceType, + flavor=types.FlavorResourceType) + @validation.image_valid_on_flavor("flavor", "image") + @validation.required_services(consts.Service.NOVA) + @validation.required_openstack(users=True) + @base.scenario(context={"cleanup": ["nova"]}) + def shelve_and_unshelve_server(self, image, flavor, + force_delete=False, **kwargs): + """Create a server, shelve, unshelve and then delete it + + :param image: image to be used to boot an instance + :param flavor: flavor to be used to boot an instance + :param force_delete: True if force_delete should be used + :param kwargs: Optional additional arguments for server creation + """ + server = self._boot_server(image, flavor, **kwargs) + self._shelve_server(server) + self._unshelve_server(server) + self._delete_server(server, force=force_delete) + @types.set(image=types.ImageResourceType, flavor=types.FlavorResourceType) @validation.image_valid_on_flavor("flavor", "image") diff --git a/rally/benchmark/scenarios/nova/utils.py b/rally/benchmark/scenarios/nova/utils.py index 2fb414f2ff..e9d3a4bf6c 100644 --- a/rally/benchmark/scenarios/nova/utils.py +++ b/rally/benchmark/scenarios/nova/utils.py @@ -39,6 +39,8 @@ option_names_and_defaults = [ ("resume", 2, 300, 2), ("pause", 2, 300, 2), ("unpause", 2, 300, 2), + ("shelve", 2, 300, 2), + ("unshelve", 2, 300, 2), ("image_create", 0, 300, 2), ("image_delete", 0, 300, 2), ("resize", 2, 400, 5), @@ -323,6 +325,41 @@ class NovaScenario(base.Scenario): check_interval=CONF.benchmark.nova_server_unpause_poll_interval ) + @base.atomic_action_timer("nova.shelve_server") + def _shelve_server(self, server): + """Shelve the given server. + + Returns when the server is actually shelved and is in the + "SHELVED_OFFLOADED" state. + + :param server: Server object + """ + server.shelve() + time.sleep(CONF.benchmark.nova_server_shelve_prepoll_delay) + bench_utils.wait_for( + server, is_ready=bench_utils.resource_is("SHELVED_OFFLOADED"), + update_resource=bench_utils.get_from_manager(), + timeout=CONF.benchmark.nova_server_shelve_timeout, + check_interval=CONF.benchmark.nova_server_shelve_poll_interval + ) + + @base.atomic_action_timer("nova.unshelve_server") + def _unshelve_server(self, server): + """Unshelve the given server. + + Returns when the server is unshelved and is in the "ACTIVE" state. + + :param server: Server object + """ + server.unshelve() + time.sleep(CONF.benchmark.nova_server_unshelve_prepoll_delay) + bench_utils.wait_for( + server, is_ready=bench_utils.resource_is("ACTIVE"), + update_resource=bench_utils.get_from_manager(), + timeout=CONF.benchmark.nova_server_unshelve_timeout, + check_interval=CONF.benchmark.nova_server_unshelve_poll_interval + ) + def _delete_server(self, server, force=False): """Delete the given server. diff --git a/samples/tasks/scenarios/nova/shelve-and-unshelve.json b/samples/tasks/scenarios/nova/shelve-and-unshelve.json new file mode 100644 index 0000000000..ffa5c2ca70 --- /dev/null +++ b/samples/tasks/scenarios/nova/shelve-and-unshelve.json @@ -0,0 +1,26 @@ +{ + "NovaServers.shelve_and_unshelve_server": [ + { + "args": { + "flavor": { + "name": "m1.nano" + }, + "image": { + "name": "^cirros.*uec$" + }, + "force_delete": false + }, + "runner": { + "type": "constant", + "times": 10, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 3, + "users_per_tenant": 2 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/nova/shelve-and-unshelve.yaml b/samples/tasks/scenarios/nova/shelve-and-unshelve.yaml new file mode 100644 index 0000000000..7bbb3b0b0c --- /dev/null +++ b/samples/tasks/scenarios/nova/shelve-and-unshelve.yaml @@ -0,0 +1,17 @@ +--- + NovaServers.shelve_and_unshelve_server: + - + args: + flavor: + name: "m1.nano" + image: + name: "^cirros.*uec$" + force_delete: false + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 3 + users_per_tenant: 2 diff --git a/tests/unit/benchmark/scenarios/nova/test_servers.py b/tests/unit/benchmark/scenarios/nova/test_servers.py index 90257fbe1a..bec2aaefdb 100644 --- a/tests/unit/benchmark/scenarios/nova/test_servers.py +++ b/tests/unit/benchmark/scenarios/nova/test_servers.py @@ -233,6 +233,24 @@ class NovaServersTestCase(test.TestCase): scenario._delete_server.assert_called_once_with(fake_server, force=False) + def test_shelve_and_unshelve_server(self): + fake_server = mock.MagicMock() + scenario = servers.NovaServers() + scenario._boot_server = mock.MagicMock(return_value=fake_server) + scenario._shelve_server = mock.MagicMock() + scenario._unshelve_server = mock.MagicMock() + scenario._delete_server = mock.MagicMock() + + scenario.shelve_and_unshelve_server("img", 0, fakearg="fakearg") + + scenario._boot_server.assert_called_once_with("img", 0, + fakearg="fakearg") + + scenario._shelve_server.assert_called_once_with(fake_server) + scenario._unshelve_server.assert_called_once_with(fake_server) + scenario._delete_server.assert_called_once_with(fake_server, + force=False) + def test_list_servers(self): scenario = servers.NovaServers() scenario._list_servers = mock.MagicMock() diff --git a/tests/unit/benchmark/scenarios/nova/test_utils.py b/tests/unit/benchmark/scenarios/nova/test_utils.py index 5c5335abb9..701b6af723 100644 --- a/tests/unit/benchmark/scenarios/nova/test_utils.py +++ b/tests/unit/benchmark/scenarios/nova/test_utils.py @@ -271,6 +271,30 @@ class NovaScenarioTestCase(test.TestCase): self._test_atomic_action_timer(nova_scenario.atomic_actions(), "nova.unpause_server") + def test__shelve_server(self): + nova_scenario = utils.NovaScenario() + nova_scenario._shelve_server(self.server) + self.server.shelve.assert_called_once_with() + self._test_assert_called_once_with( + self.wait_for.mock, self.server, + CONF.benchmark.nova_server_shelve_poll_interval, + CONF.benchmark.nova_server_shelve_timeout) + self.res_is.mock.assert_has_calls([mock.call("SHELVED_OFFLOADED")]) + self._test_atomic_action_timer(nova_scenario.atomic_actions(), + "nova.shelve_server") + + def test__unshelve_server(self): + nova_scenario = utils.NovaScenario() + nova_scenario._unshelve_server(self.server) + self.server.unshelve.assert_called_once_with() + self._test_assert_called_once_with( + self.wait_for.mock, self.server, + CONF.benchmark.nova_server_unshelve_poll_interval, + CONF.benchmark.nova_server_unshelve_timeout) + self.res_is.mock.assert_has_calls([mock.call("ACTIVE")]) + self._test_atomic_action_timer(nova_scenario.atomic_actions(), + "nova.unshelve_server") + @mock.patch(NOVA_UTILS + ".NovaScenario.clients") def test__create_image(self, mock_clients): mock_clients("nova").images.get.return_value = self.image