Add context that pre-creates heat stacks

Add custom context that creates a bunch of stacks with resources.
After test context cleanups all stacks from heat.
The context allows is needed for testing such scenario as
"list_stack", "list_resources" and others, where stacks shoule be
created before test.

Change-Id: I74ea1b1379dba68e306ad49bc8fb2291d7cf22e7
This commit is contained in:
kairat_kushaev 2015-02-06 18:49:42 +03:00
parent f7ce01c888
commit 7cfd85a145
2 changed files with 191 additions and 0 deletions

View File

@ -0,0 +1,90 @@
# Copyright 2015: Mirantis Inc.
# 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.context.cleanup import manager as resource_manager
from rally.benchmark.scenarios.heat import utils as heat_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="stacks", order=435)
class StackGenerator(base.Context):
"""Context class for create temporary stacks with resources.
Stack generator allows to generate arbitrary number of stacks for
each tenant before test scenarios. In addition, it allows to define
number of resources (namely OS::Heat::RandomString) that will be created
inside each stack. After test execution the stacks will be
automatically removed from heat.
"""
# The schema of the context configuration format
CONFIG_SCHEMA = {
"type": "object",
"$schema": consts.JSON_SCHEMA,
"properties": {
"stacks_per_tenant": {
"type": "integer",
"minimum": 1
},
"resources_per_stack": {
"type": "integer",
"minimum": 1
}
},
"additionalProperties": False
}
def __init__(self, context):
super(StackGenerator, self).__init__(context)
self.config.setdefault("stacks_per_tenant", 2)
self.config.setdefault("resources_per_stack", 10)
@staticmethod
def _prepare_stack_template(res_num):
template = {
"heat_template_version": "2014-10-16",
"description": "Test template for rally",
"resources": {}
}
rand_string = {"type": "OS::Heat::RandomString"}
for i in range(res_num):
template["resources"]["TestResource%d" % i] = rand_string
return template
@rutils.log_task_wrapper(LOG.info, _("Enter context: `Stacks`"))
def setup(self):
template = self._prepare_stack_template(
self.config["resources_per_stack"])
for user, tenant_id in rutils.iterate_per_tenants(
self.context["users"]):
heat_scenario = heat_utils.HeatScenario(
clients=osclients.Clients(user["endpoint"]))
self.context["tenants"][tenant_id]["stacks"] = []
for i in range(self.config["stacks_per_tenant"]):
stack = heat_scenario._create_stack(template)
self.context["tenants"][tenant_id]["stacks"].append(stack.id)
@rutils.log_task_wrapper(LOG.info, _("Exit context: `Stacks`"))
def cleanup(self):
resource_manager.cleanup(names=["heat.stacks"],
users=self.context.get("users", []))

View File

@ -0,0 +1,101 @@
# Copyright 2015: Mirantis Inc.
# 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 mock
from rally.benchmark.context import stacks
from tests.unit import fakes
from tests.unit import test
CTX = "rally.benchmark.context"
SCN = "rally.benchmark.scenarios"
class TestStackGenerator(test.TestCase):
def _gen_tenants(self, count):
tenants = dict()
for id in range(count):
tenants[str(id)] = dict(name=str(id))
return tenants
def test_init(self):
context = {
"task": mock.MagicMock(),
"config": {
"stacks": {
"stacks_per_tenant": 1,
"resources_per_stack": 1
}
}
}
inst = stacks.StackGenerator(context)
self.assertEqual(inst.config, context["config"]["stacks"])
@mock.patch("%s.heat.utils.HeatScenario._create_stack" % SCN,
return_value=fakes.FakeStack(id="uuid"))
@mock.patch("%s.stacks.osclients" % CTX)
def test_setup(self, mock_osclients, mock_stack_create):
tenants_count = 2
users_per_tenant = 5
stacks_per_tenant = 1
fc = fakes.FakeClients()
mock_osclients.Clients.return_value = fc
tenants = self._gen_tenants(tenants_count)
users = list()
for ten_id in tenants:
for i in range(users_per_tenant):
users.append({"id": i, "tenant_id": ten_id,
"endpoint": "endpoint"})
context = {
"config": {
"users": {
"tenants": tenants_count,
"users_per_tenant": users_per_tenant,
"concurrent": 10,
},
"stacks": {
"stacks_per_tenant": stacks_per_tenant,
"resources_per_stack": 1
}
},
"task": mock.MagicMock(),
"users": users,
"tenants": tenants
}
stack_ctx = stacks.StackGenerator(context)
stack_ctx.setup()
self.assertEqual(tenants_count * stacks_per_tenant,
mock_stack_create.call_count)
# check that stack ids have been saved in context
for ten_id in context["tenants"].keys():
self.assertEqual(stacks_per_tenant,
len(context["tenants"][ten_id]["stacks"]))
@mock.patch("%s.stacks.resource_manager.cleanup" % CTX)
def test_cleanup(self, mock_cleanup):
context = {
"task": mock.MagicMock(),
"users": mock.MagicMock()
}
stack_ctx = stacks.StackGenerator(context)
stack_ctx.cleanup()
mock_cleanup.assert_called_once_with(names=["heat.stacks"],
users=context["users"])