2 Interfaces to the QEMU monitor.
4 @copyright: 2008-2010 Red Hat Inc.
7 import socket
, time
, threading
, logging
, select
12 logging
.warning("Could not import json module. "
13 "QMP monitor functionality disabled.")
16 class MonitorError(Exception):
20 class MonitorConnectError(MonitorError
):
24 class MonitorSocketError(MonitorError
):
25 def __init__(self
, msg
, e
):
26 Exception.__init
__(self
, msg
, e
)
31 return "%s (%s)" % (self
.msg
, self
.e
)
34 class MonitorLockError(MonitorError
):
38 class MonitorProtocolError(MonitorError
):
42 class MonitorNotSupportedError(MonitorError
):
46 class QMPCmdError(MonitorError
):
47 def __init__(self
, cmd
, qmp_args
, data
):
48 MonitorError
.__init
__(self
, cmd
, qmp_args
, data
)
50 self
.qmp_args
= qmp_args
54 return ("QMP command %r failed (arguments: %r, "
55 "error message: %r)" % (self
.cmd
, self
.qmp_args
, self
.data
))
60 Common code for monitor classes.
63 def __init__(self
, name
, filename
):
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
72 self
.filename
= filename
73 self
._lock
= threading
.RLock()
74 self
._socket
= socket
.socket(socket
.AF_UNIX
, socket
.SOCK_STREAM
)
77 self
._socket
.connect(filename
)
79 raise MonitorConnectError("Could not connect to monitor socket")
83 # Automatically close the connection when the instance is garbage
88 # The following two functions are defined to make sure the state is set
89 # exclusively by the constructor call as specified in __getinitargs__().
91 def __getstate__(self
):
95 def __setstate__(self
, state
):
99 def __getinitargs__(self
):
100 # Save some information when pickling -- will be passed to the
101 # constructor upon unpickling
102 return self
.name
, self
.filename
, True
105 def _close_sock(self
):
107 self
._socket
.shutdown(socket
.SHUT_RDWR
)
112 def _acquire_lock(self
, timeout
=20):
113 end_time
= time
.time() + timeout
114 while time
.time() < end_time
:
115 if self
._lock
.acquire(False):
121 def _data_available(self
, timeout
=0):
122 timeout
= max(0, timeout
)
123 return bool(select
.select([self
._socket
], [], [], timeout
)[0])
128 while self
._data
_available
():
130 data
= self
._socket
.recv(1024)
131 except socket
.error
, e
:
132 raise MonitorSocketError("Could not receive data from monitor",
140 def is_responsive(self
):
142 Return True iff the monitor is responsive.
145 self
.verify_responsive()
151 class HumanMonitor(Monitor
):
153 Wraps "human monitor" commands.
156 def __init__(self
, name
, filename
, suppress_exceptions
=False):
158 Connect to the monitor socket and find the (qemu) prompt.
160 @param name: Monitor identifier (a string)
161 @param filename: Monitor socket filename
162 @raise MonitorConnectError: Raised if the connection fails and
163 suppress_exceptions is False
164 @raise MonitorProtocolError: Raised if the initial (qemu) prompt isn't
165 found and suppress_exceptions is False
166 @note: Other exceptions may be raised. See cmd()'s
170 Monitor
.__init
__(self
, name
, filename
)
172 self
.protocol
= "human"
174 # Find the initial (qemu) prompt
175 s
, o
= self
._read
_up
_to
_qemu
_prompt
(20)
178 raise MonitorProtocolError("Could not find (qemu) prompt "
179 "after connecting to monitor. "
180 "Output so far: %r" % o
)
182 # Save the output of 'help' for future use
183 self
._help
_str
= self
.cmd("help", debug
=False)
185 except MonitorError
, e
:
187 if suppress_exceptions
:
195 def _read_up_to_qemu_prompt(self
, timeout
=20):
197 end_time
= time
.time() + timeout
198 while self
._data
_available
(end_time
- time
.time()):
199 data
= self
._recvall
()
204 if s
.splitlines()[-1].split()[-1] == "(qemu)":
205 return True, "\n".join(s
.splitlines()[:-1])
208 return False, "\n".join(s
.splitlines())
211 def _send(self
, cmd
):
213 Send a command without waiting for output.
215 @param cmd: Command to send
216 @raise MonitorLockError: Raised if the lock cannot be acquired
217 @raise MonitorSocketError: Raised if a socket error occurs
219 if not self
._acquire
_lock
(20):
220 raise MonitorLockError("Could not acquire exclusive lock to send "
221 "monitor command '%s'" % cmd
)
225 self
._socket
.sendall(cmd
+ "\n")
226 except socket
.error
, e
:
227 raise MonitorSocketError("Could not send monitor command %r" %
236 def cmd(self
, command
, timeout
=20, debug
=True):
238 Send command to the monitor.
240 @param command: Command to send to the monitor
241 @param timeout: Time duration to wait for the (qemu) prompt to return
242 @param debug: Whether to print the commands being sent and responses
243 @return: Output received from the monitor
244 @raise MonitorLockError: Raised if the lock cannot be acquired
245 @raise MonitorSocketError: Raised if a socket error occurs
246 @raise MonitorProtocolError: Raised if the (qemu) prompt cannot be
247 found after sending the command
250 logging
.debug("(monitor %s) Sending command '%s'",
252 if not self
._acquire
_lock
(20):
253 raise MonitorLockError("Could not acquire exclusive lock to send "
254 "monitor command '%s'" % command
)
257 # Read any data that might be available
262 s
, o
= self
._read
_up
_to
_qemu
_prompt
(timeout
)
263 # Remove command echo from output
264 o
= "\n".join(o
.splitlines()[1:])
265 # Report success/failure
268 logging
.debug("(monitor %s) "
269 "Response to '%s'", self
.name
,
271 for l
in o
.splitlines():
272 logging
.debug("(monitor %s) %s", self
.name
, l
)
275 msg
= ("Could not find (qemu) prompt after command '%s'. "
276 "Output so far: %r" % (command
, o
))
277 raise MonitorProtocolError(msg
)
283 def verify_responsive(self
):
285 Make sure the monitor is responsive by sending a command.
287 self
.cmd("info status", debug
=False)
290 def verify_status(self
, status
):
294 @param status: Optional VM status, 'running' or 'paused'
295 @return: return True if VM status is same as we expected
297 o
= self
.cmd("info status", debug
=False)
298 if status
=='paused' or status
=='running':
304 # - All of the following commands raise exceptions in a similar manner to
306 # - A command wrapper should use self._help_str if it requires information
307 # about the monitor's capabilities.
311 Send "quit" without waiting for output.
316 def info(self
, what
):
318 Request info about something and return the output.
320 return self
.cmd("info %s" % what
)
323 def query(self
, what
):
327 return self
.info(what
)
330 def screendump(self
, filename
, debug
=True):
332 Request a screendump.
334 @param filename: Location for the screendump
335 @return: The command's output
337 return self
.cmd(command
="screendump %s" % filename
, debug
=debug
)
340 def migrate(self
, uri
, full_copy
=False, incremental_copy
=False, wait
=False):
344 @param uri: destination URI
345 @param full_copy: If true, migrate with full disk copy
346 @param incremental_copy: If true, migrate with incremental disk copy
347 @param wait: If true, wait for completion
348 @return: The command's output
361 def migrate_set_speed(self
, value
):
363 Set maximum speed (in bytes/sec) for migrations.
365 @param value: Speed in bytes/sec
366 @return: The command's output
368 return self
.cmd("migrate_set_speed %s" % value
)
371 def sendkey(self
, keystr
, hold_time
=1):
373 Send key combination to VM.
375 @param keystr: Key combination string
376 @param hold_time: Hold time in ms (should normally stay 1 ms)
377 @return: The command's output
379 return self
.cmd("sendkey %s %s" % (keystr
, hold_time
))
382 def mouse_move(self
, dx
, dy
):
388 @return: The command's output
390 return self
.cmd("mouse_move %d %d" % (dx
, dy
))
393 def mouse_button(self
, state
):
395 Set mouse button state.
397 @param state: Button state (1=L, 2=M, 4=R)
398 @return: The command's output
400 return self
.cmd("mouse_button %d" % state
)
403 class QMPMonitor(Monitor
):
405 Wraps QMP monitor commands.
408 def __init__(self
, name
, filename
, suppress_exceptions
=False):
410 Connect to the monitor socket, read the greeting message and issue the
411 qmp_capabilities command. Also make sure the json module is available.
413 @param name: Monitor identifier (a string)
414 @param filename: Monitor socket filename
415 @raise MonitorConnectError: Raised if the connection fails and
416 suppress_exceptions is False
417 @raise MonitorProtocolError: Raised if the no QMP greeting message is
418 received and suppress_exceptions is False
419 @raise MonitorNotSupportedError: Raised if json isn't available and
420 suppress_exceptions is False
421 @note: Other exceptions may be raised if the qmp_capabilities command
422 fails. See cmd()'s docstring.
425 Monitor
.__init
__(self
, name
, filename
)
427 self
.protocol
= "qmp"
428 self
._greeting
= None
431 # Make sure json is available
436 raise MonitorNotSupportedError("QMP requires the json module "
437 "(Python 2.6 and up)")
439 # Read greeting message
440 end_time
= time
.time() + 20
441 while time
.time() < end_time
:
442 for obj
in self
._read
_objects
():
451 raise MonitorProtocolError("No QMP greeting message received")
453 # Issue qmp_capabilities
454 self
.cmd("qmp_capabilities")
456 except MonitorError
, e
:
458 if suppress_exceptions
:
466 def _build_cmd(self
, cmd
, args
=None, id=None):
467 obj
= {"execute": cmd
}
469 obj
["arguments"] = args
475 def _read_objects(self
, timeout
=5):
477 Read lines from the monitor and try to decode them.
478 Stop when all available lines have been successfully decoded, or when
479 timeout expires. If any decoded objects are asynchronous events, store
480 them in self._events. Return all decoded objects.
482 @param timeout: Time to wait for all lines to decode successfully
483 @return: A list of objects
485 if not self
._data
_available
():
488 end_time
= time
.time() + timeout
489 while self
._data
_available
(end_time
- time
.time()):
491 # Make sure all lines are decodable
492 for line
in s
.splitlines():
497 # Found an incomplete or broken line -- keep reading
500 # All lines are OK -- stop reading
502 # Decode all decodable lines
504 for line
in s
.splitlines():
506 objs
+= [json
.loads(line
)]
509 # Keep track of asynchronous events
510 self
._events
+= [obj
for obj
in objs
if "event" in obj
]
514 def _send(self
, data
):
516 Send raw data without waiting for response.
518 @param data: Data to send
519 @raise MonitorSocketError: Raised if a socket error occurs
522 self
._socket
.sendall(data
)
523 except socket
.error
, e
:
524 raise MonitorSocketError("Could not send data: %r" % data
, e
)
527 def _get_response(self
, id=None, timeout
=20):
529 Read a response from the QMP monitor.
531 @param id: If not None, look for a response with this id
532 @param timeout: Time duration to wait for response
533 @return: The response dict, or None if none was found
535 end_time
= time
.time() + timeout
536 while self
._data
_available
(end_time
- time
.time()):
537 for obj
in self
._read
_objects
():
538 if isinstance(obj
, dict):
539 if id is not None and obj
.get("id") != id:
541 if "return" in obj
or "error" in obj
:
547 def cmd(self
, cmd
, args
=None, timeout
=20, debug
=True):
549 Send a QMP monitor command and return the response.
551 Note: an id is automatically assigned to the command and the response
552 is checked for the presence of the same id.
554 @param cmd: Command to send
555 @param args: A dict containing command arguments, or None
556 @param timeout: Time duration to wait for response
557 @return: The response received
558 @raise MonitorLockError: Raised if the lock cannot be acquired
559 @raise MonitorSocketError: Raised if a socket error occurs
560 @raise MonitorProtocolError: Raised if no response is received
561 @raise QMPCmdError: Raised if the response is an error message
562 (the exception's args are (cmd, args, data) where data is the
566 logging
.debug("(monitor %s) Sending command '%s'",
568 if not self
._acquire
_lock
(20):
569 raise MonitorLockError("Could not acquire exclusive lock to send "
570 "QMP command '%s'" % cmd
)
573 # Read any data that might be available
576 id = virt_utils
.generate_random_string(8)
577 self
._send
(json
.dumps(self
._build
_cmd
(cmd
, args
, id)) + "\n")
579 r
= self
._get
_response
(id, timeout
)
581 raise MonitorProtocolError("Received no response to QMP "
582 "command '%s', or received a "
583 "response with an incorrect id"
586 if debug
and r
["return"]:
587 logging
.debug("(monitor %s) "
588 "Response to '%s'", self
.name
, cmd
)
590 for l
in o
.splitlines():
591 logging
.debug("(monitor %s) %s", self
.name
, l
)
594 raise QMPCmdError(cmd
, args
, r
["error"])
600 def cmd_raw(self
, data
, timeout
=20):
602 Send a raw string to the QMP monitor and return the response.
603 Unlike cmd(), return the raw response dict without performing any
606 @param data: The data to send
607 @param timeout: Time duration to wait for response
608 @return: The response received
609 @raise MonitorLockError: Raised if the lock cannot be acquired
610 @raise MonitorSocketError: Raised if a socket error occurs
611 @raise MonitorProtocolError: Raised if no response is received
613 if not self
._acquire
_lock
(20):
614 raise MonitorLockError("Could not acquire exclusive lock to send "
620 r
= self
._get
_response
(None, timeout
)
622 raise MonitorProtocolError("Received no response to data: %r" %
630 def cmd_obj(self
, obj
, timeout
=20):
632 Transform a Python object to JSON, send the resulting string to the QMP
633 monitor, and return the response.
634 Unlike cmd(), return the raw response dict without performing any
637 @param obj: The object to send
638 @param timeout: Time duration to wait for response
639 @return: The response received
640 @raise MonitorLockError: Raised if the lock cannot be acquired
641 @raise MonitorSocketError: Raised if a socket error occurs
642 @raise MonitorProtocolError: Raised if no response is received
644 return self
.cmd_raw(json
.dumps(obj
) + "\n")
647 def cmd_qmp(self
, cmd
, args
=None, id=None, timeout
=20):
649 Build a QMP command from the passed arguments, send it to the monitor
650 and return the response.
651 Unlike cmd(), return the raw response dict without performing any
654 @param cmd: Command to send
655 @param args: A dict containing command arguments, or None
656 @param id: An id for the command, or None
657 @param timeout: Time duration to wait for response
658 @return: The response received
659 @raise MonitorLockError: Raised if the lock cannot be acquired
660 @raise MonitorSocketError: Raised if a socket error occurs
661 @raise MonitorProtocolError: Raised if no response is received
663 return self
.cmd_obj(self
._build
_cmd
(cmd
, args
, id), timeout
)
666 def verify_responsive(self
):
668 Make sure the monitor is responsive by sending a command.
670 self
.cmd(cmd
="query-status", debug
=False)
673 def verify_status(self
, status
):
677 @param status: Optional VM status, 'running' or 'paused'
678 @return: return True if VM status is same as we expected
680 o
= str(self
.cmd(cmd
="query-status", debug
=False))
681 if (status
=='paused' and "u'running': False" in o
):
683 if (status
=='running' and "u'running': True" in o
):
687 def get_events(self
):
689 Return a list of the asynchronous events received since the last
692 @return: A list of events (the objects returned have an "event" key)
693 @raise MonitorLockError: Raised if the lock cannot be acquired
695 if not self
._acquire
_lock
(20):
696 raise MonitorLockError("Could not acquire exclusive lock to read "
700 return self
._events
[:]
705 def get_event(self
, name
):
707 Look for an event with the given name in the list of events.
709 @param name: The name of the event to look for (e.g. 'RESET')
710 @return: An event object or None if none is found
712 for e
in self
.get_events():
713 if e
.get("event") == name
:
717 def clear_events(self
):
719 Clear the list of asynchronous events.
721 @raise MonitorLockError: Raised if the lock cannot be acquired
723 if not self
._acquire
_lock
(20):
724 raise MonitorLockError("Could not acquire exclusive lock to clear "
730 def get_greeting(self
):
732 Return QMP greeting message.
734 return self
._greeting
738 # Note: all of the following functions raise exceptions in a similar manner
743 Send "quit" and return the response.
745 return self
.cmd("quit")
748 def info(self
, what
):
750 Request info about something and return the response.
752 return self
.cmd("query-%s" % what
)
755 def query(self
, what
):
759 return self
.info(what
)
762 def screendump(self
, filename
, debug
=True):
764 Request a screendump.
766 @param filename: Location for the screendump
767 @return: The response to the command
769 args
= {"filename": filename
}
770 return self
.cmd(cmd
="screendump", args
=args
, debug
=debug
)
773 def migrate(self
, uri
, full_copy
=False, incremental_copy
=False, wait
=False):
777 @param uri: destination URI
778 @param full_copy: If true, migrate with full disk copy
779 @param incremental_copy: If true, migrate with incremental disk copy
780 @param wait: If true, wait for completion
781 @return: The response to the command
785 "inc": incremental_copy
}
786 return self
.cmd("migrate", args
)
789 def migrate_set_speed(self
, value
):
791 Set maximum speed (in bytes/sec) for migrations.
793 @param value: Speed in bytes/sec
794 @return: The response to the command
796 args
= {"value": value
}
797 return self
.cmd("migrate_set_speed", args
)