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