3 ##############################################################################
4 # Copyright (c) 2015 Ericsson AB and others.
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Apache License, Version 2.0
8 # which accompanies this distribution, and is available at
9 # http://www.apache.org/licenses/LICENSE-2.0
10 ##############################################################################
12 """ yardstick - command line tool for managing benchmarks
15 $ yardstick samples/ping-task.yaml
17 Servers are the same as VMs (Nova call them servers in the API)
19 Many tests use a client/server architecture. A test client is configured
20 to use a specific test server e.g. using an IP address. This is true for
21 example iperf. In some cases the test server is included in the kernel
22 (ping, pktgen) and no additional software is needed on the server. In other
23 cases (iperf) a server process needs to be installed and started
25 One server is required to host the test client program (such as ping or
26 iperf). In the task file this server is called host.
28 A server can be the _target_ of a test client (think ping destination
29 argument). A target server is optional but needed in most test scenarios.
30 In the task file this server is called target. This is probably the same
31 as DUT in existing terminology.
34 https://www.ietf.org/rfc/rfc1242.txt (throughput/latency)
35 https://www.ietf.org/rfc/rfc2285.txt (DUT/SUT)
47 from yardstick.benchmark.context.model import Context
48 from yardstick.benchmark.runners import base as base_runner
49 from yardstick.cmdparser import CmdParser
52 class TaskParser(object):
53 '''Parser for task config files in yaml format'''
54 def __init__(self, path):
58 '''parses the task file and return an context and scenario instances'''
59 print "Parsing task config:", self.path
61 with open(self.path) as stream:
62 cfg = yaml.load(stream)
63 except IOError as ioerror:
66 if cfg["schema"] != "yardstick:task:0.1":
67 sys.exit("error: file %s has unknown schema %s" % (self.path,
70 # TODO: support one or many contexts? Many would simpler and precise
72 context_cfgs = [cfg["context"]]
74 context_cfgs = cfg["contexts"]
76 for cfg_attrs in context_cfgs:
78 context.init(cfg_attrs)
80 run_in_parallel = cfg.get("run_in_parallel", False)
82 # TODO we need something better here, a class that represent the file
83 return cfg["scenarios"], run_in_parallel
87 '''handler for process termination'''
88 base_runner.Runner.terminate_all()
90 if len(Context.list) > 0:
91 print "Undeploying all contexts"
92 for context in Context.list:
96 def run_one_scenario(scenario_cfg, output_file):
97 '''run one scenario using context'''
98 key_filename = pkg_resources.resource_filename(
99 'yardstick.resources', 'files/yardstick_key')
101 host = Context.get_server(scenario_cfg["host"])
103 runner_cfg = scenario_cfg["runner"]
104 runner_cfg['host'] = host.public_ip
105 runner_cfg['user'] = host.context.user
106 runner_cfg['key_filename'] = key_filename
107 runner_cfg['output_filename'] = output_file
109 if "target" in scenario_cfg:
110 target = Context.get_server(scenario_cfg["target"])
112 # get public IP for target server, some scenarios require it
114 runner_cfg['target'] = target.public_ip
116 # TODO scenario_cfg["ipaddr"] is bad naming
117 if host.context != target.context:
118 # target is in another context, get its public IP
119 scenario_cfg["ipaddr"] = target.public_ip
121 # target is in the same context, get its private IP
122 scenario_cfg["ipaddr"] = target.private_ip
124 runner = base_runner.Runner.get(runner_cfg)
126 print "Starting runner of type '%s'" % runner_cfg["type"]
127 runner.run(scenario_cfg["type"], scenario_cfg)
132 def runner_join(runner):
133 '''join (wait for) a runner, exit process at runner failure'''
134 status = runner.join()
135 base_runner.Runner.release(runner)
137 sys.exit("Runner failed")
143 atexit.register(atexit_handler)
145 prog_args = CmdParser().parse_args()
147 parser = TaskParser(prog_args.taskfile[0])
148 scenarios, run_in_parallel = parser.parse()
150 if prog_args.parse_only:
153 for context in Context.list:
158 for scenario in scenarios:
159 runner = run_one_scenario(scenario, prog_args.output_file)
160 runners.append(runner)
162 # Wait for runners to finish
163 for runner in runners:
165 print "Runner ended, output in", prog_args.output_file
168 for scenario in scenarios:
169 runner = run_one_scenario(scenario, prog_args.output_file)
171 print "Runner ended, output in", prog_args.output_file
173 if prog_args.keep_deploy:
174 # keep deployment, forget about stack (hide it for exit handler)
177 for context in Context.list:
180 print "Done, exiting"
182 if __name__ == '__main__':