| OLD | NEW |
| 1 """ | 1 """ |
| 2 Interfaces to the QEMU monitor. | 2 Interfaces to the QEMU monitor. |
| 3 | 3 |
| 4 @copyright: 2008-2010 Red Hat Inc. | 4 @copyright: 2008-2010 Red Hat Inc. |
| 5 """ | 5 """ |
| 6 | 6 |
| 7 import socket, time, threading, logging, select | 7 import socket, time, threading, logging, select |
| 8 import kvm_utils | 8 import kvm_utils |
| 9 try: | 9 try: |
| 10 import json | 10 import json |
| 11 except ImportError: | 11 except ImportError: |
| 12 logging.warning("Could not import json module. " | 12 logging.warning("Could not import json module. " |
| 13 "QMP monitor functionality disabled.") | 13 "QMP monitor functionality disabled.") |
| 14 | 14 |
| 15 | 15 |
| 16 class MonitorError(Exception): | 16 class MonitorError(Exception): |
| 17 pass | 17 pass |
| 18 | 18 |
| 19 | 19 |
| 20 class MonitorConnectError(MonitorError): | 20 class MonitorConnectError(MonitorError): |
| 21 pass | 21 pass |
| 22 | 22 |
| 23 | 23 |
| 24 class MonitorSocketError(MonitorError): | 24 class MonitorSocketError(MonitorError): |
| 25 pass | 25 def __init__(self, msg, e): |
| 26 Exception.__init__(self, msg, e) |
| 27 self.msg = msg |
| 28 self.e = e |
| 29 |
| 30 def __str__(self): |
| 31 return "%s (%s)" % (self.msg, self.e) |
| 26 | 32 |
| 27 | 33 |
| 28 class MonitorLockError(MonitorError): | 34 class MonitorLockError(MonitorError): |
| 29 pass | 35 pass |
| 30 | 36 |
| 31 | 37 |
| 32 class MonitorProtocolError(MonitorError): | 38 class MonitorProtocolError(MonitorError): |
| 33 pass | 39 pass |
| 34 | 40 |
| 35 | 41 |
| 36 class MonitorNotSupportedError(MonitorError): | 42 class MonitorNotSupportedError(MonitorError): |
| 37 pass | 43 pass |
| 38 | 44 |
| 39 | 45 |
| 40 class QMPCmdError(MonitorError): | 46 class QMPCmdError(MonitorError): |
| 41 def __init__(self, cmd, qmp_args, data): | 47 def __init__(self, cmd, qmp_args, data): |
| 42 MonitorError.__init__(self, cmd, qmp_args, data) | 48 MonitorError.__init__(self, cmd, qmp_args, data) |
| 43 self.cmd = cmd | 49 self.cmd = cmd |
| 44 self.qmp_args = qmp_args | 50 self.qmp_args = qmp_args |
| 45 self.data = data | 51 self.data = data |
| 46 | 52 |
| 47 def __str__(self): | 53 def __str__(self): |
| 48 return ("QMP command %r failed (arguments: %r, error message: %r)" % | 54 return ("QMP command %r failed (arguments: %r, " |
| 49 (self.cmd, self.qmp_args, self.data)) | 55 "error message: %r)" % (self.cmd, self.qmp_args, self.data)) |
| 50 | 56 |
| 51 | 57 |
| 52 class Monitor: | 58 class Monitor: |
| 53 """ | 59 """ |
| 54 Common code for monitor classes. | 60 Common code for monitor classes. |
| 55 """ | 61 """ |
| 56 | 62 |
| 57 def __init__(self, name, filename): | 63 def __init__(self, name, filename): |
| 58 """ | 64 """ |
| 59 Initialize the instance. | 65 Initialize the instance. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 def _data_available(self, timeout=0): | 118 def _data_available(self, timeout=0): |
| 113 timeout = max(0, timeout) | 119 timeout = max(0, timeout) |
| 114 return bool(select.select([self._socket], [], [], timeout)[0]) | 120 return bool(select.select([self._socket], [], [], timeout)[0]) |
| 115 | 121 |
| 116 | 122 |
| 117 def _recvall(self): | 123 def _recvall(self): |
| 118 s = "" | 124 s = "" |
| 119 while self._data_available(): | 125 while self._data_available(): |
| 120 try: | 126 try: |
| 121 data = self._socket.recv(1024) | 127 data = self._socket.recv(1024) |
| 122 except socket.error, (errno, msg): | 128 except socket.error, e: |
| 123 raise MonitorSocketError("Could not receive data from monitor " | 129 raise MonitorSocketError("Could not receive data from monitor", |
| 124 "(%s)" % msg) | 130 e) |
| 125 if not data: | 131 if not data: |
| 126 break | 132 break |
| 127 s += data | 133 s += data |
| 128 return s | 134 return s |
| 129 | 135 |
| 130 | 136 |
| 137 def is_responsive(self): |
| 138 """ |
| 139 Return True iff the monitor is responsive. |
| 140 """ |
| 141 try: |
| 142 self.verify_responsive() |
| 143 return True |
| 144 except MonitorError: |
| 145 return False |
| 146 |
| 147 |
| 131 class HumanMonitor(Monitor): | 148 class HumanMonitor(Monitor): |
| 132 """ | 149 """ |
| 133 Wraps "human monitor" commands. | 150 Wraps "human monitor" commands. |
| 134 """ | 151 """ |
| 135 | 152 |
| 136 def __init__(self, name, filename, suppress_exceptions=False): | 153 def __init__(self, name, filename, suppress_exceptions=False): |
| 137 """ | 154 """ |
| 138 Connect to the monitor socket and find the (qemu) prompt. | 155 Connect to the monitor socket and find the (qemu) prompt. |
| 139 | 156 |
| 140 @param name: Monitor identifier (a string) | 157 @param name: Monitor identifier (a string) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 @raise MonitorLockError: Raised if the lock cannot be acquired | 211 @raise MonitorLockError: Raised if the lock cannot be acquired |
| 195 @raise MonitorSocketError: Raised if a socket error occurs | 212 @raise MonitorSocketError: Raised if a socket error occurs |
| 196 """ | 213 """ |
| 197 if not self._acquire_lock(20): | 214 if not self._acquire_lock(20): |
| 198 raise MonitorLockError("Could not acquire exclusive lock to send " | 215 raise MonitorLockError("Could not acquire exclusive lock to send " |
| 199 "monitor command '%s'" % cmd) | 216 "monitor command '%s'" % cmd) |
| 200 | 217 |
| 201 try: | 218 try: |
| 202 try: | 219 try: |
| 203 self._socket.sendall(cmd + "\n") | 220 self._socket.sendall(cmd + "\n") |
| 204 except socket.error, (errno, msg): | 221 except socket.error, e: |
| 205 raise MonitorSocketError("Could not send monitor command '%s' " | 222 raise MonitorSocketError("Could not send monitor command %r" % |
| 206 "(%s)" % (cmd, msg)) | 223 cmd, e) |
| 207 | 224 |
| 208 finally: | 225 finally: |
| 209 self._lock.release() | 226 self._lock.release() |
| 210 | 227 |
| 211 | 228 |
| 212 # Public methods | 229 # Public methods |
| 213 | 230 |
| 214 def cmd(self, command, timeout=20): | 231 def cmd(self, command, timeout=20): |
| 215 """ | 232 """ |
| 216 Send command to the monitor. | 233 Send command to the monitor. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 241 return o | 258 return o |
| 242 else: | 259 else: |
| 243 msg = ("Could not find (qemu) prompt after command '%s'. " | 260 msg = ("Could not find (qemu) prompt after command '%s'. " |
| 244 "Output so far: %r" % (command, o)) | 261 "Output so far: %r" % (command, o)) |
| 245 raise MonitorProtocolError(msg) | 262 raise MonitorProtocolError(msg) |
| 246 | 263 |
| 247 finally: | 264 finally: |
| 248 self._lock.release() | 265 self._lock.release() |
| 249 | 266 |
| 250 | 267 |
| 251 def is_responsive(self): | 268 def verify_responsive(self): |
| 252 """ | 269 """ |
| 253 Make sure the monitor is responsive by sending a command. | 270 Make sure the monitor is responsive by sending a command. |
| 254 | |
| 255 @return: True if responsive, False otherwise | |
| 256 """ | 271 """ |
| 257 try: | 272 self.cmd("info status") |
| 258 self.cmd("info status") | |
| 259 return True | |
| 260 except MonitorError: | |
| 261 return False | |
| 262 | 273 |
| 263 | 274 |
| 264 # Command wrappers | 275 # Command wrappers |
| 265 # Notes: | 276 # Notes: |
| 266 # - All of the following commands raise exceptions in a similar manner to | 277 # - All of the following commands raise exceptions in a similar manner to |
| 267 # cmd(). | 278 # cmd(). |
| 268 # - A command wrapper should use self._help_str if it requires information | 279 # - A command wrapper should use self._help_str if it requires information |
| 269 # about the monitor's capabilities. | 280 # about the monitor's capabilities. |
| 270 | 281 |
| 271 def quit(self): | 282 def quit(self): |
| (...skipping 30 matching lines...) Expand all Loading... |
| 302 def migrate(self, uri, full_copy=False, incremental_copy=False, wait=False): | 313 def migrate(self, uri, full_copy=False, incremental_copy=False, wait=False): |
| 303 """ | 314 """ |
| 304 Migrate. | 315 Migrate. |
| 305 | 316 |
| 306 @param uri: destination URI | 317 @param uri: destination URI |
| 307 @param full_copy: If true, migrate with full disk copy | 318 @param full_copy: If true, migrate with full disk copy |
| 308 @param incremental_copy: If true, migrate with incremental disk copy | 319 @param incremental_copy: If true, migrate with incremental disk copy |
| 309 @param wait: If true, wait for completion | 320 @param wait: If true, wait for completion |
| 310 @return: The command's output | 321 @return: The command's output |
| 311 """ | 322 """ |
| 312 logging.debug("Migrating to: %s" % uri) | |
| 313 cmd = "migrate" | 323 cmd = "migrate" |
| 314 if not wait: | 324 if not wait: |
| 315 cmd += " -d" | 325 cmd += " -d" |
| 316 if full_copy: | 326 if full_copy: |
| 317 cmd += " -b" | 327 cmd += " -b" |
| 318 if incremental_copy: | 328 if incremental_copy: |
| 319 cmd += " -i" | 329 cmd += " -i" |
| 320 cmd += " %s" % uri | 330 cmd += " %s" % uri |
| 321 return self.cmd(cmd) | 331 return self.cmd(cmd) |
| 322 | 332 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 | 483 |
| 474 def _send(self, data): | 484 def _send(self, data): |
| 475 """ | 485 """ |
| 476 Send raw data without waiting for response. | 486 Send raw data without waiting for response. |
| 477 | 487 |
| 478 @param data: Data to send | 488 @param data: Data to send |
| 479 @raise MonitorSocketError: Raised if a socket error occurs | 489 @raise MonitorSocketError: Raised if a socket error occurs |
| 480 """ | 490 """ |
| 481 try: | 491 try: |
| 482 self._socket.sendall(data) | 492 self._socket.sendall(data) |
| 483 except socket.error, (errno, msg): | 493 except socket.error, e: |
| 484 raise MonitorSocketError("Could not send data: %r (%s)" % | 494 raise MonitorSocketError("Could not send data: %r" % data, e) |
| 485 (data, msg)) | |
| 486 | 495 |
| 487 | 496 |
| 488 def _get_response(self, id=None, timeout=20): | 497 def _get_response(self, id=None, timeout=20): |
| 489 """ | 498 """ |
| 490 Read a response from the QMP monitor. | 499 Read a response from the QMP monitor. |
| 491 | 500 |
| 492 @param id: If not None, look for a response with this id | 501 @param id: If not None, look for a response with this id |
| 493 @param timeout: Time duration to wait for response | 502 @param timeout: Time duration to wait for response |
| 494 @return: The response dict, or None if none was found | 503 @return: The response dict, or None if none was found |
| 495 """ | 504 """ |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 @param id: An id for the command, or None | 617 @param id: An id for the command, or None |
| 609 @param timeout: Time duration to wait for response | 618 @param timeout: Time duration to wait for response |
| 610 @return: The response received | 619 @return: The response received |
| 611 @raise MonitorLockError: Raised if the lock cannot be acquired | 620 @raise MonitorLockError: Raised if the lock cannot be acquired |
| 612 @raise MonitorSocketError: Raised if a socket error occurs | 621 @raise MonitorSocketError: Raised if a socket error occurs |
| 613 @raise MonitorProtocolError: Raised if no response is received | 622 @raise MonitorProtocolError: Raised if no response is received |
| 614 """ | 623 """ |
| 615 return self.cmd_obj(self._build_cmd(cmd, args, id), timeout) | 624 return self.cmd_obj(self._build_cmd(cmd, args, id), timeout) |
| 616 | 625 |
| 617 | 626 |
| 618 def is_responsive(self): | 627 def verify_responsive(self): |
| 619 """ | 628 """ |
| 620 Make sure the monitor is responsive by sending a command. | 629 Make sure the monitor is responsive by sending a command. |
| 621 | |
| 622 @return: True if responsive, False otherwise | |
| 623 """ | 630 """ |
| 624 try: | 631 self.cmd("query-status") |
| 625 self.cmd("query-status") | |
| 626 return True | |
| 627 except MonitorError: | |
| 628 return False | |
| 629 | 632 |
| 630 | 633 |
| 631 def get_events(self): | 634 def get_events(self): |
| 632 """ | 635 """ |
| 633 Return a list of the asynchronous events received since the last | 636 Return a list of the asynchronous events received since the last |
| 634 clear_events() call. | 637 clear_events() call. |
| 635 | 638 |
| 636 @return: A list of events (the objects returned have an "event" key) | 639 @return: A list of events (the objects returned have an "event" key) |
| 637 @raise MonitorLockError: Raised if the lock cannot be acquired | 640 @raise MonitorLockError: Raised if the lock cannot be acquired |
| 638 """ | 641 """ |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 | 735 |
| 733 def migrate_set_speed(self, value): | 736 def migrate_set_speed(self, value): |
| 734 """ | 737 """ |
| 735 Set maximum speed (in bytes/sec) for migrations. | 738 Set maximum speed (in bytes/sec) for migrations. |
| 736 | 739 |
| 737 @param value: Speed in bytes/sec | 740 @param value: Speed in bytes/sec |
| 738 @return: The response to the command | 741 @return: The response to the command |
| 739 """ | 742 """ |
| 740 args = {"value": value} | 743 args = {"value": value} |
| 741 return self.cmd("migrate_set_speed", args) | 744 return self.cmd("migrate_set_speed", args) |
| OLD | NEW |