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 |
deleted file mode 100644 |
index 4862ef2b920674e3ca4de6af2ceda036efc810ae..0000000000000000000000000000000000000000 |
--- a/client/tests/kvm/scripts/virtio_guest.py |
+++ /dev/null |
@@ -1,513 +0,0 @@ |
-#!/usr/bin/python |
-# -*- coding: utf-8 -*- |
-""" |
-Auxiliary script used to send data between ports on guests. |
- |
-@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, fcntl, array, subprocess |
- |
-DEBUGPATH = "/sys/kernel/debug" |
-SYSFSPATH = "/sys/class/virtio-ports/" |
- |
- |
-class virtio_guest(): |
- |
- LOOP_NONE = 0 |
- LOOP_POLL = 1 |
- LOOP_SELECT = 2 |
- |
- def __init__(self): |
- self.files = {} |
- self.exit_thread = threading.Event() |
- self.threads = [] |
- self.ports = {} |
- |
- |
- def _readfile(self, name): |
- """ |
- Read file and return content as string |
- |
- @param name: Name of file |
- @return: Content of file as string |
- """ |
- out = "" |
- try: |
- f = open(name, "r") |
- out = f.read() |
- f.close() |
- except: |
- print "FAIL: Cannot open file %s" % (name) |
- |
- return out |
- |
- |
- def _get_port_status(self): |
- """ |
- Get info about ports from kernel debugfs. |
- |
- @return: Ports dictionary of port properties |
- """ |
- ports = {} |
- not_present_msg = "FAIL: There's no virtio-ports dir in debugfs" |
- if (not os.path.ismount(DEBUGPATH)): |
- os.system('mount -t debugfs none %s' % (DEBUGPATH)) |
- try: |
- if not os.path.isdir('%s/virtio-ports' % (DEBUGPATH)): |
- print not_present_msg |
- except: |
- print not_present_msg |
- else: |
- viop_names = os.listdir('%s/virtio-ports' % (DEBUGPATH)) |
- for name in viop_names: |
- f = open("%s/virtio-ports/%s" % (DEBUGPATH, name), 'r') |
- port = {} |
- for line in iter(f): |
- m = re.match("(\S+): (\S+)", line) |
- port[m.group(1)] = m.group(2) |
- |
- if (port['is_console'] == "yes"): |
- port["path"] = "/dev/hvc%s" % (port["console_vtermno"]) |
- # Console works like a serialport |
- else: |
- port["path"] = "/dev/%s" % name |
- |
- if (not os.path.exists(port['path'])): |
- print "FAIL: %s not exist" % port['path'] |
- |
- sysfspath = SYSFSPATH + name |
- if (not os.path.isdir(sysfspath)): |
- print "FAIL: %s not exist" % (sysfspath) |
- |
- info_name = sysfspath + "/name" |
- port_name = self._readfile(info_name).strip() |
- if (port_name != port["name"]): |
- print ("FAIL: Port info not match \n%s - %s\n%s - %s" % |
- (info_name , port_name, |
- "%s/virtio-ports/%s" % (DEBUGPATH, name), |
- port["name"])) |
- |
- ports[port['name']] = port |
- f.close() |
- |
- return ports |
- |
- |
- def init(self, in_files): |
- """ |
- Init and check port properties. |
- """ |
- self.ports = self._get_port_status() |
- |
- for item in in_files: |
- if (item[1] != self.ports[item[0]]["is_console"]): |
- print self.ports |
- print "FAIL: Host console is not like console on guest side\n" |
- print "PASS: Init and check virtioconsole files in system." |
- |
- |
- class switch(Thread): |
- """ |
- Thread that sends data between ports. |
- """ |
- def __init__ (self, in_files, out_files, event, |
- cachesize=1024, method=0): |
- """ |
- @param in_files: Array of input files. |
- @param out_files: Array of output files. |
- @param method: Method of read/write access. |
- @param cachesize: Block to receive and send. |
- """ |
- Thread.__init__(self) |
- |
- self.in_files = in_files |
- self.out_files = out_files |
- self.exit_thread = event |
- self.method = method |
- |
- self.cachesize = cachesize |
- |
- |
- def _none_mode(self): |
- """ |
- Read and write to device in blocking mode |
- """ |
- data = "" |
- while not self.exit_thread.isSet(): |
- data = "" |
- for desc in self.in_files: |
- data += os.read(desc, self.cachesize) |
- if data != "": |
- for desc in self.out_files: |
- os.write(desc, data) |
- |
- |
- def _poll_mode(self): |
- """ |
- Read and write to device in polling mode. |
- """ |
- |
- pi = select.poll() |
- po = select.poll() |
- |
- for fd in self.in_files: |
- pi.register(fd, select.POLLIN) |
- |
- for fd in self.out_files: |
- po.register(fd, select.POLLOUT) |
- |
- while not self.exit_thread.isSet(): |
- data = "" |
- t_out = self.out_files |
- |
- readyf = pi.poll(1.0) |
- for i in readyf: |
- data += os.read(i[0], self.cachesize) |
- |
- if data != "": |
- while ((len(t_out) != len(readyf)) and not |
- self.exit_thread.isSet()): |
- readyf = po.poll(1.0) |
- for desc in t_out: |
- os.write(desc, data) |
- |
- |
- def _select_mode(self): |
- """ |
- Read and write to device in selecting mode. |
- """ |
- while not self.exit_thread.isSet(): |
- ret = select.select(self.in_files, [], [], 1.0) |
- data = "" |
- if ret[0] != []: |
- for desc in ret[0]: |
- data += os.read(desc, self.cachesize) |
- if data != "": |
- ret = select.select([], self.out_files, [], 1.0) |
- while ((len(self.out_files) != len(ret[1])) and not |
- self.exit_thread.isSet()): |
- ret = select.select([], self.out_files, [], 1.0) |
- for desc in ret[1]: |
- os.write(desc, data) |
- |
- |
- def run(self): |
- if (self.method == virtio_guest.LOOP_POLL): |
- self._poll_mode() |
- elif (self.method == virtio_guest.LOOP_SELECT): |
- self._select_mode() |
- else: |
- self._none_mode() |
- |
- |
- class sender(Thread): |
- """ |
- Creates a thread which sends random blocks of data to dst port. |
- """ |
- def __init__(self, port, event, length): |
- """ |
- @param port: Destination port |
- @param length: Length of the random data block |
- """ |
- Thread.__init__(self) |
- self.port = port |
- self.exit_thread = event |
- self.data = array.array('L') |
- for i in range(max(length / self.data.itemsize, 1)): |
- self.data.append(random.randrange(sys.maxint)) |
- |
- def run(self): |
- while not self.exit_thread.isSet(): |
- os.write(self.port, self.data) |
- |
- |
- def _open(self, in_files): |
- """ |
- Open devices and return array of descriptors |
- |
- @param in_files: Files array |
- @return: Array of descriptor |
- """ |
- f = [] |
- |
- for item in in_files: |
- name = self.ports[item]["path"] |
- if (name in self.files): |
- f.append(self.files[name]) |
- else: |
- try: |
- self.files[name] = os.open(name, os.O_RDWR) |
- if (self.ports[item]["is_console"] == "yes"): |
- print os.system("stty -F %s raw -echo" % (name)) |
- print os.system("stty -F %s -a" % (name)) |
- f.append(self.files[name]) |
- except Exception as inst: |
- print "FAIL: Failed to open file %s" % (name) |
- raise inst |
- return f |
- |
- |
- def poll(self, port, expected, timeout=500): |
- """ |
- Pool event from device and print event like text. |
- |
- @param file: Device. |
- """ |
- in_f = self._open([port]) |
- |
- p = select.poll() |
- p.register(in_f[0]) |
- |
- mask = p.poll(timeout) |
- |
- 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 " |
- |
- if (mask[0][1] & expected) == expected: |
- print "PASS: Events: " + str |
- else: |
- print "FAIL: Events: " + str |
- |
- |
- def blocking(self, port, mode=False): |
- """ |
- Set port function mode blocking/nonblocking |
- |
- @param port: port to set mode |
- @param mode: False to set nonblock mode, True for block mode |
- """ |
- path = self.ports[port]["path"] |
- fd = self.files[path] |
- |
- try: |
- fl = fcntl.fcntl(fd, fcntl.F_GETFL) |
- if not mode: |
- fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) |
- else: |
- fcntl.fcntl(fd, fcntl.F_SETFL, fl & ~os.O_NONBLOCK) |
- |
- except Exception as inst: |
- print "FAIL: Setting (non)blocking mode: " + str(inst) |
- return |
- |
- print ("PASS: set blocking mode to %s mode" % |
- ("blocking" if mode else "nonblocking")) |
- |
- |
- def close(self, file): |
- """ |
- Close open port. |
- |
- @param file: File to close. |
- """ |
- descriptor = None |
- path = self.ports[file]["path"] |
- if path != None: |
- if path in self.files.keys(): |
- descriptor = self.files[path] |
- del self.files[path] |
- try: |
- os.close(descriptor) |
- except Exception as inst: |
- print "FAIL: Closing the file: " + str(inst) |
- return |
- print "PASS: Close" |
- |
- |
- def open(self, in_files): |
- """ |
- Direct open devices. |
- |
- @param in_files: Array of files. |
- @return: Array of descriptors. |
- """ |
- name = self.ports[in_files]["path"] |
- try: |
- self.files[name] = os.open(name, os.O_RDWR) |
- print "PASS: Open all filles correctly." |
- except Exception as inst: |
- print "%s\nFAIL: Failed open file %s" % (str(inst), name) |
- |
- |
- def loopback(self, in_files, out_files, cachesize=1024, mode=LOOP_NONE): |
- """ |
- Start a switch thread. |
- |
- (There is a problem with multiple opens of a single file). |
- |
- @param in_files: Array of input files. |
- @param out_files: Array of output files. |
- @param cachesize: Cachesize. |
- """ |
- self.ports = self._get_port_status() |
- |
- 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.start() |
- self.threads.append(s) |
- print "PASS: Start switch" |
- |
- |
- def exit_threads(self): |
- """ |
- Function end all running data switch. |
- """ |
- self.exit_thread.set() |
- for th in self.threads: |
- print "join" |
- th.join() |
- self.exit_thread.clear() |
- |
- del self.threads[:] |
- for desc in self.files.itervalues(): |
- os.close(desc) |
- self.files.clear() |
- print "PASS: All threads finished." |
- |
- |
- def die(self): |
- """ |
- Quit consoleswitch. |
- """ |
- self.exit_threads() |
- exit() |
- |
- |
- def send_loop_init(self, port, length): |
- """ |
- Prepares the sender thread. Requires clean thread structure. |
- """ |
- self.ports = self._get_port_status() |
- in_f = self._open([port]) |
- |
- self.threads.append(self.sender(in_f[0], self.exit_thread, length)) |
- print "PASS: Sender prepare" |
- |
- |
- def send_loop(self): |
- """ |
- Start sender data transfer. Requires senderprepare run first. |
- """ |
- self.threads[0].start() |
- print "PASS: Sender start" |
- |
- |
- def send(self, port, length=1, mode=True): |
- """ |
- Send a data of some length |
- |
- @param port: Port to write data |
- @param length: Length of data |
- @param mode: True = loop mode, False = one shoot mode |
- """ |
- in_f = self._open([port]) |
- |
- data = "" |
- while len(data) < length: |
- data += "%c" % random.randrange(255) |
- try: |
- writes = os.write(in_f[0], data) |
- except Exception as inst: |
- print inst |
- if not writes: |
- writes = 0 |
- if mode: |
- while (writes < length): |
- try: |
- writes += os.write(in_f[0], data) |
- except Exception as inst: |
- print inst |
- if writes >= length: |
- print "PASS: Send data length %d" % writes |
- else: |
- print ("FAIL: Partial send: desired %d, transfered %d" % |
- (length, writes)) |
- |
- |
- def recv(self, port, length=1, buffer=1024, mode=True): |
- """ |
- Recv a data of some length |
- |
- @param port: Port to write data |
- @param length: Length of data |
- @param mode: True = loop mode, False = one shoot mode |
- """ |
- in_f = self._open([port]) |
- |
- recvs = "" |
- try: |
- recvs = os.read(in_f[0], buffer) |
- except Exception as inst: |
- print inst |
- if mode: |
- while (len(recvs) < length): |
- try: |
- recvs += os.read(in_f[0], buffer) |
- except Exception as inst: |
- print inst |
- if len(recvs) >= length: |
- print "PASS: Recv data length %d" % len(recvs) |
- else: |
- print ("FAIL: Partial recv: desired %d, transfered %d" % |
- (length, len(recvs))) |
- |
- |
-def compile(): |
- """ |
- Compile virtio_guest.py to speed up. |
- """ |
- import py_compile |
- py_compile.compile(sys.path[0] + "/virtio_guest.py") |
- print "PASS: compile" |
- exit(0) |
- |
- |
-def main(): |
- """ |
- Main (infinite) loop of virtio_guest. |
- """ |
- if (len(sys.argv) > 1) and (sys.argv[1] == "-c"): |
- compile() |
- |
- virt = virtio_guest() |
- print "PASS: Start" |
- |
- while True: |
- str = raw_input() |
- exec str |
- |
- |
-if __name__ == "__main__": |
- main() |