aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmma Foley <emma.l.foley@intel.com>2018-02-22 19:11:12 +0000
committerEmma Foley <emma.l.foley@intel.com>2018-03-01 15:02:11 +0000
commit1681ba53783835e500e602a1b7500e0221eb08f9 (patch)
tree609e676f80093ff71daa49a21816b956852b2845
parentc9b24900ab4782c946f5a423e9c16365abced786 (diff)
Update TaskParser to deal with qualified name in Context
The context name depends on the defined name in the testcase input file, the task ID and the flags of the context. 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. This patch makes this process transparent to the developer. This patch modifies how TaskParser determines the correct context name, taking into account that the name might change based on context flags. JIRA: YARDSTICK-886 Change-Id: I44da30dac562c1a4166e084645ae91c17798651d Signed-off-by: Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com> Signed-off-by: Emma Foley <emma.l.foley@intel.com>
-rw-r--r--yardstick/benchmark/core/task.py107
-rw-r--r--yardstick/common/exceptions.py4
-rw-r--r--yardstick/tests/unit/benchmark/core/test_task.py115
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)