diff options
-rw-r--r-- | yardstick/benchmark/core/task.py | 107 | ||||
-rw-r--r-- | yardstick/common/exceptions.py | 4 | ||||
-rw-r--r-- | yardstick/tests/unit/benchmark/core/test_task.py | 115 |
3 files changed, 154 insertions, 72 deletions
diff --git a/yardstick/benchmark/core/task.py b/yardstick/benchmark/core/task.py index 5fcc9182c..270800a99 100644 --- a/yardstick/benchmark/core/task.py +++ b/yardstick/benchmark/core/task.py @@ -7,10 +7,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -""" Handler for yardstick command 'task' """ -from __future__ import absolute_import -from __future__ import print_function import sys import os from collections import OrderedDict @@ -34,6 +31,7 @@ from yardstick.dispatcher.base import Base as DispatcherBase from yardstick.common.task_template import TaskTemplate from yardstick.common import utils from yardstick.common import constants +from yardstick.common import exceptions from yardstick.common.html_template import report_template output_file_default = "/tmp/yardstick.out" @@ -518,13 +516,9 @@ class TaskParser(object): # pragma: no cover context_cfgs = [{"type": "Dummy"}] contexts = [] - name_suffix = '-{}'.format(task_id[:8]) for cfg_attrs in context_cfgs: - try: - cfg_attrs['name'] = '{}{}'.format(cfg_attrs['name'], - name_suffix) - except KeyError: - pass + + cfg_attrs['task_id'] = task_id # default to Heat context because we are testing OpenStack context_type = cfg_attrs.get("type", "Heat") context = Context.get(context_type) @@ -542,17 +536,71 @@ class TaskParser(object): # pragma: no cover # relative to task path scenario["task_path"] = os.path.dirname(self.path) - change_server_name(scenario, name_suffix) - - try: - for node in scenario['nodes']: - scenario['nodes'][node] += name_suffix - except KeyError: - pass + self._change_node_names(scenario, contexts) # TODO we need something better here, a class that represent the file return cfg["scenarios"], run_in_parallel, meet_precondition, contexts + @staticmethod + def _change_node_names(scenario, contexts): + """Change the node names in a scenario, depending on the context config + + The nodes (VMs or physical servers) are referred in the context section + with the name of the server and the name of the context: + <server name>.<context name> + + If the context is going to be undeployed at the end of the test, the + task ID is suffixed to the name to avoid interferences with previous + deployments. If the context needs to be deployed at the end of the + test, the name assigned is kept. + + There are several places where a node name could appear in the scenario + configuration: + scenario: + host: athena.demo + target: kratos.demo + targets: + - athena.demo + - kratos.demo + + scenario: + options: + server_name: # JIRA: YARDSTICK-810 + host: athena.demo + target: kratos.demo + + scenario: + nodes: + tg__0: tg_0.yardstick + vnf__0: vnf_0.yardstick + """ + def qualified_name(name): + node_name, context_name = name.split('.') + try: + ctx = next((context for context in contexts + if context.assigned_name == context_name)) + except StopIteration: + raise exceptions.ScenarioConfigContextNameNotFound( + context_name=context_name) + + return '{}.{}'.format(node_name, ctx.name) + + if 'host' in scenario: + scenario['host'] = qualified_name(scenario['host']) + if 'target' in scenario: + scenario['target'] = qualified_name(scenario['target']) + server_name = scenario.get('options', {}).get('server_name', {}) + if 'host' in server_name: + server_name['host'] = qualified_name(server_name['host']) + if 'target' in server_name: + server_name['target'] = qualified_name(server_name['target']) + if 'targets' in scenario: + for idx, target in enumerate(scenario['targets']): + scenario['targets'][idx] = qualified_name(target) + if 'nodes' in scenario: + for scenario_node, target in scenario['nodes'].items(): + scenario['nodes'][scenario_node] = qualified_name(target) + def _check_schema(self, cfg_schema, schema_type): """Check if config file is using the correct schema type""" @@ -685,30 +733,3 @@ def parse_task_args(src_name, args): % {"src": src_name, "src_type": type(kw)}) raise TypeError() return kw - - -def change_server_name(scenario, suffix): - - def add_suffix(cfg, key): - try: - value = cfg[key] - except KeyError: - pass - else: - try: - value['name'] += suffix - except TypeError: - cfg[key] += suffix - - server_name = scenario.get('options', {}).get('server_name', {}) - - add_suffix(scenario, 'host') - add_suffix(scenario, 'target') - add_suffix(server_name, 'host') - add_suffix(server_name, 'target') - - try: - key = 'targets' - scenario[key] = ['{}{}'.format(a, suffix) for a in scenario[key]] - except KeyError: - pass diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py index 3e0635e46..4f89fed32 100644 --- a/yardstick/common/exceptions.py +++ b/yardstick/common/exceptions.py @@ -70,3 +70,7 @@ class IPv6RangeError(YardstickException): class DPDKSetupDriverError(YardstickException): message = '"igb_uio" driver is not loaded' + + +class ScenarioConfigContextNameNotFound(YardstickException): + message = 'Context name "%(context_name)s" not found' diff --git a/yardstick/tests/unit/benchmark/core/test_task.py b/yardstick/tests/unit/benchmark/core/test_task.py index bac035fb9..2420df2d8 100644 --- a/yardstick/tests/unit/benchmark/core/test_task.py +++ b/yardstick/tests/unit/benchmark/core/test_task.py @@ -7,13 +7,16 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +import copy import os import mock import unittest +from yardstick.benchmark.contexts import dummy from yardstick.benchmark.core import task from yardstick.common import constants as consts +from yardstick.common import exceptions class TaskTestCase(unittest.TestCase): @@ -249,31 +252,6 @@ class TaskTestCase(unittest.TestCase): actual_result = t._parse_options(options) self.assertEqual(expected_result, actual_result) - - def test_change_server_name_host_str(self): - scenario = {'host': 'demo'} - suffix = '-8' - task.change_server_name(scenario, suffix) - self.assertEqual('demo-8', scenario['host']) - - def test_change_server_name_host_dict(self): - scenario = {'host': {'name': 'demo'}} - suffix = '-8' - task.change_server_name(scenario, suffix) - self.assertEqual('demo-8', scenario['host']['name']) - - def test_change_server_name_target_str(self): - scenario = {'target': 'demo'} - suffix = '-8' - task.change_server_name(scenario, suffix) - self.assertEqual('demo-8', scenario['target']) - - def test_change_server_name_target_dict(self): - scenario = {'target': {'name': 'demo'}} - suffix = '-8' - task.change_server_name(scenario, suffix) - self.assertEqual('demo-8', scenario['target']['name']) - @mock.patch('six.moves.builtins.open', side_effect=mock.mock_open()) @mock.patch.object(task, 'utils') @mock.patch('logging.root') @@ -292,9 +270,88 @@ class TaskTestCase(unittest.TestCase): return os.path.join(consts.YARDSTICK_ROOT_PATH, filepath) -def main(): - unittest.main() +class TaskParserTestCase(unittest.TestCase): + + def setUp(self): + self.parser = task.TaskParser('fake/path') + self.scenario = { + 'host': 'athena.demo', + 'target': 'kratos.demo', + 'targets': [ + 'ares.demo', 'mars.demo' + ], + 'options': { + 'server_name': { + 'host': 'jupiter.demo', + 'target': 'saturn.demo', + }, + }, + 'nodes': { + 'tg__0': 'tg_0.demo', + 'vnf__0': 'vnf_0.demo', + } + } + + def test__change_node_names(self): + + ctx_attrs = { + 'name': 'demo', + 'task_id': '1234567890', + 'servers': [ + 'athena', 'kratos', + 'ares', 'mars', + 'jupiter', 'saturn', + 'tg_0', 'vnf_0' + ] + } + + my_context = dummy.DummyContext() + my_context.init(ctx_attrs) + + expected_scenario = { + 'host': 'athena.demo-12345678', + 'target': 'kratos.demo-12345678', + 'targets': [ + 'ares.demo-12345678', 'mars.demo-12345678' + ], + 'options': { + 'server_name': { + 'host': 'jupiter.demo-12345678', + 'target': 'saturn.demo-12345678', + }, + }, + 'nodes': { + 'tg__0': 'tg_0.demo-12345678', + 'vnf__0': 'vnf_0.demo-12345678', + } + } + + scenario = copy.deepcopy(self.scenario) + + self.parser._change_node_names(scenario, [my_context]) + self.assertEqual(scenario, expected_scenario) + + def test__change_node_names_context_not_found(self): + scenario = copy.deepcopy(self.scenario) + self.assertRaises(exceptions.ScenarioConfigContextNameNotFound, + self.parser._change_node_names, + scenario, []) + + def test__change_node_names_context_name_unchanged(self): + ctx_attrs = { + 'name': 'demo', + 'task_id': '1234567890', + 'flags': { + 'no_setup': True, + 'no_teardown': True + } + } + + my_context = dummy.DummyContext() + my_context.init(ctx_attrs) + scenario = copy.deepcopy(self.scenario) + expected_scenario = copy.deepcopy(self.scenario) -if __name__ == '__main__': - main() + self.parser._change_node_names(scenario, [my_context]) + self.assertEqual(scenario, expected_scenario) |