KVM test: Add helpers to control the TAP/bridge
[autotest-zwu.git] / client / virt / kvm_monitor.py
blobaff716a56b8131098c1e3e0481ad7e8c2d099afb
1 """
2 Interfaces to the QEMU monitor.
4 @copyright: 2008-2010 Red Hat Inc.
5 """
7 import socket, time, threading, logging, select
8 import virt_utils
9 try:
10 import json
11 except ImportError:
12 logging.warning("Could not import json module. "
13 "QMP monitor functionality disabled.")
16 class MonitorError(Exception):
17 pass
20 class MonitorConnectError(MonitorError):
21 pass
24 class MonitorSocketError(MonitorError):
25 def __init__(self, msg, e):
26 Exception.__init__(self, msg, e)
27 self.msg = msg
28 self.e = e
30 def __str__(self):
31 return "%s (%s)" % (self.msg, self.e)
34 class MonitorLockError(MonitorError):
35 pass
38 class MonitorProtocolError(MonitorError):
39 pass
42 class MonitorNotSupportedError(MonitorError):
43 pass
46 class QMPCmdError(MonitorError):
47 def __init__(self, cmd, qmp_args, data):
48 MonitorError.__init__(self, cmd, qmp_args, data)
49 self.cmd = cmd
50 self.qmp_args = qmp_args
51 self.data = data
53 def __str__(self):
54 return ("QMP command %r failed (arguments: %r, "
55 "error message: %r)" % (self.cmd, self.qmp_args, self.data))
58 class Monitor:
59 """
60 Common code for monitor classes.
61 """
63 def __init__(self, name, filename):
64 """
65 Initialize the instance.
67 @param name: Monitor identifier (a string)
68 @param filename: Monitor socket filename
69 @raise MonitorConnectError: Raised if the connection fails
70 """
71 self.name = name
72 self.filename = filename
73 self._lock = threading.RLock()
74 self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
76 try:
77 self._socket.connect(filename)
78 except socket.error:
79 raise MonitorConnectError("Could not connect to monitor socket")
82 def __del__(self):
83 # Automatically close the connection when the instance is garbage
84 # collected
85 try:
86 self._socket.shutdown(socket.SHUT_RDWR)
87 except socket.error:
88 pass
89 self._socket.close()
92 # The following two functions are defined to make sure the state is set
93 # exclusively by the constructor call as specified in __getinitargs__().
95 def __getstate__(self):
96 pass
99 def __setstate__(self, state):
100 pass
103 def __getinitargs__(self):
104 # Save some information when pickling -- will be passed to the
105 # constructor upon unpickling
106 return self.name, self.filename, True
109 def _acquire_lock(self, timeout=20):
110 end_time = time.time() + timeout
111 while time.time() < end_time:
112 if self._lock.acquire(False):
113 return True
114 time.sleep(0.05)
115 return False
118 def _data_available(self, timeout=0):
119 timeout = max(0, timeout)
120 return bool(select.select([self._socket], [], [], timeout)[0])
123 def _recvall(self):
124 s = ""
125 while self._data_available():
126 try:
127 data = self._socket.recv(1024)
128 except socket.error, e:
129 raise MonitorSocketError("Could not receive data from monitor",
131 if not data:
132 break
133 s += data
134 return s
137 def is_responsive(self):
139 Return True iff the monitor is responsive.
141 try:
142 self.verify_responsive()
143 return True
144 except MonitorError:
145 return False
148 class HumanMonitor(Monitor):
150 Wraps "human monitor" commands.
153 def __init__(self, name, filename, suppress_exceptions=False):
155 Connect to the monitor socket and find the (qemu) prompt.
157 @param name: Monitor identifier (a string)
158 @param filename: Monitor socket filename
159 @raise MonitorConnectError: Raised if the connection fails and
160 suppress_exceptions is False
161 @raise MonitorProtocolError: Raised if the initial (qemu) prompt isn't
162 found and suppress_exceptions is False
163 @note: Other exceptions may be raised. See cmd()'s
164 docstring.
166 try:
167 Monitor.__init__(self, name, filename)
169 self.protocol = "human"
171 # Find the initial (qemu) prompt
172 s, o = self._read_up_to_qemu_prompt(20)
173 if not s:
174 raise MonitorProtocolError("Could not find (qemu) prompt "
175 "after connecting to monitor. "
176 "Output so far: %r" % o)
178 # Save the output of 'help' for future use
179 self._help_str = self.cmd("help", debug=False)
181 except MonitorError, e:
182 if suppress_exceptions:
183 logging.warn(e)
184 else:
185 raise
188 # Private methods
190 def _read_up_to_qemu_prompt(self, timeout=20):
191 s = ""
192 end_time = time.time() + timeout
193 while self._data_available(end_time - time.time()):
194 data = self._recvall()
195 if not data:
196 break
197 s += data
198 try:
199 if s.splitlines()[-1].split()[-1] == "(qemu)":
200 return True, "\n".join(s.splitlines()[:-1])
201 except IndexError:
202 continue
203 return False, "\n".join(s.splitlines())
206 def _send(self, cmd):
208 Send a command without waiting for output.
210 @param cmd: Command to send
211 @raise MonitorLockError: Raised if the lock cannot be acquired
212 @raise MonitorSocketError: Raised if a socket error occurs
214 if not self._acquire_lock(20):
215 raise MonitorLockError("Could not acquire exclusive lock to send "
216 "monitor command '%s'" % cmd)
218 try:
219 try:
220 self._socket.sendall(cmd + "\n")
221 except socket.error, e:
222 raise MonitorSocketError("Could not send monitor command %r" %
223 cmd, e)
225 finally:
226 self._lock.release()
229 # Public methods
231 def cmd(self, command, timeout=20, debug=True):
233 Send command to the monitor.
235 @param command: Command to send to the monitor
236 @param timeout: Time duration to wait for the (qemu) prompt to return
237 @param debug: Whether to print the commands being sent and responses
238 @return: Output received from the monitor
239 @raise MonitorLockError: Raised if the lock cannot be acquired
240 @raise MonitorSocketError: Raised if a socket error occurs
241 @raise MonitorProtocolError: Raised if the (qemu) prompt cannot be
242 found after sending the command
244 if debug:
245 logging.debug("(monitor %s) Sending command '%s'",
246 self.name, command)
247 if not self._acquire_lock(20):
248 raise MonitorLockError("Could not acquire exclusive lock to send "
249 "monitor command '%s'" % command)
251 try:
252 # Read any data that might be available
253 self._recvall()
254 # Send command
255 self._send(command)
256 # Read output
257 s, o = self._read_up_to_qemu_prompt(timeout)
258 # Remove command echo from output
259 o = "\n".join(o.splitlines()[1:])
260 # Report success/failure
261 if s:
262 if debug and o:
263 logging.debug("(monitor %s) "
264 "Response to '%s'", self.name,
265 command)
266 for l in o.splitlines():
267 logging.debug("(monitor %s) %s", self.name, l)
268 return o
269 else:
270 msg = ("Could not find (qemu) prompt after command '%s'. "
271 "Output so far: %r" % (command, o))
272 raise MonitorProtocolError(msg)
274 finally:
275 self._lock.release()
278 def verify_responsive(self):
280 Make sure the monitor is responsive by sending a command.
282 self.cmd("info status", debug=False)
285 def verify_status(self, status):
287 Verify VM status
289 @param status: Optional VM status, 'running' or 'paused'
290 @return: return True if VM status is same as we expected
292 o = self.cmd("info status", debug=False)
293 if status=='paused' or status=='running':
294 return (status in o)
297 # Command wrappers
298 # Notes:
299 # - All of the following commands raise exceptions in a similar manner to
300 # cmd().
301 # - A command wrapper should use self._help_str if it requires information
302 # about the monitor's capabilities.
304 def quit(self):
306 Send "quit" without waiting for output.
308 self._send("quit")
311 def info(self, what):
313 Request info about something and return the output.
315 return self.cmd("info %s" % what)
318 def query(self, what):
320 Alias for info.
322 return self.info(what)
325 def screendump(self, filename, debug=True):
327 Request a screendump.
329 @param filename: Location for the screendump
330 @return: The command's output
332 return self.cmd(command="screendump %s" % filename, debug=debug)
335 def migrate(self, uri, full_copy=False, incremental_copy=False, wait=False):
337 Migrate.
339 @param uri: destination URI
340 @param full_copy: If true, migrate with full disk copy
341 @param incremental_copy: If true, migrate with incremental disk copy
342 @param wait: If true, wait for completion
343 @return: The command's output
345 cmd = "migrate"
346 if not wait:
347 cmd += " -d"
348 if full_copy:
349 cmd += " -b"
350 if incremental_copy:
351 cmd += " -i"
352 cmd += " %s" % uri
353 return self.cmd(cmd)
356 def migrate_set_speed(self, value):
358 Set maximum speed (in bytes/sec) for migrations.
360 @param value: Speed in bytes/sec
361 @return: The command's output
363 return self.cmd("migrate_set_speed %s" % value)
366 def sendkey(self, keystr, hold_time=1):
368 Send key combination to VM.
370 @param keystr: Key combination string
371 @param hold_time: Hold time in ms (should normally stay 1 ms)
372 @return: The command's output
374 return self.cmd("sendkey %s %s" % (keystr, hold_time))
377 def mouse_move(self, dx, dy):
379 Move mouse.
381 @param dx: X amount
382 @param dy: Y amount
383 @return: The command's output
385 return self.cmd("mouse_move %d %d" % (dx, dy))
388 def mouse_button(self, state):
390 Set mouse button state.
392 @param state: Button state (1=L, 2=M, 4=R)
393 @return: The command's output
395 return self.cmd("mouse_button %d" % state)
398 class QMPMonitor(Monitor):
400 Wraps QMP monitor commands.
403 def __init__(self, name, filename, suppress_exceptions=False):
405 Connect to the monitor socket, read the greeting message and issue the
406 qmp_capabilities command. Also make sure the json module is available.
408 @param name: Monitor identifier (a string)
409 @param filename: Monitor socket filename
410 @raise MonitorConnectError: Raised if the connection fails and
411 suppress_exceptions is False
412 @raise MonitorProtocolError: Raised if the no QMP greeting message is
413 received and suppress_exceptions is False
414 @raise MonitorNotSupportedError: Raised if json isn't available and
415 suppress_exceptions is False
416 @note: Other exceptions may be raised if the qmp_capabilities command
417 fails. See cmd()'s docstring.
419 try:
420 Monitor.__init__(self, name, filename)
422 self.protocol = "qmp"
423 self._greeting = None
424 self._events = []
426 # Make sure json is available
427 try:
428 json
429 except NameError:
430 raise MonitorNotSupportedError("QMP requires the json module "
431 "(Python 2.6 and up)")
433 # Read greeting message
434 end_time = time.time() + 20
435 while time.time() < end_time:
436 for obj in self._read_objects():
437 if "QMP" in obj:
438 self._greeting = obj
439 break
440 if self._greeting:
441 break
442 time.sleep(0.1)
443 else:
444 raise MonitorProtocolError("No QMP greeting message received")
446 # Issue qmp_capabilities
447 self.cmd("qmp_capabilities")
449 except MonitorError, e:
450 if suppress_exceptions:
451 logging.warn(e)
452 else:
453 raise
456 # Private methods
458 def _build_cmd(self, cmd, args=None, id=None):
459 obj = {"execute": cmd}
460 if args is not None:
461 obj["arguments"] = args
462 if id is not None:
463 obj["id"] = id
464 return obj
467 def _read_objects(self, timeout=5):
469 Read lines from the monitor and try to decode them.
470 Stop when all available lines have been successfully decoded, or when
471 timeout expires. If any decoded objects are asynchronous events, store
472 them in self._events. Return all decoded objects.
474 @param timeout: Time to wait for all lines to decode successfully
475 @return: A list of objects
477 if not self._data_available():
478 return []
479 s = ""
480 end_time = time.time() + timeout
481 while self._data_available(end_time - time.time()):
482 s += self._recvall()
483 # Make sure all lines are decodable
484 for line in s.splitlines():
485 if line:
486 try:
487 json.loads(line)
488 except:
489 # Found an incomplete or broken line -- keep reading
490 break
491 else:
492 # All lines are OK -- stop reading
493 break
494 # Decode all decodable lines
495 objs = []
496 for line in s.splitlines():
497 try:
498 objs += [json.loads(line)]
499 except:
500 pass
501 # Keep track of asynchronous events
502 self._events += [obj for obj in objs if "event" in obj]
503 return objs
506 def _send(self, data):
508 Send raw data without waiting for response.
510 @param data: Data to send
511 @raise MonitorSocketError: Raised if a socket error occurs
513 try:
514 self._socket.sendall(data)
515 except socket.error, e:
516 raise MonitorSocketError("Could not send data: %r" % data, e)
519 def _get_response(self, id=None, timeout=20):
521 Read a response from the QMP monitor.
523 @param id: If not None, look for a response with this id
524 @param timeout: Time duration to wait for response
525 @return: The response dict, or None if none was found
527 end_time = time.time() + timeout
528 while self._data_available(end_time - time.time()):
529 for obj in self._read_objects():
530 if isinstance(obj, dict):
531 if id is not None and obj.get("id") != id:
532 continue
533 if "return" in obj or "error" in obj:
534 return obj
537 # Public methods
539 def cmd(self, cmd, args=None, timeout=20, debug=True):
541 Send a QMP monitor command and return the response.
543 Note: an id is automatically assigned to the command and the response
544 is checked for the presence of the same id.
546 @param cmd: Command to send
547 @param args: A dict containing command arguments, or None
548 @param timeout: Time duration to wait for response
549 @return: The response received
550 @raise MonitorLockError: Raised if the lock cannot be acquired
551 @raise MonitorSocketError: Raised if a socket error occurs
552 @raise MonitorProtocolError: Raised if no response is received
553 @raise QMPCmdError: Raised if the response is an error message
554 (the exception's args are (cmd, args, data) where data is the
555 error data)
557 if debug:
558 logging.debug("(monitor %s) Sending command '%s'",
559 self.name, cmd)
560 if not self._acquire_lock(20):
561 raise MonitorLockError("Could not acquire exclusive lock to send "
562 "QMP command '%s'" % cmd)
564 try:
565 # Read any data that might be available
566 self._read_objects()
567 # Send command
568 id = virt_utils.generate_random_string(8)
569 self._send(json.dumps(self._build_cmd(cmd, args, id)) + "\n")
570 # Read response
571 r = self._get_response(id, timeout)
572 if r is None:
573 raise MonitorProtocolError("Received no response to QMP "
574 "command '%s', or received a "
575 "response with an incorrect id"
576 % cmd)
577 if "return" in r:
578 if debug and r["return"]:
579 logging.debug("(monitor %s) "
580 "Response to '%s'", self.name, cmd)
581 o = str(r["return"])
582 for l in o.splitlines():
583 logging.debug("(monitor %s) %s", self.name, l)
584 return r["return"]
585 if "error" in r:
586 raise QMPCmdError(cmd, args, r["error"])
588 finally:
589 self._lock.release()
592 def cmd_raw(self, data, timeout=20):
594 Send a raw string to the QMP monitor and return the response.
595 Unlike cmd(), return the raw response dict without performing any
596 checks on it.
598 @param data: The data to send
599 @param timeout: Time duration to wait for response
600 @return: The response received
601 @raise MonitorLockError: Raised if the lock cannot be acquired
602 @raise MonitorSocketError: Raised if a socket error occurs
603 @raise MonitorProtocolError: Raised if no response is received
605 if not self._acquire_lock(20):
606 raise MonitorLockError("Could not acquire exclusive lock to send "
607 "data: %r" % data)
609 try:
610 self._read_objects()
611 self._send(data)
612 r = self._get_response(None, timeout)
613 if r is None:
614 raise MonitorProtocolError("Received no response to data: %r" %
615 data)
616 return r
618 finally:
619 self._lock.release()
622 def cmd_obj(self, obj, timeout=20):
624 Transform a Python object to JSON, send the resulting string to the QMP
625 monitor, and return the response.
626 Unlike cmd(), return the raw response dict without performing any
627 checks on it.
629 @param obj: The object to send
630 @param timeout: Time duration to wait for response
631 @return: The response received
632 @raise MonitorLockError: Raised if the lock cannot be acquired
633 @raise MonitorSocketError: Raised if a socket error occurs
634 @raise MonitorProtocolError: Raised if no response is received
636 return self.cmd_raw(json.dumps(obj) + "\n")
639 def cmd_qmp(self, cmd, args=None, id=None, timeout=20):
641 Build a QMP command from the passed arguments, send it to the monitor
642 and return the response.
643 Unlike cmd(), return the raw response dict without performing any
644 checks on it.
646 @param cmd: Command to send
647 @param args: A dict containing command arguments, or None
648 @param id: An id for the command, or None
649 @param timeout: Time duration to wait for response
650 @return: The response received
651 @raise MonitorLockError: Raised if the lock cannot be acquired
652 @raise MonitorSocketError: Raised if a socket error occurs
653 @raise MonitorProtocolError: Raised if no response is received
655 return self.cmd_obj(self._build_cmd(cmd, args, id), timeout)
658 def verify_responsive(self):
660 Make sure the monitor is responsive by sending a command.
662 self.cmd(cmd="query-status", debug=False)
665 def verify_status(self, status):
667 Verify VM status
669 @param status: Optional VM status, 'running' or 'paused'
670 @return: return True if VM status is same as we expected
672 o = str(self.cmd(cmd="query-status", debug=False))
673 if (status=='paused' and "u'running': False" in o):
674 return True
675 if (status=='running' and "u'running': True" in o):
676 return True
679 def get_events(self):
681 Return a list of the asynchronous events received since the last
682 clear_events() call.
684 @return: A list of events (the objects returned have an "event" key)
685 @raise MonitorLockError: Raised if the lock cannot be acquired
687 if not self._acquire_lock(20):
688 raise MonitorLockError("Could not acquire exclusive lock to read "
689 "QMP events")
690 try:
691 self._read_objects()
692 return self._events[:]
693 finally:
694 self._lock.release()
697 def get_event(self, name):
699 Look for an event with the given name in the list of events.
701 @param name: The name of the event to look for (e.g. 'RESET')
702 @return: An event object or None if none is found
704 for e in self.get_events():
705 if e.get("event") == name:
706 return e
709 def clear_events(self):
711 Clear the list of asynchronous events.
713 @raise MonitorLockError: Raised if the lock cannot be acquired
715 if not self._acquire_lock(20):
716 raise MonitorLockError("Could not acquire exclusive lock to clear "
717 "QMP event list")
718 self._events = []
719 self._lock.release()
722 def get_greeting(self):
724 Return QMP greeting message.
726 return self._greeting
729 # Command wrappers
730 # Note: all of the following functions raise exceptions in a similar manner
731 # to cmd().
733 def quit(self):
735 Send "quit" and return the response.
737 return self.cmd("quit")
740 def info(self, what):
742 Request info about something and return the response.
744 return self.cmd("query-%s" % what)
747 def query(self, what):
749 Alias for info.
751 return self.info(what)
754 def screendump(self, filename, debug=True):
756 Request a screendump.
758 @param filename: Location for the screendump
759 @return: The response to the command
761 args = {"filename": filename}
762 return self.cmd(cmd="screendump", args=args, debug=debug)
765 def migrate(self, uri, full_copy=False, incremental_copy=False, wait=False):
767 Migrate.
769 @param uri: destination URI
770 @param full_copy: If true, migrate with full disk copy
771 @param incremental_copy: If true, migrate with incremental disk copy
772 @param wait: If true, wait for completion
773 @return: The response to the command
775 args = {"uri": uri,
776 "blk": full_copy,
777 "inc": incremental_copy}
778 return self.cmd("migrate", args)
781 def migrate_set_speed(self, value):
783 Set maximum speed (in bytes/sec) for migrations.
785 @param value: Speed in bytes/sec
786 @return: The response to the command
788 args = {"value": value}
789 return self.cmd("migrate_set_speed", args)