]>
Commit | Line | Data |
---|---|---|
a628daa4 FZ |
1 | # QEMU qtest library |
2 | # | |
3 | # Copyright (C) 2015 Red Hat Inc. | |
4 | # | |
5 | # Authors: | |
6 | # Fam Zheng <famz@redhat.com> | |
7 | # | |
8 | # This work is licensed under the terms of the GNU GPL, version 2. See | |
9 | # the COPYING file in the top-level directory. | |
10 | # | |
11 | # Based on qmp.py. | |
12 | # | |
13 | ||
a628daa4 | 14 | import socket |
66613974 | 15 | import os |
8f8fd9ed | 16 | |
abf0bf99 | 17 | from .machine import QEMUMachine |
a628daa4 | 18 | |
4d934297 | 19 | |
a628daa4 FZ |
20 | class QEMUQtestProtocol(object): |
21 | def __init__(self, address, server=False): | |
22 | """ | |
23 | Create a QEMUQtestProtocol object. | |
24 | ||
25 | @param address: QEMU address, can be either a unix socket path (string) | |
26 | or a tuple in the form ( address, port ) for a TCP | |
27 | connection | |
28 | @param server: server mode, listens on the socket (bool) | |
29 | @raise socket.error on socket connection errors | |
30 | @note No connection is established, this is done by the connect() or | |
31 | accept() methods | |
32 | """ | |
33 | self._address = address | |
34 | self._sock = self._get_sock() | |
a5df73ba | 35 | self._sockfile = None |
a628daa4 FZ |
36 | if server: |
37 | self._sock.bind(self._address) | |
38 | self._sock.listen(1) | |
39 | ||
40 | def _get_sock(self): | |
41 | if isinstance(self._address, tuple): | |
42 | family = socket.AF_INET | |
43 | else: | |
44 | family = socket.AF_UNIX | |
45 | return socket.socket(family, socket.SOCK_STREAM) | |
46 | ||
47 | def connect(self): | |
48 | """ | |
49 | Connect to the qtest socket. | |
50 | ||
51 | @raise socket.error on socket connection errors | |
52 | """ | |
53 | self._sock.connect(self._address) | |
a5df73ba | 54 | self._sockfile = self._sock.makefile() |
a628daa4 FZ |
55 | |
56 | def accept(self): | |
57 | """ | |
58 | Await connection from QEMU. | |
59 | ||
60 | @raise socket.error on socket connection errors | |
61 | """ | |
62 | self._sock, _ = self._sock.accept() | |
a5df73ba | 63 | self._sockfile = self._sock.makefile() |
a628daa4 FZ |
64 | |
65 | def cmd(self, qtest_cmd): | |
66 | """ | |
67 | Send a qtest command on the wire. | |
68 | ||
69 | @param qtest_cmd: qtest command text to be sent | |
70 | """ | |
8eb5e674 | 71 | self._sock.sendall((qtest_cmd + "\n").encode('utf-8')) |
a5df73ba AG |
72 | resp = self._sockfile.readline() |
73 | return resp | |
a628daa4 FZ |
74 | |
75 | def close(self): | |
76 | self._sock.close() | |
a5df73ba | 77 | self._sockfile.close() |
a628daa4 FZ |
78 | |
79 | def settimeout(self, timeout): | |
80 | self._sock.settimeout(timeout) | |
66613974 DB |
81 | |
82 | ||
8f8fd9ed | 83 | class QEMUQtestMachine(QEMUMachine): |
66613974 DB |
84 | '''A QEMU VM''' |
85 | ||
2782fc51 | 86 | def __init__(self, binary, args=None, name=None, test_dir="/var/tmp", |
4c44b4a4 DB |
87 | socket_scm_helper=None): |
88 | if name is None: | |
89 | name = "qemu-%d" % os.getpid() | |
4d934297 LD |
90 | super(QEMUQtestMachine, |
91 | self).__init__(binary, args, name=name, test_dir=test_dir, | |
92 | socket_scm_helper=socket_scm_helper) | |
93 | self._qtest = None | |
66613974 DB |
94 | self._qtest_path = os.path.join(test_dir, name + "-qtest.sock") |
95 | ||
96 | def _base_args(self): | |
4c44b4a4 DB |
97 | args = super(QEMUQtestMachine, self)._base_args() |
98 | args.extend(['-qtest', 'unix:path=' + self._qtest_path, | |
976e8c54 | 99 | '-accel', 'qtest']) |
66613974 DB |
100 | return args |
101 | ||
102 | def _pre_launch(self): | |
4c44b4a4 | 103 | super(QEMUQtestMachine, self)._pre_launch() |
66613974 DB |
104 | self._qtest = QEMUQtestProtocol(self._qtest_path, server=True) |
105 | ||
106 | def _post_launch(self): | |
4c44b4a4 | 107 | super(QEMUQtestMachine, self)._post_launch() |
66613974 DB |
108 | self._qtest.accept() |
109 | ||
110 | def _post_shutdown(self): | |
4c44b4a4 | 111 | super(QEMUQtestMachine, self)._post_shutdown() |
66613974 DB |
112 | self._remove_if_exists(self._qtest_path) |
113 | ||
114 | def qtest(self, cmd): | |
115 | '''Send a qtest command to guest''' | |
116 | return self._qtest.cmd(cmd) |