Use """ to replace ''' in docstring
[yardstick.git] / yardstick / benchmark / core / task.py
index 397ba00..d05117b 100644 (file)
@@ -9,6 +9,8 @@
 
 """ Handler for yardstick command 'task' """
 
+from __future__ import absolute_import
+from __future__ import print_function
 import sys
 import os
 import yaml
@@ -18,7 +20,7 @@ import time
 import logging
 import uuid
 import errno
-from itertools import ifilter
+from six.moves import filter
 
 from yardstick.benchmark.contexts.base import Context
 from yardstick.benchmark.runners import base as base_runner
@@ -32,13 +34,13 @@ LOG = logging.getLogger(__name__)
 
 
 class Task(object):     # pragma: no cover
-    '''Task commands.
+    """Task commands.
 
        Set of commands to manage benchmark tasks.
-    '''
+    """
 
     def start(self, args, **kwargs):
-        '''Start a benchmark scenario.'''
+        """Start a benchmark scenario."""
 
         atexit.register(atexit_handler)
 
@@ -71,7 +73,7 @@ class Task(object):     # pragma: no cover
             one_task_start_time = time.time()
             parser.path = task_files[i]
             scenarios, run_in_parallel, meet_precondition = parser.parse_task(
-                 self.task_id, task_args[i], task_args_fnames[i])
+                self.task_id, task_args[i], task_args_fnames[i])
 
             if not meet_precondition:
                 LOG.info("meet_precondition is %s, please check envrionment",
@@ -96,17 +98,17 @@ class Task(object):     # pragma: no cover
         LOG.info("total finished in %d secs",
                  total_end_time - total_start_time)
 
-        print "Done, exiting"
+        print("Done, exiting")
 
     def _run(self, scenarios, run_in_parallel, output_file):
-        '''Deploys context and calls runners'''
+        """Deploys context and calls runners"""
         for context in Context.list:
             context.deploy()
 
         background_runners = []
 
         # Start all background scenarios
-        for scenario in ifilter(_is_background_scenario, scenarios):
+        for scenario in filter(_is_background_scenario, scenarios):
             scenario["runner"] = dict(type="Duration", duration=1000000000)
             runner = run_one_scenario(scenario, output_file)
             background_runners.append(runner)
@@ -121,14 +123,14 @@ class Task(object):     # pragma: no cover
             # Wait for runners to finish
             for runner in runners:
                 runner_join(runner)
-                print "Runner ended, output in", output_file
+                print("Runner ended, output in", output_file)
         else:
             # run serially
             for scenario in scenarios:
                 if not _is_background_scenario(scenario):
                     runner = run_one_scenario(scenario, output_file)
                     runner_join(runner)
-                    print "Runner ended, output in", output_file
+                    print("Runner ended, output in", output_file)
 
         # Abort background runners
         for runner in background_runners:
@@ -142,14 +144,15 @@ class Task(object):     # pragma: no cover
                 runner_join(runner)
             else:
                 base_runner.Runner.release(runner)
-            print "Background task ended"
+            print("Background task ended")
 
 
 # TODO: Move stuff below into TaskCommands class !?
 
 
 class TaskParser(object):       # pragma: no cover
-    '''Parser for task config files in yaml format'''
+    """Parser for task config files in yaml format"""
+
     def __init__(self, path):
         self.path = path
 
@@ -178,8 +181,8 @@ class TaskParser(object):       # pragma: no cover
         return task_args, task_args_fnames
 
     def parse_suite(self):
-        '''parse the suite file and return a list of task config file paths
-           and lists of optional parameters if present'''
+        """parse the suite file and return a list of task config file paths
+           and lists of optional parameters if present"""
         LOG.info("\nParsing suite file:%s", self.path)
 
         try:
@@ -223,8 +226,8 @@ class TaskParser(object):       # pragma: no cover
         return valid_task_files, valid_task_args, valid_task_args_fnames
 
     def parse_task(self, task_id, task_args=None, task_args_file=None):
-        '''parses the task file and return an context and scenario instances'''
-        print "Parsing task config:", self.path
+        """parses the task file and return an context and scenario instances"""
+        print("Parsing task config:", self.path)
 
         try:
             kw = {}
@@ -241,10 +244,10 @@ class TaskParser(object):       # pragma: no cover
                     input_task = f.read()
                     rendered_task = TaskTemplate.render(input_task, **kw)
                 except Exception as e:
-                    print(("Failed to render template:\n%(task)s\n%(err)s\n")
+                    print("Failed to render template:\n%(task)s\n%(err)s\n"
                           % {"task": input_task, "err": e})
                     raise e
-                print(("Input task is:\n%s\n") % rendered_task)
+                print("Input task is:\n%s\n" % rendered_task)
 
                 cfg = yaml.load(rendered_task)
         except IOError as ioerror:
@@ -262,7 +265,9 @@ class TaskParser(object):       # pragma: no cover
         else:
             context_cfgs = [{"type": "Dummy"}]
 
+        name_suffix = '-{}'.format(task_id[:8])
         for cfg_attrs in context_cfgs:
+            cfg_attrs['name'] = '{}{}'.format(cfg_attrs['name'], name_suffix)
             context_type = cfg_attrs.get("type", "Heat")
             if "Heat" == context_type and "networks" in cfg_attrs:
                 # bugfix: if there are more than one network,
@@ -270,7 +275,7 @@ class TaskParser(object):       # pragma: no cover
                 # the name of netwrok should follow this rule:
                 # test, test2, test3 ...
                 # sort network with the length of network's name
-                sorted_networks = sorted(cfg_attrs["networks"].keys())
+                sorted_networks = sorted(cfg_attrs["networks"])
                 # config external_network based on env var
                 cfg_attrs["networks"][sorted_networks[0]]["external_network"] \
                     = os.environ.get("EXTERNAL_NETWORK", "net04_ext")
@@ -286,18 +291,25 @@ class TaskParser(object):       # pragma: no cover
             scenario["tc"] = task_name
             scenario["task_id"] = task_id
 
+            change_server_name(scenario, name_suffix)
+
+            try:
+                change_server_name(scenario['nodes'], name_suffix)
+            except KeyError:
+                pass
+
         # TODO we need something better here, a class that represent the file
         return cfg["scenarios"], run_in_parallel, meet_precondition
 
     def _check_schema(self, cfg_schema, schema_type):
-        '''Check if config file is using the correct schema type'''
+        """Check if config file is using the correct schema type"""
 
         if cfg_schema != "yardstick:" + schema_type + ":0.1":
             sys.exit("error: file %s has unknown schema %s" % (self.path,
                                                                cfg_schema))
 
     def _check_precondition(self, cfg):
-        '''Check if the envrionment meet the preconditon'''
+        """Check if the envrionment meet the preconditon"""
 
         if "precondition" in cfg:
             precondition = cfg["precondition"]
@@ -330,31 +342,31 @@ class TaskParser(object):       # pragma: no cover
 
 
 def atexit_handler():
-    '''handler for process termination'''
+    """handler for process termination"""
     base_runner.Runner.terminate_all()
 
     if len(Context.list) > 0:
-        print "Undeploying all contexts"
+        print("Undeploying all contexts")
         for context in Context.list:
             context.undeploy()
 
 
 def is_ip_addr(addr):
-    '''check if string addr is an IP address'''
+    """check if string addr is an IP address"""
     try:
-        ipaddress.ip_address(unicode(addr))
+        ipaddress.ip_address(addr.encode('utf-8'))
         return True
     except ValueError:
         return False
 
 
 def _is_same_heat_context(host_attr, target_attr):
-    '''check if two servers are in the same heat context
+    """check if two servers are in the same heat context
     host_attr: either a name for a server created by yardstick or a dict
     with attribute name mapping when using external heat templates
     target_attr: either a name for a server created by yardstick or a dict
     with attribute name mapping when using external heat templates
-    '''
+    """
     host = None
     target = None
     for context in Context.list:
@@ -384,7 +396,7 @@ def _is_background_scenario(scenario):
 
 
 def run_one_scenario(scenario_cfg, output_file):
-    '''run one scenario using context'''
+    """run one scenario using context"""
     runner_cfg = scenario_cfg["runner"]
     runner_cfg['output_filename'] = output_file
 
@@ -425,14 +437,14 @@ def run_one_scenario(scenario_cfg, output_file):
         context_cfg["nodes"] = parse_nodes_with_context(scenario_cfg)
     runner = base_runner.Runner.get(runner_cfg)
 
-    print "Starting runner of type '%s'" % runner_cfg["type"]
+    print("Starting runner of type '%s'" % runner_cfg["type"])
     runner.run(scenario_cfg, context_cfg)
 
     return runner
 
 
 def parse_nodes_with_context(scenario_cfg):
-    '''paras the 'nodes' fields in scenario '''
+    """paras the 'nodes' fields in scenario """
     nodes = scenario_cfg["nodes"]
 
     nodes_cfg = {}
@@ -443,7 +455,7 @@ def parse_nodes_with_context(scenario_cfg):
 
 
 def runner_join(runner):
-    '''join (wait for) a runner, exit process at runner failure'''
+    """join (wait for) a runner, exit process at runner failure"""
     status = runner.join()
     base_runner.Runner.release(runner)
     if status != 0:
@@ -451,7 +463,7 @@ def runner_join(runner):
 
 
 def print_invalid_header(source_name, args):
-    print(("Invalid %(source)s passed:\n\n %(args)s\n")
+    print("Invalid %(source)s passed:\n\n %(args)s\n"
           % {"source": source_name, "args": args})
 
 
@@ -461,13 +473,13 @@ def parse_task_args(src_name, args):
         kw = {} if kw is None else kw
     except yaml.parser.ParserError as e:
         print_invalid_header(src_name, args)
-        print(("%(source)s has to be YAML. Details:\n\n%(err)s\n")
+        print("%(source)s has to be YAML. Details:\n\n%(err)s\n"
               % {"source": src_name, "err": e})
         raise TypeError()
 
     if not isinstance(kw, dict):
         print_invalid_header(src_name, args)
-        print(("%(src)s had to be dict, actually %(src_type)s\n")
+        print("%(src)s had to be dict, actually %(src_type)s\n"
               % {"src": src_name, "src_type": type(kw)})
         raise TypeError()
     return kw
@@ -482,3 +494,21 @@ def check_environment():
             if e.errno != errno.EEXIST:
                 raise
             LOG.debug('OPENRC file not found')
+
+
+def change_server_name(scenario, suffix):
+    try:
+        scenario['host'] += suffix
+    except KeyError:
+        pass
+
+    try:
+        scenario['target'] += suffix
+    except KeyError:
+        pass
+
+    try:
+        key = 'targets'
+        scenario[key] = ['{}{}'.format(a, suffix) for a in scenario[key]]
+    except KeyError:
+        pass