| Index: client/tests/kvm/scripts/virtio_console_guest.py
|
| diff --git a/client/tests/kvm/scripts/virtio_console_guest.py b/client/tests/kvm/scripts/virtio_console_guest.py
|
| index 6626593ca3fbef82b0fcbce9ff52b4b79db2ba61..8f0bb9f522ece7d6dd2a0fc22e703f04c6163256 100755
|
| --- a/client/tests/kvm/scripts/virtio_console_guest.py
|
| +++ b/client/tests/kvm/scripts/virtio_console_guest.py
|
| @@ -9,8 +9,8 @@ Auxiliary script used to send data between ports on guests.
|
| """
|
| import threading
|
| from threading import Thread
|
| -import os, select, re, random, sys, array
|
| -import fcntl, traceback, signal
|
| +import os, select, re, random, sys, array, stat
|
| +import fcntl, traceback, signal, time
|
|
|
| DEBUGPATH = "/sys/kernel/debug"
|
| SYSFSPATH = "/sys/class/virtio-ports/"
|
| @@ -547,6 +547,7 @@ class VirtioGuest:
|
| @param in_files: Array of input files.
|
| @param out_files: Array of output files.
|
| @param cachesize: Cachesize.
|
| + @param mode: Mode of switch.
|
| """
|
| self.ports = self._get_port_status()
|
|
|
| @@ -573,7 +574,7 @@ class VirtioGuest:
|
| for desc in self.files.itervalues():
|
| os.close(desc)
|
| self.files.clear()
|
| - print "PASS: All threads finished."
|
| + print "PASS: All threads finished"
|
|
|
|
|
| def die(self):
|
| @@ -702,7 +703,6 @@ def compile():
|
| def guest_exit():
|
| global exiting
|
| exiting = True
|
| - os.kill(os.getpid(), signal.SIGUSR1)
|
|
|
|
|
| def worker(virt):
|
| @@ -710,48 +710,220 @@ def worker(virt):
|
| Worker thread (infinite) loop of virtio_guest.
|
| """
|
| global exiting
|
| - print "PASS: Start"
|
| -
|
| + print "PASS: Daemon start."
|
| + p = select.poll()
|
| + p.register(sys.stdin.fileno())
|
| while not exiting:
|
| - 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))
|
| - print "FAIL: Guest command exception."
|
| + d = p.poll()
|
| + if (d[0][1] == select.POLLIN):
|
| + 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))
|
| + print "FAIL: Guest command exception."
|
| + elif (d[0][1] & select.POLLHUP):
|
| + time.sleep(0.5)
|
|
|
|
|
| def sigusr_handler(sig, frame):
|
| pass
|
|
|
|
|
| +class Daemon:
|
| + """
|
| + Daemonize guest
|
| + """
|
| + def __init__(self, stdin, stdout, stderr):
|
| + """
|
| + Init daemon.
|
| +
|
| + @param stdin: path to stdin file.
|
| + @param stdout: path to stdout file.
|
| + @param stderr: path to stderr file.
|
| + """
|
| + self.stdin = stdin
|
| + self.stdout = stdout
|
| + self.stderr = stderr
|
| +
|
| +
|
| + @staticmethod
|
| + def is_file_open(path):
|
| + """
|
| + Determine process which open file.
|
| +
|
| + @param path: Path to file.
|
| + @return [[pid,mode], ... ].
|
| + """
|
| + opens = []
|
| + pids = os.listdir('/proc')
|
| + for pid in sorted(pids):
|
| + try:
|
| + int(pid)
|
| + except ValueError:
|
| + continue
|
| + fd_dir = os.path.join('/proc', pid, 'fd')
|
| + try:
|
| + for file in os.listdir(fd_dir):
|
| + try:
|
| + p = os.path.join(fd_dir, file)
|
| + link = os.readlink(os.path.join(fd_dir, file))
|
| + if link == path:
|
| + mode = os.lstat(p).st_mode
|
| + opens.append([pid, mode])
|
| + except OSError:
|
| + continue
|
| + except OSError, e:
|
| + if e.errno == 2:
|
| + continue
|
| + raise
|
| + return opens
|
| +
|
| +
|
| + def daemonize(self):
|
| + """
|
| + Run guest as a daemon.
|
| + """
|
| + try:
|
| + pid = os.fork()
|
| + if pid > 0:
|
| + return False
|
| + except OSError, e:
|
| + sys.stderr.write("Daemonize failed: %s\n" % (e))
|
| + sys.exit(1)
|
| +
|
| + os.chdir("/")
|
| + os.setsid()
|
| + os.umask(0)
|
| +
|
| + try:
|
| + pid = os.fork()
|
| + if pid > 0:
|
| + sys.exit(0)
|
| + except OSError, e:
|
| + sys.stderr.write("Daemonize failed: %s\n" % (e))
|
| + sys.exit(1)
|
| +
|
| + sys.stdout.flush()
|
| + sys.stderr.flush()
|
| + si = file(self.stdin,'r')
|
| + so = file(self.stdout,'w')
|
| + se = file(self.stderr,'w')
|
| +
|
| + os.dup2(si.fileno(), sys.stdin.fileno())
|
| + os.dup2(so.fileno(), sys.stdout.fileno())
|
| + os.dup2(se.fileno(), sys.stderr.fileno())
|
| +
|
| + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
|
| + sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)
|
| + return True
|
| +
|
| +
|
| + def start(self):
|
| + """
|
| + Start the daemon
|
| +
|
| + @return: PID of daemon.
|
| + """
|
| + # Check for a pidfile to see if the daemon already runs
|
| + openers = self.is_file_open(self.stdout)
|
| + rundaemon = False
|
| + if len(openers) > 0:
|
| + for i in openers:
|
| + if i[1] & stat.S_IWUSR:
|
| + rundaemon = True
|
| + openers.remove(i)
|
| + if len(openers) > 0:
|
| + for i in openers:
|
| + os.kill(int(i[0]), 9)
|
| + time.sleep(0.3)
|
| +
|
| + # Start the daemon
|
| + if not rundaemon:
|
| + if self.daemonize():
|
| + self.run()
|
| +
|
| +
|
| + def run(self):
|
| + """
|
| + Run guest main thread
|
| + """
|
| + global exiting
|
| + virt = VirtioGuest()
|
| + slave = Thread(target=worker, args=(virt, ))
|
| + slave.start()
|
| + signal.signal(signal.SIGUSR1, sigusr_handler)
|
| + signal.signal(signal.SIGALRM, sigusr_handler)
|
| + while not exiting:
|
| + signal.alarm(1)
|
| + signal.pause()
|
| + catch = virt.catching_signal()
|
| + if catch:
|
| + signal.signal(signal.SIGIO, virt)
|
| + elif catch is False:
|
| + signal.signal(signal.SIGIO, signal.SIG_DFL)
|
| + if catch is not None:
|
| + virt.use_config.set()
|
| + print "PASS: guest_exit"
|
| + sys.exit(0)
|
| +
|
| +
|
| def main():
|
| """
|
| Main function with infinite loop to catch signal from system.
|
| """
|
| if (len(sys.argv) > 1) and (sys.argv[1] == "-c"):
|
| compile()
|
| + stdin = "/tmp/guest_daemon_pi"
|
| + stdout = "/tmp/guest_daemon_po"
|
| + stderr = "/tmp/guest_daemon_pe"
|
|
|
| - global exiting
|
| - virt = VirtioGuest()
|
| - slave = Thread(target=worker, args=(virt, ))
|
| - slave.start()
|
| - signal.signal(signal.SIGUSR1, sigusr_handler)
|
| - while not exiting:
|
| - signal.pause()
|
| - catch = virt.catching_signal()
|
| - if catch:
|
| - signal.signal(signal.SIGIO, virt)
|
| - elif catch is False:
|
| - signal.signal(signal.SIGIO, signal.SIG_DFL)
|
| - if catch is not None:
|
| - virt.use_config.set()
|
| - print "PASS: guest_exit"
|
| + for f in [stdin, stdout, stderr]:
|
| + try:
|
| + os.mkfifo(f)
|
| + except OSError, e:
|
| + if e.errno == 17:
|
| + pass
|
| +
|
| + daemon = Daemon(stdin,
|
| + stdout,
|
| + stderr)
|
| + daemon.start()
|
| +
|
| + d_stdin = os.open(stdin, os.O_WRONLY)
|
| + d_stdout = os.open(stdout, os.O_RDONLY)
|
| + d_stderr = os.open(stderr, os.O_RDONLY)
|
| +
|
| + s_stdin = sys.stdin.fileno()
|
| + s_stdout = sys.stdout.fileno()
|
| + s_stderr = sys.stderr.fileno()
|
| +
|
| + pid = filter(lambda x: x[0] != str(os.getpid()),
|
| + daemon.is_file_open(stdout))[0][0]
|
| +
|
| + print "PASS: Start"
|
|
|
| + while 1:
|
| + ret = select.select([d_stderr,
|
| + d_stdout,
|
| + s_stdin],
|
| + [], [], 1.0)
|
| + if s_stdin in ret[0]:
|
| + os.write(d_stdin,os.read(s_stdin, 1))
|
| + if d_stdout in ret[0]:
|
| + os.write(s_stdout,os.read(d_stdout, 1024))
|
| + if d_stderr in ret[0]:
|
| + os.write(s_stderr,os.read(d_stderr, 1024))
|
| + if not os.path.exists("/proc/" + pid):
|
| + sys.exit(0)
|
| +
|
| + os.close(d_stdin)
|
| + os.close(d_stdout)
|
| + os.close(d_stderr)
|
|
|
| if __name__ == "__main__":
|
| main()
|
|
|