virt.virt_test_utils: run_autotest - 'tar' needs relative paths to strip the leading '/'
[autotest-zwu.git] / client / virt / kvm_monitor.py
blob3980da888030d41b8590065867057cbd0490eab7
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 self._close_sock()
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):
92 pass
95 def __setstate__(self, state):
96 pass
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):
106 try:
107 self._socket.shutdown(socket.SHUT_RDWR)
108 except socket.error:
109 pass
110 self._socket.close()
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):
116 return True
117 time.sleep(0.05)
118 return False
121 def _data_available(self, timeout=0):
122 timeout = max(0, timeout)
123 return bool(select.select([self._socket], [], [], timeout)[0])
126 def _recvall(self):
127 s = ""
128 while self._data_available():
129 try:
130 data = self._socket.recv(1024)
131 except socket.error, e:
132 raise MonitorSocketError("Could not receive data from monitor",
134 if not data:
135 break
136 s += data
137 return s
140 def is_responsive(self):
142 Return True iff the monitor is responsive.
144 try:
145 self.verify_responsive()
146 return True
147 except MonitorError:
148 return False
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
167 docstring.
169 try:
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)
176 if not s:
177 self._close_sock()
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:
186 self._close_sock()
187 if suppress_exceptions:
188 logging.warn(e)
189 else:
190 raise
193 # Private methods
195 def _read_up_to_qemu_prompt(self, timeout=20):
196 s = ""
197 end_time = time.time() + timeout
198 while self._data_available(end_time - time.time()):
199 data = self._recvall()
200 if not data:
201 break
202 s += data
203 try:
204 if s.splitlines()[-1].split()[-1] == "(qemu)":
205 return True, "\n".join(s.splitlines()[:-1])
206 except IndexError:
207 continue
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)
223 try:
224 try:
225 self._socket.sendall(cmd + "\n")
226 except socket.error, e:
227 raise MonitorSocketError("Could not send monitor command %r" %
228 cmd, e)
230 finally:
231 self._lock.release()
234 # Public methods
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
249 if debug:
250 logging.debug("(monitor %s) Sending command '%s'",
251 self.name, command)
252 if not self._acquire_lock(20):
253 raise MonitorLockError("Could not acquire exclusive lock to send "
254 "monitor command '%s'" % command)
256 try:
257 # Read any data that might be available
258 self._recvall()
259 # Send command
260 self._send(command)
261 # Read output
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
266 if s:
267 if debug and o:
268 logging.debug("(monitor %s) "
269 "Response to '%s'", self.name,
270 command)
271 for l in o.splitlines():
272 logging.debug("(monitor %s) %s", self.name, l)
273 return o
274 else:
275 msg = ("Could not find (qemu) prompt after command '%s'. "
276 "Output so far: %r" % (command, o))
277 raise MonitorProtocolError(msg)
279 finally:
280 self._lock.release()
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):
292 Verify VM 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':
299 return (status in o)
302 # Command wrappers
303 # Notes:
304 # - All of the following commands raise exceptions in a similar manner to
305 # cmd().
306 # - A command wrapper should use self._help_str if it requires information
307 # about the monitor's capabilities.
309 def quit(self):
311 Send "quit" without waiting for output.
313 self._send("quit")
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):
325 Alias for info.
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):
342 Migrate.
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
350 cmd = "migrate"
351 if not wait:
352 cmd += " -d"
353 if full_copy:
354 cmd += " -b"
355 if incremental_copy:
356 cmd += " -i"
357 cmd += " %s" % uri
358 return self.cmd(cmd)
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):
384 Move mouse.
386 @param dx: X amount
387 @param dy: Y amount
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.
424 try:
425 Monitor.__init__(self, name, filename)
427 self.protocol = "qmp"
428 self._greeting = None
429 self._events = []
431 # Make sure json is available
432 try:
433 json
434 except NameError:
435 self._close_sock()
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():
443 if "QMP" in obj:
444 self._greeting = obj
445 break
446 if self._greeting:
447 break
448 time.sleep(0.1)
449 else:
450 self._close_sock()
451 raise MonitorProtocolError("No QMP greeting message received")
453 # Issue qmp_capabilities
454 self.cmd("qmp_capabilities")
456 except MonitorError, e:
457 self._close_sock()
458 if suppress_exceptions:
459 logging.warn(e)
460 else:
461 raise
464 # Private methods
466 def _build_cmd(self, cmd, args=None, id=None):
467 obj = {"execute": cmd}
468 if args is not None:
469 obj["arguments"] = args
470 if id is not None:
471 obj["id"] = id
472 return obj
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():
486 return []
487 s = ""
488 end_time = time.time() + timeout
489 while self._data_available(end_time - time.time()):
490 s += self._recvall()
491 # Make sure all lines are decodable
492 for line in s.splitlines():
493 if line:
494 try:
495 json.loads(line)
496 except:
497 # Found an incomplete or broken line -- keep reading
498 break
499 else:
500 # All lines are OK -- stop reading
501 break
502 # Decode all decodable lines
503 objs = []
504 for line in s.splitlines():
505 try:
506 objs += [json.loads(line)]
507 except:
508 pass
509 # Keep track of asynchronous events
510 self._events += [obj for obj in objs if "event" in obj]
511 return objs
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
521 try:
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:
540 continue
541 if "return" in obj or "error" in obj:
542 return obj
545 # Public methods
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
563 error data)
565 if debug:
566 logging.debug("(monitor %s) Sending command '%s'",
567 self.name, cmd)
568 if not self._acquire_lock(20):
569 raise MonitorLockError("Could not acquire exclusive lock to send "
570 "QMP command '%s'" % cmd)
572 try:
573 # Read any data that might be available
574 self._read_objects()
575 # Send command
576 id = virt_utils.generate_random_string(8)
577 self._send(json.dumps(self._build_cmd(cmd, args, id)) + "\n")
578 # Read response
579 r = self._get_response(id, timeout)
580 if r is None:
581 raise MonitorProtocolError("Received no response to QMP "
582 "command '%s', or received a "
583 "response with an incorrect id"
584 % cmd)
585 if "return" in r:
586 if debug and r["return"]:
587 logging.debug("(monitor %s) "
588 "Response to '%s'", self.name, cmd)
589 o = str(r["return"])
590 for l in o.splitlines():
591 logging.debug("(monitor %s) %s", self.name, l)
592 return r["return"]
593 if "error" in r:
594 raise QMPCmdError(cmd, args, r["error"])
596 finally:
597 self._lock.release()
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
604 checks on it.
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 "
615 "data: %r" % data)
617 try:
618 self._read_objects()
619 self._send(data)
620 r = self._get_response(None, timeout)
621 if r is None:
622 raise MonitorProtocolError("Received no response to data: %r" %
623 data)
624 return r
626 finally:
627 self._lock.release()
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
635 checks on it.
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
652 checks on it.
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):
675 Verify VM 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):
682 return True
683 if (status=='running' and "u'running': True" in o):
684 return True
687 def get_events(self):
689 Return a list of the asynchronous events received since the last
690 clear_events() call.
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 "
697 "QMP events")
698 try:
699 self._read_objects()
700 return self._events[:]
701 finally:
702 self._lock.release()
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:
714 return e
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 "
725 "QMP event list")
726 self._events = []
727 self._lock.release()
730 def get_greeting(self):
732 Return QMP greeting message.
734 return self._greeting
737 # Command wrappers
738 # Note: all of the following functions raise exceptions in a similar manner
739 # to cmd().
741 def quit(self):
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):
757 Alias for info.
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):
775 Migrate.
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
783 args = {"uri": uri,
784 "blk": full_copy,
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)