[Ceilometer] Add context and scenario for resources
- Added context ceilometer.py for creating samples and collecting resources in list - Added CeilometerResource.get_resources_on_tenant scenario Change-Id: I4cf6148cdd3fa685a2ae17eb16f1e205e1edb2bf
This commit is contained in:
parent
5c6735c073
commit
d663c1ed96
@ -296,6 +296,26 @@
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
CeilometerResource.get_tenant_resources:
|
||||
-
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 10
|
||||
concurrency: 5
|
||||
context:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
||||
ceilometer:
|
||||
counter_name: "cpu_util"
|
||||
counter_type: "gauge"
|
||||
counter_volume: 1.0
|
||||
counter_unit: "instance"
|
||||
resources_per_tenant: 3
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
CeilometerSamples.list_samples:
|
||||
-
|
||||
runner:
|
||||
@ -306,6 +326,13 @@
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
ceilometer:
|
||||
counter_name: "cpu_util"
|
||||
counter_type: "gauge"
|
||||
counter_unit: "instance"
|
||||
counter_volume: 1.0
|
||||
resources_per_tenant: 3
|
||||
samples_per_resource: 3
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
100
rally/benchmark/context/ceilometer.py
Normal file
100
rally/benchmark/context/ceilometer.py
Normal file
@ -0,0 +1,100 @@
|
||||
# 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.context import base
|
||||
from rally.benchmark.scenarios.ceilometer import utils as ceilometer_utils
|
||||
from rally.common.i18n import _
|
||||
from rally.common import log as logging
|
||||
from rally.common import utils as rutils
|
||||
from rally import consts
|
||||
from rally import osclients
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@base.context(name="ceilometer", order=450)
|
||||
class CeilometerSampleGenerator(base.Context):
|
||||
"""Context for creating samples and collecting resources for benchmarks."""
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
"type": "object",
|
||||
"$schema": consts.JSON_SCHEMA,
|
||||
"properties": {
|
||||
"counter_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"counter_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"counter_unit": {
|
||||
"type": "string"
|
||||
},
|
||||
"counter_volume": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"resources_per_tenant": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"samples_per_resource": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
},
|
||||
"required": ["counter_name", "counter_type", "counter_unit",
|
||||
"counter_volume"],
|
||||
"additionalProperties": False
|
||||
}
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
"resources_per_tenant": 5,
|
||||
"samples_per_resource": 5
|
||||
}
|
||||
|
||||
@rutils.log_task_wrapper(LOG.info, _("Enter context: `Ceilometer`"))
|
||||
def setup(self):
|
||||
counter_name = self.config["counter_name"]
|
||||
counter_type = self.config["counter_type"]
|
||||
counter_unit = self.config["counter_unit"]
|
||||
counter_volume = self.config["counter_volume"]
|
||||
resources_per_tenant = self.config["resources_per_tenant"]
|
||||
samples_per_resource = self.config["samples_per_resource"]
|
||||
for user, tenant_id in rutils.iterate_per_tenants(
|
||||
self.context["users"]):
|
||||
self.context["tenants"][tenant_id]["samples"] = []
|
||||
self.context["tenants"][tenant_id]["resources"] = []
|
||||
clients = osclients.Clients(user["endpoint"])
|
||||
scenario = ceilometer_utils.CeilometerScenario(
|
||||
clients=clients)
|
||||
for i in range(resources_per_tenant):
|
||||
for j in range(samples_per_resource):
|
||||
try:
|
||||
sample = scenario._create_sample(counter_name,
|
||||
counter_type,
|
||||
counter_unit,
|
||||
counter_volume)
|
||||
self.context["tenants"][tenant_id]["samples"].append(
|
||||
sample[0].to_dict())
|
||||
except Exception as e:
|
||||
LOG.error("Creating a sample failed: %(error)s"
|
||||
% {"error": e})
|
||||
self.context["tenants"][tenant_id]["resources"].append(
|
||||
sample[0].resource_id)
|
||||
|
||||
@rutils.log_task_wrapper(LOG.info, _("Exit context: `Ceilometer`"))
|
||||
def cleanup(self):
|
||||
# We don't have API for removal of samples and resources
|
||||
pass
|
@ -16,6 +16,7 @@ from rally.benchmark.scenarios import base
|
||||
from rally.benchmark.scenarios.ceilometer import utils as ceilometerutils
|
||||
from rally.benchmark import validation
|
||||
from rally import consts
|
||||
from rally import exceptions
|
||||
|
||||
|
||||
class CeilometerResource(ceilometerutils.CeilometerScenario):
|
||||
@ -29,4 +30,21 @@ class CeilometerResource(ceilometerutils.CeilometerScenario):
|
||||
|
||||
This scenario fetches list of all resources using GET /v2/resources.
|
||||
"""
|
||||
self._list_resources()
|
||||
self._list_resources()
|
||||
|
||||
@validation.required_services(consts.Service.CEILOMETER)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario()
|
||||
def get_tenant_resources(self):
|
||||
"""Get all tenant resources.
|
||||
|
||||
This scenario retrieves information about tenant resources using
|
||||
GET /v2/resources/(resource_id)
|
||||
"""
|
||||
resources = self.context["tenant"].get("resources", [])
|
||||
if not resources:
|
||||
msg = ("No resources found for tenant: %s"
|
||||
% self.context["tenant"].get("name"))
|
||||
raise exceptions.NotFoundException(message=msg)
|
||||
for res_id in resources:
|
||||
self._get_resource(res_id)
|
@ -138,6 +138,11 @@ class CeilometerScenario(base.Scenario):
|
||||
"""
|
||||
return self.clients("ceilometer").samples.list()
|
||||
|
||||
@base.atomic_action_timer("ceilometer.get_resource")
|
||||
def _get_resource(self, resource_id):
|
||||
"""Retrieve details about one resource."""
|
||||
return self.clients("ceilometer").resources.get(resource_id)
|
||||
|
||||
@base.atomic_action_timer("ceilometer.get_stats")
|
||||
def _get_stats(self, meter_name):
|
||||
"""Get stats for a specific meter.
|
||||
@ -191,7 +196,7 @@ class CeilometerScenario(base.Scenario):
|
||||
|
||||
@base.atomic_action_timer("ceilometer.create_sample")
|
||||
def _create_sample(self, counter_name, counter_type, counter_unit,
|
||||
counter_volume, resource_id, **kwargs):
|
||||
counter_volume, resource_id=None, **kwargs):
|
||||
"""Create a Sample with specified parameters.
|
||||
|
||||
:param counter_name: specifies name of the counter
|
||||
@ -206,7 +211,9 @@ class CeilometerScenario(base.Scenario):
|
||||
"counter_type": counter_type,
|
||||
"counter_unit": counter_unit,
|
||||
"counter_volume": counter_volume,
|
||||
"resource_id": resource_id})
|
||||
"resource_id": resource_id if resource_id
|
||||
else self._generate_random_name(
|
||||
prefix="rally_ctx_resource_")})
|
||||
return self.clients("ceilometer").samples.create(**kwargs)
|
||||
|
||||
@base.atomic_action_timer("ceilometer.query_samples")
|
||||
|
23
samples/tasks/scenarios/ceilometer/get-tenant-resources.json
Normal file
23
samples/tasks/scenarios/ceilometer/get-tenant-resources.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"CeilometerResource.get_tenant_resources": [
|
||||
{
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 10,
|
||||
"concurrency": 5
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 2,
|
||||
"users_per_tenant": 2
|
||||
},
|
||||
"ceilometer": {
|
||||
"counter_name": "cpu_util",
|
||||
"counter_type": "gauge",
|
||||
"counter_unit": "instance",
|
||||
"counter_volume": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
16
samples/tasks/scenarios/ceilometer/get-tenant-resources.yaml
Normal file
16
samples/tasks/scenarios/ceilometer/get-tenant-resources.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
CeilometerResource.get_tenant_resources:
|
||||
-
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 10
|
||||
concurrency: 5
|
||||
context:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
||||
ceilometer:
|
||||
counter_name: "cpu_util"
|
||||
counter_type: "gauge"
|
||||
counter_volume: 1.0
|
||||
counter_unit: "instance"
|
@ -10,6 +10,14 @@
|
||||
"users": {
|
||||
"tenants": 2,
|
||||
"users_per_tenant": 2
|
||||
},
|
||||
"ceilometer": {
|
||||
"counter_name": "cpu_util",
|
||||
"counter_type": "gauge",
|
||||
"counter_unit": "instance",
|
||||
"counter_volume": 1.0,
|
||||
"resources_per_tenant": 3,
|
||||
"samples_per_resource": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,3 +9,10 @@
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
||||
ceilometer:
|
||||
counter_name: "cpu_util"
|
||||
counter_type: "gauge"
|
||||
counter_unit: "instance"
|
||||
counter_volume: 1.0
|
||||
resources_per_tenant: 3
|
||||
samples_per_resource: 3
|
||||
|
123
tests/unit/benchmark/context/test_ceilometer.py
Normal file
123
tests/unit/benchmark/context/test_ceilometer.py
Normal file
@ -0,0 +1,123 @@
|
||||
# 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 copy
|
||||
|
||||
import mock
|
||||
|
||||
from rally.benchmark.context import ceilometer
|
||||
from tests.unit import fakes
|
||||
from tests.unit import test
|
||||
|
||||
CTX = "rally.benchmark.context"
|
||||
SCN = "rally.benchmark.scenarios"
|
||||
|
||||
|
||||
class CeilometerSampleGeneratorTestCase(test.TestCase):
|
||||
|
||||
def _gen_tenants(self, count):
|
||||
tenants = {}
|
||||
for id in range(count):
|
||||
tenants[str(id)] = dict(name=str(id))
|
||||
return tenants
|
||||
|
||||
def _gen_context(self, tenants_count, users_per_tenant,
|
||||
resources_per_tenant, samples_per_resource):
|
||||
tenants = self._gen_tenants(tenants_count)
|
||||
users = []
|
||||
for id_ in tenants.keys():
|
||||
for i in range(users_per_tenant):
|
||||
users.append({"id": i, "tenant_id": id_,
|
||||
"endpoint": "endpoint"})
|
||||
context = {
|
||||
"config": {
|
||||
"users": {
|
||||
"tenants": tenants_count,
|
||||
"users_per_tenant": users_per_tenant,
|
||||
"concurrent": 10,
|
||||
},
|
||||
"ceilometer": {
|
||||
"counter_name": "fake-counter-name",
|
||||
"counter_type": "fake-counter-type",
|
||||
"counter_unit": "fake-counter-unit",
|
||||
"counter_volume": 100,
|
||||
"resources_per_tenant": resources_per_tenant,
|
||||
"samples_per_resource": samples_per_resource
|
||||
}
|
||||
},
|
||||
"admin": {
|
||||
"endpoint": mock.MagicMock()
|
||||
},
|
||||
"task": mock.MagicMock(),
|
||||
"users": users,
|
||||
"tenants": tenants
|
||||
}
|
||||
return tenants, context
|
||||
|
||||
def test_init(self):
|
||||
context = {}
|
||||
context["task"] = mock.MagicMock()
|
||||
context["config"] = {
|
||||
"ceilometer": {
|
||||
"counter_name": "cpu_util",
|
||||
"counter_type": "gauge",
|
||||
"counter_unit": "instance",
|
||||
"counter_volume": 1.0,
|
||||
"resources_per_tenant": 5,
|
||||
"samples_per_resource": 5
|
||||
}
|
||||
}
|
||||
|
||||
inst = ceilometer.CeilometerSampleGenerator(context)
|
||||
self.assertEqual(inst.config, context["config"]["ceilometer"])
|
||||
|
||||
@mock.patch("%s.ceilometer.osclients" % CTX)
|
||||
def test_setup(self, mock_osclients):
|
||||
fc = fakes.FakeClients()
|
||||
mock_osclients.Clients.return_value = fc
|
||||
|
||||
tenants_count = 2
|
||||
users_per_tenant = 5
|
||||
resources_per_tenant = 5
|
||||
samples_per_resource = 5
|
||||
|
||||
tenants, real_context = self._gen_context(
|
||||
tenants_count, users_per_tenant,
|
||||
resources_per_tenant, samples_per_resource)
|
||||
|
||||
new_context = copy.deepcopy(real_context)
|
||||
for id_ in tenants.keys():
|
||||
new_context["tenants"][id_].setdefault("samples", list())
|
||||
new_context["tenants"][id_].setdefault("resources", list())
|
||||
for i in range(resources_per_tenant):
|
||||
for j in range(samples_per_resource):
|
||||
new_context["tenants"][id_]["samples"].append(
|
||||
{"counter_name": "fake-counter-name",
|
||||
"counter_type": "fake-counter-type",
|
||||
"counter_unit": "fake-counter-unit",
|
||||
"counter_volume": 100,
|
||||
"resource_id": "fake-resource-id"})
|
||||
new_context["tenants"][id_]["resources"].append(
|
||||
"fake-resource-id")
|
||||
|
||||
ceilometer_ctx = ceilometer.CeilometerSampleGenerator(real_context)
|
||||
ceilometer_ctx.setup()
|
||||
self.assertEqual(new_context, ceilometer_ctx.context)
|
||||
|
||||
@mock.patch("%s.ceilometer.osclients" % CTX)
|
||||
def test_cleanup(self, mock_osclients):
|
||||
tenants, context = self._gen_context(2, 5, 3, 3)
|
||||
ceilometer_ctx = ceilometer.CeilometerSampleGenerator(context)
|
||||
ceilometer_ctx.cleanup()
|
@ -15,6 +15,7 @@
|
||||
import mock
|
||||
|
||||
from rally.benchmark.scenarios.ceilometer import resources
|
||||
from rally import exceptions
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
@ -23,5 +24,24 @@ class CeilometerResourcesTestCase(test.TestCase):
|
||||
scenario = resources.CeilometerResource()
|
||||
scenario._list_resources = mock.MagicMock()
|
||||
scenario.list_resources()
|
||||
scenario._list_resources.assert_called_once_with()
|
||||
|
||||
scenario._list_resources.assert_called_once_with()
|
||||
def test_get_tenant_resources(self):
|
||||
scenario = resources.CeilometerResource()
|
||||
resource_list = ["id1", "id2", "id3", "id4"]
|
||||
context = {"user": {"tenant_id": "fake"},
|
||||
"tenant": {"id": "fake", "resources": resource_list}}
|
||||
scenario.context = context
|
||||
scenario._get_resource = mock.MagicMock()
|
||||
scenario.get_tenant_resources()
|
||||
for resource_id in resource_list:
|
||||
scenario._get_resource.assert_any_call(resource_id)
|
||||
|
||||
def test_get_tenant_resources_with_exception(self):
|
||||
scenario = resources.CeilometerResource()
|
||||
resource_list = []
|
||||
context = {"user": {"tenant_id": "fake"},
|
||||
"tenant": {"id": "fake", "resources": resource_list}}
|
||||
scenario.context = context
|
||||
self.assertRaises(exceptions.NotFoundException,
|
||||
scenario.get_tenant_resources)
|
@ -23,5 +23,4 @@ class CeilometerSamplesTestCase(test.TestCase):
|
||||
scenario = samples.CeilometerSamples()
|
||||
scenario._list_samples = mock.MagicMock()
|
||||
scenario.list_samples()
|
||||
|
||||
scenario._list_samples.assert_called_once_with()
|
||||
|
@ -122,6 +122,10 @@ class CeilometerScenarioTestCase(test.TestCase):
|
||||
fake_samples = self.scenario._list_samples()
|
||||
self.assertEqual(fake_samples, ["fake-samples"])
|
||||
|
||||
def test__get_resource(self):
|
||||
fake_resource_info = self.scenario._get_resource("fake-resource-id")
|
||||
self.assertEqual(fake_resource_info, ["fake-resource-info"])
|
||||
|
||||
def test__get_stats(self):
|
||||
"""Test _get_stats function."""
|
||||
fake_statistics = self.scenario._get_stats("fake-meter")
|
||||
|
@ -219,6 +219,7 @@ class FakeAlarm(FakeResource):
|
||||
self.threshold = kwargs.get("threshold")
|
||||
self.state = kwargs.get("state", "fake-alarm-state")
|
||||
self.alarm_id = kwargs.get("alarm_id", "fake-alarm-id")
|
||||
self.state = kwargs.get("state", "ok")
|
||||
self.optional_args = kwargs.get("optional_args", {})
|
||||
|
||||
|
||||
@ -229,7 +230,17 @@ class FakeSample(FakeResource):
|
||||
self.counter_type = kwargs.get("counter_type", "fake-counter-type")
|
||||
self.counter_unit = kwargs.get("counter_unit", "fake-counter-unit")
|
||||
self.counter_volume = kwargs.get("counter_volume", 100)
|
||||
self.resource_id = kwargs.get("resource_id", "fake-resource-id")
|
||||
|
||||
@property
|
||||
def resource_id(self):
|
||||
return "fake-resource-id"
|
||||
|
||||
def to_dict(self):
|
||||
return {"counter_name": self.counter_name,
|
||||
"counter_type": self.counter_type,
|
||||
"counter_unit": self.counter_unit,
|
||||
"counter_volume": self.counter_volume,
|
||||
"resource_id": self.resource_id}
|
||||
|
||||
|
||||
class FakeVolume(FakeResource):
|
||||
@ -775,6 +786,9 @@ class FakeMeterManager(FakeManager):
|
||||
|
||||
class FakeCeilometerResourceManager(FakeManager):
|
||||
|
||||
def get(self, resource_id):
|
||||
return ["fake-resource-info"]
|
||||
|
||||
def list(self):
|
||||
return ["fake-resource"]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user