Fix iperf3 target ipaddr and no options
[yardstick.git] / yardstick / benchmark / scenarios / networking / iperf3.py
1 ##############################################################################
2 # Copyright (c) 2015 Ericsson AB and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 # iperf3 scenario
11 # iperf3 homepage at: http://software.es.net/iperf/
12
13 import logging
14 import json
15 import pkg_resources
16
17 import yardstick.ssh as ssh
18 from yardstick.benchmark.scenarios import base
19
20 LOG = logging.getLogger(__name__)
21 LOG.setLevel(logging.DEBUG)
22
23
24 class Iperf(base.Scenario):
25     """Execute iperf3 between two hosts
26
27 By default TCP is used but UDP can also be configured.
28 For more info see http://software.es.net/iperf
29
30   Parameters
31     bytes - number of bytes to transmit
32       only valid with a non duration runner, mutually exclusive with blockcount
33         type:    int
34         unit:    bytes
35         default: 56
36     udp - use UDP rather than TCP
37         type:    bool
38         unit:    na
39         default: false
40     nodelay - set TCP no delay, disabling Nagle's Algorithm
41         type:    bool
42         unit:    na
43         default: false
44     blockcount - number of blocks (packets) to transmit,
45       only valid with a non duration runner, mutually exclusive with bytes
46         type:    int
47         unit:    bytes
48         default: -
49     """
50     __scenario_type__ = "Iperf3"
51
52     def __init__(self, context):
53         self.context = context
54         self.user = context.get('user', 'ubuntu')
55         self.host_ipaddr = context['host']
56         self.target_ipaddr = context['target']
57         self.key_filename = self.context.get('key_filename', '~/.ssh/id_rsa')
58         self.setup_done = False
59
60     def setup(self):
61         LOG.debug("setup, key %s", self.key_filename)
62         LOG.debug("host:%s, user:%s", self.host_ipaddr, self.user)
63         self.host = ssh.SSH(self.user, self.host_ipaddr,
64                             key_filename=self.key_filename)
65         self.host.wait(timeout=600)
66
67         LOG.debug("target:%s, user:%s", self.target_ipaddr, self.user)
68         self.target = ssh.SSH(self.user, self.target_ipaddr,
69                               key_filename=self.key_filename)
70         self.target.wait(timeout=600)
71
72         cmd = "iperf3 -s -D"
73         LOG.debug("Starting iperf3 server with command: %s", cmd)
74         status, _, stderr = self.target.execute(cmd)
75         if status:
76             raise RuntimeError(stderr)
77
78     def teardown(self):
79         LOG.debug("teardown")
80         self.host.close()
81         status, stdout, stderr = self.target.execute("pkill iperf3")
82         if status:
83             LOG.warn(stderr)
84         self.target.close()
85
86     def run(self, args):
87         """execute the benchmark"""
88
89         # if run by a duration runner, get the duration time and setup as arg
90         time = self.context.get('duration', None)
91         options = args['options']
92
93         cmd = "iperf3 -c %s --json" % (self.target_ipaddr)
94
95         # If there are no options specified
96         if not options:
97             options = ""
98
99         if "udp" in options:
100             cmd += " --udp"
101         else:
102             # tcp obviously
103             if "nodelay" in options:
104                 cmd += " --nodelay"
105
106         # these options are mutually exclusive in iperf3
107         if time:
108             cmd += " %d" % time
109         elif "bytes" in options:
110             # number of bytes to transmit (instead of --time)
111             cmd += " --bytes %d" % options["bytes"]
112         elif "blockcount" in options:
113             cmd += " --blockcount %d" % options["blockcount"]
114
115         LOG.debug("Executing command: %s", cmd)
116
117         status, stdout, stderr = self.host.execute(cmd)
118         if status:
119             # error cause in json dict on stdout
120             raise RuntimeError(stdout)
121
122         output = json.loads(stdout)
123
124         # convert bits per second to bytes per second
125         bytes_per_second = \
126             int((output["end"]["sum_received"]["bits_per_second"])) / 8
127
128         if "sla" in args:
129             sla_bytes_per_second = int(args["sla"]["bytes_per_second"])
130             assert bytes_per_second >= sla_bytes_per_second, \
131                 "bytes_per_second %d < sla (%d)" % \
132                 (bytes_per_second, sla_bytes_per_second)
133
134         return output
135
136
137 def _test():
138     '''internal test function'''
139
140     logger = logging.getLogger('yardstick')
141     logger.setLevel(logging.DEBUG)
142
143     key_filename = pkg_resources.resource_filename('yardstick.resources',
144                                                    'files/yardstick_key')
145     runner_cfg = {}
146     runner_cfg['type'] = 'Duration'
147     runner_cfg['duration'] = 5
148     runner_cfg['host'] = '10.0.2.33'
149     runner_cfg['target_ipaddr'] = '10.0.2.53'
150     runner_cfg['user'] = 'ubuntu'
151     runner_cfg['output_filename'] = "/tmp/yardstick.out"
152     runner_cfg['key_filename'] = key_filename
153
154     scenario_args = {}
155     scenario_args['options'] = {"bytes": 10000000000}
156     scenario_args['sla'] = \
157         {"bytes_per_second": 2900000000, "action": "monitor"}
158
159     from yardstick.benchmark.runners import base as base_runner
160     runner = base_runner.Runner.get(runner_cfg)
161     runner.run("Iperf3", scenario_args)
162     runner.join()
163     base_runner.Runner.release(runner)
164
165 if __name__ == '__main__':
166     _test()