diff --git a/rally-jobs/nova.yaml b/rally-jobs/nova.yaml index d01f8018..41c76dfc 100755 --- a/rally-jobs/nova.yaml +++ b/rally-jobs/nova.yaml @@ -1258,6 +1258,24 @@ failure_rate: max: 0 + NovaFlavors.create_and_delete_flavor: + - + runner: + type: "constant" + concurrency: 2 + times: 10 + args: + ram: 500 + vcpus : 1 + disk: 1 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 + NovaFlavors.create_and_list_flavor_access: - args: diff --git a/rally/plugins/openstack/scenarios/nova/flavors.py b/rally/plugins/openstack/scenarios/nova/flavors.py index 32c40edb..1b1d0d61 100644 --- a/rally/plugins/openstack/scenarios/nova/flavors.py +++ b/rally/plugins/openstack/scenarios/nova/flavors.py @@ -106,6 +106,24 @@ class CreateAndGetFlavor(utils.NovaScenario): self._get_flavor(flavor.id) +@validation.required_services(consts.Service.NOVA) +@validation.required_openstack(admin=True) +@scenario.configure(context={"admin_cleanup": ["nova"]}, + name="NovaFlavors.create_and_delete_flavor") +class CreateAndDeleteFlavor(utils.NovaScenario): + def run(self, ram, vcpus, disk, **kwargs): + """Create flavor and delete the flavor. + + :param ram: Memory in MB for the flavor + :param vcpus: Number of VCPUs for the flavor + :param disk: Size of local disk in GB + :param kwargs: Optional additional arguments for flavor creation + + """ + flavor = self._create_flavor(ram, vcpus, disk, **kwargs) + self._delete_flavor(flavor.id) + + @validation.required_services(consts.Service.NOVA) @validation.required_openstack(admin=True) @scenario.configure(context={"admin_cleanup": ["nova"]}, diff --git a/rally/plugins/openstack/scenarios/nova/utils.py b/rally/plugins/openstack/scenarios/nova/utils.py index fce8f21d..41bb9289 100755 --- a/rally/plugins/openstack/scenarios/nova/utils.py +++ b/rally/plugins/openstack/scenarios/nova/utils.py @@ -1046,6 +1046,15 @@ class NovaScenario(scenario.OpenStackScenario): return self.admin_clients("nova").flavors.create(name, ram, vcpus, disk, **kwargs) + @atomic.action_timer("nova.delete_flavor") + def _delete_flavor(self, flavor): + """Delete a flavor + + :param flavor: The ID of the :class:`Flavor` + :returns: An instance of novaclient.base.TupleWithMeta + """ + return self.admin_clients("nova").flavors.delete(flavor) + @atomic.action_timer("nova.list_flavor_access") def _list_flavor_access(self, flavor): """List access-rules for non-public flavor. diff --git a/samples/tasks/scenarios/nova/create-and-delete-flavor.json b/samples/tasks/scenarios/nova/create-and-delete-flavor.json new file mode 100644 index 00000000..33ce7826 --- /dev/null +++ b/samples/tasks/scenarios/nova/create-and-delete-flavor.json @@ -0,0 +1,27 @@ +{ + "NovaFlavors.create_and_delete_flavor": [ + { + "runner": { + "type": "constant", + "concurrency": 2, + "times": 10 + }, + "args": { + "ram": 500, + "vcpus" : 1, + "disk": 1 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/nova/create-and-delete-flavor.yaml b/samples/tasks/scenarios/nova/create-and-delete-flavor.yaml new file mode 100644 index 00000000..35d7e7b6 --- /dev/null +++ b/samples/tasks/scenarios/nova/create-and-delete-flavor.yaml @@ -0,0 +1,18 @@ +--- + NovaFlavors.create_and_delete_flavor: + - + runner: + type: "constant" + concurrency: 2 + times: 10 + args: + ram: 500 + vcpus : 1 + disk: 1 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 diff --git a/tests/unit/plugins/openstack/scenarios/nova/test_flavors.py b/tests/unit/plugins/openstack/scenarios/nova/test_flavors.py index 219affe1..96ebbd86 100644 --- a/tests/unit/plugins/openstack/scenarios/nova/test_flavors.py +++ b/tests/unit/plugins/openstack/scenarios/nova/test_flavors.py @@ -64,6 +64,16 @@ class NovaFlavorsTestCase(test.TestCase): scenario._get_flavor.assert_called_once_with( scenario._create_flavor.return_value.id) + def test_create_and_delete_flavor(self, **kwargs): + scenario = flavors.CreateAndDeleteFlavor() + scenario._create_flavor = mock.Mock() + scenario._delete_flavor = mock.Mock() + scenario.run(ram=100, vcpus=1, disk=1, **kwargs) + + scenario._create_flavor.assert_called_once_with(100, 1, 1, **kwargs) + scenario._delete_flavor.assert_called_once_with( + scenario._create_flavor.return_value.id) + def test_create_flavor_and_set_keys(self): scenario = flavors.CreateFlavorAndSetKeys() scenario._create_flavor = mock.MagicMock() diff --git a/tests/unit/plugins/openstack/scenarios/nova/test_utils.py b/tests/unit/plugins/openstack/scenarios/nova/test_utils.py index 6f39196c..be99b4b8 100755 --- a/tests/unit/plugins/openstack/scenarios/nova/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/nova/test_utils.py @@ -1078,6 +1078,17 @@ class NovaScenarioTestCase(test.ScenarioTestCase): self._test_atomic_action_timer(nova_scenario.atomic_actions(), "nova.get_flavor") + def test__delete_flavor(self): + nova_scenario = utils.NovaScenario() + result = nova_scenario._delete_flavor("foo_flavor_id") + self.assertEqual( + self.admin_clients("nova").flavors.delete.return_value, + result) + self.admin_clients("nova").flavors.delete.assert_called_once_with( + "foo_flavor_id") + self._test_atomic_action_timer(nova_scenario.atomic_actions(), + "nova.delete_flavor") + def test__update_server(self): server = mock.Mock() nova_scenario = utils.NovaScenario()