Merge "standardize ssh auth"
[yardstick.git] / yardstick / benchmark / scenarios / networking / pktgen.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 from __future__ import absolute_import
10 from __future__ import print_function
11
12 import logging
13
14 import pkg_resources
15 from oslo_serialization import jsonutils
16
17 import yardstick.ssh as ssh
18 from yardstick.benchmark.scenarios import base
19
20 LOG = logging.getLogger(__name__)
21
22
23 class Pktgen(base.Scenario):
24     """Execute pktgen between two hosts
25
26   Parameters
27     packetsize - packet size in bytes without the CRC
28         type:    int
29         unit:    bytes
30         default: 60
31     number_of_ports - number of UDP ports to test
32         type:    int
33         unit:    na
34         default: 10
35     duration - duration of the test
36         type:    int
37         unit:    seconds
38         default: 20
39     """
40     __scenario_type__ = "Pktgen"
41
42     TARGET_SCRIPT = 'pktgen_benchmark.bash'
43
44     def __init__(self, scenario_cfg, context_cfg):
45         self.scenario_cfg = scenario_cfg
46         self.context_cfg = context_cfg
47         self.setup_done = False
48
49     def setup(self):
50         """scenario setup"""
51         self.target_script = pkg_resources.resource_filename(
52             'yardstick.benchmark.scenarios.networking',
53             Pktgen.TARGET_SCRIPT)
54         host = self.context_cfg['host']
55         target = self.context_cfg['target']
56
57         LOG.info("user:%s, target:%s", target['user'], target['ip'])
58         self.server = ssh.SSH.from_node(target, defaults={"user": "ubuntu"})
59         self.server.wait(timeout=600)
60
61         LOG.info("user:%s, host:%s", host['user'], host['ip'])
62         self.client = ssh.SSH.from_node(host, defaults={"user": "ubuntu"})
63         self.client.wait(timeout=600)
64
65         # copy script to host
66         self.client._put_file_shell(self.target_script, '~/pktgen.sh')
67
68         self.setup_done = True
69
70     def _iptables_setup(self):
71         """Setup iptables on server to monitor for received packets"""
72         cmd = "sudo iptables -F; " \
73               "sudo iptables -A INPUT -p udp --dport 1000:%s -j DROP" \
74               % (1000 + self.number_of_ports)
75         LOG.debug("Executing command: %s", cmd)
76         status, _, stderr = self.server.execute(cmd)
77         if status:
78             raise RuntimeError(stderr)
79
80     def _iptables_get_result(self):
81         """Get packet statistics from server"""
82         cmd = "sudo iptables -L INPUT -vnx |" \
83               "awk '/dpts:1000:%s/ {{printf \"%%s\", $1}}'" \
84               % (1000 + self.number_of_ports)
85         LOG.debug("Executing command: %s", cmd)
86         status, stdout, stderr = self.server.execute(cmd)
87         if status:
88             raise RuntimeError(stderr)
89         return int(stdout)
90
91     def run(self, result):
92         """execute the benchmark"""
93
94         if not self.setup_done:
95             self.setup()
96
97         ipaddr = self.context_cfg["target"].get("ipaddr", '127.0.0.1')
98
99         options = self.scenario_cfg['options']
100         packetsize = options.get("packetsize", 60)
101         self.number_of_ports = options.get("number_of_ports", 10)
102         # if run by a duration runner
103         duration_time = self.scenario_cfg["runner"].get("duration", None) \
104             if "runner" in self.scenario_cfg else None
105         # if run by an arithmetic runner
106         arithmetic_time = options.get("duration", None)
107
108         if duration_time:
109             duration = duration_time
110         elif arithmetic_time:
111             duration = arithmetic_time
112         else:
113             duration = 20
114
115         self._iptables_setup()
116
117         cmd = "sudo bash pktgen.sh %s %s %s %s" \
118             % (ipaddr, self.number_of_ports, packetsize, duration)
119         LOG.debug("Executing command: %s", cmd)
120         status, stdout, stderr = self.client.execute(cmd)
121
122         if status:
123             raise RuntimeError(stderr)
124
125         result.update(jsonutils.loads(stdout))
126
127         result['packets_received'] = self._iptables_get_result()
128         result['packetsize'] = packetsize
129
130         if "sla" in self.scenario_cfg:
131             sent = result['packets_sent']
132             received = result['packets_received']
133             ppm = 1000000 * (sent - received) / sent
134             sla_max_ppm = int(self.scenario_cfg["sla"]["max_ppm"])
135             assert ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d; " \
136                 % (ppm, sla_max_ppm)
137
138
139 def _test():
140     """internal test function"""
141     key_filename = pkg_resources.resource_filename('yardstick.resources',
142                                                    'files/yardstick_key')
143     ctx = {
144         'host': {
145             'ip': '10.229.47.137',
146             'user': 'root',
147             'key_filename': key_filename
148         },
149         'target': {
150             'ip': '10.229.47.137',
151             'user': 'root',
152             'key_filename': key_filename,
153             'ipaddr': '10.229.47.137',
154         }
155     }
156
157     logger = logging.getLogger('yardstick')
158     logger.setLevel(logging.DEBUG)
159
160     options = {'packetsize': 120}
161     args = {'options': options}
162     result = {}
163
164     p = Pktgen(args, ctx)
165     p.run(result)
166     print(result)
167
168
169 if __name__ == '__main__':
170     _test()