JIRA: BOTTLENECKS-29
[bottlenecks.git] / vstf / vstf / agent / perf / netperf.py
1 ##############################################################################
2 # Copyright (c) 2015 Huawei Technologies Co.,Ltd 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 import time
11 import subprocess
12 import vstf.common.constants as cst
13 import vstf.common.decorator as deco
14 from vstf.common import perfmark as mark
15 from vstf.common.utils import kill_by_name, my_popen
16
17 import logging
18
19 LOG = logging.getLogger(__name__)
20
21
22 class Netperf(object):
23     def __init__(self):
24         self._send_processes = []
25         self._islat = False
26         self._typemap = {
27             "tcp_lat": "TCP_STREAM",
28             "tcp_bw": "TCP_STREAM",
29             "udp_lat": "UDP_STREAM",
30             "udp_bw": "UDP_STREAM",
31         }
32
33     @deco.check("protocol", choices=cst.PROTOCOLS)
34     @deco.check("namespace", defaults=None)
35     @deco.check("dst")
36     @deco.check("time", defaults=0)
37     @deco.check("size", defaults=64)
38     @deco.check("threads", defaults=1)
39     def send_start(self, **kwargs):
40         threads = kwargs.pop('threads')
41         kwargs['buf'] = cst.SOCKET_BUF
42         if kwargs['protocol'] in ['tcp_lat', 'udp_lat']:
43             self._islat = True
44         else:
45             kwargs['time'] = 0
46
47         cmd = self.format_send_start(**kwargs)
48         LOG.info("cmd:%s", cmd)
49
50         for _ in range(threads):
51             process = my_popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
52             self._send_processes.append(process)
53         time.sleep(0.5)
54         for process in self._send_processes:
55             ret = process.poll()
56             if ret is None:
57                 ret = 0
58                 error_str = "start netperf send success"
59             else:
60                 error_str = "start netperf send failed, %s" % (str(kwargs))
61                 process.wait()
62                 self._send_processes.remove(process)
63
64         return ret, error_str
65
66     def send_stop(self, **kwargs):
67         LOG.info("send_stop")
68         results = []
69         ret = 0
70         for process in self._send_processes:
71             poll = process.poll()
72             if poll is None:
73                 if not self._islat:
74                     process.kill()
75                     read = "process is stopped by killed"
76                 else:
77                     ret = process.wait()
78                     read = process.stdout.read()
79                     read = self._parse_data(read)
80                 results.append((ret, read))
81         self._send_processes = []
82         self._islat = False
83         return results
84
85     @staticmethod
86     def _parse_data(data):
87         buf = data.splitlines()
88         data = buf[2].strip().split(',')
89         result = {
90             mark.minLatency: float(data[0]),
91             mark.avgLatency: float(data[1]),
92             mark.maxLatency: float(data[2])
93         }
94         return result
95
96     @deco.namespace()
97     def format_send_start(self, **kwargs):
98         #       cmd = "netperf -H %(dst_ip)s -t %(type)s -l %(time)s -- -m %(pkt_size)s "
99         cmd = "netperf -H %(dst_ip)s -t %(type)s -l %(time)s  " \
100               "-- -m %(pkt_size)s -s %(buf)s -S %(buf)s -o  MIN_LATENCY,MEAN_LATENCY,MAX_LATENCY"
101         context = {
102             'dst_ip': kwargs['dst'][0]['ip'],
103             'type': self._typemap[kwargs['protocol']],
104             'time': kwargs['time'],
105             'pkt_size': kwargs['size'],
106             'buf': kwargs['buf'],
107         }
108         cmd = cmd % context
109         return cmd
110
111     @deco.namespace()
112     def format_receive_start(self, **kwargs):
113         cmd = 'netserver'
114         return cmd
115
116     @deco.check("namespace")
117     def receive_start(self, **kwargs):
118
119         cmd = self.format_receive_start(**kwargs)
120         LOG.info("cmd:%s", cmd)
121
122         process = my_popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
123         time.sleep(0.5)
124         ret = process.poll()
125         if ret:
126             error_str = "start netserver failed, %s" % (str(kwargs))
127         else:
128             ret = 0
129             error_str = "start netserver success"
130
131         return ret, error_str
132
133     def receive_stop(self, **kwargs):
134         LOG.info("receive_stop")
135         ret = 0
136         kill_by_name('netserver')
137         time.sleep(0.5)
138         error_str = "stop netserver success"
139         return ret, error_str
140
141     def clean(self):
142         self.send_stop()
143         self.receive_stop()
144         return True
145
146     def force_clean(self):
147         LOG.info("%s %s start", self.__class__, self.force_clean.__name__)
148         kill_by_name('netserver')
149         kill_by_name('netperf')
150         self._send_processes = []
151         self._receive_processes = []
152         return True
153
154
155 def unit_test():
156     perf = Netperf()
157     ret = perf.receive_start(namespace='receive')
158     print "*********receive_start***********"
159     print ret
160     send = {
161         "namespace": "send",
162         "protocol": "udp_lat",
163         "dst": [
164             {"ip": "192.168.1.102"}
165         ],
166         "size": 64,
167         "threads": 1,
168         "time": 10,
169     }
170     print perf.send_start(**send)
171     print perf._send_processes
172     time.sleep(10)
173     print perf.send_stop()
174     print perf.receive_stop()
175
176
177 if __name__ == "__main__":
178     from vstf.common.log import setup_logging
179
180     setup_logging(level=logging.DEBUG, log_file="/var/log/vstf/vstf-netperf.log", clevel=logging.DEBUG)
181     unit_test()