| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
| 3 """ | 3 """ |
| 4 Auxiliary script used to send data between ports on guests. | 4 Auxiliary script used to send data between ports on guests. |
| 5 | 5 |
| 6 @copyright: 2010 Red Hat, Inc. | 6 @copyright: 2008-2009 Red Hat Inc. |
| 7 @author: Jiri Zupka (jzupka@redhat.com) | 7 @author: Jiri Zupka (jzupka@redhat.com) |
| 8 @author: Lukas Doktor (ldoktor@redhat.com) | 8 @author: Lukas Doktor (ldoktor@redhat.com) |
| 9 """ | 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 |
| 10 import threading | 25 import threading |
| 11 from threading import Thread | 26 from threading import Thread |
| 12 import os, time, select, re, random, sys, array | 27 import os, time, select, re, random, sys, array, fcntl, array, subprocess |
| 13 import fcntl, array, subprocess, traceback, signal | |
| 14 | 28 |
| 15 DEBUGPATH = "/sys/kernel/debug" | 29 DEBUGPATH = "/sys/kernel/debug" |
| 16 SYSFSPATH = "/sys/class/virtio-ports/" | 30 SYSFSPATH = "/sys/class/virtio-ports/" |
| 17 | 31 |
| 18 | 32 |
| 19 class VirtioGuest: | 33 class virtio_guest(): |
| 20 """ | 34 |
| 21 Test tools of virtio_ports. | |
| 22 """ | |
| 23 LOOP_NONE = 0 | 35 LOOP_NONE = 0 |
| 24 LOOP_POLL = 1 | 36 LOOP_POLL = 1 |
| 25 LOOP_SELECT = 2 | 37 LOOP_SELECT = 2 |
| 26 | 38 |
| 27 def __init__(self): | 39 def __init__(self): |
| 28 self.files = {} | 40 self.files = {} |
| 29 self.exit_thread = threading.Event() | 41 self.exit_thread = threading.Event() |
| 30 self.threads = [] | 42 self.threads = [] |
| 31 self.ports = {} | 43 self.ports = {} |
| 32 self.poll_fds = {} | |
| 33 self.catch_signal = None | |
| 34 self.use_config = threading.Event() | |
| 35 | 44 |
| 36 | 45 |
| 37 def _readfile(self, name): | 46 def _readfile(self, name): |
| 38 """ | 47 """ |
| 39 Read file and return content as string | 48 Read file and return content as string |
| 40 | 49 |
| 41 @param name: Name of file | 50 @param name: Name of file |
| 42 @return: Content of file as string | 51 @return: Content of file as string |
| 43 """ | 52 """ |
| 44 out = "" | 53 out = "" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 """ | 118 """ |
| 110 self.ports = self._get_port_status() | 119 self.ports = self._get_port_status() |
| 111 | 120 |
| 112 for item in in_files: | 121 for item in in_files: |
| 113 if (item[1] != self.ports[item[0]]["is_console"]): | 122 if (item[1] != self.ports[item[0]]["is_console"]): |
| 114 print self.ports | 123 print self.ports |
| 115 print "FAIL: Host console is not like console on guest side\n" | 124 print "FAIL: Host console is not like console on guest side\n" |
| 116 print "PASS: Init and check virtioconsole files in system." | 125 print "PASS: Init and check virtioconsole files in system." |
| 117 | 126 |
| 118 | 127 |
| 119 class Switch(Thread): | 128 class switch(Thread): |
| 120 """ | 129 """ |
| 121 Thread that sends data between ports. | 130 Thread that sends data between ports. |
| 122 """ | 131 """ |
| 123 def __init__ (self, in_files, out_files, event, | 132 def __init__ (self, in_files, out_files, event, |
| 124 cachesize=1024, method=0): | 133 cachesize=1024, method=0): |
| 125 """ | 134 """ |
| 126 @param in_files: Array of input files. | 135 @param in_files: Array of input files. |
| 127 @param out_files: Array of output files. | 136 @param out_files: Array of output files. |
| 128 @param method: Method of read/write access. | 137 @param method: Method of read/write access. |
| 129 @param cachesize: Block to receive and send. | 138 @param cachesize: Block to receive and send. |
| 130 """ | 139 """ |
| 131 Thread.__init__(self, name="Switch") | 140 Thread.__init__(self) |
| 132 | 141 |
| 133 self.in_files = in_files | 142 self.in_files = in_files |
| 134 self.out_files = out_files | 143 self.out_files = out_files |
| 135 self.exit_thread = event | 144 self.exit_thread = event |
| 136 self.method = method | 145 self.method = method |
| 137 | 146 |
| 138 self.cachesize = cachesize | 147 self.cachesize = cachesize |
| 139 | 148 |
| 140 | 149 |
| 141 def _none_mode(self): | 150 def _none_mode(self): |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 if data != "": | 204 if data != "": |
| 196 ret = select.select([], self.out_files, [], 1.0) | 205 ret = select.select([], self.out_files, [], 1.0) |
| 197 while ((len(self.out_files) != len(ret[1])) and not | 206 while ((len(self.out_files) != len(ret[1])) and not |
| 198 self.exit_thread.isSet()): | 207 self.exit_thread.isSet()): |
| 199 ret = select.select([], self.out_files, [], 1.0) | 208 ret = select.select([], self.out_files, [], 1.0) |
| 200 for desc in ret[1]: | 209 for desc in ret[1]: |
| 201 os.write(desc, data) | 210 os.write(desc, data) |
| 202 | 211 |
| 203 | 212 |
| 204 def run(self): | 213 def run(self): |
| 205 if (self.method == VirtioGuest.LOOP_POLL): | 214 if (self.method == virtio_guest.LOOP_POLL): |
| 206 self._poll_mode() | 215 self._poll_mode() |
| 207 elif (self.method == VirtioGuest.LOOP_SELECT): | 216 elif (self.method == virtio_guest.LOOP_SELECT): |
| 208 self._select_mode() | 217 self._select_mode() |
| 209 else: | 218 else: |
| 210 self._none_mode() | 219 self._none_mode() |
| 211 | 220 |
| 212 | 221 |
| 213 class Sender(Thread): | 222 class sender(Thread): |
| 214 """ | 223 """ |
| 215 Creates a thread which sends random blocks of data to dst port. | 224 Creates a thread which sends random blocks of data to dst port. |
| 216 """ | 225 """ |
| 217 def __init__(self, port, event, length): | 226 def __init__(self, port, event, length): |
| 218 """ | 227 """ |
| 219 @param port: Destination port | 228 @param port: Destination port |
| 220 @param length: Length of the random data block | 229 @param length: Length of the random data block |
| 221 """ | 230 """ |
| 222 Thread.__init__(self, name="Sender") | 231 Thread.__init__(self) |
| 223 self.port = port | 232 self.port = port |
| 224 self.exit_thread = event | 233 self.exit_thread = event |
| 225 self.data = array.array('L') | 234 self.data = array.array('L') |
| 226 for i in range(max(length / self.data.itemsize, 1)): | 235 for i in range(max(length / self.data.itemsize, 1)): |
| 227 self.data.append(random.randrange(sys.maxint)) | 236 self.data.append(random.randrange(sys.maxint)) |
| 228 | 237 |
| 229 def run(self): | 238 def run(self): |
| 230 while not self.exit_thread.isSet(): | 239 while not self.exit_thread.isSet(): |
| 231 os.write(self.port, self.data) | 240 os.write(self.port, self.data) |
| 232 | 241 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 244 name = self.ports[item]["path"] | 253 name = self.ports[item]["path"] |
| 245 if (name in self.files): | 254 if (name in self.files): |
| 246 f.append(self.files[name]) | 255 f.append(self.files[name]) |
| 247 else: | 256 else: |
| 248 try: | 257 try: |
| 249 self.files[name] = os.open(name, os.O_RDWR) | 258 self.files[name] = os.open(name, os.O_RDWR) |
| 250 if (self.ports[item]["is_console"] == "yes"): | 259 if (self.ports[item]["is_console"] == "yes"): |
| 251 print os.system("stty -F %s raw -echo" % (name)) | 260 print os.system("stty -F %s raw -echo" % (name)) |
| 252 print os.system("stty -F %s -a" % (name)) | 261 print os.system("stty -F %s -a" % (name)) |
| 253 f.append(self.files[name]) | 262 f.append(self.files[name]) |
| 254 except Exception, inst: | 263 except Exception as inst: |
| 255 print "FAIL: Failed to open file %s" % (name) | 264 print "FAIL: Failed to open file %s" % (name) |
| 256 raise inst | 265 raise inst |
| 257 return f | 266 return f |
| 258 | 267 |
| 259 @staticmethod | |
| 260 def pollmask_to_str(mask): | |
| 261 """ | |
| 262 Conver pool mast to string | |
| 263 | |
| 264 @param mask: poll return mask | |
| 265 """ | |
| 266 str = "" | |
| 267 if (mask & select.POLLIN): | |
| 268 str += "IN " | |
| 269 if (mask & select.POLLPRI): | |
| 270 str += "PRI IN " | |
| 271 if (mask & select.POLLOUT): | |
| 272 str += "OUT " | |
| 273 if (mask & select.POLLERR): | |
| 274 str += "ERR " | |
| 275 if (mask & select.POLLHUP): | |
| 276 str += "HUP " | |
| 277 if (mask & select.POLLMSG): | |
| 278 str += "MSG " | |
| 279 return str | |
| 280 | |
| 281 | 268 |
| 282 def poll(self, port, expected, timeout=500): | 269 def poll(self, port, expected, timeout=500): |
| 283 """ | 270 """ |
| 284 Pool event from device and print event like text. | 271 Pool event from device and print event like text. |
| 285 | 272 |
| 286 @param file: Device. | 273 @param file: Device. |
| 287 """ | 274 """ |
| 288 in_f = self._open([port]) | 275 in_f = self._open([port]) |
| 289 | 276 |
| 290 p = select.poll() | 277 p = select.poll() |
| 291 p.register(in_f[0]) | 278 p.register(in_f[0]) |
| 292 | 279 |
| 293 mask = p.poll(timeout) | 280 mask = p.poll(timeout) |
| 294 | 281 |
| 295 maskstr = VirtioGuest.pollmask_to_str(mask[0][1]) | 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: | 296 if (mask[0][1] & expected) == expected: |
| 297 print "PASS: Events: " + maskstr | 297 print "PASS: Events: " + str |
| 298 else: | 298 else: |
| 299 emaskstr = VirtioGuest.pollmask_to_str(expected) | 299 print "FAIL: Events: " + str |
| 300 print "FAIL: Events: " + maskstr + " Expected: " + emaskstr | |
| 301 | |
| 302 | |
| 303 def lseek(self, port, pos, how): | |
| 304 """ | |
| 305 Use lseek on the device. The device is unseekable so PASS is returned | |
| 306 when lseek command fails and vice versa. | |
| 307 | |
| 308 @param port: Name of the port | |
| 309 @param pos: Offset | |
| 310 @param how: Relativ offset os.SEEK_{SET,CUR,END} | |
| 311 """ | |
| 312 fd = self._open([port])[0] | |
| 313 | |
| 314 try: | |
| 315 os.lseek(fd, pos, how) | |
| 316 except Exception, inst: | |
| 317 if inst.errno == 29: | |
| 318 print "PASS: the lseek failed as expected" | |
| 319 else: | |
| 320 print inst | |
| 321 print "FAIL: unknown error" | |
| 322 else: | |
| 323 print "FAIL: the lseek unexpectedly passed" | |
| 324 | 300 |
| 325 | 301 |
| 326 def blocking(self, port, mode=False): | 302 def blocking(self, port, mode=False): |
| 327 """ | 303 """ |
| 328 Set port function mode blocking/nonblocking | 304 Set port function mode blocking/nonblocking |
| 329 | 305 |
| 330 @param port: port to set mode | 306 @param port: port to set mode |
| 331 @param mode: False to set nonblock mode, True for block mode | 307 @param mode: False to set nonblock mode, True for block mode |
| 332 """ | 308 """ |
| 333 fd = self._open([port])[0] | 309 path = self.ports[port]["path"] |
| 310 fd = self.files[path] |
| 334 | 311 |
| 335 try: | 312 try: |
| 336 fl = fcntl.fcntl(fd, fcntl.F_GETFL) | 313 fl = fcntl.fcntl(fd, fcntl.F_GETFL) |
| 337 if not mode: | 314 if not mode: |
| 338 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) | 315 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) |
| 339 else: | 316 else: |
| 340 fcntl.fcntl(fd, fcntl.F_SETFL, fl & ~os.O_NONBLOCK) | 317 fcntl.fcntl(fd, fcntl.F_SETFL, fl & ~os.O_NONBLOCK) |
| 341 | 318 |
| 342 except Exception, inst: | 319 except Exception as inst: |
| 343 print "FAIL: Setting (non)blocking mode: " + str(inst) | 320 print "FAIL: Setting (non)blocking mode: " + str(inst) |
| 344 return | 321 return |
| 345 | 322 |
| 346 if mode: | 323 print ("PASS: set blocking mode to %s mode" % |
| 347 print "PASS: set to blocking mode" | 324 ("blocking" if mode else "nonblocking")) |
| 348 else: | |
| 349 print "PASS: set to nonblocking mode" | |
| 350 | |
| 351 | |
| 352 def __call__(self, sig, frame): | |
| 353 """ | |
| 354 Call function. Used for signal handle. | |
| 355 """ | |
| 356 if (sig == signal.SIGIO): | |
| 357 self.sigio_handler(sig, frame) | |
| 358 | |
| 359 | |
| 360 def sigio_handler(self, sig, frame): | |
| 361 """ | |
| 362 Handler for sigio operation. | |
| 363 | |
| 364 @param sig: signal which call handler. | |
| 365 @param frame: frame of caller | |
| 366 """ | |
| 367 if self.poll_fds: | |
| 368 p = select.poll() | |
| 369 map(p.register, self.poll_fds.keys()) | |
| 370 | |
| 371 masks = p.poll(1) | |
| 372 print masks | |
| 373 for mask in masks: | |
| 374 self.poll_fds[mask[0]][1] |= mask[1] | |
| 375 | |
| 376 | |
| 377 def get_sigio_poll_return(self, port): | |
| 378 """ | |
| 379 Return PASS, FAIL and poll walue in string format. | |
| 380 | |
| 381 @param port: Port to check poll information. | |
| 382 """ | |
| 383 fd = self._open([port])[0] | |
| 384 | |
| 385 maskstr = VirtioGuest.pollmask_to_str(self.poll_fds[fd][1]) | |
| 386 if (self.poll_fds[fd][0] ^ self.poll_fds[fd][1]): | |
| 387 emaskstr = VirtioGuest.pollmask_to_str(self.poll_fds[fd][0]) | |
| 388 print "FAIL: Events: " + maskstr + " Expected: " + emaskstr | |
| 389 else: | |
| 390 print "PASS: Events: " + maskstr | |
| 391 self.poll_fds[fd][1] = 0 | |
| 392 | |
| 393 | |
| 394 def set_pool_want_return(self, port, poll_value): | |
| 395 """ | |
| 396 Set value to static variable. | |
| 397 | |
| 398 @param port: Port which should be set excepted mask | |
| 399 @param poll_value: Value to check sigio signal. | |
| 400 """ | |
| 401 fd = self._open([port])[0] | |
| 402 self.poll_fds[fd] = [poll_value, 0] | |
| 403 print "PASS: Events: " + VirtioGuest.pollmask_to_str(poll_value) | |
| 404 | |
| 405 | |
| 406 def catching_signal(self): | |
| 407 """ | |
| 408 return: True if should set catch signal, False if ignore signal and | |
| 409 none when configuration is not changed. | |
| 410 """ | |
| 411 ret = self.catch_signal | |
| 412 self.catch_signal = None | |
| 413 return ret | |
| 414 | |
| 415 | |
| 416 def async(self, port, mode=True, exp_val = 0): | |
| 417 """ | |
| 418 Set port function mode async/sync. | |
| 419 | |
| 420 @param port: port which should be pooled. | |
| 421 @param mode: False to set sync mode, True for sync mode. | |
| 422 @param exp_val: Value which should be pooled. | |
| 423 """ | |
| 424 fd = self._open([port])[0] | |
| 425 | |
| 426 try: | |
| 427 fcntl.fcntl(fd, fcntl.F_SETOWN, os.getpid()) | |
| 428 fl = fcntl.fcntl(fd, fcntl.F_GETFL) | |
| 429 | |
| 430 self.use_config.clear() | |
| 431 if mode: | |
| 432 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_ASYNC) | |
| 433 self.poll_fds[fd] = [exp_val, 0] | |
| 434 self.catch_signal = True | |
| 435 else: | |
| 436 del self.poll_fds[fd] | |
| 437 fcntl.fcntl(fd, fcntl.F_SETFL, fl & ~os.O_ASYNC) | |
| 438 self.catch_signal = False | |
| 439 | |
| 440 os.kill(os.getpid(), signal.SIGUSR1) | |
| 441 self.use_config.wait() | |
| 442 | |
| 443 except Exception, inst: | |
| 444 print "FAIL: Setting (a)sync mode: " + str(inst) | |
| 445 return | |
| 446 | |
| 447 if mode: | |
| 448 print "PASS: Set to async mode" | |
| 449 else: | |
| 450 print "PASS: Set to sync mode" | |
| 451 | 325 |
| 452 | 326 |
| 453 def close(self, file): | 327 def close(self, file): |
| 454 """ | 328 """ |
| 455 Close open port. | 329 Close open port. |
| 456 | 330 |
| 457 @param file: File to close. | 331 @param file: File to close. |
| 458 """ | 332 """ |
| 459 descriptor = None | 333 descriptor = None |
| 460 path = self.ports[file]["path"] | 334 path = self.ports[file]["path"] |
| 461 if path != None: | 335 if path != None: |
| 462 if path in self.files.keys(): | 336 if path in self.files.keys(): |
| 463 descriptor = self.files[path] | 337 descriptor = self.files[path] |
| 464 del self.files[path] | 338 del self.files[path] |
| 465 if descriptor != None: | 339 try: |
| 466 try: | 340 os.close(descriptor) |
| 467 os.close(descriptor) | 341 except Exception as inst: |
| 468 except Exception, inst: | 342 print "FAIL: Closing the file: " + str(inst) |
| 469 print "FAIL: Closing the file: " + str(inst) | 343 return |
| 470 return | |
| 471 print "PASS: Close" | 344 print "PASS: Close" |
| 472 | 345 |
| 473 | 346 |
| 474 def open(self, in_file): | 347 def open(self, in_files): |
| 475 """ | 348 """ |
| 476 Direct open devices. | 349 Direct open devices. |
| 477 | 350 |
| 478 @param in_file: Array of files. | 351 @param in_files: Array of files. |
| 479 @return: Array of descriptors. | 352 @return: Array of descriptors. |
| 480 """ | 353 """ |
| 481 name = self.ports[in_file]["path"] | 354 name = self.ports[in_files]["path"] |
| 482 try: | 355 try: |
| 483 self.files[name] = os.open(name, os.O_RDWR) | 356 self.files[name] = os.open(name, os.O_RDWR) |
| 484 if (self.ports[in_file]["is_console"] == "yes"): | |
| 485 print os.system("stty -F %s raw -echo" % (name)) | |
| 486 print "PASS: Open all filles correctly." | 357 print "PASS: Open all filles correctly." |
| 487 except Exception, inst: | 358 except Exception as inst: |
| 488 print "%s\nFAIL: Failed open file %s" % (str(inst), name) | 359 print "%s\nFAIL: Failed open file %s" % (str(inst), name) |
| 489 | 360 |
| 490 | 361 |
| 491 def loopback(self, in_files, out_files, cachesize=1024, mode=LOOP_NONE): | 362 def loopback(self, in_files, out_files, cachesize=1024, mode=LOOP_NONE): |
| 492 """ | 363 """ |
| 493 Start a switch thread. | 364 Start a switch thread. |
| 494 | 365 |
| 495 (There is a problem with multiple opens of a single file). | 366 (There is a problem with multiple opens of a single file). |
| 496 | 367 |
| 497 @param in_files: Array of input files. | 368 @param in_files: Array of input files. |
| 498 @param out_files: Array of output files. | 369 @param out_files: Array of output files. |
| 499 @param cachesize: Cachesize. | 370 @param cachesize: Cachesize. |
| 500 """ | 371 """ |
| 501 self.ports = self._get_port_status() | 372 self.ports = self._get_port_status() |
| 502 | 373 |
| 503 in_f = self._open(in_files) | 374 in_f = self._open(in_files) |
| 504 out_f = self._open(out_files) | 375 out_f = self._open(out_files) |
| 505 | 376 |
| 506 s = self.Switch(in_f, out_f, self.exit_thread, cachesize, mode) | 377 s = self.switch(in_f, out_f, self.exit_thread, cachesize, mode) |
| 507 s.start() | 378 s.start() |
| 508 self.threads.append(s) | 379 self.threads.append(s) |
| 509 print "PASS: Start switch" | 380 print "PASS: Start switch" |
| 510 | 381 |
| 511 | 382 |
| 512 def exit_threads(self): | 383 def exit_threads(self): |
| 513 """ | 384 """ |
| 514 Function end all running data switch. | 385 Function end all running data switch. |
| 515 """ | 386 """ |
| 516 self.exit_thread.set() | 387 self.exit_thread.set() |
| (...skipping 17 matching lines...) Expand all Loading... |
| 534 exit() | 405 exit() |
| 535 | 406 |
| 536 | 407 |
| 537 def send_loop_init(self, port, length): | 408 def send_loop_init(self, port, length): |
| 538 """ | 409 """ |
| 539 Prepares the sender thread. Requires clean thread structure. | 410 Prepares the sender thread. Requires clean thread structure. |
| 540 """ | 411 """ |
| 541 self.ports = self._get_port_status() | 412 self.ports = self._get_port_status() |
| 542 in_f = self._open([port]) | 413 in_f = self._open([port]) |
| 543 | 414 |
| 544 self.threads.append(self.Sender(in_f[0], self.exit_thread, length)) | 415 self.threads.append(self.sender(in_f[0], self.exit_thread, length)) |
| 545 print "PASS: Sender prepare" | 416 print "PASS: Sender prepare" |
| 546 | 417 |
| 547 | 418 |
| 548 def send_loop(self): | 419 def send_loop(self): |
| 549 """ | 420 """ |
| 550 Start sender data transfer. Requires senderprepare run first. | 421 Start sender data transfer. Requires senderprepare run first. |
| 551 """ | 422 """ |
| 552 self.threads[0].start() | 423 self.threads[0].start() |
| 553 print "PASS: Sender start" | 424 print "PASS: Sender start" |
| 554 | 425 |
| 555 | 426 |
| 556 def send(self, port, length=1, mode=True): | 427 def send(self, port, length=1, mode=True): |
| 557 """ | 428 """ |
| 558 Send a data of some length | 429 Send a data of some length |
| 559 | 430 |
| 560 @param port: Port to write data | 431 @param port: Port to write data |
| 561 @param length: Length of data | 432 @param length: Length of data |
| 562 @param mode: True = loop mode, False = one shoot mode | 433 @param mode: True = loop mode, False = one shoot mode |
| 563 """ | 434 """ |
| 564 in_f = self._open([port]) | 435 in_f = self._open([port]) |
| 565 | 436 |
| 566 data = "" | 437 data = "" |
| 567 while len(data) < length: | 438 while len(data) < length: |
| 568 data += "%c" % random.randrange(255) | 439 data += "%c" % random.randrange(255) |
| 569 try: | 440 try: |
| 570 writes = os.write(in_f[0], data) | 441 writes = os.write(in_f[0], data) |
| 571 except Exception, inst: | 442 except Exception as inst: |
| 572 print inst | 443 print inst |
| 573 if not writes: | 444 if not writes: |
| 574 writes = 0 | 445 writes = 0 |
| 575 if mode: | 446 if mode: |
| 576 while (writes < length): | 447 while (writes < length): |
| 577 try: | 448 try: |
| 578 writes += os.write(in_f[0], data) | 449 writes += os.write(in_f[0], data) |
| 579 except Exception, inst: | 450 except Exception as inst: |
| 580 print inst | 451 print inst |
| 581 if writes >= length: | 452 if writes >= length: |
| 582 print "PASS: Send data length %d" % writes | 453 print "PASS: Send data length %d" % writes |
| 583 else: | 454 else: |
| 584 print ("FAIL: Partial send: desired %d, transfered %d" % | 455 print ("FAIL: Partial send: desired %d, transfered %d" % |
| 585 (length, writes)) | 456 (length, writes)) |
| 586 | 457 |
| 587 | 458 |
| 588 def recv(self, port, length=1, buffer=1024, mode=True): | 459 def recv(self, port, length=1, buffer=1024, mode=True): |
| 589 """ | 460 """ |
| 590 Recv a data of some length | 461 Recv a data of some length |
| 591 | 462 |
| 592 @param port: Port to write data | 463 @param port: Port to write data |
| 593 @param length: Length of data | 464 @param length: Length of data |
| 594 @param mode: True = loop mode, False = one shoot mode | 465 @param mode: True = loop mode, False = one shoot mode |
| 595 """ | 466 """ |
| 596 in_f = self._open([port]) | 467 in_f = self._open([port]) |
| 597 | 468 |
| 598 recvs = "" | 469 recvs = "" |
| 599 try: | 470 try: |
| 600 recvs = os.read(in_f[0], buffer) | 471 recvs = os.read(in_f[0], buffer) |
| 601 except Exception, inst: | 472 except Exception as inst: |
| 602 print inst | 473 print inst |
| 603 if mode: | 474 if mode: |
| 604 while (len(recvs) < length): | 475 while (len(recvs) < length): |
| 605 try: | 476 try: |
| 606 recvs += os.read(in_f[0], buffer) | 477 recvs += os.read(in_f[0], buffer) |
| 607 except Exception, inst: | 478 except Exception as inst: |
| 608 print inst | 479 print inst |
| 609 if len(recvs) >= length: | 480 if len(recvs) >= length: |
| 610 print "PASS: Recv data length %d" % len(recvs) | 481 print "PASS: Recv data length %d" % len(recvs) |
| 611 else: | 482 else: |
| 612 print ("FAIL: Partial recv: desired %d, transfered %d" % | 483 print ("FAIL: Partial recv: desired %d, transfered %d" % |
| 613 (length, len(recvs))) | 484 (length, len(recvs))) |
| 614 | 485 |
| 615 | 486 |
| 616 def clean_port(self, port, buffer=1024): | |
| 617 in_f = self._open([port]) | |
| 618 ret = select.select([in_f[0]], [], [], 1.0) | |
| 619 buf = "" | |
| 620 if ret[0]: | |
| 621 buf = os.read(in_f[0], buffer) | |
| 622 print ("PASS: Rest in socket: " + buf) | |
| 623 | |
| 624 | |
| 625 def is_alive(): | |
| 626 """ | |
| 627 Check is only main thread is alive and if guest react. | |
| 628 """ | |
| 629 if threading.activeCount() == 2: | |
| 630 print ("PASS: Guest is ok no thread alive") | |
| 631 else: | |
| 632 threads = "" | |
| 633 for thread in threading.enumerate(): | |
| 634 threads += thread.name + ", " | |
| 635 print ("FAIL: On guest run thread. Active thread:" + threads) | |
| 636 | |
| 637 | |
| 638 def compile(): | 487 def compile(): |
| 639 """ | 488 """ |
| 640 Compile virtio_guest.py to speed up. | 489 Compile virtio_guest.py to speed up. |
| 641 """ | 490 """ |
| 642 import py_compile | 491 import py_compile |
| 643 py_compile.compile(sys.path[0] + "/virtio_guest.py") | 492 py_compile.compile(sys.path[0] + "/virtio_guest.py") |
| 644 print "PASS: compile" | 493 print "PASS: compile" |
| 645 sys.exit() | 494 exit(0) |
| 646 | 495 |
| 647 | 496 |
| 648 def worker(virt): | 497 def main(): |
| 649 """ | 498 """ |
| 650 Worker thread (infinite) loop of virtio_guest. | 499 Main (infinite) loop of virtio_guest. |
| 651 """ | 500 """ |
| 501 if (len(sys.argv) > 1) and (sys.argv[1] == "-c"): |
| 502 compile() |
| 503 |
| 504 virt = virtio_guest() |
| 652 print "PASS: Start" | 505 print "PASS: Start" |
| 653 | 506 |
| 654 while True: | 507 while True: |
| 655 str = raw_input() | 508 str = raw_input() |
| 656 try: | 509 exec str |
| 657 exec str | |
| 658 except: | |
| 659 exc_type, exc_value, exc_traceback = sys.exc_info() | |
| 660 print "On Guest exception from: \n" + "".join( | |
| 661 traceback.format_exception(exc_type, | |
| 662 exc_value, | |
| 663 exc_traceback)) | |
| 664 sys.exit(0) | |
| 665 | |
| 666 | |
| 667 def sigusr_handler(sig, frame): | |
| 668 pass | |
| 669 | |
| 670 | |
| 671 def main(): | |
| 672 """ | |
| 673 Main function with infinite loop to catch signal from system. | |
| 674 """ | |
| 675 if (len(sys.argv) > 1) and (sys.argv[1] == "-c"): | |
| 676 compile() | |
| 677 | |
| 678 virt = VirtioGuest() | |
| 679 slave = Thread(target=worker, args=(virt, )) | |
| 680 slave.start() | |
| 681 signal.signal(signal.SIGUSR1, sigusr_handler) | |
| 682 while True: | |
| 683 signal.pause() | |
| 684 catch = virt.catching_signal() | |
| 685 if catch: | |
| 686 signal.signal(signal.SIGIO, virt) | |
| 687 elif catch == False: | |
| 688 signal.signal(signal.SIGIO, signal.SIG_DFL) | |
| 689 if (catch != None): | |
| 690 virt.use_config.set() | |
| 691 | 510 |
| 692 | 511 |
| 693 if __name__ == "__main__": | 512 if __name__ == "__main__": |
| 694 main() | 513 main() |
| OLD | NEW |