Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: client/tests/kvm/scripts/virtio_guest.py

Issue 3554003: Merge remote branch 'cros/upstream' into tempbranch3 (Closed) Base URL: http://git.chromium.org/git/autotest.git
Patch Set: Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « client/tests/kvm/scripts/unattended.py ('k') | client/tests/kvm/tests.cfg.sample » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 """
4 Auxiliary script used to send data between ports on guests.
5
6 @copyright: 2008-2009 Red Hat Inc.
7 @author: Jiri Zupka (jzupka@redhat.com)
8 @author: Lukas Doktor (ldoktor@redhat.com)
9 """
10 #from _pydev_SimpleXMLRPCServer import fcntl
11
12 """
13 TODO:
14 virt.init([consoles]) # sysfs, udev, OK
15 virt.open(name)
16 virt.close(name)
17 virt.poll(name, eventmask, timeout) # poll.register(), poll.poll(),
18 return event
19 virt.send(name, length) # host disconnected
20 virt.recv(name, length) # host disconnected
21 virt.blocking(name, true) # true = blocking, false = nonblocking
22 virt.loopback(in_names, out_names, type="None") # use select/poll
23 """
24
25 import threading
26 from threading import Thread
27 import os, time, select, re, random, sys, array, fcntl, array, subprocess
28
29 DEBUGPATH = "/sys/kernel/debug"
30 SYSFSPATH = "/sys/class/virtio-ports/"
31
32
33 class virtio_guest():
34
35 LOOP_NONE = 0
36 LOOP_POLL = 1
37 LOOP_SELECT = 2
38
39 def __init__(self):
40 self.files = {}
41 self.exit_thread = threading.Event()
42 self.threads = []
43 self.ports = {}
44
45
46 def _readfile(self, name):
47 """
48 Read file and return content as string
49
50 @param name: Name of file
51 @return: Content of file as string
52 """
53 out = ""
54 try:
55 f = open(name, "r")
56 out = f.read()
57 f.close()
58 except:
59 print "FAIL: Cannot open file %s" % (name)
60
61 return out
62
63
64 def _get_port_status(self):
65 """
66 Get info about ports from kernel debugfs.
67
68 @return: Ports dictionary of port properties
69 """
70 ports = {}
71 not_present_msg = "FAIL: There's no virtio-ports dir in debugfs"
72 if (not os.path.ismount(DEBUGPATH)):
73 os.system('mount -t debugfs none %s' % (DEBUGPATH))
74 try:
75 if not os.path.isdir('%s/virtio-ports' % (DEBUGPATH)):
76 print not_present_msg
77 except:
78 print not_present_msg
79 else:
80 viop_names = os.listdir('%s/virtio-ports' % (DEBUGPATH))
81 for name in viop_names:
82 f = open("%s/virtio-ports/%s" % (DEBUGPATH, name), 'r')
83 port = {}
84 for line in iter(f):
85 m = re.match("(\S+): (\S+)", line)
86 port[m.group(1)] = m.group(2)
87
88 if (port['is_console'] == "yes"):
89 port["path"] = "/dev/hvc%s" % (port["console_vtermno"])
90 # Console works like a serialport
91 else:
92 port["path"] = "/dev/%s" % name
93
94 if (not os.path.exists(port['path'])):
95 print "FAIL: %s not exist" % port['path']
96
97 sysfspath = SYSFSPATH + name
98 if (not os.path.isdir(sysfspath)):
99 print "FAIL: %s not exist" % (sysfspath)
100
101 info_name = sysfspath + "/name"
102 port_name = self._readfile(info_name).strip()
103 if (port_name != port["name"]):
104 print ("FAIL: Port info not match \n%s - %s\n%s - %s" %
105 (info_name , port_name,
106 "%s/virtio-ports/%s" % (DEBUGPATH, name),
107 port["name"]))
108
109 ports[port['name']] = port
110 f.close()
111
112 return ports
113
114
115 def init(self, in_files):
116 """
117 Init and check port properties.
118 """
119 self.ports = self._get_port_status()
120
121 for item in in_files:
122 if (item[1] != self.ports[item[0]]["is_console"]):
123 print self.ports
124 print "FAIL: Host console is not like console on guest side\n"
125 print "PASS: Init and check virtioconsole files in system."
126
127
128 class switch(Thread):
129 """
130 Thread that sends data between ports.
131 """
132 def __init__ (self, in_files, out_files, event,
133 cachesize=1024, method=0):
134 """
135 @param in_files: Array of input files.
136 @param out_files: Array of output files.
137 @param method: Method of read/write access.
138 @param cachesize: Block to receive and send.
139 """
140 Thread.__init__(self)
141
142 self.in_files = in_files
143 self.out_files = out_files
144 self.exit_thread = event
145 self.method = method
146
147 self.cachesize = cachesize
148
149
150 def _none_mode(self):
151 """
152 Read and write to device in blocking mode
153 """
154 data = ""
155 while not self.exit_thread.isSet():
156 data = ""
157 for desc in self.in_files:
158 data += os.read(desc, self.cachesize)
159 if data != "":
160 for desc in self.out_files:
161 os.write(desc, data)
162
163
164 def _poll_mode(self):
165 """
166 Read and write to device in polling mode.
167 """
168
169 pi = select.poll()
170 po = select.poll()
171
172 for fd in self.in_files:
173 pi.register(fd, select.POLLIN)
174
175 for fd in self.out_files:
176 po.register(fd, select.POLLOUT)
177
178 while not self.exit_thread.isSet():
179 data = ""
180 t_out = self.out_files
181
182 readyf = pi.poll(1.0)
183 for i in readyf:
184 data += os.read(i[0], self.cachesize)
185
186 if data != "":
187 while ((len(t_out) != len(readyf)) and not
188 self.exit_thread.isSet()):
189 readyf = po.poll(1.0)
190 for desc in t_out:
191 os.write(desc, data)
192
193
194 def _select_mode(self):
195 """
196 Read and write to device in selecting mode.
197 """
198 while not self.exit_thread.isSet():
199 ret = select.select(self.in_files, [], [], 1.0)
200 data = ""
201 if ret[0] != []:
202 for desc in ret[0]:
203 data += os.read(desc, self.cachesize)
204 if data != "":
205 ret = select.select([], self.out_files, [], 1.0)
206 while ((len(self.out_files) != len(ret[1])) and not
207 self.exit_thread.isSet()):
208 ret = select.select([], self.out_files, [], 1.0)
209 for desc in ret[1]:
210 os.write(desc, data)
211
212
213 def run(self):
214 if (self.method == virtio_guest.LOOP_POLL):
215 self._poll_mode()
216 elif (self.method == virtio_guest.LOOP_SELECT):
217 self._select_mode()
218 else:
219 self._none_mode()
220
221
222 class sender(Thread):
223 """
224 Creates a thread which sends random blocks of data to dst port.
225 """
226 def __init__(self, port, event, length):
227 """
228 @param port: Destination port
229 @param length: Length of the random data block
230 """
231 Thread.__init__(self)
232 self.port = port
233 self.exit_thread = event
234 self.data = array.array('L')
235 for i in range(max(length / self.data.itemsize, 1)):
236 self.data.append(random.randrange(sys.maxint))
237
238 def run(self):
239 while not self.exit_thread.isSet():
240 os.write(self.port, self.data)
241
242
243 def _open(self, in_files):
244 """
245 Open devices and return array of descriptors
246
247 @param in_files: Files array
248 @return: Array of descriptor
249 """
250 f = []
251
252 for item in in_files:
253 name = self.ports[item]["path"]
254 if (name in self.files):
255 f.append(self.files[name])
256 else:
257 try:
258 self.files[name] = os.open(name, os.O_RDWR)
259 if (self.ports[item]["is_console"] == "yes"):
260 print os.system("stty -F %s raw -echo" % (name))
261 print os.system("stty -F %s -a" % (name))
262 f.append(self.files[name])
263 except Exception as inst:
264 print "FAIL: Failed to open file %s" % (name)
265 raise inst
266 return f
267
268
269 def poll(self, port, expected, timeout=500):
270 """
271 Pool event from device and print event like text.
272
273 @param file: Device.
274 """
275 in_f = self._open([port])
276
277 p = select.poll()
278 p.register(in_f[0])
279
280 mask = p.poll(timeout)
281
282 str = ""
283 if (mask[0][1] & select.POLLIN):
284 str += "IN "
285 if (mask[0][1] & select.POLLPRI):
286 str += "PRI IN "
287 if (mask[0][1] & select.POLLOUT):
288 str += "OUT "
289 if (mask[0][1] & select.POLLERR):
290 str += "ERR "
291 if (mask[0][1] & select.POLLHUP):
292 str += "HUP "
293 if (mask[0][1] & select.POLLMSG):
294 str += "MSG "
295
296 if (mask[0][1] & expected) == expected:
297 print "PASS: Events: " + str
298 else:
299 print "FAIL: Events: " + str
300
301
302 def blocking(self, port, mode=False):
303 """
304 Set port function mode blocking/nonblocking
305
306 @param port: port to set mode
307 @param mode: False to set nonblock mode, True for block mode
308 """
309 path = self.ports[port]["path"]
310 fd = self.files[path]
311
312 try:
313 fl = fcntl.fcntl(fd, fcntl.F_GETFL)
314 if not mode:
315 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
316 else:
317 fcntl.fcntl(fd, fcntl.F_SETFL, fl & ~os.O_NONBLOCK)
318
319 except Exception as inst:
320 print "FAIL: Setting (non)blocking mode: " + str(inst)
321 return
322
323 print ("PASS: set blocking mode to %s mode" %
324 ("blocking" if mode else "nonblocking"))
325
326
327 def close(self, file):
328 """
329 Close open port.
330
331 @param file: File to close.
332 """
333 descriptor = None
334 path = self.ports[file]["path"]
335 if path != None:
336 if path in self.files.keys():
337 descriptor = self.files[path]
338 del self.files[path]
339 try:
340 os.close(descriptor)
341 except Exception as inst:
342 print "FAIL: Closing the file: " + str(inst)
343 return
344 print "PASS: Close"
345
346
347 def open(self, in_files):
348 """
349 Direct open devices.
350
351 @param in_files: Array of files.
352 @return: Array of descriptors.
353 """
354 name = self.ports[in_files]["path"]
355 try:
356 self.files[name] = os.open(name, os.O_RDWR)
357 print "PASS: Open all filles correctly."
358 except Exception as inst:
359 print "%s\nFAIL: Failed open file %s" % (str(inst), name)
360
361
362 def loopback(self, in_files, out_files, cachesize=1024, mode=LOOP_NONE):
363 """
364 Start a switch thread.
365
366 (There is a problem with multiple opens of a single file).
367
368 @param in_files: Array of input files.
369 @param out_files: Array of output files.
370 @param cachesize: Cachesize.
371 """
372 self.ports = self._get_port_status()
373
374 in_f = self._open(in_files)
375 out_f = self._open(out_files)
376
377 s = self.switch(in_f, out_f, self.exit_thread, cachesize, mode)
378 s.start()
379 self.threads.append(s)
380 print "PASS: Start switch"
381
382
383 def exit_threads(self):
384 """
385 Function end all running data switch.
386 """
387 self.exit_thread.set()
388 for th in self.threads:
389 print "join"
390 th.join()
391 self.exit_thread.clear()
392
393 del self.threads[:]
394 for desc in self.files.itervalues():
395 os.close(desc)
396 self.files.clear()
397 print "PASS: All threads finished."
398
399
400 def die(self):
401 """
402 Quit consoleswitch.
403 """
404 self.exit_threads()
405 exit()
406
407
408 def send_loop_init(self, port, length):
409 """
410 Prepares the sender thread. Requires clean thread structure.
411 """
412 self.ports = self._get_port_status()
413 in_f = self._open([port])
414
415 self.threads.append(self.sender(in_f[0], self.exit_thread, length))
416 print "PASS: Sender prepare"
417
418
419 def send_loop(self):
420 """
421 Start sender data transfer. Requires senderprepare run first.
422 """
423 self.threads[0].start()
424 print "PASS: Sender start"
425
426
427 def send(self, port, length=1, mode=True):
428 """
429 Send a data of some length
430
431 @param port: Port to write data
432 @param length: Length of data
433 @param mode: True = loop mode, False = one shoot mode
434 """
435 in_f = self._open([port])
436
437 data = ""
438 while len(data) < length:
439 data += "%c" % random.randrange(255)
440 try:
441 writes = os.write(in_f[0], data)
442 except Exception as inst:
443 print inst
444 if not writes:
445 writes = 0
446 if mode:
447 while (writes < length):
448 try:
449 writes += os.write(in_f[0], data)
450 except Exception as inst:
451 print inst
452 if writes >= length:
453 print "PASS: Send data length %d" % writes
454 else:
455 print ("FAIL: Partial send: desired %d, transfered %d" %
456 (length, writes))
457
458
459 def recv(self, port, length=1, buffer=1024, mode=True):
460 """
461 Recv a data of some length
462
463 @param port: Port to write data
464 @param length: Length of data
465 @param mode: True = loop mode, False = one shoot mode
466 """
467 in_f = self._open([port])
468
469 recvs = ""
470 try:
471 recvs = os.read(in_f[0], buffer)
472 except Exception as inst:
473 print inst
474 if mode:
475 while (len(recvs) < length):
476 try:
477 recvs += os.read(in_f[0], buffer)
478 except Exception as inst:
479 print inst
480 if len(recvs) >= length:
481 print "PASS: Recv data length %d" % len(recvs)
482 else:
483 print ("FAIL: Partial recv: desired %d, transfered %d" %
484 (length, len(recvs)))
485
486
487 def compile():
488 """
489 Compile virtio_guest.py to speed up.
490 """
491 import py_compile
492 py_compile.compile(sys.path[0] + "/virtio_guest.py")
493 print "PASS: compile"
494 exit(0)
495
496
497 def main():
498 """
499 Main (infinite) loop of virtio_guest.
500 """
501 if (len(sys.argv) > 1) and (sys.argv[1] == "-c"):
502 compile()
503
504 virt = virtio_guest()
505 print "PASS: Start"
506
507 while True:
508 str = raw_input()
509 exec str
510
511
512 if __name__ == "__main__":
513 main()
OLDNEW
« no previous file with comments | « client/tests/kvm/scripts/unattended.py ('k') | client/tests/kvm/tests.cfg.sample » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698