| Index: client/tests/kvm/scripts/virtio_guest.py
|
| diff --git a/client/tests/kvm/scripts/virtio_guest.py b/client/tests/kvm/scripts/virtio_guest.py
|
| old mode 100755
|
| new mode 100644
|
| index 0038f48f1885ffcffe1d166282dcee51fb5a4074..4862ef2b920674e3ca4de6af2ceda036efc810ae
|
| --- a/client/tests/kvm/scripts/virtio_guest.py
|
| +++ b/client/tests/kvm/scripts/virtio_guest.py
|
| @@ -3,23 +3,35 @@
|
| """
|
| Auxiliary script used to send data between ports on guests.
|
|
|
| -@copyright: 2010 Red Hat, Inc.
|
| +@copyright: 2008-2009 Red Hat Inc.
|
| @author: Jiri Zupka (jzupka@redhat.com)
|
| @author: Lukas Doktor (ldoktor@redhat.com)
|
| """
|
| +#from _pydev_SimpleXMLRPCServer import fcntl
|
| +
|
| +"""
|
| +TODO:
|
| +virt.init([consoles]) # sysfs, udev, OK
|
| +virt.open(name)
|
| +virt.close(name)
|
| +virt.poll(name, eventmask, timeout) # poll.register(), poll.poll(),
|
| +return event
|
| +virt.send(name, length) # host disconnected
|
| +virt.recv(name, length) # host disconnected
|
| +virt.blocking(name, true) # true = blocking, false = nonblocking
|
| +virt.loopback(in_names, out_names, type="None") # use select/poll
|
| +"""
|
| +
|
| import threading
|
| from threading import Thread
|
| -import os, time, select, re, random, sys, array
|
| -import fcntl, array, subprocess, traceback, signal
|
| +import os, time, select, re, random, sys, array, fcntl, array, subprocess
|
|
|
| DEBUGPATH = "/sys/kernel/debug"
|
| SYSFSPATH = "/sys/class/virtio-ports/"
|
|
|
|
|
| -class VirtioGuest:
|
| - """
|
| - Test tools of virtio_ports.
|
| - """
|
| +class virtio_guest():
|
| +
|
| LOOP_NONE = 0
|
| LOOP_POLL = 1
|
| LOOP_SELECT = 2
|
| @@ -29,9 +41,6 @@ class VirtioGuest:
|
| self.exit_thread = threading.Event()
|
| self.threads = []
|
| self.ports = {}
|
| - self.poll_fds = {}
|
| - self.catch_signal = None
|
| - self.use_config = threading.Event()
|
|
|
|
|
| def _readfile(self, name):
|
| @@ -116,7 +125,7 @@ class VirtioGuest:
|
| print "PASS: Init and check virtioconsole files in system."
|
|
|
|
|
| - class Switch(Thread):
|
| + class switch(Thread):
|
| """
|
| Thread that sends data between ports.
|
| """
|
| @@ -128,7 +137,7 @@ class VirtioGuest:
|
| @param method: Method of read/write access.
|
| @param cachesize: Block to receive and send.
|
| """
|
| - Thread.__init__(self, name="Switch")
|
| + Thread.__init__(self)
|
|
|
| self.in_files = in_files
|
| self.out_files = out_files
|
| @@ -202,15 +211,15 @@ class VirtioGuest:
|
|
|
|
|
| def run(self):
|
| - if (self.method == VirtioGuest.LOOP_POLL):
|
| + if (self.method == virtio_guest.LOOP_POLL):
|
| self._poll_mode()
|
| - elif (self.method == VirtioGuest.LOOP_SELECT):
|
| + elif (self.method == virtio_guest.LOOP_SELECT):
|
| self._select_mode()
|
| else:
|
| self._none_mode()
|
|
|
|
|
| - class Sender(Thread):
|
| + class sender(Thread):
|
| """
|
| Creates a thread which sends random blocks of data to dst port.
|
| """
|
| @@ -219,7 +228,7 @@ class VirtioGuest:
|
| @param port: Destination port
|
| @param length: Length of the random data block
|
| """
|
| - Thread.__init__(self, name="Sender")
|
| + Thread.__init__(self)
|
| self.port = port
|
| self.exit_thread = event
|
| self.data = array.array('L')
|
| @@ -251,33 +260,11 @@ class VirtioGuest:
|
| print os.system("stty -F %s raw -echo" % (name))
|
| print os.system("stty -F %s -a" % (name))
|
| f.append(self.files[name])
|
| - except Exception, inst:
|
| + except Exception as inst:
|
| print "FAIL: Failed to open file %s" % (name)
|
| raise inst
|
| return f
|
|
|
| - @staticmethod
|
| - def pollmask_to_str(mask):
|
| - """
|
| - Conver pool mast to string
|
| -
|
| - @param mask: poll return mask
|
| - """
|
| - str = ""
|
| - if (mask & select.POLLIN):
|
| - str += "IN "
|
| - if (mask & select.POLLPRI):
|
| - str += "PRI IN "
|
| - if (mask & select.POLLOUT):
|
| - str += "OUT "
|
| - if (mask & select.POLLERR):
|
| - str += "ERR "
|
| - if (mask & select.POLLHUP):
|
| - str += "HUP "
|
| - if (mask & select.POLLMSG):
|
| - str += "MSG "
|
| - return str
|
| -
|
|
|
| def poll(self, port, expected, timeout=500):
|
| """
|
| @@ -292,35 +279,24 @@ class VirtioGuest:
|
|
|
| mask = p.poll(timeout)
|
|
|
| - maskstr = VirtioGuest.pollmask_to_str(mask[0][1])
|
| - if (mask[0][1] & expected) == expected:
|
| - print "PASS: Events: " + maskstr
|
| - else:
|
| - emaskstr = VirtioGuest.pollmask_to_str(expected)
|
| - print "FAIL: Events: " + maskstr + " Expected: " + emaskstr
|
| -
|
| -
|
| - def lseek(self, port, pos, how):
|
| - """
|
| - Use lseek on the device. The device is unseekable so PASS is returned
|
| - when lseek command fails and vice versa.
|
| -
|
| - @param port: Name of the port
|
| - @param pos: Offset
|
| - @param how: Relativ offset os.SEEK_{SET,CUR,END}
|
| - """
|
| - fd = self._open([port])[0]
|
| + str = ""
|
| + if (mask[0][1] & select.POLLIN):
|
| + str += "IN "
|
| + if (mask[0][1] & select.POLLPRI):
|
| + str += "PRI IN "
|
| + if (mask[0][1] & select.POLLOUT):
|
| + str += "OUT "
|
| + if (mask[0][1] & select.POLLERR):
|
| + str += "ERR "
|
| + if (mask[0][1] & select.POLLHUP):
|
| + str += "HUP "
|
| + if (mask[0][1] & select.POLLMSG):
|
| + str += "MSG "
|
|
|
| - try:
|
| - os.lseek(fd, pos, how)
|
| - except Exception, inst:
|
| - if inst.errno == 29:
|
| - print "PASS: the lseek failed as expected"
|
| - else:
|
| - print inst
|
| - print "FAIL: unknown error"
|
| + if (mask[0][1] & expected) == expected:
|
| + print "PASS: Events: " + str
|
| else:
|
| - print "FAIL: the lseek unexpectedly passed"
|
| + print "FAIL: Events: " + str
|
|
|
|
|
| def blocking(self, port, mode=False):
|
| @@ -330,7 +306,8 @@ class VirtioGuest:
|
| @param port: port to set mode
|
| @param mode: False to set nonblock mode, True for block mode
|
| """
|
| - fd = self._open([port])[0]
|
| + path = self.ports[port]["path"]
|
| + fd = self.files[path]
|
|
|
| try:
|
| fl = fcntl.fcntl(fd, fcntl.F_GETFL)
|
| @@ -339,115 +316,12 @@ class VirtioGuest:
|
| else:
|
| fcntl.fcntl(fd, fcntl.F_SETFL, fl & ~os.O_NONBLOCK)
|
|
|
| - except Exception, inst:
|
| + except Exception as inst:
|
| print "FAIL: Setting (non)blocking mode: " + str(inst)
|
| return
|
|
|
| - if mode:
|
| - print "PASS: set to blocking mode"
|
| - else:
|
| - print "PASS: set to nonblocking mode"
|
| -
|
| -
|
| - def __call__(self, sig, frame):
|
| - """
|
| - Call function. Used for signal handle.
|
| - """
|
| - if (sig == signal.SIGIO):
|
| - self.sigio_handler(sig, frame)
|
| -
|
| -
|
| - def sigio_handler(self, sig, frame):
|
| - """
|
| - Handler for sigio operation.
|
| -
|
| - @param sig: signal which call handler.
|
| - @param frame: frame of caller
|
| - """
|
| - if self.poll_fds:
|
| - p = select.poll()
|
| - map(p.register, self.poll_fds.keys())
|
| -
|
| - masks = p.poll(1)
|
| - print masks
|
| - for mask in masks:
|
| - self.poll_fds[mask[0]][1] |= mask[1]
|
| -
|
| -
|
| - def get_sigio_poll_return(self, port):
|
| - """
|
| - Return PASS, FAIL and poll walue in string format.
|
| -
|
| - @param port: Port to check poll information.
|
| - """
|
| - fd = self._open([port])[0]
|
| -
|
| - maskstr = VirtioGuest.pollmask_to_str(self.poll_fds[fd][1])
|
| - if (self.poll_fds[fd][0] ^ self.poll_fds[fd][1]):
|
| - emaskstr = VirtioGuest.pollmask_to_str(self.poll_fds[fd][0])
|
| - print "FAIL: Events: " + maskstr + " Expected: " + emaskstr
|
| - else:
|
| - print "PASS: Events: " + maskstr
|
| - self.poll_fds[fd][1] = 0
|
| -
|
| -
|
| - def set_pool_want_return(self, port, poll_value):
|
| - """
|
| - Set value to static variable.
|
| -
|
| - @param port: Port which should be set excepted mask
|
| - @param poll_value: Value to check sigio signal.
|
| - """
|
| - fd = self._open([port])[0]
|
| - self.poll_fds[fd] = [poll_value, 0]
|
| - print "PASS: Events: " + VirtioGuest.pollmask_to_str(poll_value)
|
| -
|
| -
|
| - def catching_signal(self):
|
| - """
|
| - return: True if should set catch signal, False if ignore signal and
|
| - none when configuration is not changed.
|
| - """
|
| - ret = self.catch_signal
|
| - self.catch_signal = None
|
| - return ret
|
| -
|
| -
|
| - def async(self, port, mode=True, exp_val = 0):
|
| - """
|
| - Set port function mode async/sync.
|
| -
|
| - @param port: port which should be pooled.
|
| - @param mode: False to set sync mode, True for sync mode.
|
| - @param exp_val: Value which should be pooled.
|
| - """
|
| - fd = self._open([port])[0]
|
| -
|
| - try:
|
| - fcntl.fcntl(fd, fcntl.F_SETOWN, os.getpid())
|
| - fl = fcntl.fcntl(fd, fcntl.F_GETFL)
|
| -
|
| - self.use_config.clear()
|
| - if mode:
|
| - fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_ASYNC)
|
| - self.poll_fds[fd] = [exp_val, 0]
|
| - self.catch_signal = True
|
| - else:
|
| - del self.poll_fds[fd]
|
| - fcntl.fcntl(fd, fcntl.F_SETFL, fl & ~os.O_ASYNC)
|
| - self.catch_signal = False
|
| -
|
| - os.kill(os.getpid(), signal.SIGUSR1)
|
| - self.use_config.wait()
|
| -
|
| - except Exception, inst:
|
| - print "FAIL: Setting (a)sync mode: " + str(inst)
|
| - return
|
| -
|
| - if mode:
|
| - print "PASS: Set to async mode"
|
| - else:
|
| - print "PASS: Set to sync mode"
|
| + print ("PASS: set blocking mode to %s mode" %
|
| + ("blocking" if mode else "nonblocking"))
|
|
|
|
|
| def close(self, file):
|
| @@ -462,29 +336,26 @@ class VirtioGuest:
|
| if path in self.files.keys():
|
| descriptor = self.files[path]
|
| del self.files[path]
|
| - if descriptor != None:
|
| - try:
|
| - os.close(descriptor)
|
| - except Exception, inst:
|
| - print "FAIL: Closing the file: " + str(inst)
|
| - return
|
| + try:
|
| + os.close(descriptor)
|
| + except Exception as inst:
|
| + print "FAIL: Closing the file: " + str(inst)
|
| + return
|
| print "PASS: Close"
|
|
|
|
|
| - def open(self, in_file):
|
| + def open(self, in_files):
|
| """
|
| Direct open devices.
|
|
|
| - @param in_file: Array of files.
|
| + @param in_files: Array of files.
|
| @return: Array of descriptors.
|
| """
|
| - name = self.ports[in_file]["path"]
|
| + name = self.ports[in_files]["path"]
|
| try:
|
| self.files[name] = os.open(name, os.O_RDWR)
|
| - if (self.ports[in_file]["is_console"] == "yes"):
|
| - print os.system("stty -F %s raw -echo" % (name))
|
| print "PASS: Open all filles correctly."
|
| - except Exception, inst:
|
| + except Exception as inst:
|
| print "%s\nFAIL: Failed open file %s" % (str(inst), name)
|
|
|
|
|
| @@ -503,7 +374,7 @@ class VirtioGuest:
|
| in_f = self._open(in_files)
|
| out_f = self._open(out_files)
|
|
|
| - s = self.Switch(in_f, out_f, self.exit_thread, cachesize, mode)
|
| + s = self.switch(in_f, out_f, self.exit_thread, cachesize, mode)
|
| s.start()
|
| self.threads.append(s)
|
| print "PASS: Start switch"
|
| @@ -541,7 +412,7 @@ class VirtioGuest:
|
| self.ports = self._get_port_status()
|
| in_f = self._open([port])
|
|
|
| - self.threads.append(self.Sender(in_f[0], self.exit_thread, length))
|
| + self.threads.append(self.sender(in_f[0], self.exit_thread, length))
|
| print "PASS: Sender prepare"
|
|
|
|
|
| @@ -568,7 +439,7 @@ class VirtioGuest:
|
| data += "%c" % random.randrange(255)
|
| try:
|
| writes = os.write(in_f[0], data)
|
| - except Exception, inst:
|
| + except Exception as inst:
|
| print inst
|
| if not writes:
|
| writes = 0
|
| @@ -576,7 +447,7 @@ class VirtioGuest:
|
| while (writes < length):
|
| try:
|
| writes += os.write(in_f[0], data)
|
| - except Exception, inst:
|
| + except Exception as inst:
|
| print inst
|
| if writes >= length:
|
| print "PASS: Send data length %d" % writes
|
| @@ -598,13 +469,13 @@ class VirtioGuest:
|
| recvs = ""
|
| try:
|
| recvs = os.read(in_f[0], buffer)
|
| - except Exception, inst:
|
| + except Exception as inst:
|
| print inst
|
| if mode:
|
| while (len(recvs) < length):
|
| try:
|
| recvs += os.read(in_f[0], buffer)
|
| - except Exception, inst:
|
| + except Exception as inst:
|
| print inst
|
| if len(recvs) >= length:
|
| print "PASS: Recv data length %d" % len(recvs)
|
| @@ -613,28 +484,6 @@ class VirtioGuest:
|
| (length, len(recvs)))
|
|
|
|
|
| - def clean_port(self, port, buffer=1024):
|
| - in_f = self._open([port])
|
| - ret = select.select([in_f[0]], [], [], 1.0)
|
| - buf = ""
|
| - if ret[0]:
|
| - buf = os.read(in_f[0], buffer)
|
| - print ("PASS: Rest in socket: " + buf)
|
| -
|
| -
|
| -def is_alive():
|
| - """
|
| - Check is only main thread is alive and if guest react.
|
| - """
|
| - if threading.activeCount() == 2:
|
| - print ("PASS: Guest is ok no thread alive")
|
| - else:
|
| - threads = ""
|
| - for thread in threading.enumerate():
|
| - threads += thread.name + ", "
|
| - print ("FAIL: On guest run thread. Active thread:" + threads)
|
| -
|
| -
|
| def compile():
|
| """
|
| Compile virtio_guest.py to speed up.
|
| @@ -642,52 +491,22 @@ def compile():
|
| import py_compile
|
| py_compile.compile(sys.path[0] + "/virtio_guest.py")
|
| print "PASS: compile"
|
| - sys.exit()
|
| -
|
| -
|
| -def worker(virt):
|
| - """
|
| - Worker thread (infinite) loop of virtio_guest.
|
| - """
|
| - print "PASS: Start"
|
| -
|
| - while True:
|
| - str = raw_input()
|
| - try:
|
| - exec str
|
| - except:
|
| - exc_type, exc_value, exc_traceback = sys.exc_info()
|
| - print "On Guest exception from: \n" + "".join(
|
| - traceback.format_exception(exc_type,
|
| - exc_value,
|
| - exc_traceback))
|
| - sys.exit(0)
|
| -
|
| -
|
| -def sigusr_handler(sig, frame):
|
| - pass
|
| + exit(0)
|
|
|
|
|
| def main():
|
| """
|
| - Main function with infinite loop to catch signal from system.
|
| + Main (infinite) loop of virtio_guest.
|
| """
|
| if (len(sys.argv) > 1) and (sys.argv[1] == "-c"):
|
| compile()
|
|
|
| - virt = VirtioGuest()
|
| - slave = Thread(target=worker, args=(virt, ))
|
| - slave.start()
|
| - signal.signal(signal.SIGUSR1, sigusr_handler)
|
| + virt = virtio_guest()
|
| + print "PASS: Start"
|
| +
|
| while True:
|
| - signal.pause()
|
| - catch = virt.catching_signal()
|
| - if catch:
|
| - signal.signal(signal.SIGIO, virt)
|
| - elif catch == False:
|
| - signal.signal(signal.SIGIO, signal.SIG_DFL)
|
| - if (catch != None):
|
| - virt.use_config.set()
|
| + str = raw_input()
|
| + exec str
|
|
|
|
|
| if __name__ == "__main__":
|
|
|