diff --git a/rally-jobs/nova.yaml b/rally-jobs/nova.yaml index 6c409aa9..9fc8fece 100755 --- a/rally-jobs/nova.yaml +++ b/rally-jobs/nova.yaml @@ -1171,6 +1171,21 @@ failure_rate: max: 0 + NovaHosts.list_and_get_hosts: + - + args: {} + runner: + type: "constant" + concurrency: 2 + times: 5 + context: + users: + tenants: 3 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 + NovaServices.list_services: - runner: diff --git a/rally/plugins/openstack/scenarios/nova/hosts.py b/rally/plugins/openstack/scenarios/nova/hosts.py index b1f377aa..3ae5d4ab 100644 --- a/rally/plugins/openstack/scenarios/nova/hosts.py +++ b/rally/plugins/openstack/scenarios/nova/hosts.py @@ -16,6 +16,7 @@ from rally import consts from rally.plugins.openstack import scenario from rally.plugins.openstack.scenarios.nova import utils +from rally.task import atomic from rally.task import validation @@ -37,3 +38,23 @@ class ListHosts(utils.NovaScenario): availability-zones """ self._list_hosts(zone) + + +@validation.required_services(consts.Service.NOVA) +@validation.required_openstack(admin=True) +@scenario.configure(name="NovaHosts.list_and_get_hosts") +class ListAndGetHosts(utils.NovaScenario): + + def run(self, zone=None): + """List all nova hosts,and get detailed information fot this hosts. + + Measure the "nova host-describe" command performance. + + :param zone: List nova hosts in an availability-zone. + None (default value) means list hosts in all + availability-zones + """ + hosts = self._list_hosts(zone) + with atomic.ActionTimer(self, "nova.get_%s_hosts" % len(hosts)): + for host in hosts: + self._get_host(host.host_name, atomic_action=False) diff --git a/rally/plugins/openstack/scenarios/nova/utils.py b/rally/plugins/openstack/scenarios/nova/utils.py index 8e18ca30..cb432050 100755 --- a/rally/plugins/openstack/scenarios/nova/utils.py +++ b/rally/plugins/openstack/scenarios/nova/utils.py @@ -1013,6 +1013,18 @@ class NovaScenario(scenario.OpenStackScenario): """ return self.admin_clients("nova").hosts.list(zone) + @atomic.optional_action_timer("nova.get_host") + def _get_host(self, host_name): + """Describe a specific host. + + :param host_name: host name to get. + :param atomic_action: True if this is atomic action. added and + handled by the optional_action_timer() + decorator. + :returns: host object + """ + return self.admin_clients("nova").hosts.get(host_name) + @atomic.action_timer("nova.list_services") def _list_services(self, host=None, binary=None): """return all nova service details diff --git a/samples/tasks/scenarios/nova/list-and-get-hosts.json b/samples/tasks/scenarios/nova/list-and-get-hosts.json new file mode 100644 index 00000000..3e0fa5b1 --- /dev/null +++ b/samples/tasks/scenarios/nova/list-and-get-hosts.json @@ -0,0 +1,23 @@ +{ + "NovaHosts.list_and_get_hosts": [ + { + "args": {}, + "runner": { + "type": "constant", + "concurrency": 2, + "times": 10 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/nova/list-and-get-hosts.yaml b/samples/tasks/scenarios/nova/list-and-get-hosts.yaml new file mode 100644 index 00000000..2ba1d8a3 --- /dev/null +++ b/samples/tasks/scenarios/nova/list-and-get-hosts.yaml @@ -0,0 +1,15 @@ +--- + NovaHosts.list_and_get_hosts: + - + args: {} + runner: + type: "constant" + concurrency: 2 + times: 10 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 diff --git a/tests/unit/plugins/openstack/scenarios/nova/test_hosts.py b/tests/unit/plugins/openstack/scenarios/nova/test_hosts.py index 5ed15ef5..7593c7be 100644 --- a/tests/unit/plugins/openstack/scenarios/nova/test_hosts.py +++ b/tests/unit/plugins/openstack/scenarios/nova/test_hosts.py @@ -26,3 +26,18 @@ class NovaHostsTestCase(test.TestCase): scenario._list_hosts = mock.Mock() scenario.run(zone=None) scenario._list_hosts.assert_called_once_with(None) + + def test_list_and_get_hosts(self): + fake_hosts = [mock.Mock(host_name="fake_hostname")] + scenario = hosts.ListAndGetHosts() + scenario._list_hosts = mock.MagicMock( + return_value=fake_hosts) + scenario._get_host = mock.MagicMock() + scenario.run(zone="nova") + + scenario._list_hosts.assert_called_once_with("nova") + scenario._get_host.assert_called_once_with( + "fake_hostname", atomic_action=False) + + self._test_atomic_action_timer(scenario.atomic_actions(), + "nova.get_1_hosts") diff --git a/tests/unit/plugins/openstack/scenarios/nova/test_utils.py b/tests/unit/plugins/openstack/scenarios/nova/test_utils.py index 1010f32f..6f39196c 100755 --- a/tests/unit/plugins/openstack/scenarios/nova/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/nova/test_utils.py @@ -889,6 +889,17 @@ class NovaScenarioTestCase(test.ScenarioTestCase): self._test_atomic_action_timer(nova_scenario.atomic_actions(), "nova.search_hypervisors") + def test__get_host(self): + nova_scenario = utils.NovaScenario() + result = nova_scenario._get_host("host_name") + self.assertEqual( + self.admin_clients("nova").hosts.get.return_value, + result) + self.admin_clients("nova").hosts.get.assert_called_once_with( + "host_name") + self._test_atomic_action_timer(nova_scenario.atomic_actions(), + "nova.get_host") + def test__list_images(self): nova_scenario = utils.NovaScenario() result = nova_scenario._list_images(detailed=False, fakearg="fakearg")