applied the except and raise fixers to the master branch to close the gap with py3
[nepi.git] / src / nepi / resources / linux / udptest.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
5 #    This program is free software: you can redistribute it and/or modify
6 #    it under the terms of the GNU General Public License version 2 as
7 #    published by the Free Software Foundation;
8 #
9 #    This program is distributed in the hope that it will be useful,
10 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #    GNU General Public License for more details.
13 #
14 #    You should have received a copy of the GNU General Public License
15 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 #
17 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
18
19 from nepi.execution.attribute import Attribute, Flags, Types
20 from nepi.execution.resource import clsinit_copy, ResourceState
21 from nepi.resources.linux.application import LinuxApplication
22 from nepi.util.timefuncs import tnow
23
24 import os
25
26 @clsinit_copy
27 class LinuxUdpTest(LinuxApplication):
28     """ Uses the hpcbench udptest tool to gather UDP measurements.
29     Measurements require two ends, a server and a client RM.
30
31     http://hpcbench.sourceforge.net/
32     """
33     _rtype = "linux::UdpTest"
34
35     @classmethod
36     def _register_attributes(cls):
37         s = Attribute("s",
38             "Runs in server mode. ",
39             type = Types.Bool,
40             default = False,
41             flags = Flags.Design)
42
43         p = Attribute("p",
44             "Port to listen to in server mode, or to connect to in client mode. "
45             "Defaults to 5678. ",
46             type = Types.Integer,
47             flags = Flags.Design)
48
49         a = Attribute("a",
50             "Client option. Perform UDP Round Trip Time (latency) ",
51             type = Types.Bool,
52             flags = Flags.Design)
53
54         A = Attribute("A",
55             "Client option. "
56             "Message size for UDP RTT test. "
57             "UDP RTT (latency) test with specified message size.",
58             type = Types.Integer,
59             flags = Flags.Design)
60
61         b = Attribute("b",
62             "Client option. "
63             "Client UDP buffer size in bytes. Using system default "
64             "value if not defined.",
65             type = Types.Integer,
66             flags = Flags.Design)
67
68         B = Attribute("B",
69             "Client option. "
70             "Server UDP buffer size in bytes. The same as cleint's by default.",
71             type = Types.Integer,
72             flags = Flags.Design)
73
74         c = Attribute("c",
75             "Client option. "
76             "CPU log option. Tracing system info during the test. "
77             "Only available when output is defined. ",
78             type = Types.Bool,
79             flags = Flags.Design)
80
81         d = Attribute("d",
82             "Client option. "
83             "Data size of each read/write in bytes. The same as packet size "
84             "by default.",
85             type = Types.Integer,
86             flags = Flags.Design)
87
88         e = Attribute("e",
89             "Client option. "
90             "Exponential test (data size of each sending increasing from 1 "
91             "byte to packet size). ",
92             type = Types.Bool,
93             flags = Flags.Design)
94
95         g = Attribute("g",
96             "Client option. "
97             "UDP traffic generator (Keep sending data to a host). "
98             "Work without server's support.",
99             type = Types.Bool,
100             flags = Flags.Design)
101
102         target = Attribute("target",
103             "Client option. "
104             "Hostname or IP address of UDP server. Must be specified.",
105             flags = Flags.Design)
106
107         i = Attribute("i",
108             "Client option. "
109             "Bidirectional UDP throuhgput test. Default is unidirection "
110             "stream test. ",
111             type = Types.Bool,
112             flags = Flags.Design)
113
114         l = Attribute("l",
115             "Client option. "
116             "UDP datagram (packet) size in bytes ( < udp-buffer-szie ). "
117             "1460 by default.",
118             type = Types.Integer,
119             flags = Flags.Design)
120
121         m = Attribute("m",
122             "Client option. "
123             "Total message size in bytes. 1048576 by default.",
124             type = Types.Integer,
125             flags = Flags.Design)
126
127         o = Attribute("o",
128             "Client option. "
129             "Output file name. ",
130             flags = Flags.Design)
131
132         P = Attribute("P",
133             "Client option. "
134             "Write the plot file for gnuplot. Only enable when the output "
135             "is specified. ",
136             type = Types.Bool,
137             flags = Flags.Design)
138
139         q = Attribute("q",
140             "Client option. "
141             "Define the TOS field of IP packets. "
142             "Six values can be used for this setting:\n"
143             " 1:(IPTOS)-Minimize delay\n"
144             " 2:(IPTOS)-Maximize throughput\n"
145             " 3:(DiffServ)-Class1 with low drop probability\n"
146             " 4:(DiffServ)-class1 with high drop probability\n"
147             " 5:(DiffServ)-Class4 with low drop probabiltiy\n"
148             " 6:(DiffServ)-Class4 with high drop probabiltiy\n"
149             "Write the plot file for gnuplot. Only enable when the output "
150             "is specified. ",
151             type = Types.Enumerate,
152             allowed = ["1", "2", "3", "4", "5", "6"],
153             flags = Flags.Design)
154
155         r = Attribute("r",
156             "Client option. "
157             "Repetition of tests. 10 by default. ",
158             type = Types.Integer,
159             flags = Flags.Design)
160
161         t = Attribute("t",
162             "Client option. "
163             "Test time constraint in seconds. 5 by default. ",
164             type = Types.Integer,
165             flags = Flags.Design)
166
167         T = Attribute("T",
168             "Client option. "
169             "Throughput constraint for UDP generator or throughput "
170             "test. Unlimited by default. ",
171             type = Types.Integer,
172             flags = Flags.Design)
173
174         continuous = Attribute("continuous",
175             "Run nping in a while loop",
176             type = Types.Bool,
177             default = False,
178             flags = Flags.Design)
179
180         print_timestamp = Attribute("printTimestamp",
181             "Print timestamp before running nping",
182             type = Types.Bool,
183             default = False,
184             flags = Flags.Design)
185
186         cls._register_attribute(s)
187         cls._register_attribute(p)
188         cls._register_attribute(a)
189         cls._register_attribute(A)
190         cls._register_attribute(b)
191         cls._register_attribute(B)
192         cls._register_attribute(c)
193         cls._register_attribute(d)
194         cls._register_attribute(e)
195         cls._register_attribute(g)
196         cls._register_attribute(target)
197         cls._register_attribute(g)
198         cls._register_attribute(i)
199         cls._register_attribute(l)
200         cls._register_attribute(m)
201         cls._register_attribute(o)
202         cls._register_attribute(P)
203         cls._register_attribute(q)
204         cls._register_attribute(r)
205         cls._register_attribute(t)
206         cls._register_attribute(T)
207         cls._register_attribute(continuous)
208         cls._register_attribute(print_timestamp)
209
210     def __init__(self, ec, guid):
211         super(LinuxUdpTest, self).__init__(ec, guid)
212         self._home = "udptest-%s" % self.guid
213
214     def do_deploy(self):
215         if not self.get("command"):
216             self.set("command", self._start_command)
217
218         if not self.get("sources"):
219             self.set("sources", self._sources)
220
221         if not self.get("install"):
222             self.set("install", self._install)
223
224         if not self.get("build"):
225             self.set("build", self._build)
226
227         if not self.get("env"):
228             self.set("env", self._environment)
229
230         if not self.get("depends"):
231             self.set("depends", self._depends)
232
233         super(LinuxUdpTest, self).do_deploy()
234
235     def upload_start_command(self):
236         super(LinuxUdpTest, self).upload_start_command()
237
238         if self.get("s") == True:
239             # We want to make sure the server is running
240             # before the client starts.
241             # Run the command as a bash script in background,
242             # in the host ( but wait until the command has
243             # finished to continue )
244             self._run_in_background()
245     
246     def do_start(self):
247         if self.get("s") == True:
248             # Server is already running
249             if self.state == ResourceState.READY:
250                 command = self.get("command")
251                 self.info("Starting command '%s'" % command)
252
253                 self.set_started()
254             else:
255                 msg = " Failed to execute command '%s'" % command
256                 self.error(msg, out, err)
257                 raise RuntimeError(err)
258         else:
259             super(LinuxUdpTest, self).do_start()
260  
261     @property
262     def _start_command(self):
263         args = []
264         if self.get("continuous") == True:
265             args.append("while true; do ")
266
267         if self.get("printTimestamp") == True:
268             args.append("""echo "`date +'%Y%m%d%H%M%S'`";""")
269
270         if self.get("s") == True:
271             args.append("udpserver")
272         else:
273             args.append("udptest")
274
275         if self.get("p"):
276             args.append("-p %d" % self.get("p"))
277         if self.get("a") == True:
278             args.append("-a")
279         if self.get("A"):
280             args.append("-A %d" % self.get("A"))
281         if self.get("b"):
282             args.append("-b %d" % self.get("b"))
283         if self.get("B"):
284             args.append("-B %d" % self.get("B"))
285         if self.get("c") == True:
286             args.append("-c")
287         if self.get("d"):
288             args.append("-d %d" % self.get("d"))
289         if self.get("e") == True:
290             args.append("-e")
291         if self.get("g") == True:
292             args.append("-g")
293         if self.get("target"):
294             args.append("-h %s" % self.get("target"))
295         if self.get("i") == True:
296             args.append("-i")
297         if self.get("l"):
298             args.append("-l %d" % self.get("l"))
299         if self.get("m"):
300             args.append("-m %d" % self.get("m"))
301         if self.get("o"):
302             args.append("-o %d" % self.get("o"))
303         if self.get("P"):
304             args.append("-P %d" % self.get("P"))
305         if self.get("q"):
306             args.append("-q %s" % self.get("q"))
307         if self.get("r"):
308             args.append("-r %d" % self.get("r"))
309         if self.get("t"):
310             args.append("-t %d" % self.get("t"))
311         if self.get("T"):
312             args.append("-T %d" % self.get("T"))
313
314         if self.get("continuous") == True:
315             args.append("; done ")
316
317         command = " ".join(args)
318
319         return command
320
321     @property
322     def _sources(self):
323         return "http://hpcbench.sourceforge.net/udp.tar.gz"
324
325     @property
326     def _depends(self):
327         return "gcc make"
328
329     @property
330     def _build(self):
331         sources = self.get("sources").split(" ")[0]
332         sources = os.path.basename(sources)
333
334         return (
335             # Evaluate if ccnx binaries are already installed
336             " ( "
337                 " test -f ${BIN}/udptest && "
338                 " echo 'binaries found, nothing to do' "
339             " ) || ( "
340             # If not, untar and build
341                 " ( "
342                     " mkdir -p ${SRC}/udptest && "
343                     " tar xf ${SRC}/%(sources)s --strip-components=1 -C ${SRC}/udptest "
344                  " ) && "
345                     "cd ${SRC}/udptest && "
346                     # Just execute and silence warnings...
347                     " ( make ) "
348              " )") % ({ 'sources': sources,
349                  })
350
351     @property
352     def _install(self):
353         return (
354             # Evaluate if ccnx binaries are already installed
355             " ( "
356                 " test -f ${BIN}/udptest && "
357                 " echo 'binaries found, nothing to do' "
358             " ) || ( "
359             # If not, install
360                 "  mv ${SRC}/udptest ${BIN} "
361             " )")
362
363     @property
364     def _environment(self):
365         return "PATH=$PATH:${BIN}/udptest"
366
367     def valid_connection(self, guid):
368         # TODO: Validate!
369         return True
370