From c9b24900ab4782c946f5a423e9c16365abced786 Mon Sep 17 00:00:00 2001
From: Emma Foley <emma.l.foley@intel.com>
Date: Mon, 26 Feb 2018 11:43:51 +0000
Subject: Add qualified name to 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 base.Context use Flags when initialising contexts,
this sets the name property based on the no_setup and no_teardown
flags.

Since base.Context is an abstract class, it cannot be instantiated.
However, there are some non-abstract methods that need testing.
Since DummyContext does not override any of these methods, it can be used for
testing.

JIRA: YARDSTICK-886

Change-Id: I1447fb5ed447691eaeb0a97f928c0b3333799d07
Signed-off-by: Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Signed-off-by: Emma Foley <emma.l.foley@intel.com>
---
 yardstick/benchmark/contexts/base.py               |  23 ++-
 yardstick/benchmark/contexts/dummy.py              |  24 +--
 yardstick/benchmark/contexts/heat.py               |   9 +-
 yardstick/benchmark/contexts/kubernetes.py         |   3 +-
 yardstick/benchmark/contexts/node.py               |   8 +-
 .../benchmark/contexts/standalone/ovs_dpdk.py      |   3 +-
 yardstick/benchmark/contexts/standalone/sriov.py   |   3 +-
 .../benchmark/contexts/standalone/test_ovs_dpdk.py |  70 ++++----
 .../benchmark/contexts/standalone/test_sriov.py    |  58 +++----
 .../tests/unit/benchmark/contexts/test_dummy.py    |  52 +++++-
 .../tests/unit/benchmark/contexts/test_heat.py     | 127 ++++++++++----
 .../unit/benchmark/contexts/test_kubernetes.py     |   9 +-
 .../tests/unit/benchmark/contexts/test_node.py     | 191 ++++++++-------------
 yardstick/tests/unit/orchestrator/test_heat.py     |   3 +-
 14 files changed, 318 insertions(+), 265 deletions(-)

diff --git a/yardstick/benchmark/contexts/base.py b/yardstick/benchmark/contexts/base.py
index 20c160cfb..ae8319e37 100644
--- a/yardstick/benchmark/contexts/base.py
+++ b/yardstick/benchmark/contexts/base.py
@@ -40,6 +40,7 @@ class Flags(object):
 class Context(object):
     """Class that represents a context in the logical model"""
     list = []
+    SHORT_TASK_ID_LEN = 8
 
     @staticmethod
     def split_name(name, sep='.'):
@@ -52,10 +53,28 @@ class Context(object):
 
     def __init__(self):
         Context.list.append(self)
+        self._flags = Flags()
+        self._name = None
+        self._task_id = None
 
-    @abc.abstractmethod
     def init(self, attrs):
-        """Initiate context."""
+        """Initiate context"""
+        self._name = attrs['name']
+        self._task_id = attrs['task_id']
+        self._flags.parse(**attrs.get('flags', {}))
+        self._name_task_id = '{}-{}'.format(
+            self._name, self._task_id[:self.SHORT_TASK_ID_LEN])
+
+    @property
+    def name(self):
+        if self._flags.no_setup or self._flags.no_teardown:
+            return self._name
+        else:
+            return self._name_task_id
+
+    @property
+    def assigned_name(self):
+        return self._name
 
     @staticmethod
     def get_cls(context_type):
diff --git a/yardstick/benchmark/contexts/dummy.py b/yardstick/benchmark/contexts/dummy.py
index 8ae4b65b8..a9e4564fe 100644
--- a/yardstick/benchmark/contexts/dummy.py
+++ b/yardstick/benchmark/contexts/dummy.py
@@ -7,33 +7,25 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-from __future__ import absolute_import
-import logging
-
 from yardstick.benchmark.contexts.base import Context
 
 
-LOG = logging.getLogger(__name__)
-
-
 class DummyContext(Context):
-    """Class that handle dummy info"""
-
-    __context_type__ = "Dummy"
+    """Class that handle dummy info.
 
-    def __init__(self):
-        super(DummyContext, self).__init__()
+    This class is also used to test the abstract class Context because it
+    provides a minimal concrete implementation of a subclass.
+    """
 
-    def init(self, attrs):
-        pass
+    __context_type__ = "Dummy"
 
     def deploy(self):
-        """don't need to deploy"""
+        """Don't need to deploy"""
         pass
 
     def undeploy(self):
-        """don't need to undeploy"""
-        super(DummyContext, self).undeploy()
+        """Don't need to undeploy"""
+        pass
 
     def _get_server(self, attr_name):
         return None
diff --git a/yardstick/benchmark/contexts/heat.py b/yardstick/benchmark/contexts/heat.py
index 7b7f1be32..1e2537738 100644
--- a/yardstick/benchmark/contexts/heat.py
+++ b/yardstick/benchmark/contexts/heat.py
@@ -50,7 +50,6 @@ class HeatContext(Context):
     __context_type__ = "Heat"
 
     def __init__(self):
-        self.name = None
         self.stack = None
         self.networks = OrderedDict()
         self.heat_timeout = None
@@ -95,10 +94,10 @@ class HeatContext(Context):
         return sorted_networks
 
     def init(self, attrs):
-        """initializes itself from the supplied arguments"""
-        self.check_environment()
-        self.name = attrs["name"]
+        """Initializes itself from the supplied arguments"""
+        super(HeatContext, self).init(attrs)
 
+        self.check_environment()
         self._user = attrs.get("user")
 
         self.template_file = attrs.get("heat_template")
@@ -313,7 +312,7 @@ class HeatContext(Context):
                                               timeout=self.heat_timeout)
         except KeyboardInterrupt:
             raise SystemExit("\nStack create interrupted")
-        except:
+        except Exception:
             LOG.exception("stack failed")
             # let the other failures happen, we want stack trace
             raise
diff --git a/yardstick/benchmark/contexts/kubernetes.py b/yardstick/benchmark/contexts/kubernetes.py
index 2334e5076..4bea991ea 100644
--- a/yardstick/benchmark/contexts/kubernetes.py
+++ b/yardstick/benchmark/contexts/kubernetes.py
@@ -29,7 +29,6 @@ class KubernetesContext(Context):
     __context_type__ = "Kubernetes"
 
     def __init__(self):
-        self.name = ''
         self.ssh_key = ''
         self.key_path = ''
         self.public_key_path = ''
@@ -38,7 +37,7 @@ class KubernetesContext(Context):
         super(KubernetesContext, self).__init__()
 
     def init(self, attrs):
-        self.name = attrs.get('name', '')
+        super(KubernetesContext, self).init(attrs)
 
         template_cfg = attrs.get('servers', {})
         self.template = KubernetesTemplate(self.name, template_cfg)
diff --git a/yardstick/benchmark/contexts/node.py b/yardstick/benchmark/contexts/node.py
index ffc82c8ed..fa619a9aa 100644
--- a/yardstick/benchmark/contexts/node.py
+++ b/yardstick/benchmark/contexts/node.py
@@ -35,7 +35,6 @@ class NodeContext(Context):
     __context_type__ = "Node"
 
     def __init__(self):
-        self.name = None
         self.file_path = None
         self.nodes = []
         self.networks = {}
@@ -60,7 +59,8 @@ class NodeContext(Context):
 
     def init(self, attrs):
         """initializes itself from the supplied arguments"""
-        self.name = attrs["name"]
+        super(NodeContext, self).init(attrs)
+
         self.file_path = file_path = attrs.get("file", "pod.yaml")
 
         try:
@@ -157,7 +157,7 @@ class NodeContext(Context):
         except StopIteration:
             pass
         else:
-            raise ValueError("Duplicate nodes!!! Nodes: %s %s",
+            raise ValueError("Duplicate nodes!!! Nodes: %s %s" %
                              (node, duplicate))
 
         node["name"] = attr_name
@@ -204,7 +204,7 @@ class NodeContext(Context):
         self.client._put_file_shell(script_file, '~/{}'.format(script))
 
         cmd = 'sudo bash {} {}'.format(script, options)
-        status, stdout, stderr = self.client.execute(cmd)
+        status, _, stderr = self.client.execute(cmd)
         if status:
             raise RuntimeError(stderr)
 
diff --git a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
index c931d85d0..a18b42ea5 100644
--- a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
+++ b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
@@ -59,7 +59,6 @@ class OvsDpdkContext(Context):
         self.first_run = True
         self.dpdk_devbind = ''
         self.vm_names = []
-        self.name = None
         self.nfvi_host = []
         self.nodes = []
         self.networks = {}
@@ -74,8 +73,8 @@ class OvsDpdkContext(Context):
 
     def init(self, attrs):
         """initializes itself from the supplied arguments"""
+        super(OvsDpdkContext, self).init(attrs)
 
-        self.name = attrs["name"]
         self.file_path = attrs.get("file", "pod.yaml")
 
         self.nodes, self.nfvi_host, self.host_mgmt = \
diff --git a/yardstick/benchmark/contexts/standalone/sriov.py b/yardstick/benchmark/contexts/standalone/sriov.py
index 9cca3e15c..d7620552b 100644
--- a/yardstick/benchmark/contexts/standalone/sriov.py
+++ b/yardstick/benchmark/contexts/standalone/sriov.py
@@ -43,7 +43,6 @@ class SriovContext(Context):
         self.first_run = True
         self.dpdk_devbind = ''
         self.vm_names = []
-        self.name = None
         self.nfvi_host = []
         self.nodes = []
         self.networks = {}
@@ -57,8 +56,8 @@ class SriovContext(Context):
 
     def init(self, attrs):
         """initializes itself from the supplied arguments"""
+        super(SriovContext, self).init(attrs)
 
-        self.name = attrs["name"]
         self.file_path = attrs.get("file", "pod.yaml")
 
         self.nodes, self.nfvi_host, self.host_mgmt = \
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
index 02a85525a..0223fd3ff 100644
--- a/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
@@ -26,14 +26,6 @@ class OvsDpdkContextTestCase(unittest.TestCase):
     NODES_ovs_dpdk_SAMPLE = "nodes_ovs_dpdk_sample.yaml"
     NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml"
 
-    ATTRS = {
-        'name': 'StandaloneOvsDpdk',
-        'file': 'pod',
-        'flavor': {},
-        'servers': {},
-        'networks': {},
-    }
-
     NETWORKS = {
         'mgmt': {'cidr': '152.16.100.10/24'},
         'private_0': {
@@ -55,7 +47,17 @@ class OvsDpdkContextTestCase(unittest.TestCase):
     }
 
     def setUp(self):
+        self.attrs = {
+            'name': 'foo',
+            'task_id': '1234567890',
+            'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
+        }
         self.ovs_dpdk = ovs_dpdk.OvsDpdkContext()
+        self.addCleanup(self._remove_contexts)
+
+    def _remove_contexts(self):
+        if self.ovs_dpdk in self.ovs_dpdk.list:
+            self.ovs_dpdk._delete_context()
 
     @mock.patch('yardstick.benchmark.contexts.standalone.model.Server')
     @mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper')
@@ -66,9 +68,18 @@ class OvsDpdkContextTestCase(unittest.TestCase):
         self.assertTrue(self.ovs_dpdk.first_run)
 
     def test_init(self):
+        ATTRS = {
+            'name': 'StandaloneOvsDpdk',
+            'task_id': '1234567890',
+            'file': 'pod',
+            'flavor': {},
+            'servers': {},
+            'networks': {},
+        }
+
         self.ovs_dpdk.helper.parse_pod_file = mock.Mock(
             return_value=[{}, {}, {}])
-        self.assertIsNone(self.ovs_dpdk.init(self.ATTRS))
+        self.assertIsNone(self.ovs_dpdk.init(ATTRS))
 
     def test_setup_ovs(self):
         with mock.patch("yardstick.ssh.SSH") as ssh:
@@ -186,12 +197,7 @@ class OvsDpdkContextTestCase(unittest.TestCase):
 
     def test__get_server_with_dic_attr_name(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
-        }
-
-        self.ovs_dpdk.init(attrs)
+        self.ovs_dpdk.init(self.attrs)
 
         attr_name = {'name': 'foo.bar'}
         result = self.ovs_dpdk._get_server(attr_name)
@@ -200,14 +206,9 @@ class OvsDpdkContextTestCase(unittest.TestCase):
 
     def test__get_server_not_found(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
-        }
-
         self.ovs_dpdk.helper.parse_pod_file = mock.Mock(
             return_value=[{}, {}, {}])
-        self.ovs_dpdk.init(attrs)
+        self.ovs_dpdk.init(self.attrs)
 
         attr_name = 'bar.foo'
         result = self.ovs_dpdk._get_server(attr_name)
@@ -216,12 +217,7 @@ class OvsDpdkContextTestCase(unittest.TestCase):
 
     def test__get_server_mismatch(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
-        }
-
-        self.ovs_dpdk.init(attrs)
+        self.ovs_dpdk.init(self.attrs)
 
         attr_name = 'bar.foo1'
         result = self.ovs_dpdk._get_server(attr_name)
@@ -230,31 +226,23 @@ class OvsDpdkContextTestCase(unittest.TestCase):
 
     def test__get_server_duplicate(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
-        }
+        self.attrs['file'] = self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
 
-        self.ovs_dpdk.init(attrs)
+        self.ovs_dpdk.init(self.attrs)
 
-        attr_name = 'node1.foo'
+        attr_name = 'node1.foo-12345678'
         with self.assertRaises(ValueError):
             self.ovs_dpdk._get_server(attr_name)
 
     def test__get_server_found(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
-        }
-
-        self.ovs_dpdk.init(attrs)
+        self.ovs_dpdk.init(self.attrs)
 
-        attr_name = 'node1.foo'
+        attr_name = 'node1.foo-12345678'
         result = self.ovs_dpdk._get_server(attr_name)
 
         self.assertEqual(result['ip'], '10.229.47.137')
-        self.assertEqual(result['name'], 'node1.foo')
+        self.assertEqual(result['name'], 'node1.foo-12345678')
         self.assertEqual(result['user'], 'root')
         self.assertEqual(result['key_filename'], '/root/.yardstick_key')
 
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py
index f323fcd3c..f0953ef55 100644
--- a/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py
@@ -29,6 +29,7 @@ class SriovContextTestCase(unittest.TestCase):
 
     ATTRS = {
         'name': 'StandaloneSriov',
+        'task_id': '1234567890',
         'file': 'pod',
         'flavor': {},
         'servers': {},
@@ -56,7 +57,17 @@ class SriovContextTestCase(unittest.TestCase):
     }
 
     def setUp(self):
+        self.attrs = {
+            'name': 'foo',
+            'task_id': '1234567890',
+            'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
+        }
         self.sriov = sriov.SriovContext()
+        self.addCleanup(self._remove_contexts)
+
+    def _remove_contexts(self):
+        if self.sriov in self.sriov.list:
+            self.sriov._delete_context()
 
     @mock.patch('yardstick.benchmark.contexts.standalone.sriov.Libvirt')
     @mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper')
@@ -105,12 +116,7 @@ class SriovContextTestCase(unittest.TestCase):
 
     def test__get_server_with_dic_attr_name(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
-        }
-
-        self.sriov.init(attrs)
+        self.sriov.init(self.attrs)
 
         attr_name = {'name': 'foo.bar'}
         result = self.sriov._get_server(attr_name)
@@ -119,13 +125,8 @@ class SriovContextTestCase(unittest.TestCase):
 
     def test__get_server_not_found(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
-        }
-
         self.sriov.helper.parse_pod_file = mock.Mock(return_value=[{}, {}, {}])
-        self.sriov.init(attrs)
+        self.sriov.init(self.attrs)
 
         attr_name = 'bar.foo'
         result = self.sriov._get_server(attr_name)
@@ -134,12 +135,7 @@ class SriovContextTestCase(unittest.TestCase):
 
     def test__get_server_mismatch(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
-        }
-
-        self.sriov.init(attrs)
+        self.sriov.init(self.attrs)
 
         attr_name = 'bar.foo1'
         result = self.sriov._get_server(attr_name)
@@ -148,25 +144,29 @@ class SriovContextTestCase(unittest.TestCase):
 
     def test__get_server_duplicate(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
-        }
+        self.attrs['file'] = self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
 
-        self.sriov.init(attrs)
+        self.sriov.init(self.attrs)
 
-        attr_name = 'node1.foo'
+        attr_name = 'node1.foo-12345678'
         with self.assertRaises(ValueError):
             self.sriov._get_server(attr_name)
 
     def test__get_server_found(self):
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
-        }
+        self.sriov.init(self.attrs)
+
+        attr_name = 'node1.foo-12345678'
+        result = self.sriov._get_server(attr_name)
+
+        self.assertEqual(result['ip'], '10.229.47.137')
+        self.assertEqual(result['name'], 'node1.foo-12345678')
+        self.assertEqual(result['user'], 'root')
+        self.assertEqual(result['key_filename'], '/root/.yardstick_key')
 
-        self.sriov.init(attrs)
+    def test__get_server_no_task_id(self):
+        self.attrs['flags'] = {'no_setup': True}
+        self.sriov.init(self.attrs)
 
         attr_name = 'node1.foo'
         result = self.sriov._get_server(attr_name)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_dummy.py b/yardstick/tests/unit/benchmark/contexts/test_dummy.py
index 1a54035df..e393001a1 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_dummy.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_dummy.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 ##############################################################################
 # Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
 #
@@ -9,9 +7,6 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-# Unittest for yardstick.benchmark.contexts.dummy
-
-from __future__ import absolute_import
 import unittest
 
 from yardstick.benchmark.contexts import dummy
@@ -20,10 +15,55 @@ from yardstick.benchmark.contexts import dummy
 class DummyContextTestCase(unittest.TestCase):
 
     def setUp(self):
+        self.attrs = {
+            'name': 'foo',
+            'task_id': '1234567890',
+        }
         self.test_context = dummy.DummyContext()
+        self.addCleanup(self.test_context._delete_context)
+
+    def test___init__(self):
+        self.assertFalse(self.test_context._flags.no_setup)
+        self.assertFalse(self.test_context._flags.no_teardown)
+        self.assertIsNone(self.test_context._name)
+        self.assertIsNone(self.test_context._task_id)
+
+    def test_init(self):
+        self.test_context.init(self.attrs)
+        self.assertEqual(self.test_context._name, 'foo')
+        self.assertEqual(self.test_context._task_id, '1234567890')
+        self.assertFalse(self.test_context._flags.no_setup)
+        self.assertFalse(self.test_context._flags.no_teardown)
+
+        self.assertEqual(self.test_context.name, 'foo-12345678')
+        self.assertEqual(self.test_context.assigned_name, 'foo')
+
+    def test_init_flags_no_setup(self):
+        self.attrs['flags'] = {'no_setup': True, 'no_teardown': False}
+
+        self.test_context.init(self.attrs)
+
+        self.assertEqual(self.test_context._name, 'foo')
+        self.assertEqual(self.test_context._task_id, '1234567890')
+        self.assertTrue(self.test_context._flags.no_setup)
+        self.assertFalse(self.test_context._flags.no_teardown)
+
+        self.assertEqual(self.test_context.name, 'foo')
+        self.assertEqual(self.test_context.assigned_name, 'foo')
+
+    def test_init_flags_no_teardown(self):
+        self.attrs['flags'] = {'no_setup': False, 'no_teardown': True}
+
+        self.test_context.init(self.attrs)
+
+        self.assertFalse(self.test_context._flags.no_setup)
+        self.assertTrue(self.test_context._flags.no_teardown)
+
+        self.assertEqual(self.test_context.name, 'foo')
+        self.assertEqual(self.test_context.assigned_name, 'foo')
 
     def test__get_server(self):
-        self.test_context.init(None)
+        self.test_context.init(self.attrs)
         self.test_context.deploy()
 
         result = self.test_context._get_server(None)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_heat.py b/yardstick/tests/unit/benchmark/contexts/test_heat.py
index 4348bb052..baf9f40f8 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_heat.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_heat.py
@@ -18,6 +18,7 @@ import uuid
 import mock
 import unittest
 
+from yardstick.benchmark.contexts import base
 from yardstick.benchmark.contexts import heat
 from yardstick.benchmark.contexts import model
 
@@ -33,10 +34,18 @@ class HeatContextTestCase(unittest.TestCase):
 
     def setUp(self):
         self.test_context = heat.HeatContext()
+        self.addCleanup(self._remove_contexts)
         self.mock_context = mock.Mock(spec=heat.HeatContext())
 
+    def _remove_contexts(self):
+        if self.test_context in self.test_context.list:
+            self.test_context._delete_context()
+
     def test___init__(self):
-        self.assertIsNone(self.test_context.name)
+        self.assertIsNone(self.test_context._name)
+        self.assertIsNone(self.test_context._task_id)
+        self.assertFalse(self.test_context._flags.no_setup)
+        self.assertFalse(self.test_context._flags.no_teardown)
         self.assertIsNone(self.test_context.stack)
         self.assertEqual(self.test_context.networks, OrderedDict())
         self.assertEqual(self.test_context.servers, [])
@@ -64,6 +73,7 @@ class HeatContextTestCase(unittest.TestCase):
         networks = {'bar': {'cidr': '10.0.1.0/24'}}
         servers = {'baz': {'floating_ip': True, 'placement': 'pgrp1'}}
         attrs = {'name': 'foo',
+                 'task_id': '1234567890',
                  'placement_groups': pgs,
                  'server_groups': sgs,
                  'networks': networks,
@@ -71,9 +81,13 @@ class HeatContextTestCase(unittest.TestCase):
 
         self.test_context.init(attrs)
 
-        self.assertEqual(self.test_context.name, "foo")
-        self.assertEqual(self.test_context.keypair_name, "foo-key")
-        self.assertEqual(self.test_context.secgroup_name, "foo-secgroup")
+        self.assertFalse(self.test_context._flags.no_setup)
+        self.assertFalse(self.test_context._flags.no_teardown)
+        self.assertEqual(self.test_context._name, "foo")
+        self.assertEqual(self.test_context._task_id, '1234567890')
+        self.assertEqual(self.test_context.name, "foo-12345678")
+        self.assertEqual(self.test_context.keypair_name, "foo-12345678-key")
+        self.assertEqual(self.test_context.secgroup_name, "foo-12345678-secgroup")
 
         mock_pg.assert_called_with('pgrp1', self.test_context,
                                    pgs['pgrp1']['policy'])
@@ -98,32 +112,56 @@ class HeatContextTestCase(unittest.TestCase):
                 LOG.exception("key_filename: %s",
                               self.test_context.key_filename)
 
+    def test_init_no_name_or_task_id(self):
+        attrs = {}
+        self.assertRaises(KeyError, self.test_context.init, attrs)
+
+    def test_name(self):
+        self.test_context._name = 'foo'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
+        self.assertEqual(self.test_context.name, 'foo-12345678')
+        self.assertEqual(self.test_context.assigned_name, 'foo')
+
+    def test_name_flags(self):
+        self.test_context._flags = base.Flags(**{"no_setup": True, "no_teardown": True})
+        self.test_context._name = 'foo'
+        self.test_context._task_id = '1234567890'
+
+        self.assertEqual(self.test_context.name, 'foo')
+        self.assertEqual(self.test_context.assigned_name, 'foo')
+
     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
     def test__add_resources_to_template_no_servers(self, mock_template):
-
-        self.test_context.keypair_name = "foo-key"
-        self.test_context.secgroup_name = "foo-secgroup"
+        self.test_context._name = 'ctx'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
+        self.test_context.keypair_name = "ctx-key"
+        self.test_context.secgroup_name = "ctx-secgroup"
         self.test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b"
-        netattrs = {'cidr': '10.0.0.0/24', 'provider': None, 'external_network': 'ext_net'}
-        self.mock_context.name = 'bar'
+        netattrs = {'cidr': '10.0.0.0/24', 'provider': None,
+                    'external_network': 'ext_net'}
         self.test_context.networks = OrderedDict(
-            {"fool-network": model.Network("fool-network", self.mock_context,
+            {"mynet": model.Network("mynet", self.test_context,
                                            netattrs)})
 
         self.test_context._add_resources_to_template(mock_template)
         mock_template.add_keypair.assert_called_with(
-            "foo-key",
+            "ctx-key",
             "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b")
-        mock_template.add_security_group.assert_called_with("foo-secgroup")
-#        mock_template.add_network.assert_called_with("bar-fool-network", 'physnet1', None)
+        mock_template.add_security_group.assert_called_with("ctx-secgroup")
+        mock_template.add_network.assert_called_with(
+            "ctx-12345678-mynet", 'physnet1', None, None, None, None)
         mock_template.add_router.assert_called_with(
-            "bar-fool-network-router",
+            "ctx-12345678-mynet-router",
             netattrs["external_network"],
-            "bar-fool-network-subnet")
+            "ctx-12345678-mynet-subnet")
         mock_template.add_router_interface.assert_called_with(
-            "bar-fool-network-router-if0",
-            "bar-fool-network-router",
-            "bar-fool-network-subnet")
+            "ctx-12345678-mynet-router-if0",
+            "ctx-12345678-mynet-router",
+            "ctx-12345678-mynet-subnet")
 
     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
     def test_attrs_get(self, *args):
@@ -150,13 +188,16 @@ class HeatContextTestCase(unittest.TestCase):
 
     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
     def test_deploy(self, mock_template):
-        self.test_context.name = 'foo'
+        self.test_context._name = 'foo'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
         self.test_context.template_file = '/bar/baz/some-heat-file'
         self.test_context.heat_parameters = {'image': 'cirros'}
         self.test_context.get_neutron_info = mock.MagicMock()
         self.test_context.deploy()
 
-        mock_template.assert_called_with('foo',
+        mock_template.assert_called_with('foo-12345678',
                                          '/bar/baz/some-heat-file',
                                          {'image': 'cirros'})
         self.assertIsNotNone(self.test_context.stack)
@@ -164,7 +205,10 @@ class HeatContextTestCase(unittest.TestCase):
     def test_add_server_port(self):
         network1 = mock.MagicMock()
         network2 = mock.MagicMock()
-        self.test_context.name = 'foo'
+        self.test_context._name = 'foo'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
         self.test_context.stack = mock.MagicMock()
         self.test_context.networks = {
             'a': network1,
@@ -173,15 +217,15 @@ class HeatContextTestCase(unittest.TestCase):
         self.test_context.stack.outputs = {
             u'b': u'10.20.30.45',
             u'b-subnet_id': 1,
-            u'foo-a-subnet-cidr': u'10.20.0.0/15',
-            u'foo-a-subnet-gateway_ip': u'10.20.30.1',
+            u'foo-12345678-a-subnet-cidr': u'10.20.0.0/15',
+            u'foo-12345678-a-subnet-gateway_ip': u'10.20.30.1',
             u'b-mac_address': u'00:01',
             u'b-device_id': u'dev21',
             u'b-network_id': u'net789',
             u'd': u'40.30.20.15',
             u'd-subnet_id': 2,
-            u'foo-c-subnet-cidr': u'40.30.0.0/18',
-            u'foo-c-subnet-gateway_ip': u'40.30.20.254',
+            u'foo-12345678-c-subnet-cidr': u'40.30.0.0/18',
+            u'foo-12345678-c-subnet-gateway_ip': u'40.30.20.254',
             u'd-mac_address': u'00:10',
             u'd-device_id': u'dev43',
             u'd-network_id': u'net987',
@@ -221,6 +265,10 @@ class HeatContextTestCase(unittest.TestCase):
     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
     def test_undeploy(self, mock_template):
         self.test_context.stack = mock_template
+        self.test_context._name = 'foo'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
         self.test_context.undeploy()
         self.assertTrue(mock_template.delete.called)
 
@@ -228,6 +276,10 @@ class HeatContextTestCase(unittest.TestCase):
     @mock.patch('yardstick.benchmark.contexts.heat.os')
     def test_undeploy_key_filename(self, mock_os, mock_template):
         self.test_context.stack = mock_template
+        self.test_context._name = 'foo'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id)
         mock_os.path.exists.return_value = True
         self.assertIsNone(self.test_context.undeploy())
 
@@ -249,7 +301,10 @@ class HeatContextTestCase(unittest.TestCase):
         baz3_server.public_ip = '127.0.0.3'
         baz3_server.context.user = 'zab'
 
-        self.test_context.name = 'bar'
+        self.test_context._name = 'bar'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
         self.test_context._user = 'bot'
         self.test_context.stack = mock.Mock()
         self.test_context.stack.outputs = {
@@ -263,7 +318,7 @@ class HeatContextTestCase(unittest.TestCase):
         }
 
         attr_name = {
-            'name': 'foo.bar',
+            'name': 'foo.bar-12345678',
             'private_ip_attr': 'private_ip',
             'public_ip_attr': 'public_ip',
         }
@@ -288,7 +343,10 @@ class HeatContextTestCase(unittest.TestCase):
         baz3_server.public_ip = '127.0.0.3'
         baz3_server.context.user = 'zab'
 
-        self.test_context.name = 'bar'
+        self.test_context._name = 'bar'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
         self.test_context._user = 'bot'
         self.test_context.stack = mock.Mock()
         self.test_context.stack.outputs = {
@@ -302,7 +360,7 @@ class HeatContextTestCase(unittest.TestCase):
         }
 
         attr_name = {
-            'name': 'foo.bar',
+            'name': 'foo.bar-12345678',
         }
         result = self.test_context._get_server(attr_name)
         self.assertEqual(result['user'], 'bot')
@@ -327,7 +385,7 @@ class HeatContextTestCase(unittest.TestCase):
         baz3_server.public_ip = None
         baz3_server.context.user = 'zab'
 
-        self.test_context.name = 'bar1'
+        self.test_context._name = 'bar1'
         self.test_context.stack = mock.Mock()
         self.test_context.stack.outputs = {
             'private_ip': '10.0.0.1',
@@ -365,7 +423,7 @@ class HeatContextTestCase(unittest.TestCase):
         baz3_server.public_ip = None
         baz3_server.context.user = 'zab'
 
-        self.test_context.name = 'bar1'
+        self.test_context._name = 'bar1'
         self.test_context.stack = mock.Mock()
         self.test_context.stack.outputs = {
             'private_ip': '10.0.0.1',
@@ -398,7 +456,10 @@ class HeatContextTestCase(unittest.TestCase):
         baz3_server.public_ip = None
         baz3_server.context.user = 'zab'
 
-        self.test_context.name = 'bar1'
+        self.test_context._name = 'bar1'
+        self.test_context._task_id = '1235467890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
         self.test_context.stack = mock.Mock()
         self.test_context.stack.outputs = {
             'private_ip': '10.0.0.1',
@@ -434,7 +495,7 @@ class HeatContextTestCase(unittest.TestCase):
         baz3_server.public_ip = None
         baz3_server.context.user = 'zab'
 
-        self.mock_context.name = 'bar1'
+        self.mock_context._name = 'bar1'
         self.test_context.stack = mock.Mock()
         self.mock_context.stack.outputs = {
             'private_ip': '10.0.0.1',
diff --git a/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py b/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
index e149e0d18..73c59c1b8 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
@@ -10,13 +10,13 @@
 import mock
 import unittest
 
-from yardstick.benchmark.contexts.base import Context
 from yardstick.benchmark.contexts import kubernetes
 
 
 context_cfg = {
     'type': 'Kubernetes',
     'name': 'k8s',
+    'task_id': '1234567890',
     'servers': {
         'host': {
             'image': 'openretriever/yardstick',
@@ -40,11 +40,12 @@ class KubernetesTestCase(unittest.TestCase):
 
     def setUp(self):
         self.k8s_context = kubernetes.KubernetesContext()
+        self.addCleanup(self._remove_contexts)
         self.k8s_context.init(context_cfg)
 
-    def tearDown(self):
-        # clear kubernetes contexts from global list so we don't break other tests
-        Context.list = []
+    def _remove_contexts(self):
+        if self.k8s_context in self.k8s_context.list:
+            self.k8s_context._delete_context()
 
     @mock.patch.object(kubernetes.KubernetesContext, '_delete_services')
     @mock.patch.object(kubernetes.KubernetesContext, '_delete_ssh_key')
diff --git a/yardstick/tests/unit/benchmark/contexts/test_node.py b/yardstick/tests/unit/benchmark/contexts/test_node.py
index 5329d30f4..ae7c5d999 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_node.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_node.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 ##############################################################################
 # Copyright (c) 2015-2017 Huawei Technologies Co.,Ltd and others.
 #
@@ -9,9 +7,6 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-# Unittest for yardstick.benchmark.contexts.node
-
-from __future__ import absolute_import
 import os
 import unittest
 import errno
@@ -21,10 +16,6 @@ from yardstick.common import constants as consts
 from yardstick.benchmark.contexts import node
 
 
-# pylint: disable=unused-argument
-# disable this for now because I keep forgetting mock patch arg ordering
-
-
 class NodeContextTestCase(unittest.TestCase):
 
     PREFIX = 'yardstick.benchmark.contexts.node'
@@ -34,7 +25,17 @@ class NodeContextTestCase(unittest.TestCase):
 
     def setUp(self):
         self.test_context = node.NodeContext()
+        self.addCleanup(self._remove_contexts)
         self.os_path_join = os.path.join
+        self.attrs = {
+            'name': 'foo',
+            'task_id': '1234567890',
+            'file': self._get_file_abspath(self.NODES_SAMPLE)
+        }
+
+    def _remove_contexts(self):
+        if self.test_context in self.test_context.list:
+            self.test_context._delete_context()
 
     def _get_file_abspath(self, filename):
         curr_path = os.path.dirname(os.path.abspath(__file__))
@@ -42,7 +43,7 @@ class NodeContextTestCase(unittest.TestCase):
         return file_path
 
     def test___init__(self):
-        self.assertIsNone(self.test_context.name)
+        self.assertIsNone(self.test_context._name)
         self.assertIsNone(self.test_context.file_path)
         self.assertEqual(self.test_context.nodes, [])
         self.assertEqual(self.test_context.controllers, [])
@@ -74,6 +75,7 @@ class NodeContextTestCase(unittest.TestCase):
 
         attrs = {
             'name': 'foo',
+            'task_id': '1234567890',
             'file': error_path,
         }
         read_mock.side_effect = IOError(errno.EBUSY, 'busy')
@@ -97,37 +99,19 @@ class NodeContextTestCase(unittest.TestCase):
         self.assertEqual(str(raised.exception), str(read_mock.side_effect))
 
     def test_read_config_file(self):
-
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SAMPLE)
-        }
-
-        self.test_context.init(attrs)
+        self.test_context.init(self.attrs)
 
         self.assertIsNotNone(self.test_context.read_config_file())
 
     def test__dispatch_script(self):
-
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SAMPLE)
-        }
-
-        self.test_context.init(attrs)
+        self.test_context.init(self.attrs)
 
         self.test_context.env = {'bash': [{'script': 'dummy'}]}
         self.test_context._execute_script = mock.Mock()
         self.assertEqual(self.test_context._dispatch_script('bash'), None)
 
     def test__dispatch_ansible(self):
-
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SAMPLE)
-        }
-
-        self.test_context.init(attrs)
+        self.test_context.init(self.attrs)
 
         self.test_context.env = {'ansible': [{'script': 'dummy'}]}
         self.test_context._do_ansible_job = mock.Mock()
@@ -136,19 +120,13 @@ class NodeContextTestCase(unittest.TestCase):
         self.assertEqual(self.test_context._dispatch_ansible('ansible'), None)
 
     @mock.patch("{}.AnsibleCommon".format(PREFIX))
-    def test__do_ansible_job(self, mock_ansible):
+    def test__do_ansible_job(self, *args):
         self.assertEqual(None, self.test_context._do_ansible_job('dummy'))
 
-    def test_successful_init(self):
-
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SAMPLE)
-        }
-
-        self.test_context.init(attrs)
+    def test_init(self):
+        self.test_context.init(self.attrs)
 
-        self.assertEqual(self.test_context.name, "foo")
+        self.assertEqual(self.test_context.name, "foo-12345678")
         self.assertEqual(len(self.test_context.nodes), 4)
         self.assertEqual(len(self.test_context.controllers), 2)
         self.assertEqual(len(self.test_context.computes), 1)
@@ -156,81 +134,44 @@ class NodeContextTestCase(unittest.TestCase):
         self.assertEqual(len(self.test_context.baremetals), 1)
         self.assertEqual(self.test_context.baremetals[0]["name"], "node4")
 
-    def test__get_server_with_dic_attr_name(self):
-
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SAMPLE)
-        }
-
-        self.test_context.init(attrs)
-
-        attr_name = {'name': 'foo.bar'}
-        result = self.test_context._get_server(attr_name)
+    def test__get_server_with_dict_attr_name(self):
+        self.test_context.init(self.attrs)
+        result = self.test_context._get_server({'name': 'node1.foo-12345678'})
 
-        self.assertEqual(result, None)
+        self.assertIsNone(result, None)
 
     def test__get_server_not_found(self):
+        self.test_context.init(self.attrs)
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SAMPLE)
-        }
-
-        self.test_context.init(attrs)
-
-        attr_name = 'bar.foo'
-        result = self.test_context._get_server(attr_name)
-
-        self.assertEqual(result, None)
+        self.assertIsNone(self.test_context._get_server('bar.foo-12345678'))
 
     def test__get_server_mismatch(self):
+        self.test_context.init(self.attrs)
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SAMPLE)
-        }
-
-        self.test_context.init(attrs)
-
-        attr_name = 'bar.foo1'
-        result = self.test_context._get_server(attr_name)
-
-        self.assertEqual(result, None)
+        self.assertIsNone(self.test_context._get_server('bar.foo1'))
 
     def test__get_server_duplicate(self):
+        self.attrs['file'] = self._get_file_abspath(
+            self.NODES_DUPLICATE_SAMPLE)
+        self.test_context.init(self.attrs)
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
-        }
-
-        self.test_context.init(attrs)
-
-        attr_name = 'node1.foo'
         with self.assertRaises(ValueError):
-            self.test_context._get_server(attr_name)
+            self.test_context._get_server('node1.foo-12345678')
 
     def test__get_server_found(self):
+        self.test_context.init(self.attrs)
 
-        attrs = {
-            'name': 'foo',
-            'file': self._get_file_abspath(self.NODES_SAMPLE)
-        }
-
-        self.test_context.init(attrs)
-
-        attr_name = 'node1.foo'
-        result = self.test_context._get_server(attr_name)
+        result = self.test_context._get_server('node1.foo-12345678')
 
         self.assertEqual(result['ip'], '10.229.47.137')
-        self.assertEqual(result['name'], 'node1.foo')
+        self.assertEqual(result['name'], 'node1.foo-12345678')
         self.assertEqual(result['user'], 'root')
         self.assertEqual(result['key_filename'], '/root/.yardstick_key')
 
     @mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
     def test_deploy(self, dispatch_script_mock):
         obj = node.NodeContext()
+        self.addCleanup(obj._delete_context)
         obj.env = {
             'type': 'script'
         }
@@ -240,6 +181,7 @@ class NodeContextTestCase(unittest.TestCase):
     @mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
     def test_deploy_anisible(self, dispatch_ansible_mock):
         obj = node.NodeContext()
+        self.addCleanup(obj._delete_context)
         obj.env = {
             'type': 'ansible'
         }
@@ -268,6 +210,7 @@ class NodeContextTestCase(unittest.TestCase):
     @mock.patch('{}.ssh.SSH.execute'.format(PREFIX))
     def test_execute_remote_script(self, execute_mock, put_file_mock):
         obj = node.NodeContext()
+        self.addCleanup(obj._delete_context)
         obj.env = {'prefix': 'yardstick.benchmark.scenarios.compute'}
         node_name_args = 'node5'
         obj.nodes = [{
@@ -288,14 +231,18 @@ class NodeContextTestCase(unittest.TestCase):
     def test_execute_script_local(self, local_execute_mock):
         node_name = 'local'
         info = {}
-        node.NodeContext()._execute_script(node_name, info)
+        obj = node.NodeContext()
+        self.addCleanup(obj._delete_context)
+        obj._execute_script(node_name, info)
         self.assertTrue(local_execute_mock.called)
 
     @mock.patch('{}.NodeContext._execute_remote_script'.format(PREFIX))
     def test_execute_script_remote(self, remote_execute_mock):
         node_name = 'node5'
         info = {}
-        node.NodeContext()._execute_script(node_name, info)
+        obj = node.NodeContext()
+        self.addCleanup(obj._delete_context)
+        obj._execute_script(node_name, info)
         self.assertTrue(remote_execute_mock.called)
 
     def test_get_script(self):
@@ -303,13 +250,16 @@ class NodeContextTestCase(unittest.TestCase):
         info_args = {
             'script': script_args
         }
-        script, options = node.NodeContext()._get_script(info_args)
+        obj = node.NodeContext()
+        self.addCleanup(obj._delete_context)
+        script, options = obj._get_script(info_args)
         self.assertEqual(script_args, script)
         self.assertEqual('', options)
 
     def test_node_info(self):
         node_name_args = 'node5'
         obj = node.NodeContext()
+        self.addCleanup(obj._delete_context)
         obj.nodes = [{'name': node_name_args, 'check': node_name_args}]
         node_info = obj._get_node_info(node_name_args)
         self.assertEqual(node_info.get('check'), node_name_args)
@@ -318,6 +268,7 @@ class NodeContextTestCase(unittest.TestCase):
     def test_get_client(self, wait_mock):
         node_name_args = 'node5'
         obj = node.NodeContext()
+        self.addCleanup(obj._delete_context)
         obj.nodes = [{
             'name': node_name_args,
             'user': 'ubuntu',
@@ -328,26 +279,38 @@ class NodeContextTestCase(unittest.TestCase):
         self.assertTrue(wait_mock.called)
 
     def test_get_server(self):
-        self.test_context.name = 'vnf1'
-        self.test_context.nodes = [{'name': 'my', 'value': 100}]
+        self.test_context.init(self.attrs)
+        self.test_context._name = 'foo'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
+        self.assertEqual('foo-12345678', self.test_context.name)
+        self.assertIsNotNone(self.test_context._task_id)
 
-        with self.assertRaises(ValueError):
-            self.test_context.get_server('my.vnf2')
+        result = self.test_context.get_server('node1.foo-12345678')
 
-        expected = {'name': 'my.vnf1', 'value': 100, 'interfaces': {}}
-        result = self.test_context.get_server('my.vnf1')
-        self.assertDictEqual(result, expected)
+        self.assertEqual(result['ip'], '10.229.47.137')
+        self.assertEqual(result['name'], 'node1.foo-12345678')
+        self.assertEqual(result['user'], 'root')
+        self.assertEqual(result['key_filename'], '/root/.yardstick_key')
+
+    def test_get_server_server_not_in_context(self):
+        self.test_context.init(self.attrs)
+
+        with self.assertRaises(ValueError):
+            self.test_context.get_server('my2.foo-12345678')
 
     def test_get_context_from_server(self):
-        self.test_context.name = 'vnf1'
+        self.test_context._name = 'vnf1'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = '{}-{}'.format(
+            self.test_context._name, self.test_context._task_id[:8])
         self.test_context.nodes = [{'name': 'my', 'value': 100}]
         self.test_context.attrs = {'attr1': 200}
 
-        with self.assertRaises(ValueError):
-            self.test_context.get_context_from_server('my.vnf2')
-
-        result = self.test_context.get_context_from_server('my.vnf1')
-        self.assertIs(result, self.test_context)
+        self.assertIs(
+            self.test_context.get_context_from_server('my.vnf1-12345678'),
+            self.test_context)
 
     # TODO: Split this into more granular tests
     def test__get_network(self):
@@ -393,11 +356,3 @@ class NodeContextTestCase(unittest.TestCase):
         expected = network1
         result = self.test_context._get_network(attr_name)
         self.assertDictEqual(result, expected)
-
-
-def main():
-    unittest.main()
-
-
-if __name__ == '__main__':
-    main()
diff --git a/yardstick/tests/unit/orchestrator/test_heat.py b/yardstick/tests/unit/orchestrator/test_heat.py
index e0a353812..bde6647ed 100644
--- a/yardstick/tests/unit/orchestrator/test_heat.py
+++ b/yardstick/tests/unit/orchestrator/test_heat.py
@@ -160,7 +160,8 @@ class HeatTemplateTestCase(unittest.TestCase):
 
     def test__add_resources_to_template_raw(self):
         test_context = node.NodeContext()
-        test_context.name = 'foo'
+        self.addCleanup(test_context._delete_context)
+        test_context._name = 'foo'
         test_context.template_file = '/tmp/some-heat-file'
         test_context.heat_parameters = {'image': 'cirros'}
         test_context.key_filename = "/tmp/1234"
-- 
cgit 


From 1681ba53783835e500e602a1b7500e0221eb08f9 Mon Sep 17 00:00:00 2001
From: Emma Foley <emma.l.foley@intel.com>
Date: Thu, 22 Feb 2018 19:11:12 +0000
Subject: 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>
---
 yardstick/benchmark/core/task.py                 | 107 ++++++++++++---------
 yardstick/common/exceptions.py                   |   4 +
 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)
-- 
cgit 


From 4a21b4a434d5a60cb57dce576365dc6a9a6825b5 Mon Sep 17 00:00:00 2001
From: Emma Foley <emma.l.foley@intel.com>
Date: Wed, 21 Feb 2018 12:36:15 +0000
Subject: Add _create_new_stack method

The logic for creating a new stack in contexts/heat.py:HeatContext
can added to a method to make the code eassier to read and test.

This is in preparation for an update to deploy() that would allow
an existing stack to be reused, or a new stack created.
By having the create_new_stack logic in a new method, deploy()
becomes easier to read and test.

JIRA: YARDSTICK-886
Change-Id: I7af01e2209a3460658f8db0249b7c620743cced0
Signed-off-by: Emma Foley <emma.l.foley@intel.com>
---
 yardstick/benchmark/contexts/heat.py               | 22 +++++++++------
 yardstick/common/exceptions.py                     |  4 +++
 .../tests/unit/benchmark/contexts/test_heat.py     | 32 ++++++++++++++++++++++
 3 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/yardstick/benchmark/contexts/heat.py b/yardstick/benchmark/contexts/heat.py
index 1e2537738..8dd7d85e6 100644
--- a/yardstick/benchmark/contexts/heat.py
+++ b/yardstick/benchmark/contexts/heat.py
@@ -25,6 +25,7 @@ from yardstick.benchmark.contexts.model import Network
 from yardstick.benchmark.contexts.model import PlacementGroup, ServerGroup
 from yardstick.benchmark.contexts.model import Server
 from yardstick.benchmark.contexts.model import update_scheduler_hints
+from yardstick.common import exceptions as y_exc
 from yardstick.common.openstack_utils import get_neutron_client
 from yardstick.orchestrator.heat import HeatTemplate, get_short_key_uuid
 from yardstick.common import constants as consts
@@ -297,6 +298,17 @@ class HeatContext(Context):
                     network.network_type = neutron_net.get('provider:network_type')
                     network.neutron_info = neutron_net
 
+    def _create_new_stack(self, heat_template):
+         try:
+             return heat_template.create(block=True,
+                                         timeout=self.heat_timeout)
+         except KeyboardInterrupt:
+             raise y_exc.StackCreationInterrupt
+         except:
+             LOG.exception("stack failed")
+             # let the other failures happen, we want stack trace
+             raise
+
     def deploy(self):
         """deploys template into a stack using cloud"""
         LOG.info("Deploying context '%s' START", self.name)
@@ -307,15 +319,7 @@ class HeatContext(Context):
         if self.template_file is None:
             self._add_resources_to_template(heat_template)
 
-        try:
-            self.stack = heat_template.create(block=True,
-                                              timeout=self.heat_timeout)
-        except KeyboardInterrupt:
-            raise SystemExit("\nStack create interrupted")
-        except Exception:
-            LOG.exception("stack failed")
-            # let the other failures happen, we want stack trace
-            raise
+        self.stack = self._create_new_stack(heat_template)
 
         # TODO: use Neutron to get segmentation-id
         self.get_neutron_info()
diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py
index 4f89fed32..2af4c6343 100644
--- a/yardstick/common/exceptions.py
+++ b/yardstick/common/exceptions.py
@@ -74,3 +74,7 @@ class DPDKSetupDriverError(YardstickException):
 
 class ScenarioConfigContextNameNotFound(YardstickException):
     message = 'Context name "%(context_name)s" not found'
+
+
+class StackCreationInterrupt(YardstickException):
+    message = 'Stack create interrupted.'
diff --git a/yardstick/tests/unit/benchmark/contexts/test_heat.py b/yardstick/tests/unit/benchmark/contexts/test_heat.py
index baf9f40f8..2f2d4643e 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_heat.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_heat.py
@@ -21,6 +21,8 @@ import unittest
 from yardstick.benchmark.contexts import base
 from yardstick.benchmark.contexts import heat
 from yardstick.benchmark.contexts import model
+from yardstick.common import exceptions as y_exc
+from yardstick.orchestrator import heat as orch_heat
 
 
 LOG = logging.getLogger(__name__)
@@ -186,6 +188,36 @@ class HeatContextTestCase(unittest.TestCase):
         with self.assertRaises(AttributeError):
             self.test_context.user = 'foo'
 
+    def test__create_new_stack(self):
+        template = mock.Mock()
+        self.test_context._create_new_stack(template)
+        template.create.assert_called_once()
+
+    def test__create_new_stack_stack_create_failed(self):
+        template = mock.Mock()
+        template.create.side_effect = y_exc.HeatTemplateError
+
+        self.assertRaises(y_exc.HeatTemplateError,
+                          self.test_context._create_new_stack,
+                          template)
+
+    def test__create_new_stack_keyboard_interrupt(self):
+        template = mock.Mock()
+        template.create.side_effect = KeyboardInterrupt
+        self.assertRaises(y_exc.StackCreationInterrupt,
+                          self.test_context._create_new_stack,
+                          template)
+
+    @mock.patch.object(orch_heat.HeatTemplate, 'add_keypair')
+    @mock.patch.object(heat.HeatContext, '_create_new_stack')
+    def test_deploy_stack_creation_failed(self, mock_create, *args):
+        self.test_context._name = 'foo'
+        self.test_context._task_id = '1234567890'
+        self.test_context._name_task_id = 'foo-12345678'
+        mock_create.side_effect = y_exc.HeatTemplateError
+        self.assertRaises(y_exc.HeatTemplateError,
+                          self.test_context.deploy)
+
     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
     def test_deploy(self, mock_template):
         self.test_context._name = 'foo'
-- 
cgit