Add create-flavor and flavor-access-list scenario

Benchmark create-flavor and flavor-access-list
Nova API.

blueprint extend-api-benchmark-in-nova-scenarios

Change-Id: I870405aaaec727cfb3a0b460dcf60c6a7ca4b6d1
This commit is contained in:
Piyush Raman Srivastava 2016-04-01 14:57:50 +05:30 committed by Piyush
parent d46955cae3
commit 297fff010a
11 changed files with 218 additions and 0 deletions

View File

@ -984,3 +984,31 @@
sla: sla:
failure_rate: failure_rate:
max: 0 max: 0
NovaFlavors.create_flavor:
-
args:
ram: 500
vcpus: 1
disk: 1
runner:
type: "constant"
times: 5
concurrency: 2
sla:
failure_rate:
max: 0
NovaFlavors.create_and_list_flavor_access:
-
args:
ram: 500
vcpus: 1
disk: 1
runner:
type: "constant"
times: 5
concurrency: 2
sla:
failure_rate:
max: 0

View File

@ -137,6 +137,14 @@ class NovaQuotas(QuotaMixin, base.ResourceManager):
pass pass
@base.resource("nova", "flavors", order=next(_nova_order),
admin_required=True, perform_for_admin_only=True)
class NovaFlavors(base.ResourceManager):
def list(self):
return [r for r in self._manager().list()
if utils.name_matches_object(r.name, nova_utils.NovaScenario)]
@base.resource("nova", "floating_ips_bulk", order=next(_nova_order), @base.resource("nova", "floating_ips_bulk", order=next(_nova_order),
admin_required=True) admin_required=True)
class NovaFloatingIpsBulk(SynchronizedDeletion, base.ResourceManager): class NovaFloatingIpsBulk(SynchronizedDeletion, base.ResourceManager):

View File

@ -13,11 +13,14 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from rally.common import logging
from rally import consts from rally import consts
from rally.plugins.openstack import scenario from rally.plugins.openstack import scenario
from rally.plugins.openstack.scenarios.nova import utils from rally.plugins.openstack.scenarios.nova import utils
from rally.task import validation from rally.task import validation
LOG = logging.getLogger(__name__)
class NovaFlavors(utils.NovaScenario): class NovaFlavors(utils.NovaScenario):
"""Benchmark scenarios for Nova flavors.""" """Benchmark scenarios for Nova flavors."""
@ -36,3 +39,36 @@ class NovaFlavors(utils.NovaScenario):
:param kwargs: Optional additional arguments for flavor listing :param kwargs: Optional additional arguments for flavor listing
""" """
self._list_flavors(detailed, **kwargs) self._list_flavors(detailed, **kwargs)
@validation.required_services(consts.Service.NOVA)
@validation.required_openstack(admin=True)
@scenario.configure(context={"admin_cleanup": ["nova"]})
def create_and_list_flavor_access(self, ram, vcpus, disk, **kwargs):
"""Create a non-public flavor and list its access rules
: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
"""
# NOTE(pirsriva): access rules can be listed
# only for non-public flavors
if kwargs.get("is_public", False):
LOG.warn("is_public cannot be set to True for listing flavor "
"access rules. Setting is_public to False")
kwargs["is_public"] = False
flavor = self._create_flavor(ram, vcpus, disk, **kwargs)
self._list_flavor_access(flavor.id)
@validation.required_services(consts.Service.NOVA)
@validation.required_openstack(admin=True)
@scenario.configure(context={"admin_cleanup": ["nova"]})
def create_flavor(self, ram, vcpus, disk, **kwargs):
"""Create a 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
"""
self._create_flavor(ram, vcpus, disk, **kwargs)

View File

@ -948,3 +948,24 @@ class NovaScenario(scenario.OpenStackScenario):
:param binary: List all nova services matching given binary :param binary: List all nova services matching given binary
""" """
return self.admin_clients("nova").services.list(host, binary) return self.admin_clients("nova").services.list(host, binary)
@atomic.action_timer("nova.create_flavor")
def _create_flavor(self, ram, vcpus, disk, **kwargs):
"""Create a 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
"""
name = self.generate_random_name()
return self.admin_clients("nova").flavors.create(name, ram, vcpus,
disk, **kwargs)
@atomic.action_timer("nova.list_flavor_access")
def _list_flavor_access(self, flavor):
"""List access-rules for non-public flavor.
:param flavor: List access rules for flavor instance or flavor ID
"""
return self.admin_clients("nova").flavor_access.list(flavor=flavor)

View File

@ -0,0 +1,16 @@
{
"NovaFlavors.create_and_list_flavor_access": [
{
"runner": {
"type": "constant",
"concurrency": 2,
"times": 10
},
"args": {
"ram": 500,
"vcpus" : 1,
"disk": 1
}
}
]
}

View File

@ -0,0 +1,11 @@
---
NovaFlavors.create_and_list_flavor_access:
-
args:
ram: 500
vcpus: 1
disk: 1
runner:
type: "constant"
times: 10
concurrency: 2

View File

@ -0,0 +1,16 @@
{
"NovaFlavors.create_flavor": [
{
"runner": {
"type": "constant",
"concurrency": 2,
"times": 10
},
"args": {
"ram": 500,
"vcpus" : 1,
"disk": 1
}
}
]
}

View File

@ -0,0 +1,11 @@
---
NovaFlavors.create_flavor:
-
args:
ram: 500
vcpus: 1
disk: 1
runner:
type: "constant"
times: 10
concurrency: 2

View File

@ -21,6 +21,7 @@ from neutronclient.common import exceptions as neutron_exceptions
from rally.common import utils from rally.common import utils
from rally.plugins.openstack.cleanup import resources from rally.plugins.openstack.cleanup import resources
from rally.plugins.openstack.scenarios.keystone import utils as kutils from rally.plugins.openstack.scenarios.keystone import utils as kutils
from rally.plugins.openstack.scenarios.nova import utils as nutils
from tests.unit import test from tests.unit import test
BASE = "rally.plugins.openstack.cleanup.resources" BASE = "rally.plugins.openstack.cleanup.resources"
@ -116,6 +117,22 @@ class NovaFloatingIPsTestCase(test.TestCase):
self.assertIsNone(fips.name()) self.assertIsNone(fips.name())
class NovaFlavorsTestCase(test.TestCase):
@mock.patch("%s.base.ResourceManager._manager" % BASE)
@mock.patch("rally.common.utils.name_matches_object")
def test_list(self, mock_name_matches_object,
mock_resource_manager__manager):
flavors = [mock.MagicMock(name="rally_foo1"),
mock.MagicMock(name="rally_foo2"),
mock.MagicMock(name="foo3")]
mock_name_matches_object.side_effect = [False, True, True]
mock_resource_manager__manager().list.return_value = flavors
self.assertEqual(flavors[1:], resources.NovaFlavors().list())
mock_name_matches_object.assert_has_calls(
[mock.call(r.name, nutils.NovaScenario) for r in flavors])
class NovaSecurityGroupTestCase(test.TestCase): class NovaSecurityGroupTestCase(test.TestCase):
@mock.patch("%s.base.ResourceManager._manager" % BASE) @mock.patch("%s.base.ResourceManager._manager" % BASE)

View File

@ -13,12 +13,14 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import ddt
import mock import mock
from rally.plugins.openstack.scenarios.nova import flavors from rally.plugins.openstack.scenarios.nova import flavors
from tests.unit import test from tests.unit import test
@ddt.ddt
class NovaFlavorsTestCase(test.TestCase): class NovaFlavorsTestCase(test.TestCase):
def test_list_flavors(self): def test_list_flavors(self):
@ -26,3 +28,29 @@ class NovaFlavorsTestCase(test.TestCase):
scenario._list_flavors = mock.Mock() scenario._list_flavors = mock.Mock()
scenario.list_flavors(detailed=True, fakearg="fakearg") scenario.list_flavors(detailed=True, fakearg="fakearg")
scenario._list_flavors.assert_called_once_with(True, fakearg="fakearg") scenario._list_flavors.assert_called_once_with(True, fakearg="fakearg")
@ddt.data({},
{"is_public": True},
{"is_public": False},
{"fakeargs": "fakeargs"},
{"is_public": False, "fakeargs": "fakeargs"})
@ddt.unpack
def test_create_and_list_flavor_access(self, **kwargs):
scenario = flavors.NovaFlavors()
scenario._create_flavor = mock.Mock()
scenario._list_flavor_access = mock.Mock()
scenario.create_and_list_flavor_access(ram=100, vcpus=1, disk=1,
**kwargs)
kwargs.pop("is_public", None)
scenario._create_flavor.assert_called_once_with(100, 1, 1,
is_public=False,
**kwargs)
scenario._list_flavor_access.assert_called_once_with(
scenario._create_flavor.return_value.id)
def test_create_flavor(self):
scenario = flavors.NovaFlavors()
scenario._create_flavor = mock.MagicMock()
scenario.create_flavor(ram=100, vcpus=1, disk=1, fakeargs="fakeargs")
scenario._create_flavor.assert_called_once_with(100, 1, 1,
fakeargs="fakeargs")

View File

@ -943,3 +943,29 @@ class NovaScenarioTestCase(test.ScenarioTestCase):
host, binary) host, binary)
self._test_atomic_action_timer(nova_scenario.atomic_actions(), self._test_atomic_action_timer(nova_scenario.atomic_actions(),
"nova.list_services") "nova.list_services")
def test__list_flavor_access(self):
nova_scenario = utils.NovaScenario()
result = nova_scenario._list_flavor_access("foo_id")
self.assertEqual(
self.admin_clients("nova").flavor_access.list.return_value,
result)
self.admin_clients("nova").flavor_access.list.assert_called_once_with(
flavor="foo_id")
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
"nova.list_flavor_access")
def test__create_flavor(self):
nova_scenario = utils.NovaScenario()
random_name = "random_name"
nova_scenario.generate_random_name = mock.Mock(
return_value=random_name)
result = nova_scenario._create_flavor(500, 1, 1,
fakearg="fakearg")
self.assertEqual(
self.admin_clients("nova").flavors.create.return_value,
result)
self.admin_clients("nova").flavors.create.assert_called_once_with(
random_name, 500, 1, 1, fakearg="fakearg")
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
"nova.create_flavor")